return get_output_base();
}
+static struct x86_reg
+get_immediate_base( void )
+{
+ return x86_make_reg(
+ file_REG32,
+ reg_DI );
+}
+
+
/**
* Data access helpers.
*/
(index + 1) * 4 );
}
+static struct x86_reg
+get_immediate(
+ unsigned vec,
+ unsigned chan )
+{
+ return x86_make_disp(
+ get_immediate_base(),
+ (vec * 4 + chan) * 4 );
+}
+
static struct x86_reg
get_const(
unsigned vec,
SHUF( 0, 0, 0, 0 ) );
}
+static void
+emit_immediate(
+ struct x86_function *func,
+ unsigned xmm,
+ unsigned vec,
+ unsigned chan )
+{
+ emit_movss(
+ func,
+ make_xmm( xmm ),
+ get_immediate( vec, chan ) );
+ emit_shufps(
+ func,
+ make_xmm( xmm ),
+ make_xmm( xmm ),
+ SHUF( 0, 0, 0, 0 ) );
+}
+
+
/**
* Copy a shader input to xmm register
* \param xmm the destination xmm register
swizzle );
break;
+ case TGSI_FILE_IMMEDIATE:
+ emit_immediate(
+ func,
+ xmm,
+ reg->SrcRegister.Index,
+ swizzle );
+ break;
+
case TGSI_FILE_INPUT:
emit_inputf(
func,
* 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
*/
unsigned
tgsi_emit_sse2_fs(
struct tgsi_token *tokens,
- struct x86_function *func )
+ struct x86_function *func,
+ float (*immediates)[4])
{
struct tgsi_parse_context parse;
boolean instruction_phase = FALSE;
unsigned ok = 1;
+ uint num_immediates = 0;
DUMP_START();
func,
get_input_base(),
get_argument( 0 ) );
+ /* skipping outputs argument here */
emit_mov(
func,
get_const_base(),
func,
get_coef_base(),
get_argument( 4 ) );
+ emit_mov(
+ func,
+ get_immediate_base(),
+ get_argument( 5 ) );
tgsi_parse_init( &parse, tokens );
break;
case TGSI_TOKEN_TYPE_IMMEDIATE:
- /* XXX implement this */
- ok = 0;
- debug_printf("failed to emit immediate value to SSE\n");
+ /* simply copy the immediate values into the next immediates[] slot */
+ {
+ const uint size = parse.FullToken.FullImmediate.Immediate.Size - 1;
+ uint i;
+ assert(size <= 4);
+ assert(num_immediates < TGSI_EXEC_NUM_IMMEDIATES);
+ for( i = 0; i < size; i++ ) {
+ immediates[num_immediates][i] =
+ parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
+ }
+#if 0
+ debug_printf("SSE FS immediate[%d] = %f %f %f %f\n",
+ num_immediates,
+ immediates[num_immediates][0],
+ immediates[num_immediates][1],
+ immediates[num_immediates][2],
+ immediates[num_immediates][3]);
+#endif
+ num_immediates++;
+ }
break;
default:
struct tgsi_exec_vector *output,
float (*constant)[4],
struct tgsi_exec_vector *temporary,
- const struct tgsi_interp_coef *coef
+ const struct tgsi_interp_coef *coef,
+ float (*immediates)[4]
//, const struct tgsi_exec_vector *quadPos
);
struct sp_fragment_shader base;
struct x86_function sse2_program;
codegen_function func;
+ float immediates[TGSI_EXEC_NUM_IMMEDIATES][4];
};
machine->Outputs,
machine->Consts,
machine->Temps,
- machine->InterpCoefs
+ machine->InterpCoefs,
+ shader->immediates
// , &machine->QuadPos
);
x86_init_func( &shader->sse2_program );
- if (!tgsi_emit_sse2_fs( templ->tokens, &shader->sse2_program )) {
+ if (!tgsi_emit_sse2_fs( templ->tokens, &shader->sse2_program,
+ shader->immediates)) {
FREE(shader);
return NULL;
}