diff options
Diffstat (limited to 'Source/Core/Common')
| -rw-r--r-- | Source/Core/Common/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | Source/Core/Common/Common.vcxproj | 2 | ||||
| -rw-r--r-- | Source/Core/Common/Common.vcxproj.filters | 2 | ||||
| -rw-r--r-- | Source/Core/Common/Src/Thunk.h | 46 | ||||
| -rw-r--r-- | Source/Core/Common/Src/x64ABI.cpp | 80 | ||||
| -rw-r--r-- | Source/Core/Common/Src/x64Emitter.cpp | 68 | ||||
| -rw-r--r-- | Source/Core/Common/Src/x64Emitter.h | 7 | ||||
| -rw-r--r-- | Source/Core/Common/Src/x64Thunk.cpp | 121 |
8 files changed, 84 insertions, 243 deletions
diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 6e230c7fa7..0302ee78c8 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -37,7 +37,6 @@ else() if(NOT _M_GENERIC) #X86 set(SRCS ${SRCS} Src/x64FPURoundMode.cpp - Src/x64Thunk.cpp ) endif() set(SRCS ${SRCS} Src/x64CPUDetect.cpp) diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index 4066febcca..20cf92dfc3 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -217,7 +217,6 @@ <ClCompile Include="Src\x64CPUDetect.cpp" /> <ClCompile Include="Src\x64Emitter.cpp" /> <ClCompile Include="Src\x64FPURoundMode.cpp" /> - <ClCompile Include="Src\x64Thunk.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="Src\Atomic.h" /> @@ -263,7 +262,6 @@ <ClInclude Include="Src\SymbolDB.h" /> <ClInclude Include="Src\SysConf.h" /> <ClInclude Include="Src\Thread.h" /> - <ClInclude Include="Src\Thunk.h" /> <ClInclude Include="Src\Timer.h" /> <ClInclude Include="Src\x64ABI.h" /> <ClInclude Include="Src\x64Analyzer.h" /> diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index a912cc3d8a..05b9edcb14 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -47,7 +47,6 @@ <ClCompile Include="Src\x64ABI.cpp" /> <ClCompile Include="Src\x64CPUDetect.cpp" /> <ClCompile Include="Src\x64FPURoundMode.cpp" /> - <ClCompile Include="Src\x64Thunk.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="Src\Atomic.h" /> @@ -84,7 +83,6 @@ <ClInclude Include="Src\SymbolDB.h" /> <ClInclude Include="Src\SysConf.h" /> <ClInclude Include="Src\Thread.h" /> - <ClInclude Include="Src\Thunk.h" /> <ClInclude Include="Src\Timer.h" /> <ClInclude Include="Src\x64Analyzer.h" /> <ClInclude Include="Src\x64Emitter.h" /> diff --git a/Source/Core/Common/Src/Thunk.h b/Source/Core/Common/Src/Thunk.h deleted file mode 100644 index b1487badf8..0000000000 --- a/Source/Core/Common/Src/Thunk.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#ifndef _THUNK_H_ -#define _THUNK_H_ - -#include <map> - -#include "Common.h" -#include "x64Emitter.h" - -// This simple class creates a wrapper around a C/C++ function that saves all fp state -// before entering it, and restores it upon exit. This is required to be able to selectively -// call functions from generated code, without inflicting the performance hit and increase -// of complexity that it means to protect the generated code from this problem. - -// This process is called thunking. - -// There will only ever be one level of thunking on the stack, plus, -// we don't want to pollute the stack, so we store away regs somewhere global. -// NOT THREAD SAFE. This may only be used from the CPU thread. -// Any other thread using this stuff will be FATAL. - -class ThunkManager : public Gen::XCodeBlock -{ - std::map<void *, const u8 *> thunks; - - const u8 *save_regs; - const u8 *load_regs; - -public: - ThunkManager() { - Init(); - } - ~ThunkManager() { - Shutdown(); - } - void *ProtectFunction(void *function, int num_params); -private: - void Init(); - void Shutdown(); - void Reset(); -}; - -#endif // _THUNK_H_ diff --git a/Source/Core/Common/Src/x64ABI.cpp b/Source/Core/Common/Src/x64ABI.cpp index 54d19c7775..3750636c3e 100644 --- a/Source/Core/Common/Src/x64ABI.cpp +++ b/Source/Core/Common/Src/x64ABI.cpp @@ -57,6 +57,86 @@ void XEmitter::ABI_RestoreStack(unsigned int frameSize, bool noProlog) { } } +void XEmitter::ABI_PushRegistersAndAdjustStack(u32 mask, bool noProlog) +{ + int regSize = +#ifdef _M_X64 + 8; +#else + 4; +#endif + int shadow = 0; +#if defined(_WIN32) && defined(_M_X64) + shadow = 0x20; +#endif + int count = 0; + for (int r = 0; r < 16; r++) + { + if (mask & (1 << r)) + { + PUSH((X64Reg) r); + count++; + } + } + int size = ((noProlog ? -regSize : 0) - (count * regSize)) & 0xf; + for (int x = 0; x < 16; x++) + { + if (mask & (1 << (16 + x))) + size += 16; + } + size += shadow; + if (size) + SUB(regSize * 8, R(RSP), size >= 0x80 ? Imm32(size) : Imm8(size)); + int offset = shadow; + for (int x = 0; x < 16; x++) + { + if (mask & (1 << (16 + x))) + { + MOVAPD(MDisp(RSP, offset), (X64Reg) x); + offset += 16; + } + } +} + +void XEmitter::ABI_PopRegistersAndAdjustStack(u32 mask, bool noProlog) +{ + int regSize = +#ifdef _M_X64 + 8; +#else + 4; +#endif + int size = 0; +#if defined(_WIN32) && defined(_M_X64) + size += 0x20; +#endif + for (int x = 0; x < 16; x++) + { + if (mask & (1 << (16 + x))) + { + MOVAPD((X64Reg) x, MDisp(RSP, size)); + size += 16; + } + } + int count = 0; + for (int r = 0; r < 16; r++) + { + if (mask & (1 << r)) + count++; + } + size += ((noProlog ? -regSize : 0) - (count * regSize)) & 0xf; + + if (size) + ADD(regSize * 8, R(RSP), size >= 0x80 ? Imm32(size) : Imm8(size)); + for (int r = 15; r >= 0; r--) + { + if (mask & (1 << r)) + { + POP((X64Reg) r); + } + } +} + #ifdef _M_IX86 // All32 // Shared code between Win32 and Unix32 diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 9b6731856f..a5d7cb2f0f 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -1634,74 +1634,6 @@ void XEmitter::___CallCdeclImport6(void* impptr, u32 arg0, u32 arg1, u32 arg2, u CALLptr(M(impptr)); } -void XEmitter::PushRegistersAndAlignStack(u32 mask) -{ - int shadow = 0; -#ifdef _WIN32 - shadow = 0x20; -#endif - int count = 0; - for (int r = 0; r < 16; r++) - { - if (mask & (1 << r)) - { - PUSH((X64Reg) r); - count++; - } - } - int size = (count & 1) ? 0 : 8; - for (int x = 0; x < 16; x++) - { - if (mask & (1 << (16 + x))) - size += 16; - } - size += shadow; - if (size) - SUB(64, R(RSP), size >= 0x80 ? Imm32(size) : Imm8(size)); - int offset = shadow; - for (int x = 0; x < 16; x++) - { - if (mask & (1 << (16 + x))) - { - MOVAPD(MDisp(RSP, offset), (X64Reg) x); - offset += 16; - } - } -} - -void XEmitter::PopRegistersAndAlignStack(u32 mask) -{ - int size = 0; -#ifdef _WIN32 - size += 0x20; -#endif - for (int x = 0; x < 16; x++) - { - if (mask & (1 << (16 + x))) - { - MOVAPD((X64Reg) x, MDisp(RSP, size)); - size += 16; - } - } - int count = 0; - for (int r = 0; r < 16; r++) - { - if (mask & (1 << r)) - count++; - } - size += (count & 1) ? 0 : 8; - - if (size) - ADD(64, R(RSP), size >= 0x80 ? Imm32(size) : Imm8(size)); - for (int r = 15; r >= 0; r--) - { - if (mask & (1 << r)) - { - POP((X64Reg) r); - } - } -} - #endif } diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index 87724a8092..94938b290a 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -646,6 +646,10 @@ public: void ABI_PushAllCalleeSavedRegsAndAdjustStack(); void ABI_PopAllCalleeSavedRegsAndAdjustStack(); + // A more flexible version of the above. + void ABI_PushRegistersAndAdjustStack(u32 mask, bool noProlog); + void ABI_PopRegistersAndAdjustStack(u32 mask, bool noProlog); + unsigned int ABI_GetAlignedFrameSize(unsigned int frameSize, bool noProlog = false); void ABI_AlignStack(unsigned int frameSize, bool noProlog = false); void ABI_RestoreStack(unsigned int frameSize, bool noProlog = false); @@ -691,9 +695,6 @@ public: #define DECLARE_IMPORT(x) extern "C" void *__imp_##x - void PushRegistersAndAlignStack(u32 mask); - void PopRegistersAndAlignStack(u32 mask); - #endif }; // class XEmitter diff --git a/Source/Core/Common/Src/x64Thunk.cpp b/Source/Core/Common/Src/x64Thunk.cpp deleted file mode 100644 index d77d78e40e..0000000000 --- a/Source/Core/Common/Src/x64Thunk.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project -// Licensed under GPLv2 -// Refer to the license.txt file included. - -#include <map> - -#include "Common.h" -#include "MemoryUtil.h" -#include "x64ABI.h" -#include "Thunk.h" - -#define THUNK_ARENA_SIZE 1024*1024*1 - -namespace -{ - -static u8 GC_ALIGNED32(saved_fp_state[16 * 4 * 4]); -static u8 GC_ALIGNED32(saved_gpr_state[16 * 8]); -static u16 saved_mxcsr; - -} // namespace - -using namespace Gen; - -void ThunkManager::Init() -{ - AllocCodeSpace(THUNK_ARENA_SIZE); - save_regs = GetCodePtr(); - for (int i = 2; i < ABI_GetNumXMMRegs(); i++) - MOVAPS(M(saved_fp_state + i * 16), (X64Reg)(XMM0 + i)); - STMXCSR(M(&saved_mxcsr)); -#ifdef _M_X64 - MOV(64, M(saved_gpr_state + 0 ), R(RCX)); - MOV(64, M(saved_gpr_state + 8 ), R(RDX)); - MOV(64, M(saved_gpr_state + 16), R(R8) ); - MOV(64, M(saved_gpr_state + 24), R(R9) ); - MOV(64, M(saved_gpr_state + 32), R(R10)); - MOV(64, M(saved_gpr_state + 40), R(R11)); -#ifndef _WIN32 - MOV(64, M(saved_gpr_state + 48), R(RSI)); - MOV(64, M(saved_gpr_state + 56), R(RDI)); -#endif - MOV(64, M(saved_gpr_state + 64), R(RBX)); -#else - MOV(32, M(saved_gpr_state + 0 ), R(RCX)); - MOV(32, M(saved_gpr_state + 4 ), R(RDX)); -#endif - RET(); - load_regs = GetCodePtr(); - LDMXCSR(M(&saved_mxcsr)); - for (int i = 2; i < ABI_GetNumXMMRegs(); i++) - MOVAPS((X64Reg)(XMM0 + i), M(saved_fp_state + i * 16)); -#ifdef _M_X64 - MOV(64, R(RCX), M(saved_gpr_state + 0 )); - MOV(64, R(RDX), M(saved_gpr_state + 8 )); - MOV(64, R(R8) , M(saved_gpr_state + 16)); - MOV(64, R(R9) , M(saved_gpr_state + 24)); - MOV(64, R(R10), M(saved_gpr_state + 32)); - MOV(64, R(R11), M(saved_gpr_state + 40)); -#ifndef _WIN32 - MOV(64, R(RSI), M(saved_gpr_state + 48)); - MOV(64, R(RDI), M(saved_gpr_state + 56)); -#endif - MOV(64, R(RBX), M(saved_gpr_state + 64)); -#else - MOV(32, R(RCX), M(saved_gpr_state + 0 )); - MOV(32, R(RDX), M(saved_gpr_state + 4 )); -#endif - RET(); -} - -void ThunkManager::Reset() -{ - thunks.clear(); - ResetCodePtr(); -} - -void ThunkManager::Shutdown() -{ - Reset(); - FreeCodeSpace(); -} - -void *ThunkManager::ProtectFunction(void *function, int num_params) -{ - std::map<void *, const u8 *>::iterator iter; - iter = thunks.find(function); - if (iter != thunks.end()) - return (void *)iter->second; - if (!region) - PanicAlert("Trying to protect functions before the emu is started. Bad bad bad."); - - const u8 *call_point = GetCodePtr(); -#ifdef _M_X64 - // Make sure to align stack. - ABI_AlignStack(0, true); - CALL((void*)save_regs); - CALL((void*)function); - CALL((void*)load_regs); - ABI_RestoreStack(0, true); - RET(); -#else - CALL((void*)save_regs); - // Since parameters are in the previous stack frame, not in registers, this takes some - // trickery : we simply re-push the parameters. might not be optimal, but that doesn't really - // matter. - ABI_AlignStack(num_params * 4, true); - unsigned int alignedSize = ABI_GetAlignedFrameSize(num_params * 4, true); - for (int i = 0; i < num_params; i++) { - // ESP is changing, so we do not need i - PUSH(32, MDisp(ESP, alignedSize)); - } - CALL(function); - ABI_RestoreStack(num_params * 4, true); - CALL((void*)load_regs); - RET(); -#endif - - thunks[function] = call_point; - return (void *)call_point; -} |
