summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Src/Thunk.cpp
diff options
context:
space:
mode:
authorhrydgard <hrydgard@gmail.com>2008-08-12 20:05:45 +0000
committerhrydgard <hrydgard@gmail.com>2008-08-12 20:05:45 +0000
commit575bdd9166330ee2cd77e72abcacf6dce2ed863b (patch)
tree2e85bded381bf1bc3452cf72fbfcc3004dd72c10 /Source/Core/Common/Src/Thunk.cpp
parent29102ecbc6c7d012da281350d32542e15d8e4c00 (diff)
Lots of various changes. CPU detect fix. Maybe a minor speed increase. CPU bugs remain.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@180 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/Common/Src/Thunk.cpp')
-rw-r--r--Source/Core/Common/Src/Thunk.cpp147
1 files changed, 147 insertions, 0 deletions
diff --git a/Source/Core/Common/Src/Thunk.cpp b/Source/Core/Common/Src/Thunk.cpp
new file mode 100644
index 0000000000..ed7d93bc99
--- /dev/null
+++ b/Source/Core/Common/Src/Thunk.cpp
@@ -0,0 +1,147 @@
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include <map>
+
+#include "Common.h"
+#include "Thunk.h"
+#include "x64Emitter.h"
+#include "MemoryUtil.h"
+#include "ABI.h"
+
+using namespace Gen;
+
+#define THUNK_ARENA_SIZE 1024*1024*1
+
+namespace {
+static std::map<void *, const u8 *> thunks;
+u8 GC_ALIGNED32(saved_fp_state[16 * 4 * 4]);
+u8 GC_ALIGNED32(saved_gpr_state[16 * 8]);
+}
+
+static u8 *thunk_memory;
+static u8 *thunk_code;
+static const u8 *save_regs;
+static const u8 *load_regs;
+u32 saved_return;
+
+void Thunk_Init()
+{
+ thunk_memory = (u8 *)AllocateExecutableMemory(THUNK_ARENA_SIZE);
+ thunk_code = thunk_memory;
+
+ GenContext ctx(&thunk_code);
+ save_regs = GetCodePtr();
+ for (int i = 2; i < ABI_GetNumXMMRegs(); i++)
+ MOVAPS(M(saved_fp_state + i * 16), (X64Reg)(XMM0 + i));
+#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
+#else
+ MOV(32, M(saved_gpr_state + 0 ), R(RCX));
+ MOV(32, M(saved_gpr_state + 4 ), R(RDX));
+#endif
+ RET();
+ load_regs = GetCodePtr();
+ 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
+#else
+ MOV(32, R(RCX), M(saved_gpr_state + 0 ));
+ MOV(32, R(RDX), M(saved_gpr_state + 4 ));
+#endif
+ RET();
+}
+
+void Thunk_Reset()
+{
+ thunks.clear();
+ thunk_code = thunk_memory;
+}
+
+void Thunk_Shutdown()
+{
+ Thunk_Reset();
+ FreeMemoryPages(thunk_memory, THUNK_ARENA_SIZE);
+ thunk_memory = 0;
+ thunk_code = 0;
+}
+
+void *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 (!thunk_memory)
+ PanicAlert("Trying to protect functions before the emu is started. Bad bad bad.");
+
+ GenContext gen(&thunk_code);
+ const u8 *call_point = GetCodePtr();
+ // Make sure to align stack.
+#ifdef _M_X64
+#ifdef _WIN32
+ SUB(64, R(ESP), Imm8(0x28));
+#else
+ SUB(64, R(ESP), Imm8(0x8));
+#endif
+ CALL((void*)save_regs);
+ CALL((void*)function);
+ CALL((void*)load_regs);
+#ifdef _WIN32
+ ADD(64, R(ESP), Imm8(0x28));
+#else
+ ADD(64, R(ESP), Imm8(0x8));
+#endif
+ RET();
+#else
+ //INT3();
+ CALL((void*)save_regs);
+ // Re-push parameters from previous stack frame
+ for (int i = 0; i < num_params; i++) {
+ // ESP is changing, so we do not need i
+ PUSH(32, MDisp(ESP, (num_params) * 4));
+ }
+ CALL(function);
+ if (num_params)
+ ADD(32, R(ESP), Imm8(num_params * 4));
+ CALL((void*)load_regs);
+ RET();
+#endif
+
+ thunks[function] = call_point;
+ return (void *)call_point;
+} \ No newline at end of file