xref: /freebsd/lib/libc/arm/gen/setjmp.S (revision b8a496dfb6df7b86e014d0d4476cd75850e060c1)
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>
432357939bSOlivier Houchard/*
442357939bSOlivier Houchard * C library -- setjmp, longjmp
452357939bSOlivier Houchard *
462357939bSOlivier Houchard *	longjmp(a,v)
472357939bSOlivier Houchard * will generate a "return(v)" from the last call to
482357939bSOlivier Houchard *	setjmp(a)
492357939bSOlivier Houchard * by restoring registers from the stack.
502357939bSOlivier Houchard * The previous signal state is restored.
512357939bSOlivier Houchard */
522357939bSOlivier Houchard
532357939bSOlivier HouchardENTRY(setjmp)
542357939bSOlivier Houchard	/* Block all signals and retrieve the old signal mask */
552357939bSOlivier Houchard	stmfd	sp!, {r0, r14}
568ed717deSAndrew Turner	add	r2, r0, #(_JB_SIGMASK * 4)	/* oset */
578ed717deSAndrew Turner	mov	r1, #0x00000000			/* set */
583d90a3cdSOlivier Houchard	mov	r0, #0x00000001			/* SIG_BLOCK */
593d90a3cdSOlivier Houchard	bl	PIC_SYM(_C_LABEL(sigprocmask), PLT)
602357939bSOlivier Houchard	ldmfd	sp!, {r0, r14}
612357939bSOlivier Houchard
622357939bSOlivier Houchard	ldr	r1, .Lsetjmp_magic
638e03dd59SAndrew Turner
64*b8a496dfSAndrew Turner#if !defined(SOFTFLOAT_FOR_GCC)
658e03dd59SAndrew Turner	add	r2, r0, #(_JB_REG_D8 * 4)
668e03dd59SAndrew Turner	vstmia	r2, {d8-d15}
678e03dd59SAndrew Turner	vmrs	r2, fpscr
688e03dd59SAndrew Turner	str	r2, [r0, #(_JB_REG_FPSCR * 4)]
693ab06e30SAndrew Turner#endif
708e03dd59SAndrew Turner
718ed717deSAndrew Turner	str	r1, [r0]		/* store magic */
722357939bSOlivier Houchard
732357939bSOlivier Houchard	/* Store integer registers */
748ed717deSAndrew Turner	add	r0, r0, #(_JB_REG_R4 * 4)
752b6a6357SAndrew Turner#ifndef __thumb__
762357939bSOlivier Houchard        stmia	r0, {r4-r14}
772b6a6357SAndrew Turner#else
782b6a6357SAndrew Turner	stmia	r0, {r4-r12}
792b6a6357SAndrew Turner	str	r13, [r0, #((_JB_REG_R13 - _JB_REG_R4) * 4)]
802b6a6357SAndrew Turner	str	r14, [r0, #((_JB_REG_R14 - _JB_REG_R4) * 4)]
812b6a6357SAndrew Turner#endif
822357939bSOlivier Houchard        mov	r0, #0x00000000
8331489a9aSOlivier Houchard	RET
842357939bSOlivier Houchard
852357939bSOlivier Houchard.Lsetjmp_magic:
862357939bSOlivier Houchard	.word	_JB_MAGIC_SETJMP
87f2e71517SIan LeporeEND(setjmp)
882357939bSOlivier Houchard
892357939bSOlivier Houchard.weak _C_LABEL(longjmp)
902357939bSOlivier Houchard.set _C_LABEL(longjmp), _C_LABEL(__longjmp)
912357939bSOlivier HouchardENTRY(__longjmp)
928ed717deSAndrew Turner	ldr	r2, [r0]
938ed717deSAndrew Turner	ldr	ip, .Lsetjmp_magic
943ab06e30SAndrew Turner	teq	r2, ip
958ed717deSAndrew Turner	bne	.Lbotch
962357939bSOlivier Houchard
978ed717deSAndrew Turner	/* Restore the signal mask. */
988ed717deSAndrew Turner	stmfd	sp!, {r0-r2, r14}
998ed717deSAndrew Turner	mov	r2, #0x00000000
1008ed717deSAndrew Turner	add	r1, r0, #(_JB_SIGMASK * 4)	/* Signal mask */
1013d90a3cdSOlivier Houchard	mov	r0, #3				/* SIG_SETMASK */
1023d90a3cdSOlivier Houchard	bl	PIC_SYM(_C_LABEL(sigprocmask), PLT)
1038ed717deSAndrew Turner	ldmfd	sp!, {r0-r2, r14}
1042357939bSOlivier Houchard
105*b8a496dfSAndrew Turner#if !defined(SOFTFLOAT_FOR_GCC)
1068e03dd59SAndrew Turner	add	ip, r0, #(_JB_REG_D8 * 4)
1078e03dd59SAndrew Turner	vldmia	ip, {d8-d15}
1088e03dd59SAndrew Turner	ldr	ip, [r0, #(_JB_REG_FPSCR * 4)]
1098e03dd59SAndrew Turner	vmsr	fpscr, ip
1103ab06e30SAndrew Turner#endif
1118e03dd59SAndrew Turner
1128ed717deSAndrew Turner	add	r0, r0, #(_JB_REG_R4 * 4)
1132357939bSOlivier Houchard	/* Restore integer registers */
1142b6a6357SAndrew Turner#ifndef __thumb__
1152357939bSOlivier Houchard        ldmia	r0, {r4-r14}
1162b6a6357SAndrew Turner#else
1172b6a6357SAndrew Turner        ldmia	r0, {r4-r12}
1182b6a6357SAndrew Turner	ldr	r13, [r0, #((_JB_REG_R13 - _JB_REG_R4) * 4)]
1192b6a6357SAndrew Turner	ldr	r14, [r0, #((_JB_REG_R14 - _JB_REG_R4) * 4)]
1202b6a6357SAndrew Turner#endif
1212357939bSOlivier Houchard
1222357939bSOlivier Houchard	/* Validate sp and r14 */
1232357939bSOlivier Houchard	teq	sp, #0
1242b6a6357SAndrew Turner	it	ne
1252357939bSOlivier Houchard	teqne	r14, #0
1262b6a6357SAndrew Turner	it	eq
1278ed717deSAndrew Turner	beq	.Lbotch
1282357939bSOlivier Houchard
1292357939bSOlivier Houchard	/* Set return value */
1308ed717deSAndrew Turner	movs	r0, r1
1312b6a6357SAndrew Turner	it	eq
1322357939bSOlivier Houchard	moveq	r0, #0x00000001
13331489a9aSOlivier Houchard	RET
1342357939bSOlivier Houchard
1352357939bSOlivier Houchard	/* validation failed, die die die. */
1368ed717deSAndrew Turner.Lbotch:
1372357939bSOlivier Houchard	bl	PIC_SYM(_C_LABEL(longjmperror), PLT)
1382357939bSOlivier Houchard	bl	PIC_SYM(_C_LABEL(abort), PLT)
1392b6a6357SAndrew Turner1:	b	1b		/* Cannot get here */
140f2e71517SIan LeporeEND(__longjmp)
14196cdb0abSKonstantin Belousov
14296cdb0abSKonstantin Belousov	.section .note.GNU-stack,"",%progbits
143