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