xref: /freebsd-src/contrib/llvm-project/libunwind/src/UnwindRegistersSave.S (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
20b57cec5SDimitry Andric//
30b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric//
70b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric#include "assembly.h"
100b57cec5SDimitry Andric
11bdd1243dSDimitry Andric#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
12bdd1243dSDimitry Andric#define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
13bdd1243dSDimitry Andric
14bdd1243dSDimitry Andric#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
15bdd1243dSDimitry Andric#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
16bdd1243dSDimitry Andric
1781ad6265SDimitry Andric#if defined(_AIX)
1881ad6265SDimitry Andric    .toc
1981ad6265SDimitry Andric#else
200b57cec5SDimitry Andric    .text
2181ad6265SDimitry Andric#endif
220b57cec5SDimitry Andric
23*0fca6ea1SDimitry Andric#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric#if defined(__i386__)
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric#
280b57cec5SDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
290b57cec5SDimitry Andric#
300b57cec5SDimitry Andric# On entry:
310b57cec5SDimitry Andric#   +                       +
320b57cec5SDimitry Andric#   +-----------------------+
330b57cec5SDimitry Andric#   + thread_state pointer  +
340b57cec5SDimitry Andric#   +-----------------------+
350b57cec5SDimitry Andric#   + return address        +
360b57cec5SDimitry Andric#   +-----------------------+   <-- SP
370b57cec5SDimitry Andric#   +                       +
380b57cec5SDimitry Andric#
390b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
40349cc55cSDimitry Andric
41349cc55cSDimitry Andric  _LIBUNWIND_CET_ENDBR
420b57cec5SDimitry Andric  push  %eax
430b57cec5SDimitry Andric  movl  8(%esp), %eax
440b57cec5SDimitry Andric  movl  %ebx,  4(%eax)
450b57cec5SDimitry Andric  movl  %ecx,  8(%eax)
460b57cec5SDimitry Andric  movl  %edx, 12(%eax)
470b57cec5SDimitry Andric  movl  %edi, 16(%eax)
480b57cec5SDimitry Andric  movl  %esi, 20(%eax)
490b57cec5SDimitry Andric  movl  %ebp, 24(%eax)
500b57cec5SDimitry Andric  movl  %esp, %edx
510b57cec5SDimitry Andric  addl  $8, %edx
520b57cec5SDimitry Andric  movl  %edx, 28(%eax)  # store what sp was at call site as esp
530b57cec5SDimitry Andric  # skip ss
540b57cec5SDimitry Andric  # skip eflags
550b57cec5SDimitry Andric  movl  4(%esp), %edx
560b57cec5SDimitry Andric  movl  %edx, 40(%eax)  # store return address as eip
570b57cec5SDimitry Andric  # skip cs
580b57cec5SDimitry Andric  # skip ds
590b57cec5SDimitry Andric  # skip es
600b57cec5SDimitry Andric  # skip fs
610b57cec5SDimitry Andric  # skip gs
620b57cec5SDimitry Andric  movl  (%esp), %edx
630b57cec5SDimitry Andric  movl  %edx, (%eax)  # store original eax
640b57cec5SDimitry Andric  popl  %eax
650b57cec5SDimitry Andric  xorl  %eax, %eax    # return UNW_ESUCCESS
660b57cec5SDimitry Andric  ret
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric#elif defined(__x86_64__)
690b57cec5SDimitry Andric
700b57cec5SDimitry Andric#
710b57cec5SDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
720b57cec5SDimitry Andric#
730b57cec5SDimitry Andric# On entry:
740b57cec5SDimitry Andric#  thread_state pointer is in rdi
750b57cec5SDimitry Andric#
760b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
770b57cec5SDimitry Andric#if defined(_WIN64)
780b57cec5SDimitry Andric#define PTR %rcx
790b57cec5SDimitry Andric#define TMP %rdx
800b57cec5SDimitry Andric#else
810b57cec5SDimitry Andric#define PTR %rdi
820b57cec5SDimitry Andric#define TMP %rsi
830b57cec5SDimitry Andric#endif
840b57cec5SDimitry Andric
85349cc55cSDimitry Andric  _LIBUNWIND_CET_ENDBR
860b57cec5SDimitry Andric  movq  %rax,   (PTR)
870b57cec5SDimitry Andric  movq  %rbx,  8(PTR)
880b57cec5SDimitry Andric  movq  %rcx, 16(PTR)
890b57cec5SDimitry Andric  movq  %rdx, 24(PTR)
900b57cec5SDimitry Andric  movq  %rdi, 32(PTR)
910b57cec5SDimitry Andric  movq  %rsi, 40(PTR)
920b57cec5SDimitry Andric  movq  %rbp, 48(PTR)
930b57cec5SDimitry Andric  movq  %rsp, 56(PTR)
940b57cec5SDimitry Andric  addq  $8,   56(PTR)
950b57cec5SDimitry Andric  movq  %r8,  64(PTR)
960b57cec5SDimitry Andric  movq  %r9,  72(PTR)
970b57cec5SDimitry Andric  movq  %r10, 80(PTR)
980b57cec5SDimitry Andric  movq  %r11, 88(PTR)
990b57cec5SDimitry Andric  movq  %r12, 96(PTR)
1000b57cec5SDimitry Andric  movq  %r13,104(PTR)
1010b57cec5SDimitry Andric  movq  %r14,112(PTR)
1020b57cec5SDimitry Andric  movq  %r15,120(PTR)
1030b57cec5SDimitry Andric  movq  (%rsp),TMP
1040b57cec5SDimitry Andric  movq  TMP,128(PTR) # store return address as rip
1050b57cec5SDimitry Andric  # skip rflags
1060b57cec5SDimitry Andric  # skip cs
1070b57cec5SDimitry Andric  # skip fs
1080b57cec5SDimitry Andric  # skip gs
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric#if defined(_WIN64)
1110b57cec5SDimitry Andric  movdqu %xmm0,176(PTR)
1120b57cec5SDimitry Andric  movdqu %xmm1,192(PTR)
1130b57cec5SDimitry Andric  movdqu %xmm2,208(PTR)
1140b57cec5SDimitry Andric  movdqu %xmm3,224(PTR)
1150b57cec5SDimitry Andric  movdqu %xmm4,240(PTR)
1160b57cec5SDimitry Andric  movdqu %xmm5,256(PTR)
1170b57cec5SDimitry Andric  movdqu %xmm6,272(PTR)
1180b57cec5SDimitry Andric  movdqu %xmm7,288(PTR)
1190b57cec5SDimitry Andric  movdqu %xmm8,304(PTR)
1200b57cec5SDimitry Andric  movdqu %xmm9,320(PTR)
1210b57cec5SDimitry Andric  movdqu %xmm10,336(PTR)
1220b57cec5SDimitry Andric  movdqu %xmm11,352(PTR)
1230b57cec5SDimitry Andric  movdqu %xmm12,368(PTR)
1240b57cec5SDimitry Andric  movdqu %xmm13,384(PTR)
1250b57cec5SDimitry Andric  movdqu %xmm14,400(PTR)
1260b57cec5SDimitry Andric  movdqu %xmm15,416(PTR)
1270b57cec5SDimitry Andric#endif
1280b57cec5SDimitry Andric  xorl  %eax, %eax    # return UNW_ESUCCESS
1290b57cec5SDimitry Andric  ret
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric#
1340b57cec5SDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
1350b57cec5SDimitry Andric#
1360b57cec5SDimitry Andric# On entry:
1370b57cec5SDimitry Andric#  thread_state pointer is in a0 ($4)
1380b57cec5SDimitry Andric#
1390b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1400b57cec5SDimitry Andric  .set push
1410b57cec5SDimitry Andric  .set noat
1420b57cec5SDimitry Andric  .set noreorder
1430b57cec5SDimitry Andric  .set nomacro
1440b57cec5SDimitry Andric  sw    $1, (4 * 1)($4)
1450b57cec5SDimitry Andric  sw    $2, (4 * 2)($4)
1460b57cec5SDimitry Andric  sw    $3, (4 * 3)($4)
1470b57cec5SDimitry Andric  sw    $4, (4 * 4)($4)
1480b57cec5SDimitry Andric  sw    $5, (4 * 5)($4)
1490b57cec5SDimitry Andric  sw    $6, (4 * 6)($4)
1500b57cec5SDimitry Andric  sw    $7, (4 * 7)($4)
1510b57cec5SDimitry Andric  sw    $8, (4 * 8)($4)
1520b57cec5SDimitry Andric  sw    $9, (4 * 9)($4)
1530b57cec5SDimitry Andric  sw    $10, (4 * 10)($4)
1540b57cec5SDimitry Andric  sw    $11, (4 * 11)($4)
1550b57cec5SDimitry Andric  sw    $12, (4 * 12)($4)
1560b57cec5SDimitry Andric  sw    $13, (4 * 13)($4)
1570b57cec5SDimitry Andric  sw    $14, (4 * 14)($4)
1580b57cec5SDimitry Andric  sw    $15, (4 * 15)($4)
1590b57cec5SDimitry Andric  sw    $16, (4 * 16)($4)
1600b57cec5SDimitry Andric  sw    $17, (4 * 17)($4)
1610b57cec5SDimitry Andric  sw    $18, (4 * 18)($4)
1620b57cec5SDimitry Andric  sw    $19, (4 * 19)($4)
1630b57cec5SDimitry Andric  sw    $20, (4 * 20)($4)
1640b57cec5SDimitry Andric  sw    $21, (4 * 21)($4)
1650b57cec5SDimitry Andric  sw    $22, (4 * 22)($4)
1660b57cec5SDimitry Andric  sw    $23, (4 * 23)($4)
1670b57cec5SDimitry Andric  sw    $24, (4 * 24)($4)
1680b57cec5SDimitry Andric  sw    $25, (4 * 25)($4)
1690b57cec5SDimitry Andric  sw    $26, (4 * 26)($4)
1700b57cec5SDimitry Andric  sw    $27, (4 * 27)($4)
1710b57cec5SDimitry Andric  sw    $28, (4 * 28)($4)
1720b57cec5SDimitry Andric  sw    $29, (4 * 29)($4)
1730b57cec5SDimitry Andric  sw    $30, (4 * 30)($4)
1740b57cec5SDimitry Andric  sw    $31, (4 * 31)($4)
1750b57cec5SDimitry Andric  # Store return address to pc
1760b57cec5SDimitry Andric  sw    $31, (4 * 32)($4)
1775f757f3fSDimitry Andric#if __mips_isa_rev < 6
1780b57cec5SDimitry Andric  # hi and lo
1790b57cec5SDimitry Andric  mfhi  $8
1800b57cec5SDimitry Andric  sw    $8,  (4 * 33)($4)
1810b57cec5SDimitry Andric  mflo  $8
1820b57cec5SDimitry Andric  sw    $8,  (4 * 34)($4)
1835f757f3fSDimitry Andric#endif
1840b57cec5SDimitry Andric#ifdef __mips_hard_float
1850b57cec5SDimitry Andric#if __mips_fpr != 64
1860b57cec5SDimitry Andric  sdc1  $f0, (4 * 36 + 8 * 0)($4)
1870b57cec5SDimitry Andric  sdc1  $f2, (4 * 36 + 8 * 2)($4)
1880b57cec5SDimitry Andric  sdc1  $f4, (4 * 36 + 8 * 4)($4)
1890b57cec5SDimitry Andric  sdc1  $f6, (4 * 36 + 8 * 6)($4)
1900b57cec5SDimitry Andric  sdc1  $f8, (4 * 36 + 8 * 8)($4)
1910b57cec5SDimitry Andric  sdc1  $f10, (4 * 36 + 8 * 10)($4)
1920b57cec5SDimitry Andric  sdc1  $f12, (4 * 36 + 8 * 12)($4)
1930b57cec5SDimitry Andric  sdc1  $f14, (4 * 36 + 8 * 14)($4)
1940b57cec5SDimitry Andric  sdc1  $f16, (4 * 36 + 8 * 16)($4)
1950b57cec5SDimitry Andric  sdc1  $f18, (4 * 36 + 8 * 18)($4)
1960b57cec5SDimitry Andric  sdc1  $f20, (4 * 36 + 8 * 20)($4)
1970b57cec5SDimitry Andric  sdc1  $f22, (4 * 36 + 8 * 22)($4)
1980b57cec5SDimitry Andric  sdc1  $f24, (4 * 36 + 8 * 24)($4)
1990b57cec5SDimitry Andric  sdc1  $f26, (4 * 36 + 8 * 26)($4)
2000b57cec5SDimitry Andric  sdc1  $f28, (4 * 36 + 8 * 28)($4)
2010b57cec5SDimitry Andric  sdc1  $f30, (4 * 36 + 8 * 30)($4)
2020b57cec5SDimitry Andric#else
2030b57cec5SDimitry Andric  sdc1  $f0, (4 * 36 + 8 * 0)($4)
2040b57cec5SDimitry Andric  sdc1  $f1, (4 * 36 + 8 * 1)($4)
2050b57cec5SDimitry Andric  sdc1  $f2, (4 * 36 + 8 * 2)($4)
2060b57cec5SDimitry Andric  sdc1  $f3, (4 * 36 + 8 * 3)($4)
2070b57cec5SDimitry Andric  sdc1  $f4, (4 * 36 + 8 * 4)($4)
2080b57cec5SDimitry Andric  sdc1  $f5, (4 * 36 + 8 * 5)($4)
2090b57cec5SDimitry Andric  sdc1  $f6, (4 * 36 + 8 * 6)($4)
2100b57cec5SDimitry Andric  sdc1  $f7, (4 * 36 + 8 * 7)($4)
2110b57cec5SDimitry Andric  sdc1  $f8, (4 * 36 + 8 * 8)($4)
2120b57cec5SDimitry Andric  sdc1  $f9, (4 * 36 + 8 * 9)($4)
2130b57cec5SDimitry Andric  sdc1  $f10, (4 * 36 + 8 * 10)($4)
2140b57cec5SDimitry Andric  sdc1  $f11, (4 * 36 + 8 * 11)($4)
2150b57cec5SDimitry Andric  sdc1  $f12, (4 * 36 + 8 * 12)($4)
2160b57cec5SDimitry Andric  sdc1  $f13, (4 * 36 + 8 * 13)($4)
2170b57cec5SDimitry Andric  sdc1  $f14, (4 * 36 + 8 * 14)($4)
2180b57cec5SDimitry Andric  sdc1  $f15, (4 * 36 + 8 * 15)($4)
2190b57cec5SDimitry Andric  sdc1  $f16, (4 * 36 + 8 * 16)($4)
2200b57cec5SDimitry Andric  sdc1  $f17, (4 * 36 + 8 * 17)($4)
2210b57cec5SDimitry Andric  sdc1  $f18, (4 * 36 + 8 * 18)($4)
2220b57cec5SDimitry Andric  sdc1  $f19, (4 * 36 + 8 * 19)($4)
2230b57cec5SDimitry Andric  sdc1  $f20, (4 * 36 + 8 * 20)($4)
2240b57cec5SDimitry Andric  sdc1  $f21, (4 * 36 + 8 * 21)($4)
2250b57cec5SDimitry Andric  sdc1  $f22, (4 * 36 + 8 * 22)($4)
2260b57cec5SDimitry Andric  sdc1  $f23, (4 * 36 + 8 * 23)($4)
2270b57cec5SDimitry Andric  sdc1  $f24, (4 * 36 + 8 * 24)($4)
2280b57cec5SDimitry Andric  sdc1  $f25, (4 * 36 + 8 * 25)($4)
2290b57cec5SDimitry Andric  sdc1  $f26, (4 * 36 + 8 * 26)($4)
2300b57cec5SDimitry Andric  sdc1  $f27, (4 * 36 + 8 * 27)($4)
2310b57cec5SDimitry Andric  sdc1  $f28, (4 * 36 + 8 * 28)($4)
2320b57cec5SDimitry Andric  sdc1  $f29, (4 * 36 + 8 * 29)($4)
2330b57cec5SDimitry Andric  sdc1  $f30, (4 * 36 + 8 * 30)($4)
2340b57cec5SDimitry Andric  sdc1  $f31, (4 * 36 + 8 * 31)($4)
2350b57cec5SDimitry Andric#endif
2360b57cec5SDimitry Andric#endif
2370b57cec5SDimitry Andric  jr	$31
2380b57cec5SDimitry Andric  # return UNW_ESUCCESS
2390b57cec5SDimitry Andric  or    $2, $0, $0
2400b57cec5SDimitry Andric  .set pop
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric#elif defined(__mips64)
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric#
2450b57cec5SDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
2460b57cec5SDimitry Andric#
2470b57cec5SDimitry Andric# On entry:
2480b57cec5SDimitry Andric#  thread_state pointer is in a0 ($4)
2490b57cec5SDimitry Andric#
2500b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
2510b57cec5SDimitry Andric  .set push
2520b57cec5SDimitry Andric  .set noat
2530b57cec5SDimitry Andric  .set noreorder
2540b57cec5SDimitry Andric  .set nomacro
255bdd1243dSDimitry Andric  .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
256bdd1243dSDimitry Andric    sd $\i, (8 * \i)($4)
257bdd1243dSDimitry Andric  .endr
2580b57cec5SDimitry Andric  # Store return address to pc
2590b57cec5SDimitry Andric  sd    $31, (8 * 32)($4)
2605f757f3fSDimitry Andric#if __mips_isa_rev < 6
2610b57cec5SDimitry Andric  # hi and lo
2620b57cec5SDimitry Andric  mfhi  $8
2630b57cec5SDimitry Andric  sd    $8,  (8 * 33)($4)
2640b57cec5SDimitry Andric  mflo  $8
2650b57cec5SDimitry Andric  sd    $8,  (8 * 34)($4)
2665f757f3fSDimitry Andric#endif
2670b57cec5SDimitry Andric#ifdef __mips_hard_float
268bdd1243dSDimitry Andric  .irp i,FROM_0_TO_31
269bdd1243dSDimitry Andric    sdc1 $f\i, (280+8*\i)($4)
270bdd1243dSDimitry Andric  .endr
2710b57cec5SDimitry Andric#endif
2720b57cec5SDimitry Andric  jr	$31
2730b57cec5SDimitry Andric  # return UNW_ESUCCESS
2740b57cec5SDimitry Andric  or    $2, $0, $0
2750b57cec5SDimitry Andric  .set pop
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric# elif defined(__mips__)
2780b57cec5SDimitry Andric
2790b57cec5SDimitry Andric#
2800b57cec5SDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
2810b57cec5SDimitry Andric#
2820b57cec5SDimitry Andric# Just trap for the time being.
2830b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
2840b57cec5SDimitry Andric  teq $0, $0
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric#elif defined(__powerpc64__)
2870b57cec5SDimitry Andric
2880b57cec5SDimitry Andric//
2890b57cec5SDimitry Andric// extern int __unw_getcontext(unw_context_t* thread_state)
2900b57cec5SDimitry Andric//
2910b57cec5SDimitry Andric// On entry:
2920b57cec5SDimitry Andric//  thread_state pointer is in r3
2930b57cec5SDimitry Andric//
29481ad6265SDimitry Andric#if defined(_AIX)
29581ad6265SDimitry AndricDEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)
29681ad6265SDimitry Andric#else
2970b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
29881ad6265SDimitry Andric#endif
2990b57cec5SDimitry Andric// store register (GPR)
3000b57cec5SDimitry Andric#define PPC64_STR(n) \
301fe6060f1SDimitry Andric  std   n, (8 * (n + 2))(3)
3020b57cec5SDimitry Andric
3030b57cec5SDimitry Andric  // save GPRs
3040b57cec5SDimitry Andric  PPC64_STR(0)
305fe6060f1SDimitry Andric  mflr  0
306fe6060f1SDimitry Andric  std   0, PPC64_OFFS_SRR0(3) // store lr as ssr0
3070b57cec5SDimitry Andric  PPC64_STR(1)
3085f757f3fSDimitry Andric  PPC64_STR(4)        // Save r4 first since it will be used for fixing r2.
3095f757f3fSDimitry Andric#if defined(_AIX)
3105f757f3fSDimitry Andric  // The TOC register (r2) was changed by the glue code if unw_getcontext
3115f757f3fSDimitry Andric  // is called from a different module. Save the original TOC register
3125f757f3fSDimitry Andric  // in the context if this is the case.
3135f757f3fSDimitry Andric  mflr   4
3145f757f3fSDimitry Andric  lwz    4, 0(4)      // Get the first instruction at the return address.
3155f757f3fSDimitry Andric  xoris  0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"?
3165f757f3fSDimitry Andric  cmplwi 0, 0x28
3175f757f3fSDimitry Andric  bne    0, LnoR2Fix  // No need to fix up r2 if it is not.
3185f757f3fSDimitry Andric  ld     2, 40(1)     // Use the saved TOC register in the stack.
3195f757f3fSDimitry AndricLnoR2Fix:
3205f757f3fSDimitry Andric#endif
3210b57cec5SDimitry Andric  PPC64_STR(2)
3220b57cec5SDimitry Andric  PPC64_STR(3)
3230b57cec5SDimitry Andric  PPC64_STR(5)
3240b57cec5SDimitry Andric  PPC64_STR(6)
3250b57cec5SDimitry Andric  PPC64_STR(7)
3260b57cec5SDimitry Andric  PPC64_STR(8)
3270b57cec5SDimitry Andric  PPC64_STR(9)
3280b57cec5SDimitry Andric  PPC64_STR(10)
3290b57cec5SDimitry Andric  PPC64_STR(11)
3300b57cec5SDimitry Andric  PPC64_STR(12)
3310b57cec5SDimitry Andric  PPC64_STR(13)
3320b57cec5SDimitry Andric  PPC64_STR(14)
3330b57cec5SDimitry Andric  PPC64_STR(15)
3340b57cec5SDimitry Andric  PPC64_STR(16)
3350b57cec5SDimitry Andric  PPC64_STR(17)
3360b57cec5SDimitry Andric  PPC64_STR(18)
3370b57cec5SDimitry Andric  PPC64_STR(19)
3380b57cec5SDimitry Andric  PPC64_STR(20)
3390b57cec5SDimitry Andric  PPC64_STR(21)
3400b57cec5SDimitry Andric  PPC64_STR(22)
3410b57cec5SDimitry Andric  PPC64_STR(23)
3420b57cec5SDimitry Andric  PPC64_STR(24)
3430b57cec5SDimitry Andric  PPC64_STR(25)
3440b57cec5SDimitry Andric  PPC64_STR(26)
3450b57cec5SDimitry Andric  PPC64_STR(27)
3460b57cec5SDimitry Andric  PPC64_STR(28)
3470b57cec5SDimitry Andric  PPC64_STR(29)
3480b57cec5SDimitry Andric  PPC64_STR(30)
3490b57cec5SDimitry Andric  PPC64_STR(31)
3500b57cec5SDimitry Andric
351fe6060f1SDimitry Andric  mfcr  0
352fe6060f1SDimitry Andric  std   0,  PPC64_OFFS_CR(3)
353fe6060f1SDimitry Andric  mfxer 0
354fe6060f1SDimitry Andric  std   0,  PPC64_OFFS_XER(3)
3555f757f3fSDimitry Andric#if defined(_AIX)
3565f757f3fSDimitry Andric  // LR value saved from the register is not used, initialize it to 0.
3575f757f3fSDimitry Andric  li    0,  0
3585f757f3fSDimitry Andric#else
359fe6060f1SDimitry Andric  mflr  0
3605f757f3fSDimitry Andric#endif
361fe6060f1SDimitry Andric  std   0,  PPC64_OFFS_LR(3)
362fe6060f1SDimitry Andric  mfctr 0
363fe6060f1SDimitry Andric  std   0,  PPC64_OFFS_CTR(3)
364fe6060f1SDimitry Andric  mfvrsave    0
365fe6060f1SDimitry Andric  std   0,  PPC64_OFFS_VRSAVE(3)
3660b57cec5SDimitry Andric
367e8d8bef9SDimitry Andric#if defined(__VSX__)
3680b57cec5SDimitry Andric  // save VS registers
3690b57cec5SDimitry Andric  // (note that this also saves floating point registers and V registers,
3700b57cec5SDimitry Andric  // because part of VS is mapped to these registers)
3710b57cec5SDimitry Andric
372fe6060f1SDimitry Andric  addi  4, 3, PPC64_OFFS_FP
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andric// store VS register
3751ac55f4cSDimitry Andric#ifdef __LITTLE_ENDIAN__
3761ac55f4cSDimitry Andric// For little-endian targets, we need a swap since stxvd2x will store the
3771ac55f4cSDimitry Andric// register in the incorrect doubleword order.
3781ac55f4cSDimitry Andric// FIXME: when supporting targets older than Power9 on LE is no longer required
3791ac55f4cSDimitry Andric//        this can be changed to simply `stxv n, 16 * n(4)`.
3801ac55f4cSDimitry Andric#define PPC64_STVS(n)      \
3811ac55f4cSDimitry Andric  xxswapd n, n            ;\
3821ac55f4cSDimitry Andric  stxvd2x n, 0, 4         ;\
3831ac55f4cSDimitry Andric  addi    4, 4, 16
3841ac55f4cSDimitry Andric#else
3850b57cec5SDimitry Andric#define PPC64_STVS(n)      \
386fe6060f1SDimitry Andric  stxvd2x n, 0, 4         ;\
387fe6060f1SDimitry Andric  addi    4, 4, 16
3881ac55f4cSDimitry Andric#endif
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric  PPC64_STVS(0)
3910b57cec5SDimitry Andric  PPC64_STVS(1)
3920b57cec5SDimitry Andric  PPC64_STVS(2)
3930b57cec5SDimitry Andric  PPC64_STVS(3)
3940b57cec5SDimitry Andric  PPC64_STVS(4)
3950b57cec5SDimitry Andric  PPC64_STVS(5)
3960b57cec5SDimitry Andric  PPC64_STVS(6)
3970b57cec5SDimitry Andric  PPC64_STVS(7)
3980b57cec5SDimitry Andric  PPC64_STVS(8)
3990b57cec5SDimitry Andric  PPC64_STVS(9)
4000b57cec5SDimitry Andric  PPC64_STVS(10)
4010b57cec5SDimitry Andric  PPC64_STVS(11)
4020b57cec5SDimitry Andric  PPC64_STVS(12)
4030b57cec5SDimitry Andric  PPC64_STVS(13)
4040b57cec5SDimitry Andric  PPC64_STVS(14)
4050b57cec5SDimitry Andric  PPC64_STVS(15)
4060b57cec5SDimitry Andric  PPC64_STVS(16)
4070b57cec5SDimitry Andric  PPC64_STVS(17)
4080b57cec5SDimitry Andric  PPC64_STVS(18)
4090b57cec5SDimitry Andric  PPC64_STVS(19)
4100b57cec5SDimitry Andric  PPC64_STVS(20)
4110b57cec5SDimitry Andric  PPC64_STVS(21)
4120b57cec5SDimitry Andric  PPC64_STVS(22)
4130b57cec5SDimitry Andric  PPC64_STVS(23)
4140b57cec5SDimitry Andric  PPC64_STVS(24)
4150b57cec5SDimitry Andric  PPC64_STVS(25)
4160b57cec5SDimitry Andric  PPC64_STVS(26)
4170b57cec5SDimitry Andric  PPC64_STVS(27)
4180b57cec5SDimitry Andric  PPC64_STVS(28)
4190b57cec5SDimitry Andric  PPC64_STVS(29)
4200b57cec5SDimitry Andric  PPC64_STVS(30)
4210b57cec5SDimitry Andric  PPC64_STVS(31)
4220b57cec5SDimitry Andric  PPC64_STVS(32)
4230b57cec5SDimitry Andric  PPC64_STVS(33)
4240b57cec5SDimitry Andric  PPC64_STVS(34)
4250b57cec5SDimitry Andric  PPC64_STVS(35)
4260b57cec5SDimitry Andric  PPC64_STVS(36)
4270b57cec5SDimitry Andric  PPC64_STVS(37)
4280b57cec5SDimitry Andric  PPC64_STVS(38)
4290b57cec5SDimitry Andric  PPC64_STVS(39)
4300b57cec5SDimitry Andric  PPC64_STVS(40)
4310b57cec5SDimitry Andric  PPC64_STVS(41)
4320b57cec5SDimitry Andric  PPC64_STVS(42)
4330b57cec5SDimitry Andric  PPC64_STVS(43)
4340b57cec5SDimitry Andric  PPC64_STVS(44)
4350b57cec5SDimitry Andric  PPC64_STVS(45)
4360b57cec5SDimitry Andric  PPC64_STVS(46)
4370b57cec5SDimitry Andric  PPC64_STVS(47)
4380b57cec5SDimitry Andric  PPC64_STVS(48)
4390b57cec5SDimitry Andric  PPC64_STVS(49)
4400b57cec5SDimitry Andric  PPC64_STVS(50)
4410b57cec5SDimitry Andric  PPC64_STVS(51)
4420b57cec5SDimitry Andric  PPC64_STVS(52)
4430b57cec5SDimitry Andric  PPC64_STVS(53)
4440b57cec5SDimitry Andric  PPC64_STVS(54)
4450b57cec5SDimitry Andric  PPC64_STVS(55)
4460b57cec5SDimitry Andric  PPC64_STVS(56)
4470b57cec5SDimitry Andric  PPC64_STVS(57)
4480b57cec5SDimitry Andric  PPC64_STVS(58)
4490b57cec5SDimitry Andric  PPC64_STVS(59)
4500b57cec5SDimitry Andric  PPC64_STVS(60)
4510b57cec5SDimitry Andric  PPC64_STVS(61)
4520b57cec5SDimitry Andric  PPC64_STVS(62)
4530b57cec5SDimitry Andric  PPC64_STVS(63)
4540b57cec5SDimitry Andric
4550b57cec5SDimitry Andric#else
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric// store FP register
4580b57cec5SDimitry Andric#define PPC64_STF(n) \
459fe6060f1SDimitry Andric  stfd  n, (PPC64_OFFS_FP + n * 16)(3)
4600b57cec5SDimitry Andric
4610b57cec5SDimitry Andric  // save float registers
4620b57cec5SDimitry Andric  PPC64_STF(0)
4630b57cec5SDimitry Andric  PPC64_STF(1)
4640b57cec5SDimitry Andric  PPC64_STF(2)
4650b57cec5SDimitry Andric  PPC64_STF(3)
4660b57cec5SDimitry Andric  PPC64_STF(4)
4670b57cec5SDimitry Andric  PPC64_STF(5)
4680b57cec5SDimitry Andric  PPC64_STF(6)
4690b57cec5SDimitry Andric  PPC64_STF(7)
4700b57cec5SDimitry Andric  PPC64_STF(8)
4710b57cec5SDimitry Andric  PPC64_STF(9)
4720b57cec5SDimitry Andric  PPC64_STF(10)
4730b57cec5SDimitry Andric  PPC64_STF(11)
4740b57cec5SDimitry Andric  PPC64_STF(12)
4750b57cec5SDimitry Andric  PPC64_STF(13)
4760b57cec5SDimitry Andric  PPC64_STF(14)
4770b57cec5SDimitry Andric  PPC64_STF(15)
4780b57cec5SDimitry Andric  PPC64_STF(16)
4790b57cec5SDimitry Andric  PPC64_STF(17)
4800b57cec5SDimitry Andric  PPC64_STF(18)
4810b57cec5SDimitry Andric  PPC64_STF(19)
4820b57cec5SDimitry Andric  PPC64_STF(20)
4830b57cec5SDimitry Andric  PPC64_STF(21)
4840b57cec5SDimitry Andric  PPC64_STF(22)
4850b57cec5SDimitry Andric  PPC64_STF(23)
4860b57cec5SDimitry Andric  PPC64_STF(24)
4870b57cec5SDimitry Andric  PPC64_STF(25)
4880b57cec5SDimitry Andric  PPC64_STF(26)
4890b57cec5SDimitry Andric  PPC64_STF(27)
4900b57cec5SDimitry Andric  PPC64_STF(28)
4910b57cec5SDimitry Andric  PPC64_STF(29)
4920b57cec5SDimitry Andric  PPC64_STF(30)
4930b57cec5SDimitry Andric  PPC64_STF(31)
4940b57cec5SDimitry Andric
495e8d8bef9SDimitry Andric#if defined(__ALTIVEC__)
4960b57cec5SDimitry Andric  // save vector registers
4970b57cec5SDimitry Andric
4980b57cec5SDimitry Andric  // Use 16-bytes below the stack pointer as an
4990b57cec5SDimitry Andric  // aligned buffer to save each vector register.
5000b57cec5SDimitry Andric  // Note that the stack pointer is always 16-byte aligned.
501fe6060f1SDimitry Andric  subi  4, 1, 16
5020b57cec5SDimitry Andric
5030b57cec5SDimitry Andric#define PPC64_STV_UNALIGNED(n)             \
504fe6060f1SDimitry Andric  stvx  n, 0, 4                           ;\
505fe6060f1SDimitry Andric  ld    5, 0(4)                           ;\
506fe6060f1SDimitry Andric  std   5, (PPC64_OFFS_V + n * 16)(3)     ;\
507fe6060f1SDimitry Andric  ld    5, 8(4)                           ;\
508fe6060f1SDimitry Andric  std   5, (PPC64_OFFS_V + n * 16 + 8)(3)
5090b57cec5SDimitry Andric
5100b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(0)
5110b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(1)
5120b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(2)
5130b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(3)
5140b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(4)
5150b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(5)
5160b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(6)
5170b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(7)
5180b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(8)
5190b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(9)
5200b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(10)
5210b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(11)
5220b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(12)
5230b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(13)
5240b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(14)
5250b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(15)
5260b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(16)
5270b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(17)
5280b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(18)
5290b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(19)
5300b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(20)
5310b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(21)
5320b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(22)
5330b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(23)
5340b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(24)
5350b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(25)
5360b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(26)
5370b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(27)
5380b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(28)
5390b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(29)
5400b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(30)
5410b57cec5SDimitry Andric  PPC64_STV_UNALIGNED(31)
5420b57cec5SDimitry Andric
5430b57cec5SDimitry Andric#endif
544e8d8bef9SDimitry Andric#endif
5450b57cec5SDimitry Andric
546fe6060f1SDimitry Andric  li    3,  0   // return UNW_ESUCCESS
5470b57cec5SDimitry Andric  blr
5480b57cec5SDimitry Andric
5490b57cec5SDimitry Andric
5501fd87a68SDimitry Andric#elif defined(__powerpc__)
5510b57cec5SDimitry Andric
5520b57cec5SDimitry Andric//
5534f73ee07SDimitry Andric// extern int unw_getcontext(unw_context_t* thread_state)
5540b57cec5SDimitry Andric//
5550b57cec5SDimitry Andric// On entry:
5560b57cec5SDimitry Andric//  thread_state pointer is in r3
5570b57cec5SDimitry Andric//
55881ad6265SDimitry Andric#if defined(_AIX)
55981ad6265SDimitry AndricDEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)
56081ad6265SDimitry Andric#else
5610b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
56281ad6265SDimitry Andric#endif
563fe6060f1SDimitry Andric  stw     0,   8(3)
564fe6060f1SDimitry Andric  mflr    0
565fe6060f1SDimitry Andric  stw     0,   0(3) // store lr as ssr0
566fe6060f1SDimitry Andric  stw     1,  12(3)
5675f757f3fSDimitry Andric  stw     4,  24(3) // Save r4 first since it will be used for fixing r2.
5685f757f3fSDimitry Andric#if defined(_AIX)
5695f757f3fSDimitry Andric  // The TOC register (r2) was changed by the glue code if unw_getcontext
5705f757f3fSDimitry Andric  // is called from a different module. Save the original TOC register
5715f757f3fSDimitry Andric  // in the context if this is the case.
5725f757f3fSDimitry Andric  mflr    4
5735f757f3fSDimitry Andric  lwz     4,  0(4)      // Get the instruction at the return address.
5745f757f3fSDimitry Andric  xoris   0,  4, 0x8041 // Is it reloading the TOC register "lwz 2,20(1)"?
5755f757f3fSDimitry Andric  cmplwi  0,  0x14
5765f757f3fSDimitry Andric  bne     0,  LnoR2Fix  // No need to fix up r2 if it is not.
5775f757f3fSDimitry Andric  lwz     2,  20(1)     // Use the saved TOC register in the stack.
5785f757f3fSDimitry AndricLnoR2Fix:
5795f757f3fSDimitry Andric#endif
580fe6060f1SDimitry Andric  stw     2,  16(3)
581fe6060f1SDimitry Andric  stw     3,  20(3)
582fe6060f1SDimitry Andric  stw     5,  28(3)
583fe6060f1SDimitry Andric  stw     6,  32(3)
584fe6060f1SDimitry Andric  stw     7,  36(3)
585fe6060f1SDimitry Andric  stw     8,  40(3)
586fe6060f1SDimitry Andric  stw     9,  44(3)
587fe6060f1SDimitry Andric  stw     10, 48(3)
588fe6060f1SDimitry Andric  stw     11, 52(3)
589fe6060f1SDimitry Andric  stw     12, 56(3)
590fe6060f1SDimitry Andric  stw     13, 60(3)
591fe6060f1SDimitry Andric  stw     14, 64(3)
592fe6060f1SDimitry Andric  stw     15, 68(3)
593fe6060f1SDimitry Andric  stw     16, 72(3)
594fe6060f1SDimitry Andric  stw     17, 76(3)
595fe6060f1SDimitry Andric  stw     18, 80(3)
596fe6060f1SDimitry Andric  stw     19, 84(3)
597fe6060f1SDimitry Andric  stw     20, 88(3)
598fe6060f1SDimitry Andric  stw     21, 92(3)
599fe6060f1SDimitry Andric  stw     22, 96(3)
600fe6060f1SDimitry Andric  stw     23,100(3)
601fe6060f1SDimitry Andric  stw     24,104(3)
602fe6060f1SDimitry Andric  stw     25,108(3)
603fe6060f1SDimitry Andric  stw     26,112(3)
604fe6060f1SDimitry Andric  stw     27,116(3)
605fe6060f1SDimitry Andric  stw     28,120(3)
606fe6060f1SDimitry Andric  stw     29,124(3)
607fe6060f1SDimitry Andric  stw     30,128(3)
608fe6060f1SDimitry Andric  stw     31,132(3)
6090b57cec5SDimitry Andric
610d781ede6SDimitry Andric#if defined(__ALTIVEC__)
6110b57cec5SDimitry Andric  // save VRSave register
612fe6060f1SDimitry Andric  mfspr   0, 256
613fe6060f1SDimitry Andric  stw     0, 156(3)
614d781ede6SDimitry Andric#endif
6150b57cec5SDimitry Andric  // save CR registers
616fe6060f1SDimitry Andric  mfcr    0
617fe6060f1SDimitry Andric  stw     0, 136(3)
6185f757f3fSDimitry Andric#if defined(_AIX)
6195f757f3fSDimitry Andric  // LR value from the register is not used, initialize it to 0.
6205f757f3fSDimitry Andric  li      0, 0
6215f757f3fSDimitry Andric  stw     0, 144(3)
6225f757f3fSDimitry Andric#endif
6230b57cec5SDimitry Andric  // save CTR register
624fe6060f1SDimitry Andric  mfctr   0
625fe6060f1SDimitry Andric  stw     0, 148(3)
6260b57cec5SDimitry Andric
627e8d8bef9SDimitry Andric#if !defined(__NO_FPRS__)
6280b57cec5SDimitry Andric  // save float registers
629fe6060f1SDimitry Andric  stfd    0, 160(3)
630fe6060f1SDimitry Andric  stfd    1, 168(3)
631fe6060f1SDimitry Andric  stfd    2, 176(3)
632fe6060f1SDimitry Andric  stfd    3, 184(3)
633fe6060f1SDimitry Andric  stfd    4, 192(3)
634fe6060f1SDimitry Andric  stfd    5, 200(3)
635fe6060f1SDimitry Andric  stfd    6, 208(3)
636fe6060f1SDimitry Andric  stfd    7, 216(3)
637fe6060f1SDimitry Andric  stfd    8, 224(3)
638fe6060f1SDimitry Andric  stfd    9, 232(3)
639fe6060f1SDimitry Andric  stfd    10,240(3)
640fe6060f1SDimitry Andric  stfd    11,248(3)
641fe6060f1SDimitry Andric  stfd    12,256(3)
642fe6060f1SDimitry Andric  stfd    13,264(3)
643fe6060f1SDimitry Andric  stfd    14,272(3)
644fe6060f1SDimitry Andric  stfd    15,280(3)
645fe6060f1SDimitry Andric  stfd    16,288(3)
646fe6060f1SDimitry Andric  stfd    17,296(3)
647fe6060f1SDimitry Andric  stfd    18,304(3)
648fe6060f1SDimitry Andric  stfd    19,312(3)
649fe6060f1SDimitry Andric  stfd    20,320(3)
650fe6060f1SDimitry Andric  stfd    21,328(3)
651fe6060f1SDimitry Andric  stfd    22,336(3)
652fe6060f1SDimitry Andric  stfd    23,344(3)
653fe6060f1SDimitry Andric  stfd    24,352(3)
654fe6060f1SDimitry Andric  stfd    25,360(3)
655fe6060f1SDimitry Andric  stfd    26,368(3)
656fe6060f1SDimitry Andric  stfd    27,376(3)
657fe6060f1SDimitry Andric  stfd    28,384(3)
658fe6060f1SDimitry Andric  stfd    29,392(3)
659fe6060f1SDimitry Andric  stfd    30,400(3)
660fe6060f1SDimitry Andric  stfd    31,408(3)
661e8d8bef9SDimitry Andric#endif
6620b57cec5SDimitry Andric
663e8d8bef9SDimitry Andric#if defined(__ALTIVEC__)
6640b57cec5SDimitry Andric  // save vector registers
6650b57cec5SDimitry Andric
666fe6060f1SDimitry Andric  subi    4, 1, 16
667fe6060f1SDimitry Andric  rlwinm  4, 4, 0, 0, 27  // mask low 4-bits
6680b57cec5SDimitry Andric  // r4 is now a 16-byte aligned pointer into the red zone
6690b57cec5SDimitry Andric
6700b57cec5SDimitry Andric#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
671fe6060f1SDimitry Andric  stvx    _vec, 0, 4               SEPARATOR \
672fe6060f1SDimitry Andric  lwz     5, 0(4)                  SEPARATOR \
673fe6060f1SDimitry Andric  stw     5, _offset(3)            SEPARATOR \
674fe6060f1SDimitry Andric  lwz     5, 4(4)                  SEPARATOR \
675fe6060f1SDimitry Andric  stw     5, _offset+4(3)          SEPARATOR \
676fe6060f1SDimitry Andric  lwz     5, 8(4)                  SEPARATOR \
677fe6060f1SDimitry Andric  stw     5, _offset+8(3)          SEPARATOR \
678fe6060f1SDimitry Andric  lwz     5, 12(4)                 SEPARATOR \
679fe6060f1SDimitry Andric  stw     5, _offset+12(3)
6800b57cec5SDimitry Andric
681fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 0, 424+0x000)
682fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 1, 424+0x010)
683fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 2, 424+0x020)
684fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 3, 424+0x030)
685fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 4, 424+0x040)
686fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 5, 424+0x050)
687fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 6, 424+0x060)
688fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 7, 424+0x070)
689fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 8, 424+0x080)
690fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED( 9, 424+0x090)
691fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(10, 424+0x0A0)
692fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(11, 424+0x0B0)
693fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(12, 424+0x0C0)
694fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(13, 424+0x0D0)
695fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(14, 424+0x0E0)
696fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(15, 424+0x0F0)
697fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(16, 424+0x100)
698fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(17, 424+0x110)
699fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(18, 424+0x120)
700fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(19, 424+0x130)
701fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(20, 424+0x140)
702fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(21, 424+0x150)
703fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(22, 424+0x160)
704fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(23, 424+0x170)
705fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(24, 424+0x180)
706fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(25, 424+0x190)
707fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(26, 424+0x1A0)
708fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(27, 424+0x1B0)
709fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(28, 424+0x1C0)
710fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(29, 424+0x1D0)
711fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(30, 424+0x1E0)
712fe6060f1SDimitry Andric  SAVE_VECTOR_UNALIGNED(31, 424+0x1F0)
713e8d8bef9SDimitry Andric#endif
7140b57cec5SDimitry Andric
715fe6060f1SDimitry Andric  li      3, 0  // return UNW_ESUCCESS
7160b57cec5SDimitry Andric  blr
7170b57cec5SDimitry Andric
7180b57cec5SDimitry Andric
7195ffd83dbSDimitry Andric#elif defined(__aarch64__)
7200b57cec5SDimitry Andric
7210b57cec5SDimitry Andric//
7220b57cec5SDimitry Andric// extern int __unw_getcontext(unw_context_t* thread_state)
7230b57cec5SDimitry Andric//
7240b57cec5SDimitry Andric// On entry:
7250b57cec5SDimitry Andric//  thread_state pointer is in x0
7260b57cec5SDimitry Andric//
7270b57cec5SDimitry Andric  .p2align 2
7280b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
7290b57cec5SDimitry Andric  stp    x0, x1,  [x0, #0x000]
7300b57cec5SDimitry Andric  stp    x2, x3,  [x0, #0x010]
7310b57cec5SDimitry Andric  stp    x4, x5,  [x0, #0x020]
7320b57cec5SDimitry Andric  stp    x6, x7,  [x0, #0x030]
7330b57cec5SDimitry Andric  stp    x8, x9,  [x0, #0x040]
7340b57cec5SDimitry Andric  stp    x10,x11, [x0, #0x050]
7350b57cec5SDimitry Andric  stp    x12,x13, [x0, #0x060]
7360b57cec5SDimitry Andric  stp    x14,x15, [x0, #0x070]
7370b57cec5SDimitry Andric  stp    x16,x17, [x0, #0x080]
7380b57cec5SDimitry Andric  stp    x18,x19, [x0, #0x090]
7390b57cec5SDimitry Andric  stp    x20,x21, [x0, #0x0A0]
7400b57cec5SDimitry Andric  stp    x22,x23, [x0, #0x0B0]
7410b57cec5SDimitry Andric  stp    x24,x25, [x0, #0x0C0]
7420b57cec5SDimitry Andric  stp    x26,x27, [x0, #0x0D0]
7430b57cec5SDimitry Andric  stp    x28,x29, [x0, #0x0E0]
7440b57cec5SDimitry Andric  str    x30,     [x0, #0x0F0]
7450b57cec5SDimitry Andric  mov    x1,sp
7460b57cec5SDimitry Andric  str    x1,      [x0, #0x0F8]
7470b57cec5SDimitry Andric  str    x30,     [x0, #0x100]    // store return address as pc
7480b57cec5SDimitry Andric  // skip cpsr
7490b57cec5SDimitry Andric  stp    d0, d1,  [x0, #0x110]
7500b57cec5SDimitry Andric  stp    d2, d3,  [x0, #0x120]
7510b57cec5SDimitry Andric  stp    d4, d5,  [x0, #0x130]
7520b57cec5SDimitry Andric  stp    d6, d7,  [x0, #0x140]
7530b57cec5SDimitry Andric  stp    d8, d9,  [x0, #0x150]
7540b57cec5SDimitry Andric  stp    d10,d11, [x0, #0x160]
7550b57cec5SDimitry Andric  stp    d12,d13, [x0, #0x170]
7560b57cec5SDimitry Andric  stp    d14,d15, [x0, #0x180]
7570b57cec5SDimitry Andric  stp    d16,d17, [x0, #0x190]
7580b57cec5SDimitry Andric  stp    d18,d19, [x0, #0x1A0]
7590b57cec5SDimitry Andric  stp    d20,d21, [x0, #0x1B0]
7600b57cec5SDimitry Andric  stp    d22,d23, [x0, #0x1C0]
7610b57cec5SDimitry Andric  stp    d24,d25, [x0, #0x1D0]
7620b57cec5SDimitry Andric  stp    d26,d27, [x0, #0x1E0]
7630b57cec5SDimitry Andric  stp    d28,d29, [x0, #0x1F0]
7640b57cec5SDimitry Andric  str    d30,     [x0, #0x200]
7650b57cec5SDimitry Andric  str    d31,     [x0, #0x208]
7660b57cec5SDimitry Andric  mov    x0, #0                   // return UNW_ESUCCESS
7670b57cec5SDimitry Andric  ret
7680b57cec5SDimitry Andric
7690b57cec5SDimitry Andric#elif defined(__arm__) && !defined(__APPLE__)
7700b57cec5SDimitry Andric
7710b57cec5SDimitry Andric#if !defined(__ARM_ARCH_ISA_ARM)
7720b57cec5SDimitry Andric#if (__ARM_ARCH_ISA_THUMB == 2)
7730b57cec5SDimitry Andric  .syntax unified
7740b57cec5SDimitry Andric#endif
7750b57cec5SDimitry Andric  .thumb
7760b57cec5SDimitry Andric#endif
7770b57cec5SDimitry Andric
7780b57cec5SDimitry Andric@
7790b57cec5SDimitry Andric@ extern int __unw_getcontext(unw_context_t* thread_state)
7800b57cec5SDimitry Andric@
7810b57cec5SDimitry Andric@ On entry:
7820b57cec5SDimitry Andric@  thread_state pointer is in r0
7830b57cec5SDimitry Andric@
7840b57cec5SDimitry Andric@ Per EHABI #4.7 this only saves the core integer registers.
7850b57cec5SDimitry Andric@ EHABI #7.4.5 notes that in general all VRS registers should be restored
7860b57cec5SDimitry Andric@ however this is very hard to do for VFP registers because it is unknown
7870b57cec5SDimitry Andric@ to the library how many registers are implemented by the architecture.
7880b57cec5SDimitry Andric@ Instead, VFP registers are demand saved by logic external to __unw_getcontext.
7890b57cec5SDimitry Andric@
7900b57cec5SDimitry Andric  .p2align 2
7910b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
7920b57cec5SDimitry Andric#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
7930b57cec5SDimitry Andric  stm r0!, {r0-r7}
7940b57cec5SDimitry Andric  mov r1, r8
7950b57cec5SDimitry Andric  mov r2, r9
7960b57cec5SDimitry Andric  mov r3, r10
7970b57cec5SDimitry Andric  stm r0!, {r1-r3}
7980b57cec5SDimitry Andric  mov r1, r11
7990b57cec5SDimitry Andric  mov r2, sp
8000b57cec5SDimitry Andric  mov r3, lr
8010b57cec5SDimitry Andric  str r1, [r0, #0]   @ r11
8020b57cec5SDimitry Andric  @ r12 does not need storing, it it the intra-procedure-call scratch register
8030b57cec5SDimitry Andric  str r2, [r0, #8]   @ sp
8040b57cec5SDimitry Andric  str r3, [r0, #12]  @ lr
8050b57cec5SDimitry Andric  str r3, [r0, #16]  @ store return address as pc
8060b57cec5SDimitry Andric  @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
8070b57cec5SDimitry Andric  @ It is safe to use here though because we are about to return, and cpsr is
8080b57cec5SDimitry Andric  @ not expected to be preserved.
8090b57cec5SDimitry Andric  movs r0, #0        @ return UNW_ESUCCESS
8100b57cec5SDimitry Andric#else
8110b57cec5SDimitry Andric  @ 32bit thumb-2 restrictions for stm:
8120b57cec5SDimitry Andric  @ . the sp (r13) cannot be in the list
8130b57cec5SDimitry Andric  @ . the pc (r15) cannot be in the list in an STM instruction
8140b57cec5SDimitry Andric  stm r0, {r0-r12}
8150b57cec5SDimitry Andric  str sp, [r0, #52]
8160b57cec5SDimitry Andric  str lr, [r0, #56]
8170b57cec5SDimitry Andric  str lr, [r0, #60]  @ store return address as pc
8180b57cec5SDimitry Andric  mov r0, #0         @ return UNW_ESUCCESS
8190b57cec5SDimitry Andric#endif
8200b57cec5SDimitry Andric  JMP(lr)
8210b57cec5SDimitry Andric
8220b57cec5SDimitry Andric@
8230b57cec5SDimitry Andric@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
8240b57cec5SDimitry Andric@
8250b57cec5SDimitry Andric@ On entry:
8260b57cec5SDimitry Andric@  values pointer is in r0
8270b57cec5SDimitry Andric@
8280b57cec5SDimitry Andric  .p2align 2
8290b57cec5SDimitry Andric#if defined(__ELF__)
8300b57cec5SDimitry Andric  .fpu vfpv3-d16
8310b57cec5SDimitry Andric#endif
8320b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv)
8330b57cec5SDimitry Andric  vstmia r0, {d0-d15}
8340b57cec5SDimitry Andric  JMP(lr)
8350b57cec5SDimitry Andric
8360b57cec5SDimitry Andric@
8370b57cec5SDimitry Andric@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
8380b57cec5SDimitry Andric@
8390b57cec5SDimitry Andric@ On entry:
8400b57cec5SDimitry Andric@  values pointer is in r0
8410b57cec5SDimitry Andric@
8420b57cec5SDimitry Andric  .p2align 2
8430b57cec5SDimitry Andric#if defined(__ELF__)
8440b57cec5SDimitry Andric  .fpu vfpv3-d16
8450b57cec5SDimitry Andric#endif
8460b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv)
8470b57cec5SDimitry Andric  vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
8480b57cec5SDimitry Andric  JMP(lr)
8490b57cec5SDimitry Andric
8500b57cec5SDimitry Andric@
8510b57cec5SDimitry Andric@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
8520b57cec5SDimitry Andric@
8530b57cec5SDimitry Andric@ On entry:
8540b57cec5SDimitry Andric@  values pointer is in r0
8550b57cec5SDimitry Andric@
8560b57cec5SDimitry Andric  .p2align 2
8570b57cec5SDimitry Andric#if defined(__ELF__)
8580b57cec5SDimitry Andric  .fpu vfpv3
8590b57cec5SDimitry Andric#endif
8600b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv)
8610b57cec5SDimitry Andric  @ VFP and iwMMX instructions are only available when compiling with the flags
8620b57cec5SDimitry Andric  @ that enable them. We do not want to do that in the library (because we do not
8630b57cec5SDimitry Andric  @ want the compiler to generate instructions that access those) but this is
8640b57cec5SDimitry Andric  @ only accessed if the personality routine needs these registers. Use of
8650b57cec5SDimitry Andric  @ these registers implies they are, actually, available on the target, so
8660b57cec5SDimitry Andric  @ it's ok to execute.
8670b57cec5SDimitry Andric  @ So, generate the instructions using the corresponding coprocessor mnemonic.
8680b57cec5SDimitry Andric  vstmia r0, {d16-d31}
8690b57cec5SDimitry Andric  JMP(lr)
8700b57cec5SDimitry Andric
8710b57cec5SDimitry Andric#if defined(_LIBUNWIND_ARM_WMMX)
8720b57cec5SDimitry Andric
8730b57cec5SDimitry Andric@
8740b57cec5SDimitry Andric@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
8750b57cec5SDimitry Andric@
8760b57cec5SDimitry Andric@ On entry:
8770b57cec5SDimitry Andric@  values pointer is in r0
8780b57cec5SDimitry Andric@
8790b57cec5SDimitry Andric  .p2align 2
8800b57cec5SDimitry Andric#if defined(__ELF__)
8810b57cec5SDimitry Andric  .arch armv5te
8820b57cec5SDimitry Andric#endif
8830b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv)
8840b57cec5SDimitry Andric  stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
8850b57cec5SDimitry Andric  stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
8860b57cec5SDimitry Andric  stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
8870b57cec5SDimitry Andric  stcl p1, cr3, [r0], #8  @ wstrd wR3, [r0], #8
8880b57cec5SDimitry Andric  stcl p1, cr4, [r0], #8  @ wstrd wR4, [r0], #8
8890b57cec5SDimitry Andric  stcl p1, cr5, [r0], #8  @ wstrd wR5, [r0], #8
8900b57cec5SDimitry Andric  stcl p1, cr6, [r0], #8  @ wstrd wR6, [r0], #8
8910b57cec5SDimitry Andric  stcl p1, cr7, [r0], #8  @ wstrd wR7, [r0], #8
8920b57cec5SDimitry Andric  stcl p1, cr8, [r0], #8  @ wstrd wR8, [r0], #8
8930b57cec5SDimitry Andric  stcl p1, cr9, [r0], #8  @ wstrd wR9, [r0], #8
8940b57cec5SDimitry Andric  stcl p1, cr10, [r0], #8  @ wstrd wR10, [r0], #8
8950b57cec5SDimitry Andric  stcl p1, cr11, [r0], #8  @ wstrd wR11, [r0], #8
8960b57cec5SDimitry Andric  stcl p1, cr12, [r0], #8  @ wstrd wR12, [r0], #8
8970b57cec5SDimitry Andric  stcl p1, cr13, [r0], #8  @ wstrd wR13, [r0], #8
8980b57cec5SDimitry Andric  stcl p1, cr14, [r0], #8  @ wstrd wR14, [r0], #8
8990b57cec5SDimitry Andric  stcl p1, cr15, [r0], #8  @ wstrd wR15, [r0], #8
9000b57cec5SDimitry Andric  JMP(lr)
9010b57cec5SDimitry Andric
9020b57cec5SDimitry Andric@
9030b57cec5SDimitry Andric@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
9040b57cec5SDimitry Andric@
9050b57cec5SDimitry Andric@ On entry:
9060b57cec5SDimitry Andric@  values pointer is in r0
9070b57cec5SDimitry Andric@
9080b57cec5SDimitry Andric  .p2align 2
9090b57cec5SDimitry Andric#if defined(__ELF__)
9100b57cec5SDimitry Andric  .arch armv5te
9110b57cec5SDimitry Andric#endif
9120b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
9130b57cec5SDimitry Andric  stc2 p1, cr8, [r0], #4  @ wstrw wCGR0, [r0], #4
9140b57cec5SDimitry Andric  stc2 p1, cr9, [r0], #4  @ wstrw wCGR1, [r0], #4
9150b57cec5SDimitry Andric  stc2 p1, cr10, [r0], #4  @ wstrw wCGR2, [r0], #4
9160b57cec5SDimitry Andric  stc2 p1, cr11, [r0], #4  @ wstrw wCGR3, [r0], #4
9170b57cec5SDimitry Andric  JMP(lr)
9180b57cec5SDimitry Andric
9190b57cec5SDimitry Andric#endif
9200b57cec5SDimitry Andric
9210b57cec5SDimitry Andric#elif defined(__or1k__)
9220b57cec5SDimitry Andric
9230b57cec5SDimitry Andric#
9240b57cec5SDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
9250b57cec5SDimitry Andric#
9260b57cec5SDimitry Andric# On entry:
9270b57cec5SDimitry Andric#  thread_state pointer is in r3
9280b57cec5SDimitry Andric#
9290b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
9300b57cec5SDimitry Andric  l.sw       0(r3), r0
9310b57cec5SDimitry Andric  l.sw       4(r3), r1
9320b57cec5SDimitry Andric  l.sw       8(r3), r2
9330b57cec5SDimitry Andric  l.sw      12(r3), r3
9340b57cec5SDimitry Andric  l.sw      16(r3), r4
9350b57cec5SDimitry Andric  l.sw      20(r3), r5
9360b57cec5SDimitry Andric  l.sw      24(r3), r6
9370b57cec5SDimitry Andric  l.sw      28(r3), r7
9380b57cec5SDimitry Andric  l.sw      32(r3), r8
9390b57cec5SDimitry Andric  l.sw      36(r3), r9
9400b57cec5SDimitry Andric  l.sw      40(r3), r10
9410b57cec5SDimitry Andric  l.sw      44(r3), r11
9420b57cec5SDimitry Andric  l.sw      48(r3), r12
9430b57cec5SDimitry Andric  l.sw      52(r3), r13
9440b57cec5SDimitry Andric  l.sw      56(r3), r14
9450b57cec5SDimitry Andric  l.sw      60(r3), r15
9460b57cec5SDimitry Andric  l.sw      64(r3), r16
9470b57cec5SDimitry Andric  l.sw      68(r3), r17
9480b57cec5SDimitry Andric  l.sw      72(r3), r18
9490b57cec5SDimitry Andric  l.sw      76(r3), r19
9500b57cec5SDimitry Andric  l.sw      80(r3), r20
9510b57cec5SDimitry Andric  l.sw      84(r3), r21
9520b57cec5SDimitry Andric  l.sw      88(r3), r22
9530b57cec5SDimitry Andric  l.sw      92(r3), r23
9540b57cec5SDimitry Andric  l.sw      96(r3), r24
9550b57cec5SDimitry Andric  l.sw     100(r3), r25
9560b57cec5SDimitry Andric  l.sw     104(r3), r26
9570b57cec5SDimitry Andric  l.sw     108(r3), r27
9580b57cec5SDimitry Andric  l.sw     112(r3), r28
9590b57cec5SDimitry Andric  l.sw     116(r3), r29
9600b57cec5SDimitry Andric  l.sw     120(r3), r30
9610b57cec5SDimitry Andric  l.sw     124(r3), r31
9620b57cec5SDimitry Andric  # store ra to pc
9630b57cec5SDimitry Andric  l.sw     128(r3), r9
9640b57cec5SDimitry Andric  # zero epcr
9650b57cec5SDimitry Andric  l.sw     132(r3), r0
9660b57cec5SDimitry Andric
9675ffd83dbSDimitry Andric#elif defined(__hexagon__)
9685ffd83dbSDimitry Andric#
9695ffd83dbSDimitry Andric# extern int unw_getcontext(unw_context_t* thread_state)
9705ffd83dbSDimitry Andric#
9715ffd83dbSDimitry Andric# On entry:
9725ffd83dbSDimitry Andric#  thread_state pointer is in r0
9735ffd83dbSDimitry Andric#
9745ffd83dbSDimitry Andric#define OFFSET(offset) (offset/4)
9755ffd83dbSDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
9765ffd83dbSDimitry Andric  memw(r0+#32) = r8
9775ffd83dbSDimitry Andric  memw(r0+#36) = r9
9785ffd83dbSDimitry Andric  memw(r0+#40) = r10
9795ffd83dbSDimitry Andric  memw(r0+#44) = r11
9805ffd83dbSDimitry Andric
9815ffd83dbSDimitry Andric  memw(r0+#48) = r12
9825ffd83dbSDimitry Andric  memw(r0+#52) = r13
9835ffd83dbSDimitry Andric  memw(r0+#56) = r14
9845ffd83dbSDimitry Andric  memw(r0+#60) = r15
9855ffd83dbSDimitry Andric
9865ffd83dbSDimitry Andric  memw(r0+#64) = r16
9875ffd83dbSDimitry Andric  memw(r0+#68) = r17
9885ffd83dbSDimitry Andric  memw(r0+#72) = r18
9895ffd83dbSDimitry Andric  memw(r0+#76) = r19
9905ffd83dbSDimitry Andric
9915ffd83dbSDimitry Andric  memw(r0+#80) = r20
9925ffd83dbSDimitry Andric  memw(r0+#84) = r21
9935ffd83dbSDimitry Andric  memw(r0+#88) = r22
9945ffd83dbSDimitry Andric  memw(r0+#92) = r23
9955ffd83dbSDimitry Andric
9965ffd83dbSDimitry Andric  memw(r0+#96) = r24
9975ffd83dbSDimitry Andric  memw(r0+#100) = r25
9985ffd83dbSDimitry Andric  memw(r0+#104) = r26
9995ffd83dbSDimitry Andric  memw(r0+#108) = r27
10005ffd83dbSDimitry Andric
10015ffd83dbSDimitry Andric  memw(r0+#112) = r28
10025ffd83dbSDimitry Andric  memw(r0+#116) = r29
10035ffd83dbSDimitry Andric  memw(r0+#120) = r30
10045ffd83dbSDimitry Andric  memw(r0+#124) = r31
10055ffd83dbSDimitry Andric  r1 = c4   // Predicate register
10065ffd83dbSDimitry Andric  memw(r0+#128) = r1
10075ffd83dbSDimitry Andric  r1 = memw(r30)           // *FP == Saved FP
10085ffd83dbSDimitry Andric  r1 = r31
10095ffd83dbSDimitry Andric  memw(r0+#132) = r1
10105ffd83dbSDimitry Andric
10115ffd83dbSDimitry Andric  jumpr r31
10125ffd83dbSDimitry Andric
1013d56accc7SDimitry Andric#elif defined(__sparc__) && defined(__arch64__)
1014d56accc7SDimitry Andric
1015d56accc7SDimitry Andric#
1016d56accc7SDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
1017d56accc7SDimitry Andric#
1018d56accc7SDimitry Andric# On entry:
1019d56accc7SDimitry Andric#  thread_state pointer is in %o0
1020d56accc7SDimitry Andric#
1021d56accc7SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1022d56accc7SDimitry Andric  .register %g2, #scratch
1023d56accc7SDimitry Andric  .register %g3, #scratch
1024d56accc7SDimitry Andric  .register %g6, #scratch
1025d56accc7SDimitry Andric  .register %g7, #scratch
1026d56accc7SDimitry Andric  stx  %g1, [%o0 + 0x08]
1027d56accc7SDimitry Andric  stx  %g2, [%o0 + 0x10]
1028d56accc7SDimitry Andric  stx  %g3, [%o0 + 0x18]
1029d56accc7SDimitry Andric  stx  %g4, [%o0 + 0x20]
1030d56accc7SDimitry Andric  stx  %g5, [%o0 + 0x28]
1031d56accc7SDimitry Andric  stx  %g6, [%o0 + 0x30]
1032d56accc7SDimitry Andric  stx  %g7, [%o0 + 0x38]
1033d56accc7SDimitry Andric  stx  %o0, [%o0 + 0x40]
1034d56accc7SDimitry Andric  stx  %o1, [%o0 + 0x48]
1035d56accc7SDimitry Andric  stx  %o2, [%o0 + 0x50]
1036d56accc7SDimitry Andric  stx  %o3, [%o0 + 0x58]
1037d56accc7SDimitry Andric  stx  %o4, [%o0 + 0x60]
1038d56accc7SDimitry Andric  stx  %o5, [%o0 + 0x68]
1039d56accc7SDimitry Andric  stx  %o6, [%o0 + 0x70]
1040d56accc7SDimitry Andric  stx  %o7, [%o0 + 0x78]
1041d56accc7SDimitry Andric  stx  %l0, [%o0 + 0x80]
1042d56accc7SDimitry Andric  stx  %l1, [%o0 + 0x88]
1043d56accc7SDimitry Andric  stx  %l2, [%o0 + 0x90]
1044d56accc7SDimitry Andric  stx  %l3, [%o0 + 0x98]
1045d56accc7SDimitry Andric  stx  %l4, [%o0 + 0xa0]
1046d56accc7SDimitry Andric  stx  %l5, [%o0 + 0xa8]
1047d56accc7SDimitry Andric  stx  %l6, [%o0 + 0xb0]
1048d56accc7SDimitry Andric  stx  %l7, [%o0 + 0xb8]
1049d56accc7SDimitry Andric  stx  %i0, [%o0 + 0xc0]
1050d56accc7SDimitry Andric  stx  %i1, [%o0 + 0xc8]
1051d56accc7SDimitry Andric  stx  %i2, [%o0 + 0xd0]
1052d56accc7SDimitry Andric  stx  %i3, [%o0 + 0xd8]
1053d56accc7SDimitry Andric  stx  %i4, [%o0 + 0xe0]
1054d56accc7SDimitry Andric  stx  %i5, [%o0 + 0xe8]
1055d56accc7SDimitry Andric  stx  %i6, [%o0 + 0xf0]
1056d56accc7SDimitry Andric  stx  %i7, [%o0 + 0xf8]
1057d56accc7SDimitry Andric
1058d56accc7SDimitry Andric  # save StackGhost cookie
1059d56accc7SDimitry Andric  mov  %i7, %g4
1060d56accc7SDimitry Andric  save %sp, -176, %sp
1061d56accc7SDimitry Andric  # register window flush necessary even without StackGhost
1062d56accc7SDimitry Andric  flushw
1063d56accc7SDimitry Andric  restore
1064d56accc7SDimitry Andric  ldx  [%sp + 2047 + 0x78], %g5
1065d56accc7SDimitry Andric  xor  %g4, %g5, %g4
1066d56accc7SDimitry Andric  stx  %g4, [%o0 + 0x100]
1067d56accc7SDimitry Andric  retl
1068d56accc7SDimitry Andric  # return UNW_ESUCCESS
1069d56accc7SDimitry Andric   clr %o0
1070d56accc7SDimitry Andric
10710b57cec5SDimitry Andric#elif defined(__sparc__)
10720b57cec5SDimitry Andric
10730b57cec5SDimitry Andric#
10740b57cec5SDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
10750b57cec5SDimitry Andric#
10760b57cec5SDimitry Andric# On entry:
10770b57cec5SDimitry Andric#  thread_state pointer is in o0
10780b57cec5SDimitry Andric#
10790b57cec5SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
10800b57cec5SDimitry Andric  ta 3
10810b57cec5SDimitry Andric  add %o7, 8, %o7
10820b57cec5SDimitry Andric  std %g0, [%o0 +   0]
10830b57cec5SDimitry Andric  std %g2, [%o0 +   8]
10840b57cec5SDimitry Andric  std %g4, [%o0 +  16]
10850b57cec5SDimitry Andric  std %g6, [%o0 +  24]
10860b57cec5SDimitry Andric  std %o0, [%o0 +  32]
10870b57cec5SDimitry Andric  std %o2, [%o0 +  40]
10880b57cec5SDimitry Andric  std %o4, [%o0 +  48]
10890b57cec5SDimitry Andric  std %o6, [%o0 +  56]
10900b57cec5SDimitry Andric  std %l0, [%o0 +  64]
10910b57cec5SDimitry Andric  std %l2, [%o0 +  72]
10920b57cec5SDimitry Andric  std %l4, [%o0 +  80]
10930b57cec5SDimitry Andric  std %l6, [%o0 +  88]
10940b57cec5SDimitry Andric  std %i0, [%o0 +  96]
10950b57cec5SDimitry Andric  std %i2, [%o0 + 104]
10960b57cec5SDimitry Andric  std %i4, [%o0 + 112]
10970b57cec5SDimitry Andric  std %i6, [%o0 + 120]
10980b57cec5SDimitry Andric  jmp %o7
10990b57cec5SDimitry Andric   clr %o0                   // return UNW_ESUCCESS
1100480093f4SDimitry Andric
1101fe6060f1SDimitry Andric#elif defined(__riscv)
1102480093f4SDimitry Andric
1103480093f4SDimitry Andric#
1104480093f4SDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
1105480093f4SDimitry Andric#
1106480093f4SDimitry Andric# On entry:
1107480093f4SDimitry Andric#  thread_state pointer is in a0
1108480093f4SDimitry Andric#
1109480093f4SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1110fe6060f1SDimitry Andric  ISTORE    x1, (RISCV_ISIZE * 0)(a0) // store ra as pc
1111bdd1243dSDimitry Andric  .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
1112bdd1243dSDimitry Andric    ISTORE x\i, (RISCV_ISIZE * \i)(a0)
1113bdd1243dSDimitry Andric  .endr
1114480093f4SDimitry Andric
1115fe6060f1SDimitry Andric# if defined(__riscv_flen)
1116bdd1243dSDimitry Andric  .irp i,FROM_0_TO_31
1117bdd1243dSDimitry Andric    FSTORE f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0)
1118bdd1243dSDimitry Andric  .endr
1119480093f4SDimitry Andric# endif
1120480093f4SDimitry Andric
1121480093f4SDimitry Andric  li     a0, 0  // return UNW_ESUCCESS
1122480093f4SDimitry Andric  ret           // jump to ra
112381ad6265SDimitry Andric
112481ad6265SDimitry Andric#elif defined(__s390x__)
112581ad6265SDimitry Andric
112681ad6265SDimitry Andric//
112781ad6265SDimitry Andric// extern int __unw_getcontext(unw_context_t* thread_state)
112881ad6265SDimitry Andric//
112981ad6265SDimitry Andric// On entry:
113081ad6265SDimitry Andric//  thread_state pointer is in r2
113181ad6265SDimitry Andric//
113281ad6265SDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
113381ad6265SDimitry Andric
113481ad6265SDimitry Andric  // Save GPRs
113581ad6265SDimitry Andric  stmg %r0, %r15, 16(%r2)
113681ad6265SDimitry Andric
113781ad6265SDimitry Andric  // Save PSWM
113881ad6265SDimitry Andric  epsw %r0, %r1
113981ad6265SDimitry Andric  stm %r0, %r1, 0(%r2)
114081ad6265SDimitry Andric
114181ad6265SDimitry Andric  // Store return address as PSWA
114281ad6265SDimitry Andric  stg %r14, 8(%r2)
114381ad6265SDimitry Andric
114481ad6265SDimitry Andric  // Save FPRs
1145bdd1243dSDimitry Andric  .irp i,FROM_0_TO_15
1146bdd1243dSDimitry Andric    std %f\i, (144+8*\i)(%r2)
1147bdd1243dSDimitry Andric  .endr
114881ad6265SDimitry Andric
114981ad6265SDimitry Andric  // Return UNW_ESUCCESS
115081ad6265SDimitry Andric  lghi %r2, 0
115181ad6265SDimitry Andric  br %r14
115281ad6265SDimitry Andric
1153bdd1243dSDimitry Andric#elif defined(__loongarch__) && __loongarch_grlen == 64
1154bdd1243dSDimitry Andric
1155bdd1243dSDimitry Andric#
1156bdd1243dSDimitry Andric# extern int __unw_getcontext(unw_context_t* thread_state)
1157bdd1243dSDimitry Andric#
1158bdd1243dSDimitry Andric# On entry:
1159bdd1243dSDimitry Andric#  thread_state pointer is in $a0($r4)
1160bdd1243dSDimitry Andric#
1161bdd1243dSDimitry AndricDEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1162bdd1243dSDimitry Andric  .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
1163bdd1243dSDimitry Andric    st.d $r\i, $a0, (8*\i)
1164bdd1243dSDimitry Andric  .endr
1165bdd1243dSDimitry Andric  st.d    $r1,  $a0, (8 * 32) // store $ra to pc
1166bdd1243dSDimitry Andric
1167bdd1243dSDimitry Andric# if __loongarch_frlen == 64
1168bdd1243dSDimitry Andric  .irp i,FROM_0_TO_31
1169bdd1243dSDimitry Andric    fst.d $f\i, $a0, (8 * 33 + 8 * \i)
1170bdd1243dSDimitry Andric  .endr
1171bdd1243dSDimitry Andric# endif
1172bdd1243dSDimitry Andric
1173bdd1243dSDimitry Andric  move     $a0, $zero  // UNW_ESUCCESS
1174bdd1243dSDimitry Andric  jr       $ra
1175bdd1243dSDimitry Andric
11760b57cec5SDimitry Andric#endif
11770b57cec5SDimitry Andric
11780b57cec5SDimitry Andric  WEAK_ALIAS(__unw_getcontext, unw_getcontext)
11790b57cec5SDimitry Andric
1180*0fca6ea1SDimitry Andric#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */
11810b57cec5SDimitry Andric
11820b57cec5SDimitry AndricNO_EXEC_STACK_DIRECTIVE
1183