xref: /freebsd/lib/libc/arm/gen/setjmp.S (revision 96cdb0ab9d6d89d47c14f239933391a1f7d465c7)
18ed717deSAndrew Turner/*	$NetBSD: setjmp.S,v 1.14 2013/04/19 13:45:45 matt Exp $	*/
22357939bSOlivier Houchard
32357939bSOlivier Houchard/*
42357939bSOlivier Houchard * Copyright (c) 1997 Mark Brinicombe
52357939bSOlivier Houchard * All rights reserved.
62357939bSOlivier Houchard *
72357939bSOlivier Houchard * Redistribution and use in source and binary forms, with or without
82357939bSOlivier Houchard * modification, are permitted provided that the following conditions
92357939bSOlivier Houchard * are met:
102357939bSOlivier Houchard * 1. Redistributions of source code must retain the above copyright
112357939bSOlivier Houchard *    notice, this list of conditions and the following disclaimer.
122357939bSOlivier Houchard * 2. Redistributions in binary form must reproduce the above copyright
132357939bSOlivier Houchard *    notice, this list of conditions and the following disclaimer in the
142357939bSOlivier Houchard *    documentation and/or other materials provided with the distribution.
152357939bSOlivier Houchard * 3. All advertising materials mentioning features or use of this software
162357939bSOlivier Houchard *    must display the following acknowledgement:
172357939bSOlivier Houchard *	This product includes software developed by Mark Brinicombe
182357939bSOlivier Houchard * 4. Neither the name of the University nor the names of its contributors
192357939bSOlivier Houchard *    may be used to endorse or promote products derived from this software
202357939bSOlivier Houchard *    without specific prior written permission.
212357939bSOlivier Houchard *
222357939bSOlivier Houchard * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
232357939bSOlivier Houchard * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
242357939bSOlivier Houchard * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
252357939bSOlivier Houchard * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
262357939bSOlivier Houchard * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
272357939bSOlivier Houchard * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
282357939bSOlivier Houchard * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
292357939bSOlivier Houchard * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
302357939bSOlivier Houchard * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
312357939bSOlivier Houchard * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
322357939bSOlivier Houchard * SUCH DAMAGE.
332357939bSOlivier Houchard */
342357939bSOlivier Houchard
358ed717deSAndrew Turner#if !defined(__SOFTFP__) && !defined(__VFP_FP__) && !defined(__ARM_PCS)
368ed717deSAndrew Turner#error FPA is not supported anymore
378ed717deSAndrew Turner#endif
388ed717deSAndrew Turner
398e03dd59SAndrew Turner	.fpu	vfp
408e03dd59SAndrew Turner
412357939bSOlivier Houchard#include <machine/asm.h>
428ed717deSAndrew Turner#include <machine/setjmp.h>
438ed717deSAndrew Turner
442357939bSOlivier Houchard__FBSDID("$FreeBSD$");
458ed717deSAndrew Turner
462357939bSOlivier Houchard/*
472357939bSOlivier Houchard * C library -- setjmp, longjmp
482357939bSOlivier Houchard *
492357939bSOlivier Houchard *	longjmp(a,v)
502357939bSOlivier Houchard * will generate a "return(v)" from the last call to
512357939bSOlivier Houchard *	setjmp(a)
522357939bSOlivier Houchard * by restoring registers from the stack.
532357939bSOlivier Houchard * The previous signal state is restored.
542357939bSOlivier Houchard */
552357939bSOlivier Houchard
562357939bSOlivier HouchardENTRY(setjmp)
572357939bSOlivier Houchard	/* Block all signals and retrieve the old signal mask */
582357939bSOlivier Houchard	stmfd	sp!, {r0, r14}
598ed717deSAndrew Turner	add	r2, r0, #(_JB_SIGMASK * 4)	/* oset */
608ed717deSAndrew Turner	mov	r1, #0x00000000			/* set */
613d90a3cdSOlivier Houchard	mov	r0, #0x00000001			/* SIG_BLOCK */
623d90a3cdSOlivier Houchard	bl	PIC_SYM(_C_LABEL(sigprocmask), PLT)
632357939bSOlivier Houchard	ldmfd	sp!, {r0, r14}
642357939bSOlivier Houchard
652357939bSOlivier Houchard	ldr	r1, .Lsetjmp_magic
668e03dd59SAndrew Turner
678e03dd59SAndrew Turner	ldr	r2, .Lfpu_present
688e03dd59SAndrew Turner#ifdef PIC
698e03dd59SAndrew Turner	GOT_INIT(r3, .Lsetjmp_got, .Lsetjmp_gotinit)
708e03dd59SAndrew Turner	ldr	r2, [r2, r3]
718e03dd59SAndrew Turner#else
728e03dd59SAndrew Turner	ldr	r2, [r2]
738e03dd59SAndrew Turner#endif
748e03dd59SAndrew Turner	teq	r2, #0		/* do we have a FPU? */
758e03dd59SAndrew Turner	beq	1f		/*   no, don't save VFP registers */
768e03dd59SAndrew Turner
778e03dd59SAndrew Turner	orr	r1, r1, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP)
788e03dd59SAndrew Turner				/* change magic to VFP magic */
798e03dd59SAndrew Turner	add	r2, r0, #(_JB_REG_D8 * 4)
808e03dd59SAndrew Turner	vstmia	r2, {d8-d15}
818e03dd59SAndrew Turner	vmrs	r2, fpscr
828e03dd59SAndrew Turner	str	r2, [r0, #(_JB_REG_FPSCR * 4)]
838e03dd59SAndrew Turner1:
848e03dd59SAndrew Turner
858ed717deSAndrew Turner	str	r1, [r0]		/* store magic */
862357939bSOlivier Houchard
872357939bSOlivier Houchard	/* Store integer registers */
888ed717deSAndrew Turner	add	r0, r0, #(_JB_REG_R4 * 4)
892b6a6357SAndrew Turner#ifndef __thumb__
902357939bSOlivier Houchard        stmia	r0, {r4-r14}
912b6a6357SAndrew Turner#else
922b6a6357SAndrew Turner	stmia	r0, {r4-r12}
932b6a6357SAndrew Turner	str	r13, [r0, #((_JB_REG_R13 - _JB_REG_R4) * 4)]
942b6a6357SAndrew Turner	str	r14, [r0, #((_JB_REG_R14 - _JB_REG_R4) * 4)]
952b6a6357SAndrew Turner#endif
962357939bSOlivier Houchard        mov	r0, #0x00000000
9731489a9aSOlivier Houchard	RET
982357939bSOlivier Houchard
992357939bSOlivier Houchard.Lsetjmp_magic:
1002357939bSOlivier Houchard	.word	_JB_MAGIC_SETJMP
1018e03dd59SAndrew Turner	GOT_INITSYM(.Lsetjmp_got, .Lsetjmp_gotinit)
1028e03dd59SAndrew Turner.Lfpu_present:
1038e03dd59SAndrew Turner	.word	PIC_SYM(_libc_arm_fpu_present, GOTOFF)
104f2e71517SIan LeporeEND(setjmp)
1052357939bSOlivier Houchard
1062357939bSOlivier Houchard.weak _C_LABEL(longjmp)
1072357939bSOlivier Houchard.set _C_LABEL(longjmp), _C_LABEL(__longjmp)
1082357939bSOlivier HouchardENTRY(__longjmp)
1098ed717deSAndrew Turner	ldr	r2, [r0]
1108ed717deSAndrew Turner	ldr	ip, .Lsetjmp_magic
1118e03dd59SAndrew Turner	bic	r3, r2, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP)
1128e03dd59SAndrew Turner	teq	r3, ip
1138ed717deSAndrew Turner	bne	.Lbotch
1142357939bSOlivier Houchard
1158ed717deSAndrew Turner	/* Restore the signal mask. */
1168ed717deSAndrew Turner	stmfd	sp!, {r0-r2, r14}
1178ed717deSAndrew Turner	mov	r2, #0x00000000
1188ed717deSAndrew Turner	add	r1, r0, #(_JB_SIGMASK * 4)	/* Signal mask */
1193d90a3cdSOlivier Houchard	mov	r0, #3				/* SIG_SETMASK */
1203d90a3cdSOlivier Houchard	bl	PIC_SYM(_C_LABEL(sigprocmask), PLT)
1218ed717deSAndrew Turner	ldmfd	sp!, {r0-r2, r14}
1222357939bSOlivier Houchard
1238e03dd59SAndrew Turner	tst	r2, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP)
1248e03dd59SAndrew Turner						/* is this a VFP magic? */
1258e03dd59SAndrew Turner	beq	1f				/*   no, don't restore VFP */
1268e03dd59SAndrew Turner	add	ip, r0, #(_JB_REG_D8 * 4)
1278e03dd59SAndrew Turner	vldmia	ip, {d8-d15}
1288e03dd59SAndrew Turner	ldr	ip, [r0, #(_JB_REG_FPSCR * 4)]
1298e03dd59SAndrew Turner	vmsr	fpscr, ip
1308e03dd59SAndrew Turner1:
1318e03dd59SAndrew Turner
1328ed717deSAndrew Turner	add	r0, r0, #(_JB_REG_R4 * 4)
1332357939bSOlivier Houchard	/* Restore integer registers */
1342b6a6357SAndrew Turner#ifndef __thumb__
1352357939bSOlivier Houchard        ldmia	r0, {r4-r14}
1362b6a6357SAndrew Turner#else
1372b6a6357SAndrew Turner        ldmia	r0, {r4-r12}
1382b6a6357SAndrew Turner	ldr	r13, [r0, #((_JB_REG_R13 - _JB_REG_R4) * 4)]
1392b6a6357SAndrew Turner	ldr	r14, [r0, #((_JB_REG_R14 - _JB_REG_R4) * 4)]
1402b6a6357SAndrew Turner#endif
1412357939bSOlivier Houchard
1422357939bSOlivier Houchard	/* Validate sp and r14 */
1432357939bSOlivier Houchard	teq	sp, #0
1442b6a6357SAndrew Turner	it	ne
1452357939bSOlivier Houchard	teqne	r14, #0
1462b6a6357SAndrew Turner	it	eq
1478ed717deSAndrew Turner	beq	.Lbotch
1482357939bSOlivier Houchard
1492357939bSOlivier Houchard	/* Set return value */
1508ed717deSAndrew Turner	movs	r0, r1
1512b6a6357SAndrew Turner	it	eq
1522357939bSOlivier Houchard	moveq	r0, #0x00000001
15331489a9aSOlivier Houchard	RET
1542357939bSOlivier Houchard
1552357939bSOlivier Houchard	/* validation failed, die die die. */
1568ed717deSAndrew Turner.Lbotch:
1572357939bSOlivier Houchard	bl	PIC_SYM(_C_LABEL(longjmperror), PLT)
1582357939bSOlivier Houchard	bl	PIC_SYM(_C_LABEL(abort), PLT)
1592b6a6357SAndrew Turner1:	b	1b		/* Cannot get here */
160f2e71517SIan LeporeEND(__longjmp)
161*96cdb0abSKonstantin Belousov
162*96cdb0abSKonstantin Belousov	.section .note.GNU-stack,"",%progbits
163