Skip to content

Commit 23a3943

Browse files
implement longjmp for thumb1
1 parent 2d13bf8 commit 23a3943

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

libc/src/setjmp/arm/longjmp.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,57 @@
1212

1313
namespace LIBC_NAMESPACE {
1414

15+
#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1
16+
17+
[[gnu::naked]]
18+
LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) {
19+
asm(R"(
20+
# Reload r4, r5, r6, r7.
21+
ldmia r0!, {r4, r5, r6, r7}
22+
23+
# Reload r8, r9, r10. They cannot appear in register lists so load them
24+
# into the lower registers, then move them into place.
25+
ldmia r0!, {r1, r2, r3}
26+
mov r8, r1
27+
mov r9, r2
28+
mov r10, r3
29+
30+
# Reload r11, sp, lr. They cannot appear in register lists so load them
31+
# into the lower registers, then move them into place.
32+
ldmia r0!, {r1, r2, r3}
33+
mov r11, r1
34+
mov sp, r2
35+
mov lr, r3
36+
37+
# return val ?: 1;
38+
movs r0, r1
39+
beq .Lret_one
40+
bx lr
41+
42+
.Lret_one:
43+
movs r0, #1
44+
bx lr)");
45+
}
46+
47+
#else // Thumb2 or ARM
48+
1549
[[gnu::naked]]
1650
LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) {
1751
asm(R"(
52+
# While sp may appear in a register list for ARM mode, it may not for
53+
# Thumb2 mode. Just load the previous value of sp into r12 then move it
54+
# into sp, so that this code is portable between ARM and Thumb2.
55+
1856
ldm r0, {r4-r12, lr}
1957
mov sp, r12
58+
59+
# return val ?: 1;
2060
movs r0, r1
2161
it eq
2262
moveq r0, #1
2363
bx lr)");
2464
}
2565

66+
#endif
67+
2668
} // namespace LIBC_NAMESPACE

0 commit comments

Comments
 (0)