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