diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp index c59e75fa94..7d01b617e5 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp @@ -136,8 +136,7 @@ (Core::GetStartupParameter().bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) && Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8) { - // TODO(LinesPrower): - // - Fix idle skipping in JITIL! + // TODO(LinesPrower): // - Rewrite this! // It seems to be ugly and unefficient, but I don't know JIT stuff enough to make it right // It only demonstrates the idea @@ -164,8 +163,8 @@ ABI_CallFunctionC((void *)&PowerPC::OnIdle, PowerPC::ppcState.gpr[a] + (s32)(s16)inst.SIMM_16); // ! we must continue executing of the loop after exception handling, maybe there is still 0 in r0 - //MOV(32, M(&PowerPC::ppcState.pc), Imm32(js.compilerPC + 12)); - JMP(asm_routines.testExceptions, true); + //MOV(32, M(&PowerPC::ppcState.pc), Imm32(js.compilerPC)); + JMP(asm_routines.testExceptions, true); SetJumpTarget(noIdle); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp index 5f3c58dd3a..d1503f3b0e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.cpp @@ -514,6 +514,14 @@ InstLoc IRBuilder::FoldBranchCond(InstLoc Op1, InstLoc Op2) { return EmitBiOp(BranchCond, Op1, Op2); } +InstLoc IRBuilder::FoldIdleBranch(InstLoc Op1, InstLoc Op2) { + return EmitBiOp( + IdleBranch, + EmitICmpEq(getOp1(getOp1(Op1)), + getOp2(getOp1(Op1))), Op2 + ); +} + InstLoc IRBuilder::FoldICmp(unsigned Opcode, InstLoc Op1, InstLoc Op2) { if (isImm(*Op1)) { if (isImm(*Op2)) { @@ -659,6 +667,7 @@ InstLoc IRBuilder::FoldBiOp(unsigned Opcode, InstLoc Op1, InstLoc Op2, unsigned case Shrl: return FoldShrl(Op1, Op2); case Rol: return FoldRol(Op1, Op2); case BranchCond: return FoldBranchCond(Op1, Op2); + case IdleBranch: return FoldIdleBranch(Op1, Op2); case ICmpEq: case ICmpNe: case ICmpUgt: case ICmpUlt: case ICmpUge: case ICmpUle: case ICmpSgt: case ICmpSlt: case ICmpSge: case ICmpSle: @@ -1310,9 +1319,8 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) { case InterpreterFallback: case SystemCall: case RFIExit: - case InterpreterBranch: - case IdleLoop: - case ShortIdleLoop: + case InterpreterBranch: + case ShortIdleLoop: case Tramp: // No liveness effects break; @@ -1419,6 +1427,9 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) { if (!isImm(*getOp1(I))) regMarkUse(RI, I, getOp1(I), 1); break; + case IdleBranch: + regMarkUse(RI, I, getOp1(getOp1(I)), 1); + break; case BranchCond: { if (isICmp(*getOp1(I)) && isImm(*getOp2(getOp1(I)))) { @@ -2112,6 +2123,26 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) { case BlockStart: case BlockEnd: break; + + case IdleBranch: { + Jit->CMP(32, regLocForInst(RI, getOp1(getOp1(I))), + Imm32(RI.Build->GetImmValue(getOp2(getOp1(I))))); + FixupBranch cont = Jit->J_CC(CC_NE); + + RI.Jit->Cleanup(); // is it needed? + Jit->ABI_CallFunction((void *)&PowerPC::OnIdleIL); + + Jit->MOV(32, M(&PC), Imm32(ibuild->GetImmValue( getOp2(I) ))); + Jit->JMP(asm_routines.testExceptions, true); + + Jit->SetJumpTarget(cont); + if (RI.IInfo[I - RI.FirstI] & 4) + regClearInst(RI, getOp1(getOp1(I))); + if (RI.IInfo[I - RI.FirstI] & 8) + regClearInst(RI, getOp2(I)); + break; + } + case BranchCond: { if (isICmp(*getOp1(I)) && isImm(*getOp2(getOp1(I)))) { @@ -2151,15 +2182,7 @@ static void DoWriteCode(IRBuilder* ibuild, Jit64* Jit, bool UseProfile) { regWriteExit(RI, getOp1(I)); regNormalRegClear(RI, I); break; - } - case IdleLoop: { - unsigned IdleParam = ibuild->GetImmValue(getOp1(I)); - unsigned InstLoc = ibuild->GetImmValue(getOp2(I)); - Jit->ABI_CallFunctionC((void *)&PowerPC::OnIdle, IdleParam); - Jit->MOV(32, M(&PC), Imm32(InstLoc + 12)); - Jit->JMP(asm_routines.testExceptions, true); - break; - } + } case ShortIdleLoop: { unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); Jit->ABI_CallFunction((void *)&CoreTiming::Idle); diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h index d29df47a44..6ed1118ab2 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR.h @@ -156,7 +156,9 @@ namespace IREmitter { SystemCall, RFIExit, InterpreterBranch, - IdleLoop, // The "usual" idle loop, load+compare+branch + + //IdleLoop, // The "usual" idle loop, load+compare+branch + IdleBranch, // branch operation belonging to idle loop ShortIdleLoop, // Idle loop seen in homebrew like wii mahjong, // just a branch @@ -220,6 +222,7 @@ namespace IREmitter { InstLoc FoldShrl(InstLoc Op1, InstLoc Op2); InstLoc FoldXor(InstLoc Op1, InstLoc Op2); InstLoc FoldBranchCond(InstLoc Op1, InstLoc Op2); + InstLoc FoldIdleBranch(InstLoc Op1, InstLoc Op2); InstLoc FoldICmp(unsigned Opcode, InstLoc Op1, InstLoc Op2); InstLoc FoldICmpCRSigned(InstLoc Op1, InstLoc Op2); InstLoc FoldICmpCRUnsigned(InstLoc Op1, InstLoc Op2); @@ -246,6 +249,9 @@ namespace IREmitter { InstLoc EmitBranchCond(InstLoc check, InstLoc dest) { return FoldBiOp(BranchCond, check, dest); } + InstLoc EmitIdleBranch(InstLoc check, InstLoc dest) { + return FoldBiOp(IdleBranch, check, dest); + } InstLoc EmitLoadCR(unsigned crreg) { return FoldZeroOp(LoadCR, crreg); } @@ -380,10 +386,7 @@ namespace IREmitter { } InstLoc EmitRFIExit() { return FoldZeroOp(RFIExit, 0); - } - InstLoc EmitIdleLoop(InstLoc idleParam, InstLoc pc) { - return FoldBiOp(IdleLoop, idleParam, pc); - } + } InstLoc EmitShortIdleLoop(InstLoc pc) { return FoldUOp(ShortIdleLoop, pc); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Branch.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Branch.cpp index 4e05a54b5e..2bc5dd8db3 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Branch.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_Branch.cpp @@ -27,6 +27,8 @@ #include "JitRegCache.h" #include "JitAsm.h" +#include "../../HW/Memmap.h" + // The branches are known good, or at least reasonably good. // No need for a disable-mechanism. @@ -127,7 +129,19 @@ using namespace Gen; else destination = js.compilerPC + SignExt16(inst.BD << 2); - ibuild.EmitBranchCond(Test, ibuild.EmitIntConst(destination)); + if (Core::GetStartupParameter().bSkipIdle && + inst.hex == 0x4182fff8 && + (Memory::ReadUnchecked_U32(js.compilerPC - 8) & 0xFFFF0000) == 0x800D0000 && + (Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x28000000 || + (Core::GetStartupParameter().bWii && Memory::ReadUnchecked_U32(js.compilerPC - 4) == 0x2C000000)) + ) + { + ibuild.EmitIdleBranch(Test, ibuild.EmitIntConst(destination)); + } + else + { + ibuild.EmitBranchCond(Test, ibuild.EmitIntConst(destination)); + } ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4)); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStore.cpp index 851602040e..34bf12ec51 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/Jit_LoadStore.cpp @@ -53,20 +53,7 @@ void Jit64::lhax(UGeckoInstruction inst) void Jit64::lXz(UGeckoInstruction inst) { INSTRUCTION_START - JITDISABLE(LoadStore) - if (Core::GetStartupParameter().bSkipIdle && - inst.OPCD == 32 && - (inst.hex & 0xFFFF0000) == 0x800D0000 && - (Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 || - (Core::GetStartupParameter().bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) && - Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8) - { - ibuild.EmitIdleLoop(ibuild.EmitIntConst(PowerPC::ppcState.gpr[inst.RA] + (s32)(s16)inst.SIMM_16), - ibuild.EmitIntConst(js.compilerPC)); - js.compilerPC += 8; - return; - } - + JITDISABLE(LoadStore) IREmitter::InstLoc addr = ibuild.EmitIntConst(inst.SIMM_16); if (inst.RA) addr = ibuild.EmitAdd(addr, ibuild.EmitLoadGReg(inst.RA)); diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp index 7759b6a9fc..2e55b7f007 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp @@ -348,4 +348,9 @@ void OnIdle(u32 _uThreadAddr) CoreTiming::Idle(); } +void OnIdleIL() +{ + CoreTiming::Idle(); +} + } // namespace \ No newline at end of file diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.h b/Source/Core/Core/Src/PowerPC/PowerPC.h index 45455bfff3..c025660903 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.h +++ b/Source/Core/Core/Src/PowerPC/PowerPC.h @@ -92,6 +92,7 @@ void CompactCR(); void ExpandCR(); void OnIdle(u32 _uThreadAddr); +void OnIdleIL(); // Easy register access macros. #define HID2 ((UReg_HID2&)PowerPC::ppcState.spr[SPR_HID2])