2 * Copyright (c) 1997 Mark Brinicombe
3 * Copyright (c) 2010 Android Open Source Project.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
34 #include <private/bionic_asm.h>
36 // According to the ARM AAPCS document, we only need to save
37 // the following registers:
39 // Core r4-r11, sp, lr
41 // A subroutine must preserve the contents of the registers r4-r8, r10, r11
42 // and SP (and r9 in PCS variants that designate r9 as v6).
46 // Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine
47 // calls; registers s0-s15 (d0-d7, q0-q3) do not need to be preserved
48 // (and can be used for passing arguments or returning results in standard
49 // procedure-call variants). Registers d16-d31 (q8-q15), if present, do
50 // not need to be preserved.
52 // FPSCR saved because glibc does.
54 // The internal structure of a jmp_buf is totally private.
55 // Current layout (changes from release to release):
57 // word name description
58 // 0 sigflag/cookie setjmp cookie in top 31 bits, signal mask flag in low bit
59 // 1 sigmask signal mask (not used with _setjmp / _longjmp)
60 // 2 float_base base of float registers (d8 to d15)
61 // 18 float_state floating-point status and control register
62 // 19 core_base base of core registers (r4-r11, r13-r14)
63 // 29 checksum checksum of all of the core registers, to give better error messages.
64 // 30 reserved reserved entries (room to grow)
67 // NOTE: float_base must be at an even word index, since the
68 // FP registers will be loaded/stored with instructions
69 // that expect 8-byte alignment.
72 #define _JB_SIGMASK (_JB_SIGFLAG+1)
73 #define _JB_FLOAT_BASE (_JB_SIGMASK+1)
74 #define _JB_FLOAT_STATE (_JB_FLOAT_BASE + (15-8+1)*2)
75 #define _JB_CORE_BASE (_JB_FLOAT_STATE+1)
76 #define _JB_CHECKSUM (_JB_CORE_BASE+10)
88 #define MANGLE_REGISTERS 1
89 #define USE_CHECKSUM 1
91 .macro m_mangle_registers reg
106 .macro m_unmangle_registers reg
107 m_mangle_registers \reg
110 .macro m_calculate_checksum dst, src, scratch
112 .irp i,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28
113 ldr \scratch, [\src, #(\i * 4)]
114 eor \dst, \dst, \scratch
118 // int sigsetjmp(sigjmp_buf env, int save_signal_mask);
121 .cfi_def_cfa_offset 8
122 .cfi_rel_offset r0, 0
123 .cfi_rel_offset lr, 4
126 bl __bionic_setjmp_cookie_get
131 // Save the setjmp cookie for later.
134 .cfi_adjust_cfa_offset 4
136 // Record the setjmp cookie and whether or not we're saving the signal mask.
137 str r1, [r0, #(_JB_SIGFLAG * 4)]
139 // Do we need to save the signal mask?
145 .cfi_adjust_cfa_offset 4
147 // Save the current signal mask.
148 add r2, r0, #(_JB_SIGMASK * 4)
149 mov r0, #2 // SIG_SETMASK
153 // Unalign the stack.
155 .cfi_adjust_cfa_offset -4
159 .cfi_adjust_cfa_offset -4
161 .cfi_adjust_cfa_offset -8
165 // Save core registers.
166 add r1, r0, #(_JB_CORE_BASE * 4)
167 m_mangle_registers r2
169 // ARM deprecates using sp in the register list for stmia.
170 stmia r1, {r4-r11, lr}
171 str sp, [r1, #(9 * 4)]
172 m_unmangle_registers r2
174 // Save floating-point registers.
175 add r1, r0, #(_JB_FLOAT_BASE * 4)
178 // Save floating-point state.
180 str r1, [r0, #(_JB_FLOAT_STATE * 4)]
183 // Calculate the checksum.
184 m_calculate_checksum r12, r0, r2
185 str r12, [r0, #(_JB_CHECKSUM * 4)]
192 // void siglongjmp(sigjmp_buf env, int value);
194 stmfd sp!, {r0, r1, lr}
195 .cfi_def_cfa_offset 12
196 .cfi_rel_offset r0, 0
197 .cfi_rel_offset r1, 4
198 .cfi_rel_offset lr, 8
201 // Check the checksum before doing anything.
202 m_calculate_checksum r12, r0, r3
203 ldr r2, [r0, #(_JB_CHECKSUM * 4)]
206 bne __bionic_setjmp_checksum_mismatch
209 // Fetch the signal flag.
210 ldr r1, [r0, #(_JB_SIGFLAG * 4)]
212 // Do we need to restore the signal mask?
216 // Restore the signal mask.
217 ldr r0, [r0, #(_JB_SIGMASK * 4)]
221 ldmfd sp!, {r0, r1, lr}
222 .cfi_adjust_cfa_offset -12
227 // Restore floating-point registers.
228 add r2, r0, #(_JB_FLOAT_BASE * 4)
231 // Restore floating-point state.
232 ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
236 ldr r3, [r0, #(_JB_SIGFLAG * 4)]
239 // Restore core registers.
240 add r2, r0, #(_JB_CORE_BASE * 4)
242 // ARM deprecates using sp in the register list for ldmia.
243 ldmia r2, {r4-r11, lr}
244 ldr sp, [r2, #(9 * 4)]
245 m_unmangle_registers r3
247 // Save the return value/address and check the setjmp cookie.
249 .cfi_adjust_cfa_offset 8
250 .cfi_rel_offset lr, 4
252 bl __bionic_setjmp_cookie_check
254 // Restore return value/address.
256 .cfi_adjust_cfa_offset -8
264 ALIAS_SYMBOL(longjmp, siglongjmp)
265 ALIAS_SYMBOL(_longjmp, siglongjmp)