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
29275380Sandrew#include <machine/acle-compat.h>
30275380Sandrew
31275380Sandrew/* Allow the use of VFP instructions */
32275380Sandrew#if __ARM_ARCH >= 7
33275380Sandrew.fpu	vfp
34275380Sandrew#endif
35275380Sandrew
36169689Skan#ifndef __symbian__
37169689Skan
38169689Skan#include "lib1funcs.asm"
39169689Skan
40169689Skan.macro UNPREFIX name
41169689Skan	.global SYM (\name)
42169689Skan	EQUIV SYM (\name), SYM (__\name)
43169689Skan.endm
44169689Skan
45169689Skan/* r0 points to a 16-word block.  Upload these values to the actual core
46169689Skan   state.  */
47169689SkanARM_FUNC_START restore_core_regs
48169689Skan	/* We must use sp as the base register when restoring sp.  Push the
49169689Skan	   last 3 registers onto the top of the current stack to achieve
50169689Skan	   this.  */
51169689Skan	add r1, r0, #52
52169689Skan	ldmia r1, {r3, r4, r5}  /* {sp, lr, pc}.  */
53169689Skan#ifdef __INTERWORKING__
54169689Skan	/* Restore pc into ip.  */
55169689Skan	mov r2, r5
56169689Skan	stmfd sp!, {r2, r3, r4}
57169689Skan#else
58169689Skan	stmfd sp!, {r3, r4, r5}
59169689Skan#endif
60169689Skan	/* Don't bother restoring ip.  */
61169689Skan	ldmia r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp}
62169689Skan	/* Pop the three registers we pushed earlier.  */
63169689Skan#ifdef __INTERWORKING__
64169689Skan	ldmfd sp, {ip, sp, lr}
65169689Skan	bx ip
66169689Skan#else
67169689Skan	ldmfd sp, {sp, lr, pc}
68169689Skan#endif
69169689Skan	FUNC_END restore_core_regs
70169689Skan	UNPREFIX restore_core_regs
71169689Skan
72169689Skan/* Load VFP registers d0-d15 from the address in r0.  */
73169689SkanARM_FUNC_START gnu_Unwind_Restore_VFP
74169689Skan	/* Use the generic coprocessor form so that gas doesn't complain
75169689Skan	   on soft-float targets.  */
76275380Sandrew#if __ARM_ARCH >= 7
77275380Sandrew	fldmiax r0, {d0-d15}
78275380Sandrew#else
79169689Skan	ldc   p11,cr0,[r0],{0x21} /* fldmiax r0, {d0-d15} */
80275380Sandrew#endif
81169689Skan	RET
82169689Skan
83169689Skan/* Store VFR regsters d0-d15 to the address in r0.  */
84169689SkanARM_FUNC_START gnu_Unwind_Save_VFP
85169689Skan	/* Use the generic coprocessor form so that gas doesn't complain
86169689Skan	   on soft-float targets.  */
87275380Sandrew#if __ARM_ARCH >= 7
88275380Sandrew	fstmiax r0, {d0-d15}
89275380Sandrew#else
90169689Skan	stc   p11,cr0,[r0],{0x21} /* fstmiax r0, {d0-d15} */
91275380Sandrew#endif
92169689Skan	RET
93169689Skan
94169689Skan/* Wrappers to save core registers, then call the real routine.   */
95169689Skan
96169689Skan.macro  UNWIND_WRAPPER name nargs
97169689Skan	ARM_FUNC_START \name
98169689Skan	/* Create a phase2_vrs structure.  */
99169689Skan	/* Split reg push in two to ensure the correct value for sp.  */
100169689Skan	stmfd sp!, {sp, lr, pc}
101169689Skan	stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip}
102169689Skan
103169689Skan	/* Demand-save flags, plus an extra word for alignment.  */
104169689Skan	mov r3, #0
105169689Skan	stmfd sp!, {r2, r3}
106169689Skan
107169689Skan	/* Point r1 at the block.  Pass r[0..nargs) unchanged.  */
108169689Skan	add r\nargs, sp, #4
109169689Skan#if defined(__thumb__)
110169689Skan	/* Switch back to thumb mode to avoid interworking hassle.  */
111169689Skan	adr ip, .L1_\name
112169689Skan	orr ip, ip, #1
113169689Skan	bx ip
114169689Skan	.thumb
115169689Skan.L1_\name:
116169689Skan	bl SYM (__gnu\name) __PLT__
117169689Skan	ldr r3, [sp, #64]
118169689Skan	add sp, #72
119169689Skan	bx r3
120169689Skan#else
121169689Skan	bl SYM (__gnu\name) __PLT__
122169689Skan	ldr lr, [sp, #64]
123169689Skan	add sp, sp, #72
124169689Skan	RET
125169689Skan#endif
126169689Skan	FUNC_END \name
127169689Skan	UNPREFIX \name
128169689Skan.endm
129169689Skan
130169689SkanUNWIND_WRAPPER _Unwind_RaiseException 1
131169689SkanUNWIND_WRAPPER _Unwind_Resume 1
132169689SkanUNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
133169689SkanUNWIND_WRAPPER _Unwind_ForcedUnwind 3
134255095SandrewUNWIND_WRAPPER _Unwind_Backtrace 2
135169689Skan
136318714Smmel/*
137318714Smmel * Originally, we incorrectly export _Unwind_Backtrace symbol
138318714Smmel * with  GCC_3.3 version, but real GCC libgcc export it as GCC_4.3.0.
139318714Smmel * To maintain  backward compatibility, export it with both versions where
140318714Smmel * GCC_4.3.0 is default one.
141318714Smmel *
142318714Smmel * The workaround is complicated by next two issues:
143318714Smmel *  - old GNU ld cannot handle two (or more) symbol versions
144318714Smmel *    targeting same function.
145318714Smmel *  - the .weakref crashes clang 4.0
146318714Smmel */
147318714Smmel	.globl	SYM(_Unwind_Backtrace33)
148318714Smmel	TYPE(_Unwind_Backtrace33)
149318714SmmelSYM(_Unwind_Backtrace33):
150318714Smmel	b _Unwind_Backtrace
151318714Smmel
152318714Smmel	.symver	SYM(_Unwind_Backtrace33),_Unwind_Backtrace@GCC_3.3
153318714Smmel
154255095Sandrew#endif  /* ndef __symbian__ */
155