diff options
Diffstat (limited to 'src/gallium/drivers/nv50/nv50_program.c')
-rw-r--r-- | src/gallium/drivers/nv50/nv50_program.c | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index e496cf4cad8..0b78a7112b6 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -1306,18 +1306,22 @@ emit_kil(struct nv50_pc *pc, struct nv50_reg *src) { struct nv50_program_exec *e; const int r_pred = 1; - unsigned cvn = CVT_F32_F32; - if (src->mod & NV50_MOD_NEG) - cvn |= CVT_NEG; - /* write predicate reg */ - emit_cvt(pc, NULL, src, r_pred, CVTOP_RN, cvn); - - /* conditional discard */ e = exec(pc); - e->inst[0] = 0x00000002; - set_long(pc, e); - set_pred(pc, 0x1 /* LT */, r_pred, e); + e->inst[0] = 0x00000002; /* discard */ + set_long(pc, e); /* sets cond code to ALWAYS */ + + if (src) { + unsigned cvn = CVT_F32_F32; + + set_pred(pc, 0x1 /* cc = LT */, r_pred, e); + + if (src->mod & NV50_MOD_NEG) + cvn |= CVT_NEG; + /* write predicate reg */ + emit_cvt(pc, NULL, src, r_pred, CVTOP_RN, cvn); + } + emit(pc, e); } @@ -1343,6 +1347,19 @@ emit_branch(struct nv50_pc *pc, int pred, unsigned cc, return pc->p->exec_tail; } +static void +emit_ret(struct nv50_pc *pc, int pred, unsigned cc) +{ + struct nv50_program_exec *e = exec(pc); + + e->inst[0] = 0x30000002; + set_long(pc, e); + if (pred >= 0) + set_pred(pc, cc, pred, e); + + emit(pc, e); +} + #define QOP_ADD 0 #define QOP_SUBR 1 #define QOP_SUB 2 @@ -2063,6 +2080,24 @@ nv50_kill_branch(struct nv50_pc *pc) return TRUE; } +static void +nv50_fp_move_results(struct nv50_pc *pc) +{ + struct nv50_reg reg; + unsigned i; + + ctor_reg(®, P_TEMP, -1, -1); + + for (i = 0; i < pc->result_nr * 4; ++i) { + if (pc->result[i].rhw < 0 || pc->result[i].hw < 0) + continue; + if (pc->result[i].rhw != pc->result[i].hw) { + reg.hw = pc->result[i].rhw; + emit_mov(pc, ®, &pc->result[i]); + } + } +} + static boolean nv50_program_tx_insn(struct nv50_pc *pc, const struct tgsi_full_instruction *inst) @@ -2291,11 +2326,15 @@ nv50_program_tx_insn(struct nv50_pc *pc, terminate_mbb(pc); break; case TGSI_OPCODE_KIL: + assert(src[0][0] && src[0][1] && src[0][2] && src[0][3]); emit_kil(pc, src[0][0]); emit_kil(pc, src[0][1]); emit_kil(pc, src[0][2]); emit_kil(pc, src[0][3]); break; + case TGSI_OPCODE_KILP: + emit_kil(pc, NULL); + break; case TGSI_OPCODE_LIT: emit_lit(pc, &dst[0], mask, &src[0][0]); break; @@ -2352,6 +2391,11 @@ nv50_program_tx_insn(struct nv50_pc *pc, case TGSI_OPCODE_RCP: emit_flop(pc, 0, brdc, src[0][0]); break; + case TGSI_OPCODE_RET: + if (pc->p->type == PIPE_SHADER_FRAGMENT) + nv50_fp_move_results(pc); + emit_ret(pc, -1, 0); + break; case TGSI_OPCODE_RSQ: emit_flop(pc, 2, brdc, src[0][0]); break; @@ -3110,24 +3154,6 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p) } static void -nv50_fp_move_results(struct nv50_pc *pc) -{ - struct nv50_reg reg; - unsigned i; - - ctor_reg(®, P_TEMP, -1, -1); - - for (i = 0; i < pc->result_nr * 4; ++i) { - if (pc->result[i].rhw < 0 || pc->result[i].hw < 0) - continue; - if (pc->result[i].rhw != pc->result[i].hw) { - reg.hw = pc->result[i].rhw; - emit_mov(pc, ®, &pc->result[i]); - } - } -} - -static void nv50_program_fixup_insns(struct nv50_pc *pc) { struct nv50_program_exec *e, **bra_list; |