nv50,nvc0: add support for multi-sample resources
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_pc.c
index cf7b8e347fb70153c07636776a60008a876c35fb..2c3b8555f32345f85a1ff0df45dd6f1be13c181e 100644 (file)
  * SOFTWARE.
  */
 
-#define NOUVEAU_DEBUG 1
-
 #include "nvc0_pc.h"
 #include "nvc0_program.h"
 
+uint8_t
+nvc0_ir_reverse_cc(uint8_t cc)
+{
+   static const uint8_t cc_swapped[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
+
+   return cc_swapped[cc & 7] | (cc & ~7);
+}
+
 boolean
 nvc0_insn_can_load(struct nv_instruction *nvi, int s,
                    struct nv_instruction *ld)
@@ -44,6 +50,11 @@ nvc0_insn_can_load(struct nv_instruction *nvi, int s,
    if (ld->indirect >= 0)
       return FALSE;
 
+   /* a few ops can use g[] sources directly, but we don't support g[] yet */
+   if (ld->src[0]->value->reg.file == NV_FILE_MEM_L ||
+       ld->src[0]->value->reg.file == NV_FILE_MEM_G)
+      return FALSE;
+
    for (i = 0; i < 3 && nvi->src[i]; ++i)
       if (nvi->src[i]->value->reg.file == NV_FILE_IMM)
          return FALSE;
@@ -55,15 +66,11 @@ nvc0_insn_can_load(struct nv_instruction *nvi, int s,
 boolean
 nvc0_insn_is_predicateable(struct nv_instruction *nvi)
 {
-   int s;
-
-   if (!nv_op_predicateable(nvi->opcode))
+   if (nvi->predicate >= 0) /* already predicated */
       return FALSE;
-   if (nvi->predicate >= 0)
+   if (!nvc0_op_info_table[nvi->opcode].predicate &&
+       !nvc0_op_info_table[nvi->opcode].pseudo)
       return FALSE;
-   for (s = 0; s < 4 && nvi->src[s]; ++s)
-      if (nvi->src[s]->value->reg.file == NV_FILE_IMM)
-         return FALSE;
    return TRUE;
 }
 
@@ -103,6 +110,12 @@ nvc0_pc_replace_value(struct nv_pc *pc,
    return n;
 }
 
+static INLINE boolean
+is_gpr63(struct nv_value *val)
+{
+   return (val->reg.file == NV_FILE_GPR && val->reg.id == 63);
+}
+
 struct nv_value *
 nvc0_pc_find_constant(struct nv_ref *ref)
 {
@@ -116,7 +129,7 @@ nvc0_pc_find_constant(struct nv_ref *ref)
       assert(!src->insn->src[0]->mod);
       src = src->insn->src[0]->value;
    }
-   if ((src->reg.file == NV_FILE_IMM) ||
+   if ((src->reg.file == NV_FILE_IMM) || is_gpr63(src) ||
        (src->insn &&
         src->insn->opcode == NV_OP_LD &&
         src->insn->src[0]->value->reg.file >= NV_FILE_MEM_C(0) &&
@@ -130,7 +143,7 @@ nvc0_pc_find_immediate(struct nv_ref *ref)
 {
    struct nv_value *src = nvc0_pc_find_constant(ref);
 
-   return (src && src->reg.file == NV_FILE_IMM) ? src : NULL;
+   return (src && (src->reg.file == NV_FILE_IMM || is_gpr63(src))) ? src : NULL;
 }
 
 static void
@@ -187,7 +200,10 @@ nvc0_pc_pass_in_order(struct nv_basic_block *root, nv_pc_pass_func f,
             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);
@@ -244,7 +260,7 @@ nvc0_print_program(struct nv_pc *pc)
          nvc0_print_function(pc->root[i]);
 }
 
-#if NOUVEAU_DEBUG > 1
+#if NV50_DEBUG & NV50_DEBUG_PROG_CFLOW
 static void
 nv_do_print_cfgraph(struct nv_pc *pc, FILE *f, struct nv_basic_block *b)
 {
@@ -309,7 +325,7 @@ nvc0_pc_print_binary(struct nv_pc *pc)
 {
    unsigned i;
 
-   NOUVEAU_DBG("nvc0_pc_print_binary(%u ops)\n", pc->emit_size / 8);
+   NV50_DBGMSG(SHADER, "nvc0_pc_print_binary(%u ops)\n", pc->emit_size / 8);
 
    for (i = 0; i < pc->emit_size / 4; i += 2) {
       debug_printf("0x%08x ", pc->emit[i + 0]);
@@ -326,7 +342,7 @@ nvc0_emit_program(struct nv_pc *pc)
    uint32_t *code = pc->emit;
    int n;
 
-   NOUVEAU_DBG("emitting program: size = %u\n", pc->emit_size);
+   NV50_DBGMSG(SHADER, "emitting program: size = %u\n", pc->emit_size);
 
    pc->emit_pos = 0;
    for (n = 0; n < pc->num_blocks; ++n) {
@@ -347,11 +363,10 @@ nvc0_emit_program(struct nv_pc *pc)
 
    pc->emit = code;
 
-#ifdef NOUVEAU_DEBUG
+#if NV50_DEBUG & NV50_DEBUG_SHADER
    nvc0_pc_print_binary(pc);
-#else
-   debug_printf("not printing binary\n");
 #endif
+
    return 0;
 }
 
@@ -378,7 +393,7 @@ nvc0_generate_code(struct nvc0_translation_info *ti)
    ret = nvc0_tgsi_to_nc(pc, ti);
    if (ret)
       goto out;
-#if NOUVEAU_DEBUG > 1
+#if NV50_DEBUG & NV50_DEBUG_PROG_IR
    nvc0_print_program(pc);
 #endif
 
@@ -388,7 +403,7 @@ nvc0_generate_code(struct nvc0_translation_info *ti)
    ret = nvc0_pc_exec_pass0(pc);
    if (ret)
       goto out;
-#ifdef NOUVEAU_DEBUG
+#if NV50_DEBUG & NV50_DEBUG_PROG_IR
    nvc0_print_program(pc);
 #endif
 
@@ -396,8 +411,8 @@ nvc0_generate_code(struct nvc0_translation_info *ti)
    ret = nvc0_pc_exec_pass1(pc);
    if (ret)
       goto out;
-#if NOUVEAU_DEBUG > 1
-   nv_print_program(pc);
+#if NV50_DEBUG & NV50_DEBUG_PROG_CFLOW
+   nvc0_print_program(pc);
    nv_print_cfgraph(pc, "nvc0_shader_cfgraph.dot", 0);
 #endif
 
@@ -426,7 +441,7 @@ nvc0_generate_code(struct nvc0_translation_info *ti)
    ti->prog->relocs = pc->reloc_entries;
    ti->prog->num_relocs = pc->num_relocs;
 
-   NOUVEAU_DBG("SHADER TRANSLATION - %s\n", ret ? "failure" : "success");
+   NV50_DBGMSG(SHADER, "SHADER TRANSLATION - %s\n", ret ? "failed" : "success");
 
 out:
    nv_pc_free_refs(pc);
@@ -499,6 +514,9 @@ nvc0_insn_append(struct nv_basic_block *b, struct nv_instruction *i)
 
    i->bb = b;
    b->num_instructions++;
+
+   if (i->prev && i->prev->terminator)
+      nvc0_insns_permute(i->prev, i);
 }
 
 void
@@ -512,6 +530,15 @@ nvc0_insn_insert_after(struct nv_instruction *at, struct nv_instruction *ni)
    ni->prev = at;
    ni->next->prev = ni;
    ni->prev->next = ni;
+   ni->bb = at->bb;
+   ni->bb->num_instructions++;
+}
+
+void
+nvc0_insn_insert_before(struct nv_instruction *at, struct nv_instruction *ni)
+{
+   nvc0_insn_insert_after(at, ni);
+   nvc0_insns_permute(at, ni);
 }
 
 void
@@ -543,7 +570,7 @@ nvc0_insn_delete(struct nv_instruction *nvi)
 
    if (nvi == b->phi) {
       if (nvi->opcode != NV_OP_PHI)
-         NOUVEAU_DBG("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)