xref: /netbsd-src/lib/libc/arch/arm/gen/setjmp.S (revision ababa08f7df689c506f61871a408d771276359ae)
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