xref: /aosp_15_r20/external/llvm-libc/src/setjmp/arm/longjmp.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1*71db0c75SAndroid Build Coastguard Worker 
2*71db0c75SAndroid Build Coastguard Worker //===-- Implementation of longjmp -----------------------------------------===//
3*71db0c75SAndroid Build Coastguard Worker //
4*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
6*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*71db0c75SAndroid Build Coastguard Worker //
8*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*71db0c75SAndroid Build Coastguard Worker 
10*71db0c75SAndroid Build Coastguard Worker #include "src/setjmp/longjmp.h"
11*71db0c75SAndroid Build Coastguard Worker #include "src/__support/common.h"
12*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h"
13*71db0c75SAndroid Build Coastguard Worker 
14*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL {
15*71db0c75SAndroid Build Coastguard Worker 
16*71db0c75SAndroid Build Coastguard Worker #if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1
17*71db0c75SAndroid Build Coastguard Worker 
18*71db0c75SAndroid Build Coastguard Worker [[gnu::naked, gnu::target("thumb")]] LLVM_LIBC_FUNCTION(void, longjmp,
19*71db0c75SAndroid Build Coastguard Worker                                                         (jmp_buf buf,
20*71db0c75SAndroid Build Coastguard Worker                                                          int val)) {
21*71db0c75SAndroid Build Coastguard Worker   asm(R"(
22*71db0c75SAndroid Build Coastguard Worker       # Reload r4, r5, r6, r7.
23*71db0c75SAndroid Build Coastguard Worker       ldmia r0!, {r4-r7}
24*71db0c75SAndroid Build Coastguard Worker 
25*71db0c75SAndroid Build Coastguard Worker       # Reload r8, r9. They cannot appear in register lists so load them
26*71db0c75SAndroid Build Coastguard Worker       # into the lower registers, then move them into place.
27*71db0c75SAndroid Build Coastguard Worker       ldmia r0!, {r2-r3}
28*71db0c75SAndroid Build Coastguard Worker       mov r8, r2
29*71db0c75SAndroid Build Coastguard Worker       mov r9, r3
30*71db0c75SAndroid Build Coastguard Worker 
31*71db0c75SAndroid Build Coastguard Worker       # Reload r10, r11. They cannot appear in register lists so load them
32*71db0c75SAndroid Build Coastguard Worker       # into the lower registers, then move them into place.
33*71db0c75SAndroid Build Coastguard Worker       ldmia r0!, {r2-r3}
34*71db0c75SAndroid Build Coastguard Worker       mov r10, r2
35*71db0c75SAndroid Build Coastguard Worker       mov r11, r3
36*71db0c75SAndroid Build Coastguard Worker 
37*71db0c75SAndroid Build Coastguard Worker       # Reload sp, lr. They cannot appear in register lists so load them
38*71db0c75SAndroid Build Coastguard Worker       # into the lower registers, then move them into place.
39*71db0c75SAndroid Build Coastguard Worker       ldmia r0!, {r2-r3}
40*71db0c75SAndroid Build Coastguard Worker       mov sp, r2
41*71db0c75SAndroid Build Coastguard Worker       mov lr, r3
42*71db0c75SAndroid Build Coastguard Worker 
43*71db0c75SAndroid Build Coastguard Worker       # return val ?: 1;
44*71db0c75SAndroid Build Coastguard Worker       movs r0, r1
45*71db0c75SAndroid Build Coastguard Worker       bne .Lret_val
46*71db0c75SAndroid Build Coastguard Worker       movs r0, #1
47*71db0c75SAndroid Build Coastguard Worker 
48*71db0c75SAndroid Build Coastguard Worker     .Lret_val:
49*71db0c75SAndroid Build Coastguard Worker       bx lr)");
50*71db0c75SAndroid Build Coastguard Worker }
51*71db0c75SAndroid Build Coastguard Worker 
52*71db0c75SAndroid Build Coastguard Worker #else // Thumb2 or ARM
53*71db0c75SAndroid Build Coastguard Worker 
54*71db0c75SAndroid Build Coastguard Worker // TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers
55*71db0c75SAndroid Build Coastguard Worker // (d0-d16)
56*71db0c75SAndroid Build Coastguard Worker // TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti
57*71db0c75SAndroid Build Coastguard Worker [[gnu::naked]] LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) {
58*71db0c75SAndroid Build Coastguard Worker   asm(R"(
59*71db0c75SAndroid Build Coastguard Worker       # While sp may appear in a register list for ARM mode, it may not for
60*71db0c75SAndroid Build Coastguard Worker       # Thumb2 mode. Just load the previous value of sp into r12 then move it
61*71db0c75SAndroid Build Coastguard Worker       # into sp, so that this code is portable between ARM and Thumb2.
62*71db0c75SAndroid Build Coastguard Worker 
63*71db0c75SAndroid Build Coastguard Worker       ldm r0, {r4-r12, lr}
64*71db0c75SAndroid Build Coastguard Worker       mov sp, r12
65*71db0c75SAndroid Build Coastguard Worker 
66*71db0c75SAndroid Build Coastguard Worker       # return val ?: 1;
67*71db0c75SAndroid Build Coastguard Worker       movs r0, r1
68*71db0c75SAndroid Build Coastguard Worker       it eq
69*71db0c75SAndroid Build Coastguard Worker       moveq r0, #1
70*71db0c75SAndroid Build Coastguard Worker       bx lr)");
71*71db0c75SAndroid Build Coastguard Worker }
72*71db0c75SAndroid Build Coastguard Worker 
73*71db0c75SAndroid Build Coastguard Worker #endif
74*71db0c75SAndroid Build Coastguard Worker 
75*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL
76