Permalink
Browse files

Merge pull request #7492 from MerryMage/regcache2

JitRegCache: Refactor register cache
  • Loading branch information...
delroth committed Nov 9, 2018
2 parents 162e34a + 342067a commit 61b9ef33abd886c002490799b52878dfbb09754f
Showing with 2,465 additions and 1,682 deletions.
  1. +4 −0 Source/Core/Common/BitSet.h
  2. +1 −0 Source/Core/Common/Common.vcxproj
  3. +26 −0 Source/Core/Common/VariantUtil.h
  4. +5 −5 Source/Core/Core/CMakeLists.txt
  5. +10 −10 Source/Core/Core/Core.vcxproj
  6. +39 −50 Source/Core/Core/PowerPC/Jit64/Jit.cpp
  7. +4 −6 Source/Core/Core/PowerPC/Jit64/Jit.h
  8. +0 −324 Source/Core/Core/PowerPC/Jit64/JitRegCache.cpp
  9. +0 −230 Source/Core/Core/PowerPC/Jit64/JitRegCache.h
  10. +23 −11 Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp
  11. +147 −134 Source/Core/Core/PowerPC/Jit64/Jit_FloatingPoint.cpp
  12. +609 −546 Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp
  13. +120 −140 Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp
  14. +54 −48 Source/Core/Core/PowerPC/Jit64/Jit_LoadStoreFloating.cpp
  15. +20 −30 Source/Core/Core/PowerPC/Jit64/Jit_LoadStorePaired.cpp
  16. +63 −57 Source/Core/Core/PowerPC/Jit64/Jit_Paired.cpp
  17. +87 −80 Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp
  18. +284 −0 Source/Core/Core/PowerPC/Jit64/RegCache/CachedReg.h
  19. +1 −1 Source/Core/Core/PowerPC/Jit64/{ → RegCache}/FPURegCache.cpp
  20. +2 −2 Source/Core/Core/PowerPC/Jit64/{ → RegCache}/FPURegCache.h
  21. +1 −1 Source/Core/Core/PowerPC/Jit64/{ → RegCache}/GPRRegCache.cpp
  22. +2 −2 Source/Core/Core/PowerPC/Jit64/{ → RegCache}/GPRRegCache.h
  23. +729 −0 Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.cpp
  24. +222 −0 Source/Core/Core/PowerPC/Jit64/RegCache/JitRegCache.h
  25. +12 −0 Source/Core/Core/PowerPC/Jit64/RegCache/RCMode.h
  26. +0 −5 Source/Core/Core/PowerPC/JitCommon/JitBase.h
