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