OSDN Git Service

resolved conflicts for 95ac6dbb to mnc-dr-dev-plus-aosp
[android-x86/bionic.git] / libc / arch-arm / bionic / setjmp.S
1 /*
2  * Copyright (c) 1997 Mark Brinicombe
3  * Copyright (c) 2010 Android Open Source Project.
4  * 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
34 #include <private/bionic_asm.h>
35
36 // 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 //
54 // 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)
61 // 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
67 #define _JB_SIGFLAG     0
68 #define _JB_SIGMASK     (_JB_SIGFLAG+1)
69 #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
73 ENTRY(setjmp)
74   mov r1, #1
75   b sigsetjmp
76 END(setjmp)
77
78 ENTRY(_setjmp)
79   mov r1, #0
80   b sigsetjmp
81 END(_setjmp)
82
83 #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
104 // int sigsetjmp(sigjmp_buf env, int save_signal_mask);
105 ENTRY(sigsetjmp)
106   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.
123   str r1, [r0, #(_JB_SIGFLAG * 4)]
124
125   // Do we need to save the signal mask?
126   tst r1, #1
127   beq 1f
128
129   // Align the stack.
130   sub sp, #4
131   .cfi_adjust_cfa_offset 4
132
133   // 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
142
143 1:
144   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
151   // Save core registers.
152   add r1, r0, #(_JB_CORE_BASE * 4)
153   m_mangle_registers r2
154   stmia r1, {r4-r14}
155   m_unmangle_registers r2
156
157   // Save floating-point registers.
158   add r1, r0, #(_JB_FLOAT_BASE * 4)
159   vstmia  r1, {d8-d15}
160
161   // Save floating-point state.
162   fmrx r1, fpscr
163   str r1, [r0, #(_JB_FLOAT_STATE * 4)]
164
165   mov r0, #0
166   bx lr
167 END(sigsetjmp)
168
169 // void siglongjmp(sigjmp_buf env, int value);
170 ENTRY(siglongjmp)
171   stmfd sp!, {r0, r1, lr}
172   .cfi_def_cfa_offset 12
173   .cfi_rel_offset r0, 0
174   .cfi_rel_offset r1, 4
175   .cfi_rel_offset lr, 8
176
177   // Fetch the signal flag.
178   ldr r1, [r0, #(_JB_SIGFLAG * 4)]
179
180   // Do we need to restore the signal mask?
181   ands r1, r1, #1
182   beq 1f
183
184   // Restore the signal mask.
185   ldr r0, [r0, #(_JB_SIGMASK * 4)]
186   bl sigsetmask
187
188 1:
189   ldmfd sp!, {r0, r1, lr}
190   .cfi_adjust_cfa_offset -12
191   .cfi_restore r0
192   .cfi_restore r1
193   .cfi_restore lr
194
195   // Restore floating-point registers.
196   add r2, r0, #(_JB_FLOAT_BASE * 4)
197   vldmia r2, {d8-d15}
198
199   // Restore floating-point state.
200   ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
201   fmxr fpscr, r2
202
203   // Restore core registers.
204   ldr r3, [r0, #(_JB_SIGFLAG * 4)]
205   bic r3, r3, #1
206   add r2, r0, #(_JB_CORE_BASE * 4)
207   ldmia r2, {r4-r14}
208   m_unmangle_registers r3
209
210   // Save the return value/address and check the setjmp cookie.
211   stmfd sp!, {r1, lr}
212   .cfi_adjust_cfa_offset 8
213   .cfi_rel_offset lr, 4
214   mov r0, r3
215   bl __bionic_setjmp_cookie_check
216
217   // Restore return value/address.
218   ldmfd sp!, {r0, lr}
219   .cfi_adjust_cfa_offset -8
220   .cfi_restore lr
221
222   teq r0, #0
223   moveq r0, #1
224   bx lr
225 END(siglongjmp)
226
227 ALIAS_SYMBOL(longjmp, siglongjmp)
228 ALIAS_SYMBOL(_longjmp, siglongjmp)