setjmp.S revision 1.20 1 /* $NetBSD: setjmp.S,v 1.20 2025/05/03 19:57:13 riastradh Exp $ */
2
3 /*
4 * Copyright (c) 1997 Mark Brinicombe
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Mark Brinicombe
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #if !defined(__SOFTFP__) && !defined(__VFP_FP__) && !defined(__ARM_PCS)
36 #error FPA is not supported anymore
37 #endif
38
39 #if defined(__ARM_EABI__) && !defined(__ARM_PCS_VFP)
40 .fpu vfp
41 #endif
42
43 #include <machine/asm.h>
44 #include <machine/setjmp.h>
45
46 /*
47 * C library -- setjmp, longjmp
48 *
49 * longjmp(a,v)
50 * will generate a "return(v)" from the last call to
51 * setjmp(a)
52 * by restoring registers from the stack.
53 * The previous signal state is restored.
54 */
55
56 ENTRY(__setjmp14)
57 /* Get the signal mask. */
58 push {r0-r2, lr}
59 #if !defined(__thumb__)
60 adds r2, r0, #(_JB_SIGMASK * 4)
61 #else
62 mov r2, r0
63 adds r2, r2, #(_JB_SIGMASK * 4)
64 #endif
65 movs r1, #0
66 movs r0, #0
67 bl PLT_SYM(_C_LABEL(__sigprocmask14))
68 #if !defined(__thumb__) || defined(_ARM_ARCH_T2)
69 pop {r0-r2, lr}
70 #else
71 pop {r0-r3}
72 mov lr, r3
73 #endif
74
75 ldr r1, .Lsetjmp_magic
76
77 #if defined(__ARM_EABI__) && (!defined(__thumb__) || defined(_ARM_ARCH_T2))
78 PCREL_GET(r2, .Lfpu_present, .LPIC0)
79 ldr r2, [r2]
80 #if defined(__thumb__) && defined(_ARM_ARCH_T2)
81 cbz r2, 1f /* don't save if we don't have a FPU */
82 #else
83 cmp r2, #0 /* do we have a FPU? */
84 beq 1f /* no, don't save VFP registers */
85 #endif
86
87 orrs r1, r1, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP)
88 /* change magic to VFP magic */
89 adds r2, r0, #(_JB_REG_D8 * 4)
90 vstmia r2, {d8-d15}
91 vmrs r2, fpscr
92 str r2, [r0, #(_JB_REG_FPSCR * 4)]
93 1:
94 #endif /* __ARM_EABI__ && (!__thumb__ || _ARM_ARCH_T2) */
95
96 str r1, [r0] /* store magic */
97
98 /* Store integer registers */
99 adds r0, r0, #(_JB_REG_R4 * 4)
100 #if !defined(__thumb__)
101 stmia r0!, {r4-lr}
102 #else
103 stmia r0!, {r4-r7}
104 mov r2, r8
105 mov r3, r9
106 stmia r0!, {r2-r3}
107 mov r2, r10
108 mov r3, r11
109 stmia r0!, {r2-r3}
110 mov r2, sp
111 mov r3, lr
112 str r2, [r0, #4]
113 str r3, [r0, #8]
114 #endif
115 movs r0, #0
116 RET
117
118 #if defined(__ARM_EABI__) && (!defined(__thumb__) || defined(_ARM_ARCH_T2))
119 .align 0
120 .Lfpu_present:
121 .word PCREL_SYM(_libc_arm_fpu_present, .LPIC0)
122 #endif /* __ARM_EABI__ && (!__thumb__ || _ARM_ARCH_T2) */
123 END(__setjmp14)
124
125 ENTRY(__longjmp14)
126 #if !defined(__thumb__) || defined(_ARM_ARCH_T2)
127 ldr r2, [r0]
128 ldr ip, .Lsetjmp_magic
129 bic r3, r2, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP)
130 #else
131 ldr r3, .Lsetjmp_magic
132 mov ip, r3
133 ldr r3, [r0]
134 movs r2, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP)
135 bics r3, r2
136 /* r2 is not the magic but we don't need it since we can't do VFP */
137 #endif
138 cmp r3, ip
139 bne .Lbotch
140
141 /* Validate sp and lr */
142 ldr r2, [r0, #(_JB_REG_R13 * 4)]
143 #if defined(__thumb__) && defined(_ARM_ARCH_T2)
144 cbz r2, .Lbotch
145 #else
146 cmp r2, #0
147 beq .Lbotch
148 #endif
149
150 ldr r3, [r0, #(_JB_REG_R14 * 4)]
151 #if defined(__thumb__) && defined(_ARM_ARCH_T2)
152 cbz r3, .Lbotch
153 #else
154 cmp r3, #0
155 beq .Lbotch
156 #endif
157 mov sp, r2
158 mov lr, r3
159
160 /* Restore the signal mask. */
161 push {r0-r2, lr}
162 movs r2, #0
163 #if !defined(__thumb__)
164 adds r1, r0, #(_JB_SIGMASK * 4)
165 #else
166 mov r1, r0
167 adds r1, r1, #(_JB_SIGMASK * 4)
168 #endif
169 movs r0, #3 /* SIG_SETMASK */
170 bl PLT_SYM(_C_LABEL(__sigprocmask14))
171 #if !defined(__thumb__) || defined(_ARM_ARCH_T2)
172 pop {r0-r2, lr}
173 #else
174 pop {r0-r3}
175 mov lr, r3
176 #endif
177
178 #if defined(__ARM_EABI__) && (!defined(__thumb__) || defined(_ARM_ARCH_T2))
179 tst r2, #(_JB_MAGIC_SETJMP ^ _JB_MAGIC_SETJMP_VFP)
180 /* is this a VFP magic? */
181 beq 1f /* no, don't restore VFP */
182 adds r2, r0, #(_JB_REG_D8 * 4)
183 vldmia r2, {d8-d15}
184 ldr r2, [r0, #(_JB_REG_FPSCR * 4)]
185 vmsr fpscr, r2
186 1:
187 #endif /* __ARM_EABI__ && (!__thumb__ || _ARM_ARCH_T2) */
188
189 adds r0, r0, #(_JB_REG_R4 * 4)
190 /* Restore integer registers */
191 #if !defined(__thumb__) || defined(_ARM_ARCH_T2)
192 ldmia r0!, {r4-r12}
193 #else
194 ldmia r0!, {r4-r7}
195 ldmia r0!, {r2-r3}
196 mov r8, r2
197 mov r9, r3
198 ldmia r0!, {r2-r3}
199 mov r10, r2
200 mov r11, r3
201 adds r0, r0, #4 /* skip ip(r12) */
202 #endif
203
204 /* Set return value */
205 movs r0, r1
206 #if !defined(__thumb__)
207 moveq r0, #1
208 #else
209 bne 1f
210 movs r0, #1
211 1:
212 #endif
213 RET
214
215 /* validation failed, die die die. */
216 .Lbotch:
217 bl PLT_SYM(_C_LABEL(longjmperror))
218 bl PLT_SYM(_C_LABEL(abort))
219 1: b 1b /* Cannot get here */
220
221 .align 0
222 .Lsetjmp_magic:
223 .word _JB_MAGIC_SETJMP
224 END(__longjmp14)
225