Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/arm/libunwind.S @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
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__ */ |