xref: /optee_os/lib/libutils/isoc/arch/arm/setjmp_a32.S (revision 0c81fcd6798bb5fa251f130ec7657e128c17cc46)
1*0c81fcd6SJens Wiklander/*
2*0c81fcd6SJens Wiklander * Copyright (c) 1994-2009  Red Hat, Inc.
3*0c81fcd6SJens Wiklander * All rights reserved.
4*0c81fcd6SJens Wiklander *
5*0c81fcd6SJens Wiklander * Redistribution and use in source and binary forms, with or without
6*0c81fcd6SJens Wiklander * modification, are permitted provided that the following conditions are met:
7*0c81fcd6SJens Wiklander *
8*0c81fcd6SJens Wiklander * 1. Redistributions of source code must retain the above copyright notice,
9*0c81fcd6SJens Wiklander * this list of conditions and the following disclaimer.
10*0c81fcd6SJens Wiklander *
11*0c81fcd6SJens Wiklander * 2. Redistributions in binary form must reproduce the above copyright notice,
12*0c81fcd6SJens Wiklander * this list of conditions and the following disclaimer in the documentation
13*0c81fcd6SJens Wiklander * and/or other materials provided with the distribution.
14*0c81fcd6SJens Wiklander *
15*0c81fcd6SJens Wiklander * 3. Neither the name of the copyright holder nor the names of its
16*0c81fcd6SJens Wiklander * contributors may be used to endorse or promote products derived from this
17*0c81fcd6SJens Wiklander * software without specific prior written permission.
18*0c81fcd6SJens Wiklander *
19*0c81fcd6SJens Wiklander * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20*0c81fcd6SJens Wiklander * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*0c81fcd6SJens Wiklander * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*0c81fcd6SJens Wiklander * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23*0c81fcd6SJens Wiklander * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*0c81fcd6SJens Wiklander * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*0c81fcd6SJens Wiklander * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*0c81fcd6SJens Wiklander * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*0c81fcd6SJens Wiklander * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*0c81fcd6SJens Wiklander * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*0c81fcd6SJens Wiklander * POSSIBILITY OF SUCH DAMAGE.
30*0c81fcd6SJens Wiklander */
31*0c81fcd6SJens Wiklander/* This is a simple version of setjmp and longjmp.
32*0c81fcd6SJens Wiklander
33*0c81fcd6SJens Wiklander   Nick Clifton, Cygnus Solutions, 13 June 1997.  */
34*0c81fcd6SJens Wiklander
35*0c81fcd6SJens Wiklander/* ANSI concatenation macros.  */
36*0c81fcd6SJens Wiklander#define CONCAT(a, b)  CONCAT2(a, b)
37*0c81fcd6SJens Wiklander#define CONCAT2(a, b) a##b
38*0c81fcd6SJens Wiklander
39*0c81fcd6SJens Wiklander#ifndef __USER_LABEL_PREFIX__
40*0c81fcd6SJens Wiklander#error  __USER_LABEL_PREFIX__ not defined
41*0c81fcd6SJens Wiklander#endif
42*0c81fcd6SJens Wiklander
43*0c81fcd6SJens Wiklander#define SYM(x) CONCAT (__USER_LABEL_PREFIX__, x)
44*0c81fcd6SJens Wiklander
45*0c81fcd6SJens Wiklander#ifdef __ELF__
46*0c81fcd6SJens Wiklander#define TYPE(x) .type SYM(x),function
47*0c81fcd6SJens Wiklander#define SIZE(x) .size SYM(x), . - SYM(x)
48*0c81fcd6SJens Wiklander#else
49*0c81fcd6SJens Wiklander#define TYPE(x)
50*0c81fcd6SJens Wiklander#define SIZE(x)
51*0c81fcd6SJens Wiklander#endif
52*0c81fcd6SJens Wiklander
53*0c81fcd6SJens Wiklander/* Arm/Thumb interworking support:
54*0c81fcd6SJens Wiklander
55*0c81fcd6SJens Wiklander   The interworking scheme expects functions to use a BX instruction
56*0c81fcd6SJens Wiklander   to return control to their parent.  Since we need this code to work
57*0c81fcd6SJens Wiklander   in both interworked and non-interworked environments as well as with
58*0c81fcd6SJens Wiklander   older processors which do not have the BX instruction we do the
59*0c81fcd6SJens Wiklander   following:
60*0c81fcd6SJens Wiklander	Test the return address.
61*0c81fcd6SJens Wiklander	If the bottom bit is clear perform an "old style" function exit.
62*0c81fcd6SJens Wiklander	(We know that we are in ARM mode and returning to an ARM mode caller).
63*0c81fcd6SJens Wiklander	Otherwise use the BX instruction to perform the function exit.
64*0c81fcd6SJens Wiklander
65*0c81fcd6SJens Wiklander   We know that we will never attempt to perform the BX instruction on
66*0c81fcd6SJens Wiklander   an older processor, because that kind of processor will never be
67*0c81fcd6SJens Wiklander   interworked, and a return address with the bottom bit set will never
68*0c81fcd6SJens Wiklander   be generated.
69*0c81fcd6SJens Wiklander
70*0c81fcd6SJens Wiklander   In addition, we do not actually assemble the BX instruction as this would
71*0c81fcd6SJens Wiklander   require us to tell the assembler that the processor is an ARM7TDMI and
72*0c81fcd6SJens Wiklander   it would store this information in the binary.  We want this binary to be
73*0c81fcd6SJens Wiklander   able to be linked with binaries compiled for older processors however, so
74*0c81fcd6SJens Wiklander   we do not want such information stored there.
75*0c81fcd6SJens Wiklander
76*0c81fcd6SJens Wiklander   If we are running using the APCS-26 convention however, then we never
77*0c81fcd6SJens Wiklander   test the bottom bit, because this is part of the processor status.
78*0c81fcd6SJens Wiklander   Instead we just do a normal return, since we know that we cannot be
79*0c81fcd6SJens Wiklander   returning to a Thumb caller - the Thumb does not support APCS-26.
80*0c81fcd6SJens Wiklander
81*0c81fcd6SJens Wiklander   Function entry is much simpler.  If we are compiling for the Thumb we
82*0c81fcd6SJens Wiklander   just switch into ARM mode and then drop through into the rest of the
83*0c81fcd6SJens Wiklander   function.  The function exit code will take care of the restore to
84*0c81fcd6SJens Wiklander   Thumb mode.
85*0c81fcd6SJens Wiklander
86*0c81fcd6SJens Wiklander   For Thumb-2 do everything in Thumb mode.  */
87*0c81fcd6SJens Wiklander
88*0c81fcd6SJens Wiklander#if defined(__ARM_ARCH_6M__)
89*0c81fcd6SJens Wiklander/* ARMv6-M has to be implemented in Thumb mode.  */
90*0c81fcd6SJens Wiklander
91*0c81fcd6SJens Wiklander.thumb
92*0c81fcd6SJens Wiklander.thumb_func
93*0c81fcd6SJens Wiklander	.globl SYM (setjmp)
94*0c81fcd6SJens Wiklander	TYPE (setjmp)
95*0c81fcd6SJens WiklanderSYM (setjmp):
96*0c81fcd6SJens Wiklander	/* Save registers in jump buffer.  */
97*0c81fcd6SJens Wiklander	stmia	r0!, {r4, r5, r6, r7}
98*0c81fcd6SJens Wiklander	mov	r1, r8
99*0c81fcd6SJens Wiklander	mov	r2, r9
100*0c81fcd6SJens Wiklander	mov	r3, r10
101*0c81fcd6SJens Wiklander	mov	r4, fp
102*0c81fcd6SJens Wiklander	mov	r5, sp
103*0c81fcd6SJens Wiklander	mov	r6, lr
104*0c81fcd6SJens Wiklander	stmia	r0!, {r1, r2, r3, r4, r5, r6}
105*0c81fcd6SJens Wiklander	sub	r0, r0, #40
106*0c81fcd6SJens Wiklander	/* Restore callee-saved low regs.  */
107*0c81fcd6SJens Wiklander	ldmia	r0!, {r4, r5, r6, r7}
108*0c81fcd6SJens Wiklander	/* Return zero.  */
109*0c81fcd6SJens Wiklander	mov	r0, #0
110*0c81fcd6SJens Wiklander	bx lr
111*0c81fcd6SJens Wiklander
112*0c81fcd6SJens Wiklander.thumb_func
113*0c81fcd6SJens Wiklander	.globl SYM (longjmp)
114*0c81fcd6SJens Wiklander	TYPE (longjmp)
115*0c81fcd6SJens WiklanderSYM (longjmp):
116*0c81fcd6SJens Wiklander	/* Restore High regs.  */
117*0c81fcd6SJens Wiklander	add	r0, r0, #16
118*0c81fcd6SJens Wiklander	ldmia	r0!, {r2, r3, r4, r5, r6}
119*0c81fcd6SJens Wiklander	mov	r8, r2
120*0c81fcd6SJens Wiklander	mov	r9, r3
121*0c81fcd6SJens Wiklander	mov	r10, r4
122*0c81fcd6SJens Wiklander	mov	fp, r5
123*0c81fcd6SJens Wiklander	mov	sp, r6
124*0c81fcd6SJens Wiklander	ldmia	r0!, {r3} /* lr */
125*0c81fcd6SJens Wiklander	/* Restore low regs.  */
126*0c81fcd6SJens Wiklander	sub	r0, r0, #40
127*0c81fcd6SJens Wiklander	ldmia	r0!, {r4, r5, r6, r7}
128*0c81fcd6SJens Wiklander	/* Return the result argument, or 1 if it is zero.  */
129*0c81fcd6SJens Wiklander	mov	r0, r1
130*0c81fcd6SJens Wiklander	bne	1f
131*0c81fcd6SJens Wiklander	mov	r0, #1
132*0c81fcd6SJens Wiklander1:
133*0c81fcd6SJens Wiklander	bx	r3
134*0c81fcd6SJens Wiklander
135*0c81fcd6SJens Wiklander#else
136*0c81fcd6SJens Wiklander
137*0c81fcd6SJens Wiklander#ifdef __APCS_26__
138*0c81fcd6SJens Wiklander#define RET	movs		pc, lr
139*0c81fcd6SJens Wiklander#elif defined(__thumb2__)
140*0c81fcd6SJens Wiklander#define RET	bx lr
141*0c81fcd6SJens Wiklander#else
142*0c81fcd6SJens Wiklander#define RET	tst		lr, #1; \
143*0c81fcd6SJens Wiklander	        moveq		pc, lr ; \
144*0c81fcd6SJens Wiklander.word           0xe12fff1e	/* bx lr */
145*0c81fcd6SJens Wiklander#endif
146*0c81fcd6SJens Wiklander
147*0c81fcd6SJens Wiklander#ifdef __thumb2__
148*0c81fcd6SJens Wiklander.macro COND where when
149*0c81fcd6SJens Wiklander	i\where	\when
150*0c81fcd6SJens Wiklander.endm
151*0c81fcd6SJens Wiklander#else
152*0c81fcd6SJens Wiklander.macro COND where when
153*0c81fcd6SJens Wiklander.endm
154*0c81fcd6SJens Wiklander#endif
155*0c81fcd6SJens Wiklander
156*0c81fcd6SJens Wiklander#if defined(__thumb2__)
157*0c81fcd6SJens Wiklander.syntax unified
158*0c81fcd6SJens Wiklander.macro MODE
159*0c81fcd6SJens Wiklander	.thumb
160*0c81fcd6SJens Wiklander	.thumb_func
161*0c81fcd6SJens Wiklander.endm
162*0c81fcd6SJens Wiklander.macro PROLOGUE name
163*0c81fcd6SJens Wiklander.endm
164*0c81fcd6SJens Wiklander
165*0c81fcd6SJens Wiklander#elif defined(__thumb__)
166*0c81fcd6SJens Wiklander#define	MODE		.thumb_func
167*0c81fcd6SJens Wiklander.macro PROLOGUE name
168*0c81fcd6SJens Wiklander	.code 16
169*0c81fcd6SJens Wiklander	bx	pc
170*0c81fcd6SJens Wiklander	nop
171*0c81fcd6SJens Wiklander	.code 32
172*0c81fcd6SJens WiklanderSYM (.arm_start_of.\name):
173*0c81fcd6SJens Wiklander.endm
174*0c81fcd6SJens Wiklander#else /* Arm */
175*0c81fcd6SJens Wiklander#define	MODE		.code 32
176*0c81fcd6SJens Wiklander.macro PROLOGUE name
177*0c81fcd6SJens Wiklander.endm
178*0c81fcd6SJens Wiklander#endif
179*0c81fcd6SJens Wiklander
180*0c81fcd6SJens Wiklander.macro FUNC_START name
181*0c81fcd6SJens Wiklander	.text
182*0c81fcd6SJens Wiklander	.align 2
183*0c81fcd6SJens Wiklander	MODE
184*0c81fcd6SJens Wiklander	.globl SYM (\name)
185*0c81fcd6SJens Wiklander	TYPE (\name)
186*0c81fcd6SJens WiklanderSYM (\name):
187*0c81fcd6SJens Wiklander	PROLOGUE \name
188*0c81fcd6SJens Wiklander.endm
189*0c81fcd6SJens Wiklander
190*0c81fcd6SJens Wiklander.macro FUNC_END name
191*0c81fcd6SJens Wiklander	RET
192*0c81fcd6SJens Wiklander	SIZE (\name)
193*0c81fcd6SJens Wiklander.endm
194*0c81fcd6SJens Wiklander
195*0c81fcd6SJens Wiklander/* --------------------------------------------------------------------
196*0c81fcd6SJens Wiklander                 int setjmp (jmp_buf);
197*0c81fcd6SJens Wiklander   -------------------------------------------------------------------- */
198*0c81fcd6SJens Wiklander
199*0c81fcd6SJens Wiklander	FUNC_START setjmp
200*0c81fcd6SJens Wiklander
201*0c81fcd6SJens Wiklander	/* Save all the callee-preserved registers into the jump buffer.  */
202*0c81fcd6SJens Wiklander#ifdef __thumb2__
203*0c81fcd6SJens Wiklander	mov		ip, sp
204*0c81fcd6SJens Wiklander	stmea		a1!, { v1-v7, fp, ip, lr }
205*0c81fcd6SJens Wiklander#else
206*0c81fcd6SJens Wiklander	stmea		a1!, { v1-v7, fp, ip, sp, lr }
207*0c81fcd6SJens Wiklander#endif
208*0c81fcd6SJens Wiklander
209*0c81fcd6SJens Wiklander#if 0	/* Simulator does not cope with FP instructions yet.  */
210*0c81fcd6SJens Wiklander#ifndef __SOFTFP__
211*0c81fcd6SJens Wiklander	/* Save the floating point registers.  */
212*0c81fcd6SJens Wiklander	sfmea		f4, 4, [a1]
213*0c81fcd6SJens Wiklander#endif
214*0c81fcd6SJens Wiklander#endif
215*0c81fcd6SJens Wiklander	/* When setting up the jump buffer return 0.  */
216*0c81fcd6SJens Wiklander	mov		a1, #0
217*0c81fcd6SJens Wiklander
218*0c81fcd6SJens Wiklander	FUNC_END setjmp
219*0c81fcd6SJens Wiklander
220*0c81fcd6SJens Wiklander/* --------------------------------------------------------------------
221*0c81fcd6SJens Wiklander		volatile void longjmp (jmp_buf, int);
222*0c81fcd6SJens Wiklander   -------------------------------------------------------------------- */
223*0c81fcd6SJens Wiklander
224*0c81fcd6SJens Wiklander	FUNC_START longjmp
225*0c81fcd6SJens Wiklander
226*0c81fcd6SJens Wiklander	/* If we have stack extension code it ought to be handled here.  */
227*0c81fcd6SJens Wiklander
228*0c81fcd6SJens Wiklander	/* Restore the registers, retrieving the state when setjmp() was called.  */
229*0c81fcd6SJens Wiklander#ifdef __thumb2__
230*0c81fcd6SJens Wiklander	ldmfd		a1!, { v1-v7, fp, ip, lr }
231*0c81fcd6SJens Wiklander	mov		sp, ip
232*0c81fcd6SJens Wiklander#else
233*0c81fcd6SJens Wiklander	ldmfd		a1!, { v1-v7, fp, ip, sp, lr }
234*0c81fcd6SJens Wiklander#endif
235*0c81fcd6SJens Wiklander
236*0c81fcd6SJens Wiklander#if 0	/* Simulator does not cope with FP instructions yet.  */
237*0c81fcd6SJens Wiklander#ifndef __SOFTFP__
238*0c81fcd6SJens Wiklander	/* Restore floating point registers as well.  */
239*0c81fcd6SJens Wiklander	lfmfd		f4, 4, [a1]
240*0c81fcd6SJens Wiklander#endif
241*0c81fcd6SJens Wiklander#endif
242*0c81fcd6SJens Wiklander	/* Put the return value into the integer result register.
243*0c81fcd6SJens Wiklander	   But if it is zero then return 1 instead.  */
244*0c81fcd6SJens Wiklander	movs		a1, a2
245*0c81fcd6SJens Wiklander#ifdef __thumb2__
246*0c81fcd6SJens Wiklander	it		eq
247*0c81fcd6SJens Wiklander#endif
248*0c81fcd6SJens Wiklander	moveq		a1, #1
249*0c81fcd6SJens Wiklander
250*0c81fcd6SJens Wiklander	FUNC_END longjmp
251*0c81fcd6SJens Wiklander#endif
252