* SOFTWARE.
*/
-/* #define NV50PC_DEBUG */
-
#include "nv50_pc.h"
#include "nv50_program.h"
switch (i->opcode) {
case NV_OP_MOV:
case NV_OP_LDA:
+ case NV_OP_STA:
return 0;
default:
return 1;
case NV_OP_FLOOR:
case NV_OP_TRUNC:
case NV_OP_CVT:
+ case NV_OP_ROUND:
+ case NV_OP_NEG:
case NV_OP_MAD:
case NV_OP_MUL:
case NV_OP_SAT:
}
}
+/* We may want an opcode table. */
+boolean
+nv50_op_can_write_flags(uint opcode)
+{
+ if (nv_is_vector_op(opcode))
+ return FALSE;
+ switch (opcode) { /* obvious ones like KIL, CALL, etc. not included */
+ case NV_OP_PHI:
+ case NV_OP_MOV:
+ case NV_OP_SELECT:
+ case NV_OP_LINTERP:
+ case NV_OP_PINTERP:
+ case NV_OP_LDA:
+ return FALSE;
+ default:
+ break;
+ }
+ if (opcode >= NV_OP_RCP && opcode <= NV_OP_PREEX2)
+ return FALSE;
+ return TRUE;
+}
+
int
nv_nvi_refcount(struct nv_instruction *nvi)
{
int i;
for (i = 0; i < pc->num_refs; i += 64)
FREE(pc->refs[i]);
+ FREE(pc->refs);
}
static const char *
bb[p++] = b->out[j];
break;
case CFG_EDGE_LOOP_LEAVE:
- bbb[pp++] = b->out[j];
+ if (!b->out[j]->priv) {
+ bbb[pp++] = b->out[j];
+ b->out[j]->priv = 1;
+ }
break;
default:
assert(0);
static void
nv_do_print_function(void *priv, struct nv_basic_block *b)
{
- struct nv_instruction *i = b->phi;
+ struct nv_instruction *i;
debug_printf("=== BB %i ", b->id);
if (b->out[0])
nv_print_function(pc->root[i]);
}
-#ifdef NV50_PC_DEBUG
+#if NV50_DEBUG & NV50_DEBUG_PROG_CFLOW
static void
nv_do_print_cfgraph(struct nv_pc *pc, FILE *f, struct nv_basic_block *b)
{
fclose(f);
}
-#endif
+#endif /* NV50_DEBUG_PROG_CFLOW */
static INLINE void
nvcg_show_bincode(struct nv_pc *pc)
{
- int i;
+ unsigned i;
- for (i = 0; i < pc->bin_size / 4; ++i)
+ for (i = 0; i < pc->bin_size / 4; ++i) {
debug_printf("0x%08x ", pc->emit[i]);
+ if ((i % 16) == 15)
+ debug_printf("\n");
+ }
debug_printf("\n");
}
uint32_t *code = pc->emit;
int n;
- NV50_DBGMSG("emitting program: size = %u\n", pc->bin_size);
+ NV50_DBGMSG(SHADER, "emitting program: size = %u\n", pc->bin_size);
for (n = 0; n < pc->num_blocks; ++n) {
struct nv_instruction *i;
assert(pc->emit == &code[pc->bin_size / 4]);
/* XXX: we can do better than this ... */
- if (!(pc->emit[-2] & 1) || (pc->emit[-2] & 2) || (pc->emit[-1] & 3)) {
+ if (!pc->bin_size ||
+ !(pc->emit[-2] & 1) || (pc->emit[-2] & 2) || (pc->emit[-1] & 3)) {
pc->emit[0] = 0xf0000001;
pc->emit[1] = 0xe0000000;
pc->bin_size += 8;
pc->emit = code;
code[pc->bin_size / 4 - 1] |= 1;
-#ifdef NV50PC_DEBUG
+#if NV50_DEBUG & NV50_DEBUG_SHADER
nvcg_show_bincode(pc);
#endif
ret = nv50_tgsi_to_nc(pc, ti);
if (ret)
goto out;
-#ifdef NV50PC_DEBUG
+#if NV50_DEBUG & NV50_DEBUG_PROG_IR
nv_print_program(pc);
#endif
ret = nv_pc_exec_pass0(pc);
if (ret)
goto out;
-#ifdef NV50PC_DEBUG
+#if NV50_DEBUG & NV50_DEBUG_PROG_IR
nv_print_program(pc);
#endif
ret = nv_pc_exec_pass1(pc);
if (ret)
goto out;
-#ifdef NV50PC_DEBUG
+#if NV50_DEBUG & NV50_DEBUG_PROG_CFLOW
nv_print_program(pc);
nv_print_cfgraph(pc, "nv50_shader_cfgraph.dot", 0);
#endif
ret = nv_pc_exec_pass2(pc);
if (ret)
goto out;
+ assert(!(pc->bin_size % 8));
pc->emit = CALLOC(pc->bin_size / 4 + 2, 4);
if (!pc->emit) {
ti->p->immd_size = pc->immd_count * 4;
ti->p->immd = pc->immd_buf;
- /* highest 16 bit reg to num of 32 bit regs */
- ti->p->max_gpr = (pc->max_reg[NV_FILE_GPR] >> 1) + 1;
+ /* highest 16 bit reg to num of 32 bit regs, limit to >= 4 */
+ ti->p->max_gpr = MAX2(4, (pc->max_reg[NV_FILE_GPR] >> 1) + 1);
ti->p->fixups = pc->fixups;
ti->p->num_fixups = pc->num_fixups;
- NV50_DBGMSG("SHADER TRANSLATION - %s\n", ret ? "failure" : "success");
+ ti->p->uses_lmem = ti->store_to_memory;
+
+ NV50_DBGMSG(SHADER, "SHADER TRANSLATION - %s\n", ret ? "failed" : "success");
out:
nv_pc_free_refs(pc);
for (i = 0; i < pc->num_blocks; ++i)
FREE(pc->bb_list[i]);
-
+ if (pc->root)
+ FREE(pc->root);
if (ret) { /* on success, these will be referenced by nv50_program */
if (pc->emit)
FREE(pc->emit);
i->bb = b;
b->num_instructions++;
+
+ if (i->prev && i->prev->is_terminator)
+ nv_nvi_permute(i->prev, i);
}
void
if (nvi == b->phi) {
if (nvi->opcode != NV_OP_PHI)
- NV50_DBGMSG("NOTE: b->phi points to non-PHI instruction\n");
+ NV50_DBGMSG(PROG_IR, "NOTE: b->phi points to non-PHI instruction\n");
assert(!nvi->prev);
if (!nvi->next || nvi->next->opcode != NV_OP_PHI)