libunwind: update to upstream snapshot r272680
[freebsd.git] / contrib / llvm / projects / libunwind / src / UnwindRegistersSave.S
1 //===------------------------ UnwindRegistersSave.S -----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "assembly.h"
11
12     .text
13
14 #if defined(__i386__)
15
16 #
17 # extern int unw_getcontext(unw_context_t* thread_state)
18 #
19 # On entry:
20 #   +                       +
21 #   +-----------------------+
22 #   + thread_state pointer  +
23 #   +-----------------------+
24 #   + return address        +
25 #   +-----------------------+   <-- SP
26 #   +                       +
27 #
28 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
29   push  %eax
30   movl  8(%esp), %eax
31   movl  %ebx,  4(%eax)
32   movl  %ecx,  8(%eax)
33   movl  %edx, 12(%eax)
34   movl  %edi, 16(%eax)
35   movl  %esi, 20(%eax)
36   movl  %ebp, 24(%eax)
37   movl  %esp, %edx
38   addl  $8, %edx
39   movl  %edx, 28(%eax)  # store what sp was at call site as esp
40   # skip ss
41   # skip eflags
42   movl  4(%esp), %edx
43   movl  %edx, 40(%eax)  # store return address as eip
44   # skip cs
45   # skip ds
46   # skip es
47   # skip fs
48   # skip gs
49   movl  (%esp), %edx
50   movl  %edx, (%eax)  # store original eax
51   popl  %eax
52   xorl  %eax, %eax    # return UNW_ESUCCESS
53   ret
54
55 #elif defined(__x86_64__)
56
57 #
58 # extern int unw_getcontext(unw_context_t* thread_state)
59 #
60 # On entry:
61 #  thread_state pointer is in rdi
62 #
63 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
64   movq  %rax,   (%rdi)
65   movq  %rbx,  8(%rdi)
66   movq  %rcx, 16(%rdi)
67   movq  %rdx, 24(%rdi)
68   movq  %rdi, 32(%rdi)
69   movq  %rsi, 40(%rdi)
70   movq  %rbp, 48(%rdi)
71   movq  %rsp, 56(%rdi)
72   addq  $8,   56(%rdi)
73   movq  %r8,  64(%rdi)
74   movq  %r9,  72(%rdi)
75   movq  %r10, 80(%rdi)
76   movq  %r11, 88(%rdi)
77   movq  %r12, 96(%rdi)
78   movq  %r13,104(%rdi)
79   movq  %r14,112(%rdi)
80   movq  %r15,120(%rdi)
81   movq  (%rsp),%rsi
82   movq  %rsi,128(%rdi) # store return address as rip
83   # skip rflags
84   # skip cs
85   # skip fs
86   # skip gs
87   xorl  %eax, %eax    # return UNW_ESUCCESS
88   ret
89
90 # elif defined(__mips__)
91
92 #
93 # extern int unw_getcontext(unw_context_t* thread_state)
94 #
95 # Just trap for the time being.
96 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
97   teq $0, $0
98
99 #elif defined(__ppc__)
100
101 ;
102 ; extern int unw_getcontext(unw_context_t* thread_state)
103 ;
104 ; On entry:
105 ;  thread_state pointer is in r3
106 ;
107 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
108   stw    r0,  8(r3)
109   mflr  r0
110   stw    r0,  0(r3)  ; store lr as ssr0
111   stw    r1, 12(r3)
112   stw    r2, 16(r3)
113   stw    r3, 20(r3)
114   stw    r4, 24(r3)
115   stw    r5, 28(r3)
116   stw    r6, 32(r3)
117   stw    r7, 36(r3)
118   stw    r8, 40(r3)
119   stw    r9, 44(r3)
120   stw     r10, 48(r3)
121   stw     r11, 52(r3)
122   stw     r12, 56(r3)
123   stw     r13, 60(r3)
124   stw     r14, 64(r3)
125   stw     r15, 68(r3)
126   stw     r16, 72(r3)
127   stw     r17, 76(r3)
128   stw     r18, 80(r3)
129   stw     r19, 84(r3)
130   stw     r20, 88(r3)
131   stw     r21, 92(r3)
132   stw     r22, 96(r3)
133   stw     r23,100(r3)
134   stw     r24,104(r3)
135   stw     r25,108(r3)
136   stw     r26,112(r3)
137   stw     r27,116(r3)
138   stw     r28,120(r3)
139   stw     r29,124(r3)
140   stw     r30,128(r3)
141   stw     r31,132(r3)
142
143   ; save VRSave register
144   mfspr  r0,256
145   stw    r0,156(r3)
146   ; save CR registers
147   mfcr  r0
148   stw    r0,136(r3)
149   ; save CTR register
150   mfctr  r0
151   stw    r0,148(r3)
152
153   ; save float registers
154   stfd    f0, 160(r3)
155   stfd    f1, 168(r3)
156   stfd    f2, 176(r3)
157   stfd    f3, 184(r3)
158   stfd    f4, 192(r3)
159   stfd    f5, 200(r3)
160   stfd    f6, 208(r3)
161   stfd    f7, 216(r3)
162   stfd    f8, 224(r3)
163   stfd    f9, 232(r3)
164   stfd    f10,240(r3)
165   stfd    f11,248(r3)
166   stfd    f12,256(r3)
167   stfd    f13,264(r3)
168   stfd    f14,272(r3)
169   stfd    f15,280(r3)
170   stfd    f16,288(r3)
171   stfd    f17,296(r3)
172   stfd    f18,304(r3)
173   stfd    f19,312(r3)
174   stfd    f20,320(r3)
175   stfd    f21,328(r3)
176   stfd    f22,336(r3)
177   stfd    f23,344(r3)
178   stfd    f24,352(r3)
179   stfd    f25,360(r3)
180   stfd    f26,368(r3)
181   stfd    f27,376(r3)
182   stfd    f28,384(r3)
183   stfd    f29,392(r3)
184   stfd    f30,400(r3)
185   stfd    f31,408(r3)
186
187
188   ; save vector registers
189
190   subi  r4,r1,16
191   rlwinm  r4,r4,0,0,27  ; mask low 4-bits
192   ; r4 is now a 16-byte aligned pointer into the red zone
193
194 #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
195   stvx  _vec,0,r4           @\
196   lwz    r5, 0(r4)          @\
197   stw    r5, _offset(r3)    @\
198   lwz    r5, 4(r4)          @\
199   stw    r5, _offset+4(r3)  @\
200   lwz    r5, 8(r4)          @\
201   stw    r5, _offset+8(r3)  @\
202   lwz    r5, 12(r4)         @\
203   stw    r5, _offset+12(r3)
204
205   SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
206   SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
207   SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
208   SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
209   SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
210   SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
211   SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
212   SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
213   SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
214   SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
215   SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
216   SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
217   SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
218   SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
219   SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
220   SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
221   SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
222   SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
223   SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
224   SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
225   SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
226   SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
227   SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
228   SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
229   SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
230   SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
231   SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
232   SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
233   SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
234   SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
235   SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
236   SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
237
238   li  r3, 0    ; return UNW_ESUCCESS
239   blr
240
241
242 #elif defined(__arm64__) || defined(__aarch64__)
243
244 //
245 // extern int unw_getcontext(unw_context_t* thread_state)
246 //
247 // On entry:
248 //  thread_state pointer is in x0
249 //
250   .p2align 2
251 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
252   stp    x0, x1,  [x0, #0x000]
253   stp    x2, x3,  [x0, #0x010]
254   stp    x4, x5,  [x0, #0x020]
255   stp    x6, x7,  [x0, #0x030]
256   stp    x8, x9,  [x0, #0x040]
257   stp    x10,x11, [x0, #0x050]
258   stp    x12,x13, [x0, #0x060]
259   stp    x14,x15, [x0, #0x070]
260   stp    x16,x17, [x0, #0x080]
261   stp    x18,x19, [x0, #0x090]
262   stp    x20,x21, [x0, #0x0A0]
263   stp    x22,x23, [x0, #0x0B0]
264   stp    x24,x25, [x0, #0x0C0]
265   stp    x26,x27, [x0, #0x0D0]
266   stp    x28,x29, [x0, #0x0E0]
267   str    x30,     [x0, #0x0F0]
268   mov    x1,sp
269   str    x1,      [x0, #0x0F8]
270   str    x30,     [x0, #0x100]    // store return address as pc
271   // skip cpsr
272   stp    d0, d1,  [x0, #0x110]
273   stp    d2, d3,  [x0, #0x120]
274   stp    d4, d5,  [x0, #0x130]
275   stp    d6, d7,  [x0, #0x140]
276   stp    d8, d9,  [x0, #0x150]
277   stp    d10,d11, [x0, #0x160]
278   stp    d12,d13, [x0, #0x170]
279   stp    d14,d15, [x0, #0x180]
280   stp    d16,d17, [x0, #0x190]
281   stp    d18,d19, [x0, #0x1A0]
282   stp    d20,d21, [x0, #0x1B0]
283   stp    d22,d23, [x0, #0x1C0]
284   stp    d24,d25, [x0, #0x1D0]
285   stp    d26,d27, [x0, #0x1E0]
286   stp    d28,d29, [x0, #0x1F0]
287   str    d30,     [x0, #0x200]
288   str    d31,     [x0, #0x208]
289   mov    x0, #0                   // return UNW_ESUCCESS
290   ret
291
292 #elif defined(__arm__) && !defined(__APPLE__)
293
294 #if !defined(__ARM_ARCH_ISA_ARM)
295   .thumb
296 #endif
297
298 @
299 @ extern int unw_getcontext(unw_context_t* thread_state)
300 @
301 @ On entry:
302 @  thread_state pointer is in r0
303
304 @ Per EHABI #4.7 this only saves the core integer registers.
305 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
306 @ however this is very hard to do for VFP registers because it is unknown
307 @ to the library how many registers are implemented by the architecture.
308 @ Instead, VFP registers are demand saved by logic external to unw_getcontext.
309 @
310   .p2align 2
311 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
312 #if !defined(__ARM_ARCH_ISA_ARM)
313   stm r0, {r0-r7}
314   mov r2, sp
315   mov r3, lr
316   str r2, [r0, #52]
317   str r3, [r0, #56]
318   str r3, [r0, #60]  @ store return address as pc
319 #else
320   @ 32bit thumb-2 restrictions for stm:
321   @ . the sp (r13) cannot be in the list
322   @ . the pc (r15) cannot be in the list in an STM instruction
323   stm r0, {r0-r12}
324   str sp, [r0, #52]
325   str lr, [r0, #56]
326   str lr, [r0, #60]  @ store return address as pc
327 #endif
328 #if __ARM_ARCH_ISA_THUMB == 1
329   @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
330   @ It is safe to use here though because we are about to return, and cpsr is
331   @ not expected to be preserved.
332   movs r0, #0        @ return UNW_ESUCCESS
333 #else
334   mov r0, #0         @ return UNW_ESUCCESS
335 #endif
336   JMP(lr)
337
338 @
339 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
340 @
341 @ On entry:
342 @  values pointer is in r0
343 @
344   .p2align 2
345   .fpu vfpv3-d16
346 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
347   vstmia r0, {d0-d15}
348   JMP(lr)
349
350 @
351 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
352 @
353 @ On entry:
354 @  values pointer is in r0
355 @
356   .p2align 2
357   .fpu vfpv3-d16
358 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
359   vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
360   JMP(lr)
361
362 @
363 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
364 @
365 @ On entry:
366 @  values pointer is in r0
367 @
368   .p2align 2
369   .fpu vfpv3
370 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
371   @ VFP and iwMMX instructions are only available when compiling with the flags
372   @ that enable them. We do not want to do that in the library (because we do not
373   @ want the compiler to generate instructions that access those) but this is
374   @ only accessed if the personality routine needs these registers. Use of
375   @ these registers implies they are, actually, available on the target, so
376   @ it's ok to execute.
377   @ So, generate the instructions using the corresponding coprocessor mnemonic.
378   vstmia r0, {d16-d31}
379   JMP(lr)
380
381 @
382 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
383 @
384 @ On entry:
385 @  values pointer is in r0
386 @
387   .p2align 2
388 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
389 #if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
390   stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
391   stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
392   stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
393   stcl p1, cr3, [r0], #8  @ wstrd wR3, [r0], #8
394   stcl p1, cr4, [r0], #8  @ wstrd wR4, [r0], #8
395   stcl p1, cr5, [r0], #8  @ wstrd wR5, [r0], #8
396   stcl p1, cr6, [r0], #8  @ wstrd wR6, [r0], #8
397   stcl p1, cr7, [r0], #8  @ wstrd wR7, [r0], #8
398   stcl p1, cr8, [r0], #8  @ wstrd wR8, [r0], #8
399   stcl p1, cr9, [r0], #8  @ wstrd wR9, [r0], #8
400   stcl p1, cr10, [r0], #8  @ wstrd wR10, [r0], #8
401   stcl p1, cr11, [r0], #8  @ wstrd wR11, [r0], #8
402   stcl p1, cr12, [r0], #8  @ wstrd wR12, [r0], #8
403   stcl p1, cr13, [r0], #8  @ wstrd wR13, [r0], #8
404   stcl p1, cr14, [r0], #8  @ wstrd wR14, [r0], #8
405   stcl p1, cr15, [r0], #8  @ wstrd wR15, [r0], #8
406 #endif
407   JMP(lr)
408
409 @
410 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
411 @
412 @ On entry:
413 @  values pointer is in r0
414 @
415   .p2align 2
416 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
417 #if (!defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_6SM__)) || defined(__ARM_WMMX)
418   stc2 p1, cr8, [r0], #4  @ wstrw wCGR0, [r0], #4
419   stc2 p1, cr9, [r0], #4  @ wstrw wCGR1, [r0], #4
420   stc2 p1, cr10, [r0], #4  @ wstrw wCGR2, [r0], #4
421   stc2 p1, cr11, [r0], #4  @ wstrw wCGR3, [r0], #4
422 #endif
423   JMP(lr)
424
425 #elif defined(__or1k__)
426
427 #
428 # extern int unw_getcontext(unw_context_t* thread_state)
429 #
430 # On entry:
431 #  thread_state pointer is in r3
432 #
433 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
434   l.sw       0(r3), r0
435   l.sw       4(r3), r1
436   l.sw       8(r3), r2
437   l.sw      12(r3), r3
438   l.sw      16(r3), r4
439   l.sw      20(r3), r5
440   l.sw      24(r3), r6
441   l.sw      28(r3), r7
442   l.sw      32(r3), r8
443   l.sw      36(r3), r9
444   l.sw      40(r3), r10
445   l.sw      44(r3), r11
446   l.sw      48(r3), r12
447   l.sw      52(r3), r13
448   l.sw      56(r3), r14
449   l.sw      60(r3), r15
450   l.sw      64(r3), r16
451   l.sw      68(r3), r17
452   l.sw      72(r3), r18
453   l.sw      76(r3), r19
454   l.sw      80(r3), r20
455   l.sw      84(r3), r21
456   l.sw      88(r3), r22
457   l.sw      92(r3), r23
458   l.sw      96(r3), r24
459   l.sw     100(r3), r25
460   l.sw     104(r3), r26
461   l.sw     108(r3), r27
462   l.sw     112(r3), r28
463   l.sw     116(r3), r29
464   l.sw     120(r3), r30
465   l.sw     124(r3), r31
466
467 #elif defined(__riscv__)
468
469 /* RISCVTODO */
470
471 #endif