1 //===-- Implementation of longjmp -----------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "src/setjmp/longjmp.h"
10 #include "src/__support/common.h"
12 #if !defined(LIBC_TARGET_ARCH_IS_X86_64)
13 #error "Invalid file include"
16 namespace LIBC_NAMESPACE
{
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");
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
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
));
44 } // namespace LIBC_NAMESPACE