76 lines · cpp
1 2//===-- Implementation of longjmp -----------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#include "src/setjmp/longjmp.h"11#include "src/__support/common.h"12#include "src/__support/macros/config.h"13 14namespace LIBC_NAMESPACE_DECL {15 16#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 117 18[[gnu::naked, gnu::target("thumb")]] LLVM_LIBC_FUNCTION(void, longjmp,19 (jmp_buf buf,20 int val)) {21 asm(R"(22 # Reload r4, r5, r6, r7.23 ldmia r0!, {r4-r7}24 25 # Reload r8, r9. They cannot appear in register lists so load them26 # into the lower registers, then move them into place.27 ldmia r0!, {r2-r3}28 mov r8, r229 mov r9, r330 31 # Reload r10, r11. They cannot appear in register lists so load them32 # into the lower registers, then move them into place.33 ldmia r0!, {r2-r3}34 mov r10, r235 mov r11, r336 37 # Reload sp, lr. They cannot appear in register lists so load them38 # into the lower registers, then move them into place.39 ldmia r0!, {r2-r3}40 mov sp, r241 mov lr, r342 43 # return val ?: 1;44 movs r0, r145 bne .Lret_val46 movs r0, #147 48 .Lret_val:49 bx lr)");50}51 52#else // Thumb2 or ARM53 54// TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers55// (d0-d16)56// TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti57[[gnu::naked]] LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {58 asm(R"(59 # While sp may appear in a register list for ARM mode, it may not for60 # Thumb2 mode. Just load the previous value of sp into r12 then move it61 # into sp, so that this code is portable between ARM and Thumb2.62 63 ldm r0, {r4-r12, lr}64 mov sp, r1265 66 # return val ?: 1;67 movs r0, r168 it eq69 moveq r0, #170 bx lr)");71}72 73#endif74 75} // namespace LIBC_NAMESPACE_DECL76