X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_eu.c;h=3a309dce8faeb2dbe7d90dac501e657422b3fe07;hb=40241d40d0a481f9f1cd112d2d48dadf1ec6ad0f;hp=b9e91d9f04d64d721f40f8d1c95e7197dda96229;hpb=d542c45c75671e93a1cfae1f0eaf9c12f082f4f1;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_eu.c b/src/mesa/drivers/dri/i965/brw_eu.c index b9e91d9f04d..3a309dce8fa 100644 --- a/src/mesa/drivers/dri/i965/brw_eu.c +++ b/src/mesa/drivers/dri/i965/brw_eu.c @@ -1,6 +1,6 @@ /* Copyright (C) Intel Corp. 2006. All Rights Reserved. - Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to + Intel funded Tungsten Graphics to develop this 3D driver. Permission is hereby granted, free of charge, to any person obtaining @@ -26,7 +26,7 @@ **********************************************************************/ /* * Authors: - * Keith Whitwell + * Keith Whitwell */ @@ -34,12 +34,63 @@ #include "brw_defines.h" #include "brw_eu.h" -#include "glsl/ralloc.h" +#include "util/ralloc.h" + +/** + * Converts a BRW_REGISTER_TYPE_* enum to a short string (F, UD, and so on). + * + * This is different than reg_encoding from brw_disasm.c in that it operates + * on the abstract enum values, rather than the generation-specific encoding. + */ +const char * +brw_reg_type_letters(unsigned type) +{ + const char *names[] = { + [BRW_REGISTER_TYPE_UD] = "UD", + [BRW_REGISTER_TYPE_D] = "D", + [BRW_REGISTER_TYPE_UW] = "UW", + [BRW_REGISTER_TYPE_W] = "W", + [BRW_REGISTER_TYPE_F] = "F", + [BRW_REGISTER_TYPE_UB] = "UB", + [BRW_REGISTER_TYPE_B] = "B", + [BRW_REGISTER_TYPE_UV] = "UV", + [BRW_REGISTER_TYPE_V] = "V", + [BRW_REGISTER_TYPE_VF] = "VF", + [BRW_REGISTER_TYPE_DF] = "DF", + [BRW_REGISTER_TYPE_HF] = "HF", + [BRW_REGISTER_TYPE_UQ] = "UQ", + [BRW_REGISTER_TYPE_Q] = "Q", + }; + assert(type <= BRW_REGISTER_TYPE_Q); + return names[type]; +} + +/* Returns a conditional modifier that negates the condition. */ +enum brw_conditional_mod +brw_negate_cmod(uint32_t cmod) +{ + switch (cmod) { + case BRW_CONDITIONAL_Z: + return BRW_CONDITIONAL_NZ; + case BRW_CONDITIONAL_NZ: + return BRW_CONDITIONAL_Z; + case BRW_CONDITIONAL_G: + return BRW_CONDITIONAL_LE; + case BRW_CONDITIONAL_GE: + return BRW_CONDITIONAL_L; + case BRW_CONDITIONAL_L: + return BRW_CONDITIONAL_GE; + case BRW_CONDITIONAL_LE: + return BRW_CONDITIONAL_G; + default: + return ~0; + } +} /* Returns the corresponding conditional mod for swapping src0 and * src1 in e.g. CMP. */ -uint32_t +enum brw_conditional_mod brw_swap_cmod(uint32_t cmod) { switch (cmod) { @@ -55,64 +106,89 @@ brw_swap_cmod(uint32_t cmod) case BRW_CONDITIONAL_LE: return BRW_CONDITIONAL_GE; default: - return ~0; + return BRW_CONDITIONAL_NONE; } } +/** + * Get the least significant bit offset of the i+1-th component of immediate + * type \p type. For \p i equal to the two's complement of j, return the + * offset of the j-th component starting from the end of the vector. For + * scalar register types return zero. + */ +static unsigned +imm_shift(enum brw_reg_type type, unsigned i) +{ + assert(type != BRW_REGISTER_TYPE_UV && type != BRW_REGISTER_TYPE_V && + "Not implemented."); + + if (type == BRW_REGISTER_TYPE_VF) + return 8 * (i & 3); + else + return 0; +} -/* How does predicate control work when execution_size != 8? Do I - * need to test/set for 0xffff when execution_size is 16? +/** + * Swizzle an arbitrary immediate \p x of the given type according to the + * permutation specified as \p swz. */ -void brw_set_predicate_control_flag_value( struct brw_compile *p, GLuint value ) +uint32_t +brw_swizzle_immediate(enum brw_reg_type type, uint32_t x, unsigned swz) { - p->current->header.predicate_control = BRW_PREDICATE_NONE; - - if (value != 0xff) { - if (value != p->flag_value) { - brw_push_insn_state(p); - brw_MOV(p, brw_flag_reg(0, 0), brw_imm_uw(value)); - p->flag_value = value; - brw_pop_insn_state(p); + if (imm_shift(type, 1)) { + const unsigned n = 32 / imm_shift(type, 1); + uint32_t y = 0; + + for (unsigned i = 0; i < n; i++) { + /* Shift the specified component all the way to the right and left to + * discard any undesired L/MSBs, then shift it right into component i. + */ + y |= x >> imm_shift(type, (i & ~3) + BRW_GET_SWZ(swz, i & 3)) + << imm_shift(type, ~0u) + >> imm_shift(type, ~0u - i); } - p->current->header.predicate_control = BRW_PREDICATE_NORMAL; + return y; + } else { + return x; } } -void brw_set_predicate_control( struct brw_compile *p, GLuint pc ) +void +brw_set_default_exec_size(struct brw_codegen *p, unsigned value) { - p->current->header.predicate_control = pc; + brw_inst_set_exec_size(p->devinfo, p->current, value); } -void brw_set_predicate_inverse(struct brw_compile *p, bool predicate_inverse) +void brw_set_default_predicate_control( struct brw_codegen *p, unsigned pc ) { - p->current->header.predicate_inverse = predicate_inverse; + brw_inst_set_pred_control(p->devinfo, p->current, pc); } -void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional ) +void brw_set_default_predicate_inverse(struct brw_codegen *p, bool predicate_inverse) { - p->current->header.destreg__conditionalmod = conditional; + brw_inst_set_pred_inv(p->devinfo, p->current, predicate_inverse); } -void brw_set_flag_reg(struct brw_compile *p, int reg, int subreg) +void brw_set_default_flag_reg(struct brw_codegen *p, int reg, int subreg) { - p->current->bits2.da1.flag_reg_nr = reg; - p->current->bits2.da1.flag_subreg_nr = subreg; + if (p->devinfo->gen >= 7) + brw_inst_set_flag_reg_nr(p->devinfo, p->current, reg); + + brw_inst_set_flag_subreg_nr(p->devinfo, p->current, subreg); } -void brw_set_access_mode( struct brw_compile *p, GLuint access_mode ) +void brw_set_default_access_mode( struct brw_codegen *p, unsigned access_mode ) { - p->current->header.access_mode = access_mode; + brw_inst_set_access_mode(p->devinfo, p->current, access_mode); } void -brw_set_compression_control(struct brw_compile *p, +brw_set_default_compression_control(struct brw_codegen *p, enum brw_compression compression_control) { - p->compressed = (compression_control == BRW_COMPRESSION_COMPRESSED); - - if (p->brw->gen >= 6) { - /* Since we don't use the 32-wide support in gen6, we translate + if (p->devinfo->gen >= 6) { + /* Since we don't use the SIMD32 support in gen6, we translate * the pre-gen6 compression control here. */ switch (compression_control) { @@ -120,88 +196,153 @@ brw_set_compression_control(struct brw_compile *p, /* This is the "use the first set of bits of dmask/vmask/arf * according to execsize" option. */ - p->current->header.compression_control = GEN6_COMPRESSION_1Q; + brw_inst_set_qtr_control(p->devinfo, p->current, GEN6_COMPRESSION_1Q); break; case BRW_COMPRESSION_2NDHALF: - /* For 8-wide, this is "use the second set of 8 bits." */ - p->current->header.compression_control = GEN6_COMPRESSION_2Q; + /* For SIMD8, this is "use the second set of 8 bits." */ + brw_inst_set_qtr_control(p->devinfo, p->current, GEN6_COMPRESSION_2Q); break; case BRW_COMPRESSION_COMPRESSED: - /* For 16-wide instruction compression, use the first set of 16 bits - * since we don't do 32-wide dispatch. + /* For SIMD16 instruction compression, use the first set of 16 bits + * since we don't do SIMD32 dispatch. */ - p->current->header.compression_control = GEN6_COMPRESSION_1H; + brw_inst_set_qtr_control(p->devinfo, p->current, GEN6_COMPRESSION_1H); break; default: - assert(!"not reached"); - p->current->header.compression_control = GEN6_COMPRESSION_1H; - break; + unreachable("not reached"); } } else { - p->current->header.compression_control = compression_control; + brw_inst_set_qtr_control(p->devinfo, p->current, compression_control); } } -void brw_set_mask_control( struct brw_compile *p, GLuint value ) +/** + * Enable or disable instruction compression on the given instruction leaving + * the currently selected channel enable group untouched. + */ +void +brw_inst_set_compression(const struct brw_device_info *devinfo, + brw_inst *inst, bool on) { - p->current->header.mask_control = value; + if (devinfo->gen >= 6) { + /* No-op, the EU will figure out for us whether the instruction needs to + * be compressed. + */ + } else { + /* The channel group and compression controls are non-orthogonal, there + * are two possible representations for uncompressed instructions and we + * may need to preserve the current one to avoid changing the selected + * channel group inadvertently. + */ + if (on) + brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_COMPRESSED); + else if (brw_inst_qtr_control(devinfo, inst) + == BRW_COMPRESSION_COMPRESSED) + brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_NONE); + } +} + +void +brw_set_default_compression(struct brw_codegen *p, bool on) +{ + brw_inst_set_compression(p->devinfo, p->current, on); +} + +/** + * Apply the range of channel enable signals given by + * [group, group + exec_size) to the instruction passed as argument. + */ +void +brw_inst_set_group(const struct brw_device_info *devinfo, + brw_inst *inst, unsigned group) +{ + if (devinfo->gen >= 7) { + assert(group % 4 == 0 && group < 32); + brw_inst_set_qtr_control(devinfo, inst, group / 8); + brw_inst_set_nib_control(devinfo, inst, (group / 4) % 2); + + } else if (devinfo->gen == 6) { + assert(group % 8 == 0 && group < 32); + brw_inst_set_qtr_control(devinfo, inst, group / 8); + + } else { + assert(group % 8 == 0 && group < 16); + /* The channel group and compression controls are non-orthogonal, there + * are two possible representations for group zero and we may need to + * preserve the current one to avoid changing the selected compression + * enable inadvertently. + */ + if (group == 8) + brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_2NDHALF); + else if (brw_inst_qtr_control(devinfo, inst) == BRW_COMPRESSION_2NDHALF) + brw_inst_set_qtr_control(devinfo, inst, BRW_COMPRESSION_NONE); + } +} + +void +brw_set_default_group(struct brw_codegen *p, unsigned group) +{ + brw_inst_set_group(p->devinfo, p->current, group); } -void brw_set_saturate( struct brw_compile *p, bool enable ) +void brw_set_default_mask_control( struct brw_codegen *p, unsigned value ) { - p->current->header.saturate = enable; + brw_inst_set_mask_control(p->devinfo, p->current, value); } -void brw_set_acc_write_control(struct brw_compile *p, GLuint value) +void brw_set_default_saturate( struct brw_codegen *p, bool enable ) { - if (p->brw->gen >= 6) - p->current->header.acc_wr_control = value; + brw_inst_set_saturate(p->devinfo, p->current, enable); } -void brw_push_insn_state( struct brw_compile *p ) +void brw_set_default_acc_write_control(struct brw_codegen *p, unsigned value) +{ + if (p->devinfo->gen >= 6) + brw_inst_set_acc_wr_control(p->devinfo, p->current, value); +} + +void brw_push_insn_state( struct brw_codegen *p ) { assert(p->current != &p->stack[BRW_EU_MAX_INSN_STACK-1]); - memcpy(p->current+1, p->current, sizeof(struct brw_instruction)); - p->compressed_stack[p->current - p->stack] = p->compressed; + memcpy(p->current + 1, p->current, sizeof(brw_inst)); p->current++; } -void brw_pop_insn_state( struct brw_compile *p ) +void brw_pop_insn_state( struct brw_codegen *p ) { assert(p->current != p->stack); p->current--; - p->compressed = p->compressed_stack[p->current - p->stack]; } /*********************************************************************** */ void -brw_init_compile(struct brw_context *brw, struct brw_compile *p, void *mem_ctx) +brw_init_codegen(const struct brw_device_info *devinfo, + struct brw_codegen *p, void *mem_ctx) { memset(p, 0, sizeof(*p)); - p->brw = brw; + p->devinfo = devinfo; /* * Set the initial instruction store array size to 1024, if found that * isn't enough, then it will double the store size at brw_next_insn() * until out of memory. */ p->store_size = 1024; - p->store = rzalloc_array(mem_ctx, struct brw_instruction, p->store_size); + p->store = rzalloc_array(mem_ctx, brw_inst, p->store_size); p->nr_insn = 0; p->current = p->stack; - p->compressed = false; memset(p->current, 0, sizeof(p->current[0])); p->mem_ctx = mem_ctx; /* Some defaults? */ - brw_set_mask_control(p, BRW_MASK_ENABLE); /* what does this do? */ - brw_set_saturate(p, 0); - brw_set_compression_control(p, BRW_COMPRESSION_NONE); - brw_set_predicate_control_flag_value(p, 0xff); + brw_set_default_exec_size(p, BRW_EXECUTE_8); + brw_set_default_mask_control(p, BRW_MASK_ENABLE); /* what does this do? */ + brw_set_default_saturate(p, 0); + brw_set_default_compression_control(p, BRW_COMPRESSION_NONE); /* Set up control flow stack */ p->if_stack_depth = 0; @@ -213,53 +354,367 @@ brw_init_compile(struct brw_context *brw, struct brw_compile *p, void *mem_ctx) p->loop_stack = rzalloc_array(mem_ctx, int, p->loop_stack_array_size); p->if_depth_in_loop = rzalloc_array(mem_ctx, int, p->loop_stack_array_size); - brw_init_compaction_tables(brw); + brw_init_compaction_tables(devinfo); } -const GLuint *brw_get_program( struct brw_compile *p, - GLuint *sz ) +const unsigned *brw_get_program( struct brw_codegen *p, + unsigned *sz ) { - brw_compact_instructions(p); - *sz = p->next_insn_offset; - return (const GLuint *)p->store; + return (const unsigned *)p->store; } void -brw_dump_compile(struct brw_compile *p, FILE *out, int start, int end) +brw_disassemble(const struct brw_device_info *devinfo, + void *assembly, int start, int end, FILE *out) { - struct brw_context *brw = p->brw; - void *store = p->store; - bool dump_hex = false; + bool dump_hex = (INTEL_DEBUG & DEBUG_HEX) != 0; for (int offset = start; offset < end;) { - struct brw_instruction *insn = store + offset; - struct brw_instruction uncompacted; - printf("0x%08x: ", offset); - - if (insn->header.cmpt_control) { - struct brw_compact_instruction *compacted = (void *)insn; + brw_inst *insn = assembly + offset; + brw_inst uncompacted; + bool compacted = brw_inst_cmpt_control(devinfo, insn); + if (0) + fprintf(out, "0x%08x: ", offset); + + if (compacted) { + brw_compact_inst *compacted = (void *)insn; if (dump_hex) { - printf("0x%08x 0x%08x ", - ((uint32_t *)insn)[1], - ((uint32_t *)insn)[0]); + fprintf(out, "0x%08x 0x%08x ", + ((uint32_t *)insn)[1], + ((uint32_t *)insn)[0]); } - brw_uncompact_instruction(brw, &uncompacted, compacted); + brw_uncompact_instruction(devinfo, &uncompacted, compacted); insn = &uncompacted; offset += 8; } else { if (dump_hex) { - printf("0x%08x 0x%08x 0x%08x 0x%08x ", - ((uint32_t *)insn)[3], - ((uint32_t *)insn)[2], - ((uint32_t *)insn)[1], - ((uint32_t *)insn)[0]); + fprintf(out, "0x%08x 0x%08x 0x%08x 0x%08x ", + ((uint32_t *)insn)[3], + ((uint32_t *)insn)[2], + ((uint32_t *)insn)[1], + ((uint32_t *)insn)[0]); } offset += 16; } - brw_disasm(stdout, insn, p->brw->gen); + brw_disassemble_inst(out, devinfo, insn, compacted); + } +} + +enum gen { + GEN4 = (1 << 0), + GEN45 = (1 << 1), + GEN5 = (1 << 2), + GEN6 = (1 << 3), + GEN7 = (1 << 4), + GEN75 = (1 << 5), + GEN8 = (1 << 6), + GEN9 = (1 << 7), + GEN_ALL = ~0 +}; + +#define GEN_LT(gen) ((gen) - 1) +#define GEN_GE(gen) (~GEN_LT(gen)) +#define GEN_LE(gen) (GEN_LT(gen) | (gen)) + +static const struct opcode_desc opcode_10_descs[] = { + { .name = "dim", .nsrc = 1, .ndst = 1, .gens = GEN75 }, + { .name = "smov", .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN8) }, +}; + +static const struct opcode_desc opcode_35_descs[] = { + { .name = "iff", .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) }, + { .name = "brc", .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN7) }, +}; + +static const struct opcode_desc opcode_38_descs[] = { + { .name = "do", .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) }, + { .name = "case", .nsrc = 0, .ndst = 0, .gens = GEN6 }, +}; + +static const struct opcode_desc opcode_44_descs[] = { + { .name = "msave", .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) }, + { .name = "call", .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN6) }, +}; + +static const struct opcode_desc opcode_45_descs[] = { + { .name = "mrest", .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) }, + { .name = "ret", .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN6) }, +}; + +static const struct opcode_desc opcode_46_descs[] = { + { .name = "push", .nsrc = 0, .ndst = 0, .gens = GEN_LE(GEN5) }, + { .name = "fork", .nsrc = 0, .ndst = 0, .gens = GEN6 }, + { .name = "goto", .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN8) }, +}; + +static const struct opcode_desc opcode_descs[128] = { + [BRW_OPCODE_ILLEGAL] = { + .name = "illegal", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, + [BRW_OPCODE_MOV] = { + .name = "mov", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_SEL] = { + .name = "sel", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_MOVI] = { + .name = "movi", .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN45), + }, + [BRW_OPCODE_NOT] = { + .name = "not", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_AND] = { + .name = "and", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_OR] = { + .name = "or", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_XOR] = { + .name = "xor", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_SHR] = { + .name = "shr", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_SHL] = { + .name = "shl", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [10] = { + .table = opcode_10_descs, .size = ARRAY_SIZE(opcode_10_descs), + }, + /* Reserved - 11 */ + [BRW_OPCODE_ASR] = { + .name = "asr", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + /* Reserved - 13-15 */ + [BRW_OPCODE_CMP] = { + .name = "cmp", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_CMPN] = { + .name = "cmpn", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_CSEL] = { + .name = "csel", .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN8), + }, + [BRW_OPCODE_F32TO16] = { + .name = "f32to16", .nsrc = 1, .ndst = 1, .gens = GEN7 | GEN75, + }, + [BRW_OPCODE_F16TO32] = { + .name = "f16to32", .nsrc = 1, .ndst = 1, .gens = GEN7 | GEN75, + }, + /* Reserved - 21-22 */ + [BRW_OPCODE_BFREV] = { + .name = "bfrev", .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7), + }, + [BRW_OPCODE_BFE] = { + .name = "bfe", .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN7), + }, + [BRW_OPCODE_BFI1] = { + .name = "bfi1", .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN7), + }, + [BRW_OPCODE_BFI2] = { + .name = "bfi2", .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN7), + }, + /* Reserved - 27-31 */ + [BRW_OPCODE_JMPI] = { + .name = "jmpi", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, + [33] = { + .name = "brd", .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN7), + }, + [BRW_OPCODE_IF] = { + .name = "if", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, + [35] = { + .table = opcode_35_descs, .size = ARRAY_SIZE(opcode_35_descs), + }, + [BRW_OPCODE_ELSE] = { + .name = "else", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, + [BRW_OPCODE_ENDIF] = { + .name = "endif", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, + [38] = { + .table = opcode_38_descs, .size = ARRAY_SIZE(opcode_38_descs), + }, + [BRW_OPCODE_WHILE] = { + .name = "while", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, + [BRW_OPCODE_BREAK] = { + .name = "break", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, + [BRW_OPCODE_CONTINUE] = { + .name = "cont", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, + [BRW_OPCODE_HALT] = { + .name = "halt", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, + [43] = { + .name = "calla", .nsrc = 0, .ndst = 0, .gens = GEN_GE(GEN75), + }, + [44] = { + .table = opcode_44_descs, .size = ARRAY_SIZE(opcode_44_descs), + }, + [45] = { + .table = opcode_45_descs, .size = ARRAY_SIZE(opcode_45_descs), + }, + [46] = { + .table = opcode_46_descs, .size = ARRAY_SIZE(opcode_46_descs), + }, + [47] = { + .name = "pop", .nsrc = 2, .ndst = 0, .gens = GEN_LE(GEN5), + }, + [BRW_OPCODE_WAIT] = { + .name = "wait", .nsrc = 1, .ndst = 0, .gens = GEN_ALL, + }, + [BRW_OPCODE_SEND] = { + .name = "send", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_SENDC] = { + .name = "sendc", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_SENDS] = { + .name = "sends", .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN9), + }, + [BRW_OPCODE_SENDSC] = { + .name = "sendsc", .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN9), + }, + /* Reserved 53-55 */ + [BRW_OPCODE_MATH] = { + .name = "math", .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN6), + }, + /* Reserved 57-63 */ + [BRW_OPCODE_ADD] = { + .name = "add", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_MUL] = { + .name = "mul", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_AVG] = { + .name = "avg", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_FRC] = { + .name = "frc", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_RNDU] = { + .name = "rndu", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_RNDD] = { + .name = "rndd", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_RNDE] = { + .name = "rnde", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_RNDZ] = { + .name = "rndz", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_MAC] = { + .name = "mac", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_MACH] = { + .name = "mach", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_LZD] = { + .name = "lzd", .nsrc = 1, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_FBH] = { + .name = "fbh", .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7), + }, + [BRW_OPCODE_FBL] = { + .name = "fbl", .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7), + }, + [BRW_OPCODE_CBIT] = { + .name = "cbit", .nsrc = 1, .ndst = 1, .gens = GEN_GE(GEN7), + }, + [BRW_OPCODE_ADDC] = { + .name = "addc", .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN7), + }, + [BRW_OPCODE_SUBB] = { + .name = "subb", .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN7), + }, + [BRW_OPCODE_SAD2] = { + .name = "sad2", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_SADA2] = { + .name = "sada2", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + /* Reserved 82-83 */ + [BRW_OPCODE_DP4] = { + .name = "dp4", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_DPH] = { + .name = "dph", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_DP3] = { + .name = "dp3", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_DP2] = { + .name = "dp2", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + /* Reserved 88 */ + [BRW_OPCODE_LINE] = { + .name = "line", .nsrc = 2, .ndst = 1, .gens = GEN_ALL, + }, + [BRW_OPCODE_PLN] = { + .name = "pln", .nsrc = 2, .ndst = 1, .gens = GEN_GE(GEN45), + }, + [BRW_OPCODE_MAD] = { + .name = "mad", .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN6), + }, + [BRW_OPCODE_LRP] = { + .name = "lrp", .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN6), + }, + [93] = { + .name = "madm", .nsrc = 3, .ndst = 1, .gens = GEN_GE(GEN8), + }, + /* Reserved 94-124 */ + [BRW_OPCODE_NENOP] = { + .name = "nenop", .nsrc = 0, .ndst = 0, .gens = GEN45, + }, + [BRW_OPCODE_NOP] = { + .name = "nop", .nsrc = 0, .ndst = 0, .gens = GEN_ALL, + }, +}; + +static enum gen +gen_from_devinfo(const struct brw_device_info *devinfo) +{ + switch (devinfo->gen) { + case 4: return devinfo->is_g4x ? GEN45 : GEN4; + case 5: return GEN5; + case 6: return GEN6; + case 7: return devinfo->is_haswell ? GEN75 : GEN7; + case 8: return GEN8; + case 9: return GEN9; + default: + unreachable("not reached"); + } +} + +/* Return the matching opcode_desc for the specified opcode number and + * hardware generation, or NULL if the opcode is not supported by the device. + */ +const struct opcode_desc * +brw_opcode_desc(const struct brw_device_info *devinfo, enum opcode opcode) +{ + if (opcode >= ARRAY_SIZE(opcode_descs)) + return NULL; + + enum gen gen = gen_from_devinfo(devinfo); + if (opcode_descs[opcode].gens != 0) { + if ((opcode_descs[opcode].gens & gen) != 0) { + return &opcode_descs[opcode]; + } + } else if (opcode_descs[opcode].table != NULL) { + const struct opcode_desc *table = opcode_descs[opcode].table; + for (unsigned i = 0; i < opcode_descs[opcode].size; i++) { + if ((table[i].gens & gen) != 0) { + return &table[i]; + } + } } + return NULL; }