diff options
author | Christoph Bumiller <[email protected]> | 2009-10-23 22:17:44 +0200 |
---|---|---|
committer | Christoph Bumiller <[email protected]> | 2009-10-23 22:17:44 +0200 |
commit | c738c9ab67859f3d4412417333d0f023dd18dc19 (patch) | |
tree | 6f3feb4d744ec8749b6a24e3dd7c6e9491d496ab /src/gallium/drivers/nv50/nv50_program.c | |
parent | 255a90a7bd829904554889dd19a16d86fc7f9274 (diff) |
nv50: fix address reg code
Contained some rather obvious thinking errors before,
and didn't consider offsets from TGSI ADDRESS regs.
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_program.c')
-rw-r--r-- | src/gallium/drivers/nv50/nv50_program.c | 67 |
1 files changed, 44 insertions, 23 deletions
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 5c691877e04..ff6ff578f45 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -32,9 +32,11 @@ #include "nv50_context.h" #define NV50_SU_MAX_TEMP 64 -#define NV50_SU_MAX_ADDR 7 +#define NV50_SU_MAX_ADDR 4 //#define NV50_PROGRAM_DUMP +/* $a5 and $a6 always seem to be 0, and using $a7 gives you noise */ + /* ARL - gallium craps itself on progs/vp/arl.txt * * MSB - Like MAD, but MUL+SUB @@ -470,16 +472,28 @@ set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e) e->inst[1] |= (val >> 6) << 2; } +static INLINE void +set_addr(struct nv50_program_exec *e, struct nv50_reg *a) +{ + assert(!(e->inst[0] & 0x0c000000)); + assert(!(e->inst[1] & 0x00000004)); + + e->inst[0] |= (a->hw & 3) << 26; + e->inst[1] |= (a->hw >> 2) << 2; +} + static void -emit_set_addr(struct nv50_pc *pc, struct nv50_reg *dst, unsigned val) +emit_add_addr_imm(struct nv50_pc *pc, struct nv50_reg *dst, + struct nv50_reg *src0, uint16_t src1_val) { struct nv50_program_exec *e = exec(pc); - assert(val <= 0xffff); - e->inst[0] = 0xd0000000 | ((val & 0xffff) << 9); + e->inst[0] = 0xd0000000 | (src1_val << 9); e->inst[1] = 0x20000000; - e->inst[0] |= dst->hw << 2; set_long(pc, e); + e->inst[0] |= dst->hw << 2; + if (src0) /* otherwise will add to $a0, which is always 0 */ + set_addr(e, src0); emit(pc, e); } @@ -488,9 +502,10 @@ static struct nv50_reg * alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref) { int i; - struct nv50_reg *a = NULL; + struct nv50_reg *a_tgsi = NULL, *a = NULL; if (!ref) { + /* allocate for TGSI address reg */ for (i = 0; i < NV50_SU_MAX_ADDR; ++i) { if (pc->r_addr[i].index >= 0) continue; @@ -506,6 +521,13 @@ alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref) return NULL; } + /* Allocate and set an address reg so we can access 'ref'. + * + * If and r_addr has index < 0, it is not reserved for TGSI, + * and index will be the negative of the TGSI addr index the + * value in rhw is relative to, or -256 if rhw is an offset + * from 0. If rhw < 0, the reg has not been initialized. + */ for (i = NV50_SU_MAX_ADDR - 1; i >= 0; --i) { if (pc->r_addr[i].index >= 0) /* occupied for TGSI */ continue; @@ -516,17 +538,25 @@ alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref) if (!a && pc->r_addr[i].acc != pc->insn_cur) a = &pc->r_addr[i]; - if (ref->hw - pc->r_addr[i].rhw < 128) { - /* alloc'd & suitable */ + if (ref->hw - pc->r_addr[i].rhw >= 128) + continue; + + if ((ref->acc >= 0 && pc->r_addr[i].index == -256) || + (ref->acc < 0 && -pc->r_addr[i].index == ref->index)) { pc->r_addr[i].acc = pc->insn_cur; return &pc->r_addr[i]; } } assert(a); - emit_set_addr(pc, a, ref->hw * 4); - a->rhw = ref->hw % 128; + if (ref->acc < 0) + a_tgsi = pc->addr[ref->index]; + + emit_add_addr_imm(pc, a, a_tgsi, (ref->hw & ~0x7f) * 4); + + a->rhw = ref->hw & ~0x7f; a->acc = pc->insn_cur; + a->index = a_tgsi ? -ref->index : -256; return a; } @@ -563,23 +593,13 @@ emit_interp(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *iv, emit(pc, e); } -static INLINE void -set_addr(struct nv50_program_exec *e, struct nv50_reg *a) -{ - assert(!(e->inst[0] & 0x0c000000)); - assert(!(e->inst[1] & 0x00000004)); - - e->inst[0] |= (a->hw & 3) << 26; - e->inst[1] |= (a->hw >> 2) << 2; -} - static void set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s, struct nv50_program_exec *e) { set_long(pc, e); - e->param.index = src->hw; + e->param.index = src->hw & 127; e->param.shift = s; e->param.mask = m << (s % 32); @@ -1569,7 +1589,8 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src, swz = tgsi_util_get_src_register_swizzle( &src->SrcRegisterInd, 0); ctor_reg(r, P_CONST, - src->SrcRegisterInd.Index * 4 + swz, c); + src->SrcRegisterInd.Index * 4 + swz, + src->SrcRegister.Index * 4 + c); r->acc = -1; break; case TGSI_FILE_IMMEDIATE: @@ -2743,7 +2764,7 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p) return FALSE; } for (i = 0; i < NV50_SU_MAX_ADDR; ++i) - ctor_reg(&pc->r_addr[i], P_ADDR, -1, i + 1); + ctor_reg(&pc->r_addr[i], P_ADDR, -256, i + 1); return TRUE; } |