mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-07-15 16:33:27 -05:00
Merge 49e16cdf03 into 39ef77c716
This commit is contained in:
commit
3db6c15359
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user