nv50: more TGSI opcodes (SIN, SCS, ARL, RET, KILP)
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Tue, 17 Aug 2010 09:51:51 +0000 (11:51 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Tue, 17 Aug 2010 11:08:52 +0000 (13:08 +0200)
src/gallium/drivers/nv50/nv50_pc_emit.c
src/gallium/drivers/nv50/nv50_pc_optimize.c
src/gallium/drivers/nv50/nv50_tgsi_to_nc.c

index 3a3b277c1398e91278d0540a95b6c387d6ce2406..b5f4383aa1a3f840c3c092f9e4a254793d12a221 100644 (file)
@@ -747,9 +747,31 @@ emit_bitop2(struct nv_pc *pc, struct nv_instruction *i)
    }
 }
 
+static void
+emit_arl(struct nv_pc *pc, struct nv_instruction *i)
+{
+   assert(SFILE(i, 0) == NV_FILE_GPR);
+   assert(SFILE(i, 1) == NV_FILE_IMM);
+
+   assert(!i->flags_def);
+
+   pc->emit[0] = 0x00000001;
+   pc->emit[1] = 0xc0000000;
+
+   set_dst(pc, i->def[0]);
+   set_pred(pc, i);
+   set_src_0(pc, i->src[0]);
+   pc->emit[0] |= (get_immd_u32(i->src[1]) & 0x3f) << 16;
+}
+
 static void
 emit_shift(struct nv_pc *pc, struct nv_instruction *i)
 {
+   if (DFILE(i, 0) == NV_FILE_ADDR) {
+      emit_arl(pc, i);
+      return;
+   }
+
    pc->emit[0] = 0x30000001;
    pc->emit[1] = 0xc4000000;
 
index b35dd728417d2a22d9884f5668d04bdfaf7b3009..3e6e09a904f4c8ddc28575fd1174a59d54070b0a 100644 (file)
@@ -293,14 +293,15 @@ check_swap_src_0_1(struct nv_instruction *nvi)
 static int
 nv_pass_fold_stores(struct nv_pass *ctx, struct nv_basic_block *b)
 {
-   struct nv_instruction *nvi, *sti;
+   struct nv_instruction *nvi, *sti, *next;
    int j;
 
-   for (sti = b->entry; sti; sti = sti->next) {
-      if (!sti->def[0] || sti->def[0]->reg.file != NV_FILE_OUT)
-         continue;
+   for (sti = b->entry; sti; sti = next) {
+      next = sti->next;
 
       /* only handling MOV to $oX here */
+      if (!sti->def[0] || sti->def[0]->reg.file != NV_FILE_OUT)
+         continue;
       if (sti->opcode != NV_OP_MOV && sti->opcode != NV_OP_STA)
          continue;
 
@@ -320,9 +321,9 @@ nv_pass_fold_stores(struct nv_pass *ctx, struct nv_basic_block *b)
          continue;
 
       nvi->def[0] = sti->def[0];
-      sti->def[0] = NULL;
       nvi->fixed = sti->fixed;
-      sti->fixed = 0;
+
+      nv_nvi_delete(sti);
    }
    DESCEND_ARBITRARY(j, nv_pass_fold_stores);
 
index d6c5a8d6606ea52c37ec94e580d393ea5fcf6149..dafff725b8f73f960bded173f2ffcdc0f1c5afde 100644 (file)
@@ -685,6 +685,8 @@ translate_opcode(uint opcode)
    case TGSI_OPCODE_CEIL: return NV_OP_CEIL;
    case TGSI_OPCODE_FLR: return NV_OP_FLOOR;
    case TGSI_OPCODE_TRUNC: return NV_OP_TRUNC;
+   case TGSI_OPCODE_COS: return NV_OP_COS;
+   case TGSI_OPCODE_SIN: return NV_OP_SIN;
    case TGSI_OPCODE_DDX: return NV_OP_DFDX;
    case TGSI_OPCODE_DDY: return NV_OP_DFDY;
    case TGSI_OPCODE_F2I:
@@ -1226,6 +1228,14 @@ bld_instruction(struct bld_context *bld,
          dst0[c] = bld_insn_2(bld, opcode, src0, src1);
       }
       break;
+   case TGSI_OPCODE_ARL:
+      src1 = bld_imm_u32(bld, 4);
+      FOR_EACH_DST0_ENABLED_CHANNEL(c, insn) {
+         src0 = emit_fetch(bld, insn, 0, c);
+         (temp = bld_insn_1(bld, NV_OP_FLOOR, temp))->reg.type = NV_TYPE_S32;
+         dst0[c] = bld_insn_2(bld, NV_OP_SHL, temp, src1);
+      }
+      break;
    case TGSI_OPCODE_CMP:
       FOR_EACH_DST0_ENABLED_CHANNEL(c, insn) {
          src0 = emit_fetch(bld, insn, 0, c);
@@ -1245,19 +1255,19 @@ bld_instruction(struct bld_context *bld,
       }
       break;
    case TGSI_OPCODE_COS:
+   case TGSI_OPCODE_SIN:
       src0 = emit_fetch(bld, insn, 0, 0);
       temp = bld_insn_1(bld, NV_OP_PRESIN, src0);
       if (insn->Dst[0].Register.WriteMask & 7)
-         temp = bld_insn_1(bld, NV_OP_COS, temp);
+         temp = bld_insn_1(bld, opcode, temp);
       for (c = 0; c < 3; ++c)
          if (insn->Dst[0].Register.WriteMask & (1 << c))
             dst0[c] = temp;
       if (!(insn->Dst[0].Register.WriteMask & (1 << 3)))
          break;
-      /* XXX: if src0.x is src0.w, don't emit new insns */
       src0 = emit_fetch(bld, insn, 0, 3);
       temp = bld_insn_1(bld, NV_OP_PRESIN, src0);
-      dst0[3] = bld_insn_1(bld, NV_OP_COS, temp);
+      dst0[3] = bld_insn_1(bld, opcode, temp);
       break;
    case TGSI_OPCODE_DP3:
       src0 = emit_fetch(bld, insn, 0, 0);
@@ -1303,6 +1313,9 @@ bld_instruction(struct bld_context *bld,
          bld_kil(bld, src0);
       }
       break;
+   case TGSI_OPCODE_KILP:
+      (new_instruction(bld->pc, NV_OP_KIL))->fixed = 1;
+      break;
    case TGSI_OPCODE_IF:
    {
       struct nv_basic_block *b = new_basic_block(bld->pc);
@@ -1496,6 +1509,20 @@ bld_instruction(struct bld_context *bld,
          dst0[c]->reg.type = NV_TYPE_F32;
       }
       break;
+   case TGSI_OPCODE_SCS:
+      if (insn->Dst[0].Register.WriteMask & 0x3) {
+         src0 = emit_fetch(bld, insn, 0, 0);
+         temp = bld_insn_1(bld, NV_OP_PRESIN, src0);
+         if (insn->Dst[0].Register.WriteMask & 0x1)
+            dst0[0] = bld_insn_1(bld, NV_OP_COS, temp);
+         if (insn->Dst[0].Register.WriteMask & 0x2)
+            dst0[1] = bld_insn_1(bld, NV_OP_SIN, temp);
+      }
+      if (insn->Dst[0].Register.WriteMask & 0x4)
+         dst0[2] = bld_imm_f32(bld, 0.0f);
+      if (insn->Dst[0].Register.WriteMask & 0x8)
+         dst0[3] = bld_imm_f32(bld, 1.0f);
+      break;
    case TGSI_OPCODE_SUB:
       FOR_EACH_DST0_ENABLED_CHANNEL(c, insn) {
          src0 = emit_fetch(bld, insn, 0, c);
@@ -1527,12 +1554,15 @@ bld_instruction(struct bld_context *bld,
          dst0[c]->insn->src[2]->mod ^= NV_MOD_NEG;
       }
       break;
+   case TGSI_OPCODE_RET:
+      (new_instruction(bld->pc, NV_OP_RET))->fixed = 1;
+      break;
    case TGSI_OPCODE_END:
       if (bld->ti->p->type == PIPE_SHADER_FRAGMENT)
          bld_export_outputs(bld);
       break;
    default:
-      NOUVEAU_ERR("nv_bld: unhandled opcode %u\n", insn->Instruction.Opcode);
+      NOUVEAU_ERR("unhandled opcode %u\n", insn->Instruction.Opcode);
       abort();
       break;
    }