summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorMerryMage <MerryMage@users.noreply.github.com>2018-10-15 21:00:52 +0100
committerMerryMage <MerryMage@users.noreply.github.com>2018-10-28 17:57:43 +0000
commit590ec866b07dc32fd5a190b710d1aa66937a2d85 (patch)
tree6b9e1caf04535628cdb92dcdc7ec85d56e9272a4 /Source/Core
parent16f8b7413de41432c9128f1db896149fe8db3e85 (diff)
JitRegCache: Add revertable binds
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h42
-rw-r--r--Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp47
-rw-r--r--Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h3
3 files changed, 85 insertions, 7 deletions
diff --git a/Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h b/Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h
index 813fa29478..2755604247 100644
--- a/Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h
+++ b/Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h
@@ -41,6 +41,8 @@ public:
{
if (!away)
{
+ ASSERT(!revertable);
+
if (location.IsImm())
return LocationType::SpeculativeImmediate;
@@ -63,6 +65,7 @@ public:
void SetFlushed()
{
+ ASSERT(!revertable);
away = false;
location = default_location;
}
@@ -73,6 +76,24 @@ public:
location = Gen::Imm32(imm32);
}
+ bool IsRevertable() const { return revertable; }
+ void SetRevertable()
+ {
+ ASSERT(IsBound());
+ revertable = true;
+ }
+ void SetRevert()
+ {
+ ASSERT(revertable);
+ revertable = false;
+ SetFlushed();
+ }
+ void SetCommit()
+ {
+ ASSERT(revertable);
+ revertable = false;
+ }
+
bool IsLocked() const { return locked > 0; }
void Lock() { locked++; }
void Unlock()
@@ -86,6 +107,7 @@ private:
Gen::OpArg default_location{};
Gen::OpArg location{};
bool away = false; // value not in source register
+ bool revertable = false;
size_t locked = 0;
};
@@ -139,6 +161,7 @@ public:
bool ShouldLoad() const { return read; }
bool ShouldDirty() const { return write; }
bool ShouldKillImmediate() const { return kill_imm; }
+ bool ShouldBeRevertable() const { return revertable; }
void Realized() { realized = true; }
void RealizedBound()
@@ -147,16 +170,17 @@ public:
bind = true;
}
- void AddUse(RCMode mode) { AddConstraint(false, mode, false); }
- void AddUseNoImm(RCMode mode) { AddConstraint(false, mode, true); }
- void AddBind(RCMode mode) { AddConstraint(true, mode, false); }
+ void AddUse(RCMode mode) { AddConstraint(false, mode, false, false); }
+ void AddUseNoImm(RCMode mode) { AddConstraint(false, mode, true, false); }
+ void AddBind(RCMode mode) { AddConstraint(true, mode, false, false); }
+ void AddRevertableBind(RCMode mode) { AddConstraint(true, mode, false, true); }
private:
- void AddConstraint(bool should_bind, RCMode mode, bool should_kill_imm)
+ void AddConstraint(bool should_bind, RCMode mode, bool should_kill_imm, bool should_revertable)
{
if (realized)
{
- ASSERT(IsCompatible(should_bind, mode, should_kill_imm));
+ ASSERT(IsCompatible(should_bind, mode, should_kill_imm, should_revertable));
return;
}
@@ -166,6 +190,9 @@ private:
if (should_kill_imm)
kill_imm = true;
+ if (should_revertable)
+ revertable = true;
+
switch (mode)
{
case RCMode::Read:
@@ -181,12 +208,14 @@ private:
}
}
- bool IsCompatible(bool should_bind, RCMode mode, bool should_kill_imm)
+ bool IsCompatible(bool should_bind, RCMode mode, bool should_kill_imm, bool should_revertable)
{
if (should_bind && !bind)
return false;
if (should_kill_imm && !kill_imm)
return false;
+ if (should_revertable && !revertable)
+ return false;
switch (mode)
{
@@ -204,4 +233,5 @@ private:
bool write = false;
bool read = false;
bool kill_imm = false;
+ bool revertable = false;
};
diff --git a/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp b/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp
index 3526d17894..4c02b739bb 100644
--- a/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp
+++ b/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp
@@ -328,6 +328,7 @@ void RegCache::Flush(FlushMode mode, BitSet32 regsToFlush)
{
ASSERT_MSG(DYNA_REC, !m_regs[i].IsLocked(), "Someone forgot to unlock PPC reg %u (X64 reg %i).",
i, RX(i));
+ ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress!");
switch (m_regs[i].GetLocationType())
{
@@ -373,7 +374,7 @@ bool RegCache::SanityCheck() const
break;
case PPCCachedReg::LocationType::Bound:
{
- if (m_regs[i].IsLocked())
+ if (m_regs[i].IsLocked() || m_regs[i].IsRevertable())
return false;
Gen::X64Reg xr = m_regs[i].Location().GetSimpleReg();
@@ -413,6 +414,7 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsDirty(), "Xreg %i already dirty", xr);
ASSERT_MSG(DYNA_REC, !m_xregs[xr].IsLocked(), "GetFreeXReg returned locked register");
+ ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Invalid transaction state");
m_xregs[xr].SetBoundTo(i, makeDirty || m_regs[i].IsAway());
@@ -441,6 +443,9 @@ void RegCache::BindToRegister(preg_t i, bool doLoad, bool makeDirty)
void RegCache::StoreFromRegister(preg_t i, FlushMode mode)
{
+ // When a transaction is in progress, allowing the store would overwrite the old value.
+ ASSERT_MSG(DYNA_REC, !m_regs[i].IsRevertable(), "Register transaction is in progress!");
+
bool doStore = false;
switch (m_regs[i].GetLocationType())
@@ -611,6 +616,18 @@ RCX64Reg RegCache::Bind(preg_t preg, RCMode mode)
return RCX64Reg{this, preg};
}
+RCX64Reg RegCache::BindOrImm(preg_t preg, RCMode mode)
+{
+ m_constraints[preg].AddBindOrImm(mode);
+ return RCX64Reg{this, preg};
+}
+
+RCX64Reg RegCache::RevertableBind(preg_t preg, RCMode mode)
+{
+ m_constraints[preg].AddRevertableBind(mode);
+ return RCX64Reg{this, preg};
+}
+
RCX64Reg RegCache::Scratch(X64Reg xr)
{
FlushX(xr);
@@ -622,6 +639,26 @@ RCForkGuard RegCache::Fork()
return RCForkGuard{*this};
}
+void RegCache::Revert()
+{
+ ASSERT(IsAllUnlocked());
+ for (auto& reg : m_regs)
+ {
+ if (reg.IsRevertable())
+ reg.SetRevert();
+ }
+}
+
+void RegCache::Commit()
+{
+ ASSERT(IsAllUnlocked());
+ for (auto& reg : m_regs)
+ {
+ if (reg.IsRevertable())
+ reg.SetCommit();
+ }
+}
+
bool RegCache::IsAllUnlocked() const
{
return std::none_of(m_regs.begin(), m_regs.end(), [](const auto& r){ return r.IsLocked(); }) &&
@@ -673,6 +710,14 @@ void RegCache::Realize(preg_t preg)
m_constraints[preg].RealizedBound();
};
+ if (m_constraints[preg].ShouldBeRevertable())
+ {
+ StoreFromRegister(preg, FlushMode::MaintainState);
+ do_bind();
+ m_regs[preg].SetRevertable();
+ return;
+ }
+
if (m_constraints[preg].ShouldBind())
{
do_bind();
diff --git a/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h b/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h
index 64040a5172..99cba2141e 100644
--- a/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h
+++ b/Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h
@@ -235,9 +235,12 @@ public:
RCOpArg Use(preg_t preg, RCMode mode);
RCOpArg UseNoImm(preg_t preg, RCMode mode);
RCX64Reg Bind(preg_t preg, RCMode mode);
+ RCX64Reg RevertableBind(preg_t preg, RCMode mode);
RCX64Reg Scratch(Gen::X64Reg xr);
RCForkGuard Fork();
+ void Revert();
+ void Commit();
bool IsAllUnlocked() const;