diff options
author | Christoph Bumiller <[email protected]> | 2009-10-13 15:09:13 +0200 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2009-10-19 18:25:09 +0200 |
commit | f204eb184237b387432413212a3a20d83c87594b (patch) | |
tree | 80e406d038b715998bbc6060ba479ad5ec9015a5 /src/gallium/drivers | |
parent | 1635e8d6f4b96e691746e8c8c5a273089bae6843 (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')
-rw-r--r-- | src/gallium/drivers/nv50/nv50_program.c | 25 |
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]); } |