Path: blob/main/system/lib/libunwind/src/UnwindRegistersSave.S
6175 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "assembly.h"910#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,1511#define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,311213#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,3114#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,631516#if defined(_AIX)17.toc18#else19.text20#endif2122#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)2324#if defined(__i386__)2526#27# extern int __unw_getcontext(unw_context_t* thread_state)28#29# On entry:30# + +31# +-----------------------+32# + thread_state pointer +33# +-----------------------+34# + return address +35# +-----------------------+ <-- SP36# + +37#38DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)3940_LIBUNWIND_CET_ENDBR41push %eax42movl 8(%esp), %eax43movl %ebx, 4(%eax)44movl %ecx, 8(%eax)45movl %edx, 12(%eax)46movl %edi, 16(%eax)47movl %esi, 20(%eax)48movl %ebp, 24(%eax)49movl %esp, %edx50addl $8, %edx51movl %edx, 28(%eax) # store what sp was at call site as esp52# skip ss53# skip eflags54movl 4(%esp), %edx55movl %edx, 40(%eax) # store return address as eip56# skip cs57# skip ds58# skip es59# skip fs60# skip gs61movl (%esp), %edx62movl %edx, (%eax) # store original eax63popl %eax64xorl %eax, %eax # return UNW_ESUCCESS65ret6667#elif defined(__arm64ec__)6869//70// extern int __unw_getcontext(unw_context_t* thread_state)71//72// On entry:73// thread_state pointer is in x074//75.section .text,"xr",discard,"#__unw_getcontext"76.p2align 277DEFINE_LIBUNWIND_FUNCTION("#__unw_getcontext")78stp x8, x27, [x0, #0x000] // rax, rbx79stp x0, x1, [x0, #0x010] // rcx, rdx80stp x26,x25, [x0, #0x020] // rdi, rsi81mov x1, sp82stp fp, x1, [x0, #0x030] // rbp, rsp83stp x2, x3, [x0, #0x040] // r8, r984stp x4, x5, [x0, #0x050] // r10, r1185stp x19,x20, [x0, #0x060] // r12, r1386stp x21,x22, [x0, #0x070] // r14, r1587str x30, [x0, #0x080] // store return address as pc88stp q0, q1, [x0, #0x0b0] // xmm0, xmm189stp q2, q3, [x0, #0x0d0] // xmm2, xmm390stp q4, q5, [x0, #0x0f0] // xmm4, xmm591stp q6, q7, [x0, #0x110] // xmm6, xmm792stp q8, q9, [x0, #0x130] // xmm8, xmm993stp q10,q11, [x0, #0x150] // xmm10,xmm1194stp q12,q13, [x0, #0x170] // xmm12,xmm1395stp q14,q15, [x0, #0x190] // xmm14,xmm1596mov x0, #0 // return UNW_ESUCCESS97ret9899.weak_anti_dep __unw_getcontext100.set __unw_getcontext, "#__unw_getcontext"101102.section .hybmp$x,"yi"103.symidx "#__unw_getcontext"104.symidx $ientry_thunk$cdecl$i8$i8105.word 1106.text107108#elif defined(__x86_64__)109110#111# extern int __unw_getcontext(unw_context_t* thread_state)112#113# On entry:114# thread_state pointer is in rdi115#116DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)117#if defined(_WIN64)118#define PTR %rcx119#define TMP %rdx120#else121#define PTR %rdi122#define TMP %rsi123#endif124125_LIBUNWIND_CET_ENDBR126movq %rax, (PTR)127movq %rbx, 8(PTR)128movq %rcx, 16(PTR)129movq %rdx, 24(PTR)130movq %rdi, 32(PTR)131movq %rsi, 40(PTR)132movq %rbp, 48(PTR)133movq %rsp, 56(PTR)134addq $8, 56(PTR)135movq %r8, 64(PTR)136movq %r9, 72(PTR)137movq %r10, 80(PTR)138movq %r11, 88(PTR)139movq %r12, 96(PTR)140movq %r13,104(PTR)141movq %r14,112(PTR)142movq %r15,120(PTR)143movq (%rsp),TMP144movq TMP,128(PTR) # store return address as rip145# skip rflags146# skip cs147# skip fs148# skip gs149150#if defined(_WIN64)151movdqu %xmm0,176(PTR)152movdqu %xmm1,192(PTR)153movdqu %xmm2,208(PTR)154movdqu %xmm3,224(PTR)155movdqu %xmm4,240(PTR)156movdqu %xmm5,256(PTR)157movdqu %xmm6,272(PTR)158movdqu %xmm7,288(PTR)159movdqu %xmm8,304(PTR)160movdqu %xmm9,320(PTR)161movdqu %xmm10,336(PTR)162movdqu %xmm11,352(PTR)163movdqu %xmm12,368(PTR)164movdqu %xmm13,384(PTR)165movdqu %xmm14,400(PTR)166movdqu %xmm15,416(PTR)167#endif168xorl %eax, %eax # return UNW_ESUCCESS169ret170171#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32172173#174# extern int __unw_getcontext(unw_context_t* thread_state)175#176# On entry:177# thread_state pointer is in a0 ($4)178#179DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)180.set push181.set noat182.set noreorder183.set nomacro184sw $1, (4 * 1)($4)185sw $2, (4 * 2)($4)186sw $3, (4 * 3)($4)187sw $4, (4 * 4)($4)188sw $5, (4 * 5)($4)189sw $6, (4 * 6)($4)190sw $7, (4 * 7)($4)191sw $8, (4 * 8)($4)192sw $9, (4 * 9)($4)193sw $10, (4 * 10)($4)194sw $11, (4 * 11)($4)195sw $12, (4 * 12)($4)196sw $13, (4 * 13)($4)197sw $14, (4 * 14)($4)198sw $15, (4 * 15)($4)199sw $16, (4 * 16)($4)200sw $17, (4 * 17)($4)201sw $18, (4 * 18)($4)202sw $19, (4 * 19)($4)203sw $20, (4 * 20)($4)204sw $21, (4 * 21)($4)205sw $22, (4 * 22)($4)206sw $23, (4 * 23)($4)207sw $24, (4 * 24)($4)208sw $25, (4 * 25)($4)209sw $26, (4 * 26)($4)210sw $27, (4 * 27)($4)211sw $28, (4 * 28)($4)212sw $29, (4 * 29)($4)213sw $30, (4 * 30)($4)214sw $31, (4 * 31)($4)215# Store return address to pc216sw $31, (4 * 32)($4)217#if __mips_isa_rev < 6218# hi and lo219mfhi $8220sw $8, (4 * 33)($4)221mflo $8222sw $8, (4 * 34)($4)223#endif224#ifdef __mips_hard_float225#if __mips_fpr != 64226sdc1 $f0, (4 * 36 + 8 * 0)($4)227sdc1 $f2, (4 * 36 + 8 * 2)($4)228sdc1 $f4, (4 * 36 + 8 * 4)($4)229sdc1 $f6, (4 * 36 + 8 * 6)($4)230sdc1 $f8, (4 * 36 + 8 * 8)($4)231sdc1 $f10, (4 * 36 + 8 * 10)($4)232sdc1 $f12, (4 * 36 + 8 * 12)($4)233sdc1 $f14, (4 * 36 + 8 * 14)($4)234sdc1 $f16, (4 * 36 + 8 * 16)($4)235sdc1 $f18, (4 * 36 + 8 * 18)($4)236sdc1 $f20, (4 * 36 + 8 * 20)($4)237sdc1 $f22, (4 * 36 + 8 * 22)($4)238sdc1 $f24, (4 * 36 + 8 * 24)($4)239sdc1 $f26, (4 * 36 + 8 * 26)($4)240sdc1 $f28, (4 * 36 + 8 * 28)($4)241sdc1 $f30, (4 * 36 + 8 * 30)($4)242#else243sdc1 $f0, (4 * 36 + 8 * 0)($4)244sdc1 $f1, (4 * 36 + 8 * 1)($4)245sdc1 $f2, (4 * 36 + 8 * 2)($4)246sdc1 $f3, (4 * 36 + 8 * 3)($4)247sdc1 $f4, (4 * 36 + 8 * 4)($4)248sdc1 $f5, (4 * 36 + 8 * 5)($4)249sdc1 $f6, (4 * 36 + 8 * 6)($4)250sdc1 $f7, (4 * 36 + 8 * 7)($4)251sdc1 $f8, (4 * 36 + 8 * 8)($4)252sdc1 $f9, (4 * 36 + 8 * 9)($4)253sdc1 $f10, (4 * 36 + 8 * 10)($4)254sdc1 $f11, (4 * 36 + 8 * 11)($4)255sdc1 $f12, (4 * 36 + 8 * 12)($4)256sdc1 $f13, (4 * 36 + 8 * 13)($4)257sdc1 $f14, (4 * 36 + 8 * 14)($4)258sdc1 $f15, (4 * 36 + 8 * 15)($4)259sdc1 $f16, (4 * 36 + 8 * 16)($4)260sdc1 $f17, (4 * 36 + 8 * 17)($4)261sdc1 $f18, (4 * 36 + 8 * 18)($4)262sdc1 $f19, (4 * 36 + 8 * 19)($4)263sdc1 $f20, (4 * 36 + 8 * 20)($4)264sdc1 $f21, (4 * 36 + 8 * 21)($4)265sdc1 $f22, (4 * 36 + 8 * 22)($4)266sdc1 $f23, (4 * 36 + 8 * 23)($4)267sdc1 $f24, (4 * 36 + 8 * 24)($4)268sdc1 $f25, (4 * 36 + 8 * 25)($4)269sdc1 $f26, (4 * 36 + 8 * 26)($4)270sdc1 $f27, (4 * 36 + 8 * 27)($4)271sdc1 $f28, (4 * 36 + 8 * 28)($4)272sdc1 $f29, (4 * 36 + 8 * 29)($4)273sdc1 $f30, (4 * 36 + 8 * 30)($4)274sdc1 $f31, (4 * 36 + 8 * 31)($4)275#endif276#endif277jr $31278# return UNW_ESUCCESS279or $2, $0, $0280.set pop281282#elif defined(__mips64)283284#285# extern int __unw_getcontext(unw_context_t* thread_state)286#287# On entry:288# thread_state pointer is in a0 ($4)289#290DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)291.set push292.set noat293.set noreorder294.set nomacro295.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,31296sd $\i, (8 * \i)($4)297.endr298# Store return address to pc299sd $31, (8 * 32)($4)300#if __mips_isa_rev < 6301# hi and lo302mfhi $8303sd $8, (8 * 33)($4)304mflo $8305sd $8, (8 * 34)($4)306#endif307#ifdef __mips_hard_float308.irp i,FROM_0_TO_31309sdc1 $f\i, (280+8*\i)($4)310.endr311#endif312jr $31313# return UNW_ESUCCESS314or $2, $0, $0315.set pop316317# elif defined(__mips__)318319#320# extern int __unw_getcontext(unw_context_t* thread_state)321#322# Just trap for the time being.323DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)324teq $0, $0325326#elif defined(__powerpc64__)327328//329// extern int __unw_getcontext(unw_context_t* thread_state)330//331// On entry:332// thread_state pointer is in r3333//334#if defined(_AIX)335DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)336#else337DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)338#endif339// store register (GPR)340#define PPC64_STR(n) \341std n, (8 * (n + 2))(3)342343// save GPRs344PPC64_STR(0)345mflr 0346std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0347PPC64_STR(1)348PPC64_STR(4) // Save r4 first since it will be used for fixing r2.349#if defined(_AIX)350// The TOC register (r2) was changed by the glue code if unw_getcontext351// is called from a different module. Save the original TOC register352// in the context if this is the case.353mflr 4354lwz 4, 0(4) // Get the first instruction at the return address.355xoris 0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"?356cmplwi 0, 0x28357bne 0, LnoR2Fix // No need to fix up r2 if it is not.358ld 2, 40(1) // Use the saved TOC register in the stack.359LnoR2Fix:360#endif361PPC64_STR(2)362PPC64_STR(3)363PPC64_STR(5)364PPC64_STR(6)365PPC64_STR(7)366PPC64_STR(8)367PPC64_STR(9)368PPC64_STR(10)369PPC64_STR(11)370PPC64_STR(12)371PPC64_STR(13)372PPC64_STR(14)373PPC64_STR(15)374PPC64_STR(16)375PPC64_STR(17)376PPC64_STR(18)377PPC64_STR(19)378PPC64_STR(20)379PPC64_STR(21)380PPC64_STR(22)381PPC64_STR(23)382PPC64_STR(24)383PPC64_STR(25)384PPC64_STR(26)385PPC64_STR(27)386PPC64_STR(28)387PPC64_STR(29)388PPC64_STR(30)389PPC64_STR(31)390391mfcr 0392std 0, PPC64_OFFS_CR(3)393mfxer 0394std 0, PPC64_OFFS_XER(3)395#if defined(_AIX)396// LR value saved from the register is not used, initialize it to 0.397li 0, 0398#else399mflr 0400#endif401std 0, PPC64_OFFS_LR(3)402mfctr 0403std 0, PPC64_OFFS_CTR(3)404mfvrsave 0405std 0, PPC64_OFFS_VRSAVE(3)406407#if defined(__VSX__)408// save VS registers409// (note that this also saves floating point registers and V registers,410// because part of VS is mapped to these registers)411412addi 4, 3, PPC64_OFFS_FP413414// store VS register415#ifdef __LITTLE_ENDIAN__416// For little-endian targets, we need a swap since stxvd2x will store the417// register in the incorrect doubleword order.418// FIXME: when supporting targets older than Power9 on LE is no longer required419// this can be changed to simply `stxv n, 16 * n(4)`.420#define PPC64_STVS(n) \421xxswapd n, n ;\422stxvd2x n, 0, 4 ;\423addi 4, 4, 16424#else425#define PPC64_STVS(n) \426stxvd2x n, 0, 4 ;\427addi 4, 4, 16428#endif429430PPC64_STVS(0)431PPC64_STVS(1)432PPC64_STVS(2)433PPC64_STVS(3)434PPC64_STVS(4)435PPC64_STVS(5)436PPC64_STVS(6)437PPC64_STVS(7)438PPC64_STVS(8)439PPC64_STVS(9)440PPC64_STVS(10)441PPC64_STVS(11)442PPC64_STVS(12)443PPC64_STVS(13)444PPC64_STVS(14)445PPC64_STVS(15)446PPC64_STVS(16)447PPC64_STVS(17)448PPC64_STVS(18)449PPC64_STVS(19)450PPC64_STVS(20)451PPC64_STVS(21)452PPC64_STVS(22)453PPC64_STVS(23)454PPC64_STVS(24)455PPC64_STVS(25)456PPC64_STVS(26)457PPC64_STVS(27)458PPC64_STVS(28)459PPC64_STVS(29)460PPC64_STVS(30)461PPC64_STVS(31)462PPC64_STVS(32)463PPC64_STVS(33)464PPC64_STVS(34)465PPC64_STVS(35)466PPC64_STVS(36)467PPC64_STVS(37)468PPC64_STVS(38)469PPC64_STVS(39)470PPC64_STVS(40)471PPC64_STVS(41)472PPC64_STVS(42)473PPC64_STVS(43)474PPC64_STVS(44)475PPC64_STVS(45)476PPC64_STVS(46)477PPC64_STVS(47)478PPC64_STVS(48)479PPC64_STVS(49)480PPC64_STVS(50)481PPC64_STVS(51)482PPC64_STVS(52)483PPC64_STVS(53)484PPC64_STVS(54)485PPC64_STVS(55)486PPC64_STVS(56)487PPC64_STVS(57)488PPC64_STVS(58)489PPC64_STVS(59)490PPC64_STVS(60)491PPC64_STVS(61)492PPC64_STVS(62)493PPC64_STVS(63)494495#else496497// store FP register498#define PPC64_STF(n) \499stfd n, (PPC64_OFFS_FP + n * 16)(3)500501// save float registers502PPC64_STF(0)503PPC64_STF(1)504PPC64_STF(2)505PPC64_STF(3)506PPC64_STF(4)507PPC64_STF(5)508PPC64_STF(6)509PPC64_STF(7)510PPC64_STF(8)511PPC64_STF(9)512PPC64_STF(10)513PPC64_STF(11)514PPC64_STF(12)515PPC64_STF(13)516PPC64_STF(14)517PPC64_STF(15)518PPC64_STF(16)519PPC64_STF(17)520PPC64_STF(18)521PPC64_STF(19)522PPC64_STF(20)523PPC64_STF(21)524PPC64_STF(22)525PPC64_STF(23)526PPC64_STF(24)527PPC64_STF(25)528PPC64_STF(26)529PPC64_STF(27)530PPC64_STF(28)531PPC64_STF(29)532PPC64_STF(30)533PPC64_STF(31)534535#if defined(__ALTIVEC__)536// save vector registers537538// Use 16-bytes below the stack pointer as an539// aligned buffer to save each vector register.540// Note that the stack pointer is always 16-byte aligned.541subi 4, 1, 16542543#define PPC64_STV_UNALIGNED(n) \544stvx n, 0, 4 ;\545ld 5, 0(4) ;\546std 5, (PPC64_OFFS_V + n * 16)(3) ;\547ld 5, 8(4) ;\548std 5, (PPC64_OFFS_V + n * 16 + 8)(3)549550PPC64_STV_UNALIGNED(0)551PPC64_STV_UNALIGNED(1)552PPC64_STV_UNALIGNED(2)553PPC64_STV_UNALIGNED(3)554PPC64_STV_UNALIGNED(4)555PPC64_STV_UNALIGNED(5)556PPC64_STV_UNALIGNED(6)557PPC64_STV_UNALIGNED(7)558PPC64_STV_UNALIGNED(8)559PPC64_STV_UNALIGNED(9)560PPC64_STV_UNALIGNED(10)561PPC64_STV_UNALIGNED(11)562PPC64_STV_UNALIGNED(12)563PPC64_STV_UNALIGNED(13)564PPC64_STV_UNALIGNED(14)565PPC64_STV_UNALIGNED(15)566PPC64_STV_UNALIGNED(16)567PPC64_STV_UNALIGNED(17)568PPC64_STV_UNALIGNED(18)569PPC64_STV_UNALIGNED(19)570PPC64_STV_UNALIGNED(20)571PPC64_STV_UNALIGNED(21)572PPC64_STV_UNALIGNED(22)573PPC64_STV_UNALIGNED(23)574PPC64_STV_UNALIGNED(24)575PPC64_STV_UNALIGNED(25)576PPC64_STV_UNALIGNED(26)577PPC64_STV_UNALIGNED(27)578PPC64_STV_UNALIGNED(28)579PPC64_STV_UNALIGNED(29)580PPC64_STV_UNALIGNED(30)581PPC64_STV_UNALIGNED(31)582583#endif584#endif585586li 3, 0 // return UNW_ESUCCESS587blr588589590#elif defined(__powerpc__)591592//593// extern int unw_getcontext(unw_context_t* thread_state)594//595// On entry:596// thread_state pointer is in r3597//598#if defined(_AIX)599DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)600#else601DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)602#endif603stw 0, 8(3)604mflr 0605stw 0, 0(3) // store lr as ssr0606stw 1, 12(3)607stw 4, 24(3) // Save r4 first since it will be used for fixing r2.608#if defined(_AIX)609// The TOC register (r2) was changed by the glue code if unw_getcontext610// is called from a different module. Save the original TOC register611// in the context if this is the case.612mflr 4613lwz 4, 0(4) // Get the instruction at the return address.614xoris 0, 4, 0x8041 // Is it reloading the TOC register "lwz 2,20(1)"?615cmplwi 0, 0x14616bne 0, LnoR2Fix // No need to fix up r2 if it is not.617lwz 2, 20(1) // Use the saved TOC register in the stack.618LnoR2Fix:619#endif620stw 2, 16(3)621stw 3, 20(3)622stw 5, 28(3)623stw 6, 32(3)624stw 7, 36(3)625stw 8, 40(3)626stw 9, 44(3)627stw 10, 48(3)628stw 11, 52(3)629stw 12, 56(3)630stw 13, 60(3)631stw 14, 64(3)632stw 15, 68(3)633stw 16, 72(3)634stw 17, 76(3)635stw 18, 80(3)636stw 19, 84(3)637stw 20, 88(3)638stw 21, 92(3)639stw 22, 96(3)640stw 23,100(3)641stw 24,104(3)642stw 25,108(3)643stw 26,112(3)644stw 27,116(3)645stw 28,120(3)646stw 29,124(3)647stw 30,128(3)648stw 31,132(3)649650#if defined(__ALTIVEC__)651// save VRSave register652mfspr 0, 256653stw 0, 156(3)654#endif655// save CR registers656mfcr 0657stw 0, 136(3)658#if defined(_AIX)659// LR value from the register is not used, initialize it to 0.660li 0, 0661stw 0, 144(3)662#endif663// save CTR register664mfctr 0665stw 0, 148(3)666667#if !defined(__NO_FPRS__)668// save float registers669stfd 0, 160(3)670stfd 1, 168(3)671stfd 2, 176(3)672stfd 3, 184(3)673stfd 4, 192(3)674stfd 5, 200(3)675stfd 6, 208(3)676stfd 7, 216(3)677stfd 8, 224(3)678stfd 9, 232(3)679stfd 10,240(3)680stfd 11,248(3)681stfd 12,256(3)682stfd 13,264(3)683stfd 14,272(3)684stfd 15,280(3)685stfd 16,288(3)686stfd 17,296(3)687stfd 18,304(3)688stfd 19,312(3)689stfd 20,320(3)690stfd 21,328(3)691stfd 22,336(3)692stfd 23,344(3)693stfd 24,352(3)694stfd 25,360(3)695stfd 26,368(3)696stfd 27,376(3)697stfd 28,384(3)698stfd 29,392(3)699stfd 30,400(3)700stfd 31,408(3)701#endif702703#if defined(__ALTIVEC__)704// save vector registers705706subi 4, 1, 16707rlwinm 4, 4, 0, 0, 27 // mask low 4-bits708// r4 is now a 16-byte aligned pointer into the red zone709710#define SAVE_VECTOR_UNALIGNED(_vec, _offset) \711stvx _vec, 0, 4 SEPARATOR \712lwz 5, 0(4) SEPARATOR \713stw 5, _offset(3) SEPARATOR \714lwz 5, 4(4) SEPARATOR \715stw 5, _offset+4(3) SEPARATOR \716lwz 5, 8(4) SEPARATOR \717stw 5, _offset+8(3) SEPARATOR \718lwz 5, 12(4) SEPARATOR \719stw 5, _offset+12(3)720721SAVE_VECTOR_UNALIGNED( 0, 424+0x000)722SAVE_VECTOR_UNALIGNED( 1, 424+0x010)723SAVE_VECTOR_UNALIGNED( 2, 424+0x020)724SAVE_VECTOR_UNALIGNED( 3, 424+0x030)725SAVE_VECTOR_UNALIGNED( 4, 424+0x040)726SAVE_VECTOR_UNALIGNED( 5, 424+0x050)727SAVE_VECTOR_UNALIGNED( 6, 424+0x060)728SAVE_VECTOR_UNALIGNED( 7, 424+0x070)729SAVE_VECTOR_UNALIGNED( 8, 424+0x080)730SAVE_VECTOR_UNALIGNED( 9, 424+0x090)731SAVE_VECTOR_UNALIGNED(10, 424+0x0A0)732SAVE_VECTOR_UNALIGNED(11, 424+0x0B0)733SAVE_VECTOR_UNALIGNED(12, 424+0x0C0)734SAVE_VECTOR_UNALIGNED(13, 424+0x0D0)735SAVE_VECTOR_UNALIGNED(14, 424+0x0E0)736SAVE_VECTOR_UNALIGNED(15, 424+0x0F0)737SAVE_VECTOR_UNALIGNED(16, 424+0x100)738SAVE_VECTOR_UNALIGNED(17, 424+0x110)739SAVE_VECTOR_UNALIGNED(18, 424+0x120)740SAVE_VECTOR_UNALIGNED(19, 424+0x130)741SAVE_VECTOR_UNALIGNED(20, 424+0x140)742SAVE_VECTOR_UNALIGNED(21, 424+0x150)743SAVE_VECTOR_UNALIGNED(22, 424+0x160)744SAVE_VECTOR_UNALIGNED(23, 424+0x170)745SAVE_VECTOR_UNALIGNED(24, 424+0x180)746SAVE_VECTOR_UNALIGNED(25, 424+0x190)747SAVE_VECTOR_UNALIGNED(26, 424+0x1A0)748SAVE_VECTOR_UNALIGNED(27, 424+0x1B0)749SAVE_VECTOR_UNALIGNED(28, 424+0x1C0)750SAVE_VECTOR_UNALIGNED(29, 424+0x1D0)751SAVE_VECTOR_UNALIGNED(30, 424+0x1E0)752SAVE_VECTOR_UNALIGNED(31, 424+0x1F0)753#endif754755li 3, 0 // return UNW_ESUCCESS756blr757758759#elif defined(__aarch64__)760761//762// extern int __unw_getcontext(unw_context_t* thread_state)763//764// On entry:765// thread_state pointer is in x0766//767.p2align 2768DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)769stp x0, x1, [x0, #0x000]770stp x2, x3, [x0, #0x010]771stp x4, x5, [x0, #0x020]772stp x6, x7, [x0, #0x030]773stp x8, x9, [x0, #0x040]774stp x10,x11, [x0, #0x050]775stp x12,x13, [x0, #0x060]776stp x14,x15, [x0, #0x070]777stp x16,x17, [x0, #0x080]778stp x18,x19, [x0, #0x090]779stp x20,x21, [x0, #0x0A0]780stp x22,x23, [x0, #0x0B0]781stp x24,x25, [x0, #0x0C0]782stp x26,x27, [x0, #0x0D0]783stp x28,x29, [x0, #0x0E0]784str x30, [x0, #0x0F0]785mov x1,sp786str x1, [x0, #0x0F8]787str x30, [x0, #0x100] // store return address as pc788// skip cpsr789#if defined(__ARM_FP) && __ARM_FP != 0790stp d0, d1, [x0, #0x110]791stp d2, d3, [x0, #0x120]792stp d4, d5, [x0, #0x130]793stp d6, d7, [x0, #0x140]794stp d8, d9, [x0, #0x150]795stp d10,d11, [x0, #0x160]796stp d12,d13, [x0, #0x170]797stp d14,d15, [x0, #0x180]798stp d16,d17, [x0, #0x190]799stp d18,d19, [x0, #0x1A0]800stp d20,d21, [x0, #0x1B0]801stp d22,d23, [x0, #0x1C0]802stp d24,d25, [x0, #0x1D0]803stp d26,d27, [x0, #0x1E0]804stp d28,d29, [x0, #0x1F0]805str d30, [x0, #0x200]806str d31, [x0, #0x208]807#endif808mov x0, #0 // return UNW_ESUCCESS809ret810811#elif defined(__arm__) && !defined(__APPLE__)812813#if !defined(__ARM_ARCH_ISA_ARM)814#if (__ARM_ARCH_ISA_THUMB == 2)815.syntax unified816#endif817.thumb818#endif819820@821@ extern int __unw_getcontext(unw_context_t* thread_state)822@823@ On entry:824@ thread_state pointer is in r0825@826@ Per EHABI #4.7 this only saves the core integer registers.827@ EHABI #7.4.5 notes that in general all VRS registers should be restored828@ however this is very hard to do for VFP registers because it is unknown829@ to the library how many registers are implemented by the architecture.830@ Instead, VFP registers are demand saved by logic external to __unw_getcontext.831@832.p2align 2833DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)834#if !defined(__ARM_ARCH_ISA_ARM) && __ARM_ARCH_ISA_THUMB == 1835stm r0!, {r0-r7}836mov r1, r8837mov r2, r9838mov r3, r10839stm r0!, {r1-r3}840mov r1, r11841mov r2, sp842mov r3, lr843str r1, [r0, #0] @ r11844@ r12 does not need storing, it it the intra-procedure-call scratch register845str r2, [r0, #8] @ sp846str r3, [r0, #12] @ lr847str r3, [r0, #16] @ store return address as pc848@ T1 does not have a non-cpsr-clobbering register-zeroing instruction.849@ It is safe to use here though because we are about to return, and cpsr is850@ not expected to be preserved.851movs r0, #0 @ return UNW_ESUCCESS852#else853@ 32bit thumb-2 restrictions for stm:854@ . the sp (r13) cannot be in the list855@ . the pc (r15) cannot be in the list in an STM instruction856stm r0, {r0-r12}857str sp, [r0, #52]858str lr, [r0, #56]859str lr, [r0, #60] @ store return address as pc860mov r0, #0 @ return UNW_ESUCCESS861#endif862JMP(lr)863864@865@ static void libunwind::Registers_arm::saveVFPWithFSTMD(unw_fpreg_t* values)866@867@ On entry:868@ values pointer is in r0869@870.p2align 2871#if defined(__ELF__)872.fpu vfpv3-d16873#endif874DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMDEPv)875vstmia r0, {d0-d15}876JMP(lr)877878@879@ static void libunwind::Registers_arm::saveVFPWithFSTMX(unw_fpreg_t* values)880@881@ On entry:882@ values pointer is in r0883@884.p2align 2885#if defined(__ELF__)886.fpu vfpv3-d16887#endif888DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveVFPWithFSTMXEPv)889vstmia r0, {d0-d15} @ fstmiax is deprecated in ARMv7+ and now behaves like vstmia890JMP(lr)891892@893@ static void libunwind::Registers_arm::saveVFPv3(unw_fpreg_t* values)894@895@ On entry:896@ values pointer is in r0897@898.p2align 2899#if defined(__ELF__)900.fpu vfpv3901#endif902DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveVFPv3EPv)903@ VFP and iwMMX instructions are only available when compiling with the flags904@ that enable them. We do not want to do that in the library (because we do not905@ want the compiler to generate instructions that access those) but this is906@ only accessed if the personality routine needs these registers. Use of907@ these registers implies they are, actually, available on the target, so908@ it's ok to execute.909@ So, generate the instructions using the corresponding coprocessor mnemonic.910vstmia r0, {d16-d31}911JMP(lr)912913#if defined(_LIBUNWIND_ARM_WMMX)914915@916@ static void libunwind::Registers_arm::saveiWMMX(unw_fpreg_t* values)917@918@ On entry:919@ values pointer is in r0920@921.p2align 2922#if defined(__ELF__)923.arch armv5te924#endif925DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm9saveiWMMXEPv)926stcl p1, cr0, [r0], #8 @ wstrd wR0, [r0], #8927stcl p1, cr1, [r0], #8 @ wstrd wR1, [r0], #8928stcl p1, cr2, [r0], #8 @ wstrd wR2, [r0], #8929stcl p1, cr3, [r0], #8 @ wstrd wR3, [r0], #8930stcl p1, cr4, [r0], #8 @ wstrd wR4, [r0], #8931stcl p1, cr5, [r0], #8 @ wstrd wR5, [r0], #8932stcl p1, cr6, [r0], #8 @ wstrd wR6, [r0], #8933stcl p1, cr7, [r0], #8 @ wstrd wR7, [r0], #8934stcl p1, cr8, [r0], #8 @ wstrd wR8, [r0], #8935stcl p1, cr9, [r0], #8 @ wstrd wR9, [r0], #8936stcl p1, cr10, [r0], #8 @ wstrd wR10, [r0], #8937stcl p1, cr11, [r0], #8 @ wstrd wR11, [r0], #8938stcl p1, cr12, [r0], #8 @ wstrd wR12, [r0], #8939stcl p1, cr13, [r0], #8 @ wstrd wR13, [r0], #8940stcl p1, cr14, [r0], #8 @ wstrd wR14, [r0], #8941stcl p1, cr15, [r0], #8 @ wstrd wR15, [r0], #8942JMP(lr)943944@945@ static void libunwind::Registers_arm::saveiWMMXControl(unw_uint32_t* values)946@947@ On entry:948@ values pointer is in r0949@950.p2align 2951#if defined(__ELF__)952.arch armv5te953#endif954DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControlEPj)955stc2 p1, cr8, [r0], #4 @ wstrw wCGR0, [r0], #4956stc2 p1, cr9, [r0], #4 @ wstrw wCGR1, [r0], #4957stc2 p1, cr10, [r0], #4 @ wstrw wCGR2, [r0], #4958stc2 p1, cr11, [r0], #4 @ wstrw wCGR3, [r0], #4959JMP(lr)960961#endif962963#elif defined(__or1k__)964965#966# extern int __unw_getcontext(unw_context_t* thread_state)967#968# On entry:969# thread_state pointer is in r3970#971DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)972l.sw 0(r3), r0973l.sw 4(r3), r1974l.sw 8(r3), r2975l.sw 12(r3), r3976l.sw 16(r3), r4977l.sw 20(r3), r5978l.sw 24(r3), r6979l.sw 28(r3), r7980l.sw 32(r3), r8981l.sw 36(r3), r9982l.sw 40(r3), r10983l.sw 44(r3), r11984l.sw 48(r3), r12985l.sw 52(r3), r13986l.sw 56(r3), r14987l.sw 60(r3), r15988l.sw 64(r3), r16989l.sw 68(r3), r17990l.sw 72(r3), r18991l.sw 76(r3), r19992l.sw 80(r3), r20993l.sw 84(r3), r21994l.sw 88(r3), r22995l.sw 92(r3), r23996l.sw 96(r3), r24997l.sw 100(r3), r25998l.sw 104(r3), r26999l.sw 108(r3), r271000l.sw 112(r3), r281001l.sw 116(r3), r291002l.sw 120(r3), r301003l.sw 124(r3), r311004# store ra to pc1005l.sw 128(r3), r91006# zero epcr1007l.sw 132(r3), r010081009#elif defined(__hexagon__)1010#1011# extern int unw_getcontext(unw_context_t* thread_state)1012#1013# On entry:1014# thread_state pointer is in r01015#1016#define OFFSET(offset) (offset/4)1017DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)1018memw(r0+#32) = r81019memw(r0+#36) = r91020memw(r0+#40) = r101021memw(r0+#44) = r1110221023memw(r0+#48) = r121024memw(r0+#52) = r131025memw(r0+#56) = r141026memw(r0+#60) = r1510271028memw(r0+#64) = r161029memw(r0+#68) = r171030memw(r0+#72) = r181031memw(r0+#76) = r1910321033memw(r0+#80) = r201034memw(r0+#84) = r211035memw(r0+#88) = r221036memw(r0+#92) = r2310371038memw(r0+#96) = r241039memw(r0+#100) = r251040memw(r0+#104) = r261041memw(r0+#108) = r2710421043memw(r0+#112) = r281044memw(r0+#116) = r291045memw(r0+#120) = r301046memw(r0+#124) = r311047r1 = c4 // Predicate register1048memw(r0+#128) = r11049r1 = memw(r30) // *FP == Saved FP1050r1 = r311051memw(r0+#132) = r110521053jumpr r3110541055#elif defined(__sparc__) && defined(__arch64__)10561057#1058# extern int __unw_getcontext(unw_context_t* thread_state)1059#1060# On entry:1061# thread_state pointer is in %o01062#1063DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)1064.register %g2, #scratch1065.register %g3, #scratch1066.register %g6, #scratch1067.register %g7, #scratch1068stx %g1, [%o0 + 0x08]1069stx %g2, [%o0 + 0x10]1070stx %g3, [%o0 + 0x18]1071stx %g4, [%o0 + 0x20]1072stx %g5, [%o0 + 0x28]1073stx %g6, [%o0 + 0x30]1074stx %g7, [%o0 + 0x38]1075stx %o0, [%o0 + 0x40]1076stx %o1, [%o0 + 0x48]1077stx %o2, [%o0 + 0x50]1078stx %o3, [%o0 + 0x58]1079stx %o4, [%o0 + 0x60]1080stx %o5, [%o0 + 0x68]1081stx %o6, [%o0 + 0x70]1082stx %o7, [%o0 + 0x78]1083stx %l0, [%o0 + 0x80]1084stx %l1, [%o0 + 0x88]1085stx %l2, [%o0 + 0x90]1086stx %l3, [%o0 + 0x98]1087stx %l4, [%o0 + 0xa0]1088stx %l5, [%o0 + 0xa8]1089stx %l6, [%o0 + 0xb0]1090stx %l7, [%o0 + 0xb8]1091stx %i0, [%o0 + 0xc0]1092stx %i1, [%o0 + 0xc8]1093stx %i2, [%o0 + 0xd0]1094stx %i3, [%o0 + 0xd8]1095stx %i4, [%o0 + 0xe0]1096stx %i5, [%o0 + 0xe8]1097stx %i6, [%o0 + 0xf0]1098stx %i7, [%o0 + 0xf8]10991100# save StackGhost cookie1101mov %i7, %g41102save %sp, -176, %sp1103# register window flush necessary even without StackGhost1104flushw1105restore1106ldx [%sp + 2047 + 0x78], %g51107xor %g4, %g5, %g41108stx %g4, [%o0 + 0x100]1109retl1110# return UNW_ESUCCESS1111clr %o011121113#elif defined(__sparc__)11141115#1116# extern int __unw_getcontext(unw_context_t* thread_state)1117#1118# On entry:1119# thread_state pointer is in o01120#1121DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)1122ta 31123add %o7, 8, %o71124std %g0, [%o0 + 0]1125std %g2, [%o0 + 8]1126std %g4, [%o0 + 16]1127std %g6, [%o0 + 24]1128std %o0, [%o0 + 32]1129std %o2, [%o0 + 40]1130std %o4, [%o0 + 48]1131std %o6, [%o0 + 56]1132std %l0, [%o0 + 64]1133std %l2, [%o0 + 72]1134std %l4, [%o0 + 80]1135std %l6, [%o0 + 88]1136std %i0, [%o0 + 96]1137std %i2, [%o0 + 104]1138std %i4, [%o0 + 112]1139std %i6, [%o0 + 120]1140jmp %o71141clr %o0 // return UNW_ESUCCESS11421143#elif defined(__riscv)11441145#1146# extern int __unw_getcontext(unw_context_t* thread_state)1147#1148# On entry:1149# thread_state pointer is in a01150#1151DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)1152ISTORE x1, (RISCV_ISIZE * 0)(a0) // store ra as pc1153#if defined(__riscv_32e)1154.irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,151155#else1156.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,311157#endif1158ISTORE x\i, (RISCV_ISIZE * \i)(a0)1159.endr11601161# if defined(__riscv_flen)1162.irp i,FROM_0_TO_311163FSTORE f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0)1164.endr1165# endif11661167li a0, 0 // return UNW_ESUCCESS1168ret // jump to ra11691170#elif defined(__s390x__)11711172//1173// extern int __unw_getcontext(unw_context_t* thread_state)1174//1175// On entry:1176// thread_state pointer is in r21177//1178DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)11791180// Save GPRs1181stmg %r0, %r15, 16(%r2)11821183// Save PSWM1184epsw %r0, %r11185stm %r0, %r1, 0(%r2)11861187// Store return address as PSWA1188stg %r14, 8(%r2)11891190// Save FPRs1191.irp i,FROM_0_TO_151192std %f\i, (144+8*\i)(%r2)1193.endr11941195// Return UNW_ESUCCESS1196lghi %r2, 01197br %r1411981199#elif defined(__loongarch__) && __loongarch_grlen == 6412001201#1202# extern int __unw_getcontext(unw_context_t* thread_state)1203#1204# On entry:1205# thread_state pointer is in $a0($r4)1206#1207DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)1208.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,311209st.d $r\i, $a0, (8*\i)1210.endr1211st.d $r1, $a0, (8 * 32) // store $ra to pc12121213# if __loongarch_frlen == 641214.irp i,FROM_0_TO_311215fst.d $f\i, $a0, (8 * 33 + 8 * \i)1216.endr1217# endif12181219move $a0, $zero // UNW_ESUCCESS1220jr $ra12211222#endif12231224#ifdef __arm64ec__1225.globl "#unw_getcontext"1226.set "#unw_getcontext", "#__unw_getcontext"1227.weak_anti_dep unw_getcontext1228.set unw_getcontext, "#unw_getcontext"1229EXPORT_SYMBOL(unw_getcontext)1230#else1231WEAK_ALIAS(__unw_getcontext, unw_getcontext)1232#endif12331234#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */12351236NO_EXEC_STACK_DIRECTIVE123712381239