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-exception
7//
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 == 1
17
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 them
26 # into the lower registers, then move them into place.
27 ldmia r0!, {r2-r3}
28 mov r8, r2
29 mov r9, r3
30
31 # Reload r10, r11. They cannot appear in register lists so load them
32 # into the lower registers, then move them into place.
33 ldmia r0!, {r2-r3}
34 mov r10, r2
35 mov r11, r3
36
37 # Reload sp, lr. They cannot appear in register lists so load them
38 # into the lower registers, then move them into place.
39 ldmia r0!, {r2-r3}
40 mov sp, r2
41 mov lr, r3
42
43 # return val ?: 1;
44 movs r0, r1
45 bne .Lret_val
46 movs r0, #1
47
48 .Lret_val:
49 bx lr)");
50}
51
52#else // Thumb2 or ARM
53
54// TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers
55// (d0-d16)
56// TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti
57[[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 for
60 # Thumb2 mode. Just load the previous value of sp into r12 then move it
61 # into sp, so that this code is portable between ARM and Thumb2.
62
63 ldm r0, {r4-r12, lr}
64 mov sp, r12
65
66 # return val ?: 1;
67 movs r0, r1
68 it eq
69 moveq r0, #1
70 bx lr)");
71}
72
73#endif
74
75} // namespace LIBC_NAMESPACE_DECL
76

source code of libc/src/setjmp/arm/longjmp.cpp