File xenia_PR2228.patch of Package xenia
From cec5fcfd06221bb83883e4c60c54eb1170d3a82b Mon Sep 17 00:00:00 2001
From: guccigang420 <>
Date: Sat, 9 Sep 2023 14:16:43 +0200
Subject: [PATCH] Added System-V ABI support in x64 backend & fixed mmap usage
---
src/xenia/base/mapped_memory_posix.cc | 3 +
src/xenia/base/memory_posix.cc | 7 +-
src/xenia/cpu/backend/x64/x64_backend.cc | 144 +++++++++++++++++++++++
3 files changed, 152 insertions(+), 2 deletions(-)
diff --git a/src/xenia/base/mapped_memory_posix.cc b/src/xenia/base/mapped_memory_posix.cc
index 330ced53fa..924466d3c0 100644
--- a/src/xenia/base/mapped_memory_posix.cc
+++ b/src/xenia/base/mapped_memory_posix.cc
@@ -56,6 +56,9 @@ class PosixMappedMemory : public MappedMemory {
map_length = size_t(file_stat.st_size);
}
+ // Ensure that the file is large enough.
+ ftruncate(file_descriptor, map_length);
+
void* data =
mmap(0, map_length, protection, MAP_SHARED, file_descriptor, offset);
if (!data) {
diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc
index 5355d14700..a567a4baaf 100644
--- a/src/xenia/cpu/backend/x64/x64_backend.cc
+++ b/src/xenia/cpu/backend/x64/x64_backend.cc
@@ -418,6 +418,7 @@ X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
X64ThunkEmitter::~X64ThunkEmitter() {}
HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
+#if XE_PLATFORM_WIN32
// rcx = target
// rdx = arg0 (context)
// r8 = arg1 (guest return address)
@@ -460,6 +461,53 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
mov(rdx, qword[rsp + 8 * 2]);
mov(r8, qword[rsp + 8 * 3]);
ret();
+#elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC
+ // System-V ABI args:
+ // rdi = target
+ // rsi = arg0 (context)
+ // rdx = arg1 (guest return address)
+
+ struct _code_offsets {
+ size_t prolog;
+ size_t prolog_stack_alloc;
+ size_t body;
+ size_t epilog;
+ size_t tail;
+ } code_offsets = {};
+
+ const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
+
+ code_offsets.prolog = getSize();
+
+ // rsp + 0 = return address
+ mov(qword[rsp + 8 * 3], rdx);
+ mov(qword[rsp + 8 * 2], rsi);
+ mov(qword[rsp + 8 * 1], rdi);
+ sub(rsp, stack_size);
+
+ code_offsets.prolog_stack_alloc = getSize();
+ code_offsets.body = getSize();
+
+ // Save nonvolatile registers.
+ EmitSaveNonvolatileRegs();
+
+ mov(rax, rdi);
+ // mov(rsi, rsi); // context
+ mov(rcx, rdx); // return address
+ call(rax);
+
+ EmitLoadNonvolatileRegs();
+
+ code_offsets.epilog = getSize();
+
+ add(rsp, stack_size);
+ mov(rdi, qword[rsp + 8 * 1]);
+ mov(rsi, qword[rsp + 8 * 2]);
+ mov(rdx, qword[rsp + 8 * 3]);
+ ret();
+#else
+ assert_always("Unknown platform ABI in host to guest thunk!");
+#endif
code_offsets.tail = getSize();
@@ -479,6 +527,7 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
}
GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
+#if XE_PLATFORM_WIN32
// rcx = target function
// rdx = arg0
// r8 = arg1
@@ -515,6 +564,57 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
add(rsp, stack_size);
ret();
+#elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC
+ // This function is being called using the Microsoft ABI from CallNative
+ // rcx = target function
+ // rdx = arg0
+ // r8 = arg1
+ // r9 = arg2
+
+ // Must be translated to System-V ABI:
+ // rdi = target function
+ // rsi = arg0
+ // rdx = arg1
+ // rcx = arg2
+ // r8, r9 - unused argument registers
+
+ struct _code_offsets {
+ size_t prolog;
+ size_t prolog_stack_alloc;
+ size_t body;
+ size_t epilog;
+ size_t tail;
+ } code_offsets = {};
+
+ const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
+
+ code_offsets.prolog = getSize();
+
+ // rsp + 0 = return address
+ sub(rsp, stack_size);
+
+ code_offsets.prolog_stack_alloc = getSize();
+ code_offsets.body = getSize();
+
+ // Save off volatile registers.
+ EmitSaveVolatileRegs();
+
+ mov(rax, rcx); // function
+ mov(rdi, GetContextReg()); // context
+ mov(rsi, rdx); // arg0
+ mov(rdx, r8); // arg1
+ mov(rcx, r9); // arg2
+ call(rax);
+
+ EmitLoadVolatileRegs();
+
+ code_offsets.epilog = getSize();
+
+ add(rsp, stack_size);
+ ret();
+#else
+ assert_always("Unknown platform ABI in guest to host thunk!")
+#endif
code_offsets.tail = getSize();
@@ -537,6 +637,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
uint64_t ResolveFunction(void* raw_context, uint64_t target_address);
ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
+#if XE_PLATFORM_WIN32
// ebx = target PPC address
// rcx = context
@@ -572,6 +673,49 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
add(rsp, stack_size);
jmp(rax);
+#elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC
+ // Function is called with the following params:
+ // ebx = target PPC address
+ // rsi = context
+
+ // System-V ABI args:
+ // rdi = context
+ // rsi = target PPC address
+
+ struct _code_offsets {
+ size_t prolog;
+ size_t prolog_stack_alloc;
+ size_t body;
+ size_t epilog;
+ size_t tail;
+ } code_offsets = {};
+
+ const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
+
+ code_offsets.prolog = getSize();
+
+ // rsp + 0 = return address
+ sub(rsp, stack_size);
+
+ code_offsets.prolog_stack_alloc = getSize();
+ code_offsets.body = getSize();
+
+ // Save volatile registers
+ EmitSaveVolatileRegs();
+ mov(rdi, rsi); // context
+ mov(rsi, rbx); // target PPC address
+ mov(rax, reinterpret_cast<uint64_t>(&ResolveFunction));
+ call(rax);
+
+ EmitLoadVolatileRegs();
+
+ code_offsets.epilog = getSize();
+
+ add(rsp, stack_size);
+ jmp(rax);
+#else
+ assert_always("Unknown platform ABI in resolve function!");
+#endif
code_offsets.tail = getSize();