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:
nodchip 2010-10-15 00:45:45 +00:00
parent 6d2c35a332
commit 59381f8343
5 changed files with 32 additions and 44 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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);

View File

@ -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:

View File

@ -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}},