nv50: DPH, XPD, some TODOs
authorBen Skeggs <skeggsb@gmail.com>
Thu, 5 Jun 2008 13:48:23 +0000 (23:48 +1000)
committerBen Skeggs <skeggsb@gmail.com>
Sun, 29 Jun 2008 05:46:14 +0000 (15:46 +1000)
src/gallium/drivers/nv50/nv50_program.c

index 6d3d8ff302b8c59c51f055b91545930c75df6ef6..91f24369f1405a3b424562038c77b0d4a7c7e4e3 100644 (file)
 
 #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,
@@ -512,6 +531,25 @@ emit_mad(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0,
        emit(pc, inst);
 }
 
+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: