}
TargetNVC0::TargetNVC0(unsigned int card) :
- Target(card < 0x110, false, card >= 0xe4)
+ Target(card < 0x110, false, card >= 0xe4 && card < 0x140)
{
chipset = card;
initOpInfo();
}
}
-struct opProperties
+struct nvc0_opProperties
{
operation op;
unsigned int mNeg : 4;
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 },
{ 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 },
{ 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))
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) {
}
}
+ // 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 ® = ld->getSrc(0)->asImm()->reg;
// 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:
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;
}
case OP_XOR:
case OP_POPCNT:
case OP_BFIND:
+ case OP_XMAD:
break;
case OP_SET:
if (insn->sType != TYPE_F32)