From: Brian Paul Date: Fri, 10 Jul 2009 19:07:16 +0000 (-0600) Subject: tgis: implement indirect addressing for destination registers X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=baa7ff47d548cdcc1ea68657ee1b0500f78041be;p=mesa.git tgis: implement indirect addressing for destination registers Includes the TGSI interpreter, but not the SSE/PPC/etc code generators. --- diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c index a1891a140ac..18c448a2c77 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.c +++ b/src/gallium/auxiliary/tgsi/tgsi_build.c @@ -584,6 +584,7 @@ tgsi_build_full_instruction( *dst_register = tgsi_build_dst_register( reg->DstRegister.File, reg->DstRegister.WriteMask, + reg->DstRegister.Indirect, reg->DstRegister.Index, instruction, header ); @@ -631,6 +632,28 @@ tgsi_build_full_instruction( header ); prev_token = (struct tgsi_token *) dst_register_ext_modulate; } + + if( reg->DstRegister.Indirect ) { + struct tgsi_src_register *ind; + + if( maxsize <= size ) + return 0; + ind = (struct tgsi_src_register *) &tokens[size]; + size++; + + *ind = tgsi_build_src_register( + reg->DstRegisterInd.File, + reg->DstRegisterInd.SwizzleX, + reg->DstRegisterInd.SwizzleY, + reg->DstRegisterInd.SwizzleZ, + reg->DstRegisterInd.SwizzleW, + reg->DstRegisterInd.Negate, + reg->DstRegisterInd.Indirect, + reg->DstRegisterInd.Dimension, + reg->DstRegisterInd.Index, + instruction, + header ); + } } for( i = 0; i < full_inst->Instruction.NumSrcRegs; i++ ) { @@ -1194,6 +1217,7 @@ struct tgsi_dst_register tgsi_build_dst_register( unsigned file, unsigned mask, + unsigned indirect, int index, struct tgsi_instruction *instruction, struct tgsi_header *header ) @@ -1208,6 +1232,7 @@ tgsi_build_dst_register( dst_register.File = file; dst_register.WriteMask = mask; dst_register.Index = index; + dst_register.Indirect = indirect; instruction_grow( instruction, header ); @@ -1220,6 +1245,7 @@ tgsi_default_full_dst_register( void ) struct tgsi_full_dst_register full_dst_register; full_dst_register.DstRegister = tgsi_default_dst_register(); + full_dst_register.DstRegisterInd = tgsi_default_src_register(); full_dst_register.DstRegisterExtConcode = tgsi_default_dst_register_ext_concode(); full_dst_register.DstRegisterExtModulate = diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.h b/src/gallium/auxiliary/tgsi/tgsi_build.h index 0fd6fabd83d..9a3a077cf2b 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.h +++ b/src/gallium/auxiliary/tgsi/tgsi_build.h @@ -289,6 +289,7 @@ struct tgsi_dst_register tgsi_build_dst_register( unsigned file, unsigned mask, + unsigned indirect, int index, struct tgsi_instruction *instruction, struct tgsi_header *header ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index 76a09af18ee..9b844716bb6 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -355,11 +355,22 @@ iter_instruction( CHR( ',' ); CHR( ' ' ); - _dump_register( - ctx, - dst->DstRegister.File, - dst->DstRegister.Index, - dst->DstRegister.Index ); + if (dst->DstRegister.Indirect) { + _dump_register_ind( + ctx, + dst->DstRegister.File, + dst->DstRegister.Index, + dst->DstRegisterInd.File, + dst->DstRegisterInd.Index, + dst->DstRegisterInd.SwizzleX ); + } + else { + _dump_register( + ctx, + dst->DstRegister.File, + dst->DstRegister.Index, + dst->DstRegister.Index ); + } ENM( dst->DstRegisterExtModulate.Modulate, modulate_names ); _dump_writemask( ctx, dst->DstRegister.WriteMask ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index aba7a3f9374..5cb322a5fa2 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -1395,28 +1395,69 @@ store_dest( union tgsi_exec_channel null; union tgsi_exec_channel *dst; uint execmask = mach->ExecMask; + int offset = 0; /* indirection offset */ + int index; #ifdef DEBUG check_inf_or_nan(chan); #endif + /* There is an extra source register that indirectly subscripts + * a register file. The direct index now becomes an offset + * that is being added to the indirect register. + * + * file[ind[2].x+1], + * where: + * ind = DstRegisterInd.File + * [2] = DstRegisterInd.Index + * .x = DstRegisterInd.SwizzleX + */ + if (reg->DstRegister.Indirect) { + union tgsi_exec_channel index; + union tgsi_exec_channel indir_index; + uint swizzle; + + /* which address register (always zero for now) */ + index.i[0] = + index.i[1] = + index.i[2] = + index.i[3] = reg->DstRegisterInd.Index; + + /* get current value of address register[swizzle] */ + swizzle = tgsi_util_get_src_register_swizzle( ®->DstRegisterInd, CHAN_X ); + + /* fetch values from the address/indirection register */ + fetch_src_file_channel( + mach, + reg->DstRegisterInd.File, + swizzle, + &index, + &indir_index ); + + /* save indirection offset */ + offset = (int) indir_index.f[0]; + } + switch (reg->DstRegister.File) { case TGSI_FILE_NULL: dst = &null; break; case TGSI_FILE_OUTPUT: - dst = &mach->Outputs[mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] - + reg->DstRegister.Index].xyzw[chan_index]; + index = mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] + + reg->DstRegister.Index; + dst = &mach->Outputs[offset + index].xyzw[chan_index]; break; case TGSI_FILE_TEMPORARY: - assert( reg->DstRegister.Index < TGSI_EXEC_NUM_TEMPS ); - dst = &mach->Temps[reg->DstRegister.Index].xyzw[chan_index]; + index = reg->DstRegister.Index; + assert( index < TGSI_EXEC_NUM_TEMPS ); + dst = &mach->Temps[offset + index].xyzw[chan_index]; break; case TGSI_FILE_ADDRESS: - dst = &mach->Addrs[reg->DstRegister.Index].xyzw[chan_index]; + index = reg->DstRegister.Index; + dst = &mach->Addrs[index].xyzw[chan_index]; break; default: diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c index 0081f74ffc4..7f2cfb7988f 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.c +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c @@ -219,7 +219,6 @@ tgsi_parse_token( /* * No support for indirect or multi-dimensional addressing. */ - assert( !inst->FullDstRegisters[i].DstRegister.Indirect ); assert( !inst->FullDstRegisters[i].DstRegister.Dimension ); extended = inst->FullDstRegisters[i].DstRegister.Extended; @@ -246,6 +245,17 @@ tgsi_parse_token( extended = token.Extended; } + + if( inst->FullDstRegisters[i].DstRegister.Indirect ) { + next_token( ctx, &inst->FullDstRegisters[i].DstRegisterInd ); + + /* + * No support for indirect or multi-dimensional addressing. + */ + assert( !inst->FullDstRegisters[i].DstRegisterInd.Indirect ); + assert( !inst->FullDstRegisters[i].DstRegisterInd.Dimension ); + assert( !inst->FullDstRegisters[i].DstRegisterInd.Extended ); + } } assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h index 054350712d8..a289e26e3ac 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.h +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h @@ -48,6 +48,7 @@ struct tgsi_full_header struct tgsi_full_dst_register { struct tgsi_dst_register DstRegister; + struct tgsi_src_register DstRegisterInd; struct tgsi_dst_register_ext_concode DstRegisterExtConcode; struct tgsi_dst_register_ext_modulate DstRegisterExtModulate; };