49 lines
1.5 KiB
C++
49 lines
1.5 KiB
C++
#include "prx/libc/include/General.hpp"
|
|
#include "prx/libc/include/general/AsmMacros.hpp"
|
|
|
|
// setjmp/longjmp must capture the guest's own frame, so they are written directly in assembly with
|
|
// the guest (System V) calling convention. The saved state fits the guest's 96-byte jmp_buf:
|
|
// return address, rbx, rsp, rbp, r12-r15, MXCSR and the x87 control word.
|
|
|
|
asm(".text\n"
|
|
APS5_ASM_FUNCTION("setjmp_nid_postfix")
|
|
" mov (%rsp), %rax\n"
|
|
" mov %rax, 0(%rdi)\n"
|
|
" mov %rbx, 8(%rdi)\n"
|
|
" lea 8(%rsp), %rax\n"
|
|
" mov %rax, 16(%rdi)\n"
|
|
" mov %rbp, 24(%rdi)\n"
|
|
" mov %r12, 32(%rdi)\n"
|
|
" mov %r13, 40(%rdi)\n"
|
|
" mov %r14, 48(%rdi)\n"
|
|
" mov %r15, 56(%rdi)\n"
|
|
" stmxcsr 64(%rdi)\n"
|
|
" fnstcw 68(%rdi)\n"
|
|
" xor %eax, %eax\n"
|
|
" ret\n"
|
|
APS5_ASM_FUNCTION("longjmp_nid_postfix")
|
|
#ifdef _WIN32
|
|
" mov %rdi, %rbx\n"
|
|
" mov %esi, %r12d\n"
|
|
" mov 16(%rdi), %rdi\n"
|
|
" and $-16, %rsp\n"
|
|
" call GuestStackSwitch_nid_no_patch\n"
|
|
" mov %rbx, %rdi\n"
|
|
" mov %r12d, %esi\n"
|
|
#endif
|
|
" mov %esi, %eax\n"
|
|
" test %eax, %eax\n"
|
|
" jnz 1f\n"
|
|
" inc %eax\n"
|
|
"1:\n"
|
|
" mov 8(%rdi), %rbx\n"
|
|
" mov 16(%rdi), %rsp\n"
|
|
" mov 24(%rdi), %rbp\n"
|
|
" mov 32(%rdi), %r12\n"
|
|
" mov 40(%rdi), %r13\n"
|
|
" mov 48(%rdi), %r14\n"
|
|
" mov 56(%rdi), %r15\n"
|
|
" ldmxcsr 64(%rdi)\n"
|
|
" fldcw 68(%rdi)\n"
|
|
" jmp *0(%rdi)\n");
|