summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary/tgsi
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary/tgsi')
-rw-r--r--src/gallium/auxiliary/tgsi/Makefile1
-rw-r--r--src/gallium/auxiliary/tgsi/SConscript1
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt48
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_build.c23
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_build.h2
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump.c45
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_dump_c.c8
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.c203
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_exec.h53
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_info.c258
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_info.h17
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h172
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_parse.c13
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_parse.h6
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ppc.c25
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sanity.c33
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sse2.c674
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_sse2.h28
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_text.c18
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.c938
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_ureg.h590
-rw-r--r--src/gallium/auxiliary/tgsi/tgsi_util.h4
22 files changed, 2614 insertions, 546 deletions
diff --git a/src/gallium/auxiliary/tgsi/Makefile b/src/gallium/auxiliary/tgsi/Makefile
index b4900e8dba..5f0a580b09 100644
--- a/src/gallium/auxiliary/tgsi/Makefile
+++ b/src/gallium/auxiliary/tgsi/Makefile
@@ -16,6 +16,7 @@ C_SOURCES = \
tgsi_sse2.c \
tgsi_text.c \
tgsi_transform.c \
+ tgsi_ureg.c \
tgsi_util.c
include ../../Makefile.template
diff --git a/src/gallium/auxiliary/tgsi/SConscript b/src/gallium/auxiliary/tgsi/SConscript
index 8200cce42f..b6bc2924f0 100644
--- a/src/gallium/auxiliary/tgsi/SConscript
+++ b/src/gallium/auxiliary/tgsi/SConscript
@@ -16,6 +16,7 @@ tgsi = env.ConvenienceLibrary(
'tgsi_sse2.c',
'tgsi_text.c',
'tgsi_transform.c',
+ 'tgsi_ureg.c',
'tgsi_util.c',
])
diff --git a/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt
index a3f4947c73..eb492076b7 100644
--- a/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt
+++ b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt
@@ -187,11 +187,7 @@ TGSI Instruction Specification
1.2.6 CND0 - Condition Zero
- dst.x = (src2.x >= 0.0) ? src0.x : src1.x
- dst.y = (src2.y >= 0.0) ? src0.y : src1.y
- dst.z = (src2.z >= 0.0) ? src0.z : src1.z
- dst.w = (src2.w >= 0.0) ? src0.w : src1.w
-
+ Removed. Use (CMP src2, src1, src0) instead.
1.2.7 DOT2ADD - 2-component Dot Product And Add
@@ -665,9 +661,18 @@ TGSI Instruction Specification
TBD
-1.9.8 LOOP - Loop
+1.9.8 BGNFOR - Begin a For-Loop
- TBD
+ dst.x = floor(src.x)
+ dst.y = floor(src.y)
+ dst.z = floor(src.z)
+
+ if (dst.y <= 0)
+ pc = [matching ENDFOR] + 1
+ endif
+
+ Note: The destination must be a loop register.
+ The source must be a constant register.
1.9.9 REP - Repeat
@@ -685,9 +690,16 @@ TGSI Instruction Specification
TBD
-1.9.12 ENDLOOP - End Loop
+1.9.12 ENDFOR - End a For-Loop
- TBD
+ dst.x = dst.x + dst.z
+ dst.y = dst.y - 1.0
+
+ if (dst.y > 0)
+ pc = [matching BGNFOR instruction] + 1
+ endif
+
+ Note: The destination must be a loop register.
1.9.13 ENDREP - End Repeat
@@ -840,7 +852,7 @@ TGSI Instruction Specification
----------
-1.13.1 BGNLOOP2 - Begin Loop
+1.13.1 BGNLOOP - Begin a Loop
TBD
@@ -850,7 +862,7 @@ TGSI Instruction Specification
TBD
-1.13.3 ENDLOOP2 - End Loop
+1.13.3 ENDLOOP - End a Loop
TBD
@@ -1015,12 +1027,12 @@ TGSI Instruction Specification
1.18.1 EXPP - Approximate Exponential Base 2
- Alias for EXP.
+ Use EXP. See also 1.19.3.
1.18.2 LOGP - Logarithm Base 2
- Alias for LG2.
+ Use LOG. See also 1.19.4.
1.19 vs_2_0
@@ -1037,6 +1049,16 @@ TGSI Instruction Specification
Alias for ARR.
+1.19.3 EXPP - Approximate Exponential Base 2
+
+ Use EX2.
+
+
+1.19.4 LOGP - Logarithm Base 2
+
+ Use LG2.
+
+
2 Explanation of symbols used
==============================
diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c
index 94d9c638e1..e0cfc54420 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_build.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_build.c
@@ -335,7 +335,10 @@ tgsi_default_full_immediate( void )
struct tgsi_full_immediate fullimm;
fullimm.Immediate = tgsi_default_immediate();
- fullimm.u.Pointer = (void *) 0;
+ fullimm.u[0].Float = 0.0f;
+ fullimm.u[1].Float = 0.0f;
+ fullimm.u[2].Float = 0.0f;
+ fullimm.u[3].Float = 0.0f;
return fullimm;
}
@@ -352,19 +355,19 @@ immediate_grow(
header_bodysize_grow( header );
}
-struct tgsi_immediate_float32
+union tgsi_immediate_data
tgsi_build_immediate_float32(
float value,
struct tgsi_immediate *immediate,
struct tgsi_header *header )
{
- struct tgsi_immediate_float32 immediate_float32;
+ union tgsi_immediate_data immediate_data;
- immediate_float32.Float = value;
+ immediate_data.Float = value;
immediate_grow( immediate, header );
- return immediate_float32;
+ return immediate_data;
}
unsigned
@@ -384,16 +387,18 @@ tgsi_build_full_immediate(
*immediate = tgsi_build_immediate( header );
+ assert( full_imm->Immediate.NrTokens <= 4 + 1 );
+
for( i = 0; i < full_imm->Immediate.NrTokens - 1; i++ ) {
- struct tgsi_immediate_float32 *if32;
+ union tgsi_immediate_data *data;
if( maxsize <= size )
return 0;
- if32 = (struct tgsi_immediate_float32 *) &tokens[size];
+ data = (union tgsi_immediate_data *) &tokens[size];
size++;
- *if32 = tgsi_build_immediate_float32(
- full_imm->u.ImmediateFloat32[i].Float,
+ *data = tgsi_build_immediate_float32(
+ full_imm->u[i].Float,
immediate,
header );
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.h b/src/gallium/auxiliary/tgsi/tgsi_build.h
index 9a3a077cf2..17d977b059 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_build.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_build.h
@@ -119,7 +119,7 @@ tgsi_build_immediate(
struct tgsi_full_immediate
tgsi_default_full_immediate( void );
-struct tgsi_immediate_float32
+union tgsi_immediate_data
tgsi_build_immediate_float32(
float value,
struct tgsi_immediate *immediate,
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c
index a6994ecd48..111d95b666 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_dump.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c
@@ -33,12 +33,20 @@
#include "tgsi_info.h"
#include "tgsi_iterate.h"
+
+/** Number of spaces to indent for IF/LOOP/etc */
+static const int indent_spaces = 3;
+
+
struct dump_ctx
{
struct tgsi_iterate_context iter;
uint instno;
+ int indent;
+ uint indentation;
+
void (*printf)(struct dump_ctx *ctx, const char *format, ...);
};
@@ -82,7 +90,7 @@ static const char *processor_type_names[] =
"GEOM"
};
-static const char *file_names[] =
+static const char *file_names[TGSI_FILE_COUNT] =
{
"NULL",
"CONST",
@@ -91,7 +99,8 @@ static const char *file_names[] =
"TEMP",
"SAMP",
"ADDR",
- "IMM"
+ "IMM",
+ "LOOP"
};
static const char *interpolate_names[] =
@@ -295,10 +304,12 @@ iter_immediate(
ENM( imm->Immediate.DataType, immediate_type_names );
TXT( " { " );
+
+ assert( imm->Immediate.NrTokens <= 4 + 1 );
for (i = 0; i < imm->Immediate.NrTokens - 1; i++) {
switch (imm->Immediate.DataType) {
case TGSI_IMM_FLOAT32:
- FLT( imm->u.ImmediateFloat32[i].Float );
+ FLT( imm->u[i].Float );
break;
default:
assert( 0 );
@@ -332,13 +343,19 @@ iter_instruction(
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
uint instno = ctx->instno++;
-
+ const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
uint i;
boolean first_reg = TRUE;
INSTID( instno );
TXT( ": " );
- TXT( tgsi_get_opcode_info( inst->Instruction.Opcode )->mnemonic );
+
+ ctx->indent -= info->pre_dedent;
+ for(i = 0; (int)i < ctx->indent; ++i)
+ TXT( " " );
+ ctx->indent += info->post_indent;
+
+ TXT( info->mnemonic );
switch (inst->Instruction.Saturate) {
case TGSI_SAT_NONE:
@@ -470,14 +487,22 @@ iter_instruction(
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_IF:
case TGSI_OPCODE_ELSE:
- case TGSI_OPCODE_BGNLOOP2:
- case TGSI_OPCODE_ENDLOOP2:
+ case TGSI_OPCODE_BGNLOOP:
+ case TGSI_OPCODE_ENDLOOP:
case TGSI_OPCODE_CAL:
TXT( " :" );
UID( inst->InstructionExtLabel.Label );
break;
}
+ /* update indentation */
+ if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
+ inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
+ inst->Instruction.Opcode == TGSI_OPCODE_BGNFOR ||
+ inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
+ ctx->indentation += indent_spaces;
+ }
+
EOL();
return TRUE;
@@ -491,7 +516,9 @@ tgsi_dump_instruction(
struct dump_ctx ctx;
ctx.instno = instno;
+ ctx.indent = 0;
ctx.printf = dump_ctx_printf;
+ ctx.indentation = 0;
iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
}
@@ -523,7 +550,9 @@ tgsi_dump(
ctx.iter.epilog = NULL;
ctx.instno = 0;
+ ctx.indent = 0;
ctx.printf = dump_ctx_printf;
+ ctx.indentation = 0;
tgsi_iterate_shader( tokens, &ctx.iter );
}
@@ -575,7 +604,9 @@ tgsi_dump_str(
ctx.base.iter.epilog = NULL;
ctx.base.instno = 0;
+ ctx.base.indent = 0;
ctx.base.printf = &str_dump_ctx_printf;
+ ctx.base.indentation = 0;
ctx.str = str;
ctx.str[0] = 0;
diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump_c.c b/src/gallium/auxiliary/tgsi/tgsi_dump_c.c
index 3dc61c48ca..4a9c02b141 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_dump_c.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_dump_c.c
@@ -69,7 +69,7 @@ static const char *TGSI_TOKEN_TYPES[] =
"TOKEN_TYPE_INSTRUCTION"
};
-static const char *TGSI_FILES[] =
+static const char *TGSI_FILES[TGSI_FILE_COUNT] =
{
"FILE_NULL",
"FILE_CONSTANT",
@@ -78,7 +78,8 @@ static const char *TGSI_FILES[] =
"FILE_TEMPORARY",
"FILE_SAMPLER",
"FILE_ADDRESS",
- "FILE_IMMEDIATE"
+ "FILE_IMMEDIATE",
+ "FILE_LOOP"
};
static const char *TGSI_INTERPOLATES[] =
@@ -283,12 +284,13 @@ dump_immediate_verbose(
UIX( imm->Immediate.Padding );
}
+ assert( imm->Immediate.NrTokens <= 4 + 1 );
for( i = 0; i < imm->Immediate.NrTokens - 1; i++ ) {
EOL();
switch( imm->Immediate.DataType ) {
case TGSI_IMM_FLOAT32:
TXT( "\nFloat: " );
- FLT( imm->u.ImmediateFloat32[i].Float );
+ FLT( imm->u[i].Float );
break;
default:
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c
index 259894e72e..c79c56debd 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c
@@ -304,14 +304,14 @@ tgsi_exec_machine_bind_shader(
case TGSI_TOKEN_TYPE_IMMEDIATE:
{
uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
- assert( size % 4 == 0 );
- assert( mach->ImmLimit + size / 4 <= TGSI_EXEC_NUM_IMMEDIATES );
+ assert( size <= 4 );
+ assert( mach->ImmLimit + 1 <= TGSI_EXEC_NUM_IMMEDIATES );
for( i = 0; i < size; i++ ) {
- mach->Imms[mach->ImmLimit + i / 4][i % 4] =
- parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
+ mach->Imms[mach->ImmLimit][i] =
+ parse.FullToken.FullImmediate.u[i].Float;
}
- mach->ImmLimit += size / 4;
+ mach->ImmLimit += 1;
}
break;
@@ -373,13 +373,18 @@ tgsi_exec_machine_bind_shader(
}
-void
-tgsi_exec_machine_init(
- struct tgsi_exec_machine *mach )
+struct tgsi_exec_machine *
+tgsi_exec_machine_create( void )
{
+ struct tgsi_exec_machine *mach;
uint i;
- mach->Temps = (struct tgsi_exec_vector *) tgsi_align_128bit( mach->_Temps);
+ mach = align_malloc( sizeof *mach, 16 );
+ if (!mach)
+ goto fail;
+
+ memset(mach, 0, sizeof(*mach));
+
mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR];
/* Setup constants. */
@@ -401,22 +406,24 @@ tgsi_exec_machine_init(
(void) print_chan;
(void) print_temp;
#endif
+
+ return mach;
+
+fail:
+ align_free(mach);
+ return NULL;
}
void
-tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach)
+tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach)
{
- if (mach->Instructions) {
+ if (mach) {
FREE(mach->Instructions);
- mach->Instructions = NULL;
- mach->NumInstructions = 0;
- }
- if (mach->Declarations) {
FREE(mach->Declarations);
- mach->Declarations = NULL;
- mach->NumDeclarations = 0;
}
+
+ align_free(mach);
}
@@ -2015,8 +2022,7 @@ exec_instruction(
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_ARL:
- case TGSI_OPCODE_FLOOR:
- /* TGSI_OPCODE_FLR */
+ case TGSI_OPCODE_FLR:
FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH( &r[0], 0, chan_index );
micro_flr( &r[0], &r[0] );
@@ -2299,8 +2305,7 @@ exec_instruction(
}
break;
- case TGSI_OPCODE_LERP:
- /* TGSI_OPCODE_LRP */
+ case TGSI_OPCODE_LRP:
FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH(&r[0], 0, chan_index);
FETCH(&r[1], 1, chan_index);
@@ -2324,18 +2329,7 @@ exec_instruction(
}
break;
- case TGSI_OPCODE_CND0:
- FOR_EACH_ENABLED_CHANNEL(*inst, chan_index) {
- FETCH(&r[0], 0, chan_index);
- FETCH(&r[1], 1, chan_index);
- FETCH(&r[2], 2, chan_index);
- micro_le(&r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[2], &r[0], &r[1]);
- STORE(&r[0], 0, chan_index);
- }
- break;
-
- case TGSI_OPCODE_DOT2ADD:
- /* TGSI_OPCODE_DP2A */
+ case TGSI_OPCODE_DP2A:
FETCH( &r[0], 0, CHAN_X );
FETCH( &r[1], 1, CHAN_X );
micro_mul( &r[0], &r[0], &r[1] );
@@ -2353,18 +2347,7 @@ exec_instruction(
}
break;
- case TGSI_OPCODE_INDEX:
- /* XXX: considered for removal */
- assert (0);
- break;
-
- case TGSI_OPCODE_NEGATE:
- /* XXX: considered for removal */
- assert (0);
- break;
-
- case TGSI_OPCODE_FRAC:
- /* TGSI_OPCODE_FRC */
+ case TGSI_OPCODE_FRC:
FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH( &r[0], 0, chan_index );
micro_frc( &r[0], &r[0] );
@@ -2392,8 +2375,7 @@ exec_instruction(
}
break;
- case TGSI_OPCODE_EXPBASE2:
- /* TGSI_OPCODE_EX2 */
+ case TGSI_OPCODE_EX2:
FETCH(&r[0], 0, CHAN_X);
#if FAST_MATH
@@ -2407,8 +2389,7 @@ exec_instruction(
}
break;
- case TGSI_OPCODE_LOGBASE2:
- /* TGSI_OPCODE_LG2 */
+ case TGSI_OPCODE_LG2:
FETCH( &r[0], 0, CHAN_X );
micro_lg2( &r[0], &r[0] );
FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
@@ -2416,8 +2397,7 @@ exec_instruction(
}
break;
- case TGSI_OPCODE_POWER:
- /* TGSI_OPCODE_POW */
+ case TGSI_OPCODE_POW:
FETCH(&r[0], 0, CHAN_X);
FETCH(&r[1], 1, CHAN_X);
@@ -2428,8 +2408,7 @@ exec_instruction(
}
break;
- case TGSI_OPCODE_CROSSPRODUCT:
- /* TGSI_OPCODE_XPD */
+ case TGSI_OPCODE_XPD:
FETCH(&r[0], 0, CHAN_Y);
FETCH(&r[1], 1, CHAN_Z);
@@ -2471,11 +2450,6 @@ exec_instruction(
}
break;
- case TGSI_OPCODE_MULTIPLYMATRIX:
- /* XXX: considered for removal */
- assert (0);
- break;
-
case TGSI_OPCODE_ABS:
FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH(&r[0], 0, chan_index);
@@ -2782,19 +2756,32 @@ exec_instruction(
if (mach->ExecMask) {
/* do the call */
- /* push the Cond, Loop, Cont stacks */
+ /* First, record the depths of the execution stacks.
+ * This is important for deeply nested/looped return statements.
+ * We have to unwind the stacks by the correct amount. For a
+ * real code generator, we could determine the number of entries
+ * to pop off each stack with simple static analysis and avoid
+ * implementing this data structure at run time.
+ */
+ mach->CallStack[mach->CallStackTop].CondStackTop = mach->CondStackTop;
+ mach->CallStack[mach->CallStackTop].LoopStackTop = mach->LoopStackTop;
+ mach->CallStack[mach->CallStackTop].ContStackTop = mach->ContStackTop;
+ /* note that PC was already incremented above */
+ mach->CallStack[mach->CallStackTop].ReturnAddr = *pc;
+
+ mach->CallStackTop++;
+
+ /* Second, push the Cond, Loop, Cont, Func stacks */
assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
mach->CondStack[mach->CondStackTop++] = mach->CondMask;
assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
mach->ContStack[mach->ContStackTop++] = mach->ContMask;
-
assert(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING);
mach->FuncStack[mach->FuncStackTop++] = mach->FuncMask;
- /* note that PC was already incremented above */
- mach->CallStack[mach->CallStackTop++] = *pc;
+ /* Finally, jump to the subroutine */
*pc = inst->InstructionExtLabel.Label;
}
break;
@@ -2811,18 +2798,24 @@ exec_instruction(
*pc = -1;
return;
}
- *pc = mach->CallStack[--mach->CallStackTop];
- /* pop the Cond, Loop, Cont stacks */
- assert(mach->CondStackTop > 0);
- mach->CondMask = mach->CondStack[--mach->CondStackTop];
- assert(mach->LoopStackTop > 0);
- mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
- assert(mach->ContStackTop > 0);
- mach->ContMask = mach->ContStack[--mach->ContStackTop];
+ assert(mach->CallStackTop > 0);
+ mach->CallStackTop--;
+
+ mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop;
+ mach->CondMask = mach->CondStack[mach->CondStackTop];
+
+ mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop;
+ mach->LoopMask = mach->LoopStack[mach->LoopStackTop];
+
+ mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop;
+ mach->ContMask = mach->ContStack[mach->ContStackTop];
+
assert(mach->FuncStackTop > 0);
mach->FuncMask = mach->FuncStack[--mach->FuncStackTop];
+ *pc = mach->CallStack[mach->CallStackTop].ReturnAddr;
+
UPDATE_EXEC_MASK(mach);
}
break;
@@ -3119,26 +3112,81 @@ exec_instruction(
mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]] = 0;
break;
- case TGSI_OPCODE_LOOP:
+ case TGSI_OPCODE_BGNFOR:
+ assert(mach->LoopCounterStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ for (chan_index = 0; chan_index < 3; chan_index++) {
+ FETCH( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[chan_index], 0, chan_index );
+ }
+ STORE( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[CHAN_Y], 0, CHAN_X );
+ ++mach->LoopCounterStackTop;
/* fall-through (for now) */
- case TGSI_OPCODE_BGNLOOP2:
+ case TGSI_OPCODE_BGNLOOP:
/* push LoopMask and ContMasks */
assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
mach->ContStack[mach->ContStackTop++] = mach->ContMask;
+ assert(mach->LoopLabelStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
+ mach->LoopLabelStack[mach->LoopLabelStackTop++] = *pc - 1;
+ break;
+
+ case TGSI_OPCODE_ENDFOR:
+ assert(mach->LoopCounterStackTop > 0);
+ micro_sub( &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X],
+ &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X],
+ &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] );
+ /* update LoopMask */
+ if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[0] <= 0) {
+ mach->LoopMask &= ~0x1;
+ }
+ if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[1] <= 0 ) {
+ mach->LoopMask &= ~0x2;
+ }
+ if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[2] <= 0 ) {
+ mach->LoopMask &= ~0x4;
+ }
+ if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[3] <= 0 ) {
+ mach->LoopMask &= ~0x8;
+ }
+ micro_add( &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Y],
+ &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Y],
+ &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Z]);
+ assert(mach->LoopLabelStackTop > 0);
+ inst = mach->Instructions + mach->LoopLabelStack[mach->LoopLabelStackTop - 1];
+ STORE( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[CHAN_Y], 0, CHAN_X );
+ /* Restore ContMask, but don't pop */
+ assert(mach->ContStackTop > 0);
+ mach->ContMask = mach->ContStack[mach->ContStackTop - 1];
+ UPDATE_EXEC_MASK(mach);
+ if (mach->ExecMask) {
+ /* repeat loop: jump to instruction just past BGNLOOP */
+ assert(mach->LoopLabelStackTop > 0);
+ *pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1;
+ }
+ else {
+ /* exit loop: pop LoopMask */
+ assert(mach->LoopStackTop > 0);
+ mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
+ /* pop ContMask */
+ assert(mach->ContStackTop > 0);
+ mach->ContMask = mach->ContStack[--mach->ContStackTop];
+ assert(mach->LoopLabelStackTop > 0);
+ --mach->LoopLabelStackTop;
+ assert(mach->LoopCounterStackTop > 0);
+ --mach->LoopCounterStackTop;
+ }
+ UPDATE_EXEC_MASK(mach);
break;
-
+
case TGSI_OPCODE_ENDLOOP:
- /* fall-through (for now at least) */
- case TGSI_OPCODE_ENDLOOP2:
/* Restore ContMask, but don't pop */
assert(mach->ContStackTop > 0);
mach->ContMask = mach->ContStack[mach->ContStackTop - 1];
UPDATE_EXEC_MASK(mach);
if (mach->ExecMask) {
/* repeat loop: jump to instruction just past BGNLOOP */
- *pc = inst->InstructionExtLabel.Label + 1;
+ assert(mach->LoopLabelStackTop > 0);
+ *pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1;
}
else {
/* exit loop: pop LoopMask */
@@ -3147,6 +3195,8 @@ exec_instruction(
/* pop ContMask */
assert(mach->ContStackTop > 0);
mach->ContMask = mach->ContStack[--mach->ContStackTop];
+ assert(mach->LoopLabelStackTop > 0);
+ --mach->LoopLabelStackTop;
}
UPDATE_EXEC_MASK(mach);
break;
@@ -3214,7 +3264,6 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach )
mach->FuncMask = 0xf;
mach->ExecMask = 0xf;
- mach->CondStackTop = 0; /* temporarily subvert this assertion */
assert(mach->CondStackTop == 0);
assert(mach->LoopStackTop == 0);
assert(mach->ContStackTop == 0);
diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h
index 182e5e228b..c72f76809d 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_exec.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h
@@ -29,6 +29,7 @@
#define TGSI_EXEC_H
#include "pipe/p_compiler.h"
+#include "pipe/p_state.h"
#if defined __cplusplus
extern "C" {
@@ -94,7 +95,6 @@ struct tgsi_exec_labels
#define TGSI_EXEC_NUM_TEMPS 128
-#define TGSI_EXEC_NUM_TEMP_EXTRAS 6
#define TGSI_EXEC_NUM_IMMEDIATES 256
/*
@@ -162,9 +162,14 @@ struct tgsi_exec_labels
#define TGSI_EXEC_MASK_I (TGSI_EXEC_NUM_TEMPS + 3)
#define TGSI_EXEC_MASK_C 2
+/* 4 register buffer for various purposes */
#define TGSI_EXEC_TEMP_R0 (TGSI_EXEC_NUM_TEMPS + 4)
+#define TGSI_EXEC_NUM_TEMP_R 4
+
+#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 8)
+#define TGSI_EXEC_NUM_ADDRS 1
+#define TGSI_EXEC_NUM_TEMP_EXTRAS 9
-#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 5)
#define TGSI_EXEC_MAX_COND_NESTING 20
@@ -181,30 +186,38 @@ struct tgsi_exec_labels
*/
#define TGSI_EXEC_MAX_CONST_BUFFER 4096
+
+/** function call/activation record */
+struct tgsi_call_record
+{
+ uint CondStackTop;
+ uint LoopStackTop;
+ uint ContStackTop;
+ uint ReturnAddr;
+};
+
+
/**
* Run-time virtual machine state for executing TGSI shader.
*/
struct tgsi_exec_machine
{
/* Total = program temporaries + internal temporaries
- * + 1 padding to align to 16 bytes
*/
- struct tgsi_exec_vector _Temps[TGSI_EXEC_NUM_TEMPS +
- TGSI_EXEC_NUM_TEMP_EXTRAS + 1];
+ struct tgsi_exec_vector Temps[TGSI_EXEC_NUM_TEMPS +
+ TGSI_EXEC_NUM_TEMP_EXTRAS];
+
+ float Imms[TGSI_EXEC_NUM_IMMEDIATES][4];
+
+ struct tgsi_exec_vector Inputs[PIPE_MAX_ATTRIBS];
+ struct tgsi_exec_vector Outputs[PIPE_MAX_ATTRIBS];
- /*
- * This will point to _Temps after aligning to 16B boundary.
- */
- struct tgsi_exec_vector *Temps;
struct tgsi_exec_vector *Addrs;
struct tgsi_sampler **Samplers;
- float Imms[TGSI_EXEC_NUM_IMMEDIATES][4];
unsigned ImmLimit;
const float (*Consts)[4];
- struct tgsi_exec_vector *Inputs;
- struct tgsi_exec_vector *Outputs;
const struct tgsi_token *Tokens; /**< Declarations, instructions */
unsigned Processor; /**< TGSI_PROCESSOR_x */
@@ -230,6 +243,14 @@ struct tgsi_exec_machine
uint LoopStack[TGSI_EXEC_MAX_LOOP_NESTING];
int LoopStackTop;
+ /** Loop label stack */
+ uint LoopLabelStack[TGSI_EXEC_MAX_LOOP_NESTING];
+ int LoopLabelStackTop;
+
+ /** Loop counter stack (x = count, y = current, z = step) */
+ struct tgsi_exec_vector LoopCounterStack[TGSI_EXEC_MAX_LOOP_NESTING];
+ int LoopCounterStackTop;
+
/** Loop continue mask stack (see comments in tgsi_exec.c) */
uint ContStack[TGSI_EXEC_MAX_LOOP_NESTING];
int ContStackTop;
@@ -239,7 +260,7 @@ struct tgsi_exec_machine
int FuncStackTop;
/** Function call stack for saving/restoring the program counter */
- uint CallStack[TGSI_EXEC_MAX_CALL_NESTING];
+ struct tgsi_call_record CallStack[TGSI_EXEC_MAX_CALL_NESTING];
int CallStackTop;
struct tgsi_full_instruction *Instructions;
@@ -251,9 +272,11 @@ struct tgsi_exec_machine
struct tgsi_exec_labels Labels;
};
+struct tgsi_exec_machine *
+tgsi_exec_machine_create( void );
+
void
-tgsi_exec_machine_init(
- struct tgsi_exec_machine *mach );
+tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach);
void
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c
index 37f2b66d1f..17af4cb7ad 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.c
@@ -26,136 +26,156 @@
**************************************************************************/
#include "util/u_debug.h"
+#include "util/u_memory.h"
#include "tgsi_info.h"
static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
{
- { 1, 1, 0, 0, "ARL", NULL, NULL },
- { 1, 1, 0, 0, "MOV", NULL, NULL },
- { 1, 1, 0, 0, "LIT", NULL, NULL },
- { 1, 1, 0, 0, "RCP", "RECIP", NULL },
- { 1, 1, 0, 0, "RSQ", "RECIPSQRT", NULL },
- { 1, 1, 0, 0, "EXP", "EXPP", NULL },
- { 1, 1, 0, 0, "LOG", NULL, NULL },
- { 1, 2, 0, 0, "MUL", NULL, NULL },
- { 1, 2, 0, 0, "ADD", NULL, NULL },
- { 1, 2, 0, 0, "DP3", "DOT3", NULL },
- { 1, 2, 0, 0, "DP4", "DOT4", NULL },
- { 1, 2, 0, 0, "DST", NULL, NULL },
- { 1, 2, 0, 0, "MIN", NULL, NULL },
- { 1, 2, 0, 0, "MAX", NULL, NULL },
- { 1, 2, 0, 0, "SLT", "SETLT", NULL },
- { 1, 2, 0, 0, "SGE", "SETGE", NULL },
- { 1, 3, 0, 0, "MAD", "MADD", NULL },
- { 1, 2, 0, 0, "SUB", NULL, NULL },
- { 1, 3, 0, 0, "LRP", "LERP", NULL },
- { 1, 3, 0, 0, "CND", NULL, NULL },
- { 1, 3, 0, 0, "CND0", NULL, NULL },
- { 1, 3, 0, 0, "DP2A", "DP2ADD", "DOT2ADD" },
- { 1, 2, 0, 0, "INDEX", NULL, NULL },
- { 1, 1, 0, 0, "NEGATE", NULL, NULL },
- { 1, 1, 0, 0, "FRC", "FRAC", NULL },
- { 1, 3, 0, 0, "CLAMP", NULL, NULL },
- { 1, 1, 0, 0, "FLR", "FLOOR", NULL },
- { 1, 1, 0, 0, "ROUND", NULL, NULL },
- { 1, 1, 0, 0, "EX2", "EXPBASE2", NULL },
- { 1, 1, 0, 0, "LG2", "LOGBASE2", "LOGP" },
- { 1, 2, 0, 0, "POW", "POWER", NULL },
- { 1, 2, 0, 0, "XPD", "CRS", "CROSSPRODUCT" },
- { 1, 2, 0, 0, "M4X4", "MULTIPLYMATRIX", NULL },
- { 1, 1, 0, 0, "ABS", NULL, NULL },
- { 1, 1, 0, 0, "RCC", NULL, NULL },
- { 1, 2, 0, 0, "DPH", NULL, NULL },
- { 1, 1, 0, 0, "COS", NULL, NULL },
- { 1, 1, 0, 0, "DDX", "DSX", NULL },
- { 1, 1, 0, 0, "DDY", "DSY", NULL },
- { 0, 0, 0, 0, "KILP", NULL, NULL },
- { 1, 1, 0, 0, "PK2H", NULL, NULL },
- { 1, 1, 0, 0, "PK2US", NULL, NULL },
- { 1, 1, 0, 0, "PK4B", NULL, NULL },
- { 1, 1, 0, 0, "PK4UB", NULL, NULL },
- { 1, 2, 0, 0, "RFL", NULL, NULL },
- { 1, 2, 0, 0, "SEQ", NULL, NULL },
- { 1, 2, 0, 0, "SFL", NULL, NULL },
- { 1, 2, 0, 0, "SGT", NULL, NULL },
- { 1, 1, 0, 0, "SIN", NULL, NULL },
- { 1, 2, 0, 0, "SLE", NULL, NULL },
- { 1, 2, 0, 0, "SNE", NULL, NULL },
- { 1, 2, 0, 0, "STR", NULL, NULL },
- { 1, 2, 1, 0, "TEX", "TEXLD", NULL },
- { 1, 4, 1, 0, "TXD", "TEXLDD", NULL },
- { 1, 2, 1, 0, "TXP", NULL, NULL },
- { 1, 1, 0, 0, "UP2H", NULL, NULL },
- { 1, 1, 0, 0, "UP2US", NULL, NULL },
- { 1, 1, 0, 0, "UP4B", NULL, NULL },
- { 1, 1, 0, 0, "UP4UB", NULL, NULL },
- { 1, 3, 0, 0, "X2D", NULL, NULL },
- { 1, 1, 0, 0, "ARA", NULL, NULL },
- { 1, 1, 0, 0, "ARR", "MOVA", NULL },
- { 0, 1, 0, 0, "BRA", NULL, NULL },
- { 0, 0, 0, 1, "CAL", "CALL", NULL },
- { 0, 0, 0, 0, "RET", NULL, NULL },
- { 1, 1, 0, 0, "SGN", "SSG", NULL },
- { 1, 3, 0, 0, "CMP", NULL, NULL },
- { 1, 1, 0, 0, "SCS", "SINCOS", NULL },
- { 1, 2, 1, 0, "TXB", "TEXLDB", NULL },
- { 1, 1, 0, 0, "NRM", NULL, NULL },
- { 1, 2, 0, 0, "DIV", NULL, NULL },
- { 1, 2, 0, 0, "DP2", NULL, NULL },
- { 1, 2, 1, 0, "TXL", NULL, NULL },
- { 0, 0, 0, 0, "BRK", "BREAK", NULL },
- { 0, 1, 0, 1, "IF", NULL, NULL },
- { 0, 0, 0, 0, "LOOP", NULL, NULL },
- { 0, 1, 0, 0, "REP", NULL, NULL },
- { 0, 0, 0, 1, "ELSE", NULL, NULL },
- { 0, 0, 0, 0, "ENDIF", NULL, NULL },
- { 0, 0, 0, 0, "ENDLOOP", NULL, NULL },
- { 0, 0, 0, 0, "ENDREP", NULL, NULL },
- { 0, 1, 0, 0, "PUSHA", NULL, NULL },
- { 1, 0, 0, 0, "POPA", NULL, NULL },
- { 1, 1, 0, 0, "CEIL", NULL, NULL },
- { 1, 1, 0, 0, "I2F", NULL, NULL },
- { 1, 1, 0, 0, "NOT", NULL, NULL },
- { 1, 1, 0, 0, "INT", "TRUNC", NULL },
- { 1, 2, 0, 0, "SHL", NULL, NULL },
- { 1, 2, 0, 0, "SHR", NULL, NULL },
- { 1, 2, 0, 0, "AND", NULL, NULL },
- { 1, 2, 0, 0, "OR", NULL, NULL },
- { 1, 2, 0, 0, "MOD", NULL, NULL },
- { 1, 2, 0, 0, "XOR", NULL, NULL },
- { 1, 3, 0, 0, "SAD", NULL, NULL },
- { 1, 2, 1, 0, "TXF", NULL, NULL },
- { 1, 2, 1, 0, "TXQ", NULL, NULL },
- { 0, 0, 0, 0, "CONT", NULL, NULL },
- { 0, 0, 0, 0, "EMIT", NULL, NULL },
- { 0, 0, 0, 0, "ENDPRIM", NULL, NULL },
- { 0, 0, 0, 1, "BGNLOOP2", NULL, NULL },
- { 0, 0, 0, 0, "BGNSUB", NULL, NULL },
- { 0, 0, 0, 1, "ENDLOOP2", NULL, NULL },
- { 0, 0, 0, 0, "ENDSUB", NULL, NULL },
- { 1, 1, 0, 0, "NOISE1", NULL, NULL },
- { 1, 1, 0, 0, "NOISE2", NULL, NULL },
- { 1, 1, 0, 0, "NOISE3", NULL, NULL },
- { 1, 1, 0, 0, "NOISE4", NULL, NULL },
- { 0, 0, 0, 0, "NOP", NULL, NULL },
- { 1, 2, 0, 0, "M4X3", NULL, NULL },
- { 1, 2, 0, 0, "M3X4", NULL, NULL },
- { 1, 2, 0, 0, "M3X3", NULL, NULL },
- { 1, 2, 0, 0, "M3X2", NULL, NULL },
- { 1, 1, 0, 0, "NRM4", NULL, NULL },
- { 0, 1, 0, 0, "CALLNZ", NULL, NULL },
- { 0, 1, 0, 0, "IFC", NULL, NULL },
- { 0, 1, 0, 0, "BREAKC", NULL, NULL },
- { 0, 1, 0, 0, "KIL", "TEXKILL", NULL },
- { 0, 0, 0, 0, "END", NULL, NULL },
- { 1, 1, 0, 0, "SWZ", NULL, NULL }
+ { 1, 1, 0, 0, 0, 0, "ARL", TGSI_OPCODE_ARL },
+ { 1, 1, 0, 0, 0, 0, "MOV", TGSI_OPCODE_MOV },
+ { 1, 1, 0, 0, 0, 0, "LIT", TGSI_OPCODE_LIT },
+ { 1, 1, 0, 0, 0, 0, "RCP", TGSI_OPCODE_RCP },
+ { 1, 1, 0, 0, 0, 0, "RSQ", TGSI_OPCODE_RSQ },
+ { 1, 1, 0, 0, 0, 0, "EXP", TGSI_OPCODE_EXP },
+ { 1, 1, 0, 0, 0, 0, "LOG", TGSI_OPCODE_LOG },
+ { 1, 2, 0, 0, 0, 0, "MUL", TGSI_OPCODE_MUL },
+ { 1, 2, 0, 0, 0, 0, "ADD", TGSI_OPCODE_ADD },
+ { 1, 2, 0, 0, 0, 0, "DP3", TGSI_OPCODE_DP3 },
+ { 1, 2, 0, 0, 0, 0, "DP4", TGSI_OPCODE_DP4 },
+ { 1, 2, 0, 0, 0, 0, "DST", TGSI_OPCODE_DST },
+ { 1, 2, 0, 0, 0, 0, "MIN", TGSI_OPCODE_MIN },
+ { 1, 2, 0, 0, 0, 0, "MAX", TGSI_OPCODE_MAX },
+ { 1, 2, 0, 0, 0, 0, "SLT", TGSI_OPCODE_SLT },
+ { 1, 2, 0, 0, 0, 0, "SGE", TGSI_OPCODE_SGE },
+ { 1, 3, 0, 0, 0, 0, "MAD", TGSI_OPCODE_MAD },
+ { 1, 2, 0, 0, 0, 0, "SUB", TGSI_OPCODE_SUB },
+ { 1, 3, 0, 0, 0, 0, "LRP", TGSI_OPCODE_LRP },
+ { 1, 3, 0, 0, 0, 0, "CND", TGSI_OPCODE_CND },
+ { 0, 0, 0, 0, 0, 0, "", 20 }, /* removed */
+ { 1, 3, 0, 0, 0, 0, "DP2A", TGSI_OPCODE_DP2A },
+ { 0, 0, 0, 0, 0, 0, "", 22 }, /* removed */
+ { 0, 0, 0, 0, 0, 0, "", 23 }, /* removed */
+ { 1, 1, 0, 0, 0, 0, "FRC", TGSI_OPCODE_FRC },
+ { 1, 3, 0, 0, 0, 0, "CLAMP", TGSI_OPCODE_CLAMP },
+ { 1, 1, 0, 0, 0, 0, "FLR", TGSI_OPCODE_FLR },
+ { 1, 1, 0, 0, 0, 0, "ROUND", TGSI_OPCODE_ROUND },
+ { 1, 1, 0, 0, 0, 0, "EX2", TGSI_OPCODE_EX2 },
+ { 1, 1, 0, 0, 0, 0, "LG2", TGSI_OPCODE_LG2 },
+ { 1, 2, 0, 0, 0, 0, "POW", TGSI_OPCODE_POW },
+ { 1, 2, 0, 0, 0, 0, "XPD", TGSI_OPCODE_XPD },
+ { 0, 0, 0, 0, 0, 0, "", 32 }, /* removed */
+ { 1, 1, 0, 0, 0, 0, "ABS", TGSI_OPCODE_ABS },
+ { 1, 1, 0, 0, 0, 0, "RCC", TGSI_OPCODE_RCC },
+ { 1, 2, 0, 0, 0, 0, "DPH", TGSI_OPCODE_DPH },
+ { 1, 1, 0, 0, 0, 0, "COS", TGSI_OPCODE_COS },
+ { 1, 1, 0, 0, 0, 0, "DDX", TGSI_OPCODE_DDX },
+ { 1, 1, 0, 0, 0, 0, "DDY", TGSI_OPCODE_DDY },
+ { 0, 0, 0, 0, 0, 0, "KILP", TGSI_OPCODE_KILP },
+ { 1, 1, 0, 0, 0, 0, "PK2H", TGSI_OPCODE_PK2H },
+ { 1, 1, 0, 0, 0, 0, "PK2US", TGSI_OPCODE_PK2US },
+ { 1, 1, 0, 0, 0, 0, "PK4B", TGSI_OPCODE_PK4B },
+ { 1, 1, 0, 0, 0, 0, "PK4UB", TGSI_OPCODE_PK4UB },
+ { 1, 2, 0, 0, 0, 0, "RFL", TGSI_OPCODE_RFL },
+ { 1, 2, 0, 0, 0, 0, "SEQ", TGSI_OPCODE_SEQ },
+ { 1, 2, 0, 0, 0, 0, "SFL", TGSI_OPCODE_SFL },
+ { 1, 2, 0, 0, 0, 0, "SGT", TGSI_OPCODE_SGT },
+ { 1, 1, 0, 0, 0, 0, "SIN", TGSI_OPCODE_SIN },
+ { 1, 2, 0, 0, 0, 0, "SLE", TGSI_OPCODE_SLE },
+ { 1, 2, 0, 0, 0, 0, "SNE", TGSI_OPCODE_SNE },
+ { 1, 2, 0, 0, 0, 0, "STR", TGSI_OPCODE_STR },
+ { 1, 2, 1, 0, 0, 0, "TEX", TGSI_OPCODE_TEX },
+ { 1, 4, 1, 0, 0, 0, "TXD", TGSI_OPCODE_TXD },
+ { 1, 2, 1, 0, 0, 0, "TXP", TGSI_OPCODE_TXP },
+ { 1, 1, 0, 0, 0, 0, "UP2H", TGSI_OPCODE_UP2H },
+ { 1, 1, 0, 0, 0, 0, "UP2US", TGSI_OPCODE_UP2US },
+ { 1, 1, 0, 0, 0, 0, "UP4B", TGSI_OPCODE_UP4B },
+ { 1, 1, 0, 0, 0, 0, "UP4UB", TGSI_OPCODE_UP4UB },
+ { 1, 3, 0, 0, 0, 0, "X2D", TGSI_OPCODE_X2D },
+ { 1, 1, 0, 0, 0, 0, "ARA", TGSI_OPCODE_ARA },
+ { 1, 1, 0, 0, 0, 0, "ARR", TGSI_OPCODE_ARR },
+ { 0, 1, 0, 0, 0, 0, "BRA", TGSI_OPCODE_BRA },
+ { 0, 0, 0, 1, 0, 0, "CAL", TGSI_OPCODE_CAL },
+ { 0, 0, 0, 0, 0, 0, "RET", TGSI_OPCODE_RET },
+ { 1, 1, 0, 0, 0, 0, "SSG", TGSI_OPCODE_SSG },
+ { 1, 3, 0, 0, 0, 0, "CMP", TGSI_OPCODE_CMP },
+ { 1, 1, 0, 0, 0, 0, "SCS", TGSI_OPCODE_SCS },
+ { 1, 2, 1, 0, 0, 0, "TXB", TGSI_OPCODE_TXB },
+ { 1, 1, 0, 0, 0, 0, "NRM", TGSI_OPCODE_NRM },
+ { 1, 2, 0, 0, 0, 0, "DIV", TGSI_OPCODE_DIV },
+ { 1, 2, 0, 0, 0, 0, "DP2", TGSI_OPCODE_DP2 },
+ { 1, 2, 1, 0, 0, 0, "TXL", TGSI_OPCODE_TXL },
+ { 0, 0, 0, 0, 0, 0, "BRK", TGSI_OPCODE_BRK },
+ { 0, 1, 0, 1, 0, 1, "IF", TGSI_OPCODE_IF },
+ { 1, 1, 0, 0, 0, 1, "BGNFOR", TGSI_OPCODE_BGNFOR },
+ { 0, 1, 0, 0, 0, 1, "REP", TGSI_OPCODE_REP },
+ { 0, 0, 0, 1, 1, 1, "ELSE", TGSI_OPCODE_ELSE },
+ { 0, 0, 0, 0, 1, 0, "ENDIF", TGSI_OPCODE_ENDIF },
+ { 1, 0, 0, 0, 1, 0, "ENDFOR", TGSI_OPCODE_ENDFOR },
+ { 0, 0, 0, 0, 1, 0, "ENDREP", TGSI_OPCODE_ENDREP },
+ { 0, 1, 0, 0, 0, 0, "PUSHA", TGSI_OPCODE_PUSHA },
+ { 1, 0, 0, 0, 0, 0, "POPA", TGSI_OPCODE_POPA },
+ { 1, 1, 0, 0, 0, 0, "CEIL", TGSI_OPCODE_CEIL },
+ { 1, 1, 0, 0, 0, 0, "I2F", TGSI_OPCODE_I2F },
+ { 1, 1, 0, 0, 0, 0, "NOT", TGSI_OPCODE_NOT },
+ { 1, 1, 0, 0, 0, 0, "TRUNC", TGSI_OPCODE_TRUNC },
+ { 1, 2, 0, 0, 0, 0, "SHL", TGSI_OPCODE_SHL },
+ { 1, 2, 0, 0, 0, 0, "SHR", TGSI_OPCODE_SHR },
+ { 1, 2, 0, 0, 0, 0, "AND", TGSI_OPCODE_AND },
+ { 1, 2, 0, 0, 0, 0, "OR", TGSI_OPCODE_OR },
+ { 1, 2, 0, 0, 0, 0, "MOD", TGSI_OPCODE_MOD },
+ { 1, 2, 0, 0, 0, 0, "XOR", TGSI_OPCODE_XOR },
+ { 1, 3, 0, 0, 0, 0, "SAD", TGSI_OPCODE_SAD },
+ { 1, 2, 1, 0, 0, 0, "TXF", TGSI_OPCODE_TXF },
+ { 1, 2, 1, 0, 0, 0, "TXQ", TGSI_OPCODE_TXQ },
+ { 0, 0, 0, 0, 0, 0, "CONT", TGSI_OPCODE_CONT },
+ { 0, 0, 0, 0, 0, 0, "EMIT", TGSI_OPCODE_EMIT },
+ { 0, 0, 0, 0, 0, 0, "ENDPRIM", TGSI_OPCODE_ENDPRIM },
+ { 0, 0, 0, 1, 0, 1, "BGNLOOP", TGSI_OPCODE_BGNLOOP },
+ { 0, 0, 0, 0, 0, 1, "BGNSUB", TGSI_OPCODE_BGNSUB },
+ { 0, 0, 0, 1, 1, 0, "ENDLOOP", TGSI_OPCODE_ENDLOOP },
+ { 0, 0, 0, 0, 1, 0, "ENDSUB", TGSI_OPCODE_ENDSUB },
+ { 1, 1, 0, 0, 0, 0, "NOISE1", TGSI_OPCODE_NOISE1 },
+ { 1, 1, 0, 0, 0, 0, "NOISE2", TGSI_OPCODE_NOISE2 },
+ { 1, 1, 0, 0, 0, 0, "NOISE3", TGSI_OPCODE_NOISE3 },
+ { 1, 1, 0, 0, 0, 0, "NOISE4", TGSI_OPCODE_NOISE4 },
+ { 0, 0, 0, 0, 0, 0, "NOP", TGSI_OPCODE_NOP },
+ { 0, 0, 0, 0, 0, 0, "", 108 }, /* removed */
+ { 0, 0, 0, 0, 0, 0, "", 109 }, /* removed */
+ { 0, 0, 0, 0, 0, 0, "", 110 }, /* removed */
+ { 0, 0, 0, 0, 0, 0, "", 111 }, /* removed */
+ { 1, 1, 0, 0, 0, 0, "NRM4", TGSI_OPCODE_NRM4 },
+ { 0, 1, 0, 0, 0, 0, "CALLNZ", TGSI_OPCODE_CALLNZ },
+ { 0, 1, 0, 0, 0, 0, "IFC", TGSI_OPCODE_IFC },
+ { 0, 1, 0, 0, 0, 0, "BREAKC", TGSI_OPCODE_BREAKC },
+ { 0, 1, 0, 0, 0, 0, "KIL", TGSI_OPCODE_KIL },
+ { 0, 0, 0, 0, 0, 0, "END", TGSI_OPCODE_END },
+ { 1, 1, 0, 0, 0, 0, "SWZ", TGSI_OPCODE_SWZ }
};
const struct tgsi_opcode_info *
tgsi_get_opcode_info( uint opcode )
{
+ static boolean firsttime = 1;
+
+ if (firsttime) {
+ unsigned i;
+ firsttime = 0;
+ for (i = 0; i < Elements(opcode_info); i++)
+ assert(opcode_info[i].opcode == i);
+ }
+
if (opcode < TGSI_OPCODE_LAST)
return &opcode_info[opcode];
+
assert( 0 );
return NULL;
}
+
+
+const char *
+tgsi_get_opcode_name( uint opcode )
+{
+ const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode);
+ return info->mnemonic;
+}
+
diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.h b/src/gallium/auxiliary/tgsi/tgsi_info.h
index 077e25acd7..74713c3b98 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_info.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_info.h
@@ -36,18 +36,23 @@ extern "C" {
struct tgsi_opcode_info
{
- uint num_dst;
- uint num_src;
- boolean is_tex;
- boolean is_branch;
+ unsigned num_dst:3;
+ unsigned num_src:3;
+ unsigned is_tex:1;
+ unsigned is_branch:1;
+ int pre_dedent:2;
+ int post_indent:2;
const char *mnemonic;
- const char *alt_mnemonic1;
- const char *alt_mnemonic2;
+ uint opcode;
};
const struct tgsi_opcode_info *
tgsi_get_opcode_info( uint opcode );
+const char *
+tgsi_get_opcode_name( uint opcode );
+
+
#if defined __cplusplus
}
#endif
diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
new file mode 100644
index 0000000000..e7bcf4bf75
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
@@ -0,0 +1,172 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+#ifndef OP12_TEX
+#define OP12_TEX(a) OP12(a)
+#endif
+
+#ifndef OP14_TEX
+#define OP14_TEX(a) OP14(a)
+#endif
+
+#ifndef OP00_LBL
+#define OP00_LBL(a) OP00(a)
+#endif
+
+#ifndef OP01_LBL
+#define OP01_LBL(a) OP01(a)
+#endif
+
+OP11(ARL)
+OP11(MOV)
+OP11(LIT)
+OP11(RCP)
+OP11(RSQ)
+OP11(EXP)
+OP11(LOG)
+OP12(MUL)
+OP12(ADD)
+OP12(DP3)
+OP12(DP4)
+OP12(DST)
+OP12(MIN)
+OP12(MAX)
+OP12(SLT)
+OP12(SGE)
+OP13(MAD)
+OP12(SUB)
+OP13(LRP)
+OP13(CND)
+OP13(DP2A)
+OP11(FRC)
+OP13(CLAMP)
+OP11(FLR)
+OP11(ROUND)
+OP11(EX2)
+OP11(LG2)
+OP12(POW)
+OP12(XPD)
+OP11(ABS)
+OP11(RCC)
+OP12(DPH)
+OP11(COS)
+OP11(DDX)
+OP11(DDY)
+OP00(KILP)
+OP11(PK2H)
+OP11(PK2US)
+OP11(PK4B)
+OP11(PK4UB)
+OP12(RFL)
+OP12(SEQ)
+OP12(SFL)
+OP12(SGT)
+OP11(SIN)
+OP12(SLE)
+OP12(SNE)
+OP12(STR)
+OP12_TEX(TEX)
+OP14_TEX(TXD)
+OP12_TEX(TXP)
+OP11(UP2H)
+OP11(UP2US)
+OP11(UP4B)
+OP11(UP4UB)
+OP13(X2D)
+OP11(ARA)
+OP11(ARR)
+OP01(BRA)
+OP00_LBL(CAL)
+OP00(RET)
+OP11(SSG)
+OP13(CMP)
+OP11(SCS)
+OP12_TEX(TXB)
+OP11(NRM)
+OP12(DIV)
+OP12(DP2)
+OP12_TEX(TXL)
+OP00(BRK)
+OP01_LBL(IF)
+OP11(BGNFOR)
+OP01(REP)
+OP00_LBL(ELSE)
+OP00(ENDIF)
+OP10(ENDFOR)
+OP00(ENDREP)
+OP01(PUSHA)
+OP10(POPA)
+OP11(CEIL)
+OP11(I2F)
+OP11(NOT)
+OP11(TRUNC)
+OP12(SHL)
+OP12(SHR)
+OP12(AND)
+OP12(OR)
+OP12(MOD)
+OP12(XOR)
+OP13(SAD)
+OP12_TEX(TXF)
+OP12_TEX(TXQ)
+OP00(CONT)
+OP00(EMIT)
+OP00(ENDPRIM)
+OP00_LBL(BGNLOOP)
+OP00(BGNSUB)
+OP00_LBL(ENDLOOP)
+OP00(ENDSUB)
+OP11(NOISE1)
+OP11(NOISE2)
+OP11(NOISE3)
+OP11(NOISE4)
+OP00(NOP)
+OP11(NRM4)
+OP01(CALLNZ)
+OP01(IFC)
+OP01(BREAKC)
+OP01(KIL)
+OP00(END)
+OP11(SWZ)
+
+
+#undef OP00
+#undef OP01
+#undef OP10
+#undef OP11
+#undef OP12
+#undef OP13
+
+#ifdef OP14
+#undef OP14
+#endif
+
+#undef OP00_LBL
+#undef OP01_LBL
+
+#undef OP12_TEX
+#undef OP14_TEX
+
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c
index 7f2cfb7988..4870f82b6b 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_parse.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c
@@ -42,9 +42,6 @@ void
tgsi_full_token_free(
union tgsi_full_token *full_token )
{
- if( full_token->Token.Type == TGSI_TOKEN_TYPE_IMMEDIATE ) {
- FREE( (void *) full_token->FullImmediate.u.Pointer );
- }
}
unsigned
@@ -156,14 +153,8 @@ tgsi_parse_token(
case TGSI_IMM_FLOAT32:
{
uint imm_count = imm->Immediate.NrTokens - 1;
- struct tgsi_immediate_float32 *data;
-
- data = (struct tgsi_immediate_float32 *) MALLOC(sizeof(struct tgsi_immediate_float32) * imm_count);
- if (data) {
- for (i = 0; i < imm_count; i++) {
- next_token(ctx, &data[i]);
- }
- imm->u.ImmediateFloat32 = data;
+ for (i = 0; i < imm_count; i++) {
+ next_token(ctx, &imm->u[i]);
}
}
break;
diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h
index 5268c02900..a26ee5ba86 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_parse.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h
@@ -73,11 +73,7 @@ struct tgsi_full_declaration
struct tgsi_full_immediate
{
struct tgsi_immediate Immediate;
- union
- {
- const void *Pointer;
- const struct tgsi_immediate_float32 *ImmediateFloat32;
- } u;
+ union tgsi_immediate_data u[4];
};
#define TGSI_FULL_MAX_DST_REGISTERS 2
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ppc.c b/src/gallium/auxiliary/tgsi/tgsi_ppc.c
index 8466d9bc22..4b1c7d4e01 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ppc.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ppc.c
@@ -38,6 +38,7 @@
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_sse.h"
+#include "tgsi/tgsi_info.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_util.h"
#include "tgsi_dump.h"
@@ -619,17 +620,17 @@ emit_unaryop(struct gen_context *gen, struct tgsi_full_instruction *inst)
ppc_vandc(gen->f, v1, v0, bit31_vec); /* v1 = v0 & ~bit31 */
}
break;
- case TGSI_OPCODE_FLOOR:
+ case TGSI_OPCODE_FLR:
ppc_vrfim(gen->f, v1, v0); /* v1 = floor(v0) */
break;
- case TGSI_OPCODE_FRAC:
+ case TGSI_OPCODE_FRC:
ppc_vrfim(gen->f, v1, v0); /* tmp = floor(v0) */
ppc_vsubfp(gen->f, v1, v0, v1); /* v1 = v0 - v1 */
break;
- case TGSI_OPCODE_EXPBASE2:
+ case TGSI_OPCODE_EX2:
ppc_vexptefp(gen->f, v1, v0); /* v1 = 2^v0 */
break;
- case TGSI_OPCODE_LOGBASE2:
+ case TGSI_OPCODE_LG2:
/* XXX this may be broken! */
ppc_vlogefp(gen->f, v1, v0); /* v1 = log2(v0) */
break;
@@ -1120,10 +1121,10 @@ emit_instruction(struct gen_context *gen,
case TGSI_OPCODE_MOV:
case TGSI_OPCODE_SWZ:
case TGSI_OPCODE_ABS:
- case TGSI_OPCODE_FLOOR:
- case TGSI_OPCODE_FRAC:
- case TGSI_OPCODE_EXPBASE2:
- case TGSI_OPCODE_LOGBASE2:
+ case TGSI_OPCODE_FLR:
+ case TGSI_OPCODE_FRC:
+ case TGSI_OPCODE_EX2:
+ case TGSI_OPCODE_LG2:
emit_unaryop(gen, inst);
break;
case TGSI_OPCODE_RSQ:
@@ -1326,8 +1327,10 @@ tgsi_emit_ppc(const struct tgsi_token *tokens,
ok = emit_instruction(&gen, &parse.FullToken.FullInstruction);
if (!ok) {
- debug_printf("failed to translate tgsi opcode %d to PPC (%s)\n",
- parse.FullToken.FullInstruction.Instruction.Opcode,
+ uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode;
+ debug_printf("failed to translate tgsi opcode %d (%s) to PPC (%s)\n",
+ opcode,
+ tgsi_get_opcode_name(opcode),
parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX ?
"vertex shader" : "fragment shader");
}
@@ -1342,7 +1345,7 @@ tgsi_emit_ppc(const struct tgsi_token *tokens,
assert(num_immediates < TGSI_EXEC_NUM_IMMEDIATES);
for (i = 0; i < size; i++) {
immediates[num_immediates][i] =
- parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
+ parse.FullToken.FullImmediate.u[i].Float;
}
num_immediates++;
}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
index 6f1f5c2b4b..8a13885da9 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c
@@ -131,7 +131,7 @@ is_register_used(
return (ctx->regs_used[file][index / BITS_IN_REG_FLAG] & (1 << (index % BITS_IN_REG_FLAG))) ? TRUE : FALSE;
}
-static const char *file_names[] =
+static const char *file_names[TGSI_FILE_COUNT] =
{
"NULL",
"CONST",
@@ -140,7 +140,8 @@ static const char *file_names[] =
"TEMP",
"SAMP",
"ADDR",
- "IMM"
+ "IMM",
+ "LOOP"
};
static boolean
@@ -198,10 +199,10 @@ iter_instruction(
}
if (info->num_dst != inst->Instruction.NumDstRegs) {
- report_error( ctx, "Invalid number of destination operands, should be %u", info->num_dst );
+ report_error( ctx, "%s: Invalid number of destination operands, should be %u", info->mnemonic, info->num_dst );
}
if (info->num_src != inst->Instruction.NumSrcRegs) {
- report_error( ctx, "Invalid number of source operands, should be %u", info->num_src );
+ report_error( ctx, "%s: Invalid number of source operands, should be %u", info->mnemonic, info->num_src );
}
/* Check destination and source registers' validity.
@@ -234,9 +235,29 @@ iter_instruction(
index,
"indirect",
FALSE );
- if (file != TGSI_FILE_ADDRESS || index != 0)
- report_warning( ctx, "Indirect register not ADDR[0]" );
+ if (!(file == TGSI_FILE_ADDRESS || file == TGSI_FILE_LOOP) || index != 0) {
+ report_warning(ctx, "Indirect register neither ADDR[0] nor LOOP[0]");
+ }
+ }
+ }
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_BGNFOR:
+ case TGSI_OPCODE_ENDFOR:
+ if (inst->FullDstRegisters[0].DstRegister.File != TGSI_FILE_LOOP ||
+ inst->FullDstRegisters[0].DstRegister.Index != 0) {
+ report_error(ctx, "Destination register must be LOOP[0]");
+ }
+ break;
+ }
+
+ switch (inst->Instruction.Opcode) {
+ case TGSI_OPCODE_BGNFOR:
+ if (inst->FullSrcRegisters[0].SrcRegister.File != TGSI_FILE_CONSTANT &&
+ inst->FullSrcRegisters[0].SrcRegister.File != TGSI_FILE_IMMEDIATE) {
+ report_error(ctx, "Source register file must be either CONST or IMM");
}
+ break;
}
ctx->num_instructions++;
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
index a13368c80c..3cdf8b9f35 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c
@@ -32,9 +32,11 @@
#include "util/u_debug.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
+#include "util/u_memory.h"
#if defined(PIPE_ARCH_SSE)
#include "util/u_sse.h"
#endif
+#include "tgsi/tgsi_info.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_util.h"
#include "tgsi_exec.h"
@@ -100,37 +102,55 @@ get_const_base( void )
{
return x86_make_reg(
file_REG32,
- reg_CX );
+ reg_AX );
}
static struct x86_reg
-get_input_base( void )
+get_machine_base( void )
{
return x86_make_reg(
file_REG32,
- reg_AX );
+ reg_CX );
+}
+
+static struct x86_reg
+get_input_base( void )
+{
+ return x86_make_disp(
+ get_machine_base(),
+ Offset(struct tgsi_exec_machine, Inputs) );
}
static struct x86_reg
get_output_base( void )
{
- return x86_make_reg(
- file_REG32,
- reg_DX );
+ return x86_make_disp(
+ get_machine_base(),
+ Offset(struct tgsi_exec_machine, Outputs) );
}
static struct x86_reg
get_temp_base( void )
{
+ return x86_make_disp(
+ get_machine_base(),
+ Offset(struct tgsi_exec_machine, Temps) );
+}
+
+static struct x86_reg
+get_coef_base( void )
+{
return x86_make_reg(
file_REG32,
reg_BX );
}
static struct x86_reg
-get_coef_base( void )
+get_sampler_base( void )
{
- return get_output_base();
+ return x86_make_reg(
+ file_REG32,
+ reg_DI );
}
static struct x86_reg
@@ -138,7 +158,7 @@ get_immediate_base( void )
{
return x86_make_reg(
file_REG32,
- reg_DI );
+ reg_DX );
}
@@ -168,6 +188,15 @@ get_const(
}
static struct x86_reg
+get_sampler_ptr(
+ unsigned unit )
+{
+ return x86_make_disp(
+ get_sampler_base(),
+ unit * sizeof( struct tgsi_sampler * ) );
+}
+
+static struct x86_reg
get_input(
unsigned vec,
unsigned chan )
@@ -241,12 +270,14 @@ emit_const(
/* 'vec' is the offset from the address register's value.
* We're loading CONST[ADDR+vec] into an xmm register.
*/
- struct x86_reg r0 = get_input_base();
- struct x86_reg r1 = get_output_base();
+ struct x86_reg r0 = get_immediate_base();
+ struct x86_reg r1 = get_coef_base();
uint i;
assert( indirectFile == TGSI_FILE_ADDRESS );
assert( indirectIndex == 0 );
+ assert( r0.mod == mod_REG );
+ assert( r1.mod == mod_REG );
x86_push( func, r0 );
x86_push( func, r1 );
@@ -520,24 +551,15 @@ emit_coef_dady(
* that the stack pointer is 16 byte aligned, as expected.
*/
static void
-emit_func_call_dst(
+emit_func_call(
struct x86_function *func,
- unsigned xmm_save,
- unsigned xmm_dst,
+ unsigned xmm_save_mask,
+ const struct x86_reg *arg,
+ unsigned nr_args,
void (PIPE_CDECL *code)() )
{
struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX );
unsigned i, n;
- unsigned xmm_mask;
-
- /* Bitmask of the xmm registers to save */
- xmm_mask = (1 << xmm_save) - 1;
- xmm_mask &= ~(1 << xmm_dst);
-
- sse_movaps(
- func,
- get_temp( TEMP_R0, 0 ),
- make_xmm( xmm_dst ) );
x86_push(
func,
@@ -549,8 +571,10 @@ emit_func_call_dst(
func,
x86_make_reg( file_REG32, reg_DX) );
+ /* Store XMM regs to the stack
+ */
for(i = 0, n = 0; i < 8; ++i)
- if(xmm_mask & (1 << i))
+ if(xmm_save_mask & (1 << i))
++n;
x86_sub_imm(
@@ -559,26 +583,42 @@ emit_func_call_dst(
n*16);
for(i = 0, n = 0; i < 8; ++i)
- if(xmm_mask & (1 << i)) {
+ if(xmm_save_mask & (1 << i)) {
sse_movups(
func,
x86_make_disp( x86_make_reg( file_REG32, reg_SP ), n*16 ),
make_xmm( i ) );
++n;
}
+
+ for (i = 0; i < nr_args; i++) {
+ /* Load the address of the buffer we use for passing arguments and
+ * receiving results:
+ */
+ x86_lea(
+ func,
+ ecx,
+ arg[i] );
- x86_lea(
- func,
- ecx,
- get_temp( TEMP_R0, 0 ) );
-
- x86_push( func, ecx );
+ /* Push actual function arguments (currently just the pointer to
+ * the buffer above), and call the function:
+ */
+ x86_push( func, ecx );
+ }
+
x86_mov_reg_imm( func, ecx, (unsigned long) code );
x86_call( func, ecx );
- x86_pop(func, ecx );
-
+
+ /* Pop the arguments (or just add an immediate to esp)
+ */
+ for (i = 0; i < nr_args; i++) {
+ x86_pop(func, ecx );
+ }
+
+ /* Pop the saved XMM regs:
+ */
for(i = 0, n = 0; i < 8; ++i)
- if(xmm_mask & (1 << i)) {
+ if(xmm_save_mask & (1 << i)) {
sse_movups(
func,
make_xmm( i ),
@@ -602,34 +642,86 @@ emit_func_call_dst(
x86_pop(
func,
x86_make_reg( file_REG32, reg_AX) );
+}
+
+static void
+emit_func_call_dst_src1(
+ struct x86_function *func,
+ unsigned xmm_save,
+ unsigned xmm_dst,
+ unsigned xmm_src0,
+ void (PIPE_CDECL *code)() )
+{
+ struct x86_reg store = get_temp( TEMP_R0, 0 );
+ unsigned xmm_mask = ((1 << xmm_save) - 1) & ~(1 << xmm_dst);
+
+ /* Store our input parameters (in xmm regs) to the buffer we use
+ * for passing arguments. We will pass a pointer to this buffer as
+ * the actual function argument.
+ */
+ sse_movaps(
+ func,
+ store,
+ make_xmm( xmm_src0 ) );
+
+ emit_func_call( func,
+ xmm_mask,
+ &store,
+ 1,
+ code );
sse_movaps(
func,
make_xmm( xmm_dst ),
- get_temp( TEMP_R0, 0 ) );
+ store );
}
+
static void
-emit_func_call_dst_src(
+emit_func_call_dst_src2(
struct x86_function *func,
unsigned xmm_save,
unsigned xmm_dst,
- unsigned xmm_src,
+ unsigned xmm_src0,
+ unsigned xmm_src1,
void (PIPE_CDECL *code)() )
{
+ struct x86_reg store = get_temp( TEMP_R0, 0 );
+ unsigned xmm_mask = ((1 << xmm_save) - 1) & ~(1 << xmm_dst);
+
+ /* Store two inputs to parameter buffer.
+ */
sse_movaps(
func,
- get_temp( TEMP_R0, 1 ),
- make_xmm( xmm_src ) );
+ store,
+ make_xmm( xmm_src0 ) );
- emit_func_call_dst(
+ sse_movaps(
func,
- xmm_save,
- xmm_dst,
- code );
+ x86_make_disp( store, 4 * sizeof(float) ),
+ make_xmm( xmm_src1 ) );
+
+
+ /* Emit the call
+ */
+ emit_func_call( func,
+ xmm_mask,
+ &store,
+ 1,
+ code );
+
+ /* Retrieve the results:
+ */
+ sse_movaps(
+ func,
+ make_xmm( xmm_dst ),
+ store );
}
+
+
+
#if defined(PIPE_ARCH_SSE)
/*
@@ -782,10 +874,11 @@ emit_cos(
unsigned xmm_save,
unsigned xmm_dst )
{
- emit_func_call_dst(
+ emit_func_call_dst_src1(
func,
xmm_save,
xmm_dst,
+ xmm_dst,
cos4f );
}
@@ -812,10 +905,11 @@ emit_ex2(
unsigned xmm_save,
unsigned xmm_dst )
{
- emit_func_call_dst(
+ emit_func_call_dst_src1(
func,
xmm_save,
xmm_dst,
+ xmm_dst,
ex24f );
}
@@ -857,10 +951,11 @@ emit_flr(
unsigned xmm_save,
unsigned xmm_dst )
{
- emit_func_call_dst(
+ emit_func_call_dst_src1(
func,
xmm_save,
xmm_dst,
+ xmm_dst,
flr4f );
}
@@ -880,10 +975,11 @@ emit_frc(
unsigned xmm_save,
unsigned xmm_dst )
{
- emit_func_call_dst(
+ emit_func_call_dst_src1(
func,
xmm_save,
xmm_dst,
+ xmm_dst,
frc4f );
}
@@ -910,10 +1006,11 @@ emit_lg2(
unsigned xmm_save,
unsigned xmm_dst )
{
- emit_func_call_dst(
+ emit_func_call_dst_src1(
func,
xmm_save,
xmm_dst,
+ xmm_dst,
lg24f );
}
@@ -975,13 +1072,15 @@ emit_pow(
struct x86_function *func,
unsigned xmm_save,
unsigned xmm_dst,
- unsigned xmm_src )
+ unsigned xmm_src0,
+ unsigned xmm_src1 )
{
- emit_func_call_dst_src(
+ emit_func_call_dst_src2(
func,
xmm_save,
xmm_dst,
- xmm_src,
+ xmm_src0,
+ xmm_src1,
pow4f );
}
@@ -1017,10 +1116,11 @@ emit_rnd(
unsigned xmm_save,
unsigned xmm_dst )
{
- emit_func_call_dst(
+ emit_func_call_dst_src1(
func,
xmm_save,
xmm_dst,
+ xmm_dst,
rnd4f );
}
@@ -1099,10 +1199,11 @@ emit_sgn(
unsigned xmm_save,
unsigned xmm_dst )
{
- emit_func_call_dst(
+ emit_func_call_dst_src1(
func,
xmm_save,
xmm_dst,
+ xmm_dst,
sgn4f );
}
@@ -1121,10 +1222,11 @@ emit_sin (struct x86_function *func,
unsigned xmm_save,
unsigned xmm_dst)
{
- emit_func_call_dst(
+ emit_func_call_dst_src1(
func,
xmm_save,
xmm_dst,
+ xmm_dst,
sin4f );
}
@@ -1140,6 +1242,12 @@ emit_sub(
make_xmm( xmm_src ) );
}
+
+
+
+
+
+
/**
* Register fetch.
*/
@@ -1298,20 +1406,164 @@ emit_store(
#define STORE( FUNC, INST, XMM, INDEX, CHAN )\
emit_store( FUNC, XMM, &(INST).FullDstRegisters[INDEX], &(INST), CHAN )
+
+static void PIPE_CDECL
+fetch_texel( struct tgsi_sampler **sampler,
+ float *store )
+{
+#if 0
+ uint j;
+
+ debug_printf("%s sampler: %p (%p) store: %p\n",
+ __FUNCTION__,
+ sampler, *sampler,
+ store );
+
+ debug_printf("lodbias %f\n", store[12]);
+
+ for (j = 0; j < 4; j++)
+ debug_printf("sample %d texcoord %f %f\n",
+ j,
+ store[0+j],
+ store[4+j]);
+#endif
+
+ {
+ float rgba[NUM_CHANNELS][QUAD_SIZE];
+ (*sampler)->get_samples(*sampler,
+ &store[0],
+ &store[4],
+ &store[8],
+ 0.0f, /*store[12], lodbias */
+ rgba);
+
+ memcpy( store, rgba, 16 * sizeof(float));
+ }
+
+#if 0
+ for (j = 0; j < 4; j++)
+ debug_printf("sample %d result %f %f %f %f\n",
+ j,
+ store[0+j],
+ store[4+j],
+ store[8+j],
+ store[12+j]);
+#endif
+}
+
/**
* High-level instruction translators.
*/
static void
+emit_tex( struct x86_function *func,
+ const struct tgsi_full_instruction *inst,
+ boolean lodbias,
+ boolean projected)
+{
+ const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
+ struct x86_reg args[2];
+ unsigned count;
+ unsigned i;
+
+ switch (inst->InstructionExtTexture.Texture) {
+ case TGSI_TEXTURE_1D:
+ count = 1;
+ break;
+ case TGSI_TEXTURE_2D:
+ case TGSI_TEXTURE_RECT:
+ count = 2;
+ break;
+ case TGSI_TEXTURE_SHADOW1D:
+ case TGSI_TEXTURE_SHADOW2D:
+ case TGSI_TEXTURE_SHADOWRECT:
+ case TGSI_TEXTURE_3D:
+ case TGSI_TEXTURE_CUBE:
+ count = 3;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ if (lodbias) {
+ FETCH( func, *inst, 3, 0, 3 );
+ }
+ else {
+ emit_tempf(
+ func,
+ 3,
+ TGSI_EXEC_TEMP_00000000_I,
+ TGSI_EXEC_TEMP_00000000_C );
+
+ }
+
+ /* store lodbias whether enabled or not -- fetch_texel currently
+ * respects it always.
+ */
+ sse_movaps( func,
+ get_temp( TEMP_R0, 3 ),
+ make_xmm( 3 ) );
+
+
+ if (projected) {
+ FETCH( func, *inst, 3, 0, 3 );
+
+ emit_rcp( func, 3, 3 );
+ }
+
+ for (i = 0; i < count; i++) {
+ FETCH( func, *inst, i, 0, i );
+
+ if (projected) {
+ sse_mulps(
+ func,
+ make_xmm( i ),
+ make_xmm( 3 ) );
+ }
+
+ /* Store in the argument buffer:
+ */
+ sse_movaps(
+ func,
+ get_temp( TEMP_R0, i ),
+ make_xmm( i ) );
+ }
+
+ args[0] = get_temp( TEMP_R0, 0 );
+ args[1] = get_sampler_ptr( unit );
+
+
+ emit_func_call( func,
+ 0,
+ args,
+ Elements(args),
+ fetch_texel );
+
+ /* If all four channels are enabled, could use a pointer to
+ * dst[0].x instead of TEMP_R0 for store?
+ */
+ FOR_EACH_DST0_ENABLED_CHANNEL( *inst, i ) {
+
+ sse_movaps(
+ func,
+ make_xmm( 0 ),
+ get_temp( TEMP_R0, i ) );
+
+ STORE( func, *inst, 0, 0, i );
+ }
+}
+
+
+static void
emit_kil(
struct x86_function *func,
const struct tgsi_full_src_register *reg )
{
unsigned uniquemask;
- unsigned registers[4];
- unsigned nextregister = 0;
- unsigned firstchan = ~0;
+ unsigned unique_count = 0;
unsigned chan_index;
+ unsigned i;
/* This mask stores component bits that were already tested. Note that
* we test if the value is less than zero, so 1.0 and 0.0 need not to be
@@ -1331,18 +1583,11 @@ emit_kil(
uniquemask |= 1 << swizzle;
/* allocate register */
- registers[chan_index] = nextregister;
emit_fetch(
func,
- nextregister,
+ unique_count++,
reg,
chan_index );
- nextregister++;
-
- /* mark the first channel used */
- if( firstchan == ~0 ) {
- firstchan = chan_index;
- }
}
}
@@ -1353,32 +1598,32 @@ emit_kil(
func,
x86_make_reg( file_REG32, reg_DX ) );
- FOR_EACH_CHANNEL( chan_index ) {
- if( uniquemask & (1 << chan_index) ) {
- sse_cmpps(
+ for (i = 0 ; i < unique_count; i++ ) {
+ struct x86_reg dataXMM = make_xmm(i);
+
+ sse_cmpps(
+ func,
+ dataXMM,
+ get_temp(
+ TGSI_EXEC_TEMP_00000000_I,
+ TGSI_EXEC_TEMP_00000000_C ),
+ cc_LessThan );
+
+ if( i == 0 ) {
+ sse_movmskps(
func,
- make_xmm( registers[chan_index] ),
- get_temp(
- TGSI_EXEC_TEMP_00000000_I,
- TGSI_EXEC_TEMP_00000000_C ),
- cc_LessThan );
-
- if( chan_index == firstchan ) {
- sse_pmovmskb(
- func,
- x86_make_reg( file_REG32, reg_AX ),
- make_xmm( registers[chan_index] ) );
- }
- else {
- sse_pmovmskb(
- func,
- x86_make_reg( file_REG32, reg_DX ),
- make_xmm( registers[chan_index] ) );
- x86_or(
- func,
- x86_make_reg( file_REG32, reg_AX ),
- x86_make_reg( file_REG32, reg_DX ) );
- }
+ x86_make_reg( file_REG32, reg_AX ),
+ dataXMM );
+ }
+ else {
+ sse_movmskps(
+ func,
+ x86_make_reg( file_REG32, reg_DX ),
+ dataXMM );
+ x86_or(
+ func,
+ x86_make_reg( file_REG32, reg_AX ),
+ x86_make_reg( file_REG32, reg_DX ) );
}
}
@@ -1581,7 +1826,7 @@ emit_instruction(
get_temp(
TGSI_EXEC_TEMP_MINUS_128_I,
TGSI_EXEC_TEMP_MINUS_128_C ) );
- emit_pow( func, 3, 1, 2 );
+ emit_pow( func, 3, 1, 1, 2 );
FETCH( func, *inst, 0, 0, CHAN_X );
sse_xorps(
func,
@@ -1828,8 +2073,7 @@ emit_instruction(
}
break;
- case TGSI_OPCODE_LERP:
- /* TGSI_OPCODE_LRP */
+ case TGSI_OPCODE_LRP:
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH( func, *inst, 0, 0, chan_index );
FETCH( func, *inst, 1, 1, chan_index );
@@ -1845,12 +2089,7 @@ emit_instruction(
return 0;
break;
- case TGSI_OPCODE_CND0:
- return 0;
- break;
-
- case TGSI_OPCODE_DOT2ADD:
- /* TGSI_OPCODE_DP2A */
+ case TGSI_OPCODE_DP2A:
FETCH( func, *inst, 0, 0, CHAN_X ); /* xmm0 = src[0].x */
FETCH( func, *inst, 1, 1, CHAN_X ); /* xmm1 = src[1].x */
emit_mul( func, 0, 1 ); /* xmm0 = xmm0 * xmm1 */
@@ -1865,16 +2104,7 @@ emit_instruction(
}
break;
- case TGSI_OPCODE_INDEX:
- return 0;
- break;
-
- case TGSI_OPCODE_NEGATE:
- return 0;
- break;
-
- case TGSI_OPCODE_FRAC:
- /* TGSI_OPCODE_FRC */
+ case TGSI_OPCODE_FRC:
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH( func, *inst, 0, 0, chan_index );
emit_frc( func, 0, 0 );
@@ -1886,8 +2116,7 @@ emit_instruction(
return 0;
break;
- case TGSI_OPCODE_FLOOR:
- /* TGSI_OPCODE_FLR */
+ case TGSI_OPCODE_FLR:
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH( func, *inst, 0, 0, chan_index );
emit_flr( func, 0, 0 );
@@ -1903,8 +2132,7 @@ emit_instruction(
}
break;
- case TGSI_OPCODE_EXPBASE2:
- /* TGSI_OPCODE_EX2 */
+ case TGSI_OPCODE_EX2:
FETCH( func, *inst, 0, 0, CHAN_X );
emit_ex2( func, 0, 0 );
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
@@ -1912,8 +2140,7 @@ emit_instruction(
}
break;
- case TGSI_OPCODE_LOGBASE2:
- /* TGSI_OPCODE_LG2 */
+ case TGSI_OPCODE_LG2:
FETCH( func, *inst, 0, 0, CHAN_X );
emit_lg2( func, 0, 0 );
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
@@ -1921,18 +2148,16 @@ emit_instruction(
}
break;
- case TGSI_OPCODE_POWER:
- /* TGSI_OPCODE_POW */
+ case TGSI_OPCODE_POW:
FETCH( func, *inst, 0, 0, CHAN_X );
FETCH( func, *inst, 1, 1, CHAN_X );
- emit_pow( func, 0, 0, 1 );
+ emit_pow( func, 0, 0, 0, 1 );
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
STORE( func, *inst, 0, 0, chan_index );
}
break;
- case TGSI_OPCODE_CROSSPRODUCT:
- /* TGSI_OPCODE_XPD */
+ case TGSI_OPCODE_XPD:
if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
FETCH( func, *inst, 1, 1, CHAN_Z );
@@ -1978,10 +2203,6 @@ emit_instruction(
}
break;
- case TGSI_OPCODE_MULTIPLYMATRIX:
- return 0;
- break;
-
case TGSI_OPCODE_ABS:
FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
FETCH( func, *inst, 0, 0, chan_index );
@@ -2094,21 +2315,7 @@ emit_instruction(
break;
case TGSI_OPCODE_TEX:
- if (0) {
- /* Disable dummy texture code:
- */
- emit_tempf(
- func,
- 0,
- TEMP_ONE_I,
- TEMP_ONE_C );
- FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) {
- STORE( func, *inst, 0, 0, chan_index );
- }
- }
- else {
- return 0;
- }
+ emit_tex( func, inst, FALSE, FALSE );
break;
case TGSI_OPCODE_TXD:
@@ -2206,7 +2413,7 @@ emit_instruction(
break;
case TGSI_OPCODE_TXB:
- return 0;
+ emit_tex( func, inst, TRUE, FALSE );
break;
case TGSI_OPCODE_NRM:
@@ -2314,9 +2521,13 @@ emit_instruction(
break;
case TGSI_OPCODE_TXL:
- return 0;
+ emit_tex( func, inst, TRUE, FALSE );
break;
+ case TGSI_OPCODE_TXP:
+ emit_tex( func, inst, FALSE, TRUE );
+ break;
+
case TGSI_OPCODE_BRK:
return 0;
break;
@@ -2325,7 +2536,7 @@ emit_instruction(
return 0;
break;
- case TGSI_OPCODE_LOOP:
+ case TGSI_OPCODE_BGNFOR:
return 0;
break;
@@ -2341,7 +2552,7 @@ emit_instruction(
return 0;
break;
- case TGSI_OPCODE_ENDLOOP:
+ case TGSI_OPCODE_ENDFOR:
return 0;
break;
@@ -2496,7 +2707,7 @@ emit_declaration(
static void aos_to_soa( struct x86_function *func,
uint arg_aos,
- uint arg_soa,
+ uint arg_machine,
uint arg_num,
uint arg_stride )
{
@@ -2511,7 +2722,10 @@ static void aos_to_soa( struct x86_function *func,
x86_push( func, x86_make_reg( file_REG32, reg_BX ) );
x86_mov( func, aos_input, x86_fn_arg( func, arg_aos ) );
- x86_mov( func, soa_input, x86_fn_arg( func, arg_soa ) );
+ x86_mov( func, soa_input, x86_fn_arg( func, arg_machine ) );
+ x86_lea( func, soa_input,
+ x86_make_disp( soa_input,
+ Offset(struct tgsi_exec_machine, Inputs) ) );
x86_mov( func, num_inputs, x86_fn_arg( func, arg_num ) );
x86_mov( func, stride, x86_fn_arg( func, arg_stride ) );
@@ -2553,28 +2767,30 @@ static void aos_to_soa( struct x86_function *func,
x86_jcc( func, cc_NE, inner_loop );
/* Restore EBX */
- x86_pop( func, aos_input );
+ x86_pop( func, x86_make_reg( file_REG32, reg_BX ) );
}
-static void soa_to_aos( struct x86_function *func, uint aos, uint soa, uint num, uint stride )
+static void soa_to_aos( struct x86_function *func,
+ uint arg_aos,
+ uint arg_machine,
+ uint arg_num,
+ uint arg_stride )
{
- struct x86_reg soa_output;
- struct x86_reg aos_output;
- struct x86_reg num_outputs;
- struct x86_reg temp;
+ struct x86_reg soa_output = x86_make_reg( file_REG32, reg_AX );
+ struct x86_reg aos_output = x86_make_reg( file_REG32, reg_BX );
+ struct x86_reg num_outputs = x86_make_reg( file_REG32, reg_CX );
+ struct x86_reg temp = x86_make_reg( file_REG32, reg_DX );
int inner_loop;
- soa_output = x86_make_reg( file_REG32, reg_AX );
- aos_output = x86_make_reg( file_REG32, reg_BX );
- num_outputs = x86_make_reg( file_REG32, reg_CX );
- temp = x86_make_reg( file_REG32, reg_DX );
-
/* Save EBX */
- x86_push( func, aos_output );
+ x86_push( func, x86_make_reg( file_REG32, reg_BX ) );
- x86_mov( func, soa_output, x86_fn_arg( func, soa ) );
- x86_mov( func, aos_output, x86_fn_arg( func, aos ) );
- x86_mov( func, num_outputs, x86_fn_arg( func, num ) );
+ x86_mov( func, aos_output, x86_fn_arg( func, arg_aos ) );
+ x86_mov( func, soa_output, x86_fn_arg( func, arg_machine ) );
+ x86_lea( func, soa_output,
+ x86_make_disp( soa_output,
+ Offset(struct tgsi_exec_machine, Outputs) ) );
+ x86_mov( func, num_outputs, x86_fn_arg( func, arg_num ) );
/* do */
inner_loop = x86_get_label( func );
@@ -2591,7 +2807,7 @@ static void soa_to_aos( struct x86_function *func, uint aos, uint soa, uint num,
sse_unpcklps( func, make_xmm( 3 ), make_xmm( 4 ) );
sse_unpckhps( func, make_xmm( 5 ), make_xmm( 4 ) );
- x86_mov( func, temp, x86_fn_arg( func, stride ) );
+ x86_mov( func, temp, x86_fn_arg( func, arg_stride ) );
x86_push( func, aos_output );
sse_movlps( func, x86_make_disp( aos_output, 0 ), make_xmm( 0 ) );
sse_movlps( func, x86_make_disp( aos_output, 8 ), make_xmm( 3 ) );
@@ -2615,20 +2831,13 @@ static void soa_to_aos( struct x86_function *func, uint aos, uint soa, uint num,
x86_jcc( func, cc_NE, inner_loop );
/* Restore EBX */
- x86_pop( func, aos_output );
+ x86_pop( func, x86_make_reg( file_REG32, reg_BX ) );
}
/**
* Translate a TGSI vertex/fragment shader to SSE2 code.
* Slightly different things are done for vertex vs. fragment shaders.
*
- * Note that fragment shaders are responsible for interpolating shader
- * inputs. Because on x86 we have only 4 GP registers, and here we
- * have 5 shader arguments (input, output, const, temp and coef), the
- * code is split into two phases -- DECLARATION and INSTRUCTION phase.
- * GP register holding the output argument is aliased with the coeff
- * argument, as outputs are not needed in the DECLARATION phase.
- *
* \param tokens the TGSI input shader
* \param func the output SSE code/function
* \param immediates buffer to place immediates, later passed to SSE func
@@ -2642,7 +2851,6 @@ tgsi_emit_sse2(
boolean do_swizzles )
{
struct tgsi_parse_context parse;
- boolean instruction_phase = FALSE;
unsigned ok = 1;
uint num_immediates = 0;
@@ -2654,74 +2862,48 @@ tgsi_emit_sse2(
/* Can't just use EDI, EBX without save/restoring them:
*/
- x86_push(
- func,
- get_immediate_base() );
-
- x86_push(
- func,
- get_temp_base() );
-
+ x86_push( func, x86_make_reg( file_REG32, reg_BX ) );
+ x86_push( func, x86_make_reg( file_REG32, reg_DI ) );
/*
* Different function args for vertex/fragment shaders:
*/
- if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
- /* DECLARATION phase, do not load output argument. */
- x86_mov(
- func,
- get_input_base(),
- x86_fn_arg( func, 1 ) );
- /* skipping outputs argument here */
- x86_mov(
- func,
- get_const_base(),
- x86_fn_arg( func, 3 ) );
- x86_mov(
- func,
- get_temp_base(),
- x86_fn_arg( func, 4 ) );
- x86_mov(
- func,
- get_coef_base(),
- x86_fn_arg( func, 5 ) );
- x86_mov(
- func,
- get_immediate_base(),
- x86_fn_arg( func, 6 ) );
- }
- else {
- assert(parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX);
-
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX) {
if (do_swizzles)
aos_to_soa( func,
- 6, /* aos_input */
- 1, /* machine->input */
- 7, /* num_inputs */
- 8 ); /* input_stride */
+ 4, /* aos_input */
+ 1, /* machine */
+ 5, /* num_inputs */
+ 6 ); /* input_stride */
+ }
+ x86_mov(
+ func,
+ get_machine_base(),
+ x86_fn_arg( func, 1 ) );
+ x86_mov(
+ func,
+ get_const_base(),
+ x86_fn_arg( func, 2 ) );
+ x86_mov(
+ func,
+ get_immediate_base(),
+ x86_fn_arg( func, 3 ) );
+
+ if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
x86_mov(
- func,
- get_input_base(),
- x86_fn_arg( func, 1 ) );
- x86_mov(
- func,
- get_output_base(),
- x86_fn_arg( func, 2 ) );
- x86_mov(
- func,
- get_const_base(),
- x86_fn_arg( func, 3 ) );
- x86_mov(
- func,
- get_temp_base(),
- x86_fn_arg( func, 4 ) );
- x86_mov(
- func,
- get_immediate_base(),
- x86_fn_arg( func, 5 ) );
+ func,
+ get_coef_base(),
+ x86_fn_arg( func, 4 ) );
}
+ x86_mov(
+ func,
+ get_sampler_base(),
+ x86_make_disp( get_machine_base(),
+ Offset( struct tgsi_exec_machine, Samplers ) ) );
+
+
while( !tgsi_parse_end_of_tokens( &parse ) && ok ) {
tgsi_parse_token( &parse );
@@ -2735,24 +2917,15 @@ tgsi_emit_sse2(
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
- if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
- if( !instruction_phase ) {
- /* INSTRUCTION phase, overwrite coeff with output. */
- instruction_phase = TRUE;
- x86_mov(
- func,
- get_output_base(),
- x86_fn_arg( func, 2 ) );
- }
- }
-
ok = emit_instruction(
func,
&parse.FullToken.FullInstruction );
if (!ok) {
- debug_printf("failed to translate tgsi opcode %d to SSE (%s)\n",
- parse.FullToken.FullInstruction.Instruction.Opcode,
+ uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode;
+ debug_printf("failed to translate tgsi opcode %d (%s) to SSE (%s)\n",
+ opcode,
+ tgsi_get_opcode_name(opcode),
parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX ?
"vertex shader" : "fragment shader");
}
@@ -2767,7 +2940,7 @@ tgsi_emit_sse2(
assert(num_immediates < TGSI_EXEC_NUM_IMMEDIATES);
for( i = 0; i < size; i++ ) {
immediates[num_immediates][i] =
- parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
+ parse.FullToken.FullImmediate.u[i].Float;
}
#if 0
debug_printf("SSE FS immediate[%d] = %f %f %f %f\n",
@@ -2789,18 +2962,17 @@ tgsi_emit_sse2(
if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX) {
if (do_swizzles)
- soa_to_aos( func, 9, 2, 10, 11 );
+ soa_to_aos( func,
+ 7, /* aos_output */
+ 1, /* machine */
+ 8, /* num_outputs */
+ 9 ); /* output_stride */
}
/* Can't just use EBX, EDI without save/restoring them:
*/
- x86_pop(
- func,
- get_temp_base() );
-
- x86_pop(
- func,
- get_immediate_base() );
+ x86_pop( func, x86_make_reg( file_REG32, reg_DI ) );
+ x86_pop( func, x86_make_reg( file_REG32, reg_BX ) );
emit_ret( func );
diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.h b/src/gallium/auxiliary/tgsi/tgsi_sse2.h
index af838b2a25..d81ee3d00e 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_sse2.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.h
@@ -34,6 +34,7 @@ extern "C" {
struct tgsi_token;
struct x86_function;
+struct tgsi_interp_coef;
unsigned
tgsi_emit_sse2(
@@ -42,6 +43,33 @@ tgsi_emit_sse2(
float (*immediates)[4],
boolean do_swizzles );
+
+/* This is the function prototype generated when do_swizzles is false
+ * -- effectively for fragment shaders.
+ */
+typedef void (PIPE_CDECL *tgsi_sse2_fs_function) (
+ struct tgsi_exec_machine *machine, /* 1 */
+ const float (*constant)[4], /* 2 */
+ const float (*immediate)[4], /* 3 */
+ const struct tgsi_interp_coef *coef /* 4 */
+ );
+
+
+/* This is the function prototype generated when do_swizzles is true
+ * -- effectively for vertex shaders.
+ */
+typedef void (PIPE_CDECL *tgsi_sse2_vs_func) (
+ struct tgsi_exec_machine *machine, /* 1 */
+ const float (*constant)[4], /* 2 */
+ const float (*immediate)[4], /* 3 */
+ const float (*aos_input)[4], /* 4 */
+ uint num_inputs, /* 5 */
+ uint input_stride, /* 6 */
+ float (*aos_output)[4], /* 7 */
+ uint num_outputs, /* 8 */
+ uint output_stride ); /* 9 */
+
+
#if defined __cplusplus
}
#endif
diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c
index a76bbc9140..d438450b1e 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_text.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_text.c
@@ -231,7 +231,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
"TEMP",
"SAMP",
"ADDR",
- "IMM"
+ "IMM",
+ "LOOP"
};
static boolean
@@ -789,16 +790,6 @@ match_inst_mnemonic(const char **pcur,
if (str_match_no_case(pcur, info->mnemonic)) {
return TRUE;
}
- if (info->alt_mnemonic1) {
- if (str_match_no_case(pcur, info->alt_mnemonic1)) {
- return TRUE;
- }
- if (info->alt_mnemonic2) {
- if (str_match_no_case(pcur, info->alt_mnemonic2)) {
- return TRUE;
- }
- }
- }
return FALSE;
}
@@ -1091,7 +1082,10 @@ static boolean parse_immediate( struct translate_ctx *ctx )
imm = tgsi_default_full_immediate();
imm.Immediate.NrTokens += 4;
imm.Immediate.DataType = TGSI_IMM_FLOAT32;
- imm.u.Pointer = values;
+ imm.u[0].Float = values[0];
+ imm.u[1].Float = values[1];
+ imm.u[2].Float = values[2];
+ imm.u[3].Float = values[3];
advance = tgsi_build_full_immediate(
&imm,
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
new file mode 100644
index 0000000000..f7096bd8e2
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -0,0 +1,938 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "tgsi/tgsi_ureg.h"
+#include "tgsi/tgsi_info.h"
+#include "tgsi/tgsi_dump.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+union tgsi_any_token {
+ struct tgsi_version version;
+ struct tgsi_header header;
+ struct tgsi_processor processor;
+ struct tgsi_token token;
+ struct tgsi_declaration decl;
+ struct tgsi_declaration_range decl_range;
+ struct tgsi_declaration_semantic decl_semantic;
+ struct tgsi_immediate imm;
+ union tgsi_immediate_data imm_data;
+ struct tgsi_instruction insn;
+ struct tgsi_instruction_ext_nv insn_ext_nv;
+ struct tgsi_instruction_ext_label insn_ext_label;
+ struct tgsi_instruction_ext_texture insn_ext_texture;
+ struct tgsi_instruction_ext_predicate insn_ext_predicate;
+ struct tgsi_src_register src;
+ struct tgsi_src_register_ext_swz src_ext_swz;
+ struct tgsi_src_register_ext_mod src_ext_mod;
+ struct tgsi_dimension dim;
+ struct tgsi_dst_register dst;
+ struct tgsi_dst_register_ext_concode dst_ext_code;
+ struct tgsi_dst_register_ext_modulate dst_ext_mod;
+ struct tgsi_dst_register_ext_predicate dst_ext_pred;
+ unsigned value;
+};
+
+
+struct ureg_tokens {
+ union tgsi_any_token *tokens;
+ unsigned size;
+ unsigned order;
+ unsigned count;
+};
+
+#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS
+#define UREG_MAX_OUTPUT PIPE_MAX_ATTRIBS
+#define UREG_MAX_IMMEDIATE 32
+#define UREG_MAX_TEMP 256
+#define UREG_MAX_ADDR 2
+
+#define DOMAIN_DECL 0
+#define DOMAIN_INSN 1
+
+struct ureg_program
+{
+ unsigned processor;
+ struct pipe_context *pipe;
+
+ struct {
+ unsigned semantic_name;
+ unsigned semantic_index;
+ unsigned interp;
+ } input[UREG_MAX_INPUT];
+ unsigned nr_inputs;
+
+ struct {
+ unsigned semantic_name;
+ unsigned semantic_index;
+ } output[UREG_MAX_OUTPUT];
+ unsigned nr_outputs;
+
+ struct {
+ float v[4];
+ unsigned nr;
+ } immediate[UREG_MAX_IMMEDIATE];
+ unsigned nr_immediates;
+
+ struct ureg_src sampler[PIPE_MAX_SAMPLERS];
+ unsigned nr_samplers;
+
+ unsigned temps_active[UREG_MAX_TEMP / 32];
+ unsigned nr_temps;
+
+ unsigned nr_addrs;
+
+ unsigned nr_constants;
+ unsigned nr_instructions;
+
+ struct ureg_tokens domain[2];
+};
+
+static union tgsi_any_token error_tokens[32];
+
+static void tokens_error( struct ureg_tokens *tokens )
+{
+ tokens->tokens = error_tokens;
+ tokens->size = Elements(error_tokens);
+ tokens->count = 0;
+}
+
+
+static void tokens_expand( struct ureg_tokens *tokens,
+ unsigned count )
+{
+ unsigned old_size = tokens->size * sizeof(unsigned);
+
+ if (tokens->tokens == error_tokens)
+ goto fail;
+
+ while (tokens->count + count > tokens->size) {
+ tokens->size = (1 << ++tokens->order);
+ }
+
+ tokens->tokens = REALLOC(tokens->tokens,
+ old_size,
+ tokens->size * sizeof(unsigned));
+ if (tokens->tokens == NULL)
+ goto fail;
+
+ return;
+
+fail:
+ tokens_error(tokens);
+}
+
+static void set_bad( struct ureg_program *ureg )
+{
+ tokens_error(&ureg->domain[0]);
+}
+
+
+
+static union tgsi_any_token *get_tokens( struct ureg_program *ureg,
+ unsigned domain,
+ unsigned count )
+{
+ struct ureg_tokens *tokens = &ureg->domain[domain];
+ union tgsi_any_token *result;
+
+ if (tokens->count + count > tokens->size)
+ tokens_expand(tokens, count);
+
+ result = &tokens->tokens[tokens->count];
+ tokens->count += count;
+ return result;
+}
+
+
+static union tgsi_any_token *retrieve_token( struct ureg_program *ureg,
+ unsigned domain,
+ unsigned nr )
+{
+ if (ureg->domain[domain].tokens == error_tokens)
+ return &error_tokens[0];
+
+ return &ureg->domain[domain].tokens[nr];
+}
+
+
+
+static INLINE struct ureg_dst
+ureg_dst_register( unsigned file,
+ unsigned index )
+{
+ struct ureg_dst dst;
+
+ dst.File = file;
+ dst.WriteMask = TGSI_WRITEMASK_XYZW;
+ dst.Indirect = 0;
+ dst.IndirectIndex = 0;
+ dst.IndirectSwizzle = 0;
+ dst.Saturate = 0;
+ dst.Index = index;
+ dst.Pad1 = 0;
+ dst.Pad2 = 0;
+
+ return dst;
+}
+
+static INLINE struct ureg_src
+ureg_src_register( unsigned file,
+ unsigned index )
+{
+ struct ureg_src src;
+
+ src.File = file;
+ src.SwizzleX = TGSI_SWIZZLE_X;
+ src.SwizzleY = TGSI_SWIZZLE_Y;
+ src.SwizzleZ = TGSI_SWIZZLE_Z;
+ src.SwizzleW = TGSI_SWIZZLE_W;
+ src.Pad = 0;
+ src.Indirect = 0;
+ src.IndirectIndex = 0;
+ src.IndirectSwizzle = 0;
+ src.Absolute = 0;
+ src.Index = index;
+ src.Negate = 0;
+
+ return src;
+}
+
+
+
+
+static struct ureg_src
+ureg_DECL_input( struct ureg_program *ureg,
+ unsigned name,
+ unsigned index,
+ unsigned interp_mode )
+{
+ unsigned i;
+
+ for (i = 0; i < ureg->nr_inputs; i++) {
+ if (ureg->input[i].semantic_name == name &&
+ ureg->input[i].semantic_index == index)
+ goto out;
+ }
+
+ if (ureg->nr_inputs < UREG_MAX_INPUT) {
+ ureg->input[i].semantic_name = name;
+ ureg->input[i].semantic_index = index;
+ ureg->input[i].interp = interp_mode;
+ ureg->nr_inputs++;
+ }
+ else {
+ set_bad( ureg );
+ }
+
+out:
+ return ureg_src_register( TGSI_FILE_INPUT, i );
+}
+
+
+
+struct ureg_src
+ureg_DECL_fs_input( struct ureg_program *ureg,
+ unsigned name,
+ unsigned index,
+ unsigned interp )
+{
+ assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
+ return ureg_DECL_input( ureg, name, index, interp );
+}
+
+
+struct ureg_src
+ureg_DECL_vs_input( struct ureg_program *ureg,
+ unsigned name,
+ unsigned index )
+{
+ assert(ureg->processor == TGSI_PROCESSOR_VERTEX);
+ return ureg_DECL_input( ureg, name, index, TGSI_INTERPOLATE_CONSTANT );
+}
+
+
+struct ureg_dst
+ureg_DECL_output( struct ureg_program *ureg,
+ unsigned name,
+ unsigned index )
+{
+ unsigned i;
+
+ for (i = 0; i < ureg->nr_outputs; i++) {
+ if (ureg->output[i].semantic_name == name &&
+ ureg->output[i].semantic_index == index)
+ goto out;
+ }
+
+ if (ureg->nr_outputs < UREG_MAX_OUTPUT) {
+ ureg->output[i].semantic_name = name;
+ ureg->output[i].semantic_index = index;
+ ureg->nr_outputs++;
+ }
+ else {
+ set_bad( ureg );
+ }
+
+out:
+ return ureg_dst_register( TGSI_FILE_OUTPUT, i );
+}
+
+
+/* Returns a new constant register. Keep track of which have been
+ * referred to so that we can emit decls later.
+ *
+ * There is nothing in this code to bind this constant to any tracked
+ * value or manage any constant_buffer contents -- that's the
+ * resposibility of the calling code.
+ */
+struct ureg_src ureg_DECL_constant(struct ureg_program *ureg )
+{
+ return ureg_src_register( TGSI_FILE_CONSTANT, ureg->nr_constants++ );
+}
+
+
+/* Allocate a new temporary. Temporaries greater than UREG_MAX_TEMP
+ * are legal, but will not be released.
+ */
+struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
+{
+ unsigned i;
+
+ for (i = 0; i < UREG_MAX_TEMP; i += 32) {
+ int bit = ffs(~ureg->temps_active[i/32]);
+ if (bit != 0) {
+ i += bit - 1;
+ goto out;
+ }
+ }
+
+ /* No reusable temps, so allocate a new one:
+ */
+ i = ureg->nr_temps++;
+
+out:
+ if (i < UREG_MAX_TEMP)
+ ureg->temps_active[i/32] |= 1 << (i % 32);
+
+ if (i >= ureg->nr_temps)
+ ureg->nr_temps = i + 1;
+
+ return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
+}
+
+
+void ureg_release_temporary( struct ureg_program *ureg,
+ struct ureg_dst tmp )
+{
+ if(tmp.File == TGSI_FILE_TEMPORARY)
+ if (tmp.Index < UREG_MAX_TEMP)
+ ureg->temps_active[tmp.Index/32] &= ~(1 << (tmp.Index % 32));
+}
+
+
+/* Allocate a new address register.
+ */
+struct ureg_dst ureg_DECL_address( struct ureg_program *ureg )
+{
+ if (ureg->nr_addrs < UREG_MAX_ADDR)
+ return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ );
+
+ assert( 0 );
+ return ureg_dst_register( TGSI_FILE_ADDRESS, 0 );
+}
+
+/* Allocate a new sampler.
+ */
+struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
+ unsigned nr )
+{
+ unsigned i;
+
+ for (i = 0; i < ureg->nr_samplers; i++)
+ if (ureg->sampler[i].Index == nr)
+ return ureg->sampler[i];
+
+ if (i < PIPE_MAX_SAMPLERS) {
+ ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr );
+ ureg->nr_samplers++;
+ return ureg->sampler[i];
+ }
+
+ assert( 0 );
+ return ureg->sampler[0];
+}
+
+
+
+
+static int match_or_expand_immediate( const float *v,
+ unsigned nr,
+ float *v2,
+ unsigned *nr2,
+ unsigned *swizzle )
+{
+ unsigned i, j;
+
+ *swizzle = 0;
+
+ for (i = 0; i < nr; i++) {
+ boolean found = FALSE;
+
+ for (j = 0; j < *nr2 && !found; j++) {
+ if (v[i] == v2[j]) {
+ *swizzle |= j << (i * 2);
+ found = TRUE;
+ }
+ }
+
+ if (!found) {
+ if (*nr2 >= 4)
+ return FALSE;
+
+ v2[*nr2] = v[i];
+ *swizzle |= *nr2 << (i * 2);
+ (*nr2)++;
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+
+struct ureg_src ureg_DECL_immediate( struct ureg_program *ureg,
+ const float *v,
+ unsigned nr )
+{
+ unsigned i, j;
+ unsigned swizzle;
+
+ /* Could do a first pass where we examine all existing immediates
+ * without expanding.
+ */
+
+ for (i = 0; i < ureg->nr_immediates; i++) {
+ if (match_or_expand_immediate( v,
+ nr,
+ ureg->immediate[i].v,
+ &ureg->immediate[i].nr,
+ &swizzle ))
+ goto out;
+ }
+
+ if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) {
+ i = ureg->nr_immediates++;
+ if (match_or_expand_immediate( v,
+ nr,
+ ureg->immediate[i].v,
+ &ureg->immediate[i].nr,
+ &swizzle ))
+ goto out;
+ }
+
+ set_bad( ureg );
+
+out:
+ /* Make sure that all referenced elements are from this immediate.
+ * Has the effect of making size-one immediates into scalars.
+ */
+ for (j = nr; j < 4; j++)
+ swizzle |= (swizzle & 0x3) << (j * 2);
+
+ return ureg_swizzle( ureg_src_register( TGSI_FILE_IMMEDIATE, i ),
+ (swizzle >> 0) & 0x3,
+ (swizzle >> 2) & 0x3,
+ (swizzle >> 4) & 0x3,
+ (swizzle >> 6) & 0x3);
+}
+
+
+void
+ureg_emit_src( struct ureg_program *ureg,
+ struct ureg_src src )
+{
+ unsigned size = (1 +
+ (src.Absolute ? 1 : 0) +
+ (src.Indirect ? 1 : 0));
+
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
+ unsigned n = 0;
+
+ assert(src.File != TGSI_FILE_NULL);
+ assert(src.File != TGSI_FILE_OUTPUT);
+ assert(src.File < TGSI_FILE_COUNT);
+
+ out[n].value = 0;
+ out[n].src.File = src.File;
+ out[n].src.SwizzleX = src.SwizzleX;
+ out[n].src.SwizzleY = src.SwizzleY;
+ out[n].src.SwizzleZ = src.SwizzleZ;
+ out[n].src.SwizzleW = src.SwizzleW;
+ out[n].src.Index = src.Index;
+ out[n].src.Negate = src.Negate;
+ n++;
+
+ if (src.Absolute) {
+ out[0].src.Extended = 1;
+ out[0].src.Negate = 0;
+ out[n].value = 0;
+ out[n].src_ext_mod.Type = TGSI_SRC_REGISTER_EXT_TYPE_MOD;
+ out[n].src_ext_mod.Absolute = 1;
+ out[n].src_ext_mod.Negate = src.Negate;
+ n++;
+ }
+
+ if (src.Indirect) {
+ out[0].src.Indirect = 1;
+ out[n].value = 0;
+ out[n].src.File = TGSI_FILE_ADDRESS;
+ out[n].src.SwizzleX = src.IndirectSwizzle;
+ out[n].src.SwizzleY = src.IndirectSwizzle;
+ out[n].src.SwizzleZ = src.IndirectSwizzle;
+ out[n].src.SwizzleW = src.IndirectSwizzle;
+ out[n].src.Index = src.IndirectIndex;
+ n++;
+ }
+
+ assert(n == size);
+}
+
+
+void
+ureg_emit_dst( struct ureg_program *ureg,
+ struct ureg_dst dst )
+{
+ unsigned size = (1 +
+ (dst.Indirect ? 1 : 0));
+
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
+ unsigned n = 0;
+
+ assert(dst.File != TGSI_FILE_NULL);
+ assert(dst.File != TGSI_FILE_CONSTANT);
+ assert(dst.File != TGSI_FILE_INPUT);
+ assert(dst.File != TGSI_FILE_SAMPLER);
+ assert(dst.File != TGSI_FILE_IMMEDIATE);
+ assert(dst.File < TGSI_FILE_COUNT);
+
+ out[n].value = 0;
+ out[n].dst.File = dst.File;
+ out[n].dst.WriteMask = dst.WriteMask;
+ out[n].dst.Indirect = dst.Indirect;
+ out[n].dst.Index = dst.Index;
+ n++;
+
+ if (dst.Indirect) {
+ out[n].value = 0;
+ out[n].src.File = TGSI_FILE_ADDRESS;
+ out[n].src.SwizzleX = dst.IndirectSwizzle;
+ out[n].src.SwizzleY = dst.IndirectSwizzle;
+ out[n].src.SwizzleZ = dst.IndirectSwizzle;
+ out[n].src.SwizzleW = dst.IndirectSwizzle;
+ out[n].src.Index = dst.IndirectIndex;
+ n++;
+ }
+
+ assert(n == size);
+}
+
+
+
+unsigned
+ureg_emit_insn(struct ureg_program *ureg,
+ unsigned opcode,
+ boolean saturate,
+ unsigned num_dst,
+ unsigned num_src )
+{
+ union tgsi_any_token *out;
+
+ out = get_tokens( ureg, DOMAIN_INSN, 1 );
+ out[0].value = 0;
+ out[0].insn.Type = TGSI_TOKEN_TYPE_INSTRUCTION;
+ out[0].insn.NrTokens = 0;
+ out[0].insn.Opcode = opcode;
+ out[0].insn.Saturate = saturate;
+ out[0].insn.NumDstRegs = num_dst;
+ out[0].insn.NumSrcRegs = num_src;
+ out[0].insn.Padding = 0;
+ out[0].insn.Extended = 0;
+
+ ureg->nr_instructions++;
+
+ return ureg->domain[DOMAIN_INSN].count - 1;
+}
+
+
+void
+ureg_emit_label(struct ureg_program *ureg,
+ unsigned insn_token,
+ unsigned *label_token )
+{
+ union tgsi_any_token *out, *insn;
+
+ if(!label_token)
+ return;
+
+ out = get_tokens( ureg, DOMAIN_INSN, 1 );
+ insn = retrieve_token( ureg, DOMAIN_INSN, insn_token );
+
+ insn->insn.Extended = 1;
+
+ out[0].value = 0;
+ out[0].insn_ext_label.Type = TGSI_INSTRUCTION_EXT_TYPE_LABEL;
+
+ *label_token = ureg->domain[DOMAIN_INSN].count - 1;
+}
+
+/* Will return a number which can be used in a label to point to the
+ * next instruction to be emitted.
+ */
+unsigned
+ureg_get_instruction_number( struct ureg_program *ureg )
+{
+ return ureg->nr_instructions;
+}
+
+/* Patch a given label (expressed as a token number) to point to a
+ * given instruction (expressed as an instruction number).
+ */
+void
+ureg_fixup_label(struct ureg_program *ureg,
+ unsigned label_token,
+ unsigned instruction_number )
+{
+ union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token );
+
+ assert(out->insn_ext_label.Type == TGSI_INSTRUCTION_EXT_TYPE_LABEL);
+ out->insn_ext_label.Label = instruction_number;
+}
+
+
+void
+ureg_emit_texture(struct ureg_program *ureg,
+ unsigned insn_token,
+ unsigned target )
+{
+ union tgsi_any_token *out, *insn;
+
+ out = get_tokens( ureg, DOMAIN_INSN, 1 );
+ insn = retrieve_token( ureg, DOMAIN_INSN, insn_token );
+
+ insn->insn.Extended = 1;
+
+ out[0].value = 0;
+ out[0].insn_ext_texture.Type = TGSI_INSTRUCTION_EXT_TYPE_TEXTURE;
+ out[0].insn_ext_texture.Texture = target;
+}
+
+
+void
+ureg_fixup_insn_size(struct ureg_program *ureg,
+ unsigned insn )
+{
+ union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn );
+
+ assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
+ out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1;
+}
+
+
+void
+ureg_insn(struct ureg_program *ureg,
+ unsigned opcode,
+ const struct ureg_dst *dst,
+ unsigned nr_dst,
+ const struct ureg_src *src,
+ unsigned nr_src )
+{
+ unsigned insn, i;
+ boolean saturate;
+
+#ifdef DEBUG
+ {
+ const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
+ assert(info);
+ if(info) {
+ assert(nr_dst == info->num_dst);
+ assert(nr_src == info->num_src);
+ }
+ }
+#endif
+
+ saturate = nr_dst ? dst[0].Saturate : FALSE;
+
+ insn = ureg_emit_insn( ureg, opcode, saturate, nr_dst, nr_src );
+
+ for (i = 0; i < nr_dst; i++)
+ ureg_emit_dst( ureg, dst[i] );
+
+ for (i = 0; i < nr_src; i++)
+ ureg_emit_src( ureg, src[i] );
+
+ ureg_fixup_insn_size( ureg, insn );
+}
+
+
+
+static void emit_decl( struct ureg_program *ureg,
+ unsigned file,
+ unsigned index,
+ unsigned semantic_name,
+ unsigned semantic_index,
+ unsigned interp )
+{
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 );
+
+ out[0].value = 0;
+ out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
+ out[0].decl.NrTokens = 3;
+ out[0].decl.File = file;
+ out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */
+ out[0].decl.Interpolate = interp;
+ out[0].decl.Semantic = 1;
+
+ out[1].value = 0;
+ out[1].decl_range.First =
+ out[1].decl_range.Last = index;
+
+ out[2].value = 0;
+ out[2].decl_semantic.SemanticName = semantic_name;
+ out[2].decl_semantic.SemanticIndex = semantic_index;
+
+}
+
+
+static void emit_decl_range( struct ureg_program *ureg,
+ unsigned file,
+ unsigned first,
+ unsigned count )
+{
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
+
+ out[0].value = 0;
+ out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
+ out[0].decl.NrTokens = 2;
+ out[0].decl.File = file;
+ out[0].decl.UsageMask = 0xf;
+ out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT;
+ out[0].decl.Semantic = 0;
+
+ out[1].value = 0;
+ out[1].decl_range.First = first;
+ out[1].decl_range.Last = first + count - 1;
+}
+
+static void emit_immediate( struct ureg_program *ureg,
+ const float *v )
+{
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 );
+
+ out[0].value = 0;
+ out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
+ out[0].imm.NrTokens = 5;
+ out[0].imm.DataType = TGSI_IMM_FLOAT32;
+ out[0].imm.Padding = 0;
+ out[0].imm.Extended = 0;
+
+ out[1].imm_data.Float = v[0];
+ out[2].imm_data.Float = v[1];
+ out[3].imm_data.Float = v[2];
+ out[4].imm_data.Float = v[3];
+}
+
+
+
+
+static void emit_decls( struct ureg_program *ureg )
+{
+ unsigned i;
+
+ for (i = 0; i < ureg->nr_inputs; i++) {
+ emit_decl( ureg,
+ TGSI_FILE_INPUT,
+ i,
+ ureg->input[i].semantic_name,
+ ureg->input[i].semantic_index,
+ ureg->input[i].interp );
+ }
+
+ for (i = 0; i < ureg->nr_outputs; i++) {
+ emit_decl( ureg,
+ TGSI_FILE_OUTPUT,
+ i,
+ ureg->output[i].semantic_name,
+ ureg->output[i].semantic_index,
+ TGSI_INTERPOLATE_CONSTANT );
+ }
+
+ for (i = 0; i < ureg->nr_samplers; i++) {
+ emit_decl_range( ureg,
+ TGSI_FILE_SAMPLER,
+ ureg->sampler[i].Index, 1 );
+ }
+
+ if (ureg->nr_constants) {
+ emit_decl_range( ureg,
+ TGSI_FILE_CONSTANT,
+ 0, ureg->nr_constants );
+ }
+
+ if (ureg->nr_temps) {
+ emit_decl_range( ureg,
+ TGSI_FILE_TEMPORARY,
+ 0, ureg->nr_temps );
+ }
+
+ if (ureg->nr_addrs) {
+ emit_decl_range( ureg,
+ TGSI_FILE_ADDRESS,
+ 0, ureg->nr_addrs );
+ }
+
+ for (i = 0; i < ureg->nr_immediates; i++) {
+ emit_immediate( ureg,
+ ureg->immediate[i].v );
+ }
+}
+
+/* Append the instruction tokens onto the declarations to build a
+ * contiguous stream suitable to send to the driver.
+ */
+static void copy_instructions( struct ureg_program *ureg )
+{
+ unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count;
+ union tgsi_any_token *out = get_tokens( ureg,
+ DOMAIN_DECL,
+ nr_tokens );
+
+ memcpy(out,
+ ureg->domain[DOMAIN_INSN].tokens,
+ nr_tokens * sizeof out[0] );
+}
+
+
+static void
+fixup_header_size(struct ureg_program *ureg)
+{
+ union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 1 );
+
+ out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 3;
+}
+
+
+static void
+emit_header( struct ureg_program *ureg )
+{
+ union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 );
+
+ out[0].version.MajorVersion = 1;
+ out[0].version.MinorVersion = 1;
+ out[0].version.Padding = 0;
+
+ out[1].header.HeaderSize = 2;
+ out[1].header.BodySize = 0;
+
+ out[2].processor.Processor = ureg->processor;
+ out[2].processor.Padding = 0;
+}
+
+
+const struct tgsi_token *ureg_finalize( struct ureg_program *ureg )
+{
+ const struct tgsi_token *tokens;
+
+ emit_header( ureg );
+ emit_decls( ureg );
+ copy_instructions( ureg );
+ fixup_header_size( ureg );
+
+ if (ureg->domain[0].tokens == error_tokens ||
+ ureg->domain[1].tokens == error_tokens) {
+ debug_printf("%s: error in generated shader\n", __FUNCTION__);
+ assert(0);
+ return NULL;
+ }
+
+ tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
+
+ if (0) {
+ debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__,
+ ureg->domain[DOMAIN_DECL].count);
+ tgsi_dump( tokens, 0 );
+ }
+
+ return tokens;
+}
+
+
+void *ureg_create_shader( struct ureg_program *ureg,
+ struct pipe_context *pipe )
+{
+ struct pipe_shader_state state;
+
+ state.tokens = ureg_finalize(ureg);
+ if(!state.tokens)
+ return NULL;
+
+ if (ureg->processor == TGSI_PROCESSOR_VERTEX)
+ return pipe->create_vs_state( pipe, &state );
+ else
+ return pipe->create_fs_state( pipe, &state );
+}
+
+
+
+
+struct ureg_program *ureg_create( unsigned processor )
+{
+ struct ureg_program *ureg = CALLOC_STRUCT( ureg_program );
+ if (ureg == NULL)
+ return NULL;
+
+ ureg->processor = processor;
+ return ureg;
+}
+
+
+void ureg_destroy( struct ureg_program *ureg )
+{
+ unsigned i;
+
+ for (i = 0; i < Elements(ureg->domain); i++) {
+ if (ureg->domain[i].tokens &&
+ ureg->domain[i].tokens != error_tokens)
+ FREE(ureg->domain[i].tokens);
+ }
+
+ FREE(ureg);
+}
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
new file mode 100644
index 0000000000..acbca59040
--- /dev/null
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h
@@ -0,0 +1,590 @@
+/**************************************************************************
+ *
+ * Copyright 2009 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * 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, sub license, 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE, INC AND/OR ITS SUPPLIERS 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.
+ *
+ **************************************************************************/
+
+#ifndef TGSI_UREG_H
+#define TGSI_UREG_H
+
+#include "pipe/p_compiler.h"
+#include "pipe/p_shader_tokens.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ureg_program;
+
+/* Almost a tgsi_src_register, but we need to pull in the Absolute
+ * flag from the _ext token. Indirect flag always implies ADDR[0].
+ */
+struct ureg_src
+{
+ unsigned File : 4; /* TGSI_FILE_ */
+ unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
+ unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
+ unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
+ unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
+ unsigned Pad : 1; /* BOOL */
+ unsigned Indirect : 1; /* BOOL */
+ unsigned Absolute : 1; /* BOOL */
+ int Index : 16; /* SINT */
+ unsigned Negate : 1; /* BOOL */
+ int IndirectIndex : 16; /* SINT */
+ int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
+};
+
+/* Very similar to a tgsi_dst_register, removing unsupported fields
+ * and adding a Saturate flag. It's easier to push saturate into the
+ * destination register than to try and create a _SAT varient of each
+ * instruction function.
+ */
+struct ureg_dst
+{
+ unsigned File : 4; /* TGSI_FILE_ */
+ unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
+ unsigned Indirect : 1; /* BOOL */
+ unsigned Saturate : 1; /* BOOL */
+ int Index : 16; /* SINT */
+ unsigned Pad1 : 5;
+ unsigned Pad2 : 1; /* BOOL */
+ int IndirectIndex : 16; /* SINT */
+ int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
+};
+
+struct pipe_context;
+
+struct ureg_program *
+ureg_create( unsigned processor );
+
+const struct tgsi_token *
+ureg_finalize( struct ureg_program * );
+
+void *
+ureg_create_shader( struct ureg_program *,
+ struct pipe_context *pipe );
+
+void
+ureg_destroy( struct ureg_program * );
+
+
+/***********************************************************************
+ * Convenience routine:
+ */
+static INLINE void *
+ureg_create_shader_and_destroy( struct ureg_program *p,
+ struct pipe_context *pipe )
+{
+ void *result = ureg_create_shader( p, pipe );
+ ureg_destroy( p );
+ return result;
+}
+
+
+
+/***********************************************************************
+ * Build shader declarations:
+ */
+
+struct ureg_src
+ureg_DECL_fs_input( struct ureg_program *,
+ unsigned semantic_name,
+ unsigned semantic_index,
+ unsigned interp_mode );
+
+struct ureg_src
+ureg_DECL_vs_input( struct ureg_program *,
+ unsigned semantic_name,
+ unsigned semantic_index );
+
+struct ureg_dst
+ureg_DECL_output( struct ureg_program *,
+ unsigned semantic_name,
+ unsigned semantic_index );
+
+struct ureg_src
+ureg_DECL_immediate( struct ureg_program *,
+ const float *v,
+ unsigned nr );
+
+struct ureg_src
+ureg_DECL_constant( struct ureg_program * );
+
+struct ureg_dst
+ureg_DECL_temporary( struct ureg_program * );
+
+void
+ureg_release_temporary( struct ureg_program *ureg,
+ struct ureg_dst tmp );
+
+struct ureg_dst
+ureg_DECL_address( struct ureg_program * );
+
+/* Supply an index to the sampler declaration as this is the hook to
+ * the external pipe_sampler state. Users of this function probably
+ * don't want just any sampler, but a specific one which they've set
+ * up state for in the context.
+ */
+struct ureg_src
+ureg_DECL_sampler( struct ureg_program *,
+ unsigned index );
+
+
+static INLINE struct ureg_src
+ureg_imm4f( struct ureg_program *ureg,
+ float a, float b,
+ float c, float d)
+{
+ float v[4];
+ v[0] = a;
+ v[1] = b;
+ v[2] = c;
+ v[3] = d;
+ return ureg_DECL_immediate( ureg, v, 4 );
+}
+
+static INLINE struct ureg_src
+ureg_imm3f( struct ureg_program *ureg,
+ float a, float b,
+ float c)
+{
+ float v[3];
+ v[0] = a;
+ v[1] = b;
+ v[2] = c;
+ return ureg_DECL_immediate( ureg, v, 3 );
+}
+
+static INLINE struct ureg_src
+ureg_imm2f( struct ureg_program *ureg,
+ float a, float b)
+{
+ float v[2];
+ v[0] = a;
+ v[1] = b;
+ return ureg_DECL_immediate( ureg, v, 2 );
+}
+
+static INLINE struct ureg_src
+ureg_imm1f( struct ureg_program *ureg,
+ float a)
+{
+ float v[1];
+ v[0] = a;
+ return ureg_DECL_immediate( ureg, v, 1 );
+}
+
+/***********************************************************************
+ * Functions for patching up labels
+ */
+
+
+/* Will return a number which can be used in a label to point to the
+ * next instruction to be emitted.
+ */
+unsigned
+ureg_get_instruction_number( struct ureg_program *ureg );
+
+
+/* Patch a given label (expressed as a token number) to point to a
+ * given instruction (expressed as an instruction number).
+ *
+ * Labels are obtained from instruction emitters, eg ureg_CAL().
+ * Instruction numbers are obtained from ureg_get_instruction_number(),
+ * above.
+ */
+void
+ureg_fixup_label(struct ureg_program *ureg,
+ unsigned label_token,
+ unsigned instruction_number );
+
+
+/* Generic instruction emitter. Use if you need to pass the opcode as
+ * a parameter, rather than using the emit_OP() varients below.
+ */
+void
+ureg_insn(struct ureg_program *ureg,
+ unsigned opcode,
+ const struct ureg_dst *dst,
+ unsigned nr_dst,
+ const struct ureg_src *src,
+ unsigned nr_src );
+
+
+/***********************************************************************
+ * Internal instruction helpers, don't call these directly:
+ */
+
+unsigned
+ureg_emit_insn(struct ureg_program *ureg,
+ unsigned opcode,
+ boolean saturate,
+ unsigned num_dst,
+ unsigned num_src );
+
+void
+ureg_emit_label(struct ureg_program *ureg,
+ unsigned insn_token,
+ unsigned *label_token );
+
+void
+ureg_emit_texture(struct ureg_program *ureg,
+ unsigned insn_token,
+ unsigned target );
+
+void
+ureg_emit_dst( struct ureg_program *ureg,
+ struct ureg_dst dst );
+
+void
+ureg_emit_src( struct ureg_program *ureg,
+ struct ureg_src src );
+
+void
+ureg_fixup_insn_size(struct ureg_program *ureg,
+ unsigned insn );
+
+
+#define OP00( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP01( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_src src ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
+ ureg_emit_src( ureg, src ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP00_LBL( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ unsigned *label_token ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \
+ ureg_emit_label( ureg, insn, label_token ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP01_LBL( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_src src, \
+ unsigned *label_token ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \
+ ureg_emit_label( ureg, insn, label_token ); \
+ ureg_emit_src( ureg, src ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP10( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+
+#define OP11( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst, \
+ struct ureg_src src ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_emit_src( ureg, src ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP12( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst, \
+ struct ureg_src src0, \
+ struct ureg_src src1 ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_emit_src( ureg, src0 ); \
+ ureg_emit_src( ureg, src1 ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP12_TEX( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst, \
+ unsigned target, \
+ struct ureg_src src0, \
+ struct ureg_src src1 ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \
+ ureg_emit_texture( ureg, insn, target ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_emit_src( ureg, src0 ); \
+ ureg_emit_src( ureg, src1 ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP13( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst, \
+ struct ureg_src src0, \
+ struct ureg_src src1, \
+ struct ureg_src src2 ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_emit_src( ureg, src0 ); \
+ ureg_emit_src( ureg, src1 ); \
+ ureg_emit_src( ureg, src2 ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+#define OP14_TEX( op ) \
+static INLINE void ureg_##op( struct ureg_program *ureg, \
+ struct ureg_dst dst, \
+ unsigned target, \
+ struct ureg_src src0, \
+ struct ureg_src src1, \
+ struct ureg_src src2, \
+ struct ureg_src src3 ) \
+{ \
+ unsigned opcode = TGSI_OPCODE_##op; \
+ unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 4 ); \
+ ureg_emit_texture( ureg, insn, target ); \
+ ureg_emit_dst( ureg, dst ); \
+ ureg_emit_src( ureg, src0 ); \
+ ureg_emit_src( ureg, src1 ); \
+ ureg_emit_src( ureg, src2 ); \
+ ureg_emit_src( ureg, src3 ); \
+ ureg_fixup_insn_size( ureg, insn ); \
+}
+
+
+/* Use a template include to generate a correctly-typed ureg_OP()
+ * function for each TGSI opcode:
+ */
+#include "tgsi_opcode_tmp.h"
+
+
+/***********************************************************************
+ * Inline helpers for manipulating register structs:
+ */
+static INLINE struct ureg_src
+ureg_negate( struct ureg_src reg )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ reg.Negate ^= 1;
+ return reg;
+}
+
+static INLINE struct ureg_src
+ureg_abs( struct ureg_src reg )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ reg.Absolute = 1;
+ reg.Negate = 0;
+ return reg;
+}
+
+static INLINE struct ureg_src
+ureg_swizzle( struct ureg_src reg,
+ int x, int y, int z, int w )
+{
+ unsigned swz = ( (reg.SwizzleX << 0) |
+ (reg.SwizzleY << 2) |
+ (reg.SwizzleZ << 4) |
+ (reg.SwizzleW << 6));
+
+ assert(reg.File != TGSI_FILE_NULL);
+ assert(x < 4);
+ assert(y < 4);
+ assert(z < 4);
+ assert(w < 4);
+
+ reg.SwizzleX = (swz >> (x*2)) & 0x3;
+ reg.SwizzleY = (swz >> (y*2)) & 0x3;
+ reg.SwizzleZ = (swz >> (z*2)) & 0x3;
+ reg.SwizzleW = (swz >> (w*2)) & 0x3;
+ return reg;
+}
+
+static INLINE struct ureg_src
+ureg_scalar( struct ureg_src reg, int x )
+{
+ return ureg_swizzle(reg, x, x, x, x);
+}
+
+static INLINE struct ureg_dst
+ureg_writemask( struct ureg_dst reg,
+ unsigned writemask )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ reg.WriteMask &= writemask;
+ return reg;
+}
+
+static INLINE struct ureg_dst
+ureg_saturate( struct ureg_dst reg )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ reg.Saturate = 1;
+ return reg;
+}
+
+static INLINE struct ureg_dst
+ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ assert(addr.File == TGSI_FILE_ADDRESS);
+ reg.Indirect = 1;
+ reg.IndirectIndex = addr.Index;
+ reg.IndirectSwizzle = addr.SwizzleX;
+ return reg;
+}
+
+static INLINE struct ureg_src
+ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
+{
+ assert(reg.File != TGSI_FILE_NULL);
+ assert(addr.File == TGSI_FILE_ADDRESS);
+ reg.Indirect = 1;
+ reg.IndirectIndex = addr.Index;
+ reg.IndirectSwizzle = addr.SwizzleX;
+ return reg;
+}
+
+static INLINE struct ureg_dst
+ureg_dst( struct ureg_src src )
+{
+ struct ureg_dst dst;
+
+ dst.File = src.File;
+ dst.WriteMask = TGSI_WRITEMASK_XYZW;
+ dst.Indirect = src.Indirect;
+ dst.IndirectIndex = src.IndirectIndex;
+ dst.IndirectSwizzle = src.IndirectSwizzle;
+ dst.Saturate = 0;
+ dst.Index = src.Index;
+ dst.Pad1 = 0;
+ dst.Pad2 = 0;
+
+ return dst;
+}
+
+static INLINE struct ureg_src
+ureg_src( struct ureg_dst dst )
+{
+ struct ureg_src src;
+
+ src.File = dst.File;
+ src.SwizzleX = TGSI_SWIZZLE_X;
+ src.SwizzleY = TGSI_SWIZZLE_Y;
+ src.SwizzleZ = TGSI_SWIZZLE_Z;
+ src.SwizzleW = TGSI_SWIZZLE_W;
+ src.Pad = 0;
+ src.Indirect = dst.Indirect;
+ src.IndirectIndex = dst.IndirectIndex;
+ src.IndirectSwizzle = dst.IndirectSwizzle;
+ src.Absolute = 0;
+ src.Index = dst.Index;
+ src.Negate = 0;
+
+ return src;
+}
+
+
+
+static INLINE struct ureg_dst
+ureg_dst_undef( void )
+{
+ struct ureg_dst dst;
+
+ dst.File = TGSI_FILE_NULL;
+ dst.WriteMask = 0;
+ dst.Indirect = 0;
+ dst.IndirectIndex = 0;
+ dst.IndirectSwizzle = 0;
+ dst.Saturate = 0;
+ dst.Index = 0;
+ dst.Pad1 = 0;
+ dst.Pad2 = 0;
+
+ return dst;
+}
+
+static INLINE struct ureg_src
+ureg_src_undef( void )
+{
+ struct ureg_src src;
+
+ src.File = TGSI_FILE_NULL;
+ src.SwizzleX = 0;
+ src.SwizzleY = 0;
+ src.SwizzleZ = 0;
+ src.SwizzleW = 0;
+ src.Pad = 0;
+ src.Indirect = 0;
+ src.IndirectIndex = 0;
+ src.IndirectSwizzle = 0;
+ src.Absolute = 0;
+ src.Index = 0;
+ src.Negate = 0;
+
+ return src;
+}
+
+static INLINE boolean
+ureg_src_is_undef( struct ureg_src src )
+{
+ return src.File == TGSI_FILE_NULL;
+}
+
+static INLINE boolean
+ureg_dst_is_undef( struct ureg_dst dst )
+{
+ return dst.File == TGSI_FILE_NULL;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.h b/src/gallium/auxiliary/tgsi/tgsi_util.h
index 7877f34558..21eb656327 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_util.h
+++ b/src/gallium/auxiliary/tgsi/tgsi_util.h
@@ -32,6 +32,10 @@
extern "C" {
#endif
+struct tgsi_src_register;
+struct tgsi_src_register_ext_swz;
+struct tgsi_full_src_register;
+
void *
tgsi_align_128bit(
void *unaligned );