diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 1248b1ab01..8cd4a08d2e 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -351,10 +351,8 @@ void Jit64::Shutdown() void Jit64::FallBackToInterpreter(UGeckoInstruction inst) { FlushCarry(); - gpr.Flush(BitSet32(0xFFFFFFFF), RegCache::FlushMode::Full, - RegCache::IgnoreDiscardedRegisters::Yes); - fpr.Flush(BitSet32(0xFFFFFFFF), RegCache::FlushMode::Full, - RegCache::IgnoreDiscardedRegisters::Yes); + gpr.Flush(RegCache::FlushMode::Full, RegCache::IgnoreDiscardedRegisters::Yes); + fpr.Flush(RegCache::FlushMode::Full, RegCache::IgnoreDiscardedRegisters::Yes); if (js.op->canEndBlock) { @@ -404,11 +402,8 @@ void Jit64::FallBackToInterpreter(UGeckoInstruction inst) SwitchToFarCode(); SetJumpTarget(exception); - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - - gpr.Flush(); - fpr.Flush(); + gpr.Flush(RegCache::FlushMode::MaintainState); + fpr.Flush(RegCache::FlushMode::MaintainState); MOV(32, PPCSTATE(pc), Imm32(js.op->address)); WriteExceptionExit(); @@ -1049,11 +1044,8 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) FixupBranch noCPInt = J_CC(CC_Z, Jump::Near); { - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - - gpr.Flush(); - fpr.Flush(); + gpr.Flush(RegCache::FlushMode::MaintainState); + fpr.Flush(RegCache::FlushMode::MaintainState); MOV(32, PPCSTATE(pc), Imm32(op.address)); WriteExternalExceptionExit(); @@ -1112,11 +1104,8 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) SwitchToFarCode(); SetJumpTarget(b1); { - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - - gpr.Flush(); - fpr.Flush(); + gpr.Flush(RegCache::FlushMode::MaintainState); + fpr.Flush(RegCache::FlushMode::MaintainState); // If a FPU exception occurs, the exception handler will read // from PC. Update PC with the latest value in case that happens. @@ -1211,13 +1200,10 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) m_exception_handler_at_loc[js.fastmemLoadStore] = GetWritableCodePtr(); } - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - - gpr.Revert(); - fpr.Revert(); - gpr.Flush(); - fpr.Flush(); + BitSet32 gpr_revertable = gpr.RegistersRevertable(); + BitSet32 fpr_revertable = fpr.RegistersRevertable(); + gpr.Flush(~gpr_revertable, RegCache::FlushMode::MaintainState); + fpr.Flush(~fpr_revertable, RegCache::FlushMode::MaintainState); MOV(32, PPCSTATE(pc), Imm32(op.address)); WriteExceptionExit(); @@ -1377,11 +1363,8 @@ void Jit64::FlushRegistersBeforeSlowAccess() BitSet32 fprs = mem_checks.GetFPRsUsedInConditions(); if (gprs || fprs) { - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - - gpr.Flush(gprs); - fpr.Flush(fprs); + gpr.Flush(gprs, RegCache::FlushMode::MaintainState); + fpr.Flush(fprs, RegCache::FlushMode::MaintainState); } } } diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp index 4667238720..70676dc198 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp @@ -197,10 +197,8 @@ void Jit64::bcx(UGeckoInstruction inst) } { - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - gpr.Flush(); - fpr.Flush(); + gpr.Flush(RegCache::FlushMode::MaintainState); + fpr.Flush(RegCache::FlushMode::MaintainState); WriteBranchWatch(js.compilerPC, js.op->branchTo, inst, {}); if (js.op->branchIsIdleLoop) @@ -268,10 +266,8 @@ void Jit64::bcctrx(UGeckoInstruction inst) MOV(32, PPCSTATE_LR, Imm32(js.compilerPC + 4)); // LR = PC + 4; { - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - gpr.Flush(); - fpr.Flush(); + gpr.Flush(RegCache::FlushMode::MaintainState); + fpr.Flush(RegCache::FlushMode::MaintainState); WriteBranchWatchDestInRSCRATCH(js.compilerPC, inst, BitSet32{RSCRATCH}); WriteExitDestInRSCRATCH(inst.LK_3, js.compilerPC + 4); // Would really like to continue the block here, but it ends. TODO. @@ -327,10 +323,8 @@ void Jit64::bclrx(UGeckoInstruction inst) MOV(32, PPCSTATE_LR, Imm32(js.compilerPC + 4)); { - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - gpr.Flush(); - fpr.Flush(); + gpr.Flush(RegCache::FlushMode::MaintainState); + fpr.Flush(RegCache::FlushMode::MaintainState); if (js.op->branchIsIdleLoop) { diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index 978951118c..ac600dc659 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -460,11 +460,8 @@ void Jit64::DoMergedBranchCondition() } { - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - - gpr.Flush(); - fpr.Flush(); + gpr.Flush(RegCache::FlushMode::MaintainState); + fpr.Flush(RegCache::FlushMode::MaintainState); DoMergedBranch(); } @@ -2555,9 +2552,6 @@ void Jit64::twX(UGeckoInstruction inst) { SwitchToFarCode(); - RCForkGuard gpr_guard = gpr.Fork(); - RCForkGuard fpr_guard = fpr.Fork(); - for (const FixupBranch& fixup : fixups) { SetJumpTarget(fixup); @@ -2566,8 +2560,8 @@ void Jit64::twX(UGeckoInstruction inst) OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_PROGRAM)); MOV(32, PPCSTATE_SRR1, Imm32(static_cast(ProgramExceptionCause::Trap))); - gpr.Flush(); - fpr.Flush(); + gpr.Flush(RegCache::FlushMode::MaintainState); + fpr.Flush(RegCache::FlushMode::MaintainState); MOV(32, PPCSTATE(pc), Imm32(js.compilerPC)); WriteExceptionExit(); diff --git a/Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h b/Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h index 99a6e47225..a80451760a 100644 --- a/Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h +++ b/Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h @@ -62,12 +62,6 @@ public: ASSERT(m_in_host_register); m_revertable = true; } - void SetRevert() - { - ASSERT(m_revertable); - m_revertable = false; - SetFlushed(false); - } void SetCommit() { ASSERT(m_revertable); diff --git a/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp index 592813011d..93bb14516e 100644 --- a/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp @@ -209,28 +209,6 @@ void RCX64Reg::Unlock() contents = std::monostate{}; } -RCForkGuard::RCForkGuard(RegCache& rc_) : rc(&rc_), m_regs(rc_.m_regs), m_xregs(rc_.m_xregs) -{ - ASSERT(!rc->IsAnyConstraintActive()); -} - -RCForkGuard::RCForkGuard(RCForkGuard&& other) noexcept - : rc(other.rc), m_regs(other.m_regs), m_xregs(other.m_xregs) -{ - other.rc = nullptr; -} - -void RCForkGuard::EndFork() -{ - if (!rc) - return; - - ASSERT(!rc->IsAnyConstraintActive()); - rc->m_regs = m_regs; - rc->m_xregs = m_xregs; - rc = nullptr; -} - RegCache::RegCache(Jit64& jit) : m_jit{jit} { } @@ -309,11 +287,6 @@ RCX64Reg RegCache::Scratch(X64Reg xr) return RCX64Reg{this, xr}; } -RCForkGuard RegCache::Fork() -{ - return RCForkGuard{*this}; -} - void RegCache::Discard(BitSet32 pregs) { ASSERT_MSG(DYNA_REC, std::ranges::none_of(m_xregs, &X64CachedReg::IsLocked), @@ -357,14 +330,16 @@ void RegCache::Reset(BitSet32 pregs) } } -void RegCache::Revert() +BitSet32 RegCache::RegistersRevertable() const { ASSERT(IsAllUnlocked()); - for (auto& reg : m_regs) + BitSet32 result; + for (size_t i = 0; i < m_regs.size(); i++) { - if (reg.IsRevertable()) - reg.SetRevert(); + if (m_regs[i].IsRevertable()) + result[i] = true; } + return result; } void RegCache::Commit() @@ -477,7 +452,8 @@ void RegCache::StoreFromRegister(preg_t i, FlushMode mode, if (mode == FlushMode::Full && m_regs[i].IsInHostRegister()) m_xregs[m_regs[i].GetHostRegister()].Unbind(); - m_regs[i].SetFlushed(mode != FlushMode::Full); + if (mode != FlushMode::MaintainState) + m_regs[i].SetFlushed(mode != FlushMode::Full); } X64Reg RegCache::GetFreeXReg() diff --git a/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h index 7a692a2b63..4e4a4cc86e 100644 --- a/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h @@ -94,28 +94,6 @@ private: std::variant contents; }; -class RCForkGuard -{ -public: - ~RCForkGuard() { EndFork(); } - RCForkGuard(RCForkGuard&&) noexcept; - - RCForkGuard(const RCForkGuard&) = delete; - RCForkGuard& operator=(const RCForkGuard&) = delete; - RCForkGuard& operator=(RCForkGuard&&) = delete; - - void EndFork(); - -private: - friend class RegCache; - - explicit RCForkGuard(RegCache& rc_); - - RegCache* rc; - std::array m_regs; - std::array m_xregs; -}; - class RegCache { public: @@ -123,6 +101,10 @@ public: { // All dirty registers get written back, and all registers get removed from the cache. Full, + // All dirty registers get written back, but the state of the cache is untouched. + // The host registers may get clobbered. This is intended for use when doing a block exit + // after a conditional branch. + MaintainState, // All dirty registers get written back and get set as no longer dirty. // No registers are removed from the cache. Undirty, @@ -176,12 +158,16 @@ public: RCX64Reg Scratch(); RCX64Reg Scratch(Gen::X64Reg xr); - RCForkGuard Fork(); void Discard(BitSet32 pregs); void Flush(BitSet32 pregs = BitSet32::AllTrue(32), FlushMode mode = FlushMode::Full, IgnoreDiscardedRegisters ignore_discarded_registers = IgnoreDiscardedRegisters::No); + void Flush(FlushMode mode, + IgnoreDiscardedRegisters ignore_discarded_registers = IgnoreDiscardedRegisters::No) + { + Flush(BitSet32::AllTrue(32), mode, ignore_discarded_registers); + } void Reset(BitSet32 pregs); - void Revert(); + BitSet32 RegistersRevertable() const; void Commit(); bool IsAllUnlocked() const; @@ -192,7 +178,6 @@ public: protected: friend class RCOpArg; friend class RCX64Reg; - friend class RCForkGuard; virtual Gen::OpArg GetDefaultLocation(preg_t preg) const = 0; virtual void StoreRegister(preg_t preg, const Gen::OpArg& new_loc,