tgsi: fix SSE code emit for XPD
Rearrange things so that the writes to the dest registers happen
after we've fetched/used all src registers.
The problematic instruction was: XPD TEMP[2].xyz, TEMP[0], TEMP[2];
Note that the dst reg is also a src reg.
This fixes bad shading with progs/glsl/bump.c since Eric's changes to the
Mesa program optimizer in commit d6690ce15f.
The optimizer rearranges some registers so we occasionally wind up with
something like the above.
This commit is contained in:
@@ -2142,40 +2142,50 @@ emit_instruction(
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_XPD:
|
||||
/* Note: we do all stores after all operands have been fetched
|
||||
* to avoid src/dst register aliasing issues for an instruction
|
||||
* such as: XPD TEMP[2].xyz, TEMP[0], TEMP[2];
|
||||
*/
|
||||
if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
|
||||
IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ) {
|
||||
FETCH( func, *inst, 1, 1, CHAN_Z );
|
||||
FETCH( func, *inst, 3, 0, CHAN_Z );
|
||||
FETCH( func, *inst, 1, 1, CHAN_Z ); /* xmm[1] = src[1].z */
|
||||
FETCH( func, *inst, 3, 0, CHAN_Z ); /* xmm[3] = src[0].z */
|
||||
}
|
||||
if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) ||
|
||||
IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
|
||||
FETCH( func, *inst, 0, 0, CHAN_Y );
|
||||
FETCH( func, *inst, 4, 1, CHAN_Y );
|
||||
FETCH( func, *inst, 0, 0, CHAN_Y ); /* xmm[0] = src[0].y */
|
||||
FETCH( func, *inst, 4, 1, CHAN_Y ); /* xmm[4] = src[1].y */
|
||||
}
|
||||
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) {
|
||||
emit_MOV( func, 2, 0 );
|
||||
emit_mul( func, 2, 1 );
|
||||
emit_MOV( func, 5, 3 );
|
||||
emit_mul( func, 5, 4 );
|
||||
emit_sub( func, 2, 5 );
|
||||
STORE( func, *inst, 2, 0, CHAN_X );
|
||||
emit_MOV( func, 7, 0 ); /* xmm[7] = xmm[0] */
|
||||
emit_mul( func, 7, 1 ); /* xmm[7] = xmm[2] * xmm[1] */
|
||||
emit_MOV( func, 5, 3 ); /* xmm[5] = xmm[3] */
|
||||
emit_mul( func, 5, 4 ); /* xmm[5] = xmm[5] * xmm[4] */
|
||||
emit_sub( func, 7, 5 ); /* xmm[7] = xmm[2] - xmm[5] */
|
||||
/* store xmm[7] in dst.x below */
|
||||
}
|
||||
if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ||
|
||||
IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) ) {
|
||||
FETCH( func, *inst, 2, 1, CHAN_X );
|
||||
FETCH( func, *inst, 5, 0, CHAN_X );
|
||||
FETCH( func, *inst, 2, 1, CHAN_X ); /* xmm[2] = src[1].x */
|
||||
FETCH( func, *inst, 5, 0, CHAN_X ); /* xmm[5] = src[0].x */
|
||||
}
|
||||
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) {
|
||||
emit_mul( func, 3, 2 );
|
||||
emit_mul( func, 1, 5 );
|
||||
emit_sub( func, 3, 1 );
|
||||
STORE( func, *inst, 3, 0, CHAN_Y );
|
||||
emit_mul( func, 3, 2 ); /* xmm[3] = xmm[3] * xmm[2] */
|
||||
emit_mul( func, 1, 5 ); /* xmm[1] = xmm[1] * xmm[5] */
|
||||
emit_sub( func, 3, 1 ); /* xmm[3] = xmm[3] - xmm[1] */
|
||||
/* store xmm[3] in dst.y below */
|
||||
}
|
||||
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) {
|
||||
emit_mul( func, 5, 4 );
|
||||
emit_mul( func, 0, 2 );
|
||||
emit_sub( func, 5, 0 );
|
||||
STORE( func, *inst, 5, 0, CHAN_Z );
|
||||
emit_mul( func, 5, 4 ); /* xmm[5] = xmm[5] * xmm[4] */
|
||||
emit_mul( func, 0, 2 ); /* xmm[0] = xmm[0] * xmm[2] */
|
||||
emit_sub( func, 5, 0 ); /* xmm[5] = xmm[5] - xmm[0] */
|
||||
STORE( func, *inst, 5, 0, CHAN_Z ); /* dst.z = xmm[5] */
|
||||
}
|
||||
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) {
|
||||
STORE( func, *inst, 7, 0, CHAN_X ); /* dst.x = xmm[7] */
|
||||
}
|
||||
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) {
|
||||
STORE( func, *inst, 3, 0, CHAN_Y ); /* dst.y = xmm[3] */
|
||||
}
|
||||
IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W ) {
|
||||
emit_tempf(
|
||||
|
||||
Reference in New Issue
Block a user