summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>2009-12-02 19:59:07 +0100
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>2009-12-12 16:38:59 +0100
commitf7a97344924461d64bfa5bd1b6a2c1151b70cc7c (patch)
tree1cfb092e72caef3f24441b71507339502f34161c /src
parent6a15ec9141b070b088d03d87673d0d2741b7db6b (diff)
nv50: use copies of tgsi src nv50_regs
So we can use the 'mod' member without concern if a source is used multiple times in 1 insn.
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c48
1 files changed, 22 insertions, 26 deletions
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index f0fe7e6168..6116056857 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -131,6 +131,9 @@ struct nv50_pc {
struct nv50_reg *r_brdc;
struct nv50_reg *r_dst[4];
+ struct nv50_reg reg_instances[16];
+ unsigned reg_instance_nr;
+
unsigned interp_mode[32];
/* perspective interpolation registers */
struct nv50_reg *iv_p;
@@ -150,6 +153,19 @@ struct nv50_pc {
boolean allow32;
};
+static INLINE struct nv50_reg *
+reg_instance(struct nv50_pc *pc, struct nv50_reg *reg)
+{
+ struct nv50_reg *dup = NULL;
+ if (reg) {
+ assert(pc->reg_instance_nr < 16);
+ dup = &pc->reg_instances[pc->reg_instance_nr++];
+ *dup = *reg;
+ reg->mod = 0;
+ }
+ return dup;
+}
+
static INLINE void
ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw)
{
@@ -898,7 +914,6 @@ static INLINE void
emit_sub(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
struct nv50_reg *src1)
{
- assert(src0 != src1);
src1->mod ^= NV50_MOD_NEG;
emit_add(pc, dst, src0, src1);
src1->mod ^= NV50_MOD_NEG;
@@ -967,7 +982,6 @@ static INLINE void
emit_msb(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
struct nv50_reg *src1, struct nv50_reg *src2)
{
- assert(src2 != src0 && src2 != src1);
src2->mod ^= NV50_MOD_NEG;
emit_mad(pc, dst, src0, src1, src2);
src2->mod ^= NV50_MOD_NEG;
@@ -1515,8 +1529,6 @@ convert_to_long(struct nv50_pc *pc, struct nv50_program_exec *e)
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:
@@ -1526,29 +1538,14 @@ negate_supported(const struct tgsi_full_instruction *insn, int i)
case TGSI_OPCODE_ADD:
case TGSI_OPCODE_SUB:
case TGSI_OPCODE_MAD:
- break;
+ return TRUE;
case TGSI_OPCODE_POW:
if (i == 1)
- break;
+ return TRUE;
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->Src[s].Register.Index ==
- insn->Src[i].Register.Index) &&
- (insn->Src[s].Register.File ==
- insn->Src[i].Register.File))
- return FALSE;
- }
-
- return TRUE;
}
/* Return a read mask for source registers deduced from opcode & write mask. */
@@ -1882,7 +1879,8 @@ nv50_program_tx_insn(struct nv50_pc *pc,
for (c = 0; c < 4; c++)
if (src_mask & (1 << c))
- src[i][c] = tgsi_src(pc, c, fs, neg_supp);
+ src[i][c] = reg_instance(pc,
+ tgsi_src(pc, c, fs, neg_supp));
}
brdc = temp = pc->r_brdc;
@@ -2249,16 +2247,14 @@ nv50_program_tx_insn(struct nv50_pc *pc,
for (c = 0; c < 4; c++) {
if (!src[i][c])
continue;
- src[i][c]->mod = 0;
- if (src[i][c]->index == -1 && src[i][c]->type == P_IMMD)
- FREE(src[i][c]);
- else
if (src[i][c]->acc < 0 && src[i][c]->type == P_CONST)
FREE(src[i][c]); /* indirect constant */
}
}
kill_temp_temp(pc);
+ pc->reg_instance_nr = 0;
+
return TRUE;
}