Home | History | Annotate | Download | only in src
      1 //===------------------------ UnwindRegistersSave.S -----------------------===//
      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     .text
     12 
     13 #if !defined(__USING_SJLJ_EXCEPTIONS__)
     14 
     15 #if defined(__i386__)
     16 
     17 #
     18 # extern int unw_getcontext(unw_context_t* thread_state)
     19 #
     20 # On entry:
     21 #   +                       +
     22 #   +-----------------------+
     23 #   + thread_state pointer  +
     24 #   +-----------------------+
     25 #   + return address        +
     26 #   +-----------------------+   <-- SP
     27 #   +                       +
     28 #
     29 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
     30   push  %eax
     31   movl  8(%esp), %eax
     32   movl  %ebx,  4(%eax)
     33   movl  %ecx,  8(%eax)
     34   movl  %edx, 12(%eax)
     35   movl  %edi, 16(%eax)
     36   movl  %esi, 20(%eax)
     37   movl  %ebp, 24(%eax)
     38   movl  %esp, %edx
     39   addl  $8, %edx
     40   movl  %edx, 28(%eax)  # store what sp was at call site as esp
     41   # skip ss
     42   # skip eflags
     43   movl  4(%esp), %edx
     44   movl  %edx, 40(%eax)  # store return address as eip
     45   # skip cs
     46   # skip ds
     47   # skip es
     48   # skip fs
     49   # skip gs
     50   movl  (%esp), %edx
     51   movl  %edx, (%eax)  # store original eax
     52   popl  %eax
     53   xorl  %eax, %eax    # return UNW_ESUCCESS
     54   ret
     55 
     56 #elif defined(__x86_64__)
     57 
     58 #
     59 # extern int unw_getcontext(unw_context_t* thread_state)
     60 #
     61 # On entry:
     62 #  thread_state pointer is in rdi
     63 #
     64 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
     65 #if defined(_WIN64)
     66 #define PTR %rcx
     67 #define TMP %rdx
     68 #else
     69 #define PTR %rdi
     70 #define TMP %rsi
     71 #endif
     72 
     73   movq  %rax,   (PTR)
     74   movq  %rbx,  8(PTR)
     75   movq  %rcx, 16(PTR)
     76   movq  %rdx, 24(PTR)
     77   movq  %rdi, 32(PTR)
     78   movq  %rsi, 40(PTR)
     79   movq  %rbp, 48(PTR)
     80   movq  %rsp, 56(PTR)
     81   addq  $8,   56(PTR)
     82   movq  %r8,  64(PTR)
     83   movq  %r9,  72(PTR)
     84   movq  %r10, 80(PTR)
     85   movq  %r11, 88(PTR)
     86   movq  %r12, 96(PTR)
     87   movq  %r13,104(PTR)
     88   movq  %r14,112(PTR)
     89   movq  %r15,120(PTR)
     90   movq  (%rsp),TMP
     91   movq  TMP,128(PTR) # store return address as rip
     92   # skip rflags
     93   # skip cs
     94   # skip fs
     95   # skip gs
     96 
     97 #if defined(_WIN64)
     98   movdqu %xmm0,176(PTR)
     99   movdqu %xmm1,192(PTR)
    100   movdqu %xmm2,208(PTR)
    101   movdqu %xmm3,224(PTR)
    102   movdqu %xmm4,240(PTR)
    103   movdqu %xmm5,256(PTR)
    104   movdqu %xmm6,272(PTR)
    105   movdqu %xmm7,288(PTR)
    106   movdqu %xmm8,304(PTR)
    107   movdqu %xmm9,320(PTR)
    108   movdqu %xmm10,336(PTR)
    109   movdqu %xmm11,352(PTR)
    110   movdqu %xmm12,368(PTR)
    111   movdqu %xmm13,384(PTR)
    112   movdqu %xmm14,400(PTR)
    113   movdqu %xmm15,416(PTR)
    114 #endif
    115   xorl  %eax, %eax    # return UNW_ESUCCESS
    116   ret
    117 
    118 #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
    119 
    120 #
    121 # extern int unw_getcontext(unw_context_t* thread_state)
    122 #
    123 # On entry:
    124 #  thread_state pointer is in a0 ($4)
    125 #
    126 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    127   .set push
    128   .set noat
    129   .set noreorder
    130   .set nomacro
    131   sw    $1, (4 * 1)($4)
    132   sw    $2, (4 * 2)($4)
    133   sw    $3, (4 * 3)($4)
    134   sw    $4, (4 * 4)($4)
    135   sw    $5, (4 * 5)($4)
    136   sw    $6, (4 * 6)($4)
    137   sw    $7, (4 * 7)($4)
    138   sw    $8, (4 * 8)($4)
    139   sw    $9, (4 * 9)($4)
    140   sw    $10, (4 * 10)($4)
    141   sw    $11, (4 * 11)($4)
    142   sw    $12, (4 * 12)($4)
    143   sw    $13, (4 * 13)($4)
    144   sw    $14, (4 * 14)($4)
    145   sw    $15, (4 * 15)($4)
    146   sw    $16, (4 * 16)($4)
    147   sw    $17, (4 * 17)($4)
    148   sw    $18, (4 * 18)($4)
    149   sw    $19, (4 * 19)($4)
    150   sw    $20, (4 * 20)($4)
    151   sw    $21, (4 * 21)($4)
    152   sw    $22, (4 * 22)($4)
    153   sw    $23, (4 * 23)($4)
    154   sw    $24, (4 * 24)($4)
    155   sw    $25, (4 * 25)($4)
    156   sw    $26, (4 * 26)($4)
    157   sw    $27, (4 * 27)($4)
    158   sw    $28, (4 * 28)($4)
    159   sw    $29, (4 * 29)($4)
    160   sw    $30, (4 * 30)($4)
    161   sw    $31, (4 * 31)($4)
    162   # Store return address to pc
    163   sw    $31, (4 * 32)($4)
    164   # hi and lo
    165   mfhi  $8
    166   sw    $8,  (4 * 33)($4)
    167   mflo  $8
    168   sw    $8,  (4 * 34)($4)
    169 #ifdef __mips_hard_float
    170 #if __mips_fpr != 64
    171   sdc1  $f0, (4 * 36 + 8 * 0)($4)
    172   sdc1  $f2, (4 * 36 + 8 * 2)($4)
    173   sdc1  $f4, (4 * 36 + 8 * 4)($4)
    174   sdc1  $f6, (4 * 36 + 8 * 6)($4)
    175   sdc1  $f8, (4 * 36 + 8 * 8)($4)
    176   sdc1  $f10, (4 * 36 + 8 * 10)($4)
    177   sdc1  $f12, (4 * 36 + 8 * 12)($4)
    178   sdc1  $f14, (4 * 36 + 8 * 14)($4)
    179   sdc1  $f16, (4 * 36 + 8 * 16)($4)
    180   sdc1  $f18, (4 * 36 + 8 * 18)($4)
    181   sdc1  $f20, (4 * 36 + 8 * 20)($4)
    182   sdc1  $f22, (4 * 36 + 8 * 22)($4)
    183   sdc1  $f24, (4 * 36 + 8 * 24)($4)
    184   sdc1  $f26, (4 * 36 + 8 * 26)($4)
    185   sdc1  $f28, (4 * 36 + 8 * 28)($4)
    186   sdc1  $f30, (4 * 36 + 8 * 30)($4)
    187 #else
    188   sdc1  $f0, (4 * 36 + 8 * 0)($4)
    189   sdc1  $f1, (4 * 36 + 8 * 1)($4)
    190   sdc1  $f2, (4 * 36 + 8 * 2)($4)
    191   sdc1  $f3, (4 * 36 + 8 * 3)($4)
    192   sdc1  $f4, (4 * 36 + 8 * 4)($4)
    193   sdc1  $f5, (4 * 36 + 8 * 5)($4)
    194   sdc1  $f6, (4 * 36 + 8 * 6)($4)
    195   sdc1  $f7, (4 * 36 + 8 * 7)($4)
    196   sdc1  $f8, (4 * 36 + 8 * 8)($4)
    197   sdc1  $f9, (4 * 36 + 8 * 9)($4)
    198   sdc1  $f10, (4 * 36 + 8 * 10)($4)
    199   sdc1  $f11, (4 * 36 + 8 * 11)($4)
    200   sdc1  $f12, (4 * 36 + 8 * 12)($4)
    201   sdc1  $f13, (4 * 36 + 8 * 13)($4)
    202   sdc1  $f14, (4 * 36 + 8 * 14)($4)
    203   sdc1  $f15, (4 * 36 + 8 * 15)($4)
    204   sdc1  $f16, (4 * 36 + 8 * 16)($4)
    205   sdc1  $f17, (4 * 36 + 8 * 17)($4)
    206   sdc1  $f18, (4 * 36 + 8 * 18)($4)
    207   sdc1  $f19, (4 * 36 + 8 * 19)($4)
    208   sdc1  $f20, (4 * 36 + 8 * 20)($4)
    209   sdc1  $f21, (4 * 36 + 8 * 21)($4)
    210   sdc1  $f22, (4 * 36 + 8 * 22)($4)
    211   sdc1  $f23, (4 * 36 + 8 * 23)($4)
    212   sdc1  $f24, (4 * 36 + 8 * 24)($4)
    213   sdc1  $f25, (4 * 36 + 8 * 25)($4)
    214   sdc1  $f26, (4 * 36 + 8 * 26)($4)
    215   sdc1  $f27, (4 * 36 + 8 * 27)($4)
    216   sdc1  $f28, (4 * 36 + 8 * 28)($4)
    217   sdc1  $f29, (4 * 36 + 8 * 29)($4)
    218   sdc1  $f30, (4 * 36 + 8 * 30)($4)
    219   sdc1  $f31, (4 * 36 + 8 * 31)($4)
    220 #endif
    221 #endif
    222   jr	$31
    223   # return UNW_ESUCCESS
    224   or    $2, $0, $0
    225   .set pop
    226 
    227 #elif defined(__mips64)
    228 
    229 #
    230 # extern int unw_getcontext(unw_context_t* thread_state)
    231 #
    232 # On entry:
    233 #  thread_state pointer is in a0 ($4)
    234 #
    235 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    236   .set push
    237   .set noat
    238   .set noreorder
    239   .set nomacro
    240   sd    $1, (8 * 1)($4)
    241   sd    $2, (8 * 2)($4)
    242   sd    $3, (8 * 3)($4)
    243   sd    $4, (8 * 4)($4)
    244   sd    $5, (8 * 5)($4)
    245   sd    $6, (8 * 6)($4)
    246   sd    $7, (8 * 7)($4)
    247   sd    $8, (8 * 8)($4)
    248   sd    $9, (8 * 9)($4)
    249   sd    $10, (8 * 10)($4)
    250   sd    $11, (8 * 11)($4)
    251   sd    $12, (8 * 12)($4)
    252   sd    $13, (8 * 13)($4)
    253   sd    $14, (8 * 14)($4)
    254   sd    $15, (8 * 15)($4)
    255   sd    $16, (8 * 16)($4)
    256   sd    $17, (8 * 17)($4)
    257   sd    $18, (8 * 18)($4)
    258   sd    $19, (8 * 19)($4)
    259   sd    $20, (8 * 20)($4)
    260   sd    $21, (8 * 21)($4)
    261   sd    $22, (8 * 22)($4)
    262   sd    $23, (8 * 23)($4)
    263   sd    $24, (8 * 24)($4)
    264   sd    $25, (8 * 25)($4)
    265   sd    $26, (8 * 26)($4)
    266   sd    $27, (8 * 27)($4)
    267   sd    $28, (8 * 28)($4)
    268   sd    $29, (8 * 29)($4)
    269   sd    $30, (8 * 30)($4)
    270   sd    $31, (8 * 31)($4)
    271   # Store return address to pc
    272   sd    $31, (8 * 32)($4)
    273   # hi and lo
    274   mfhi  $8
    275   sd    $8,  (8 * 33)($4)
    276   mflo  $8
    277   sd    $8,  (8 * 34)($4)
    278 #ifdef __mips_hard_float
    279   sdc1  $f0, (8 * 35)($4)
    280   sdc1  $f1, (8 * 36)($4)
    281   sdc1  $f2, (8 * 37)($4)
    282   sdc1  $f3, (8 * 38)($4)
    283   sdc1  $f4, (8 * 39)($4)
    284   sdc1  $f5, (8 * 40)($4)
    285   sdc1  $f6, (8 * 41)($4)
    286   sdc1  $f7, (8 * 42)($4)
    287   sdc1  $f8, (8 * 43)($4)
    288   sdc1  $f9, (8 * 44)($4)
    289   sdc1  $f10, (8 * 45)($4)
    290   sdc1  $f11, (8 * 46)($4)
    291   sdc1  $f12, (8 * 47)($4)
    292   sdc1  $f13, (8 * 48)($4)
    293   sdc1  $f14, (8 * 49)($4)
    294   sdc1  $f15, (8 * 50)($4)
    295   sdc1  $f16, (8 * 51)($4)
    296   sdc1  $f17, (8 * 52)($4)
    297   sdc1  $f18, (8 * 53)($4)
    298   sdc1  $f19, (8 * 54)($4)
    299   sdc1  $f20, (8 * 55)($4)
    300   sdc1  $f21, (8 * 56)($4)
    301   sdc1  $f22, (8 * 57)($4)
    302   sdc1  $f23, (8 * 58)($4)
    303   sdc1  $f24, (8 * 59)($4)
    304   sdc1  $f25, (8 * 60)($4)
    305   sdc1  $f26, (8 * 61)($4)
    306   sdc1  $f27, (8 * 62)($4)
    307   sdc1  $f28, (8 * 63)($4)
    308   sdc1  $f29, (8 * 64)($4)
    309   sdc1  $f30, (8 * 65)($4)
    310   sdc1  $f31, (8 * 66)($4)
    311 #endif
    312   jr	$31
    313   # return UNW_ESUCCESS
    314   or    $2, $0, $0
    315   .set pop
    316 
    317 # elif defined(__mips__)
    318 
    319 #
    320 # extern int unw_getcontext(unw_context_t* thread_state)
    321 #
    322 # Just trap for the time being.
    323 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    324   teq $0, $0
    325 
    326 #elif defined(__powerpc64__)
    327 
    328 //
    329 // extern int unw_getcontext(unw_context_t* thread_state)
    330 //
    331 // On entry:
    332 //  thread_state pointer is in r3
    333 //
    334 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    335 
    336 // store register (GPR)
    337 #define PPC64_STR(n) \
    338   std   %r##n, (8 * (n + 2))(%r3)
    339 
    340   // save GPRs
    341   PPC64_STR(0)
    342   mflr  %r0
    343   std   %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0
    344   PPC64_STR(1)
    345   PPC64_STR(2)
    346   PPC64_STR(3)
    347   PPC64_STR(4)
    348   PPC64_STR(5)
    349   PPC64_STR(6)
    350   PPC64_STR(7)
    351   PPC64_STR(8)
    352   PPC64_STR(9)
    353   PPC64_STR(10)
    354   PPC64_STR(11)
    355   PPC64_STR(12)
    356   PPC64_STR(13)
    357   PPC64_STR(14)
    358   PPC64_STR(15)
    359   PPC64_STR(16)
    360   PPC64_STR(17)
    361   PPC64_STR(18)
    362   PPC64_STR(19)
    363   PPC64_STR(20)
    364   PPC64_STR(21)
    365   PPC64_STR(22)
    366   PPC64_STR(23)
    367   PPC64_STR(24)
    368   PPC64_STR(25)
    369   PPC64_STR(26)
    370   PPC64_STR(27)
    371   PPC64_STR(28)
    372   PPC64_STR(29)
    373   PPC64_STR(30)
    374   PPC64_STR(31)
    375 
    376   mfcr  %r0
    377   std   %r0,  PPC64_OFFS_CR(%r3)
    378   mfxer %r0
    379   std   %r0,  PPC64_OFFS_XER(%r3)
    380   mflr  %r0
    381   std   %r0,  PPC64_OFFS_LR(%r3)
    382   mfctr %r0
    383   std   %r0,  PPC64_OFFS_CTR(%r3)
    384   mfvrsave    %r0
    385   std   %r0,  PPC64_OFFS_VRSAVE(%r3)
    386 
    387 #ifdef PPC64_HAS_VMX
    388   // save VS registers
    389   // (note that this also saves floating point registers and V registers,
    390   // because part of VS is mapped to these registers)
    391 
    392   addi  %r4, %r3, PPC64_OFFS_FP
    393 
    394 // store VS register
    395 #define PPC64_STVS(n)      \
    396   stxvd2x %vs##n, 0, %r4  ;\
    397   addi    %r4, %r4, 16
    398 
    399   PPC64_STVS(0)
    400   PPC64_STVS(1)
    401   PPC64_STVS(2)
    402   PPC64_STVS(3)
    403   PPC64_STVS(4)
    404   PPC64_STVS(5)
    405   PPC64_STVS(6)
    406   PPC64_STVS(7)
    407   PPC64_STVS(8)
    408   PPC64_STVS(9)
    409   PPC64_STVS(10)
    410   PPC64_STVS(11)
    411   PPC64_STVS(12)
    412   PPC64_STVS(13)
    413   PPC64_STVS(14)
    414   PPC64_STVS(15)
    415   PPC64_STVS(16)
    416   PPC64_STVS(17)
    417   PPC64_STVS(18)
    418   PPC64_STVS(19)
    419   PPC64_STVS(20)
    420   PPC64_STVS(21)
    421   PPC64_STVS(22)
    422   PPC64_STVS(23)
    423   PPC64_STVS(24)
    424   PPC64_STVS(25)
    425   PPC64_STVS(26)
    426   PPC64_STVS(27)
    427   PPC64_STVS(28)
    428   PPC64_STVS(29)
    429   PPC64_STVS(30)
    430   PPC64_STVS(31)
    431   PPC64_STVS(32)
    432   PPC64_STVS(33)
    433   PPC64_STVS(34)
    434   PPC64_STVS(35)
    435   PPC64_STVS(36)
    436   PPC64_STVS(37)
    437   PPC64_STVS(38)
    438   PPC64_STVS(39)
    439   PPC64_STVS(40)
    440   PPC64_STVS(41)
    441   PPC64_STVS(42)
    442   PPC64_STVS(43)
    443   PPC64_STVS(44)
    444   PPC64_STVS(45)
    445   PPC64_STVS(46)
    446   PPC64_STVS(47)
    447   PPC64_STVS(48)
    448   PPC64_STVS(49)
    449   PPC64_STVS(50)
    450   PPC64_STVS(51)
    451   PPC64_STVS(52)
    452   PPC64_STVS(53)
    453   PPC64_STVS(54)
    454   PPC64_STVS(55)
    455   PPC64_STVS(56)
    456   PPC64_STVS(57)
    457   PPC64_STVS(58)
    458   PPC64_STVS(59)
    459   PPC64_STVS(60)
    460   PPC64_STVS(61)
    461   PPC64_STVS(62)
    462   PPC64_STVS(63)
    463 
    464 #else
    465 
    466 // store FP register
    467 #define PPC64_STF(n) \
    468   stfd  %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
    469 
    470   // save float registers
    471   PPC64_STF(0)
    472   PPC64_STF(1)
    473   PPC64_STF(2)
    474   PPC64_STF(3)
    475   PPC64_STF(4)
    476   PPC64_STF(5)
    477   PPC64_STF(6)
    478   PPC64_STF(7)
    479   PPC64_STF(8)
    480   PPC64_STF(9)
    481   PPC64_STF(10)
    482   PPC64_STF(11)
    483   PPC64_STF(12)
    484   PPC64_STF(13)
    485   PPC64_STF(14)
    486   PPC64_STF(15)
    487   PPC64_STF(16)
    488   PPC64_STF(17)
    489   PPC64_STF(18)
    490   PPC64_STF(19)
    491   PPC64_STF(20)
    492   PPC64_STF(21)
    493   PPC64_STF(22)
    494   PPC64_STF(23)
    495   PPC64_STF(24)
    496   PPC64_STF(25)
    497   PPC64_STF(26)
    498   PPC64_STF(27)
    499   PPC64_STF(28)
    500   PPC64_STF(29)
    501   PPC64_STF(30)
    502   PPC64_STF(31)
    503 
    504   // save vector registers
    505 
    506   // Use 16-bytes below the stack pointer as an
    507   // aligned buffer to save each vector register.
    508   // Note that the stack pointer is always 16-byte aligned.
    509   subi  %r4, %r1, 16
    510 
    511 #define PPC64_STV_UNALIGNED(n)                 \
    512   stvx  %v##n, 0, %r4                         ;\
    513   ld    %r5, 0(%r4)                           ;\
    514   std   %r5, (PPC64_OFFS_V + n * 16)(%r3)     ;\
    515   ld    %r5, 8(%r4)                           ;\
    516   std   %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3)
    517 
    518   PPC64_STV_UNALIGNED(0)
    519   PPC64_STV_UNALIGNED(1)
    520   PPC64_STV_UNALIGNED(2)
    521   PPC64_STV_UNALIGNED(3)
    522   PPC64_STV_UNALIGNED(4)
    523   PPC64_STV_UNALIGNED(5)
    524   PPC64_STV_UNALIGNED(6)
    525   PPC64_STV_UNALIGNED(7)
    526   PPC64_STV_UNALIGNED(8)
    527   PPC64_STV_UNALIGNED(9)
    528   PPC64_STV_UNALIGNED(10)
    529   PPC64_STV_UNALIGNED(11)
    530   PPC64_STV_UNALIGNED(12)
    531   PPC64_STV_UNALIGNED(13)
    532   PPC64_STV_UNALIGNED(14)
    533   PPC64_STV_UNALIGNED(15)
    534   PPC64_STV_UNALIGNED(16)
    535   PPC64_STV_UNALIGNED(17)
    536   PPC64_STV_UNALIGNED(18)
    537   PPC64_STV_UNALIGNED(19)
    538   PPC64_STV_UNALIGNED(20)
    539   PPC64_STV_UNALIGNED(21)
    540   PPC64_STV_UNALIGNED(22)
    541   PPC64_STV_UNALIGNED(23)
    542   PPC64_STV_UNALIGNED(24)
    543   PPC64_STV_UNALIGNED(25)
    544   PPC64_STV_UNALIGNED(26)
    545   PPC64_STV_UNALIGNED(27)
    546   PPC64_STV_UNALIGNED(28)
    547   PPC64_STV_UNALIGNED(29)
    548   PPC64_STV_UNALIGNED(30)
    549   PPC64_STV_UNALIGNED(31)
    550 
    551 #endif
    552 
    553   li    %r3,  0   // return UNW_ESUCCESS
    554   blr
    555 
    556 
    557 #elif defined(__ppc__)
    558 
    559 ;
    560 ; extern int unw_getcontext(unw_context_t* thread_state)
    561 ;
    562 ; On entry:
    563 ;  thread_state pointer is in r3
    564 ;
    565 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    566   stw    r0,  8(r3)
    567   mflr  r0
    568   stw    r0,  0(r3)  ; store lr as ssr0
    569   stw    r1, 12(r3)
    570   stw    r2, 16(r3)
    571   stw    r3, 20(r3)
    572   stw    r4, 24(r3)
    573   stw    r5, 28(r3)
    574   stw    r6, 32(r3)
    575   stw    r7, 36(r3)
    576   stw    r8, 40(r3)
    577   stw    r9, 44(r3)
    578   stw     r10, 48(r3)
    579   stw     r11, 52(r3)
    580   stw     r12, 56(r3)
    581   stw     r13, 60(r3)
    582   stw     r14, 64(r3)
    583   stw     r15, 68(r3)
    584   stw     r16, 72(r3)
    585   stw     r17, 76(r3)
    586   stw     r18, 80(r3)
    587   stw     r19, 84(r3)
    588   stw     r20, 88(r3)
    589   stw     r21, 92(r3)
    590   stw     r22, 96(r3)
    591   stw     r23,100(r3)
    592   stw     r24,104(r3)
    593   stw     r25,108(r3)
    594   stw     r26,112(r3)
    595   stw     r27,116(r3)
    596   stw     r28,120(r3)
    597   stw     r29,124(r3)
    598   stw     r30,128(r3)
    599   stw     r31,132(r3)
    600 
    601   ; save VRSave register
    602   mfspr  r0,256
    603   stw    r0,156(r3)
    604   ; save CR registers
    605   mfcr  r0
    606   stw    r0,136(r3)
    607   ; save CTR register
    608   mfctr  r0
    609   stw    r0,148(r3)
    610 
    611   ; save float registers
    612   stfd    f0, 160(r3)
    613   stfd    f1, 168(r3)
    614   stfd    f2, 176(r3)
    615   stfd    f3, 184(r3)
    616   stfd    f4, 192(r3)
    617   stfd    f5, 200(r3)
    618   stfd    f6, 208(r3)
    619   stfd    f7, 216(r3)
    620   stfd    f8, 224(r3)
    621   stfd    f9, 232(r3)
    622   stfd    f10,240(r3)
    623   stfd    f11,248(r3)
    624   stfd    f12,256(r3)
    625   stfd    f13,264(r3)
    626   stfd    f14,272(r3)
    627   stfd    f15,280(r3)
    628   stfd    f16,288(r3)
    629   stfd    f17,296(r3)
    630   stfd    f18,304(r3)
    631   stfd    f19,312(r3)
    632   stfd    f20,320(r3)
    633   stfd    f21,328(r3)
    634   stfd    f22,336(r3)
    635   stfd    f23,344(r3)
    636   stfd    f24,352(r3)
    637   stfd    f25,360(r3)
    638   stfd    f26,368(r3)
    639   stfd    f27,376(r3)
    640   stfd    f28,384(r3)
    641   stfd    f29,392(r3)
    642   stfd    f30,400(r3)
    643   stfd    f31,408(r3)
    644 
    645 
    646   ; save vector registers
    647 
    648   subi  r4,r1,16
    649   rlwinm  r4,r4,0,0,27  ; mask low 4-bits
    650   ; r4 is now a 16-byte aligned pointer into the red zone
    651 
    652 #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
    653   stvx  _vec,0,r4           @\
    654   lwz    r5, 0(r4)          @\
    655   stw    r5, _offset(r3)    @\
    656   lwz    r5, 4(r4)          @\
    657   stw    r5, _offset+4(r3)  @\
    658   lwz    r5, 8(r4)          @\
    659   stw    r5, _offset+8(r3)  @\
    660   lwz    r5, 12(r4)         @\
    661   stw    r5, _offset+12(r3)
    662 
    663   SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
    664   SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
    665   SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
    666   SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
    667   SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
    668   SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
    669   SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
    670   SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
    671   SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
    672   SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
    673   SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
    674   SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
    675   SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
    676   SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
    677   SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
    678   SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
    679   SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
    680   SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
    681   SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
    682   SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
    683   SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
    684   SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
    685   SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
    686   SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
    687   SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
    688   SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
    689   SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
    690   SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
    691   SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
    692   SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
    693   SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
    694   SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
    695 
    696   li  r3, 0    ; return UNW_ESUCCESS
    697   blr
    698 
    699 
    700 #elif defined(__arm64__) || defined(__aarch64__)
    701 
    702 //
    703 // extern int unw_getcontext(unw_context_t* thread_state)
    704 //
    705 // On entry:
    706 //  thread_state pointer is in x0
    707 //
    708   .p2align 2
    709 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    710   stp    x0, x1,  [x0, #0x000]
    711   stp    x2, x3,  [x0, #0x010]
    712   stp    x4, x5,  [x0, #0x020]
    713   stp    x6, x7,  [x0, #0x030]
    714   stp    x8, x9,  [x0, #0x040]
    715   stp    x10,x11, [x0, #0x050]
    716   stp    x12,x13, [x0, #0x060]
    717   stp    x14,x15, [x0, #0x070]
    718   stp    x16,x17, [x0, #0x080]
    719   stp    x18,x19, [x0, #0x090]
    720   stp    x20,x21, [x0, #0x0A0]
    721   stp    x22,x23, [x0, #0x0B0]
    722   stp    x24,x25, [x0, #0x0C0]
    723   stp    x26,x27, [x0, #0x0D0]
    724   stp    x28,x29, [x0, #0x0E0]
    725   str    x30,     [x0, #0x0F0]
    726   mov    x1,sp
    727   str    x1,      [x0, #0x0F8]
    728   str    x30,     [x0, #0x100]    // store return address as pc
    729   // skip cpsr
    730   stp    d0, d1,  [x0, #0x110]
    731   stp    d2, d3,  [x0, #0x120]
    732   stp    d4, d5,  [x0, #0x130]
    733   stp    d6, d7,  [x0, #0x140]
    734   stp    d8, d9,  [x0, #0x150]
    735   stp    d10,d11, [x0, #0x160]
    736   stp    d12,d13, [x0, #0x170]
    737   stp    d14,d15, [x0, #0x180]
    738   stp    d16,d17, [x0, #0x190]
    739   stp    d18,d19, [x0, #0x1A0]
    740   stp    d20,d21, [x0, #0x1B0]
    741   stp    d22,d23, [x0, #0x1C0]
    742   stp    d24,d25, [x0, #0x1D0]
    743   stp    d26,d27, [x0, #0x1E0]
    744   stp    d28,d29, [x0, #0x1F0]
    745   str    d30,     [x0, #0x200]
    746   str    d31,     [x0, #0x208]
    747   mov    x0, #0                   // return UNW_ESUCCESS
    748   ret
    749 
    750 #elif defined(__arm__) && !defined(__APPLE__)
    751 
    752 #if !defined(__ARM_ARCH_ISA_ARM)
    753   .thumb
    754 #endif
    755 
    756 @
    757 @ extern int unw_getcontext(unw_context_t* thread_state)
    758 @
    759 @ On entry:
    760 @  thread_state pointer is in r0
    761 @
    762 @ Per EHABI #4.7 this only saves the core integer registers.
    763 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
    764 @ however this is very hard to do for VFP registers because it is unknown
    765 @ to the library how many registers are implemented by the architecture.
    766 @ Instead, VFP registers are demand saved by logic external to unw_getcontext.
    767 @
    768   .p2align 2
    769 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    770 #if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
    771   stm r0!, {r0-r7}
    772   mov r1, r8
    773   mov r2, r9
    774   mov r3, r10
    775   stm r0!, {r1-r3}
    776   mov r1, r11
    777   mov r2, sp
    778   mov r3, lr
    779   str r1, [r0, #0]   @ r11
    780   @ r12 does not need storing, it it the intra-procedure-call scratch register
    781   str r2, [r0, #8]   @ sp
    782   str r3, [r0, #12]  @ lr
    783   str r3, [r0, #16]  @ store return address as pc
    784   @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
    785   @ It is safe to use here though because we are about to return, and cpsr is
    786   @ not expected to be preserved.
    787   movs r0, #0        @ return UNW_ESUCCESS
    788 #else
    789   @ 32bit thumb-2 restrictions for stm:
    790   @ . the sp (r13) cannot be in the list
    791   @ . the pc (r15) cannot be in the list in an STM instruction
    792   stm r0, {r0-r12}
    793   str sp, [r0, #52]
    794   str lr, [r0, #56]
    795   str lr, [r0, #60]  @ store return address as pc
    796   mov r0, #0         @ return UNW_ESUCCESS
    797 #endif
    798   JMP(lr)
    799 
    800 @
    801 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
    802 @
    803 @ On entry:
    804 @  values pointer is in r0
    805 @
    806   .p2align 2
    807 #if defined(__ELF__)
    808   .fpu vfpv3-d16
    809 #endif
    810 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv)
    811   vstmia r0, {d0-d15}
    812   JMP(lr)
    813 
    814 @
    815 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
    816 @
    817 @ On entry:
    818 @  values pointer is in r0
    819 @
    820   .p2align 2
    821 #if defined(__ELF__)
    822   .fpu vfpv3-d16
    823 #endif
    824 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv)
    825   vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
    826   JMP(lr)
    827 
    828 @
    829 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
    830 @
    831 @ On entry:
    832 @  values pointer is in r0
    833 @
    834   .p2align 2
    835 #if defined(__ELF__)
    836   .fpu vfpv3
    837 #endif
    838 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv)
    839   @ VFP and iwMMX instructions are only available when compiling with the flags
    840   @ that enable them. We do not want to do that in the library (because we do not
    841   @ want the compiler to generate instructions that access those) but this is
    842   @ only accessed if the personality routine needs these registers. Use of
    843   @ these registers implies they are, actually, available on the target, so
    844   @ it's ok to execute.
    845   @ So, generate the instructions using the corresponding coprocessor mnemonic.
    846   vstmia r0, {d16-d31}
    847   JMP(lr)
    848 
    849 #if defined(_LIBUNWIND_ARM_WMMX)
    850 
    851 @
    852 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
    853 @
    854 @ On entry:
    855 @  values pointer is in r0
    856 @
    857   .p2align 2
    858 #if defined(__ELF__)
    859   .arch armv5te
    860 #endif
    861 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv)
    862   stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
    863   stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
    864   stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
    865   stcl p1, cr3, [r0], #8  @ wstrd wR3, [r0], #8
    866   stcl p1, cr4, [r0], #8  @ wstrd wR4, [r0], #8
    867   stcl p1, cr5, [r0], #8  @ wstrd wR5, [r0], #8
    868   stcl p1, cr6, [r0], #8  @ wstrd wR6, [r0], #8
    869   stcl p1, cr7, [r0], #8  @ wstrd wR7, [r0], #8
    870   stcl p1, cr8, [r0], #8  @ wstrd wR8, [r0], #8
    871   stcl p1, cr9, [r0], #8  @ wstrd wR9, [r0], #8
    872   stcl p1, cr10, [r0], #8  @ wstrd wR10, [r0], #8
    873   stcl p1, cr11, [r0], #8  @ wstrd wR11, [r0], #8
    874   stcl p1, cr12, [r0], #8  @ wstrd wR12, [r0], #8
    875   stcl p1, cr13, [r0], #8  @ wstrd wR13, [r0], #8
    876   stcl p1, cr14, [r0], #8  @ wstrd wR14, [r0], #8
    877   stcl p1, cr15, [r0], #8  @ wstrd wR15, [r0], #8
    878   JMP(lr)
    879 
    880 @
    881 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
    882 @
    883 @ On entry:
    884 @  values pointer is in r0
    885 @
    886   .p2align 2
    887 #if defined(__ELF__)
    888   .arch armv5te
    889 #endif
    890 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
    891   stc2 p1, cr8, [r0], #4  @ wstrw wCGR0, [r0], #4
    892   stc2 p1, cr9, [r0], #4  @ wstrw wCGR1, [r0], #4
    893   stc2 p1, cr10, [r0], #4  @ wstrw wCGR2, [r0], #4
    894   stc2 p1, cr11, [r0], #4  @ wstrw wCGR3, [r0], #4
    895   JMP(lr)
    896 
    897 #endif
    898 
    899 #elif defined(__or1k__)
    900 
    901 #
    902 # extern int unw_getcontext(unw_context_t* thread_state)
    903 #
    904 # On entry:
    905 #  thread_state pointer is in r3
    906 #
    907 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    908   l.sw       0(r3), r0
    909   l.sw       4(r3), r1
    910   l.sw       8(r3), r2
    911   l.sw      12(r3), r3
    912   l.sw      16(r3), r4
    913   l.sw      20(r3), r5
    914   l.sw      24(r3), r6
    915   l.sw      28(r3), r7
    916   l.sw      32(r3), r8
    917   l.sw      36(r3), r9
    918   l.sw      40(r3), r10
    919   l.sw      44(r3), r11
    920   l.sw      48(r3), r12
    921   l.sw      52(r3), r13
    922   l.sw      56(r3), r14
    923   l.sw      60(r3), r15
    924   l.sw      64(r3), r16
    925   l.sw      68(r3), r17
    926   l.sw      72(r3), r18
    927   l.sw      76(r3), r19
    928   l.sw      80(r3), r20
    929   l.sw      84(r3), r21
    930   l.sw      88(r3), r22
    931   l.sw      92(r3), r23
    932   l.sw      96(r3), r24
    933   l.sw     100(r3), r25
    934   l.sw     104(r3), r26
    935   l.sw     108(r3), r27
    936   l.sw     112(r3), r28
    937   l.sw     116(r3), r29
    938   l.sw     120(r3), r30
    939   l.sw     124(r3), r31
    940   # store ra to pc
    941   l.sw     128(r3), r9
    942   # zero epcr
    943   l.sw     132(r3), r0
    944 
    945 #elif defined(__sparc__)
    946 
    947 #
    948 # extern int unw_getcontext(unw_context_t* thread_state)
    949 #
    950 # On entry:
    951 #  thread_state pointer is in o0
    952 #
    953 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    954   ta 3
    955   add %o7, 8, %o7
    956   std %g0, [%o0 +   0]
    957   std %g2, [%o0 +   8]
    958   std %g4, [%o0 +  16]
    959   std %g6, [%o0 +  24]
    960   std %o0, [%o0 +  32]
    961   std %o2, [%o0 +  40]
    962   std %o4, [%o0 +  48]
    963   std %o6, [%o0 +  56]
    964   std %l0, [%o0 +  64]
    965   std %l2, [%o0 +  72]
    966   std %l4, [%o0 +  80]
    967   std %l6, [%o0 +  88]
    968   std %i0, [%o0 +  96]
    969   std %i2, [%o0 + 104]
    970   std %i4, [%o0 + 112]
    971   std %i6, [%o0 + 120]
    972   jmp %o7
    973    clr %o0                   // return UNW_ESUCCESS
    974 #endif
    975 #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
    976 
    977 NO_EXEC_STACK_DIRECTIVE
    978