diff options
author | Eric Anholt <eric@anholt.net> | 2006-08-29 18:31:34 -0700 |
---|---|---|
committer | Damien Lespiau <damien.lespiau@intel.com> | 2013-03-04 15:54:23 +0000 |
commit | 3bcf6b29cdef3cde36a55a5dde6d451a8d8e2f4b (patch) | |
tree | aa7217f598e315cd28e5204d6cbf7e7e3cea252d | |
parent | 2dac0a19a438d27b03e901cc70ef0a9a27039154 (diff) |
Add support for register-indirect access in destination registers.
This is untested. Also, a few bits for source operand register-indirect access
sneak in with this commit.
-rw-r--r-- | assembler/gen4asm.h | 4 | ||||
-rw-r--r-- | assembler/gram.y | 133 | ||||
-rw-r--r-- | assembler/lex.l | 17 |
3 files changed, 139 insertions, 15 deletions
diff --git a/assembler/gen4asm.h b/assembler/gen4asm.h index 2ac54b9c..2db36994 100644 --- a/assembler/gen4asm.h +++ b/assembler/gen4asm.h @@ -50,6 +50,9 @@ struct dst_operand { int horiz_stride; int address_mode; /* 0 if direct, 1 if register-indirect */ + + /* Indirect addressing */ + int address_subreg_nr; int indirect_offset; }; @@ -65,6 +68,7 @@ struct src_operand { int horiz_stride, width, vert_stride; int address_mode; /* 0 if direct, 1 if register-indirect */ + int address_subreg_nr; int indirect_offset; /* XXX */ int swizzle_set; diff --git a/assembler/gram.y b/assembler/gram.y index 9aa729c2..544d321c 100644 --- a/assembler/gram.y +++ b/assembler/gram.y @@ -44,9 +44,13 @@ struct region { int vert_stride, width, horiz_stride; } region; - struct gen_reg { + struct direct_reg { int reg_file, reg_nr, subreg_nr; } direct_reg; + struct indirect_reg { + int reg_file, address_subreg_nr, indirect_offset; + } indirect_reg; + double imm32; struct dst_operand dst_operand; @@ -57,6 +61,7 @@ %token LPAREN RPAREN %token LANGLE RANGLE %token LCURLY RCURLY +%token LSQUARE RSQUARE %token COMMA %token DOT %token PLUS MINUS ABS @@ -72,6 +77,7 @@ %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 @@ -104,16 +110,17 @@ %type <integer> unaryop binaryop binaryaccop %type <integer> conditionalmodifier saturate negate abs chansel %type <integer> writemask_x writemask_y writemask_z writemask_w -%type <integer> regtype srcimmtype execsize dstregion +%type <integer> regtype 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 +%type <region> region region_wh %type <direct_reg> directgenreg directmsgreg addrreg accreg flagreg maskreg %type <direct_reg> maskstackreg maskstackdepthreg notifyreg %type <direct_reg> statereg controlreg ipreg nullreg %type <direct_reg> dstoperandex_typed srcarchoperandex_typed +%type <indirect_reg> indirectgenreg indirectmsgreg addrparam %type <integer> mask_subreg maskstack_subreg maskstackdepth_subreg %type <imm32> imm32 %type <dst_operand> dst dstoperand dstoperandex dstreg post_dst writemask @@ -468,19 +475,37 @@ dstoperandex: dstoperandex_typed dstregion regtype dstoperandex_typed: accreg | flagreg | addrreg | maskreg ; -/* XXX: indirectgenreg, indirectmsgreg */ +/* Returns a partially complete destination register consisting of the + * direct or indirect register addressing fields, but not stride or writemask. + */ dstreg: directgenreg { + $$.address_mode = BRW_ADDRESS_DIRECT; $$.reg_file = $1.reg_file; $$.reg_nr = $1.reg_nr; $$.subreg_nr = $1.subreg_nr; } | directmsgreg { + $$.address_mode = BRW_ADDRESS_DIRECT; $$.reg_file = $1.reg_file; $$.reg_nr = $1.reg_nr; $$.subreg_nr = $1.subreg_nr; } + | indirectgenreg + { + $$.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 + { + $$.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 */ @@ -540,7 +565,7 @@ imm32reg: imm32 srcimmtype directsrcaccoperand: directsrcoperand | accreg regtype { - set_src_operand(&$$, &$1, $2); + set_direct_src_operand(&$$, &$1, $2); } ; @@ -559,27 +584,27 @@ srcarchoperandex: srcarchoperandex_typed region regtype } | maskstackreg { - set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UB); + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UB); } | controlreg { - set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } | statereg { - set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } | notifyreg { - set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } | ipreg { - set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } | nullreg { - set_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); + set_direct_src_operand(&$$, &$1, BRW_REGISTER_TYPE_UD); } ; @@ -611,6 +636,30 @@ directsrcoperand: | srcarchoperandex ; +/* 1.4.4: Address Registers */ +/* Returns a partially-completed indirect_reg consisting of the address + * register fields for register-indirect access. + */ +addrparam: addrreg immaddroffset + { + if ($2 < -512 || $2 > 511) { + fprintf(stderr, "Address immediate offset %d out of" + "range\n", $2); + YYERROR; + } + $$.address_subreg_nr = $1.subreg_nr; + $$.indirect_offset = $2; + } +; + +/* The immaddroffset provides an immediate offset value added to the addresses + * from the address register in register-indirect register access. + */ +immaddroffset: /* empty */ { $$ = 0; } + | INTEGER +; + + /* 1.4.5: Register files and register numbers */ subregnum: DOT INTEGER { @@ -631,6 +680,14 @@ directgenreg: GENREG subregnum } ; +indirectgenreg: GENREGFILE LSQUARE addrparam RSQUARE + { + $$.reg_file = BRW_GENERAL_REGISTER_FILE; + $$.address_subreg_nr = $3.address_subreg_nr; + $$.indirect_offset = $3.indirect_offset; + } +; + directmsgreg: MSGREG subregnum { $$.reg_file = BRW_MESSAGE_REGISTER_FILE; @@ -639,8 +696,21 @@ directmsgreg: MSGREG subregnum } ; +indirectmsgreg: MSGREGFILE LSQUARE addrparam RSQUARE + { + $$.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; + } $$.reg_file = BRW_ARCHITECTURE_REGISTER_FILE; $$.reg_nr = BRW_ARF_ADDRESS | $1; $$.subreg_nr = $2; @@ -821,6 +891,19 @@ region: LANGLE INTEGER COMMA INTEGER COMMA INTEGER RANGLE } ; +/* 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. XXX: source indirect addressing not set up yet. + */ +region_wh: LANGLE INTEGER COMMA INTEGER RANGLE + { + $$.vert_stride = BRW_VERTICAL_STRIDE_ONE_DIMENSIONAL; + $$.width = ffs($2) - 1; + $$.horiz_stride = ffs($4); + } +; + + /* 1.4.8: Types */ /* regtype returns an integer register type suitable for inserting into an @@ -1052,7 +1135,8 @@ void yyerror (char *msg) int set_instruction_dest(struct brw_instruction *instr, struct dst_operand *dest) { - if (instr->header.access_mode == BRW_ALIGN_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 = dest->subreg_nr; @@ -1064,13 +1148,32 @@ int set_instruction_dest(struct brw_instruction *instr, "instruction\n"); return 1; } - } else { + } 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 = dest->subreg_nr; instr->bits1.da16.dest_reg_nr = dest->reg_nr; instr->bits1.da16.dest_address_mode = dest->address_mode; 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 = 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 = dest->address_subreg_nr; + instr->bits1.ia16.dest_writemask = dest->writemask; + instr->bits1.ia16.dest_indirect_offset = dest->indirect_offset; + instr->bits1.ia16.dest_address_mode = dest->address_mode; } return 0; @@ -1180,8 +1283,8 @@ void set_instruction_predicate(struct brw_instruction *instr, instr->bits2.da1.flag_reg_nr = predicate->bits2.da1.flag_reg_nr; } -void set_src_operand(struct src_operand *src, struct gen_reg *reg, - int type) +void set_direct_src_operand(struct src_operand *src, struct direct_reg *reg, + int type) { bzero(src, sizeof(*src)); src->reg_file = reg->reg_file; diff --git a/assembler/lex.l b/assembler/lex.l index e971360d..ef9101a5 100644 --- a/assembler/lex.l +++ b/assembler/lex.l @@ -102,12 +102,23 @@ int saved_state = INITIAL; ">" { return RANGLE; } "{" { return LCURLY; } "}" { return RCURLY; } +"[" { return LSQUARE; } +"]" { return RSQUARE; } "," { return COMMA; } "." { return DOT; } "+" { return PLUS; } "-" { return MINUS; } "(abs)" { return ABS; } + /* Most register accesses are lexed as REGFILE[0-9]+, to prevent the register + * with subreg from being lexed as REGFILE NUMBER instead of + * REGISTER INTEGER DOT INTEGER like we want. The alternative was to use a + * start condition, which wasn't very clean-looking. + * + * However, this means we need to lex the general and message register file + * characters as well, for register-indirect access which is formatted + * like g[a#.#] or m[a#.#]. + */ "acc"[0-9]+ { yylval.integer = atoi(yytext + 1); return ACCREG; @@ -120,6 +131,9 @@ int saved_state = INITIAL; yylval.integer = atoi(yytext + 1); return MSGREG; } +"m" { + return MSGREGFILE; +} "mask"[0-9]+ { yylval.integer = atoi(yytext + 1); return MASKREG; @@ -152,6 +166,9 @@ int saved_state = INITIAL; yylval.integer = atoi(yytext + 1); return GENREG; } +[gr] { + return GENREGFILE; +} "cr"[0-9]+ { yylval.integer = atoi(yytext + 1); return CONTROLREG; |