2
2
******************************************************************************
3
3
* Xenia : Xbox 360 Emulator Research Project *
4
4
******************************************************************************
5
- * Copyright 2019 Ben Vanik. All rights reserved. *
5
+ * Copyright 2025 Ben Vanik. All rights reserved. *
6
6
* Released under the BSD license - see LICENSE in the root for more details. *
7
7
******************************************************************************
8
8
*/
9
9
10
10
#include " xenia/cpu/backend/x64/x64_backend.h"
11
11
12
- #include < stddef.h>
13
12
#include < algorithm>
13
+ #include < cstddef>
14
14
#include " third_party/capstone/include/capstone/capstone.h"
15
15
#include " third_party/capstone/include/capstone/x86.h"
16
16
@@ -629,6 +629,7 @@ void* X64HelperEmitter::EmitCurrentForOffsets(const _code_offsets& code_offsets,
629
629
return fn;
630
630
}
631
631
HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk () {
632
+ #ifdef XE_PLATFORM_WIN32
632
633
// rcx = target
633
634
// rdx = arg0 (context)
634
635
// r8 = arg1 (guest return address)
@@ -666,6 +667,53 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
666
667
mov (rdx, qword[rsp + 8 * 2 ]);
667
668
mov (r8, qword[rsp + 8 * 3 ]);
668
669
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 (rdi, ptr[rsi + offsetof (ppc::PPCContext, virtual_membase)]); // membase
702
+ mov (rcx, rdx); // return address
703
+ call (rax);
704
+
705
+ EmitLoadNonvolatileRegs ();
706
+
707
+ code_offsets.epilog = getSize ();
708
+
709
+ add (rsp, stack_size);
710
+ mov (rdi, qword[rsp + 8 * 1 ]);
711
+ mov (rsi, qword[rsp + 8 * 2 ]);
712
+ mov (rdx, qword[rsp + 8 * 3 ]);
713
+ ret ();
714
+ #else
715
+ assert_always (" Unknown platform ABI in host to guest thunk!" );
716
+ #endif
669
717
670
718
code_offsets.tail = getSize ();
671
719
@@ -685,6 +733,7 @@ HostToGuestThunk X64HelperEmitter::EmitHostToGuestThunk() {
685
733
}
686
734
687
735
GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk () {
736
+ #if XE_PLATFORM_WIN32
688
737
// rcx = target function
689
738
// rdx = arg0
690
739
// r8 = arg1
@@ -716,6 +765,57 @@ GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
716
765
717
766
add (rsp, stack_size);
718
767
ret ();
768
+ #elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC
769
+ // This function is being called using the Microsoft ABI from CallNative
770
+ // rcx = target function
771
+ // rdx = arg0
772
+ // r8 = arg1
773
+ // r9 = arg2
774
+
775
+ // Must be translated to System-V ABI:
776
+ // rdi = target function
777
+ // rsi = arg0
778
+ // rdx = arg1
779
+ // rcx = arg2
780
+ // r8, r9 - unused argument registers
781
+
782
+ struct _code_offsets {
783
+ size_t prolog;
784
+ size_t prolog_stack_alloc;
785
+ size_t body;
786
+ size_t epilog;
787
+ size_t tail;
788
+ } code_offsets = {};
789
+
790
+ const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
791
+
792
+ code_offsets.prolog = getSize ();
793
+
794
+ // rsp + 0 = return address
795
+ sub (rsp, stack_size);
796
+
797
+ code_offsets.prolog_stack_alloc = getSize ();
798
+ code_offsets.body = getSize ();
799
+
800
+ // Save off volatile registers.
801
+ EmitSaveVolatileRegs ();
802
+
803
+ mov (rax, rcx); // function
804
+ mov (rdi, GetContextReg ()); // context
805
+ mov (rsi, rdx); // arg0
806
+ mov (rdx, r8); // arg1
807
+ mov (rcx, r9); // arg2
808
+ call (rax);
809
+
810
+ EmitLoadVolatileRegs ();
811
+
812
+ code_offsets.epilog = getSize ();
813
+
814
+ add (rsp, stack_size);
815
+ ret ();
816
+ #else
817
+ assert_always (" Unknown platform ABI in guest to host thunk!" )
818
+ #endif
719
819
720
820
code_offsets.tail = getSize ();
721
821
@@ -738,6 +838,7 @@ GuestToHostThunk X64HelperEmitter::EmitGuestToHostThunk() {
738
838
uint64_t ResolveFunction (void * raw_context, uint64_t target_address);
739
839
740
840
ResolveFunctionThunk X64HelperEmitter::EmitResolveFunctionThunk () {
841
+ #if XE_PLATFORM_WIN32
741
842
// ebx = target PPC address
742
843
// rcx = context
743
844
@@ -767,6 +868,48 @@ ResolveFunctionThunk X64HelperEmitter::EmitResolveFunctionThunk() {
767
868
768
869
add (rsp, stack_size);
769
870
jmp (rax);
871
+ #elif XE_PLATFORM_LINUX || XE_PLATFORM_MAC
872
+ // Function is called with the following params:
873
+ // ebx = target PPC address
874
+ // rsi = context
875
+
876
+ // System-V ABI args:
877
+ // rdi = context
878
+ // rsi = target PPC address
879
+
880
+ struct _code_offsets {
881
+ size_t prolog;
882
+ size_t prolog_stack_alloc;
883
+ size_t body;
884
+ size_t epilog;
885
+ size_t tail;
886
+ } code_offsets = {};
887
+ const size_t stack_size = StackLayout::THUNK_STACK_SIZE;
888
+
889
+ code_offsets.prolog = getSize ();
890
+
891
+ // rsp + 0 = return address
892
+ sub (rsp, stack_size);
893
+
894
+ code_offsets.prolog_stack_alloc = getSize ();
895
+ code_offsets.body = getSize ();
896
+
897
+ // Save volatile registers
898
+ EmitSaveVolatileRegs ();
899
+ mov (rdi, rsi); // context
900
+ mov (rsi, rbx); // target PPC address
901
+ mov (rax, reinterpret_cast <uint64_t >(&ResolveFunction));
902
+ call (rax);
903
+
904
+ EmitLoadVolatileRegs ();
905
+
906
+ code_offsets.epilog = getSize ();
907
+
908
+ add (rsp, stack_size);
909
+ jmp (rax);
910
+ #else
911
+ assert_always (" Unknown platform ABI in resolve function!" );
912
+ #endif
770
913
771
914
code_offsets.tail = getSize ();
772
915
0 commit comments