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