1 //===-------------------- UnwindRegistersRestore.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 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) 17 # 18 # void libunwind::Registers_x86::jumpto() 19 # 20 #if defined(_WIN32) 21 # On windows, the 'this' pointer is passed in ecx instead of on the stack 22 movl %ecx, %eax 23 #else 24 # On entry: 25 # + + 26 # +-----------------------+ 27 # + thread_state pointer + 28 # +-----------------------+ 29 # + return address + 30 # +-----------------------+ <-- SP 31 # + + 32 movl 4(%esp), %eax 33 #endif 34 # set up eax and ret on new stack location 35 movl 28(%eax), %edx # edx holds new stack pointer 36 subl $8,%edx 37 movl %edx, 28(%eax) 38 movl 0(%eax), %ebx 39 movl %ebx, 0(%edx) 40 movl 40(%eax), %ebx 41 movl %ebx, 4(%edx) 42 # we now have ret and eax pushed onto where new stack will be 43 # restore all registers 44 movl 4(%eax), %ebx 45 movl 8(%eax), %ecx 46 movl 12(%eax), %edx 47 movl 16(%eax), %edi 48 movl 20(%eax), %esi 49 movl 24(%eax), %ebp 50 movl 28(%eax), %esp 51 # skip ss 52 # skip eflags 53 pop %eax # eax was already pushed on new stack 54 ret # eip was already pushed on new stack 55 # skip cs 56 # skip ds 57 # skip es 58 # skip fs 59 # skip gs 60 61 #elif defined(__x86_64__) 62 63 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) 64 # 65 # void libunwind::Registers_x86_64::jumpto() 66 # 67 #if defined(_WIN64) 68 # On entry, thread_state pointer is in rcx; move it into rdi 69 # to share restore code below. Since this routine restores and 70 # overwrites all registers, we can use the same registers for 71 # pointers and temporaries as on unix even though win64 normally 72 # mustn't clobber some of them. 73 movq %rcx, %rdi 74 #else 75 # On entry, thread_state pointer is in rdi 76 #endif 77 78 movq 56(%rdi), %rax # rax holds new stack pointer 79 subq $16, %rax 80 movq %rax, 56(%rdi) 81 movq 32(%rdi), %rbx # store new rdi on new stack 82 movq %rbx, 0(%rax) 83 movq 128(%rdi), %rbx # store new rip on new stack 84 movq %rbx, 8(%rax) 85 # restore all registers 86 movq 0(%rdi), %rax 87 movq 8(%rdi), %rbx 88 movq 16(%rdi), %rcx 89 movq 24(%rdi), %rdx 90 # restore rdi later 91 movq 40(%rdi), %rsi 92 movq 48(%rdi), %rbp 93 # restore rsp later 94 movq 64(%rdi), %r8 95 movq 72(%rdi), %r9 96 movq 80(%rdi), %r10 97 movq 88(%rdi), %r11 98 movq 96(%rdi), %r12 99 movq 104(%rdi), %r13 100 movq 112(%rdi), %r14 101 movq 120(%rdi), %r15 102 # skip rflags 103 # skip cs 104 # skip fs 105 # skip gs 106 107 #if defined(_WIN64) 108 movdqu 176(%rdi),%xmm0 109 movdqu 192(%rdi),%xmm1 110 movdqu 208(%rdi),%xmm2 111 movdqu 224(%rdi),%xmm3 112 movdqu 240(%rdi),%xmm4 113 movdqu 256(%rdi),%xmm5 114 movdqu 272(%rdi),%xmm6 115 movdqu 288(%rdi),%xmm7 116 movdqu 304(%rdi),%xmm8 117 movdqu 320(%rdi),%xmm9 118 movdqu 336(%rdi),%xmm10 119 movdqu 352(%rdi),%xmm11 120 movdqu 368(%rdi),%xmm12 121 movdqu 384(%rdi),%xmm13 122 movdqu 400(%rdi),%xmm14 123 movdqu 416(%rdi),%xmm15 124 #endif 125 movq 56(%rdi), %rsp # cut back rsp to new location 126 pop %rdi # rdi was saved here earlier 127 ret # rip was saved here 128 129 130 #elif defined(__powerpc64__) 131 132 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) 133 // 134 // void libunwind::Registers_ppc64::jumpto() 135 // 136 // On entry: 137 // thread_state pointer is in r3 138 // 139 140 // load register (GPR) 141 #define PPC64_LR(n) \ 142 ld %r##n, (8 * (n + 2))(%r3) 143 144 // restore integral registers 145 // skip r0 for now 146 // skip r1 for now 147 PPC64_LR(2) 148 // skip r3 for now 149 // skip r4 for now 150 // skip r5 for now 151 PPC64_LR(6) 152 PPC64_LR(7) 153 PPC64_LR(8) 154 PPC64_LR(9) 155 PPC64_LR(10) 156 PPC64_LR(11) 157 PPC64_LR(12) 158 PPC64_LR(13) 159 PPC64_LR(14) 160 PPC64_LR(15) 161 PPC64_LR(16) 162 PPC64_LR(17) 163 PPC64_LR(18) 164 PPC64_LR(19) 165 PPC64_LR(20) 166 PPC64_LR(21) 167 PPC64_LR(22) 168 PPC64_LR(23) 169 PPC64_LR(24) 170 PPC64_LR(25) 171 PPC64_LR(26) 172 PPC64_LR(27) 173 PPC64_LR(28) 174 PPC64_LR(29) 175 PPC64_LR(30) 176 PPC64_LR(31) 177 178 #ifdef PPC64_HAS_VMX 179 180 // restore VS registers 181 // (note that this also restores floating point registers and V registers, 182 // because part of VS is mapped to these registers) 183 184 addi %r4, %r3, PPC64_OFFS_FP 185 186 // load VS register 187 #define PPC64_LVS(n) \ 188 lxvd2x %vs##n, 0, %r4 ;\ 189 addi %r4, %r4, 16 190 191 // restore the first 32 VS regs (and also all floating point regs) 192 PPC64_LVS(0) 193 PPC64_LVS(1) 194 PPC64_LVS(2) 195 PPC64_LVS(3) 196 PPC64_LVS(4) 197 PPC64_LVS(5) 198 PPC64_LVS(6) 199 PPC64_LVS(7) 200 PPC64_LVS(8) 201 PPC64_LVS(9) 202 PPC64_LVS(10) 203 PPC64_LVS(11) 204 PPC64_LVS(12) 205 PPC64_LVS(13) 206 PPC64_LVS(14) 207 PPC64_LVS(15) 208 PPC64_LVS(16) 209 PPC64_LVS(17) 210 PPC64_LVS(18) 211 PPC64_LVS(19) 212 PPC64_LVS(20) 213 PPC64_LVS(21) 214 PPC64_LVS(22) 215 PPC64_LVS(23) 216 PPC64_LVS(24) 217 PPC64_LVS(25) 218 PPC64_LVS(26) 219 PPC64_LVS(27) 220 PPC64_LVS(28) 221 PPC64_LVS(29) 222 PPC64_LVS(30) 223 PPC64_LVS(31) 224 225 // use VRSAVE to conditionally restore the remaining VS regs, 226 // that are where the V regs are mapped 227 228 ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave 229 cmpwi %r5, 0 230 beq Lnovec 231 232 // conditionally load VS 233 #define PPC64_CLVS_BOTTOM(n) \ 234 beq Ldone##n ;\ 235 addi %r4, %r3, PPC64_OFFS_FP + n * 16 ;\ 236 lxvd2x %vs##n, 0, %r4 ;\ 237 Ldone##n: 238 239 #define PPC64_CLVSl(n) \ 240 andis. %r0, %r5, (1<<(47-n)) ;\ 241 PPC64_CLVS_BOTTOM(n) 242 243 #define PPC64_CLVSh(n) \ 244 andi. %r0, %r5, (1<<(63-n)) ;\ 245 PPC64_CLVS_BOTTOM(n) 246 247 PPC64_CLVSl(32) 248 PPC64_CLVSl(33) 249 PPC64_CLVSl(34) 250 PPC64_CLVSl(35) 251 PPC64_CLVSl(36) 252 PPC64_CLVSl(37) 253 PPC64_CLVSl(38) 254 PPC64_CLVSl(39) 255 PPC64_CLVSl(40) 256 PPC64_CLVSl(41) 257 PPC64_CLVSl(42) 258 PPC64_CLVSl(43) 259 PPC64_CLVSl(44) 260 PPC64_CLVSl(45) 261 PPC64_CLVSl(46) 262 PPC64_CLVSl(47) 263 PPC64_CLVSh(48) 264 PPC64_CLVSh(49) 265 PPC64_CLVSh(50) 266 PPC64_CLVSh(51) 267 PPC64_CLVSh(52) 268 PPC64_CLVSh(53) 269 PPC64_CLVSh(54) 270 PPC64_CLVSh(55) 271 PPC64_CLVSh(56) 272 PPC64_CLVSh(57) 273 PPC64_CLVSh(58) 274 PPC64_CLVSh(59) 275 PPC64_CLVSh(60) 276 PPC64_CLVSh(61) 277 PPC64_CLVSh(62) 278 PPC64_CLVSh(63) 279 280 #else 281 282 // load FP register 283 #define PPC64_LF(n) \ 284 lfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) 285 286 // restore float registers 287 PPC64_LF(0) 288 PPC64_LF(1) 289 PPC64_LF(2) 290 PPC64_LF(3) 291 PPC64_LF(4) 292 PPC64_LF(5) 293 PPC64_LF(6) 294 PPC64_LF(7) 295 PPC64_LF(8) 296 PPC64_LF(9) 297 PPC64_LF(10) 298 PPC64_LF(11) 299 PPC64_LF(12) 300 PPC64_LF(13) 301 PPC64_LF(14) 302 PPC64_LF(15) 303 PPC64_LF(16) 304 PPC64_LF(17) 305 PPC64_LF(18) 306 PPC64_LF(19) 307 PPC64_LF(20) 308 PPC64_LF(21) 309 PPC64_LF(22) 310 PPC64_LF(23) 311 PPC64_LF(24) 312 PPC64_LF(25) 313 PPC64_LF(26) 314 PPC64_LF(27) 315 PPC64_LF(28) 316 PPC64_LF(29) 317 PPC64_LF(30) 318 PPC64_LF(31) 319 320 // restore vector registers if any are in use 321 ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave 322 cmpwi %r5, 0 323 beq Lnovec 324 325 subi %r4, %r1, 16 326 // r4 is now a 16-byte aligned pointer into the red zone 327 // the _vectorScalarRegisters may not be 16-byte aligned 328 // so copy via red zone temp buffer 329 330 #define PPC64_CLV_UNALIGNED_BOTTOM(n) \ 331 beq Ldone##n ;\ 332 ld %r0, (PPC64_OFFS_V + n * 16)(%r3) ;\ 333 std %r0, 0(%r4) ;\ 334 ld %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3) ;\ 335 std %r0, 8(%r4) ;\ 336 lvx %v##n, 0, %r4 ;\ 337 Ldone ## n: 338 339 #define PPC64_CLV_UNALIGNEDl(n) \ 340 andis. %r0, %r5, (1<<(15-n)) ;\ 341 PPC64_CLV_UNALIGNED_BOTTOM(n) 342 343 #define PPC64_CLV_UNALIGNEDh(n) \ 344 andi. %r0, %r5, (1<<(31-n)) ;\ 345 PPC64_CLV_UNALIGNED_BOTTOM(n) 346 347 PPC64_CLV_UNALIGNEDl(0) 348 PPC64_CLV_UNALIGNEDl(1) 349 PPC64_CLV_UNALIGNEDl(2) 350 PPC64_CLV_UNALIGNEDl(3) 351 PPC64_CLV_UNALIGNEDl(4) 352 PPC64_CLV_UNALIGNEDl(5) 353 PPC64_CLV_UNALIGNEDl(6) 354 PPC64_CLV_UNALIGNEDl(7) 355 PPC64_CLV_UNALIGNEDl(8) 356 PPC64_CLV_UNALIGNEDl(9) 357 PPC64_CLV_UNALIGNEDl(10) 358 PPC64_CLV_UNALIGNEDl(11) 359 PPC64_CLV_UNALIGNEDl(12) 360 PPC64_CLV_UNALIGNEDl(13) 361 PPC64_CLV_UNALIGNEDl(14) 362 PPC64_CLV_UNALIGNEDl(15) 363 PPC64_CLV_UNALIGNEDh(16) 364 PPC64_CLV_UNALIGNEDh(17) 365 PPC64_CLV_UNALIGNEDh(18) 366 PPC64_CLV_UNALIGNEDh(19) 367 PPC64_CLV_UNALIGNEDh(20) 368 PPC64_CLV_UNALIGNEDh(21) 369 PPC64_CLV_UNALIGNEDh(22) 370 PPC64_CLV_UNALIGNEDh(23) 371 PPC64_CLV_UNALIGNEDh(24) 372 PPC64_CLV_UNALIGNEDh(25) 373 PPC64_CLV_UNALIGNEDh(26) 374 PPC64_CLV_UNALIGNEDh(27) 375 PPC64_CLV_UNALIGNEDh(28) 376 PPC64_CLV_UNALIGNEDh(29) 377 PPC64_CLV_UNALIGNEDh(30) 378 PPC64_CLV_UNALIGNEDh(31) 379 380 #endif 381 382 Lnovec: 383 ld %r0, PPC64_OFFS_CR(%r3) 384 mtcr %r0 385 ld %r0, PPC64_OFFS_SRR0(%r3) 386 mtctr %r0 387 388 PPC64_LR(0) 389 PPC64_LR(5) 390 PPC64_LR(4) 391 PPC64_LR(1) 392 PPC64_LR(3) 393 bctr 394 395 #elif defined(__ppc__) 396 397 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) 398 ; 399 ; void libunwind::Registers_ppc::jumpto() 400 ; 401 ; On entry: 402 ; thread_state pointer is in r3 403 ; 404 405 ; restore integral registerrs 406 ; skip r0 for now 407 ; skip r1 for now 408 lwz r2, 16(r3) 409 ; skip r3 for now 410 ; skip r4 for now 411 ; skip r5 for now 412 lwz r6, 32(r3) 413 lwz r7, 36(r3) 414 lwz r8, 40(r3) 415 lwz r9, 44(r3) 416 lwz r10, 48(r3) 417 lwz r11, 52(r3) 418 lwz r12, 56(r3) 419 lwz r13, 60(r3) 420 lwz r14, 64(r3) 421 lwz r15, 68(r3) 422 lwz r16, 72(r3) 423 lwz r17, 76(r3) 424 lwz r18, 80(r3) 425 lwz r19, 84(r3) 426 lwz r20, 88(r3) 427 lwz r21, 92(r3) 428 lwz r22, 96(r3) 429 lwz r23,100(r3) 430 lwz r24,104(r3) 431 lwz r25,108(r3) 432 lwz r26,112(r3) 433 lwz r27,116(r3) 434 lwz r28,120(r3) 435 lwz r29,124(r3) 436 lwz r30,128(r3) 437 lwz r31,132(r3) 438 439 ; restore float registers 440 lfd f0, 160(r3) 441 lfd f1, 168(r3) 442 lfd f2, 176(r3) 443 lfd f3, 184(r3) 444 lfd f4, 192(r3) 445 lfd f5, 200(r3) 446 lfd f6, 208(r3) 447 lfd f7, 216(r3) 448 lfd f8, 224(r3) 449 lfd f9, 232(r3) 450 lfd f10,240(r3) 451 lfd f11,248(r3) 452 lfd f12,256(r3) 453 lfd f13,264(r3) 454 lfd f14,272(r3) 455 lfd f15,280(r3) 456 lfd f16,288(r3) 457 lfd f17,296(r3) 458 lfd f18,304(r3) 459 lfd f19,312(r3) 460 lfd f20,320(r3) 461 lfd f21,328(r3) 462 lfd f22,336(r3) 463 lfd f23,344(r3) 464 lfd f24,352(r3) 465 lfd f25,360(r3) 466 lfd f26,368(r3) 467 lfd f27,376(r3) 468 lfd f28,384(r3) 469 lfd f29,392(r3) 470 lfd f30,400(r3) 471 lfd f31,408(r3) 472 473 ; restore vector registers if any are in use 474 lwz r5,156(r3) ; test VRsave 475 cmpwi r5,0 476 beq Lnovec 477 478 subi r4,r1,16 479 rlwinm r4,r4,0,0,27 ; mask low 4-bits 480 ; r4 is now a 16-byte aligned pointer into the red zone 481 ; the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer 482 483 484 #define LOAD_VECTOR_UNALIGNEDl(_index) \ 485 andis. r0,r5,(1<<(15-_index)) @\ 486 beq Ldone ## _index @\ 487 lwz r0, 424+_index*16(r3) @\ 488 stw r0, 0(r4) @\ 489 lwz r0, 424+_index*16+4(r3) @\ 490 stw r0, 4(r4) @\ 491 lwz r0, 424+_index*16+8(r3) @\ 492 stw r0, 8(r4) @\ 493 lwz r0, 424+_index*16+12(r3)@\ 494 stw r0, 12(r4) @\ 495 lvx v ## _index,0,r4 @\ 496 Ldone ## _index: 497 498 #define LOAD_VECTOR_UNALIGNEDh(_index) \ 499 andi. r0,r5,(1<<(31-_index)) @\ 500 beq Ldone ## _index @\ 501 lwz r0, 424+_index*16(r3) @\ 502 stw r0, 0(r4) @\ 503 lwz r0, 424+_index*16+4(r3) @\ 504 stw r0, 4(r4) @\ 505 lwz r0, 424+_index*16+8(r3) @\ 506 stw r0, 8(r4) @\ 507 lwz r0, 424+_index*16+12(r3)@\ 508 stw r0, 12(r4) @\ 509 lvx v ## _index,0,r4 @\ 510 Ldone ## _index: 511 512 513 LOAD_VECTOR_UNALIGNEDl(0) 514 LOAD_VECTOR_UNALIGNEDl(1) 515 LOAD_VECTOR_UNALIGNEDl(2) 516 LOAD_VECTOR_UNALIGNEDl(3) 517 LOAD_VECTOR_UNALIGNEDl(4) 518 LOAD_VECTOR_UNALIGNEDl(5) 519 LOAD_VECTOR_UNALIGNEDl(6) 520 LOAD_VECTOR_UNALIGNEDl(7) 521 LOAD_VECTOR_UNALIGNEDl(8) 522 LOAD_VECTOR_UNALIGNEDl(9) 523 LOAD_VECTOR_UNALIGNEDl(10) 524 LOAD_VECTOR_UNALIGNEDl(11) 525 LOAD_VECTOR_UNALIGNEDl(12) 526 LOAD_VECTOR_UNALIGNEDl(13) 527 LOAD_VECTOR_UNALIGNEDl(14) 528 LOAD_VECTOR_UNALIGNEDl(15) 529 LOAD_VECTOR_UNALIGNEDh(16) 530 LOAD_VECTOR_UNALIGNEDh(17) 531 LOAD_VECTOR_UNALIGNEDh(18) 532 LOAD_VECTOR_UNALIGNEDh(19) 533 LOAD_VECTOR_UNALIGNEDh(20) 534 LOAD_VECTOR_UNALIGNEDh(21) 535 LOAD_VECTOR_UNALIGNEDh(22) 536 LOAD_VECTOR_UNALIGNEDh(23) 537 LOAD_VECTOR_UNALIGNEDh(24) 538 LOAD_VECTOR_UNALIGNEDh(25) 539 LOAD_VECTOR_UNALIGNEDh(26) 540 LOAD_VECTOR_UNALIGNEDh(27) 541 LOAD_VECTOR_UNALIGNEDh(28) 542 LOAD_VECTOR_UNALIGNEDh(29) 543 LOAD_VECTOR_UNALIGNEDh(30) 544 LOAD_VECTOR_UNALIGNEDh(31) 545 546 Lnovec: 547 lwz r0, 136(r3) ; __cr 548 mtocrf 255,r0 549 lwz r0, 148(r3) ; __ctr 550 mtctr r0 551 lwz r0, 0(r3) ; __ssr0 552 mtctr r0 553 lwz r0, 8(r3) ; do r0 now 554 lwz r5,28(r3) ; do r5 now 555 lwz r4,24(r3) ; do r4 now 556 lwz r1,12(r3) ; do sp now 557 lwz r3,20(r3) ; do r3 last 558 bctr 559 560 #elif defined(__arm64__) || defined(__aarch64__) 561 562 // 563 // void libunwind::Registers_arm64::jumpto() 564 // 565 // On entry: 566 // thread_state pointer is in x0 567 // 568 .p2align 2 569 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) 570 // skip restore of x0,x1 for now 571 ldp x2, x3, [x0, #0x010] 572 ldp x4, x5, [x0, #0x020] 573 ldp x6, x7, [x0, #0x030] 574 ldp x8, x9, [x0, #0x040] 575 ldp x10,x11, [x0, #0x050] 576 ldp x12,x13, [x0, #0x060] 577 ldp x14,x15, [x0, #0x070] 578 ldp x16,x17, [x0, #0x080] 579 ldp x18,x19, [x0, #0x090] 580 ldp x20,x21, [x0, #0x0A0] 581 ldp x22,x23, [x0, #0x0B0] 582 ldp x24,x25, [x0, #0x0C0] 583 ldp x26,x27, [x0, #0x0D0] 584 ldp x28,x29, [x0, #0x0E0] 585 ldr x30, [x0, #0x100] // restore pc into lr 586 ldr x1, [x0, #0x0F8] 587 mov sp,x1 // restore sp 588 589 ldp d0, d1, [x0, #0x110] 590 ldp d2, d3, [x0, #0x120] 591 ldp d4, d5, [x0, #0x130] 592 ldp d6, d7, [x0, #0x140] 593 ldp d8, d9, [x0, #0x150] 594 ldp d10,d11, [x0, #0x160] 595 ldp d12,d13, [x0, #0x170] 596 ldp d14,d15, [x0, #0x180] 597 ldp d16,d17, [x0, #0x190] 598 ldp d18,d19, [x0, #0x1A0] 599 ldp d20,d21, [x0, #0x1B0] 600 ldp d22,d23, [x0, #0x1C0] 601 ldp d24,d25, [x0, #0x1D0] 602 ldp d26,d27, [x0, #0x1E0] 603 ldp d28,d29, [x0, #0x1F0] 604 ldr d30, [x0, #0x200] 605 ldr d31, [x0, #0x208] 606 607 ldp x0, x1, [x0, #0x000] // restore x0,x1 608 ret x30 // jump to pc 609 610 #elif defined(__arm__) && !defined(__APPLE__) 611 612 #if !defined(__ARM_ARCH_ISA_ARM) 613 .thumb 614 #endif 615 616 @ 617 @ void libunwind::Registers_arm::restoreCoreAndJumpTo() 618 @ 619 @ On entry: 620 @ thread_state pointer is in r0 621 @ 622 .p2align 2 623 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv) 624 #if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 625 @ r8-r11: ldm into r1-r4, then mov to r8-r11 626 adds r0, #0x20 627 ldm r0!, {r1-r4} 628 subs r0, #0x30 629 mov r8, r1 630 mov r9, r2 631 mov r10, r3 632 mov r11, r4 633 @ r12 does not need loading, it it the intra-procedure-call scratch register 634 ldr r2, [r0, #0x34] 635 ldr r3, [r0, #0x3c] 636 mov sp, r2 637 mov lr, r3 @ restore pc into lr 638 ldm r0, {r0-r7} 639 #else 640 @ Use lr as base so that r0 can be restored. 641 mov lr, r0 642 @ 32bit thumb-2 restrictions for ldm: 643 @ . the sp (r13) cannot be in the list 644 @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction 645 ldm lr, {r0-r12} 646 ldr sp, [lr, #52] 647 ldr lr, [lr, #60] @ restore pc into lr 648 #endif 649 JMP(lr) 650 651 @ 652 @ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values) 653 @ 654 @ On entry: 655 @ values pointer is in r0 656 @ 657 .p2align 2 658 #if defined(__ELF__) 659 .fpu vfpv3-d16 660 #endif 661 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPv) 662 @ VFP and iwMMX instructions are only available when compiling with the flags 663 @ that enable them. We do not want to do that in the library (because we do not 664 @ want the compiler to generate instructions that access those) but this is 665 @ only accessed if the personality routine needs these registers. Use of 666 @ these registers implies they are, actually, available on the target, so 667 @ it's ok to execute. 668 @ So, generate the instruction using the corresponding coprocessor mnemonic. 669 vldmia r0, {d0-d15} 670 JMP(lr) 671 672 @ 673 @ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values) 674 @ 675 @ On entry: 676 @ values pointer is in r0 677 @ 678 .p2align 2 679 #if defined(__ELF__) 680 .fpu vfpv3-d16 681 #endif 682 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPv) 683 vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia 684 JMP(lr) 685 686 @ 687 @ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values) 688 @ 689 @ On entry: 690 @ values pointer is in r0 691 @ 692 .p2align 2 693 #if defined(__ELF__) 694 .fpu vfpv3 695 #endif 696 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPv) 697 vldmia r0, {d16-d31} 698 JMP(lr) 699 700 #if defined(__ARM_WMMX) 701 702 @ 703 @ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values) 704 @ 705 @ On entry: 706 @ values pointer is in r0 707 @ 708 .p2align 2 709 #if defined(__ELF__) 710 .arch armv5te 711 #endif 712 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPv) 713 ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8 714 ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8 715 ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8 716 ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8 717 ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8 718 ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8 719 ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8 720 ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8 721 ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8 722 ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8 723 ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8 724 ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8 725 ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8 726 ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8 727 ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8 728 ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8 729 JMP(lr) 730 731 @ 732 @ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values) 733 @ 734 @ On entry: 735 @ values pointer is in r0 736 @ 737 .p2align 2 738 #if defined(__ELF__) 739 .arch armv5te 740 #endif 741 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj) 742 ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4 743 ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4 744 ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4 745 ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4 746 JMP(lr) 747 748 #endif 749 750 #elif defined(__or1k__) 751 752 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) 753 # 754 # void libunwind::Registers_or1k::jumpto() 755 # 756 # On entry: 757 # thread_state pointer is in r3 758 # 759 760 # restore integral registers 761 l.lwz r0, 0(r3) 762 l.lwz r1, 4(r3) 763 l.lwz r2, 8(r3) 764 # skip r3 for now 765 l.lwz r4, 16(r3) 766 l.lwz r5, 20(r3) 767 l.lwz r6, 24(r3) 768 l.lwz r7, 28(r3) 769 l.lwz r8, 32(r3) 770 # skip r9 771 l.lwz r10, 40(r3) 772 l.lwz r11, 44(r3) 773 l.lwz r12, 48(r3) 774 l.lwz r13, 52(r3) 775 l.lwz r14, 56(r3) 776 l.lwz r15, 60(r3) 777 l.lwz r16, 64(r3) 778 l.lwz r17, 68(r3) 779 l.lwz r18, 72(r3) 780 l.lwz r19, 76(r3) 781 l.lwz r20, 80(r3) 782 l.lwz r21, 84(r3) 783 l.lwz r22, 88(r3) 784 l.lwz r23, 92(r3) 785 l.lwz r24, 96(r3) 786 l.lwz r25,100(r3) 787 l.lwz r26,104(r3) 788 l.lwz r27,108(r3) 789 l.lwz r28,112(r3) 790 l.lwz r29,116(r3) 791 l.lwz r30,120(r3) 792 l.lwz r31,124(r3) 793 794 # at last, restore r3 795 l.lwz r3, 12(r3) 796 797 # load new pc into ra 798 l.lwz r9, 128(r3) 799 # jump to pc 800 l.jr r9 801 l.nop 802 803 #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 804 805 // 806 // void libunwind::Registers_mips_o32::jumpto() 807 // 808 // On entry: 809 // thread state pointer is in a0 ($4) 810 // 811 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) 812 .set push 813 .set noat 814 .set noreorder 815 .set nomacro 816 #ifdef __mips_hard_float 817 #if __mips_fpr != 64 818 ldc1 $f0, (4 * 36 + 8 * 0)($4) 819 ldc1 $f2, (4 * 36 + 8 * 2)($4) 820 ldc1 $f4, (4 * 36 + 8 * 4)($4) 821 ldc1 $f6, (4 * 36 + 8 * 6)($4) 822 ldc1 $f8, (4 * 36 + 8 * 8)($4) 823 ldc1 $f10, (4 * 36 + 8 * 10)($4) 824 ldc1 $f12, (4 * 36 + 8 * 12)($4) 825 ldc1 $f14, (4 * 36 + 8 * 14)($4) 826 ldc1 $f16, (4 * 36 + 8 * 16)($4) 827 ldc1 $f18, (4 * 36 + 8 * 18)($4) 828 ldc1 $f20, (4 * 36 + 8 * 20)($4) 829 ldc1 $f22, (4 * 36 + 8 * 22)($4) 830 ldc1 $f24, (4 * 36 + 8 * 24)($4) 831 ldc1 $f26, (4 * 36 + 8 * 26)($4) 832 ldc1 $f28, (4 * 36 + 8 * 28)($4) 833 ldc1 $f30, (4 * 36 + 8 * 30)($4) 834 #else 835 ldc1 $f0, (4 * 36 + 8 * 0)($4) 836 ldc1 $f1, (4 * 36 + 8 * 1)($4) 837 ldc1 $f2, (4 * 36 + 8 * 2)($4) 838 ldc1 $f3, (4 * 36 + 8 * 3)($4) 839 ldc1 $f4, (4 * 36 + 8 * 4)($4) 840 ldc1 $f5, (4 * 36 + 8 * 5)($4) 841 ldc1 $f6, (4 * 36 + 8 * 6)($4) 842 ldc1 $f7, (4 * 36 + 8 * 7)($4) 843 ldc1 $f8, (4 * 36 + 8 * 8)($4) 844 ldc1 $f9, (4 * 36 + 8 * 9)($4) 845 ldc1 $f10, (4 * 36 + 8 * 10)($4) 846 ldc1 $f11, (4 * 36 + 8 * 11)($4) 847 ldc1 $f12, (4 * 36 + 8 * 12)($4) 848 ldc1 $f13, (4 * 36 + 8 * 13)($4) 849 ldc1 $f14, (4 * 36 + 8 * 14)($4) 850 ldc1 $f15, (4 * 36 + 8 * 15)($4) 851 ldc1 $f16, (4 * 36 + 8 * 16)($4) 852 ldc1 $f17, (4 * 36 + 8 * 17)($4) 853 ldc1 $f18, (4 * 36 + 8 * 18)($4) 854 ldc1 $f19, (4 * 36 + 8 * 19)($4) 855 ldc1 $f20, (4 * 36 + 8 * 20)($4) 856 ldc1 $f21, (4 * 36 + 8 * 21)($4) 857 ldc1 $f22, (4 * 36 + 8 * 22)($4) 858 ldc1 $f23, (4 * 36 + 8 * 23)($4) 859 ldc1 $f24, (4 * 36 + 8 * 24)($4) 860 ldc1 $f25, (4 * 36 + 8 * 25)($4) 861 ldc1 $f26, (4 * 36 + 8 * 26)($4) 862 ldc1 $f27, (4 * 36 + 8 * 27)($4) 863 ldc1 $f28, (4 * 36 + 8 * 28)($4) 864 ldc1 $f29, (4 * 36 + 8 * 29)($4) 865 ldc1 $f30, (4 * 36 + 8 * 30)($4) 866 ldc1 $f31, (4 * 36 + 8 * 31)($4) 867 #endif 868 #endif 869 // restore hi and lo 870 lw $8, (4 * 33)($4) 871 mthi $8 872 lw $8, (4 * 34)($4) 873 mtlo $8 874 // r0 is zero 875 lw $1, (4 * 1)($4) 876 lw $2, (4 * 2)($4) 877 lw $3, (4 * 3)($4) 878 // skip a0 for now 879 lw $5, (4 * 5)($4) 880 lw $6, (4 * 6)($4) 881 lw $7, (4 * 7)($4) 882 lw $8, (4 * 8)($4) 883 lw $9, (4 * 9)($4) 884 lw $10, (4 * 10)($4) 885 lw $11, (4 * 11)($4) 886 lw $12, (4 * 12)($4) 887 lw $13, (4 * 13)($4) 888 lw $14, (4 * 14)($4) 889 lw $15, (4 * 15)($4) 890 lw $16, (4 * 16)($4) 891 lw $17, (4 * 17)($4) 892 lw $18, (4 * 18)($4) 893 lw $19, (4 * 19)($4) 894 lw $20, (4 * 20)($4) 895 lw $21, (4 * 21)($4) 896 lw $22, (4 * 22)($4) 897 lw $23, (4 * 23)($4) 898 lw $24, (4 * 24)($4) 899 lw $25, (4 * 25)($4) 900 lw $26, (4 * 26)($4) 901 lw $27, (4 * 27)($4) 902 lw $28, (4 * 28)($4) 903 lw $29, (4 * 29)($4) 904 lw $30, (4 * 30)($4) 905 // load new pc into ra 906 lw $31, (4 * 32)($4) 907 // jump to ra, load a0 in the delay slot 908 jr $31 909 lw $4, (4 * 4)($4) 910 .set pop 911 912 #elif defined(__mips64) 913 914 // 915 // void libunwind::Registers_mips_newabi::jumpto() 916 // 917 // On entry: 918 // thread state pointer is in a0 ($4) 919 // 920 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) 921 .set push 922 .set noat 923 .set noreorder 924 .set nomacro 925 #ifdef __mips_hard_float 926 ldc1 $f0, (8 * 35)($4) 927 ldc1 $f1, (8 * 36)($4) 928 ldc1 $f2, (8 * 37)($4) 929 ldc1 $f3, (8 * 38)($4) 930 ldc1 $f4, (8 * 39)($4) 931 ldc1 $f5, (8 * 40)($4) 932 ldc1 $f6, (8 * 41)($4) 933 ldc1 $f7, (8 * 42)($4) 934 ldc1 $f8, (8 * 43)($4) 935 ldc1 $f9, (8 * 44)($4) 936 ldc1 $f10, (8 * 45)($4) 937 ldc1 $f11, (8 * 46)($4) 938 ldc1 $f12, (8 * 47)($4) 939 ldc1 $f13, (8 * 48)($4) 940 ldc1 $f14, (8 * 49)($4) 941 ldc1 $f15, (8 * 50)($4) 942 ldc1 $f16, (8 * 51)($4) 943 ldc1 $f17, (8 * 52)($4) 944 ldc1 $f18, (8 * 53)($4) 945 ldc1 $f19, (8 * 54)($4) 946 ldc1 $f20, (8 * 55)($4) 947 ldc1 $f21, (8 * 56)($4) 948 ldc1 $f22, (8 * 57)($4) 949 ldc1 $f23, (8 * 58)($4) 950 ldc1 $f24, (8 * 59)($4) 951 ldc1 $f25, (8 * 60)($4) 952 ldc1 $f26, (8 * 61)($4) 953 ldc1 $f27, (8 * 62)($4) 954 ldc1 $f28, (8 * 63)($4) 955 ldc1 $f29, (8 * 64)($4) 956 ldc1 $f30, (8 * 65)($4) 957 ldc1 $f31, (8 * 66)($4) 958 #endif 959 // restore hi and lo 960 ld $8, (8 * 33)($4) 961 mthi $8 962 ld $8, (8 * 34)($4) 963 mtlo $8 964 // r0 is zero 965 ld $1, (8 * 1)($4) 966 ld $2, (8 * 2)($4) 967 ld $3, (8 * 3)($4) 968 // skip a0 for now 969 ld $5, (8 * 5)($4) 970 ld $6, (8 * 6)($4) 971 ld $7, (8 * 7)($4) 972 ld $8, (8 * 8)($4) 973 ld $9, (8 * 9)($4) 974 ld $10, (8 * 10)($4) 975 ld $11, (8 * 11)($4) 976 ld $12, (8 * 12)($4) 977 ld $13, (8 * 13)($4) 978 ld $14, (8 * 14)($4) 979 ld $15, (8 * 15)($4) 980 ld $16, (8 * 16)($4) 981 ld $17, (8 * 17)($4) 982 ld $18, (8 * 18)($4) 983 ld $19, (8 * 19)($4) 984 ld $20, (8 * 20)($4) 985 ld $21, (8 * 21)($4) 986 ld $22, (8 * 22)($4) 987 ld $23, (8 * 23)($4) 988 ld $24, (8 * 24)($4) 989 ld $25, (8 * 25)($4) 990 ld $26, (8 * 26)($4) 991 ld $27, (8 * 27)($4) 992 ld $28, (8 * 28)($4) 993 ld $29, (8 * 29)($4) 994 ld $30, (8 * 30)($4) 995 // load new pc into ra 996 ld $31, (8 * 32)($4) 997 // jump to ra, load a0 in the delay slot 998 jr $31 999 ld $4, (8 * 4)($4) 1000 .set pop 1001 1002 #elif defined(__sparc__) 1003 1004 // 1005 // void libunwind::Registers_sparc_o32::jumpto() 1006 // 1007 // On entry: 1008 // thread_state pointer is in o0 1009 // 1010 DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) 1011 ta 3 1012 ldd [%o0 + 64], %l0 1013 ldd [%o0 + 72], %l2 1014 ldd [%o0 + 80], %l4 1015 ldd [%o0 + 88], %l6 1016 ldd [%o0 + 96], %i0 1017 ldd [%o0 + 104], %i2 1018 ldd [%o0 + 112], %i4 1019 ldd [%o0 + 120], %i6 1020 ld [%o0 + 60], %o7 1021 jmp %o7 1022 nop 1023 1024 #endif 1025 1026 #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ 1027 1028 NO_EXEC_STACK_DIRECTIVE 1029 1030