nv50/ir: fix PFETCH and add RDSV to get VSTRIDE for GPs
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 4 Apr 2013 20:57:42 +0000 (22:57 +0200)
committerMaarten Lankhorst <maarten.lankhorst@canonical.com>
Mon, 27 Jan 2014 15:40:42 +0000 (16:40 +0100)
src/gallium/drivers/nouveau/codegen/nv50_ir.h
src/gallium/drivers/nouveau/codegen/nv50_ir_emit_nv50.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_print.cpp

index 68c76e5a9cb34dd62b2757c398f2575dfc539c05..6a001d3ad14ea03a844f207f3a90edf4aa516375 100644 (file)
@@ -366,6 +366,7 @@ enum SVSemantic
    SV_CLOCK,
    SV_LBASE,
    SV_SBASE,
+   SV_VERTEX_STRIDE,
    SV_UNDEFINED,
    SV_LAST
 };
index 3eabfa6ae8f05e5b36a8390c19cab0f36aa0150e..68c543b6b265b10572cd1ea7ff574f055ff08fe9 100644 (file)
@@ -87,6 +87,7 @@ private:
    void emitLOAD(const Instruction *);
    void emitSTORE(const Instruction *);
    void emitMOV(const Instruction *);
+   void emitRDSV(const Instruction *);
    void emitNOP();
    void emitINTERP(const Instruction *);
    void emitPFETCH(const Instruction *);
@@ -772,6 +773,29 @@ CodeEmitterNV50::emitMOV(const Instruction *i)
    }
 }
 
+static inline uint8_t getSRegEncoding(const ValueRef &ref)
+{
+   switch (SDATA(ref).sv.sv) {
+   case SV_PHYSID:        return 0;
+   case SV_CLOCK:         return 1;
+   case SV_VERTEX_STRIDE: return 3;
+// case SV_PM_COUNTER:    return 4 + SDATA(ref).sv.index;
+   case SV_SAMPLE_INDEX:  return 8;
+   default:
+      assert(!"no sreg for system value");
+      return 0;
+   }
+}
+
+void
+CodeEmitterNV50::emitRDSV(const Instruction *i)
+{
+   code[0] = 0x00000001;
+   code[1] = 0x60000000 | (getSRegEncoding(i->src(0)) << 14);
+   defId(i->def(0), 2);
+   emitFlagsRd(i);
+}
+
 void
 CodeEmitterNV50::emitNOP()
 {
@@ -794,15 +818,40 @@ CodeEmitterNV50::emitQUADOP(const Instruction *i, uint8_t lane, uint8_t quOp)
       srcId(i->src(0), 32 + 14);
 }
 
+/* NOTE: This returns the base address of a vertex inside the primitive.
+ * src0 is an immediate, the index (not offset) of the vertex
+ * inside the primitive. XXX: signed or unsigned ?
+ * src1 (may be NULL) should use whatever units the hardware requires
+ * (on nv50 this is bytes, so, relative index * 4; signed 16 bit value).
+ */
 void
 CodeEmitterNV50::emitPFETCH(const Instruction *i)
 {
-   code[0] = 0x11800001;
-   code[1] = 0x04200000 | (0xf << 14);
+   const uint32_t prim = i->src(0).get()->reg.data.u32;
+   assert(prim <= 127);
 
-   defId(i->def(0), 2);
-   srcAddr8(i->src(0), 9);
-   setAReg16(i, 0);
+   if (i->def(0).getFile() == FILE_ADDRESS) {
+      // shl $aX a[] 0
+      code[0] = 0x00000001 | ((DDATA(i->def(0)).id + 1) << 2);
+      code[1] = 0xc0200000;
+      code[0] |= prim << 9;
+      assert(!i->srcExists(1));
+   } else
+   if (i->srcExists(1)) {
+      // ld b32 $rX a[$aX+base]
+      code[0] = 0x00000001;
+      code[1] = 0x04200000 | (0xf << 14);
+      defId(i->def(0), 2);
+      code[0] |= prim << 9;
+      setARegBits(SDATA(i->src(1)).id + 1);
+   } else {
+      // mov b32 $rX a[]
+      code[0] = 0x10000001;
+      code[1] = 0x04200000 | (0xf << 14);
+      defId(i->def(0), 2);
+      code[0] |= prim << 9;
+   }
+   emitFlagsRd(i);
 }
 
 void
@@ -1626,6 +1675,9 @@ CodeEmitterNV50::emitInstruction(Instruction *insn)
    case OP_PFETCH:
       emitPFETCH(insn);
       break;
+   case OP_RDSV:
+      emitRDSV(insn);
+      break;
    case OP_LINTERP:
    case OP_PINTERP:
       emitINTERP(insn);
index ee39b3c588009ed27749839687d1720f43ffb376..ae42d03d596be2f64c9b9f4ee2070caed60c9f8d 100644 (file)
@@ -265,6 +265,7 @@ static const char *SemanticStr[SV_LAST + 1] =
    "CLOCK",
    "LBASE",
    "SBASE",
+   "VERTEX_STRIDE",
    "?",
    "(INVALID)"
 };