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