Home | History | Annotate | Download | only in Unwind
      1 //===------------------------ UnwindRegistersSave.S -----------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "assembly.h"
     11 
     12     .text
     13 
     14 #if __i386__
     15 
     16 #
     17 # extern int unw_getcontext(unw_context_t* thread_state)
     18 #
     19 # On entry:
     20 #   +                       +
     21 #   +-----------------------+
     22 #   + thread_state pointer  +
     23 #   +-----------------------+
     24 #   + return address        +
     25 #   +-----------------------+   <-- SP
     26 #   +                       +
     27 #
     28 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
     29   push  %eax
     30   movl  8(%esp), %eax
     31   movl  %ebx,  4(%eax)
     32   movl  %ecx,  8(%eax)
     33   movl  %edx, 12(%eax)
     34   movl  %edi, 16(%eax)
     35   movl  %esi, 20(%eax)
     36   movl  %ebp, 24(%eax)
     37   movl  %esp, %edx
     38   addl  $8, %edx
     39   movl  %edx, 28(%eax)  # store what sp was at call site as esp
     40   # skip ss
     41   # skip eflags
     42   movl  4(%esp), %edx
     43   movl  %edx, 40(%eax)  # store return address as eip
     44   # skip cs
     45   # skip ds
     46   # skip es
     47   # skip fs
     48   # skip gs
     49   movl  (%esp), %edx
     50   movl  %edx, (%eax)  # store original eax
     51   popl  %eax
     52   xorl  %eax, %eax    # return UNW_ESUCCESS
     53   ret
     54 
     55 #elif __x86_64__
     56 
     57 #
     58 # extern int unw_getcontext(unw_context_t* thread_state)
     59 #
     60 # On entry:
     61 #  thread_state pointer is in rdi
     62 #
     63 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
     64   movq  %rax,   (%rdi)
     65   movq  %rbx,  8(%rdi)
     66   movq  %rcx, 16(%rdi)
     67   movq  %rdx, 24(%rdi)
     68   movq  %rdi, 32(%rdi)
     69   movq  %rsi, 40(%rdi)
     70   movq  %rbp, 48(%rdi)
     71   movq  %rsp, 56(%rdi)
     72   addq  $8,   56(%rdi)
     73   movq  %r8,  64(%rdi)
     74   movq  %r9,  72(%rdi)
     75   movq  %r10, 80(%rdi)
     76   movq  %r11, 88(%rdi)
     77   movq  %r12, 96(%rdi)
     78   movq  %r13,104(%rdi)
     79   movq  %r14,112(%rdi)
     80   movq  %r15,120(%rdi)
     81   movq  (%rsp),%rsi
     82   movq  %rsi,128(%rdi) # store return address as rip
     83   # skip rflags
     84   # skip cs
     85   # skip fs
     86   # skip gs
     87   xorl  %eax, %eax    # return UNW_ESUCCESS
     88   ret
     89 
     90 #elif __ppc__
     91 
     92 ;
     93 ; extern int unw_getcontext(unw_context_t* thread_state)
     94 ;
     95 ; On entry:
     96 ;  thread_state pointer is in r3
     97 ;
     98 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
     99   stw    r0,  8(r3)
    100   mflr  r0
    101   stw    r0,  0(r3)  ; store lr as ssr0
    102   stw    r1, 12(r3)
    103   stw    r2, 16(r3)
    104   stw    r3, 20(r3)
    105   stw    r4, 24(r3)
    106   stw    r5, 28(r3)
    107   stw    r6, 32(r3)
    108   stw    r7, 36(r3)
    109   stw    r8, 40(r3)
    110   stw    r9, 44(r3)
    111   stw     r10, 48(r3)
    112   stw     r11, 52(r3)
    113   stw     r12, 56(r3)
    114   stw     r13, 60(r3)
    115   stw     r14, 64(r3)
    116   stw     r15, 68(r3)
    117   stw     r16, 72(r3)
    118   stw     r17, 76(r3)
    119   stw     r18, 80(r3)
    120   stw     r19, 84(r3)
    121   stw     r20, 88(r3)
    122   stw     r21, 92(r3)
    123   stw     r22, 96(r3)
    124   stw     r23,100(r3)
    125   stw     r24,104(r3)
    126   stw     r25,108(r3)
    127   stw     r26,112(r3)
    128   stw     r27,116(r3)
    129   stw     r28,120(r3)
    130   stw     r29,124(r3)
    131   stw     r30,128(r3)
    132   stw     r31,132(r3)
    133 
    134   ; save VRSave register
    135   mfspr  r0,256
    136   stw    r0,156(r3)
    137   ; save CR registers
    138   mfcr  r0
    139   stw    r0,136(r3)
    140   ; save CTR register
    141   mfctr  r0
    142   stw    r0,148(r3)
    143 
    144   ; save float registers
    145   stfd    f0, 160(r3)
    146   stfd    f1, 168(r3)
    147   stfd    f2, 176(r3)
    148   stfd    f3, 184(r3)
    149   stfd    f4, 192(r3)
    150   stfd    f5, 200(r3)
    151   stfd    f6, 208(r3)
    152   stfd    f7, 216(r3)
    153   stfd    f8, 224(r3)
    154   stfd    f9, 232(r3)
    155   stfd    f10,240(r3)
    156   stfd    f11,248(r3)
    157   stfd    f12,256(r3)
    158   stfd    f13,264(r3)
    159   stfd    f14,272(r3)
    160   stfd    f15,280(r3)
    161   stfd    f16,288(r3)
    162   stfd    f17,296(r3)
    163   stfd    f18,304(r3)
    164   stfd    f19,312(r3)
    165   stfd    f20,320(r3)
    166   stfd    f21,328(r3)
    167   stfd    f22,336(r3)
    168   stfd    f23,344(r3)
    169   stfd    f24,352(r3)
    170   stfd    f25,360(r3)
    171   stfd    f26,368(r3)
    172   stfd    f27,376(r3)
    173   stfd    f28,384(r3)
    174   stfd    f29,392(r3)
    175   stfd    f30,400(r3)
    176   stfd    f31,408(r3)
    177 
    178 
    179   ; save vector registers
    180 
    181   subi  r4,r1,16
    182   rlwinm  r4,r4,0,0,27  ; mask low 4-bits
    183   ; r4 is now a 16-byte aligned pointer into the red zone
    184 
    185 #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
    186   stvx  _vec,0,r4           @\
    187   lwz    r5, 0(r4)          @\
    188   stw    r5, _offset(r3)    @\
    189   lwz    r5, 4(r4)          @\
    190   stw    r5, _offset+4(r3)  @\
    191   lwz    r5, 8(r4)          @\
    192   stw    r5, _offset+8(r3)  @\
    193   lwz    r5, 12(r4)         @\
    194   stw    r5, _offset+12(r3)
    195 
    196   SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
    197   SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
    198   SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
    199   SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
    200   SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
    201   SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
    202   SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
    203   SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
    204   SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
    205   SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
    206   SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
    207   SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
    208   SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
    209   SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
    210   SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
    211   SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
    212   SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
    213   SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
    214   SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
    215   SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
    216   SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
    217   SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
    218   SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
    219   SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
    220   SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
    221   SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
    222   SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
    223   SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
    224   SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
    225   SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
    226   SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
    227   SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
    228 
    229   li  r3, 0    ; return UNW_ESUCCESS
    230   blr
    231 
    232 
    233 #elif __arm64__
    234 
    235 ;
    236 ; extern int unw_getcontext(unw_context_t* thread_state)
    237 ;
    238 ; On entry:
    239 ;  thread_state pointer is in x0
    240 ;
    241   .p2align 2
    242 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    243   stp    x0, x1,  [x0, #0x000]
    244   stp    x2, x3,  [x0, #0x010]
    245   stp    x4, x5,  [x0, #0x020]
    246   stp    x6, x7,  [x0, #0x030]
    247   stp    x8, x9,  [x0, #0x040]
    248   stp    x10,x11, [x0, #0x050]
    249   stp    x12,x13, [x0, #0x060]
    250   stp    x14,x15, [x0, #0x070]
    251   stp    x16,x17, [x0, #0x080]
    252   stp    x18,x19, [x0, #0x090]
    253   stp    x20,x21, [x0, #0x0A0]
    254   stp    x22,x23, [x0, #0x0B0]
    255   stp    x24,x25, [x0, #0x0C0]
    256   stp    x26,x27, [x0, #0x0D0]
    257   stp    x28,fp,  [x0, #0x0E0]
    258   str    lr,      [x0, #0x0F0]
    259   mov    x1,sp
    260   str    x1,      [x0, #0x0F8]
    261   str    lr,      [x0, #0x100]    ; store return address as pc
    262   ; skip cpsr
    263   stp    d0, d1,  [x0, #0x110]
    264   stp    d2, d3,  [x0, #0x120]
    265   stp    d4, d5,  [x0, #0x130]
    266   stp    d6, d7,  [x0, #0x140]
    267   stp    d8, d9,  [x0, #0x150]
    268   stp    d10,d11, [x0, #0x160]
    269   stp    d12,d13, [x0, #0x170]
    270   stp    d14,d15, [x0, #0x180]
    271   stp    d16,d17, [x0, #0x190]
    272   stp    d18,d19, [x0, #0x1A0]
    273   stp    d20,d21, [x0, #0x1B0]
    274   stp    d22,d23, [x0, #0x1C0]
    275   stp    d24,d25, [x0, #0x1D0]
    276   stp    d26,d27, [x0, #0x1E0]
    277   stp    d28,d29, [x0, #0x1F0]
    278   str    d30,     [x0, #0x200]
    279   str    d31,     [x0, #0x208]
    280   ldr    x0, #0      ; return UNW_ESUCCESS
    281   ret
    282 
    283 #elif __arm__ && !__APPLE__
    284 
    285 @
    286 @ extern int unw_getcontext(unw_context_t* thread_state)
    287 @
    288 @ On entry:
    289 @  thread_state pointer is in r0
    290 @
    291 @ Per EHABI #4.7 this only saves the core integer registers.
    292 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
    293 @ however this is very hard to do for VFP registers because it is unknown
    294 @ to the lbirary how many registers are implemented by the architecture.
    295 @ Instead, VFP registers are demand saved by logic external to unw_getcontext.
    296 @
    297   .p2align 2
    298 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    299   @ 32bit thumb-2 restrictions for stm:
    300   @ . the sp (r13) cannot be in the list
    301   @ . the pc (r15) cannot be in the list in an STM instruction
    302   stm r0, {r0-r12}
    303   str sp, [r0, #52]
    304   str lr, [r0, #56]
    305   str lr, [r0, #60]  @ store return address as pc
    306   mov r0, #0         @ return UNW_ESUCCESS
    307 #if _ARM_ARCH > 4
    308   bx lr
    309 #else
    310   mov pc, lr
    311 #endif
    312 
    313 @
    314 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
    315 @
    316 @ On entry:
    317 @  values pointer is in r0
    318 @
    319   .p2align 2
    320 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
    321   stc p11, cr0, [r0], {#0x20}  @ fstmiad r0, {d0-d15}
    322   mov pc, lr
    323 
    324 @
    325 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
    326 @
    327 @ On entry:
    328 @  values pointer is in r0
    329 @
    330   .p2align 2
    331 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
    332   stc p11, cr0, [r0], {#0x21}  @ fstmiax r0, {d0-d15}
    333   mov pc, lr
    334 
    335 @
    336 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
    337 @
    338 @ On entry:
    339 @  values pointer is in r0
    340 @
    341   .p2align 2
    342 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
    343   @ VFP and iwMMX instructions are only available when compiling with the flags
    344   @ that enable them. We don't want to do that in the library (because we don't
    345   @ want the compiler to generate instructions that access those) but this is
    346   @ only accessed if the personality routine needs these registers. Use of
    347   @ these registers implies they are, actually, available on the target, so
    348   @ it's ok to execute.
    349   @ So, generate the instructions using the corresponding coprocessor mnemonic.
    350   stcl p11, cr0, [r0], {#0x20}  @ vldm r0, {d16-d31}
    351   mov pc, lr
    352 
    353 @
    354 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
    355 @
    356 @ On entry:
    357 @  values pointer is in r0
    358 @
    359   .p2align 2
    360 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
    361   stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
    362   stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
    363   stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
    364   stcl p1, cr3, [r0], #8  @ wstrd wR3, [r0], #8
    365   stcl p1, cr4, [r0], #8  @ wstrd wR4, [r0], #8
    366   stcl p1, cr5, [r0], #8  @ wstrd wR5, [r0], #8
    367   stcl p1, cr6, [r0], #8  @ wstrd wR6, [r0], #8
    368   stcl p1, cr7, [r0], #8  @ wstrd wR7, [r0], #8
    369   stcl p1, cr8, [r0], #8  @ wstrd wR8, [r0], #8
    370   stcl p1, cr9, [r0], #8  @ wstrd wR9, [r0], #8
    371   stcl p1, cr10, [r0], #8  @ wstrd wR10, [r0], #8
    372   stcl p1, cr11, [r0], #8  @ wstrd wR11, [r0], #8
    373   stcl p1, cr12, [r0], #8  @ wstrd wR12, [r0], #8
    374   stcl p1, cr13, [r0], #8  @ wstrd wR13, [r0], #8
    375   stcl p1, cr14, [r0], #8  @ wstrd wR14, [r0], #8
    376   stcl p1, cr15, [r0], #8  @ wstrd wR15, [r0], #8
    377   mov pc, lr
    378 
    379 @
    380 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
    381 @
    382 @ On entry:
    383 @  values pointer is in r0
    384 @
    385   .p2align 2
    386 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
    387   stc2 p1, cr8, [r0], #4  @ wstrw wCGR0, [r0], #4
    388   stc2 p1, cr9, [r0], #4  @ wstrw wCGR1, [r0], #4
    389   stc2 p1, cr10, [r0], #4  @ wstrw wCGR2, [r0], #4
    390   stc2 p1, cr11, [r0], #4  @ wstrw wCGR3, [r0], #4
    391   mov pc, lr
    392 
    393 #endif
    394