@@ -47,7 +47,6 @@
|
|||||||
<ClCompile Include="src\xenia\cpu\backend\x64\x64_emitter.cc" />
|
<ClCompile Include="src\xenia\cpu\backend\x64\x64_emitter.cc" />
|
||||||
<ClCompile Include="src\xenia\cpu\backend\x64\x64_function.cc" />
|
<ClCompile Include="src\xenia\cpu\backend\x64\x64_function.cc" />
|
||||||
<ClCompile Include="src\xenia\cpu\backend\x64\x64_sequences.cc" />
|
<ClCompile Include="src\xenia\cpu\backend\x64\x64_sequences.cc" />
|
||||||
<ClCompile Include="src\xenia\cpu\backend\x64\x64_thunk_emitter.cc" />
|
|
||||||
<ClCompile Include="src\xenia\cpu\backend\x64\x64_tracers.cc" />
|
<ClCompile Include="src\xenia\cpu\backend\x64\x64_tracers.cc" />
|
||||||
<ClCompile Include="src\xenia\cpu\compiler\compiler.cc" />
|
<ClCompile Include="src\xenia\cpu\compiler\compiler.cc" />
|
||||||
<ClCompile Include="src\xenia\cpu\compiler\compiler_pass.cc" />
|
<ClCompile Include="src\xenia\cpu\compiler\compiler_pass.cc" />
|
||||||
@@ -306,7 +305,7 @@
|
|||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_emitter.h" />
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_emitter.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_function.h" />
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_function.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_sequences.h" />
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_sequences.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_thunk_emitter.h" />
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_stack_layout.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_tracers.h" />
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_tracers.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\compiler\compiler.h" />
|
<ClInclude Include="src\xenia\cpu\compiler\compiler.h" />
|
||||||
<ClInclude Include="src\xenia\cpu\compiler\compiler_pass.h" />
|
<ClInclude Include="src\xenia\cpu\compiler\compiler_pass.h" />
|
||||||
|
|||||||
@@ -277,9 +277,6 @@
|
|||||||
<ClCompile Include="src\xenia\cpu\backend\x64\x64_sequences.cc">
|
<ClCompile Include="src\xenia\cpu\backend\x64\x64_sequences.cc">
|
||||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="src\xenia\cpu\backend\x64\x64_thunk_emitter.cc">
|
|
||||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\xenia\cpu\backend\x64\x64_tracers.cc">
|
<ClCompile Include="src\xenia\cpu\backend\x64\x64_tracers.cc">
|
||||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -921,9 +918,6 @@
|
|||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_sequences.h">
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_sequences.h">
|
||||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_thunk_emitter.h">
|
|
||||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_tracers.h">
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_tracers.h">
|
||||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -1476,6 +1470,9 @@
|
|||||||
<ClInclude Include="src\xenia\vfs\virtual_file_system.h">
|
<ClInclude Include="src\xenia\vfs\virtual_file_system.h">
|
||||||
<Filter>src\xenia\vfs</Filter>
|
<Filter>src\xenia\vfs</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\xenia\cpu\backend\x64\x64_stack_layout.h">
|
||||||
|
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="src\xenia\cpu\backend\x64\x64_sequence.inl">
|
<None Include="src\xenia\cpu\backend\x64\x64_sequence.inl">
|
||||||
|
|||||||
@@ -10,9 +10,10 @@
|
|||||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||||
|
|
||||||
#include "xenia/cpu/backend/x64/x64_assembler.h"
|
#include "xenia/cpu/backend/x64/x64_assembler.h"
|
||||||
|
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||||
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
||||||
#include "xenia/cpu/backend/x64/x64_thunk_emitter.h"
|
#include "xenia/cpu/backend/x64/x64_stack_layout.h"
|
||||||
#include "xenia/cpu/processor.h"
|
#include "xenia/cpu/processor.h"
|
||||||
#include "third_party/xbyak/xbyak/xbyak_util.h"
|
#include "third_party/xbyak/xbyak/xbyak_util.h"
|
||||||
|
|
||||||
@@ -25,6 +26,15 @@ namespace cpu {
|
|||||||
namespace backend {
|
namespace backend {
|
||||||
namespace x64 {
|
namespace x64 {
|
||||||
|
|
||||||
|
class X64ThunkEmitter : public X64Emitter {
|
||||||
|
public:
|
||||||
|
X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator);
|
||||||
|
~X64ThunkEmitter() override;
|
||||||
|
HostToGuestThunk EmitHostToGuestThunk();
|
||||||
|
GuestToHostThunk EmitGuestToHostThunk();
|
||||||
|
ResolveFunctionThunk EmitResolveFunctionThunk();
|
||||||
|
};
|
||||||
|
|
||||||
X64Backend::X64Backend(Processor* processor)
|
X64Backend::X64Backend(Processor* processor)
|
||||||
: Backend(processor), code_cache_(nullptr), emitter_data_(0) {}
|
: Backend(processor), code_cache_(nullptr), emitter_data_(0) {}
|
||||||
|
|
||||||
@@ -68,11 +78,11 @@ bool X64Backend::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate thunks used to transition between jitted code and host code.
|
// Generate thunks used to transition between jitted code and host code.
|
||||||
auto allocator = std::make_unique<XbyakAllocator>();
|
XbyakAllocator allocator;
|
||||||
auto thunk_emitter = std::make_unique<X64ThunkEmitter>(this, allocator.get());
|
X64ThunkEmitter thunk_emitter(this, &allocator);
|
||||||
host_to_guest_thunk_ = thunk_emitter->EmitHostToGuestThunk();
|
host_to_guest_thunk_ = thunk_emitter.EmitHostToGuestThunk();
|
||||||
guest_to_host_thunk_ = thunk_emitter->EmitGuestToHostThunk();
|
guest_to_host_thunk_ = thunk_emitter.EmitGuestToHostThunk();
|
||||||
resolve_function_thunk_ = thunk_emitter->EmitResolveFunctionThunk();
|
resolve_function_thunk_ = thunk_emitter.EmitResolveFunctionThunk();
|
||||||
|
|
||||||
// Set the code cache to use the ResolveFunction thunk for default
|
// Set the code cache to use the ResolveFunction thunk for default
|
||||||
// indirections.
|
// indirections.
|
||||||
@@ -98,6 +108,178 @@ std::unique_ptr<Assembler> X64Backend::CreateAssembler() {
|
|||||||
return std::make_unique<X64Assembler>(this);
|
return std::make_unique<X64Assembler>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using namespace Xbyak;
|
||||||
|
|
||||||
|
X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
|
||||||
|
: X64Emitter(backend, allocator) {}
|
||||||
|
|
||||||
|
X64ThunkEmitter::~X64ThunkEmitter() {}
|
||||||
|
|
||||||
|
HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
|
||||||
|
// rcx = target
|
||||||
|
// rdx = arg0
|
||||||
|
// r8 = arg1
|
||||||
|
|
||||||
|
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
|
||||||
|
// rsp + 0 = return address
|
||||||
|
mov(qword[rsp + 8 * 3], r8);
|
||||||
|
mov(qword[rsp + 8 * 2], rdx);
|
||||||
|
mov(qword[rsp + 8 * 1], rcx);
|
||||||
|
sub(rsp, stack_size);
|
||||||
|
|
||||||
|
mov(qword[rsp + 48], rbx);
|
||||||
|
mov(qword[rsp + 56], rcx);
|
||||||
|
mov(qword[rsp + 64], rbp);
|
||||||
|
mov(qword[rsp + 72], rsi);
|
||||||
|
mov(qword[rsp + 80], rdi);
|
||||||
|
mov(qword[rsp + 88], r12);
|
||||||
|
mov(qword[rsp + 96], r13);
|
||||||
|
mov(qword[rsp + 104], r14);
|
||||||
|
mov(qword[rsp + 112], r15);
|
||||||
|
|
||||||
|
/*movaps(ptr[rsp + 128], xmm6);
|
||||||
|
movaps(ptr[rsp + 144], xmm7);
|
||||||
|
movaps(ptr[rsp + 160], xmm8);
|
||||||
|
movaps(ptr[rsp + 176], xmm9);
|
||||||
|
movaps(ptr[rsp + 192], xmm10);
|
||||||
|
movaps(ptr[rsp + 208], xmm11);
|
||||||
|
movaps(ptr[rsp + 224], xmm12);
|
||||||
|
movaps(ptr[rsp + 240], xmm13);
|
||||||
|
movaps(ptr[rsp + 256], xmm14);
|
||||||
|
movaps(ptr[rsp + 272], xmm15);*/
|
||||||
|
|
||||||
|
mov(rax, rcx);
|
||||||
|
mov(rcx, rdx);
|
||||||
|
mov(rdx, r8);
|
||||||
|
call(rax);
|
||||||
|
|
||||||
|
/*movaps(xmm6, ptr[rsp + 128]);
|
||||||
|
movaps(xmm7, ptr[rsp + 144]);
|
||||||
|
movaps(xmm8, ptr[rsp + 160]);
|
||||||
|
movaps(xmm9, ptr[rsp + 176]);
|
||||||
|
movaps(xmm10, ptr[rsp + 192]);
|
||||||
|
movaps(xmm11, ptr[rsp + 208]);
|
||||||
|
movaps(xmm12, ptr[rsp + 224]);
|
||||||
|
movaps(xmm13, ptr[rsp + 240]);
|
||||||
|
movaps(xmm14, ptr[rsp + 256]);
|
||||||
|
movaps(xmm15, ptr[rsp + 272]);*/
|
||||||
|
|
||||||
|
mov(rbx, qword[rsp + 48]);
|
||||||
|
mov(rcx, qword[rsp + 56]);
|
||||||
|
mov(rbp, qword[rsp + 64]);
|
||||||
|
mov(rsi, qword[rsp + 72]);
|
||||||
|
mov(rdi, qword[rsp + 80]);
|
||||||
|
mov(r12, qword[rsp + 88]);
|
||||||
|
mov(r13, qword[rsp + 96]);
|
||||||
|
mov(r14, qword[rsp + 104]);
|
||||||
|
mov(r15, qword[rsp + 112]);
|
||||||
|
|
||||||
|
add(rsp, stack_size);
|
||||||
|
mov(rcx, qword[rsp + 8 * 1]);
|
||||||
|
mov(rdx, qword[rsp + 8 * 2]);
|
||||||
|
mov(r8, qword[rsp + 8 * 3]);
|
||||||
|
ret();
|
||||||
|
|
||||||
|
void* fn = Emplace(0, stack_size);
|
||||||
|
return (HostToGuestThunk)fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
|
||||||
|
// rcx = context
|
||||||
|
// rdx = target function
|
||||||
|
// r8 = arg0
|
||||||
|
// r9 = arg1
|
||||||
|
// r10 = arg2
|
||||||
|
|
||||||
|
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
|
||||||
|
// rsp + 0 = return address
|
||||||
|
mov(qword[rsp + 8 * 2], rdx);
|
||||||
|
mov(qword[rsp + 8 * 1], rcx);
|
||||||
|
sub(rsp, stack_size);
|
||||||
|
|
||||||
|
mov(qword[rsp + 48], rbx);
|
||||||
|
mov(qword[rsp + 56], rcx);
|
||||||
|
mov(qword[rsp + 64], rbp);
|
||||||
|
mov(qword[rsp + 72], rsi);
|
||||||
|
mov(qword[rsp + 80], rdi);
|
||||||
|
mov(qword[rsp + 88], r12);
|
||||||
|
mov(qword[rsp + 96], r13);
|
||||||
|
mov(qword[rsp + 104], r14);
|
||||||
|
mov(qword[rsp + 112], r15);
|
||||||
|
|
||||||
|
// TODO(benvanik): save things? XMM0-5?
|
||||||
|
|
||||||
|
mov(rax, rdx);
|
||||||
|
mov(rdx, r8);
|
||||||
|
mov(r8, r9);
|
||||||
|
mov(r9, r10);
|
||||||
|
call(rax);
|
||||||
|
|
||||||
|
mov(rbx, qword[rsp + 48]);
|
||||||
|
mov(rcx, qword[rsp + 56]);
|
||||||
|
mov(rbp, qword[rsp + 64]);
|
||||||
|
mov(rsi, qword[rsp + 72]);
|
||||||
|
mov(rdi, qword[rsp + 80]);
|
||||||
|
mov(r12, qword[rsp + 88]);
|
||||||
|
mov(r13, qword[rsp + 96]);
|
||||||
|
mov(r14, qword[rsp + 104]);
|
||||||
|
mov(r15, qword[rsp + 112]);
|
||||||
|
|
||||||
|
add(rsp, stack_size);
|
||||||
|
mov(rcx, qword[rsp + 8 * 1]);
|
||||||
|
mov(rdx, qword[rsp + 8 * 2]);
|
||||||
|
ret();
|
||||||
|
|
||||||
|
void* fn = Emplace(0, stack_size);
|
||||||
|
return (HostToGuestThunk)fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// X64Emitter handles actually resolving functions.
|
||||||
|
extern "C" uint64_t ResolveFunction(void* raw_context, uint32_t target_address);
|
||||||
|
|
||||||
|
ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
|
||||||
|
// ebx = target PPC address
|
||||||
|
// rcx = context
|
||||||
|
|
||||||
|
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
|
||||||
|
// rsp + 0 = return address
|
||||||
|
mov(qword[rsp + 8 * 2], rdx);
|
||||||
|
mov(qword[rsp + 8 * 1], rcx);
|
||||||
|
sub(rsp, stack_size);
|
||||||
|
|
||||||
|
mov(qword[rsp + 48], rbx);
|
||||||
|
mov(qword[rsp + 56], rcx);
|
||||||
|
mov(qword[rsp + 64], rbp);
|
||||||
|
mov(qword[rsp + 72], rsi);
|
||||||
|
mov(qword[rsp + 80], rdi);
|
||||||
|
mov(qword[rsp + 88], r12);
|
||||||
|
mov(qword[rsp + 96], r13);
|
||||||
|
mov(qword[rsp + 104], r14);
|
||||||
|
mov(qword[rsp + 112], r15);
|
||||||
|
|
||||||
|
mov(rdx, rbx);
|
||||||
|
mov(rax, uint64_t(&ResolveFunction));
|
||||||
|
call(rax);
|
||||||
|
|
||||||
|
mov(rbx, qword[rsp + 48]);
|
||||||
|
mov(rcx, qword[rsp + 56]);
|
||||||
|
mov(rbp, qword[rsp + 64]);
|
||||||
|
mov(rsi, qword[rsp + 72]);
|
||||||
|
mov(rdi, qword[rsp + 80]);
|
||||||
|
mov(r12, qword[rsp + 88]);
|
||||||
|
mov(r13, qword[rsp + 96]);
|
||||||
|
mov(r14, qword[rsp + 104]);
|
||||||
|
mov(r15, qword[rsp + 112]);
|
||||||
|
|
||||||
|
add(rsp, stack_size);
|
||||||
|
mov(rcx, qword[rsp + 8 * 1]);
|
||||||
|
mov(rdx, qword[rsp + 8 * 2]);
|
||||||
|
jmp(rax);
|
||||||
|
|
||||||
|
void* fn = Emplace(0, stack_size);
|
||||||
|
return (ResolveFunctionThunk)fn;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
|
|||||||
@@ -38,8 +38,12 @@ class X64Backend : public Backend {
|
|||||||
|
|
||||||
X64CodeCache* code_cache() const { return code_cache_; }
|
X64CodeCache* code_cache() const { return code_cache_; }
|
||||||
uint32_t emitter_data() const { return emitter_data_; }
|
uint32_t emitter_data() const { return emitter_data_; }
|
||||||
|
|
||||||
|
// Call a generated function, saving all stack parameters.
|
||||||
HostToGuestThunk host_to_guest_thunk() const { return host_to_guest_thunk_; }
|
HostToGuestThunk host_to_guest_thunk() const { return host_to_guest_thunk_; }
|
||||||
|
// Function that guest code can call to transition into host code.
|
||||||
GuestToHostThunk guest_to_host_thunk() const { return guest_to_host_thunk_; }
|
GuestToHostThunk guest_to_host_thunk() const { return guest_to_host_thunk_; }
|
||||||
|
// Function that thunks to the ResolveFunction in X64Emitter.
|
||||||
ResolveFunctionThunk resolve_function_thunk() const {
|
ResolveFunctionThunk resolve_function_thunk() const {
|
||||||
return resolve_function_thunk_;
|
return resolve_function_thunk_;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,10 +24,9 @@
|
|||||||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||||
#include "xenia/cpu/backend/x64/x64_function.h"
|
#include "xenia/cpu/backend/x64/x64_function.h"
|
||||||
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
#include "xenia/cpu/backend/x64/x64_sequences.h"
|
||||||
#include "xenia/cpu/backend/x64/x64_thunk_emitter.h"
|
#include "xenia/cpu/backend/x64/x64_stack_layout.h"
|
||||||
#include "xenia/cpu/cpu_flags.h"
|
#include "xenia/cpu/cpu_flags.h"
|
||||||
#include "xenia/cpu/debug_info.h"
|
#include "xenia/cpu/debug_info.h"
|
||||||
#include "xenia/cpu/hir/hir_builder.h"
|
|
||||||
#include "xenia/cpu/processor.h"
|
#include "xenia/cpu/processor.h"
|
||||||
#include "xenia/cpu/symbol_info.h"
|
#include "xenia/cpu/symbol_info.h"
|
||||||
#include "xenia/cpu/thread_state.h"
|
#include "xenia/cpu/thread_state.h"
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#include "third_party/xbyak/xbyak/xbyak_util.h"
|
#include "third_party/xbyak/xbyak/xbyak_util.h"
|
||||||
|
|
||||||
#include "xenia/base/arena.h"
|
#include "xenia/base/arena.h"
|
||||||
|
#include "xenia/cpu/hir/hir_builder.h"
|
||||||
|
#include "xenia/cpu/hir/instr.h"
|
||||||
#include "xenia/cpu/hir/value.h"
|
#include "xenia/cpu/hir/value.h"
|
||||||
#include "xenia/debug/function_trace_data.h"
|
#include "xenia/debug/function_trace_data.h"
|
||||||
#include "xenia/memory.h"
|
#include "xenia/memory.h"
|
||||||
@@ -24,10 +26,6 @@ class DebugInfo;
|
|||||||
class FunctionInfo;
|
class FunctionInfo;
|
||||||
class Processor;
|
class Processor;
|
||||||
class SymbolInfo;
|
class SymbolInfo;
|
||||||
namespace hir {
|
|
||||||
class HIRBuilder;
|
|
||||||
class Instr;
|
|
||||||
} // namespace hir
|
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
@@ -156,7 +154,6 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
|||||||
void DebugBreak();
|
void DebugBreak();
|
||||||
void Trap(uint16_t trap_type = 0);
|
void Trap(uint16_t trap_type = 0);
|
||||||
void UnimplementedInstr(const hir::Instr* i);
|
void UnimplementedInstr(const hir::Instr* i);
|
||||||
void UnimplementedExtern(const hir::Instr* i);
|
|
||||||
|
|
||||||
void Call(const hir::Instr* instr, FunctionInfo* symbol_info);
|
void Call(const hir::Instr* instr, FunctionInfo* symbol_info);
|
||||||
void CallIndirect(const hir::Instr* instr, const Xbyak::Reg64& reg);
|
void CallIndirect(const hir::Instr* instr, const Xbyak::Reg64& reg);
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef XENIA_BACKEND_X64_X64_THUNK_EMITTER_H_
|
#ifndef XENIA_BACKEND_X64_X64_STACK_LAYOUT_H_
|
||||||
#define XENIA_BACKEND_X64_X64_THUNK_EMITTER_H_
|
#define XENIA_BACKEND_X64_X64_STACK_LAYOUT_H_
|
||||||
|
|
||||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||||
@@ -123,24 +123,9 @@ class StackLayout {
|
|||||||
const static size_t GUEST_CALL_RET_ADDR = 96;
|
const static size_t GUEST_CALL_RET_ADDR = 96;
|
||||||
};
|
};
|
||||||
|
|
||||||
class X64ThunkEmitter : public X64Emitter {
|
|
||||||
public:
|
|
||||||
X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator);
|
|
||||||
virtual ~X64ThunkEmitter();
|
|
||||||
|
|
||||||
// Call a generated function, saving all stack parameters.
|
|
||||||
HostToGuestThunk EmitHostToGuestThunk();
|
|
||||||
|
|
||||||
// Function that guest code can call to transition into host code.
|
|
||||||
GuestToHostThunk EmitGuestToHostThunk();
|
|
||||||
|
|
||||||
// Function that thunks to the ResolveFunction in X64Emitter.
|
|
||||||
ResolveFunctionThunk EmitResolveFunctionThunk();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace x64
|
} // namespace x64
|
||||||
} // namespace backend
|
} // namespace backend
|
||||||
} // namespace cpu
|
} // namespace cpu
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
#endif // XENIA_BACKEND_X64_X64_THUNK_EMITTER_H_
|
#endif // XENIA_BACKEND_X64_X64_STACK_LAYOUT_H_
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
/**
|
|
||||||
******************************************************************************
|
|
||||||
* Xenia : Xbox 360 Emulator Research Project *
|
|
||||||
******************************************************************************
|
|
||||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
|
||||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
||||||
******************************************************************************
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "xenia/cpu/backend/x64/x64_thunk_emitter.h"
|
|
||||||
|
|
||||||
#include "third_party/xbyak/xbyak/xbyak.h"
|
|
||||||
|
|
||||||
namespace xe {
|
|
||||||
namespace cpu {
|
|
||||||
namespace backend {
|
|
||||||
namespace x64 {
|
|
||||||
|
|
||||||
using namespace Xbyak;
|
|
||||||
|
|
||||||
X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
|
|
||||||
: X64Emitter(backend, allocator) {}
|
|
||||||
|
|
||||||
X64ThunkEmitter::~X64ThunkEmitter() {}
|
|
||||||
|
|
||||||
HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
|
|
||||||
// rcx = target
|
|
||||||
// rdx = arg0
|
|
||||||
// r8 = arg1
|
|
||||||
|
|
||||||
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
|
|
||||||
// rsp + 0 = return address
|
|
||||||
mov(qword[rsp + 8 * 3], r8);
|
|
||||||
mov(qword[rsp + 8 * 2], rdx);
|
|
||||||
mov(qword[rsp + 8 * 1], rcx);
|
|
||||||
sub(rsp, stack_size);
|
|
||||||
|
|
||||||
mov(qword[rsp + 48], rbx);
|
|
||||||
mov(qword[rsp + 56], rcx);
|
|
||||||
mov(qword[rsp + 64], rbp);
|
|
||||||
mov(qword[rsp + 72], rsi);
|
|
||||||
mov(qword[rsp + 80], rdi);
|
|
||||||
mov(qword[rsp + 88], r12);
|
|
||||||
mov(qword[rsp + 96], r13);
|
|
||||||
mov(qword[rsp + 104], r14);
|
|
||||||
mov(qword[rsp + 112], r15);
|
|
||||||
|
|
||||||
/*movaps(ptr[rsp + 128], xmm6);
|
|
||||||
movaps(ptr[rsp + 144], xmm7);
|
|
||||||
movaps(ptr[rsp + 160], xmm8);
|
|
||||||
movaps(ptr[rsp + 176], xmm9);
|
|
||||||
movaps(ptr[rsp + 192], xmm10);
|
|
||||||
movaps(ptr[rsp + 208], xmm11);
|
|
||||||
movaps(ptr[rsp + 224], xmm12);
|
|
||||||
movaps(ptr[rsp + 240], xmm13);
|
|
||||||
movaps(ptr[rsp + 256], xmm14);
|
|
||||||
movaps(ptr[rsp + 272], xmm15);*/
|
|
||||||
|
|
||||||
mov(rax, rcx);
|
|
||||||
mov(rcx, rdx);
|
|
||||||
mov(rdx, r8);
|
|
||||||
call(rax);
|
|
||||||
|
|
||||||
/*movaps(xmm6, ptr[rsp + 128]);
|
|
||||||
movaps(xmm7, ptr[rsp + 144]);
|
|
||||||
movaps(xmm8, ptr[rsp + 160]);
|
|
||||||
movaps(xmm9, ptr[rsp + 176]);
|
|
||||||
movaps(xmm10, ptr[rsp + 192]);
|
|
||||||
movaps(xmm11, ptr[rsp + 208]);
|
|
||||||
movaps(xmm12, ptr[rsp + 224]);
|
|
||||||
movaps(xmm13, ptr[rsp + 240]);
|
|
||||||
movaps(xmm14, ptr[rsp + 256]);
|
|
||||||
movaps(xmm15, ptr[rsp + 272]);*/
|
|
||||||
|
|
||||||
mov(rbx, qword[rsp + 48]);
|
|
||||||
mov(rcx, qword[rsp + 56]);
|
|
||||||
mov(rbp, qword[rsp + 64]);
|
|
||||||
mov(rsi, qword[rsp + 72]);
|
|
||||||
mov(rdi, qword[rsp + 80]);
|
|
||||||
mov(r12, qword[rsp + 88]);
|
|
||||||
mov(r13, qword[rsp + 96]);
|
|
||||||
mov(r14, qword[rsp + 104]);
|
|
||||||
mov(r15, qword[rsp + 112]);
|
|
||||||
|
|
||||||
add(rsp, stack_size);
|
|
||||||
mov(rcx, qword[rsp + 8 * 1]);
|
|
||||||
mov(rdx, qword[rsp + 8 * 2]);
|
|
||||||
mov(r8, qword[rsp + 8 * 3]);
|
|
||||||
ret();
|
|
||||||
|
|
||||||
void* fn = Emplace(0, stack_size);
|
|
||||||
return (HostToGuestThunk)fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
|
|
||||||
// rcx = context
|
|
||||||
// rdx = target function
|
|
||||||
// r8 = arg0
|
|
||||||
// r9 = arg1
|
|
||||||
// r10 = arg2
|
|
||||||
|
|
||||||
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
|
|
||||||
// rsp + 0 = return address
|
|
||||||
mov(qword[rsp + 8 * 2], rdx);
|
|
||||||
mov(qword[rsp + 8 * 1], rcx);
|
|
||||||
sub(rsp, stack_size);
|
|
||||||
|
|
||||||
mov(qword[rsp + 48], rbx);
|
|
||||||
mov(qword[rsp + 56], rcx);
|
|
||||||
mov(qword[rsp + 64], rbp);
|
|
||||||
mov(qword[rsp + 72], rsi);
|
|
||||||
mov(qword[rsp + 80], rdi);
|
|
||||||
mov(qword[rsp + 88], r12);
|
|
||||||
mov(qword[rsp + 96], r13);
|
|
||||||
mov(qword[rsp + 104], r14);
|
|
||||||
mov(qword[rsp + 112], r15);
|
|
||||||
|
|
||||||
// TODO(benvanik): save things? XMM0-5?
|
|
||||||
|
|
||||||
mov(rax, rdx);
|
|
||||||
mov(rdx, r8);
|
|
||||||
mov(r8, r9);
|
|
||||||
mov(r9, r10);
|
|
||||||
call(rax);
|
|
||||||
|
|
||||||
mov(rbx, qword[rsp + 48]);
|
|
||||||
mov(rcx, qword[rsp + 56]);
|
|
||||||
mov(rbp, qword[rsp + 64]);
|
|
||||||
mov(rsi, qword[rsp + 72]);
|
|
||||||
mov(rdi, qword[rsp + 80]);
|
|
||||||
mov(r12, qword[rsp + 88]);
|
|
||||||
mov(r13, qword[rsp + 96]);
|
|
||||||
mov(r14, qword[rsp + 104]);
|
|
||||||
mov(r15, qword[rsp + 112]);
|
|
||||||
|
|
||||||
add(rsp, stack_size);
|
|
||||||
mov(rcx, qword[rsp + 8 * 1]);
|
|
||||||
mov(rdx, qword[rsp + 8 * 2]);
|
|
||||||
ret();
|
|
||||||
|
|
||||||
void* fn = Emplace(0, stack_size);
|
|
||||||
return (HostToGuestThunk)fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
// X64Emitter handles actually resolving functions.
|
|
||||||
extern "C" uint64_t ResolveFunction(void* raw_context, uint32_t target_address);
|
|
||||||
|
|
||||||
ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
|
|
||||||
// ebx = target PPC address
|
|
||||||
// rcx = context
|
|
||||||
|
|
||||||
const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
|
|
||||||
// rsp + 0 = return address
|
|
||||||
mov(qword[rsp + 8 * 2], rdx);
|
|
||||||
mov(qword[rsp + 8 * 1], rcx);
|
|
||||||
sub(rsp, stack_size);
|
|
||||||
|
|
||||||
mov(qword[rsp + 48], rbx);
|
|
||||||
mov(qword[rsp + 56], rcx);
|
|
||||||
mov(qword[rsp + 64], rbp);
|
|
||||||
mov(qword[rsp + 72], rsi);
|
|
||||||
mov(qword[rsp + 80], rdi);
|
|
||||||
mov(qword[rsp + 88], r12);
|
|
||||||
mov(qword[rsp + 96], r13);
|
|
||||||
mov(qword[rsp + 104], r14);
|
|
||||||
mov(qword[rsp + 112], r15);
|
|
||||||
|
|
||||||
mov(rdx, rbx);
|
|
||||||
mov(rax, uint64_t(&ResolveFunction));
|
|
||||||
call(rax);
|
|
||||||
|
|
||||||
mov(rbx, qword[rsp + 48]);
|
|
||||||
mov(rcx, qword[rsp + 56]);
|
|
||||||
mov(rbp, qword[rsp + 64]);
|
|
||||||
mov(rsi, qword[rsp + 72]);
|
|
||||||
mov(rdi, qword[rsp + 80]);
|
|
||||||
mov(r12, qword[rsp + 88]);
|
|
||||||
mov(r13, qword[rsp + 96]);
|
|
||||||
mov(r14, qword[rsp + 104]);
|
|
||||||
mov(r15, qword[rsp + 112]);
|
|
||||||
|
|
||||||
add(rsp, stack_size);
|
|
||||||
mov(rcx, qword[rsp + 8 * 1]);
|
|
||||||
mov(rdx, qword[rsp + 8 * 2]);
|
|
||||||
jmp(rax);
|
|
||||||
|
|
||||||
void* fn = Emplace(0, stack_size);
|
|
||||||
return (ResolveFunctionThunk)fn;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace x64
|
|
||||||
} // namespace backend
|
|
||||||
} // namespace cpu
|
|
||||||
} // namespace xe
|
|
||||||
Reference in New Issue
Block a user