1*ababa08fSskrll/* $NetBSD: setjmp.S,v 1.19 2024/05/06 06:57:32 skrll Exp $ */ 218b395d0Schristos 318b395d0Schristos/* 418b395d0Schristos * Copyright (c) 1997 Mark Brinicombe 518b395d0Schristos * All rights reserved. 618b395d0Schristos * 718b395d0Schristos * Redistribution and use in source and binary forms, with or without 818b395d0Schristos * modification, are permitted provided that the following conditions 918b395d0Schristos * are met: 1018b395d0Schristos * 1. Redistributions of source code must retain the above copyright 1118b395d0Schristos * notice, this list of conditions and the following disclaimer. 1218b395d0Schristos * 2. Redistributions in binary form must reproduce the above copyright 1318b395d0Schristos * notice, this list of conditions and the following disclaimer in the 1418b395d0Schristos * documentation and/or other materials provided with the distribution. 1518b395d0Schristos * 3. All advertising materials mentioning features or use of this software 1618b395d0Schristos * must display the following acknowledgement: 1718b395d0Schristos * This product includes software developed by Mark Brinicombe 1818b395d0Schristos * 4. Neither the name of the University nor the names of its contributors 1918b395d0Schristos * may be used to endorse or promote products derived from this software 2018b395d0Schristos * without specific prior written permission. 2118b395d0Schristos * 2218b395d0Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2318b395d0Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2418b395d0Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2518b395d0Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2618b395d0Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2718b395d0Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2818b395d0Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2918b395d0Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3018b395d0Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3118b395d0Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3218b395d0Schristos * SUCH DAMAGE. 3318b395d0Schristos */ 3418b395d0Schristos 35b9421e37Smatt#if !defined(__SOFTFP__) && !defined(__VFP_FP__) && !defined(__ARM_PCS) 3660e85183Smatt#error FPA is not supported anymore 3760e85183Smatt#endif 3860e85183Smatt 392a674d4fSmatt#if defined(__ARM_EABI__) && !defined(__ARM_PCS_VFP) 4023ce88cdSmatt .fpu vfp 4123ce88cdSmatt#endif 4223ce88cdSmatt 4318b395d0Schristos#include <machine/asm.h> 4418b395d0Schristos#include <machine/setjmp.h> 4518b395d0Schristos 4618b395d0Schristos/* 4718b395d0Schristos * C library -- setjmp, longjmp 4818b395d0Schristos * 4918b395d0Schristos * longjmp(a,v) 5018b395d0Schristos * will generate a "return(v)" from the last call to 5118b395d0Schristos * setjmp(a) 5218b395d0Schristos * by restoring registers from the stack. 5318b395d0Schristos * The previous signal state is restored. 5418b395d0Schristos */ 5518b395d0Schristos 5618b395d0SchristosENTRY(__setjmp14) 5718b395d0Schristos /* Get the signal mask. */ 582a674d4fSmatt push {r0-r2, lr} 592a674d4fSmatt#if !defined(__thumb__) 602a674d4fSmatt adds r2, r0, #(_JB_SIGMASK * 4) 612a674d4fSmatt#else 622a674d4fSmatt mov r2, r0 632a674d4fSmatt adds r2, r2, #(_JB_SIGMASK * 4) 642a674d4fSmatt#endif 652a674d4fSmatt movs r1, #0 662a674d4fSmatt movs r0, #0 67d0dcd65cSjoerg bl PLT_SYM(_C_LABEL(__sigprocmask14)) 682a674d4fSmatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 692a674d4fSmatt pop {r0-r2, lr} 702a674d4fSmatt#else 712a674d4fSmatt pop {r0-r3} 722a674d4fSmatt mov lr, r3 732a674d4fSmatt#endif 7418b395d0Schristos 7518b395d0Schristos ldr r1, .Lsetjmp_magic 7618b395d0Schristos 772a674d4fSmatt#if defined(__ARM_EABI__) && (!defined(__thumb__) || defined(_ARM_ARCH_T2)) 7823ce88cdSmatt ldr r2, .Lfpu_present 794d12bfcdSjoerg#ifdef __PIC__ 802a674d4fSmatt add r2, r2, pc /* pc = &.LPIC0 */ 8123ce88cdSmatt#endif 822a674d4fSmatt ldr r2, [r2] 832a674d4fSmatt.LPIC0: 842a674d4fSmatt#if defined(__thumb__) && defined(_ARM_ARCH_T2) 852a674d4fSmatt cbz r2, 1f /* don't save if we don't have a FPU */ 862a674d4fSmatt#else 872a674d4fSmatt cmp r2, #0 /* do we have a FPU? */ 8823ce88cdSmatt beq 1f /* no, don't save VFP registers */ 892a674d4fSmatt#endif 9023ce88cdSmatt 912a674d4fSmatt orrs r1, r1, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP) 9223ce88cdSmatt /* change magic to VFP magic */ 932a674d4fSmatt adds r2, r0, #(_JB_REG_D8 * 4) 9423ce88cdSmatt vstmia r2, {d8-d15} 9523ce88cdSmatt vmrs r2, fpscr 9623ce88cdSmatt str r2, [r0, #(_JB_REG_FPSCR * 4)] 9723ce88cdSmatt1: 982a674d4fSmatt#endif /* __ARM_EABI__ && (!__thumb__ || _ARM_ARCH_T2) */ 9923ce88cdSmatt 10023ce88cdSmatt str r1, [r0] /* store magic */ 10160e85183Smatt 10218b395d0Schristos /* Store integer registers */ 1032a674d4fSmatt adds r0, r0, #(_JB_REG_R4 * 4) 1042a674d4fSmatt#if !defined(__thumb__) 1052a674d4fSmatt stmia r0!, {r4-lr} 1062a674d4fSmatt#else 1072a674d4fSmatt stmia r0!, {r4-r7} 1082a674d4fSmatt mov r2, r8 1092a674d4fSmatt mov r3, r9 1102a674d4fSmatt stmia r0!, {r2-r3} 1112a674d4fSmatt mov r2, r10 1122a674d4fSmatt mov r3, r11 1132a674d4fSmatt stmia r0!, {r2-r3} 1142a674d4fSmatt mov r2, sp 1152a674d4fSmatt mov r3, lr 1162a674d4fSmatt str r2, [r0, #4] 1172a674d4fSmatt str r3, [r0, #8] 1182a674d4fSmatt#endif 1192a674d4fSmatt movs r0, #0 12018b395d0Schristos RET 12118b395d0Schristos 1222a674d4fSmatt#if defined(__ARM_EABI__) && (!defined(__thumb__) || defined(_ARM_ARCH_T2)) 1232a674d4fSmatt .align 0 12423ce88cdSmatt.Lfpu_present: 1252a674d4fSmatt .word REL_SYM(_libc_arm_fpu_present, .LPIC0) 1262a674d4fSmatt#endif /* __ARM_EABI__ && (!__thumb__ || _ARM_ARCH_T2) */ 1272a674d4fSmattEND(__setjmp14) 12818b395d0Schristos 12918b395d0SchristosENTRY(__longjmp14) 1302a674d4fSmatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 13123ce88cdSmatt ldr r2, [r0] 13223ce88cdSmatt ldr ip, .Lsetjmp_magic 13323ce88cdSmatt bic r3, r2, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP) 1342a674d4fSmatt#else 1352a674d4fSmatt ldr r3, .Lsetjmp_magic 1362a674d4fSmatt mov ip, r3 1372a674d4fSmatt ldr r3, [r0] 1382a674d4fSmatt movs r2, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP) 1392a674d4fSmatt bics r3, r2 1402a674d4fSmatt /* r2 is not the magic but we don't need it since we can't do VFP */ 1412a674d4fSmatt#endif 1422a674d4fSmatt cmp r3, ip 1435ea8d4cfSskrll bne .Lbotch 14418b395d0Schristos 145*ababa08fSskrll /* Validate sp and lr */ 146*ababa08fSskrll ldr r2, [r0, #(_JB_REG_R13 * 4)] 147*ababa08fSskrll#if defined(__thumb__) && defined(_ARM_ARCH_T2) 148*ababa08fSskrll cbz r2, .Lbotch 149*ababa08fSskrll#else 150*ababa08fSskrll cmp r2, #0 151*ababa08fSskrll beq .Lbotch 152*ababa08fSskrll#endif 153*ababa08fSskrll 154*ababa08fSskrll ldr r3, [r0, #(_JB_REG_R14 * 4)] 155*ababa08fSskrll#if defined(__thumb__) && defined(_ARM_ARCH_T2) 156*ababa08fSskrll cbz r3, .Lbotch 157*ababa08fSskrll#else 158*ababa08fSskrll cmp r3, #0 159*ababa08fSskrll beq .Lbotch 160*ababa08fSskrll#endif 161*ababa08fSskrll mov sp, r2 162*ababa08fSskrll mov lr, r3 163*ababa08fSskrll 16418b395d0Schristos /* Restore the signal mask. */ 1652a674d4fSmatt push {r0-r2, lr} 1662a674d4fSmatt movs r2, #0 1672a674d4fSmatt#if !defined(__thumb__) 1682a674d4fSmatt adds r1, r0, #(_JB_SIGMASK * 4) 1692a674d4fSmatt#else 1702a674d4fSmatt mov r1, r0 1712a674d4fSmatt adds r1, r1, #(_JB_SIGMASK * 4) 1722a674d4fSmatt#endif 1732a674d4fSmatt movs r0, #3 /* SIG_SETMASK */ 174d0dcd65cSjoerg bl PLT_SYM(_C_LABEL(__sigprocmask14)) 1752a674d4fSmatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 1762a674d4fSmatt pop {r0-r2, lr} 1772a674d4fSmatt#else 1782a674d4fSmatt pop {r0-r3} 1792a674d4fSmatt mov lr, r3 1802a674d4fSmatt#endif 18118b395d0Schristos 1822a674d4fSmatt#if defined(__ARM_EABI__) && (!defined(__thumb__) || defined(_ARM_ARCH_T2)) 18323ce88cdSmatt tst r2, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP) 18423ce88cdSmatt /* is this a VFP magic? */ 18523ce88cdSmatt beq 1f /* no, don't restore VFP */ 1862a674d4fSmatt adds r2, r0, #(_JB_REG_D8 * 4) 1872a674d4fSmatt vldmia r2, {d8-d15} 1882a674d4fSmatt ldr r2, [r0, #(_JB_REG_FPSCR * 4)] 1892a674d4fSmatt vmsr fpscr, r2 19023ce88cdSmatt1: 1912a674d4fSmatt#endif /* __ARM_EABI__ && (!__thumb__ || _ARM_ARCH_T2) */ 19260e85183Smatt 1932a674d4fSmatt adds r0, r0, #(_JB_REG_R4 * 4) 19418b395d0Schristos /* Restore integer registers */ 1952a674d4fSmatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2) 1962a674d4fSmatt ldmia r0!, {r4-r12} 1972a674d4fSmatt#else 1982a674d4fSmatt ldmia r0!, {r4-r7} 1992a674d4fSmatt ldmia r0!, {r2-r3} 2002a674d4fSmatt mov r8, r2 2012a674d4fSmatt mov r9, r3 2022a674d4fSmatt ldmia r0!, {r2-r3} 2032a674d4fSmatt mov r10, r2 2042a674d4fSmatt mov r11, r3 2052a674d4fSmatt adds r0, r0, #4 /* skip ip(r12) */ 2062a674d4fSmatt#endif 20718b395d0Schristos 20818b395d0Schristos /* Set return value */ 20992551f87Smatt movs r0, r1 2102a674d4fSmatt#if !defined(__thumb__) 2112a674d4fSmatt moveq r0, #1 2122a674d4fSmatt#else 2132a674d4fSmatt bne 1f 2142a674d4fSmatt movs r0, #1 2152a674d4fSmatt1: 2162a674d4fSmatt#endif 21718b395d0Schristos RET 21818b395d0Schristos 21918b395d0Schristos /* validation failed, die die die. */ 22018b395d0Schristos.Lbotch: 221d0dcd65cSjoerg bl PLT_SYM(_C_LABEL(longjmperror)) 222d0dcd65cSjoerg bl PLT_SYM(_C_LABEL(abort)) 2232a674d4fSmatt1: b 1b /* Cannot get here */ 2242a674d4fSmatt 2252a674d4fSmatt .align 0 2262a674d4fSmatt.Lsetjmp_magic: 2272a674d4fSmatt .word _JB_MAGIC_SETJMP 2282a674d4fSmattEND(__longjmp14) 229