99
1010#include " xenia/cpu/backend/x64/x64_backend.h"
1111
12- #include < stddef.h >
12+ #include < cstddef >
1313#include < algorithm>
1414#include " third_party/capstone/include/capstone/capstone.h"
1515#include " third_party/capstone/include/capstone/x86.h"
@@ -629,6 +629,7 @@ void* X64HelperEmitter::EmitCurrentForOffsets(const _code_offsets& code_offsets,
629629 return fn;
630630}
631631HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk () {
632+ #ifdef XE_PLATFORM_WINDOWS
632633 // rcx = target
633634 // rdx = arg0 (context)
634635 // r8 = arg1 (guest return address)
@@ -666,6 +667,52 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
666667 mov (rdx, qword[rsp + 8 * 2 ]);
667668 mov (r8, qword[rsp + 8 * 3 ]);
668669 ret ();
670+ #elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC
671+ // System-V ABI args:
672+ // rdi = target
673+ // rsi = arg0 (context)
674+ // rdx = arg1 (guest return address)
675+
676+ struct _code_offsets {
677+ size_t prolog;
678+ size_t prolog_stack_alloc;
679+ size_t body;
680+ size_t epilog;
681+ size_t tail;
682+ } code_offsets = {};
683+
684+ const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
685+
686+ code_offsets.prolog = getSize ();
687+ // rsp + 0 = return address
688+ mov (qword[rsp + 8 * 3 ], rdx);
689+ mov (qword[rsp + 8 * 2 ], rsi);
690+ mov (qword[rsp + 8 * 1 ], rdi);
691+ sub (rsp, stack_size);
692+
693+ code_offsets.prolog_stack_alloc = getSize ();
694+ code_offsets.body = getSize ();
695+
696+ // Save nonvolatile registers.
697+ EmitSaveNonvolatileRegs ();
698+
699+ mov (rax, rdi);
700+ // mov(rsi, rsi); // context
701+ mov (rcx, rdx); // return address
702+ call (rax);
703+
704+ EmitLoadNonvolatileRegs ();
705+
706+ code_offsets.epilog = getSize ();
707+
708+ add (rsp, stack_size);
709+ mov (rdi, qword[rsp + 8 * 1 ]);
710+ mov (rsi, qword[rsp + 8 * 2 ]);
711+ mov (rdx, qword[rsp + 8 * 3 ]);
712+ ret ();
713+ #else
714+ assert_always (" Unknown platform ABI in host to guest thunk!" );
715+ #endif
669716
670717 code_offsets.tail = getSize ();
671718
@@ -685,6 +732,7 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
685732}
686733
687734GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk () {
735+ #if XE_PLATFORM_WIN32
688736 // rcx = target function
689737 // rdx = arg0
690738 // r8 = arg1
@@ -716,6 +764,57 @@ GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
716764
717765 add (rsp, stack_size);
718766 ret ();
767+ #elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC
768+ // This function is being called using the Microsoft ABI from CallNative
769+ // rcx = target function
770+ // rdx = arg0
771+ // r8 = arg1
772+ // r9 = arg2
773+
774+ // Must be translated to System-V ABI:
775+ // rdi = target function
776+ // rsi = arg0
777+ // rdx = arg1
778+ // rcx = arg2
779+ // r8, r9 - unused argument registers
780+
781+ struct _code_offsets {
782+ size_t prolog;
783+ size_t prolog_stack_alloc;
784+ size_t body;
785+ size_t epilog;
786+ size_t tail;
787+ } code_offsets = {};
788+
789+ const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
790+
791+ code_offsets.prolog = getSize ();
792+
793+ // rsp + 0 = return address
794+ sub (rsp, stack_size);
795+
796+ code_offsets.prolog_stack_alloc = getSize ();
797+ code_offsets.body = getSize ();
798+
799+ // Save off volatile registers.
800+ EmitSaveVolatileRegs ();
801+
802+ mov (rax, rcx); // function
803+ mov (rdi, GetContextReg ()); // context
804+ mov (rsi, rdx); // arg0
805+ mov (rdx, r8); // arg1
806+ mov (rcx, r9); // arg2
807+ call (rax);
808+
809+ EmitLoadVolatileRegs ();
810+
811+ code_offsets.epilog = getSize ();
812+
813+ add (rsp, stack_size);
814+ ret ();
815+ #else
816+ assert_always (" Unknown platform ABI in guest to host thunk!" )
817+ #endif
719818
720819 code_offsets.tail = getSize ();
721820
@@ -738,6 +837,7 @@ GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
738837uint64_t ResolveFunction (void * raw_context, uint64_t target_address);
739838
740839ResolveFunctionThunk X64HelperEmitter::EmitResolveFunctionThunk () {
840+ #if XE_PLATFORM_WIN32
741841 // ebx = target PPC address
742842 // rcx = context
743843
@@ -767,6 +867,48 @@ ResolveFunctionThunk X64HelperEmitter::EmitResolveFunctionThunk() {
767867
768868 add (rsp, stack_size);
769869 jmp (rax);
870+ #elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC
871+ // Function is called with the following params:
872+ // ebx = target PPC address
873+ // rsi = context
874+
875+ // System-V ABI args:
876+ // rdi = context
877+ // rsi = target PPC address
878+
879+ struct _code_offsets {
880+ size_t prolog;
881+ size_t prolog_stack_alloc;
882+ size_t body;
883+ size_t epilog;
884+ size_t tail;
885+ } code_offsets = {};
886+ const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
887+
888+ code_offsets.prolog = getSize ();
889+
890+ // rsp + 0 = return address
891+ sub (rsp, stack_size);
892+
893+ code_offsets.prolog_stack_alloc = getSize ();
894+ code_offsets.body = getSize ();
895+
896+ // Save volatile registers
897+ EmitSaveVolatileRegs ();
898+ mov (rdi, rsi); // context
899+ mov (rsi, rbx); // target PPC address
900+ mov (rax, reinterpret_cast <uint64_t >(&ResolveFunction));
901+ call (rax);
902+
903+ EmitLoadVolatileRegs ();
904+
905+ code_offsets.epilog = getSize ();
906+
907+ add (rsp, stack_size);
908+ jmp (rax);
909+ #else
910+ assert_always (" Unknown platform ABI in resolve function!" );
911+ #endif
770912
771913 code_offsets.tail = getSize ();
772914
0 commit comments