Skip to content

Commit 999ec74

Browse files
uytvbnbwrsandman
authored andcommitted
[Linux] Implement thunk generation
1 parent 03c0c8d commit 999ec74

File tree

2 files changed

+60
-18
lines changed

2 files changed

+60
-18
lines changed

src/xenia/cpu/backend/x64/x64_backend.cc

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -403,9 +403,9 @@ X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
403403
X64ThunkEmitter::~X64ThunkEmitter() {}
404404

405405
HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
406-
// rcx = target
407-
// rdx = arg0 (context)
408-
// r8 = arg1 (guest return address)
406+
// rcx (win), rdi (linux) = target
407+
// rdx (win), rsi (linux) = arg0 (context)
408+
// r8 (win), rdx (linux) = arg1 (guest return address)
409409

410410
struct _code_offsets {
411411
size_t prolog;
@@ -420,9 +420,15 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
420420
code_offsets.prolog = getSize();
421421

422422
// rsp + 0 = return address
423+
#if XE_PLATFORM_LINUX
424+
mov(qword[rsp + 8 * 3], rdx);
425+
mov(qword[rsp + 8 * 2], rsi);
426+
mov(qword[rsp + 8 * 1], rdi);
427+
#else
423428
mov(qword[rsp + 8 * 3], r8);
424429
mov(qword[rsp + 8 * 2], rdx);
425430
mov(qword[rsp + 8 * 1], rcx);
431+
#endif
426432
sub(rsp, stack_size);
427433

428434
code_offsets.prolog_stack_alloc = getSize();
@@ -431,19 +437,31 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
431437
// Save nonvolatile registers.
432438
EmitSaveNonvolatileRegs();
433439

440+
#ifdef XE_PLATFORM_LINUX
441+
mov(rax, rdi);
442+
// context already in rsi
443+
mov(rcx, rdx); // return address
444+
#else
434445
mov(rax, rcx);
435446
mov(rsi, rdx); // context
436447
mov(rcx, r8); // return address
448+
#endif
437449
call(rax);
438450

439451
EmitLoadNonvolatileRegs();
440452

441453
code_offsets.epilog = getSize();
442454

443455
add(rsp, stack_size);
456+
#if XE_PLATFORM_LINUX
457+
mov(rdi, qword[rsp + 8 * 1]);
458+
mov(rsi, qword[rsp + 8 * 2]);
459+
mov(rdx, qword[rsp + 8 * 3]);
460+
#else
444461
mov(rcx, qword[rsp + 8 * 1]);
445462
mov(rdx, qword[rsp + 8 * 2]);
446463
mov(r8, qword[rsp + 8 * 3]);
464+
#endif
447465
ret();
448466

449467
code_offsets.tail = getSize();
@@ -464,10 +482,12 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
464482
}
465483

466484
GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
467-
// rcx = target function
468-
// rdx = arg0
469-
// r8 = arg1
470-
// r9 = arg2
485+
// rcx (windows), rdi (linux) = target function
486+
// rdx (windows), rsi (linux) = arg0
487+
// r8 (windows), rdx (linux) = arg1
488+
// r9 (windows), rcx (linux) = arg2
489+
// --- (windows), r8 (linux) = arg3
490+
// --- (windows), r9 (linux) = arg4
471491

472492
struct _code_offsets {
473493
size_t prolog;
@@ -490,8 +510,13 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
490510
// Save off volatile registers.
491511
EmitSaveVolatileRegs();
492512

493-
mov(rax, rcx); // function
513+
mov(rax, rcx); // function
514+
#if XE_PLATFORM_LINUX
515+
mov(rdi, GetContextReg()); // context
516+
mov(rsi, rbx);
517+
#else
494518
mov(rcx, GetContextReg()); // context
519+
#endif
495520
call(rax);
496521

497522
EmitLoadVolatileRegs();
@@ -546,8 +571,13 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
546571
// Save volatile registers
547572
EmitSaveVolatileRegs();
548573

549-
mov(rcx, rsi); // context
574+
#if XE_PLATFORM_LINUX
575+
mov(rdi, rsi); // context
576+
mov(rsi, rbx);
577+
#else
578+
mov(rcx, rsi); // context
550579
mov(rdx, rbx);
580+
#endif
551581
mov(rax, uint64_t(&ResolveFunction));
552582
call(rax);
553583

src/xenia/cpu/backend/x64/x64_emitter.cc

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,9 @@ void X64Emitter::CallExtern(const hir::Instr* instr, const Function* function) {
499499
if (builtin_function->handler()) {
500500
undefined = false;
501501
// rcx = target function
502-
// rdx = arg0
503-
// r8 = arg1
504-
// r9 = arg2
502+
// rdx (windows), r8 (linux) = arg0
503+
// r8 (windows), rdx (linux) = arg1
504+
// r9 (windows), rcx (linux) = arg2
505505
auto thunk = backend()->guest_to_host_thunk();
506506
mov(rax, reinterpret_cast<uint64_t>(thunk));
507507
mov(rcx, reinterpret_cast<uint64_t>(builtin_function->handler()));
@@ -515,9 +515,9 @@ void X64Emitter::CallExtern(const hir::Instr* instr, const Function* function) {
515515
if (extern_function->extern_handler()) {
516516
undefined = false;
517517
// rcx = target function
518-
// rdx = arg0
519-
// r8 = arg1
520-
// r9 = arg2
518+
// rdx (windows), r8 (linux) = arg0
519+
// r8 (windows), rdx (linux) = arg1
520+
// r9 (windows), rcx (linux) = arg2
521521
auto thunk = backend()->guest_to_host_thunk();
522522
mov(rax, reinterpret_cast<uint64_t>(thunk));
523523
mov(rcx, reinterpret_cast<uint64_t>(extern_function->extern_handler()));
@@ -550,9 +550,9 @@ void X64Emitter::CallNative(uint64_t (*fn)(void* raw_context, uint64_t arg0),
550550

551551
void X64Emitter::CallNativeSafe(void* fn) {
552552
// rcx = target function
553-
// rdx = arg0
554-
// r8 = arg1
555-
// r9 = arg2
553+
// rdx (windows), r8 (linux) = arg0
554+
// r8 (windows), rdx (linux) = arg1
555+
// r9 (windows), rcx (linux) = arg2
556556
auto thunk = backend()->guest_to_host_thunk();
557557
mov(rax, reinterpret_cast<uint64_t>(thunk));
558558
mov(rcx, reinterpret_cast<uint64_t>(fn));
@@ -566,6 +566,17 @@ void X64Emitter::SetReturnAddress(uint64_t value) {
566566
}
567567

568568
Xbyak::Reg64 X64Emitter::GetNativeParam(uint32_t param) {
569+
#if XE_PLATFORM_LINUX
570+
if (param == 0)
571+
return rbx;
572+
else if (param == 1)
573+
return rdx;
574+
else if (param == 2)
575+
return rcx;
576+
577+
assert_always();
578+
return rcx;
579+
#else
569580
if (param == 0)
570581
return rdx;
571582
else if (param == 1)
@@ -575,6 +586,7 @@ Xbyak::Reg64 X64Emitter::GetNativeParam(uint32_t param) {
575586

576587
assert_always();
577588
return r9;
589+
#endif
578590
}
579591

580592
// Important: If you change these, you must update the thunks in x64_backend.cc!

0 commit comments

Comments
 (0)