blob: 6b9c62628b6130cca75e47e63e53561414c601b7 [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/*
2 * Copyright (c) 1997 Mark Brinicombe
David 'Digit' Turner68b5f552010-03-25 09:54:33 -07003 * Copyright (c) 2010 Android Open Source Project.
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Mark Brinicombe
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
Elliott Hughes851e68a2014-02-19 16:53:20 -080034#include <private/bionic_asm.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080035#include <machine/setjmp.h>
36
Elliott Hughesb3932992014-12-05 15:39:51 -080037// According to the ARM AAPCS document, we only need to save
38// the following registers:
39//
40// Core r4-r14
41//
42// VFP d8-d15 (see section 5.1.2.1)
43//
44// Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
45// calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
46// (and can be used for passing arguments or returning results in standard
47// procedure-call variants). Registers d16-d31 (q8-q15), if present, do
48// not need to be preserved.
49//
50// FPSCR saved because glibc does.
51
52// The internal structure of a jmp_buf is totally private.
53// Current layout (may change in the future):
54//
55// word name description
56// 0 magic magic number
57// 1 sigmask signal mask (not used with _setjmp / _longjmp)
58// 2 float_base base of float registers (d8 to d15)
59// 18 float_state floating-point status and control register
60// 19 core_base base of core registers (r4 to r14)
61// 30 reserved reserved entries (room to grow)
62// 64
63//
64// NOTE: float_base must be at an even word index, since the
65// FP registers will be loaded/stored with instructions
66// that expect 8-byte alignment.
67
68#define _JB_MAGIC 0
69#define _JB_SIGMASK (_JB_MAGIC+1)
70#define _JB_FLOAT_BASE (_JB_SIGMASK+1)
71#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
72#define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
73
74.L_setjmp_magic_signal_mask_n: .word 0x4278f500
75.L_setjmp_magic_signal_mask_y: .word 0x4278f501
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080076
77ENTRY(setjmp)
Elliott Hughesb3932992014-12-05 15:39:51 -080078 mov r1, #1
79 b sigsetjmp
Kenny Root420878c2011-02-16 11:55:58 -080080END(setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080081
Elliott Hughesb3932992014-12-05 15:39:51 -080082ENTRY(_setjmp)
83 mov r1, #0
84 b sigsetjmp
85END(_setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080086
Elliott Hughesb3932992014-12-05 15:39:51 -080087// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
88ENTRY(sigsetjmp)
89 // Do we need to save the signal mask?
90 teq r1, #0
91 ldreq r1, .L_setjmp_magic_signal_mask_n
92 beq 1f
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080093
Elliott Hughesb3932992014-12-05 15:39:51 -080094 // Get current signal mask.
95 stmfd sp!, {r0, r14}
96 .cfi_def_cfa_offset 8
97 .cfi_rel_offset r0, 0
98 .cfi_rel_offset r14, 4
99 mov r0, #0
100 bl sigblock
101 mov r1, r0
102 ldmfd sp!, {r0, r14}
103 .cfi_def_cfa_offset 0
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800104
Elliott Hughesb3932992014-12-05 15:39:51 -0800105 // Save signal mask.
106 str r1, [r0, #(_JB_SIGMASK * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800107
Elliott Hughesb3932992014-12-05 15:39:51 -0800108 ldr r1, .L_setjmp_magic_signal_mask_y
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800109
Elliott Hughesb3932992014-12-05 15:39:51 -08001101:
111 // Save magic number.
112 str r1, [r0, #(_JB_MAGIC * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800113
Elliott Hughesb3932992014-12-05 15:39:51 -0800114 // Save core registers.
115 add r1, r0, #(_JB_CORE_BASE * 4)
116 stmia r1, {r4-r14}
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800117
Elliott Hughesb3932992014-12-05 15:39:51 -0800118 // Save floating-point registers.
119 add r1, r0, #(_JB_FLOAT_BASE * 4)
120 vstmia r1, {d8-d15}
David 'Digit' Turner68b5f552010-03-25 09:54:33 -0700121
Elliott Hughesb3932992014-12-05 15:39:51 -0800122 // Save floating-point state.
123 fmrx r1, fpscr
124 str r1, [r0, #(_JB_FLOAT_STATE * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800125
Elliott Hughesb3932992014-12-05 15:39:51 -0800126 mov r0, #0
127 bx lr
128END(sigsetjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800129
Elliott Hughesb3932992014-12-05 15:39:51 -0800130// void siglongjmp(sigjmp_buf env, int value);
131ENTRY(siglongjmp)
132 // Check magic.
133 ldr r3, [r0, #(_JB_MAGIC * 4)]
134 ldr r2, .L_setjmp_magic_signal_mask_n
135 teq r2, r3
136 beq 1f
137 ldr r2, .L_setjmp_magic_signal_mask_y
138 teq r2, r3
139 bne longjmperror
140
141 // Restore signal mask.
142 stmfd sp!, {r0, r1, r14}
143 .cfi_def_cfa_offset 12
144 .cfi_rel_offset r0, 0
145 .cfi_rel_offset r1, 4
146 .cfi_rel_offset r14, 8
147 sub sp, sp, #4 // Align the stack.
148 .cfi_adjust_cfa_offset 4
149
150 ldr r0, [r0, #(_JB_SIGMASK * 4)]
151 bl sigsetmask
152
153 add sp, sp, #4 // Unalign the stack.
154 .cfi_adjust_cfa_offset -4
155 ldmfd sp!, {r0, r1, r14}
156 .cfi_def_cfa_offset 0
157
1581:
159 // Restore floating-point registers.
160 add r2, r0, #(_JB_FLOAT_BASE * 4)
161 vldmia r2, {d8-d15}
162
163 // Restore floating-point state.
164 ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
165 fmxr fpscr, r2
166
167 // Restore core registers.
168 add r2, r0, #(_JB_CORE_BASE * 4)
169 ldmia r2, {r4-r14}
170
171 // Validate sp and r14.
172 teq sp, #0
173 teqne r14, #0
174 bleq longjmperror
175
176 // Set return value.
177 mov r0, r1
178 teq r0, #0
179 moveq r0, #1
180 bx lr
181END(siglongjmp)
182
183 .globl longjmp
184 .equ longjmp, siglongjmp
185 .globl _longjmp
186 .equ _longjmp, siglongjmp