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 | |
16 | #if __riscv_xlen == 64 |
17 | #define STORE(A, B, C) "sd " #A ", %c[" #B "](" #C ")\n\t" |
18 | #define LOAD(A, B, C) "ld " #A ", %c[" #B "](" #C ")\n\t" |
19 | #elif __riscv_xlen == 32 |
20 | #define STORE(A, B, C) "sw " #A ", %c[" #B "](" #C ")\n\t" |
21 | #define LOAD(A, B, C) "lw " #A ", %c[" #B "](" #C ")\n\t" |
22 | #else |
23 | #error "Unsupported RISC-V architecture" |
24 | #endif |
25 | |
26 | namespace LIBC_NAMESPACE_DECL { |
27 | [[gnu::naked]] |
28 | LLVM_LIBC_FUNCTION(int, sigsetjmp, (sigjmp_buf, int)) { |
29 | // clang-format off |
30 | asm("beqz a1, .Lnosave\n\t" |
31 | STORE(ra, retaddr, a0) |
32 | STORE(s0, extra, a0) |
33 | "mv s0, a0\n\t" |
34 | "call %c[setjmp]\n\t" |
35 | "mv a1, a0\n\t" |
36 | "mv a0, s0\n\t" |
37 | LOAD(s0, extra, a0) |
38 | LOAD(ra, retaddr, a0) |
39 | "tail %c[epilogue]\n" |
40 | ".Lnosave:\n\t" |
41 | "tail %c[setjmp]" |
42 | // clang-format on |
43 | ::[retaddr] "i" (offsetof(__jmp_buf, sig_retaddr)), |
44 | [extra] "i" (offsetof(__jmp_buf, sig_extra)), [setjmp] "i" (setjmp), |
45 | [epilogue] "i" (sigsetjmp_epilogue) |
46 | : "a0" , "a1" , "s0" ); |
47 | } |
48 | |
49 | } // namespace LIBC_NAMESPACE_DECL |
50 | |