Merge pull request #4516 from lioncash/jit

Jit: Move most x86-64-specific code out of JitCommon
This commit is contained in:
Markus Wick
2016-12-14 23:57:16 +01:00
committed by GitHub
29 changed files with 232 additions and 190 deletions
+4 -3
View File
@@ -206,10 +206,11 @@ if(_M_X86)
PowerPC/Jit64/Jit_Paired.cpp
PowerPC/Jit64/JitRegCache.cpp
PowerPC/Jit64/Jit_SystemRegisters.cpp
PowerPC/Jit64Common/BlockCache.cpp
PowerPC/Jit64Common/Jit64AsmCommon.cpp
PowerPC/JitCommon/JitBackpatch.cpp
PowerPC/JitCommon/Jit_Util.cpp
PowerPC/JitCommon/TrampolineCache.cpp)
PowerPC/Jit64Common/Jit64Base.cpp
PowerPC/Jit64Common/Jit64Util.cpp
PowerPC/Jit64Common/TrampolineCache.cpp)
elseif(_M_ARM_64)
set(SRCS ${SRCS}
PowerPC/JitArm64/Jit.cpp
+8 -5
View File
@@ -237,13 +237,14 @@
<ClCompile Include="PowerPC\Jit64\Jit_LoadStorePaired.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit_Paired.cpp" />
<ClCompile Include="PowerPC\Jit64\Jit_SystemRegisters.cpp" />
<ClCompile Include="PowerPC\Jit64Common\BlockCache.cpp" />
<ClCompile Include="PowerPC\Jit64Common\Jit64AsmCommon.cpp" />
<ClCompile Include="PowerPC\Jit64Common\Jit64Base.cpp" />
<ClCompile Include="PowerPC\Jit64Common\Jit64Util.cpp" />
<ClCompile Include="PowerPC\Jit64Common\TrampolineCache.cpp" />
<ClCompile Include="PowerPC\JitCommon\JitAsmCommon.cpp" />
<ClCompile Include="PowerPC\JitCommon\JitBackpatch.cpp" />
<ClCompile Include="PowerPC\JitCommon\JitBase.cpp" />
<ClCompile Include="PowerPC\JitCommon\JitCache.cpp" />
<ClCompile Include="PowerPC\JitCommon\Jit_Util.cpp" />
<ClCompile Include="PowerPC\JitCommon\TrampolineCache.cpp" />
<ClCompile Include="PowerPC\CachedInterpreter.cpp" />
<ClCompile Include="PowerPC\JitInterface.cpp" />
<ClCompile Include="PowerPC\MMU.cpp" />
@@ -429,12 +430,14 @@
<ClInclude Include="PowerPC\Jit64\JitRegCache.h" />
<ClInclude Include="PowerPC\JitILCommon\IR.h" />
<ClInclude Include="PowerPC\JitILCommon\JitILBase.h" />
<ClInclude Include="PowerPC\Jit64Common\BlockCache.h" />
<ClInclude Include="PowerPC\Jit64Common\Jit64AsmCommon.h" />
<ClInclude Include="PowerPC\Jit64Common\Jit64Base.h" />
<ClInclude Include="PowerPC\Jit64Common\Jit64Util.h" />
<ClInclude Include="PowerPC\Jit64Common\TrampolineCache.h" />
<ClInclude Include="PowerPC\JitCommon\JitAsmCommon.h" />
<ClInclude Include="PowerPC\JitCommon\JitBase.h" />
<ClInclude Include="PowerPC\JitCommon\JitCache.h" />
<ClInclude Include="PowerPC\JitCommon\Jit_Util.h" />
<ClInclude Include="PowerPC\JitCommon\TrampolineCache.h" />
<ClInclude Include="PowerPC\CachedInterpreter.h" />
<ClInclude Include="PowerPC\JitInterface.h" />
<ClInclude Include="PowerPC\PowerPC.h" />
+23 -14
View File
@@ -651,9 +651,6 @@
<ClCompile Include="PowerPC\SignatureDB.cpp">
<Filter>PowerPC</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitCommon\Jit_Util.cpp">
<Filter>PowerPC\JitCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitCommon\JitAsmCommon.cpp">
<Filter>PowerPC\JitCommon</Filter>
</ClCompile>
@@ -663,9 +660,6 @@
<ClCompile Include="PowerPC\JitCommon\JitCache.cpp">
<Filter>PowerPC\JitCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitCommon\TrampolineCache.cpp">
<Filter>PowerPC\JitCommon</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64IL\IR_X86.cpp">
<Filter>PowerPC\JitIL</Filter>
</ClCompile>
@@ -741,12 +735,21 @@
<ClCompile Include="PowerPC\MMU.cpp">
<Filter>PowerPC</Filter>
</ClCompile>
<ClCompile Include="PowerPC\JitCommon\JitBackpatch.cpp">
<Filter>PowerPC\JitCommon</Filter>
<ClCompile Include="PowerPC\Jit64Common\BlockCache.cpp">
<Filter>PowerPC\Jit64Common</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64Common\Jit64AsmCommon.cpp">
<Filter>PowerPC\Jit64Common</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64Common\Jit64Base.cpp">
<Filter>PowerPC\Jit64Common</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64Common\Jit64Util.cpp">
<Filter>PowerPC\Jit64Common</Filter>
</ClCompile>
<ClCompile Include="PowerPC\Jit64Common\TrampolineCache.cpp">
<Filter>PowerPC\Jit64Common</Filter>
</ClCompile>
<ClCompile Include="Analytics.cpp" />
<ClCompile Include="IPC_HLE\WII_IPC_HLE_Device_usb_ven.cpp">
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
@@ -1238,9 +1241,6 @@
<ClInclude Include="PowerPC\SignatureDB.h">
<Filter>PowerPC</Filter>
</ClInclude>
<ClInclude Include="PowerPC\JitCommon\Jit_Util.h">
<Filter>PowerPC\JitCommon</Filter>
</ClInclude>
<ClInclude Include="PowerPC\JitCommon\JitAsmCommon.h">
<Filter>PowerPC\JitCommon</Filter>
</ClInclude>
@@ -1250,9 +1250,6 @@
<ClInclude Include="PowerPC\JitCommon\JitCache.h">
<Filter>PowerPC\JitCommon</Filter>
</ClInclude>
<ClInclude Include="PowerPC\JitCommon\TrampolineCache.h">
<Filter>PowerPC\JitCommon</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64IL\JitIL.h">
<Filter>PowerPC\JitIL</Filter>
</ClInclude>
@@ -1278,9 +1275,21 @@
<ClInclude Include="HW\GCKeyboard.h">
<Filter>HW %28Flipper/Hollywood%29\GCKeyboard</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64Common\BlockCache.h">
<Filter>PowerPC\Jit64Common</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64Common\Jit64AsmCommon.h">
<Filter>PowerPC\Jit64Common</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64Common\Jit64Base.h">
<Filter>PowerPC\Jit64Common</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64Common\Jit64Util.h">
<Filter>PowerPC\Jit64Common</Filter>
</ClInclude>
<ClInclude Include="PowerPC\Jit64Common\TrampolineCache.h">
<Filter>PowerPC\Jit64Common</Filter>
</ClInclude>
<ClInclude Include="Analytics.h" />
<ClInclude Include="IPC_HLE\WII_IPC_HLE_Device_usb_ven.h">
<Filter>IPC HLE %28IOS/Starlet%29\USB</Filter>
@@ -10,6 +10,7 @@
#include "Core/HLE/HLE.h"
#include "Core/HW/CPU.h"
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PowerPC.h"
+1 -1
View File
@@ -26,7 +26,7 @@
#include "Core/PowerPC/Jit64/Jit64_Tables.h"
#include "Core/PowerPC/Jit64/JitAsm.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/JitCommon/Jit_Util.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/Profiler.h"
+1 -1
View File
@@ -23,7 +23,7 @@
#include "Common/x64Emitter.h"
#include "Core/PowerPC/Jit64/JitAsm.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
#include "Core/PowerPC/JitCommon/JitCache.h"
#include "Core/PowerPC/PPCAnalyst.h"
@@ -14,7 +14,7 @@
#include "Common/x64Emitter.h"
#include "Core/PowerPC/Jit64/Jit.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/JitCommon/Jit_Util.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Core/PowerPC/PowerPC.h"
using namespace Gen;
@@ -11,7 +11,7 @@
#include "Common/x64Emitter.h"
#include "Core/PowerPC/Jit64/Jit.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/JitCommon/Jit_Util.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PowerPC.h"
@@ -17,7 +17,7 @@
#include "Core/HW/DSP.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/JitCommon/Jit_Util.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
@@ -4,11 +4,10 @@
#include "Core/PowerPC/Jit64/Jit.h"
#include "Common/BitSet.h"
#include "Common/CPUDetect.h"
#include "Common/CommonTypes.h"
#include "Common/x64Emitter.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/JitCommon/Jit_Util.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
using namespace Gen;
@@ -6,13 +6,12 @@
// Should give a very noticeable speed boost to paired single heavy code.
#include "Core/PowerPC/Jit64/Jit.h"
#include "Common/BitSet.h"
#include "Common/CPUDetect.h"
#include "Common/CommonTypes.h"
#include "Common/x64Emitter.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Core/PowerPC/JitCommon/JitAsmCommon.h"
#include "Core/PowerPC/JitCommon/Jit_Util.h"
#include "Core/PowerPC/PowerPC.h"
using namespace Gen;
@@ -9,7 +9,7 @@
#include "Core/CoreTiming.h"
#include "Core/HW/ProcessorInterface.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
#include "Core/PowerPC/JitCommon/Jit_Util.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Core/PowerPC/PowerPC.h"
using namespace Gen;
@@ -0,0 +1,40 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/PowerPC/Jit64Common/BlockCache.h"
#include "Common/CommonTypes.h"
#include "Common/x64Emitter.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
void JitBlockCache::WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest)
{
u8* location = source.exitPtrs;
const u8* address = dest ? dest->checkedEntry : jit->GetAsmRoutines()->dispatcher;
Gen::XEmitter emit(location);
if (*location == 0xE8)
{
emit.CALL(address);
}
else
{
// If we're going to link with the next block, there is no need
// to emit JMP. So just NOP out the gap to the next block.
// Support up to 3 additional bytes because of alignment.
s64 offset = address - emit.GetCodePtr();
if (offset > 0 && offset <= 5 + 3)
emit.NOP(offset);
else
emit.JMP(address, true);
}
}
void JitBlockCache::WriteDestroyBlock(const JitBlock& block)
{
// Only clear the entry points as we might still be within this block.
Gen::XEmitter emit(const_cast<u8*>(block.checkedEntry));
emit.INT3();
Gen::XEmitter emit2(const_cast<u8*>(block.normalEntry));
emit2.INT3();
}
@@ -0,0 +1,14 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "Core/PowerPC/JitCommon/JitCache.h"
class JitBlockCache : public JitBaseBlockCache
{
private:
void WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest) override;
void WriteDestroyBlock(const JitBlock& block) override;
};
@@ -11,8 +11,8 @@
#include "Common/x64Emitter.h"
#include "Core/HW/GPFifo.h"
#include "Core/PowerPC/Gekko.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
#include "Core/PowerPC/JitCommon/Jit_Util.h"
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Core/PowerPC/PowerPC.h"
#define QUANTIZED_REGS_TO_SAVE \
@@ -4,8 +4,9 @@
#pragma once
#include "Common/CommonTypes.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Core/PowerPC/JitCommon/JitAsmCommon.h"
#include "Core/PowerPC/JitCommon/Jit_Util.h"
enum EQuantizeType : u32;
@@ -1,22 +1,24 @@
// Copyright 2008 Dolphin Emulator Project
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <cinttypes>
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
#include <disasm.h>
#include <sstream>
#include <string>
#include "disasm.h"
#include "Common/Assert.h"
#include "Common/BitSet.h"
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h"
#include "Common/GekkoDisassembler.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Common/x64Emitter.h"
#include "Common/StringUtil.h"
#include "Common/x64Reg.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
using namespace Gen;
#include "Core/MachineContext.h"
#include "Core/PowerPC/PPCAnalyst.h"
// This generates some fairly heavy trampolines, but it doesn't really hurt.
// Only instructions that access I/O will get these, and there won't be that
@@ -24,19 +26,20 @@ using namespace Gen;
bool Jitx86Base::HandleFault(uintptr_t access_address, SContext* ctx)
{
// TODO: do we properly handle off-the-end?
if (access_address >= (uintptr_t)Memory::physical_base &&
access_address < (uintptr_t)Memory::physical_base + 0x100010000)
return BackPatch((u32)(access_address - (uintptr_t)Memory::physical_base), ctx);
if (access_address >= (uintptr_t)Memory::logical_base &&
access_address < (uintptr_t)Memory::logical_base + 0x100010000)
return BackPatch((u32)(access_address - (uintptr_t)Memory::logical_base), ctx);
const auto base_ptr = reinterpret_cast<uintptr_t>(Memory::physical_base);
if (access_address >= base_ptr && access_address < base_ptr + 0x100010000)
return BackPatch(static_cast<u32>(access_address - base_ptr), ctx);
const auto logical_base_ptr = reinterpret_cast<uintptr_t>(Memory::logical_base);
if (access_address >= logical_base_ptr && access_address < logical_base_ptr + 0x100010000)
return BackPatch(static_cast<u32>(access_address - logical_base_ptr), ctx);
return false;
}
bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
{
u8* codePtr = (u8*)ctx->CTX_PC;
u8* codePtr = reinterpret_cast<u8*>(ctx->CTX_PC);
if (!IsInSpace(codePtr))
return false; // this will become a regular crash real soon after this
@@ -87,7 +90,7 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
// before faulting (eg: the store+swap was not an atomic op like MOVBE), let's
// swap it back so that the swap can happen again (this double swap isn't ideal but
// only happens the first time we fault).
if (info.nonAtomicSwapStoreSrc != INVALID_REG)
if (info.nonAtomicSwapStoreSrc != Gen::INVALID_REG)
{
u64* ptr = ContextRN(ctx, info.nonAtomicSwapStoreSrc);
switch (info.accessSize << 3)
@@ -122,3 +125,41 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx)
return true;
}
void LogGeneratedX86(int size, PPCAnalyst::CodeBuffer* code_buffer, const u8* normalEntry,
JitBlock* b)
{
for (int i = 0; i < size; i++)
{
const PPCAnalyst::CodeOp& op = code_buffer->codebuffer[i];
std::string temp = StringFromFormat(
"%08x %s", op.address, GekkoDisassembler::Disassemble(op.inst.hex, op.address).c_str());
DEBUG_LOG(DYNA_REC, "IR_X86 PPC: %s\n", temp.c_str());
}
disassembler x64disasm;
x64disasm.set_syntax_intel();
u64 disasmPtr = reinterpret_cast<u64>(normalEntry);
const u8* end = normalEntry + b->codeSize;
while (reinterpret_cast<u8*>(disasmPtr) < end)
{
char sptr[1000] = "";
disasmPtr += x64disasm.disasm64(disasmPtr, disasmPtr, reinterpret_cast<u8*>(disasmPtr), sptr);
DEBUG_LOG(DYNA_REC, "IR_X86 x86: %s", sptr);
}
if (b->codeSize <= 250)
{
std::stringstream ss;
ss << std::hex;
for (u8 i = 0; i <= b->codeSize; i++)
{
ss.width(2);
ss.fill('0');
ss << static_cast<u32>(*(normalEntry + i));
}
DEBUG_LOG(DYNA_REC, "IR_X86 bin: %s\n\n\n", ss.str().c_str());
}
}
@@ -0,0 +1,48 @@
// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <cstdint>
#include "Common/CommonTypes.h"
#include "Common/x64Reg.h"
#include "Core/PowerPC/Jit64Common/BlockCache.h"
#include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h"
#include "Core/PowerPC/Jit64Common/TrampolineCache.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
namespace PPCAnalyst
{
class CodeBuffer;
}
// The following register assignments are common to Jit64 and Jit64IL:
// RSCRATCH and RSCRATCH2 are always scratch registers and can be used without
// limitation.
constexpr Gen::X64Reg RSCRATCH = Gen::RAX;
constexpr Gen::X64Reg RSCRATCH2 = Gen::RDX;
// RSCRATCH_EXTRA may be in the allocation order, so it has to be flushed
// before use.
constexpr Gen::X64Reg RSCRATCH_EXTRA = Gen::RCX;
// RMEM points to the start of emulated memory.
constexpr Gen::X64Reg RMEM = Gen::RBX;
// RPPCSTATE points to ppcState + 0x80. It's offset because we want to be able
// to address as much as possible in a one-byte offset form.
constexpr Gen::X64Reg RPPCSTATE = Gen::RBP;
class Jitx86Base : public JitBase, public QuantizedMemoryRoutines
{
protected:
bool BackPatch(u32 emAddress, SContext* ctx);
JitBlockCache blocks;
TrampolineCache trampolines;
public:
JitBlockCache* GetBlockCache() override { return &blocks; }
bool HandleFault(uintptr_t access_address, SContext* ctx) override;
};
void LogGeneratedX86(int size, PPCAnalyst::CodeBuffer* code_buffer, const u8* normalEntry,
JitBlock* b);
@@ -2,7 +2,7 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/PowerPC/JitCommon/Jit_Util.h"
#include "Core/PowerPC/Jit64Common/Jit64Util.h"
#include "Common/BitSet.h"
#include "Common/CommonTypes.h"
#include "Common/Intrinsics.h"
@@ -11,7 +11,8 @@
#include "Common/x64Emitter.h"
#include "Core/HW/MMIO.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
#include "Core/PowerPC/Jit64Common/Jit64Base.h"
#include "Core/PowerPC/Jit64Common/TrampolineCache.h"
#include "Core/PowerPC/PowerPC.h"
using namespace Gen;
@@ -79,7 +80,7 @@ bool EmuCodeBlock::UnsafeLoadToReg(X64Reg reg_value, OpArg opAddress, int access
{
// This method can potentially clobber the address if it shares a register
// with the load target. In this case we can just subtract offset from the
// register (see JitBackpatch for this implementation).
// register (see Jit64Base for this implementation).
offsetAddedToAddress = (reg_value == opAddress.GetSimpleReg());
LEA(32, reg_value, MDisp(opAddress.GetSimpleReg(), offset));
@@ -8,6 +8,7 @@
#include "Common/BitSet.h"
#include "Common/CPUDetect.h"
#include "Common/CommonTypes.h"
#include "Common/x64Emitter.h"
#include "Core/PowerPC/PowerPC.h"
@@ -48,16 +49,16 @@ public:
}
};
static const int CODE_SIZE = 1024 * 1024 * 32;
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.
static const int FARCODE_SIZE = 1024 * 1024 * 8;
static const int FARCODE_SIZE_MMU = 1024 * 1024 * 48;
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
static const int TRAMPOLINE_CODE_SIZE = 1024 * 1024 * 8;
static const int TRAMPOLINE_CODE_SIZE_MMU = 1024 * 1024 * 32;
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

Some files were not shown because too many files have changed in this diff Show More