Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LINUX/CPU/BASE] Added System-V ABI support in x64 backend & fixed mmap initialization #2228

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/xenia/base/mapped_memory_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
144 changes: 144 additions & 0 deletions src/xenia/cpu/backend/x64/x64_backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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();

Expand All @@ -479,6 +527,7 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
}

GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
#if XE_PLATFORM_WIN32
// rcx = target function
// rdx = arg0
// r8 = arg1
Expand Down Expand Up @@ -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();

Expand All @@ -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

Expand Down Expand Up @@ -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();

Expand Down