AnyPS5/core/libs/prx/libc/src/JumpBuffer.cpp

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");