• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3  Intel funded Tungsten Graphics to
4  develop this 3D driver.
5 
6  Permission is hereby granted, free of charge, to any person obtaining
7  a copy of this software and associated documentation files (the
8  "Software"), to deal in the Software without restriction, including
9  without limitation the rights to use, copy, modify, merge, publish,
10  distribute, sublicense, and/or sell copies of the Software, and to
11  permit persons to whom the Software is furnished to do so, subject to
12  the following conditions:
13 
14  The above copyright notice and this permission notice (including the
15  next paragraph) shall be included in all copies or substantial
16  portions of the Software.
17 
18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 
26  **********************************************************************/
27  /*
28   * Authors:
29   *   Keith Whitwell <keithw@vmware.com>
30   */
31 
32 
33 #include "brw_context.h"
34 #include "brw_defines.h"
35 #include "brw_eu.h"
36 
37 #include "util/ralloc.h"
38 
39 /**
40  * Converts a BRW_REGISTER_TYPE_* enum to a short string (F, UD, and so on).
41  *
42  * This is different than reg_encoding from brw_disasm.c in that it operates
43  * on the abstract enum values, rather than the generation-specific encoding.
44  */
45 const char *
brw_reg_type_letters(unsigned type)46 brw_reg_type_letters(unsigned type)
47 {
48    const char *names[] = {
49       [BRW_REGISTER_TYPE_UD] = "UD",
50       [BRW_REGISTER_TYPE_D]  = "D",
51       [BRW_REGISTER_TYPE_UW] = "UW",
52       [BRW_REGISTER_TYPE_W]  = "W",
53       [BRW_REGISTER_TYPE_F]  = "F",
54       [BRW_REGISTER_TYPE_UB] = "UB",
55       [BRW_REGISTER_TYPE_B]  = "B",
56       [BRW_REGISTER_TYPE_UV] = "UV",
57       [BRW_REGISTER_TYPE_V]  = "V",
58       [BRW_REGISTER_TYPE_VF] = "VF",
59       [BRW_REGISTER_TYPE_DF] = "DF",
60       [BRW_REGISTER_TYPE_HF] = "HF",
61       [BRW_REGISTER_TYPE_UQ] = "UQ",
62       [BRW_REGISTER_TYPE_Q]  = "Q",
63    };
64    assert(type <= BRW_REGISTER_TYPE_Q);
65    return names[type];
66 }
67 
68 /* Returns a conditional modifier that negates the condition. */
69 enum brw_conditional_mod
brw_negate_cmod(uint32_t cmod)70 brw_negate_cmod(uint32_t cmod)
71 {
72    switch (cmod) {
73    case BRW_CONDITIONAL_Z:
74       return BRW_CONDITIONAL_NZ;
75    case BRW_CONDITIONAL_NZ:
76       return BRW_CONDITIONAL_Z;
77    case BRW_CONDITIONAL_G:
78       return BRW_CONDITIONAL_LE;
79    case BRW_CONDITIONAL_GE:
80       return BRW_CONDITIONAL_L;
81    case BRW_CONDITIONAL_L:
82       return BRW_CONDITIONAL_GE;
83    case BRW_CONDITIONAL_LE:
84       return BRW_CONDITIONAL_G;
85    default:
86       return ~0;
87    }
88 }
89 
90 /* Returns the corresponding conditional mod for swapping src0 and
91  * src1 in e.g. CMP.
92  */
93 enum brw_conditional_mod
brw_swap_cmod(uint32_t cmod)94 brw_swap_cmod(uint32_t cmod)
95 {
96    switch (cmod) {
97    case BRW_CONDITIONAL_Z:
98    case BRW_CONDITIONAL_NZ:
99       return cmod;
100    case BRW_CONDITIONAL_G:
101       return BRW_CONDITIONAL_L;
102    case BRW_CONDITIONAL_GE:
103       return BRW_CONDITIONAL_LE;
104    case BRW_CONDITIONAL_L:
105       return BRW_CONDITIONAL_G;
106    case BRW_CONDITIONAL_LE:
107       return BRW_CONDITIONAL_GE;
108    default:
109       return BRW_CONDITIONAL_NONE;
110    }
111 }
112 
113 /**
114  * Get the least significant bit offset of the i+1-th component of immediate
115  * type \p type.  For \p i equal to the two's complement of j, return the
116  * offset of the j-th component starting from the end of the vector.  For
117  * scalar register types return zero.
118  */
119 static unsigned
imm_shift(enum brw_reg_type type,unsigned i)120 imm_shift(enum brw_reg_type type, unsigned i)
121 {
122    assert(type != BRW_REGISTER_TYPE_UV && type != BRW_REGISTER_TYPE_V &&
123           "Not implemented.");
124 
125    if (type == BRW_REGISTER_TYPE_VF)
126       return 8 * (i & 3);
127    else
128       return 0;
129 }
130 
131 /**
132  * Swizzle an arbitrary immediate \p x of the given type according to the
133  * permutation specified as \p swz.
134  */
135 uint32_t
brw_swizzle_immediate(enum brw_reg_type type,uint32_t x,unsigned swz)136 brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz)
137 {
138    if (imm_shift(type, 1)) {
139       const unsigned n = 32 / imm_shift(type, 1);
140       uint32_t y = 0;
141 
142       for (unsigned i = 0; i < n; i++) {
143          /* Shift the specified component all the way to the right and left to
144           * discard any undesired L/MSBs, then shift it right into component i.
145           */
146          y |= x >> imm_shift(type, (i & ~3) + BRW_GET_SWZ(swz, i & 3))
147                 << imm_shift(type, ~0u)
148                 >> imm_shift(type, ~0u - i);
149       }
150 
151       return y;
152    } else {
153       return x;
154    }
155 }
156 
157 void
brw_set_default_exec_size(struct brw_codegen * p,unsigned value)158 brw_set_default_exec_size(struct brw_codegen *p, unsigned value)
159 {
160    brw_inst_set_exec_size(p->devinfo, p->current, value);
161 }
162 
brw_set_default_predicate_control(struct brw_codegen * p,unsigned pc)163 void brw_set_default_predicate_control( struct brw_codegen *p, unsigned pc )
164 {
165    brw_inst_set_pred_control(p->devinfo, p->current, pc);
166 }
167 
brw_set_default_predicate_inverse(struct brw_codegen * p,bool predicate_inverse)168 void brw_set_default_predicate_inverse(struct brw_codegen *p, bool predicate_inverse)
169 {
170    brw_inst_set_pred_inv(p->devinfo, p->current, predicate_inverse);
171 }
172 
brw_set_default_flag_reg(struct brw_codegen * p,int reg,int subreg)173 void brw_set_default_flag_reg(struct brw_codegen *p, int reg, int subreg)
174 {
175    if (p->devinfo->gen >= 7)
176       brw_inst_set_flag_reg_nr(p->devinfo, p->current, reg);
177 
178    brw_inst_set_flag_subreg_nr(p->devinfo, p->current, subreg);
179 }
180 
brw_set_default_access_mode(struct brw_codegen * p,unsigned access_mode)181 void brw_set_default_access_mode( struct brw_codegen *p, unsigned access_mode )
182 {
183    brw_inst_set_access_mode(p->devinfo, p->current, access_mode);
184 }
185 
186 void
brw_set_default_compression_control(struct brw_codegen * p,enum brw_compression compression_control)187 brw_set_default_compression_control(struct brw_codegen *p,
188 			    enum brw_compression compression_control)
189 {
190    if (p->devinfo->gen >= 6) {
191       /* Since we don't use the SIMD32 support in gen6, we translate
192        * the pre-gen6 compression control here.
193        */
194       switch (compression_control) {
195       case BRW_COMPRESSION_NONE:
196 	 /* This is the "use the first set of bits of dmask/vmask/arf
197 	  * according to execsize" option.
198 	  */
199          brw_inst_set_qtr_control(p->devinfo, p->current, GEN6_COMPRESSION_1Q);
200 	 break;
201       case BRW_COMPRESSION_2NDHALF:
202 	 /* For SIMD8, this is "use the second set of 8 bits." */
203          brw_inst_set_qtr_control(p->devinfo, p->current, GEN6_COMPRESSION_2Q);
204 	 break;
205       case BRW_COMPRESSION_COMPRESSED:
206 	 /* For SIMD16 instruction compression, use the first set of 16 bits
207 	  * since we don't do SIMD32 dispatch.
208 	  */
209          brw_inst_set_qtr_control(p->devinfo, p->current, GEN6_COMPRESSION_1H);
210 	 break;
211       default:
212          unreachable("not reached");
213       }
214    } else {
215       brw_inst_set_qtr_control(p->devinfo, p->current, compression_control);
216    }
217 }
218 
219 /**
220  * Enable or disable instruction compression on the given instruction leaving
221  * the currently selected channel enable group untouched.
222  */
223 void
brw_inst_set_compression(const struct gen_device_info * devinfo,brw_inst * inst,bool on)224 brw_inst_set_compression(const struct gen_device_info *devinfo,
225                          brw_inst *inst, bool on)
226 {
227    if (devinfo->gen >= 6) {
228       /* No-op, the EU will figure out for us whether the instruction needs to
229        * be compressed.
230        */
231    } else {
232       /* The channel group and compression controls are non-orthogonal, there
233        * are two possible representations for uncompressed instructions and we
234        * may need to preserve the current one to avoid changing the selected
235        * channel group inadvertently.
236        */
237       if (on)
238          brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_COMPRESSED);
239       else if (brw_inst_qtr_control(devinfo, inst)
240                == BRW_COMPRESSION_COMPRESSED)
241          brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_NONE);
242    }
243 }
244 
245 void
brw_set_default_compression(struct brw_codegen * p,bool on)246 brw_set_default_compression(struct brw_codegen *p, bool on)
247 {
248    brw_inst_set_compression(p->devinfo, p->current, on);
249 }
250 
251 /**
252  * Apply the range of channel enable signals given by
253  * [group, group + exec_size) to the instruction passed as argument.
254  */
255 void
brw_inst_set_group(const struct gen_device_info * devinfo,brw_inst * inst,unsigned group)256 brw_inst_set_group(const struct gen_device_info *devinfo,
257                    brw_inst *inst, unsigned group)
258 {
259    if (devinfo->gen >= 7) {
260       assert(group % 4 == 0 && group < 32);
261       brw_inst_set_qtr_control(devinfo, inst, group / 8);
262       brw_inst_set_nib_control(devinfo, inst, (group / 4) % 2);
263 
264    } else if (devinfo->gen == 6) {
265       assert(group % 8 == 0 && group < 32);
266       brw_inst_set_qtr_control(devinfo, inst, group / 8);
267 
268    } else {
269       assert(group % 8 == 0 && group < 16);
270       /* The channel group and compression controls are non-orthogonal, there
271        * are two possible representations for group zero and we may need to
272        * preserve the current one to avoid changing the selected compression
273        * enable inadvertently.
274        */
275       if (group == 8)
276          brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_2NDHALF);
277       else if (brw_inst_qtr_control(devinfo, inst) == BRW_COMPRESSION_2NDHALF)
278          brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_NONE);
279    }
280 }
281 
282 void
brw_set_default_group(struct brw_codegen * p,unsigned group)283 brw_set_default_group(struct brw_codegen *p, unsigned group)
284 {
285    brw_inst_set_group(p->devinfo, p->current, group);
286 }
287 
brw_set_default_mask_control(struct brw_codegen * p,unsigned value)288 void brw_set_default_mask_control( struct brw_codegen *p, unsigned value )
289 {
290    brw_inst_set_mask_control(p->devinfo, p->current, value);
291 }
292 
brw_set_default_saturate(struct brw_codegen * p,bool enable)293 void brw_set_default_saturate( struct brw_codegen *p, bool enable )
294 {
295    brw_inst_set_saturate(p->devinfo, p->current, enable);
296 }
297 
brw_set_default_acc_write_control(struct brw_codegen * p,unsigned value)298 void brw_set_default_acc_write_control(struct brw_codegen *p, unsigned value)
299 {
300    if (p->devinfo->gen >= 6)
301       brw_inst_set_acc_wr_control(p->devinfo, p->current, value);
302 }
303 
brw_push_insn_state(struct brw_codegen * p)304 void brw_push_insn_state( struct brw_codegen *p )
305 {
306    assert(p->current != &p->stack[BRW_EU_MAX_INSN_STACK-1]);
307    memcpy(p->current + 1, p->current, sizeof(brw_inst));
308    p->current++;
309 }
310 
brw_pop_insn_state(struct brw_codegen * p)311 void brw_pop_insn_state( struct brw_codegen *p )
312 {
313    assert(p->current != p->stack);
314    p->current--;
315 }
316 
317 
318 /***********************************************************************
319  */
320 void
brw_init_codegen(const struct gen_device_info * devinfo,struct brw_codegen * p,void * mem_ctx)321 brw_init_codegen(const struct gen_device_info *devinfo,
322                  struct brw_codegen *p, void *mem_ctx)
323 {
324    memset(p, 0, sizeof(*p));
325 
326    p->devinfo = devinfo;
327    /*
328     * Set the initial instruction store array size to 1024, if found that
329     * isn't enough, then it will double the store size at brw_next_insn()
330     * until out of memory.
331     */
332    p->store_size = 1024;
333    p->store = rzalloc_array(mem_ctx, brw_inst, p->store_size);
334    p->nr_insn = 0;
335    p->current = p->stack;
336    memset(p->current, 0, sizeof(p->current[0]));
337 
338    p->mem_ctx = mem_ctx;
339 
340    /* Some defaults?
341     */
342    brw_set_default_exec_size(p, BRW_EXECUTE_8);
343    brw_set_default_mask_control(p, BRW_MASK_ENABLE); /* what does this do? */
344    brw_set_default_saturate(p, 0);
345    brw_set_default_compression_control(p, BRW_COMPRESSION_NONE);
346 
347    /* Set up control flow stack */
348    p->if_stack_depth = 0;
349    p->if_stack_array_size = 16;
350    p->if_stack = rzalloc_array(mem_ctx, int, p->if_stack_array_size);
351 
352    p->loop_stack_depth = 0;
353    p->loop_stack_array_size = 16;
354    p->loop_stack = rzalloc_array(mem_ctx, int, p->loop_stack_array_size);
355    p->if_depth_in_loop = rzalloc_array(mem_ctx, int, p->loop_stack_array_size);
356 
357    brw_init_compaction_tables(devinfo);
358 }
359 
360 
brw_get_program(struct brw_codegen * p,unsigned * sz)361 const unsigned *brw_get_program( struct brw_codegen *p,
362 			       unsigned *sz )
363 {
364    *sz = p->next_insn_offset;
365    return (const unsigned *)p->store;
366 }
367 
368 void
brw_disassemble(const struct gen_device_info * devinfo,void * assembly,int start,int end,FILE * out)369 brw_disassemble(const struct gen_device_info *devinfo,
370                 void *assembly, int start, int end, FILE *out)
371 {
372    bool dump_hex = (INTEL_DEBUG & DEBUG_HEX) != 0;
373 
374    for (int offset = start; offset < end;) {
375       brw_inst *insn = assembly + offset;
376       brw_inst uncompacted;
377       bool compacted = brw_inst_cmpt_control(devinfo, insn);
378       if (0)
379          fprintf(out, "0x%08x: ", offset);
380 
381       if (compacted) {
382          brw_compact_inst *compacted = (void *)insn;
383 	 if (dump_hex) {
384 	    fprintf(out, "0x%08x 0x%08x                       ",
385 		    ((uint32_t *)insn)[1],
386 		    ((uint32_t *)insn)[0]);
387 	 }
388 
389 	 brw_uncompact_instruction(devinfo, &uncompacted, compacted);
390 	 insn = &uncompacted;
391 	 offset += 8;
392       } else {
393 	 if (dump_hex) {
394 	    fprintf(out, "0x%08x 0x%08x 0x%08x 0x%08x ",
395 		    ((uint32_t *)insn)[3],
396 		    ((uint32_t *)insn)[2],
397 		    ((uint32_t *)insn)[1],
398 		    ((uint32_t *)insn)[0]);
399 	 }
400 	 offset += 16;
401       }
402 
403       brw_disassemble_inst(out, devinfo, insn, compacted);
404    }
405 }
406 
407 enum gen {
408    GEN4  = (1 << 0),
409    GEN45 = (1 << 1),
410    GEN5  = (1 << 2),
411    GEN6  = (1 << 3),
412    GEN7  = (1 << 4),
413    GEN75 = (1 << 5),
414    GEN8  = (1 << 6),
415    GEN9  = (1 << 7),
416    GEN_ALL = ~0
417 };
418 
419 #define GEN_LT(gen) ((gen) - 1)
420 #define GEN_GE(gen) (~GEN_LT(gen))
421 #define GEN_LE(gen) (GEN_LT(gen) | (gen))
422 
423 static const struct opcode_desc opcode_10_descs[] = {
424    { .name = "dim",   .nsrc = 1, .ndst = 1, .gens = GEN75 },
425    { .name = "smov",  .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN8) },
426 };
427 
428 static const struct opcode_desc opcode_35_descs[] = {
429    { .name = "iff",   .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
430    { .name = "brc",   .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN7) },
431 };
432 
433 static const struct opcode_desc opcode_38_descs[] = {
434    { .name = "do",    .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
435    { .name = "case",  .nsrc = 0, .ndst = 0, .gens = GEN6 },
436 };
437 
438 static const struct opcode_desc opcode_44_descs[] = {
439    { .name = "msave", .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
440    { .name = "call",  .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN6) },
441 };
442 
443 static const struct opcode_desc opcode_45_descs[] = {
444    { .name = "mrest", .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
445    { .name = "ret",   .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN6) },
446 };
447 
448 static const struct opcode_desc opcode_46_descs[] = {
449    { .name = "push",  .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) },
450    { .name = "fork",  .nsrc = 0, .ndst = 0, .gens = GEN6 },
451    { .name = "goto",  .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN8) },
452 };
453 
454 static const struct opcode_desc opcode_descs[128] = {
455    [BRW_OPCODE_ILLEGAL] = {
456       .name = "illegal", .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
457    },
458    [BRW_OPCODE_MOV] = {
459       .name = "mov",     .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
460    },
461    [BRW_OPCODE_SEL] = {
462       .name = "sel",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
463    },
464    [BRW_OPCODE_MOVI] = {
465       .name = "movi",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN45),
466    },
467    [BRW_OPCODE_NOT] = {
468       .name = "not",     .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
469    },
470    [BRW_OPCODE_AND] = {
471       .name = "and",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
472    },
473    [BRW_OPCODE_OR] = {
474       .name = "or",      .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
475    },
476    [BRW_OPCODE_XOR] = {
477       .name = "xor",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
478    },
479    [BRW_OPCODE_SHR] = {
480       .name = "shr",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
481    },
482    [BRW_OPCODE_SHL] = {
483       .name = "shl",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
484    },
485    [10] = {
486       .table = opcode_10_descs, .size = ARRAY_SIZE(opcode_10_descs),
487    },
488    /* Reserved - 11 */
489    [BRW_OPCODE_ASR] = {
490       .name = "asr",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
491    },
492    /* Reserved - 13-15 */
493    [BRW_OPCODE_CMP] = {
494       .name = "cmp",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
495    },
496    [BRW_OPCODE_CMPN] = {
497       .name = "cmpn",    .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
498    },
499    [BRW_OPCODE_CSEL] = {
500       .name = "csel",    .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN8),
501    },
502    [BRW_OPCODE_F32TO16] = {
503       .name = "f32to16", .nsrc = 1, .ndst = 1, .gens = GEN7 | GEN75,
504    },
505    [BRW_OPCODE_F16TO32] = {
506       .name = "f16to32", .nsrc = 1, .ndst = 1, .gens = GEN7 | GEN75,
507    },
508    /* Reserved - 21-22 */
509    [BRW_OPCODE_BFREV] = {
510       .name = "bfrev",   .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7),
511    },
512    [BRW_OPCODE_BFE] = {
513       .name = "bfe",     .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN7),
514    },
515    [BRW_OPCODE_BFI1] = {
516       .name = "bfi1",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN7),
517    },
518    [BRW_OPCODE_BFI2] = {
519       .name = "bfi2",    .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN7),
520    },
521    /* Reserved - 27-31 */
522    [BRW_OPCODE_JMPI] = {
523       .name = "jmpi",    .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
524    },
525    [33] = {
526       .name = "brd",     .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN7),
527    },
528    [BRW_OPCODE_IF] = {
529       .name = "if",      .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
530    },
531    [35] = {
532       .table = opcode_35_descs, .size = ARRAY_SIZE(opcode_35_descs),
533    },
534    [BRW_OPCODE_ELSE] = {
535       .name = "else",    .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
536    },
537    [BRW_OPCODE_ENDIF] = {
538       .name = "endif",   .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
539    },
540    [38] = {
541       .table = opcode_38_descs, .size = ARRAY_SIZE(opcode_38_descs),
542    },
543    [BRW_OPCODE_WHILE] = {
544       .name = "while",   .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
545    },
546    [BRW_OPCODE_BREAK] = {
547       .name = "break",   .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
548    },
549    [BRW_OPCODE_CONTINUE] = {
550       .name = "cont",    .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
551    },
552    [BRW_OPCODE_HALT] = {
553       .name = "halt",    .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
554    },
555    [43] = {
556       .name = "calla",   .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN75),
557    },
558    [44] = {
559       .table = opcode_44_descs, .size = ARRAY_SIZE(opcode_44_descs),
560    },
561    [45] = {
562       .table = opcode_45_descs, .size = ARRAY_SIZE(opcode_45_descs),
563    },
564    [46] = {
565       .table = opcode_46_descs, .size = ARRAY_SIZE(opcode_46_descs),
566    },
567    [47] = {
568       .name = "pop",     .nsrc = 2, .ndst = 0, .gens = GEN_LE(GEN5),
569    },
570    [BRW_OPCODE_WAIT] = {
571       .name = "wait",    .nsrc = 1, .ndst = 0, .gens = GEN_ALL,
572    },
573    [BRW_OPCODE_SEND] = {
574       .name = "send",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
575    },
576    [BRW_OPCODE_SENDC] = {
577       .name = "sendc",   .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
578    },
579    [BRW_OPCODE_SENDS] = {
580       .name = "sends",   .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN9),
581    },
582    [BRW_OPCODE_SENDSC] = {
583       .name = "sendsc",  .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN9),
584    },
585    /* Reserved 53-55 */
586    [BRW_OPCODE_MATH] = {
587       .name = "math",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN6),
588    },
589    /* Reserved 57-63 */
590    [BRW_OPCODE_ADD] = {
591       .name = "add",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
592    },
593    [BRW_OPCODE_MUL] = {
594       .name = "mul",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
595    },
596    [BRW_OPCODE_AVG] = {
597       .name = "avg",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
598    },
599    [BRW_OPCODE_FRC] = {
600       .name = "frc",     .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
601    },
602    [BRW_OPCODE_RNDU] = {
603       .name = "rndu",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
604    },
605    [BRW_OPCODE_RNDD] = {
606       .name = "rndd",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
607    },
608    [BRW_OPCODE_RNDE] = {
609       .name = "rnde",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
610    },
611    [BRW_OPCODE_RNDZ] = {
612       .name = "rndz",    .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
613    },
614    [BRW_OPCODE_MAC] = {
615       .name = "mac",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
616    },
617    [BRW_OPCODE_MACH] = {
618       .name = "mach",    .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
619    },
620    [BRW_OPCODE_LZD] = {
621       .name = "lzd",     .nsrc = 1, .ndst = 1, .gens = GEN_ALL,
622    },
623    [BRW_OPCODE_FBH] = {
624       .name = "fbh",     .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7),
625    },
626    [BRW_OPCODE_FBL] = {
627       .name = "fbl",     .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7),
628    },
629    [BRW_OPCODE_CBIT] = {
630       .name = "cbit",    .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7),
631    },
632    [BRW_OPCODE_ADDC] = {
633       .name = "addc",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN7),
634    },
635    [BRW_OPCODE_SUBB] = {
636       .name = "subb",    .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN7),
637    },
638    [BRW_OPCODE_SAD2] = {
639       .name = "sad2",    .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
640    },
641    [BRW_OPCODE_SADA2] = {
642       .name = "sada2",   .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
643    },
644    /* Reserved 82-83 */
645    [BRW_OPCODE_DP4] = {
646       .name = "dp4",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
647    },
648    [BRW_OPCODE_DPH] = {
649       .name = "dph",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
650    },
651    [BRW_OPCODE_DP3] = {
652       .name = "dp3",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
653    },
654    [BRW_OPCODE_DP2] = {
655       .name = "dp2",     .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
656    },
657    /* Reserved 88 */
658    [BRW_OPCODE_LINE] = {
659       .name = "line",    .nsrc = 2, .ndst = 1, .gens = GEN_ALL,
660    },
661    [BRW_OPCODE_PLN] = {
662       .name = "pln",     .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN45),
663    },
664    [BRW_OPCODE_MAD] = {
665       .name = "mad",     .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN6),
666    },
667    [BRW_OPCODE_LRP] = {
668       .name = "lrp",     .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN6),
669    },
670    [93] = {
671       .name = "madm",    .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN8),
672    },
673    /* Reserved 94-124 */
674    [BRW_OPCODE_NENOP] = {
675       .name = "nenop",   .nsrc = 0, .ndst = 0, .gens = GEN45,
676    },
677    [BRW_OPCODE_NOP] = {
678       .name = "nop",     .nsrc = 0, .ndst = 0, .gens = GEN_ALL,
679    },
680 };
681 
682 static enum gen
gen_from_devinfo(const struct gen_device_info * devinfo)683 gen_from_devinfo(const struct gen_device_info *devinfo)
684 {
685    switch (devinfo->gen) {
686    case 4: return devinfo->is_g4x ? GEN45 : GEN4;
687    case 5: return GEN5;
688    case 6: return GEN6;
689    case 7: return devinfo->is_haswell ? GEN75 : GEN7;
690    case 8: return GEN8;
691    case 9: return GEN9;
692    default:
693       unreachable("not reached");
694    }
695 }
696 
697 /* Return the matching opcode_desc for the specified opcode number and
698  * hardware generation, or NULL if the opcode is not supported by the device.
699  */
700 const struct opcode_desc *
brw_opcode_desc(const struct gen_device_info * devinfo,enum opcode opcode)701 brw_opcode_desc(const struct gen_device_info *devinfo, enum opcode opcode)
702 {
703    if (opcode >= ARRAY_SIZE(opcode_descs))
704       return NULL;
705 
706    enum gen gen = gen_from_devinfo(devinfo);
707    if (opcode_descs[opcode].gens != 0) {
708       if ((opcode_descs[opcode].gens & gen) != 0) {
709          return &opcode_descs[opcode];
710       }
711    } else if (opcode_descs[opcode].table != NULL) {
712       const struct opcode_desc *table = opcode_descs[opcode].table;
713       for (unsigned i = 0; i < opcode_descs[opcode].size; i++) {
714          if ((table[i].gens & gen) != 0) {
715             return &table[i];
716          }
717       }
718    }
719    return NULL;
720 }
721