diff --git a/libxenia.vcxproj b/libxenia.vcxproj
index ddb29f09f..53538d182 100644
--- a/libxenia.vcxproj
+++ b/libxenia.vcxproj
@@ -47,7 +47,6 @@
-
@@ -306,7 +305,7 @@
-
+
diff --git a/libxenia.vcxproj.filters b/libxenia.vcxproj.filters
index cd19ffd7e..8a342f6c9 100644
--- a/libxenia.vcxproj.filters
+++ b/libxenia.vcxproj.filters
@@ -277,9 +277,6 @@
src\xenia\cpu\backend\x64
-
- src\xenia\cpu\backend\x64
-
src\xenia\cpu\backend\x64
@@ -921,9 +918,6 @@
src\xenia\cpu\backend\x64
-
- src\xenia\cpu\backend\x64
-
src\xenia\cpu\backend\x64
@@ -1476,6 +1470,9 @@
src\xenia\vfs
+
+ src\xenia\cpu\backend\x64
+
diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc
index f892453b5..50a112c81 100644
--- a/src/xenia/cpu/backend/x64/x64_backend.cc
+++ b/src/xenia/cpu/backend/x64/x64_backend.cc
@@ -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();
- auto thunk_emitter = std::make_unique(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 X64Backend::CreateAssembler() {
return std::make_unique(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
diff --git a/src/xenia/cpu/backend/x64/x64_backend.h b/src/xenia/cpu/backend/x64/x64_backend.h
index 0bbd5c01b..dc390d103 100644
--- a/src/xenia/cpu/backend/x64/x64_backend.h
+++ b/src/xenia/cpu/backend/x64/x64_backend.h
@@ -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_;
}
diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc
index a5f0061d5..7a1cbd3de 100644
--- a/src/xenia/cpu/backend/x64/x64_emitter.cc
+++ b/src/xenia/cpu/backend/x64/x64_emitter.cc
@@ -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"
diff --git a/src/xenia/cpu/backend/x64/x64_emitter.h b/src/xenia/cpu/backend/x64/x64_emitter.h
index c5e895472..c9d1cc4f1 100644
--- a/src/xenia/cpu/backend/x64/x64_emitter.h
+++ b/src/xenia/cpu/backend/x64/x64_emitter.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);
diff --git a/src/xenia/cpu/backend/x64/x64_thunk_emitter.h b/src/xenia/cpu/backend/x64/x64_stack_layout.h
similarity index 82%
rename from src/xenia/cpu/backend/x64/x64_thunk_emitter.h
rename to src/xenia/cpu/backend/x64/x64_stack_layout.h
index 792fca66f..75b6fa470 100644
--- a/src/xenia/cpu/backend/x64/x64_thunk_emitter.h
+++ b/src/xenia/cpu/backend/x64/x64_stack_layout.h
@@ -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_
diff --git a/src/xenia/cpu/backend/x64/x64_thunk_emitter.cc b/src/xenia/cpu/backend/x64/x64_thunk_emitter.cc
deleted file mode 100644
index 6b2ce971e..000000000
--- a/src/xenia/cpu/backend/x64/x64_thunk_emitter.cc
+++ /dev/null
@@ -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