This commit is contained in:
Martino Fontana 2026-06-30 20:26:18 +02:00 committed by GitHub
commit 3db6c15359
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 42 additions and 116 deletions

View File

@ -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);
}
}
}

View File

@ -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<true>(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)
{

View File

@ -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<u32>(ProgramExceptionCause::Trap)));
gpr.Flush();
fpr.Flush();
gpr.Flush(RegCache::FlushMode::MaintainState);
fpr.Flush(RegCache::FlushMode::MaintainState);
MOV(32, PPCSTATE(pc), Imm32(js.compilerPC));
WriteExceptionExit();

View File

@ -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);

View File

@ -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()

View File

@ -94,28 +94,6 @@ private:
std::variant<std::monostate, Gen::X64Reg, preg_t> 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<PPCCachedReg, 32> m_regs;
std::array<X64CachedReg, NUM_XREGS> 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,