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__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
120
121#
122# extern int unw_getcontext(unw_context_t* thread_state)
123#
124# On entry:
125#  thread_state pointer is in a0 ($4)
126#
127DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
128  .set push
129  .set noat
130  .set noreorder
131  .set nomacro
132  sw    $1, (4 * 1)($4)
133  sw    $2, (4 * 2)($4)
134  sw    $3, (4 * 3)($4)
135  sw    $4, (4 * 4)($4)
136  sw    $5, (4 * 5)($4)
137  sw    $6, (4 * 6)($4)
138  sw    $7, (4 * 7)($4)
139  sw    $8, (4 * 8)($4)
140  sw    $9, (4 * 9)($4)
141  sw    $10, (4 * 10)($4)
142  sw    $11, (4 * 11)($4)
143  sw    $12, (4 * 12)($4)
144  sw    $13, (4 * 13)($4)
145  sw    $14, (4 * 14)($4)
146  sw    $15, (4 * 15)($4)
147  sw    $16, (4 * 16)($4)
148  sw    $17, (4 * 17)($4)
149  sw    $18, (4 * 18)($4)
150  sw    $19, (4 * 19)($4)
151  sw    $20, (4 * 20)($4)
152  sw    $21, (4 * 21)($4)
153  sw    $22, (4 * 22)($4)
154  sw    $23, (4 * 23)($4)
155  sw    $24, (4 * 24)($4)
156  sw    $25, (4 * 25)($4)
157  sw    $26, (4 * 26)($4)
158  sw    $27, (4 * 27)($4)
159  sw    $28, (4 * 28)($4)
160  sw    $29, (4 * 29)($4)
161  sw    $30, (4 * 30)($4)
162  sw    $31, (4 * 31)($4)
163  # Store return address to pc
164  sw    $31, (4 * 32)($4)
165  # hi and lo
166  mfhi  $8
167  sw    $8,  (4 * 33)($4)
168  mflo  $8
169  sw    $8,  (4 * 34)($4)
170#ifdef __mips_hard_float
171#if __mips_fpr != 64
172  sdc1  $f0, (4 * 36 + 8 * 0)($4)
173  sdc1  $f2, (4 * 36 + 8 * 2)($4)
174  sdc1  $f4, (4 * 36 + 8 * 4)($4)
175  sdc1  $f6, (4 * 36 + 8 * 6)($4)
176  sdc1  $f8, (4 * 36 + 8 * 8)($4)
177  sdc1  $f10, (4 * 36 + 8 * 10)($4)
178  sdc1  $f12, (4 * 36 + 8 * 12)($4)
179  sdc1  $f14, (4 * 36 + 8 * 14)($4)
180  sdc1  $f16, (4 * 36 + 8 * 16)($4)
181  sdc1  $f18, (4 * 36 + 8 * 18)($4)
182  sdc1  $f20, (4 * 36 + 8 * 20)($4)
183  sdc1  $f22, (4 * 36 + 8 * 22)($4)
184  sdc1  $f24, (4 * 36 + 8 * 24)($4)
185  sdc1  $f26, (4 * 36 + 8 * 26)($4)
186  sdc1  $f28, (4 * 36 + 8 * 28)($4)
187  sdc1  $f30, (4 * 36 + 8 * 30)($4)
188#else
189  sdc1  $f0, (4 * 36 + 8 * 0)($4)
190  sdc1  $f1, (4 * 36 + 8 * 1)($4)
191  sdc1  $f2, (4 * 36 + 8 * 2)($4)
192  sdc1  $f3, (4 * 36 + 8 * 3)($4)
193  sdc1  $f4, (4 * 36 + 8 * 4)($4)
194  sdc1  $f5, (4 * 36 + 8 * 5)($4)
195  sdc1  $f6, (4 * 36 + 8 * 6)($4)
196  sdc1  $f7, (4 * 36 + 8 * 7)($4)
197  sdc1  $f8, (4 * 36 + 8 * 8)($4)
198  sdc1  $f9, (4 * 36 + 8 * 9)($4)
199  sdc1  $f10, (4 * 36 + 8 * 10)($4)
200  sdc1  $f11, (4 * 36 + 8 * 11)($4)
201  sdc1  $f12, (4 * 36 + 8 * 12)($4)
202  sdc1  $f13, (4 * 36 + 8 * 13)($4)
203  sdc1  $f14, (4 * 36 + 8 * 14)($4)
204  sdc1  $f15, (4 * 36 + 8 * 15)($4)
205  sdc1  $f16, (4 * 36 + 8 * 16)($4)
206  sdc1  $f17, (4 * 36 + 8 * 17)($4)
207  sdc1  $f18, (4 * 36 + 8 * 18)($4)
208  sdc1  $f19, (4 * 36 + 8 * 19)($4)
209  sdc1  $f20, (4 * 36 + 8 * 20)($4)
210  sdc1  $f21, (4 * 36 + 8 * 21)($4)
211  sdc1  $f22, (4 * 36 + 8 * 22)($4)
212  sdc1  $f23, (4 * 36 + 8 * 23)($4)
213  sdc1  $f24, (4 * 36 + 8 * 24)($4)
214  sdc1  $f25, (4 * 36 + 8 * 25)($4)
215  sdc1  $f26, (4 * 36 + 8 * 26)($4)
216  sdc1  $f27, (4 * 36 + 8 * 27)($4)
217  sdc1  $f28, (4 * 36 + 8 * 28)($4)
218  sdc1  $f29, (4 * 36 + 8 * 29)($4)
219  sdc1  $f30, (4 * 36 + 8 * 30)($4)
220  sdc1  $f31, (4 * 36 + 8 * 31)($4)
221#endif
222#endif
223  jr	$31
224  # return UNW_ESUCCESS
225  or    $2, $0, $0
226  .set pop
227
228#elif defined(__mips64)
229
230#
231# extern int unw_getcontext(unw_context_t* thread_state)
232#
233# On entry:
234#  thread_state pointer is in a0 ($4)
235#
236DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
237  .set push
238  .set noat
239  .set noreorder
240  .set nomacro
241  sd    $1, (8 * 1)($4)
242  sd    $2, (8 * 2)($4)
243  sd    $3, (8 * 3)($4)
244  sd    $4, (8 * 4)($4)
245  sd    $5, (8 * 5)($4)
246  sd    $6, (8 * 6)($4)
247  sd    $7, (8 * 7)($4)
248  sd    $8, (8 * 8)($4)
249  sd    $9, (8 * 9)($4)
250  sd    $10, (8 * 10)($4)
251  sd    $11, (8 * 11)($4)
252  sd    $12, (8 * 12)($4)
253  sd    $13, (8 * 13)($4)
254  sd    $14, (8 * 14)($4)
255  sd    $15, (8 * 15)($4)
256  sd    $16, (8 * 16)($4)
257  sd    $17, (8 * 17)($4)
258  sd    $18, (8 * 18)($4)
259  sd    $19, (8 * 19)($4)
260  sd    $20, (8 * 20)($4)
261  sd    $21, (8 * 21)($4)
262  sd    $22, (8 * 22)($4)
263  sd    $23, (8 * 23)($4)
264  sd    $24, (8 * 24)($4)
265  sd    $25, (8 * 25)($4)
266  sd    $26, (8 * 26)($4)
267  sd    $27, (8 * 27)($4)
268  sd    $28, (8 * 28)($4)
269  sd    $29, (8 * 29)($4)
270  sd    $30, (8 * 30)($4)
271  sd    $31, (8 * 31)($4)
272  # Store return address to pc
273  sd    $31, (8 * 32)($4)
274  # hi and lo
275  mfhi  $8
276  sd    $8,  (8 * 33)($4)
277  mflo  $8
278  sd    $8,  (8 * 34)($4)
279#ifdef __mips_hard_float
280  sdc1  $f0, (8 * 35)($4)
281  sdc1  $f1, (8 * 36)($4)
282  sdc1  $f2, (8 * 37)($4)
283  sdc1  $f3, (8 * 38)($4)
284  sdc1  $f4, (8 * 39)($4)
285  sdc1  $f5, (8 * 40)($4)
286  sdc1  $f6, (8 * 41)($4)
287  sdc1  $f7, (8 * 42)($4)
288  sdc1  $f8, (8 * 43)($4)
289  sdc1  $f9, (8 * 44)($4)
290  sdc1  $f10, (8 * 45)($4)
291  sdc1  $f11, (8 * 46)($4)
292  sdc1  $f12, (8 * 47)($4)
293  sdc1  $f13, (8 * 48)($4)
294  sdc1  $f14, (8 * 49)($4)
295  sdc1  $f15, (8 * 50)($4)
296  sdc1  $f16, (8 * 51)($4)
297  sdc1  $f17, (8 * 52)($4)
298  sdc1  $f18, (8 * 53)($4)
299  sdc1  $f19, (8 * 54)($4)
300  sdc1  $f20, (8 * 55)($4)
301  sdc1  $f21, (8 * 56)($4)
302  sdc1  $f22, (8 * 57)($4)
303  sdc1  $f23, (8 * 58)($4)
304  sdc1  $f24, (8 * 59)($4)
305  sdc1  $f25, (8 * 60)($4)
306  sdc1  $f26, (8 * 61)($4)
307  sdc1  $f27, (8 * 62)($4)
308  sdc1  $f28, (8 * 63)($4)
309  sdc1  $f29, (8 * 64)($4)
310  sdc1  $f30, (8 * 65)($4)
311  sdc1  $f31, (8 * 66)($4)
312#endif
313  jr	$31
314  # return UNW_ESUCCESS
315  or    $2, $0, $0
316  .set pop
317
318# elif defined(__mips__)
319
320#
321# extern int unw_getcontext(unw_context_t* thread_state)
322#
323# Just trap for the time being.
324DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
325  teq $0, $0
326
327#elif defined(__powerpc64__)
328
329//
330// extern int unw_getcontext(unw_context_t* thread_state)
331//
332// On entry:
333//  thread_state pointer is in r3
334//
335DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
336
337// store register (GPR)
338#define PPC64_STR(n) \
339  std   %r##n, (8 * (n + 2))(%r3)
340
341  // save GPRs
342  PPC64_STR(0)
343  mflr  %r0
344  std   %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0
345  PPC64_STR(1)
346  PPC64_STR(2)
347  PPC64_STR(3)
348  PPC64_STR(4)
349  PPC64_STR(5)
350  PPC64_STR(6)
351  PPC64_STR(7)
352  PPC64_STR(8)
353  PPC64_STR(9)
354  PPC64_STR(10)
355  PPC64_STR(11)
356  PPC64_STR(12)
357  PPC64_STR(13)
358  PPC64_STR(14)
359  PPC64_STR(15)
360  PPC64_STR(16)
361  PPC64_STR(17)
362  PPC64_STR(18)
363  PPC64_STR(19)
364  PPC64_STR(20)
365  PPC64_STR(21)
366  PPC64_STR(22)
367  PPC64_STR(23)
368  PPC64_STR(24)
369  PPC64_STR(25)
370  PPC64_STR(26)
371  PPC64_STR(27)
372  PPC64_STR(28)
373  PPC64_STR(29)
374  PPC64_STR(30)
375  PPC64_STR(31)
376
377  mfcr  %r0
378  std   %r0,  PPC64_OFFS_CR(%r3)
379  mfxer %r0
380  std   %r0,  PPC64_OFFS_XER(%r3)
381  mflr  %r0
382  std   %r0,  PPC64_OFFS_LR(%r3)
383  mfctr %r0
384  std   %r0,  PPC64_OFFS_CTR(%r3)
385  mfvrsave    %r0
386  std   %r0,  PPC64_OFFS_VRSAVE(%r3)
387
388#ifdef PPC64_HAS_VMX
389  // save VS registers
390  // (note that this also saves floating point registers and V registers,
391  // because part of VS is mapped to these registers)
392
393  addi  %r4, %r3, PPC64_OFFS_FP
394
395// store VS register
396#define PPC64_STVS(n)      \
397  stxvd2x %vs##n, 0, %r4  ;\
398  addi    %r4, %r4, 16
399
400  PPC64_STVS(0)
401  PPC64_STVS(1)
402  PPC64_STVS(2)
403  PPC64_STVS(3)
404  PPC64_STVS(4)
405  PPC64_STVS(5)
406  PPC64_STVS(6)
407  PPC64_STVS(7)
408  PPC64_STVS(8)
409  PPC64_STVS(9)
410  PPC64_STVS(10)
411  PPC64_STVS(11)
412  PPC64_STVS(12)
413  PPC64_STVS(13)
414  PPC64_STVS(14)
415  PPC64_STVS(15)
416  PPC64_STVS(16)
417  PPC64_STVS(17)
418  PPC64_STVS(18)
419  PPC64_STVS(19)
420  PPC64_STVS(20)
421  PPC64_STVS(21)
422  PPC64_STVS(22)
423  PPC64_STVS(23)
424  PPC64_STVS(24)
425  PPC64_STVS(25)
426  PPC64_STVS(26)
427  PPC64_STVS(27)
428  PPC64_STVS(28)
429  PPC64_STVS(29)
430  PPC64_STVS(30)
431  PPC64_STVS(31)
432  PPC64_STVS(32)
433  PPC64_STVS(33)
434  PPC64_STVS(34)
435  PPC64_STVS(35)
436  PPC64_STVS(36)
437  PPC64_STVS(37)
438  PPC64_STVS(38)
439  PPC64_STVS(39)
440  PPC64_STVS(40)
441  PPC64_STVS(41)
442  PPC64_STVS(42)
443  PPC64_STVS(43)
444  PPC64_STVS(44)
445  PPC64_STVS(45)
446  PPC64_STVS(46)
447  PPC64_STVS(47)
448  PPC64_STVS(48)
449  PPC64_STVS(49)
450  PPC64_STVS(50)
451  PPC64_STVS(51)
452  PPC64_STVS(52)
453  PPC64_STVS(53)
454  PPC64_STVS(54)
455  PPC64_STVS(55)
456  PPC64_STVS(56)
457  PPC64_STVS(57)
458  PPC64_STVS(58)
459  PPC64_STVS(59)
460  PPC64_STVS(60)
461  PPC64_STVS(61)
462  PPC64_STVS(62)
463  PPC64_STVS(63)
464
465#else
466
467// store FP register
468#define PPC64_STF(n) \
469  stfd  %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
470
471  // save float registers
472  PPC64_STF(0)
473  PPC64_STF(1)
474  PPC64_STF(2)
475  PPC64_STF(3)
476  PPC64_STF(4)
477  PPC64_STF(5)
478  PPC64_STF(6)
479  PPC64_STF(7)
480  PPC64_STF(8)
481  PPC64_STF(9)
482  PPC64_STF(10)
483  PPC64_STF(11)
484  PPC64_STF(12)
485  PPC64_STF(13)
486  PPC64_STF(14)
487  PPC64_STF(15)
488  PPC64_STF(16)
489  PPC64_STF(17)
490  PPC64_STF(18)
491  PPC64_STF(19)
492  PPC64_STF(20)
493  PPC64_STF(21)
494  PPC64_STF(22)
495  PPC64_STF(23)
496  PPC64_STF(24)
497  PPC64_STF(25)
498  PPC64_STF(26)
499  PPC64_STF(27)
500  PPC64_STF(28)
501  PPC64_STF(29)
502  PPC64_STF(30)
503  PPC64_STF(31)
504
505  // save vector registers
506
507  // Use 16-bytes below the stack pointer as an
508  // aligned buffer to save each vector register.
509  // Note that the stack pointer is always 16-byte aligned.
510  subi  %r4, %r1, 16
511
512#define PPC64_STV_UNALIGNED(n)                 \
513  stvx  %v##n, 0, %r4                         ;\
514  ld    %r5, 0(%r4)                           ;\
515  std   %r5, (PPC64_OFFS_V + n * 16)(%r3)     ;\
516  ld    %r5, 8(%r4)                           ;\
517  std   %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3)
518
519  PPC64_STV_UNALIGNED(0)
520  PPC64_STV_UNALIGNED(1)
521  PPC64_STV_UNALIGNED(2)
522  PPC64_STV_UNALIGNED(3)
523  PPC64_STV_UNALIGNED(4)
524  PPC64_STV_UNALIGNED(5)
525  PPC64_STV_UNALIGNED(6)
526  PPC64_STV_UNALIGNED(7)
527  PPC64_STV_UNALIGNED(8)
528  PPC64_STV_UNALIGNED(9)
529  PPC64_STV_UNALIGNED(10)
530  PPC64_STV_UNALIGNED(11)
531  PPC64_STV_UNALIGNED(12)
532  PPC64_STV_UNALIGNED(13)
533  PPC64_STV_UNALIGNED(14)
534  PPC64_STV_UNALIGNED(15)
535  PPC64_STV_UNALIGNED(16)
536  PPC64_STV_UNALIGNED(17)
537  PPC64_STV_UNALIGNED(18)
538  PPC64_STV_UNALIGNED(19)
539  PPC64_STV_UNALIGNED(20)
540  PPC64_STV_UNALIGNED(21)
541  PPC64_STV_UNALIGNED(22)
542  PPC64_STV_UNALIGNED(23)
543  PPC64_STV_UNALIGNED(24)
544  PPC64_STV_UNALIGNED(25)
545  PPC64_STV_UNALIGNED(26)
546  PPC64_STV_UNALIGNED(27)
547  PPC64_STV_UNALIGNED(28)
548  PPC64_STV_UNALIGNED(29)
549  PPC64_STV_UNALIGNED(30)
550  PPC64_STV_UNALIGNED(31)
551
552#endif
553
554  li    %r3,  0   // return UNW_ESUCCESS
555  blr
556
557
558#elif defined(__ppc__)
559
560;
561; extern int unw_getcontext(unw_context_t* thread_state)
562;
563; On entry:
564;  thread_state pointer is in r3
565;
566DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
567  stw    r0,  8(r3)
568  mflr  r0
569  stw    r0,  0(r3)  ; store lr as ssr0
570  stw    r1, 12(r3)
571  stw    r2, 16(r3)
572  stw    r3, 20(r3)
573  stw    r4, 24(r3)
574  stw    r5, 28(r3)
575  stw    r6, 32(r3)
576  stw    r7, 36(r3)
577  stw    r8, 40(r3)
578  stw    r9, 44(r3)
579  stw     r10, 48(r3)
580  stw     r11, 52(r3)
581  stw     r12, 56(r3)
582  stw     r13, 60(r3)
583  stw     r14, 64(r3)
584  stw     r15, 68(r3)
585  stw     r16, 72(r3)
586  stw     r17, 76(r3)
587  stw     r18, 80(r3)
588  stw     r19, 84(r3)
589  stw     r20, 88(r3)
590  stw     r21, 92(r3)
591  stw     r22, 96(r3)
592  stw     r23,100(r3)
593  stw     r24,104(r3)
594  stw     r25,108(r3)
595  stw     r26,112(r3)
596  stw     r27,116(r3)
597  stw     r28,120(r3)
598  stw     r29,124(r3)
599  stw     r30,128(r3)
600  stw     r31,132(r3)
601
602  ; save VRSave register
603  mfspr  r0,256
604  stw    r0,156(r3)
605  ; save CR registers
606  mfcr  r0
607  stw    r0,136(r3)
608  ; save CTR register
609  mfctr  r0
610  stw    r0,148(r3)
611
612  ; save float registers
613  stfd    f0, 160(r3)
614  stfd    f1, 168(r3)
615  stfd    f2, 176(r3)
616  stfd    f3, 184(r3)
617  stfd    f4, 192(r3)
618  stfd    f5, 200(r3)
619  stfd    f6, 208(r3)
620  stfd    f7, 216(r3)
621  stfd    f8, 224(r3)
622  stfd    f9, 232(r3)
623  stfd    f10,240(r3)
624  stfd    f11,248(r3)
625  stfd    f12,256(r3)
626  stfd    f13,264(r3)
627  stfd    f14,272(r3)
628  stfd    f15,280(r3)
629  stfd    f16,288(r3)
630  stfd    f17,296(r3)
631  stfd    f18,304(r3)
632  stfd    f19,312(r3)
633  stfd    f20,320(r3)
634  stfd    f21,328(r3)
635  stfd    f22,336(r3)
636  stfd    f23,344(r3)
637  stfd    f24,352(r3)
638  stfd    f25,360(r3)
639  stfd    f26,368(r3)
640  stfd    f27,376(r3)
641  stfd    f28,384(r3)
642  stfd    f29,392(r3)
643  stfd    f30,400(r3)
644  stfd    f31,408(r3)
645
646
647  ; save vector registers
648
649  subi  r4,r1,16
650  rlwinm  r4,r4,0,0,27  ; mask low 4-bits
651  ; r4 is now a 16-byte aligned pointer into the red zone
652
653#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
654  stvx  _vec,0,r4           @\
655  lwz    r5, 0(r4)          @\
656  stw    r5, _offset(r3)    @\
657  lwz    r5, 4(r4)          @\
658  stw    r5, _offset+4(r3)  @\
659  lwz    r5, 8(r4)          @\
660  stw    r5, _offset+8(r3)  @\
661  lwz    r5, 12(r4)         @\
662  stw    r5, _offset+12(r3)
663
664  SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
665  SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
666  SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
667  SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
668  SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
669  SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
670  SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
671  SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
672  SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
673  SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
674  SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
675  SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
676  SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
677  SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
678  SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
679  SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
680  SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
681  SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
682  SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
683  SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
684  SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
685  SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
686  SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
687  SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
688  SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
689  SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
690  SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
691  SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
692  SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
693  SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
694  SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
695  SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
696
697  li  r3, 0    ; return UNW_ESUCCESS
698  blr
699
700
701#elif defined(__arm64__) || defined(__aarch64__)
702
703//
704// extern int unw_getcontext(unw_context_t* thread_state)
705//
706// On entry:
707//  thread_state pointer is in x0
708//
709  .p2align 2
710DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
711  stp    x0, x1,  [x0, #0x000]
712  stp    x2, x3,  [x0, #0x010]
713  stp    x4, x5,  [x0, #0x020]
714  stp    x6, x7,  [x0, #0x030]
715  stp    x8, x9,  [x0, #0x040]
716  stp    x10,x11, [x0, #0x050]
717  stp    x12,x13, [x0, #0x060]
718  stp    x14,x15, [x0, #0x070]
719  stp    x16,x17, [x0, #0x080]
720  stp    x18,x19, [x0, #0x090]
721  stp    x20,x21, [x0, #0x0A0]
722  stp    x22,x23, [x0, #0x0B0]
723  stp    x24,x25, [x0, #0x0C0]
724  stp    x26,x27, [x0, #0x0D0]
725  stp    x28,x29, [x0, #0x0E0]
726  str    x30,     [x0, #0x0F0]
727  mov    x1,sp
728  str    x1,      [x0, #0x0F8]
729  str    x30,     [x0, #0x100]    // store return address as pc
730  // skip cpsr
731  stp    d0, d1,  [x0, #0x110]
732  stp    d2, d3,  [x0, #0x120]
733  stp    d4, d5,  [x0, #0x130]
734  stp    d6, d7,  [x0, #0x140]
735  stp    d8, d9,  [x0, #0x150]
736  stp    d10,d11, [x0, #0x160]
737  stp    d12,d13, [x0, #0x170]
738  stp    d14,d15, [x0, #0x180]
739  stp    d16,d17, [x0, #0x190]
740  stp    d18,d19, [x0, #0x1A0]
741  stp    d20,d21, [x0, #0x1B0]
742  stp    d22,d23, [x0, #0x1C0]
743  stp    d24,d25, [x0, #0x1D0]
744  stp    d26,d27, [x0, #0x1E0]
745  stp    d28,d29, [x0, #0x1F0]
746  str    d30,     [x0, #0x200]
747  str    d31,     [x0, #0x208]
748  mov    x0, #0                   // return UNW_ESUCCESS
749  ret
750
751#elif defined(__arm__) && !defined(__APPLE__)
752
753#if !defined(__ARM_ARCH_ISA_ARM)
754  .thumb
755#endif
756
757@
758@ extern int unw_getcontext(unw_context_t* thread_state)
759@
760@ On entry:
761@  thread_state pointer is in r0
762@
763@ Per EHABI #4.7 this only saves the core integer registers.
764@ EHABI #7.4.5 notes that in general all VRS registers should be restored
765@ however this is very hard to do for VFP registers because it is unknown
766@ to the library how many registers are implemented by the architecture.
767@ Instead, VFP registers are demand saved by logic external to unw_getcontext.
768@
769  .p2align 2
770DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
771#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
772  stm r0!, {r0-r7}
773  mov r1, r8
774  mov r2, r9
775  mov r3, r10
776  stm r0!, {r1-r3}
777  mov r1, r11
778  mov r2, sp
779  mov r3, lr
780  str r1, [r0, #0]   @ r11
781  @ r12 does not need storing, it it the intra-procedure-call scratch register
782  str r2, [r0, #8]   @ sp
783  str r3, [r0, #12]  @ lr
784  str r3, [r0, #16]  @ store return address as pc
785  @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
786  @ It is safe to use here though because we are about to return, and cpsr is
787  @ not expected to be preserved.
788  movs r0, #0        @ return UNW_ESUCCESS
789#else
790  @ 32bit thumb-2 restrictions for stm:
791  @ . the sp (r13) cannot be in the list
792  @ . the pc (r15) cannot be in the list in an STM instruction
793  stm r0, {r0-r12}
794  str sp, [r0, #52]
795  str lr, [r0, #56]
796  str lr, [r0, #60]  @ store return address as pc
797  mov r0, #0         @ return UNW_ESUCCESS
798#endif
799  JMP(lr)
800
801@
802@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
803@
804@ On entry:
805@  values pointer is in r0
806@
807  .p2align 2
808#if defined(__ELF__)
809  .fpu vfpv3-d16
810#endif
811DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
812  vstmia r0, {d0-d15}
813  JMP(lr)
814
815@
816@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
817@
818@ On entry:
819@  values pointer is in r0
820@
821  .p2align 2
822#if defined(__ELF__)
823  .fpu vfpv3-d16
824#endif
825DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
826  vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
827  JMP(lr)
828
829@
830@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
831@
832@ On entry:
833@  values pointer is in r0
834@
835  .p2align 2
836#if defined(__ELF__)
837  .fpu vfpv3
838#endif
839DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
840  @ VFP and iwMMX instructions are only available when compiling with the flags
841  @ that enable them. We do not want to do that in the library (because we do not
842  @ want the compiler to generate instructions that access those) but this is
843  @ only accessed if the personality routine needs these registers. Use of
844  @ these registers implies they are, actually, available on the target, so
845  @ it's ok to execute.
846  @ So, generate the instructions using the corresponding coprocessor mnemonic.
847  vstmia r0, {d16-d31}
848  JMP(lr)
849
850#if defined(_LIBUNWIND_ARM_WMMX)
851
852@
853@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
854@
855@ On entry:
856@  values pointer is in r0
857@
858  .p2align 2
859#if defined(__ELF__)
860  .arch armv5te
861#endif
862DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
863  stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
864  stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
865  stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
866  stcl p1, cr3, [r0], #8  @ wstrd wR3, [r0], #8
867  stcl p1, cr4, [r0], #8  @ wstrd wR4, [r0], #8
868  stcl p1, cr5, [r0], #8  @ wstrd wR5, [r0], #8
869  stcl p1, cr6, [r0], #8  @ wstrd wR6, [r0], #8
870  stcl p1, cr7, [r0], #8  @ wstrd wR7, [r0], #8
871  stcl p1, cr8, [r0], #8  @ wstrd wR8, [r0], #8
872  stcl p1, cr9, [r0], #8  @ wstrd wR9, [r0], #8
873  stcl p1, cr10, [r0], #8  @ wstrd wR10, [r0], #8
874  stcl p1, cr11, [r0], #8  @ wstrd wR11, [r0], #8
875  stcl p1, cr12, [r0], #8  @ wstrd wR12, [r0], #8
876  stcl p1, cr13, [r0], #8  @ wstrd wR13, [r0], #8
877  stcl p1, cr14, [r0], #8  @ wstrd wR14, [r0], #8
878  stcl p1, cr15, [r0], #8  @ wstrd wR15, [r0], #8
879  JMP(lr)
880
881@
882@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
883@
884@ On entry:
885@  values pointer is in r0
886@
887  .p2align 2
888#if defined(__ELF__)
889  .arch armv5te
890#endif
891DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
892  stc2 p1, cr8, [r0], #4  @ wstrw wCGR0, [r0], #4
893  stc2 p1, cr9, [r0], #4  @ wstrw wCGR1, [r0], #4
894  stc2 p1, cr10, [r0], #4  @ wstrw wCGR2, [r0], #4
895  stc2 p1, cr11, [r0], #4  @ wstrw wCGR3, [r0], #4
896  JMP(lr)
897
898#endif
899
900#elif defined(__or1k__)
901
902#
903# extern int unw_getcontext(unw_context_t* thread_state)
904#
905# On entry:
906#  thread_state pointer is in r3
907#
908DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
909  l.sw       0(r3), r0
910  l.sw       4(r3), r1
911  l.sw       8(r3), r2
912  l.sw      12(r3), r3
913  l.sw      16(r3), r4
914  l.sw      20(r3), r5
915  l.sw      24(r3), r6
916  l.sw      28(r3), r7
917  l.sw      32(r3), r8
918  l.sw      36(r3), r9
919  l.sw      40(r3), r10
920  l.sw      44(r3), r11
921  l.sw      48(r3), r12
922  l.sw      52(r3), r13
923  l.sw      56(r3), r14
924  l.sw      60(r3), r15
925  l.sw      64(r3), r16
926  l.sw      68(r3), r17
927  l.sw      72(r3), r18
928  l.sw      76(r3), r19
929  l.sw      80(r3), r20
930  l.sw      84(r3), r21
931  l.sw      88(r3), r22
932  l.sw      92(r3), r23
933  l.sw      96(r3), r24
934  l.sw     100(r3), r25
935  l.sw     104(r3), r26
936  l.sw     108(r3), r27
937  l.sw     112(r3), r28
938  l.sw     116(r3), r29
939  l.sw     120(r3), r30
940  l.sw     124(r3), r31
941  # store ra to pc
942  l.sw     128(r3), r9
943  # zero epcr
944  l.sw     132(r3), r0
945
946#elif defined(__sparc__)
947
948#
949# extern int unw_getcontext(unw_context_t* thread_state)
950#
951# On entry:
952#  thread_state pointer is in o0
953#
954DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
955  ta 3
956  add %o7, 8, %o7
957  std %g0, [%o0 +   0]
958  std %g2, [%o0 +   8]
959  std %g4, [%o0 +  16]
960  std %g6, [%o0 +  24]
961  std %o0, [%o0 +  32]
962  std %o2, [%o0 +  40]
963  std %o4, [%o0 +  48]
964  std %o6, [%o0 +  56]
965  std %l0, [%o0 +  64]
966  std %l2, [%o0 +  72]
967  std %l4, [%o0 +  80]
968  std %l6, [%o0 +  88]
969  std %i0, [%o0 +  96]
970  std %i2, [%o0 + 104]
971  std %i4, [%o0 + 112]
972  std %i6, [%o0 + 120]
973  jmp %o7
974   clr %o0                   // return UNW_ESUCCESS
975#endif
976#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
977
978NO_EXEC_STACK_DIRECTIVE
979