libunwind-arm.S revision 169689
1169689Skan/* Support functions for the unwinder.
2169689Skan   Copyright (C) 2003, 2004, 2005  Free Software Foundation, Inc.
3169689Skan   Contributed by Paul Brook
4169689Skan
5169689Skan   This file is free software; you can redistribute it and/or modify it
6169689Skan   under the terms of the GNU General Public License as published by the
7169689Skan   Free Software Foundation; either version 2, or (at your option) any
8169689Skan   later version.
9169689Skan
10169689Skan   In addition to the permissions in the GNU General Public License, the
11169689Skan   Free Software Foundation gives you unlimited permission to link the
12169689Skan   compiled version of this file into combinations with other programs,
13169689Skan   and to distribute those combinations without any restriction coming
14169689Skan   from the use of this file.  (The General Public License restrictions
15169689Skan   do apply in other respects; for example, they cover modification of
16169689Skan   the file, and distribution when not linked into a combine
17169689Skan   executable.)
18169689Skan
19169689Skan   This file is distributed in the hope that it will be useful, but
20169689Skan   WITHOUT ANY WARRANTY; without even the implied warranty of
21169689Skan   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22169689Skan   General Public License for more details.
23169689Skan
24169689Skan   You should have received a copy of the GNU General Public License
25169689Skan   along with this program; see the file COPYING.  If not, write to
26169689Skan   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27169689Skan   Boston, MA 02110-1301, USA.  */
28169689Skan
29169689Skan#ifndef __symbian__
30169689Skan
31169689Skan#include "lib1funcs.asm"
32169689Skan
33169689Skan.macro UNPREFIX name
34169689Skan	.global SYM (\name)
35169689Skan	EQUIV SYM (\name), SYM (__\name)
36169689Skan.endm
37169689Skan
38169689Skan/* r0 points to a 16-word block.  Upload these values to the actual core
39169689Skan   state.  */
40169689SkanARM_FUNC_START restore_core_regs
41169689Skan	/* We must use sp as the base register when restoring sp.  Push the
42169689Skan	   last 3 registers onto the top of the current stack to achieve
43169689Skan	   this.  */
44169689Skan	add r1, r0, #52
45169689Skan	ldmia r1, {r3, r4, r5}  /* {sp, lr, pc}.  */
46169689Skan#ifdef __INTERWORKING__
47169689Skan	/* Restore pc into ip.  */
48169689Skan	mov r2, r5
49169689Skan	stmfd sp!, {r2, r3, r4}
50169689Skan#else
51169689Skan	stmfd sp!, {r3, r4, r5}
52169689Skan#endif
53169689Skan	/* Don't bother restoring ip.  */
54169689Skan	ldmia r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp}
55169689Skan	/* Pop the three registers we pushed earlier.  */
56169689Skan#ifdef __INTERWORKING__
57169689Skan	ldmfd sp, {ip, sp, lr}
58169689Skan	bx ip
59169689Skan#else
60169689Skan	ldmfd sp, {sp, lr, pc}
61169689Skan#endif
62169689Skan	FUNC_END restore_core_regs
63169689Skan	UNPREFIX restore_core_regs
64169689Skan
65169689Skan/* Load VFP registers d0-d15 from the address in r0.  */
66169689SkanARM_FUNC_START gnu_Unwind_Restore_VFP
67169689Skan	/* Use the generic coprocessor form so that gas doesn't complain
68169689Skan	   on soft-float targets.  */
69169689Skan	ldc   p11,cr0,[r0],{0x21} /* fldmiax r0, {d0-d15} */
70169689Skan	RET
71169689Skan
72169689Skan/* Store VFR regsters d0-d15 to the address in r0.  */
73169689SkanARM_FUNC_START gnu_Unwind_Save_VFP
74169689Skan	/* Use the generic coprocessor form so that gas doesn't complain
75169689Skan	   on soft-float targets.  */
76169689Skan	stc   p11,cr0,[r0],{0x21} /* fstmiax r0, {d0-d15} */
77169689Skan	RET
78169689Skan
79169689Skan/* Wrappers to save core registers, then call the real routine.   */
80169689Skan
81169689Skan.macro  UNWIND_WRAPPER name nargs
82169689Skan	ARM_FUNC_START \name
83169689Skan	/* Create a phase2_vrs structure.  */
84169689Skan	/* Split reg push in two to ensure the correct value for sp.  */
85169689Skan	stmfd sp!, {sp, lr, pc}
86169689Skan	stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip}
87169689Skan
88169689Skan	/* Demand-save flags, plus an extra word for alignment.  */
89169689Skan	mov r3, #0
90169689Skan	stmfd sp!, {r2, r3}
91169689Skan
92169689Skan	/* Point r1 at the block.  Pass r[0..nargs) unchanged.  */
93169689Skan	add r\nargs, sp, #4
94169689Skan#if defined(__thumb__)
95169689Skan	/* Switch back to thumb mode to avoid interworking hassle.  */
96169689Skan	adr ip, .L1_\name
97169689Skan	orr ip, ip, #1
98169689Skan	bx ip
99169689Skan	.thumb
100169689Skan.L1_\name:
101169689Skan	bl SYM (__gnu\name) __PLT__
102169689Skan	ldr r3, [sp, #64]
103169689Skan	add sp, #72
104169689Skan	bx r3
105169689Skan#else
106169689Skan	bl SYM (__gnu\name) __PLT__
107169689Skan	ldr lr, [sp, #64]
108169689Skan	add sp, sp, #72
109169689Skan	RET
110169689Skan#endif
111169689Skan	FUNC_END \name
112169689Skan	UNPREFIX \name
113169689Skan.endm
114169689Skan
115169689SkanUNWIND_WRAPPER _Unwind_RaiseException 1
116169689SkanUNWIND_WRAPPER _Unwind_Resume 1
117169689SkanUNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
118169689SkanUNWIND_WRAPPER _Unwind_ForcedUnwind 3
119169689Skan
120169689Skan#endif  /* __symbian__ */
121