JitIL: Added an IR instruction. Fixed the NSMBW bug reported in Issue 3097.
In Issue 3097, two bugs are reported (The bad collision checking in NSMBW and MP2 collision issue). In this commit, the bug in NSMBW is fixed. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6282 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
6d2c35a332
commit
59381f8343
|
@ -346,6 +346,11 @@ InstLoc IRBuilder::FoldUOp(unsigned Opcode, InstLoc Op1, unsigned extra) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (Opcode == Not) {
|
||||
if (getOpcode(*Op1) == Not) {
|
||||
return getOp1(Op1);
|
||||
}
|
||||
}
|
||||
|
||||
return EmitUOp(Opcode, Op1, extra);
|
||||
}
|
||||
|
@ -759,10 +764,8 @@ InstLoc IRBuilder::FoldOr(InstLoc Op1, InstLoc Op2) {
|
|||
}
|
||||
|
||||
// (~A | ~B) == (~(A & B)) - De Morgan's Law
|
||||
if (InstLoc notOp1 = isNot(Op1)) {
|
||||
if (InstLoc notOp2 = isNot(Op2)) {
|
||||
return FoldXor(EmitIntConst(-1U), FoldAnd(notOp1, notOp2));
|
||||
}
|
||||
if (getOpcode(*Op1) == Not && getOpcode(*Op2) == Not) {
|
||||
return EmitNot(FoldAnd(getOp1(Op1), getOp1(Op2)));
|
||||
}
|
||||
|
||||
if (Op1 == Op2) return Op1;
|
||||
|
@ -778,18 +781,14 @@ InstLoc IRBuilder::FoldXor(InstLoc Op1, InstLoc Op2) {
|
|||
}
|
||||
if (isImm(*Op2)) {
|
||||
if (!GetImmValue(Op2)) return Op1;
|
||||
if (GetImmValue(Op2) == 0xFFFFFFFFU) {
|
||||
return EmitNot(Op1);
|
||||
}
|
||||
if (getOpcode(*Op1) == Xor && isImm(*getOp2(Op1))) {
|
||||
unsigned RHS = GetImmValue(Op2) ^
|
||||
GetImmValue(getOp2(Op1));
|
||||
return FoldXor(getOp1(Op1), EmitIntConst(RHS));
|
||||
}
|
||||
|
||||
// ~(~X) => X
|
||||
if (GetImmValue(Op2) == -1U) {
|
||||
if (InstLoc notOp1 = isNot(Op1)) {
|
||||
return notOp1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Op1 == Op2) return EmitIntConst(0);
|
||||
|
@ -1115,7 +1114,7 @@ unsigned IRBuilder::getNumberOfOperands(InstLoc I) const {
|
|||
numberOfOperands[CInt32] = 0;
|
||||
|
||||
static unsigned ZeroOp[] = {LoadCR, LoadLink, LoadMSR, LoadGReg, LoadCTR, InterpreterBranch, LoadCarry, RFIExit, LoadFReg, LoadFRegDENToZero, LoadGQR, Int3, };
|
||||
static unsigned UOp[] = {StoreLink, BranchUncond, StoreCR, StoreMSR, StoreFPRF, StoreGReg, StoreCTR, Load8, Load16, Load32, SExt16, SExt8, Cntlzw, StoreCarry, SystemCall, ShortIdleLoop, LoadSingle, LoadDouble, LoadPaired, StoreFReg, DupSingleToMReg, DupSingleToPacked, ExpandPackedToMReg, CompactMRegToPacked, FSNeg, FSRSqrt, FDNeg, FPDup0, FPDup1, FPNeg, DoubleToSingle, StoreGQR, StoreSRR, };
|
||||
static unsigned UOp[] = {StoreLink, BranchUncond, StoreCR, StoreMSR, StoreFPRF, StoreGReg, StoreCTR, Load8, Load16, Load32, SExt16, SExt8, Cntlzw, Not, StoreCarry, SystemCall, ShortIdleLoop, LoadSingle, LoadDouble, LoadPaired, StoreFReg, DupSingleToMReg, DupSingleToPacked, ExpandPackedToMReg, CompactMRegToPacked, FSNeg, FSRSqrt, FDNeg, FPDup0, FPDup1, FPNeg, DoubleToSingle, StoreGQR, StoreSRR, };
|
||||
static unsigned BiOp[] = {BranchCond, IdleBranch, And, Xor, Sub, Or, Add, Mul, Rol, Shl, Shrl, Sarl, ICmpEq, ICmpNe, ICmpUgt, ICmpUlt, ICmpSgt, ICmpSlt, ICmpSge, ICmpSle, Store8, Store16, Store32, ICmpCRSigned, ICmpCRUnsigned, InterpreterFallback, StoreSingle, StoreDouble, StorePaired, InsertDoubleInMReg, FSMul, FSAdd, FSSub, FDMul, FDAdd, FDSub, FPAdd, FPMul, FPSub, FPMerge00, FPMerge01, FPMerge10, FPMerge11, FDCmpCR, };
|
||||
for (size_t i = 0; i < sizeof(ZeroOp) / sizeof(ZeroOp[0]); ++i) {
|
||||
numberOfOperands[ZeroOp[i]] = 0;
|
||||
|
@ -1192,26 +1191,6 @@ bool IRBuilder::maskedValueIsZero(InstLoc Op1, InstLoc Op2) const {
|
|||
return (~ComputeKnownZeroBits(Op1) & ~ComputeKnownZeroBits(Op1)) == 0;
|
||||
}
|
||||
|
||||
// Returns I' if I == ~I'.
|
||||
InstLoc IRBuilder::isNot(InstLoc I) const {
|
||||
if (getOpcode(*I) == Xor) {
|
||||
const InstLoc Op1 = getOp1(I);
|
||||
const InstLoc Op2 = getOp2(I);
|
||||
|
||||
// if (-1 ^ x) return x
|
||||
if (isImm(*Op1) && GetImmValue(Op1) == -1U) {
|
||||
return Op2;
|
||||
}
|
||||
|
||||
// if (x ^ -1) return x
|
||||
if (isImm(*Op2) && GetImmValue(Op2) == -1U) {
|
||||
return Op1;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Returns I' if I == (0 - I')
|
||||
InstLoc IRBuilder::isNeg(InstLoc I) const {
|
||||
if (getOpcode(*I) == Sub && isImm(*getOp1(I)) && GetImmValue(getOp1(I)) == 0) {
|
||||
|
|
|
@ -42,6 +42,7 @@ enum Opcode {
|
|||
BSwap32,
|
||||
BSwap16,
|
||||
Cntlzw, // Count leading zeros
|
||||
Not,
|
||||
Load8, // These loads zext
|
||||
Load16,
|
||||
Load32,
|
||||
|
@ -288,7 +289,7 @@ public:
|
|||
return FoldUOp(StoreGReg, value, reg);
|
||||
}
|
||||
InstLoc EmitNot(InstLoc op1) {
|
||||
return EmitXor(op1, EmitIntConst(0xFFFFFFFFU));
|
||||
return FoldUOp(Not, op1);
|
||||
}
|
||||
InstLoc EmitAnd(InstLoc op1, InstLoc op2) {
|
||||
return FoldBiOp(And, op1, op2);
|
||||
|
@ -573,7 +574,6 @@ private:
|
|||
unsigned getComplexity(InstLoc I) const;
|
||||
void simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2);
|
||||
bool maskedValueIsZero(InstLoc Op1, InstLoc Op2) const;
|
||||
InstLoc isNot(InstLoc I) const;
|
||||
InstLoc isNeg(InstLoc I) const;
|
||||
|
||||
std::vector<Inst> InstList; // FIXME: We must ensure this is
|
||||
|
|
|
@ -768,6 +768,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
|
|||
case BSwap32:
|
||||
case BSwap16:
|
||||
case Cntlzw:
|
||||
case Not:
|
||||
case DupSingleToMReg:
|
||||
case DoubleToSingle:
|
||||
case ExpandPackedToMReg:
|
||||
|
@ -1072,6 +1073,14 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
|
|||
regNormalRegClear(RI, I);
|
||||
break;
|
||||
}
|
||||
case Not: {
|
||||
if (!thisUsed) break;
|
||||
X64Reg reg = regBinLHSReg(RI, I);
|
||||
Jit->NOT(32, R(reg));
|
||||
RI.regs[reg] = I;
|
||||
regNormalRegClear(RI, I);
|
||||
break;
|
||||
}
|
||||
case And: {
|
||||
if (!thisUsed) break;
|
||||
regEmitBinInst(RI, I, &JitIL::AND, true);
|
||||
|
|
|
@ -198,23 +198,23 @@ void JitIL::crXX(UGeckoInstruction inst)
|
|||
break;
|
||||
case 129:
|
||||
// crandc
|
||||
ecx = ibuild.EmitXor(ecx, ibuild.EmitIntConst(0xFFFFFFFFU));
|
||||
ecx = ibuild.EmitNot(ecx);
|
||||
eax = ibuild.EmitAnd(eax, ecx);
|
||||
break;
|
||||
case 289:
|
||||
// creqv
|
||||
eax = ibuild.EmitXor(eax, ecx);
|
||||
eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(0xFFFFFFFFU));
|
||||
eax = ibuild.EmitNot(eax);
|
||||
break;
|
||||
case 225:
|
||||
// crnand
|
||||
eax = ibuild.EmitAnd(eax, ecx);
|
||||
eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(0xFFFFFFFFU));
|
||||
eax = ibuild.EmitNot(eax);
|
||||
break;
|
||||
case 33:
|
||||
// crnor
|
||||
eax = ibuild.EmitOr(eax, ecx);
|
||||
eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(0xFFFFFFFFU));
|
||||
eax = ibuild.EmitNot(eax);
|
||||
break;
|
||||
case 449:
|
||||
// cror
|
||||
|
@ -222,7 +222,7 @@ void JitIL::crXX(UGeckoInstruction inst)
|
|||
break;
|
||||
case 417:
|
||||
// crorc
|
||||
ecx = ibuild.EmitXor(ecx, ibuild.EmitIntConst(0xFFFFFFFFU));
|
||||
ecx = ibuild.EmitNot(ecx);
|
||||
eax = ibuild.EmitOr(eax, ecx);
|
||||
break;
|
||||
case 193:
|
||||
|
|
|
@ -196,13 +196,13 @@ static GekkoOPTemplate table19[] =
|
|||
static GekkoOPTemplate table31[] =
|
||||
{
|
||||
{28, &JitIL::boolX}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{60, &JitIL::Default}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{60, &JitIL::boolX}, //"andcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{444, &JitIL::boolX}, //"orx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{124, &JitIL::Default}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{124, &JitIL::boolX}, //"norx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{316, &JitIL::boolX}, //"xorx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{412, &JitIL::Default}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{476, &JitIL::Default}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{284, &JitIL::Default}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{412, &JitIL::boolX}, //"orcx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{476, &JitIL::boolX}, //"nandx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{284, &JitIL::boolX}, //"eqvx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
||||
{0, &JitIL::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
|
||||
{32, &JitIL::cmpXX}, //"cmpl", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
|
||||
{26, &JitIL::cntlzwx}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
|
||||
|
|
Loading…
Reference in New Issue