Merge pull request #4522 from lioncash/jitutil
Jit64Common: Split Jit64Util contents into separate files
This commit is contained in:
commit
10862cd0e8
|
@ -209,9 +209,10 @@ if(_M_X86)
|
||||||
PowerPC/Jit64/JitRegCache.cpp
|
PowerPC/Jit64/JitRegCache.cpp
|
||||||
PowerPC/Jit64/Jit_SystemRegisters.cpp
|
PowerPC/Jit64/Jit_SystemRegisters.cpp
|
||||||
PowerPC/Jit64Common/BlockCache.cpp
|
PowerPC/Jit64Common/BlockCache.cpp
|
||||||
|
PowerPC/Jit64Common/EmuCodeBlock.cpp
|
||||||
|
PowerPC/Jit64Common/FarCodeCache.cpp
|
||||||
PowerPC/Jit64Common/Jit64AsmCommon.cpp
|
PowerPC/Jit64Common/Jit64AsmCommon.cpp
|
||||||
PowerPC/Jit64Common/Jit64Base.cpp
|
PowerPC/Jit64Common/Jit64Base.cpp
|
||||||
PowerPC/Jit64Common/Jit64Util.cpp
|
|
||||||
PowerPC/Jit64Common/TrampolineCache.cpp)
|
PowerPC/Jit64Common/TrampolineCache.cpp)
|
||||||
elseif(_M_ARM_64)
|
elseif(_M_ARM_64)
|
||||||
set(SRCS ${SRCS}
|
set(SRCS ${SRCS}
|
||||||
|
|
|
@ -238,9 +238,10 @@
|
||||||
<ClCompile Include="PowerPC\Jit64\Jit_Paired.cpp" />
|
<ClCompile Include="PowerPC\Jit64\Jit_Paired.cpp" />
|
||||||
<ClCompile Include="PowerPC\Jit64\Jit_SystemRegisters.cpp" />
|
<ClCompile Include="PowerPC\Jit64\Jit_SystemRegisters.cpp" />
|
||||||
<ClCompile Include="PowerPC\Jit64Common\BlockCache.cpp" />
|
<ClCompile Include="PowerPC\Jit64Common\BlockCache.cpp" />
|
||||||
|
<ClCompile Include="PowerPC\Jit64Common\EmuCodeBlock.cpp" />
|
||||||
|
<ClCompile Include="PowerPC\Jit64Common\FarCodeCache.cpp" />
|
||||||
<ClCompile Include="PowerPC\Jit64Common\Jit64AsmCommon.cpp" />
|
<ClCompile Include="PowerPC\Jit64Common\Jit64AsmCommon.cpp" />
|
||||||
<ClCompile Include="PowerPC\Jit64Common\Jit64Base.cpp" />
|
<ClCompile Include="PowerPC\Jit64Common\Jit64Base.cpp" />
|
||||||
<ClCompile Include="PowerPC\Jit64Common\Jit64Util.cpp" />
|
|
||||||
<ClCompile Include="PowerPC\Jit64Common\TrampolineCache.cpp" />
|
<ClCompile Include="PowerPC\Jit64Common\TrampolineCache.cpp" />
|
||||||
<ClCompile Include="PowerPC\JitCommon\JitAsmCommon.cpp" />
|
<ClCompile Include="PowerPC\JitCommon\JitAsmCommon.cpp" />
|
||||||
<ClCompile Include="PowerPC\JitCommon\JitBase.cpp" />
|
<ClCompile Include="PowerPC\JitCommon\JitBase.cpp" />
|
||||||
|
@ -433,10 +434,13 @@
|
||||||
<ClInclude Include="PowerPC\JitILCommon\IR.h" />
|
<ClInclude Include="PowerPC\JitILCommon\IR.h" />
|
||||||
<ClInclude Include="PowerPC\JitILCommon\JitILBase.h" />
|
<ClInclude Include="PowerPC\JitILCommon\JitILBase.h" />
|
||||||
<ClInclude Include="PowerPC\Jit64Common\BlockCache.h" />
|
<ClInclude Include="PowerPC\Jit64Common\BlockCache.h" />
|
||||||
|
<ClInclude Include="PowerPC\Jit64Common\EmuCodeBlock.h" />
|
||||||
|
<ClInclude Include="PowerPC\Jit64Common\FarCodeCache.h" />
|
||||||
<ClInclude Include="PowerPC\Jit64Common\Jit64AsmCommon.h" />
|
<ClInclude Include="PowerPC\Jit64Common\Jit64AsmCommon.h" />
|
||||||
<ClInclude Include="PowerPC\Jit64Common\Jit64Base.h" />
|
<ClInclude Include="PowerPC\Jit64Common\Jit64Base.h" />
|
||||||
<ClInclude Include="PowerPC\Jit64Common\Jit64Util.h" />
|
<ClInclude Include="PowerPC\Jit64Common\Jit64PowerPCState.h" />
|
||||||
<ClInclude Include="PowerPC\Jit64Common\TrampolineCache.h" />
|
<ClInclude Include="PowerPC\Jit64Common\TrampolineCache.h" />
|
||||||
|
<ClInclude Include="PowerPC\Jit64Common\TrampolineInfo.h" />
|
||||||
<ClInclude Include="PowerPC\JitCommon\JitAsmCommon.h" />
|
<ClInclude Include="PowerPC\JitCommon\JitAsmCommon.h" />
|
||||||
<ClInclude Include="PowerPC\JitCommon\JitBase.h" />
|
<ClInclude Include="PowerPC\JitCommon\JitBase.h" />
|
||||||
<ClInclude Include="PowerPC\JitCommon\JitCache.h" />
|
<ClInclude Include="PowerPC\JitCommon\JitCache.h" />
|
||||||
|
|
|
@ -735,15 +735,18 @@
|
||||||
<ClCompile Include="PowerPC\Jit64Common\BlockCache.cpp">
|
<ClCompile Include="PowerPC\Jit64Common\BlockCache.cpp">
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="PowerPC\Jit64Common\EmuCodeBlock.cpp">
|
||||||
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PowerPC\Jit64Common\FarCodeCache.cpp">
|
||||||
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="PowerPC\Jit64Common\Jit64AsmCommon.cpp">
|
<ClCompile Include="PowerPC\Jit64Common\Jit64AsmCommon.cpp">
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="PowerPC\Jit64Common\Jit64Base.cpp">
|
<ClCompile Include="PowerPC\Jit64Common\Jit64Base.cpp">
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="PowerPC\Jit64Common\Jit64Util.cpp">
|
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="PowerPC\Jit64Common\TrampolineCache.cpp">
|
<ClCompile Include="PowerPC\Jit64Common\TrampolineCache.cpp">
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -1281,18 +1284,27 @@
|
||||||
<ClInclude Include="PowerPC\Jit64Common\BlockCache.h">
|
<ClInclude Include="PowerPC\Jit64Common\BlockCache.h">
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="PowerPC\Jit64Common\EmuCodeBlock.h">
|
||||||
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PowerPC\Jit64Common\FarCodeCache.h">
|
||||||
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="PowerPC\Jit64Common\Jit64AsmCommon.h">
|
<ClInclude Include="PowerPC\Jit64Common\Jit64AsmCommon.h">
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="PowerPC\Jit64Common\Jit64Base.h">
|
<ClInclude Include="PowerPC\Jit64Common\Jit64Base.h">
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="PowerPC\Jit64Common\Jit64Util.h">
|
<ClInclude Include="PowerPC\Jit64Common\Jit64PowerPCState.h">
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="PowerPC\Jit64Common\TrampolineCache.h">
|
<ClInclude Include="PowerPC\Jit64Common\TrampolineCache.h">
|
||||||
<Filter>PowerPC\Jit64Common</Filter>
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="PowerPC\Jit64Common\TrampolineInfo.h">
|
||||||
|
<Filter>PowerPC\Jit64Common</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="Analytics.h" />
|
<ClInclude Include="Analytics.h" />
|
||||||
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_ven.h">
|
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_ven.h">
|
||||||
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
|
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "Core/HLE/HLE.h"
|
#include "Core/HLE/HLE.h"
|
||||||
#include "Core/HW/CPU.h"
|
#include "Core/HW/CPU.h"
|
||||||
#include "Core/PowerPC/Gekko.h"
|
#include "Core/PowerPC/Gekko.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
|
||||||
#include "Core/PowerPC/PPCAnalyst.h"
|
#include "Core/PowerPC/PPCAnalyst.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
#include "Core/PowerPC/Jit64/Jit64_Tables.h"
|
#include "Core/PowerPC/Jit64/Jit64_Tables.h"
|
||||||
#include "Core/PowerPC/Jit64/JitAsm.h"
|
#include "Core/PowerPC/Jit64/JitAsm.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/FarCodeCache.h"
|
||||||
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
|
#include "Core/PowerPC/Jit64Common/TrampolineCache.h"
|
||||||
#include "Core/PowerPC/JitInterface.h"
|
#include "Core/PowerPC/JitInterface.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
#include "Core/PowerPC/Profiler.h"
|
#include "Core/PowerPC/Profiler.h"
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "Core/HW/CPU.h"
|
#include "Core/HW/CPU.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
#include "Core/PowerPC/Jit64/JitAsm.h"
|
#include "Core/PowerPC/Jit64/JitAsm.h"
|
||||||
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "Common/x64Emitter.h"
|
#include "Common/x64Emitter.h"
|
||||||
#include "Core/PowerPC/Jit64/Jit.h"
|
#include "Core/PowerPC/Jit64/Jit.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "Core/CoreTiming.h"
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/PowerPC/Gekko.h"
|
#include "Core/PowerPC/Gekko.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/PPCAnalyst.h"
|
#include "Core/PowerPC/PPCAnalyst.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/PowerPC/Jit64/Jit.h"
|
#include "Core/PowerPC/Jit64/Jit.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/PPCAnalyst.h"
|
#include "Core/PowerPC/PPCAnalyst.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/CPUDetect.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/MathUtil.h"
|
#include "Common/MathUtil.h"
|
||||||
#include "Common/x64Emitter.h"
|
#include "Common/x64Emitter.h"
|
||||||
#include "Core/PowerPC/Jit64/Jit.h"
|
#include "Core/PowerPC/Jit64/Jit.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/PPCAnalyst.h"
|
#include "Core/PowerPC/PPCAnalyst.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include "Core/HW/DSP.h"
|
#include "Core/HW/DSP.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
|
||||||
#include "Core/PowerPC/JitInterface.h"
|
#include "Core/PowerPC/JitInterface.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/x64Emitter.h"
|
#include "Common/x64Emitter.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/x64Emitter.h"
|
#include "Common/x64Emitter.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/JitCommon/JitAsmCommon.h"
|
#include "Core/PowerPC/JitCommon/JitAsmCommon.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,13 @@
|
||||||
|
|
||||||
#include "Core/PowerPC/Jit64/Jit.h"
|
#include "Core/PowerPC/Jit64/Jit.h"
|
||||||
#include "Common/BitSet.h"
|
#include "Common/BitSet.h"
|
||||||
|
#include "Common/CPUDetect.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/x64Emitter.h"
|
#include "Common/x64Emitter.h"
|
||||||
#include "Core/CoreTiming.h"
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/HW/ProcessorInterface.h"
|
#include "Core/HW/ProcessorInterface.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
|
@ -1,22 +1,45 @@
|
||||||
// Copyright 2008 Dolphin Emulator Project
|
// Copyright 2016 Dolphin Emulator Project
|
||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/EmuCodeBlock.h"
|
||||||
#include "Common/BitSet.h"
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/CPUDetect.h"
|
||||||
#include "Common/Intrinsics.h"
|
#include "Common/Intrinsics.h"
|
||||||
#include "Common/MathUtil.h"
|
#include "Common/MathUtil.h"
|
||||||
#include "Common/x64ABI.h"
|
|
||||||
#include "Common/x64Emitter.h"
|
|
||||||
#include "Core/HW/MMIO.h"
|
#include "Core/HW/MMIO.h"
|
||||||
#include "Core/HW/Memmap.h"
|
#include "Core/HW/Memmap.h"
|
||||||
|
#include "Core/PowerPC/Gekko.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
|
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
|
||||||
#include "Core/PowerPC/Jit64Common/TrampolineCache.h"
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
OpArg SwapImmediate(int access_size, const OpArg& reg_value)
|
||||||
|
{
|
||||||
|
if (access_size == 32)
|
||||||
|
return Imm32(Common::swap32(reg_value.Imm32()));
|
||||||
|
|
||||||
|
if (access_size == 16)
|
||||||
|
return Imm16(Common::swap16(reg_value.Imm16()));
|
||||||
|
|
||||||
|
return Imm8(reg_value.Imm8());
|
||||||
|
}
|
||||||
|
|
||||||
|
OpArg FixImmediate(int access_size, OpArg arg)
|
||||||
|
{
|
||||||
|
if (arg.IsImm())
|
||||||
|
{
|
||||||
|
arg = access_size == 8 ? arg.AsImm8() : access_size == 16 ? arg.AsImm16() : arg.AsImm32();
|
||||||
|
}
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
void EmuCodeBlock::MemoryExceptionCheck()
|
void EmuCodeBlock::MemoryExceptionCheck()
|
||||||
{
|
{
|
||||||
// TODO: We really should untangle the trampolines, exception handlers and
|
// TODO: We really should untangle the trampolines, exception handlers and
|
||||||
|
@ -47,6 +70,49 @@ void EmuCodeBlock::MemoryExceptionCheck()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuCodeBlock::SwitchToFarCode()
|
||||||
|
{
|
||||||
|
nearcode = GetWritableCodePtr();
|
||||||
|
SetCodePtr(farcode.GetWritableCodePtr());
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuCodeBlock::SwitchToNearCode()
|
||||||
|
{
|
||||||
|
farcode.SetCodePtr(GetWritableCodePtr());
|
||||||
|
SetCodePtr(nearcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
FixupBranch EmuCodeBlock::CheckIfSafeAddress(const OpArg& reg_value, X64Reg reg_addr,
|
||||||
|
BitSet32 registers_in_use)
|
||||||
|
{
|
||||||
|
registers_in_use[reg_addr] = true;
|
||||||
|
if (reg_value.IsSimpleReg())
|
||||||
|
registers_in_use[reg_value.GetSimpleReg()] = true;
|
||||||
|
|
||||||
|
// Get ourselves a free register; try to pick one that doesn't involve pushing, if we can.
|
||||||
|
X64Reg scratch = RSCRATCH;
|
||||||
|
if (!registers_in_use[RSCRATCH])
|
||||||
|
scratch = RSCRATCH;
|
||||||
|
else if (!registers_in_use[RSCRATCH_EXTRA])
|
||||||
|
scratch = RSCRATCH_EXTRA;
|
||||||
|
else
|
||||||
|
scratch = reg_addr;
|
||||||
|
|
||||||
|
if (scratch == reg_addr)
|
||||||
|
PUSH(scratch);
|
||||||
|
else
|
||||||
|
MOV(32, R(scratch), R(reg_addr));
|
||||||
|
|
||||||
|
// Perform lookup to see if we can use fast path.
|
||||||
|
SHR(32, R(scratch), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
||||||
|
TEST(32, MScaled(scratch, SCALE_4, PtrOffset(&PowerPC::dbat_table[0])), Imm32(2));
|
||||||
|
|
||||||
|
if (scratch == reg_addr)
|
||||||
|
POP(scratch);
|
||||||
|
|
||||||
|
return J_CC(CC_Z, farcode.Enabled());
|
||||||
|
}
|
||||||
|
|
||||||
void EmuCodeBlock::UnsafeLoadRegToReg(X64Reg reg_addr, X64Reg reg_value, int accessSize, s32 offset,
|
void EmuCodeBlock::UnsafeLoadRegToReg(X64Reg reg_addr, X64Reg reg_value, int accessSize, s32 offset,
|
||||||
bool signExtend)
|
bool signExtend)
|
||||||
{
|
{
|
||||||
|
@ -63,6 +129,38 @@ void EmuCodeBlock::UnsafeLoadRegToRegNoSwap(X64Reg reg_addr, X64Reg reg_value, i
|
||||||
MOVZX(32, accessSize, reg_value, MComplex(RMEM, reg_addr, SCALE_1, offset));
|
MOVZX(32, accessSize, reg_value, MComplex(RMEM, reg_addr, SCALE_1, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuCodeBlock::UnsafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int accessSize, s32 offset,
|
||||||
|
bool swap, MovInfo* info)
|
||||||
|
{
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
info->address = GetWritableCodePtr();
|
||||||
|
info->nonAtomicSwapStore = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpArg dest = MComplex(RMEM, reg_addr, SCALE_1, offset);
|
||||||
|
if (reg_value.IsImm())
|
||||||
|
{
|
||||||
|
if (swap)
|
||||||
|
reg_value = SwapImmediate(accessSize, reg_value);
|
||||||
|
MOV(accessSize, dest, reg_value);
|
||||||
|
}
|
||||||
|
else if (swap)
|
||||||
|
{
|
||||||
|
SwapAndStore(accessSize, dest, reg_value.GetSimpleReg(), info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MOV(accessSize, dest, reg_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuCodeBlock::UnsafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize,
|
||||||
|
s32 offset, bool swap, Gen::MovInfo* info)
|
||||||
|
{
|
||||||
|
UnsafeWriteRegToReg(R(reg_value), reg_addr, accessSize, offset, swap, info);
|
||||||
|
}
|
||||||
|
|
||||||
bool EmuCodeBlock::UnsafeLoadToReg(X64Reg reg_value, OpArg opAddress, int accessSize, s32 offset,
|
bool EmuCodeBlock::UnsafeLoadToReg(X64Reg reg_value, OpArg opAddress, int accessSize, s32 offset,
|
||||||
bool signExtend, MovInfo* info)
|
bool signExtend, MovInfo* info)
|
||||||
{
|
{
|
||||||
|
@ -104,6 +202,28 @@ bool EmuCodeBlock::UnsafeLoadToReg(X64Reg reg_value, OpArg opAddress, int access
|
||||||
return offsetAddedToAddress;
|
return offsetAddedToAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuCodeBlock::UnsafeWriteGatherPipe(int accessSize)
|
||||||
|
{
|
||||||
|
// No need to protect these, they don't touch any state
|
||||||
|
// question - should we inline them instead? Pro: Lose a CALL Con: Code bloat
|
||||||
|
switch (accessSize)
|
||||||
|
{
|
||||||
|
case 8:
|
||||||
|
CALL(jit->GetAsmRoutines()->fifoDirectWrite8);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
CALL(jit->GetAsmRoutines()->fifoDirectWrite16);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
CALL(jit->GetAsmRoutines()->fifoDirectWrite32);
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
CALL(jit->GetAsmRoutines()->fifoDirectWrite64);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
jit->js.fifoBytesSinceCheck += accessSize >> 3;
|
||||||
|
}
|
||||||
|
|
||||||
// Visitor that generates code to read a MMIO value.
|
// Visitor that generates code to read a MMIO value.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class MMIOReadCodeGenerator : public MMIO::ReadHandlingMethodVisitor<T>
|
class MMIOReadCodeGenerator : public MMIO::ReadHandlingMethodVisitor<T>
|
||||||
|
@ -212,37 +332,6 @@ void EmuCodeBlock::MMIOLoadToReg(MMIO::Mapping* mmio, Gen::X64Reg reg_value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FixupBranch EmuCodeBlock::CheckIfSafeAddress(const OpArg& reg_value, X64Reg reg_addr,
|
|
||||||
BitSet32 registers_in_use)
|
|
||||||
{
|
|
||||||
registers_in_use[reg_addr] = true;
|
|
||||||
if (reg_value.IsSimpleReg())
|
|
||||||
registers_in_use[reg_value.GetSimpleReg()] = true;
|
|
||||||
|
|
||||||
// Get ourselves a free register; try to pick one that doesn't involve pushing, if we can.
|
|
||||||
X64Reg scratch = RSCRATCH;
|
|
||||||
if (!registers_in_use[RSCRATCH])
|
|
||||||
scratch = RSCRATCH;
|
|
||||||
else if (!registers_in_use[RSCRATCH_EXTRA])
|
|
||||||
scratch = RSCRATCH_EXTRA;
|
|
||||||
else
|
|
||||||
scratch = reg_addr;
|
|
||||||
|
|
||||||
if (scratch == reg_addr)
|
|
||||||
PUSH(scratch);
|
|
||||||
else
|
|
||||||
MOV(32, R(scratch), R(reg_addr));
|
|
||||||
|
|
||||||
// Perform lookup to see if we can use fast path.
|
|
||||||
SHR(32, R(scratch), Imm8(PowerPC::BAT_INDEX_SHIFT));
|
|
||||||
TEST(32, MScaled(scratch, SCALE_4, PtrOffset(&PowerPC::dbat_table[0])), Imm32(2));
|
|
||||||
|
|
||||||
if (scratch == reg_addr)
|
|
||||||
POP(scratch);
|
|
||||||
|
|
||||||
return J_CC(CC_Z, farcode.Enabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress, int accessSize,
|
void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg& opAddress, int accessSize,
|
||||||
s32 offset, BitSet32 registersInUse, bool signExtend, int flags)
|
s32 offset, BitSet32 registersInUse, bool signExtend, int flags)
|
||||||
{
|
{
|
||||||
|
@ -399,119 +488,6 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static OpArg SwapImmediate(int accessSize, const OpArg& reg_value)
|
|
||||||
{
|
|
||||||
if (accessSize == 32)
|
|
||||||
return Imm32(Common::swap32(reg_value.Imm32()));
|
|
||||||
else if (accessSize == 16)
|
|
||||||
return Imm16(Common::swap16(reg_value.Imm16()));
|
|
||||||
else
|
|
||||||
return Imm8(reg_value.Imm8());
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuCodeBlock::UnsafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int accessSize, s32 offset,
|
|
||||||
bool swap, MovInfo* info)
|
|
||||||
{
|
|
||||||
if (info)
|
|
||||||
{
|
|
||||||
info->address = GetWritableCodePtr();
|
|
||||||
info->nonAtomicSwapStore = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
OpArg dest = MComplex(RMEM, reg_addr, SCALE_1, offset);
|
|
||||||
if (reg_value.IsImm())
|
|
||||||
{
|
|
||||||
if (swap)
|
|
||||||
reg_value = SwapImmediate(accessSize, reg_value);
|
|
||||||
MOV(accessSize, dest, reg_value);
|
|
||||||
}
|
|
||||||
else if (swap)
|
|
||||||
{
|
|
||||||
SwapAndStore(accessSize, dest, reg_value.GetSimpleReg(), info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MOV(accessSize, dest, reg_value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static OpArg FixImmediate(int accessSize, OpArg arg)
|
|
||||||
{
|
|
||||||
if (arg.IsImm())
|
|
||||||
{
|
|
||||||
arg = accessSize == 8 ? arg.AsImm8() : accessSize == 16 ? arg.AsImm16() : arg.AsImm32();
|
|
||||||
}
|
|
||||||
return arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuCodeBlock::UnsafeWriteGatherPipe(int accessSize)
|
|
||||||
{
|
|
||||||
// No need to protect these, they don't touch any state
|
|
||||||
// question - should we inline them instead? Pro: Lose a CALL Con: Code bloat
|
|
||||||
switch (accessSize)
|
|
||||||
{
|
|
||||||
case 8:
|
|
||||||
CALL(jit->GetAsmRoutines()->fifoDirectWrite8);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
CALL(jit->GetAsmRoutines()->fifoDirectWrite16);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
CALL(jit->GetAsmRoutines()->fifoDirectWrite32);
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
CALL(jit->GetAsmRoutines()->fifoDirectWrite64);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
jit->js.fifoBytesSinceCheck += accessSize >> 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address,
|
|
||||||
BitSet32 registersInUse)
|
|
||||||
{
|
|
||||||
arg = FixImmediate(accessSize, arg);
|
|
||||||
|
|
||||||
// If we already know the address through constant folding, we can do some
|
|
||||||
// fun tricks...
|
|
||||||
if (jit->jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(address))
|
|
||||||
{
|
|
||||||
if (!arg.IsSimpleReg(RSCRATCH))
|
|
||||||
MOV(accessSize, R(RSCRATCH), arg);
|
|
||||||
|
|
||||||
UnsafeWriteGatherPipe(accessSize);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (PowerPC::IsOptimizableRAMAddress(address))
|
|
||||||
{
|
|
||||||
WriteToConstRamAddress(accessSize, arg, address);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Helps external systems know which instruction triggered the write
|
|
||||||
MOV(32, PPCSTATE(pc), Imm32(jit->js.compilerPC));
|
|
||||||
|
|
||||||
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
|
||||||
switch (accessSize)
|
|
||||||
{
|
|
||||||
case 64:
|
|
||||||
ABI_CallFunctionAC(64, PowerPC::Write_U64, arg, address);
|
|
||||||
break;
|
|
||||||
case 32:
|
|
||||||
ABI_CallFunctionAC(32, PowerPC::Write_U32, arg, address);
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
ABI_CallFunctionAC(16, PowerPC::Write_U16, arg, address);
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
ABI_CallFunctionAC(8, PowerPC::Write_U8, arg, address);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int accessSize, s32 offset,
|
void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int accessSize, s32 offset,
|
||||||
BitSet32 registersInUse, int flags)
|
BitSet32 registersInUse, int flags)
|
||||||
{
|
{
|
||||||
|
@ -625,6 +601,63 @@ void EmuCodeBlock::SafeWriteRegToReg(OpArg reg_value, X64Reg reg_addr, int acces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuCodeBlock::SafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize,
|
||||||
|
s32 offset, BitSet32 registersInUse, int flags)
|
||||||
|
{
|
||||||
|
SafeWriteRegToReg(R(reg_value), reg_addr, accessSize, offset, registersInUse, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuCodeBlock::WriteClobbersRegValue(int accessSize, bool swap)
|
||||||
|
{
|
||||||
|
return swap && !cpu_info.bMOVBE && accessSize > 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EmuCodeBlock::WriteToConstAddress(int accessSize, OpArg arg, u32 address,
|
||||||
|
BitSet32 registersInUse)
|
||||||
|
{
|
||||||
|
arg = FixImmediate(accessSize, arg);
|
||||||
|
|
||||||
|
// If we already know the address through constant folding, we can do some
|
||||||
|
// fun tricks...
|
||||||
|
if (jit->jo.optimizeGatherPipe && PowerPC::IsOptimizableGatherPipeWrite(address))
|
||||||
|
{
|
||||||
|
if (!arg.IsSimpleReg(RSCRATCH))
|
||||||
|
MOV(accessSize, R(RSCRATCH), arg);
|
||||||
|
|
||||||
|
UnsafeWriteGatherPipe(accessSize);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (PowerPC::IsOptimizableRAMAddress(address))
|
||||||
|
{
|
||||||
|
WriteToConstRamAddress(accessSize, arg, address);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Helps external systems know which instruction triggered the write
|
||||||
|
MOV(32, PPCSTATE(pc), Imm32(jit->js.compilerPC));
|
||||||
|
|
||||||
|
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
||||||
|
switch (accessSize)
|
||||||
|
{
|
||||||
|
case 64:
|
||||||
|
ABI_CallFunctionAC(64, PowerPC::Write_U64, arg, address);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
ABI_CallFunctionAC(32, PowerPC::Write_U32, arg, address);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
ABI_CallFunctionAC(16, PowerPC::Write_U16, arg, address);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
ABI_CallFunctionAC(8, PowerPC::Write_U8, arg, address);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EmuCodeBlock::WriteToConstRamAddress(int accessSize, OpArg arg, u32 address, bool swap)
|
void EmuCodeBlock::WriteToConstRamAddress(int accessSize, OpArg arg, u32 address, bool swap)
|
||||||
{
|
{
|
||||||
X64Reg reg;
|
X64Reg reg;
|
||||||
|
@ -653,6 +686,30 @@ void EmuCodeBlock::WriteToConstRamAddress(int accessSize, OpArg arg, u32 address
|
||||||
MOV(accessSize, MRegSum(RMEM, RSCRATCH2), R(reg));
|
MOV(accessSize, MRegSum(RMEM, RSCRATCH2), R(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuCodeBlock::JitGetAndClearCAOV(bool oe)
|
||||||
|
{
|
||||||
|
if (oe)
|
||||||
|
AND(8, PPCSTATE(xer_so_ov), Imm8(~XER_OV_MASK)); // XER.OV = 0
|
||||||
|
SHR(8, PPCSTATE(xer_ca), Imm8(1)); // carry = XER.CA, XER.CA = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuCodeBlock::JitSetCA()
|
||||||
|
{
|
||||||
|
MOV(8, PPCSTATE(xer_ca), Imm8(1)); // XER.CA = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some testing shows CA is set roughly ~1/3 of the time (relative to clears), so
|
||||||
|
// branchless calculation of CA is probably faster in general.
|
||||||
|
void EmuCodeBlock::JitSetCAIf(CCFlags conditionCode)
|
||||||
|
{
|
||||||
|
SETcc(conditionCode, PPCSTATE(xer_ca));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuCodeBlock::JitClearCA()
|
||||||
|
{
|
||||||
|
MOV(8, PPCSTATE(xer_ca), Imm8(0));
|
||||||
|
}
|
||||||
|
|
||||||
void EmuCodeBlock::ForceSinglePrecision(X64Reg output, const OpArg& input, bool packed,
|
void EmuCodeBlock::ForceSinglePrecision(X64Reg output, const OpArg& input, bool packed,
|
||||||
bool duplicate)
|
bool duplicate)
|
||||||
{
|
{
|
||||||
|
@ -1083,30 +1140,6 @@ void EmuCodeBlock::SetFPRF(Gen::X64Reg xmm)
|
||||||
OR(32, PPCSTATE(fpscr), R(RSCRATCH));
|
OR(32, PPCSTATE(fpscr), R(RSCRATCH));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuCodeBlock::JitGetAndClearCAOV(bool oe)
|
|
||||||
{
|
|
||||||
if (oe)
|
|
||||||
AND(8, PPCSTATE(xer_so_ov), Imm8(~XER_OV_MASK)); // XER.OV = 0
|
|
||||||
SHR(8, PPCSTATE(xer_ca), Imm8(1)); // carry = XER.CA, XER.CA = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuCodeBlock::JitSetCA()
|
|
||||||
{
|
|
||||||
MOV(8, PPCSTATE(xer_ca), Imm8(1)); // XER.CA = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some testing shows CA is set roughly ~1/3 of the time (relative to clears), so
|
|
||||||
// branchless calculation of CA is probably faster in general.
|
|
||||||
void EmuCodeBlock::JitSetCAIf(CCFlags conditionCode)
|
|
||||||
{
|
|
||||||
SETcc(conditionCode, PPCSTATE(xer_ca));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuCodeBlock::JitClearCA()
|
|
||||||
{
|
|
||||||
MOV(8, PPCSTATE(xer_ca), Imm8(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmuCodeBlock::Clear()
|
void EmuCodeBlock::Clear()
|
||||||
{
|
{
|
||||||
backPatchInfo.clear();
|
backPatchInfo.clear();
|
|
@ -1,106 +1,23 @@
|
||||||
// Copyright 2010 Dolphin Emulator Project
|
// Copyright 2016 Dolphin Emulator Project
|
||||||
// Licensed under GPLv2+
|
// Licensed under GPLv2+
|
||||||
// Refer to the license.txt file included./
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "Common/BitSet.h"
|
#include "Common/BitSet.h"
|
||||||
#include "Common/CPUDetect.h"
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/x64Emitter.h"
|
#include "Common/x64Emitter.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
|
||||||
|
#include "Core/PowerPC/Jit64Common/FarCodeCache.h"
|
||||||
|
#include "Core/PowerPC/Jit64Common/TrampolineInfo.h"
|
||||||
|
|
||||||
namespace MMIO
|
namespace MMIO
|
||||||
{
|
{
|
||||||
class Mapping;
|
class Mapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We offset by 0x80 because the range of one byte memory offsets is
|
|
||||||
// -0x80..0x7f.
|
|
||||||
#define PPCSTATE(x) \
|
|
||||||
MDisp(RPPCSTATE, (int)((char*)&PowerPC::ppcState.x - (char*)&PowerPC::ppcState) - 0x80)
|
|
||||||
// In case you want to disable the ppcstate register:
|
|
||||||
// #define PPCSTATE(x) M(&PowerPC::ppcState.x)
|
|
||||||
#define PPCSTATE_LR PPCSTATE(spr[SPR_LR])
|
|
||||||
#define PPCSTATE_CTR PPCSTATE(spr[SPR_CTR])
|
|
||||||
#define PPCSTATE_SRR0 PPCSTATE(spr[SPR_SRR0])
|
|
||||||
#define PPCSTATE_SRR1 PPCSTATE(spr[SPR_SRR1])
|
|
||||||
|
|
||||||
// A place to throw blocks of code we don't want polluting the cache, e.g. rarely taken
|
|
||||||
// exception branches.
|
|
||||||
class FarCodeCache : public Gen::X64CodeBlock
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
bool m_enabled = false;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool Enabled() const { return m_enabled; }
|
|
||||||
void Init(int size)
|
|
||||||
{
|
|
||||||
AllocCodeSpace(size);
|
|
||||||
m_enabled = true;
|
|
||||||
}
|
|
||||||
void Shutdown()
|
|
||||||
{
|
|
||||||
FreeCodeSpace();
|
|
||||||
m_enabled = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr int CODE_SIZE = 1024 * 1024 * 32;
|
|
||||||
|
|
||||||
// a bit of a hack; the MMU results in a vast amount more code ending up in the far cache,
|
|
||||||
// mostly exception handling, so give it a whole bunch more space if the MMU is on.
|
|
||||||
constexpr int FARCODE_SIZE = 1024 * 1024 * 8;
|
|
||||||
constexpr int FARCODE_SIZE_MMU = 1024 * 1024 * 48;
|
|
||||||
|
|
||||||
// same for the trampoline code cache, because fastmem results in far more backpatches in MMU mode
|
|
||||||
constexpr int TRAMPOLINE_CODE_SIZE = 1024 * 1024 * 8;
|
|
||||||
constexpr int TRAMPOLINE_CODE_SIZE_MMU = 1024 * 1024 * 32;
|
|
||||||
|
|
||||||
// Stores information we need to batch-patch a MOV with a call to the slow read/write path after
|
|
||||||
// it faults. There will be 10s of thousands of these structs live, so be wary of making this too
|
|
||||||
// big.
|
|
||||||
struct TrampolineInfo final
|
|
||||||
{
|
|
||||||
// The start of the store operation that failed -- we will patch a JMP here
|
|
||||||
u8* start;
|
|
||||||
|
|
||||||
// The start + len = end of the store operation (points to the next instruction)
|
|
||||||
u32 len;
|
|
||||||
|
|
||||||
// The PPC PC for the current load/store block
|
|
||||||
u32 pc;
|
|
||||||
|
|
||||||
// Saved because we need these to make the ABI call in the trampoline
|
|
||||||
BitSet32 registersInUse;
|
|
||||||
|
|
||||||
// The MOV operation
|
|
||||||
Gen::X64Reg nonAtomicSwapStoreSrc;
|
|
||||||
|
|
||||||
// src/dest for load/store
|
|
||||||
s32 offset;
|
|
||||||
Gen::X64Reg op_reg;
|
|
||||||
Gen::OpArg op_arg;
|
|
||||||
|
|
||||||
// Original SafeLoadXXX/SafeStoreXXX flags
|
|
||||||
u8 flags;
|
|
||||||
|
|
||||||
// Memory access size (in bytes)
|
|
||||||
u8 accessSize : 4;
|
|
||||||
|
|
||||||
// true if this is a read op vs a write
|
|
||||||
bool read : 1;
|
|
||||||
|
|
||||||
// for read operations, true if needs sign-extension after load
|
|
||||||
bool signExtend : 1;
|
|
||||||
|
|
||||||
// Set to true if we added the offset to the address and need to undo it
|
|
||||||
bool offsetAddedToAddress : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Like XCodeBlock but has some utilities for memory access.
|
// Like XCodeBlock but has some utilities for memory access.
|
||||||
class EmuCodeBlock : public Gen::X64CodeBlock
|
class EmuCodeBlock : public Gen::X64CodeBlock
|
||||||
{
|
{
|
||||||
|
@ -111,17 +28,8 @@ public:
|
||||||
void MemoryExceptionCheck();
|
void MemoryExceptionCheck();
|
||||||
|
|
||||||
// Simple functions to switch between near and far code emitting
|
// Simple functions to switch between near and far code emitting
|
||||||
void SwitchToFarCode()
|
void SwitchToFarCode();
|
||||||
{
|
void SwitchToNearCode();
|
||||||
nearcode = GetWritableCodePtr();
|
|
||||||
SetCodePtr(farcode.GetWritableCodePtr());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitchToNearCode()
|
|
||||||
{
|
|
||||||
farcode.SetCodePtr(GetWritableCodePtr());
|
|
||||||
SetCodePtr(nearcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Gen::FixupBranch CheckIfSafeAddress(const Gen::OpArg& reg_value, Gen::X64Reg reg_addr,
|
Gen::FixupBranch CheckIfSafeAddress(const Gen::OpArg& reg_value, Gen::X64Reg reg_addr,
|
||||||
BitSet32 registers_in_use);
|
BitSet32 registers_in_use);
|
||||||
|
@ -133,10 +41,8 @@ public:
|
||||||
void UnsafeWriteRegToReg(Gen::OpArg reg_value, Gen::X64Reg reg_addr, int accessSize,
|
void UnsafeWriteRegToReg(Gen::OpArg reg_value, Gen::X64Reg reg_addr, int accessSize,
|
||||||
s32 offset = 0, bool swap = true, Gen::MovInfo* info = nullptr);
|
s32 offset = 0, bool swap = true, Gen::MovInfo* info = nullptr);
|
||||||
void UnsafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize,
|
void UnsafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize,
|
||||||
s32 offset = 0, bool swap = true, Gen::MovInfo* info = nullptr)
|
s32 offset = 0, bool swap = true, Gen::MovInfo* info = nullptr);
|
||||||
{
|
|
||||||
UnsafeWriteRegToReg(R(reg_value), reg_addr, accessSize, offset, swap, info);
|
|
||||||
}
|
|
||||||
bool UnsafeLoadToReg(Gen::X64Reg reg_value, Gen::OpArg opAddress, int accessSize, s32 offset,
|
bool UnsafeLoadToReg(Gen::X64Reg reg_value, Gen::OpArg opAddress, int accessSize, s32 offset,
|
||||||
bool signExtend, Gen::MovInfo* info = nullptr);
|
bool signExtend, Gen::MovInfo* info = nullptr);
|
||||||
void UnsafeWriteGatherPipe(int accessSize);
|
void UnsafeWriteGatherPipe(int accessSize);
|
||||||
|
@ -169,20 +75,15 @@ public:
|
||||||
void SafeWriteRegToReg(Gen::OpArg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset,
|
void SafeWriteRegToReg(Gen::OpArg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset,
|
||||||
BitSet32 registersInUse, int flags = 0);
|
BitSet32 registersInUse, int flags = 0);
|
||||||
void SafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset,
|
void SafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset,
|
||||||
BitSet32 registersInUse, int flags = 0)
|
BitSet32 registersInUse, int flags = 0);
|
||||||
{
|
|
||||||
SafeWriteRegToReg(R(reg_value), reg_addr, accessSize, offset, registersInUse, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
// applies to safe and unsafe WriteRegToReg
|
// applies to safe and unsafe WriteRegToReg
|
||||||
bool WriteClobbersRegValue(int accessSize, bool swap)
|
bool WriteClobbersRegValue(int accessSize, bool swap);
|
||||||
{
|
|
||||||
return swap && !cpu_info.bMOVBE && accessSize > 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteToConstRamAddress(int accessSize, Gen::OpArg arg, u32 address, bool swap = true);
|
|
||||||
// returns true if an exception could have been caused
|
// returns true if an exception could have been caused
|
||||||
bool WriteToConstAddress(int accessSize, Gen::OpArg arg, u32 address, BitSet32 registersInUse);
|
bool WriteToConstAddress(int accessSize, Gen::OpArg arg, u32 address, BitSet32 registersInUse);
|
||||||
|
void WriteToConstRamAddress(int accessSize, Gen::OpArg arg, u32 address, bool swap = true);
|
||||||
|
|
||||||
void JitGetAndClearCAOV(bool oe);
|
void JitGetAndClearCAOV(bool oe);
|
||||||
void JitSetCA();
|
void JitSetCA();
|
||||||
void JitSetCAIf(Gen::CCFlags conditionCode);
|
void JitSetCAIf(Gen::CCFlags conditionCode);
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2016 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "Core/PowerPC/Jit64Common/FarCodeCache.h"
|
||||||
|
|
||||||
|
void FarCodeCache::Init(int size)
|
||||||
|
{
|
||||||
|
AllocCodeSpace(size);
|
||||||
|
m_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FarCodeCache::Shutdown()
|
||||||
|
{
|
||||||
|
FreeCodeSpace();
|
||||||
|
m_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FarCodeCache::Enabled() const
|
||||||
|
{
|
||||||
|
return m_enabled;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2016 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common/x64Emitter.h"
|
||||||
|
|
||||||
|
// a bit of a hack; the MMU results in a vast amount more code ending up in the far cache,
|
||||||
|
// mostly exception handling, so give it a whole bunch more space if the MMU is on.
|
||||||
|
constexpr int FARCODE_SIZE = 1024 * 1024 * 8;
|
||||||
|
constexpr int FARCODE_SIZE_MMU = 1024 * 1024 * 48;
|
||||||
|
|
||||||
|
// A place to throw blocks of code we don't want polluting the cache, e.g. rarely taken
|
||||||
|
// exception branches.
|
||||||
|
class FarCodeCache : public Gen::X64CodeBlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Init(int size);
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
bool Enabled() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_enabled = false;
|
||||||
|
};
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h"
|
#include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h"
|
||||||
#include "Common/Assert.h"
|
#include "Common/Assert.h"
|
||||||
|
#include "Common/CPUDetect.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/JitRegister.h"
|
#include "Common/JitRegister.h"
|
||||||
#include "Common/MathUtil.h"
|
#include "Common/MathUtil.h"
|
||||||
|
@ -12,7 +13,7 @@
|
||||||
#include "Core/HW/GPFifo.h"
|
#include "Core/HW/GPFifo.h"
|
||||||
#include "Core/PowerPC/Gekko.h"
|
#include "Core/PowerPC/Gekko.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
|
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
#define QUANTIZED_REGS_TO_SAVE \
|
#define QUANTIZED_REGS_TO_SAVE \
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/EmuCodeBlock.h"
|
||||||
#include "Core/PowerPC/JitCommon/JitAsmCommon.h"
|
#include "Core/PowerPC/JitCommon/JitAsmCommon.h"
|
||||||
|
|
||||||
enum EQuantizeType : u32;
|
enum EQuantizeType : u32;
|
||||||
|
|
|
@ -32,6 +32,8 @@ constexpr Gen::X64Reg RMEM = Gen::RBX;
|
||||||
// to address as much as possible in a one-byte offset form.
|
// to address as much as possible in a one-byte offset form.
|
||||||
constexpr Gen::X64Reg RPPCSTATE = Gen::RBP;
|
constexpr Gen::X64Reg RPPCSTATE = Gen::RBP;
|
||||||
|
|
||||||
|
constexpr int CODE_SIZE = 1024 * 1024 * 32;
|
||||||
|
|
||||||
class Jitx86Base : public JitBase, public QuantizedMemoryRoutines
|
class Jitx86Base : public JitBase, public QuantizedMemoryRoutines
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2010 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included./
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
// We offset by 0x80 because the range of one byte memory offsets is
|
||||||
|
// -0x80..0x7f.
|
||||||
|
#define PPCSTATE(x) \
|
||||||
|
MDisp(RPPCSTATE, (int)((char*)&PowerPC::ppcState.x - (char*)&PowerPC::ppcState) - 0x80)
|
||||||
|
// In case you want to disable the ppcstate register:
|
||||||
|
// #define PPCSTATE(x) M(&PowerPC::ppcState.x)
|
||||||
|
#define PPCSTATE_LR PPCSTATE(spr[SPR_LR])
|
||||||
|
#define PPCSTATE_CTR PPCSTATE(spr[SPR_CTR])
|
||||||
|
#define PPCSTATE_SRR0 PPCSTATE(spr[SPR_SRR0])
|
||||||
|
#define PPCSTATE_SRR1 PPCSTATE(spr[SPR_SRR1])
|
|
@ -12,7 +12,8 @@
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
#include "Common/x64Emitter.h"
|
#include "Common/x64Emitter.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
|
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
|
#include "Core/PowerPC/Jit64Common/TrampolineInfo.h"
|
||||||
#include "Core/PowerPC/JitCommon/JitBase.h"
|
#include "Core/PowerPC/JitCommon/JitBase.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
|
#include "Core/PowerPC/Jit64Common/EmuCodeBlock.h"
|
||||||
|
|
||||||
|
struct TrampolineInfo;
|
||||||
|
|
||||||
|
// a bit of a hack; the MMU results in more code ending up in the trampoline cache,
|
||||||
|
// because fastmem results in far more backpatches in MMU mode
|
||||||
|
constexpr int TRAMPOLINE_CODE_SIZE = 1024 * 1024 * 8;
|
||||||
|
constexpr int TRAMPOLINE_CODE_SIZE_MMU = 1024 * 1024 * 32;
|
||||||
|
|
||||||
// We need at least this many bytes for backpatching.
|
// We need at least this many bytes for backpatching.
|
||||||
constexpr int BACKPATCH_SIZE = 5;
|
constexpr int BACKPATCH_SIZE = 5;
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// Copyright 2016 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Common/BitSet.h"
|
||||||
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Common/x64Emitter.h"
|
||||||
|
|
||||||
|
// Stores information we need to batch-patch a MOV with a call to the slow read/write path after
|
||||||
|
// it faults. There will be 10s of thousands of these structs live, so be wary of making this too
|
||||||
|
// big.
|
||||||
|
struct TrampolineInfo final
|
||||||
|
{
|
||||||
|
// The start of the store operation that failed -- we will patch a JMP here
|
||||||
|
u8* start;
|
||||||
|
|
||||||
|
// The start + len = end of the store operation (points to the next instruction)
|
||||||
|
u32 len;
|
||||||
|
|
||||||
|
// The PPC PC for the current load/store block
|
||||||
|
u32 pc;
|
||||||
|
|
||||||
|
// Saved because we need these to make the ABI call in the trampoline
|
||||||
|
BitSet32 registersInUse;
|
||||||
|
|
||||||
|
// The MOV operation
|
||||||
|
Gen::X64Reg nonAtomicSwapStoreSrc;
|
||||||
|
|
||||||
|
// src/dest for load/store
|
||||||
|
s32 offset;
|
||||||
|
Gen::X64Reg op_reg;
|
||||||
|
Gen::OpArg op_arg;
|
||||||
|
|
||||||
|
// Original SafeLoadXXX/SafeStoreXXX flags
|
||||||
|
u8 flags;
|
||||||
|
|
||||||
|
// Memory access size (in bytes)
|
||||||
|
u8 accessSize : 4;
|
||||||
|
|
||||||
|
// true if this is a read op vs a write
|
||||||
|
bool read : 1;
|
||||||
|
|
||||||
|
// for read operations, true if needs sign-extension after load
|
||||||
|
bool signExtend : 1;
|
||||||
|
|
||||||
|
// Set to true if we added the offset to the address and need to undo it
|
||||||
|
bool offsetAddedToAddress : 1;
|
||||||
|
};
|
|
@ -39,6 +39,7 @@ The register allocation is linear scan allocation.
|
||||||
#include "Core/HW/CPU.h"
|
#include "Core/HW/CPU.h"
|
||||||
#include "Core/HW/ProcessorInterface.h"
|
#include "Core/HW/ProcessorInterface.h"
|
||||||
#include "Core/PowerPC/Gekko.h"
|
#include "Core/PowerPC/Gekko.h"
|
||||||
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/Jit64IL/JitIL.h"
|
#include "Core/PowerPC/Jit64IL/JitIL.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "Core/HLE/HLE.h"
|
#include "Core/HLE/HLE.h"
|
||||||
#include "Core/HW/CPU.h"
|
#include "Core/HW/CPU.h"
|
||||||
#include "Core/PatchEngine.h"
|
#include "Core/PatchEngine.h"
|
||||||
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/Jit64IL/JitIL.h"
|
#include "Core/PowerPC/Jit64IL/JitIL.h"
|
||||||
#include "Core/PowerPC/Jit64IL/JitIL_Tables.h"
|
#include "Core/PowerPC/Jit64IL/JitIL_Tables.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "Core/PowerPC/JitILCommon/JitILBase.h"
|
#include "Core/PowerPC/JitILCommon/JitILBase.h"
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
|
||||||
void JitILBase::psq_st(UGeckoInstruction inst)
|
void JitILBase::psq_st(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue