summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv50
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2009-10-13 15:09:13 +0200
committerChristoph Bumiller <[email protected]>2009-10-19 18:25:09 +0200
commitf204eb184237b387432413212a3a20d83c87594b (patch)
tree80e406d038b715998bbc6060ba479ad5ec9015a5 /src/gallium/drivers/nv50
parent1635e8d6f4b96e691746e8c8c5a273089bae6843 (diff)
nv50: quick fix for insn src negation
We only have a per nv50_reg negation flag, if an nv50_reg is used more than once in a TGSI op with different sign modes, we'd generate wrong code. We probably can't do much better without more invasive changes.
Diffstat (limited to 'src/gallium/drivers/nv50')
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 89e0ac8db9f..1bd6f717d10 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -1293,9 +1293,12 @@ convert_to_long(struct nv50_pc *pc, struct nv50_program_exec *e)
e->inst[1] |= q;
}
+/* Some operations support an optional negation flag. */
static boolean
negate_supported(const struct tgsi_full_instruction *insn, int i)
{
+ int s;
+
switch (insn->Instruction.Opcode) {
case TGSI_OPCODE_DDY:
case TGSI_OPCODE_DP3:
@@ -1305,12 +1308,29 @@ negate_supported(const struct tgsi_full_instruction *insn, int i)
case TGSI_OPCODE_ADD:
case TGSI_OPCODE_SUB:
case TGSI_OPCODE_MAD:
- return TRUE;
+ break;
case TGSI_OPCODE_POW:
- return (i == 1) ? TRUE : FALSE;
+ if (i == 1)
+ break;
+ return FALSE;
default:
return FALSE;
}
+
+ /* Watch out for possible multiple uses of an nv50_reg, we
+ * can't use nv50_reg::neg in these cases.
+ */
+ for (s = 0; s < insn->Instruction.NumSrcRegs; ++s) {
+ if (s == i)
+ continue;
+ if ((insn->FullSrcRegisters[s].SrcRegister.Index ==
+ insn->FullSrcRegisters[i].SrcRegister.Index) &&
+ (insn->FullSrcRegisters[s].SrcRegister.File ==
+ insn->FullSrcRegisters[i].SrcRegister.File))
+ return FALSE;
+ }
+
+ return TRUE;
}
/* Return a read mask for source registers deduced from opcode & write mask. */
@@ -1956,6 +1976,7 @@ nv50_program_tx_insn(struct nv50_pc *pc,
for (c = 0; c < 4; c++) {
if (!src[i][c])
continue;
+ src[i][c]->neg = 0;
if (src[i][c]->index == -1 && src[i][c]->type == P_IMMD)
FREE(src[i][c]);
}