Home | History | Annotate | Download | only in i965
      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 (at) 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 *
     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
     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
     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
    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
    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
    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 
    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 
    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 
    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 
    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
    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
    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
    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
    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
    283 brw_set_default_group(struct brw_codegen *p, unsigned group)
    284 {
    285    brw_inst_set_group(p->devinfo, p->current, group);
    286 }
    287 
    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 
    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 
    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 
    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 
    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
    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 
    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
    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
    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 *
    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