blob: 7a99fc065ce8f7806d8b7c0ab7de76415c603fa1 [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//
54// word name description
55// 0 magic magic number
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_MAGIC 0
68#define _JB_SIGMASK (_JB_MAGIC+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.L_setjmp_magic_signal_mask_n: .word 0x4278f500
74.L_setjmp_magic_signal_mask_y: .word 0x4278f501
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080075
76ENTRY(setjmp)
Elliott Hughesb3932992014-12-05 15:39:51 -080077 mov r1, #1
78 b sigsetjmp
Kenny Root420878c2011-02-16 11:55:58 -080079END(setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080080
Elliott Hughesb3932992014-12-05 15:39:51 -080081ENTRY(_setjmp)
82 mov r1, #0
83 b sigsetjmp
84END(_setjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080085
Elliott Hughesb3932992014-12-05 15:39:51 -080086// int sigsetjmp(sigjmp_buf env, int save_signal_mask);
87ENTRY(sigsetjmp)
88 // Do we need to save the signal mask?
89 teq r1, #0
90 ldreq r1, .L_setjmp_magic_signal_mask_n
91 beq 1f
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080092
Elliott Hughesb3932992014-12-05 15:39:51 -080093 // Get current signal mask.
94 stmfd sp!, {r0, r14}
95 .cfi_def_cfa_offset 8
96 .cfi_rel_offset r0, 0
97 .cfi_rel_offset r14, 4
98 mov r0, #0
99 bl sigblock
100 mov r1, r0
101 ldmfd sp!, {r0, r14}
102 .cfi_def_cfa_offset 0
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800103
Elliott Hughesb3932992014-12-05 15:39:51 -0800104 // Save signal mask.
105 str r1, [r0, #(_JB_SIGMASK * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800106
Elliott Hughesb3932992014-12-05 15:39:51 -0800107 ldr r1, .L_setjmp_magic_signal_mask_y
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800108
Elliott Hughesb3932992014-12-05 15:39:51 -08001091:
110 // Save magic number.
111 str r1, [r0, #(_JB_MAGIC * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800112
Elliott Hughesb3932992014-12-05 15:39:51 -0800113 // Save core registers.
114 add r1, r0, #(_JB_CORE_BASE * 4)
115 stmia r1, {r4-r14}
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800116
Elliott Hughesb3932992014-12-05 15:39:51 -0800117 // Save floating-point registers.
118 add r1, r0, #(_JB_FLOAT_BASE * 4)
119 vstmia r1, {d8-d15}
David 'Digit' Turner68b5f552010-03-25 09:54:33 -0700120
Elliott Hughesb3932992014-12-05 15:39:51 -0800121 // Save floating-point state.
122 fmrx r1, fpscr
123 str r1, [r0, #(_JB_FLOAT_STATE * 4)]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800124
Elliott Hughesb3932992014-12-05 15:39:51 -0800125 mov r0, #0
126 bx lr
127END(sigsetjmp)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800128
Elliott Hughesb3932992014-12-05 15:39:51 -0800129// void siglongjmp(sigjmp_buf env, int value);
130ENTRY(siglongjmp)
131 // Check magic.
132 ldr r3, [r0, #(_JB_MAGIC * 4)]
133 ldr r2, .L_setjmp_magic_signal_mask_n
134 teq r2, r3
135 beq 1f
136 ldr r2, .L_setjmp_magic_signal_mask_y
137 teq r2, r3
138 bne longjmperror
139
140 // Restore signal mask.
141 stmfd sp!, {r0, r1, r14}
142 .cfi_def_cfa_offset 12
143 .cfi_rel_offset r0, 0
144 .cfi_rel_offset r1, 4
145 .cfi_rel_offset r14, 8
146 sub sp, sp, #4 // Align the stack.
147 .cfi_adjust_cfa_offset 4
148
149 ldr r0, [r0, #(_JB_SIGMASK * 4)]
150 bl sigsetmask
151
152 add sp, sp, #4 // Unalign the stack.
153 .cfi_adjust_cfa_offset -4
154 ldmfd sp!, {r0, r1, r14}
155 .cfi_def_cfa_offset 0
156
1571:
158 // Restore floating-point registers.
159 add r2, r0, #(_JB_FLOAT_BASE * 4)
160 vldmia r2, {d8-d15}
161
162 // Restore floating-point state.
163 ldr r2, [r0, #(_JB_FLOAT_STATE * 4)]
164 fmxr fpscr, r2
165
166 // Restore core registers.
167 add r2, r0, #(_JB_CORE_BASE * 4)
168 ldmia r2, {r4-r14}
169
170 // Validate sp and r14.
171 teq sp, #0
172 teqne r14, #0
173 bleq longjmperror
174
175 // Set return value.
176 mov r0, r1
177 teq r0, #0
178 moveq r0, #1
179 bx lr
180END(siglongjmp)
181
182 .globl longjmp
183 .equ longjmp, siglongjmp
184 .globl _longjmp
185 .equ _longjmp, siglongjmp