summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2008-06-05 23:48:23 +1000
committerBen Skeggs <[email protected]>2008-06-29 15:46:14 +1000
commit21e18e2b74d71c93af06ef4c603ca371c4614237 (patch)
tree4e67bb7f871252ff44d3ccfcc1221bfdc7156ee1
parentfbf4027dd9b279ec159906dcad134f71e34aaec8 (diff)
nv50: DPH, XPD, some TODOs
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 6d3d8ff302b..91f24369f14 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -12,6 +12,25 @@
#define NV50_SU_MAX_TEMP 64
+/* ABS
+ * ARL
+ * DST - const(1.0)
+ * FLR
+ * FRC
+ * LIT
+ * POW
+ * SGE - cvt
+ * SLT - cvt
+ * SWZ
+ *
+ * MSB - Like MAD, but MUL+SUB
+ * - Fuck it off, introduce a way to negate args for ops that
+ * support it.
+ *
+ * Need ability to specifiy driver IMMD values, like nv40 constant()
+ *
+ * Look into inlining IMMD for ops other than MOV
+ */
struct nv50_reg {
enum {
P_TEMP,
@@ -513,6 +532,25 @@ emit_mad(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
}
static void
+emit_msb(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
+ struct nv50_reg *src1, struct nv50_reg *src2)
+{
+ unsigned inst[2] = { 0, 0 };
+
+ inst[0] |= 0xe0000000;
+ set_long(pc, inst);
+ inst[1] |= 0x08000000; /* src0 * src1 - src2 */
+
+ check_swap_src_0_1(pc, &src0, &src1);
+ set_dst(pc, dst, inst);
+ set_src_0(pc, src0, inst);
+ set_src_1(pc, src1, inst);
+ set_src_2(pc, src2, inst);
+
+ emit(pc, inst);
+}
+
+static void
emit_flop(struct nv50_pc *pc, unsigned sub,
struct nv50_reg *dst, struct nv50_reg *src)
{
@@ -594,6 +632,19 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
}
free_temp(pc, temp);
break;
+ case TGSI_OPCODE_DPH:
+ temp = alloc_temp(pc, NULL);
+ emit_mul(pc, temp, src[0][0], src[1][0]);
+ emit_mad(pc, temp, src[0][1], src[1][1], temp);
+ emit_mad(pc, temp, src[0][2], src[1][2], temp);
+ emit_add(pc, temp, src[1][3], 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_EX2:
temp = alloc_temp(pc, NULL);
for (c = 0; c < 4; c++) {
@@ -682,6 +733,16 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
emit_sub(pc, dst[c], src[0][c], src[1][c]);
}
break;
+ case TGSI_OPCODE_XPD:
+ temp = alloc_temp(pc, NULL);
+ emit_mul(pc, temp, src[0][2], src[1][1]);
+ emit_msb(pc, dst[0], src[0][1], src[1][2], temp);
+ emit_mul(pc, temp, src[0][0], src[1][2]);
+ emit_msb(pc, dst[1], src[0][2], src[1][0], temp);
+ emit_mul(pc, temp, src[0][1], src[1][0]);
+ emit_msb(pc, dst[2], src[0][0], src[1][1], temp);
+ free_temp(pc, temp);
+ break;
case TGSI_OPCODE_END:
break;
default: