1/* longjmp for ARM. 2 Copyright (C) 1997-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library. If not, see 17 <https://www.gnu.org/licenses/>. */ 18 19#include <sysdep.h> 20#include <stap-probe.h> 21#include <bits/setjmp.h> 22#include <rtld-global-offsets.h> 23#include <arm-features.h> 24 25/* __longjmp(jmpbuf, val) */ 26 27ENTRY (__longjmp) 28 mov ip, r0 29 30#ifdef CHECK_SP 31 ldr r4, [ip] /* jmpbuf's sp */ 32 cfi_undefined (r4) 33#ifdef PTR_DEMANGLE 34 PTR_DEMANGLE (r4, r4, a3, a4) 35#endif 36 CHECK_SP (r4) 37#endif 38 39#ifdef PTR_DEMANGLE 40 ldr a4, [ip], #4 41 PTR_DEMANGLE (a4, a4, a3, r4) 42 cfi_undefined (r4) 43 ldr r4, [ip], #4 44 PTR_DEMANGLE2 (r4, r4, a3) 45#else 46 ldr a4, [ip], #4 47 ldr r4, [ip], #4 48 cfi_undefined (r4) 49#endif 50 /* longjmp probe expects longjmp first argument (4@r0), second 51 argument (-4@r1), and target address (4@r4), respectively. */ 52 LIBC_PROBE (longjmp, 3, 4@r0, -4@r1, 4@r4) 53 mov sp, a4 54 mov lr, r4 55 ldmia ip!, JMP_BUF_REGLIST 56 cfi_restore (v1) 57 cfi_restore (v2) 58 cfi_restore (v3) 59 cfi_restore (v4) 60 cfi_restore (v5) 61 cfi_restore (v6) 62 cfi_restore (sl) 63 cfi_restore (fp) 64 cfi_restore (sp) 65 cfi_restore (lr) 66 67#if !defined ARM_ASSUME_NO_IWMMXT || defined __SOFTFP__ 68# define NEED_HWCAP 1 69#endif 70 71#ifdef NEED_HWCAP 72# if IS_IN (rtld) 73 LDST_PCREL (ldr, a4, a3, \ 74 C_SYMBOL_NAME(_rtld_local_ro) \ 75 + RTLD_GLOBAL_RO_DL_HWCAP_OFFSET) 76# else 77# ifdef SHARED 78 LDR_GLOBAL (a4, a3, C_SYMBOL_NAME(_rtld_global_ro), \ 79 RTLD_GLOBAL_RO_DL_HWCAP_OFFSET) 80# else 81 LDR_GLOBAL (a4, a3, C_SYMBOL_NAME(_dl_hwcap), 0) 82# endif 83# endif 84#endif 85 86#ifdef __SOFTFP__ 87 tst a4, #HWCAP_ARM_VFP 88 beq .Lno_vfp 89#endif 90 91 /* Restore the VFP registers. */ 92 /* Following instruction is vldmia ip!, {d8-d15}. */ 93 ldc p11, cr8, [r12], #64 94.Lno_vfp: 95 96#ifndef ARM_ASSUME_NO_IWMMXT 97 tst a4, #HWCAP_ARM_IWMMXT 98 beq .Lno_iwmmxt 99 100 /* Restore the call-preserved iWMMXt registers. */ 101 /* Following instructions are wldrd wr10, [ip], #8 (etc.) */ 102 ldcl p1, cr10, [r12], #8 103 ldcl p1, cr11, [r12], #8 104 ldcl p1, cr12, [r12], #8 105 ldcl p1, cr13, [r12], #8 106 ldcl p1, cr14, [r12], #8 107 ldcl p1, cr15, [r12], #8 108.Lno_iwmmxt: 109#endif 110 111 /* longjmp_target probe expects longjmp first argument (4@r0), second 112 argument (-4@r1), and target address (4@r14), respectively. */ 113 LIBC_PROBE (longjmp_target, 3, 4@r0, -4@r1, 4@r14) 114 115 movs r0, r1 /* get the return value in place */ 116 it eq 117 moveq r0, #1 /* can't let setjmp() return zero! */ 118 119 DO_RET(lr) 120 121END (__longjmp) 122