1*71db0c75SAndroid Build Coastguard Worker 2*71db0c75SAndroid Build Coastguard Worker //===-- Implementation of longjmp -----------------------------------------===// 3*71db0c75SAndroid Build Coastguard Worker // 4*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information. 6*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*71db0c75SAndroid Build Coastguard Worker // 8*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*71db0c75SAndroid Build Coastguard Worker 10*71db0c75SAndroid Build Coastguard Worker #include "src/setjmp/longjmp.h" 11*71db0c75SAndroid Build Coastguard Worker #include "src/__support/common.h" 12*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h" 13*71db0c75SAndroid Build Coastguard Worker 14*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL { 15*71db0c75SAndroid Build Coastguard Worker 16*71db0c75SAndroid Build Coastguard Worker #if defined(__thumb__) && __ARM_ARCH_ISA_THUMB == 1 17*71db0c75SAndroid Build Coastguard Worker 18*71db0c75SAndroid Build Coastguard Worker [[gnu::naked, gnu::target("thumb")]] LLVM_LIBC_FUNCTION(void, longjmp, 19*71db0c75SAndroid Build Coastguard Worker (jmp_buf buf, 20*71db0c75SAndroid Build Coastguard Worker int val)) { 21*71db0c75SAndroid Build Coastguard Worker asm(R"( 22*71db0c75SAndroid Build Coastguard Worker # Reload r4, r5, r6, r7. 23*71db0c75SAndroid Build Coastguard Worker ldmia r0!, {r4-r7} 24*71db0c75SAndroid Build Coastguard Worker 25*71db0c75SAndroid Build Coastguard Worker # Reload r8, r9. They cannot appear in register lists so load them 26*71db0c75SAndroid Build Coastguard Worker # into the lower registers, then move them into place. 27*71db0c75SAndroid Build Coastguard Worker ldmia r0!, {r2-r3} 28*71db0c75SAndroid Build Coastguard Worker mov r8, r2 29*71db0c75SAndroid Build Coastguard Worker mov r9, r3 30*71db0c75SAndroid Build Coastguard Worker 31*71db0c75SAndroid Build Coastguard Worker # Reload r10, r11. They cannot appear in register lists so load them 32*71db0c75SAndroid Build Coastguard Worker # into the lower registers, then move them into place. 33*71db0c75SAndroid Build Coastguard Worker ldmia r0!, {r2-r3} 34*71db0c75SAndroid Build Coastguard Worker mov r10, r2 35*71db0c75SAndroid Build Coastguard Worker mov r11, r3 36*71db0c75SAndroid Build Coastguard Worker 37*71db0c75SAndroid Build Coastguard Worker # Reload sp, lr. They cannot appear in register lists so load them 38*71db0c75SAndroid Build Coastguard Worker # into the lower registers, then move them into place. 39*71db0c75SAndroid Build Coastguard Worker ldmia r0!, {r2-r3} 40*71db0c75SAndroid Build Coastguard Worker mov sp, r2 41*71db0c75SAndroid Build Coastguard Worker mov lr, r3 42*71db0c75SAndroid Build Coastguard Worker 43*71db0c75SAndroid Build Coastguard Worker # return val ?: 1; 44*71db0c75SAndroid Build Coastguard Worker movs r0, r1 45*71db0c75SAndroid Build Coastguard Worker bne .Lret_val 46*71db0c75SAndroid Build Coastguard Worker movs r0, #1 47*71db0c75SAndroid Build Coastguard Worker 48*71db0c75SAndroid Build Coastguard Worker .Lret_val: 49*71db0c75SAndroid Build Coastguard Worker bx lr)"); 50*71db0c75SAndroid Build Coastguard Worker } 51*71db0c75SAndroid Build Coastguard Worker 52*71db0c75SAndroid Build Coastguard Worker #else // Thumb2 or ARM 53*71db0c75SAndroid Build Coastguard Worker 54*71db0c75SAndroid Build Coastguard Worker // TODO(https://github.com/llvm/llvm-project/issues/94061): fp registers 55*71db0c75SAndroid Build Coastguard Worker // (d0-d16) 56*71db0c75SAndroid Build Coastguard Worker // TODO(https://github.com/llvm/llvm-project/issues/94062): pac+bti 57*71db0c75SAndroid Build Coastguard Worker [[gnu::naked]] LLVM_LIBC_FUNCTION(void, longjmp, (jmp_buf buf, int val)) { 58*71db0c75SAndroid Build Coastguard Worker asm(R"( 59*71db0c75SAndroid Build Coastguard Worker # While sp may appear in a register list for ARM mode, it may not for 60*71db0c75SAndroid Build Coastguard Worker # Thumb2 mode. Just load the previous value of sp into r12 then move it 61*71db0c75SAndroid Build Coastguard Worker # into sp, so that this code is portable between ARM and Thumb2. 62*71db0c75SAndroid Build Coastguard Worker 63*71db0c75SAndroid Build Coastguard Worker ldm r0, {r4-r12, lr} 64*71db0c75SAndroid Build Coastguard Worker mov sp, r12 65*71db0c75SAndroid Build Coastguard Worker 66*71db0c75SAndroid Build Coastguard Worker # return val ?: 1; 67*71db0c75SAndroid Build Coastguard Worker movs r0, r1 68*71db0c75SAndroid Build Coastguard Worker it eq 69*71db0c75SAndroid Build Coastguard Worker moveq r0, #1 70*71db0c75SAndroid Build Coastguard Worker bx lr)"); 71*71db0c75SAndroid Build Coastguard Worker } 72*71db0c75SAndroid Build Coastguard Worker 73*71db0c75SAndroid Build Coastguard Worker #endif 74*71db0c75SAndroid Build Coastguard Worker 75*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL 76