1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/*
29 * Copyright (c) 2001-2002 Opsycon AB  (www.opsycon.se / www.opsycon.com)
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 *    notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 *    notice, this list of conditions and the following disclaimer in the
38 *    documentation and/or other materials provided with the distribution.
39 * 3. Neither the name of Opsycon AB nor the names of its contributors
40 *    may be used to endorse or promote products derived from this software
41 *    without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
44 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 *
55 */
56/*-
57 * Copyright (c) 1991, 1993, 1995,
58 *	The Regents of the University of California.  All rights reserved.
59 *
60 * This code is derived from software contributed to Berkeley by
61 * Havard Eidnes.
62 *
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
65 * are met:
66 * 1. Redistributions of source code must retain the above copyright
67 *    notice, this list of conditions and the following disclaimer.
68 * 2. Redistributions in binary form must reproduce the above copyright
69 *    notice, this list of conditions and the following disclaimer in the
70 *    documentation and/or other materials provided with the distribution.
71 * 3. Neither the name of the University nor the names of its contributors
72 *    may be used to endorse or promote products derived from this software
73 *    without specific prior written permission.
74 *
75 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
76 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
77 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
78 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
79 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
80 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
81 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
82 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
83 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
84 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
85 * SUCH DAMAGE.
86 */
87/*
88 * Copyright (c) 1992, 1993
89 *	The Regents of the University of California.  All rights reserved.
90 *
91 * This code is derived from software contributed to Berkeley by
92 * Ralph Campbell.
93 *
94 * Redistribution and use in source and binary forms, with or without
95 * modification, are permitted provided that the following conditions
96 * are met:
97 * 1. Redistributions of source code must retain the above copyright
98 *    notice, this list of conditions and the following disclaimer.
99 * 2. Redistributions in binary form must reproduce the above copyright
100 *    notice, this list of conditions and the following disclaimer in the
101 *    documentation and/or other materials provided with the distribution.
102 * 3. Neither the name of the University nor the names of its contributors
103 *    may be used to endorse or promote products derived from this software
104 *    without specific prior written permission.
105 *
106 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
107 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
108 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
109 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
110 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
111 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
112 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
113 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
114 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
115 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
116 * SUCH DAMAGE.
117 *
118 *	@(#)signal.h	8.1 (Berkeley) 6/10/93
119 */
120
121#include <private/bionic_asm.h>
122#include <machine/setjmp.h>
123
124/* jmpbuf is declared to users as an array of longs, which is only
125 * 4-byte aligned in 32-bit builds.  The Mips jmpbuf begins with a
126 * dynamically-sized 0- or 4-byte unused filler so that double-prec FP regs
127 * are saved to 8-byte-aligned mem cells.
128 * All the following jmpbuf offsets are from the rounded-DOWN base addr.
129 */
130
131/* Fields of same size on all MIPS abis: */
132/*     	field:		byte offset:	size:						*/
133/*     	dynam filler	(0*4)		   0-4 bytes of rounddown filler, DON'T TOUCH!!
134						often overlays user storage!!		*/
135#define	SC_FPSR_OFFSET	(1*4)		/* 4 bytes, floating point control/status reg */
136/* following fields are 8-byte aligned */
137#define	SC_FLAG_OFFSET	(2*4)		/* 8 bytes, cookie and savesigs flag, first actual field  */
138#define	SC_MASK_OFFSET	(4*4)		/* 16 bytes, mips32/mips64 version of sigset_t */
139#define	SC_SPARE_OFFSET	(8*4)		/* 8 bytes, reserved for future uses */
140
141/* Registers that are 4-byte on mips32 o32, and 8-byte on mips64 n64 abi */
142#define	SC_REGS_OFFSET	(10*4)		/* SC_REGS_BYTES */
143#define	SC_REGS_SAVED	12 /*regs*/	/* ra,s0-s8,gp,sp */
144#define	SC_REGS_BYTES   (SC_REGS_SAVED*REGSZ)
145#define	SC_REGS		SC_REGS_OFFSET
146
147/* Double floating pt registers are 8-bytes on all abis,
148 * but the number of saved fp regs varies for o32/n32 versus n64 abis:
149 */
150
151#ifdef __LP64__
152#define	SC_FPREGS_SAVED	8  /* all  fp regs f24,f25,f26,f27,f28,f29,f30,f31 */
153#else
154#define	SC_FPREGS_SAVED	6  /* even fp regs f20,f22,f24,f26,f28,f30 */
155#endif
156
157#define	SC_FPREGS_OFFSET (SC_REGS_OFFSET + SC_REGS_BYTES)  /* SC_FPREGS_BYTES */
158#define	SC_FPREGS_BYTES (SC_FPREGS_SAVED*REGSZ_FP)
159#define	SC_FPREGS	SC_FPREGS_OFFSET
160
161#define	SC_TOTAL_BYTES	(SC_FPREGS_OFFSET + SC_FPREGS_BYTES)
162#define	SC_TOTAL_LONGS	(SC_TOTAL_BYTES/REGSZ)
163
164#if SC_TOTAL_LONGS > _JBLEN
165#error _JBLEN is too small
166#endif
167
168.macro m_mangle_reg_and_store reg, cookie, temp, offset
169	xor	\temp, \reg, \cookie
170	REG_S	\temp, \offset
171.endm
172
173.macro m_unmangle_reg_and_load reg, cookie, temp, offset
174	REG_L	\temp, \offset
175	xor	\reg, \temp, \cookie
176.endm
177
178/*
179 *
180 *  GPOFF and FRAMESIZE must be the same for all setjmp/longjmp routines
181 *
182 */
183
184FRAMESZ= MKFSIZ(2,6)
185A1OFF= FRAMESZ-4*REGSZ
186A0OFF= FRAMESZ-3*REGSZ
187GPOFF= FRAMESZ-2*REGSZ
188RAOFF= FRAMESZ-1*REGSZ
189
190NON_LEAF(sigsetjmp, FRAMESZ, ra)
191	.mask	0x80000000, RAOFF
192	PTR_SUBU sp, FRAMESZ			# allocate stack frame
193	SETUP_GP64(GPOFF, sigsetjmp)
194	SAVE_GP(GPOFF)
195	.set	reorder
196
197setjmp_common:
198#ifndef __LP64__
199	li	t0, ~7
200	and	a0, t0				# round jmpbuf addr DOWN to 8-byte boundary
201#endif
202	REG_S	ra, RAOFF(sp)			# spill state
203	REG_S	a0, A0OFF(sp)
204
205	# get the cookie and store it along with the signal flag.
206	move	a0, a1
207	jal	__bionic_setjmp_cookie_get
208	REG_L	a0, A0OFF(sp)
209
210	REG_S	v0, SC_FLAG_OFFSET(a0)		# save cookie and savesigs flag
211	andi	t0, v0, 1			# extract savesigs flag
212
213	beqz	t0, 1f				# do saving of signal mask?
214
215	# call sigprocmask(int how ignored, sigset_t* null, sigset_t* SC_MASK(a0)):
216	LA	a2, SC_MASK_OFFSET(a0)		# gets current signal mask
217	li	a0, 0				# how; ignored when new mask is null
218	li	a1, 0				# null new mask
219	jal	sigprocmask			# get current signal mask
220	REG_L	a0, A0OFF(sp)
2211:
222	REG_L	gp, GPOFF(sp)			# restore spills
223	REG_L	ra, RAOFF(sp)
224	REG_L	t0, SC_FLAG_OFFSET(a0)		# move cookie to temp reg
225
226	# callee-saved long-sized regs:
227	PTR_ADDU v1, sp, FRAMESZ		# save orig sp
228
229	# m_mangle_reg_and_store reg, cookie, temp, offset
230	m_mangle_reg_and_store	ra, t0, t1, SC_REGS+0*REGSZ(a0)
231	m_mangle_reg_and_store	s0, t0, t2, SC_REGS+1*REGSZ(a0)
232	m_mangle_reg_and_store	s1, t0, t3, SC_REGS+2*REGSZ(a0)
233	m_mangle_reg_and_store	s2, t0, t1, SC_REGS+3*REGSZ(a0)
234	m_mangle_reg_and_store	s3, t0, t2, SC_REGS+4*REGSZ(a0)
235	m_mangle_reg_and_store	s4, t0, t3, SC_REGS+5*REGSZ(a0)
236	m_mangle_reg_and_store	s5, t0, t1, SC_REGS+6*REGSZ(a0)
237	m_mangle_reg_and_store	s6, t0, t2, SC_REGS+7*REGSZ(a0)
238	m_mangle_reg_and_store	s7, t0, t3, SC_REGS+8*REGSZ(a0)
239	m_mangle_reg_and_store	s8, t0, t1, SC_REGS+9*REGSZ(a0)
240	m_mangle_reg_and_store	gp, t0, t2, SC_REGS+10*REGSZ(a0)
241	m_mangle_reg_and_store	v1, t0, t3, SC_REGS+11*REGSZ(a0)
242
243	cfc1	v0, $31
244
245#ifdef __LP64__
246	# callee-saved fp regs on mips n64 ABI are $f24..$f31
247	s.d	$f24, SC_FPREGS+0*REGSZ_FP(a0)
248	s.d	$f25, SC_FPREGS+1*REGSZ_FP(a0)
249	s.d	$f26, SC_FPREGS+2*REGSZ_FP(a0)
250	s.d	$f27, SC_FPREGS+3*REGSZ_FP(a0)
251	s.d	$f28, SC_FPREGS+4*REGSZ_FP(a0)
252	s.d	$f29, SC_FPREGS+5*REGSZ_FP(a0)
253	s.d	$f30, SC_FPREGS+6*REGSZ_FP(a0)
254	s.d	$f31, SC_FPREGS+7*REGSZ_FP(a0)
255#else
256	# callee-saved fp regs on mips o32 ABI are
257	#   the even-numbered double fp regs $f20,$f22,...$f30
258	s.d	$f20, SC_FPREGS+0*REGSZ_FP(a0)
259	s.d	$f22, SC_FPREGS+1*REGSZ_FP(a0)
260	s.d	$f24, SC_FPREGS+2*REGSZ_FP(a0)
261	s.d	$f26, SC_FPREGS+3*REGSZ_FP(a0)
262	s.d	$f28, SC_FPREGS+4*REGSZ_FP(a0)
263	s.d	$f30, SC_FPREGS+5*REGSZ_FP(a0)
264#endif
265	sw	v0, SC_FPSR_OFFSET(a0)
266	move	v0, zero
267	RESTORE_GP64
268	PTR_ADDU sp, FRAMESZ
269	j	ra
270END(sigsetjmp)
271
272
273# Alternate entry points:
274
275NON_LEAF(setjmp, FRAMESZ, ra)
276	.mask	0x80000000, RAOFF
277	PTR_SUBU sp, FRAMESZ
278	SETUP_GP64(GPOFF, setjmp)		# can't share sigsetjmp's gp code
279	SAVE_GP(GPOFF)
280	.set	reorder
281
282	li	a1, 1				# save/restore signals state
283	b	setjmp_common			# tail call
284END(setjmp)
285
286
287NON_LEAF(_setjmp, FRAMESZ, ra)
288	.mask	0x80000000, RAOFF
289	PTR_SUBU sp, FRAMESZ
290	SETUP_GP64(GPOFF, _setjmp)		# can't share sigsetjmp's gp code
291	SAVE_GP(GPOFF)
292	.set	reorder
293
294	li	a1, 0				# don't save/restore signals
295	b	setjmp_common			# tail call
296END(_setjmp)
297
298
299NON_LEAF(siglongjmp, FRAMESZ, ra)
300	.mask	0x80000000, RAOFF
301	PTR_SUBU sp, FRAMESZ
302	SETUP_GP64(GPOFF, siglongjmp)
303	SAVE_GP(GPOFF)
304	.set	reorder
305
306#ifndef __LP64__
307	li	t0, ~7
308	and	a0, t0				# round jmpbuf addr DOWN to 8-byte boundary
309#endif
310
311	move	s1, a1				# temp spill
312	move	s0, a0
313
314	# extract savesigs flag
315	REG_L	s2, SC_FLAG_OFFSET(s0)
316	andi	t0, s2, 1
317	beqz	t0, 1f				# restore signal mask?
318
319	# call sigprocmask(int how SIG_SETMASK, sigset_t* SC_MASK(a0), sigset_t* null):
320	LA	a1, SC_MASK_OFFSET(s0)		# signals being restored
321	li	a0, 3				# mips SIG_SETMASK
322	li	a2, 0				# null
323	jal	sigprocmask			# restore signal mask
3241:
325	move	t0, s2				# get cookie to temp reg
326	move	a1, s1
327	move	a0, s0
328
329	# callee-saved long-sized regs:
330
331	# m_unmangle_reg_and_load reg, cookie, temp, offset
332	# don't restore gp yet, old value is needed for cookie_check call
333	m_unmangle_reg_and_load ra, t0, t1, SC_REGS+0*REGSZ(a0)
334	m_unmangle_reg_and_load s0, t0, t2, SC_REGS+1*REGSZ(a0)
335	m_unmangle_reg_and_load s1, t0, t3, SC_REGS+2*REGSZ(a0)
336	m_unmangle_reg_and_load s2, t0, t1, SC_REGS+3*REGSZ(a0)
337	m_unmangle_reg_and_load s3, t0, t2, SC_REGS+4*REGSZ(a0)
338	m_unmangle_reg_and_load s4, t0, t3, SC_REGS+5*REGSZ(a0)
339	m_unmangle_reg_and_load s5, t0, t1, SC_REGS+6*REGSZ(a0)
340	m_unmangle_reg_and_load s6, t0, t2, SC_REGS+7*REGSZ(a0)
341	m_unmangle_reg_and_load s7, t0, t3, SC_REGS+8*REGSZ(a0)
342	m_unmangle_reg_and_load s8, t0, t1, SC_REGS+9*REGSZ(a0)
343	m_unmangle_reg_and_load v1, t0, t2, SC_REGS+10*REGSZ(a0)
344	m_unmangle_reg_and_load sp, t0, t3, SC_REGS+11*REGSZ(a0)
345
346	lw	v0, SC_FPSR_OFFSET(a0)
347	ctc1	v0, $31			# restore old fr mode before fp values
348#ifdef __LP64__
349	# callee-saved fp regs on mips n64 ABI are $f24..$f31
350	l.d	$f24, SC_FPREGS+0*REGSZ_FP(a0)
351	l.d	$f25, SC_FPREGS+1*REGSZ_FP(a0)
352	l.d	$f26, SC_FPREGS+2*REGSZ_FP(a0)
353	l.d	$f27, SC_FPREGS+3*REGSZ_FP(a0)
354	l.d	$f28, SC_FPREGS+4*REGSZ_FP(a0)
355	l.d	$f29, SC_FPREGS+5*REGSZ_FP(a0)
356	l.d	$f30, SC_FPREGS+6*REGSZ_FP(a0)
357	l.d	$f31, SC_FPREGS+7*REGSZ_FP(a0)
358#else
359	# callee-saved fp regs on mips o32 ABI are
360	#   the even-numbered double fp regs $f20,$f22,...$f30
361	l.d	$f20, SC_FPREGS+0*REGSZ_FP(a0)
362	l.d	$f22, SC_FPREGS+1*REGSZ_FP(a0)
363	l.d	$f24, SC_FPREGS+2*REGSZ_FP(a0)
364	l.d	$f26, SC_FPREGS+3*REGSZ_FP(a0)
365	l.d	$f28, SC_FPREGS+4*REGSZ_FP(a0)
366	l.d	$f30, SC_FPREGS+5*REGSZ_FP(a0)
367#endif
368
369	# check cookie
370	PTR_SUBU sp, FRAMESZ
371	REG_S	v1, GPOFF(sp)
372	REG_S	ra, RAOFF(sp)
373	REG_S	a1, A1OFF(sp)
374	move	a0, t0
375	jal	__bionic_setjmp_cookie_check
376	REG_L	gp, GPOFF(sp)
377	REG_L	ra, RAOFF(sp)
378	REG_L	a1, A1OFF(sp)
379	PTR_ADDU sp, FRAMESZ
380
381	sltiu	t0, a1, 1		# never return 0!
382	xor	v0, a1, t0
383	j	ra			# return to setjmp call site
384END(siglongjmp)
385
386ALIAS_SYMBOL(longjmp, siglongjmp)
387ALIAS_SYMBOL(_longjmp, siglongjmp)
388