[AMDGPU] prevent shrinking udiv/urem if either operand is in (SignedMax,UnsignedMax...
[llvm-project.git] / libunwind / src / UnwindRegistersSave.S
bloba489a8ba6df159d8cf855551af0a98d5874a7027
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__) && !defined(__wasm__)
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(4)        // Save r4 first since it will be used for fixing r2.
309 #if defined(_AIX)
310   // The TOC register (r2) was changed by the glue code if unw_getcontext
311   // is called from a different module. Save the original TOC register
312   // in the context if this is the case.
313   mflr   4
314   lwz    4, 0(4)      // Get the first instruction at the return address.
315   xoris  0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"?
316   cmplwi 0, 0x28
317   bne    0, LnoR2Fix  // No need to fix up r2 if it is not.
318   ld     2, 40(1)     // Use the saved TOC register in the stack.
319 LnoR2Fix:
320 #endif
321   PPC64_STR(2)
322   PPC64_STR(3)
323   PPC64_STR(5)
324   PPC64_STR(6)
325   PPC64_STR(7)
326   PPC64_STR(8)
327   PPC64_STR(9)
328   PPC64_STR(10)
329   PPC64_STR(11)
330   PPC64_STR(12)
331   PPC64_STR(13)
332   PPC64_STR(14)
333   PPC64_STR(15)
334   PPC64_STR(16)
335   PPC64_STR(17)
336   PPC64_STR(18)
337   PPC64_STR(19)
338   PPC64_STR(20)
339   PPC64_STR(21)
340   PPC64_STR(22)
341   PPC64_STR(23)
342   PPC64_STR(24)
343   PPC64_STR(25)
344   PPC64_STR(26)
345   PPC64_STR(27)
346   PPC64_STR(28)
347   PPC64_STR(29)
348   PPC64_STR(30)
349   PPC64_STR(31)
351   mfcr  0
352   std   0,  PPC64_OFFS_CR(3)
353   mfxer 0
354   std   0,  PPC64_OFFS_XER(3)
355 #if defined(_AIX)
356   // LR value saved from the register is not used, initialize it to 0.
357   li    0,  0
358 #else
359   mflr  0
360 #endif
361   std   0,  PPC64_OFFS_LR(3)
362   mfctr 0
363   std   0,  PPC64_OFFS_CTR(3)
364   mfvrsave    0
365   std   0,  PPC64_OFFS_VRSAVE(3)
367 #if defined(__VSX__)
368   // save VS registers
369   // (note that this also saves floating point registers and V registers,
370   // because part of VS is mapped to these registers)
372   addi  4, 3, PPC64_OFFS_FP
374 // store VS register
375 #ifdef __LITTLE_ENDIAN__
376 // For little-endian targets, we need a swap since stxvd2x will store the
377 // register in the incorrect doubleword order.
378 // FIXME: when supporting targets older than Power9 on LE is no longer required
379 //        this can be changed to simply `stxv n, 16 * n(4)`.
380 #define PPC64_STVS(n)      \
381   xxswapd n, n            ;\
382   stxvd2x n, 0, 4         ;\
383   addi    4, 4, 16
384 #else
385 #define PPC64_STVS(n)      \
386   stxvd2x n, 0, 4         ;\
387   addi    4, 4, 16
388 #endif
390   PPC64_STVS(0)
391   PPC64_STVS(1)
392   PPC64_STVS(2)
393   PPC64_STVS(3)
394   PPC64_STVS(4)
395   PPC64_STVS(5)
396   PPC64_STVS(6)
397   PPC64_STVS(7)
398   PPC64_STVS(8)
399   PPC64_STVS(9)
400   PPC64_STVS(10)
401   PPC64_STVS(11)
402   PPC64_STVS(12)
403   PPC64_STVS(13)
404   PPC64_STVS(14)
405   PPC64_STVS(15)
406   PPC64_STVS(16)
407   PPC64_STVS(17)
408   PPC64_STVS(18)
409   PPC64_STVS(19)
410   PPC64_STVS(20)
411   PPC64_STVS(21)
412   PPC64_STVS(22)
413   PPC64_STVS(23)
414   PPC64_STVS(24)
415   PPC64_STVS(25)
416   PPC64_STVS(26)
417   PPC64_STVS(27)
418   PPC64_STVS(28)
419   PPC64_STVS(29)
420   PPC64_STVS(30)
421   PPC64_STVS(31)
422   PPC64_STVS(32)
423   PPC64_STVS(33)
424   PPC64_STVS(34)
425   PPC64_STVS(35)
426   PPC64_STVS(36)
427   PPC64_STVS(37)
428   PPC64_STVS(38)
429   PPC64_STVS(39)
430   PPC64_STVS(40)
431   PPC64_STVS(41)
432   PPC64_STVS(42)
433   PPC64_STVS(43)
434   PPC64_STVS(44)
435   PPC64_STVS(45)
436   PPC64_STVS(46)
437   PPC64_STVS(47)
438   PPC64_STVS(48)
439   PPC64_STVS(49)
440   PPC64_STVS(50)
441   PPC64_STVS(51)
442   PPC64_STVS(52)
443   PPC64_STVS(53)
444   PPC64_STVS(54)
445   PPC64_STVS(55)
446   PPC64_STVS(56)
447   PPC64_STVS(57)
448   PPC64_STVS(58)
449   PPC64_STVS(59)
450   PPC64_STVS(60)
451   PPC64_STVS(61)
452   PPC64_STVS(62)
453   PPC64_STVS(63)
455 #else
457 // store FP register
458 #define PPC64_STF(n) \
459   stfd  n, (PPC64_OFFS_FP + n * 16)(3)
461   // save float registers
462   PPC64_STF(0)
463   PPC64_STF(1)
464   PPC64_STF(2)
465   PPC64_STF(3)
466   PPC64_STF(4)
467   PPC64_STF(5)
468   PPC64_STF(6)
469   PPC64_STF(7)
470   PPC64_STF(8)
471   PPC64_STF(9)
472   PPC64_STF(10)
473   PPC64_STF(11)
474   PPC64_STF(12)
475   PPC64_STF(13)
476   PPC64_STF(14)
477   PPC64_STF(15)
478   PPC64_STF(16)
479   PPC64_STF(17)
480   PPC64_STF(18)
481   PPC64_STF(19)
482   PPC64_STF(20)
483   PPC64_STF(21)
484   PPC64_STF(22)
485   PPC64_STF(23)
486   PPC64_STF(24)
487   PPC64_STF(25)
488   PPC64_STF(26)
489   PPC64_STF(27)
490   PPC64_STF(28)
491   PPC64_STF(29)
492   PPC64_STF(30)
493   PPC64_STF(31)
495 #if defined(__ALTIVEC__)
496   // save vector registers
498   // Use 16-bytes below the stack pointer as an
499   // aligned buffer to save each vector register.
500   // Note that the stack pointer is always 16-byte aligned.
501   subi  4, 1, 16
503 #define PPC64_STV_UNALIGNED(n)             \
504   stvx  n, 0, 4                           ;\
505   ld    5, 0(4)                           ;\
506   std   5, (PPC64_OFFS_V + n * 16)(3)     ;\
507   ld    5, 8(4)                           ;\
508   std   5, (PPC64_OFFS_V + n * 16 + 8)(3)
510   PPC64_STV_UNALIGNED(0)
511   PPC64_STV_UNALIGNED(1)
512   PPC64_STV_UNALIGNED(2)
513   PPC64_STV_UNALIGNED(3)
514   PPC64_STV_UNALIGNED(4)
515   PPC64_STV_UNALIGNED(5)
516   PPC64_STV_UNALIGNED(6)
517   PPC64_STV_UNALIGNED(7)
518   PPC64_STV_UNALIGNED(8)
519   PPC64_STV_UNALIGNED(9)
520   PPC64_STV_UNALIGNED(10)
521   PPC64_STV_UNALIGNED(11)
522   PPC64_STV_UNALIGNED(12)
523   PPC64_STV_UNALIGNED(13)
524   PPC64_STV_UNALIGNED(14)
525   PPC64_STV_UNALIGNED(15)
526   PPC64_STV_UNALIGNED(16)
527   PPC64_STV_UNALIGNED(17)
528   PPC64_STV_UNALIGNED(18)
529   PPC64_STV_UNALIGNED(19)
530   PPC64_STV_UNALIGNED(20)
531   PPC64_STV_UNALIGNED(21)
532   PPC64_STV_UNALIGNED(22)
533   PPC64_STV_UNALIGNED(23)
534   PPC64_STV_UNALIGNED(24)
535   PPC64_STV_UNALIGNED(25)
536   PPC64_STV_UNALIGNED(26)
537   PPC64_STV_UNALIGNED(27)
538   PPC64_STV_UNALIGNED(28)
539   PPC64_STV_UNALIGNED(29)
540   PPC64_STV_UNALIGNED(30)
541   PPC64_STV_UNALIGNED(31)
543 #endif
544 #endif
546   li    3,  0   // return UNW_ESUCCESS
547   blr
550 #elif defined(__powerpc__)
553 // extern int unw_getcontext(unw_context_t* thread_state)
555 // On entry:
556 //  thread_state pointer is in r3
558 #if defined(_AIX)
559 DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)
560 #else
561 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
562 #endif
563   stw     0,   8(3)
564   mflr    0
565   stw     0,   0(3) // store lr as ssr0
566   stw     1,  12(3)
567   stw     4,  24(3) // Save r4 first since it will be used for fixing r2.
568 #if defined(_AIX)
569   // The TOC register (r2) was changed by the glue code if unw_getcontext
570   // is called from a different module. Save the original TOC register
571   // in the context if this is the case.
572   mflr    4
573   lwz     4,  0(4)      // Get the instruction at the return address.
574   xoris   0,  4, 0x8041 // Is it reloading the TOC register "lwz 2,20(1)"?
575   cmplwi  0,  0x14
576   bne     0,  LnoR2Fix  // No need to fix up r2 if it is not.
577   lwz     2,  20(1)     // Use the saved TOC register in the stack.
578 LnoR2Fix:
579 #endif
580   stw     2,  16(3)
581   stw     3,  20(3)
582   stw     5,  28(3)
583   stw     6,  32(3)
584   stw     7,  36(3)
585   stw     8,  40(3)
586   stw     9,  44(3)
587   stw     10, 48(3)
588   stw     11, 52(3)
589   stw     12, 56(3)
590   stw     13, 60(3)
591   stw     14, 64(3)
592   stw     15, 68(3)
593   stw     16, 72(3)
594   stw     17, 76(3)
595   stw     18, 80(3)
596   stw     19, 84(3)
597   stw     20, 88(3)
598   stw     21, 92(3)
599   stw     22, 96(3)
600   stw     23,100(3)
601   stw     24,104(3)
602   stw     25,108(3)
603   stw     26,112(3)
604   stw     27,116(3)
605   stw     28,120(3)
606   stw     29,124(3)
607   stw     30,128(3)
608   stw     31,132(3)
610 #if defined(__ALTIVEC__)
611   // save VRSave register
612   mfspr   0, 256
613   stw     0, 156(3)
614 #endif
615   // save CR registers
616   mfcr    0
617   stw     0, 136(3)
618 #if defined(_AIX)
619   // LR value from the register is not used, initialize it to 0.
620   li      0, 0
621   stw     0, 144(3)
622 #endif
623   // save CTR register
624   mfctr   0
625   stw     0, 148(3)
627 #if !defined(__NO_FPRS__)
628   // save float registers
629   stfd    0, 160(3)
630   stfd    1, 168(3)
631   stfd    2, 176(3)
632   stfd    3, 184(3)
633   stfd    4, 192(3)
634   stfd    5, 200(3)
635   stfd    6, 208(3)
636   stfd    7, 216(3)
637   stfd    8, 224(3)
638   stfd    9, 232(3)
639   stfd    10,240(3)
640   stfd    11,248(3)
641   stfd    12,256(3)
642   stfd    13,264(3)
643   stfd    14,272(3)
644   stfd    15,280(3)
645   stfd    16,288(3)
646   stfd    17,296(3)
647   stfd    18,304(3)
648   stfd    19,312(3)
649   stfd    20,320(3)
650   stfd    21,328(3)
651   stfd    22,336(3)
652   stfd    23,344(3)
653   stfd    24,352(3)
654   stfd    25,360(3)
655   stfd    26,368(3)
656   stfd    27,376(3)
657   stfd    28,384(3)
658   stfd    29,392(3)
659   stfd    30,400(3)
660   stfd    31,408(3)
661 #endif
663 #if defined(__ALTIVEC__)
664   // save vector registers
666   subi    4, 1, 16
667   rlwinm  4, 4, 0, 0, 27  // mask low 4-bits
668   // r4 is now a 16-byte aligned pointer into the red zone
670 #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
671   stvx    _vec, 0, 4               SEPARATOR \
672   lwz     5, 0(4)                  SEPARATOR \
673   stw     5, _offset(3)            SEPARATOR \
674   lwz     5, 4(4)                  SEPARATOR \
675   stw     5, _offset+4(3)          SEPARATOR \
676   lwz     5, 8(4)                  SEPARATOR \
677   stw     5, _offset+8(3)          SEPARATOR \
678   lwz     5, 12(4)                 SEPARATOR \
679   stw     5, _offset+12(3)
681   SAVE_VECTOR_UNALIGNED( 0, 424+0x000)
682   SAVE_VECTOR_UNALIGNED( 1, 424+0x010)
683   SAVE_VECTOR_UNALIGNED( 2, 424+0x020)
684   SAVE_VECTOR_UNALIGNED( 3, 424+0x030)
685   SAVE_VECTOR_UNALIGNED( 4, 424+0x040)
686   SAVE_VECTOR_UNALIGNED( 5, 424+0x050)
687   SAVE_VECTOR_UNALIGNED( 6, 424+0x060)
688   SAVE_VECTOR_UNALIGNED( 7, 424+0x070)
689   SAVE_VECTOR_UNALIGNED( 8, 424+0x080)
690   SAVE_VECTOR_UNALIGNED( 9, 424+0x090)
691   SAVE_VECTOR_UNALIGNED(10, 424+0x0A0)
692   SAVE_VECTOR_UNALIGNED(11, 424+0x0B0)
693   SAVE_VECTOR_UNALIGNED(12, 424+0x0C0)
694   SAVE_VECTOR_UNALIGNED(13, 424+0x0D0)
695   SAVE_VECTOR_UNALIGNED(14, 424+0x0E0)
696   SAVE_VECTOR_UNALIGNED(15, 424+0x0F0)
697   SAVE_VECTOR_UNALIGNED(16, 424+0x100)
698   SAVE_VECTOR_UNALIGNED(17, 424+0x110)
699   SAVE_VECTOR_UNALIGNED(18, 424+0x120)
700   SAVE_VECTOR_UNALIGNED(19, 424+0x130)
701   SAVE_VECTOR_UNALIGNED(20, 424+0x140)
702   SAVE_VECTOR_UNALIGNED(21, 424+0x150)
703   SAVE_VECTOR_UNALIGNED(22, 424+0x160)
704   SAVE_VECTOR_UNALIGNED(23, 424+0x170)
705   SAVE_VECTOR_UNALIGNED(24, 424+0x180)
706   SAVE_VECTOR_UNALIGNED(25, 424+0x190)
707   SAVE_VECTOR_UNALIGNED(26, 424+0x1A0)
708   SAVE_VECTOR_UNALIGNED(27, 424+0x1B0)
709   SAVE_VECTOR_UNALIGNED(28, 424+0x1C0)
710   SAVE_VECTOR_UNALIGNED(29, 424+0x1D0)
711   SAVE_VECTOR_UNALIGNED(30, 424+0x1E0)
712   SAVE_VECTOR_UNALIGNED(31, 424+0x1F0)
713 #endif
715   li      3, 0  // return UNW_ESUCCESS
716   blr
719 #elif defined(__aarch64__)
722 // extern int __unw_getcontext(unw_context_t* thread_state)
724 // On entry:
725 //  thread_state pointer is in x0
727   .p2align 2
728 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
729   stp    x0, x1,  [x0, #0x000]
730   stp    x2, x3,  [x0, #0x010]
731   stp    x4, x5,  [x0, #0x020]
732   stp    x6, x7,  [x0, #0x030]
733   stp    x8, x9,  [x0, #0x040]
734   stp    x10,x11, [x0, #0x050]
735   stp    x12,x13, [x0, #0x060]
736   stp    x14,x15, [x0, #0x070]
737   stp    x16,x17, [x0, #0x080]
738   stp    x18,x19, [x0, #0x090]
739   stp    x20,x21, [x0, #0x0A0]
740   stp    x22,x23, [x0, #0x0B0]
741   stp    x24,x25, [x0, #0x0C0]
742   stp    x26,x27, [x0, #0x0D0]
743   stp    x28,x29, [x0, #0x0E0]
744   str    x30,     [x0, #0x0F0]
745   mov    x1,sp
746   str    x1,      [x0, #0x0F8]
747   str    x30,     [x0, #0x100]    // store return address as pc
748   // skip cpsr
749 #if defined(__ARM_FP) && __ARM_FP != 0
750   stp    d0, d1,  [x0, #0x110]
751   stp    d2, d3,  [x0, #0x120]
752   stp    d4, d5,  [x0, #0x130]
753   stp    d6, d7,  [x0, #0x140]
754   stp    d8, d9,  [x0, #0x150]
755   stp    d10,d11, [x0, #0x160]
756   stp    d12,d13, [x0, #0x170]
757   stp    d14,d15, [x0, #0x180]
758   stp    d16,d17, [x0, #0x190]
759   stp    d18,d19, [x0, #0x1A0]
760   stp    d20,d21, [x0, #0x1B0]
761   stp    d22,d23, [x0, #0x1C0]
762   stp    d24,d25, [x0, #0x1D0]
763   stp    d26,d27, [x0, #0x1E0]
764   stp    d28,d29, [x0, #0x1F0]
765   str    d30,     [x0, #0x200]
766   str    d31,     [x0, #0x208]
767 #endif
768   mov    x0, #0                   // return UNW_ESUCCESS
769   ret
771 #elif defined(__arm__) && !defined(__APPLE__)
773 #if !defined(__ARM_ARCH_ISA_ARM)
774 #if (__ARM_ARCH_ISA_THUMB == 2)
775   .syntax unified
776 #endif
777   .thumb
778 #endif
781 @ extern int __unw_getcontext(unw_context_t* thread_state)
783 @ On entry:
784 @  thread_state pointer is in r0
786 @ Per EHABI #4.7 this only saves the core integer registers.
787 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
788 @ however this is very hard to do for VFP registers because it is unknown
789 @ to the library how many registers are implemented by the architecture.
790 @ Instead, VFP registers are demand saved by logic external to __unw_getcontext.
792   .p2align 2
793 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
794 #if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
795   stm r0!, {r0-r7}
796   mov r1, r8
797   mov r2, r9
798   mov r3, r10
799   stm r0!, {r1-r3}
800   mov r1, r11
801   mov r2, sp
802   mov r3, lr
803   str r1, [r0, #0]   @ r11
804   @ r12 does not need storing, it it the intra-procedure-call scratch register
805   str r2, [r0, #8]   @ sp
806   str r3, [r0, #12]  @ lr
807   str r3, [r0, #16]  @ store return address as pc
808   @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
809   @ It is safe to use here though because we are about to return, and cpsr is
810   @ not expected to be preserved.
811   movs r0, #0        @ return UNW_ESUCCESS
812 #else
813   @ 32bit thumb-2 restrictions for stm:
814   @ . the sp (r13) cannot be in the list
815   @ . the pc (r15) cannot be in the list in an STM instruction
816   stm r0, {r0-r12}
817   str sp, [r0, #52]
818   str lr, [r0, #56]
819   str lr, [r0, #60]  @ store return address as pc
820   mov r0, #0         @ return UNW_ESUCCESS
821 #endif
822   JMP(lr)
825 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
827 @ On entry:
828 @  values pointer is in r0
830   .p2align 2
831 #if defined(__ELF__)
832   .fpu vfpv3-d16
833 #endif
834 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv)
835   vstmia r0, {d0-d15}
836   JMP(lr)
839 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
841 @ On entry:
842 @  values pointer is in r0
844   .p2align 2
845 #if defined(__ELF__)
846   .fpu vfpv3-d16
847 #endif
848 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv)
849   vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
850   JMP(lr)
853 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
855 @ On entry:
856 @  values pointer is in r0
858   .p2align 2
859 #if defined(__ELF__)
860   .fpu vfpv3
861 #endif
862 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv)
863   @ VFP and iwMMX instructions are only available when compiling with the flags
864   @ that enable them. We do not want to do that in the library (because we do not
865   @ want the compiler to generate instructions that access those) but this is
866   @ only accessed if the personality routine needs these registers. Use of
867   @ these registers implies they are, actually, available on the target, so
868   @ it's ok to execute.
869   @ So, generate the instructions using the corresponding coprocessor mnemonic.
870   vstmia r0, {d16-d31}
871   JMP(lr)
873 #if defined(_LIBUNWIND_ARM_WMMX)
876 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
878 @ On entry:
879 @  values pointer is in r0
881   .p2align 2
882 #if defined(__ELF__)
883   .arch armv5te
884 #endif
885 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv)
886   stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
887   stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
888   stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
889   stcl p1, cr3, [r0], #8  @ wstrd wR3, [r0], #8
890   stcl p1, cr4, [r0], #8  @ wstrd wR4, [r0], #8
891   stcl p1, cr5, [r0], #8  @ wstrd wR5, [r0], #8
892   stcl p1, cr6, [r0], #8  @ wstrd wR6, [r0], #8
893   stcl p1, cr7, [r0], #8  @ wstrd wR7, [r0], #8
894   stcl p1, cr8, [r0], #8  @ wstrd wR8, [r0], #8
895   stcl p1, cr9, [r0], #8  @ wstrd wR9, [r0], #8
896   stcl p1, cr10, [r0], #8  @ wstrd wR10, [r0], #8
897   stcl p1, cr11, [r0], #8  @ wstrd wR11, [r0], #8
898   stcl p1, cr12, [r0], #8  @ wstrd wR12, [r0], #8
899   stcl p1, cr13, [r0], #8  @ wstrd wR13, [r0], #8
900   stcl p1, cr14, [r0], #8  @ wstrd wR14, [r0], #8
901   stcl p1, cr15, [r0], #8  @ wstrd wR15, [r0], #8
902   JMP(lr)
905 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
907 @ On entry:
908 @  values pointer is in r0
910   .p2align 2
911 #if defined(__ELF__)
912   .arch armv5te
913 #endif
914 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
915   stc2 p1, cr8, [r0], #4  @ wstrw wCGR0, [r0], #4
916   stc2 p1, cr9, [r0], #4  @ wstrw wCGR1, [r0], #4
917   stc2 p1, cr10, [r0], #4  @ wstrw wCGR2, [r0], #4
918   stc2 p1, cr11, [r0], #4  @ wstrw wCGR3, [r0], #4
919   JMP(lr)
921 #endif
923 #elif defined(__or1k__)
926 # extern int __unw_getcontext(unw_context_t* thread_state)
928 # On entry:
929 #  thread_state pointer is in r3
931 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
932   l.sw       0(r3), r0
933   l.sw       4(r3), r1
934   l.sw       8(r3), r2
935   l.sw      12(r3), r3
936   l.sw      16(r3), r4
937   l.sw      20(r3), r5
938   l.sw      24(r3), r6
939   l.sw      28(r3), r7
940   l.sw      32(r3), r8
941   l.sw      36(r3), r9
942   l.sw      40(r3), r10
943   l.sw      44(r3), r11
944   l.sw      48(r3), r12
945   l.sw      52(r3), r13
946   l.sw      56(r3), r14
947   l.sw      60(r3), r15
948   l.sw      64(r3), r16
949   l.sw      68(r3), r17
950   l.sw      72(r3), r18
951   l.sw      76(r3), r19
952   l.sw      80(r3), r20
953   l.sw      84(r3), r21
954   l.sw      88(r3), r22
955   l.sw      92(r3), r23
956   l.sw      96(r3), r24
957   l.sw     100(r3), r25
958   l.sw     104(r3), r26
959   l.sw     108(r3), r27
960   l.sw     112(r3), r28
961   l.sw     116(r3), r29
962   l.sw     120(r3), r30
963   l.sw     124(r3), r31
964   # store ra to pc
965   l.sw     128(r3), r9
966   # zero epcr
967   l.sw     132(r3), r0
969 #elif defined(__hexagon__)
971 # extern int unw_getcontext(unw_context_t* thread_state)
973 # On entry:
974 #  thread_state pointer is in r0
976 #define OFFSET(offset) (offset/4)
977 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
978   memw(r0+#32) = r8
979   memw(r0+#36) = r9
980   memw(r0+#40) = r10
981   memw(r0+#44) = r11
983   memw(r0+#48) = r12
984   memw(r0+#52) = r13
985   memw(r0+#56) = r14
986   memw(r0+#60) = r15
988   memw(r0+#64) = r16
989   memw(r0+#68) = r17
990   memw(r0+#72) = r18
991   memw(r0+#76) = r19
993   memw(r0+#80) = r20
994   memw(r0+#84) = r21
995   memw(r0+#88) = r22
996   memw(r0+#92) = r23
998   memw(r0+#96) = r24
999   memw(r0+#100) = r25
1000   memw(r0+#104) = r26
1001   memw(r0+#108) = r27
1003   memw(r0+#112) = r28
1004   memw(r0+#116) = r29
1005   memw(r0+#120) = r30
1006   memw(r0+#124) = r31
1007   r1 = c4   // Predicate register
1008   memw(r0+#128) = r1
1009   r1 = memw(r30)           // *FP == Saved FP
1010   r1 = r31
1011   memw(r0+#132) = r1
1013   jumpr r31
1015 #elif defined(__sparc__) && defined(__arch64__)
1018 # extern int __unw_getcontext(unw_context_t* thread_state)
1020 # On entry:
1021 #  thread_state pointer is in %o0
1023 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1024   .register %g2, #scratch
1025   .register %g3, #scratch
1026   .register %g6, #scratch
1027   .register %g7, #scratch
1028   stx  %g1, [%o0 + 0x08]
1029   stx  %g2, [%o0 + 0x10]
1030   stx  %g3, [%o0 + 0x18]
1031   stx  %g4, [%o0 + 0x20]
1032   stx  %g5, [%o0 + 0x28]
1033   stx  %g6, [%o0 + 0x30]
1034   stx  %g7, [%o0 + 0x38]
1035   stx  %o0, [%o0 + 0x40]
1036   stx  %o1, [%o0 + 0x48]
1037   stx  %o2, [%o0 + 0x50]
1038   stx  %o3, [%o0 + 0x58]
1039   stx  %o4, [%o0 + 0x60]
1040   stx  %o5, [%o0 + 0x68]
1041   stx  %o6, [%o0 + 0x70]
1042   stx  %o7, [%o0 + 0x78]
1043   stx  %l0, [%o0 + 0x80]
1044   stx  %l1, [%o0 + 0x88]
1045   stx  %l2, [%o0 + 0x90]
1046   stx  %l3, [%o0 + 0x98]
1047   stx  %l4, [%o0 + 0xa0]
1048   stx  %l5, [%o0 + 0xa8]
1049   stx  %l6, [%o0 + 0xb0]
1050   stx  %l7, [%o0 + 0xb8]
1051   stx  %i0, [%o0 + 0xc0]
1052   stx  %i1, [%o0 + 0xc8]
1053   stx  %i2, [%o0 + 0xd0]
1054   stx  %i3, [%o0 + 0xd8]
1055   stx  %i4, [%o0 + 0xe0]
1056   stx  %i5, [%o0 + 0xe8]
1057   stx  %i6, [%o0 + 0xf0]
1058   stx  %i7, [%o0 + 0xf8]
1060   # save StackGhost cookie
1061   mov  %i7, %g4
1062   save %sp, -176, %sp
1063   # register window flush necessary even without StackGhost
1064   flushw
1065   restore
1066   ldx  [%sp + 2047 + 0x78], %g5
1067   xor  %g4, %g5, %g4
1068   stx  %g4, [%o0 + 0x100]
1069   retl
1070   # return UNW_ESUCCESS
1071    clr %o0
1073 #elif defined(__sparc__)
1076 # extern int __unw_getcontext(unw_context_t* thread_state)
1078 # On entry:
1079 #  thread_state pointer is in o0
1081 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1082   ta 3
1083   add %o7, 8, %o7
1084   std %g0, [%o0 +   0]
1085   std %g2, [%o0 +   8]
1086   std %g4, [%o0 +  16]
1087   std %g6, [%o0 +  24]
1088   std %o0, [%o0 +  32]
1089   std %o2, [%o0 +  40]
1090   std %o4, [%o0 +  48]
1091   std %o6, [%o0 +  56]
1092   std %l0, [%o0 +  64]
1093   std %l2, [%o0 +  72]
1094   std %l4, [%o0 +  80]
1095   std %l6, [%o0 +  88]
1096   std %i0, [%o0 +  96]
1097   std %i2, [%o0 + 104]
1098   std %i4, [%o0 + 112]
1099   std %i6, [%o0 + 120]
1100   jmp %o7
1101    clr %o0                   // return UNW_ESUCCESS
1103 #elif defined(__riscv)
1106 # extern int __unw_getcontext(unw_context_t* thread_state)
1108 # On entry:
1109 #  thread_state pointer is in a0
1111 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1112   ISTORE    x1, (RISCV_ISIZE * 0)(a0) // store ra as pc
1113 #if defined(__riscv_32e)
1114   .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
1115 #else
1116   .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
1117 #endif
1118     ISTORE x\i, (RISCV_ISIZE * \i)(a0)
1119   .endr
1121 # if defined(__riscv_flen)
1122   .irp i,FROM_0_TO_31
1123     FSTORE f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0)
1124   .endr
1125 # endif
1127   li     a0, 0  // return UNW_ESUCCESS
1128   ret           // jump to ra
1130 #elif defined(__s390x__)
1133 // extern int __unw_getcontext(unw_context_t* thread_state)
1135 // On entry:
1136 //  thread_state pointer is in r2
1138 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1140   // Save GPRs
1141   stmg %r0, %r15, 16(%r2)
1143   // Save PSWM
1144   epsw %r0, %r1
1145   stm %r0, %r1, 0(%r2)
1147   // Store return address as PSWA
1148   stg %r14, 8(%r2)
1150   // Save FPRs
1151   .irp i,FROM_0_TO_15
1152     std %f\i, (144+8*\i)(%r2)
1153   .endr
1155   // Return UNW_ESUCCESS
1156   lghi %r2, 0
1157   br %r14
1159 #elif defined(__loongarch__) && __loongarch_grlen == 64
1162 # extern int __unw_getcontext(unw_context_t* thread_state)
1164 # On entry:
1165 #  thread_state pointer is in $a0($r4)
1167 DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1168   .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
1169     st.d $r\i, $a0, (8*\i)
1170   .endr
1171   st.d    $r1,  $a0, (8 * 32) // store $ra to pc
1173 # if __loongarch_frlen == 64
1174   .irp i,FROM_0_TO_31
1175     fst.d $f\i, $a0, (8 * 33 + 8 * \i)
1176   .endr
1177 # endif
1179   move     $a0, $zero  // UNW_ESUCCESS
1180   jr       $ra
1182 #endif
1184   WEAK_ALIAS(__unw_getcontext, unw_getcontext)
1186 #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */
1188 NO_EXEC_STACK_DIRECTIVE