summaryrefslogtreecommitdiff
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2008-06-07 16:08:36 +1000
committerBen Skeggs <skeggsb@gmail.com>2008-06-29 15:46:15 +1000
commitea4b09cbcbd9db82648ab30f18c0f46a66ab9f69 (patch)
tree8d885b3e40250cd0404ed12e3b98648db7bb83db /src/gallium/drivers
parent688064236ba8b5997014493eb6c6e3fe0739813e (diff)
nv50: POW!
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 9fcd7c36c6..79893a9ad4 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -14,15 +14,17 @@
/* ARL
* LIT - other buggery
- * POW
*
* MSB - Like MAD, but MUL+SUB
* - Fuck it off, introduce a way to negate args for ops that
* support it.
*
- * Look into inlining IMMD for ops other than MOV
+ * Look into inlining IMMD for ops other than MOV (make it general?)
* - Maybe even relax restrictions a bit, can't do P_RESULT + P_IMMD,
* but can emit to P_TEMP first - then MOV later. NVIDIA does this
+ *
+ * Verify half-insns work where expected - and force disable them where they
+ * don't work - MUL has it forcibly disabled atm as it fixes POW..
*/
struct nv50_reg {
enum {
@@ -489,6 +491,7 @@ emit_mul(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
unsigned inst[2] = { 0, 0 };
inst[0] |= 0xc0000000;
+ set_long(pc, inst);
check_swap_src_0_1(pc, &src0, &src1);
set_dst(pc, dst, inst);
@@ -870,6 +873,19 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
emit_mul(pc, dst[c], src[0][c], src[1][c]);
}
break;
+ case TGSI_OPCODE_POW:
+ temp = alloc_temp(pc, NULL);
+ emit_flop(pc, 3, temp, src[0][0]);
+ emit_mul(pc, temp, temp, src[1][0]);
+ emit_preex2(pc, temp, temp);
+ emit_flop(pc, 6, temp, temp);
+ for (c = 0; c < 4; c++) {
+ if (!(mask & (1 << c)))
+ continue;
+ emit_mov(pc, dst[c], temp);
+ }
+ free_temp(pc, temp);
+ break;
case TGSI_OPCODE_RCP:
for (c = 0; c < 4; c++) {
if (!(mask & (1 << c)))