65 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "src/__support/common.h"10#include "src/__support/macros/config.h"11#include "src/setjmp/setjmp_impl.h"12 13namespace LIBC_NAMESPACE_DECL {14 15#if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 116 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 support24 # 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 them26 # together with the rest.27 mov r1, r828 mov r2, r929 mov r3, r1030 stmia r0!, {r1-r3}31 32 mov r1, r1133 mov r2, sp34 mov r3, lr35 stmia r0!, {r1-r3}36 37 # Return 0.38 movs r0, #039 bx lr)");40}41 42#else // Thumb2 or ARM43 44// TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers45// (d0-d16)46// TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti47[[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 for50 # Thumb2 mode. Just move it into r12 then stm that, so that this code51 # is portable between ARM and Thumb2.52 mov r12, sp53 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, #059 bx lr)");60}61 62#endif63 64} // namespace LIBC_NAMESPACE_DECL65