From 4545fa589de494d71044bd6c25c2b61faa53b9fc Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 2 Jun 2014 08:24:25 +0200 Subject: [PATCH 01/14] Jit64: remove unused FlushMode enum --- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 28 +++++++++---------- .../Core/Core/PowerPC/Jit64/JitRegCache.cpp | 2 +- Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 8 ++---- Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp | 24 ++++++++-------- .../Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 12 ++++---- .../PowerPC/Jit64/Jit_SystemRegisters.cpp | 4 +-- 6 files changed, 37 insertions(+), 41 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 67b4b5a4cf..6cd5082dc6 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -207,8 +207,8 @@ void Jit64::Shutdown() // This is only called by FallBackToInterpreter() in this file. It will execute an instruction with the interpreter functions. void Jit64::WriteCallInterpreter(UGeckoInstruction inst) { - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); if (js.isLastInstruction) { MOV(32, M(&PC), Imm32(js.compilerPC)); @@ -230,8 +230,8 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction _inst) void Jit64::HLEFunction(UGeckoInstruction _inst) { - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); ABI_CallFunctionCC((void*)&HLE::Execute, js.compilerPC, _inst.hex); } @@ -543,8 +543,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc { if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound) { - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); //This instruction uses FPU - needs to add FP exception bailout TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); // Test FP enabled bit @@ -564,8 +564,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc // Add an external exception check if the instruction writes to the FIFO. if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end()) { - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT)); FixupBranch clearInt = J_CC(CC_NZ, true); @@ -587,8 +587,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING) { - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); MOV(32, M(&PC), Imm32(ops[i].address)); ABI_CallFunction(reinterpret_cast(&PowerPC::CheckBreakPoints)); @@ -604,8 +604,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc if (js.memcheck && (opinfo->flags & FL_LOADSTORE)) { // In case we are about to jump to the dispatcher, flush regs - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI)); FixupBranch noMemException = J_CC(CC_Z, true); @@ -672,8 +672,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc if (code_block.m_broken) { - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); WriteExit(nextPC); } diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index 69cec425d5..bb26a3e6b3 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -362,7 +362,7 @@ void FPURegCache::StoreFromRegister(int i) } } -void RegCache::Flush(FlushMode mode) +void RegCache::Flush() { for (int i = 0; i < NUMXREGS; i++) { diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index b687f17d23..fe2880d80b 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -7,10 +7,6 @@ #include "Common/x64Emitter.h" using namespace Gen; -enum FlushMode -{ - FLUSH_ALL -}; enum GrabMode { @@ -79,8 +75,8 @@ public: FlushR(reg1); FlushR(reg2); LockX(reg1); LockX(reg2); } - virtual void Flush(FlushMode mode); - virtual void Flush(PPCAnalyst::CodeOp *op) {Flush(FLUSH_ALL);} + virtual void Flush(); + virtual void Flush(PPCAnalyst::CodeOp *op) {Flush();} int SanityCheck() const; void KillImmediate(int preg, bool doLoad, bool makeDirty); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp index 73d3c34294..a30929b18b 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp @@ -26,8 +26,8 @@ void Jit64::sc(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITBranchOff) - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); MOV(32, M(&PC), Imm32(js.compilerPC + 4)); LOCK(); OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_SYSCALL)); @@ -39,8 +39,8 @@ void Jit64::rfi(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITBranchOff) - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); // See Interpreter rfi for details const u32 mask = 0x87C0FFFF; const u32 clearMSR13 = 0xFFFBFFFF; // Mask used to clear the bit MSR[13] @@ -71,8 +71,8 @@ void Jit64::bx(UGeckoInstruction inst) return; } - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); u32 destination; if (inst.AA) @@ -104,8 +104,8 @@ void Jit64::bcx(UGeckoInstruction inst) // USES_CR - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); FixupBranch pCTRDontBranch; if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR @@ -151,8 +151,8 @@ void Jit64::bcctrx(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITBranchOff) - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); // bcctrx doesn't decrement and/or test CTR _dbg_assert_msg_(POWERPC, inst.BO_2 & BO_DONT_DECREMENT_FLAG, "bcctrx with decrement and test CTR option is invalid!"); @@ -202,8 +202,8 @@ void Jit64::bclrx(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITBranchOff) - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); FixupBranch pCTRDontBranch; if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index c35913302b..228fd78929 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -386,8 +386,8 @@ void Jit64::cmpXX(UGeckoInstruction inst) { js.downcountAmount++; - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); int test_bit = 8 >> (js.next_inst.BI & 3); u8 conditionResult = (js.next_inst.BO & BO_BRANCH_IF_TRUE) ? test_bit : 0; @@ -485,8 +485,8 @@ void Jit64::cmpXX(UGeckoInstruction inst) // if (rand() & 1) // std::swap(destination1, destination2), condition = !condition; - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); FixupBranch pLesser = J_CC(less_than); FixupBranch pGreater = J_CC(greater_than); MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x2)); // == 0 @@ -2182,8 +2182,8 @@ void Jit64::twx(UGeckoInstruction inst) s32 a = inst.RA; - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); if (inst.OPCD == 3) // twi CMP(32, gpr.R(a), gpr.R(inst.RB)); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp index 3c0732c692..0f5a23a1da 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -102,8 +102,8 @@ void Jit64::mtmsr(UGeckoInstruction inst) } MOV(32, M(&MSR), gpr.R(inst.RS)); gpr.UnlockAll(); - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); + gpr.Flush(); + fpr.Flush(); // If some exceptions are pending and EE are now enabled, force checking // external exceptions when going out of mtmsr in order to execute delayed From c800918fd812b79679571cd6968bc461fbd0c467 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 2 Jun 2014 09:52:48 +0200 Subject: [PATCH 02/14] RegCache64: remove unused functions --- .../Core/Core/PowerPC/Jit64/JitRegCache.cpp | 20 ------------------- Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 15 -------------- 2 files changed, 35 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index bb26a3e6b3..55376a46a2 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -13,12 +13,8 @@ RegCache::RegCache() : emit(nullptr) { memset(locks, 0, sizeof(locks)); memset(xlocks, 0, sizeof(xlocks)); - memset(saved_locks, 0, sizeof(saved_locks)); - memset(saved_xlocks, 0, sizeof(saved_xlocks)); memset(regs, 0, sizeof(regs)); memset(xregs, 0, sizeof(xregs)); - memset(saved_regs, 0, sizeof(saved_regs)); - memset(saved_xregs, 0, sizeof(saved_xregs)); } void RegCache::Start(PPCAnalyst::BlockRegStats &stats) @@ -117,22 +113,6 @@ X64Reg RegCache::GetFreeXReg() return (X64Reg) -1; } -void RegCache::SaveState() -{ - memcpy(saved_locks, locks, sizeof(locks)); - memcpy(saved_xlocks, xlocks, sizeof(xlocks)); - memcpy(saved_regs, regs, sizeof(regs)); - memcpy(saved_xregs, xregs, sizeof(xregs)); -} - -void RegCache::LoadState() -{ - memcpy(xlocks, saved_xlocks, sizeof(xlocks)); - memcpy(locks, saved_locks, sizeof(locks)); - memcpy(regs, saved_regs, sizeof(regs)); - memcpy(xregs, saved_xregs, sizeof(xregs)); -} - void RegCache::FlushR(X64Reg reg) { if (reg >= NUMXREGS) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index fe2880d80b..15361b36e8 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -8,13 +8,6 @@ using namespace Gen; -enum GrabMode -{ - M_READ = 1, - M_WRITE = 2, - M_READWRITE = 3, -}; - struct PPCCachedReg { OpArg location; @@ -41,17 +34,12 @@ class RegCache { private: bool locks[32]; - bool saved_locks[32]; - bool saved_xlocks[NUMXREGS]; protected: bool xlocks[NUMXREGS]; PPCCachedReg regs[32]; X64CachedReg xregs[NUMXREGS]; - PPCCachedReg saved_regs[32]; - X64CachedReg saved_xregs[NUMXREGS]; - virtual const int *GetAllocationOrder(int &count) = 0; XEmitter *emit; @@ -113,9 +101,6 @@ public: X64Reg GetFreeXReg(); - - void SaveState(); - void LoadState(); }; class GPRRegCache : public RegCache From 60898124825b3722bb12360d6a332118aed7568e Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 2 Jun 2014 13:02:52 +0200 Subject: [PATCH 03/14] RegCache64: move x?locks into register structs --- .../Core/Core/PowerPC/Jit64/JitRegCache.cpp | 46 +++++++++---------- Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 8 ++-- 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index 55376a46a2..05d1e8e2e4 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -11,8 +11,6 @@ using namespace PowerPC; RegCache::RegCache() : emit(nullptr) { - memset(locks, 0, sizeof(locks)); - memset(xlocks, 0, sizeof(xlocks)); memset(regs, 0, sizeof(regs)); memset(xregs, 0, sizeof(xregs)); } @@ -23,7 +21,7 @@ void RegCache::Start(PPCAnalyst::BlockRegStats &stats) { xregs[i].free = true; xregs[i].dirty = false; - xlocks[i] = false; + xregs[i].locked = false; } for (int i = 0; i < 32; i++) { @@ -51,34 +49,34 @@ void RegCache::Start(PPCAnalyst::BlockRegStats &stats) // these are powerpc reg indices void RegCache::Lock(int p1, int p2, int p3, int p4) { - locks[p1] = true; - if (p2 != 0xFF) locks[p2] = true; - if (p3 != 0xFF) locks[p3] = true; - if (p4 != 0xFF) locks[p4] = true; + regs[p1].locked = true; + if (p2 != 0xFF) regs[p2].locked = true; + if (p3 != 0xFF) regs[p3].locked = true; + if (p4 != 0xFF) regs[p4].locked = true; } // these are x64 reg indices void RegCache::LockX(int x1, int x2, int x3, int x4) { - if (xlocks[x1]) { + if (xregs[x1].locked) { PanicAlert("RegCache: x %i already locked!", x1); } - xlocks[x1] = true; - if (x2 != 0xFF) xlocks[x2] = true; - if (x3 != 0xFF) xlocks[x3] = true; - if (x4 != 0xFF) xlocks[x4] = true; + xregs[x1].locked = true; + if (x2 != 0xFF) xregs[x2].locked = true; + if (x3 != 0xFF) xregs[x3].locked = true; + if (x4 != 0xFF) xregs[x4].locked = true; } void RegCache::UnlockAll() { - for (auto& lock : locks) - lock = false; + for (auto& reg : regs) + reg.locked = false; } void RegCache::UnlockAllX() { - for (auto& xlock : xlocks) - xlock = false; + for (auto& xreg : xregs) + xreg.locked = false; } X64Reg RegCache::GetFreeXReg() @@ -88,7 +86,7 @@ X64Reg RegCache::GetFreeXReg() for (int i = 0; i < aCount; i++) { X64Reg xr = (X64Reg)aOrder[i]; - if (!xlocks[xr] && xregs[xr].free) + if (!xregs[xr].locked && xregs[xr].free) { return (X64Reg)xr; } @@ -99,10 +97,10 @@ X64Reg RegCache::GetFreeXReg() for (int i = 0; i < aCount; i++) { X64Reg xr = (X64Reg)aOrder[i]; - if (xlocks[xr]) + if (xregs[xr].locked) continue; int preg = xregs[xr].ppcReg; - if (!locks[preg]) + if (!regs[preg].locked) { StoreFromRegister(preg); return xr; @@ -132,7 +130,7 @@ int RegCache::SanityCheck() const if (regs[i].location.IsSimpleReg()) { Gen::X64Reg simple = regs[i].location.GetSimpleReg(); - if (xlocks[simple]) + if (xregs[simple].locked) return 1; if (xregs[simple].ppcReg != i) return 2; @@ -238,7 +236,7 @@ void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty) { X64Reg xr = GetFreeXReg(); if (xregs[xr].dirty) PanicAlert("Xreg already dirty"); - if (xlocks[xr]) PanicAlert("GetFreeXReg returned locked register"); + if (xregs[xr].locked) PanicAlert("GetFreeXReg returned locked register"); xregs[xr].free = false; xregs[xr].ppcReg = i; xregs[xr].dirty = makeDirty || regs[i].location.IsImm(); @@ -262,7 +260,7 @@ void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty) xregs[RX(i)].dirty |= makeDirty; } - if (xlocks[RX(i)]) + if (xregs[RX(i)].locked) { PanicAlert("Seriously WTF, this reg should have been flushed"); } @@ -346,13 +344,13 @@ void RegCache::Flush() { for (int i = 0; i < NUMXREGS; i++) { - if (xlocks[i]) + if (xregs[i].locked) PanicAlert("Someone forgot to unlock X64 reg %i.", i); } for (int i = 0; i < 32; i++) { - if (locks[i]) + if (regs[i].locked) { PanicAlert("Someone forgot to unlock PPC reg %i (X64 reg %i).", i, RX(i)); } diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index 15361b36e8..45a7235e08 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -12,6 +12,7 @@ struct PPCCachedReg { OpArg location; bool away; // value not in source register + bool locked; }; struct X64CachedReg @@ -19,6 +20,7 @@ struct X64CachedReg int ppcReg; bool dirty; bool free; + bool locked; }; typedef int XReg; @@ -32,11 +34,7 @@ typedef int PReg; class RegCache { -private: - bool locks[32]; - protected: - bool xlocks[NUMXREGS]; PPCCachedReg regs[32]; X64CachedReg xregs[NUMXREGS]; @@ -91,7 +89,7 @@ public: bool IsFreeX(int xreg) const { - return xregs[xreg].free && !xlocks[xreg]; + return xregs[xreg].free && !xregs[xreg].locked; } bool IsBound(int preg) const From 8693e0abaaff92f785ecb9ee1772793d44c4b012 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 2 Jun 2014 13:13:21 +0200 Subject: [PATCH 04/14] RegCache64: Use std::array --- .../Core/Core/PowerPC/Jit64/JitRegCache.cpp | 28 +++++++++---------- Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 6 ++-- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index 05d1e8e2e4..a8f7e82ddc 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -11,22 +11,22 @@ using namespace PowerPC; RegCache::RegCache() : emit(nullptr) { - memset(regs, 0, sizeof(regs)); - memset(xregs, 0, sizeof(xregs)); } void RegCache::Start(PPCAnalyst::BlockRegStats &stats) { - for (int i = 0; i < NUMXREGS; i++) + for (auto& xreg : xregs) { - xregs[i].free = true; - xregs[i].dirty = false; - xregs[i].locked = false; + xreg.free = true; + xreg.dirty = false; + xreg.locked = false; + xreg.ppcReg = -1; } - for (int i = 0; i < 32; i++) + for (int i = 0; i < (int)regs.size(); i++) { regs[i].location = GetDefaultLocation(i); regs[i].away = false; + regs[i].locked = false; } // todo: sort to find the most popular regs @@ -113,7 +113,7 @@ X64Reg RegCache::GetFreeXReg() void RegCache::FlushR(X64Reg reg) { - if (reg >= NUMXREGS) + if (reg >= xregs.size()) PanicAlert("Flushing non existent reg"); if (!xregs[reg].free) { @@ -123,7 +123,7 @@ void RegCache::FlushR(X64Reg reg) int RegCache::SanityCheck() const { - for (int i = 0; i < 32; i++) + for (int i = 0; i < (int)regs.size(); i++) { if (regs[i].away) { @@ -243,7 +243,7 @@ void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty) OpArg newloc = ::Gen::R(xr); if (doLoad) emit->MOV(32, newloc, regs[i].location); - for (int j = 0; j < 32; j++) + for (int j = 0; j < (int)regs.size(); j++) { if (i != j && regs[j].location.IsSimpleReg() && regs[j].location.GetSimpleReg() == xr) { @@ -299,7 +299,7 @@ void FPURegCache::BindToRegister(int i, bool doLoad, bool makeDirty) { // Reg is at home in the memory register file. Let's pull it out. X64Reg xr = GetFreeXReg(); - _assert_msg_(DYNA_REC, xr < NUMXREGS, "WTF - load - invalid reg"); + _assert_msg_(DYNA_REC, xr < xregs.size(), "WTF - load - invalid reg"); xregs[xr].ppcReg = i; xregs[xr].free = false; xregs[xr].dirty = makeDirty; @@ -328,7 +328,7 @@ void FPURegCache::StoreFromRegister(int i) if (regs[i].away) { X64Reg xr = regs[i].location.GetSimpleReg(); - _assert_msg_(DYNA_REC, xr < NUMXREGS, "WTF - store - invalid reg"); + _assert_msg_(DYNA_REC, xr < xregs.size(), "WTF - store - invalid reg"); OpArg newLoc = GetDefaultLocation(i); if (xregs[xr].dirty) emit->MOVAPD(newLoc, xr); @@ -342,13 +342,13 @@ void FPURegCache::StoreFromRegister(int i) void RegCache::Flush() { - for (int i = 0; i < NUMXREGS; i++) + for (int i = 0; i < (int)xregs.size(); i++) { if (xregs[i].locked) PanicAlert("Someone forgot to unlock X64 reg %i.", i); } - for (int i = 0; i < 32; i++) + for (int i = 0; i < (int)regs.size(); i++) { if (regs[i].locked) { diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index 45a7235e08..534867d2bc 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -4,6 +4,8 @@ #pragma once +#include + #include "Common/x64Emitter.h" using namespace Gen; @@ -35,8 +37,8 @@ typedef int PReg; class RegCache { protected: - PPCCachedReg regs[32]; - X64CachedReg xregs[NUMXREGS]; + std::array regs; + std::array xregs; virtual const int *GetAllocationOrder(int &count) = 0; From fd9bfddde75317df645740a8698a65f8cc18e3c9 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 2 Jun 2014 13:26:31 +0200 Subject: [PATCH 05/14] RegCache64: devirtualize RegCache::Start --- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 4 ++-- Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp | 12 +----------- Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 4 +--- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 6cd5082dc6..bf18f33b24 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -468,8 +468,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc // Start up the register allocators // They use the information in gpa/fpa to preload commonly used registers. - gpr.Start(js.gpa); - fpr.Start(js.fpa); + gpr.Start(); + fpr.Start(); js.downcountAmount = 0; if (!Core::g_CoreStartupParameter.bEnableDebugging) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index a8f7e82ddc..d121a9d808 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -13,7 +13,7 @@ RegCache::RegCache() : emit(nullptr) { } -void RegCache::Start(PPCAnalyst::BlockRegStats &stats) +void RegCache::Start() { for (auto& xreg : xregs) { @@ -163,16 +163,6 @@ void GPRRegCache::SetImmediate32(int preg, u32 immValue) regs[preg].location = Imm32(immValue); } -void GPRRegCache::Start(PPCAnalyst::BlockRegStats &stats) -{ - RegCache::Start(stats); -} - -void FPURegCache::Start(PPCAnalyst::BlockRegStats &stats) -{ - RegCache::Start(stats); -} - const int *GPRRegCache::GetAllocationOrder(int &count) { static const int allocationOrder[] = diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index 534867d2bc..674b72bcd8 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -48,7 +48,7 @@ public: RegCache(); virtual ~RegCache() {} - virtual void Start(PPCAnalyst::BlockRegStats &stats) = 0; + void Start(); void DiscardRegContentsIfCached(int preg); void SetEmitter(XEmitter *emitter) {emit = emitter;} @@ -106,7 +106,6 @@ public: class GPRRegCache : public RegCache { public: - void Start(PPCAnalyst::BlockRegStats &stats) override; void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) override; void StoreFromRegister(int preg) override; OpArg GetDefaultLocation(int reg) const override; @@ -118,7 +117,6 @@ public: class FPURegCache : public RegCache { public: - void Start(PPCAnalyst::BlockRegStats &stats) override; void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) override; void StoreFromRegister(int preg) override; const int *GetAllocationOrder(int &count) override; From 9e9b71fa87d81f032323e49f1e0122e6a9d3ee82 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 2 Jun 2014 13:55:50 +0200 Subject: [PATCH 06/14] RegCache: merge fpr+gpr StoreFromRegister --- .../Core/Core/PowerPC/Jit64/JitRegCache.cpp | 26 +++++++------------ Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 7 ++--- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index d121a9d808..b35a823ee4 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -256,7 +256,7 @@ void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty) } } -void GPRRegCache::StoreFromRegister(int i) +void RegCache::StoreFromRegister(int i) { if (regs[i].away) { @@ -276,12 +276,17 @@ void GPRRegCache::StoreFromRegister(int i) } OpArg newLoc = GetDefaultLocation(i); if (doStore) - emit->MOV(32, newLoc, regs[i].location); + StoreRegister(i, newLoc); regs[i].location = newLoc; regs[i].away = false; } } +void GPRRegCache::StoreRegister(int preg, OpArg newLoc) +{ + emit->MOV(32, newLoc, regs[preg].location); +} + void FPURegCache::BindToRegister(int i, bool doLoad, bool makeDirty) { _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - load - imm"); @@ -312,22 +317,9 @@ void FPURegCache::BindToRegister(int i, bool doLoad, bool makeDirty) } } -void FPURegCache::StoreFromRegister(int i) +void FPURegCache::StoreRegister(int preg, OpArg newLoc) { - _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - store - imm"); - if (regs[i].away) - { - X64Reg xr = regs[i].location.GetSimpleReg(); - _assert_msg_(DYNA_REC, xr < xregs.size(), "WTF - store - invalid reg"); - OpArg newLoc = GetDefaultLocation(i); - if (xregs[xr].dirty) - emit->MOVAPD(newLoc, xr); - xregs[xr].free = true; - xregs[xr].dirty = false; - xregs[xr].ppcReg = -1; - regs[i].location = newLoc; - regs[i].away = false; - } + emit->MOVAPD(newLoc, regs[preg].location.GetSimpleReg()); } void RegCache::Flush() diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index 674b72bcd8..48517b27b0 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -71,7 +71,8 @@ public: //TODO - instead of doload, use "read", "write" //read only will not set dirty flag virtual void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) = 0; - virtual void StoreFromRegister(int preg) = 0; + void StoreFromRegister(int preg); + virtual void StoreRegister(int preg, OpArg newLoc) = 0; const OpArg &R(int preg) const {return regs[preg].location;} X64Reg RX(int preg) const @@ -107,7 +108,7 @@ class GPRRegCache : public RegCache { public: void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) override; - void StoreFromRegister(int preg) override; + void StoreRegister(int preg, OpArg newLoc) override; OpArg GetDefaultLocation(int reg) const override; const int *GetAllocationOrder(int &count) override; void SetImmediate32(int preg, u32 immValue); @@ -118,7 +119,7 @@ class FPURegCache : public RegCache { public: void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) override; - void StoreFromRegister(int preg) override; + void StoreRegister(int preg, OpArg newLoc) override; const int *GetAllocationOrder(int &count) override; OpArg GetDefaultLocation(int reg) const override; }; From 38c3812a60c44f492c5cb5844dd5ca5a9a40d3fc Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 2 Jun 2014 14:11:33 +0200 Subject: [PATCH 07/14] RegCache: merge fpr+gpr BindToRegister --- .../Core/Core/PowerPC/Jit64/JitRegCache.cpp | 41 ++++++------------- Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 7 ++-- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index b35a823ee4..97865a7b3f 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -217,7 +217,7 @@ void RegCache::KillImmediate(int preg, bool doLoad, bool makeDirty) } } -void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty) +void RegCache::BindToRegister(int i, bool doLoad, bool makeDirty) { if (!regs[i].away && regs[i].location.IsImm()) PanicAlert("Bad immediate"); @@ -230,9 +230,8 @@ void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty) xregs[xr].free = false; xregs[xr].ppcReg = i; xregs[xr].dirty = makeDirty || regs[i].location.IsImm(); - OpArg newloc = ::Gen::R(xr); if (doLoad) - emit->MOV(32, newloc, regs[i].location); + LoadRegister(i, xr); for (int j = 0; j < (int)regs.size(); j++) { if (i != j && regs[j].location.IsSimpleReg() && regs[j].location.GetSimpleReg() == xr) @@ -241,7 +240,7 @@ void GPRRegCache::BindToRegister(int i, bool doLoad, bool makeDirty) } } regs[i].away = true; - regs[i].location = newloc; + regs[i].location = ::Gen::R(xr); } else { @@ -282,39 +281,23 @@ void RegCache::StoreFromRegister(int i) } } +void GPRRegCache::LoadRegister(int preg, X64Reg newLoc) +{ + emit->MOV(32, ::Gen::R(newLoc), regs[preg].location); +} + void GPRRegCache::StoreRegister(int preg, OpArg newLoc) { emit->MOV(32, newLoc, regs[preg].location); } -void FPURegCache::BindToRegister(int i, bool doLoad, bool makeDirty) +void FPURegCache::LoadRegister(int preg, X64Reg newLoc) { - _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - load - imm"); - if (!regs[i].away) + if (!regs[preg].location.IsImm() && (regs[preg].location.offset & 0xF)) { - // Reg is at home in the memory register file. Let's pull it out. - X64Reg xr = GetFreeXReg(); - _assert_msg_(DYNA_REC, xr < xregs.size(), "WTF - load - invalid reg"); - xregs[xr].ppcReg = i; - xregs[xr].free = false; - xregs[xr].dirty = makeDirty; - OpArg newloc = ::Gen::R(xr); - if (doLoad) - { - if (!regs[i].location.IsImm() && (regs[i].location.offset & 0xF)) - { - PanicAlert("WARNING - misaligned fp register location %i", i); - } - emit->MOVAPD(xr, regs[i].location); - } - regs[i].location = newloc; - regs[i].away = true; - } - else - { - // There are no immediates in the FPR reg file, so we already had this in a register. Make dirty as necessary. - xregs[RX(i)].dirty |= makeDirty; + PanicAlert("WARNING - misaligned fp register location %i", preg); } + emit->MOVAPD(newLoc, regs[preg].location); } void FPURegCache::StoreRegister(int preg, OpArg newLoc) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index 48517b27b0..45a8b623cc 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -70,9 +70,10 @@ public: //TODO - instead of doload, use "read", "write" //read only will not set dirty flag - virtual void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) = 0; + void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true); void StoreFromRegister(int preg); virtual void StoreRegister(int preg, OpArg newLoc) = 0; + virtual void LoadRegister(int preg, X64Reg newLoc) = 0; const OpArg &R(int preg) const {return regs[preg].location;} X64Reg RX(int preg) const @@ -107,8 +108,8 @@ public: class GPRRegCache : public RegCache { public: - void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) override; void StoreRegister(int preg, OpArg newLoc) override; + void LoadRegister(int preg, X64Reg newLoc) override; OpArg GetDefaultLocation(int reg) const override; const int *GetAllocationOrder(int &count) override; void SetImmediate32(int preg, u32 immValue); @@ -118,8 +119,8 @@ public: class FPURegCache : public RegCache { public: - void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) override; void StoreRegister(int preg, OpArg newLoc) override; + void LoadRegister(int preg, X64Reg newLoc) override; const int *GetAllocationOrder(int &count) override; OpArg GetDefaultLocation(int reg) const override; }; From 0cd9eea99ec677ab4860c4cefbb96f8ca4c9fd58 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 2 Jun 2014 14:21:40 +0200 Subject: [PATCH 08/14] RegCache: make state clear optional on flushes --- .../Core/Core/PowerPC/Jit64/JitRegCache.cpp | 30 +++++++++---------- Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 6 ++-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index 97865a7b3f..40693326c7 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -255,7 +255,7 @@ void RegCache::BindToRegister(int i, bool doLoad, bool makeDirty) } } -void RegCache::StoreFromRegister(int i) +void RegCache::StoreFromRegister(int i, bool clearState) { if (regs[i].away) { @@ -263,10 +263,13 @@ void RegCache::StoreFromRegister(int i) if (regs[i].location.IsSimpleReg()) { X64Reg xr = RX(i); - xregs[xr].free = true; - xregs[xr].ppcReg = -1; doStore = xregs[xr].dirty; - xregs[xr].dirty = false; + if(clearState) + { + xregs[xr].free = true; + xregs[xr].ppcReg = -1; + xregs[xr].dirty = false; + } } else { @@ -276,8 +279,11 @@ void RegCache::StoreFromRegister(int i) OpArg newLoc = GetDefaultLocation(i); if (doStore) StoreRegister(i, newLoc); - regs[i].location = newLoc; - regs[i].away = false; + if(clearState) + { + regs[i].location = newLoc; + regs[i].away = false; + } } } @@ -305,7 +311,7 @@ void FPURegCache::StoreRegister(int preg, OpArg newLoc) emit->MOVAPD(newLoc, regs[preg].location.GetSimpleReg()); } -void RegCache::Flush() +void RegCache::Flush(bool clearState) { for (int i = 0; i < (int)xregs.size(); i++) { @@ -321,15 +327,9 @@ void RegCache::Flush() } if (regs[i].away) { - if (regs[i].location.IsSimpleReg()) + if (regs[i].location.IsSimpleReg() || regs[i].location.IsImm()) { - X64Reg xr = RX(i); - StoreFromRegister(i); - xregs[xr].dirty = false; - } - else if (regs[i].location.IsImm()) - { - StoreFromRegister(i); + StoreFromRegister(i, clearState); } else { diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index 45a8b623cc..97f2f57d49 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -63,15 +63,15 @@ public: FlushR(reg1); FlushR(reg2); LockX(reg1); LockX(reg2); } - virtual void Flush(); - virtual void Flush(PPCAnalyst::CodeOp *op) {Flush();} + void Flush(bool clearState = true); + void Flush(PPCAnalyst::CodeOp *op) {Flush();} int SanityCheck() const; void KillImmediate(int preg, bool doLoad, bool makeDirty); //TODO - instead of doload, use "read", "write" //read only will not set dirty flag void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true); - void StoreFromRegister(int preg); + void StoreFromRegister(int preg, bool clearState = true); virtual void StoreRegister(int preg, OpArg newLoc) = 0; virtual void LoadRegister(int preg, X64Reg newLoc) = 0; From 541bfd071e5842588d3f491652101f77cededc7f Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 2 Jun 2014 14:32:00 +0200 Subject: [PATCH 09/14] Jit64: Don't flush the regcache on bcx --- Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp index a30929b18b..afb7325a21 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp @@ -104,17 +104,14 @@ void Jit64::bcx(UGeckoInstruction inst) // USES_CR - gpr.Flush(); - fpr.Flush(); - FixupBranch pCTRDontBranch; if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR { SUB(32, M(&CTR), Imm8(1)); if (inst.BO & BO_BRANCH_IF_CTR_0) - pCTRDontBranch = J_CC(CC_NZ); + pCTRDontBranch = J_CC(CC_NZ, true); else - pCTRDontBranch = J_CC(CC_Z); + pCTRDontBranch = J_CC(CC_Z, true); } FixupBranch pConditionDontBranch; @@ -122,9 +119,9 @@ void Jit64::bcx(UGeckoInstruction inst) { TEST(8, M(&PowerPC::ppcState.cr_fast[inst.BI >> 2]), Imm8(8 >> (inst.BI & 3))); if (inst.BO & BO_BRANCH_IF_TRUE) // Conditional branch - pConditionDontBranch = J_CC(CC_Z); + pConditionDontBranch = J_CC(CC_Z, true); else - pConditionDontBranch = J_CC(CC_NZ); + pConditionDontBranch = J_CC(CC_NZ, true); } if (inst.LK) @@ -135,6 +132,9 @@ void Jit64::bcx(UGeckoInstruction inst) destination = SignExt16(inst.BD << 2); else destination = js.compilerPC + SignExt16(inst.BD << 2); + + gpr.Flush(false); + fpr.Flush(false); WriteExit(destination); if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) @@ -143,7 +143,11 @@ void Jit64::bcx(UGeckoInstruction inst) SetJumpTarget( pCTRDontBranch ); if (!analyzer.HasOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE)) + { + gpr.Flush(); + fpr.Flush(); WriteExit(js.compilerPC + 4); + } } void Jit64::bcctrx(UGeckoInstruction inst) From 5e1a465d50f35b3c207389c0677f7e4a486213b4 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 10 Jun 2014 02:42:00 -0500 Subject: [PATCH 10/14] Change register cache to using an enum to determine flush mode. This is easier to identify what the flush is doing rather than a "true" as argument. --- Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp | 10 +++++----- Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 10 ++++++++-- Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp | 4 ++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index 40693326c7..122cc7f218 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -255,7 +255,7 @@ void RegCache::BindToRegister(int i, bool doLoad, bool makeDirty) } } -void RegCache::StoreFromRegister(int i, bool clearState) +void RegCache::StoreFromRegister(int i, FlushMode mode) { if (regs[i].away) { @@ -264,7 +264,7 @@ void RegCache::StoreFromRegister(int i, bool clearState) { X64Reg xr = RX(i); doStore = xregs[xr].dirty; - if(clearState) + if(mode == FLUSH_ALL) { xregs[xr].free = true; xregs[xr].ppcReg = -1; @@ -279,7 +279,7 @@ void RegCache::StoreFromRegister(int i, bool clearState) OpArg newLoc = GetDefaultLocation(i); if (doStore) StoreRegister(i, newLoc); - if(clearState) + if(mode == FLUSH_ALL) { regs[i].location = newLoc; regs[i].away = false; @@ -311,7 +311,7 @@ void FPURegCache::StoreRegister(int preg, OpArg newLoc) emit->MOVAPD(newLoc, regs[preg].location.GetSimpleReg()); } -void RegCache::Flush(bool clearState) +void RegCache::Flush(FlushMode mode) { for (int i = 0; i < (int)xregs.size(); i++) { @@ -329,7 +329,7 @@ void RegCache::Flush(bool clearState) { if (regs[i].location.IsSimpleReg() || regs[i].location.IsImm()) { - StoreFromRegister(i, clearState); + StoreFromRegister(i, mode); } else { diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index 97f2f57d49..62fca8d009 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -10,6 +10,12 @@ using namespace Gen; +enum FlushMode +{ + FLUSH_ALL, + FLUSH_MAINTAIN_STATE, +}; + struct PPCCachedReg { OpArg location; @@ -63,7 +69,7 @@ public: FlushR(reg1); FlushR(reg2); LockX(reg1); LockX(reg2); } - void Flush(bool clearState = true); + void Flush(FlushMode mode = FLUSH_ALL); void Flush(PPCAnalyst::CodeOp *op) {Flush();} int SanityCheck() const; void KillImmediate(int preg, bool doLoad, bool makeDirty); @@ -71,7 +77,7 @@ public: //TODO - instead of doload, use "read", "write" //read only will not set dirty flag void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true); - void StoreFromRegister(int preg, bool clearState = true); + void StoreFromRegister(int preg, FlushMode mode = FLUSH_ALL); virtual void StoreRegister(int preg, OpArg newLoc) = 0; virtual void LoadRegister(int preg, X64Reg newLoc) = 0; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp index afb7325a21..66b728f1bf 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp @@ -133,8 +133,8 @@ void Jit64::bcx(UGeckoInstruction inst) else destination = js.compilerPC + SignExt16(inst.BD << 2); - gpr.Flush(false); - fpr.Flush(false); + gpr.Flush(FLUSH_MAINTAIN_STATE); + fpr.Flush(FLUSH_MAINTAIN_STATE); WriteExit(destination); if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) From b99edd62022f14c3b7a5d812d10d8edbc3ee79e0 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 10 Jun 2014 02:44:16 -0500 Subject: [PATCH 11/14] Add conditional register cache flushing to JIT64's bcctrx conditional route. --- Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp index 66b728f1bf..1c80474e04 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp @@ -155,9 +155,6 @@ void Jit64::bcctrx(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITBranchOff) - gpr.Flush(); - fpr.Flush(); - // bcctrx doesn't decrement and/or test CTR _dbg_assert_msg_(POWERPC, inst.BO_2 & BO_DONT_DECREMENT_FLAG, "bcctrx with decrement and test CTR option is invalid!"); @@ -166,6 +163,9 @@ void Jit64::bcctrx(UGeckoInstruction inst) // BO_2 == 1z1zz -> b always //NPC = CTR & 0xfffffffc; + gpr.Flush(); + fpr.Flush(); + MOV(32, R(EAX), M(&CTR)); if (inst.LK_3) MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4; @@ -192,6 +192,9 @@ void Jit64::bcctrx(UGeckoInstruction inst) //MOV(32, M(&PC), R(EAX)); => Already done in WriteExitDestInEAX() if (inst.LK_3) MOV(32, M(&LR), Imm32(js.compilerPC + 4)); // LR = PC + 4; + + gpr.Flush(FLUSH_MAINTAIN_STATE); + fpr.Flush(FLUSH_MAINTAIN_STATE); WriteExitDestInEAX(); // Would really like to continue the block here, but it ends. TODO. SetJumpTarget(b); From 06e8c7d7c938dad12a260dc05f39e0fc170cbc87 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 10 Jun 2014 02:45:04 -0500 Subject: [PATCH 12/14] Add conditional register cache flushing to JIT64's bcx instruction. --- Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp index 1c80474e04..494b9cee1c 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp @@ -209,9 +209,6 @@ void Jit64::bclrx(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITBranchOff) - gpr.Flush(); - fpr.Flush(); - FixupBranch pCTRDontBranch; if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR { @@ -242,6 +239,9 @@ void Jit64::bclrx(UGeckoInstruction inst) AND(32, R(EAX), Imm32(0xFFFFFFFC)); if (inst.LK) MOV(32, M(&LR), Imm32(js.compilerPC + 4)); + + gpr.Flush(FLUSH_MAINTAIN_STATE); + fpr.Flush(FLUSH_MAINTAIN_STATE); WriteExitDestInEAX(); if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) From b4ec70f0ac7fe8a527227bb21554c8893dfbffa9 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 10 Jun 2014 02:46:10 -0500 Subject: [PATCH 13/14] Add conditional register cache flushing to JIT64's twx instruction. --- Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index 228fd78929..91eb133c36 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -2182,9 +2182,6 @@ void Jit64::twx(UGeckoInstruction inst) s32 a = inst.RA; - gpr.Flush(); - fpr.Flush(); - if (inst.OPCD == 3) // twi CMP(32, gpr.R(a), gpr.R(inst.RB)); else // tw @@ -2209,6 +2206,10 @@ void Jit64::twx(UGeckoInstruction inst) } LOCK(); OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_PROGRAM)); + + gpr.Flush(FLUSH_MAINTAIN_STATE); + fpr.Flush(FLUSH_MAINTAIN_STATE); + WriteExceptionExit(); SetJumpTarget(dont_trap); From c2b6a41e6b5cfdad3255c0333e67f8f4bdf1a789 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Tue, 10 Jun 2014 02:52:15 -0500 Subject: [PATCH 14/14] Fix a few code style remarks. Removes some casting of size_t to int. --- Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index 122cc7f218..fcf9e64839 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -22,7 +22,7 @@ void RegCache::Start() xreg.locked = false; xreg.ppcReg = -1; } - for (int i = 0; i < (int)regs.size(); i++) + for (size_t i = 0; i < regs.size(); i++) { regs[i].location = GetDefaultLocation(i); regs[i].away = false; @@ -264,7 +264,7 @@ void RegCache::StoreFromRegister(int i, FlushMode mode) { X64Reg xr = RX(i); doStore = xregs[xr].dirty; - if(mode == FLUSH_ALL) + if (mode == FLUSH_ALL) { xregs[xr].free = true; xregs[xr].ppcReg = -1; @@ -279,7 +279,7 @@ void RegCache::StoreFromRegister(int i, FlushMode mode) OpArg newLoc = GetDefaultLocation(i); if (doStore) StoreRegister(i, newLoc); - if(mode == FLUSH_ALL) + if (mode == FLUSH_ALL) { regs[i].location = newLoc; regs[i].away = false; @@ -313,17 +313,17 @@ void FPURegCache::StoreRegister(int preg, OpArg newLoc) void RegCache::Flush(FlushMode mode) { - for (int i = 0; i < (int)xregs.size(); i++) + for (size_t i = 0; i < xregs.size(); i++) { if (xregs[i].locked) - PanicAlert("Someone forgot to unlock X64 reg %i.", i); + PanicAlert("Someone forgot to unlock X64 reg %zu.", i); } - for (int i = 0; i < (int)regs.size(); i++) + for (size_t i = 0; i < regs.size(); i++) { if (regs[i].locked) { - PanicAlert("Someone forgot to unlock PPC reg %i (X64 reg %i).", i, RX(i)); + PanicAlert("Someone forgot to unlock PPC reg %zu (X64 reg %i).", i, RX(i)); } if (regs[i].away) { @@ -333,7 +333,7 @@ void RegCache::Flush(FlushMode mode) } else { - _assert_msg_(DYNA_REC,0,"Jit64 - Flush unhandled case, reg %i PC: %08x", i, PC); + _assert_msg_(DYNA_REC,0,"Jit64 - Flush unhandled case, reg %zu PC: %08x", i, PC); } } }