1 | //===-- Implementation of longjmp -----------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "src/setjmp/longjmp.h" |
10 | #include "src/__support/common.h" |
11 | |
12 | #if !defined(LIBC_TARGET_ARCH_IS_X86_64) |
13 | #error "Invalid file include" |
14 | #endif |
15 | |
16 | namespace LIBC_NAMESPACE { |
17 | |
18 | LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) { |
19 | register __UINT64_TYPE__ rbx __asm__("rbx" ); |
20 | register __UINT64_TYPE__ rbp __asm__("rbp" ); |
21 | register __UINT64_TYPE__ r12 __asm__("r12" ); |
22 | register __UINT64_TYPE__ r13 __asm__("r13" ); |
23 | register __UINT64_TYPE__ r14 __asm__("r14" ); |
24 | register __UINT64_TYPE__ r15 __asm__("r15" ); |
25 | register __UINT64_TYPE__ rsp __asm__("rsp" ); |
26 | register __UINT64_TYPE__ rax __asm__("rax" ); |
27 | |
28 | // ABI requires that the return value should be stored in rax. So, we store |
29 | // |val| in rax. Note that this has to happen before we restore the registers |
30 | // from values in |buf|. Otherwise, once rsp and rbp are updated, we cannot |
31 | // read |val|. |
32 | val = val == 0 ? 1 : val; |
33 | LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r" (rax) : "m" (val) :); |
34 | LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r" (rbx) : "m" (buf->rbx) :); |
35 | LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r" (rbp) : "m" (buf->rbp) :); |
36 | LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r" (r12) : "m" (buf->r12) :); |
37 | LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r" (r13) : "m" (buf->r13) :); |
38 | LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r" (r14) : "m" (buf->r14) :); |
39 | LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r" (r15) : "m" (buf->r15) :); |
40 | LIBC_INLINE_ASM("mov %1, %0\n\t" : "=r" (rsp) : "m" (buf->rsp) :); |
41 | LIBC_INLINE_ASM("jmp *%0\n\t" : : "m" (buf->rip)); |
42 | } |
43 | |
44 | } // namespace LIBC_NAMESPACE |
45 | |