%{ /* * Copyright © 2006 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. * * Authors: * Eric Anholt * */ #include #include #include "gen4asm.h" #include "brw_defines.h" %} %start ROOT %union { char *s; int integer; double number; struct brw_instruction instruction; struct brw_program program; struct region { int vert_stride, width, horiz_stride; } region; struct gen_reg { int reg_file, reg_nr, subreg_nr; } direct_reg; double imm32; struct src_operand src_operand; } %token SEMICOLON %token LPAREN RPAREN %token LANGLE RANGLE %token LCURLY RCURLY %token COMMA %token DOT %token MINUS ABS %token TYPE_UD, TYPE_D, TYPE_UW, TYPE_W, TYPE_UB, TYPE_B, %token TYPE_VF, TYPE_HF, TYPE_V, TYPE_F %token ALIGN1 ALIGN16 SECHALF COMPR SWITCH ATOMIC NODDCHK NODDCLR %token MASK_DISABLE BREAKPOINT EOT %token GENREG MSGREG ADDRESSREG ACCREG FLAGREG %token MASKREG AMASK IMASK LMASK CMASK %token MASKSTACKREG LMS IMS MASKSTACKDEPTHREG IMSD LMSD %token NOTIFYREG STATEREG CONTROLREG IPREG %token MOV FRC RNDU RNDD RNDE RNDZ NOT LZD %token MUL MAC MACH LINE SAD2 SADA2 DP4 DPH DP3 DP2 %token AVG ADD SEL AND OR XOR SHR SHL ASR CMP CMPN %token SEND NOP JMPI IF IFF WHILE SEND ELSE BREAK CONT HALT MSAVE %token PUSH MREST POP WAIT DO ENDIF ILLEGAL %token NULL_TOKEN MATH SAMPLER GATEWAY READ WRITE URB THREAD_SPAWNER %token MSGLEN RETURNLEN %token ALLOCATE USED COMPLETE TRANSPOSE INTERLEAVE %token SATURATE %token INTEGER %token NUMBER %token INV LOG EXP SQRT RSQ POW SIN COS SINCOS INTDIV INTMOD %token INTDIVMOD %token SIGNED SCALAR %token X Y Z W %type instruction unaryinstruction binaryinstruction %type binaryaccinstruction triinstruction sendinstruction %type specialinstruction %type dst dstoperand dstoperandex dstreg %type post_dst msgtarget %type instoptions instoption_list %type instrseq %type instoption %type unaryop binaryop binaryaccop %type conditionalmodifier saturate negate abs chansel %type regtype srcimmtype execsize dstregion %type subregnum sampler_datatype %type urb_swizzle urb_allocate urb_used urb_complete %type math_function math_signed math_scalar %type region %type directgenreg directmsgreg addrreg accreg flagreg maskreg %type maskstackreg maskstackdepthreg notifyreg %type statereg controlreg ipreg nullreg %type dstoperandex_typed srcarchoperandex_typed %type mask_subreg maskstack_subreg maskstackdepth_subreg %type imm32 %type directsrcoperand srcarchoperandex directsrcaccoperand %type src srcimm imm32reg payload srcacc srcaccimm swizzle %% ROOT: instrseq { compiled_program = $1; } ; instrseq: instruction SEMICOLON instrseq { struct brw_program_instruction *list_entry = calloc(sizeof(struct brw_program_instruction), 1); list_entry->instruction = $1; list_entry->next = $3.first; $3.first = list_entry; $$ = $3; } | instruction SEMICOLON { struct brw_program_instruction *list_entry = calloc(sizeof(struct brw_program_instruction), 1); list_entry->instruction = $1; list_entry->next = NULL; $$.first = list_entry; } | error SEMICOLON instrseq { $$ = $3; } ; /* 1.4.1: Instruction groups */ instruction: unaryinstruction | binaryinstruction | binaryaccinstruction | triinstruction | specialinstruction ; unaryinstruction: predicate unaryop conditionalmodifier saturate execsize dst srcaccimm instoptions { bzero(&$$, sizeof($$)); $$.header.opcode = $2; $$.header.destreg__conditionalmod = $3; $$.header.saturate = $4; $$.header.execution_size = $5; set_instruction_options(&$$, &$8); set_instruction_dest(&$$, &$6); if (set_instruction_src0(&$$, &$7) != 0) YYERROR; } ; unaryop: MOV | FRC | RNDU | RNDD | RNDE | RNDZ | NOT | LZD ; binaryinstruction: predicate binaryop conditionalmodifier saturate execsize dst src srcimm instoptions { bzero(&$$, sizeof($$)); $$.header.opcode = $2; $$.header.destreg__conditionalmod = $3; $$.header.saturate = $4; $$.header.execution_size = $5; set_instruction_options(&$$, &$9); set_instruction_dest(&$$, &$6); if (set_instruction_src0(&$$, &$7) != 0) YYERROR; if (set_instruction_src1(&$$, &$8) != 0) YYERROR; } ; binaryop: MUL | MAC | MACH | LINE | SAD2 | SADA2 | DP4 | DPH | DP3 | DP2 ; binaryaccinstruction: predicate binaryaccop conditionalmodifier saturate execsize dst srcacc srcimm instoptions { bzero(&$$, sizeof($$)); $$.header.opcode = $2; $$.header.destreg__conditionalmod = $3; $$.header.saturate = $4; $$.header.execution_size = $5; set_instruction_options(&$$, &$9); set_instruction_dest(&$$, &$6); if (set_instruction_src0(&$$, &$7) != 0) YYERROR; if (set_instruction_src1(&$$, &$8) != 0) YYERROR; } ; binaryaccop: AVG | ADD | SEL | AND | OR | XOR | SHR | SHL | ASR | CMP | CMPN ; triinstruction: sendinstruction ; sendinstruction: predicate SEND execsize INTEGER post_dst payload msgtarget MSGLEN INTEGER RETURNLEN INTEGER instoptions { /* Send instructions are messy. The first argument is the * post destination -- the grf register that the response * starts from. The second argument is the current * destination, which is the start of the message arguments * to the shared function, and where src0 payload is loaded * to if not null. The payload is typically based on the * grf 0 thread payload of your current thread, and is * implicitly loaded if non-null. */ bzero(&$$, sizeof($$)); $$.header.opcode = $2; $$.header.execution_size = $3; $$.header.destreg__conditionalmod = $4; /* msg reg index */ set_instruction_dest(&$$, &$5); if (set_instruction_src0(&$$, &$6) != 0) YYERROR; $$.bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE; $$.bits1.da1.src1_reg_type = BRW_REGISTER_TYPE_D; $$.bits3.generic = $7.bits3.generic; $$.bits3.generic.msg_length = $9; $$.bits3.generic.response_length = $11; $$.bits3.generic.end_of_thread = $12.bits3.generic.end_of_thread; } ; branchloopop: IF | IFF | WHILE ; breakop: BREAK | CONT | WAIT ; maskpushop: MSAVE | PUSH ; specialinstruction: NOP { bzero(&$$, sizeof($$)); $$.header.opcode = $1; } ; /* XXX! */ payload: directsrcoperand ; post_dst: dst ; msgtarget: NULL_TOKEN { $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_NULL; } | SAMPLER LPAREN INTEGER COMMA INTEGER COMMA sampler_datatype RPAREN { $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_SAMPLER; $$.bits3.sampler.binding_table_index = $3; $$.bits3.sampler.sampler = $5; switch ($7) { case TYPE_F: $$.bits3.sampler.return_format = BRW_SAMPLER_RETURN_FORMAT_FLOAT32; break; case TYPE_UD: $$.bits3.sampler.return_format = BRW_SAMPLER_RETURN_FORMAT_UINT32; break; case TYPE_D: $$.bits3.sampler.return_format = BRW_SAMPLER_RETURN_FORMAT_SINT32; break; } } | MATH math_function saturate math_signed math_scalar { $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_MATH; $$.bits3.math.function = $2; if ($3 == BRW_INSTRUCTION_SATURATE) $$.bits3.math.saturate = 1; else $$.bits3.math.saturate = 0; $$.bits3.math.int_type = $4; $$.bits3.math.precision = BRW_MATH_PRECISION_FULL; $$.bits3.math.data_type = $5; } | GATEWAY { $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_GATEWAY; } | READ { $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_DATAPORT_READ; } | WRITE LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA INTEGER RPAREN { $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_DATAPORT_WRITE; $$.bits3.dp_write.binding_table_index = $3; /* The msg control field of brw_struct.h is split into * msg control and pixel_scoreboard_clear, even though * pixel_scoreboard_clear isn't common to all write messages. */ $$.bits3.dp_write.pixel_scoreboard_clear = ($5 & 0x8) >> 3; $$.bits3.dp_write.msg_control = $5 & 0x7; $$.bits3.dp_write.msg_type = $7; $$.bits3.dp_write.send_commit_msg = $9; } | URB INTEGER urb_swizzle urb_allocate urb_used urb_complete { $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_URB; $$.bits3.urb.opcode = BRW_URB_OPCODE_WRITE; $$.bits3.urb.offset = $2; $$.bits3.urb.swizzle_control = $3; $$.bits3.urb.pad = 0; $$.bits3.urb.allocate = $4; $$.bits3.urb.used = $5; $$.bits3.urb.complete = $6; } | THREAD_SPAWNER { $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_THREAD_SPAWNER; } ; urb_allocate: ALLOCATE { $$ = 1; } | /* empty */ { $$ = 0; } ; urb_used: USED { $$ = 1; } | /* empty */ { $$ = 0; } ; urb_complete: COMPLETE { $$ = 1; } | /* empty */ { $$ = 0; } ; urb_swizzle: TRANSPOSE { $$ = BRW_URB_SWIZZLE_TRANSPOSE; } | INTERLEAVE { $$ = BRW_URB_SWIZZLE_INTERLEAVE; } | /* empty */ { $$ = BRW_URB_SWIZZLE_NONE; } ; sampler_datatype: TYPE_F | TYPE_UD | TYPE_D ; math_function: INV | LOG | EXP | SQRT | POW | SIN | COS | SINCOS | INTDIV | INTMOD | INTDIVMOD ; math_signed: /* empty */ { $$ = 0; } | SIGNED { $$ = 1; } ; math_scalar: /* empty */ { $$ = 0; } | SCALAR { $$ = 1; } ; /* 1.4.2: Destination register */ dst: dstoperand | dstoperandex ; /* XXX: writemask */ dstoperand: dstreg dstregion regtype { /* Returns an instruction with just the destination register * filled in. */ $$.bits1 = $1.bits1; $$.bits1.da1.dest_horiz_stride = $2; $$.bits1.da1.dest_reg_type = $3; } ; /* The dstoperandex returns an instruction with just the destination register * filled in. */ dstoperandex: dstoperandex_typed dstregion regtype { $$.bits1.da1.dest_reg_file = $1.reg_file; $$.bits1.da1.dest_reg_nr = $1.reg_nr; $$.bits1.da1.dest_subreg_nr = $1.subreg_nr; $$.bits1.da1.dest_horiz_stride = $2; $$.bits1.da1.dest_reg_type = $3; } | maskstackreg { $$.bits1.da1.dest_reg_file = $1.reg_file; $$.bits1.da1.dest_reg_nr = $1.reg_nr; $$.bits1.da1.dest_subreg_nr = $1.subreg_nr; $$.bits1.da1.dest_horiz_stride = 1; $$.bits1.da1.dest_reg_type = BRW_REGISTER_TYPE_UW; } | controlreg { $$.bits1.da1.dest_reg_file = $1.reg_file; $$.bits1.da1.dest_reg_nr = $1.reg_nr; $$.bits1.da1.dest_subreg_nr = $1.subreg_nr; $$.bits1.da1.dest_horiz_stride = 1; $$.bits1.da1.dest_reg_type = BRW_REGISTER_TYPE_UD; } | ipreg { $$.bits1.da1.dest_reg_file = $1.reg_file; $$.bits1.da1.dest_reg_nr = $1.reg_nr; $$.bits1.da1.dest_subreg_nr = $1.subreg_nr; $$.bits1.da1.dest_horiz_stride = 1; $$.bits1.da1.dest_reg_type = BRW_REGISTER_TYPE_UD; } | nullreg { $$.bits1.da1.dest_reg_file = $1.reg_file; $$.bits1.da1.dest_reg_nr = $1.reg_nr; $$.bits1.da1.dest_subreg_nr = $1.subreg_nr; $$.bits1.da1.dest_horiz_stride = 1; $$.bits1.da1.dest_reg_type = BRW_REGISTER_TYPE_F; } ; dstoperandex_typed: accreg | flagreg | addrreg | maskreg ; /* XXX: indirectgenreg, indirectmsgreg */ dstreg: directgenreg { $$.bits1.da1.dest_reg_file = $1.reg_file; $$.bits1.da1.dest_reg_nr = $1.reg_nr; $$.bits1.da1.dest_subreg_nr = $1.subreg_nr; } | directmsgreg { $$.bits1.da1.dest_reg_file = $1.reg_file; $$.bits1.da1.dest_reg_nr = $1.reg_nr; $$.bits1.da1.dest_subreg_nr = $1.subreg_nr; } ; /* 1.4.3: Source register */ srcaccimm: srcacc | imm32reg ; /* XXX: indirectsrcaccoperand */ srcacc: directsrcaccoperand ; srcimm: directsrcoperand | imm32reg ; imm32reg: imm32 srcimmtype { union { int i; float f; } intfloat; $$.reg_file = BRW_IMMEDIATE_VALUE; $$.reg_type = $2; switch ($2) { case BRW_REGISTER_TYPE_UD: $$.imm32 = $1; break; case BRW_REGISTER_TYPE_D: $$.imm32 = $1; break; case BRW_REGISTER_TYPE_UW: $$.imm32 = $1; break; case BRW_REGISTER_TYPE_W: $$.imm32 = $1; break; case BRW_REGISTER_TYPE_UB: /* There is no native byte immediate type */ $$.imm32 = (unsigned int)$1; $$.reg_type = BRW_REGISTER_TYPE_UD; break; case BRW_REGISTER_TYPE_B: /* There is no native byte immediate type */ $$.imm32 = (int)$1; $$.reg_type = BRW_REGISTER_TYPE_D; break; case BRW_REGISTER_TYPE_F: intfloat.f = $1; $$.imm32 = intfloat.i; break; default: fprintf(stderr, "unknown immediate type %d\n", $2); YYERROR; } } ; directsrcaccoperand: directsrcoperand | accreg regtype { set_src_operand(&$$, &$1, $2); } ; /* Returns a source operand in the src0 fields of an instruction. */ srcarchoperandex: srcarchoperandex_typed region regtype { $$.reg_file = $1.reg_file; $$.reg_type = $3; $$.subreg_nr = $1.subreg_nr; $$.reg_nr = $1.reg_nr; $$.vert_stride = $2.vert_stride; $$.width = $2.width; $$.horiz_stride = $2.horiz_stride; $$.negate = 0; $$.abs = 0; } | maskstackreg { set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UB); } | controlreg { set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } | statereg { set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } | notifyreg { set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } | ipreg { set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } | nullreg { set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } ; srcarchoperandex_typed: flagreg | addrreg | maskreg ; /* XXX: indirectsrcoperand */ src: directsrcoperand ; directsrcoperand: negate abs directgenreg region regtype swizzle { $$.reg_file = $3.reg_file; $$.reg_nr = $3.reg_nr; $$.subreg_nr = $3.subreg_nr; $$.reg_type = $5; $$.vert_stride = $4.vert_stride; $$.width = $4.width; $$.horiz_stride = $4.horiz_stride; $$.negate = $1; $$.abs = $2; $$.swizzle_set = $6.swizzle_set; $$.swizzle_x = $6.swizzle_x; $$.swizzle_y = $6.swizzle_y; $$.swizzle_z = $6.swizzle_z; $$.swizzle_w = $6.swizzle_w; } | srcarchoperandex ; /* 1.4.5: Register files and register numbers */ subregnum: DOT INTEGER { $$ = $2; } | { /* Default to subreg 0 if unspecified. */ $$ = 0; } ; directgenreg: GENREG subregnum { $$.reg_file = BRW_GENERAL_REGISTER_FILE; $$.reg_nr = $1; $$.subreg_nr = $2; } ; directmsgreg: MSGREG subregnum { $$.reg_file = BRW_MESSAGE_REGISTER_FILE; $$.reg_nr = $1; $$.subreg_nr = $2; } ; addrreg: ADDRESSREG subregnum { $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_ADDRESS | $1; $$.subreg_nr = $2; } ; accreg: ACCREG subregnum { if ($1 > 1) { fprintf(stderr, "accumulator register number %d out of range", $1); YYERROR; } $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_ACCUMULATOR | $1; $$.subreg_nr = $2; } ; flagreg: FLAGREG subregnum { if ($1 > 0) { fprintf(stderr, "flag register number %d out of range", $1); YYERROR; } $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_FLAG | $1; $$.subreg_nr = $2; } ; maskreg: MASKREG subregnum { if ($1 > 0) { fprintf(stderr, "mask register number %d out of range", $1); YYERROR; } $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_MASK; $$.subreg_nr = $2; } | mask_subreg { $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_MASK; $$.subreg_nr = $1; } ; mask_subreg: AMASK | IMASK | LMASK | CMASK ; maskstackreg: MASKSTACKREG subregnum { if ($1 > 0) { fprintf(stderr, "mask stack register number %d out of range", $1); YYERROR; } $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_MASK_STACK; $$.subreg_nr = $2; } | maskstack_subreg { $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_MASK_STACK; $$.subreg_nr = $1; } ; maskstack_subreg: IMS | LMS ; maskstackdepthreg: MASKSTACKDEPTHREG subregnum { if ($1 > 0) { fprintf(stderr, "mask stack register number %d out of range", $1); YYERROR; } $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_MASK_STACK_DEPTH; $$.subreg_nr = $2; } | maskstackdepth_subreg { $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_MASK_STACK_DEPTH; $$.subreg_nr = $1; } ; maskstackdepth_subreg: IMSD | LMSD ; notifyreg: NOTIFYREG { if ($1 > 1) { fprintf(stderr, "notification register number %d out of range", $1); YYERROR; } $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_NOTIFICATION_COUNT; $$.subreg_nr = 0; } ; statereg: STATEREG subregnum { if ($1 > 0) { fprintf(stderr, "state register number %d out of range", $1); YYERROR; } if ($2 > 1) { fprintf(stderr, "state subregister number %d out of range", $1); YYERROR; } $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_STATE | $1; $$.subreg_nr = $2; } ; controlreg: CONTROLREG subregnum { if ($1 > 0) { fprintf(stderr, "control register number %d out of range", $1); YYERROR; } if ($2 > 2) { fprintf(stderr, "control subregister number %d out of range", $1); YYERROR; } $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_CONTROL | $1; $$.subreg_nr = $2; } ; ipreg: IPREG { $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_IP; $$.subreg_nr = 0; } ; nullreg: NULL_TOKEN { $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_NULL; $$.subreg_nr = 0; } ; /* 1.4.7: Regions */ dstregion: LANGLE INTEGER RANGLE { /* Returns a value for a horiz_stride field of an * instruction. */ if ($2 != 1 && $2 != 2 && $2 != 4) { fprintf(stderr, "Invalid horiz size %d\n", $2); } $$ = ffs($2); } ; region: LANGLE INTEGER COMMA INTEGER COMMA INTEGER RANGLE { $$.vert_stride = ffs($2); $$.width = ffs($4) - 1; $$.horiz_stride = ffs($6); } ; /* 1.4.8: Types */ /* regtype returns an integer register type suitable for inserting into an * instruction. */ regtype: 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; } ; /* XXX: Add TYPE_VF and TYPE_HF */ srcimmtype: regtype ; /* 1.4.10: Swizzle control */ /* Returns the swizzle control for an align16 instruction's source operand * in the src0 fields. */ swizzle: /* empty */ { $$.swizzle_set = 0; $$.swizzle_x = BRW_CHANNEL_X; $$.swizzle_y = BRW_CHANNEL_Y; $$.swizzle_z = BRW_CHANNEL_Z; $$.swizzle_w = BRW_CHANNEL_W; } | DOT chansel { $$.swizzle_set = 1; $$.swizzle_x = $2; $$.swizzle_y = $2; $$.swizzle_z = $2; $$.swizzle_w = $2; } | DOT chansel chansel chansel chansel { $$.swizzle_set = 1; $$.swizzle_x = $2; $$.swizzle_y = $3; $$.swizzle_z = $4; $$.swizzle_w = $5; } ; chansel: X | Y | Z | W ; /* 1.4.11: Immediate values */ imm32: INTEGER { $$ = $1; } | NUMBER { $$ = $1; } ; /* 1.4.12: Predication and modifiers */ /* XXX: do the predicate */ predicate: ; negate: /* empty */ { $$ = 0; } | MINUS { $$ = 1; } ; abs: /* empty */ { $$ = 0; } | ABS { $$ = 1; } ; execsize: LPAREN INTEGER RPAREN { /* Returns a value for the execution_size field of an * instruction. */ if ($2 != 1 && $2 != 2 && $2 != 4 && $2 != 8 && $2 != 16 && $2 != 32) { fprintf(stderr, "Invalid execution size %d\n", $2); YYERROR; } $$ = ffs($2) - 1; } ; saturate: /* empty */ { $$ = BRW_INSTRUCTION_NORMAL; } | DOT SATURATE { $$ = BRW_INSTRUCTION_SATURATE; } ; conditionalmodifier: { $$ = 0; } ; /* 1.4.13: Instruction options */ instoptions: LCURLY instoption_list RCURLY { $$ = $2; } ; instoption_list: instoption instoption_list { $$ = $2; switch ($1) { case ALIGN1: $$.header.access_mode = BRW_ALIGN_1; break; case ALIGN16: $$.header.access_mode = BRW_ALIGN_16; break; case SECHALF: $$.header.compression_control |= BRW_COMPRESSION_2NDHALF; break; case COMPR: $$.header.compression_control |= BRW_COMPRESSION_COMPRESSED; break; case SWITCH: $$.header.thread_control |= BRW_THREAD_SWITCH; break; case ATOMIC: $$.header.thread_control |= BRW_THREAD_ATOMIC; break; case NODDCHK: $$.header.dependency_control |= BRW_DEPENDENCY_NOTCHECKED; break; case NODDCLR: $$.header.dependency_control |= BRW_DEPENDENCY_NOTCLEARED; break; case MASK_DISABLE: $$.header.mask_control = BRW_MASK_DISABLE; break; case BREAKPOINT: $$.header.debug_control = BRW_DEBUG_BREAKPOINT; break; case EOT: /* XXX: EOT shouldn't be an instoption, I don't think */ $$.bits3.generic.end_of_thread = 1; break; } } | /* empty, header defaults to zeroes. */ { bzero(&$$, sizeof($$)); } ; instoption: ALIGN1 { $$ = ALIGN1; } | ALIGN16 { $$ = ALIGN16; } | SECHALF { $$ = SECHALF; } | COMPR { $$ = COMPR; } | SWITCH { $$ = SWITCH; } | ATOMIC { $$ = ATOMIC; } | NODDCHK { $$ = NODDCHK; } | NODDCLR { $$ = NODDCLR; } | MASK_DISABLE { $$ = MASK_DISABLE; } | BREAKPOINT { $$ = BREAKPOINT; } | EOT { $$ = EOT; } ; %% extern int yylineno; void yyerror (char *msg) { fprintf(stderr, "parse error \"%s\" at line %d, token \"%s\"\n", msg, yylineno, lex_text()); } /** * Fills in the destination register information in instr from the bits in dst. */ void set_instruction_dest(struct brw_instruction *instr, struct brw_instruction *dest) { instr->bits1.da1.dest_reg_file = dest->bits1.da1.dest_reg_file; instr->bits1.da1.dest_reg_type = dest->bits1.da1.dest_reg_type; instr->bits1.da1.dest_subreg_nr = dest->bits1.da1.dest_subreg_nr; instr->bits1.da1.dest_reg_nr = dest->bits1.da1.dest_reg_nr; instr->bits1.da1.dest_horiz_stride = dest->bits1.da1.dest_horiz_stride; instr->bits1.da1.dest_address_mode = dest->bits1.da1.dest_address_mode; } /* Sets the first source operand for the instruction. Returns 0 on success. */ int set_instruction_src0(struct brw_instruction *instr, struct src_operand *src) { instr->bits1.da1.src0_reg_file = src->reg_file; instr->bits1.da1.src0_reg_type = src->reg_type; if (src->reg_file == BRW_IMMEDIATE_VALUE) { instr->bits3.ud = src->imm32; } else if (instr->header.access_mode == BRW_ALIGN_1) { instr->bits2.da1.src0_subreg_nr = src->subreg_nr; instr->bits2.da1.src0_reg_nr = src->reg_nr; instr->bits2.da1.src0_vert_stride = src->vert_stride; instr->bits2.da1.src0_width = src->width; instr->bits2.da1.src0_horiz_stride = src->horiz_stride; instr->bits2.da1.src0_negate = src->negate; instr->bits2.da1.src0_abs = src->abs; instr->bits2.da1.src0_address_mode = src->address_mode; if (src->swizzle_set) { fprintf(stderr, "error: swizzle bits set in align1 " "instruction\n"); return 1; } } else { instr->bits2.da16.src0_subreg_nr = src->subreg_nr; instr->bits2.da16.src0_reg_nr = src->reg_nr; instr->bits2.da16.src0_vert_stride = src->vert_stride; instr->bits2.da16.src0_negate = src->negate; instr->bits2.da16.src0_abs = src->abs; instr->bits2.da16.src0_swz_x = src->swizzle_x; instr->bits2.da16.src0_swz_y = src->swizzle_y; instr->bits2.da16.src0_swz_z = src->swizzle_z; instr->bits2.da16.src0_swz_w = src->swizzle_w; instr->bits2.da16.src0_address_mode = src->address_mode; } return 0; } /* Sets the second source operand for the instruction. Returns 0 on success. */ int set_instruction_src1(struct brw_instruction *instr, struct src_operand *src) { instr->bits1.da1.src1_reg_file = src->reg_file; instr->bits1.da1.src1_reg_type = src->reg_type; if (src->reg_file == BRW_IMMEDIATE_VALUE) { instr->bits3.ud = src->imm32; } else if (instr->header.access_mode == BRW_ALIGN_1) { instr->bits3.da1.src1_subreg_nr = src->subreg_nr; instr->bits3.da1.src1_reg_nr = src->reg_nr; instr->bits3.da1.src1_vert_stride = src->vert_stride; instr->bits3.da1.src1_width = src->width; instr->bits3.da1.src1_horiz_stride = src->horiz_stride; instr->bits3.da1.src1_negate = src->negate; instr->bits3.da1.src1_abs = src->abs; if (src->address_mode != BRW_ADDRESS_DIRECT) { fprintf(stderr, "error: swizzle bits set in align1 " "instruction\n"); return 1; } if (src->swizzle_set) { fprintf(stderr, "error: swizzle bits set in align1 " "instruction\n"); return 1; } } else { instr->bits3.da16.src1_subreg_nr = src->subreg_nr; instr->bits3.da16.src1_reg_nr = src->reg_nr; instr->bits3.da16.src1_vert_stride = src->vert_stride; instr->bits3.da16.src1_negate = src->negate; instr->bits3.da16.src1_abs = src->abs; instr->bits3.da16.src1_swz_x = src->swizzle_x; instr->bits3.da16.src1_swz_y = src->swizzle_y; instr->bits3.da16.src1_swz_z = src->swizzle_z; instr->bits3.da16.src1_swz_w = src->swizzle_w; if (src->address_mode != BRW_ADDRESS_DIRECT) { fprintf(stderr, "error: swizzle bits set in align1 " "instruction\n"); return 1; } } return 0; } void set_instruction_options(struct brw_instruction *instr, struct brw_instruction *options) { /* XXX: more instr options */ instr->header.access_mode = options->header.access_mode; instr->header.mask_control = options->header.mask_control; instr->header.dependency_control = options->header.dependency_control; instr->header.compression_control = options->header.compression_control; } void set_src_operand(struct src_operand *src, struct gen_reg *reg, int type) { bzero(src, sizeof(*src)); src->reg_file = reg->reg_file; src->reg_type = type; src->subreg_nr = reg->subreg_nr; src->reg_nr = reg->reg_nr; src->vert_stride = 0; src->width = 0; src->horiz_stride = 1; src->negate = 0; src->abs = 0; }