summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2010-09-13 00:59:38 +0200
committerChristoph Bumiller <[email protected]>2010-09-13 17:26:41 +0200
commit0b8170103c8eaff46b75e89608198b3eb564bc52 (patch)
tree363b7d151dd5f5175e4448809c9b3d27ba2f324f
parent3b3c20744f2ea90f6aaae33b337bdc5e135f3198 (diff)
nv50: fix indirect CONST access with large or negative offsets
-rw-r--r--src/gallium/drivers/nv50/nv50_pc_emit.c6
-rw-r--r--src/gallium/drivers/nv50/nv50_tgsi_to_nc.c9
2 files changed, 12 insertions, 3 deletions
diff --git a/src/gallium/drivers/nv50/nv50_pc_emit.c b/src/gallium/drivers/nv50/nv50_pc_emit.c
index 8c64b198756..1eb44741f16 100644
--- a/src/gallium/drivers/nv50/nv50_pc_emit.c
+++ b/src/gallium/drivers/nv50/nv50_pc_emit.c
@@ -696,7 +696,9 @@ emit_add_b32(struct nv_pc *pc, struct nv_instruction *i)
static void
emit_add_a16(struct nv_pc *pc, struct nv_instruction *i)
{
- pc->emit[0] = 0xd0000001 | (get_immd_u32(i->src[0]) << 9);
+ int s = (i->opcode == NV_OP_MOV) ? 0 : 1;
+
+ pc->emit[0] = 0xd0000001 | ((uint16_t)get_immd_u32(i->src[s]) << 9);
pc->emit[1] = 0x20000000;
pc->emit[0] |= (DREG(i->def[0])->id + 1) << 2;
@@ -704,7 +706,7 @@ emit_add_a16(struct nv_pc *pc, struct nv_instruction *i)
set_pred(pc, i);
if (i->src[1])
- set_a16_bits(pc, SREG(i->src[1])->id);
+ set_a16_bits(pc, SREG(i->src[1])->id + 1);
}
static void
diff --git a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
index 54d6fb960f8..a2b6901c81e 100644
--- a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
+++ b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
@@ -665,6 +665,7 @@ bld_get_address(struct bld_context *bld, int id, struct nv_value *indirect)
{
int i;
struct nv_instruction *nvi;
+ struct nv_value *val;
for (i = 0; i < 4; ++i) {
if (!bld->saved_addr[i][0])
@@ -677,7 +678,13 @@ bld_get_address(struct bld_context *bld, int id, struct nv_value *indirect)
}
i &= 3;
- bld->saved_addr[i][0] = bld_load_imm_u32(bld, id);
+ val = bld_imm_u32(bld, id);
+ if (indirect)
+ val = bld_insn_2(bld, NV_OP_ADD, indirect, val);
+ else
+ val = bld_insn_1(bld, NV_OP_MOV, val);
+
+ bld->saved_addr[i][0] = val;
bld->saved_addr[i][0]->reg.file = NV_FILE_ADDR;
bld->saved_addr[i][0]->reg.type = NV_TYPE_U16;
bld->saved_addr[i][1] = indirect;