parent
5e950cb066
commit
3745746fcc
|
@ -47,7 +47,6 @@
|
|||
<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_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\compiler\compiler.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_function.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\compiler\compiler.h" />
|
||||
<ClInclude Include="src\xenia\cpu\compiler\compiler_pass.h" />
|
||||
|
|
|
@ -277,9 +277,6 @@
|
|||
<ClCompile Include="src\xenia\cpu\backend\x64\x64_sequences.cc">
|
||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||
</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">
|
||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||
</ClCompile>
|
||||
|
@ -921,9 +918,6 @@
|
|||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_sequences.h">
|
||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||
</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">
|
||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1476,6 +1470,9 @@
|
|||
<ClInclude Include="src\xenia\vfs\virtual_file_system.h">
|
||||
<Filter>src\xenia\vfs</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\xenia\cpu\backend\x64\x64_stack_layout.h">
|
||||
<Filter>src\xenia\cpu\backend\x64</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<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_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_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 "third_party/xbyak/xbyak/xbyak_util.h"
|
||||
|
||||
|
@ -25,6 +26,15 @@ namespace cpu {
|
|||
namespace backend {
|
||||
namespace x64 {
|
||||
|
||||
class X64ThunkEmitter : public X64Emitter {
|
||||
public:
|
||||
X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator);
|
||||
~X64ThunkEmitter() override;
|
||||
HostToGuestThunk EmitHostToGuestThunk();
|
||||
GuestToHostThunk EmitGuestToHostThunk();
|
||||
ResolveFunctionThunk EmitResolveFunctionThunk();
|
||||
};
|
||||
|
||||
X64Backend::X64Backend(Processor* processor)
|
||||
: 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.
|
||||
auto allocator = std::make_unique<XbyakAllocator>();
|
||||
auto thunk_emitter = std::make_unique<X64ThunkEmitter>(this, allocator.get());
|
||||
host_to_guest_thunk_ = thunk_emitter->EmitHostToGuestThunk();
|
||||
guest_to_host_thunk_ = thunk_emitter->EmitGuestToHostThunk();
|
||||
resolve_function_thunk_ = thunk_emitter->EmitResolveFunctionThunk();
|
||||
XbyakAllocator allocator;
|
||||
X64ThunkEmitter thunk_emitter(this, &allocator);
|
||||
host_to_guest_thunk_ = thunk_emitter.EmitHostToGuestThunk();
|
||||
guest_to_host_thunk_ = thunk_emitter.EmitGuestToHostThunk();
|
||||
resolve_function_thunk_ = thunk_emitter.EmitResolveFunctionThunk();
|
||||
|
||||
// Set the code cache to use the ResolveFunction thunk for default
|
||||
// indirections.
|
||||
|
@ -98,6 +108,178 @@ std::unique_ptr<Assembler> X64Backend::CreateAssembler() {
|
|||
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 backend
|
||||
} // namespace cpu
|
||||
|
|
|
@ -38,8 +38,12 @@ class X64Backend : public Backend {
|
|||
|
||||
X64CodeCache* code_cache() const { return code_cache_; }
|
||||
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_; }
|
||||
// Function that guest code can call to transition into host code.
|
||||
GuestToHostThunk guest_to_host_thunk() const { return guest_to_host_thunk_; }
|
||||
// Function that thunks to the ResolveFunction in X64Emitter.
|
||||
ResolveFunctionThunk resolve_function_thunk() const {
|
||||
return resolve_function_thunk_;
|
||||
}
|
||||
|
|
|
@ -24,10 +24,9 @@
|
|||
#include "xenia/cpu/backend/x64/x64_code_cache.h"
|
||||
#include "xenia/cpu/backend/x64/x64_function.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/debug_info.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/cpu/symbol_info.h"
|
||||
#include "xenia/cpu/thread_state.h"
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include "third_party/xbyak/xbyak/xbyak_util.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/debug/function_trace_data.h"
|
||||
#include "xenia/memory.h"
|
||||
|
@ -24,10 +26,6 @@ class DebugInfo;
|
|||
class FunctionInfo;
|
||||
class Processor;
|
||||
class SymbolInfo;
|
||||
namespace hir {
|
||||
class HIRBuilder;
|
||||
class Instr;
|
||||
} // namespace hir
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
|
@ -156,7 +154,6 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
|||
void DebugBreak();
|
||||
void Trap(uint16_t trap_type = 0);
|
||||
void UnimplementedInstr(const hir::Instr* i);
|
||||
void UnimplementedExtern(const hir::Instr* i);
|
||||
|
||||
void Call(const hir::Instr* instr, FunctionInfo* symbol_info);
|
||||
void CallIndirect(const hir::Instr* instr, const Xbyak::Reg64& reg);
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_BACKEND_X64_X64_THUNK_EMITTER_H_
|
||||
#define XENIA_BACKEND_X64_X64_THUNK_EMITTER_H_
|
||||
#ifndef XENIA_BACKEND_X64_X64_STACK_LAYOUT_H_
|
||||
#define XENIA_BACKEND_X64_X64_STACK_LAYOUT_H_
|
||||
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/backend/x64/x64_emitter.h"
|
||||
|
@ -123,24 +123,9 @@ class StackLayout {
|
|||
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 backend
|
||||
} // namespace cpu
|
||||
} // 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
|
Loading…
Reference in New Issue