1 //===-- Implementation of setjmp ------------------------------------------===// 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/__support/common.h" 10 #include "src/__support/macros/config.h" 11 #include "src/setjmp/setjmp_impl.h" 12 13 namespace LIBC_NAMESPACE_DECL { 14 15 #if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1 16 17 [[gnu::naked, gnu::target("thumb")]] LLVM_LIBC_FUNCTION(int, setjmp, 18 (jmp_buf buf)) { 19 asm(R"( 20 # Store r4, r5, r6, and r7 into buf. 21 stmia r0!, {r4-r7} 22 23 # Store r8, r9, r10, r11, sp, and lr into buf. Thumb(1) doesn't support 24 # the high registers > r7 in stmia, so move them into lower GPRs first. 25 # Thumb(1) also doesn't support using str with sp or lr, move them 26 # together with the rest. 27 mov r1, r8 28 mov r2, r9 29 mov r3, r10 30 stmia r0!, {r1-r3} 31 32 mov r1, r11 33 mov r2, sp 34 mov r3, lr 35 stmia r0!, {r1-r3} 36 37 # Return 0. 38 movs r0, #0 39 bx lr)"); 40 } 41 42 #else // Thumb2 or ARM 43 44 // TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers 45 // (d0-d16) 46 // TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti 47 [[gnu::naked]] LLVM_LIBC_FUNCTION(int, setjmp, (jmp_buf buf)) { 48 asm(R"( 49 # While sp may appear in a register list for ARM mode, it may not for 50 # Thumb2 mode. Just move it into r12 then stm that, so that this code 51 # is portable between ARM and Thumb2. 52 mov r12, sp 53 54 # Store r4, r5, r6, r7, r8, r9, r10, r11, sp, and lr into buf. 55 stm r0, {r4-r12, lr} 56 57 # Return zero. 58 mov r0, #0 59 bx lr)"); 60 } 61 62 #endif 63 64 } // namespace LIBC_NAMESPACE_DECL 65