1//===----------------------------------------------------------------------===// 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#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 12#define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 13 14#define FROM_0_TO_31 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 15#define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 16 17#if defined(_AIX) 18 .toc 19#else 20 .text 21#endif 22 23#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) 24 25#if defined(__i386__) 26DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) 27# 28# extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); 29# 30# On entry: 31# + + 32# +-----------------------+ 33# + thread_state pointer + 34# +-----------------------+ 35# + return address + 36# +-----------------------+ <-- SP 37# + + 38 39 _LIBUNWIND_CET_ENDBR 40 movl 4(%esp), %eax 41 # set up eax and ret on new stack location 42 movl 28(%eax), %edx # edx holds new stack pointer 43 subl $8,%edx 44 movl %edx, 28(%eax) 45 movl 0(%eax), %ebx 46 movl %ebx, 0(%edx) 47 movl 40(%eax), %ebx 48 movl %ebx, 4(%edx) 49 # we now have ret and eax pushed onto where new stack will be 50 # restore all registers 51 movl 4(%eax), %ebx 52 movl 8(%eax), %ecx 53 movl 12(%eax), %edx 54 movl 16(%eax), %edi 55 movl 20(%eax), %esi 56 movl 24(%eax), %ebp 57 movl 28(%eax), %esp 58 # skip ss 59 # skip eflags 60 pop %eax # eax was already pushed on new stack 61 pop %ecx 62 jmp *%ecx 63 # skip cs 64 # skip ds 65 # skip es 66 # skip fs 67 # skip gs 68 69#elif defined(__x86_64__) 70 71DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) 72# 73# extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *); 74# 75#if defined(_WIN64) 76# On entry, thread_state pointer is in rcx; move it into rdi 77# to share restore code below. Since this routine restores and 78# overwrites all registers, we can use the same registers for 79# pointers and temporaries as on unix even though win64 normally 80# mustn't clobber some of them. 81 movq %rcx, %rdi 82#else 83# On entry, thread_state pointer is in rdi 84#endif 85 86 _LIBUNWIND_CET_ENDBR 87 movq 56(%rdi), %rax # rax holds new stack pointer 88 subq $16, %rax 89 movq %rax, 56(%rdi) 90 movq 32(%rdi), %rbx # store new rdi on new stack 91 movq %rbx, 0(%rax) 92 movq 128(%rdi), %rbx # store new rip on new stack 93 movq %rbx, 8(%rax) 94 # restore all registers 95 movq 0(%rdi), %rax 96 movq 8(%rdi), %rbx 97 movq 16(%rdi), %rcx 98 movq 24(%rdi), %rdx 99 # restore rdi later 100 movq 40(%rdi), %rsi 101 movq 48(%rdi), %rbp 102 # restore rsp later 103 movq 64(%rdi), %r8 104 movq 72(%rdi), %r9 105 movq 80(%rdi), %r10 106 movq 88(%rdi), %r11 107 movq 96(%rdi), %r12 108 movq 104(%rdi), %r13 109 movq 112(%rdi), %r14 110 movq 120(%rdi), %r15 111 # skip rflags 112 # skip cs 113 # skip fs 114 # skip gs 115 116#if defined(_WIN64) 117 movdqu 176(%rdi),%xmm0 118 movdqu 192(%rdi),%xmm1 119 movdqu 208(%rdi),%xmm2 120 movdqu 224(%rdi),%xmm3 121 movdqu 240(%rdi),%xmm4 122 movdqu 256(%rdi),%xmm5 123 movdqu 272(%rdi),%xmm6 124 movdqu 288(%rdi),%xmm7 125 movdqu 304(%rdi),%xmm8 126 movdqu 320(%rdi),%xmm9 127 movdqu 336(%rdi),%xmm10 128 movdqu 352(%rdi),%xmm11 129 movdqu 368(%rdi),%xmm12 130 movdqu 384(%rdi),%xmm13 131 movdqu 400(%rdi),%xmm14 132 movdqu 416(%rdi),%xmm15 133#endif 134 movq 56(%rdi), %rsp # cut back rsp to new location 135 pop %rdi # rdi was saved here earlier 136 pop %rcx 137 jmpq *%rcx 138 139 140#elif defined(__powerpc64__) 141 142DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) 143// 144// void libunwind::Registers_ppc64::jumpto() 145// 146// On entry: 147// thread_state pointer is in r3 148// 149 150// load register (GPR) 151#define PPC64_LR(n) \ 152 ld n, (8 * (n + 2))(3) 153 154 // restore integral registers 155 // skip r0 for now 156 // skip r1 for now 157 PPC64_LR(2) 158 // skip r3 for now 159 // skip r4 for now 160 // skip r5 for now 161 PPC64_LR(6) 162 PPC64_LR(7) 163 PPC64_LR(8) 164 PPC64_LR(9) 165 PPC64_LR(10) 166 PPC64_LR(11) 167 PPC64_LR(12) 168 PPC64_LR(13) 169 PPC64_LR(14) 170 PPC64_LR(15) 171 PPC64_LR(16) 172 PPC64_LR(17) 173 PPC64_LR(18) 174 PPC64_LR(19) 175 PPC64_LR(20) 176 PPC64_LR(21) 177 PPC64_LR(22) 178 PPC64_LR(23) 179 PPC64_LR(24) 180 PPC64_LR(25) 181 PPC64_LR(26) 182 PPC64_LR(27) 183 PPC64_LR(28) 184 PPC64_LR(29) 185 PPC64_LR(30) 186 PPC64_LR(31) 187 188#if defined(__VSX__) 189 190 // restore VS registers 191 // (note that this also restores floating point registers and V registers, 192 // because part of VS is mapped to these registers) 193 194 addi 4, 3, PPC64_OFFS_FP 195 196// load VS register 197#ifdef __LITTLE_ENDIAN__ 198// For little-endian targets, we need a swap since lxvd2x will load the register 199// in the incorrect doubleword order. 200// FIXME: when supporting targets older than Power9 on LE is no longer required, 201// this can be changed to simply `lxv n, (16 * n)(4)`. 202#define PPC64_LVS(n) \ 203 lxvd2x n, 0, 4 ;\ 204 xxswapd n, n ;\ 205 addi 4, 4, 16 206#else 207#define PPC64_LVS(n) \ 208 lxvd2x n, 0, 4 ;\ 209 addi 4, 4, 16 210#endif 211 212 // restore the first 32 VS regs (and also all floating point regs) 213 PPC64_LVS(0) 214 PPC64_LVS(1) 215 PPC64_LVS(2) 216 PPC64_LVS(3) 217 PPC64_LVS(4) 218 PPC64_LVS(5) 219 PPC64_LVS(6) 220 PPC64_LVS(7) 221 PPC64_LVS(8) 222 PPC64_LVS(9) 223 PPC64_LVS(10) 224 PPC64_LVS(11) 225 PPC64_LVS(12) 226 PPC64_LVS(13) 227 PPC64_LVS(14) 228 PPC64_LVS(15) 229 PPC64_LVS(16) 230 PPC64_LVS(17) 231 PPC64_LVS(18) 232 PPC64_LVS(19) 233 PPC64_LVS(20) 234 PPC64_LVS(21) 235 PPC64_LVS(22) 236 PPC64_LVS(23) 237 PPC64_LVS(24) 238 PPC64_LVS(25) 239 PPC64_LVS(26) 240 PPC64_LVS(27) 241 PPC64_LVS(28) 242 PPC64_LVS(29) 243 PPC64_LVS(30) 244 PPC64_LVS(31) 245 246#ifdef __LITTLE_ENDIAN__ 247#define PPC64_CLVS_RESTORE(n) \ 248 addi 4, 3, PPC64_OFFS_FP + n * 16 ;\ 249 lxvd2x n, 0, 4 ;\ 250 xxswapd n, n 251#else 252#define PPC64_CLVS_RESTORE(n) \ 253 addi 4, 3, PPC64_OFFS_FP + n * 16 ;\ 254 lxvd2x n, 0, 4 255#endif 256 257#if !defined(_AIX) 258 // use VRSAVE to conditionally restore the remaining VS regs, that are 259 // where the V regs are mapped. In the AIX ABI, VRSAVE is not used. 260 ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave 261 cmpwi 5, 0 262 beq Lnovec 263 264// conditionally load VS 265#define PPC64_CLVSl(n) \ 266 andis. 0, 5, (1 PPC_LEFT_SHIFT(47-n)) ;\ 267 beq Ldone##n ;\ 268 PPC64_CLVS_RESTORE(n) ;\ 269Ldone##n: 270 271#define PPC64_CLVSh(n) \ 272 andi. 0, 5, (1 PPC_LEFT_SHIFT(63-n)) ;\ 273 beq Ldone##n ;\ 274 PPC64_CLVS_RESTORE(n) ;\ 275Ldone##n: 276 277#else 278 279#define PPC64_CLVSl(n) PPC64_CLVS_RESTORE(n) 280#define PPC64_CLVSh(n) PPC64_CLVS_RESTORE(n) 281 282#endif // !defined(_AIX) 283 284 PPC64_CLVSl(32) 285 PPC64_CLVSl(33) 286 PPC64_CLVSl(34) 287 PPC64_CLVSl(35) 288 PPC64_CLVSl(36) 289 PPC64_CLVSl(37) 290 PPC64_CLVSl(38) 291 PPC64_CLVSl(39) 292 PPC64_CLVSl(40) 293 PPC64_CLVSl(41) 294 PPC64_CLVSl(42) 295 PPC64_CLVSl(43) 296 PPC64_CLVSl(44) 297 PPC64_CLVSl(45) 298 PPC64_CLVSl(46) 299 PPC64_CLVSl(47) 300 PPC64_CLVSh(48) 301 PPC64_CLVSh(49) 302 PPC64_CLVSh(50) 303 PPC64_CLVSh(51) 304 PPC64_CLVSh(52) 305 PPC64_CLVSh(53) 306 PPC64_CLVSh(54) 307 PPC64_CLVSh(55) 308 PPC64_CLVSh(56) 309 PPC64_CLVSh(57) 310 PPC64_CLVSh(58) 311 PPC64_CLVSh(59) 312 PPC64_CLVSh(60) 313 PPC64_CLVSh(61) 314 PPC64_CLVSh(62) 315 PPC64_CLVSh(63) 316 317#else 318 319// load FP register 320#define PPC64_LF(n) \ 321 lfd n, (PPC64_OFFS_FP + n * 16)(3) 322 323 // restore float registers 324 PPC64_LF(0) 325 PPC64_LF(1) 326 PPC64_LF(2) 327 PPC64_LF(3) 328 PPC64_LF(4) 329 PPC64_LF(5) 330 PPC64_LF(6) 331 PPC64_LF(7) 332 PPC64_LF(8) 333 PPC64_LF(9) 334 PPC64_LF(10) 335 PPC64_LF(11) 336 PPC64_LF(12) 337 PPC64_LF(13) 338 PPC64_LF(14) 339 PPC64_LF(15) 340 PPC64_LF(16) 341 PPC64_LF(17) 342 PPC64_LF(18) 343 PPC64_LF(19) 344 PPC64_LF(20) 345 PPC64_LF(21) 346 PPC64_LF(22) 347 PPC64_LF(23) 348 PPC64_LF(24) 349 PPC64_LF(25) 350 PPC64_LF(26) 351 PPC64_LF(27) 352 PPC64_LF(28) 353 PPC64_LF(29) 354 PPC64_LF(30) 355 PPC64_LF(31) 356 357#if defined(__ALTIVEC__) 358 359#define PPC64_CLV_UNALIGNED_RESTORE(n) \ 360 ld 0, (PPC64_OFFS_V + n * 16)(3) ;\ 361 std 0, 0(4) ;\ 362 ld 0, (PPC64_OFFS_V + n * 16 + 8)(3) ;\ 363 std 0, 8(4) ;\ 364 lvx n, 0, 4 365 366#if !defined(_AIX) 367 // restore vector registers if any are in use. In the AIX ABI, VRSAVE is 368 // not used. 369 ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave 370 cmpwi 5, 0 371 beq Lnovec 372 373#define PPC64_CLV_UNALIGNEDl(n) \ 374 andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\ 375 beq Ldone##n ;\ 376 PPC64_CLV_UNALIGNED_RESTORE(n) ;\ 377Ldone ## n: 378 379#define PPC64_CLV_UNALIGNEDh(n) \ 380 andi. 0, 5, (1 PPC_LEFT_SHIFT(31-n)) ;\ 381 beq Ldone##n ;\ 382 PPC64_CLV_UNALIGNED_RESTORE(n) ;\ 383Ldone ## n: 384 385#else 386 387#define PPC64_CLV_UNALIGNEDl(n) PPC64_CLV_UNALIGNED_RESTORE(n) 388#define PPC64_CLV_UNALIGNEDh(n) PPC64_CLV_UNALIGNED_RESTORE(n) 389 390#endif // !defined(_AIX) 391 392 subi 4, 1, 16 393 // r4 is now a 16-byte aligned pointer into the red zone 394 // the _vectorScalarRegisters may not be 16-byte aligned 395 // so copy via red zone temp buffer 396 397 PPC64_CLV_UNALIGNEDl(0) 398 PPC64_CLV_UNALIGNEDl(1) 399 PPC64_CLV_UNALIGNEDl(2) 400 PPC64_CLV_UNALIGNEDl(3) 401 PPC64_CLV_UNALIGNEDl(4) 402 PPC64_CLV_UNALIGNEDl(5) 403 PPC64_CLV_UNALIGNEDl(6) 404 PPC64_CLV_UNALIGNEDl(7) 405 PPC64_CLV_UNALIGNEDl(8) 406 PPC64_CLV_UNALIGNEDl(9) 407 PPC64_CLV_UNALIGNEDl(10) 408 PPC64_CLV_UNALIGNEDl(11) 409 PPC64_CLV_UNALIGNEDl(12) 410 PPC64_CLV_UNALIGNEDl(13) 411 PPC64_CLV_UNALIGNEDl(14) 412 PPC64_CLV_UNALIGNEDl(15) 413 PPC64_CLV_UNALIGNEDh(16) 414 PPC64_CLV_UNALIGNEDh(17) 415 PPC64_CLV_UNALIGNEDh(18) 416 PPC64_CLV_UNALIGNEDh(19) 417 PPC64_CLV_UNALIGNEDh(20) 418 PPC64_CLV_UNALIGNEDh(21) 419 PPC64_CLV_UNALIGNEDh(22) 420 PPC64_CLV_UNALIGNEDh(23) 421 PPC64_CLV_UNALIGNEDh(24) 422 PPC64_CLV_UNALIGNEDh(25) 423 PPC64_CLV_UNALIGNEDh(26) 424 PPC64_CLV_UNALIGNEDh(27) 425 PPC64_CLV_UNALIGNEDh(28) 426 PPC64_CLV_UNALIGNEDh(29) 427 PPC64_CLV_UNALIGNEDh(30) 428 PPC64_CLV_UNALIGNEDh(31) 429 430#endif 431#endif 432 433Lnovec: 434 ld 0, PPC64_OFFS_CR(3) 435 mtcr 0 436 ld 0, PPC64_OFFS_SRR0(3) 437 mtctr 0 438 439#if defined(_AIX) 440 // After setting GPR1 to a higher address, AIX wipes out the original 441 // stack space below that address invalidated by the new GPR1 value. Use 442 // GPR0 to save the value of GPR3 in the context before it is wiped out. 443 // This compromises the content of GPR0 which is a volatile register. 444 ld 0, (8 * (3 + 2))(3) 445#else 446 PPC64_LR(0) 447#endif 448 PPC64_LR(5) 449 PPC64_LR(4) 450 PPC64_LR(1) 451#if defined(_AIX) 452 mr 3, 0 453#else 454 PPC64_LR(3) 455#endif 456 bctr 457 458#elif defined(__powerpc__) 459 460DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) 461// 462// void libunwind::Registers_ppc::jumpto() 463// 464// On entry: 465// thread_state pointer is in r3 466// 467 468 // restore integral registers 469 // skip r0 for now 470 // skip r1 for now 471 lwz 2, 16(3) 472 // skip r3 for now 473 // skip r4 for now 474 // skip r5 for now 475 lwz 6, 32(3) 476 lwz 7, 36(3) 477 lwz 8, 40(3) 478 lwz 9, 44(3) 479 lwz 10, 48(3) 480 lwz 11, 52(3) 481 lwz 12, 56(3) 482 lwz 13, 60(3) 483 lwz 14, 64(3) 484 lwz 15, 68(3) 485 lwz 16, 72(3) 486 lwz 17, 76(3) 487 lwz 18, 80(3) 488 lwz 19, 84(3) 489 lwz 20, 88(3) 490 lwz 21, 92(3) 491 lwz 22, 96(3) 492 lwz 23,100(3) 493 lwz 24,104(3) 494 lwz 25,108(3) 495 lwz 26,112(3) 496 lwz 27,116(3) 497 lwz 28,120(3) 498 lwz 29,124(3) 499 lwz 30,128(3) 500 lwz 31,132(3) 501 502#ifndef __NO_FPRS__ 503 // restore float registers 504 lfd 0, 160(3) 505 lfd 1, 168(3) 506 lfd 2, 176(3) 507 lfd 3, 184(3) 508 lfd 4, 192(3) 509 lfd 5, 200(3) 510 lfd 6, 208(3) 511 lfd 7, 216(3) 512 lfd 8, 224(3) 513 lfd 9, 232(3) 514 lfd 10,240(3) 515 lfd 11,248(3) 516 lfd 12,256(3) 517 lfd 13,264(3) 518 lfd 14,272(3) 519 lfd 15,280(3) 520 lfd 16,288(3) 521 lfd 17,296(3) 522 lfd 18,304(3) 523 lfd 19,312(3) 524 lfd 20,320(3) 525 lfd 21,328(3) 526 lfd 22,336(3) 527 lfd 23,344(3) 528 lfd 24,352(3) 529 lfd 25,360(3) 530 lfd 26,368(3) 531 lfd 27,376(3) 532 lfd 28,384(3) 533 lfd 29,392(3) 534 lfd 30,400(3) 535 lfd 31,408(3) 536#endif 537 538#if defined(__ALTIVEC__) 539 540#define LOAD_VECTOR_RESTORE(_index) \ 541 lwz 0, 424+_index*16(3) SEPARATOR \ 542 stw 0, 0(4) SEPARATOR \ 543 lwz 0, 424+_index*16+4(3) SEPARATOR \ 544 stw 0, 4(4) SEPARATOR \ 545 lwz 0, 424+_index*16+8(3) SEPARATOR \ 546 stw 0, 8(4) SEPARATOR \ 547 lwz 0, 424+_index*16+12(3) SEPARATOR \ 548 stw 0, 12(4) SEPARATOR \ 549 lvx _index, 0, 4 550 551#if !defined(_AIX) 552 // restore vector registers if any are in use. In the AIX ABI, VRSAVE 553 // is not used. 554 lwz 5, 156(3) // test VRsave 555 cmpwi 5, 0 556 beq Lnovec 557 558#define LOAD_VECTOR_UNALIGNEDl(_index) \ 559 andis. 0, 5, (1 PPC_LEFT_SHIFT(15-_index)) SEPARATOR \ 560 beq Ldone ## _index SEPARATOR \ 561 LOAD_VECTOR_RESTORE(_index) SEPARATOR \ 562 Ldone ## _index: 563 564#define LOAD_VECTOR_UNALIGNEDh(_index) \ 565 andi. 0, 5, (1 PPC_LEFT_SHIFT(31-_index)) SEPARATOR \ 566 beq Ldone ## _index SEPARATOR \ 567 LOAD_VECTOR_RESTORE(_index) SEPARATOR \ 568 Ldone ## _index: 569 570#else 571 572#define LOAD_VECTOR_UNALIGNEDl(_index) LOAD_VECTOR_RESTORE(_index) 573#define LOAD_VECTOR_UNALIGNEDh(_index) LOAD_VECTOR_RESTORE(_index) 574 575#endif // !defined(_AIX) 576 577 subi 4, 1, 16 578 rlwinm 4, 4, 0, 0, 27 // mask low 4-bits 579 // r4 is now a 16-byte aligned pointer into the red zone 580 // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer 581 582 LOAD_VECTOR_UNALIGNEDl(0) 583 LOAD_VECTOR_UNALIGNEDl(1) 584 LOAD_VECTOR_UNALIGNEDl(2) 585 LOAD_VECTOR_UNALIGNEDl(3) 586 LOAD_VECTOR_UNALIGNEDl(4) 587 LOAD_VECTOR_UNALIGNEDl(5) 588 LOAD_VECTOR_UNALIGNEDl(6) 589 LOAD_VECTOR_UNALIGNEDl(7) 590 LOAD_VECTOR_UNALIGNEDl(8) 591 LOAD_VECTOR_UNALIGNEDl(9) 592 LOAD_VECTOR_UNALIGNEDl(10) 593 LOAD_VECTOR_UNALIGNEDl(11) 594 LOAD_VECTOR_UNALIGNEDl(12) 595 LOAD_VECTOR_UNALIGNEDl(13) 596 LOAD_VECTOR_UNALIGNEDl(14) 597 LOAD_VECTOR_UNALIGNEDl(15) 598 LOAD_VECTOR_UNALIGNEDh(16) 599 LOAD_VECTOR_UNALIGNEDh(17) 600 LOAD_VECTOR_UNALIGNEDh(18) 601 LOAD_VECTOR_UNALIGNEDh(19) 602 LOAD_VECTOR_UNALIGNEDh(20) 603 LOAD_VECTOR_UNALIGNEDh(21) 604 LOAD_VECTOR_UNALIGNEDh(22) 605 LOAD_VECTOR_UNALIGNEDh(23) 606 LOAD_VECTOR_UNALIGNEDh(24) 607 LOAD_VECTOR_UNALIGNEDh(25) 608 LOAD_VECTOR_UNALIGNEDh(26) 609 LOAD_VECTOR_UNALIGNEDh(27) 610 LOAD_VECTOR_UNALIGNEDh(28) 611 LOAD_VECTOR_UNALIGNEDh(29) 612 LOAD_VECTOR_UNALIGNEDh(30) 613 LOAD_VECTOR_UNALIGNEDh(31) 614#endif 615 616Lnovec: 617 lwz 0, 136(3) // __cr 618 mtcr 0 619 lwz 0, 148(3) // __ctr 620 mtctr 0 621 lwz 0, 0(3) // __ssr0 622 mtctr 0 623 lwz 0, 8(3) // do r0 now 624 lwz 5, 28(3) // do r5 now 625 lwz 4, 24(3) // do r4 now 626 lwz 1, 12(3) // do sp now 627 lwz 3, 20(3) // do r3 last 628 bctr 629 630#elif defined(__aarch64__) 631 632#if defined(__ARM_FEATURE_GCS_DEFAULT) 633.arch_extension gcs 634#endif 635 636// 637// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); 638// 639// On entry: 640// thread_state pointer is in x0 641// 642 .p2align 2 643DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) 644 // skip restore of x0,x1 for now 645 ldp x2, x3, [x0, #0x010] 646 ldp x4, x5, [x0, #0x020] 647 ldp x6, x7, [x0, #0x030] 648 ldp x8, x9, [x0, #0x040] 649 ldp x10,x11, [x0, #0x050] 650 ldp x12,x13, [x0, #0x060] 651 ldp x14,x15, [x0, #0x070] 652 // x16 and x17 were clobbered by the call into the unwinder, so no point in 653 // restoring them. 654 ldp x18,x19, [x0, #0x090] 655 ldp x20,x21, [x0, #0x0A0] 656 ldp x22,x23, [x0, #0x0B0] 657 ldp x24,x25, [x0, #0x0C0] 658 ldp x26,x27, [x0, #0x0D0] 659 ldp x28,x29, [x0, #0x0E0] 660 ldr x30, [x0, #0x100] // restore pc into lr 661 662 ldp d0, d1, [x0, #0x110] 663 ldp d2, d3, [x0, #0x120] 664 ldp d4, d5, [x0, #0x130] 665 ldp d6, d7, [x0, #0x140] 666 ldp d8, d9, [x0, #0x150] 667 ldp d10,d11, [x0, #0x160] 668 ldp d12,d13, [x0, #0x170] 669 ldp d14,d15, [x0, #0x180] 670 ldp d16,d17, [x0, #0x190] 671 ldp d18,d19, [x0, #0x1A0] 672 ldp d20,d21, [x0, #0x1B0] 673 ldp d22,d23, [x0, #0x1C0] 674 ldp d24,d25, [x0, #0x1D0] 675 ldp d26,d27, [x0, #0x1E0] 676 ldp d28,d29, [x0, #0x1F0] 677 ldr d30, [x0, #0x200] 678 ldr d31, [x0, #0x208] 679 680 // Finally, restore sp. This must be done after the last read from the 681 // context struct, because it is allocated on the stack, and an exception 682 // could clobber the de-allocated portion of the stack after sp has been 683 // restored. 684 ldr x16, [x0, #0x0F8] 685 ldp x0, x1, [x0, #0x000] // restore x0,x1 686 mov sp,x16 // restore sp 687#if defined(__ARM_FEATURE_GCS_DEFAULT) 688 // If GCS is enabled we need to push the address we're returning to onto the 689 // GCS stack. We can't just return using br, as there won't be a BTI landing 690 // pad instruction at the destination. 691 mov x16, #1 692 chkfeat x16 693 cbnz x16, Lnogcs 694 gcspushm x30 695Lnogcs: 696#endif 697 ret x30 // jump to pc 698 699#elif defined(__arm__) && !defined(__APPLE__) 700 701#if !defined(__ARM_ARCH_ISA_ARM) 702#if (__ARM_ARCH_ISA_THUMB == 2) 703 .syntax unified 704#endif 705 .thumb 706#endif 707 708@ 709@ void libunwind::Registers_arm::restoreCoreAndJumpTo() 710@ 711@ On entry: 712@ thread_state pointer is in r0 713@ 714 .p2align 2 715DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv) 716#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 717 @ r8-r11: ldm into r1-r4, then mov to r8-r11 718 adds r0, #0x20 719 ldm r0!, {r1-r4} 720 subs r0, #0x30 721 mov r8, r1 722 mov r9, r2 723 mov r10, r3 724 mov r11, r4 725 @ r12 does not need loading, it it the intra-procedure-call scratch register 726 ldr r2, [r0, #0x34] 727 ldr r3, [r0, #0x3c] 728 mov sp, r2 729 mov lr, r3 @ restore pc into lr 730 ldm r0, {r0-r7} 731#else 732 @ Use lr as base so that r0 can be restored. 733 mov lr, r0 734 @ 32bit thumb-2 restrictions for ldm: 735 @ . the sp (r13) cannot be in the list 736 @ . the pc (r15) and lr (r14) cannot both be in the list in an LDM instruction 737 ldm lr, {r0-r12} 738 ldr sp, [lr, #52] 739 ldr lr, [lr, #60] @ restore pc into lr 740#endif 741#if defined(__ARM_FEATURE_BTI_DEFAULT) && !defined(__ARM_ARCH_ISA_ARM) 742 // 'bx' is not BTI setting when used with lr, therefore r12 is used instead 743 mov r12, lr 744 JMP(r12) 745#else 746 JMP(lr) 747#endif 748 749@ 750@ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values) 751@ 752@ On entry: 753@ values pointer is in r0 754@ 755 .p2align 2 756#if defined(__ELF__) 757 .fpu vfpv3-d16 758#endif 759DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMDEPv) 760 @ VFP and iwMMX instructions are only available when compiling with the flags 761 @ that enable them. We do not want to do that in the library (because we do not 762 @ want the compiler to generate instructions that access those) but this is 763 @ only accessed if the personality routine needs these registers. Use of 764 @ these registers implies they are, actually, available on the target, so 765 @ it's ok to execute. 766 @ So, generate the instruction using the corresponding coprocessor mnemonic. 767 vldmia r0, {d0-d15} 768 JMP(lr) 769 770@ 771@ static void libunwind::Registers_arm::restoreVFPWithFLDMX(unw_fpreg_t* values) 772@ 773@ On entry: 774@ values pointer is in r0 775@ 776 .p2align 2 777#if defined(__ELF__) 778 .fpu vfpv3-d16 779#endif 780DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreVFPWithFLDMXEPv) 781 vldmia r0, {d0-d15} @ fldmiax is deprecated in ARMv7+ and now behaves like vldmia 782 JMP(lr) 783 784@ 785@ static void libunwind::Registers_arm::restoreVFPv3(unw_fpreg_t* values) 786@ 787@ On entry: 788@ values pointer is in r0 789@ 790 .p2align 2 791#if defined(__ELF__) 792 .fpu vfpv3 793#endif 794DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreVFPv3EPv) 795 vldmia r0, {d16-d31} 796 JMP(lr) 797 798#if defined(__ARM_WMMX) 799 800@ 801@ static void libunwind::Registers_arm::restoreiWMMX(unw_fpreg_t* values) 802@ 803@ On entry: 804@ values pointer is in r0 805@ 806 .p2align 2 807#if defined(__ELF__) 808 .arch armv5te 809#endif 810DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm12restoreiWMMXEPv) 811 ldcl p1, cr0, [r0], #8 @ wldrd wR0, [r0], #8 812 ldcl p1, cr1, [r0], #8 @ wldrd wR1, [r0], #8 813 ldcl p1, cr2, [r0], #8 @ wldrd wR2, [r0], #8 814 ldcl p1, cr3, [r0], #8 @ wldrd wR3, [r0], #8 815 ldcl p1, cr4, [r0], #8 @ wldrd wR4, [r0], #8 816 ldcl p1, cr5, [r0], #8 @ wldrd wR5, [r0], #8 817 ldcl p1, cr6, [r0], #8 @ wldrd wR6, [r0], #8 818 ldcl p1, cr7, [r0], #8 @ wldrd wR7, [r0], #8 819 ldcl p1, cr8, [r0], #8 @ wldrd wR8, [r0], #8 820 ldcl p1, cr9, [r0], #8 @ wldrd wR9, [r0], #8 821 ldcl p1, cr10, [r0], #8 @ wldrd wR10, [r0], #8 822 ldcl p1, cr11, [r0], #8 @ wldrd wR11, [r0], #8 823 ldcl p1, cr12, [r0], #8 @ wldrd wR12, [r0], #8 824 ldcl p1, cr13, [r0], #8 @ wldrd wR13, [r0], #8 825 ldcl p1, cr14, [r0], #8 @ wldrd wR14, [r0], #8 826 ldcl p1, cr15, [r0], #8 @ wldrd wR15, [r0], #8 827 JMP(lr) 828 829@ 830@ static void libunwind::Registers_arm::restoreiWMMXControl(unw_uint32_t* values) 831@ 832@ On entry: 833@ values pointer is in r0 834@ 835 .p2align 2 836#if defined(__ELF__) 837 .arch armv5te 838#endif 839DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXControlEPj) 840 ldc2 p1, cr8, [r0], #4 @ wldrw wCGR0, [r0], #4 841 ldc2 p1, cr9, [r0], #4 @ wldrw wCGR1, [r0], #4 842 ldc2 p1, cr10, [r0], #4 @ wldrw wCGR2, [r0], #4 843 ldc2 p1, cr11, [r0], #4 @ wldrw wCGR3, [r0], #4 844 JMP(lr) 845 846#endif 847 848#elif defined(__or1k__) 849 850DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) 851# 852# void libunwind::Registers_or1k::jumpto() 853# 854# On entry: 855# thread_state pointer is in r3 856# 857 858 # restore integral registers 859 l.lwz r0, 0(r3) 860 l.lwz r1, 4(r3) 861 l.lwz r2, 8(r3) 862 # skip r3 for now 863 l.lwz r4, 16(r3) 864 l.lwz r5, 20(r3) 865 l.lwz r6, 24(r3) 866 l.lwz r7, 28(r3) 867 l.lwz r8, 32(r3) 868 # skip r9 869 l.lwz r10, 40(r3) 870 l.lwz r11, 44(r3) 871 l.lwz r12, 48(r3) 872 l.lwz r13, 52(r3) 873 l.lwz r14, 56(r3) 874 l.lwz r15, 60(r3) 875 l.lwz r16, 64(r3) 876 l.lwz r17, 68(r3) 877 l.lwz r18, 72(r3) 878 l.lwz r19, 76(r3) 879 l.lwz r20, 80(r3) 880 l.lwz r21, 84(r3) 881 l.lwz r22, 88(r3) 882 l.lwz r23, 92(r3) 883 l.lwz r24, 96(r3) 884 l.lwz r25,100(r3) 885 l.lwz r26,104(r3) 886 l.lwz r27,108(r3) 887 l.lwz r28,112(r3) 888 l.lwz r29,116(r3) 889 l.lwz r30,120(r3) 890 l.lwz r31,124(r3) 891 892 # load new pc into ra 893 l.lwz r9, 128(r3) 894 895 # at last, restore r3 896 l.lwz r3, 12(r3) 897 898 # jump to pc 899 l.jr r9 900 l.nop 901 902#elif defined(__hexagon__) 903# On entry: 904# thread_state pointer is in r2 905DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_hexagon6jumptoEv) 906# 907# void libunwind::Registers_hexagon::jumpto() 908# 909 r8 = memw(r0+#32) 910 r9 = memw(r0+#36) 911 r10 = memw(r0+#40) 912 r11 = memw(r0+#44) 913 914 r12 = memw(r0+#48) 915 r13 = memw(r0+#52) 916 r14 = memw(r0+#56) 917 r15 = memw(r0+#60) 918 919 r16 = memw(r0+#64) 920 r17 = memw(r0+#68) 921 r18 = memw(r0+#72) 922 r19 = memw(r0+#76) 923 924 r20 = memw(r0+#80) 925 r21 = memw(r0+#84) 926 r22 = memw(r0+#88) 927 r23 = memw(r0+#92) 928 929 r24 = memw(r0+#96) 930 r25 = memw(r0+#100) 931 r26 = memw(r0+#104) 932 r27 = memw(r0+#108) 933 934 r28 = memw(r0+#112) 935 r29 = memw(r0+#116) 936 r30 = memw(r0+#120) 937 r31 = memw(r0+#132) 938 939 r1 = memw(r0+#128) 940 c4 = r1 // Predicate register 941 r1 = memw(r0+#4) 942 r0 = memw(r0) 943 jumpr r31 944#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 945 946// 947// void libunwind::Registers_mips_o32::jumpto() 948// 949// On entry: 950// thread state pointer is in a0 ($4) 951// 952DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) 953 .set push 954 .set noat 955 .set noreorder 956 .set nomacro 957#ifdef __mips_hard_float 958#if __mips_fpr != 64 959 ldc1 $f0, (4 * 36 + 8 * 0)($4) 960 ldc1 $f2, (4 * 36 + 8 * 2)($4) 961 ldc1 $f4, (4 * 36 + 8 * 4)($4) 962 ldc1 $f6, (4 * 36 + 8 * 6)($4) 963 ldc1 $f8, (4 * 36 + 8 * 8)($4) 964 ldc1 $f10, (4 * 36 + 8 * 10)($4) 965 ldc1 $f12, (4 * 36 + 8 * 12)($4) 966 ldc1 $f14, (4 * 36 + 8 * 14)($4) 967 ldc1 $f16, (4 * 36 + 8 * 16)($4) 968 ldc1 $f18, (4 * 36 + 8 * 18)($4) 969 ldc1 $f20, (4 * 36 + 8 * 20)($4) 970 ldc1 $f22, (4 * 36 + 8 * 22)($4) 971 ldc1 $f24, (4 * 36 + 8 * 24)($4) 972 ldc1 $f26, (4 * 36 + 8 * 26)($4) 973 ldc1 $f28, (4 * 36 + 8 * 28)($4) 974 ldc1 $f30, (4 * 36 + 8 * 30)($4) 975#else 976 ldc1 $f0, (4 * 36 + 8 * 0)($4) 977 ldc1 $f1, (4 * 36 + 8 * 1)($4) 978 ldc1 $f2, (4 * 36 + 8 * 2)($4) 979 ldc1 $f3, (4 * 36 + 8 * 3)($4) 980 ldc1 $f4, (4 * 36 + 8 * 4)($4) 981 ldc1 $f5, (4 * 36 + 8 * 5)($4) 982 ldc1 $f6, (4 * 36 + 8 * 6)($4) 983 ldc1 $f7, (4 * 36 + 8 * 7)($4) 984 ldc1 $f8, (4 * 36 + 8 * 8)($4) 985 ldc1 $f9, (4 * 36 + 8 * 9)($4) 986 ldc1 $f10, (4 * 36 + 8 * 10)($4) 987 ldc1 $f11, (4 * 36 + 8 * 11)($4) 988 ldc1 $f12, (4 * 36 + 8 * 12)($4) 989 ldc1 $f13, (4 * 36 + 8 * 13)($4) 990 ldc1 $f14, (4 * 36 + 8 * 14)($4) 991 ldc1 $f15, (4 * 36 + 8 * 15)($4) 992 ldc1 $f16, (4 * 36 + 8 * 16)($4) 993 ldc1 $f17, (4 * 36 + 8 * 17)($4) 994 ldc1 $f18, (4 * 36 + 8 * 18)($4) 995 ldc1 $f19, (4 * 36 + 8 * 19)($4) 996 ldc1 $f20, (4 * 36 + 8 * 20)($4) 997 ldc1 $f21, (4 * 36 + 8 * 21)($4) 998 ldc1 $f22, (4 * 36 + 8 * 22)($4) 999 ldc1 $f23, (4 * 36 + 8 * 23)($4) 1000 ldc1 $f24, (4 * 36 + 8 * 24)($4) 1001 ldc1 $f25, (4 * 36 + 8 * 25)($4) 1002 ldc1 $f26, (4 * 36 + 8 * 26)($4) 1003 ldc1 $f27, (4 * 36 + 8 * 27)($4) 1004 ldc1 $f28, (4 * 36 + 8 * 28)($4) 1005 ldc1 $f29, (4 * 36 + 8 * 29)($4) 1006 ldc1 $f30, (4 * 36 + 8 * 30)($4) 1007 ldc1 $f31, (4 * 36 + 8 * 31)($4) 1008#endif 1009#endif 1010#if __mips_isa_rev < 6 1011 // restore hi and lo 1012 lw $8, (4 * 33)($4) 1013 mthi $8 1014 lw $8, (4 * 34)($4) 1015 mtlo $8 1016#endif 1017 // r0 is zero 1018 lw $1, (4 * 1)($4) 1019 lw $2, (4 * 2)($4) 1020 lw $3, (4 * 3)($4) 1021 // skip a0 for now 1022 lw $5, (4 * 5)($4) 1023 lw $6, (4 * 6)($4) 1024 lw $7, (4 * 7)($4) 1025 lw $8, (4 * 8)($4) 1026 lw $9, (4 * 9)($4) 1027 lw $10, (4 * 10)($4) 1028 lw $11, (4 * 11)($4) 1029 lw $12, (4 * 12)($4) 1030 lw $13, (4 * 13)($4) 1031 lw $14, (4 * 14)($4) 1032 lw $15, (4 * 15)($4) 1033 lw $16, (4 * 16)($4) 1034 lw $17, (4 * 17)($4) 1035 lw $18, (4 * 18)($4) 1036 lw $19, (4 * 19)($4) 1037 lw $20, (4 * 20)($4) 1038 lw $21, (4 * 21)($4) 1039 lw $22, (4 * 22)($4) 1040 lw $23, (4 * 23)($4) 1041 lw $24, (4 * 24)($4) 1042 lw $25, (4 * 25)($4) 1043 lw $26, (4 * 26)($4) 1044 lw $27, (4 * 27)($4) 1045 lw $28, (4 * 28)($4) 1046 lw $29, (4 * 29)($4) 1047 lw $30, (4 * 30)($4) 1048 // load new pc into ra 1049 lw $31, (4 * 32)($4) 1050 // jump to ra, load a0 in the delay slot 1051 jr $31 1052 lw $4, (4 * 4)($4) 1053 .set pop 1054 1055#elif defined(__mips64) 1056 1057// 1058// void libunwind::Registers_mips_newabi::jumpto() 1059// 1060// On entry: 1061// thread state pointer is in a0 ($4) 1062// 1063DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) 1064 .set push 1065 .set noat 1066 .set noreorder 1067 .set nomacro 1068#ifdef __mips_hard_float 1069 .irp i,FROM_0_TO_31 1070 ldc1 $f\i, (280+8*\i)($4) 1071 .endr 1072#endif 1073#if __mips_isa_rev < 6 1074 // restore hi and lo 1075 ld $8, (8 * 33)($4) 1076 mthi $8 1077 ld $8, (8 * 34)($4) 1078 mtlo $8 1079#endif 1080 // r0 is zero 1081 ld $1, (8 * 1)($4) 1082 ld $2, (8 * 2)($4) 1083 ld $3, (8 * 3)($4) 1084 // skip a0 for now 1085 .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 1086 ld $\i, (8 * \i)($4) 1087 .endr 1088 // load new pc into ra 1089 ld $31, (8 * 32)($4) 1090 // jump to ra, load a0 in the delay slot 1091 jr $31 1092 ld $4, (8 * 4)($4) 1093 .set pop 1094 1095#elif defined(__sparc__) && defined(__arch64__) 1096 1097DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_sparc646jumptoEv) 1098// 1099// void libunwind::Registers_sparc64::jumpto() 1100// 1101// On entry: 1102// thread_state pointer is in %o0 1103// 1104 .register %g2, #scratch 1105 .register %g3, #scratch 1106 .register %g6, #scratch 1107 .register %g7, #scratch 1108 flushw 1109 ldx [%o0 + 0x08], %g1 1110 ldx [%o0 + 0x10], %g2 1111 ldx [%o0 + 0x18], %g3 1112 ldx [%o0 + 0x20], %g4 1113 ldx [%o0 + 0x28], %g5 1114 ldx [%o0 + 0x30], %g6 1115 ldx [%o0 + 0x38], %g7 1116 ldx [%o0 + 0x48], %o1 1117 ldx [%o0 + 0x50], %o2 1118 ldx [%o0 + 0x58], %o3 1119 ldx [%o0 + 0x60], %o4 1120 ldx [%o0 + 0x68], %o5 1121 ldx [%o0 + 0x70], %o6 1122 ldx [%o0 + 0x78], %o7 1123 ldx [%o0 + 0x80], %l0 1124 ldx [%o0 + 0x88], %l1 1125 ldx [%o0 + 0x90], %l2 1126 ldx [%o0 + 0x98], %l3 1127 ldx [%o0 + 0xa0], %l4 1128 ldx [%o0 + 0xa8], %l5 1129 ldx [%o0 + 0xb0], %l6 1130 ldx [%o0 + 0xb8], %l7 1131 ldx [%o0 + 0xc0], %i0 1132 ldx [%o0 + 0xc8], %i1 1133 ldx [%o0 + 0xd0], %i2 1134 ldx [%o0 + 0xd8], %i3 1135 ldx [%o0 + 0xe0], %i4 1136 ldx [%o0 + 0xe8], %i5 1137 ldx [%o0 + 0xf0], %i6 1138 ldx [%o0 + 0xf8], %i7 1139 jmp %o7 1140 ldx [%o0 + 0x40], %o0 1141 1142#elif defined(__sparc__) 1143 1144// 1145// void libunwind::Registers_sparc_o32::jumpto() 1146// 1147// On entry: 1148// thread_state pointer is in o0 1149// 1150DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) 1151 ta 3 1152 ldd [%o0 + 64], %l0 1153 ldd [%o0 + 72], %l2 1154 ldd [%o0 + 80], %l4 1155 ldd [%o0 + 88], %l6 1156 ldd [%o0 + 96], %i0 1157 ldd [%o0 + 104], %i2 1158 ldd [%o0 + 112], %i4 1159 ldd [%o0 + 120], %i6 1160 ld [%o0 + 60], %o7 1161 jmp %o7 1162 nop 1163 1164#elif defined(__riscv) 1165 1166// 1167// void libunwind::Registers_riscv::jumpto() 1168// 1169// On entry: 1170// thread_state pointer is in a0 1171// 1172 .p2align 2 1173DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) 1174# if defined(__riscv_flen) 1175 .irp i,FROM_0_TO_31 1176 FLOAD f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0) 1177 .endr 1178# endif 1179 1180 // x0 is zero 1181 ILOAD x1, (RISCV_ISIZE * 0)(a0) // restore pc into ra 1182 .irp i,2,3,4,5,6,7,8,9 1183 ILOAD x\i, (RISCV_ISIZE * \i)(a0) 1184 .endr 1185 // skip a0 for now 1186 .irp i,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 1187 ILOAD x\i, (RISCV_ISIZE * \i)(a0) 1188 .endr 1189 ILOAD x10, (RISCV_ISIZE * 10)(a0) // restore a0 1190 1191 ret // jump to ra 1192 1193#elif defined(__s390x__) 1194 1195DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv) 1196// 1197// void libunwind::Registers_s390x::jumpto() 1198// 1199// On entry: 1200// thread_state pointer is in r2 1201// 1202 1203 // Skip PSWM, but load PSWA into r1 1204 lg %r1, 8(%r2) 1205 1206 // Restore FPRs 1207 .irp i,FROM_0_TO_15 1208 ld %f\i, (144+8*\i)(%r2) 1209 .endr 1210 1211 // Restore GPRs - skipping %r0 and %r1 1212 lmg %r2, %r15, 32(%r2) 1213 1214 // Return to PSWA (was loaded into %r1 above) 1215 br %r1 1216 1217#elif defined(__loongarch__) && __loongarch_grlen == 64 1218 1219// 1220// void libunwind::Registers_loongarch::jumpto() 1221// 1222// On entry: 1223// thread_state pointer is in $a0($r4) 1224// 1225 .p2align 2 1226DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv) 1227# if __loongarch_frlen == 64 1228 .irp i,FROM_0_TO_31 1229 fld.d $f\i, $a0, (8 * 33 + 8 * \i) 1230 .endr 1231# endif 1232 1233 // $r0 is zero 1234 .irp i,1,2,3 1235 ld.d $r\i, $a0, (8 * \i) 1236 .endr 1237 // skip $a0 for now 1238 .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 1239 ld.d $r\i, $a0, (8 * \i) 1240 .endr 1241 1242 ld.d $ra, $a0, (8 * 32) // load new pc into $ra 1243 ld.d $a0, $a0, (8 * 4) // restore $a0 last 1244 1245 jr $ra 1246 1247#endif 1248 1249#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ 1250 1251NO_EXEC_STACK_DIRECTIVE 1252 1253