commit 4411b1e3b3c11c69ec11148783327759a94165e2 Author: chr Date: Wed May 6 11:46:17 2009 +0200 Enable half insns and immediates for MOV and ADD. diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index e4fc261..2ab7b57 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -426,7 +426,7 @@ set_dst(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_program_exec *e) static INLINE void set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e) { - unsigned val = fui(pc->immd_buf[imm->hw]); /* XXX */ + unsigned val = fui(pc->immd_buf[imm->hw - pc->param_nr * 4]); set_long(pc, e); /*XXX: can't be predicated - bits overlap.. catch cases where both @@ -505,12 +505,11 @@ emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) set_dst(pc, dst, e); - if (0 && dst->type != P_RESULT && src->type == P_IMMD) { + if (pc->allow32 && dst->type != P_RESULT && src->type == P_IMMD) { set_immd(pc, src, e); /*XXX: 32-bit, but steals part of "half" reg space - need to * catch and handle this case if/when we do half-regs */ - e->inst[0] |= 0x00008000; } else if (src->type == P_IMMD || src->type == P_CONST) { set_long(pc, e); @@ -526,13 +525,15 @@ emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) e->inst[0] |= (src->hw << 9); } - /* We really should support "half" instructions here at some point, - * but I don't feel confident enough about them yet. - */ - set_long(pc, e); - if (is_long(e) && !is_immd(e)) { + if (!is_long(e) || is_immd(e)) + e->inst[0] |= 0x00008000; + else { e->inst[1] |= 0x04000000; /* 32-bit */ - e->inst[1] |= 0x0003c000; /* "subsubop" 0xf == mov */ + + /* XXX: look into this 0x3 or 0xf again */ + e->inst[1] |= 0x0000c000; /* "subsubop" 0x3 */ + if (!(e->inst[1] & 0x20000000)) + e->inst[1] |= 0x00030000; /* "subsubop" 0xf */ } emit(pc, e); @@ -606,6 +607,7 @@ set_src_1(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e) e->inst[0] |= (src->hw << 16); } +/* XXX: can source 2 really be a constant ? */ static void set_src_2(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e) { @@ -670,7 +672,10 @@ emit_add(struct nv50_pc *pc, struct nv50_reg *dst, check_swap_src_0_1(pc, &src0, &src1); set_dst(pc, dst, e); set_src_0(pc, src0, e); - if (is_long(e)) + if (!is_long(e) && src1->type == P_IMMD && pc->allow32) + set_immd(pc, src1, e); + else + if (requires_long(e, src1)) set_src_2(pc, src1, e); else set_src_1(pc, src1, e); @@ -902,6 +907,7 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask, struct nv50_reg *neg128 = alloc_immd(pc, -127.999999); struct nv50_reg *pos128 = alloc_immd(pc, 127.999999); struct nv50_reg *tmp[4]; + boolean allow32 = pc->allow32; if (mask & (3 << 1)) { if (mask & (1 << 1)) @@ -911,6 +917,8 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask, emit_minmax(pc, 4, tmp[0], src[0], zero); } + pc->allow32 = FALSE; + if (mask & (1 << 2)) { set_pred_wr(pc, 1, 0, pc->p->exec_tail); @@ -926,6 +934,8 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask, set_pred(pc, 3, 0, pc->p->exec_tail); } + pc->allow32 = allow32; + /* do this last, in case src[i,j] == dst[0,3] */ if (mask & (1 << 0)) emit_mov(pc, dst[0], one);