0
|
1 /* Support functions for the unwinder.
|
|
2 Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
|
|
3 Contributed by Paul Brook
|
|
4
|
|
5 This file is free software; you can redistribute it and/or modify it
|
|
6 under the terms of the GNU General Public License as published by the
|
|
7 Free Software Foundation; either version 3, or (at your option) any
|
|
8 later version.
|
|
9
|
|
10 This file is distributed in the hope that it will be useful, but
|
|
11 WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13 General Public License for more details.
|
|
14
|
|
15 Under Section 7 of GPL version 3, you are granted additional
|
|
16 permissions described in the GCC Runtime Library Exception, version
|
|
17 3.1, as published by the Free Software Foundation.
|
|
18
|
|
19 You should have received a copy of the GNU General Public License and
|
|
20 a copy of the GCC Runtime Library Exception along with this program;
|
|
21 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
22 <http://www.gnu.org/licenses/>. */
|
|
23
|
|
24 /* An executable stack is *not* required for these functions. */
|
|
25 #if defined(__ELF__) && defined(__linux__)
|
|
26 .section .note.GNU-stack,"",%progbits
|
|
27 .previous
|
|
28 #endif
|
|
29
|
|
30 #ifndef __symbian__
|
|
31
|
|
32 #include "lib1funcs.asm"
|
|
33
|
|
34 .macro UNPREFIX name
|
|
35 .global SYM (\name)
|
|
36 EQUIV SYM (\name), SYM (__\name)
|
|
37 .endm
|
|
38
|
|
39 #if (__ARM_ARCH__ == 4)
|
|
40 /* Some coprocessors require armv5. We know this code will never be run on
|
|
41 other cpus. Tell gas to allow armv5, but only mark the objects as armv4.
|
|
42 */
|
|
43 .arch armv5t
|
|
44 #ifdef __ARM_ARCH_4T__
|
|
45 .object_arch armv4t
|
|
46 #else
|
|
47 .object_arch armv4
|
|
48 #endif
|
|
49 #endif
|
|
50
|
|
51 #ifdef __ARM_ARCH_6M__
|
|
52
|
|
53 /* r0 points to a 16-word block. Upload these values to the actual core
|
|
54 state. */
|
|
55 FUNC_START restore_core_regs
|
|
56 mov r1, r0
|
|
57 add r1, r1, #52
|
|
58 ldmia r1!, {r3, r4, r5}
|
|
59 sub r3, r3, #4
|
|
60 mov ip, r3
|
|
61 str r5, [r3]
|
|
62 mov lr, r4
|
|
63 /* Restore r8-r11. */
|
|
64 mov r1, r0
|
|
65 add r1, r1, #32
|
|
66 ldmia r1!, {r2, r3, r4, r5}
|
|
67 mov r8, r2
|
|
68 mov r9, r3
|
|
69 mov sl, r4
|
|
70 mov fp, r5
|
|
71 mov r1, r0
|
|
72 add r1, r1, #8
|
|
73 ldmia r1!, {r2, r3, r4, r5, r6, r7}
|
|
74 ldr r1, [r0, #4]
|
|
75 ldr r0, [r0]
|
|
76 mov sp, ip
|
|
77 pop {pc}
|
|
78 FUNC_END restore_core_regs
|
|
79 UNPREFIX restore_core_regs
|
|
80
|
|
81 /* ARMV6M does not have coprocessors, so these should never be used. */
|
|
82 FUNC_START gnu_Unwind_Restore_VFP
|
|
83 RET
|
|
84
|
|
85 /* Store VFR regsters d0-d15 to the address in r0. */
|
|
86 FUNC_START gnu_Unwind_Save_VFP
|
|
87 RET
|
|
88
|
|
89 /* Load VFP registers d0-d15 from the address in r0.
|
|
90 Use this to load from FSTMD format. */
|
|
91 FUNC_START gnu_Unwind_Restore_VFP_D
|
|
92 RET
|
|
93
|
|
94 /* Store VFP registers d0-d15 to the address in r0.
|
|
95 Use this to store in FLDMD format. */
|
|
96 FUNC_START gnu_Unwind_Save_VFP_D
|
|
97 RET
|
|
98
|
|
99 /* Load VFP registers d16-d31 from the address in r0.
|
|
100 Use this to load from FSTMD (=VSTM) format. Needs VFPv3. */
|
|
101 FUNC_START gnu_Unwind_Restore_VFP_D_16_to_31
|
|
102 RET
|
|
103
|
|
104 /* Store VFP registers d16-d31 to the address in r0.
|
|
105 Use this to store in FLDMD (=VLDM) format. Needs VFPv3. */
|
|
106 FUNC_START gnu_Unwind_Save_VFP_D_16_to_31
|
|
107 RET
|
|
108
|
|
109 FUNC_START gnu_Unwind_Restore_WMMXD
|
|
110 RET
|
|
111
|
|
112 FUNC_START gnu_Unwind_Save_WMMXD
|
|
113 RET
|
|
114
|
|
115 FUNC_START gnu_Unwind_Restore_WMMXC
|
|
116 RET
|
|
117
|
|
118 FUNC_START gnu_Unwind_Save_WMMXC
|
|
119 RET
|
|
120
|
|
121 .macro UNWIND_WRAPPER name nargs
|
|
122 FUNC_START \name
|
|
123 /* Create a phase2_vrs structure. */
|
|
124 /* Save r0 in the PC slot so we can use it as a scratch register. */
|
|
125 push {r0}
|
|
126 add r0, sp, #4
|
|
127 push {r0, lr} /* Push original SP and LR. */
|
|
128 /* Make space for r8-r12. */
|
|
129 sub sp, sp, #20
|
|
130 /* Save low registers. */
|
|
131 push {r0, r1, r2, r3, r4, r5, r6, r7}
|
|
132 /* Save high registers. */
|
|
133 add r0, sp, #32
|
|
134 mov r1, r8
|
|
135 mov r2, r9
|
|
136 mov r3, sl
|
|
137 mov r4, fp
|
|
138 mov r5, ip
|
|
139 stmia r0!, {r1, r2, r3, r4, r5}
|
|
140 /* Restore original low register values. */
|
|
141 add r0, sp, #4
|
|
142 ldmia r0!, {r1, r2, r3, r4, r5}
|
|
143 /* Restore orginial r0. */
|
|
144 ldr r0, [sp, #60]
|
|
145 str r0, [sp]
|
|
146 /* Demand-save flags, plus an extra word for alignment. */
|
|
147 mov r3, #0
|
|
148 push {r2, r3}
|
|
149 /* Point r1 at the block. Pass r[0..nargs) unchanged. */
|
|
150 add r\nargs, sp, #4
|
|
151
|
|
152 bl SYM (__gnu\name)
|
|
153
|
|
154 ldr r3, [sp, #64]
|
|
155 add sp, sp, #72
|
|
156 bx r3
|
|
157
|
|
158 FUNC_END \name
|
|
159 UNPREFIX \name
|
|
160 .endm
|
|
161
|
|
162 #else /* !__ARM_ARCH_6M__ */
|
|
163
|
|
164 /* r0 points to a 16-word block. Upload these values to the actual core
|
|
165 state. */
|
|
166 ARM_FUNC_START restore_core_regs
|
|
167 /* We must use sp as the base register when restoring sp. Push the
|
|
168 last 3 registers onto the top of the current stack to achieve
|
|
169 this. */
|
|
170 add r1, r0, #52
|
|
171 ldmia r1, {r3, r4, r5} /* {sp, lr, pc}. */
|
|
172 #if defined(__thumb2__)
|
|
173 /* Thumb-2 doesn't allow sp in a load-multiple instruction, so push
|
|
174 the target address onto the target stack. This is safe as
|
|
175 we're always returning to somewhere further up the call stack. */
|
|
176 mov ip, r3
|
|
177 mov lr, r4
|
|
178 str r5, [ip, #-4]!
|
|
179 #elif defined(__INTERWORKING__)
|
|
180 /* Restore pc into ip. */
|
|
181 mov r2, r5
|
|
182 stmfd sp!, {r2, r3, r4}
|
|
183 #else
|
|
184 stmfd sp!, {r3, r4, r5}
|
|
185 #endif
|
|
186 /* Don't bother restoring ip. */
|
|
187 ldmia r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp}
|
|
188 #if defined(__thumb2__)
|
|
189 /* Pop the return address off the target stack. */
|
|
190 mov sp, ip
|
|
191 pop {pc}
|
|
192 #elif defined(__INTERWORKING__)
|
|
193 /* Pop the three registers we pushed earlier. */
|
|
194 ldmfd sp, {ip, sp, lr}
|
|
195 bx ip
|
|
196 #else
|
|
197 ldmfd sp, {sp, lr, pc}
|
|
198 #endif
|
|
199 FUNC_END restore_core_regs
|
|
200 UNPREFIX restore_core_regs
|
|
201
|
|
202 /* Load VFP registers d0-d15 from the address in r0.
|
|
203 Use this to load from FSTMX format. */
|
|
204 ARM_FUNC_START gnu_Unwind_Restore_VFP
|
|
205 /* Use the generic coprocessor form so that gas doesn't complain
|
|
206 on soft-float targets. */
|
|
207 ldc p11,cr0,[r0],{0x21} /* fldmiax r0, {d0-d15} */
|
|
208 RET
|
|
209
|
|
210 /* Store VFP registers d0-d15 to the address in r0.
|
|
211 Use this to store in FSTMX format. */
|
|
212 ARM_FUNC_START gnu_Unwind_Save_VFP
|
|
213 /* Use the generic coprocessor form so that gas doesn't complain
|
|
214 on soft-float targets. */
|
|
215 stc p11,cr0,[r0],{0x21} /* fstmiax r0, {d0-d15} */
|
|
216 RET
|
|
217
|
|
218 /* Load VFP registers d0-d15 from the address in r0.
|
|
219 Use this to load from FSTMD format. */
|
|
220 ARM_FUNC_START gnu_Unwind_Restore_VFP_D
|
|
221 ldc p11,cr0,[r0],{0x20} /* fldmiad r0, {d0-d15} */
|
|
222 RET
|
|
223
|
|
224 /* Store VFP registers d0-d15 to the address in r0.
|
|
225 Use this to store in FLDMD format. */
|
|
226 ARM_FUNC_START gnu_Unwind_Save_VFP_D
|
|
227 stc p11,cr0,[r0],{0x20} /* fstmiad r0, {d0-d15} */
|
|
228 RET
|
|
229
|
|
230 /* Load VFP registers d16-d31 from the address in r0.
|
|
231 Use this to load from FSTMD (=VSTM) format. Needs VFPv3. */
|
|
232 ARM_FUNC_START gnu_Unwind_Restore_VFP_D_16_to_31
|
|
233 ldcl p11,cr0,[r0],{0x20} /* vldm r0, {d16-d31} */
|
|
234 RET
|
|
235
|
|
236 /* Store VFP registers d16-d31 to the address in r0.
|
|
237 Use this to store in FLDMD (=VLDM) format. Needs VFPv3. */
|
|
238 ARM_FUNC_START gnu_Unwind_Save_VFP_D_16_to_31
|
|
239 stcl p11,cr0,[r0],{0x20} /* vstm r0, {d16-d31} */
|
|
240 RET
|
|
241
|
|
242 ARM_FUNC_START gnu_Unwind_Restore_WMMXD
|
|
243 /* Use the generic coprocessor form so that gas doesn't complain
|
|
244 on non-iWMMXt targets. */
|
|
245 ldcl p1, cr0, [r0], #8 /* wldrd wr0, [r0], #8 */
|
|
246 ldcl p1, cr1, [r0], #8 /* wldrd wr1, [r0], #8 */
|
|
247 ldcl p1, cr2, [r0], #8 /* wldrd wr2, [r0], #8 */
|
|
248 ldcl p1, cr3, [r0], #8 /* wldrd wr3, [r0], #8 */
|
|
249 ldcl p1, cr4, [r0], #8 /* wldrd wr4, [r0], #8 */
|
|
250 ldcl p1, cr5, [r0], #8 /* wldrd wr5, [r0], #8 */
|
|
251 ldcl p1, cr6, [r0], #8 /* wldrd wr6, [r0], #8 */
|
|
252 ldcl p1, cr7, [r0], #8 /* wldrd wr7, [r0], #8 */
|
|
253 ldcl p1, cr8, [r0], #8 /* wldrd wr8, [r0], #8 */
|
|
254 ldcl p1, cr9, [r0], #8 /* wldrd wr9, [r0], #8 */
|
|
255 ldcl p1, cr10, [r0], #8 /* wldrd wr10, [r0], #8 */
|
|
256 ldcl p1, cr11, [r0], #8 /* wldrd wr11, [r0], #8 */
|
|
257 ldcl p1, cr12, [r0], #8 /* wldrd wr12, [r0], #8 */
|
|
258 ldcl p1, cr13, [r0], #8 /* wldrd wr13, [r0], #8 */
|
|
259 ldcl p1, cr14, [r0], #8 /* wldrd wr14, [r0], #8 */
|
|
260 ldcl p1, cr15, [r0], #8 /* wldrd wr15, [r0], #8 */
|
|
261 RET
|
|
262
|
|
263 ARM_FUNC_START gnu_Unwind_Save_WMMXD
|
|
264 /* Use the generic coprocessor form so that gas doesn't complain
|
|
265 on non-iWMMXt targets. */
|
|
266 stcl p1, cr0, [r0], #8 /* wstrd wr0, [r0], #8 */
|
|
267 stcl p1, cr1, [r0], #8 /* wstrd wr1, [r0], #8 */
|
|
268 stcl p1, cr2, [r0], #8 /* wstrd wr2, [r0], #8 */
|
|
269 stcl p1, cr3, [r0], #8 /* wstrd wr3, [r0], #8 */
|
|
270 stcl p1, cr4, [r0], #8 /* wstrd wr4, [r0], #8 */
|
|
271 stcl p1, cr5, [r0], #8 /* wstrd wr5, [r0], #8 */
|
|
272 stcl p1, cr6, [r0], #8 /* wstrd wr6, [r0], #8 */
|
|
273 stcl p1, cr7, [r0], #8 /* wstrd wr7, [r0], #8 */
|
|
274 stcl p1, cr8, [r0], #8 /* wstrd wr8, [r0], #8 */
|
|
275 stcl p1, cr9, [r0], #8 /* wstrd wr9, [r0], #8 */
|
|
276 stcl p1, cr10, [r0], #8 /* wstrd wr10, [r0], #8 */
|
|
277 stcl p1, cr11, [r0], #8 /* wstrd wr11, [r0], #8 */
|
|
278 stcl p1, cr12, [r0], #8 /* wstrd wr12, [r0], #8 */
|
|
279 stcl p1, cr13, [r0], #8 /* wstrd wr13, [r0], #8 */
|
|
280 stcl p1, cr14, [r0], #8 /* wstrd wr14, [r0], #8 */
|
|
281 stcl p1, cr15, [r0], #8 /* wstrd wr15, [r0], #8 */
|
|
282 RET
|
|
283
|
|
284 ARM_FUNC_START gnu_Unwind_Restore_WMMXC
|
|
285 /* Use the generic coprocessor form so that gas doesn't complain
|
|
286 on non-iWMMXt targets. */
|
|
287 ldc2 p1, cr8, [r0], #4 /* wldrw wcgr0, [r0], #4 */
|
|
288 ldc2 p1, cr9, [r0], #4 /* wldrw wcgr1, [r0], #4 */
|
|
289 ldc2 p1, cr10, [r0], #4 /* wldrw wcgr2, [r0], #4 */
|
|
290 ldc2 p1, cr11, [r0], #4 /* wldrw wcgr3, [r0], #4 */
|
|
291 RET
|
|
292
|
|
293 ARM_FUNC_START gnu_Unwind_Save_WMMXC
|
|
294 /* Use the generic coprocessor form so that gas doesn't complain
|
|
295 on non-iWMMXt targets. */
|
|
296 stc2 p1, cr8, [r0], #4 /* wstrw wcgr0, [r0], #4 */
|
|
297 stc2 p1, cr9, [r0], #4 /* wstrw wcgr1, [r0], #4 */
|
|
298 stc2 p1, cr10, [r0], #4 /* wstrw wcgr2, [r0], #4 */
|
|
299 stc2 p1, cr11, [r0], #4 /* wstrw wcgr3, [r0], #4 */
|
|
300 RET
|
|
301
|
|
302 /* Wrappers to save core registers, then call the real routine. */
|
|
303
|
|
304 .macro UNWIND_WRAPPER name nargs
|
|
305 ARM_FUNC_START \name
|
|
306 /* Create a phase2_vrs structure. */
|
|
307 /* Split reg push in two to ensure the correct value for sp. */
|
|
308 #if defined(__thumb2__)
|
|
309 mov ip, sp
|
|
310 push {lr} /* PC is ignored. */
|
|
311 push {ip, lr} /* Push original SP and LR. */
|
|
312 #else
|
|
313 stmfd sp!, {sp, lr, pc}
|
|
314 #endif
|
|
315 stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip}
|
|
316
|
|
317 /* Demand-save flags, plus an extra word for alignment. */
|
|
318 mov r3, #0
|
|
319 stmfd sp!, {r2, r3}
|
|
320
|
|
321 /* Point r1 at the block. Pass r[0..nargs) unchanged. */
|
|
322 add r\nargs, sp, #4
|
|
323 #if defined(__thumb__) && !defined(__thumb2__)
|
|
324 /* Switch back to thumb mode to avoid interworking hassle. */
|
|
325 adr ip, .L1_\name
|
|
326 orr ip, ip, #1
|
|
327 bx ip
|
|
328 .thumb
|
|
329 .L1_\name:
|
|
330 bl SYM (__gnu\name) __PLT__
|
|
331 ldr r3, [sp, #64]
|
|
332 add sp, #72
|
|
333 bx r3
|
|
334 #else
|
|
335 bl SYM (__gnu\name) __PLT__
|
|
336 ldr lr, [sp, #64]
|
|
337 add sp, sp, #72
|
|
338 RET
|
|
339 #endif
|
|
340 FUNC_END \name
|
|
341 UNPREFIX \name
|
|
342 .endm
|
|
343
|
|
344 #endif /* !__ARM_ARCH_6M__ */
|
|
345
|
|
346 UNWIND_WRAPPER _Unwind_RaiseException 1
|
|
347 UNWIND_WRAPPER _Unwind_Resume 1
|
|
348 UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
|
|
349 UNWIND_WRAPPER _Unwind_ForcedUnwind 3
|
|
350 UNWIND_WRAPPER _Unwind_Backtrace 2
|
|
351
|
|
352 #endif /* ndef __symbian__ */
|