OSDN Git Service

Add timespec/timeval conversion helpers.
[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
155   // ARM deprecates using sp in the register list for stmia.
156   stmia r1, {r4-r12, lr}
157   str sp, [r1, #(10 * 4)]
158   m_unmangle_registers r2
159
160   // Save floating-point registers.
161   add r1, r0, #(_JB_FLOAT_BASE * 4)
162   vstmia  r1, {d8-d15}
163
164   // Save floating-point state.
165   fmrx r1, fpscr
166   str r1, [r0, #(_JB_FLOAT_STATE * 4)]
167
168   mov r0, #0
169   bx lr
170 END(sigsetjmp)
171
172 // void siglongjmp(sigjmp_buf env, int value);
173 ENTRY(siglongjmp)
174   stmfd sp!, {r0, r1, lr}
175   .cfi_def_cfa_offset 12
176   .cfi_rel_offset r0, 0
177   .cfi_rel_offset r1, 4
178   .cfi_rel_offset lr, 8
179
180   // 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.
188   ldr r0, [r0, #(_JB_SIGMASK * 4)]
189   bl sigsetmask
190
191 1:
192   ldmfd sp!, {r0, r1, lr}
193   .cfi_adjust_cfa_offset -12
194   .cfi_restore r0
195   .cfi_restore r1
196   .cfi_restore lr
197
198   // 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.
207   ldr r3, [r0, #(_JB_SIGFLAG * 4)]
208   bic r3, r3, #1
209   add r2, r0, #(_JB_CORE_BASE * 4)
210
211   // ARM deprecates using sp in the register list for ldmia.
212   ldmia r2, {r4-r12, lr}
213   ldr sp, [r2, #(10 * 4)]
214   m_unmangle_registers r3
215
216   // 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
222
223   // Restore return value/address.
224   ldmfd sp!, {r0, lr}
225   .cfi_adjust_cfa_offset -8
226   .cfi_restore lr
227
228   teq r0, #0
229   moveq r0, #1
230   bx lr
231 END(siglongjmp)
232
233 ALIAS_SYMBOL(longjmp, siglongjmp)
234 ALIAS_SYMBOL(_longjmp, siglongjmp)