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 #elif __mips64 394 # 395 # extern int unw_getcontext(unw_context_t* thread_state) 396 # ToDo: 397 # 398 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) 399 j $31 400 401 #elif __mips__ 402 # 403 # extern int unw_getcontext(unw_context_t* thread_state) 404 # ToDo: 405 # 406 DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) 407 j $31 408 409 #endif 410