| //===-- Implementation of sigsetjmp ---------------------------------------===// | |
| // | |
| // 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/sigsetjmp.h" | |
| #include "hdr/offsetof_macros.h" | |
| #include "src/__support/common.h" | |
| #include "src/__support/macros/config.h" | |
| #include "src/setjmp/setjmp_impl.h" | |
| #include "src/setjmp/sigsetjmp_epilogue.h" | |
| namespace LIBC_NAMESPACE_DECL { | |
| [[gnu::naked]] | |
| LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf buf)) { | |
| #if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1 | |
| // Thumb1 does not support the high registers > r7 in stmia, so move them | |
| // into lower GPRs first. | |
| asm(R"( | |
| tst r1, r1 | |
| bne .Ldosave | |
| b %c[setjmp] | |
| .Ldosave: | |
| str r4, [r0, #%c[extra]] | |
| mov r4, lr | |
| str r4, [r0, #%c[retaddr]] | |
| mov r4, r0 | |
| bl %c[setjmp] | |
| mov r1, r0 | |
| mov r0, r4 | |
| ldr r4, [r0, #%c[retaddr]] | |
| mov lr, r4 | |
| ldr r4, [r0, #%c[extra]] | |
| b %c[epilogue] | |
| )" ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)), | |
| [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp), | |
| [epilogue] "i"(sigsetjmp_epilogue) | |
| : "r0", "r1", "r4"); | |
| #else | |
| // Some thumb2 linkers do not support conditional branch to PLT. | |
| // We branch to local labels instead. | |
| asm(R"( | |
| tst r1, r1 | |
| bne .Ldosave | |
| b %c[setjmp] | |
| .Ldosave: | |
| str r4, [r0, #%c[extra]] | |
| str lr, [r0, #%c[retaddr]] | |
| mov r4, r0 | |
| bl %c[setjmp] | |
| mov r1, r0 | |
| mov r0, r4 | |
| ldr lr, [r0, #%c[retaddr]] | |
| ldr r4, [r0, #%c[extra]] | |
| b %c[epilogue] | |
| )" ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)), | |
| [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "X"(setjmp), | |
| [epilogue] "X"(sigsetjmp_epilogue) | |
| : "r0", "r1", "r4"); | |
| #endif | |
| } | |
| } // namespace LIBC_NAMESPACE_DECL |