diff options
Diffstat (limited to 'assembler/gram.y')
-rw-r--r-- | assembler/gram.y | 3167 |
1 files changed, 3167 insertions, 0 deletions
diff --git a/assembler/gram.y b/assembler/gram.y new file mode 100644 index 00000000..2ed79c13 --- /dev/null +++ b/assembler/gram.y @@ -0,0 +1,3167 @@ +%{ +/* + * 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 <eric@anholt.net> + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> +#include "gen4asm.h" +#include "brw_defines.h" + +#define DEFAULT_EXECSIZE (ffs(program_defaults.execute_size) - 1) +#define DEFAULT_DSTREGION -1 + +extern long int gen_level; +extern int advanced_flag; +extern int yylineno; +extern int need_export; +static struct src_operand src_null_reg = +{ + .reg_file = BRW_ARCHITECTURE_REGISTER_FILE, + .reg_nr = BRW_ARF_NULL, + .reg_type = BRW_REGISTER_TYPE_UD, +}; +static struct dst_operand dst_null_reg = +{ + .reg_file = BRW_ARCHITECTURE_REGISTER_FILE, + .reg_nr = BRW_ARF_NULL, +}; +static struct dst_operand ip_dst = +{ + .reg_file = BRW_ARCHITECTURE_REGISTER_FILE, + .reg_nr = BRW_ARF_IP, + .reg_type = BRW_REGISTER_TYPE_UD, + .address_mode = BRW_ADDRESS_DIRECT, + .horiz_stride = 1, + .writemask = 0xF, +}; +static struct src_operand ip_src = +{ + .reg_file = BRW_ARCHITECTURE_REGISTER_FILE, + .reg_nr = BRW_ARF_IP, + .reg_type = BRW_REGISTER_TYPE_UD, + .address_mode = BRW_ADDRESS_DIRECT, + .swizzle_x = BRW_CHANNEL_X, + .swizzle_y = BRW_CHANNEL_Y, + .swizzle_z = BRW_CHANNEL_Z, + .swizzle_w = BRW_CHANNEL_W, +}; + +static int get_type_size(GLuint type); +int set_instruction_dest(struct brw_instruction *instr, + struct dst_operand *dest); +int set_instruction_src0(struct brw_instruction *instr, + struct src_operand *src); +int set_instruction_src1(struct brw_instruction *instr, + struct src_operand *src); +int set_instruction_dest_three_src(struct brw_instruction *instr, + struct dst_operand *dest); +int set_instruction_src0_three_src(struct brw_instruction *instr, + struct src_operand *src); +int set_instruction_src1_three_src(struct brw_instruction *instr, + struct src_operand *src); +int set_instruction_src2_three_src(struct brw_instruction *instr, + struct src_operand *src); +void set_instruction_options(struct brw_instruction *instr, + struct brw_instruction *options); +void set_instruction_predicate(struct brw_instruction *instr, + struct brw_instruction *predicate); +void set_direct_dst_operand(struct dst_operand *dst, struct direct_reg *reg, + int type); +void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg, + int type); + +%} + +%start ROOT + +%union { + char *string; + int integer; + double number; + struct brw_instruction instruction; + struct brw_program program; + struct region region; + struct regtype regtype; + struct direct_reg direct_reg; + struct indirect_reg indirect_reg; + struct condition condition; + struct declared_register symbol_reg; + imm32_t imm32; + + struct dst_operand dst_operand; + struct src_operand src_operand; +} + +%token COLON +%token SEMICOLON +%token LPAREN RPAREN +%token LANGLE RANGLE +%token LCURLY RCURLY +%token LSQUARE RSQUARE +%token COMMA EQ +%token ABS DOT +%token PLUS MINUS MULTIPLY DIVIDE + +%token <integer> TYPE_UD TYPE_D TYPE_UW TYPE_W TYPE_UB TYPE_B +%token <integer> TYPE_VF TYPE_HF TYPE_V TYPE_F + +%token ALIGN1 ALIGN16 SECHALF COMPR SWITCH ATOMIC NODDCHK NODDCLR +%token MASK_DISABLE BREAKPOINT ACCWRCTRL EOT + +%token SEQ ANY2H ALL2H ANY4H ALL4H ANY8H ALL8H ANY16H ALL16H ANYV ALLV +%token <integer> ZERO EQUAL NOT_ZERO NOT_EQUAL GREATER GREATER_EQUAL LESS LESS_EQUAL +%token <integer> ROUND_INCREMENT OVERFLOW UNORDERED +%token <integer> GENREG MSGREG ADDRESSREG ACCREG FLAGREG +%token <integer> MASKREG AMASK IMASK LMASK CMASK +%token <integer> MASKSTACKREG LMS IMS MASKSTACKDEPTHREG IMSD LMSD +%token <integer> NOTIFYREG STATEREG CONTROLREG IPREG +%token GENREGFILE MSGREGFILE + +%token <integer> MOV FRC RNDU RNDD RNDE RNDZ NOT LZD +%token <integer> MUL MAC MACH LINE SAD2 SADA2 DP4 DPH DP3 DP2 +%token <integer> AVG ADD SEL AND OR XOR SHR SHL ASR CMP CMPN PLN +%token <integer> ADDC BFI1 BFREV CBIT F16TO32 F32TO16 FBH FBL +%token <integer> SEND NOP JMPI IF IFF WHILE ELSE BREAK CONT HALT MSAVE +%token <integer> PUSH MREST POP WAIT DO ENDIF ILLEGAL +%token <integer> MATH_INST +%token <integer> MAD LRP BFE BFI2 SUBB +%token <integer> CALL RET +%token <integer> BRD BRC + +%token NULL_TOKEN MATH SAMPLER GATEWAY READ WRITE URB THREAD_SPAWNER VME DATA_PORT CRE + +%token MSGLEN RETURNLEN +%token <integer> ALLOCATE USED COMPLETE TRANSPOSE INTERLEAVE +%token SATURATE + +%token <integer> INTEGER +%token <string> STRING +%token <number> NUMBER + +%token <integer> INV LOG EXP SQRT RSQ POW SIN COS SINCOS INTDIV INTMOD +%token <integer> INTDIVMOD +%token SIGNED SCALAR + +%token <integer> X Y Z W + +%token <integer> KERNEL_PRAGMA END_KERNEL_PRAGMA CODE_PRAGMA END_CODE_PRAGMA +%token <integer> REG_COUNT_PAYLOAD_PRAGMA REG_COUNT_TOTAL_PRAGMA DECLARE_PRAGMA +%token <integer> BASE ELEMENTSIZE SRCREGION DSTREGION TYPE + +%token <integer> DEFAULT_EXEC_SIZE_PRAGMA DEFAULT_REG_TYPE_PRAGMA +%nonassoc SUBREGNUM +%nonassoc SNDOPR +%left PLUS MINUS +%left MULTIPLY DIVIDE +%right UMINUS +%nonassoc DOT +%nonassoc STR_SYMBOL_REG +%nonassoc EMPTEXECSIZE +%nonassoc LPAREN + +%type <integer> exp sndopr +%type <integer> simple_int +%type <instruction> instruction unaryinstruction binaryinstruction +%type <instruction> binaryaccinstruction trinaryinstruction sendinstruction +%type <instruction> jumpinstruction +%type <instruction> breakinstruction syncinstruction +%type <instruction> msgtarget +%type <instruction> instoptions instoption_list predicate +%type <instruction> mathinstruction +%type <instruction> subroutineinstruction +%type <instruction> multibranchinstruction +%type <instruction> nopinstruction loopinstruction ifelseinstruction haltinstruction +%type <string> label +%type <program> instrseq +%type <integer> instoption +%type <integer> unaryop binaryop binaryaccop breakop +%type <integer> trinaryop +%type <condition> conditionalmodifier +%type <integer> condition saturate negate abs chansel +%type <integer> writemask_x writemask_y writemask_z writemask_w +%type <integer> srcimmtype execsize dstregion immaddroffset +%type <integer> subregnum sampler_datatype +%type <integer> urb_swizzle urb_allocate urb_used urb_complete +%type <integer> math_function math_signed math_scalar +%type <integer> predctrl predstate +%type <region> region region_wh indirectregion declare_srcregion; +%type <regtype> regtype +%type <direct_reg> directgenreg directmsgreg addrreg accreg flagreg maskreg +%type <direct_reg> maskstackreg notifyreg +/* %type <direct_reg> maskstackdepthreg */ +%type <direct_reg> statereg controlreg ipreg nullreg +%type <direct_reg> dstoperandex_typed srcarchoperandex_typed +%type <direct_reg> sendleadreg +%type <indirect_reg> indirectgenreg indirectmsgreg addrparam +%type <integer> mask_subreg maskstack_subreg +%type <integer> declare_elementsize declare_dstregion declare_type +/* %type <intger> maskstackdepth_subreg */ +%type <symbol_reg> symbol_reg symbol_reg_p; +%type <imm32> imm32 +%type <dst_operand> dst dstoperand dstoperandex dstreg post_dst writemask +%type <dst_operand> declare_base +%type <src_operand> directsrcoperand srcarchoperandex directsrcaccoperand +%type <src_operand> indirectsrcoperand +%type <src_operand> src srcimm imm32reg payload srcacc srcaccimm swizzle +%type <src_operand> relativelocation relativelocation2 +%% +simple_int: INTEGER { $$ = $1; } + | MINUS INTEGER { $$ = -$2;} +; + +exp: INTEGER { $$ = $1; } + | exp PLUS exp { $$ = $1 + $3; } + | exp MINUS exp { $$ = $1 - $3; } + | exp MULTIPLY exp { $$ = $1 * $3; } + | exp DIVIDE exp { if ($3) $$ = $1 / $3; else YYERROR;} + | MINUS exp %prec UMINUS { $$ = -$2;} + | LPAREN exp RPAREN { $$ = $2; } + ; + +ROOT: instrseq + { + compiled_program = $1; + } +; + + +label: STRING COLON +; + +declare_base: BASE EQ dstreg + { + $$ = $3; + } +; +declare_elementsize: ELEMENTSIZE EQ exp + { + $$ = $3; + } +; +declare_srcregion: /* empty */ + { + /* XXX is this default correct?*/ + memset (&$$, '\0', sizeof ($$)); + $$.vert_stride = ffs(0); + $$.width = ffs(1) - 1; + $$.horiz_stride = ffs(0); + } + | SRCREGION EQ region + { + $$ = $3; + } +; +declare_dstregion: /* empty */ + { + $$ = 1; + } + | DSTREGION EQ dstregion + { + $$ = $3; + } +; +declare_type: TYPE EQ regtype + { + $$ = $3.type; + } +; +declare_pragma: DECLARE_PRAGMA STRING declare_base declare_elementsize declare_srcregion declare_dstregion declare_type + { + struct declared_register *reg; + int defined; + defined = (reg = find_register($2)) != NULL; + if (defined) { + fprintf(stderr, "WARNING: %s already defined\n", $2); + free($2); // $2 has been malloc'ed by strdup + } else { + reg = calloc(sizeof(struct declared_register), 1); + reg->name = $2; + } + reg->base.reg_file = $3.reg_file; + reg->base.reg_nr = $3.reg_nr; + reg->base.subreg_nr = $3.subreg_nr; + reg->element_size = $4; + reg->src_region = $5; + reg->dst_region = $6; + reg->type = $7; + if (!defined) { + insert_register(reg); + } + } +; + +reg_count_total_pragma: REG_COUNT_TOTAL_PRAGMA exp +; +reg_count_payload_pragma: REG_COUNT_PAYLOAD_PRAGMA exp +; + +default_exec_size_pragma: DEFAULT_EXEC_SIZE_PRAGMA exp + { + program_defaults.execute_size = $2; + } +; +default_reg_type_pragma: DEFAULT_REG_TYPE_PRAGMA regtype + { + program_defaults.register_type = $2.type; + } +; +pragma: reg_count_total_pragma + |reg_count_payload_pragma + |default_exec_size_pragma + |default_reg_type_pragma + |declare_pragma +; + +instrseq: instrseq pragma + { + $$ = $1; + } + | instrseq instruction SEMICOLON + { + struct brw_program_instruction *list_entry = + calloc(sizeof(struct brw_program_instruction), 1); + list_entry->instruction = $2; + list_entry->next = NULL; + if ($1.last) { + $1.last->next = list_entry; + } else { + $1.first = list_entry; + } + $1.last = list_entry; + $$ = $1; + } + | 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; + $$.last = list_entry; + } + | instrseq SEMICOLON + { + $$ = $1; + } + | instrseq label + { + struct brw_program_instruction *list_entry = + calloc(sizeof(struct brw_program_instruction), 1); + list_entry->string = strdup($2); + list_entry->islabel = 1; + list_entry->next = NULL; + if ($1.last) { + $1.last->next = list_entry; + } else { + $1.first = list_entry; + } + $1.last = list_entry; + $$ = $1; + } + | label + { + struct brw_program_instruction *list_entry = + calloc(sizeof(struct brw_program_instruction), 1); + list_entry->string = strdup($1); + list_entry->islabel = 1; + + list_entry->next = NULL; + + $$.first = list_entry; + $$.last = list_entry; + } + | pragma + { + $$.first = NULL; + $$.last = NULL; + } + | instrseq error SEMICOLON { + $$ = $1; + } +; + +/* 1.4.1: Instruction groups */ +// binaryinstruction: Source operands cannot be accumulators +// binaryaccinstruction: Source operands can be accumulators +instruction: unaryinstruction + | binaryinstruction + | binaryaccinstruction + | trinaryinstruction + | sendinstruction + | jumpinstruction + | ifelseinstruction + | breakinstruction + | syncinstruction + | mathinstruction + | subroutineinstruction + | multibranchinstruction + | nopinstruction + | haltinstruction + | loopinstruction +; + +ifelseinstruction: ENDIF + { + // for Gen4 + if(IS_GENp(6)) { // For gen6+. + fprintf(stderr, "ENDIF Syntax error: should be 'ENDIF execsize relativelocation'\n"); + YYERROR; + } + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $1; + $$.header.thread_control |= BRW_THREAD_SWITCH; + $$.bits1.da1.dest_horiz_stride = 1; + $$.bits1.da1.src1_reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + $$.bits1.da1.src1_reg_type = BRW_REGISTER_TYPE_UD; + } + | ENDIF execsize relativelocation instoptions + { + // for Gen6+ + /* Gen6, Gen7 bspec: predication is prohibited */ + if(!IS_GENp(6)) { // for gen6- + fprintf(stderr, "ENDIF Syntax error: should be 'ENDIF'\n"); + YYERROR; + } + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $1; + $$.header.execution_size = $2; + $$.first_reloc_target = $3.reloc_target; + $$.first_reloc_offset = $3.imm32; + } + | ELSE execsize relativelocation instoptions + { + if(!IS_GENp(6)) { + // for Gen4, Gen5. gen_level < 60 + /* Set the istack pop count, which must always be 1. */ + $3.imm32 |= (1 << 16); + + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $1; + $$.header.execution_size = $2; + $$.header.thread_control |= BRW_THREAD_SWITCH; + set_instruction_dest(&$$, &ip_dst); + set_instruction_src0(&$$, &ip_src); + set_instruction_src1(&$$, &$3); + $$.first_reloc_target = $3.reloc_target; + $$.first_reloc_offset = $3.imm32; + } else if(IS_GENp(6)) { + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $1; + $$.header.execution_size = $2; + $$.first_reloc_target = $3.reloc_target; + $$.first_reloc_offset = $3.imm32; + } else { + fprintf(stderr, "'ELSE' instruction is not implemented.\n"); + YYERROR; + } + } + | predicate IF execsize relativelocation + { + /* for Gen4, Gen5 */ + /* The branch instructions require that the IP register + * be the destination and first source operand, while the + * offset is the second source operand. The offset is added + * to the pre-incremented IP. + */ + /* for Gen6 */ + if(IS_GENp(7)) { + /* Error in Gen7+. */ + fprintf(stderr, "Syntax error: IF should be 'IF execsize JIP UIP'\n"); + YYERROR; + } + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = $3; + if(!IS_GENp(6)) { + $$.header.thread_control |= BRW_THREAD_SWITCH; + set_instruction_dest(&$$, &ip_dst); + set_instruction_src0(&$$, &ip_src); + set_instruction_src1(&$$, &$4); + } + $$.first_reloc_target = $4.reloc_target; + $$.first_reloc_offset = $4.imm32; + } + | predicate IF execsize relativelocation relativelocation + { + /* for Gen7+ */ + if(!IS_GENp(7)) { + fprintf(stderr, "Syntax error: IF should be 'IF execsize relativelocation'\n"); + YYERROR; + } + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.first_reloc_target = $4.reloc_target; + $$.first_reloc_offset = $4.imm32; + $$.second_reloc_target = $5.reloc_target; + $$.second_reloc_offset = $5.imm32; + } +; + +loopinstruction: predicate WHILE execsize relativelocation instoptions + { + if(!IS_GENp(6)) { + /* The branch instructions require that the IP register + * be the destination and first source operand, while the + * offset is the second source operand. The offset is added + * to the pre-incremented IP. + */ + set_instruction_dest(&$$, &ip_dst); + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.thread_control |= BRW_THREAD_SWITCH; + set_instruction_src0(&$$, &ip_src); + set_instruction_src1(&$$, &$4); + $$.first_reloc_target = $4.reloc_target; + $$.first_reloc_offset = $4.imm32; + } else if (IS_GENp(6)) { + /* Gen6 spec: + dest must have the same element size as src0. + dest horizontal stride must be 1. */ + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.first_reloc_target = $4.reloc_target; + $$.first_reloc_offset = $4.imm32; + } else { + fprintf(stderr, "'WHILE' instruction is not implemented!\n"); + YYERROR; + } + } + | DO + { + // deprecated + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $1; + }; + +haltinstruction: predicate HALT execsize relativelocation relativelocation instoptions + { + // for Gen6, Gen7 + /* Gen6, Gen7 bspec: dst and src0 must be the null reg. */ + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.first_reloc_target = $4.reloc_target; + $$.first_reloc_offset = $4.imm32; + $$.second_reloc_target = $5.reloc_target; + $$.second_reloc_offset = $5.imm32; + set_instruction_dest(&$$, &dst_null_reg); + set_instruction_src0(&$$, &src_null_reg); + }; + +multibranchinstruction: + predicate BRD execsize relativelocation instoptions + { + /* Gen7 bspec: dest must be null. use Switch option */ + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.thread_control |= BRW_THREAD_SWITCH; + $$.first_reloc_target = $4.reloc_target; + $$.first_reloc_offset = $4.imm32; + set_instruction_dest(&$$, &dst_null_reg); + } + | predicate BRC execsize relativelocation relativelocation instoptions + { + /* Gen7 bspec: dest must be null. src0 must be null. use Switch option */ + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.thread_control |= BRW_THREAD_SWITCH; + $$.first_reloc_target = $4.reloc_target; + $$.first_reloc_offset = $4.imm32; + $$.second_reloc_target = $5.reloc_target; + $$.second_reloc_offset = $5.imm32; + set_instruction_dest(&$$, &dst_null_reg); + set_instruction_src0(&$$, &src_null_reg); + } +; + +subroutineinstruction: + predicate CALL execsize dst relativelocation instoptions + { + /* + Gen6 bspec: + source, dest type should be DWORD. + dest must be QWord aligned. + source0 region control must be <2,2,1>. + execution size must be 2. + QtrCtrl is prohibited. + JIP is an immediate operand, must be of type W. + Gen7 bspec: + source, dest type should be DWORD. + dest must be QWord aligned. + source0 region control must be <2,2,1>. + execution size must be 2. + */ + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = 1; /* execution size must be 2. Here 1 is encoded 2. */ + + $4.reg_type = BRW_REGISTER_TYPE_D; /* dest type should be DWORD */ + set_instruction_dest(&$$, &$4); + + struct src_operand src0; + memset(&src0, 0, sizeof(src0)); + src0.reg_type = BRW_REGISTER_TYPE_D; /* source type should be DWORD */ + /* source0 region control must be <2,2,1>. */ + src0.horiz_stride = 1; /*encoded 1*/ + src0.width = 1; /*encoded 2*/ + src0.vert_stride = 2; /*encoded 2*/ + set_instruction_src0(&$$, &src0); + + $$.first_reloc_target = $5.reloc_target; + $$.first_reloc_offset = $5.imm32; + } + | predicate RET execsize dstoperandex src instoptions + { + /* + Gen6, 7: + source cannot be accumulator. + dest must be null. + src0 region control must be <2,2,1> (not specified clearly. should be same as CALL) + */ + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = 1; /* execution size of RET should be 2 */ + set_instruction_dest(&$$, &dst_null_reg); + $5.reg_type = BRW_REGISTER_TYPE_D; + $5.horiz_stride = 1; /*encoded 1*/ + $5.width = 1; /*encoded 2*/ + $5.vert_stride = 2; /*encoded 2*/ + set_instruction_src0(&$$, &$5); + } +; + +unaryinstruction: + predicate unaryop conditionalmodifier saturate execsize + dst srcaccimm instoptions + { + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.sfid_destreg__conditionalmod = $3.cond; + $$.header.saturate = $4; + $$.header.execution_size = $5; + set_instruction_options(&$$, &$8); + set_instruction_predicate(&$$, &$1); + if (set_instruction_dest(&$$, &$6) != 0) + YYERROR; + if (set_instruction_src0(&$$, &$7) != 0) + YYERROR; + + if ($3.flag_subreg_nr != -1) { + if ($$.header.predicate_control != BRW_PREDICATE_NONE && + ($1.bits2.da1.flag_reg_nr != $3.flag_reg_nr || + $1.bits2.da1.flag_subreg_nr != $3.flag_subreg_nr)) + fprintf(stderr, "WARNING: must use the same flag register if both prediction and conditional modifier are enabled\n"); + + $$.bits2.da1.flag_reg_nr = $3.flag_reg_nr; + $$.bits2.da1.flag_subreg_nr = $3.flag_subreg_nr; + } + + if (!IS_GENp(6) && + get_type_size($$.bits1.da1.dest_reg_type) * (1 << $$.header.execution_size) == 64) + $$.header.compression_control = BRW_COMPRESSION_COMPRESSED; + } +; + +unaryop: MOV | FRC | RNDU | RNDD | RNDE | RNDZ | NOT | LZD | BFREV | CBIT + | F16TO32 | F32TO16 | FBH | FBL +; + +// Source operands cannot be accumulators +binaryinstruction: + predicate binaryop conditionalmodifier saturate execsize + dst src srcimm instoptions + { + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.sfid_destreg__conditionalmod = $3.cond; + $$.header.saturate = $4; + $$.header.execution_size = $5; + set_instruction_options(&$$, &$9); + set_instruction_predicate(&$$, &$1); + if (set_instruction_dest(&$$, &$6) != 0) + YYERROR; + if (set_instruction_src0(&$$, &$7) != 0) + YYERROR; + if (set_instruction_src1(&$$, &$8) != 0) + YYERROR; + + if ($3.flag_subreg_nr != -1) { + if ($$.header.predicate_control != BRW_PREDICATE_NONE && + ($1.bits2.da1.flag_reg_nr != $3.flag_reg_nr || + $1.bits2.da1.flag_subreg_nr != $3.flag_subreg_nr)) + fprintf(stderr, "WARNING: must use the same flag register if both prediction and conditional modifier are enabled\n"); + + $$.bits2.da1.flag_reg_nr = $3.flag_reg_nr; + $$.bits2.da1.flag_subreg_nr = $3.flag_subreg_nr; + } + + if (!IS_GENp(6) && + get_type_size($$.bits1.da1.dest_reg_type) * (1 << $$.header.execution_size) == 64) + $$.header.compression_control = BRW_COMPRESSION_COMPRESSED; + } +; + +/* bspec: BFI1 should not access accumulator. */ +binaryop: MUL | MAC | MACH | LINE | SAD2 | SADA2 | DP4 | DPH | DP3 | DP2 | PLN | BFI1 +; + +// Source operands can be accumulators +binaryaccinstruction: + predicate binaryaccop conditionalmodifier saturate execsize + dst srcacc srcimm instoptions + { + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.sfid_destreg__conditionalmod = $3.cond; + $$.header.saturate = $4; + $$.header.execution_size = $5; + set_instruction_options(&$$, &$9); + set_instruction_predicate(&$$, &$1); + if (set_instruction_dest(&$$, &$6) != 0) + YYERROR; + if (set_instruction_src0(&$$, &$7) != 0) + YYERROR; + if (set_instruction_src1(&$$, &$8) != 0) + YYERROR; + + if ($3.flag_subreg_nr != -1) { + if ($$.header.predicate_control != BRW_PREDICATE_NONE && + ($1.bits2.da1.flag_reg_nr != $3.flag_reg_nr || + $1.bits2.da1.flag_subreg_nr != $3.flag_subreg_nr)) + fprintf(stderr, "WARNING: must use the same flag register if both prediction and conditional modifier are enabled\n"); + + $$.bits2.da1.flag_reg_nr = $3.flag_reg_nr; + $$.bits2.da1.flag_subreg_nr = $3.flag_subreg_nr; + } + + if (!IS_GENp(6) && + get_type_size($$.bits1.da1.dest_reg_type) * (1 << $$.header.execution_size) == 64) + $$.header.compression_control = BRW_COMPRESSION_COMPRESSED; + } +; + +/* TODO: bspec says ADDC/SUBB/CMP/CMPN/SHL/BFI1 cannot use accumulator as dest. */ +binaryaccop: AVG | ADD | SEL | AND | OR | XOR | SHR | SHL | ASR | CMP | CMPN | ADDC | SUBB +; + +trinaryop: MAD | LRP | BFE | BFI2 +; + +trinaryinstruction: + predicate trinaryop conditionalmodifier saturate execsize + dst src src src instoptions +{ + memset(&$$, 0, sizeof($$)); + + $$.header.predicate_control = $1.header.predicate_control; + $$.header.predicate_inverse = $1.header.predicate_inverse; + $$.bits1.three_src_gen6.flag_reg_nr = $1.bits2.da1.flag_reg_nr; + $$.bits1.three_src_gen6.flag_subreg_nr = $1.bits2.da1.flag_subreg_nr; + + $$.header.opcode = $2; + $$.header.sfid_destreg__conditionalmod = $3.cond; + $$.header.saturate = $4; + $$.header.execution_size = $5; + + if (set_instruction_dest_three_src(&$$, &$6)) + YYERROR; + if (set_instruction_src0_three_src(&$$, &$7)) + YYERROR; + if (set_instruction_src1_three_src(&$$, &$8)) + YYERROR; + if (set_instruction_src2_three_src(&$$, &$9)) + YYERROR; + set_instruction_options(&$$, &$10); + + if ($3.flag_subreg_nr != -1) { + if ($$.header.predicate_control != BRW_PREDICATE_NONE && + ($1.bits2.da1.flag_reg_nr != $3.flag_reg_nr || + $1.bits2.da1.flag_subreg_nr != $3.flag_subreg_nr)) + fprintf(stderr, "WARNING: must use the same flag register if both prediction and conditional modifier are enabled\n"); + } +} +; + +sendinstruction: predicate SEND execsize exp post_dst payload msgtarget + MSGLEN exp RETURNLEN exp 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. + */ + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.sfid_destreg__conditionalmod = $4; /* msg reg index */ + set_instruction_predicate(&$$, &$1); + if (set_instruction_dest(&$$, &$5) != 0) + YYERROR; + + if (IS_GENp(6)) { + struct src_operand src0; + + memset(&src0, 0, sizeof(src0)); + src0.address_mode = BRW_ADDRESS_DIRECT; + + if (IS_GENp(7)) + src0.reg_file = BRW_GENERAL_REGISTER_FILE; + else + src0.reg_file = BRW_MESSAGE_REGISTER_FILE; + + src0.reg_type = BRW_REGISTER_TYPE_D; + src0.reg_nr = $4; + src0.subreg_nr = 0; + set_instruction_src0(&$$, &src0); + } else { + if (set_instruction_src0(&$$, &$6) != 0) + YYERROR; + } + + $$.bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE; + $$.bits1.da1.src1_reg_type = BRW_REGISTER_TYPE_D; + + if (IS_GENp(5)) { + if (IS_GENp(6)) { + $$.header.sfid_destreg__conditionalmod = $7.bits2.send_gen5.sfid; + } else { + $$.header.sfid_destreg__conditionalmod = $4; /* msg reg index */ + $$.bits2.send_gen5.sfid = $7.bits2.send_gen5.sfid; + $$.bits2.send_gen5.end_of_thread = $12.bits3.generic_gen5.end_of_thread; + } + + $$.bits3.generic_gen5 = $7.bits3.generic_gen5; + $$.bits3.generic_gen5.msg_length = $9; + $$.bits3.generic_gen5.response_length = $11; + $$.bits3.generic_gen5.end_of_thread = + $12.bits3.generic_gen5.end_of_thread; + } else { + $$.header.sfid_destreg__conditionalmod = $4; /* msg reg index */ + $$.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; + } + } + | predicate SEND execsize dst sendleadreg payload directsrcoperand instoptions + { + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.sfid_destreg__conditionalmod = $5.reg_nr; /* msg reg index */ + + set_instruction_predicate(&$$, &$1); + + if (set_instruction_dest(&$$, &$4) != 0) + YYERROR; + if (set_instruction_src0(&$$, &$6) != 0) + YYERROR; + /* XXX is this correct? */ + if (set_instruction_src1(&$$, &$7) != 0) + YYERROR; + } + | predicate SEND execsize dst sendleadreg payload imm32reg instoptions + { + if ($7.reg_type != BRW_REGISTER_TYPE_UD && + $7.reg_type != BRW_REGISTER_TYPE_D && + $7.reg_type != BRW_REGISTER_TYPE_V) { + fprintf (stderr, "%d: non-int D/UD/V representation: %d,type=%d\n", yylineno, $7.imm32, $7.reg_type); + YYERROR; + } + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.sfid_destreg__conditionalmod = $5.reg_nr; /* msg reg index */ + + set_instruction_predicate(&$$, &$1); + if (set_instruction_dest(&$$, &$4) != 0) + YYERROR; + if (set_instruction_src0(&$$, &$6) != 0) + YYERROR; + $$.bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE; + $$.bits1.da1.src1_reg_type = $7.reg_type; + $$.bits3.ud = $7.imm32; + } + | predicate SEND execsize dst sendleadreg sndopr imm32reg instoptions + { + struct src_operand src0; + + if (!IS_GENp(6)) { + fprintf(stderr, "error: the syntax of send instruction\n"); + YYERROR; + } + + if ($7.reg_type != BRW_REGISTER_TYPE_UD && + $7.reg_type != BRW_REGISTER_TYPE_D && + $7.reg_type != BRW_REGISTER_TYPE_V) { + fprintf (stderr, "%d: non-int D/UD/V representation: %d,type=%d\n", yylineno, $7.imm32, $7.reg_type); + YYERROR; + } + + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.sfid_destreg__conditionalmod = ($6 & EX_DESC_SFID_MASK); /* SFID */ + set_instruction_predicate(&$$, &$1); + + if (set_instruction_dest(&$$, &$4) != 0) + YYERROR; + + memset(&src0, 0, sizeof(src0)); + src0.address_mode = BRW_ADDRESS_DIRECT; + + if (IS_GENp(7)) { + src0.reg_file = BRW_GENERAL_REGISTER_FILE; + src0.reg_type = BRW_REGISTER_TYPE_UB; + } else { + src0.reg_file = BRW_MESSAGE_REGISTER_FILE; + src0.reg_type = BRW_REGISTER_TYPE_D; + } + + src0.reg_nr = $5.reg_nr; + src0.subreg_nr = 0; + set_instruction_src0(&$$, &src0); + + $$.bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE; + $$.bits1.da1.src1_reg_type = $7.reg_type; + $$.bits3.ud = $7.imm32; + $$.bits3.generic_gen5.end_of_thread = !!($6 & EX_DESC_EOT_MASK); + } + | predicate SEND execsize dst sendleadreg sndopr directsrcoperand instoptions + { + struct src_operand src0; + + if (!IS_GENp(6)) { + fprintf(stderr, "error: the syntax of send instruction\n"); + YYERROR; + } + + if ($7.reg_file != BRW_ARCHITECTURE_REGISTER_FILE || + ($7.reg_nr & 0xF0) != BRW_ARF_ADDRESS || + ($7.reg_nr & 0x0F) != 0 || + $7.subreg_nr != 0) { + fprintf (stderr, "%d: scalar register must be a0.0<0;1,0>:ud\n", yylineno); + YYERROR; + } + + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.sfid_destreg__conditionalmod = ($6 & EX_DESC_SFID_MASK); /* SFID */ + set_instruction_predicate(&$$, &$1); + + if (set_instruction_dest(&$$, &$4) != 0) + YYERROR; + + memset(&src0, 0, sizeof(src0)); + src0.address_mode = BRW_ADDRESS_DIRECT; + + if (IS_GENp(7)) { + src0.reg_file = BRW_GENERAL_REGISTER_FILE; + src0.reg_type = BRW_REGISTER_TYPE_UB; + } else { + src0.reg_file = BRW_MESSAGE_REGISTER_FILE; + src0.reg_type = BRW_REGISTER_TYPE_D; + } + + src0.reg_nr = $5.reg_nr; + src0.subreg_nr = 0; + set_instruction_src0(&$$, &src0); + + set_instruction_src1(&$$, &$7); + $$.bits3.generic_gen5.end_of_thread = !!($6 & EX_DESC_EOT_MASK); + } + | predicate SEND execsize dst sendleadreg payload sndopr imm32reg instoptions + { + if ($8.reg_type != BRW_REGISTER_TYPE_UD && + $8.reg_type != BRW_REGISTER_TYPE_D && + $8.reg_type != BRW_REGISTER_TYPE_V) { + fprintf (stderr, "%d: non-int D/UD/V representation: %d,type=%d\n", yylineno, $8.imm32, $8.reg_type); + YYERROR; + } + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.sfid_destreg__conditionalmod = $5.reg_nr; /* msg reg index */ + + set_instruction_predicate(&$$, &$1); + if (set_instruction_dest(&$$, &$4) != 0) + YYERROR; + if (set_instruction_src0(&$$, &$6) != 0) + YYERROR; + $$.bits1.da1.src1_reg_file = BRW_IMMEDIATE_VALUE; + $$.bits1.da1.src1_reg_type = $8.reg_type; + if (IS_GENx(5)) { + $$.bits2.send_gen5.sfid = ($7 & EX_DESC_SFID_MASK); + $$.bits3.ud = $8.imm32; + $$.bits3.generic_gen5.end_of_thread = !!($7 & EX_DESC_EOT_MASK); + } + else + $$.bits3.ud = $8.imm32; + } + | predicate SEND execsize dst sendleadreg payload exp directsrcoperand instoptions + { + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.header.sfid_destreg__conditionalmod = $5.reg_nr; /* msg reg index */ + + set_instruction_predicate(&$$, &$1); + + if (set_instruction_dest(&$$, &$4) != 0) + YYERROR; + if (set_instruction_src0(&$$, &$6) != 0) + YYERROR; + /* XXX is this correct? */ + if (set_instruction_src1(&$$, &$8) != 0) + YYERROR; + if (IS_GENx(5)) { + $$.bits2.send_gen5.sfid = $7; + } + } + +; + +sndopr: exp %prec SNDOPR + { + $$ = $1; + } +; + +jumpinstruction: predicate JMPI execsize relativelocation2 + { + /* The jump instruction requires that the IP register + * be the destination and first source operand, while the + * offset is the second source operand. The next instruction + * is the post-incremented IP plus the offset. + */ + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.execution_size = ffs(1) - 1; + if(advanced_flag) + $$.header.mask_control = BRW_MASK_DISABLE; + set_instruction_predicate(&$$, &$1); + set_instruction_dest(&$$, &ip_dst); + set_instruction_src0(&$$, &ip_src); + set_instruction_src1(&$$, &$4); + $$.first_reloc_target = $4.reloc_target; + $$.first_reloc_offset = $4.imm32; + } +; + +mathinstruction: predicate MATH_INST execsize dst src srcimm math_function instoptions + { + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.sfid_destreg__conditionalmod = $7; + $$.header.execution_size = $3; + set_instruction_options(&$$, &$8); + set_instruction_predicate(&$$, &$1); + if (set_instruction_dest(&$$, &$4) != 0) + YYERROR; + if (set_instruction_src0(&$$, &$5) != 0) + YYERROR; + if (set_instruction_src1(&$$, &$6) != 0) + YYERROR; + } +; + +breakinstruction: predicate breakop execsize relativelocation relativelocation instoptions + { + // for Gen6, Gen7 + memset(&$$, 0, sizeof($$)); + set_instruction_predicate(&$$, &$1); + $$.header.opcode = $2; + $$.header.execution_size = $3; + $$.first_reloc_target = $4.reloc_target; + $$.first_reloc_offset = $4.imm32; + $$.second_reloc_target = $5.reloc_target; + $$.second_reloc_offset = $5.imm32; + } +; + +breakop: BREAK | CONT +; + +/* +maskpushop: MSAVE | PUSH +; + */ + +syncinstruction: predicate WAIT notifyreg + { + struct dst_operand notify_dst; + struct src_operand notify_src; + + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $2; + $$.header.execution_size = ffs(1) - 1; + set_direct_dst_operand(¬ify_dst, &$3, BRW_REGISTER_TYPE_D); + set_instruction_dest(&$$, ¬ify_dst); + set_direct_src_operand(¬ify_src, &$3, BRW_REGISTER_TYPE_D); + set_instruction_src0(&$$, ¬ify_src); + set_instruction_src1(&$$, &src_null_reg); + } + +; + +nopinstruction: NOP + { + memset(&$$, 0, sizeof($$)); + $$.header.opcode = $1; + }; + +/* XXX! */ +payload: directsrcoperand +; + +post_dst: dst +; + +msgtarget: NULL_TOKEN + { + if (IS_GENp(5)) { + $$.bits2.send_gen5.sfid= BRW_MESSAGE_TARGET_NULL; + $$.bits3.generic_gen5.header_present = 0; /* ??? */ + } else { + $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_NULL; + } + } + | SAMPLER LPAREN INTEGER COMMA INTEGER COMMA + sampler_datatype RPAREN + { + if (IS_GENp(7)) { + $$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_SAMPLER; + $$.bits3.generic_gen5.header_present = 1; /* ??? */ + $$.bits3.sampler_gen7.binding_table_index = $3; + $$.bits3.sampler_gen7.sampler = $5; + $$.bits3.sampler_gen7.simd_mode = 2; /* SIMD16, maybe we should add a new parameter */ + } else if (IS_GENp(5)) { + $$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_SAMPLER; + $$.bits3.generic_gen5.header_present = 1; /* ??? */ + $$.bits3.sampler_gen5.binding_table_index = $3; + $$.bits3.sampler_gen5.sampler = $5; + $$.bits3.sampler_gen5.simd_mode = 2; /* SIMD16, maybe we should add a new parameter */ + } else { + $$.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 + { + if (IS_GENp(6)) { + fprintf (stderr, "Gen6+ doesn't have math function\n"); + YYERROR; + } else if (IS_GENx(5)) { + $$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_MATH; + $$.bits3.generic_gen5.header_present = 0; + $$.bits3.math_gen5.function = $2; + if ($3 == BRW_INSTRUCTION_SATURATE) + $$.bits3.math_gen5.saturate = 1; + else + $$.bits3.math_gen5.saturate = 0; + $$.bits3.math_gen5.int_type = $4; + $$.bits3.math_gen5.precision = BRW_MATH_PRECISION_FULL; + $$.bits3.math_gen5.data_type = $5; + } else { + $$.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 + { + if (IS_GENp(5)) { + $$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_GATEWAY; + $$.bits3.generic_gen5.header_present = 0; /* ??? */ + } else { + $$.bits3.generic.msg_target = BRW_MESSAGE_TARGET_GATEWAY; + } + } + | READ LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA + INTEGER RPAREN + { + if (IS_GENx(7)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_DP_SC; + $$.bits3.generic_gen5.header_present = 1; + $$.bits3.dp_gen7.binding_table_index = $3; + $$.bits3.dp_gen7.msg_control = $7; + $$.bits3.dp_gen7.msg_type = $9; + } else if (IS_GENx(6)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_DP_SC; + $$.bits3.generic_gen5.header_present = 1; + $$.bits3.dp_read_gen6.binding_table_index = $3; + $$.bits3.dp_read_gen6.msg_control = $7; + $$.bits3.dp_read_gen6.msg_type = $9; + } else if (IS_GENx(5)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_DATAPORT_READ; + $$.bits3.generic_gen5.header_present = 1; + $$.bits3.dp_read_gen5.binding_table_index = $3; + $$.bits3.dp_read_gen5.target_cache = $5; + $$.bits3.dp_read_gen5.msg_control = $7; + $$.bits3.dp_read_gen5.msg_type = $9; + } else { + $$.bits3.generic.msg_target = + BRW_MESSAGE_TARGET_DATAPORT_READ; + $$.bits3.dp_read.binding_table_index = $3; + $$.bits3.dp_read.target_cache = $5; + $$.bits3.dp_read.msg_control = $7; + $$.bits3.dp_read.msg_type = $9; + } + } + | WRITE LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA + INTEGER RPAREN + { + if (IS_GENx(7)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_DP_RC; + $$.bits3.generic_gen5.header_present = 1; + $$.bits3.dp_gen7.binding_table_index = $3; + $$.bits3.dp_gen7.msg_control = $5; + $$.bits3.dp_gen7.msg_type = $7; + } else if (IS_GENx(6)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_DP_RC; + /* Sandybridge supports headerlesss message for render target write. + * Currently the GFX assembler doesn't support it. so the program must provide + * message header + */ + $$.bits3.generic_gen5.header_present = 1; + $$.bits3.dp_write_gen6.binding_table_index = $3; + $$.bits3.dp_write_gen6.msg_control = $5; + $$.bits3.dp_write_gen6.msg_type = $7; + $$.bits3.dp_write_gen6.send_commit_msg = $9; + } else if (IS_GENx(5)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_DATAPORT_WRITE; + $$.bits3.generic_gen5.header_present = 1; + $$.bits3.dp_write_gen5.binding_table_index = $3; + $$.bits3.dp_write_gen5.pixel_scoreboard_clear = ($5 & 0x8) >> 3; + $$.bits3.dp_write_gen5.msg_control = $5 & 0x7; + $$.bits3.dp_write_gen5.msg_type = $7; + $$.bits3.dp_write_gen5.send_commit_msg = $9; + } else { + $$.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; + } + } + | WRITE LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA + INTEGER COMMA INTEGER RPAREN + { + if (IS_GENx(7)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_DP_RC; + $$.bits3.generic_gen5.header_present = ($11 != 0); + $$.bits3.dp_gen7.binding_table_index = $3; + $$.bits3.dp_gen7.msg_control = $5; + $$.bits3.dp_gen7.msg_type = $7; + } else if (IS_GENx(6)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_DP_RC; + $$.bits3.generic_gen5.header_present = ($11 != 0); + $$.bits3.dp_write_gen6.binding_table_index = $3; + $$.bits3.dp_write_gen6.msg_control = $5; + $$.bits3.dp_write_gen6.msg_type = $7; + $$.bits3.dp_write_gen6.send_commit_msg = $9; + } else if (IS_GENx(5)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_DATAPORT_WRITE; + $$.bits3.generic_gen5.header_present = ($11 != 0); + $$.bits3.dp_write_gen5.binding_table_index = $3; + $$.bits3.dp_write_gen5.pixel_scoreboard_clear = ($5 & 0x8) >> 3; + $$.bits3.dp_write_gen5.msg_control = $5 & 0x7; + $$.bits3.dp_write_gen5.msg_type = $7; + $$.bits3.dp_write_gen5.send_commit_msg = $9; + } else { + $$.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; + if (IS_GENp(5)) { + $$.bits2.send_gen5.sfid = BRW_MESSAGE_TARGET_URB; + $$.bits3.generic_gen5.header_present = 1; + $$.bits3.urb_gen5.opcode = BRW_URB_OPCODE_WRITE; + $$.bits3.urb_gen5.offset = $2; + $$.bits3.urb_gen5.swizzle_control = $3; + $$.bits3.urb_gen5.pad = 0; + $$.bits3.urb_gen5.allocate = $4; + $$.bits3.urb_gen5.used = $5; + $$.bits3.urb_gen5.complete = $6; + } else { + $$.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 LPAREN INTEGER COMMA INTEGER COMMA + INTEGER RPAREN + { + $$.bits3.generic.msg_target = + BRW_MESSAGE_TARGET_THREAD_SPAWNER; + if (IS_GENp(5)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_THREAD_SPAWNER; + $$.bits3.generic_gen5.header_present = 0; + $$.bits3.thread_spawner_gen5.opcode = $3; + $$.bits3.thread_spawner_gen5.requester_type = $5; + $$.bits3.thread_spawner_gen5.resource_select = $7; + } else { + $$.bits3.generic.msg_target = + BRW_MESSAGE_TARGET_THREAD_SPAWNER; + $$.bits3.thread_spawner.opcode = $3; + $$.bits3.thread_spawner.requester_type = $5; + $$.bits3.thread_spawner.resource_select = $7; + } + } + | VME LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA INTEGER RPAREN + { + $$.bits3.generic.msg_target = + BRW_MESSAGE_TARGET_VME; + + if (IS_GENp(6)) { + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_VME; + $$.bits3.vme_gen6.binding_table_index = $3; + $$.bits3.vme_gen6.search_path_index = $5; + $$.bits3.vme_gen6.lut_subindex = $7; + $$.bits3.vme_gen6.message_type = $9; + $$.bits3.generic_gen5.header_present = 1; + } else { + fprintf (stderr, "Gen6- doesn't have vme function\n"); + YYERROR; + } + } + | CRE LPAREN INTEGER COMMA INTEGER RPAREN + { + if (gen_level < 75) { + fprintf (stderr, "Below Gen7.5 doesn't have CRE function\n"); + YYERROR; + } + $$.bits3.generic.msg_target = + BRW_MESSAGE_TARGET_CRE; + + $$.bits2.send_gen5.sfid = + BRW_MESSAGE_TARGET_CRE; + $$.bits3.cre_gen75.binding_table_index = $3; + $$.bits3.cre_gen75.message_type = $5; + $$.bits3.generic_gen5.header_present = 1; + } + + | DATA_PORT LPAREN INTEGER COMMA INTEGER COMMA INTEGER COMMA + INTEGER COMMA INTEGER COMMA INTEGER RPAREN + { + $$.bits2.send_gen5.sfid = $3; + $$.bits3.generic_gen5.header_present = ($13 != 0); + + if (IS_GENp(7)) { + if ($3 != BRW_MESSAGE_TARGET_DP_SC && + $3 != BRW_MESSAGE_TARGET_DP_RC && + $3 != BRW_MESSAGE_TARGET_DP_CC && + $3 != BRW_MESSAGE_TARGET_DP_DC) { + fprintf (stderr, "error: wrong cache type\n"); + YYERROR; + } + + $$.bits3.dp_gen7.category = $11; + $$.bits3.dp_gen7.binding_table_index = $9; + $$.bits3.dp_gen7.msg_control = $7; + $$.bits3.dp_gen7.msg_type = $5; + } else if (IS_GENx(6)) { + if ($3 != BRW_MESSAGE_TARGET_DP_SC && + $3 != BRW_MESSAGE_TARGET_DP_RC && + $3 != BRW_MESSAGE_TARGET_DP_CC) { + fprintf (stderr, "error: wrong cache type\n"); + YYERROR; + } + + $$.bits3.dp_gen6.send_commit_msg = $11; + $$.bits3.dp_gen6.binding_table_index = $9; + $$.bits3.dp_gen6.msg_control = $7; + $$.bits3.dp_gen6.msg_type = $5; + } else if (!IS_GENp(5)) { + fprintf (stderr, "Gen6- doesn't support data port for sampler/render/constant/data cache\n"); + YYERROR; + } + } +; + +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 +; + +dstoperand: symbol_reg dstregion + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = $1.base.reg_file; + $$.reg_nr = $1.base.reg_nr; + $$.subreg_nr = $1.base.subreg_nr; + if ($2 == DEFAULT_DSTREGION) { + $$.horiz_stride = $1.dst_region; + } else { + $$.horiz_stride = $2; + } + $$.reg_type = $1.type; + } + | dstreg dstregion writemask regtype + { + /* Returns an instruction with just the destination register + * filled in. + */ + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = $1.reg_file; + $$.reg_nr = $1.reg_nr; + $$.subreg_nr = $1.subreg_nr; + $$.address_mode = $1.address_mode; + $$.address_subreg_nr = $1.address_subreg_nr; + $$.indirect_offset = $1.indirect_offset; + $$.horiz_stride = $2; + $$.writemask_set = $3.writemask_set; + $$.writemask = $3.writemask; + $$.reg_type = $4.type; + } +; + +/* The dstoperandex returns an instruction with just the destination register + * filled in. + */ +dstoperandex: dstoperandex_typed dstregion regtype + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = $1.reg_file; + $$.reg_nr = $1.reg_nr; + $$.subreg_nr = $1.subreg_nr; + $$.horiz_stride = $2; + $$.reg_type = $3.type; + } + | maskstackreg + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = $1.reg_file; + $$.reg_nr = $1.reg_nr; + $$.subreg_nr = $1.subreg_nr; + $$.horiz_stride = 1; + $$.reg_type = BRW_REGISTER_TYPE_UW; + } + | controlreg + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = $1.reg_file; + $$.reg_nr = $1.reg_nr; + $$.subreg_nr = $1.subreg_nr; + $$.horiz_stride = 1; + $$.reg_type = BRW_REGISTER_TYPE_UD; + } + | ipreg + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = $1.reg_file; + $$.reg_nr = $1.reg_nr; + $$.subreg_nr = $1.subreg_nr; + $$.horiz_stride = 1; + $$.reg_type = BRW_REGISTER_TYPE_UD; + } + | nullreg dstregion regtype + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = $1.reg_file; + $$.reg_nr = $1.reg_nr; + $$.subreg_nr = $1.subreg_nr; + $$.horiz_stride = $2; + $$.reg_type = $3.type; + } +; + +dstoperandex_typed: accreg | flagreg | addrreg | maskreg +; + +symbol_reg: STRING %prec STR_SYMBOL_REG + { + struct declared_register *dcl_reg = find_register($1); + + if (dcl_reg == NULL) { + fprintf(stderr, "can't find register %s\n", $1); + YYERROR; + } + + memcpy(&$$, dcl_reg, sizeof(*dcl_reg)); + free($1); // $1 has been malloc'ed by strdup + } + | symbol_reg_p + { + $$=$1; + } +; + +symbol_reg_p: STRING LPAREN exp RPAREN + { + struct declared_register *dcl_reg = find_register($1); + + if (dcl_reg == NULL) { + fprintf(stderr, "can't find register %s\n", $1); + YYERROR; + } + + memcpy(&$$, dcl_reg, sizeof(*dcl_reg)); + $$.base.reg_nr += $3; + free($1); + } + | STRING LPAREN exp COMMA exp RPAREN + { + struct declared_register *dcl_reg = find_register($1); + + if (dcl_reg == NULL) { + fprintf(stderr, "can't find register %s\n", $1); + YYERROR; + } + + memcpy(&$$, dcl_reg, sizeof(*dcl_reg)); + $$.base.reg_nr += $3; + $$.base.subreg_nr += $5; + if(advanced_flag) { + $$.base.reg_nr += $$.base.subreg_nr / (32 / get_type_size(dcl_reg->type)); + $$.base.subreg_nr = $$.base.subreg_nr % (32 / get_type_size(dcl_reg->type)); + } else { + $$.base.reg_nr += $$.base.subreg_nr / 32; + $$.base.subreg_nr = $$.base.subreg_nr % 32; + } + free($1); + } +; +/* Returns a partially complete destination register consisting of the + * direct or indirect register addressing fields, but not stride or writemask. + */ +dstreg: directgenreg + { + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_DIRECT; + $$.reg_file = $1.reg_file; + $$.reg_nr = $1.reg_nr; + $$.subreg_nr = $1.subreg_nr; + } + | directmsgreg + { + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_DIRECT; + $$.reg_file = $1.reg_file; + $$.reg_nr = $1.reg_nr; + $$.subreg_nr = $1.subreg_nr; + } + | indirectgenreg + { + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; + $$.reg_file = $1.reg_file; + $$.address_subreg_nr = $1.address_subreg_nr; + $$.indirect_offset = $1.indirect_offset; + } + | indirectmsgreg + { + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; + $$.reg_file = $1.reg_file; + $$.address_subreg_nr = $1.address_subreg_nr; + $$.indirect_offset = $1.indirect_offset; + } +; + +/* 1.4.3: Source register */ +srcaccimm: srcacc | imm32reg +; + +srcacc: directsrcaccoperand | indirectsrcoperand +; + +srcimm: directsrcoperand | indirectsrcoperand| imm32reg +; + +imm32reg: imm32 srcimmtype + { + union { + int i; + float f; + } intfloat; + uint32_t d; + + switch ($2) { + case BRW_REGISTER_TYPE_UD: + case BRW_REGISTER_TYPE_D: + case BRW_REGISTER_TYPE_V: + case BRW_REGISTER_TYPE_VF: + switch ($1.r) { + case imm32_d: + d = $1.u.d; + break; + default: + fprintf (stderr, "%d: non-int D/UD/V/VF representation: %d,type=%d\n", yylineno, $1.r, $2); + YYERROR; + } + break; + case BRW_REGISTER_TYPE_UW: + case BRW_REGISTER_TYPE_W: + switch ($1.r) { + case imm32_d: + d = $1.u.d; + break; + default: + fprintf (stderr, "non-int W/UW representation\n"); + YYERROR; + } + d &= 0xffff; + d |= d << 16; + break; + case BRW_REGISTER_TYPE_F: + switch ($1.r) { + case imm32_f: + intfloat.f = $1.u.f; + break; + case imm32_d: + intfloat.f = (float) $1.u.d; + break; + default: + fprintf (stderr, "non-float F representation\n"); + YYERROR; + } + d = intfloat.i; + break; +#if 0 + case BRW_REGISTER_TYPE_VF: + fprintf (stderr, "Immediate type VF not supported yet\n"); + YYERROR; +#endif + default: + fprintf(stderr, "unknown immediate type %d\n", $2); + YYERROR; + } + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_IMMEDIATE_VALUE; + $$.reg_type = $2; + $$.imm32 = d; + } +; + +directsrcaccoperand: directsrcoperand + | accreg region regtype + { + set_direct_src_operand(&$$, &$1, $3.type); + $$.vert_stride = $2.vert_stride; + $$.width = $2.width; + $$.horiz_stride = $2.horiz_stride; + $$.default_region = $2.is_default; + } +; + +/* Returns a source operand in the src0 fields of an instruction. */ +srcarchoperandex: srcarchoperandex_typed region regtype + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = $1.reg_file; + $$.reg_type = $3.type; + $$.subreg_nr = $1.subreg_nr; + $$.reg_nr = $1.reg_nr; + $$.vert_stride = $2.vert_stride; + $$.width = $2.width; + $$.horiz_stride = $2.horiz_stride; + $$.default_region = $2.is_default; + $$.negate = 0; + $$.abs = 0; + } + | maskstackreg + { + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UB); + } + | controlreg + { + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + } +/* | statereg + { + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + }*/ + | notifyreg + { + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + } + | ipreg + { + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + } + | nullreg region regtype + { + if ($3.is_default) { + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + } else { + set_direct_src_operand(&$$, &$1, $3.type); + } + $$.default_region = 1; + } +; + +srcarchoperandex_typed: flagreg | addrreg | maskreg +; + +sendleadreg: symbol_reg + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = $1.base.reg_file; + $$.reg_nr = $1.base.reg_nr; + $$.subreg_nr = $1.base.subreg_nr; + } + | directgenreg | directmsgreg +; + +src: directsrcoperand | indirectsrcoperand +; + +directsrcoperand: negate abs symbol_reg region regtype + { + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_DIRECT; + $$.reg_file = $3.base.reg_file; + $$.reg_nr = $3.base.reg_nr; + $$.subreg_nr = $3.base.subreg_nr; + if ($5.is_default) { + $$.reg_type = $3.type; + } else { + $$.reg_type = $5.type; + } + if ($4.is_default) { + $$.vert_stride = $3.src_region.vert_stride; + $$.width = $3.src_region.width; + $$.horiz_stride = $3.src_region.horiz_stride; + } else { + $$.vert_stride = $4.vert_stride; + $$.width = $4.width; + $$.horiz_stride = $4.horiz_stride; + } + $$.negate = $1; + $$.abs = $2; + } + | statereg region regtype + { + if($2.is_default ==1 && $3.is_default == 1) + { + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + } + else{ + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_DIRECT; + $$.reg_file = $1.reg_file; + $$.reg_nr = $1.reg_nr; + $$.subreg_nr = $1.subreg_nr; + $$.vert_stride = $2.vert_stride; + $$.width = $2.width; + $$.horiz_stride = $2.horiz_stride; + $$.reg_type = $3.type; + } + } + | negate abs directgenreg region regtype swizzle + { + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_DIRECT; + $$.reg_file = $3.reg_file; + $$.reg_nr = $3.reg_nr; + $$.subreg_nr = $3.subreg_nr; + $$.reg_type = $5.type; + $$.vert_stride = $4.vert_stride; + $$.width = $4.width; + $$.horiz_stride = $4.horiz_stride; + $$.default_region = $4.is_default; + $$.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 +; + +indirectsrcoperand: + negate abs indirectgenreg indirectregion regtype swizzle + { + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; + $$.reg_file = $3.reg_file; + $$.address_subreg_nr = $3.address_subreg_nr; + $$.indirect_offset = $3.indirect_offset; + $$.reg_type = $5.type; + $$.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; + } +; + +/* 1.4.4: Address Registers */ +/* Returns a partially-completed indirect_reg consisting of the address + * register fields for register-indirect access. + */ +addrparam: addrreg COMMA immaddroffset + { + if ($3 < -512 || $3 > 511) { + fprintf(stderr, "Address immediate offset %d out of" + "range %d\n", $3, yylineno); + YYERROR; + } + memset (&$$, '\0', sizeof ($$)); + $$.address_subreg_nr = $1.subreg_nr; + $$.indirect_offset = $3; + } + | addrreg + { + memset (&$$, '\0', sizeof ($$)); + $$.address_subreg_nr = $1.subreg_nr; + $$.indirect_offset = 0; + } +; + +/* The immaddroffset provides an immediate offset value added to the addresses + * from the address register in register-indirect register access. + */ +immaddroffset: /* empty */ { $$ = 0; } + | exp +; + + +/* 1.4.5: Register files and register numbers */ +subregnum: DOT exp + { + $$ = $2; + } + | %prec SUBREGNUM + { + /* Default to subreg 0 if unspecified. */ + $$ = 0; + } +; + +directgenreg: GENREG subregnum + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_GENERAL_REGISTER_FILE; + $$.reg_nr = $1; + $$.subreg_nr = $2; + } +; + +indirectgenreg: GENREGFILE LSQUARE addrparam RSQUARE + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_GENERAL_REGISTER_FILE; + $$.address_subreg_nr = $3.address_subreg_nr; + $$.indirect_offset = $3.indirect_offset; + } +; + +directmsgreg: MSGREG subregnum + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_MESSAGE_REGISTER_FILE; + $$.reg_nr = $1; + $$.subreg_nr = $2; + } +; + +indirectmsgreg: MSGREGFILE LSQUARE addrparam RSQUARE + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_MESSAGE_REGISTER_FILE; + $$.address_subreg_nr = $3.address_subreg_nr; + $$.indirect_offset = $3.indirect_offset; + } +; + +addrreg: ADDRESSREG subregnum + { + if ($1 != 0) { + fprintf(stderr, + "address register number %d out of range", $1); + YYERROR; + } + memset (&$$, '\0', sizeof ($$)); + $$.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; + } + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + $$.reg_nr = BRW_ARF_ACCUMULATOR | $1; + $$.subreg_nr = $2; + } +; + +flagreg: FLAGREG subregnum + { + if ((!IS_GENp(7) && $1) > 0 || + (IS_GENp(7) && $1 > 1)) { + fprintf(stderr, + "flag register number %d out of range\n", $1); + YYERROR; + } + + if ($2 > 1) { + fprintf(stderr, + "flag subregister number %d out of range\n", $1); + YYERROR; + } + + memset (&$$, '\0', sizeof ($$)); + $$.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; + } + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + $$.reg_nr = BRW_ARF_MASK; + $$.subreg_nr = $2; + } + | mask_subreg + { + memset (&$$, '\0', sizeof ($$)); + $$.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; + } + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + $$.reg_nr = BRW_ARF_MASK_STACK; + $$.subreg_nr = $2; + } + | maskstack_subreg + { + memset (&$$, '\0', sizeof ($$)); + $$.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; + } + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + $$.reg_nr = BRW_ARF_MASK_STACK_DEPTH; + $$.subreg_nr = $2; + } + | maskstackdepth_subreg + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + $$.reg_nr = BRW_ARF_MASK_STACK_DEPTH; + $$.subreg_nr = $1; + } +; + +maskstackdepth_subreg: IMSD | LMSD +; + */ + +notifyreg: NOTIFYREG regtype + { + int num_notifyreg = (IS_GENp(6)) ? 3 : 2; + + if ($1 > num_notifyreg) { + fprintf(stderr, + "notification register number %d out of range", + $1); + YYERROR; + } + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + + if (IS_GENp(6)) { + $$.reg_nr = BRW_ARF_NOTIFICATION_COUNT; + $$.subreg_nr = $1; + } else { + $$.reg_nr = BRW_ARF_NOTIFICATION_COUNT | $1; + $$.subreg_nr = 0; + } + } +/* + | NOTIFYREG regtype + { + if ($1 > 1) { + fprintf(stderr, + "notification register number %d out of range", + $1); + YYERROR; + } + memset (&$$, '\0', sizeof ($$)); + $$.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; + } + memset (&$$, '\0', sizeof ($$)); + $$.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; + } + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + $$.reg_nr = BRW_ARF_CONTROL | $1; + $$.subreg_nr = $2; + } +; + +ipreg: IPREG regtype + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + $$.reg_nr = BRW_ARF_IP; + $$.subreg_nr = 0; + } +; + +nullreg: NULL_TOKEN + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; + $$.reg_nr = BRW_ARF_NULL; + $$.subreg_nr = 0; + } +; + +/* 1.4.6: Relative locations */ +relativelocation: + simple_int + { + if (($1 > 32767) || ($1 < -32768)) { + fprintf(stderr, + "error: relative offset %d out of range \n", + $1); + YYERROR; + } + + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_IMMEDIATE_VALUE; + $$.reg_type = BRW_REGISTER_TYPE_D; + $$.imm32 = $1 & 0x0000ffff; + } + | STRING + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_IMMEDIATE_VALUE; + $$.reg_type = BRW_REGISTER_TYPE_D; + $$.reloc_target = $1; + } +; + +relativelocation2: + STRING + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_IMMEDIATE_VALUE; + $$.reg_type = BRW_REGISTER_TYPE_D; + $$.reloc_target = $1; + } + | exp + { + memset (&$$, '\0', sizeof ($$)); + $$.reg_file = BRW_IMMEDIATE_VALUE; + $$.reg_type = BRW_REGISTER_TYPE_D; + $$.imm32 = $1; + } + | directgenreg region regtype + { + set_direct_src_operand(&$$, &$1, $3.type); + $$.vert_stride = $2.vert_stride; + $$.width = $2.width; + $$.horiz_stride = $2.horiz_stride; + $$.default_region = $2.is_default; + } + | symbol_reg_p + { + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_DIRECT; + $$.reg_file = $1.base.reg_file; + $$.reg_nr = $1.base.reg_nr; + $$.subreg_nr = $1.base.subreg_nr; + $$.reg_type = $1.type; + $$.vert_stride = $1.src_region.vert_stride; + $$.width = $1.src_region.width; + $$.horiz_stride = $1.src_region.horiz_stride; + } + | indirectgenreg indirectregion regtype + { + memset (&$$, '\0', sizeof ($$)); + $$.address_mode = BRW_ADDRESS_REGISTER_INDIRECT_REGISTER; + $$.reg_file = $1.reg_file; + $$.address_subreg_nr = $1.address_subreg_nr; + $$.indirect_offset = $1.indirect_offset; + $$.reg_type = $3.type; + $$.vert_stride = $2.vert_stride; + $$.width = $2.width; + $$.horiz_stride = $2.horiz_stride; + } +; + +/* 1.4.7: Regions */ +dstregion: /* empty */ + { + $$ = DEFAULT_DSTREGION; + } + |LANGLE exp 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: /* empty */ + { + /* XXX is this default value correct?*/ + memset (&$$, '\0', sizeof ($$)); + $$.vert_stride = ffs(0); + $$.width = ffs(1) - 1; + $$.horiz_stride = ffs(0); + $$.is_default = 1; + } + |LANGLE exp RANGLE + { + /* XXX is this default value correct for accreg?*/ + memset (&$$, '\0', sizeof ($$)); + $$.vert_stride = ffs($2); + $$.width = ffs(1) - 1; + $$.horiz_stride = ffs(0); + } + |LANGLE exp COMMA exp COMMA exp RANGLE + { + memset (&$$, '\0', sizeof ($$)); + $$.vert_stride = ffs($2); + $$.width = ffs($4) - 1; + $$.horiz_stride = ffs($6); + } + | LANGLE exp SEMICOLON exp COMMA exp RANGLE + { + memset (&$$, '\0', sizeof ($$)); + $$.vert_stride = ffs($2); + $$.width = ffs($4) - 1; + $$.horiz_stride = ffs($6); + } + +; +/* region_wh is used in specifying indirect operands where rather than having + * a vertical stride, you use subsequent address registers to get a new base + * offset for the next row. + */ +region_wh: LANGLE exp COMMA exp RANGLE + { + memset (&$$, '\0', sizeof ($$)); + $$.vert_stride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL; + $$.width = ffs($2) - 1; + $$.horiz_stride = ffs($4); + } +; + +indirectregion: region | region_wh +; + +/* 1.4.8: Types */ + +/* regtype returns an integer register type suitable for inserting into an + * instruction. + */ +regtype: /* empty */ + { $$.type = program_defaults.register_type;$$.is_default = 1;} + | TYPE_F { $$.type = BRW_REGISTER_TYPE_F;$$.is_default = 0; } + | TYPE_UD { $$.type = BRW_REGISTER_TYPE_UD;$$.is_default = 0; } + | TYPE_D { $$.type = BRW_REGISTER_TYPE_D;$$.is_default = 0; } + | TYPE_UW { $$.type = BRW_REGISTER_TYPE_UW;$$.is_default = 0; } + | TYPE_W { $$.type = BRW_REGISTER_TYPE_W;$$.is_default = 0; } + | TYPE_UB { $$.type = BRW_REGISTER_TYPE_UB;$$.is_default = 0; } + | TYPE_B { $$.type = BRW_REGISTER_TYPE_B;$$.is_default = 0; } +; + +srcimmtype: /* empty */ + { + /* XXX change to default when pragma parse is done */ + $$ = BRW_REGISTER_TYPE_D; + } + |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_V { $$ = BRW_REGISTER_TYPE_V; } + | TYPE_VF { $$ = BRW_REGISTER_TYPE_VF; } +; + +/* 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.9: Write mask */ +/* Returns a partially completed dst_operand, with just the writemask bits + * filled out. + */ +writemask: /* empty */ + { + $$.writemask_set = 0; + $$.writemask = 0xf; + } + | DOT writemask_x writemask_y writemask_z writemask_w + { + $$.writemask_set = 1; + $$.writemask = $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; } +; + +/* 1.4.11: Immediate values */ +imm32: exp { $$.r = imm32_d; $$.u.d = $1; } + | NUMBER { $$.r = imm32_f; $$.u.f = $1; } +; + +/* 1.4.12: Predication and modifiers */ +predicate: /* empty */ + { + $$.header.predicate_control = BRW_PREDICATE_NONE; + $$.bits2.da1.flag_reg_nr = 0; + $$.bits2.da1.flag_subreg_nr = 0; + $$.header.predicate_inverse = 0; + } + | LPAREN predstate flagreg predctrl RPAREN + { + $$.header.predicate_control = $4; + /* XXX: Should deal with erroring when the user tries to + * set a predicate for one flag register and conditional + * modification on the other flag register. + */ + $$.bits2.da1.flag_reg_nr = ($3.reg_nr & 0xF); + $$.bits2.da1.flag_subreg_nr = $3.subreg_nr; + $$.header.predicate_inverse = $2; + } +; + +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 { $$ = BRW_PREDICATE_ALIGN1_ANYV; } + | ALLV { $$ = BRW_PREDICATE_ALIGN1_ALLV; } + | ANY2H { $$ = BRW_PREDICATE_ALIGN1_ANY2H; } + | ALL2H { $$ = BRW_PREDICATE_ALIGN1_ALL2H; } + | ANY4H { $$ = BRW_PREDICATE_ALIGN1_ANY4H; } + | ALL4H { $$ = BRW_PREDICATE_ALIGN1_ALL4H; } + | ANY8H { $$ = BRW_PREDICATE_ALIGN1_ANY8H; } + | ALL8H { $$ = BRW_PREDICATE_ALIGN1_ALL8H; } + | ANY16H { $$ = BRW_PREDICATE_ALIGN1_ANY16H; } + | ALL16H { $$ = BRW_PREDICATE_ALIGN1_ALL16H; } +; + +negate: /* empty */ { $$ = 0; } + | MINUS { $$ = 1; } +; + +abs: /* empty */ { $$ = 0; } + | ABS { $$ = 1; } +; + +execsize: /* empty */ %prec EMPTEXECSIZE + { + $$ = ffs(program_defaults.execute_size) - 1; + } + |LPAREN exp 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; } + | SATURATE { $$ = BRW_INSTRUCTION_SATURATE; } +; +conditionalmodifier: condition + { + $$.cond = $1; + $$.flag_reg_nr = 0; + $$.flag_subreg_nr = -1; + } + | condition DOT flagreg + { + $$.cond = $1; + $$.flag_reg_nr = ($3.reg_nr & 0xF); + $$.flag_subreg_nr = $3.subreg_nr; + } + +condition: /* empty */ { $$ = BRW_CONDITIONAL_NONE; } + | ZERO + | EQUAL + | NOT_ZERO + | NOT_EQUAL + | GREATER + | GREATER_EQUAL + | LESS + | LESS_EQUAL + | ROUND_INCREMENT + | OVERFLOW + | UNORDERED +; + +/* 1.4.13: Instruction options */ +instoptions: /* empty */ + { memset(&$$, 0, sizeof($$)); } + | LCURLY instoption_list RCURLY + { $$ = $2; } +; + +instoption_list:instoption_list COMMA instoption + { + $$ = $1; + switch ($3) { + 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: + if (!IS_GENp(6)) { + $$.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 ACCWRCTRL: + $$.header.acc_wr_control = BRW_ACCWRCTRL_ACCWRCTRL; + } + } + | instoption_list instoption + { + $$ = $1; + switch ($2) { + 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: + if (!IS_GENp(6)) { + $$.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. */ + { + memset(&$$, 0, sizeof($$)); + } +; + +instoption: ALIGN1 { $$ = ALIGN1; } + | ALIGN16 { $$ = ALIGN16; } + | SECHALF { $$ = SECHALF; } + | COMPR { $$ = COMPR; } + | SWITCH { $$ = SWITCH; } + | ATOMIC { $$ = ATOMIC; } + | NODDCHK { $$ = NODDCHK; } + | NODDCLR { $$ = NODDCLR; } + | MASK_DISABLE { $$ = MASK_DISABLE; } + | BREAKPOINT { $$ = BREAKPOINT; } + | ACCWRCTRL { $$ = ACCWRCTRL; } + | EOT { $$ = EOT; } +; + +%% +extern int yylineno; +extern char *input_filename; + +int errors; + +void yyerror (char *msg) +{ + fprintf(stderr, "%s: %d: %s at \"%s\"\n", + input_filename, yylineno, msg, lex_text()); + ++errors; +} + +static int get_type_size(GLuint type) +{ + int size = 1; + + switch (type) { + case BRW_REGISTER_TYPE_F: + case BRW_REGISTER_TYPE_UD: + case BRW_REGISTER_TYPE_D: + size = 4; + break; + + case BRW_REGISTER_TYPE_UW: + case BRW_REGISTER_TYPE_W: + size = 2; + break; + + case BRW_REGISTER_TYPE_UB: + case BRW_REGISTER_TYPE_B: + size = 1; + break; + + default: + assert(0); + size = 1; + break; + } + + return size; +} + +static int get_subreg_address(GLuint regfile, GLuint type, GLuint subreg, GLuint address_mode) +{ + int unit_size = 1; + + if (address_mode == BRW_ADDRESS_DIRECT) { + if (advanced_flag == 1) { + if ((regfile == BRW_GENERAL_REGISTER_FILE || + regfile == BRW_MESSAGE_REGISTER_FILE || + regfile == BRW_ARCHITECTURE_REGISTER_FILE)) { + + unit_size = get_type_size(type); + } + } + } else { + unit_size = 1; + } + + return subreg * unit_size; +} + +/* only used in indirect address mode. + * input: sub-register number of an address register + * output: the value of AddrSubRegNum in the instruction binary code + * + * input output(advanced_flag==0) output(advanced_flag==1) + * a0.0 0 0 + * a0.1 invalid input 1 + * a0.2 1 2 + * a0.3 invalid input 3 + * a0.4 2 4 + * a0.5 invalid input 5 + * a0.6 3 6 + * a0.7 invalid input 7 + * a0.8 4 invalid input + * a0.10 5 invalid input + * a0.12 6 invalid input + * a0.14 7 invalid input + */ +static int get_indirect_subreg_address(GLuint subreg) +{ + return advanced_flag == 0 ? subreg / 2 : subreg; +} + +static void reset_instruction_src_region(struct brw_instruction *instr, + struct src_operand *src) +{ + if (!src->default_region) + return; + + if (src->reg_file == BRW_ARCHITECTURE_REGISTER_FILE && + ((src->reg_nr & 0xF0) == BRW_ARF_ADDRESS)) { + src->vert_stride = ffs(0); + src->width = ffs(1) - 1; + src->horiz_stride = ffs(0); + } else if (src->reg_file == BRW_ARCHITECTURE_REGISTER_FILE && + ((src->reg_nr & 0xF0) == BRW_ARF_ACCUMULATOR)) { + int horiz_stride = 1, width, vert_stride; + if (instr->header.compression_control == BRW_COMPRESSION_COMPRESSED) { + width = 16; + } else { + width = 8; + } + + if (width > (1 << instr->header.execution_size)) + width = (1 << instr->header.execution_size); + + vert_stride = horiz_stride * width; + src->vert_stride = ffs(vert_stride); + src->width = ffs(width) - 1; + src->horiz_stride = ffs(horiz_stride); + } else if ((src->reg_file == BRW_ARCHITECTURE_REGISTER_FILE) && + (src->reg_nr == BRW_ARF_NULL) && + (instr->header.opcode == BRW_OPCODE_SEND)) { + src->vert_stride = ffs(8); + src->width = ffs(8) - 1; + src->horiz_stride = ffs(1); + } else { + + int horiz_stride = 1, width, vert_stride; + + if (instr->header.execution_size == 0) { /* scalar */ + horiz_stride = 0; + width = 1; + vert_stride = 0; + } else { + if ((instr->header.opcode == BRW_OPCODE_MUL) || + (instr->header.opcode == BRW_OPCODE_MAC) || + (instr->header.opcode == BRW_OPCODE_CMP) || + (instr->header.opcode == BRW_OPCODE_ASR) || + (instr->header.opcode == BRW_OPCODE_ADD) || + (instr->header.opcode == BRW_OPCODE_SHL)) { + horiz_stride = 0; + width = 1; + vert_stride = 0; + } else { + width = (1 << instr->header.execution_size) / horiz_stride; + vert_stride = horiz_stride * width; + + if (get_type_size(src->reg_type) * (width + src->subreg_nr) > 32) { + horiz_stride = 0; + width = 1; + vert_stride = 0; + } + } + } + + src->vert_stride = ffs(vert_stride); + src->width = ffs(width) - 1; + src->horiz_stride = ffs(horiz_stride); + } +} + +/** + * Fills in the destination register information in instr from the bits in dst. + */ +int set_instruction_dest(struct brw_instruction *instr, + struct dst_operand *dest) +{ + if (dest->horiz_stride == DEFAULT_DSTREGION) + dest->horiz_stride = ffs(1); + if (dest->address_mode == BRW_ADDRESS_DIRECT && + instr->header.access_mode == BRW_ALIGN_1) { + instr->bits1.da1.dest_reg_file = dest->reg_file; + instr->bits1.da1.dest_reg_type = dest->reg_type; + instr->bits1.da1.dest_subreg_nr = get_subreg_address(dest->reg_file, dest->reg_type, dest->subreg_nr, dest->address_mode); + instr->bits1.da1.dest_reg_nr = dest->reg_nr; + instr->bits1.da1.dest_horiz_stride = dest->horiz_stride; + instr->bits1.da1.dest_address_mode = dest->address_mode; + if (dest->writemask_set) { + fprintf(stderr, "error: write mask set in align1 " + "instruction\n"); + return 1; + } + } else if (dest->address_mode == BRW_ADDRESS_DIRECT) { + instr->bits1.da16.dest_reg_file = dest->reg_file; + instr->bits1.da16.dest_reg_type = dest->reg_type; + instr->bits1.da16.dest_subreg_nr = get_subreg_address(dest->reg_file, dest->reg_type, dest->subreg_nr, dest->address_mode); + instr->bits1.da16.dest_reg_nr = dest->reg_nr; + instr->bits1.da16.dest_address_mode = dest->address_mode; + instr->bits1.da16.dest_horiz_stride = ffs(1); + instr->bits1.da16.dest_writemask = dest->writemask; + } else if (instr->header.access_mode == BRW_ALIGN_1) { + instr->bits1.ia1.dest_reg_file = dest->reg_file; + instr->bits1.ia1.dest_reg_type = dest->reg_type; + instr->bits1.ia1.dest_subreg_nr = get_indirect_subreg_address(dest->address_subreg_nr); + instr->bits1.ia1.dest_horiz_stride = dest->horiz_stride; + instr->bits1.ia1.dest_indirect_offset = dest->indirect_offset; + instr->bits1.ia1.dest_address_mode = dest->address_mode; + if (dest->writemask_set) { + fprintf(stderr, "error: write mask set in align1 " + "instruction\n"); + return 1; + } + } else { + instr->bits1.ia16.dest_reg_file = dest->reg_file; + instr->bits1.ia16.dest_reg_type = dest->reg_type; + instr->bits1.ia16.dest_subreg_nr = get_indirect_subreg_address(dest->address_subreg_nr); + instr->bits1.ia16.dest_writemask = dest->writemask; + instr->bits1.ia16.dest_horiz_stride = ffs(1); + instr->bits1.ia16.dest_indirect_offset = (dest->indirect_offset >> 4); /* half register aligned */ + instr->bits1.ia16.dest_address_mode = dest->address_mode; + } + + return 0; +} + +/* Sets the first source operand for the instruction. Returns 0 on success. */ +int set_instruction_src0(struct brw_instruction *instr, + struct src_operand *src) +{ + if (advanced_flag) { + reset_instruction_src_region(instr, 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 (src->address_mode == BRW_ADDRESS_DIRECT) { + if (instr->header.access_mode == BRW_ALIGN_1) { + instr->bits2.da1.src0_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode); + 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 = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode); + 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; + } + } else { + if (instr->header.access_mode == BRW_ALIGN_1) { + instr->bits2.ia1.src0_indirect_offset = src->indirect_offset; + instr->bits2.ia1.src0_subreg_nr = get_indirect_subreg_address(src->address_subreg_nr); + instr->bits2.ia1.src0_abs = src->abs; + instr->bits2.ia1.src0_negate = src->negate; + instr->bits2.ia1.src0_address_mode = src->address_mode; + instr->bits2.ia1.src0_horiz_stride = src->horiz_stride; + instr->bits2.ia1.src0_width = src->width; + instr->bits2.ia1.src0_vert_stride = src->vert_stride; + if (src->swizzle_set) { + fprintf(stderr, "error: swizzle bits set in align1 " + "instruction\n"); + return 1; + } + } else { + instr->bits2.ia16.src0_swz_x = src->swizzle_x; + instr->bits2.ia16.src0_swz_y = src->swizzle_y; + instr->bits2.ia16.src0_indirect_offset = (src->indirect_offset >> 4); /* half register aligned */ + instr->bits2.ia16.src0_subreg_nr = get_indirect_subreg_address(src->address_subreg_nr); + instr->bits2.ia16.src0_abs = src->abs; + instr->bits2.ia16.src0_negate = src->negate; + instr->bits2.ia16.src0_address_mode = src->address_mode; + instr->bits2.ia16.src0_swz_z = src->swizzle_z; + instr->bits2.ia16.src0_swz_w = src->swizzle_w; + instr->bits2.ia16.src0_vert_stride = src->vert_stride; + } + } + + 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) +{ + if (advanced_flag) { + reset_instruction_src_region(instr, 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 (src->address_mode == BRW_ADDRESS_DIRECT) { + if (instr->header.access_mode == BRW_ALIGN_1) { + instr->bits3.da1.src1_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode); + 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; + instr->bits3.da1.src1_address_mode = src->address_mode; + /* XXX why? + 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 = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode); + 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; + instr->bits3.da16.src1_address_mode = src->address_mode; + if (src->address_mode != BRW_ADDRESS_DIRECT) { + fprintf(stderr, "error: swizzle bits set in align1 " + "instruction\n"); + return 1; + } + } + } else { + if (instr->header.access_mode == BRW_ALIGN_1) { + instr->bits3.ia1.src1_indirect_offset = src->indirect_offset; + instr->bits3.ia1.src1_subreg_nr = get_indirect_subreg_address(src->address_subreg_nr); + instr->bits3.ia1.src1_abs = src->abs; + instr->bits3.ia1.src1_negate = src->negate; + instr->bits3.ia1.src1_address_mode = src->address_mode; + instr->bits3.ia1.src1_horiz_stride = src->horiz_stride; + instr->bits3.ia1.src1_width = src->width; + instr->bits3.ia1.src1_vert_stride = src->vert_stride; + if (src->swizzle_set) { + fprintf(stderr, "error: swizzle bits set in align1 " + "instruction\n"); + return 1; + } + } else { + instr->bits3.ia16.src1_swz_x = src->swizzle_x; + instr->bits3.ia16.src1_swz_y = src->swizzle_y; + instr->bits3.ia16.src1_indirect_offset = (src->indirect_offset >> 4); /* half register aligned */ + instr->bits3.ia16.src1_subreg_nr = get_indirect_subreg_address(src->address_subreg_nr); + instr->bits3.ia16.src1_abs = src->abs; + instr->bits3.ia16.src1_negate = src->negate; + instr->bits3.ia16.src1_address_mode = src->address_mode; + instr->bits3.ia16.src1_swz_z = src->swizzle_z; + instr->bits3.ia16.src1_swz_w = src->swizzle_w; + instr->bits3.ia16.src1_vert_stride = src->vert_stride; + } + } + + return 0; +} + +/* convert 2-src reg type to 3-src reg type + * + * 2-src reg type: + * 000=UD 001=D 010=UW 011=W 100=UB 101=B 110=DF 111=F + * + * 3-src reg type: + * 00=F 01=D 10=UD 11=DF + */ +static int reg_type_2_to_3(int reg_type) +{ + int r = 0; + switch(reg_type) { + case 7: r = 0; break; + case 1: r = 1; break; + case 0: r = 2; break; + // TODO: supporting DF + } + return r; +} + +int set_instruction_dest_three_src(struct brw_instruction *instr, + struct dst_operand *dest) +{ + instr->bits1.three_src_gen6.dest_reg_file = dest->reg_file; + instr->bits1.three_src_gen6.dest_reg_nr = dest->reg_nr; + instr->bits1.three_src_gen6.dest_subreg_nr = get_subreg_address(dest->reg_file, dest->reg_type, dest->subreg_nr, dest->address_mode) / 4; // in DWORD + instr->bits1.three_src_gen6.dest_writemask = dest->writemask; + instr->bits1.three_src_gen6.dest_reg_type = reg_type_2_to_3(dest->reg_type); + return 0; +} + +int set_instruction_src0_three_src(struct brw_instruction *instr, + struct src_operand *src) +{ + if (advanced_flag) { + reset_instruction_src_region(instr, src); + } + // TODO: supporting src0 swizzle, src0 modifier, src0 rep_ctrl + instr->bits1.three_src_gen6.src_reg_type = reg_type_2_to_3(src->reg_type); + instr->bits2.three_src_gen6.src0_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode) / 4; // in DWORD + instr->bits2.three_src_gen6.src0_reg_nr = src->reg_nr; + return 0; +} + +int set_instruction_src1_three_src(struct brw_instruction *instr, + struct src_operand *src) +{ + if (advanced_flag) { + reset_instruction_src_region(instr, src); + } + // TODO: supporting src1 swizzle, src1 modifier, src1 rep_ctrl + int v = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode) / 4; // in DWORD + instr->bits2.three_src_gen6.src1_subreg_nr_low = v % 4; // lower 2 bits + instr->bits3.three_src_gen6.src1_subreg_nr_high = v / 4; // highest bit + instr->bits3.three_src_gen6.src1_reg_nr = src->reg_nr; + return 0; +} + +int set_instruction_src2_three_src(struct brw_instruction *instr, + struct src_operand *src) +{ + if (advanced_flag) { + reset_instruction_src_region(instr, src); + } + // TODO: supporting src2 swizzle, src2 modifier, src2 rep_ctrl + instr->bits3.three_src_gen6.src2_subreg_nr = get_subreg_address(src->reg_file, src->reg_type, src->subreg_nr, src->address_mode) / 4; // in DWORD + instr->bits3.three_src_gen6.src2_reg_nr = src->reg_nr; + 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_instruction_predicate(struct brw_instruction *instr, + struct brw_instruction *predicate) +{ + instr->header.predicate_control = predicate->header.predicate_control; + instr->header.predicate_inverse = predicate->header.predicate_inverse; + instr->bits2.da1.flag_reg_nr = predicate->bits2.da1.flag_reg_nr; + instr->bits2.da1.flag_subreg_nr = predicate->bits2.da1.flag_subreg_nr; +} + +void set_direct_dst_operand(struct dst_operand *dst, struct direct_reg *reg, + int type) +{ + memset(dst, 0, sizeof(*dst)); + dst->address_mode = BRW_ADDRESS_DIRECT; + dst->reg_file = reg->reg_file; + dst->reg_nr = reg->reg_nr; + dst->subreg_nr = reg->subreg_nr; + dst->reg_type = type; + dst->horiz_stride = 1; + dst->writemask_set = 0; + dst->writemask = 0xf; +} + +void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg, + int type) +{ + memset(src, 0, sizeof(*src)); + src->address_mode = BRW_ADDRESS_DIRECT; + 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 = 0; + src->negate = 0; + src->abs = 0; + src->swizzle_set = 0; + src->swizzle_x = BRW_CHANNEL_X; + src->swizzle_y = BRW_CHANNEL_Y; + src->swizzle_z = BRW_CHANNEL_Z; + src->swizzle_w = BRW_CHANNEL_W; +} |