diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 67b4b5a4cf..bf18f33b24 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); } @@ -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) @@ -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..fcf9e64839 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -11,28 +11,22 @@ using namespace PowerPC; 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) +void RegCache::Start() { - for (int i = 0; i < NUMXREGS; i++) + for (auto& xreg : xregs) { - xregs[i].free = true; - xregs[i].dirty = false; - xlocks[i] = false; + xreg.free = true; + xreg.dirty = false; + xreg.locked = false; + xreg.ppcReg = -1; } - for (int i = 0; i < 32; i++) + for (size_t i = 0; i < regs.size(); i++) { regs[i].location = GetDefaultLocation(i); regs[i].away = false; + regs[i].locked = false; } // todo: sort to find the most popular regs @@ -55,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() @@ -92,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; } @@ -103,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; @@ -117,25 +111,9 @@ 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) + if (reg >= xregs.size()) PanicAlert("Flushing non existent reg"); if (!xregs[reg].free) { @@ -145,14 +123,14 @@ 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) { 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; @@ -185,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[] = @@ -249,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"); @@ -258,14 +226,13 @@ 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(); - OpArg newloc = ::Gen::R(xr); if (doLoad) - emit->MOV(32, newloc, regs[i].location); - for (int j = 0; j < 32; j++) + LoadRegister(i, xr); + for (int j = 0; j < (int)regs.size(); j++) { if (i != j && regs[j].location.IsSimpleReg() && regs[j].location.GetSimpleReg() == xr) { @@ -273,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,13 +249,13 @@ 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"); } } -void GPRRegCache::StoreFromRegister(int i) +void RegCache::StoreFromRegister(int i, FlushMode mode) { if (regs[i].away) { @@ -296,10 +263,13 @@ void GPRRegCache::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 (mode == FLUSH_ALL) + { + xregs[xr].free = true; + xregs[xr].ppcReg = -1; + xregs[xr].dirty = false; + } } else { @@ -308,89 +278,62 @@ void GPRRegCache::StoreFromRegister(int i) } OpArg newLoc = GetDefaultLocation(i); if (doStore) - emit->MOV(32, newLoc, regs[i].location); - regs[i].location = newLoc; - regs[i].away = false; - } -} - -void FPURegCache::BindToRegister(int i, bool doLoad, bool makeDirty) -{ - _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - load - imm"); - if (!regs[i].away) - { - // 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"); - xregs[xr].ppcReg = i; - xregs[xr].free = false; - xregs[xr].dirty = makeDirty; - OpArg newloc = ::Gen::R(xr); - if (doLoad) + StoreRegister(i, newLoc); + if (mode == FLUSH_ALL) { - 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 = false; } - 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; } } -void FPURegCache::StoreFromRegister(int i) +void GPRRegCache::LoadRegister(int preg, X64Reg newLoc) { - _assert_msg_(DYNA_REC, !regs[i].location.IsImm(), "WTF - store - imm"); - if (regs[i].away) + 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::LoadRegister(int preg, X64Reg newLoc) +{ + if (!regs[preg].location.IsImm() && (regs[preg].location.offset & 0xF)) { - X64Reg xr = regs[i].location.GetSimpleReg(); - _assert_msg_(DYNA_REC, xr < NUMXREGS, "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; + PanicAlert("WARNING - misaligned fp register location %i", preg); } + emit->MOVAPD(newLoc, regs[preg].location); +} + +void FPURegCache::StoreRegister(int preg, OpArg newLoc) +{ + emit->MOVAPD(newLoc, regs[preg].location.GetSimpleReg()); } void RegCache::Flush(FlushMode mode) { - for (int i = 0; i < NUMXREGS; i++) + for (size_t i = 0; i < xregs.size(); i++) { - if (xlocks[i]) - PanicAlert("Someone forgot to unlock X64 reg %i.", i); + if (xregs[i].locked) + PanicAlert("Someone forgot to unlock X64 reg %zu.", i); } - for (int i = 0; i < 32; i++) + for (size_t i = 0; i < regs.size(); i++) { - if (locks[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) { - 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, 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); } } } diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index b687f17d23..62fca8d009 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -4,25 +4,23 @@ #pragma once +#include + #include "Common/x64Emitter.h" using namespace Gen; + enum FlushMode { - FLUSH_ALL -}; - -enum GrabMode -{ - M_READ = 1, - M_WRITE = 2, - M_READWRITE = 3, + FLUSH_ALL, + FLUSH_MAINTAIN_STATE, }; struct PPCCachedReg { OpArg location; bool away; // value not in source register + bool locked; }; struct X64CachedReg @@ -30,6 +28,7 @@ struct X64CachedReg int ppcReg; bool dirty; bool free; + bool locked; }; typedef int XReg; @@ -43,18 +42,9 @@ typedef int PReg; 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]; + std::array regs; + std::array xregs; virtual const int *GetAllocationOrder(int &count) = 0; @@ -64,7 +54,7 @@ public: RegCache(); virtual ~RegCache() {} - virtual void Start(PPCAnalyst::BlockRegStats &stats) = 0; + void Start(); void DiscardRegContentsIfCached(int preg); void SetEmitter(XEmitter *emitter) {emit = emitter;} @@ -79,15 +69,17 @@ public: FlushR(reg1); FlushR(reg2); LockX(reg1); LockX(reg2); } - virtual void Flush(FlushMode mode); - virtual void Flush(PPCAnalyst::CodeOp *op) {Flush(FLUSH_ALL);} + void Flush(FlushMode mode = FLUSH_ALL); + 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 - virtual void BindToRegister(int preg, bool doLoad = true, bool makeDirty = true) = 0; - virtual void StoreFromRegister(int preg) = 0; + void BindToRegister(int preg, bool doLoad = true, bool makeDirty = 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; const OpArg &R(int preg) const {return regs[preg].location;} X64Reg RX(int preg) const @@ -107,7 +99,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 @@ -117,17 +109,13 @@ public: X64Reg GetFreeXReg(); - - void SaveState(); - void LoadState(); }; 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; + 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); @@ -137,9 +125,8 @@ 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; + 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; }; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp index 73d3c34294..494b9cee1c 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,17 +104,14 @@ void Jit64::bcx(UGeckoInstruction inst) // USES_CR - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); - 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(FLUSH_MAINTAIN_STATE); + fpr.Flush(FLUSH_MAINTAIN_STATE); 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) @@ -151,9 +155,6 @@ void Jit64::bcctrx(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITBranchOff) - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); - // 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!"); @@ -162,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; @@ -188,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); @@ -202,9 +209,6 @@ void Jit64::bclrx(UGeckoInstruction inst) INSTRUCTION_START JITDISABLE(bJITBranchOff) - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); - FixupBranch pCTRDontBranch; if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) // Decrement and test CTR { @@ -235,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) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index c35913302b..91eb133c36 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,9 +2182,6 @@ void Jit64::twx(UGeckoInstruction inst) s32 a = inst.RA; - gpr.Flush(FLUSH_ALL); - fpr.Flush(FLUSH_ALL); - 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); 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