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__) 26 27# 28# extern int __unw_getcontext(unw_context_t* thread_state) 29# 30# On entry: 31# + + 32# +-----------------------+ 33# + thread_state pointer + 34# +-----------------------+ 35# + return address + 36# +-----------------------+ <-- SP 37# + + 38# 39DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 40 41 _LIBUNWIND_CET_ENDBR 42 push %eax 43 movl 8(%esp), %eax 44 movl %ebx, 4(%eax) 45 movl %ecx, 8(%eax) 46 movl %edx, 12(%eax) 47 movl %edi, 16(%eax) 48 movl %esi, 20(%eax) 49 movl %ebp, 24(%eax) 50 movl %esp, %edx 51 addl $8, %edx 52 movl %edx, 28(%eax) # store what sp was at call site as esp 53 # skip ss 54 # skip eflags 55 movl 4(%esp), %edx 56 movl %edx, 40(%eax) # store return address as eip 57 # skip cs 58 # skip ds 59 # skip es 60 # skip fs 61 # skip gs 62 movl (%esp), %edx 63 movl %edx, (%eax) # store original eax 64 popl %eax 65 xorl %eax, %eax # return UNW_ESUCCESS 66 ret 67 68#elif defined(__x86_64__) 69 70# 71# extern int __unw_getcontext(unw_context_t* thread_state) 72# 73# On entry: 74# thread_state pointer is in rdi 75# 76DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 77#if defined(_WIN64) 78#define PTR %rcx 79#define TMP %rdx 80#else 81#define PTR %rdi 82#define TMP %rsi 83#endif 84 85 _LIBUNWIND_CET_ENDBR 86 movq %rax, (PTR) 87 movq %rbx, 8(PTR) 88 movq %rcx, 16(PTR) 89 movq %rdx, 24(PTR) 90 movq %rdi, 32(PTR) 91 movq %rsi, 40(PTR) 92 movq %rbp, 48(PTR) 93 movq %rsp, 56(PTR) 94 addq $8, 56(PTR) 95 movq %r8, 64(PTR) 96 movq %r9, 72(PTR) 97 movq %r10, 80(PTR) 98 movq %r11, 88(PTR) 99 movq %r12, 96(PTR) 100 movq %r13,104(PTR) 101 movq %r14,112(PTR) 102 movq %r15,120(PTR) 103 movq (%rsp),TMP 104 movq TMP,128(PTR) # store return address as rip 105 # skip rflags 106 # skip cs 107 # skip fs 108 # skip gs 109 110#if defined(_WIN64) 111 movdqu %xmm0,176(PTR) 112 movdqu %xmm1,192(PTR) 113 movdqu %xmm2,208(PTR) 114 movdqu %xmm3,224(PTR) 115 movdqu %xmm4,240(PTR) 116 movdqu %xmm5,256(PTR) 117 movdqu %xmm6,272(PTR) 118 movdqu %xmm7,288(PTR) 119 movdqu %xmm8,304(PTR) 120 movdqu %xmm9,320(PTR) 121 movdqu %xmm10,336(PTR) 122 movdqu %xmm11,352(PTR) 123 movdqu %xmm12,368(PTR) 124 movdqu %xmm13,384(PTR) 125 movdqu %xmm14,400(PTR) 126 movdqu %xmm15,416(PTR) 127#endif 128 xorl %eax, %eax # return UNW_ESUCCESS 129 ret 130 131#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 132 133# 134# extern int __unw_getcontext(unw_context_t* thread_state) 135# 136# On entry: 137# thread_state pointer is in a0 ($4) 138# 139DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 140 .set push 141 .set noat 142 .set noreorder 143 .set nomacro 144 sw $1, (4 * 1)($4) 145 sw $2, (4 * 2)($4) 146 sw $3, (4 * 3)($4) 147 sw $4, (4 * 4)($4) 148 sw $5, (4 * 5)($4) 149 sw $6, (4 * 6)($4) 150 sw $7, (4 * 7)($4) 151 sw $8, (4 * 8)($4) 152 sw $9, (4 * 9)($4) 153 sw $10, (4 * 10)($4) 154 sw $11, (4 * 11)($4) 155 sw $12, (4 * 12)($4) 156 sw $13, (4 * 13)($4) 157 sw $14, (4 * 14)($4) 158 sw $15, (4 * 15)($4) 159 sw $16, (4 * 16)($4) 160 sw $17, (4 * 17)($4) 161 sw $18, (4 * 18)($4) 162 sw $19, (4 * 19)($4) 163 sw $20, (4 * 20)($4) 164 sw $21, (4 * 21)($4) 165 sw $22, (4 * 22)($4) 166 sw $23, (4 * 23)($4) 167 sw $24, (4 * 24)($4) 168 sw $25, (4 * 25)($4) 169 sw $26, (4 * 26)($4) 170 sw $27, (4 * 27)($4) 171 sw $28, (4 * 28)($4) 172 sw $29, (4 * 29)($4) 173 sw $30, (4 * 30)($4) 174 sw $31, (4 * 31)($4) 175 # Store return address to pc 176 sw $31, (4 * 32)($4) 177#if __mips_isa_rev < 6 178 # hi and lo 179 mfhi $8 180 sw $8, (4 * 33)($4) 181 mflo $8 182 sw $8, (4 * 34)($4) 183#endif 184#ifdef __mips_hard_float 185#if __mips_fpr != 64 186 sdc1 $f0, (4 * 36 + 8 * 0)($4) 187 sdc1 $f2, (4 * 36 + 8 * 2)($4) 188 sdc1 $f4, (4 * 36 + 8 * 4)($4) 189 sdc1 $f6, (4 * 36 + 8 * 6)($4) 190 sdc1 $f8, (4 * 36 + 8 * 8)($4) 191 sdc1 $f10, (4 * 36 + 8 * 10)($4) 192 sdc1 $f12, (4 * 36 + 8 * 12)($4) 193 sdc1 $f14, (4 * 36 + 8 * 14)($4) 194 sdc1 $f16, (4 * 36 + 8 * 16)($4) 195 sdc1 $f18, (4 * 36 + 8 * 18)($4) 196 sdc1 $f20, (4 * 36 + 8 * 20)($4) 197 sdc1 $f22, (4 * 36 + 8 * 22)($4) 198 sdc1 $f24, (4 * 36 + 8 * 24)($4) 199 sdc1 $f26, (4 * 36 + 8 * 26)($4) 200 sdc1 $f28, (4 * 36 + 8 * 28)($4) 201 sdc1 $f30, (4 * 36 + 8 * 30)($4) 202#else 203 sdc1 $f0, (4 * 36 + 8 * 0)($4) 204 sdc1 $f1, (4 * 36 + 8 * 1)($4) 205 sdc1 $f2, (4 * 36 + 8 * 2)($4) 206 sdc1 $f3, (4 * 36 + 8 * 3)($4) 207 sdc1 $f4, (4 * 36 + 8 * 4)($4) 208 sdc1 $f5, (4 * 36 + 8 * 5)($4) 209 sdc1 $f6, (4 * 36 + 8 * 6)($4) 210 sdc1 $f7, (4 * 36 + 8 * 7)($4) 211 sdc1 $f8, (4 * 36 + 8 * 8)($4) 212 sdc1 $f9, (4 * 36 + 8 * 9)($4) 213 sdc1 $f10, (4 * 36 + 8 * 10)($4) 214 sdc1 $f11, (4 * 36 + 8 * 11)($4) 215 sdc1 $f12, (4 * 36 + 8 * 12)($4) 216 sdc1 $f13, (4 * 36 + 8 * 13)($4) 217 sdc1 $f14, (4 * 36 + 8 * 14)($4) 218 sdc1 $f15, (4 * 36 + 8 * 15)($4) 219 sdc1 $f16, (4 * 36 + 8 * 16)($4) 220 sdc1 $f17, (4 * 36 + 8 * 17)($4) 221 sdc1 $f18, (4 * 36 + 8 * 18)($4) 222 sdc1 $f19, (4 * 36 + 8 * 19)($4) 223 sdc1 $f20, (4 * 36 + 8 * 20)($4) 224 sdc1 $f21, (4 * 36 + 8 * 21)($4) 225 sdc1 $f22, (4 * 36 + 8 * 22)($4) 226 sdc1 $f23, (4 * 36 + 8 * 23)($4) 227 sdc1 $f24, (4 * 36 + 8 * 24)($4) 228 sdc1 $f25, (4 * 36 + 8 * 25)($4) 229 sdc1 $f26, (4 * 36 + 8 * 26)($4) 230 sdc1 $f27, (4 * 36 + 8 * 27)($4) 231 sdc1 $f28, (4 * 36 + 8 * 28)($4) 232 sdc1 $f29, (4 * 36 + 8 * 29)($4) 233 sdc1 $f30, (4 * 36 + 8 * 30)($4) 234 sdc1 $f31, (4 * 36 + 8 * 31)($4) 235#endif 236#endif 237 jr $31 238 # return UNW_ESUCCESS 239 or $2, $0, $0 240 .set pop 241 242#elif defined(__mips64) 243 244# 245# extern int __unw_getcontext(unw_context_t* thread_state) 246# 247# On entry: 248# thread_state pointer is in a0 ($4) 249# 250DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 251 .set push 252 .set noat 253 .set noreorder 254 .set nomacro 255 .irp i,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 256 sd $\i, (8 * \i)($4) 257 .endr 258 # Store return address to pc 259 sd $31, (8 * 32)($4) 260#if __mips_isa_rev < 6 261 # hi and lo 262 mfhi $8 263 sd $8, (8 * 33)($4) 264 mflo $8 265 sd $8, (8 * 34)($4) 266#endif 267#ifdef __mips_hard_float 268 .irp i,FROM_0_TO_31 269 sdc1 $f\i, (280+8*\i)($4) 270 .endr 271#endif 272 jr $31 273 # return UNW_ESUCCESS 274 or $2, $0, $0 275 .set pop 276 277# elif defined(__mips__) 278 279# 280# extern int __unw_getcontext(unw_context_t* thread_state) 281# 282# Just trap for the time being. 283DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 284 teq $0, $0 285 286#elif defined(__powerpc64__) 287 288// 289// extern int __unw_getcontext(unw_context_t* thread_state) 290// 291// On entry: 292// thread_state pointer is in r3 293// 294#if defined(_AIX) 295DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext) 296#else 297DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 298#endif 299// store register (GPR) 300#define PPC64_STR(n) \ 301 std n, (8 * (n + 2))(3) 302 303 // save GPRs 304 PPC64_STR(0) 305 mflr 0 306 std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0 307 PPC64_STR(1) 308 PPC64_STR(4) // Save r4 first since it will be used for fixing r2. 309#if defined(_AIX) 310 // The TOC register (r2) was changed by the glue code if unw_getcontext 311 // is called from a different module. Save the original TOC register 312 // in the context if this is the case. 313 mflr 4 314 lwz 4, 0(4) // Get the first instruction at the return address. 315 xoris 0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"? 316 cmplwi 0, 0x28 317 bne 0, LnoR2Fix // No need to fix up r2 if it is not. 318 ld 2, 40(1) // Use the saved TOC register in the stack. 319LnoR2Fix: 320#endif 321 PPC64_STR(2) 322 PPC64_STR(3) 323 PPC64_STR(5) 324 PPC64_STR(6) 325 PPC64_STR(7) 326 PPC64_STR(8) 327 PPC64_STR(9) 328 PPC64_STR(10) 329 PPC64_STR(11) 330 PPC64_STR(12) 331 PPC64_STR(13) 332 PPC64_STR(14) 333 PPC64_STR(15) 334 PPC64_STR(16) 335 PPC64_STR(17) 336 PPC64_STR(18) 337 PPC64_STR(19) 338 PPC64_STR(20) 339 PPC64_STR(21) 340 PPC64_STR(22) 341 PPC64_STR(23) 342 PPC64_STR(24) 343 PPC64_STR(25) 344 PPC64_STR(26) 345 PPC64_STR(27) 346 PPC64_STR(28) 347 PPC64_STR(29) 348 PPC64_STR(30) 349 PPC64_STR(31) 350 351 mfcr 0 352 std 0, PPC64_OFFS_CR(3) 353 mfxer 0 354 std 0, PPC64_OFFS_XER(3) 355#if defined(_AIX) 356 // LR value saved from the register is not used, initialize it to 0. 357 li 0, 0 358#else 359 mflr 0 360#endif 361 std 0, PPC64_OFFS_LR(3) 362 mfctr 0 363 std 0, PPC64_OFFS_CTR(3) 364 mfvrsave 0 365 std 0, PPC64_OFFS_VRSAVE(3) 366 367#if defined(__VSX__) 368 // save VS registers 369 // (note that this also saves floating point registers and V registers, 370 // because part of VS is mapped to these registers) 371 372 addi 4, 3, PPC64_OFFS_FP 373 374// store VS register 375#ifdef __LITTLE_ENDIAN__ 376// For little-endian targets, we need a swap since stxvd2x will store the 377// register in the incorrect doubleword order. 378// FIXME: when supporting targets older than Power9 on LE is no longer required 379// this can be changed to simply `stxv n, 16 * n(4)`. 380#define PPC64_STVS(n) \ 381 xxswapd n, n ;\ 382 stxvd2x n, 0, 4 ;\ 383 addi 4, 4, 16 384#else 385#define PPC64_STVS(n) \ 386 stxvd2x n, 0, 4 ;\ 387 addi 4, 4, 16 388#endif 389 390 PPC64_STVS(0) 391 PPC64_STVS(1) 392 PPC64_STVS(2) 393 PPC64_STVS(3) 394 PPC64_STVS(4) 395 PPC64_STVS(5) 396 PPC64_STVS(6) 397 PPC64_STVS(7) 398 PPC64_STVS(8) 399 PPC64_STVS(9) 400 PPC64_STVS(10) 401 PPC64_STVS(11) 402 PPC64_STVS(12) 403 PPC64_STVS(13) 404 PPC64_STVS(14) 405 PPC64_STVS(15) 406 PPC64_STVS(16) 407 PPC64_STVS(17) 408 PPC64_STVS(18) 409 PPC64_STVS(19) 410 PPC64_STVS(20) 411 PPC64_STVS(21) 412 PPC64_STVS(22) 413 PPC64_STVS(23) 414 PPC64_STVS(24) 415 PPC64_STVS(25) 416 PPC64_STVS(26) 417 PPC64_STVS(27) 418 PPC64_STVS(28) 419 PPC64_STVS(29) 420 PPC64_STVS(30) 421 PPC64_STVS(31) 422 PPC64_STVS(32) 423 PPC64_STVS(33) 424 PPC64_STVS(34) 425 PPC64_STVS(35) 426 PPC64_STVS(36) 427 PPC64_STVS(37) 428 PPC64_STVS(38) 429 PPC64_STVS(39) 430 PPC64_STVS(40) 431 PPC64_STVS(41) 432 PPC64_STVS(42) 433 PPC64_STVS(43) 434 PPC64_STVS(44) 435 PPC64_STVS(45) 436 PPC64_STVS(46) 437 PPC64_STVS(47) 438 PPC64_STVS(48) 439 PPC64_STVS(49) 440 PPC64_STVS(50) 441 PPC64_STVS(51) 442 PPC64_STVS(52) 443 PPC64_STVS(53) 444 PPC64_STVS(54) 445 PPC64_STVS(55) 446 PPC64_STVS(56) 447 PPC64_STVS(57) 448 PPC64_STVS(58) 449 PPC64_STVS(59) 450 PPC64_STVS(60) 451 PPC64_STVS(61) 452 PPC64_STVS(62) 453 PPC64_STVS(63) 454 455#else 456 457// store FP register 458#define PPC64_STF(n) \ 459 stfd n, (PPC64_OFFS_FP + n * 16)(3) 460 461 // save float registers 462 PPC64_STF(0) 463 PPC64_STF(1) 464 PPC64_STF(2) 465 PPC64_STF(3) 466 PPC64_STF(4) 467 PPC64_STF(5) 468 PPC64_STF(6) 469 PPC64_STF(7) 470 PPC64_STF(8) 471 PPC64_STF(9) 472 PPC64_STF(10) 473 PPC64_STF(11) 474 PPC64_STF(12) 475 PPC64_STF(13) 476 PPC64_STF(14) 477 PPC64_STF(15) 478 PPC64_STF(16) 479 PPC64_STF(17) 480 PPC64_STF(18) 481 PPC64_STF(19) 482 PPC64_STF(20) 483 PPC64_STF(21) 484 PPC64_STF(22) 485 PPC64_STF(23) 486 PPC64_STF(24) 487 PPC64_STF(25) 488 PPC64_STF(26) 489 PPC64_STF(27) 490 PPC64_STF(28) 491 PPC64_STF(29) 492 PPC64_STF(30) 493 PPC64_STF(31) 494 495#if defined(__ALTIVEC__) 496 // save vector registers 497 498 // Use 16-bytes below the stack pointer as an 499 // aligned buffer to save each vector register. 500 // Note that the stack pointer is always 16-byte aligned. 501 subi 4, 1, 16 502 503#define PPC64_STV_UNALIGNED(n) \ 504 stvx n, 0, 4 ;\ 505 ld 5, 0(4) ;\ 506 std 5, (PPC64_OFFS_V + n * 16)(3) ;\ 507 ld 5, 8(4) ;\ 508 std 5, (PPC64_OFFS_V + n * 16 + 8)(3) 509 510 PPC64_STV_UNALIGNED(0) 511 PPC64_STV_UNALIGNED(1) 512 PPC64_STV_UNALIGNED(2) 513 PPC64_STV_UNALIGNED(3) 514 PPC64_STV_UNALIGNED(4) 515 PPC64_STV_UNALIGNED(5) 516 PPC64_STV_UNALIGNED(6) 517 PPC64_STV_UNALIGNED(7) 518 PPC64_STV_UNALIGNED(8) 519 PPC64_STV_UNALIGNED(9) 520 PPC64_STV_UNALIGNED(10) 521 PPC64_STV_UNALIGNED(11) 522 PPC64_STV_UNALIGNED(12) 523 PPC64_STV_UNALIGNED(13) 524 PPC64_STV_UNALIGNED(14) 525 PPC64_STV_UNALIGNED(15) 526 PPC64_STV_UNALIGNED(16) 527 PPC64_STV_UNALIGNED(17) 528 PPC64_STV_UNALIGNED(18) 529 PPC64_STV_UNALIGNED(19) 530 PPC64_STV_UNALIGNED(20) 531 PPC64_STV_UNALIGNED(21) 532 PPC64_STV_UNALIGNED(22) 533 PPC64_STV_UNALIGNED(23) 534 PPC64_STV_UNALIGNED(24) 535 PPC64_STV_UNALIGNED(25) 536 PPC64_STV_UNALIGNED(26) 537 PPC64_STV_UNALIGNED(27) 538 PPC64_STV_UNALIGNED(28) 539 PPC64_STV_UNALIGNED(29) 540 PPC64_STV_UNALIGNED(30) 541 PPC64_STV_UNALIGNED(31) 542 543#endif 544#endif 545 546 li 3, 0 // return UNW_ESUCCESS 547 blr 548 549 550#elif defined(__powerpc__) 551 552// 553// extern int unw_getcontext(unw_context_t* thread_state) 554// 555// On entry: 556// thread_state pointer is in r3 557// 558#if defined(_AIX) 559DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext) 560#else 561DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 562#endif 563 stw 0, 8(3) 564 mflr 0 565 stw 0, 0(3) // store lr as ssr0 566 stw 1, 12(3) 567 stw 4, 24(3) // Save r4 first since it will be used for fixing r2. 568#if defined(_AIX) 569 // The TOC register (r2) was changed by the glue code if unw_getcontext 570 // is called from a different module. Save the original TOC register 571 // in the context if this is the case. 572 mflr 4 573 lwz 4, 0(4) // Get the instruction at the return address. 574 xoris 0, 4, 0x8041 // Is it reloading the TOC register "lwz 2,20(1)"? 575 cmplwi 0, 0x14 576 bne 0, LnoR2Fix // No need to fix up r2 if it is not. 577 lwz 2, 20(1) // Use the saved TOC register in the stack. 578LnoR2Fix: 579#endif 580 stw 2, 16(3) 581 stw 3, 20(3) 582 stw 5, 28(3) 583 stw 6, 32(3) 584 stw 7, 36(3) 585 stw 8, 40(3) 586 stw 9, 44(3) 587 stw 10, 48(3) 588 stw 11, 52(3) 589 stw 12, 56(3) 590 stw 13, 60(3) 591 stw 14, 64(3) 592 stw 15, 68(3) 593 stw 16, 72(3) 594 stw 17, 76(3) 595 stw 18, 80(3) 596 stw 19, 84(3) 597 stw 20, 88(3) 598 stw 21, 92(3) 599 stw 22, 96(3) 600 stw 23,100(3) 601 stw 24,104(3) 602 stw 25,108(3) 603 stw 26,112(3) 604 stw 27,116(3) 605 stw 28,120(3) 606 stw 29,124(3) 607 stw 30,128(3) 608 stw 31,132(3) 609 610#if defined(__ALTIVEC__) 611 // save VRSave register 612 mfspr 0, 256 613 stw 0, 156(3) 614#endif 615 // save CR registers 616 mfcr 0 617 stw 0, 136(3) 618#if defined(_AIX) 619 // LR value from the register is not used, initialize it to 0. 620 li 0, 0 621 stw 0, 144(3) 622#endif 623 // save CTR register 624 mfctr 0 625 stw 0, 148(3) 626 627#if !defined(__NO_FPRS__) 628 // save float registers 629 stfd 0, 160(3) 630 stfd 1, 168(3) 631 stfd 2, 176(3) 632 stfd 3, 184(3) 633 stfd 4, 192(3) 634 stfd 5, 200(3) 635 stfd 6, 208(3) 636 stfd 7, 216(3) 637 stfd 8, 224(3) 638 stfd 9, 232(3) 639 stfd 10,240(3) 640 stfd 11,248(3) 641 stfd 12,256(3) 642 stfd 13,264(3) 643 stfd 14,272(3) 644 stfd 15,280(3) 645 stfd 16,288(3) 646 stfd 17,296(3) 647 stfd 18,304(3) 648 stfd 19,312(3) 649 stfd 20,320(3) 650 stfd 21,328(3) 651 stfd 22,336(3) 652 stfd 23,344(3) 653 stfd 24,352(3) 654 stfd 25,360(3) 655 stfd 26,368(3) 656 stfd 27,376(3) 657 stfd 28,384(3) 658 stfd 29,392(3) 659 stfd 30,400(3) 660 stfd 31,408(3) 661#endif 662 663#if defined(__ALTIVEC__) 664 // save vector registers 665 666 subi 4, 1, 16 667 rlwinm 4, 4, 0, 0, 27 // mask low 4-bits 668 // r4 is now a 16-byte aligned pointer into the red zone 669 670#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ 671 stvx _vec, 0, 4 SEPARATOR \ 672 lwz 5, 0(4) SEPARATOR \ 673 stw 5, _offset(3) SEPARATOR \ 674 lwz 5, 4(4) SEPARATOR \ 675 stw 5, _offset+4(3) SEPARATOR \ 676 lwz 5, 8(4) SEPARATOR \ 677 stw 5, _offset+8(3) SEPARATOR \ 678 lwz 5, 12(4) SEPARATOR \ 679 stw 5, _offset+12(3) 680 681 SAVE_VECTOR_UNALIGNED( 0, 424+0x000) 682 SAVE_VECTOR_UNALIGNED( 1, 424+0x010) 683 SAVE_VECTOR_UNALIGNED( 2, 424+0x020) 684 SAVE_VECTOR_UNALIGNED( 3, 424+0x030) 685 SAVE_VECTOR_UNALIGNED( 4, 424+0x040) 686 SAVE_VECTOR_UNALIGNED( 5, 424+0x050) 687 SAVE_VECTOR_UNALIGNED( 6, 424+0x060) 688 SAVE_VECTOR_UNALIGNED( 7, 424+0x070) 689 SAVE_VECTOR_UNALIGNED( 8, 424+0x080) 690 SAVE_VECTOR_UNALIGNED( 9, 424+0x090) 691 SAVE_VECTOR_UNALIGNED(10, 424+0x0A0) 692 SAVE_VECTOR_UNALIGNED(11, 424+0x0B0) 693 SAVE_VECTOR_UNALIGNED(12, 424+0x0C0) 694 SAVE_VECTOR_UNALIGNED(13, 424+0x0D0) 695 SAVE_VECTOR_UNALIGNED(14, 424+0x0E0) 696 SAVE_VECTOR_UNALIGNED(15, 424+0x0F0) 697 SAVE_VECTOR_UNALIGNED(16, 424+0x100) 698 SAVE_VECTOR_UNALIGNED(17, 424+0x110) 699 SAVE_VECTOR_UNALIGNED(18, 424+0x120) 700 SAVE_VECTOR_UNALIGNED(19, 424+0x130) 701 SAVE_VECTOR_UNALIGNED(20, 424+0x140) 702 SAVE_VECTOR_UNALIGNED(21, 424+0x150) 703 SAVE_VECTOR_UNALIGNED(22, 424+0x160) 704 SAVE_VECTOR_UNALIGNED(23, 424+0x170) 705 SAVE_VECTOR_UNALIGNED(24, 424+0x180) 706 SAVE_VECTOR_UNALIGNED(25, 424+0x190) 707 SAVE_VECTOR_UNALIGNED(26, 424+0x1A0) 708 SAVE_VECTOR_UNALIGNED(27, 424+0x1B0) 709 SAVE_VECTOR_UNALIGNED(28, 424+0x1C0) 710 SAVE_VECTOR_UNALIGNED(29, 424+0x1D0) 711 SAVE_VECTOR_UNALIGNED(30, 424+0x1E0) 712 SAVE_VECTOR_UNALIGNED(31, 424+0x1F0) 713#endif 714 715 li 3, 0 // return UNW_ESUCCESS 716 blr 717 718 719#elif defined(__aarch64__) 720 721// 722// extern int __unw_getcontext(unw_context_t* thread_state) 723// 724// On entry: 725// thread_state pointer is in x0 726// 727 .p2align 2 728DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 729 stp x0, x1, [x0, #0x000] 730 stp x2, x3, [x0, #0x010] 731 stp x4, x5, [x0, #0x020] 732 stp x6, x7, [x0, #0x030] 733 stp x8, x9, [x0, #0x040] 734 stp x10,x11, [x0, #0x050] 735 stp x12,x13, [x0, #0x060] 736 stp x14,x15, [x0, #0x070] 737 stp x16,x17, [x0, #0x080] 738 stp x18,x19, [x0, #0x090] 739 stp x20,x21, [x0, #0x0A0] 740 stp x22,x23, [x0, #0x0B0] 741 stp x24,x25, [x0, #0x0C0] 742 stp x26,x27, [x0, #0x0D0] 743 stp x28,x29, [x0, #0x0E0] 744 str x30, [x0, #0x0F0] 745 mov x1,sp 746 str x1, [x0, #0x0F8] 747 str x30, [x0, #0x100] // store return address as pc 748 // skip cpsr 749#if defined(__ARM_FP) && __ARM_FP != 0 750 stp d0, d1, [x0, #0x110] 751 stp d2, d3, [x0, #0x120] 752 stp d4, d5, [x0, #0x130] 753 stp d6, d7, [x0, #0x140] 754 stp d8, d9, [x0, #0x150] 755 stp d10,d11, [x0, #0x160] 756 stp d12,d13, [x0, #0x170] 757 stp d14,d15, [x0, #0x180] 758 stp d16,d17, [x0, #0x190] 759 stp d18,d19, [x0, #0x1A0] 760 stp d20,d21, [x0, #0x1B0] 761 stp d22,d23, [x0, #0x1C0] 762 stp d24,d25, [x0, #0x1D0] 763 stp d26,d27, [x0, #0x1E0] 764 stp d28,d29, [x0, #0x1F0] 765 str d30, [x0, #0x200] 766 str d31, [x0, #0x208] 767#endif 768 mov x0, #0 // return UNW_ESUCCESS 769 ret 770 771#elif defined(__arm__) && !defined(__APPLE__) 772 773#if !defined(__ARM_ARCH_ISA_ARM) 774#if (__ARM_ARCH_ISA_THUMB == 2) 775 .syntax unified 776#endif 777 .thumb 778#endif 779 780@ 781@ extern int __unw_getcontext(unw_context_t* thread_state) 782@ 783@ On entry: 784@ thread_state pointer is in r0 785@ 786@ Per EHABI #4.7 this only saves the core integer registers. 787@ EHABI #7.4.5 notes that in general all VRS registers should be restored 788@ however this is very hard to do for VFP registers because it is unknown 789@ to the library how many registers are implemented by the architecture. 790@ Instead, VFP registers are demand saved by logic external to __unw_getcontext. 791@ 792 .p2align 2 793DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 794#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1 795 stm r0!, {r0-r7} 796 mov r1, r8 797 mov r2, r9 798 mov r3, r10 799 stm r0!, {r1-r3} 800 mov r1, r11 801 mov r2, sp 802 mov r3, lr 803 str r1, [r0, #0] @ r11 804 @ r12 does not need storing, it it the intra-procedure-call scratch register 805 str r2, [r0, #8] @ sp 806 str r3, [r0, #12] @ lr 807 str r3, [r0, #16] @ store return address as pc 808 @ T1 does not have a non-cpsr-clobbering register-zeroing instruction. 809 @ It is safe to use here though because we are about to return, and cpsr is 810 @ not expected to be preserved. 811 movs r0, #0 @ return UNW_ESUCCESS 812#else 813 @ 32bit thumb-2 restrictions for stm: 814 @ . the sp (r13) cannot be in the list 815 @ . the pc (r15) cannot be in the list in an STM instruction 816 stm r0, {r0-r12} 817 str sp, [r0, #52] 818 str lr, [r0, #56] 819 str lr, [r0, #60] @ store return address as pc 820 mov r0, #0 @ return UNW_ESUCCESS 821#endif 822 JMP(lr) 823 824@ 825@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values) 826@ 827@ On entry: 828@ values pointer is in r0 829@ 830 .p2align 2 831#if defined(__ELF__) 832 .fpu vfpv3-d16 833#endif 834DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv) 835 vstmia r0, {d0-d15} 836 JMP(lr) 837 838@ 839@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values) 840@ 841@ On entry: 842@ values pointer is in r0 843@ 844 .p2align 2 845#if defined(__ELF__) 846 .fpu vfpv3-d16 847#endif 848DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv) 849 vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia 850 JMP(lr) 851 852@ 853@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values) 854@ 855@ On entry: 856@ values pointer is in r0 857@ 858 .p2align 2 859#if defined(__ELF__) 860 .fpu vfpv3 861#endif 862DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv) 863 @ VFP and iwMMX instructions are only available when compiling with the flags 864 @ that enable them. We do not want to do that in the library (because we do not 865 @ want the compiler to generate instructions that access those) but this is 866 @ only accessed if the personality routine needs these registers. Use of 867 @ these registers implies they are, actually, available on the target, so 868 @ it's ok to execute. 869 @ So, generate the instructions using the corresponding coprocessor mnemonic. 870 vstmia r0, {d16-d31} 871 JMP(lr) 872 873#if defined(_LIBUNWIND_ARM_WMMX) 874 875@ 876@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values) 877@ 878@ On entry: 879@ values pointer is in r0 880@ 881 .p2align 2 882#if defined(__ELF__) 883 .arch armv5te 884#endif 885DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv) 886 stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8 887 stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8 888 stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8 889 stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8 890 stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8 891 stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8 892 stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8 893 stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8 894 stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8 895 stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8 896 stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8 897 stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8 898 stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8 899 stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8 900 stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8 901 stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8 902 JMP(lr) 903 904@ 905@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values) 906@ 907@ On entry: 908@ values pointer is in r0 909@ 910 .p2align 2 911#if defined(__ELF__) 912 .arch armv5te 913#endif 914DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj) 915 stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4 916 stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4 917 stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4 918 stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4 919 JMP(lr) 920 921#endif 922 923#elif defined(__or1k__) 924 925# 926# extern int __unw_getcontext(unw_context_t* thread_state) 927# 928# On entry: 929# thread_state pointer is in r3 930# 931DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 932 l.sw 0(r3), r0 933 l.sw 4(r3), r1 934 l.sw 8(r3), r2 935 l.sw 12(r3), r3 936 l.sw 16(r3), r4 937 l.sw 20(r3), r5 938 l.sw 24(r3), r6 939 l.sw 28(r3), r7 940 l.sw 32(r3), r8 941 l.sw 36(r3), r9 942 l.sw 40(r3), r10 943 l.sw 44(r3), r11 944 l.sw 48(r3), r12 945 l.sw 52(r3), r13 946 l.sw 56(r3), r14 947 l.sw 60(r3), r15 948 l.sw 64(r3), r16 949 l.sw 68(r3), r17 950 l.sw 72(r3), r18 951 l.sw 76(r3), r19 952 l.sw 80(r3), r20 953 l.sw 84(r3), r21 954 l.sw 88(r3), r22 955 l.sw 92(r3), r23 956 l.sw 96(r3), r24 957 l.sw 100(r3), r25 958 l.sw 104(r3), r26 959 l.sw 108(r3), r27 960 l.sw 112(r3), r28 961 l.sw 116(r3), r29 962 l.sw 120(r3), r30 963 l.sw 124(r3), r31 964 # store ra to pc 965 l.sw 128(r3), r9 966 # zero epcr 967 l.sw 132(r3), r0 968 969#elif defined(__hexagon__) 970# 971# extern int unw_getcontext(unw_context_t* thread_state) 972# 973# On entry: 974# thread_state pointer is in r0 975# 976#define OFFSET(offset) (offset/4) 977DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 978 memw(r0+#32) = r8 979 memw(r0+#36) = r9 980 memw(r0+#40) = r10 981 memw(r0+#44) = r11 982 983 memw(r0+#48) = r12 984 memw(r0+#52) = r13 985 memw(r0+#56) = r14 986 memw(r0+#60) = r15 987 988 memw(r0+#64) = r16 989 memw(r0+#68) = r17 990 memw(r0+#72) = r18 991 memw(r0+#76) = r19 992 993 memw(r0+#80) = r20 994 memw(r0+#84) = r21 995 memw(r0+#88) = r22 996 memw(r0+#92) = r23 997 998 memw(r0+#96) = r24 999 memw(r0+#100) = r25 1000 memw(r0+#104) = r26 1001 memw(r0+#108) = r27 1002 1003 memw(r0+#112) = r28 1004 memw(r0+#116) = r29 1005 memw(r0+#120) = r30 1006 memw(r0+#124) = r31 1007 r1 = c4 // Predicate register 1008 memw(r0+#128) = r1 1009 r1 = memw(r30) // *FP == Saved FP 1010 r1 = r31 1011 memw(r0+#132) = r1 1012 1013 jumpr r31 1014 1015#elif defined(__sparc__) && defined(__arch64__) 1016 1017# 1018# extern int __unw_getcontext(unw_context_t* thread_state) 1019# 1020# On entry: 1021# thread_state pointer is in %o0 1022# 1023DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 1024 .register %g2, #scratch 1025 .register %g3, #scratch 1026 .register %g6, #scratch 1027 .register %g7, #scratch 1028 stx %g1, [%o0 + 0x08] 1029 stx %g2, [%o0 + 0x10] 1030 stx %g3, [%o0 + 0x18] 1031 stx %g4, [%o0 + 0x20] 1032 stx %g5, [%o0 + 0x28] 1033 stx %g6, [%o0 + 0x30] 1034 stx %g7, [%o0 + 0x38] 1035 stx %o0, [%o0 + 0x40] 1036 stx %o1, [%o0 + 0x48] 1037 stx %o2, [%o0 + 0x50] 1038 stx %o3, [%o0 + 0x58] 1039 stx %o4, [%o0 + 0x60] 1040 stx %o5, [%o0 + 0x68] 1041 stx %o6, [%o0 + 0x70] 1042 stx %o7, [%o0 + 0x78] 1043 stx %l0, [%o0 + 0x80] 1044 stx %l1, [%o0 + 0x88] 1045 stx %l2, [%o0 + 0x90] 1046 stx %l3, [%o0 + 0x98] 1047 stx %l4, [%o0 + 0xa0] 1048 stx %l5, [%o0 + 0xa8] 1049 stx %l6, [%o0 + 0xb0] 1050 stx %l7, [%o0 + 0xb8] 1051 stx %i0, [%o0 + 0xc0] 1052 stx %i1, [%o0 + 0xc8] 1053 stx %i2, [%o0 + 0xd0] 1054 stx %i3, [%o0 + 0xd8] 1055 stx %i4, [%o0 + 0xe0] 1056 stx %i5, [%o0 + 0xe8] 1057 stx %i6, [%o0 + 0xf0] 1058 stx %i7, [%o0 + 0xf8] 1059 1060 # save StackGhost cookie 1061 mov %i7, %g4 1062 save %sp, -176, %sp 1063 # register window flush necessary even without StackGhost 1064 flushw 1065 restore 1066 ldx [%sp + 2047 + 0x78], %g5 1067 xor %g4, %g5, %g4 1068 stx %g4, [%o0 + 0x100] 1069 retl 1070 # return UNW_ESUCCESS 1071 clr %o0 1072 1073#elif defined(__sparc__) 1074 1075# 1076# extern int __unw_getcontext(unw_context_t* thread_state) 1077# 1078# On entry: 1079# thread_state pointer is in o0 1080# 1081DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 1082 ta 3 1083 add %o7, 8, %o7 1084 std %g0, [%o0 + 0] 1085 std %g2, [%o0 + 8] 1086 std %g4, [%o0 + 16] 1087 std %g6, [%o0 + 24] 1088 std %o0, [%o0 + 32] 1089 std %o2, [%o0 + 40] 1090 std %o4, [%o0 + 48] 1091 std %o6, [%o0 + 56] 1092 std %l0, [%o0 + 64] 1093 std %l2, [%o0 + 72] 1094 std %l4, [%o0 + 80] 1095 std %l6, [%o0 + 88] 1096 std %i0, [%o0 + 96] 1097 std %i2, [%o0 + 104] 1098 std %i4, [%o0 + 112] 1099 std %i6, [%o0 + 120] 1100 jmp %o7 1101 clr %o0 // return UNW_ESUCCESS 1102 1103#elif defined(__riscv) 1104 1105# 1106# extern int __unw_getcontext(unw_context_t* thread_state) 1107# 1108# On entry: 1109# thread_state pointer is in a0 1110# 1111DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 1112 ISTORE x1, (RISCV_ISIZE * 0)(a0) // store ra as pc 1113#if defined(__riscv_32e) 1114 .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 1115#else 1116 .irp i,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 1117#endif 1118 ISTORE x\i, (RISCV_ISIZE * \i)(a0) 1119 .endr 1120 1121# if defined(__riscv_flen) 1122 .irp i,FROM_0_TO_31 1123 FSTORE f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0) 1124 .endr 1125# endif 1126 1127 li a0, 0 // return UNW_ESUCCESS 1128 ret // jump to ra 1129 1130#elif defined(__s390x__) 1131 1132// 1133// extern int __unw_getcontext(unw_context_t* thread_state) 1134// 1135// On entry: 1136// thread_state pointer is in r2 1137// 1138DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 1139 1140 // Save GPRs 1141 stmg %r0, %r15, 16(%r2) 1142 1143 // Save PSWM 1144 epsw %r0, %r1 1145 stm %r0, %r1, 0(%r2) 1146 1147 // Store return address as PSWA 1148 stg %r14, 8(%r2) 1149 1150 // Save FPRs 1151 .irp i,FROM_0_TO_15 1152 std %f\i, (144+8*\i)(%r2) 1153 .endr 1154 1155 // Return UNW_ESUCCESS 1156 lghi %r2, 0 1157 br %r14 1158 1159#elif defined(__loongarch__) && __loongarch_grlen == 64 1160 1161# 1162# extern int __unw_getcontext(unw_context_t* thread_state) 1163# 1164# On entry: 1165# thread_state pointer is in $a0($r4) 1166# 1167DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) 1168 .irp i,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 1169 st.d $r\i, $a0, (8*\i) 1170 .endr 1171 st.d $r1, $a0, (8 * 32) // store $ra to pc 1172 1173# if __loongarch_frlen == 64 1174 .irp i,FROM_0_TO_31 1175 fst.d $f\i, $a0, (8 * 33 + 8 * \i) 1176 .endr 1177# endif 1178 1179 move $a0, $zero // UNW_ESUCCESS 1180 jr $ra 1181 1182#endif 1183 1184 WEAK_ALIAS(__unw_getcontext, unw_getcontext) 1185 1186#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ 1187 1188NO_EXEC_STACK_DIRECTIVE 1189