%{ /* * Copyright © 2018 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include #include #include #include #include "i965_asm.h" #define YYLTYPE YYLTYPE typedef struct YYLTYPE { int first_line; int first_column; int last_line; int last_column; } YYLTYPE; enum message_level { WARN, ERROR, }; int yydebug = 1; static void message(enum message_level level, YYLTYPE *location, const char *fmt, ...) { static const char *level_str[] = { "warning", "error" }; va_list args; if (location) fprintf(stderr, "%s:%d:%d: %s: ", input_filename, location->first_line, location->first_column, level_str[level]); else fprintf(stderr, "%s:%s: ", input_filename, level_str[level]); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); } #define warn(flag, l, fmt, ...) \ do { \ if (warning_flags & WARN_ ## flag) \ message(WARN, l, fmt, ## __VA_ARGS__); \ } while (0) #define error(l, fmt, ...) \ do { \ message(ERROR, l, fmt, ## __VA_ARGS__); \ } while (0) static bool isPowerofTwo(unsigned int x) { return x && (!(x & (x - 1))); } static struct brw_reg set_direct_src_operand(struct brw_reg *reg, int type) { return brw_reg(reg->file, reg->nr, reg->subnr, 0, // negate 0, // abs type, 0, // vstride 0, // width 0, // hstride BRW_SWIZZLE_NOOP, WRITEMASK_XYZW); } static void i965_asm_unary_instruction(int opcode, struct brw_codegen *p, struct brw_reg dest, struct brw_reg src0) { switch (opcode) { case BRW_OPCODE_BFREV: brw_BFREV(p, dest, src0); break; case BRW_OPCODE_CBIT: brw_CBIT(p, dest, src0); break; case BRW_OPCODE_F32TO16: brw_F32TO16(p, dest, src0); break; case BRW_OPCODE_F16TO32: brw_F16TO32(p, dest, src0); break; case BRW_OPCODE_MOV: brw_MOV(p, dest, src0); break; case BRW_OPCODE_FBL: brw_FBL(p, dest, src0); break; case BRW_OPCODE_FRC: brw_FRC(p, dest, src0); break; case BRW_OPCODE_FBH: brw_FBH(p, dest, src0); break; case BRW_OPCODE_NOT: brw_NOT(p, dest, src0); break; case BRW_OPCODE_RNDE: brw_RNDE(p, dest, src0); break; case BRW_OPCODE_RNDZ: brw_RNDZ(p, dest, src0); break; case BRW_OPCODE_RNDD: brw_RNDD(p, dest, src0); break; case BRW_OPCODE_LZD: brw_LZD(p, dest, src0); break; case BRW_OPCODE_DIM: brw_DIM(p, dest, src0); break; case BRW_OPCODE_RNDU: fprintf(stderr, "Opcode BRW_OPCODE_RNDU unhandled\n"); break; default: fprintf(stderr, "Unsupported unary opcode\n"); } } static void i965_asm_binary_instruction(int opcode, struct brw_codegen *p, struct brw_reg dest, struct brw_reg src0, struct brw_reg src1) { switch (opcode) { case BRW_OPCODE_ADDC: brw_ADDC(p, dest, src0, src1); break; case BRW_OPCODE_BFI1: brw_BFI1(p, dest, src0, src1); break; case BRW_OPCODE_DP2: brw_DP2(p, dest, src0, src1); break; case BRW_OPCODE_DP3: brw_DP3(p, dest, src0, src1); break; case BRW_OPCODE_DP4: brw_DP4(p, dest, src0, src1); break; case BRW_OPCODE_DPH: brw_DPH(p, dest, src0, src1); break; case BRW_OPCODE_LINE: brw_LINE(p, dest, src0, src1); break; case BRW_OPCODE_MAC: brw_MAC(p, dest, src0, src1); break; case BRW_OPCODE_MACH: brw_MACH(p, dest, src0, src1); break; case BRW_OPCODE_PLN: brw_PLN(p, dest, src0, src1); break; case BRW_OPCODE_ROL: brw_ROL(p, dest, src0, src1); break; case BRW_OPCODE_ROR: brw_ROR(p, dest, src0, src1); break; case BRW_OPCODE_SAD2: fprintf(stderr, "Opcode BRW_OPCODE_SAD2 unhandled\n"); break; case BRW_OPCODE_SADA2: fprintf(stderr, "Opcode BRW_OPCODE_SADA2 unhandled\n"); break; case BRW_OPCODE_SUBB: brw_SUBB(p, dest, src0, src1); break; case BRW_OPCODE_ADD: brw_ADD(p, dest, src0, src1); break; case BRW_OPCODE_CMP: /* Third parameter is conditional modifier * which gets updated later */ brw_CMP(p, dest, 0, src0, src1); break; case BRW_OPCODE_AND: brw_AND(p, dest, src0, src1); break; case BRW_OPCODE_ASR: brw_ASR(p, dest, src0, src1); break; case BRW_OPCODE_AVG: brw_AVG(p, dest, src0, src1); break; case BRW_OPCODE_OR: brw_OR(p, dest, src0, src1); break; case BRW_OPCODE_SEL: brw_SEL(p, dest, src0, src1); break; case BRW_OPCODE_SHL: brw_SHL(p, dest, src0, src1); break; case BRW_OPCODE_SHR: brw_SHR(p, dest, src0, src1); break; case BRW_OPCODE_XOR: brw_XOR(p, dest, src0, src1); break; case BRW_OPCODE_MUL: brw_MUL(p, dest, src0, src1); break; default: fprintf(stderr, "Unsupported binary opcode\n"); } } static void i965_asm_ternary_instruction(int opcode, struct brw_codegen *p, struct brw_reg dest, struct brw_reg src0, struct brw_reg src1, struct brw_reg src2) { switch (opcode) { case BRW_OPCODE_MAD: brw_MAD(p, dest, src0, src1, src2); break; case BRW_OPCODE_CSEL: brw_CSEL(p, dest, src0, src1, src2); break; case BRW_OPCODE_LRP: brw_LRP(p, dest, src0, src1, src2); break; case BRW_OPCODE_BFE: brw_BFE(p, dest, src0, src1, src2); break; case BRW_OPCODE_BFI2: brw_BFI2(p, dest, src0, src1, src2); break; default: fprintf(stderr, "Unsupported ternary opcode\n"); } } static void i965_asm_set_instruction_options(struct brw_codegen *p, struct options options) { brw_inst_set_access_mode(p->devinfo, brw_last_inst, options.access_mode); brw_inst_set_mask_control(p->devinfo, brw_last_inst, options.mask_control); brw_inst_set_thread_control(p->devinfo, brw_last_inst, options.thread_control); brw_inst_set_no_dd_check(p->devinfo, brw_last_inst, options.no_dd_check); brw_inst_set_no_dd_clear(p->devinfo, brw_last_inst, options.no_dd_clear); brw_inst_set_debug_control(p->devinfo, brw_last_inst, options.debug_control); if (p->devinfo->gen >= 6) brw_inst_set_acc_wr_control(p->devinfo, brw_last_inst, options.acc_wr_control); brw_inst_set_cmpt_control(p->devinfo, brw_last_inst, options.compaction); } static void i965_asm_set_dst_nr(struct brw_codegen *p, struct brw_reg *reg, struct options options) { if (p->devinfo->gen <= 6) { if (reg->file == BRW_MESSAGE_REGISTER_FILE && options.qtr_ctrl == BRW_COMPRESSION_COMPRESSED && !options.is_compr) reg->nr |= BRW_MRF_COMPR4; } } static void add_label(struct brw_codegen *p, const char* label_name, enum instr_label_type type) { if (!label_name) { return; } struct instr_label *label = rzalloc(p->mem_ctx, struct instr_label); label->name = ralloc_strdup(p->mem_ctx, label_name); label->offset = p->next_insn_offset; label->type = type; list_addtail(&label->link, &instr_labels); } %} %locations %start ROOT %union { char *string; double number; int integer; unsigned long long int llint; struct brw_reg reg; enum brw_reg_type reg_type; struct brw_codegen *program; struct predicate predicate; struct condition condition; struct options options; brw_inst *instruction; } %token ABS %token COLON %token COMMA %token DOT %token LANGLE RANGLE %token LCURLY RCURLY %token LPAREN RPAREN %token LSQUARE RSQUARE %token PLUS MINUS %token SEMICOLON /* datatypes */ %token TYPE_B TYPE_UB %token TYPE_W TYPE_UW %token TYPE_D TYPE_UD %token TYPE_Q TYPE_UQ %token TYPE_V TYPE_UV %token TYPE_F TYPE_HF %token TYPE_DF TYPE_NF %token TYPE_VF /* label */ %token JUMP_LABEL %token JUMP_LABEL_TARGET /* opcodes */ %token ADD ADD3 ADDC AND ASR AVG %token BFE BFI1 BFI2 BFB BFREV BRC BRD BREAK %token CALL CALLA CASE CBIT CMP CMPN CONT CSEL %token DIM DO DPAS DPASW DP2 DP3 DP4 DP4A DPH %token ELSE ENDIF F16TO32 F32TO16 FBH FBL FORK FRC %token GOTO %token HALT %token IF IFF ILLEGAL %token JMPI JOIN %token LINE LRP LZD %token MAC MACH MAD MADM MOV MOVI MUL MREST MSAVE %token NENOP NOP NOT %token OR %token PLN POP PUSH %token RET RNDD RNDE RNDU RNDZ ROL ROR %token SAD2 SADA2 SEL SEND SENDC SENDS SENDSC SHL SHR SMOV SUBB SYNC %token WAIT WHILE %token XOR /* extended math functions */ %token COS EXP FDIV INV INVM INTDIV INTDIVMOD INTMOD LOG POW RSQ %token RSQRTM SIN SINCOS SQRT /* shared functions for send */ %token CONST CRE DATA DP_DATA_1 GATEWAY MATH PIXEL_INTERP READ RENDER SAMPLER %token THREAD_SPAWNER URB VME WRITE DP_SAMPLER /* Conditional modifiers */ %token EQUAL GREATER GREATER_EQUAL LESS LESS_EQUAL NOT_EQUAL %token NOT_ZERO OVERFLOW UNORDERED ZERO /* register Access Modes */ %token ALIGN1 ALIGN16 /* accumulator write control */ %token ACCWREN /* compaction control */ %token CMPTCTRL /* compression control */ %token COMPR COMPR4 SECHALF /* mask control (WeCtrl) */ %token WECTRL /* debug control */ %token BREAKPOINT /* dependency control */ %token NODDCLR NODDCHK /* end of thread */ %token EOT /* mask control */ %token MASK_DISABLE; /* predicate control */ %token ANYV ALLV ANY2H ALL2H ANY4H ALL4H ANY8H ALL8H ANY16H ALL16H %token ANY32H ALL32H /* round instructions */ %token ROUND_INCREMENT /* staturation */ %token SATURATE /* thread control */ %token ATOMIC SWITCH /* quater control */ %token QTR_2Q QTR_3Q QTR_4Q QTR_2H QTR_2N QTR_3N QTR_4N QTR_5N %token QTR_6N QTR_7N QTR_8N /* channels */ %token X Y Z W /* reg files */ %token GENREGFILE MSGREGFILE /* vertical stride in register region */ %token VxH /* register type */ %token GENREG MSGREG ADDRREG ACCREG FLAGREG NOTIFYREG STATEREG %token CONTROLREG IPREG PERFORMANCEREG THREADREG CHANNELENABLEREG %token MASKREG %token INTEGER %token LONG %token NULL_TOKEN %precedence SUBREGNUM %left PLUS MINUS %precedence DOT %precedence EMPTYEXECSIZE %precedence LPAREN %type execsize simple_int exp %type exp2 /* predicate control */ %type predctrl predstate %type predicate /* conditional modifier */ %type cond_mod %type condModifiers /* instruction options */ %type instoptions instoption_list %type instoption /* writemask */ %type writemask_x writemask_y writemask_z writemask_w %type writemask /* dst operand */ %type dst dstoperand dstoperandex dstoperandex_typed dstreg %type dstregion %type saturate relativelocation rellocation %type relativelocation2 /* src operand */ %type directsrcoperand directsrcaccoperand indirectsrcoperand srcacc %type srcarcoperandex srcaccimm srcarcoperandex_typed srcimm %type indirectgenreg indirectregion %type immreg src reg32 payload directgenreg_list addrparam region %type region_wh directgenreg directmsgreg indirectmsgreg %type swizzle /* registers */ %type accreg addrreg channelenablereg controlreg flagreg ipreg %type notifyreg nullreg performancereg threadcontrolreg statereg maskreg %type subregnum /* register types */ %type reg_type imm_type /* immediate values */ %type immval /* instruction opcodes */ %type unaryopcodes binaryopcodes binaryaccopcodes ternaryopcodes %type sendop %type sendopcode %type negate abs chansel math_function sharedfunction %type jumplabeltarget %type jumplabel %code { static void add_instruction_option(struct options *options, int option) { switch (option) { case ALIGN1: options->access_mode = BRW_ALIGN_1; break; case ALIGN16: options->access_mode = BRW_ALIGN_16; break; case SECHALF: options->qtr_ctrl |= BRW_COMPRESSION_2NDHALF; break; case COMPR: options->qtr_ctrl |= BRW_COMPRESSION_COMPRESSED; options->is_compr = true; break; case COMPR4: options->qtr_ctrl |= BRW_COMPRESSION_COMPRESSED; break; case SWITCH: options->thread_control |= BRW_THREAD_SWITCH; break; case ATOMIC: options->thread_control |= BRW_THREAD_ATOMIC; break; case NODDCHK: options->no_dd_check = true; break; case NODDCLR: options->no_dd_clear = BRW_DEPENDENCY_NOTCLEARED; break; case MASK_DISABLE: options->mask_control |= BRW_MASK_DISABLE; break; case BREAKPOINT: options->debug_control = BRW_DEBUG_BREAKPOINT; break; case WECTRL: options->mask_control |= BRW_WE_ALL; break; case CMPTCTRL: options->compaction = true; break; case ACCWREN: options->acc_wr_control = true; break; case EOT: options->end_of_thread = true; break; /* TODO : Figure out how to set instruction group and get rid of * code below */ case QTR_2Q: options->qtr_ctrl = BRW_COMPRESSION_2NDHALF; break; case QTR_3Q: options->qtr_ctrl = BRW_COMPRESSION_COMPRESSED; break; case QTR_4Q: options->qtr_ctrl = 3; break; case QTR_2H: options->qtr_ctrl = BRW_COMPRESSION_COMPRESSED; break; case QTR_2N: options->qtr_ctrl = BRW_COMPRESSION_NONE; options->nib_ctrl = true; break; case QTR_3N: options->qtr_ctrl = BRW_COMPRESSION_2NDHALF; break; case QTR_4N: options->qtr_ctrl = BRW_COMPRESSION_2NDHALF; options->nib_ctrl = true; break; case QTR_5N: options->qtr_ctrl = BRW_COMPRESSION_COMPRESSED; break; case QTR_6N: options->qtr_ctrl = BRW_COMPRESSION_COMPRESSED; options->nib_ctrl = true; break; case QTR_7N: options->qtr_ctrl = 3; break; case QTR_8N: options->qtr_ctrl = 3; options->nib_ctrl = true; break; } } } %% ROOT: instrseq ; instrseq: instrseq instruction SEMICOLON | instrseq relocatableinstruction SEMICOLON | instruction SEMICOLON | relocatableinstruction SEMICOLON | instrseq jumplabeltarget | jumplabeltarget ; /* Instruction Group */ instruction: unaryinstruction | binaryinstruction | binaryaccinstruction | mathinstruction | nopinstruction | syncinstruction | ternaryinstruction | sendinstruction | illegalinstruction ; relocatableinstruction: jumpinstruction | branchinstruction | breakinstruction | loopinstruction ; illegalinstruction: ILLEGAL execsize instoptions { brw_next_insn(p, $1); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $2); i965_asm_set_instruction_options(p, $3); } ; /* Unary instruction */ unaryinstruction: predicate unaryopcodes saturate cond_mod execsize dst srcaccimm instoptions { i965_asm_set_dst_nr(p, &$6, $8); brw_set_default_access_mode(p, $8.access_mode); i965_asm_unary_instruction($2, p, $6, $7); brw_pop_insn_state(p); i965_asm_set_instruction_options(p, $8); brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, $4.cond_modifier); if (p->devinfo->gen >= 7) { if ($2 != BRW_OPCODE_DIM) { brw_inst_set_flag_reg_nr(p->devinfo, brw_last_inst, $4.flag_reg_nr); brw_inst_set_flag_subreg_nr(p->devinfo, brw_last_inst, $4.flag_subreg_nr); } } if ($7.file != BRW_IMMEDIATE_VALUE) { brw_inst_set_src0_vstride(p->devinfo, brw_last_inst, $7.vstride); } brw_inst_set_saturate(p->devinfo, brw_last_inst, $3); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $5); // TODO: set instruction group instead of qtr and nib ctrl brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $8.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $8.nib_ctrl); } ; unaryopcodes: BFREV | CBIT | DIM | F16TO32 | F32TO16 | FBH | FBL | FRC | LZD | MOV | NOT | RNDD | RNDE | RNDU | RNDZ ; /* Binary instruction */ binaryinstruction: predicate binaryopcodes saturate cond_mod execsize dst srcimm srcimm instoptions { i965_asm_set_dst_nr(p, &$6, $9); brw_set_default_access_mode(p, $9.access_mode); i965_asm_binary_instruction($2, p, $6, $7, $8); i965_asm_set_instruction_options(p, $9); brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, $4.cond_modifier); if (p->devinfo->gen >= 7) { brw_inst_set_flag_reg_nr(p->devinfo, brw_last_inst, $4.flag_reg_nr); brw_inst_set_flag_subreg_nr(p->devinfo, brw_last_inst, $4.flag_subreg_nr); } brw_inst_set_saturate(p->devinfo, brw_last_inst, $3); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $5); // TODO: set instruction group instead of qtr and nib ctrl brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $9.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $9.nib_ctrl); brw_pop_insn_state(p); } ; binaryopcodes: ADDC | BFI1 | DP2 | DP3 | DP4 | DPH | LINE | MAC | MACH | MUL | PLN | ROL | ROR | SAD2 | SADA2 | SUBB ; /* Binary acc instruction */ binaryaccinstruction: predicate binaryaccopcodes saturate cond_mod execsize dst srcacc srcimm instoptions { i965_asm_set_dst_nr(p, &$6, $9); brw_set_default_access_mode(p, $9.access_mode); i965_asm_binary_instruction($2, p, $6, $7, $8); brw_pop_insn_state(p); i965_asm_set_instruction_options(p, $9); brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, $4.cond_modifier); if (p->devinfo->gen >= 7) { if (!brw_inst_flag_reg_nr(p->devinfo, brw_last_inst)) { brw_inst_set_flag_reg_nr(p->devinfo, brw_last_inst, $4.flag_reg_nr); brw_inst_set_flag_subreg_nr(p->devinfo, brw_last_inst, $4.flag_subreg_nr); } } brw_inst_set_saturate(p->devinfo, brw_last_inst, $3); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $5); // TODO: set instruction group instead of qtr and nib ctrl brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $9.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $9.nib_ctrl); } ; binaryaccopcodes: ADD | AND | ASR | AVG | CMP | CMPN | OR | SEL | SHL | SHR | XOR ; /* Math instruction */ mathinstruction: predicate MATH saturate math_function execsize dst src srcimm instoptions { brw_set_default_access_mode(p, $9.access_mode); gen6_math(p, $6, $4, $7, $8); i965_asm_set_instruction_options(p, $9); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $5); brw_inst_set_saturate(p->devinfo, brw_last_inst, $3); // TODO: set instruction group instead brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $9.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $9.nib_ctrl); brw_pop_insn_state(p); } ; math_function: COS | EXP | FDIV | INV | INVM | INTDIV | INTDIVMOD | INTMOD | LOG | POW | RSQ | RSQRTM | SIN | SQRT | SINCOS ; /* NOP instruction */ nopinstruction: NOP { brw_NOP(p); } ; /* Ternary operand instruction */ ternaryinstruction: predicate ternaryopcodes saturate cond_mod execsize dst src src src instoptions { brw_set_default_access_mode(p, $10.access_mode); i965_asm_ternary_instruction($2, p, $6, $7, $8, $9); brw_pop_insn_state(p); i965_asm_set_instruction_options(p, $10); brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, $4.cond_modifier); if (p->devinfo->gen >= 7) { brw_inst_set_3src_a16_flag_reg_nr(p->devinfo, brw_last_inst, $4.flag_reg_nr); brw_inst_set_3src_a16_flag_subreg_nr(p->devinfo, brw_last_inst, $4.flag_subreg_nr); } brw_inst_set_saturate(p->devinfo, brw_last_inst, $3); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $5); // TODO: set instruction group instead of qtr and nib ctrl brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $10.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $10.nib_ctrl); } ; ternaryopcodes: CSEL | BFE | BFI2 | LRP | MAD ; /* Sync instruction */ syncinstruction: WAIT execsize dst instoptions { brw_next_insn(p, $1); i965_asm_set_instruction_options(p, $4); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $2); brw_set_default_access_mode(p, $4.access_mode); struct brw_reg dest = $3; dest.swizzle = brw_swizzle_for_mask(dest.writemask); if (dest.file != ARF || dest.nr != BRW_ARF_NOTIFICATION_COUNT) error(&@1, "WAIT must use the notification register\n"); brw_set_dest(p, brw_last_inst, dest); brw_set_src0(p, brw_last_inst, dest); brw_set_src1(p, brw_last_inst, brw_null_reg()); brw_inst_set_mask_control(p->devinfo, brw_last_inst, BRW_MASK_DISABLE); } ; /* Send instruction */ sendinstruction: predicate sendopcode execsize dst payload exp2 sharedfunction instoptions { i965_asm_set_instruction_options(p, $8); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, $4); brw_set_src0(p, brw_last_inst, $5); brw_inst_set_bits(brw_last_inst, 127, 96, $6); brw_inst_set_src1_file_type(p->devinfo, brw_last_inst, BRW_IMMEDIATE_VALUE, BRW_REGISTER_TYPE_UD); brw_inst_set_sfid(p->devinfo, brw_last_inst, $7); brw_inst_set_eot(p->devinfo, brw_last_inst, $8.end_of_thread); // TODO: set instruction group instead of qtr and nib ctrl brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $8.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $8.nib_ctrl); brw_pop_insn_state(p); } | predicate sendopcode execsize exp dst payload exp2 sharedfunction instoptions { i965_asm_set_instruction_options(p, $9); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_inst_set_base_mrf(p->devinfo, brw_last_inst, $4); brw_set_dest(p, brw_last_inst, $5); brw_set_src0(p, brw_last_inst, $6); brw_inst_set_bits(brw_last_inst, 127, 96, $7); brw_inst_set_src1_file_type(p->devinfo, brw_last_inst, BRW_IMMEDIATE_VALUE, BRW_REGISTER_TYPE_UD); brw_inst_set_sfid(p->devinfo, brw_last_inst, $8); brw_inst_set_eot(p->devinfo, brw_last_inst, $9.end_of_thread); // TODO: set instruction group instead of qtr and nib ctrl brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $9.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $9.nib_ctrl); brw_pop_insn_state(p); } | predicate sendopcode execsize dst payload payload exp2 sharedfunction instoptions { i965_asm_set_instruction_options(p, $9); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, $4); brw_set_src0(p, brw_last_inst, $5); brw_inst_set_bits(brw_last_inst, 127, 96, $7); brw_inst_set_sfid(p->devinfo, brw_last_inst, $8); brw_inst_set_eot(p->devinfo, brw_last_inst, $9.end_of_thread); // TODO: set instruction group instead of qtr and nib ctrl brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $9.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $9.nib_ctrl); brw_pop_insn_state(p); } | predicate SENDS execsize dst payload payload exp2 exp2 sharedfunction instoptions { brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $10); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, $4); brw_set_src0(p, brw_last_inst, $5); brw_set_src1(p, brw_last_inst, $6); if (brw_inst_send_sel_reg32_ex_desc(p->devinfo, brw_last_inst)) { brw_inst_set_send_ex_desc_ia_subreg_nr(p->devinfo, brw_last_inst, $5.subnr); } else { brw_inst_set_sends_ex_desc(p->devinfo, brw_last_inst, $8); } brw_inst_set_bits(brw_last_inst, 127, 96, $7); brw_inst_set_sfid(p->devinfo, brw_last_inst, $9); brw_inst_set_eot(p->devinfo, brw_last_inst, $10.end_of_thread); // TODO: set instruction group instead of qtr and nib ctrl brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $10.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $10.nib_ctrl); brw_pop_insn_state(p); } | predicate SENDS execsize dst payload payload src exp2 sharedfunction instoptions { brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $10); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, $4); brw_set_src0(p, brw_last_inst, $5); brw_set_src1(p, brw_last_inst, $6); brw_inst_set_send_sel_reg32_desc(p->devinfo, brw_last_inst, 1); brw_inst_set_sends_ex_desc(p->devinfo, brw_last_inst, $8); brw_inst_set_sfid(p->devinfo, brw_last_inst, $9); brw_inst_set_eot(p->devinfo, brw_last_inst, $10.end_of_thread); // TODO: set instruction group instead of qtr and nib ctrl brw_inst_set_qtr_control(p->devinfo, brw_last_inst, $10.qtr_ctrl); if (p->devinfo->gen >= 7) brw_inst_set_nib_control(p->devinfo, brw_last_inst, $10.nib_ctrl); brw_pop_insn_state(p); } ; sendop: SEND | SENDC ; sendopcode: sendop { $$ = brw_next_insn(p, $1); } ; sharedfunction: NULL_TOKEN { $$ = BRW_SFID_NULL; } | MATH { $$ = BRW_SFID_MATH; } | GATEWAY { $$ = BRW_SFID_MESSAGE_GATEWAY; } | READ { $$ = BRW_SFID_DATAPORT_READ; } | WRITE { $$ = BRW_SFID_DATAPORT_WRITE; } | URB { $$ = BRW_SFID_URB; } | THREAD_SPAWNER { $$ = BRW_SFID_THREAD_SPAWNER; } | VME { $$ = BRW_SFID_VME; } | RENDER { $$ = GEN6_SFID_DATAPORT_RENDER_CACHE; } | CONST { $$ = GEN6_SFID_DATAPORT_CONSTANT_CACHE; } | DATA { $$ = GEN7_SFID_DATAPORT_DATA_CACHE; } | PIXEL_INTERP { $$ = GEN7_SFID_PIXEL_INTERPOLATOR; } | DP_DATA_1 { $$ = HSW_SFID_DATAPORT_DATA_CACHE_1; } | CRE { $$ = HSW_SFID_CRE; } | SAMPLER { $$ = BRW_SFID_SAMPLER; } | DP_SAMPLER { $$ = GEN6_SFID_DATAPORT_SAMPLER_CACHE; } ; exp2: LONG { $$ = $1; } | MINUS LONG { $$ = -$2; } ; /* Jump instruction */ jumpinstruction: predicate JMPI execsize relativelocation2 instoptions { brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $5); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, brw_ip_reg()); brw_set_src0(p, brw_last_inst, brw_ip_reg()); brw_set_src1(p, brw_last_inst, $4); brw_inst_set_pred_control(p->devinfo, brw_last_inst, brw_inst_pred_control(p->devinfo, brw_last_inst)); brw_pop_insn_state(p); } ; /* branch instruction */ branchinstruction: predicate ENDIF execsize JUMP_LABEL instoptions { add_label(p, $4, INSTR_LABEL_JIP); brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $5); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); if (p->devinfo->gen == 6) { brw_set_dest(p, brw_last_inst, brw_imm_w(0x0)); brw_set_src0(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src1(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); } else if (p->devinfo->gen == 7) { brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src0(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src1(p, brw_last_inst, brw_imm_w(0x0)); } else { brw_set_src0(p, brw_last_inst, brw_imm_d(0x0)); } brw_pop_insn_state(p); } | predicate ENDIF execsize relativelocation instoptions { brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $5); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src0(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src1(p, brw_last_inst, brw_imm_d(0x0)); brw_inst_set_gen4_pop_count(p->devinfo, brw_last_inst, $4); brw_inst_set_thread_control(p->devinfo, brw_last_inst, BRW_THREAD_SWITCH); brw_pop_insn_state(p); } | ELSE execsize JUMP_LABEL jumplabel instoptions { add_label(p, $3, INSTR_LABEL_JIP); add_label(p, $4, INSTR_LABEL_UIP); brw_next_insn(p, $1); i965_asm_set_instruction_options(p, $5); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $2); if (p->devinfo->gen == 6) { brw_set_dest(p, brw_last_inst, brw_imm_w(0x0)); brw_set_src0(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src1(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); } else if (p->devinfo->gen == 7) { brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src0(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src1(p, brw_last_inst, brw_imm_w(0)); } else { brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); if (p->devinfo->gen < 12) brw_set_src0(p, brw_last_inst, brw_imm_d(0)); } } | ELSE execsize relativelocation rellocation instoptions { brw_next_insn(p, $1); i965_asm_set_instruction_options(p, $5); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $2); brw_set_dest(p, brw_last_inst, brw_ip_reg()); brw_set_src0(p, brw_last_inst, brw_ip_reg()); brw_set_src1(p, brw_last_inst, brw_imm_d(0x0)); brw_inst_set_gen4_jump_count(p->devinfo, brw_last_inst, $3); brw_inst_set_gen4_pop_count(p->devinfo, brw_last_inst, $4); if (!p->single_program_flow) brw_inst_set_thread_control(p->devinfo, brw_last_inst, BRW_THREAD_SWITCH); } | predicate IF execsize JUMP_LABEL jumplabel instoptions { add_label(p, $4, INSTR_LABEL_JIP); add_label(p, $5, INSTR_LABEL_UIP); brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $6); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); if (p->devinfo->gen == 6) { brw_set_dest(p, brw_last_inst, brw_imm_w(0x0)); brw_set_src0(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); brw_set_src1(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); } else if (p->devinfo->gen == 7) { brw_set_dest(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); brw_set_src0(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); brw_set_src1(p, brw_last_inst, brw_imm_w(0x0)); } else { brw_set_dest(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); if (p->devinfo->gen < 12) brw_set_src0(p, brw_last_inst, brw_imm_d(0x0)); } brw_pop_insn_state(p); } | predicate IF execsize relativelocation rellocation instoptions { brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $6); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, brw_ip_reg()); brw_set_src0(p, brw_last_inst, brw_ip_reg()); brw_set_src1(p, brw_last_inst, brw_imm_d(0x0)); brw_inst_set_gen4_jump_count(p->devinfo, brw_last_inst, $4); brw_inst_set_gen4_pop_count(p->devinfo, brw_last_inst, $5); if (!p->single_program_flow) brw_inst_set_thread_control(p->devinfo, brw_last_inst, BRW_THREAD_SWITCH); brw_pop_insn_state(p); } | predicate IFF execsize JUMP_LABEL instoptions { add_label(p, $4, INSTR_LABEL_JIP); brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $5); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); if (p->devinfo->gen == 6) { brw_set_src0(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); brw_set_src1(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); } else if (p->devinfo->gen == 7) { brw_set_dest(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); brw_set_src0(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); brw_set_src1(p, brw_last_inst, brw_imm_w(0x0)); } else { brw_set_dest(p, brw_last_inst, vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_D))); if (p->devinfo->gen < 12) brw_set_src0(p, brw_last_inst, brw_imm_d(0x0)); } brw_pop_insn_state(p); } | predicate IFF execsize relativelocation instoptions { brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $5); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, brw_ip_reg()); brw_set_src0(p, brw_last_inst, brw_ip_reg()); brw_inst_set_gen4_jump_count(p->devinfo, brw_last_inst, $4); brw_set_src1(p, brw_last_inst, brw_imm_d($4)); if (!p->single_program_flow) brw_inst_set_thread_control(p->devinfo, brw_last_inst, BRW_THREAD_SWITCH); brw_pop_insn_state(p); } ; /* break instruction */ breakinstruction: predicate BREAK execsize JUMP_LABEL JUMP_LABEL instoptions { add_label(p, $4, INSTR_LABEL_JIP); add_label(p, $5, INSTR_LABEL_UIP); brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $6); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); if (p->devinfo->gen >= 8) { brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src0(p, brw_last_inst, brw_imm_d(0x0)); } else { brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src0(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src1(p, brw_last_inst, brw_imm_d(0x0)); } brw_pop_insn_state(p); } | predicate BREAK execsize relativelocation relativelocation instoptions { brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $6); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, brw_ip_reg()); brw_set_src0(p, brw_last_inst, brw_ip_reg()); brw_set_src1(p, brw_last_inst, brw_imm_d(0x0)); brw_inst_set_gen4_jump_count(p->devinfo, brw_last_inst, $4); brw_inst_set_gen4_pop_count(p->devinfo, brw_last_inst, $5); brw_pop_insn_state(p); } | predicate HALT execsize JUMP_LABEL JUMP_LABEL instoptions { add_label(p, $4, INSTR_LABEL_JIP); add_label(p, $5, INSTR_LABEL_UIP); brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $6); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); if (p->devinfo->gen >= 8) { brw_set_src0(p, brw_last_inst, brw_imm_d(0x0)); } else { brw_set_src0(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src1(p, brw_last_inst, brw_imm_d(0x0)); } brw_pop_insn_state(p); } | predicate CONT execsize JUMP_LABEL JUMP_LABEL instoptions { add_label(p, $4, INSTR_LABEL_JIP); add_label(p, $5, INSTR_LABEL_UIP); brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $6); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, brw_ip_reg()); if (p->devinfo->gen >= 8) { brw_set_src0(p, brw_last_inst, brw_imm_d(0x0)); } else { brw_set_src0(p, brw_last_inst, brw_ip_reg()); brw_set_src1(p, brw_last_inst, brw_imm_d(0x0)); } brw_pop_insn_state(p); } | predicate CONT execsize relativelocation relativelocation instoptions { brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $6); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, brw_ip_reg()); brw_set_src0(p, brw_last_inst, brw_ip_reg()); brw_set_src1(p, brw_last_inst, brw_imm_d(0x0)); brw_inst_set_gen4_jump_count(p->devinfo, brw_last_inst, $4); brw_inst_set_gen4_pop_count(p->devinfo, brw_last_inst, $5); brw_pop_insn_state(p); } ; /* loop instruction */ loopinstruction: predicate WHILE execsize JUMP_LABEL instoptions { add_label(p, $4, INSTR_LABEL_JIP); brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $5); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); if (p->devinfo->gen >= 8) { brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src0(p, brw_last_inst, brw_imm_d(0x0)); } else if (p->devinfo->gen == 7) { brw_set_dest(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src0(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src1(p, brw_last_inst, brw_imm_w(0x0)); } else { brw_set_dest(p, brw_last_inst, brw_imm_w(0x0)); brw_set_src0(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); brw_set_src1(p, brw_last_inst, retype(brw_null_reg(), BRW_REGISTER_TYPE_D)); } brw_pop_insn_state(p); } | predicate WHILE execsize relativelocation instoptions { brw_next_insn(p, $2); i965_asm_set_instruction_options(p, $5); brw_inst_set_exec_size(p->devinfo, brw_last_inst, $3); brw_set_dest(p, brw_last_inst, brw_ip_reg()); brw_set_src0(p, brw_last_inst, brw_ip_reg()); brw_set_src1(p, brw_last_inst, brw_imm_d(0x0)); brw_inst_set_gen4_jump_count(p->devinfo, brw_last_inst, $4); brw_inst_set_gen4_pop_count(p->devinfo, brw_last_inst, 0); brw_pop_insn_state(p); } | DO execsize instoptions { brw_next_insn(p, $1); if (p->devinfo->gen < 6) { brw_inst_set_exec_size(p->devinfo, brw_last_inst, $2); i965_asm_set_instruction_options(p, $3); brw_set_dest(p, brw_last_inst, brw_null_reg()); brw_set_src0(p, brw_last_inst, brw_null_reg()); brw_set_src1(p, brw_last_inst, brw_null_reg()); brw_inst_set_qtr_control(p->devinfo, brw_last_inst, BRW_COMPRESSION_NONE); } } ; /* Relative location */ relativelocation2: immreg | reg32 ; simple_int: INTEGER { $$ = $1; } | MINUS INTEGER { $$ = -$2; } | LONG { $$ = $1; } | MINUS LONG { $$ = -$2; } ; rellocation: relativelocation | %empty { $$ = 0; } ; relativelocation: simple_int { $$ = $1; } ; jumplabel: JUMP_LABEL { $$ = $1; } | %empty { $$ = NULL; } ; jumplabeltarget: JUMP_LABEL_TARGET { struct target_label *label = rzalloc(p->mem_ctx, struct target_label); label->name = ralloc_strdup(p->mem_ctx, $1); label->offset = p->next_insn_offset; list_addtail(&label->link, &target_labels); } ; /* Destination register */ dst: dstoperand | dstoperandex ; dstoperand: dstreg dstregion writemask reg_type { $$ = $1; $$.vstride = BRW_VERTICAL_STRIDE_1; $$.width = BRW_WIDTH_1; $$.hstride = $2; $$.type = $4; $$.writemask = $3; $$.swizzle = BRW_SWIZZLE_NOOP; $$.subnr = $$.subnr * brw_reg_type_to_size($4); } ; dstoperandex: dstoperandex_typed dstregion writemask reg_type { $$ = $1; $$.hstride = $2; $$.type = $4; $$.writemask = $3; $$.subnr = $$.subnr * brw_reg_type_to_size($4); } /* BSpec says "When the conditional modifier is present, updates * to the selected flag register also occur. In this case, the * register region fields of the ‘null’ operand are valid." */ | nullreg dstregion writemask reg_type { $$ = $1; $$.vstride = BRW_VERTICAL_STRIDE_1; $$.width = BRW_WIDTH_1; $$.hstride = $2; $$.writemask = $3; $$.type = $4; } | threadcontrolreg { $$ = $1; $$.hstride = 1; $$.type = BRW_REGISTER_TYPE_UW; } ; dstoperandex_typed: accreg | addrreg | channelenablereg | controlreg | flagreg | ipreg | maskreg | notifyreg | performancereg | statereg ; dstreg: directgenreg { $$ = $1; $$.address_mode = BRW_ADDRESS_DIRECT; } | indirectgenreg { $$ = $1; $$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; } | directmsgreg { $$ = $1; $$.address_mode = BRW_ADDRESS_DIRECT; } | indirectmsgreg { $$ = $1; $$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; } ; /* Source register */ srcaccimm: srcacc | immreg ; immreg: immval imm_type { switch ($2) { case BRW_REGISTER_TYPE_UD: $$ = brw_imm_ud($1); break; case BRW_REGISTER_TYPE_D: $$ = brw_imm_d($1); break; case BRW_REGISTER_TYPE_UW: $$ = brw_imm_uw($1 | ($1 << 16)); break; case BRW_REGISTER_TYPE_W: $$ = brw_imm_w($1); break; case BRW_REGISTER_TYPE_F: $$ = brw_imm_reg(BRW_REGISTER_TYPE_F); /* Set u64 instead of ud since DIM uses a 64-bit F-typed imm */ $$.u64 = $1; break; case BRW_REGISTER_TYPE_V: $$ = brw_imm_v($1); break; case BRW_REGISTER_TYPE_UV: $$ = brw_imm_uv($1); break; case BRW_REGISTER_TYPE_VF: $$ = brw_imm_vf($1); break; case BRW_REGISTER_TYPE_Q: $$ = brw_imm_q($1); break; case BRW_REGISTER_TYPE_UQ: $$ = brw_imm_uq($1); break; case BRW_REGISTER_TYPE_DF: $$ = brw_imm_reg(BRW_REGISTER_TYPE_DF); $$.d64 = $1; break; default: error(&@2, "Unknown immediate type %s\n", brw_reg_type_to_letters($2)); } } ; reg32: directgenreg region reg_type { $$ = set_direct_src_operand(&$1, $3); $$ = stride($$, $2.vstride, $2.width, $2.hstride); } ; payload: directsrcoperand ; src: directsrcoperand | indirectsrcoperand ; srcacc: directsrcaccoperand | indirectsrcoperand ; srcimm: directsrcoperand | indirectsrcoperand | immreg ; directsrcaccoperand: directsrcoperand | accreg region reg_type { $$ = set_direct_src_operand(&$1, $3); $$.vstride = $2.vstride; $$.width = $2.width; $$.hstride = $2.hstride; } ; srcarcoperandex: srcarcoperandex_typed region reg_type { $$ = brw_reg($1.file, $1.nr, $1.subnr, 0, 0, $3, $2.vstride, $2.width, $2.hstride, BRW_SWIZZLE_NOOP, WRITEMASK_XYZW); } | nullreg region reg_type { $$ = set_direct_src_operand(&$1, $3); $$.vstride = $2.vstride; $$.width = $2.width; $$.hstride = $2.hstride; } | threadcontrolreg { $$ = set_direct_src_operand(&$1, BRW_REGISTER_TYPE_UW); } ; srcarcoperandex_typed: channelenablereg | controlreg | flagreg | ipreg | maskreg | statereg ; indirectsrcoperand: negate abs indirectgenreg indirectregion swizzle reg_type { $$ = brw_reg($3.file, 0, $3.subnr, $1, // negate $2, // abs $6, $4.vstride, $4.width, $4.hstride, $5, WRITEMASK_X); $$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; // brw_reg set indirect_offset to 0 so set it to valid value $$.indirect_offset = $3.indirect_offset; } ; directgenreg_list: directgenreg | directmsgreg | notifyreg | addrreg | performancereg ; directsrcoperand: negate abs directgenreg_list region swizzle reg_type { $$ = brw_reg($3.file, $3.nr, $3.subnr, $1, $2, $6, $4.vstride, $4.width, $4.hstride, $5, WRITEMASK_X); } | srcarcoperandex ; /* Address register */ addrparam: addrreg exp { memset(&$$, '\0', sizeof($$)); $$.subnr = $1.subnr; $$.indirect_offset = $2; } | addrreg ; /* Register files and register numbers */ exp: INTEGER { $$ = $1; } | LONG { $$ = $1; } ; subregnum: DOT exp { $$ = $2; } | %empty %prec SUBREGNUM { $$ = 0; } ; directgenreg: GENREG subregnum { memset(&$$, '\0', sizeof($$)); $$.file = BRW_GENERAL_REGISTER_FILE; $$.nr = $1; $$.subnr = $2; } ; indirectgenreg: GENREGFILE LSQUARE addrparam RSQUARE { memset(&$$, '\0', sizeof($$)); $$.file = BRW_GENERAL_REGISTER_FILE; $$.subnr = $3.subnr; $$.indirect_offset = $3.indirect_offset; } ; directmsgreg: MSGREG subregnum { $$.file = BRW_MESSAGE_REGISTER_FILE; $$.nr = $1; $$.subnr = $2; } ; indirectmsgreg: MSGREGFILE LSQUARE addrparam RSQUARE { memset(&$$, '\0', sizeof($$)); $$.file = BRW_MESSAGE_REGISTER_FILE; $$.subnr = $3.subnr; $$.indirect_offset = $3.indirect_offset; } ; addrreg: ADDRREG subregnum { int subnr = (p->devinfo->gen >= 8) ? 16 : 8; if ($2 > subnr) error(&@2, "Address sub register number %d" "out of range\n", $2); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_ADDRESS; $$.subnr = $2; } ; accreg: ACCREG subregnum { int nr_reg; if (p->devinfo->gen < 8) nr_reg = 2; else nr_reg = 10; if ($1 > nr_reg) error(&@1, "Accumulator register number %d" " out of range\n", $1); memset(&$$, '\0', sizeof($$)); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_ACCUMULATOR; $$.subnr = $2; } ; flagreg: FLAGREG subregnum { // SNB = 1 flag reg and IVB+ = 2 flag reg int nr_reg = (p->devinfo->gen >= 7) ? 2 : 1; int subnr = nr_reg; if ($1 > nr_reg) error(&@1, "Flag register number %d" " out of range \n", $1); if ($2 > subnr) error(&@2, "Flag subregister number %d" " out of range\n", $2); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_FLAG | $1; $$.subnr = $2; } ; maskreg: MASKREG subregnum { if ($1 > 0) error(&@1, "Mask register number %d" " out of range\n", $1); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_MASK; $$.subnr = $2; } ; notifyreg: NOTIFYREG subregnum { int subnr = (p->devinfo->gen >= 11) ? 2 : 3; if ($2 > subnr) error(&@2, "Notification sub register number %d" " out of range\n", $2); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_NOTIFICATION_COUNT; $$.subnr = $2; } ; statereg: STATEREG subregnum { if ($1 > 2) error(&@1, "State register number %d" " out of range\n", $1); if ($2 > 4) error(&@2, "State sub register number %d" " out of range\n", $2); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_STATE; $$.subnr = $2; } ; controlreg: CONTROLREG subregnum { if ($2 > 3) error(&@2, "control sub register number %d" " out of range\n", $2); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_CONTROL; $$.subnr = $2; } ; ipreg: IPREG { $$ = brw_ip_reg(); } ; nullreg: NULL_TOKEN { $$ = brw_null_reg(); } ; threadcontrolreg: THREADREG subregnum { if ($2 > 7) error(&@2, "Thread control sub register number %d" " out of range\n", $2); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_TDR; $$.subnr = $2; } ; performancereg: PERFORMANCEREG subregnum { int subnr; if (p->devinfo->gen >= 10) subnr = 5; else if (p->devinfo->gen <= 8) subnr = 3; else subnr = 4; if ($2 > subnr) error(&@2, "Performance sub register number %d" " out of range\n", $2); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_TIMESTAMP; $$.subnr = $2; } ; channelenablereg: CHANNELENABLEREG subregnum { if ($1 > 0) error(&@1, "Channel enable register number %d" " out of range\n", $1); $$.file = BRW_ARCHITECTURE_REGISTER_FILE; $$.nr = BRW_ARF_MASK; $$.subnr = $2; } ; /* Immediate values */ immval: exp2 { $$ = $1; } | LSQUARE exp2 COMMA exp2 COMMA exp2 COMMA exp2 RSQUARE { $$ = ($2 << 0) | ($4 << 8) | ($6 << 16) | ($8 << 24); } ; /* Regions */ dstregion: %empty { $$ = BRW_HORIZONTAL_STRIDE_1; } | LANGLE exp RANGLE { if ($2 != 0 && ($2 > 4 || !isPowerofTwo($2))) error(&@2, "Invalid Horizontal stride %d\n", $2); $$ = ffs($2); } ; indirectregion: region | region_wh ; region: %empty { $$ = stride($$, 0, 1, 0); } | LANGLE exp RANGLE { if ($2 != 0 && ($2 > 32 || !isPowerofTwo($2))) error(&@2, "Invalid VertStride %d\n", $2); $$ = stride($$, $2, 1, 0); } | LANGLE exp COMMA exp COMMA exp RANGLE { if ($2 != 0 && ($2 > 32 || !isPowerofTwo($2))) error(&@2, "Invalid VertStride %d\n", $2); if ($4 > 16 || !isPowerofTwo($4)) error(&@4, "Invalid width %d\n", $4); if ($6 != 0 && ($6 > 4 || !isPowerofTwo($6))) error(&@6, "Invalid Horizontal stride in" " region_wh %d\n", $6); $$ = stride($$, $2, $4, $6); } | LANGLE exp SEMICOLON exp COMMA exp RANGLE { if ($2 != 0 && ($2 > 32 || !isPowerofTwo($2))) error(&@2, "Invalid VertStride %d\n", $2); if ($4 > 16 || !isPowerofTwo($4)) error(&@4, "Invalid width %d\n", $4); if ($6 != 0 && ($6 > 4 || !isPowerofTwo($6))) error(&@6, "Invalid Horizontal stride in" " region_wh %d\n", $6); $$ = stride($$, $2, $4, $6); } | LANGLE VxH COMMA exp COMMA exp RANGLE { if ($4 > 16 || !isPowerofTwo($4)) error(&@4, "Invalid width %d\n", $4); if ($6 != 0 && ($6 > 4 || !isPowerofTwo($6))) error(&@6, "Invalid Horizontal stride in" " region_wh %d\n", $6); $$ = brw_VxH_indirect(0, 0); } ; region_wh: LANGLE exp COMMA exp RANGLE { if ($2 > 16 || !isPowerofTwo($2)) error(&@2, "Invalid width %d\n", $2); if ($4 != 0 && ($4 > 4 || !isPowerofTwo($4))) error(&@4, "Invalid Horizontal stride in" " region_wh %d\n", $4); $$ = stride($$, 0, $2, $4); $$.vstride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL; } ; reg_type: TYPE_F { $$ = BRW_REGISTER_TYPE_F; } | TYPE_UD { $$ = BRW_REGISTER_TYPE_UD; } | TYPE_D { $$ = BRW_REGISTER_TYPE_D; } | TYPE_UW { $$ = BRW_REGISTER_TYPE_UW; } | TYPE_W { $$ = BRW_REGISTER_TYPE_W; } | TYPE_UB { $$ = BRW_REGISTER_TYPE_UB; } | TYPE_B { $$ = BRW_REGISTER_TYPE_B; } | TYPE_DF { $$ = BRW_REGISTER_TYPE_DF; } | TYPE_UQ { $$ = BRW_REGISTER_TYPE_UQ; } | TYPE_Q { $$ = BRW_REGISTER_TYPE_Q; } | TYPE_HF { $$ = BRW_REGISTER_TYPE_HF; } | TYPE_NF { $$ = BRW_REGISTER_TYPE_NF; } ; imm_type: reg_type { $$ = $1; } | TYPE_V { $$ = BRW_REGISTER_TYPE_V; } | TYPE_VF { $$ = BRW_REGISTER_TYPE_VF; } | TYPE_UV { $$ = BRW_REGISTER_TYPE_UV; } ; writemask: %empty { $$ = WRITEMASK_XYZW; } | DOT writemask_x writemask_y writemask_z writemask_w { $$ = $2 | $3 | $4 | $5; } ; writemask_x: %empty { $$ = 0; } | X { $$ = 1 << BRW_CHANNEL_X; } ; writemask_y: %empty { $$ = 0; } | Y { $$ = 1 << BRW_CHANNEL_Y; } ; writemask_z: %empty { $$ = 0; } | Z { $$ = 1 << BRW_CHANNEL_Z; } ; writemask_w: %empty { $$ = 0; } | W { $$ = 1 << BRW_CHANNEL_W; } ; swizzle: %empty { $$ = BRW_SWIZZLE_NOOP; } | DOT chansel { $$ = BRW_SWIZZLE4($2, $2, $2, $2); } | DOT chansel chansel chansel chansel { $$ = BRW_SWIZZLE4($2, $3, $4, $5); } ; chansel: X | Y | Z | W ; /* Instruction prediction and modifiers */ predicate: %empty { brw_push_insn_state(p); brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); brw_set_default_flag_reg(p, 0, 0); brw_set_default_predicate_inverse(p, false); } | LPAREN predstate flagreg predctrl RPAREN { brw_push_insn_state(p); brw_set_default_predicate_inverse(p, $2); brw_set_default_flag_reg(p, $3.nr, $3.subnr); brw_set_default_predicate_control(p, $4); } ; predstate: %empty { $$ = 0; } | PLUS { $$ = 0; } | MINUS { $$ = 1; } ; predctrl: %empty { $$ = BRW_PREDICATE_NORMAL; } | DOT X { $$ = BRW_PREDICATE_ALIGN16_REPLICATE_X; } | DOT Y { $$ = BRW_PREDICATE_ALIGN16_REPLICATE_Y; } | DOT Z { $$ = BRW_PREDICATE_ALIGN16_REPLICATE_Z; } | DOT W { $$ = BRW_PREDICATE_ALIGN16_REPLICATE_W; } | ANYV | ALLV | ANY2H | ALL2H | ANY4H | ALL4H | ANY8H | ALL8H | ANY16H | ALL16H | ANY32H | ALL32H ; /* Source Modification */ negate: %empty { $$ = 0; } | MINUS { $$ = 1; } ; abs: %empty { $$ = 0; } | ABS { $$ = 1; } ; /* Flag (Conditional) Modifier */ cond_mod: condModifiers { $$.cond_modifier = $1; $$.flag_reg_nr = 0; $$.flag_subreg_nr = 0; } | condModifiers DOT flagreg { $$.cond_modifier = $1; $$.flag_reg_nr = $3.nr; $$.flag_subreg_nr = $3.subnr; } ; condModifiers: %empty { $$ = BRW_CONDITIONAL_NONE; } | ZERO | EQUAL | NOT_ZERO | NOT_EQUAL | GREATER | GREATER_EQUAL | LESS | LESS_EQUAL | OVERFLOW | ROUND_INCREMENT | UNORDERED ; saturate: %empty { $$ = BRW_INSTRUCTION_NORMAL; } | SATURATE { $$ = BRW_INSTRUCTION_SATURATE; } ; /* Execution size */ execsize: %empty %prec EMPTYEXECSIZE { $$ = 0; } | LPAREN exp2 RPAREN { if ($2 > 32 || !isPowerofTwo($2)) error(&@2, "Invalid execution size %d\n", $2); $$ = cvt($2) - 1; } ; /* Instruction options */ instoptions: %empty { memset(&$$, 0, sizeof($$)); } | LCURLY instoption_list RCURLY { memset(&$$, 0, sizeof($$)); $$ = $2; } ; instoption_list: instoption_list COMMA instoption { memset(&$$, 0, sizeof($$)); $$ = $1; add_instruction_option(&$$, $3); } | instoption_list instoption { memset(&$$, 0, sizeof($$)); $$ = $1; add_instruction_option(&$$, $2); } | %empty { memset(&$$, 0, sizeof($$)); } ; instoption: ALIGN1 { $$ = ALIGN1;} | ALIGN16 { $$ = ALIGN16; } | ACCWREN { $$ = ACCWREN; } | SECHALF { $$ = SECHALF; } | COMPR { $$ = COMPR; } | COMPR4 { $$ = COMPR4; } | BREAKPOINT { $$ = BREAKPOINT; } | NODDCLR { $$ = NODDCLR; } | NODDCHK { $$ = NODDCHK; } | MASK_DISABLE { $$ = MASK_DISABLE; } | EOT { $$ = EOT; } | SWITCH { $$ = SWITCH; } | ATOMIC { $$ = ATOMIC; } | CMPTCTRL { $$ = CMPTCTRL; } | WECTRL { $$ = WECTRL; } | QTR_2Q { $$ = QTR_2Q; } | QTR_3Q { $$ = QTR_3Q; } | QTR_4Q { $$ = QTR_4Q; } | QTR_2H { $$ = QTR_2H; } | QTR_2N { $$ = QTR_2N; } | QTR_3N { $$ = QTR_3N; } | QTR_4N { $$ = QTR_4N; } | QTR_5N { $$ = QTR_5N; } | QTR_6N { $$ = QTR_6N; } | QTR_7N { $$ = QTR_7N; } | QTR_8N { $$ = QTR_8N; } ; %% extern int yylineno; void yyerror(char *msg) { fprintf(stderr, "%s: %d: %s at \"%s\"\n", input_filename, yylineno, msg, lex_text()); ++errors; }