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 | |
14 | namespace 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 | |