-
Notifications
You must be signed in to change notification settings - Fork 11.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc][arm] implement a basic setjmp/longjmp (#93220)
Note: our baremetal arm configuration compiles this as `--target=arm-none-eabi`, so this code is built in -marm mode. It could be smaller with `--target=armv7-none-eabi -mthumb`. The assembler is valid ARMv5, or THUMB2, but not THUMB(1).
- Loading branch information
1 parent
abad845
commit f1ce6a4
Showing
9 changed files
with
178 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
add_entrypoint_object( | ||
setjmp | ||
SRCS | ||
setjmp.cpp | ||
HDRS | ||
../setjmp_impl.h | ||
DEPENDS | ||
libc.include.setjmp | ||
) | ||
|
||
add_entrypoint_object( | ||
longjmp | ||
SRCS | ||
longjmp.cpp | ||
HDRS | ||
../longjmp.h | ||
DEPENDS | ||
libc.include.setjmp | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
|
||
//===-- Implementation of longjmp -----------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "src/setjmp/longjmp.h" | ||
#include "src/__support/common.h" | ||
|
||
namespace LIBC_NAMESPACE { | ||
|
||
#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1 | ||
|
||
[[gnu::naked, gnu::target("thumb")]] | ||
LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) { | ||
asm(R"( | ||
# Reload r4, r5, r6, r7. | ||
ldmia r0!, {r4-r7} | ||
# Reload r8, r9. They cannot appear in register lists so load them | ||
# into the lower registers, then move them into place. | ||
ldmia r0!, {r2-r3} | ||
mov r8, r2 | ||
mov r9, r3 | ||
# Reload r10, r11. They cannot appear in register lists so load them | ||
# into the lower registers, then move them into place. | ||
ldmia r0!, {r2-r3} | ||
mov r10, r2 | ||
mov r11, r3 | ||
# Reload sp, lr. They cannot appear in register lists so load them | ||
# into the lower registers, then move them into place. | ||
ldmia r0!, {r2-r3} | ||
mov sp, r2 | ||
mov lr, r3 | ||
# return val ?: 1; | ||
movs r0, r1 | ||
bne .Lret_val | ||
movs r0, #1 | ||
.Lret_val: | ||
bx lr)"); | ||
} | ||
|
||
#else // Thumb2 or ARM | ||
|
||
// TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers | ||
// (d0-d16) | ||
// TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti | ||
[[gnu::naked]] | ||
LLVM_LIBC_FUNCTION(void, longjmp, (__jmp_buf * buf, int val)) { | ||
asm(R"( | ||
# While sp may appear in a register list for ARM mode, it may not for | ||
# Thumb2 mode. Just load the previous value of sp into r12 then move it | ||
# into sp, so that this code is portable between ARM and Thumb2. | ||
ldm r0, {r4-r12, lr} | ||
mov sp, r12 | ||
# return val ?: 1; | ||
movs r0, r1 | ||
it eq | ||
moveq r0, #1 | ||
bx lr)"); | ||
} | ||
|
||
#endif | ||
|
||
} // namespace LIBC_NAMESPACE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
//===-- Implementation of setjmp ------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "src/__support/common.h" | ||
#include "src/setjmp/setjmp_impl.h" | ||
|
||
namespace LIBC_NAMESPACE { | ||
|
||
#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1 | ||
|
||
[[gnu::naked, gnu::target("thumb")]] | ||
LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) { | ||
asm(R"( | ||
# Store r4, r5, r6, and r7 into buf. | ||
stmia r0!, {r4-r7} | ||
# Store r8, r9, r10, r11, sp, and lr into buf. Thumb(1) doesn't support | ||
# the high registers > r7 in stmia, so move them into lower GPRs first. | ||
# Thumb(1) also doesn't support using str with sp or lr, move them | ||
# together with the rest. | ||
mov r1, r8 | ||
mov r2, r9 | ||
mov r3, r10 | ||
stmia r0!, {r1-r3} | ||
mov r1, r11 | ||
mov r2, sp | ||
mov r3, lr | ||
stmia r0!, {r1-r3} | ||
# Return 0. | ||
movs r0, #0 | ||
bx lr)"); | ||
} | ||
|
||
#else // Thumb2 or ARM | ||
|
||
// TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers | ||
// (d0-d16) | ||
// TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti | ||
[[gnu::naked]] | ||
LLVM_LIBC_FUNCTION(int, setjmp, (__jmp_buf * buf)) { | ||
asm(R"( | ||
# While sp may appear in a register list for ARM mode, it may not for | ||
# Thumb2 mode. Just move it into r12 then stm that, so that this code | ||
# is portable between ARM and Thumb2. | ||
mov r12, sp | ||
# Store r4, r5, r6, r7, r8, r9, r10, r11, sp, and lr into buf. | ||
stm r0, {r4-r12, lr} | ||
# Return zero. | ||
mov r0, #0 | ||
bx lr)"); | ||
} | ||
|
||
#endif | ||
|
||
} // namespace LIBC_NAMESPACE |