blob: 464f7d8dec42e41562978d00a3d4d017f7693f73 [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
Elliott Hughesb3932992014-12-05 15:39:51 -080036// According to the ARM AAPCS document, we only need to save
37// the following registers:
38//
39// Core r4-r14
40//
41// VFP d8-d15 (see section 5.1.2.1)
42//
43// Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
44// calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
45// (and can be used for passing arguments or returning results in standard
46// procedure-call variants). Registers d16-d31 (q8-q15), if present, do
47// not need to be preserved.
48//
49// FPSCR saved because glibc does.
50
51// The internal structure of a jmp_buf is totally private.
52// Current layout (may change in the future):
53//
Josh Gao7fda8d22015-09-10 15:40:24 -070054// word name description
55// 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
56// 1 sigmask signal mask (not used with _setjmp / _longjmp)
57// 2 float_base base of float registers (d8 to d15)
58// 18 float_state floating-point status and control register
59// 19 core_base base of core registers (r4 to r14)
60// 30 reserved reserved entries (room to grow)
Elliott Hughesb3932992014-12-05 15:39:51 -080061// 64
62//
63// NOTE: float_base must be at an even word index, since the
64// FP registers will be loaded/stored with instructions
65// that expect 8-byte alignment.
66
Elliott Hughes75096222014-12-08 16:01:20 -080067#define _JB_SIGFLAG 0
68#define _JB_SIGMASK (_JB_SIGFLAG+1)
Elliott Hughesb3932992014-12-05 15:39:51 -080069#define _JB_FLOAT_BASE (_JB_SIGMASK+1)
70#define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
71#define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
72
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080073ENTRY(setjmp)
Elliott Hughesb3932992014-12-05 15:39:51 -080074 mov r1, #1
75 b sigsetjmp
Kenny Root420878c2011-02-16 11:55:58 -080076END(setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080077
Elliott Hughesb3932992014-12-05 15:39:51 -080078ENTRY(_setjmp)
79 mov r1, #0
80 b sigsetjmp
81END(_setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080082
Josh Gao7fda8d22015-09-10 15:40:24 -070083#define MANGLE_REGISTERS 1
84.macro m_mangle_registers reg
85#if MANGLE_REGISTERS
86 eor r4, r4, \reg
87 eor r5, r5, \reg
88 eor r6, r6, \reg
89 eor r7, r7, \reg
90 eor r8, r8, \reg
91 eor r9, r9, \reg
92 eor r10, r10, \reg
93 eor r11, r11, \reg
94 eor r12, r12, \reg
95 eor r13, r13, \reg
96 eor r14, r14, \reg
97#endif
98.endm
99
100.macro m_unmangle_registers reg
101 m_mangle_registers \reg
102.endm
103
Elliott Hughesb3932992014-12-05 15:39:51 -0800104// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
105ENTRY(sigsetjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -0700106 stmfd sp!, {r0, lr}
107 .cfi_def_cfa_offset 8
108 .cfi_rel_offset r0, 0
109 .cfi_rel_offset lr, 4
110
111 mov r0, r1
112 bl __bionic_setjmp_cookie_get
113 mov r1, r0
114
115 ldmfd sp, {r0}
116
117 // Save the setjmp cookie for later.
118 bic r2, r1, #1
119 stmfd sp!, {r2}
120 .cfi_adjust_cfa_offset 4
121
122 // Record the setjmp cookie and whether or not we're saving the signal mask.
Elliott Hughes75096222014-12-08 16:01:20 -0800123 str r1, [r0, #(_JB_SIGFLAG * 4)]
124
Elliott Hughesb3932992014-12-05 15:39:51 -0800125 // Do we need to save the signal mask?
Josh Gao7fda8d22015-09-10 15:40:24 -0700126 tst r1, #1
Elliott Hughesb3932992014-12-05 15:39:51 -0800127 beq 1f
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800128
Josh Gao7fda8d22015-09-10 15:40:24 -0700129 // Align the stack.
130 sub sp, #4
131 .cfi_adjust_cfa_offset 4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800132
Josh Gao7fda8d22015-09-10 15:40:24 -0700133 // Save the current signal mask.
134 add r2, r0, #(_JB_SIGMASK * 4)
135 mov r0, #2 // SIG_SETMASK
136 mov r1, #0
137 bl sigprocmask
138
139 // Unalign the stack.
140 add sp, #4
141 .cfi_adjust_cfa_offset -4
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800142
Elliott Hughesb3932992014-12-05 15:39:51 -08001431:
Josh Gao7fda8d22015-09-10 15:40:24 -0700144 ldmfd sp!, {r2}
145 .cfi_adjust_cfa_offset -4
146 ldmfd sp!, {r0, lr}
147 .cfi_adjust_cfa_offset -8
148 .cfi_restore r0
149 .cfi_restore lr
150
Elliott Hughesb3932992014-12-05 15:39:51 -0800151 // Save core registers.
152 add r1, r0, #(_JB_CORE_BASE * 4)
Josh Gao7fda8d22015-09-10 15:40:24 -0700153 m_mangle_registers r2
Josh Gaob24d7432015-10-19 12:56:50 -0700154
155 // ARM deprecates using sp in the register list for stmia.
156 stmia r1, {r4-r12, lr}
157 str sp, [r1, #(10 * 4)]
Josh Gao7fda8d22015-09-10 15:40:24 -0700158 m_unmangle_registers r2
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800159
Elliott Hughesb3932992014-12-05 15:39:51 -0800160 // Save floating-point registers.
161 add r1, r0, #(_JB_FLOAT_BASE * 4)
162 vstmia r1, {d8-d15}
David 'Digit' Turner68b5f552010-03-25 09:54:33 -0700163
Elliott Hughesb3932992014-12-05 15:39:51 -0800164 // Save floating-point state.
165 fmrx r1, fpscr
166 str r1, [r0, #(_JB_FLOAT_STATE * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800167
Elliott Hughesb3932992014-12-05 15:39:51 -0800168 mov r0, #0
169 bx lr
170END(sigsetjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800171
Elliott Hughesb3932992014-12-05 15:39:51 -0800172// void siglongjmp(sigjmp_buf env, int value);
173ENTRY(siglongjmp)
Josh Gao7fda8d22015-09-10 15:40:24 -0700174 stmfd sp!, {r0, r1, lr}
Elliott Hughesb3932992014-12-05 15:39:51 -0800175 .cfi_def_cfa_offset 12
176 .cfi_rel_offset r0, 0
177 .cfi_rel_offset r1, 4
Josh Gao7fda8d22015-09-10 15:40:24 -0700178 .cfi_rel_offset lr, 8
Elliott Hughesb3932992014-12-05 15:39:51 -0800179
Josh Gao7fda8d22015-09-10 15:40:24 -0700180 // Fetch the signal flag.
181 ldr r1, [r0, #(_JB_SIGFLAG * 4)]
182
183 // Do we need to restore the signal mask?
184 ands r1, r1, #1
185 beq 1f
186
187 // Restore the signal mask.
Elliott Hughesb3932992014-12-05 15:39:51 -0800188 ldr r0, [r0, #(_JB_SIGMASK * 4)]
189 bl sigsetmask
190
Elliott Hughesb3932992014-12-05 15:39:51 -08001911:
Josh Gao7fda8d22015-09-10 15:40:24 -0700192 ldmfd sp!, {r0, r1, lr}
193 .cfi_adjust_cfa_offset -12
194 .cfi_restore r0
195 .cfi_restore r1
196 .cfi_restore lr
197
Elliott Hughesb3932992014-12-05 15:39:51 -0800198 // Restore floating-point registers.
199 add r2, r0, #(_JB_FLOAT_BASE * 4)
200 vldmia r2, {d8-d15}
201
202 // Restore floating-point state.
203 ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
204 fmxr fpscr, r2
205
206 // Restore core registers.
Josh Gao7fda8d22015-09-10 15:40:24 -0700207 ldr r3, [r0, #(_JB_SIGFLAG * 4)]
208 bic r3, r3, #1
Elliott Hughesb3932992014-12-05 15:39:51 -0800209 add r2, r0, #(_JB_CORE_BASE * 4)
Josh Gaob24d7432015-10-19 12:56:50 -0700210
211 // ARM deprecates using sp in the register list for ldmia.
212 ldmia r2, {r4-r12, lr}
213 ldr sp, [r2, #(10 * 4)]
Josh Gao7fda8d22015-09-10 15:40:24 -0700214 m_unmangle_registers r3
Elliott Hughesb3932992014-12-05 15:39:51 -0800215
Josh Gao7fda8d22015-09-10 15:40:24 -0700216 // Save the return value/address and check the setjmp cookie.
217 stmfd sp!, {r1, lr}
218 .cfi_adjust_cfa_offset 8
219 .cfi_rel_offset lr, 4
220 mov r0, r3
221 bl __bionic_setjmp_cookie_check
Elliott Hughesb3932992014-12-05 15:39:51 -0800222
Josh Gao7fda8d22015-09-10 15:40:24 -0700223 // Restore return value/address.
224 ldmfd sp!, {r0, lr}
225 .cfi_adjust_cfa_offset -8
226 .cfi_restore lr
227
Elliott Hughesb3932992014-12-05 15:39:51 -0800228 teq r0, #0
229 moveq r0, #1
230 bx lr
231END(siglongjmp)
232
Christopher Ferris24958512015-03-25 09:12:00 -0700233ALIAS_SYMBOL(longjmp, siglongjmp)
234ALIAS_SYMBOL(_longjmp, siglongjmp)