summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nv50
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2010-08-17 11:51:51 +0200
committerChristoph Bumiller <[email protected]>2010-08-17 13:08:52 +0200
commitce1629564d1cce80b2762d266640e3181a68e848 (patch)
tree56b18f99238ad4deb78d3f0247d6db3866255826 /src/gallium/drivers/nv50
parent62f933a6f617050a267079b27360eaae2d0e1a70 (diff)
nv50: more TGSI opcodes (SIN, SCS, ARL, RET, KILP)
Diffstat (limited to 'src/gallium/drivers/nv50')
-rw-r--r--src/gallium/drivers/nv50/nv50_pc_emit.c22
-rw-r--r--src/gallium/drivers/nv50/nv50_pc_optimize.c13
-rw-r--r--src/gallium/drivers/nv50/nv50_tgsi_to_nc.c38
3 files changed, 63 insertions, 10 deletions
diff --git a/src/gallium/drivers/nv50/nv50_pc_emit.c b/src/gallium/drivers/nv50/nv50_pc_emit.c
index 3a3b277c139..b5f4383aa1a 100644
--- a/src/gallium/drivers/nv50/nv50_pc_emit.c
+++ b/src/gallium/drivers/nv50/nv50_pc_emit.c
@@ -748,8 +748,30 @@ 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;
diff --git a/src/gallium/drivers/nv50/nv50_pc_optimize.c b/src/gallium/drivers/nv50/nv50_pc_optimize.c
index b35dd728417..3e6e09a904f 100644
--- a/src/gallium/drivers/nv50/nv50_pc_optimize.c
+++ b/src/gallium/drivers/nv50/nv50_pc_optimize.c
@@ -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);
diff --git a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
index d6c5a8d6606..dafff725b8f 100644
--- a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
+++ b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
@@ -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;
}