nvc0/ir: fix load propagation for sub 4 byte addressing
[mesa.git] / src / gallium / drivers / nouveau / codegen / nv50_ir_target_nvc0.cpp
index 9304e3923617ba8c5b3957019d0c992d816a9aea..d2255c2cd2bbdeef04892676ea607aff27c5dad7 100644 (file)
@@ -30,7 +30,7 @@ Target *getTargetNVC0(unsigned int chipset)
 }
 
 TargetNVC0::TargetNVC0(unsigned int card) :
-   Target(card < 0x110, false, card >= 0xe4)
+   Target(card < 0x110, false, card >= 0xe4 && card < 0x140)
 {
    chipset = card;
    initOpInfo();
@@ -85,7 +85,7 @@ TargetNVC0::getBuiltinOffset(int builtin) const
    }
 }
 
-struct opProperties
+struct nvc0_opProperties
 {
    operation op;
    unsigned int mNeg   : 4;
@@ -96,7 +96,7 @@ struct opProperties
    unsigned int fImmd  : 4; // last bit indicates if full immediate is suppoted
 };
 
-static const struct opProperties _initProps[] =
+static const struct nvc0_opProperties _initProps[] =
 {
    //           neg  abs  not  sat  c[]  imm
    { OP_ADD,    0x3, 0x3, 0x0, 0x8, 0x2, 0x2 | 0x8 },
@@ -146,7 +146,7 @@ static const struct opProperties _initProps[] =
    { OP_PINTERP, 0x0, 0x0, 0x0, 0x8, 0x0, 0x0 },
 };
 
-static const struct opProperties _initPropsNVE4[] = {
+static const struct nvc0_opProperties _initPropsNVE4[] = {
    { OP_SULDB,   0x0, 0x0, 0x0, 0x0, 0x2, 0x0 },
    { OP_SUSTB,   0x0, 0x0, 0x0, 0x0, 0x2, 0x0 },
    { OP_SUSTP,   0x0, 0x0, 0x0, 0x0, 0x2, 0x0 },
@@ -155,19 +155,20 @@ static const struct opProperties _initPropsNVE4[] = {
    { OP_SUEAU,   0x0, 0x0, 0x0, 0x0, 0x6, 0x2 }
 };
 
-static const struct opProperties _initPropsGM107[] = {
+static const struct nvc0_opProperties _initPropsGM107[] = {
    { OP_SULDB,   0x0, 0x0, 0x0, 0x0, 0x0, 0x2 },
    { OP_SULDP,   0x0, 0x0, 0x0, 0x0, 0x0, 0x2 },
    { OP_SUSTB,   0x0, 0x0, 0x0, 0x0, 0x0, 0x4 },
    { OP_SUSTP,   0x0, 0x0, 0x0, 0x0, 0x0, 0x4 },
    { OP_SUREDB,  0x0, 0x0, 0x0, 0x0, 0x0, 0x4 },
    { OP_SUREDP,  0x0, 0x0, 0x0, 0x0, 0x0, 0x4 },
+   { OP_XMAD,    0x0, 0x0, 0x0, 0x0, 0x6, 0x2 },
 };
 
-void TargetNVC0::initProps(const struct opProperties *props, int size)
+void TargetNVC0::initProps(const struct nvc0_opProperties *props, int size)
 {
    for (int i = 0; i < size; ++i) {
-      const struct opProperties *prop = &props[i];
+      const struct nvc0_opProperties *prop = &props[i];
 
       for (int s = 0; s < 3; ++s) {
          if (prop->mNeg & (1 << s))
@@ -357,6 +358,18 @@ TargetNVC0::insnCanLoad(const Instruction *i, int s,
    if ((i->op == OP_SHL || i->op == OP_SHR) && typeSizeof(i->sType) == 8 &&
        sf == FILE_MEMORY_CONST)
       return false;
+   // constant buffer loads can't be used with cbcc xmads
+   if (i->op == OP_XMAD && sf == FILE_MEMORY_CONST &&
+       (i->subOp & NV50_IR_SUBOP_XMAD_CMODE_MASK) == NV50_IR_SUBOP_XMAD_CBCC)
+      return false;
+   // constant buffer loads for the third operand can't be used with psl/mrg xmads
+   if (i->op == OP_XMAD && sf == FILE_MEMORY_CONST && s == 2 &&
+       (i->subOp & (NV50_IR_SUBOP_XMAD_PSL | NV50_IR_SUBOP_XMAD_MRG)))
+      return false;
+   // for xmads, immediates can't have the h1 flag set
+   if (i->op == OP_XMAD && sf == FILE_IMMEDIATE && s < 2 &&
+       i->subOp & NV50_IR_SUBOP_XMAD_H1(s))
+      return false;
 
    for (int k = 0; i->srcExists(k); ++k) {
       if (i->src(k).getFile() == FILE_IMMEDIATE) {
@@ -374,6 +387,12 @@ TargetNVC0::insnCanLoad(const Instruction *i, int s,
       }
    }
 
+   // only loads can do sub 4 byte addressing
+   if (sf == FILE_MEMORY_CONST &&
+       (ld->getSrc(0)->reg.data.offset & 0x3)
+       && i->op != OP_LOAD)
+      return false;
+
    // not all instructions support full 32 bit immediates
    if (sf == FILE_IMMEDIATE) {
       Storage &reg = ld->getSrc(0)->asImm()->reg;
@@ -393,6 +412,9 @@ TargetNVC0::insnCanLoad(const Instruction *i, int s,
             // with u32, 0xfffff counts as 0xffffffff as well
             if (reg.data.s32 > 0x7ffff || reg.data.s32 < -0x80000)
                return false;
+            // XMADs can only have 16-bit immediates
+            if (i->op == OP_XMAD && reg.data.u32 > 0xffff)
+               return false;
             break;
          case TYPE_U8:
          case TYPE_S8:
@@ -449,6 +471,8 @@ TargetNVC0::isOpSupported(operation op, DataType ty) const
       return false;
    if (op == OP_POW || op == OP_SQRT || op == OP_DIV || op == OP_MOD)
       return false;
+   if (op == OP_XMAD)
+      return false;
    return true;
 }
 
@@ -468,6 +492,7 @@ TargetNVC0::isModSupported(const Instruction *insn, int s, Modifier mod) const
       case OP_XOR:
       case OP_POPCNT:
       case OP_BFIND:
+      case OP_XMAD:
          break;
       case OP_SET:
          if (insn->sType != TYPE_F32)