mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 15:19:42 -06:00
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:
@ -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);
|
return EmitUOp(Opcode, Op1, extra);
|
||||||
}
|
}
|
||||||
@ -759,10 +764,8 @@ InstLoc IRBuilder::FoldOr(InstLoc Op1, InstLoc Op2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// (~A | ~B) == (~(A & B)) - De Morgan's Law
|
// (~A | ~B) == (~(A & B)) - De Morgan's Law
|
||||||
if (InstLoc notOp1 = isNot(Op1)) {
|
if (getOpcode(*Op1) == Not && getOpcode(*Op2) == Not) {
|
||||||
if (InstLoc notOp2 = isNot(Op2)) {
|
return EmitNot(FoldAnd(getOp1(Op1), getOp1(Op2)));
|
||||||
return FoldXor(EmitIntConst(-1U), FoldAnd(notOp1, notOp2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Op1 == Op2) return Op1;
|
if (Op1 == Op2) return Op1;
|
||||||
@ -778,18 +781,14 @@ InstLoc IRBuilder::FoldXor(InstLoc Op1, InstLoc Op2) {
|
|||||||
}
|
}
|
||||||
if (isImm(*Op2)) {
|
if (isImm(*Op2)) {
|
||||||
if (!GetImmValue(Op2)) return Op1;
|
if (!GetImmValue(Op2)) return Op1;
|
||||||
|
if (GetImmValue(Op2) == 0xFFFFFFFFU) {
|
||||||
|
return EmitNot(Op1);
|
||||||
|
}
|
||||||
if (getOpcode(*Op1) == Xor && isImm(*getOp2(Op1))) {
|
if (getOpcode(*Op1) == Xor && isImm(*getOp2(Op1))) {
|
||||||
unsigned RHS = GetImmValue(Op2) ^
|
unsigned RHS = GetImmValue(Op2) ^
|
||||||
GetImmValue(getOp2(Op1));
|
GetImmValue(getOp2(Op1));
|
||||||
return FoldXor(getOp1(Op1), EmitIntConst(RHS));
|
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);
|
if (Op1 == Op2) return EmitIntConst(0);
|
||||||
@ -1115,7 +1114,7 @@ unsigned IRBuilder::getNumberOfOperands(InstLoc I) const {
|
|||||||
numberOfOperands[CInt32] = 0;
|
numberOfOperands[CInt32] = 0;
|
||||||
|
|
||||||
static unsigned ZeroOp[] = {LoadCR, LoadLink, LoadMSR, LoadGReg, LoadCTR, InterpreterBranch, LoadCarry, RFIExit, LoadFReg, LoadFRegDENToZero, LoadGQR, Int3, };
|
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, };
|
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) {
|
for (size_t i = 0; i < sizeof(ZeroOp) / sizeof(ZeroOp[0]); ++i) {
|
||||||
numberOfOperands[ZeroOp[i]] = 0;
|
numberOfOperands[ZeroOp[i]] = 0;
|
||||||
@ -1192,26 +1191,6 @@ bool IRBuilder::maskedValueIsZero(InstLoc Op1, InstLoc Op2) const {
|
|||||||
return (~ComputeKnownZeroBits(Op1) & ~ComputeKnownZeroBits(Op1)) == 0;
|
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')
|
// Returns I' if I == (0 - I')
|
||||||
InstLoc IRBuilder::isNeg(InstLoc I) const {
|
InstLoc IRBuilder::isNeg(InstLoc I) const {
|
||||||
if (getOpcode(*I) == Sub && isImm(*getOp1(I)) && GetImmValue(getOp1(I)) == 0) {
|
if (getOpcode(*I) == Sub && isImm(*getOp1(I)) && GetImmValue(getOp1(I)) == 0) {
|
||||||
|
@ -42,6 +42,7 @@ enum Opcode {
|
|||||||
BSwap32,
|
BSwap32,
|
||||||
BSwap16,
|
BSwap16,
|
||||||
Cntlzw, // Count leading zeros
|
Cntlzw, // Count leading zeros
|
||||||
|
Not,
|
||||||
Load8, // These loads zext
|
Load8, // These loads zext
|
||||||
Load16,
|
Load16,
|
||||||
Load32,
|
Load32,
|
||||||
@ -288,7 +289,7 @@ public:
|
|||||||
return FoldUOp(StoreGReg, value, reg);
|
return FoldUOp(StoreGReg, value, reg);
|
||||||
}
|
}
|
||||||
InstLoc EmitNot(InstLoc op1) {
|
InstLoc EmitNot(InstLoc op1) {
|
||||||
return EmitXor(op1, EmitIntConst(0xFFFFFFFFU));
|
return FoldUOp(Not, op1);
|
||||||
}
|
}
|
||||||
InstLoc EmitAnd(InstLoc op1, InstLoc op2) {
|
InstLoc EmitAnd(InstLoc op1, InstLoc op2) {
|
||||||
return FoldBiOp(And, op1, op2);
|
return FoldBiOp(And, op1, op2);
|
||||||
@ -573,7 +574,6 @@ private:
|
|||||||
unsigned getComplexity(InstLoc I) const;
|
unsigned getComplexity(InstLoc I) const;
|
||||||
void simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2);
|
void simplifyCommutative(unsigned Opcode, InstLoc& Op1, InstLoc& Op2);
|
||||||
bool maskedValueIsZero(InstLoc Op1, InstLoc Op2) const;
|
bool maskedValueIsZero(InstLoc Op1, InstLoc Op2) const;
|
||||||
InstLoc isNot(InstLoc I) const;
|
|
||||||
InstLoc isNeg(InstLoc I) const;
|
InstLoc isNeg(InstLoc I) const;
|
||||||
|
|
||||||
std::vector<Inst> InstList; // FIXME: We must ensure this is
|
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 BSwap32:
|
||||||
case BSwap16:
|
case BSwap16:
|
||||||
case Cntlzw:
|
case Cntlzw:
|
||||||
|
case Not:
|
||||||
case DupSingleToMReg:
|
case DupSingleToMReg:
|
||||||
case DoubleToSingle:
|
case DoubleToSingle:
|
||||||
case ExpandPackedToMReg:
|
case ExpandPackedToMReg:
|
||||||
@ -1072,6 +1073,14 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
|
|||||||
regNormalRegClear(RI, I);
|
regNormalRegClear(RI, I);
|
||||||
break;
|
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: {
|
case And: {
|
||||||
if (!thisUsed) break;
|
if (!thisUsed) break;
|
||||||
regEmitBinInst(RI, I, &JitIL::AND, true);
|
regEmitBinInst(RI, I, &JitIL::AND, true);
|
||||||
|
@ -198,23 +198,23 @@ void JitIL::crXX(UGeckoInstruction inst)
|
|||||||
break;
|
break;
|
||||||
case 129:
|
case 129:
|
||||||
// crandc
|
// crandc
|
||||||
ecx = ibuild.EmitXor(ecx, ibuild.EmitIntConst(0xFFFFFFFFU));
|
ecx = ibuild.EmitNot(ecx);
|
||||||
eax = ibuild.EmitAnd(eax, ecx);
|
eax = ibuild.EmitAnd(eax, ecx);
|
||||||
break;
|
break;
|
||||||
case 289:
|
case 289:
|
||||||
// creqv
|
// creqv
|
||||||
eax = ibuild.EmitXor(eax, ecx);
|
eax = ibuild.EmitXor(eax, ecx);
|
||||||
eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(0xFFFFFFFFU));
|
eax = ibuild.EmitNot(eax);
|
||||||
break;
|
break;
|
||||||
case 225:
|
case 225:
|
||||||
// crnand
|
// crnand
|
||||||
eax = ibuild.EmitAnd(eax, ecx);
|
eax = ibuild.EmitAnd(eax, ecx);
|
||||||
eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(0xFFFFFFFFU));
|
eax = ibuild.EmitNot(eax);
|
||||||
break;
|
break;
|
||||||
case 33:
|
case 33:
|
||||||
// crnor
|
// crnor
|
||||||
eax = ibuild.EmitOr(eax, ecx);
|
eax = ibuild.EmitOr(eax, ecx);
|
||||||
eax = ibuild.EmitXor(eax, ibuild.EmitIntConst(0xFFFFFFFFU));
|
eax = ibuild.EmitNot(eax);
|
||||||
break;
|
break;
|
||||||
case 449:
|
case 449:
|
||||||
// cror
|
// cror
|
||||||
@ -222,7 +222,7 @@ void JitIL::crXX(UGeckoInstruction inst)
|
|||||||
break;
|
break;
|
||||||
case 417:
|
case 417:
|
||||||
// crorc
|
// crorc
|
||||||
ecx = ibuild.EmitXor(ecx, ibuild.EmitIntConst(0xFFFFFFFFU));
|
ecx = ibuild.EmitNot(ecx);
|
||||||
eax = ibuild.EmitOr(eax, ecx);
|
eax = ibuild.EmitOr(eax, ecx);
|
||||||
break;
|
break;
|
||||||
case 193:
|
case 193:
|
||||||
|
@ -196,13 +196,13 @@ static GekkoOPTemplate table19[] =
|
|||||||
static GekkoOPTemplate table31[] =
|
static GekkoOPTemplate table31[] =
|
||||||
{
|
{
|
||||||
{28, &JitIL::boolX}, //"andx", OPTYPE_INTEGER, FL_OUT_A | FL_IN_SB | FL_RC_BIT}},
|
{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}},
|
{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}},
|
{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}},
|
{412, &JitIL::boolX}, //"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}},
|
{476, &JitIL::boolX}, //"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}},
|
{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}},
|
{0, &JitIL::cmpXX}, //"cmp", OPTYPE_INTEGER, FL_IN_AB | FL_SET_CRn}},
|
||||||
{32, &JitIL::cmpXX}, //"cmpl", 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}},
|
{26, &JitIL::cntlzwx}, //"cntlzwx",OPTYPE_INTEGER, FL_OUT_A | FL_IN_S | FL_RC_BIT}},
|
||||||
|
Reference in New Issue
Block a user