_setjmp.S revision 271337
197403Sobrien/*	$NetBSD: _setjmp.S,v 1.12 2013/04/19 13:45:45 matt Exp $	*/
297403Sobrien
3169691Skan/*
497403Sobrien * Copyright (c) 1997 Mark Brinicombe
597403Sobrien * All rights reserved.
697403Sobrien *
797403Sobrien * Redistribution and use in source and binary forms, with or without
897403Sobrien * modification, are permitted provided that the following conditions
997403Sobrien * are met:
1097403Sobrien * 1. Redistributions of source code must retain the above copyright
1197403Sobrien *    notice, this list of conditions and the following disclaimer.
1297403Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1397403Sobrien *    notice, this list of conditions and the following disclaimer in the
1497403Sobrien *    documentation and/or other materials provided with the distribution.
1597403Sobrien * 3. All advertising materials mentioning features or use of this software
1697403Sobrien *    must display the following acknowledgement:
1797403Sobrien *	This product includes software developed by Mark Brinicombe
18169691Skan * 4. Neither the name of the University nor the names of its contributors
1997403Sobrien *    may be used to endorse or promote products derived from this software
2097403Sobrien *    without specific prior written permission.
2197403Sobrien *
2297403Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2397403Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2497403Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2597403Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2697403Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2797403Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2897403Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2997403Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3097403Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3197403Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3297403Sobrien * SUCH DAMAGE.
3397403Sobrien */
3497403Sobrien
3597403Sobrien#if !defined(__SOFTFP__) && !defined(__VFP_FP__) && !defined(__ARM_PCS)
3697403Sobrien#error FPA is not supported anymore
3797403Sobrien#endif
3897403Sobrien
3997403Sobrien#if defined(__ARM_EABI__) && !defined(_STANDALONE)
4097403Sobrien	.fpu	vfp
4197403Sobrien#endif
4297403Sobrien
4397403Sobrien#include <machine/asm.h>
4497403Sobrien#include <machine/setjmp.h>
4597403Sobrien
4697403Sobrien__FBSDID("$FreeBSD: stable/10/lib/libc/arm/gen/_setjmp.S 271337 2014-09-09 22:24:01Z ian $");
4797403Sobrien
4897403Sobrien/*
4997403Sobrien * C library -- _setjmp, _longjmp
5097403Sobrien *
5197403Sobrien *	_longjmp(a,v)
5297403Sobrien * will generate a "return(v)" from the last call to
5397403Sobrien *	_setjmp(a)
5497403Sobrien * by restoring registers from the stack.
5597403Sobrien * The previous signal state is NOT restored.
5697403Sobrien *
5797403Sobrien * Note: r0 is the return value
5897403Sobrien *       r1-r3,ip are scratch registers in functions
5997403Sobrien */
6097403Sobrien
61132720SkanENTRY(_setjmp)
62132720Skan	ldr	r1, .L_setjmp_magic
6397403Sobrien
64169691Skan#if defined(__ARM_EABI__) && !defined(_STANDALONE)
65169691Skan	ldr	r2, .Lfpu_present
6697403Sobrien#ifdef PIC
6797403Sobrien	GOT_INIT(r3, .L_setjmp_got, .L_setjmp_gotinit)
6897403Sobrien	ldr	r2, [r2, r3]
6997403Sobrien#else
7097403Sobrien	ldr	r2, [r2]
71132720Skan#endif
7297403Sobrien	teq	r2, #0		/* do we have a FPU? */
7397403Sobrien	beq	1f		/*   no, don't save VFP registers */
7497403Sobrien
7597403Sobrien	orr	r1, r1, #(_JB_MAGIC__SETJMP ^ _JB_MAGIC__SETJMP_VFP)
7697403Sobrien				/* change magic to VFP magic */
7797403Sobrien	add	r2, r0, #(_JB_REG_D8 * 4)
78132720Skan	vstmia	r2, {d8-d15}
79132720Skan	vmrs	r2, fpscr
80132720Skan	str	r2, [r0, #(_JB_REG_FPSCR * 4)]
8197403Sobrien1:
82132720Skan#endif /* __ARM_EABI__ */
8397403Sobrien
8497403Sobrien	str	r1, [r0]
85132720Skan
86132720Skan	add	r0, r0, #(_JB_REG_R4 * 4)
8797403Sobrien	/* Store integer registers */
88132720Skan        stmia	r0, {r4-r14}
8997403Sobrien
90132720Skan        mov	r0, #0x00000000
9197403Sobrien	RET
92132720SkanEND(_setjmp)
93132720Skan
9497403Sobrien.L_setjmp_magic:
9597403Sobrien	.word	_JB_MAGIC__SETJMP
9697403Sobrien#if defined(__ARM_EABI__) && !defined(_STANDALONE)
9797403Sobrien	GOT_INITSYM(.L_setjmp_got, .L_setjmp_gotinit)
9897403Sobrien.Lfpu_present:
99132720Skan	.word	PIC_SYM(_libc_arm_fpu_present, GOTOFF)
100132720Skan#endif /* __ARM_EABI__ */
10197403Sobrien
10297403SobrienWEAK_ALIAS(___longjmp, _longjmp)
10397403SobrienENTRY(_longjmp)
10497403Sobrien	ldr	r2, [r0]			/* get magic from jmp_buf */
10597403Sobrien	bic	r3, r2, #(_JB_MAGIC__SETJMP ^ _JB_MAGIC__SETJMP_VFP)
10697403Sobrien						/* ignore VFP-ness of magic */
10797403Sobrien	ldr	ip, .L_setjmp_magic		/* load magic */
108169691Skan	teq	ip, r3				/* magic correct? */
109169691Skan	bne	botch				/*   no, botch */
11097403Sobrien
111#if defined(__ARM_EABI__) && !defined(_STANDALONE)
112	teq	r3, r2				/* did magic change? */
113	beq	1f				/*   no, don't restore VFP */
114	add	ip, r0, #(_JB_REG_D8 * 4)
115	vldmia	ip, {d8-d15}
116	ldr	ip, [r0, #(_JB_REG_FPSCR * 4)]
117	vmsr	fpscr, ip
1181:
119#endif /* __ARM_EABI__ */
120
121	add	r0, r0, #(_JB_REG_R4 * 4)
122       	/* Restore integer registers */
123        ldmia	r0, {r4-r14}
124
125	/* Validate sp and r14 */
126	teq	sp, #0
127	teqne	r14, #0
128	beq	botch
129
130	/* Set return value */
131	movs	r0, r1
132	moveq	r0, #0x00000001
133	RET
134
135	/* validation failed, die die die. */
136botch:
137#if !defined(_STANDALONE)
138	bl	PIC_SYM(_C_LABEL(longjmperror), PLT)
139	bl	PIC_SYM(_C_LABEL(abort), PLT)
140	b	. - 8		/* Cannot get here */
141#else
142	b	.
143#endif
144END(_longjmp)
145