Home | History | Annotate | Download | only in src
      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 defined(__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 defined(__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 defined(__mips__)
     91 
     92 #
     93 # extern int unw_getcontext(unw_context_t* thread_state)
     94 #
     95 # Just trap for the time being.
     96 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
     97   teq $0, $0
     98 
     99 #elif defined(__ppc__)
    100 
    101 ;
    102 ; extern int unw_getcontext(unw_context_t* thread_state)
    103 ;
    104 ; On entry:
    105 ;  thread_state pointer is in r3
    106 ;
    107 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    108   stw    r0,  8(r3)
    109   mflr  r0
    110   stw    r0,  0(r3)  ; store lr as ssr0
    111   stw    r1, 12(r3)
    112   stw    r2, 16(r3)
    113   stw    r3, 20(r3)
    114   stw    r4, 24(r3)
    115   stw    r5, 28(r3)
    116   stw    r6, 32(r3)
    117   stw    r7, 36(r3)
    118   stw    r8, 40(r3)
    119   stw    r9, 44(r3)
    120   stw     r10, 48(r3)
    121   stw     r11, 52(r3)
    122   stw     r12, 56(r3)
    123   stw     r13, 60(r3)
    124   stw     r14, 64(r3)
    125   stw     r15, 68(r3)
    126   stw     r16, 72(r3)
    127   stw     r17, 76(r3)
    128   stw     r18, 80(r3)
    129   stw     r19, 84(r3)
    130   stw     r20, 88(r3)
    131   stw     r21, 92(r3)
    132   stw     r22, 96(r3)
    133   stw     r23,100(r3)
    134   stw     r24,104(r3)
    135   stw     r25,108(r3)
    136   stw     r26,112(r3)
    137   stw     r27,116(r3)
    138   stw     r28,120(r3)
    139   stw     r29,124(r3)
    140   stw     r30,128(r3)
    141   stw     r31,132(r3)
    142 
    143   ; save VRSave register
    144   mfspr  r0,256
    145   stw    r0,156(r3)
    146   ; save CR registers
    147   mfcr  r0
    148   stw    r0,136(r3)
    149   ; save CTR register
    150   mfctr  r0
    151   stw    r0,148(r3)
    152 
    153   ; save float registers
    154   stfd    f0, 160(r3)
    155   stfd    f1, 168(r3)
    156   stfd    f2, 176(r3)
    157   stfd    f3, 184(r3)
    158   stfd    f4, 192(r3)
    159   stfd    f5, 200(r3)
    160   stfd    f6, 208(r3)
    161   stfd    f7, 216(r3)
    162   stfd    f8, 224(r3)
    163   stfd    f9, 232(r3)
    164   stfd    f10,240(r3)
    165   stfd    f11,248(r3)
    166   stfd    f12,256(r3)
    167   stfd    f13,264(r3)
    168   stfd    f14,272(r3)
    169   stfd    f15,280(r3)
    170   stfd    f16,288(r3)
    171   stfd    f17,296(r3)
    172   stfd    f18,304(r3)
    173   stfd    f19,312(r3)
    174   stfd    f20,320(r3)
    175   stfd    f21,328(r3)
    176   stfd    f22,336(r3)
    177   stfd    f23,344(r3)
    178   stfd    f24,352(r3)
    179   stfd    f25,360(r3)
    180   stfd    f26,368(r3)
    181   stfd    f27,376(r3)
    182   stfd    f28,384(r3)
    183   stfd    f29,392(r3)
    184   stfd    f30,400(r3)
    185   stfd    f31,408(r3)
    186 
    187 
    188   ; save vector registers
    189 
    190   subi  r4,r1,16
    191   rlwinm  r4,r4,0,0,27  ; mask low 4-bits
    192   ; r4 is now a 16-byte aligned pointer into the red zone
    193 
    194 #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \
    195   stvx  _vec,0,r4           @\
    196   lwz    r5, 0(r4)          @\
    197   stw    r5, _offset(r3)    @\
    198   lwz    r5, 4(r4)          @\
    199   stw    r5, _offset+4(r3)  @\
    200   lwz    r5, 8(r4)          @\
    201   stw    r5, _offset+8(r3)  @\
    202   lwz    r5, 12(r4)         @\
    203   stw    r5, _offset+12(r3)
    204 
    205   SAVE_VECTOR_UNALIGNED( v0, 424+0x000)
    206   SAVE_VECTOR_UNALIGNED( v1, 424+0x010)
    207   SAVE_VECTOR_UNALIGNED( v2, 424+0x020)
    208   SAVE_VECTOR_UNALIGNED( v3, 424+0x030)
    209   SAVE_VECTOR_UNALIGNED( v4, 424+0x040)
    210   SAVE_VECTOR_UNALIGNED( v5, 424+0x050)
    211   SAVE_VECTOR_UNALIGNED( v6, 424+0x060)
    212   SAVE_VECTOR_UNALIGNED( v7, 424+0x070)
    213   SAVE_VECTOR_UNALIGNED( v8, 424+0x080)
    214   SAVE_VECTOR_UNALIGNED( v9, 424+0x090)
    215   SAVE_VECTOR_UNALIGNED(v10, 424+0x0A0)
    216   SAVE_VECTOR_UNALIGNED(v11, 424+0x0B0)
    217   SAVE_VECTOR_UNALIGNED(v12, 424+0x0C0)
    218   SAVE_VECTOR_UNALIGNED(v13, 424+0x0D0)
    219   SAVE_VECTOR_UNALIGNED(v14, 424+0x0E0)
    220   SAVE_VECTOR_UNALIGNED(v15, 424+0x0F0)
    221   SAVE_VECTOR_UNALIGNED(v16, 424+0x100)
    222   SAVE_VECTOR_UNALIGNED(v17, 424+0x110)
    223   SAVE_VECTOR_UNALIGNED(v18, 424+0x120)
    224   SAVE_VECTOR_UNALIGNED(v19, 424+0x130)
    225   SAVE_VECTOR_UNALIGNED(v20, 424+0x140)
    226   SAVE_VECTOR_UNALIGNED(v21, 424+0x150)
    227   SAVE_VECTOR_UNALIGNED(v22, 424+0x160)
    228   SAVE_VECTOR_UNALIGNED(v23, 424+0x170)
    229   SAVE_VECTOR_UNALIGNED(v24, 424+0x180)
    230   SAVE_VECTOR_UNALIGNED(v25, 424+0x190)
    231   SAVE_VECTOR_UNALIGNED(v26, 424+0x1A0)
    232   SAVE_VECTOR_UNALIGNED(v27, 424+0x1B0)
    233   SAVE_VECTOR_UNALIGNED(v28, 424+0x1C0)
    234   SAVE_VECTOR_UNALIGNED(v29, 424+0x1D0)
    235   SAVE_VECTOR_UNALIGNED(v30, 424+0x1E0)
    236   SAVE_VECTOR_UNALIGNED(v31, 424+0x1F0)
    237 
    238   li  r3, 0    ; return UNW_ESUCCESS
    239   blr
    240 
    241 
    242 #elif defined(__arm64__) || defined(__aarch64__)
    243 
    244 //
    245 // extern int unw_getcontext(unw_context_t* thread_state)
    246 //
    247 // On entry:
    248 //  thread_state pointer is in x0
    249 //
    250   .p2align 2
    251 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    252   stp    x0, x1,  [x0, #0x000]
    253   stp    x2, x3,  [x0, #0x010]
    254   stp    x4, x5,  [x0, #0x020]
    255   stp    x6, x7,  [x0, #0x030]
    256   stp    x8, x9,  [x0, #0x040]
    257   stp    x10,x11, [x0, #0x050]
    258   stp    x12,x13, [x0, #0x060]
    259   stp    x14,x15, [x0, #0x070]
    260   stp    x16,x17, [x0, #0x080]
    261   stp    x18,x19, [x0, #0x090]
    262   stp    x20,x21, [x0, #0x0A0]
    263   stp    x22,x23, [x0, #0x0B0]
    264   stp    x24,x25, [x0, #0x0C0]
    265   stp    x26,x27, [x0, #0x0D0]
    266   stp    x28,x29, [x0, #0x0E0]
    267   str    x30,     [x0, #0x0F0]
    268   mov    x1,sp
    269   str    x1,      [x0, #0x0F8]
    270   str    x30,     [x0, #0x100]    // store return address as pc
    271   // skip cpsr
    272   stp    d0, d1,  [x0, #0x110]
    273   stp    d2, d3,  [x0, #0x120]
    274   stp    d4, d5,  [x0, #0x130]
    275   stp    d6, d7,  [x0, #0x140]
    276   stp    d8, d9,  [x0, #0x150]
    277   stp    d10,d11, [x0, #0x160]
    278   stp    d12,d13, [x0, #0x170]
    279   stp    d14,d15, [x0, #0x180]
    280   stp    d16,d17, [x0, #0x190]
    281   stp    d18,d19, [x0, #0x1A0]
    282   stp    d20,d21, [x0, #0x1B0]
    283   stp    d22,d23, [x0, #0x1C0]
    284   stp    d24,d25, [x0, #0x1D0]
    285   stp    d26,d27, [x0, #0x1E0]
    286   stp    d28,d29, [x0, #0x1F0]
    287   str    d30,     [x0, #0x200]
    288   str    d31,     [x0, #0x208]
    289   mov    x0, #0                   // return UNW_ESUCCESS
    290   ret
    291 
    292 #elif defined(__arm__) && !defined(__APPLE__)
    293 
    294 #if !defined(__ARM_ARCH_ISA_ARM)
    295   .thumb
    296 #endif
    297 
    298 @
    299 @ extern int unw_getcontext(unw_context_t* thread_state)
    300 @
    301 @ On entry:
    302 @  thread_state pointer is in r0
    303 @
    304 @ Per EHABI #4.7 this only saves the core integer registers.
    305 @ EHABI #7.4.5 notes that in general all VRS registers should be restored
    306 @ however this is very hard to do for VFP registers because it is unknown
    307 @ to the library how many registers are implemented by the architecture.
    308 @ Instead, VFP registers are demand saved by logic external to unw_getcontext.
    309 @
    310   .p2align 2
    311 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    312 #if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1
    313   stm r0!, {r0-r7}
    314   mov r1, r8
    315   mov r2, r9
    316   mov r3, r10
    317   stm r0!, {r1-r3}
    318   mov r1, r11
    319   mov r2, sp
    320   mov r3, lr
    321   str r1, [r0, #0]   @ r11
    322   @ r12 does not need storing, it it the intra-procedure-call scratch register
    323   str r2, [r0, #8]   @ sp
    324   str r3, [r0, #12]  @ lr
    325   str r3, [r0, #16]  @ store return address as pc
    326   @ T1 does not have a non-cpsr-clobbering register-zeroing instruction.
    327   @ It is safe to use here though because we are about to return, and cpsr is
    328   @ not expected to be preserved.
    329   movs r0, #0        @ return UNW_ESUCCESS
    330 #else
    331   @ 32bit thumb-2 restrictions for stm:
    332   @ . the sp (r13) cannot be in the list
    333   @ . the pc (r15) cannot be in the list in an STM instruction
    334   stm r0, {r0-r12}
    335   str sp, [r0, #52]
    336   str lr, [r0, #56]
    337   str lr, [r0, #60]  @ store return address as pc
    338   mov r0, #0         @ return UNW_ESUCCESS
    339 #endif
    340   JMP(lr)
    341 
    342 @
    343 @ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)
    344 @
    345 @ On entry:
    346 @  values pointer is in r0
    347 @
    348   .p2align 2
    349   .fpu vfpv3-d16
    350 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPy)
    351   vstmia r0, {d0-d15}
    352   JMP(lr)
    353 
    354 @
    355 @ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)
    356 @
    357 @ On entry:
    358 @  values pointer is in r0
    359 @
    360   .p2align 2
    361   .fpu vfpv3-d16
    362 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPy)
    363   vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia
    364   JMP(lr)
    365 
    366 @
    367 @ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)
    368 @
    369 @ On entry:
    370 @  values pointer is in r0
    371 @
    372   .p2align 2
    373   .fpu vfpv3
    374 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPy)
    375   @ VFP and iwMMX instructions are only available when compiling with the flags
    376   @ that enable them. We do not want to do that in the library (because we do not
    377   @ want the compiler to generate instructions that access those) but this is
    378   @ only accessed if the personality routine needs these registers. Use of
    379   @ these registers implies they are, actually, available on the target, so
    380   @ it's ok to execute.
    381   @ So, generate the instructions using the corresponding coprocessor mnemonic.
    382   vstmia r0, {d16-d31}
    383   JMP(lr)
    384 
    385 #if defined(_LIBUNWIND_ARM_WMMX)
    386 
    387 @
    388 @ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)
    389 @
    390 @ On entry:
    391 @  values pointer is in r0
    392 @
    393   .p2align 2
    394   .arch armv5te
    395 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPy)
    396   stcl p1, cr0, [r0], #8  @ wstrd wR0, [r0], #8
    397   stcl p1, cr1, [r0], #8  @ wstrd wR1, [r0], #8
    398   stcl p1, cr2, [r0], #8  @ wstrd wR2, [r0], #8
    399   stcl p1, cr3, [r0], #8  @ wstrd wR3, [r0], #8
    400   stcl p1, cr4, [r0], #8  @ wstrd wR4, [r0], #8
    401   stcl p1, cr5, [r0], #8  @ wstrd wR5, [r0], #8
    402   stcl p1, cr6, [r0], #8  @ wstrd wR6, [r0], #8
    403   stcl p1, cr7, [r0], #8  @ wstrd wR7, [r0], #8
    404   stcl p1, cr8, [r0], #8  @ wstrd wR8, [r0], #8
    405   stcl p1, cr9, [r0], #8  @ wstrd wR9, [r0], #8
    406   stcl p1, cr10, [r0], #8  @ wstrd wR10, [r0], #8
    407   stcl p1, cr11, [r0], #8  @ wstrd wR11, [r0], #8
    408   stcl p1, cr12, [r0], #8  @ wstrd wR12, [r0], #8
    409   stcl p1, cr13, [r0], #8  @ wstrd wR13, [r0], #8
    410   stcl p1, cr14, [r0], #8  @ wstrd wR14, [r0], #8
    411   stcl p1, cr15, [r0], #8  @ wstrd wR15, [r0], #8
    412   JMP(lr)
    413 
    414 @
    415 @ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)
    416 @
    417 @ On entry:
    418 @  values pointer is in r0
    419 @
    420   .p2align 2
    421   .arch armv5te
    422 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)
    423   stc2 p1, cr8, [r0], #4  @ wstrw wCGR0, [r0], #4
    424   stc2 p1, cr9, [r0], #4  @ wstrw wCGR1, [r0], #4
    425   stc2 p1, cr10, [r0], #4  @ wstrw wCGR2, [r0], #4
    426   stc2 p1, cr11, [r0], #4  @ wstrw wCGR3, [r0], #4
    427   JMP(lr)
    428 
    429 #endif
    430 
    431 #elif defined(__or1k__)
    432 
    433 #
    434 # extern int unw_getcontext(unw_context_t* thread_state)
    435 #
    436 # On entry:
    437 #  thread_state pointer is in r3
    438 #
    439 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
    440   l.sw       0(r3), r0
    441   l.sw       4(r3), r1
    442   l.sw       8(r3), r2
    443   l.sw      12(r3), r3
    444   l.sw      16(r3), r4
    445   l.sw      20(r3), r5
    446   l.sw      24(r3), r6
    447   l.sw      28(r3), r7
    448   l.sw      32(r3), r8
    449   l.sw      36(r3), r9
    450   l.sw      40(r3), r10
    451   l.sw      44(r3), r11
    452   l.sw      48(r3), r12
    453   l.sw      52(r3), r13
    454   l.sw      56(r3), r14
    455   l.sw      60(r3), r15
    456   l.sw      64(r3), r16
    457   l.sw      68(r3), r17
    458   l.sw      72(r3), r18
    459   l.sw      76(r3), r19
    460   l.sw      80(r3), r20
    461   l.sw      84(r3), r21
    462   l.sw      88(r3), r22
    463   l.sw      92(r3), r23
    464   l.sw      96(r3), r24
    465   l.sw     100(r3), r25
    466   l.sw     104(r3), r26
    467   l.sw     108(r3), r27
    468   l.sw     112(r3), r28
    469   l.sw     116(r3), r29
    470   l.sw     120(r3), r30
    471   l.sw     124(r3), r31
    472 #endif
    473 
    474 NO_EXEC_STACK_DIRECTIVE
    475 
    476