[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / libunwind / src / UnwindRegistersSave.S
blob58ffd1b9e1fb35ab8355e672a172d39f4f174eb8
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "assembly.h"
11 #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
12 #define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
14 #define FROM_0_TO_31 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
15 #define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63
17 #if defined(_AIX)
18     .toc
19 #else
20     .text
21 #endif
23 #if !defined(__USING_SJLJ_EXCEPTIONS__)
25 #if defined(__i386__)
28 # extern int __unw_getcontext(unw_context_t* thread_state)
30 # On entry:
31 #   +                       +
32 #   +-----------------------+
33 #   + thread_state pointer  +
34 #   +-----------------------+
35 #   + return address        +
36 #   +-----------------------+   <-- SP
37 #   +                       +
39 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
41   _LIBUNWIND_CET_ENDBR
42   push  %eax
43   movl  8(%esp), %eax
44   movl  %ebx,  4(%eax)
45   movl  %ecx,  8(%eax)
46   movl  %edx, 12(%eax)
47   movl  %edi, 16(%eax)
48   movl  %esi, 20(%eax)
49   movl  %ebp, 24(%eax)
50   movl  %esp, %edx
51   addl  $8, %edx
52   movl  %edx, 28(%eax)  # store what sp was at call site as esp
53   # skip ss
54   # skip eflags
55   movl  4(%esp), %edx
56   movl  %edx, 40(%eax)  # store return address as eip
57   # skip cs
58   # skip ds
59   # skip es
60   # skip fs
61   # skip gs
62   movl  (%esp), %edx
63   movl  %edx, (%eax)  # store original eax
64   popl  %eax
65   xorl  %eax, %eax    # return UNW_ESUCCESS
66   ret
68 #elif defined(__x86_64__)
71 # extern int __unw_getcontext(unw_context_t* thread_state)
73 # On entry:
74 #  thread_state pointer is in rdi
76 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
77 #if defined(_WIN64)
78 #define PTR %rcx
79 #define TMP %rdx
80 #else
81 #define PTR %rdi
82 #define TMP %rsi
83 #endif
85   _LIBUNWIND_CET_ENDBR
86   movq  %rax,   (PTR)
87   movq  %rbx,  8(PTR)
88   movq  %rcx, 16(PTR)
89   movq  %rdx, 24(PTR)
90   movq  %rdi, 32(PTR)
91   movq  %rsi, 40(PTR)
92   movq  %rbp, 48(PTR)
93   movq  %rsp, 56(PTR)
94   addq  $8,   56(PTR)
95   movq  %r8,  64(PTR)
96   movq  %r9,  72(PTR)
97   movq  %r10, 80(PTR)
98   movq  %r11, 88(PTR)
99   movq  %r12, 96(PTR)
100   movq  %r13,104(PTR)
101   movq  %r14,112(PTR)
102   movq  %r15,120(PTR)
103   movq  (%rsp),TMP
104   movq  TMP,128(PTR) # store return address as rip
105   # skip rflags
106   # skip cs
107   # skip fs
108   # skip gs
110 #if defined(_WIN64)
111   movdqu %xmm0,176(PTR)
112   movdqu %xmm1,192(PTR)
113   movdqu %xmm2,208(PTR)
114   movdqu %xmm3,224(PTR)
115   movdqu %xmm4,240(PTR)
116   movdqu %xmm5,256(PTR)
117   movdqu %xmm6,272(PTR)
118   movdqu %xmm7,288(PTR)
119   movdqu %xmm8,304(PTR)
120   movdqu %xmm9,320(PTR)
121   movdqu %xmm10,336(PTR)
122   movdqu %xmm11,352(PTR)
123   movdqu %xmm12,368(PTR)
124   movdqu %xmm13,384(PTR)
125   movdqu %xmm14,400(PTR)
126   movdqu %xmm15,416(PTR)
127 #endif
128   xorl  %eax, %eax    # return UNW_ESUCCESS
129   ret
131 #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
134 # extern int __unw_getcontext(unw_context_t* thread_state)
136 # On entry:
137 #  thread_state pointer is in a0 ($4)
139 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
140   .set push
141   .set noat
142   .set noreorder
143   .set nomacro
144   sw    $1, (4 * 1)($4)
145   sw    $2, (4 * 2)($4)
146   sw    $3, (4 * 3)($4)
147   sw    $4, (4 * 4)($4)
148   sw    $5, (4 * 5)($4)
149   sw    $6, (4 * 6)($4)
150   sw    $7, (4 * 7)($4)
151   sw    $8, (4 * 8)($4)
152   sw    $9, (4 * 9)($4)
153   sw    $10, (4 * 10)($4)
154   sw    $11, (4 * 11)($4)
155   sw    $12, (4 * 12)($4)
156   sw    $13, (4 * 13)($4)
157   sw    $14, (4 * 14)($4)
158   sw    $15, (4 * 15)($4)
159   sw    $16, (4 * 16)($4)
160   sw    $17, (4 * 17)($4)
161   sw    $18, (4 * 18)($4)
162   sw    $19, (4 * 19)($4)
163   sw    $20, (4 * 20)($4)
164   sw    $21, (4 * 21)($4)
165   sw    $22, (4 * 22)($4)
166   sw    $23, (4 * 23)($4)
167   sw    $24, (4 * 24)($4)
168   sw    $25, (4 * 25)($4)
169   sw    $26, (4 * 26)($4)
170   sw    $27, (4 * 27)($4)
171   sw    $28, (4 * 28)($4)
172   sw    $29, (4 * 29)($4)
173   sw    $30, (4 * 30)($4)
174   sw    $31, (4 * 31)($4)
175   # Store return address to pc
176   sw    $31, (4 * 32)($4)
177 #if __mips_isa_rev < 6
178   # hi and lo
179   mfhi  $8
180   sw    $8,  (4 * 33)($4)
181   mflo  $8
182   sw    $8,  (4 * 34)($4)
183 #endif
184 #ifdef __mips_hard_float
185 #if __mips_fpr != 64
186   sdc1  $f0, (4 * 36 + 8 * 0)($4)
187   sdc1  $f2, (4 * 36 + 8 * 2)($4)
188   sdc1  $f4, (4 * 36 + 8 * 4)($4)
189   sdc1  $f6, (4 * 36 + 8 * 6)($4)
190   sdc1  $f8, (4 * 36 + 8 * 8)($4)
191   sdc1  $f10, (4 * 36 + 8 * 10)($4)
192   sdc1  $f12, (4 * 36 + 8 * 12)($4)
193   sdc1  $f14, (4 * 36 + 8 * 14)($4)
194   sdc1  $f16, (4 * 36 + 8 * 16)($4)
195   sdc1  $f18, (4 * 36 + 8 * 18)($4)
196   sdc1  $f20, (4 * 36 + 8 * 20)($4)
197   sdc1  $f22, (4 * 36 + 8 * 22)($4)
198   sdc1  $f24, (4 * 36 + 8 * 24)($4)
199   sdc1  $f26, (4 * 36 + 8 * 26)($4)
200   sdc1  $f28, (4 * 36 + 8 * 28)($4)
201   sdc1  $f30, (4 * 36 + 8 * 30)($4)
202 #else
203   sdc1  $f0, (4 * 36 + 8 * 0)($4)
204   sdc1  $f1, (4 * 36 + 8 * 1)($4)
205   sdc1  $f2, (4 * 36 + 8 * 2)($4)
206   sdc1  $f3, (4 * 36 + 8 * 3)($4)
207   sdc1  $f4, (4 * 36 + 8 * 4)($4)
208   sdc1  $f5, (4 * 36 + 8 * 5)($4)
209   sdc1  $f6, (4 * 36 + 8 * 6)($4)
210   sdc1  $f7, (4 * 36 + 8 * 7)($4)
211   sdc1  $f8, (4 * 36 + 8 * 8)($4)
212   sdc1  $f9, (4 * 36 + 8 * 9)($4)
213   sdc1  $f10, (4 * 36 + 8 * 10)($4)
214   sdc1  $f11, (4 * 36 + 8 * 11)($4)
215   sdc1  $f12, (4 * 36 + 8 * 12)($4)
216   sdc1  $f13, (4 * 36 + 8 * 13)($4)
217   sdc1  $f14, (4 * 36 + 8 * 14)($4)
218   sdc1  $f15, (4 * 36 + 8 * 15)($4)
219   sdc1  $f16, (4 * 36 + 8 * 16)($4)
220   sdc1  $f17, (4 * 36 + 8 * 17)($4)
221   sdc1  $f18, (4 * 36 + 8 * 18)($4)
222   sdc1  $f19, (4 * 36 + 8 * 19)($4)
223   sdc1  $f20, (4 * 36 + 8 * 20)($4)
224   sdc1  $f21, (4 * 36 + 8 * 21)($4)
225   sdc1  $f22, (4 * 36 + 8 * 22)($4)
226   sdc1  $f23, (4 * 36 + 8 * 23)($4)
227   sdc1  $f24, (4 * 36 + 8 * 24)($4)
228   sdc1  $f25, (4 * 36 + 8 * 25)($4)
229   sdc1  $f26, (4 * 36 + 8 * 26)($4)
230   sdc1  $f27, (4 * 36 + 8 * 27)($4)
231   sdc1  $f28, (4 * 36 + 8 * 28)($4)
232   sdc1  $f29, (4 * 36 + 8 * 29)($4)
233   sdc1  $f30, (4 * 36 + 8 * 30)($4)
234   sdc1  $f31, (4 * 36 + 8 * 31)($4)
235 #endif
236 #endif
237   jr    $31
238   # return UNW_ESUCCESS
239   or    $2, $0, $0
240   .set pop
242 #elif defined(__mips64)
245 # extern int __unw_getcontext(unw_context_t* thread_state)
247 # On entry:
248 #  thread_state pointer is in a0 ($4)
250 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
251   .set push
252   .set noat
253   .set noreorder
254   .set nomacro
255   .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
256     sd $\i, (8 * \i)($4)
257   .endr
258   # Store return address to pc
259   sd    $31, (8 * 32)($4)
260 #if __mips_isa_rev < 6
261   # hi and lo
262   mfhi  $8
263   sd    $8,  (8 * 33)($4)
264   mflo  $8
265   sd    $8,  (8 * 34)($4)
266 #endif
267 #ifdef __mips_hard_float
268   .irp i,FROM_0_TO_31
269     sdc1 $f\i, (280+8*\i)($4)
270   .endr
271 #endif
272   jr    $31
273   # return UNW_ESUCCESS
274   or    $2, $0, $0
275   .set pop
277 # elif defined(__mips__)
280 # extern int __unw_getcontext(unw_context_t* thread_state)
282 # Just trap for the time being.
283 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
284   teq $0, $0
286 #elif defined(__powerpc64__)
289 // extern int __unw_getcontext(unw_context_t* thread_state)
291 // On entry:
292 //  thread_state pointer is in r3
294 #if defined(_AIX)
295 DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)
296 #else
297 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
298 #endif
299 // store register (GPR)
300 #define PPC64_STR(n) \
301   std   n, (8 * (n + 2))(3)
303   // save GPRs
304   PPC64_STR(0)
305   mflr  0
306   std   0, PPC64_OFFS_SRR0(3) // store lr as ssr0
307   PPC64_STR(1)
308   PPC64_STR(2)
309   PPC64_STR(3)
310   PPC64_STR(4)
311   PPC64_STR(5)
312   PPC64_STR(6)
313   PPC64_STR(7)
314   PPC64_STR(8)
315   PPC64_STR(9)
316   PPC64_STR(10)
317   PPC64_STR(11)
318   PPC64_STR(12)
319   PPC64_STR(13)
320   PPC64_STR(14)
321   PPC64_STR(15)
322   PPC64_STR(16)
323   PPC64_STR(17)
324   PPC64_STR(18)
325   PPC64_STR(19)
326   PPC64_STR(20)
327   PPC64_STR(21)
328   PPC64_STR(22)
329   PPC64_STR(23)
330   PPC64_STR(24)
331   PPC64_STR(25)
332   PPC64_STR(26)
333   PPC64_STR(27)
334   PPC64_STR(28)
335   PPC64_STR(29)
336   PPC64_STR(30)
337   PPC64_STR(31)
339   mfcr  0
340   std   0,  PPC64_OFFS_CR(3)
341   mfxer 0
342   std   0,  PPC64_OFFS_XER(3)
343   mflr  0
344   std   0,  PPC64_OFFS_LR(3)
345   mfctr 0
346   std   0,  PPC64_OFFS_CTR(3)
347   mfvrsave    0
348   std   0,  PPC64_OFFS_VRSAVE(3)
350 #if defined(__VSX__)
351   // save VS registers
352   // (note that this also saves floating point registers and V registers,
353   // because part of VS is mapped to these registers)
355   addi  4, 3, PPC64_OFFS_FP
357 // store VS register
358 #ifdef __LITTLE_ENDIAN__
359 // For little-endian targets, we need a swap since stxvd2x will store the
360 // register in the incorrect doubleword order.
361 // FIXME: when supporting targets older than Power9 on LE is no longer required
362 //        this can be changed to simply `stxv n, 16 * n(4)`.
363 #define PPC64_STVS(n)      \
364   xxswapd n, n            ;\
365   stxvd2x n, 0, 4         ;\
366   addi    4, 4, 16
367 #else
368 #define PPC64_STVS(n)      \
369   stxvd2x n, 0, 4         ;\
370   addi    4, 4, 16
371 #endif
373   PPC64_STVS(0)
374   PPC64_STVS(1)
375   PPC64_STVS(2)
376   PPC64_STVS(3)
377   PPC64_STVS(4)
378   PPC64_STVS(5)
379   PPC64_STVS(6)
380   PPC64_STVS(7)
381   PPC64_STVS(8)
382   PPC64_STVS(9)
383   PPC64_STVS(10)
384   PPC64_STVS(11)
385   PPC64_STVS(12)
386   PPC64_STVS(13)
387   PPC64_STVS(14)
388   PPC64_STVS(15)
389   PPC64_STVS(16)
390   PPC64_STVS(17)
391   PPC64_STVS(18)
392   PPC64_STVS(19)
393   PPC64_STVS(20)
394   PPC64_STVS(21)
395   PPC64_STVS(22)
396   PPC64_STVS(23)
397   PPC64_STVS(24)
398   PPC64_STVS(25)
399   PPC64_STVS(26)
400   PPC64_STVS(27)
401   PPC64_STVS(28)
402   PPC64_STVS(29)
403   PPC64_STVS(30)
404   PPC64_STVS(31)
405   PPC64_STVS(32)
406   PPC64_STVS(33)
407   PPC64_STVS(34)
408   PPC64_STVS(35)
409   PPC64_STVS(36)
410   PPC64_STVS(37)
411   PPC64_STVS(38)
412   PPC64_STVS(39)
413   PPC64_STVS(40)
414   PPC64_STVS(41)
415   PPC64_STVS(42)
416   PPC64_STVS(43)
417   PPC64_STVS(44)
418   PPC64_STVS(45)
419   PPC64_STVS(46)
420   PPC64_STVS(47)
421   PPC64_STVS(48)
422   PPC64_STVS(49)
423   PPC64_STVS(50)
424   PPC64_STVS(51)
425   PPC64_STVS(52)
426   PPC64_STVS(53)
427   PPC64_STVS(54)
428   PPC64_STVS(55)
429   PPC64_STVS(56)
430   PPC64_STVS(57)
431   PPC64_STVS(58)
432   PPC64_STVS(59)
433   PPC64_STVS(60)
434   PPC64_STVS(61)
435   PPC64_STVS(62)
436   PPC64_STVS(63)
438 #else
440 // store FP register
441 #define PPC64_STF(n) \
442   stfd  n, (PPC64_OFFS_FP + n * 16)(3)
444   // save float registers
445   PPC64_STF(0)
446   PPC64_STF(1)
447   PPC64_STF(2)
448   PPC64_STF(3)
449   PPC64_STF(4)
450   PPC64_STF(5)
451   PPC64_STF(6)
452   PPC64_STF(7)
453   PPC64_STF(8)
454   PPC64_STF(9)
455   PPC64_STF(10)
456   PPC64_STF(11)
457   PPC64_STF(12)
458   PPC64_STF(13)
459   PPC64_STF(14)
460   PPC64_STF(15)
461   PPC64_STF(16)
462   PPC64_STF(17)
463   PPC64_STF(18)
464   PPC64_STF(19)
465   PPC64_STF(20)
466   PPC64_STF(21)
467   PPC64_STF(22)
468   PPC64_STF(23)
469   PPC64_STF(24)
470   PPC64_STF(25)
471   PPC64_STF(26)
472   PPC64_STF(27)
473   PPC64_STF(28)
474   PPC64_STF(29)
475   PPC64_STF(30)
476   PPC64_STF(31)
478 #if defined(__ALTIVEC__)
479   // save vector registers
481   // Use 16-bytes below the stack pointer as an
482   // aligned buffer to save each vector register.
483   // Note that the stack pointer is always 16-byte aligned.
484   subi  4, 1, 16
486 #define PPC64_STV_UNALIGNED(n)             \
487   stvx  n, 0, 4                           ;\
488   ld    5, 0(4)                           ;\
489   std   5, (PPC64_OFFS_V + n * 16)(3)     ;\
490   ld    5, 8(4)                           ;\
491   std   5, (PPC64_OFFS_V + n * 16 + 8)(3)
493   PPC64_STV_UNALIGNED(0)
494   PPC64_STV_UNALIGNED(1)
495   PPC64_STV_UNALIGNED(2)
496   PPC64_STV_UNALIGNED(3)
497   PPC64_STV_UNALIGNED(4)
498   PPC64_STV_UNALIGNED(5)
499   PPC64_STV_UNALIGNED(6)
500   PPC64_STV_UNALIGNED(7)
501   PPC64_STV_UNALIGNED(8)
502   PPC64_STV_UNALIGNED(9)
503   PPC64_STV_UNALIGNED(10)
504   PPC64_STV_UNALIGNED(11)
505   PPC64_STV_UNALIGNED(12)
506   PPC64_STV_UNALIGNED(13)
507   PPC64_STV_UNALIGNED(14)
508   PPC64_STV_UNALIGNED(15)
509   PPC64_STV_UNALIGNED(16)
510   PPC64_STV_UNALIGNED(17)
511   PPC64_STV_UNALIGNED(18)
512   PPC64_STV_UNALIGNED(19)
513   PPC64_STV_UNALIGNED(20)
514   PPC64_STV_UNALIGNED(21)
515   PPC64_STV_UNALIGNED(22)
516   PPC64_STV_UNALIGNED(23)
517   PPC64_STV_UNALIGNED(24)
518   PPC64_STV_UNALIGNED(25)
519   PPC64_STV_UNALIGNED(26)
520   PPC64_STV_UNALIGNED(27)
521   PPC64_STV_UNALIGNED(28)
522   PPC64_STV_UNALIGNED(29)
523   PPC64_STV_UNALIGNED(30)
524   PPC64_STV_UNALIGNED(31)
526 #endif
527 #endif
529   li    3,  0   // return UNW_ESUCCESS
530   blr
533 #elif defined(__powerpc__)
536 // extern int unw_getcontext(unw_context_t* thread_state)
538 // On entry:
539 //  thread_state pointer is in r3
541 #if defined(_AIX)
542 DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)
543 #else
544 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
545 #endif
546   stw     0,   8(3)
547   mflr    0
548   stw     0,   0(3) // store lr as ssr0
549   stw     1,  12(3)
550   stw     2,  16(3)
551   stw     3,  20(3)
552   stw     4,  24(3)
553   stw     5,  28(3)
554   stw     6,  32(3)
555   stw     7,  36(3)
556   stw     8,  40(3)
557   stw     9,  44(3)
558   stw     10, 48(3)
559   stw     11, 52(3)
560   stw     12, 56(3)
561   stw     13, 60(3)
562   stw     14, 64(3)
563   stw     15, 68(3)
564   stw     16, 72(3)
565   stw     17, 76(3)
566   stw     18, 80(3)
567   stw     19, 84(3)
568   stw     20, 88(3)
569   stw     21, 92(3)
570   stw     22, 96(3)
571   stw     23,100(3)
572   stw     24,104(3)
573   stw     25,108(3)
574   stw     26,112(3)
575   stw     27,116(3)
576   stw     28,120(3)
577   stw     29,124(3)
578   stw     30,128(3)
579   stw     31,132(3)
581 #if defined(__ALTIVEC__)
582   // save VRSave register
583   mfspr   0, 256
584   stw     0, 156(3)
585 #endif
586   // save CR registers
587   mfcr    0
588   stw     0, 136(3)
589   // save CTR register
590   mfctr   0
591   stw     0, 148(3)
593 #if !defined(__NO_FPRS__)
594   // save float registers
595   stfd    0, 160(3)
596   stfd    1, 168(3)
597   stfd    2, 176(3)
598   stfd    3, 184(3)
599   stfd    4, 192(3)
600   stfd    5, 200(3)
601   stfd    6, 208(3)
602   stfd    7, 216(3)
603   stfd    8, 224(3)
604   stfd    9, 232(3)
605   stfd    10,240(3)
606   stfd    11,248(3)
607   stfd    12,256(3)
608   stfd    13,264(3)
609   stfd    14,272(3)
610   stfd    15,280(3)
611   stfd    16,288(3)
612   stfd    17,296(3)
613   stfd    18,304(3)
614   stfd    19,312(3)
615   stfd    20,320(3)
616   stfd    21,328(3)
617   stfd    22,336(3)
618   stfd    23,344(3)
619   stfd    24,352(3)
620   stfd    25,360(3)
621   stfd    26,368(3)
622   stfd    27,376(3)
623   stfd    28,384(3)
624   stfd    29,392(3)
625   stfd    30,400(3)
626   stfd    31,408(3)
627 #endif
629 #if defined(__ALTIVEC__)
630   // save vector registers
632   subi    4, 1, 16
633   rlwinm  4, 4, 0, 0, 27  // mask low 4-bits
634   // r4 is now a 16-byte aligned pointer into the red zone
636 #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
637   stvx    _vec, 0, 4               SEPARATOR \
638   lwz     5, 0(4)                  SEPARATOR \
639   stw     5, _offset(3)            SEPARATOR \
640   lwz     5, 4(4)                  SEPARATOR \
641   stw     5, _offset+4(3)          SEPARATOR \
642   lwz     5, 8(4)                  SEPARATOR \
643   stw     5, _offset+8(3)          SEPARATOR \
644   lwz     5, 12(4)                 SEPARATOR \
645   stw     5, _offset+12(3)
647   SAVE_VECTOR_UNALIGNED( 0, 424+0x000)
648   SAVE_VECTOR_UNALIGNED( 1, 424+0x010)
649   SAVE_VECTOR_UNALIGNED( 2, 424+0x020)
650   SAVE_VECTOR_UNALIGNED( 3, 424+0x030)
651   SAVE_VECTOR_UNALIGNED( 4, 424+0x040)
652   SAVE_VECTOR_UNALIGNED( 5, 424+0x050)
653   SAVE_VECTOR_UNALIGNED( 6, 424+0x060)
654   SAVE_VECTOR_UNALIGNED( 7, 424+0x070)
655   SAVE_VECTOR_UNALIGNED( 8, 424+0x080)
656   SAVE_VECTOR_UNALIGNED( 9, 424+0x090)
657   SAVE_VECTOR_UNALIGNED(10, 424+0x0A0)
658   SAVE_VECTOR_UNALIGNED(11, 424+0x0B0)
659   SAVE_VECTOR_UNALIGNED(12, 424+0x0C0)
660   SAVE_VECTOR_UNALIGNED(13, 424+0x0D0)
661   SAVE_VECTOR_UNALIGNED(14, 424+0x0E0)
662   SAVE_VECTOR_UNALIGNED(15, 424+0x0F0)
663   SAVE_VECTOR_UNALIGNED(16, 424+0x100)
664   SAVE_VECTOR_UNALIGNED(17, 424+0x110)
665   SAVE_VECTOR_UNALIGNED(18, 424+0x120)
666   SAVE_VECTOR_UNALIGNED(19, 424+0x130)
667   SAVE_VECTOR_UNALIGNED(20, 424+0x140)
668   SAVE_VECTOR_UNALIGNED(21, 424+0x150)
669   SAVE_VECTOR_UNALIGNED(22, 424+0x160)
670   SAVE_VECTOR_UNALIGNED(23, 424+0x170)
671   SAVE_VECTOR_UNALIGNED(24, 424+0x180)
672   SAVE_VECTOR_UNALIGNED(25, 424+0x190)
673   SAVE_VECTOR_UNALIGNED(26, 424+0x1A0)
674   SAVE_VECTOR_UNALIGNED(27, 424+0x1B0)
675   SAVE_VECTOR_UNALIGNED(28, 424+0x1C0)
676   SAVE_VECTOR_UNALIGNED(29, 424+0x1D0)
677   SAVE_VECTOR_UNALIGNED(30, 424+0x1E0)
678   SAVE_VECTOR_UNALIGNED(31, 424+0x1F0)
679 #endif
681   li      3, 0  // return UNW_ESUCCESS
682   blr
685 #elif defined(__aarch64__)
688 // extern int __unw_getcontext(unw_context_t* thread_state)
690 // On entry:
691 //  thread_state pointer is in x0
693   .p2align 2
694 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
695   stp    x0, x1,  [x0, #0x000]
696   stp    x2, x3,  [x0, #0x010]
697   stp    x4, x5,  [x0, #0x020]
698   stp    x6, x7,  [x0, #0x030]
699   stp    x8, x9,  [x0, #0x040]
700   stp    x10,x11, [x0, #0x050]
701   stp    x12,x13, [x0, #0x060]
702   stp    x14,x15, [x0, #0x070]
703   stp    x16,x17, [x0, #0x080]
704   stp    x18,x19, [x0, #0x090]
705   stp    x20,x21, [x0, #0x0A0]
706   stp    x22,x23, [x0, #0x0B0]
707   stp    x24,x25, [x0, #0x0C0]
708   stp    x26,x27, [x0, #0x0D0]
709   stp    x28,x29, [x0, #0x0E0]
710   str    x30,     [x0, #0x0F0]
711   mov    x1,sp
712   str    x1,      [x0, #0x0F8]
713   str    x30,     [x0, #0x100]    // store return address as pc
714   // skip cpsr
715   stp    d0, d1,  [x0, #0x110]
716   stp    d2, d3,  [x0, #0x120]
717   stp    d4, d5,  [x0, #0x130]
718   stp    d6, d7,  [x0, #0x140]
719   stp    d8, d9,  [x0, #0x150]
720   stp    d10,d11, [x0, #0x160]
721   stp    d12,d13, [x0, #0x170]
722   stp    d14,d15, [x0, #0x180]
723   stp    d16,d17, [x0, #0x190]
724   stp    d18,d19, [x0, #0x1A0]
725   stp    d20,d21, [x0, #0x1B0]
726   stp    d22,d23, [x0, #0x1C0]
727   stp    d24,d25, [x0, #0x1D0]
728   stp    d26,d27, [x0, #0x1E0]
729   stp    d28,d29, [x0, #0x1F0]
730   str    d30,     [x0, #0x200]
731   str    d31,     [x0, #0x208]
732   mov    x0, #0                   // return UNW_ESUCCESS
733   ret
735 #elif defined(__arm__) && !defined(__APPLE__)
737 #if !defined(__ARM_ARCH_ISA_ARM)
738 #if (__ARM_ARCH_ISA_THUMB == 2)
739   .syntax unified
740 #endif
741   .thumb
742 #endif
745 @ extern int __unw_getcontext(unw_context_t* thread_state)
747 @ On entry:
748 @  thread_state pointer is in r0
750 @ Per EHABI #4.7 this only saves the core integer registers.
751 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
752 @ however this is very hard to do for VFP registers because it is unknown
753 @ to the library how many registers are implemented by the architecture.
754 @ Instead, VFP registers are demand saved by logic external to __unw_getcontext.
756   .p2align 2
757 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
758 #if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
759   stm r0!, {r0-r7}
760   mov r1, r8
761   mov r2, r9
762   mov r3, r10
763   stm r0!, {r1-r3}
764   mov r1, r11
765   mov r2, sp
766   mov r3, lr
767   str r1, [r0, #0]   @ r11
768   @ r12 does not need storing, it it the intra-procedure-call scratch register
769   str r2, [r0, #8]   @ sp
770   str r3, [r0, #12]  @ lr
771   str r3, [r0, #16]  @ store return address as pc
772   @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
773   @ It is safe to use here though because we are about to return, and cpsr is
774   @ not expected to be preserved.
775   movs r0, #0        @ return UNW_ESUCCESS
776 #else
777   @ 32bit thumb-2 restrictions for stm:
778   @ . the sp (r13) cannot be in the list
779   @ . the pc (r15) cannot be in the list in an STM instruction
780   stm r0, {r0-r12}
781   str sp, [r0, #52]
782   str lr, [r0, #56]
783   str lr, [r0, #60]  @ store return address as pc
784   mov r0, #0         @ return UNW_ESUCCESS
785 #endif
786   JMP(lr)
789 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
791 @ On entry:
792 @  values pointer is in r0
794   .p2align 2
795 #if defined(__ELF__)
796   .fpu vfpv3-d16
797 #endif
798 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv)
799   vstmia r0, {d0-d15}
800   JMP(lr)
803 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
805 @ On entry:
806 @  values pointer is in r0
808   .p2align 2
809 #if defined(__ELF__)
810   .fpu vfpv3-d16
811 #endif
812 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv)
813   vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
814   JMP(lr)
817 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
819 @ On entry:
820 @  values pointer is in r0
822   .p2align 2
823 #if defined(__ELF__)
824   .fpu vfpv3
825 #endif
826 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv)
827   @ VFP and iwMMX instructions are only available when compiling with the flags
828   @ that enable them. We do not want to do that in the library (because we do not
829   @ want the compiler to generate instructions that access those) but this is
830   @ only accessed if the personality routine needs these registers. Use of
831   @ these registers implies they are, actually, available on the target, so
832   @ it's ok to execute.
833   @ So, generate the instructions using the corresponding coprocessor mnemonic.
834   vstmia r0, {d16-d31}
835   JMP(lr)
837 #if defined(_LIBUNWIND_ARM_WMMX)
840 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
842 @ On entry:
843 @  values pointer is in r0
845   .p2align 2
846 #if defined(__ELF__)
847   .arch armv5te
848 #endif
849 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv)
850   stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
851   stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
852   stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
853   stcl p1, cr3, [r0], #8  @ wstrd wR3, [r0], #8
854   stcl p1, cr4, [r0], #8  @ wstrd wR4, [r0], #8
855   stcl p1, cr5, [r0], #8  @ wstrd wR5, [r0], #8
856   stcl p1, cr6, [r0], #8  @ wstrd wR6, [r0], #8
857   stcl p1, cr7, [r0], #8  @ wstrd wR7, [r0], #8
858   stcl p1, cr8, [r0], #8  @ wstrd wR8, [r0], #8
859   stcl p1, cr9, [r0], #8  @ wstrd wR9, [r0], #8
860   stcl p1, cr10, [r0], #8  @ wstrd wR10, [r0], #8
861   stcl p1, cr11, [r0], #8  @ wstrd wR11, [r0], #8
862   stcl p1, cr12, [r0], #8  @ wstrd wR12, [r0], #8
863   stcl p1, cr13, [r0], #8  @ wstrd wR13, [r0], #8
864   stcl p1, cr14, [r0], #8  @ wstrd wR14, [r0], #8
865   stcl p1, cr15, [r0], #8  @ wstrd wR15, [r0], #8
866   JMP(lr)
869 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
871 @ On entry:
872 @  values pointer is in r0
874   .p2align 2
875 #if defined(__ELF__)
876   .arch armv5te
877 #endif
878 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
879   stc2 p1, cr8, [r0], #4  @ wstrw wCGR0, [r0], #4
880   stc2 p1, cr9, [r0], #4  @ wstrw wCGR1, [r0], #4
881   stc2 p1, cr10, [r0], #4  @ wstrw wCGR2, [r0], #4
882   stc2 p1, cr11, [r0], #4  @ wstrw wCGR3, [r0], #4
883   JMP(lr)
885 #endif
887 #elif defined(__or1k__)
890 # extern int __unw_getcontext(unw_context_t* thread_state)
892 # On entry:
893 #  thread_state pointer is in r3
895 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
896   l.sw       0(r3), r0
897   l.sw       4(r3), r1
898   l.sw       8(r3), r2
899   l.sw      12(r3), r3
900   l.sw      16(r3), r4
901   l.sw      20(r3), r5
902   l.sw      24(r3), r6
903   l.sw      28(r3), r7
904   l.sw      32(r3), r8
905   l.sw      36(r3), r9
906   l.sw      40(r3), r10
907   l.sw      44(r3), r11
908   l.sw      48(r3), r12
909   l.sw      52(r3), r13
910   l.sw      56(r3), r14
911   l.sw      60(r3), r15
912   l.sw      64(r3), r16
913   l.sw      68(r3), r17
914   l.sw      72(r3), r18
915   l.sw      76(r3), r19
916   l.sw      80(r3), r20
917   l.sw      84(r3), r21
918   l.sw      88(r3), r22
919   l.sw      92(r3), r23
920   l.sw      96(r3), r24
921   l.sw     100(r3), r25
922   l.sw     104(r3), r26
923   l.sw     108(r3), r27
924   l.sw     112(r3), r28
925   l.sw     116(r3), r29
926   l.sw     120(r3), r30
927   l.sw     124(r3), r31
928   # store ra to pc
929   l.sw     128(r3), r9
930   # zero epcr
931   l.sw     132(r3), r0
933 #elif defined(__hexagon__)
935 # extern int unw_getcontext(unw_context_t* thread_state)
937 # On entry:
938 #  thread_state pointer is in r0
940 #define OFFSET(offset) (offset/4)
941 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
942   memw(r0+#32) = r8
943   memw(r0+#36) = r9
944   memw(r0+#40) = r10
945   memw(r0+#44) = r11
947   memw(r0+#48) = r12
948   memw(r0+#52) = r13
949   memw(r0+#56) = r14
950   memw(r0+#60) = r15
952   memw(r0+#64) = r16
953   memw(r0+#68) = r17
954   memw(r0+#72) = r18
955   memw(r0+#76) = r19
957   memw(r0+#80) = r20
958   memw(r0+#84) = r21
959   memw(r0+#88) = r22
960   memw(r0+#92) = r23
962   memw(r0+#96) = r24
963   memw(r0+#100) = r25
964   memw(r0+#104) = r26
965   memw(r0+#108) = r27
967   memw(r0+#112) = r28
968   memw(r0+#116) = r29
969   memw(r0+#120) = r30
970   memw(r0+#124) = r31
971   r1 = c4   // Predicate register
972   memw(r0+#128) = r1
973   r1 = memw(r30)           // *FP == Saved FP
974   r1 = r31
975   memw(r0+#132) = r1
977   jumpr r31
979 #elif defined(__sparc__) && defined(__arch64__)
982 # extern int __unw_getcontext(unw_context_t* thread_state)
984 # On entry:
985 #  thread_state pointer is in %o0
987 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
988   .register %g2, #scratch
989   .register %g3, #scratch
990   .register %g6, #scratch
991   .register %g7, #scratch
992   stx  %g1, [%o0 + 0x08]
993   stx  %g2, [%o0 + 0x10]
994   stx  %g3, [%o0 + 0x18]
995   stx  %g4, [%o0 + 0x20]
996   stx  %g5, [%o0 + 0x28]
997   stx  %g6, [%o0 + 0x30]
998   stx  %g7, [%o0 + 0x38]
999   stx  %o0, [%o0 + 0x40]
1000   stx  %o1, [%o0 + 0x48]
1001   stx  %o2, [%o0 + 0x50]
1002   stx  %o3, [%o0 + 0x58]
1003   stx  %o4, [%o0 + 0x60]
1004   stx  %o5, [%o0 + 0x68]
1005   stx  %o6, [%o0 + 0x70]
1006   stx  %o7, [%o0 + 0x78]
1007   stx  %l0, [%o0 + 0x80]
1008   stx  %l1, [%o0 + 0x88]
1009   stx  %l2, [%o0 + 0x90]
1010   stx  %l3, [%o0 + 0x98]
1011   stx  %l4, [%o0 + 0xa0]
1012   stx  %l5, [%o0 + 0xa8]
1013   stx  %l6, [%o0 + 0xb0]
1014   stx  %l7, [%o0 + 0xb8]
1015   stx  %i0, [%o0 + 0xc0]
1016   stx  %i1, [%o0 + 0xc8]
1017   stx  %i2, [%o0 + 0xd0]
1018   stx  %i3, [%o0 + 0xd8]
1019   stx  %i4, [%o0 + 0xe0]
1020   stx  %i5, [%o0 + 0xe8]
1021   stx  %i6, [%o0 + 0xf0]
1022   stx  %i7, [%o0 + 0xf8]
1024   # save StackGhost cookie
1025   mov  %i7, %g4
1026   save %sp, -176, %sp
1027   # register window flush necessary even without StackGhost
1028   flushw
1029   restore
1030   ldx  [%sp + 2047 + 0x78], %g5
1031   xor  %g4, %g5, %g4
1032   stx  %g4, [%o0 + 0x100]
1033   retl
1034   # return UNW_ESUCCESS
1035    clr %o0
1037 #elif defined(__sparc__)
1040 # extern int __unw_getcontext(unw_context_t* thread_state)
1042 # On entry:
1043 #  thread_state pointer is in o0
1045 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1046   ta 3
1047   add %o7, 8, %o7
1048   std %g0, [%o0 +   0]
1049   std %g2, [%o0 +   8]
1050   std %g4, [%o0 +  16]
1051   std %g6, [%o0 +  24]
1052   std %o0, [%o0 +  32]
1053   std %o2, [%o0 +  40]
1054   std %o4, [%o0 +  48]
1055   std %o6, [%o0 +  56]
1056   std %l0, [%o0 +  64]
1057   std %l2, [%o0 +  72]
1058   std %l4, [%o0 +  80]
1059   std %l6, [%o0 +  88]
1060   std %i0, [%o0 +  96]
1061   std %i2, [%o0 + 104]
1062   std %i4, [%o0 + 112]
1063   std %i6, [%o0 + 120]
1064   jmp %o7
1065    clr %o0                   // return UNW_ESUCCESS
1067 #elif defined(__riscv)
1070 # extern int __unw_getcontext(unw_context_t* thread_state)
1072 # On entry:
1073 #  thread_state pointer is in a0
1075 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1076   ISTORE    x1, (RISCV_ISIZE * 0)(a0) // store ra as pc
1077   .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
1078     ISTORE x\i, (RISCV_ISIZE * \i)(a0)
1079   .endr
1081 # if defined(__riscv_flen)
1082   .irp i,FROM_0_TO_31
1083     FSTORE f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0)
1084   .endr
1085 # endif
1087   li     a0, 0  // return UNW_ESUCCESS
1088   ret           // jump to ra
1090 #elif defined(__s390x__)
1093 // extern int __unw_getcontext(unw_context_t* thread_state)
1095 // On entry:
1096 //  thread_state pointer is in r2
1098 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1100   // Save GPRs
1101   stmg %r0, %r15, 16(%r2)
1103   // Save PSWM
1104   epsw %r0, %r1
1105   stm %r0, %r1, 0(%r2)
1107   // Store return address as PSWA
1108   stg %r14, 8(%r2)
1110   // Save FPRs
1111   .irp i,FROM_0_TO_15
1112     std %f\i, (144+8*\i)(%r2)
1113   .endr
1115   // Return UNW_ESUCCESS
1116   lghi %r2, 0
1117   br %r14
1119 #elif defined(__loongarch__) && __loongarch_grlen == 64
1122 # extern int __unw_getcontext(unw_context_t* thread_state)
1124 # On entry:
1125 #  thread_state pointer is in $a0($r4)
1127 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1128   .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
1129     st.d $r\i, $a0, (8*\i)
1130   .endr
1131   st.d    $r1,  $a0, (8 * 32) // store $ra to pc
1133 # if __loongarch_frlen == 64
1134   .irp i,FROM_0_TO_31
1135     fst.d $f\i, $a0, (8 * 33 + 8 * \i)
1136   .endr
1137 # endif
1139   move     $a0, $zero  // UNW_ESUCCESS
1140   jr       $ra
1142 #endif
1144   WEAK_ALIAS(__unw_getcontext, unw_getcontext)
1146 #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
1148 NO_EXEC_STACK_DIRECTIVE