@@ -193,10 +193,14 @@ class BitSet
constexpr BitSet operator&(BitSet other) const { return BitSet(m_val & other.m_val); }
constexpr BitSet operator^(BitSet other) const { return BitSet(m_val ^ other.m_val); }
constexpr BitSet operator~() const { return BitSet(~m_val); }
constexpr BitSet operator<<(IntTy shift) const { return BitSet(m_val << shift); }
constexpr BitSet operator>>(IntTy shift) const { return BitSet(m_val >> shift); }
constexpr explicit operator bool() const { return m_val != 0; }
BitSet& operator|=(BitSet other) { return *this = *this | other; }
BitSet& operator&=(BitSet other) { return *this = *this & other; }
BitSet& operator^=(BitSet other) { return *this = *this ^ other; }
BitSet& operator<<=(IntTy shift) { return *this = *this << shift; }
BitSet& operator>>=(IntTy shift) { return *this = *this >> shift; }
// Warning: Even though on modern CPUs this is a single fast instruction,
// Dolphin's official builds do not currently assume POPCNT support on x86,
// so slower explicit bit twiddling is generated. Still should generally
@@ -159,6 +159,7 @@
<ClInclude Include="TraversalClient.h" />
<ClInclude Include="TraversalProto.h" />
<ClInclude Include="UPnP.h" />
<ClInclude Include="VariantUtil.h" />
<ClInclude Include="Version.h" />
<ClInclude Include="WorkQueueThread.h" />
<ClInclude Include="x64ABI.h" />
@@ -0,0 +1,26 @@
// Copyright 2018 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <variant>
namespace detail
{
template <typename... From>
struct VariantCastProxy
{
const std::variant<From...>& v;
template <typename... To>
operator std::variant<To...>() const
{
return std::visit([](auto&& arg) { return std::variant<To...>{arg}; }, v);
}
};
} // namespace detail
template <typename... From>
auto VariantCast(const std::variant<From...>& v)
{
return detail::VariantCastProxy<From...>{v};
}
@@ -236,20 +236,20 @@ if(_M_X86)
DSP/Jit/x64/DSPJitMultiplier.cpp
DSP/Jit/x64/DSPJitTables.cpp
DSP/Jit/x64/DSPJitUtil.cpp
PowerPC/Jit64/FPURegCache.cpp
PowerPC/Jit64/GPRRegCache.cpp
PowerPC/Jit64/Jit.cpp
PowerPC/Jit64/Jit64_Tables.cpp
PowerPC/Jit64/JitAsm.cpp
PowerPC/Jit64/Jit_Branch.cpp
PowerPC/Jit64/Jit.cpp
PowerPC/Jit64/Jit_FloatingPoint.cpp
PowerPC/Jit64/Jit_Integer.cpp
PowerPC/Jit64/Jit_LoadStore.cpp
PowerPC/Jit64/Jit_LoadStoreFloating.cpp
PowerPC/Jit64/Jit_LoadStorePaired.cpp
PowerPC/Jit64/Jit_Paired.cpp
PowerPC/Jit64/JitRegCache.cpp
PowerPC/Jit64/Jit_SystemRegisters.cpp
PowerPC/Jit64/JitAsm.cpp
PowerPC/Jit64/RegCache/FPURegCache.cpp
PowerPC/Jit64/RegCache/GPRRegCache.cpp
PowerPC/Jit64/RegCache/JitRegCache.cpp
PowerPC/Jit64Common/BlockCache.cpp
PowerPC/Jit64Common/ConstantPool.cpp
PowerPC/Jit64Common/EmuCodeBlock.cpp
@@ -241,8 +241,8 @@
</ClCompile>
<ClCompile Include="IOS\USB\Bluetooth\WiimoteDevice.cpp" />
<ClCompile Include="IOS\USB\Bluetooth\WiimoteHIDAttr.cpp" />
<ClCompile Include="IOS\WFS\WFSSRV.cpp" />
<ClCompile Include="IOS\WFS\WFSI.cpp" />
<ClCompile Include="IOS\WFS\WFSSRV.cpp" />
<ClCompile Include="MemTools.cpp" />
<ClCompile Include="Movie.cpp" />
<ClCompile Include="NetPlayClient.cpp" />
@@ -260,13 +260,8 @@
<ClCompile Include="PowerPC\Interpreter\Interpreter_Paired.cpp" />
<ClCompile Include="PowerPC\Interpreter\Interpreter_SystemRegisters.cpp" />
<ClCompile Include="PowerPC\Interpreter\Interpreter_Tables.cpp" />
<ClCompile Include="PowerPC\Jit64Common\ConstantPool.cpp" />
<ClCompile Include="PowerPC\Jit64\FPURegCache.cpp" />
<ClCompile Include="PowerPC\Jit64\GPRRegCache.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit64_Tables.cpp" />
<ClCompile Include="PowerPC\Jit64\JitAsm.cpp" />
<ClCompile Include="PowerPC\Jit64\JitRegCache.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit_Branch.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit_FloatingPoint.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit_Integer.cpp" />
@@ -275,7 +270,12 @@
<ClCompile Include="PowerPC\Jit64\Jit_LoadStorePaired.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit_Paired.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit_SystemRegisters.cpp" />
<ClCompile Include="PowerPC\Jit64\JitAsm.cpp" />
<ClCompile Include="PowerPC\Jit64\RegCache\FPURegCache.cpp" />
<ClCompile Include="PowerPC\Jit64\RegCache\GPRRegCache.cpp" />
<ClCompile Include="PowerPC\Jit64\RegCache\JitRegCache.cpp" />
<ClCompile Include="PowerPC\Jit64Common\BlockCache.cpp" />
<ClCompile Include="PowerPC\Jit64Common\ConstantPool.cpp" />
<ClCompile Include="PowerPC\Jit64Common\EmuCodeBlock.cpp" />
<ClCompile Include="PowerPC\Jit64Common\FarCodeCache.cpp" />
<ClCompile Include="PowerPC\Jit64Common\Jit64AsmCommon.cpp" />
@@ -284,17 +284,17 @@
<ClCompile Include="PowerPC\JitCommon\JitAsmCommon.cpp" />
<ClCompile Include="PowerPC\JitCommon\JitBase.cpp" />
<ClCompile Include="PowerPC\JitCommon\JitCache.cpp" />
<ClCompile Include="PowerPC\SignatureDB\CSVSignatureDB.cpp" />
<ClCompile Include="PowerPC\SignatureDB\DSYSignatureDB.cpp" />
<ClCompile Include="PowerPC\SignatureDB\MEGASignatureDB.cpp" />
<ClCompile Include="PowerPC\SignatureDB\SignatureDB.cpp" />
<ClCompile Include="PowerPC\JitInterface.cpp" />
<ClCompile Include="PowerPC\MMU.cpp" />
<ClCompile Include="PowerPC\PowerPC.cpp" />
<ClCompile Include="PowerPC\PPCAnalyst.cpp" />
<ClCompile Include="PowerPC\PPCCache.cpp" />
<ClCompile Include="PowerPC\PPCSymbolDB.cpp" />
<ClCompile Include="PowerPC\PPCTables.cpp" />
<ClCompile Include="PowerPC\SignatureDB\CSVSignatureDB.cpp" />
<ClCompile Include="PowerPC\SignatureDB\DSYSignatureDB.cpp" />
<ClCompile Include="PowerPC\SignatureDB\MEGASignatureDB.cpp" />
<ClCompile Include="PowerPC\SignatureDB\SignatureDB.cpp" />
<ClCompile Include="State.cpp" />
<ClCompile Include="SysConf.cpp" />
<ClCompile Include="TitleDatabase.cpp" />
@@ -27,7 +27,7 @@
#include "Core/HW/ProcessorInterface.h"
#include "Core/PatchEngine.h"
#include "Core/PowerPC/Jit64/JitAsm.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/Jit64/RegCache/JitRegCache.h"
#include "Core/PowerPC/Jit64Common/FarCodeCache.h"
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
#include "Core/PowerPC/Jit64Common/TrampolineCache.h"
@@ -756,8 +756,6 @@ u8* Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
js.downcountAmount += opinfo->numCycles;
js.fastmemLoadStore = nullptr;
js.fixupExceptionHandler = false;
js.revertGprLoad = -1;
js.revertFprLoad = -1;
if (!SConfig::GetInstance().bEnableDebugging)
js.downcountAmount += PatchEngine::GetSpeedhackCycles(js.compilerPC);
@@ -800,13 +798,17 @@ u8* Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
ProcessorInterface::INT_CAUSE_PE_FINISH));
FixupBranch noCPInt = J_CC(CC_Z, true);
gpr.Flush(RegCache::FlushMode::MaintainState);
fpr.Flush(RegCache::FlushMode::MaintainState);
{
RCForkGuard gpr_guard = gpr.Fork();
RCForkGuard fpr_guard = fpr.Fork();
MOV(32, PPCSTATE(pc), Imm32(op.address));
WriteExternalExceptionExit();
SwitchToNearCode();
gpr.Flush();
fpr.Flush();
MOV(32, PPCSTATE(pc), Imm32(op.address));
WriteExternalExceptionExit();
}
SwitchToNearCode();
SetJumpTarget(noCPInt);
SetJumpTarget(noExtIntEnable);
}
@@ -824,14 +826,19 @@ u8* Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
SwitchToFarCode();
SetJumpTarget(b1);
gpr.Flush(RegCache::FlushMode::MaintainState);
fpr.Flush(RegCache::FlushMode::MaintainState);
{
RCForkGuard gpr_guard = gpr.Fork();
RCForkGuard fpr_guard = fpr.Fork();
// If a FPU exception occurs, the exception handler will read
// from PC. Update PC with the latest value in case that happens.
MOV(32, PPCSTATE(pc), Imm32(op.address));
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
WriteExceptionExit();
gpr.Flush();
fpr.Flush();
// If a FPU exception occurs, the exception handler will read
// from PC. Update PC with the latest value in case that happens.
MOV(32, PPCSTATE(pc), Imm32(op.address));
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
WriteExceptionExit();
}
SwitchToNearCode();
js.firstFPInstructionFound = true;
@@ -866,20 +873,8 @@ u8* Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
// output, which needs to be bound in the actual instruction compilation.
// TODO: make this smarter in the case that we're actually register-starved, i.e.
// prioritize the more important registers.
for (int reg : op.regsIn)
{
if (gpr.NumFreeRegisters() < 2)
break;
if (op.gprInReg[reg] && !gpr.R(reg).IsImm())
gpr.BindToRegister(reg, true, false);
}
for (int reg : op.fregsIn)
{
if (fpr.NumFreeRegisters() < 2)
break;
if (op.fprInXmm[reg])
fpr.BindToRegister(reg, true, false);
}
gpr.PreloadRegisters(op.regsIn & op.gprInReg);
fpr.PreloadRegisters(op.fregsIn & op.fprInXmm);
CompileInstruction(op);
@@ -908,24 +903,25 @@ u8* Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
m_exception_handler_at_loc[js.fastmemLoadStore] = GetWritableCodePtr();
}
BitSet32 gprToFlush = BitSet32::AllTrue(32);
BitSet32 fprToFlush = BitSet32::AllTrue(32);
if (js.revertGprLoad >= 0)
gprToFlush[js.revertGprLoad] = false;
if (js.revertFprLoad >= 0)
fprToFlush[js.revertFprLoad] = false;
gpr.Flush(RegCache::FlushMode::MaintainState, gprToFlush);
fpr.Flush(RegCache::FlushMode::MaintainState, fprToFlush);
RCForkGuard gpr_guard = gpr.Fork();
RCForkGuard fpr_guard = fpr.Fork();
gpr.Revert();
fpr.Revert();
gpr.Flush();
fpr.Flush();
MOV(32, PPCSTATE(pc), Imm32(op.address));
WriteExceptionExit();
SwitchToNearCode();
}
gpr.Commit();
fpr.Commit();
// If we have a register that will never be used again, flush it.
for (int j : ~op.gprInUse)
gpr.StoreFromRegister(j);
for (int j : ~op.fprInUse)
fpr.StoreFromRegister(j);
gpr.Flush(~op.gprInUse);
fpr.Flush(~op.fprInUse);
if (opinfo->flags & FL_LOADSTORE)
++js.numLoadStoreInst;
@@ -969,15 +965,8 @@ BitSet8 Jit64::ComputeStaticGQRs(const PPCAnalyst::CodeBlock& cb) const
BitSet32 Jit64::CallerSavedRegistersInUse() const
{
BitSet32 result;
for (size_t i = 0; i < RegCache::NUM_XREGS; i++)
{
if (!gpr.IsFreeX(i))
result[i] = true;
if (!fpr.IsFreeX(i))
result[16 + i] = true;
}
return result & ABI_ALL_CALLER_SAVED;
BitSet32 in_use = gpr.RegistersInUse() | (fpr.RegistersInUse() << 16);
return in_use & ABI_ALL_CALLER_SAVED;
}
void Jit64::EnableBlockLink()
@@ -21,10 +21,10 @@
#include "Common/CommonTypes.h"
#include "Common/x64ABI.h"
#include "Common/x64Emitter.h"
#include "Core/PowerPC/Jit64/FPURegCache.h"
#include "Core/PowerPC/Jit64/GPRRegCache.h"
#include "Core/PowerPC/Jit64/JitAsm.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/Jit64/RegCache/FPURegCache.h"
#include "Core/PowerPC/Jit64/RegCache/GPRRegCache.h"
#include "Core/PowerPC/Jit64/RegCache/JitRegCache.h"
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
#include "Core/PowerPC/JitCommon/JitCache.h"
@@ -88,10 +88,8 @@ class Jit64 : public Jitx86Base
void FinalizeCarryOverflow(bool oe, bool inv = false);
void FinalizeCarry(Gen::CCFlags cond);
void FinalizeCarry(bool ca);
void ComputeRC(const Gen::OpArg& arg, bool needs_test = true, bool needs_sext = true);
void ComputeRC(preg_t preg, bool needs_test = true, bool needs_sext = true);
// Use to extract bytes from a register using the regcache. offset is in bytes.
Gen::OpArg ExtractFromReg(int reg, int offset);
void AndWithMask(Gen::X64Reg reg, u32 mask);
bool CheckMergedBranch(u32 crf) const;
void DoMergedBranch();
Oops, something went wrong.

0 comments on commit 61b9ef3

Please sign in to comment.