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