@@ -418,6 +418,7 @@ X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
418418X64ThunkEmitter::~X64ThunkEmitter () {}
419419
420420HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk () {
421+ #if  XE_PLATFORM_WIN32
421422  //  rcx = target
422423  //  rdx = arg0 (context)
423424  //  r8 = arg1 (guest return address)
@@ -460,6 +461,53 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
460461  mov (rdx, qword[rsp + 8  * 2 ]);
461462  mov (r8, qword[rsp + 8  * 3 ]);
462463  ret ();
464+ #elif  XE_PLATFORM_LINUX || XE_PLATFORM_MAC
465+   //  System-V ABI args:
466+   //  rdi = target
467+   //  rsi = arg0 (context)
468+   //  rdx = arg1 (guest return address)
469+ 
470+   struct  _code_offsets  {
471+     size_t  prolog;
472+     size_t  prolog_stack_alloc;
473+     size_t  body;
474+     size_t  epilog;
475+     size_t  tail;
476+   } code_offsets = {};
477+ 
478+   const  size_t  stack_size = StackLayout::THUNK_STACK_SIZE;
479+ 
480+   code_offsets.prolog  = getSize ();
481+ 
482+   //  rsp + 0 = return address
483+   mov (qword[rsp + 8  * 3 ], rdx);
484+   mov (qword[rsp + 8  * 2 ], rsi);
485+   mov (qword[rsp + 8  * 1 ], rdi);
486+   sub (rsp, stack_size);
487+ 
488+   code_offsets.prolog_stack_alloc  = getSize ();
489+   code_offsets.body  = getSize ();
490+ 
491+   //  Save nonvolatile registers.
492+   EmitSaveNonvolatileRegs ();
493+ 
494+   mov (rax, rdi);
495+   //  mov(rsi, rsi);   // context
496+   mov (rcx, rdx);  //  return address
497+   call (rax);
498+ 
499+   EmitLoadNonvolatileRegs ();
500+ 
501+   code_offsets.epilog  = getSize ();
502+ 
503+   add (rsp, stack_size);
504+   mov (rdi, qword[rsp + 8  * 1 ]);
505+   mov (rsi, qword[rsp + 8  * 2 ]);
506+   mov (rdx, qword[rsp + 8  * 3 ]);
507+   ret ();
508+ #else 
509+   assert_always (" Unknown platform ABI in host to guest thunk!" 
510+ #endif 
463511
464512  code_offsets.tail  = getSize ();
465513
@@ -479,6 +527,7 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
479527}
480528
481529GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk () {
530+ #if  XE_PLATFORM_WIN32
482531  //  rcx = target function
483532  //  rdx = arg0
484533  //  r8  = arg1
@@ -515,6 +564,57 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
515564
516565  add (rsp, stack_size);
517566  ret ();
567+ #elif  XE_PLATFORM_LINUX || XE_PLATFORM_MAC
568+   //  This function is being called using the Microsoft ABI from CallNative
569+   //  rcx = target function
570+   //  rdx = arg0
571+   //  r8  = arg1
572+   //  r9  = arg2
573+ 
574+   //  Must be translated to System-V ABI:
575+   //  rdi = target function
576+   //  rsi = arg0
577+   //  rdx = arg1
578+   //  rcx = arg2
579+   //  r8, r9 - unused argument registers
580+ 
581+   struct  _code_offsets  {
582+     size_t  prolog;
583+     size_t  prolog_stack_alloc;
584+     size_t  body;
585+     size_t  epilog;
586+     size_t  tail;
587+   } code_offsets = {};
588+ 
589+   const  size_t  stack_size = StackLayout::THUNK_STACK_SIZE;
590+ 
591+   code_offsets.prolog  = getSize ();
592+ 
593+   //  rsp + 0 = return address
594+   sub (rsp, stack_size);
595+ 
596+   code_offsets.prolog_stack_alloc  = getSize ();
597+   code_offsets.body  = getSize ();
598+ 
599+   //  Save off volatile registers.
600+   EmitSaveVolatileRegs ();
601+ 
602+   mov (rax, rcx);              //  function
603+   mov (rdi, GetContextReg ());  //  context
604+   mov (rsi, rdx);              //  arg0
605+   mov (rdx, r8);               //  arg1
606+   mov (rcx, r9);               //  arg2
607+   call (rax);
608+ 
609+   EmitLoadVolatileRegs ();
610+ 
611+   code_offsets.epilog  = getSize ();
612+ 
613+   add (rsp, stack_size);
614+   ret ();
615+ #else 
616+   assert_always (" Unknown platform ABI in guest to host thunk!" 
617+ #endif 
518618
519619  code_offsets.tail  = getSize ();
520620
@@ -537,6 +637,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
537637uint64_t  ResolveFunction (void * raw_context, uint64_t  target_address);
538638
539639ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk () {
640+ #if  XE_PLATFORM_WIN32
540641  //  ebx = target PPC address
541642  //  rcx = context
542643
@@ -572,6 +673,49 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
572673
573674  add (rsp, stack_size);
574675  jmp (rax);
676+ #elif  XE_PLATFORM_LINUX || XE_PLATFORM_MAC
677+   //  Function is called with the following params:
678+   //  ebx = target PPC address
679+   //  rsi = context
680+ 
681+   //  System-V ABI args:
682+   //  rdi = context
683+   //  rsi = target PPC address
684+ 
685+   struct  _code_offsets  {
686+     size_t  prolog;
687+     size_t  prolog_stack_alloc;
688+     size_t  body;
689+     size_t  epilog;
690+     size_t  tail;
691+   } code_offsets = {};
692+ 
693+   const  size_t  stack_size = StackLayout::THUNK_STACK_SIZE;
694+ 
695+   code_offsets.prolog  = getSize ();
696+ 
697+   //  rsp + 0 = return address
698+   sub (rsp, stack_size);
699+ 
700+   code_offsets.prolog_stack_alloc  = getSize ();
701+   code_offsets.body  = getSize ();
702+ 
703+   //  Save volatile registers
704+   EmitSaveVolatileRegs ();
705+   mov (rdi, rsi);  //  context
706+   mov (rsi, rbx);  //  target PPC address
707+   mov (rax, reinterpret_cast <uint64_t >(&ResolveFunction));
708+   call (rax);
709+ 
710+   EmitLoadVolatileRegs ();
711+ 
712+   code_offsets.epilog  = getSize ();
713+ 
714+   add (rsp, stack_size);
715+   jmp (rax);
716+ #else 
717+   assert_always (" Unknown platform ABI in resolve function!" 
718+ #endif 
575719
576720  code_offsets.tail  = getSize ();
577721
0 commit comments