1//===-- Implementation of sigsetjmp ---------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "src/setjmp/sigsetjmp.h"
10#include "hdr/offsetof_macros.h"
11#include "src/__support/common.h"
12#include "src/__support/macros/config.h"
13#include "src/setjmp/setjmp_impl.h"
14#include "src/setjmp/sigsetjmp_epilogue.h"
15
16namespace LIBC_NAMESPACE_DECL {
17[[gnu::naked]]
18LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf buf)) {
19#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1
20 // Thumb1 does not support the high registers > r7 in stmia, so move them
21 // into lower GPRs first.
22 asm(R"(
23 tst r1, r1
24 bne .Ldosave
25 b %c[setjmp]
26.Ldosave:
27 str r4, [r0, #%c[extra]]
28 mov r4, lr
29 str r4, [r0, #%c[retaddr]]
30 mov r4, r0
31 bl %c[setjmp]
32 mov r1, r0
33 mov r0, r4
34 ldr r4, [r0, #%c[retaddr]]
35 mov lr, r4
36 ldr r4, [r0, #%c[extra]]
37 b %c[epilogue]
38 )" ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)),
39 [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "i"(setjmp),
40 [epilogue] "i"(sigsetjmp_epilogue)
41 : "r0", "r1", "r4");
42#else
43 // Some thumb2 linkers do not support conditional branch to PLT.
44 // We branch to local labels instead.
45 asm(R"(
46 tst r1, r1
47 bne .Ldosave
48 b %c[setjmp]
49.Ldosave:
50 str r4, [r0, #%c[extra]]
51 str lr, [r0, #%c[retaddr]]
52 mov r4, r0
53 bl %c[setjmp]
54 mov r1, r0
55 mov r0, r4
56 ldr lr, [r0, #%c[retaddr]]
57 ldr r4, [r0, #%c[extra]]
58 b %c[epilogue]
59 )" ::[retaddr] "i"(offsetof(__jmp_buf, sig_retaddr)),
60 [extra] "i"(offsetof(__jmp_buf, sig_extra)), [setjmp] "X"(setjmp),
61 [epilogue] "X"(sigsetjmp_epilogue)
62 : "r0", "r1", "r4");
63#endif
64}
65} // namespace LIBC_NAMESPACE_DECL
66

source code of libc/src/setjmp/arm/sigsetjmp.cpp