1 /* Support functions for the unwinder.
2 Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Paul Brook
6 This file is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
11 This file is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 /* An executable stack is *not* required for these functions. */
26 #if defined(__ELF__) && defined(__linux__)
27 .section .note.GNU-stack,"",%progbits
32 /* Some attributes that are common to all routines in this file. */
33 /* Tag_ABI_align_needed: This code does not require 8-byte
34 alignment from the caller. */
35 /* .eabi_attribute 24, 0 -- default setting. */
36 /* Tag_ABI_align_preserved: This code preserves 8-byte
37 alignment in any callee. */
39 #endif /* __ARM_EABI__ */
43 #include "lib1funcs.asm"
47 EQUIV SYM (\name), SYM (__\name)
50 #if (__ARM_ARCH__ == 4)
51 /* Some coprocessors require armv5. We know this code will never be run on
52 other cpus. Tell gas to allow armv5, but only mark the objects as armv4.
55 #ifdef __ARM_ARCH_4T__
62 #ifdef __ARM_ARCH_6M__
64 /* r0 points to a 16-word block. Upload these values to the actual core
66 FUNC_START restore_core_regs
69 ldmia r1!, {r3, r4, r5}
77 ldmia r1!, {r2, r3, r4, r5}
84 ldmia r1!, {r2, r3, r4, r5, r6, r7}
89 FUNC_END restore_core_regs
90 UNPREFIX restore_core_regs
92 /* ARMV6M does not have coprocessors, so these should never be used. */
93 FUNC_START gnu_Unwind_Restore_VFP
96 /* Store VFR regsters d0-d15 to the address in r0. */
97 FUNC_START gnu_Unwind_Save_VFP
100 /* Load VFP registers d0-d15 from the address in r0.
101 Use this to load from FSTMD format. */
102 FUNC_START gnu_Unwind_Restore_VFP_D
105 /* Store VFP registers d0-d15 to the address in r0.
106 Use this to store in FLDMD format. */
107 FUNC_START gnu_Unwind_Save_VFP_D
110 /* Load VFP registers d16-d31 from the address in r0.
111 Use this to load from FSTMD (=VSTM) format. Needs VFPv3. */
112 FUNC_START gnu_Unwind_Restore_VFP_D_16_to_31
115 /* Store VFP registers d16-d31 to the address in r0.
116 Use this to store in FLDMD (=VLDM) format. Needs VFPv3. */
117 FUNC_START gnu_Unwind_Save_VFP_D_16_to_31
120 FUNC_START gnu_Unwind_Restore_WMMXD
123 FUNC_START gnu_Unwind_Save_WMMXD
126 FUNC_START gnu_Unwind_Restore_WMMXC
129 FUNC_START gnu_Unwind_Save_WMMXC
132 .macro UNWIND_WRAPPER name nargs
134 /* Create a phase2_vrs structure. */
135 /* Save r0 in the PC slot so we can use it as a scratch register. */
138 push {r0, lr} /* Push original SP and LR. */
139 /* Make space for r8-r12. */
141 /* Save low registers. */
142 push {r0, r1, r2, r3, r4, r5, r6, r7}
143 /* Save high registers. */
150 stmia r0!, {r1, r2, r3, r4, r5}
151 /* Restore original low register values. */
153 ldmia r0!, {r1, r2, r3, r4, r5}
154 /* Restore orginial r0. */
157 /* Demand-save flags, plus an extra word for alignment. */
160 /* Point r1 at the block. Pass r[0..nargs) unchanged. */
173 #else /* !__ARM_ARCH_6M__ */
175 /* r0 points to a 16-word block. Upload these values to the actual core
177 ARM_FUNC_START restore_core_regs
178 /* We must use sp as the base register when restoring sp. Push the
179 last 3 registers onto the top of the current stack to achieve
182 ldmia r1, {r3, r4, r5} /* {sp, lr, pc}. */
183 #if defined(__thumb2__)
184 /* Thumb-2 doesn't allow sp in a load-multiple instruction, so push
185 the target address onto the target stack. This is safe as
186 we're always returning to somewhere further up the call stack. */
190 #elif defined(__INTERWORKING__)
191 /* Restore pc into ip. */
193 stmfd sp!, {r2, r3, r4}
195 stmfd sp!, {r3, r4, r5}
197 /* Don't bother restoring ip. */
198 ldmia r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp}
199 #if defined(__thumb2__)
200 /* Pop the return address off the target stack. */
203 #elif defined(__INTERWORKING__)
204 /* Pop the three registers we pushed earlier. */
205 ldmfd sp, {ip, sp, lr}
208 ldmfd sp, {sp, lr, pc}
210 FUNC_END restore_core_regs
211 UNPREFIX restore_core_regs
213 /* Load VFP registers d0-d15 from the address in r0.
214 Use this to load from FSTMX format. */
215 ARM_FUNC_START gnu_Unwind_Restore_VFP
216 /* Use the generic coprocessor form so that gas doesn't complain
217 on soft-float targets. */
218 ldc p11,cr0,[r0],{0x21} /* fldmiax r0, {d0-d15} */
221 /* Store VFP registers d0-d15 to the address in r0.
222 Use this to store in FSTMX format. */
223 ARM_FUNC_START gnu_Unwind_Save_VFP
224 /* Use the generic coprocessor form so that gas doesn't complain
225 on soft-float targets. */
226 stc p11,cr0,[r0],{0x21} /* fstmiax r0, {d0-d15} */
229 /* Load VFP registers d0-d15 from the address in r0.
230 Use this to load from FSTMD format. */
231 ARM_FUNC_START gnu_Unwind_Restore_VFP_D
232 ldc p11,cr0,[r0],{0x20} /* fldmiad r0, {d0-d15} */
235 /* Store VFP registers d0-d15 to the address in r0.
236 Use this to store in FLDMD format. */
237 ARM_FUNC_START gnu_Unwind_Save_VFP_D
238 stc p11,cr0,[r0],{0x20} /* fstmiad r0, {d0-d15} */
241 /* Load VFP registers d16-d31 from the address in r0.
242 Use this to load from FSTMD (=VSTM) format. Needs VFPv3. */
243 ARM_FUNC_START gnu_Unwind_Restore_VFP_D_16_to_31
244 ldcl p11,cr0,[r0],{0x20} /* vldm r0, {d16-d31} */
247 /* Store VFP registers d16-d31 to the address in r0.
248 Use this to store in FLDMD (=VLDM) format. Needs VFPv3. */
249 ARM_FUNC_START gnu_Unwind_Save_VFP_D_16_to_31
250 stcl p11,cr0,[r0],{0x20} /* vstm r0, {d16-d31} */
253 ARM_FUNC_START gnu_Unwind_Restore_WMMXD
254 /* Use the generic coprocessor form so that gas doesn't complain
255 on non-iWMMXt targets. */
256 ldcl p1, cr0, [r0], #8 /* wldrd wr0, [r0], #8 */
257 ldcl p1, cr1, [r0], #8 /* wldrd wr1, [r0], #8 */
258 ldcl p1, cr2, [r0], #8 /* wldrd wr2, [r0], #8 */
259 ldcl p1, cr3, [r0], #8 /* wldrd wr3, [r0], #8 */
260 ldcl p1, cr4, [r0], #8 /* wldrd wr4, [r0], #8 */
261 ldcl p1, cr5, [r0], #8 /* wldrd wr5, [r0], #8 */
262 ldcl p1, cr6, [r0], #8 /* wldrd wr6, [r0], #8 */
263 ldcl p1, cr7, [r0], #8 /* wldrd wr7, [r0], #8 */
264 ldcl p1, cr8, [r0], #8 /* wldrd wr8, [r0], #8 */
265 ldcl p1, cr9, [r0], #8 /* wldrd wr9, [r0], #8 */
266 ldcl p1, cr10, [r0], #8 /* wldrd wr10, [r0], #8 */
267 ldcl p1, cr11, [r0], #8 /* wldrd wr11, [r0], #8 */
268 ldcl p1, cr12, [r0], #8 /* wldrd wr12, [r0], #8 */
269 ldcl p1, cr13, [r0], #8 /* wldrd wr13, [r0], #8 */
270 ldcl p1, cr14, [r0], #8 /* wldrd wr14, [r0], #8 */
271 ldcl p1, cr15, [r0], #8 /* wldrd wr15, [r0], #8 */
274 ARM_FUNC_START gnu_Unwind_Save_WMMXD
275 /* Use the generic coprocessor form so that gas doesn't complain
276 on non-iWMMXt targets. */
277 stcl p1, cr0, [r0], #8 /* wstrd wr0, [r0], #8 */
278 stcl p1, cr1, [r0], #8 /* wstrd wr1, [r0], #8 */
279 stcl p1, cr2, [r0], #8 /* wstrd wr2, [r0], #8 */
280 stcl p1, cr3, [r0], #8 /* wstrd wr3, [r0], #8 */
281 stcl p1, cr4, [r0], #8 /* wstrd wr4, [r0], #8 */
282 stcl p1, cr5, [r0], #8 /* wstrd wr5, [r0], #8 */
283 stcl p1, cr6, [r0], #8 /* wstrd wr6, [r0], #8 */
284 stcl p1, cr7, [r0], #8 /* wstrd wr7, [r0], #8 */
285 stcl p1, cr8, [r0], #8 /* wstrd wr8, [r0], #8 */
286 stcl p1, cr9, [r0], #8 /* wstrd wr9, [r0], #8 */
287 stcl p1, cr10, [r0], #8 /* wstrd wr10, [r0], #8 */
288 stcl p1, cr11, [r0], #8 /* wstrd wr11, [r0], #8 */
289 stcl p1, cr12, [r0], #8 /* wstrd wr12, [r0], #8 */
290 stcl p1, cr13, [r0], #8 /* wstrd wr13, [r0], #8 */
291 stcl p1, cr14, [r0], #8 /* wstrd wr14, [r0], #8 */
292 stcl p1, cr15, [r0], #8 /* wstrd wr15, [r0], #8 */
295 ARM_FUNC_START gnu_Unwind_Restore_WMMXC
296 /* Use the generic coprocessor form so that gas doesn't complain
297 on non-iWMMXt targets. */
298 ldc2 p1, cr8, [r0], #4 /* wldrw wcgr0, [r0], #4 */
299 ldc2 p1, cr9, [r0], #4 /* wldrw wcgr1, [r0], #4 */
300 ldc2 p1, cr10, [r0], #4 /* wldrw wcgr2, [r0], #4 */
301 ldc2 p1, cr11, [r0], #4 /* wldrw wcgr3, [r0], #4 */
304 ARM_FUNC_START gnu_Unwind_Save_WMMXC
305 /* Use the generic coprocessor form so that gas doesn't complain
306 on non-iWMMXt targets. */
307 stc2 p1, cr8, [r0], #4 /* wstrw wcgr0, [r0], #4 */
308 stc2 p1, cr9, [r0], #4 /* wstrw wcgr1, [r0], #4 */
309 stc2 p1, cr10, [r0], #4 /* wstrw wcgr2, [r0], #4 */
310 stc2 p1, cr11, [r0], #4 /* wstrw wcgr3, [r0], #4 */
313 /* Wrappers to save core registers, then call the real routine. */
315 .macro UNWIND_WRAPPER name nargs
317 /* Create a phase2_vrs structure. */
318 /* Split reg push in two to ensure the correct value for sp. */
319 #if defined(__thumb2__)
321 push {lr} /* PC is ignored. */
322 push {ip, lr} /* Push original SP and LR. */
324 stmfd sp!, {sp, lr, pc}
326 stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip}
328 /* Demand-save flags, plus an extra word for alignment. */
332 /* Point r1 at the block. Pass r[0..nargs) unchanged. */
334 #if defined(__thumb__) && !defined(__thumb2__)
335 /* Switch back to thumb mode to avoid interworking hassle. */
341 bl SYM (__gnu\name) __PLT__
346 bl SYM (__gnu\name) __PLT__
355 #endif /* !__ARM_ARCH_6M__ */
357 UNWIND_WRAPPER _Unwind_RaiseException 1
358 UNWIND_WRAPPER _Unwind_Resume 1
359 UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
360 UNWIND_WRAPPER _Unwind_ForcedUnwind 3
361 UNWIND_WRAPPER _Unwind_Backtrace 2
363 #endif /* ndef __symbian__ */