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