From ff0a6b833120670dff0185bfc832e7c17150141a Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 30 Sep 2018 13:14:00 +0100 Subject: [PATCH] JitRegCache: Encapsulate behavior of X64CachedReg --- .../Core/Core/PowerPC/Jit64/JitRegCache.cpp | 64 ++++++++----------- Source/Core/Core/PowerPC/Jit64/JitRegCache.h | 45 ++++++++++--- 2 files changed, 62 insertions(+), 47 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp index 67f04e9f5b..20a1c2b9c9 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp @@ -26,13 +26,7 @@ RegCache::RegCache(Jit64& jit) : m_jit{jit} void RegCache::Start() { - for (auto& xreg : m_xregs) - { - xreg.free = true; - xreg.dirty = false; - xreg.locked = false; - xreg.ppcReg = static_cast(INVALID_REG); - } + m_xregs.fill({}); for (size_t i = 0; i < m_regs.size(); i++) { m_regs[i] = PPCCachedReg{GetDefaultLocation(i)}; @@ -44,9 +38,7 @@ void RegCache::DiscardRegContentsIfCached(size_t preg) if (m_regs[preg].IsBound()) { X64Reg xr = m_regs[preg].Location().GetSimpleReg(); - m_xregs[xr].free = true; - m_xregs[xr].dirty = false; - m_xregs[xr].ppcReg = static_cast(INVALID_REG); + m_xregs[xr].Flushed(); m_regs[preg].Flushed(); } } @@ -60,8 +52,10 @@ void RegCache::Flush(FlushMode mode, BitSet32 regsToFlush) { for (size_t i = 0; i < m_xregs.size(); i++) { - if (m_xregs[i].locked) + if (m_xregs[i].IsLocked()) + { PanicAlert("Someone forgot to unlock X64 reg %zu", i); + } } for (unsigned int i : regsToFlush) @@ -93,9 +87,10 @@ void RegCache::FlushR(X64Reg reg) { if (reg >= m_xregs.size()) PanicAlert("Flushing non existent reg"); - if (!m_xregs[reg].free) + ASSERT(!m_xregs[reg].IsLocked()); + if (!m_xregs[reg].IsFree()) { - StoreFromRegister(m_xregs[reg].ppcReg); + StoreFromRegister(m_xregs[reg].Contents()); } } @@ -131,9 +126,9 @@ int RegCache::SanityCheck() const case PPCCachedReg::LocationType::Bound: { Gen::X64Reg simple = m_regs[i].Location().GetSimpleReg(); - if (m_xregs[simple].locked) + if (m_xregs[simple].IsLocked()) return 1; - if (m_xregs[simple].ppcReg != i) + if (m_xregs[simple].Contents() != i) return 2; break; } @@ -152,7 +147,7 @@ void RegCache::KillImmediate(size_t preg, bool doLoad, bool makeDirty) case PPCCachedReg::LocationType::SpeculativeImmediate: break; case PPCCachedReg::LocationType::Bound: - m_xregs[RX(preg)].dirty |= makeDirty; + m_xregs[RX(preg)].MakeDirty(makeDirty); break; case PPCCachedReg::LocationType::Immediate: BindToRegister(preg, doLoad, makeDirty); @@ -165,14 +160,11 @@ void RegCache::BindToRegister(size_t i, bool doLoad, bool makeDirty) if (!m_regs[i].IsBound()) { X64Reg xr = GetFreeXReg(); - if (m_xregs[xr].dirty) + if (m_xregs[xr].IsDirty()) PanicAlert("Xreg already dirty"); - if (m_xregs[xr].locked) + if (m_xregs[xr].IsLocked()) PanicAlert("GetFreeXReg returned locked register"); - m_xregs[xr].free = false; - m_xregs[xr].ppcReg = i; - m_xregs[xr].dirty = makeDirty || m_regs[i].IsAway(); - + m_xregs[xr].BoundTo(i, makeDirty || m_regs[i].IsAway()); if (doLoad) LoadRegister(i, xr); for (size_t j = 0; j < m_regs.size(); j++) @@ -188,10 +180,10 @@ void RegCache::BindToRegister(size_t i, bool doLoad, bool makeDirty) { // reg location must be simplereg; memory locations // and immediates are taken care of above. - m_xregs[RX(i)].dirty |= makeDirty; + m_xregs[RX(i)].MakeDirty(makeDirty); } - if (m_xregs[RX(i)].locked) + if (m_xregs[RX(i)].IsLocked()) { PanicAlert("Seriously WTF, this reg should have been flushed"); } @@ -209,13 +201,9 @@ void RegCache::StoreFromRegister(size_t i, FlushMode mode) case PPCCachedReg::LocationType::Bound: { X64Reg xr = RX(i); - doStore = m_xregs[xr].dirty; + doStore = m_xregs[xr].IsDirty(); if (mode == FlushMode::All) - { - m_xregs[xr].free = true; - m_xregs[xr].ppcReg = static_cast(INVALID_REG); - m_xregs[xr].dirty = false; - } + m_xregs[xr].Flushed(); break; } case PPCCachedReg::LocationType::Immediate: @@ -252,12 +240,12 @@ void RegCache::UnlockAll() void RegCache::UnlockAllX() { for (auto& xreg : m_xregs) - xreg.locked = false; + xreg.Unlock(); } bool RegCache::IsFreeX(size_t xreg) const { - return m_xregs[xreg].free && !m_xregs[xreg].locked; + return m_xregs[xreg].IsFree(); } X64Reg RegCache::GetFreeXReg() @@ -267,7 +255,7 @@ X64Reg RegCache::GetFreeXReg() for (size_t i = 0; i < aCount; i++) { X64Reg xr = aOrder[i]; - if (!m_xregs[xr].locked && m_xregs[xr].free) + if (m_xregs[xr].IsFree()) { return xr; } @@ -281,8 +269,8 @@ X64Reg RegCache::GetFreeXReg() for (size_t i = 0; i < aCount; i++) { X64Reg xreg = (X64Reg)aOrder[i]; - size_t preg = m_xregs[xreg].ppcReg; - if (m_xregs[xreg].locked || m_regs[preg].IsLocked()) + size_t preg = m_xregs[xreg].Contents(); + if (m_xregs[xreg].IsLocked() || m_regs[preg].IsLocked()) continue; float score = ScoreRegister(xreg); if (score < min_score) @@ -310,7 +298,7 @@ int RegCache::NumFreeRegisters() const size_t aCount; const X64Reg* aOrder = GetAllocationOrder(&aCount); for (size_t i = 0; i < aCount; i++) - if (!m_xregs[aOrder[i]].locked && m_xregs[aOrder[i]].free) + if (m_xregs[aOrder[i]].IsFree()) count++; return count; } @@ -319,14 +307,14 @@ int RegCache::NumFreeRegisters() const // means more bad. float RegCache::ScoreRegister(X64Reg xreg) const { - size_t preg = m_xregs[xreg].ppcReg; + size_t preg = m_xregs[xreg].Contents(); float score = 0; // If it's not dirty, we don't need a store to write it back to the register file, so // bias a bit against dirty registers. Testing shows that a bias of 2 seems roughly // right: 3 causes too many extra clobbers, while 1 saves very few clobbers relative // to the number of extra stores it causes. - if (m_xregs[xreg].dirty) + if (m_xregs[xreg].IsDirty()) score += 2; // If the register isn't actually needed in a physical register for a later instruction, diff --git a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h index eee6782513..007ff66cd8 100644 --- a/Source/Core/Core/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/PowerPC/Jit64/JitRegCache.h @@ -84,12 +84,39 @@ private: bool locked = false; }; -struct X64CachedReg +class X64CachedReg { - size_t ppcReg; - bool dirty; - bool free; - bool locked; +public: + size_t Contents() const { return ppcReg; } + + void BoundTo(size_t ppcReg_, bool dirty_) + { + free = false; + ppcReg = ppcReg_; + dirty = dirty_; + } + + void Flushed() + { + ppcReg = static_cast(Gen::INVALID_REG); + free = true; + dirty = false; + } + + bool IsFree() const { return free && !locked; } + + bool IsDirty() const { return dirty; } + void MakeDirty(bool makeDirty = true) { dirty |= makeDirty; } + + bool IsLocked() const { return locked; } + void Lock() { locked = true; } + void Unlock() { locked = false; } + +private: + size_t ppcReg = static_cast(Gen::INVALID_REG); + bool free = true; + bool dirty = false; + bool locked = false; }; class RegCache @@ -153,9 +180,9 @@ public: template void LockX(T x) { - if (m_xregs[x].locked) + if (m_xregs[x].IsLocked()) PanicAlert("RegCache: x %i already locked!", x); - m_xregs[x].locked = true; + m_xregs[x].Lock(); } template void LockX(T first, Args... args) @@ -167,9 +194,9 @@ public: template void UnlockX(T x) { - if (!m_xregs[x].locked) + if (!m_xregs[x].IsLocked()) PanicAlert("RegCache: x %i already unlocked!", x); - m_xregs[x].locked = false; + m_xregs[x].Unlock(); } template void UnlockX(T first, Args... args)