From 59381f834314f4637bc78dbb95bb7651833a6e2e Mon Sep 17 00:00:00 2001 From: nodchip Date: Fri, 15 Oct 2010 00:45:45 +0000 Subject: [PATCH] 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 --- Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp | 43 +++++-------------- Source/Core/Core/Src/PowerPC/Jit64IL/IR.h | 4 +- .../Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp | 9 ++++ .../PowerPC/Jit64IL/JitIL_SystemRegisters.cpp | 10 ++--- .../Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp | 10 ++--- 5 files changed, 32 insertions(+), 44 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp index f9125da873..b2561903e2 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp @@ -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) { diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h index 991173c6ed..c18bfeddc2 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h @@ -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 InstList; // FIXME: We must ensure this is diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index fe086179c2..dd71fcac1b 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -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); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp index 8e1fb71fe8..f3e25dc2dd 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_SystemRegisters.cpp @@ -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: diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp index f9316d6e40..45c9100f3d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL_Tables.cpp @@ -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}},