@@ -418,6 +418,7 @@ X64ThunkEmitter::X64ThunkEmitter(X64Backend* backend, XbyakAllocator* allocator)
418
418
X64ThunkEmitter::~X64ThunkEmitter () {}
419
419
420
420
HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk () {
421
+ #if XE_PLATFORM_WIN32
421
422
// rcx = target
422
423
// rdx = arg0 (context)
423
424
// r8 = arg1 (guest return address)
@@ -460,6 +461,53 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
460
461
mov (rdx, qword[rsp + 8 * 2 ]);
461
462
mov (r8, qword[rsp + 8 * 3 ]);
462
463
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
463
511
464
512
code_offsets.tail = getSize ();
465
513
@@ -479,6 +527,7 @@ HostToGuestThunk X64ThunkEmitter::EmitHostToGuestThunk() {
479
527
}
480
528
481
529
GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk () {
530
+ #if XE_PLATFORM_WIN32
482
531
// rcx = target function
483
532
// rdx = arg0
484
533
// r8 = arg1
@@ -515,6 +564,57 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
515
564
516
565
add (rsp, stack_size);
517
566
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
518
618
519
619
code_offsets.tail = getSize ();
520
620
@@ -537,6 +637,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
537
637
uint64_t ResolveFunction (void * raw_context, uint64_t target_address);
538
638
539
639
ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk () {
640
+ #if XE_PLATFORM_WIN32
540
641
// ebx = target PPC address
541
642
// rcx = context
542
643
@@ -572,6 +673,49 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
572
673
573
674
add (rsp, stack_size);
574
675
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
575
719
576
720
code_offsets.tail = getSize ();
577
721
0 commit comments