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