nv50: fixes + untested _SAT modifier
authorBen Skeggs <skeggsb@gmail.com>
Sat, 7 Jun 2008 06:01:06 +0000 (16:01 +1000)
committerBen Skeggs <skeggsb@gmail.com>
Sun, 29 Jun 2008 05:46:15 +0000 (15:46 +1000)
src/gallium/drivers/nv50/nv50_program.c

index cad1d9d679571ce66da0175d1d5060de8d10a3b3..9fcd7c36c61d426db84b172de73920206bfaf8b1 100644 (file)
@@ -15,7 +15,6 @@
 /* ARL
  * LIT - other buggery
  * POW
- * SAT
  *
  * MSB - Like MAD, but MUL+SUB
  *     - Fuck it off, introduce a way to negate args for ops that
@@ -679,8 +678,8 @@ emit_flr(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src)
 {
        unsigned inst[2] = { 0, 0 };
 
-       set_long(pc, inst);
        inst[0] = 0xa0000000; /* cvt */
+       set_long(pc, inst);
        inst[1] |= (6 << 29); /* cvt */
        inst[1] |= 0x08000000; /* integer mode */
        inst[1] |= 0x04000000; /* 32 bit */
@@ -696,13 +695,14 @@ static boolean
 nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
 {
        const struct tgsi_full_instruction *inst = &tok->FullInstruction;
-       struct nv50_reg *dst[4], *src[3][4], *temp;
-       unsigned mask;
+       struct nv50_reg *rdst[4], *dst[4], *src[3][4], *temp;
+       unsigned mask, sat;
        int i, c;
 
        NOUVEAU_ERR("insn %p\n", tok);
 
        mask = inst->FullDstRegisters[0].DstRegister.WriteMask;
+       sat = inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE;
 
        for (c = 0; c < 4; c++) {
                if (mask & (1 << c))
@@ -716,13 +716,20 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
                        src[i][c] = tgsi_src(pc, c, &inst->FullSrcRegisters[i]);
        }
 
+       if (sat) {
+               for (c = 0; c < 4; c++) {
+                       rdst[c] = dst[c];
+                       dst[c] = temp_temp(pc);
+               }
+       }
+
        switch (inst->Instruction.Opcode) {
        case TGSI_OPCODE_ABS:
                for (c = 0; c < 4; c++) {
                        unsigned inst[2] = { 0, 0 };
 
-                       set_long(pc, inst);
                        inst[0] = 0xa0000000; /* cvt */
+                       set_long(pc, inst);
                        inst[1] |= (6 << 29); /* cvt */
                        inst[1] |= 0x04000000; /* 32 bit */
                        inst[1] |= (1 << 14); /* src .f32 */
@@ -922,6 +929,25 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok)
                return FALSE;
        }
 
+       if (sat) {
+               for (c = 0; c < 4; c++) {
+                       unsigned inst[2] = { 0, 0 };
+
+                       if (!(mask & (1 << c)))
+                               continue;
+
+                       inst[0] = 0xa0000000; /* cvt */
+                       set_long(pc, inst);
+                       inst[1] |= (6 << 29); /* cvt */
+                       inst[1] |= 0x04000000; /* 32 bit */
+                       inst[1] |= (1 << 14); /* src .f32 */
+                       inst[1] |= ((1 << 5) << 14); /* .sat */
+                       set_dst(pc, rdst[c], inst);
+                       set_src_0(pc, dst[c], inst);
+                       emit(pc, inst);
+               }
+       }
+
        kill_temp_temp(pc);
        return TRUE;
 }