@@ -13,24 +13,23 @@ namespace LIBC_NAMESPACE {
13
13
14
14
#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1
15
15
16
- [[gnu::naked]]
16
+ [[gnu::naked, gnu::target( " thumb " ) ]]
17
17
LLVM_LIBC_FUNCTION (int , setjmp, (__jmp_buf * buf)) {
18
18
asm (R"(
19
19
# Store r4, r5, r6, and r7 into buf.
20
20
stmia r0!, {r4-r7}
21
21
22
- # Store r8, r9, r10, and r11 into buf. Thumb(1) doesn't support the high
23
- # registers > r7 in stmia, so move them into lower GPRs first.
24
- mov r4, r8
25
- mov r5, r9
26
- mov r6, r10
27
- mov r7, r11
28
- stmia r0!, {r4-r7}
29
-
30
- # Store sp into buf. Thumb(1) doesn't support sp in str, move to GPR
31
- # first.
32
- mov r4, sp
33
- str r4, [r0]
22
+ # Store r8, r9, r10, r11, sp, and lr into buf. Thumb(1) doesn't support
23
+ # the high registers > r7 in stmia, so move them into lower GPRs first.
24
+ # Thumb(1) also doesn't support using str with sp or lr, move them
25
+ # together with the rest.
26
+ mov r2, r8
27
+ mov r3, r9
28
+ mov r4, r10
29
+ mov r5, r11
30
+ mov r6, sp
31
+ mov r7, lr
32
+ stmia r0!, {r2-r7}
34
33
35
34
# Return 0.
36
35
movs r0, #0
@@ -42,8 +41,15 @@ LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) {
42
41
[[gnu::naked]]
43
42
LLVM_LIBC_FUNCTION (int , setjmp, (__jmp_buf * buf)) {
44
43
asm (R"(
44
+ # While sp may appear in a register list for ARM mode, it may not for
45
+ # Thumb2 mode. Just move it into r12 then stm that, so that this code
46
+ # is portable between ARM and Thumb2.
45
47
mov r12, sp
48
+
49
+ # Store r4, r5, r6, r7, r8, r9, r10, r11, sp, and lr into buf.
46
50
stm r0, {r4-r12, lr}
51
+
52
+ # Return zero.
47
53
mov r0, #0
48
54
bx lr)" );
49
55
}
0 commit comments