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