From b029fb598aff7d169ad9d60ec6eafa774faef921 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Mon, 12 May 2014 15:17:14 +0200 Subject: [PATCH] new libunwind, updated to netbsd b1f513eedd existing libunwind used '0' in lsda_encoding as 'not present,' whereas that is a valid encoding and does occur and would be ignored. a missing encoding is actually 0xff. The commit that addresses this is: commit 8d4b51028d1a12b58d616f4b605254a877caafcf Author: joerg Date: Tue Mar 11 23:52:17 2014 +0000 0 is a valid LSDA encoding and can be seen in statically linked programs. Initialize lsdaEncoding to DW_EH_PE_omit and check for that value to decide whether a value should be decoded. more bugfixes are necessary. this update is up to: commit b1f513eedd332426d88acbb118b6e9070966dcb9 Author: joerg Date: Wed May 14 22:13:36 2014 +0000 Lazy VFP processing works a lot better if the functions contain a return instruction. --- sys/lib/libunwind/AddressSpace.hpp | 47 +- sys/lib/libunwind/DwarfInstructions.hpp | 13 +- sys/lib/libunwind/DwarfParser.hpp | 23 +- sys/lib/libunwind/Makefile.inc | 15 +- sys/lib/libunwind/Registers.hpp | 777 ++++++++++++++++- sys/lib/libunwind/UnwindCursor.hpp | 4 +- sys/lib/libunwind/libunwind.cxx | 35 +- sys/lib/libunwind/unwind.h | 1 + sys/lib/libunwind/unwind_registers.S | 1014 ++++++++++++++++++++++- 9 files changed, 1838 insertions(+), 91 deletions(-) diff --git a/sys/lib/libunwind/AddressSpace.hpp b/sys/lib/libunwind/AddressSpace.hpp index 31b56191b..c655d2dc8 100644 --- a/sys/lib/libunwind/AddressSpace.hpp +++ b/sys/lib/libunwind/AddressSpace.hpp @@ -48,7 +48,6 @@ struct unw_proc_info_t { uintptr_t lsda; // Address of Language Specific Data Area uintptr_t handler; // Personality routine uintptr_t extra_args; // Extra stack space for frameless routines - uint32_t unwind_info_size; // Size of DWARF unwind info uintptr_t unwind_info; // Address of DWARF unwind info }; @@ -76,13 +75,29 @@ public: pthread_rwlock_init(&fdeTreeLock, NULL); } - uint8_t get8(pint_t addr) { return *((uint8_t *)addr); } + uint8_t get8(pint_t addr) { + uint8_t val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } - uint16_t get16(pint_t addr) { return *((uint16_t *)addr); } + uint16_t get16(pint_t addr) { + uint16_t val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } - uint32_t get32(pint_t addr) { return *((uint32_t *)addr); } + uint32_t get32(pint_t addr) { + uint32_t val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } - uint64_t get64(pint_t addr) { return *((uint64_t *)addr); } + uint64_t get64(pint_t addr) { + uint64_t val; + memcpy(&val, (void *)addr, sizeof(val)); + return val; + } uintptr_t getP(pint_t addr) { if (sizeof(uintptr_t) == sizeof(uint32_t)) @@ -249,6 +264,7 @@ public: return false; if (n->hdr_start == 0) { fdeStart = n->hdr_base; + data_base = n->data_base; return true; } @@ -271,6 +287,7 @@ public: len = (len + 1) / 2; } fdeStart = base + (int32_t)get32(first + 4); + data_base = n->data_base; return true; } @@ -336,9 +353,9 @@ public: private: findPCRange_t findPCRange; bool needsReload; -#if !defined(__minix) +#ifndef __minix pthread_rwlock_t fdeTreeLock; -#endif /* !defined(__minix) */ +#endif rb_tree_t segmentTree; rb_tree_t dsoTree; @@ -433,8 +450,8 @@ static int phdr_callback(struct dl_phdr_info *info, size_t size, void *data_) { } static int rangeCmp(void *context, const void *n1_, const void *n2_) { - LocalAddressSpace::Range *n1 = (LocalAddressSpace::Range *)n1_; - LocalAddressSpace::Range *n2 = (LocalAddressSpace::Range *)n2_; + const LocalAddressSpace::Range *n1 = (const LocalAddressSpace::Range *)n1_; + const LocalAddressSpace::Range *n2 = (const LocalAddressSpace::Range *)n2_; if (n1->first_pc < n2->first_pc) return -1; @@ -445,8 +462,8 @@ static int rangeCmp(void *context, const void *n1_, const void *n2_) { } static int rangeCmpKey(void *context, const void *n_, const void *pc_) { - LocalAddressSpace::Range *n = (LocalAddressSpace::Range *)n_; - LocalAddressSpace::pint_t *pc = (LocalAddressSpace::pint_t *)pc_; + const LocalAddressSpace::Range *n = (const LocalAddressSpace::Range *)n_; + const LocalAddressSpace::pint_t *pc = (const LocalAddressSpace::pint_t *)pc_; if (n->last_pc < *pc) return -1; if (n->first_pc > *pc) @@ -455,8 +472,8 @@ static int rangeCmpKey(void *context, const void *n_, const void *pc_) { } static int dsoTableCmp(void *context, const void *n1_, const void *n2_) { - LocalAddressSpace::Range *n1 = (LocalAddressSpace::Range *)n1_; - LocalAddressSpace::Range *n2 = (LocalAddressSpace::Range *)n2_; + const LocalAddressSpace::Range *n1 = (const LocalAddressSpace::Range *)n1_; + const LocalAddressSpace::Range *n2 = (const LocalAddressSpace::Range *)n2_; if (n1->ehframe_base < n2->ehframe_base) return -1; @@ -466,8 +483,8 @@ static int dsoTableCmp(void *context, const void *n1_, const void *n2_) { } static int dsoTableCmpKey(void *context, const void *n_, const void *ptr_) { - LocalAddressSpace::Range *n = (LocalAddressSpace::Range *)n_; - LocalAddressSpace::pint_t *ptr = (LocalAddressSpace::pint_t *)ptr_; + const LocalAddressSpace::Range *n = (const LocalAddressSpace::Range *)n_; + const LocalAddressSpace::pint_t *ptr = (const LocalAddressSpace::pint_t *)ptr_; if (n->ehframe_base < *ptr) return -1; if (n->ehframe_base > *ptr) diff --git a/sys/lib/libunwind/DwarfInstructions.hpp b/sys/lib/libunwind/DwarfInstructions.hpp index 37c0a3c13..56fe8466e 100644 --- a/sys/lib/libunwind/DwarfInstructions.hpp +++ b/sys/lib/libunwind/DwarfInstructions.hpp @@ -39,12 +39,6 @@ public: static step_result stepWithDwarf(A &, pint_t, pint_t, R &, unw_proc_info_t *); private: - // Pseudo-register used for return addresses. - enum { - DW_X86_RET_ADDR = 8, - DW_X86_64_RET_ADDR = 16, - }; - static pint_t evaluateExpression(pint_t, A &, const R &, pint_t); static pint_t getSavedRegister(A &, const R &, pint_t, @@ -54,9 +48,6 @@ private: const typename CFI_Parser::RegisterLocation &); static int lastRestoreReg(const R &) { return R::LAST_RESTORE_REG; } - static bool isReturnAddressRegister(int regno, const R &) { - return regno == R::IP_PSEUDO_REG; - } static pint_t getCFA(A &addressSpace, const typename CFI_Parser::PrologInfo &prolog, @@ -145,7 +136,7 @@ step_result DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) { if (prolog.savedRegisters[i].location == CFI_Parser::kRegisterUnused) continue; - if (isReturnAddressRegister(i, registers)) + if (i == (int)cieInfo.returnAddressRegister) returnAddress = getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]); else if (registers.validRegister(i)) @@ -162,7 +153,7 @@ step_result DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // The CFA is defined as the stack pointer at the call site. // Therefore the SP is restored by setting it to the CFA. newRegisters.setSP(cfa); - newRegisters.setIP(returnAddress); + newRegisters.setIP(returnAddress + R::RETURN_OFFSET); // Now replace register set with the working copy. registers = newRegisters; diff --git a/sys/lib/libunwind/DwarfParser.hpp b/sys/lib/libunwind/DwarfParser.hpp index 671502022..6e8ef2cab 100644 --- a/sys/lib/libunwind/DwarfParser.hpp +++ b/sys/lib/libunwind/DwarfParser.hpp @@ -43,6 +43,7 @@ public: uint8_t personalityOffsetInCIE; bool isSignalFrame; bool fdesHaveAugmentationData; + uint8_t returnAddressRegister; }; /// Information about an FDE (Frame Description Entry) @@ -172,7 +173,7 @@ bool CFI_Parser::decodeFDE(A &addressSpace, pint_t fdeStart, if (cieInfo->fdesHaveAugmentationData) { uintptr_t augLen = addressSpace.getULEB128(p, nextCFI); pint_t endOfAug = p + augLen; - if (cieInfo->lsdaEncoding != 0) { + if (cieInfo->lsdaEncoding != DW_EH_PE_omit) { // Peek at value (without indirection). Zero means no LSDA. pint_t lsdaStart = p; if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F, @@ -198,7 +199,7 @@ template bool CFI_Parser::parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo) { cieInfo->pointerEncoding = 0; - cieInfo->lsdaEncoding = 0; + cieInfo->lsdaEncoding = DW_EH_PE_omit; cieInfo->personalityEncoding = 0; cieInfo->personalityOffsetInCIE = 0; cieInfo->personality = 0; @@ -238,7 +239,7 @@ bool CFI_Parser::parseCIE(A &addressSpace, pint_t cie, // Parse data alignment factor cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd); // Parse return address register - addressSpace.getULEB128(p, cieContentEnd); + cieInfo->returnAddressRegister = (uint8_t)addressSpace.getULEB128(p, cieContentEnd); // Parse augmentation data based on augmentation string. if (addressSpace.get8(strStart) == 'z') { // parse augmentation data length @@ -460,6 +461,8 @@ CFI_Parser::parseInstructions(A &addressSpace, pint_t instructions, reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd)); offset = addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; + if (reg > kMaxRegisterNumber) + return false; results->savedRegisters[reg].location = kRegisterOffsetFromCFA; results->savedRegisters[reg].value = offset; break; @@ -481,6 +484,20 @@ CFI_Parser::parseInstructions(A &addressSpace, pint_t instructions, length = addressSpace.getULEB128(p, instructionsEnd); p += length; break; + case DW_CFA_GNU_window_save: +#if defined(__sparc__) + for (reg = 8; reg < 16; ++reg) { + results->savedRegisters[reg].location = kRegisterInRegister; + results->savedRegisters[reg].value = reg + 16; + } + for (reg = 16; reg < 32; ++reg) { + results->savedRegisters[reg].location = kRegisterInCFA; + results->savedRegisters[reg].value = (reg - 16) * sizeof(typename R::reg_t); + } + break; +#else + return false; +#endif case DW_CFA_GNU_args_size: offset = addressSpace.getULEB128(p, instructionsEnd); results->spExtraArgSize = offset; diff --git a/sys/lib/libunwind/Makefile.inc b/sys/lib/libunwind/Makefile.inc index 4a5940786..1195ef6a9 100644 --- a/sys/lib/libunwind/Makefile.inc +++ b/sys/lib/libunwind/Makefile.inc @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.1 2013/10/14 01:14:57 joerg Exp $ +# $NetBSD: Makefile.inc,v 1.5 2014/03/19 16:46:23 joerg Exp $ .PATH: ${NETBSDSRCDIR}/sys/lib/libunwind @@ -7,4 +7,15 @@ SRCS+= libunwind.cxx \ INCS+= unwind.h -COPTS.libuwind.cxx+= -funwind-tables -fno-rtti -fno-exceptions -fvisibility=hidden -Wno-old-style-cast +.if ${HAVE_GCC:U48} == "4" +CLEANFILES+= cstdint +DPSRCS+= cstdint + +cstdint: + echo '#include ' > ${.TARGET} + +COPTS.libunwind.cxx+= "-D__builtin_unreachable()=abort()" +.else +COPTS.libunwind.cxx+= ${${ACTIVE_CXX} == "gcc":? -std=c++0x : -std=c++11 } +.endif +COPTS.libunwind.cxx+= -funwind-tables -fno-rtti -fno-exceptions -fvisibility=hidden -Wno-old-style-cast diff --git a/sys/lib/libunwind/Registers.hpp b/sys/lib/libunwind/Registers.hpp index dc18d076b..0467525ed 100644 --- a/sys/lib/libunwind/Registers.hpp +++ b/sys/lib/libunwind/Registers.hpp @@ -32,9 +32,9 @@ enum { class Registers_x86 { public: enum { - LAST_RESTORE_REG = REGNO_X86_EIP, - IP_PSEUDO_REG = REGNO_X86_EIP, LAST_REGISTER = REGNO_X86_EIP, + LAST_RESTORE_REG = REGNO_X86_EIP, + RETURN_OFFSET = 0, }; __dso_hidden Registers_x86(); @@ -97,9 +97,9 @@ enum { class Registers_x86_64 { public: enum { - LAST_RESTORE_REG = REGNO_X86_64_RIP, - IP_PSEUDO_REG = REGNO_X86_64_RIP, LAST_REGISTER = REGNO_X86_64_RIP, + LAST_RESTORE_REG = REGNO_X86_64_RIP, + RETURN_OFFSET = 0, }; __dso_hidden Registers_x86_64(); @@ -144,19 +144,18 @@ enum { DWARF_PPC32_R31 = 31, DWARF_PPC32_F0 = 32, DWARF_PPC32_F31 = 63, - DWARF_PPC32_V0 = 1124, - DWARF_PPC32_V31 = 1155, DWARF_PPC32_LR = 65, - DWARF_PPC32_CTR = 66, - DWARF_PPC32_XER = 76, + DWARF_PPC32_CR = 70, + DWARF_PPC32_V0 = 77, + DWARF_PPC32_V31 = 108, + REGNO_PPC32_R0 = 0, - REGNO_PPC32_R1 = 0, + REGNO_PPC32_R1 = 1, REGNO_PPC32_R31 = 31, - REGNO_PPC32_CR = 32, - REGNO_PPC32_LR = 33, - REGNO_PPC32_CTR = 34, - REGNO_PPC32_XER = 35, - REGNO_PPC32_SRR0 = 36, + REGNO_PPC32_LR = 32, + REGNO_PPC32_CR = 33, + REGNO_PPC32_SRR0 = 34, + REGNO_PPC32_F0 = REGNO_PPC32_SRR0 + 1, REGNO_PPC32_F31 = REGNO_PPC32_F0 + 31, REGNO_PPC32_V0 = REGNO_PPC32_F31 + 1, @@ -166,9 +165,9 @@ enum { class Registers_ppc32 { public: enum { - LAST_RESTORE_REG = REGNO_PPC32_V31, - IP_PSEUDO_REG = REGNO_PPC32_SRR0, LAST_REGISTER = REGNO_PPC32_V31, + LAST_RESTORE_REG = REGNO_PPC32_V31, + RETURN_OFFSET = 0, }; __dso_hidden Registers_ppc32(); @@ -180,7 +179,14 @@ public: return REGNO_PPC32_F0 + (num - DWARF_PPC32_F0); if (num >= DWARF_PPC32_V0 && num <= DWARF_PPC32_V31) return REGNO_PPC32_V0 + (num - DWARF_PPC32_V0); - return LAST_REGISTER + 1; + switch (num) { + case DWARF_PPC32_LR: + return REGNO_PPC32_LR; + case DWARF_PPC32_CR: + return REGNO_PPC32_CR; + default: + return LAST_REGISTER + 1; + } } bool validRegister(int num) const { @@ -225,10 +231,747 @@ private: uint64_t low, high; }; uint32_t reg[REGNO_PPC32_SRR0 + 1]; + uint32_t dummy; uint64_t fpreg[32]; vecreg_t vecreg[64]; }; +enum { + DWARF_ARM32_R0 = 0, + DWARF_ARM32_R15 = 15, + DWARF_ARM32_SPSR = 128, + DWARF_ARM32_OLD_S0 = 64, + DWARF_ARM32_OLD_S31 = 91, + DWARF_ARM32_D0 = 256, + DWARF_ARM32_D31 = 287, + REGNO_ARM32_R0 = 0, + REGNO_ARM32_SP = 13, + REGNO_ARM32_R15 = 15, + REGNO_ARM32_SPSR = 16, + REGNO_ARM32_D0 = 17, + REGNO_ARM32_D15 = 32, + REGNO_ARM32_D31 = 48, +}; + +class Registers_arm32 { +public: + enum { + LAST_REGISTER = REGNO_ARM32_D31, + LAST_RESTORE_REG = REGNO_ARM32_D31, + RETURN_OFFSET = 0, + }; + + __dso_hidden Registers_arm32(); + + static int dwarf2regno(int num) { + if (num >= DWARF_ARM32_R0 && num <= DWARF_ARM32_R15) + return REGNO_ARM32_R0 + (num - DWARF_ARM32_R0); + if (num == DWARF_ARM32_SPSR) + return REGNO_ARM32_SPSR; + if (num >= DWARF_ARM32_D0 && num <= DWARF_ARM32_D31) + return REGNO_ARM32_D0 + (num - DWARF_ARM32_D0); + if (num >= DWARF_ARM32_OLD_S0 && num <= DWARF_ARM32_OLD_S31) { + assert(num % 2 == 0); + return REGNO_ARM32_D0 + (num - DWARF_ARM32_OLD_S0) / 2; + } + return LAST_REGISTER + 1; + } + + bool validRegister(int num) const { + return num >= 0 && num <= REGNO_ARM32_SPSR; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_ARM32_R15]; } + + void setIP(uint64_t value) { reg[REGNO_ARM32_R15] = value; } + + uint64_t getSP() const { return reg[REGNO_ARM32_SP]; } + + void setSP(uint64_t value) { reg[REGNO_ARM32_SP] = value; } + + bool validFloatVectorRegister(int num) const { + return (num >= REGNO_ARM32_D0 && num <= REGNO_ARM32_D31); + } + + void copyFloatVectorRegister(int num, uint64_t addr_) { + if (num <= REGNO_ARM32_D15) { + if ((flags & 1) == 0) { + lazyVFP1(); + flags |= 1; + } + } else { + if ((flags & 2) == 0) { + lazyVFP3(); + flags |= 2; + } + } + const void *addr = reinterpret_cast(addr_); + memcpy(fpreg + (num - REGNO_ARM32_D0), addr, sizeof(fpreg[0])); + } + + __dso_hidden void lazyVFP1(); + __dso_hidden void lazyVFP3(); + __dso_hidden void jumpto() const __dead; + +private: + uint32_t reg[REGNO_ARM32_SPSR + 1]; + uint32_t flags; + uint64_t fpreg[32]; +}; + +enum { + DWARF_VAX_R0 = 0, + DWARF_VAX_R15 = 15, + DWARF_VAX_PSW = 16, + + REGNO_VAX_R0 = 0, + REGNO_VAX_R14 = 14, + REGNO_VAX_R15 = 15, + REGNO_VAX_PSW = 16, +}; + +class Registers_vax { +public: + enum { + LAST_REGISTER = REGNO_VAX_PSW, + LAST_RESTORE_REG = REGNO_VAX_PSW, + RETURN_OFFSET = 0, + }; + + __dso_hidden Registers_vax(); + + static int dwarf2regno(int num) { + if (num >= DWARF_VAX_R0 && num <= DWARF_VAX_R15) + return REGNO_VAX_R0 + (num - DWARF_VAX_R0); + if (num == DWARF_VAX_PSW) + return REGNO_VAX_PSW; + return LAST_REGISTER + 1; + } + + bool validRegister(int num) const { + return num >= 0 && num <= LAST_RESTORE_REG; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_VAX_R15]; } + + void setIP(uint64_t value) { reg[REGNO_VAX_R15] = value; } + + uint64_t getSP() const { return reg[REGNO_VAX_R14]; } + + void setSP(uint64_t value) { reg[REGNO_VAX_R14] = value; } + + bool validFloatVectorRegister(int num) const { + return false; + } + + void copyFloatVectorRegister(int num, uint64_t addr_) { + } + + __dso_hidden void jumpto() const __dead; + +private: + uint32_t reg[REGNO_VAX_PSW + 1]; +}; + +enum { + DWARF_M68K_A0 = 0, + DWARF_M68K_A7 = 7, + DWARF_M68K_D0 = 8, + DWARF_M68K_D7 = 15, + DWARF_M68K_FP0 = 16, + DWARF_M68K_FP7 = 23, + DWARF_M68K_PC = 24, + + REGNO_M68K_A0 = 0, + REGNO_M68K_A7 = 7, + REGNO_M68K_D0 = 8, + REGNO_M68K_D7 = 15, + REGNO_M68K_PC = 16, + REGNO_M68K_FP0 = 17, + REGNO_M68K_FP7 = 24, +}; + +class Registers_M68K { +public: + enum { + LAST_REGISTER = REGNO_M68K_FP7, + LAST_RESTORE_REG = REGNO_M68K_FP7, + RETURN_OFFSET = 0, + }; + + __dso_hidden Registers_M68K(); + + static int dwarf2regno(int num) { + if (num >= DWARF_M68K_A0 && num <= DWARF_M68K_A7) + return REGNO_M68K_A0 + (num - DWARF_M68K_A0); + if (num >= DWARF_M68K_D0 && num <= DWARF_M68K_D7) + return REGNO_M68K_D0 + (num - DWARF_M68K_D0); + if (num >= DWARF_M68K_FP0 && num <= DWARF_M68K_FP7) + return REGNO_M68K_FP0 + (num - DWARF_M68K_FP0); + if (num == DWARF_M68K_PC) + return REGNO_M68K_PC; + return LAST_REGISTER + 1; + } + + bool validRegister(int num) const { + return num >= 0 && num <= REGNO_M68K_PC; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_M68K_PC]; } + + void setIP(uint64_t value) { reg[REGNO_M68K_PC] = value; } + + uint64_t getSP() const { return reg[REGNO_M68K_A7]; } + + void setSP(uint64_t value) { reg[REGNO_M68K_A7] = value; } + + bool validFloatVectorRegister(int num) const { + return num >= REGNO_M68K_FP0 && num <= REGNO_M68K_FP7; + } + + void copyFloatVectorRegister(int num, uint64_t addr_) { + assert(validFloatVectorRegister(num)); + const void *addr = reinterpret_cast(addr_); + memcpy(fpreg + (num - REGNO_M68K_FP0), addr, sizeof(fpreg[0])); + } + + __dso_hidden void jumpto() const __dead; + +private: + typedef uint32_t fpreg_t[3]; + + uint32_t reg[REGNO_M68K_PC + 1]; + uint32_t dummy; + fpreg_t fpreg[8]; +}; + +enum { + DWARF_SH3_R0 = 0, + DWARF_SH3_R15 = 15, + DWARF_SH3_PC = 16, + DWARF_SH3_PR = 17, + + REGNO_SH3_R0 = 0, + REGNO_SH3_R15 = 15, + REGNO_SH3_PC = 16, + REGNO_SH3_PR = 17, +}; + +class Registers_SH3 { +public: + enum { + LAST_REGISTER = REGNO_SH3_PR, + LAST_RESTORE_REG = REGNO_SH3_PR, + RETURN_OFFSET = 0, + }; + + __dso_hidden Registers_SH3(); + + static int dwarf2regno(int num) { + if (num >= DWARF_SH3_R0 && num <= DWARF_SH3_R15) + return REGNO_SH3_R0 + (num - DWARF_SH3_R0); + if (num == DWARF_SH3_PC) + return REGNO_SH3_PC; + if (num == DWARF_SH3_PR) + return REGNO_SH3_PR; + return LAST_REGISTER + 1; + } + + bool validRegister(int num) const { + return num >= 0 && num <= REGNO_SH3_PR; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_SH3_PC]; } + + void setIP(uint64_t value) { reg[REGNO_SH3_PC] = value; } + + uint64_t getSP() const { return reg[REGNO_SH3_R15]; } + + void setSP(uint64_t value) { reg[REGNO_SH3_R15] = value; } + + bool validFloatVectorRegister(int num) const { return false; } + + void copyFloatVectorRegister(int num, uint64_t addr_) {} + + __dso_hidden void jumpto() const __dead; + +private: + uint32_t reg[REGNO_SH3_PR + 1]; +}; + +enum { + DWARF_SPARC64_R0 = 0, + DWARF_SPARC64_R31 = 31, + DWARF_SPARC64_PC = 32, + + REGNO_SPARC64_R0 = 0, + REGNO_SPARC64_R14 = 14, + REGNO_SPARC64_R15 = 15, + REGNO_SPARC64_R31 = 31, + REGNO_SPARC64_PC = 32, +}; + +class Registers_SPARC64 { +public: + enum { + LAST_REGISTER = REGNO_SPARC64_PC, + LAST_RESTORE_REG = REGNO_SPARC64_PC, + RETURN_OFFSET = 8, + }; + typedef uint64_t reg_t; + + __dso_hidden Registers_SPARC64(); + + static int dwarf2regno(int num) { + if (num >= DWARF_SPARC64_R0 && num <= DWARF_SPARC64_R31) + return REGNO_SPARC64_R0 + (num - DWARF_SPARC64_R0); + if (num == DWARF_SPARC64_PC) + return REGNO_SPARC64_PC; + return LAST_REGISTER + 1; + } + + bool validRegister(int num) const { + return num >= 0 && num <= REGNO_SPARC64_PC; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_SPARC64_PC]; } + + void setIP(uint64_t value) { reg[REGNO_SPARC64_PC] = value; } + + uint64_t getSP() const { return reg[REGNO_SPARC64_R14]; } + + void setSP(uint64_t value) { reg[REGNO_SPARC64_R14] = value; } + + bool validFloatVectorRegister(int num) const { return false; } + + void copyFloatVectorRegister(int num, uint64_t addr_) {} + + __dso_hidden void jumpto() const __dead; + +private: + uint64_t reg[REGNO_SPARC64_PC + 1]; +}; + +enum { + DWARF_SPARC_R0 = 0, + DWARF_SPARC_R31 = 31, + DWARF_SPARC_PC = 32, + + REGNO_SPARC_R0 = 0, + REGNO_SPARC_R14 = 14, + REGNO_SPARC_R15 = 15, + REGNO_SPARC_R31 = 31, + REGNO_SPARC_PC = 32, +}; + +class Registers_SPARC { +public: + enum { + LAST_REGISTER = REGNO_SPARC_PC, + LAST_RESTORE_REG = REGNO_SPARC_PC, + RETURN_OFFSET = 8, + }; + typedef uint32_t reg_t; + + __dso_hidden Registers_SPARC(); + + static int dwarf2regno(int num) { + if (num >= DWARF_SPARC_R0 && num <= DWARF_SPARC_R31) + return REGNO_SPARC_R0 + (num - DWARF_SPARC_R0); + if (num == DWARF_SPARC_PC) + return REGNO_SPARC_PC; + return LAST_REGISTER + 1; + } + + bool validRegister(int num) const { + return num >= 0 && num <= REGNO_SPARC_PC; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_SPARC_PC]; } + + void setIP(uint64_t value) { reg[REGNO_SPARC_PC] = value; } + + uint64_t getSP() const { return reg[REGNO_SPARC_R14]; } + + void setSP(uint64_t value) { reg[REGNO_SPARC_R14] = value; } + + bool validFloatVectorRegister(int num) const { return false; } + + void copyFloatVectorRegister(int num, uint64_t addr_) {} + + __dso_hidden void jumpto() const __dead; + +private: + uint32_t reg[REGNO_SPARC_PC + 1]; +}; + +enum { + DWARF_ALPHA_R0 = 0, + DWARF_ALPHA_R30 = 30, + DWARF_ALPHA_F0 = 32, + DWARF_ALPHA_F30 = 62, + + REGNO_ALPHA_R0 = 0, + REGNO_ALPHA_R26 = 26, + REGNO_ALPHA_R30 = 30, + REGNO_ALPHA_PC = 31, + REGNO_ALPHA_F0 = 32, + REGNO_ALPHA_F30 = 62, +}; + +class Registers_Alpha { +public: + enum { + LAST_REGISTER = REGNO_ALPHA_F30, + LAST_RESTORE_REG = REGNO_ALPHA_F30, + RETURN_OFFSET = 0, + }; + typedef uint32_t reg_t; + + __dso_hidden Registers_Alpha(); + + static int dwarf2regno(int num) { return num; } + + bool validRegister(int num) const { + return num >= 0 && num <= REGNO_ALPHA_PC; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_ALPHA_PC]; } + + void setIP(uint64_t value) { reg[REGNO_ALPHA_PC] = value; } + + uint64_t getSP() const { return reg[REGNO_ALPHA_R30]; } + + void setSP(uint64_t value) { reg[REGNO_ALPHA_R30] = value; } + + bool validFloatVectorRegister(int num) const { + return num >= REGNO_ALPHA_F0 && num <= REGNO_ALPHA_F30; + } + + void copyFloatVectorRegister(int num, uint64_t addr_) { + assert(validFloatVectorRegister(num)); + const void *addr = reinterpret_cast(addr_); + memcpy(fpreg + (num - REGNO_ALPHA_F0), addr, sizeof(fpreg[0])); + } + + __dso_hidden void jumpto() const __dead; + +private: + uint64_t reg[REGNO_ALPHA_PC + 1]; + uint64_t fpreg[31]; +}; + +enum { + DWARF_HPPA_R1 = 1, + DWARF_HPPA_R31 = 31, + DWARF_HPPA_FR4L = 32, + DWARF_HPPA_FR31H = 87, + + REGNO_HPPA_PC = 0, + REGNO_HPPA_R1 = 1, + REGNO_HPPA_R2 = 2, + REGNO_HPPA_R30 = 30, + REGNO_HPPA_R31 = 31, + REGNO_HPPA_FR4L = 32, + REGNO_HPPA_FR31H = 87, +}; + +class Registers_HPPA { +public: + enum { + LAST_REGISTER = REGNO_HPPA_FR31H, + LAST_RESTORE_REG = REGNO_HPPA_FR31H, + RETURN_OFFSET = -3, // strictly speaking, this is a mask + }; + + __dso_hidden Registers_HPPA(); + + static int dwarf2regno(int num) { + if (num >= DWARF_HPPA_R1 && num <= DWARF_HPPA_R31) + return REGNO_HPPA_R1 + (num - DWARF_HPPA_R1); + if (num >= DWARF_HPPA_FR4L && num <= DWARF_HPPA_FR31H) + return REGNO_HPPA_FR4L + (num - DWARF_HPPA_FR31H); + return LAST_REGISTER + 1; + } + + bool validRegister(int num) const { + return num >= REGNO_HPPA_PC && num <= REGNO_HPPA_R31; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_HPPA_PC]; } + + void setIP(uint64_t value) { reg[REGNO_HPPA_PC] = value; } + + uint64_t getSP() const { return reg[REGNO_HPPA_R30]; } + + void setSP(uint64_t value) { reg[REGNO_HPPA_R30] = value; } + + bool validFloatVectorRegister(int num) const { + return num >= REGNO_HPPA_FR4L && num <= REGNO_HPPA_FR31H; + } + + void copyFloatVectorRegister(int num, uint64_t addr_) { + assert(validFloatVectorRegister(num)); + const void *addr = reinterpret_cast(addr_); + memcpy(fpreg + (num - REGNO_HPPA_FR4L), addr, sizeof(fpreg[0])); + } + + __dso_hidden void jumpto() const __dead; + +private: + uint32_t reg[REGNO_HPPA_R31 + 1]; + uint32_t fpreg[56]; +}; + +enum { + DWARF_MIPS_R1 = 0, + DWARF_MIPS_R31 = 31, + DWARF_MIPS_F0 = 32, + DWARF_MIPS_F31 = 63, + + REGNO_MIPS_PC = 0, + REGNO_MIPS_R1 = 0, + REGNO_MIPS_R29 = 29, + REGNO_MIPS_R31 = 31, + REGNO_MIPS_F0 = 33, + REGNO_MIPS_F31 = 64 +}; + +class Registers_MIPS { +public: + enum { + LAST_REGISTER = REGNO_MIPS_F31, + LAST_RESTORE_REG = REGNO_MIPS_F31, + RETURN_OFFSET = 0, + }; + + __dso_hidden Registers_MIPS(); + + static int dwarf2regno(int num) { + if (num >= DWARF_MIPS_R1 && num <= DWARF_MIPS_R31) + return REGNO_MIPS_R1 + (num - DWARF_MIPS_R1); + if (num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31) + return REGNO_MIPS_F0 + (num - DWARF_MIPS_F0); + return LAST_REGISTER + 1; + } + + bool validRegister(int num) const { + return num >= REGNO_MIPS_PC && num <= REGNO_MIPS_R31; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_MIPS_PC]; } + + void setIP(uint64_t value) { reg[REGNO_MIPS_PC] = value; } + + uint64_t getSP() const { return reg[REGNO_MIPS_R29]; } + + void setSP(uint64_t value) { reg[REGNO_MIPS_R29] = value; } + + bool validFloatVectorRegister(int num) const { + return num >= DWARF_MIPS_F0 && num <= DWARF_MIPS_F31; + } + + void copyFloatVectorRegister(int num, uint64_t addr_) { + assert(validFloatVectorRegister(num)); + const void *addr = reinterpret_cast(addr_); + memcpy(fpreg + (num - REGNO_MIPS_F0), addr, sizeof(fpreg[0])); + } + + __dso_hidden void jumpto() const __dead; + +private: + uint32_t reg[REGNO_MIPS_R31 + 1]; + uint64_t fpreg[32]; +}; + +enum { + DWARF_MIPS64_R1 = 0, + DWARF_MIPS64_R31 = 31, + DWARF_MIPS64_F0 = 32, + DWARF_MIPS64_F31 = 63, + + REGNO_MIPS64_PC = 0, + REGNO_MIPS64_R1 = 0, + REGNO_MIPS64_R29 = 29, + REGNO_MIPS64_R31 = 31, + REGNO_MIPS64_F0 = 33, + REGNO_MIPS64_F31 = 64 +}; + +class Registers_MIPS64 { +public: + enum { + LAST_REGISTER = REGNO_MIPS64_F31, + LAST_RESTORE_REG = REGNO_MIPS64_F31, + RETURN_OFFSET = 0, + }; + + __dso_hidden Registers_MIPS64(); + + static int dwarf2regno(int num) { + if (num >= DWARF_MIPS64_R1 && num <= DWARF_MIPS64_R31) + return REGNO_MIPS64_R1 + (num - DWARF_MIPS64_R1); + if (num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31) + return REGNO_MIPS64_F0 + (num - DWARF_MIPS64_F0); + return LAST_REGISTER + 1; + } + + bool validRegister(int num) const { + return num >= REGNO_MIPS64_PC && num <= REGNO_MIPS64_R31; + } + + uint64_t getRegister(int num) const { + assert(validRegister(num)); + return reg[num]; + } + + void setRegister(int num, uint64_t value) { + assert(validRegister(num)); + reg[num] = value; + } + + uint64_t getIP() const { return reg[REGNO_MIPS64_PC]; } + + void setIP(uint64_t value) { reg[REGNO_MIPS64_PC] = value; } + + uint64_t getSP() const { return reg[REGNO_MIPS64_R29]; } + + void setSP(uint64_t value) { reg[REGNO_MIPS64_R29] = value; } + + bool validFloatVectorRegister(int num) const { + return num >= DWARF_MIPS64_F0 && num <= DWARF_MIPS64_F31; + } + + void copyFloatVectorRegister(int num, uint64_t addr_) { + assert(validFloatVectorRegister(num)); + const void *addr = reinterpret_cast(addr_); + memcpy(fpreg + (num - REGNO_MIPS64_F0), addr, sizeof(fpreg[0])); + } + + __dso_hidden void jumpto() const __dead; + +private: + uint64_t reg[REGNO_MIPS64_R31 + 1]; + uint64_t fpreg[32]; +}; + +#if __i386__ +typedef Registers_x86 NativeUnwindRegisters; +#elif __x86_64__ +typedef Registers_x86_64 NativeUnwindRegisters; +#elif __powerpc__ +typedef Registers_ppc32 NativeUnwindRegisters; +#elif __arm__ +typedef Registers_arm32 NativeUnwindRegisters; +#elif __vax__ +typedef Registers_vax NativeUnwindRegisters; +#elif __m68k__ +typedef Registers_M68K NativeUnwindRegisters; +#elif __mips_n64 || __mips_n32 +typedef Registers_MIPS64 NativeUnwindRegisters; +#elif __mips__ +typedef Registers_MIPS NativeUnwindRegisters; +#elif __sh3__ +typedef Registers_SH3 NativeUnwindRegisters; +#elif __sparc64__ +typedef Registers_SPARC64 NativeUnwindRegisters; +#elif __sparc__ +typedef Registers_SPARC NativeUnwindRegisters; +#elif __alpha__ +typedef Registers_Alpha NativeUnwindRegisters; +#elif __hppa__ +typedef Registers_HPPA NativeUnwindRegisters; +#endif } // namespace _Unwind #endif // __REGISTERS_HPP__ diff --git a/sys/lib/libunwind/UnwindCursor.hpp b/sys/lib/libunwind/UnwindCursor.hpp index 2c094674b..32052f1be 100644 --- a/sys/lib/libunwind/UnwindCursor.hpp +++ b/sys/lib/libunwind/UnwindCursor.hpp @@ -63,6 +63,9 @@ public: this->setInfoBasedOnIPRegister(true); if (fUnwindInfoMissing) return UNW_STEP_END; + + if (fInfo.extra_args) + setSP(getSP() + fInfo.extra_args); return UNW_STEP_SUCCESS; } __builtin_unreachable(); @@ -134,7 +137,6 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { fInfo.handler = cieInfo.personality; fInfo.extra_args = prolog.spExtraArgSize; fInfo.unwind_info = fdeInfo.fdeStart; - fInfo.unwind_info_size = fdeInfo.fdeLength; } }; // namespace _Unwind diff --git a/sys/lib/libunwind/libunwind.cxx b/sys/lib/libunwind/libunwind.cxx index 30f579e86..8cdb86371 100644 --- a/sys/lib/libunwind/libunwind.cxx +++ b/sys/lib/libunwind/libunwind.cxx @@ -17,22 +17,12 @@ using namespace _Unwind; -#if __i386__ -typedef Registers_x86 ThisUnwindRegisters; -#elif __x86_64__ -typedef Registers_x86_64 ThisUnwindRegisters; -#elif __powerpc__ -typedef Registers_ppc32 ThisUnwindRegisters; -#else -#error Unsupported architecture -#endif - -typedef CFI_Parser MyCFIParser; +typedef CFI_Parser MyCFIParser; // Internal object representing the address space of this process. static LocalAddressSpace sThisAddressSpace(MyCFIParser::findPCRange); -typedef UnwindCursor ThisUnwindCursor; +typedef UnwindCursor ThisUnwindCursor; static _Unwind_Reason_Code unwind_phase1(ThisUnwindCursor &cursor, struct _Unwind_Exception *exc) { @@ -197,7 +187,7 @@ static _Unwind_Reason_Code unwind_phase2_forced(ThisUnwindCursor &cursor, } _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) { - ThisUnwindRegisters registers; + NativeUnwindRegisters registers; ThisUnwindCursor cursor1(registers, sThisAddressSpace); ThisUnwindCursor cursor2(registers, sThisAddressSpace); @@ -216,7 +206,7 @@ _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) { _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, void *stop_arg) { - ThisUnwindRegisters registers; + NativeUnwindRegisters registers; ThisUnwindCursor cursor(registers, sThisAddressSpace); // Mark this as forced unwind for _Unwind_Resume(). @@ -227,7 +217,7 @@ _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc, } void _Unwind_Resume(struct _Unwind_Exception *exc) { - ThisUnwindRegisters registers; + NativeUnwindRegisters registers; ThisUnwindCursor cursor(registers, sThisAddressSpace); if (exc->private_1 != 0) @@ -273,17 +263,18 @@ uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { return cursor->getIP(); } +uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *isSignalFrame) { + ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; + *isSignalFrame = cursor->isSignalFrame() ? 1 : 0; + return cursor->getIP(); +} + void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) { ThisUnwindCursor *cursor = (ThisUnwindCursor *)context; cursor->setIP(new_value); unw_proc_info_t info; cursor->getInfo(&info); - uint64_t orgArgSize = info.extra_args; - uint64_t orgFuncStart = info.start_ip; cursor->setInfoBasedOnIPRegister(false); - // Adjust REG_SP if there was a DW_CFA_GNU_args_size. - if (orgFuncStart == info.start_ip && orgArgSize != 0) - cursor->setSP(cursor->getSP() + orgArgSize); } uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) { @@ -301,7 +292,7 @@ uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { } _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { - ThisUnwindRegisters registers; + NativeUnwindRegisters registers; ThisUnwindCursor cursor(registers, sThisAddressSpace); cursor.setInfoBasedOnIPRegister(); @@ -327,7 +318,7 @@ uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { } void *_Unwind_FindEnclosingFunction(void *pc) { - ThisUnwindRegisters registers; + NativeUnwindRegisters registers; ThisUnwindCursor cursor(registers, sThisAddressSpace); unw_proc_info_t info; diff --git a/sys/lib/libunwind/unwind.h b/sys/lib/libunwind/unwind.h index c89b01f87..498bb7583 100644 --- a/sys/lib/libunwind/unwind.h +++ b/sys/lib/libunwind/unwind.h @@ -67,6 +67,7 @@ void _Unwind_DeleteException(struct _Unwind_Exception *); uintptr_t _Unwind_GetGR(struct _Unwind_Context *, int); void _Unwind_SetGR(struct _Unwind_Context *, int, uintptr_t); uintptr_t _Unwind_GetIP(struct _Unwind_Context *); +uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *, int *); uintptr_t _Unwind_GetCFA(struct _Unwind_Context *); void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t); uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *); diff --git a/sys/lib/libunwind/unwind_registers.S b/sys/lib/libunwind/unwind_registers.S index b87f16380..a4dcfadde 100644 --- a/sys/lib/libunwind/unwind_registers.S +++ b/sys/lib/libunwind/unwind_registers.S @@ -116,6 +116,7 @@ ENTRY(_ZNK7_Unwind16Registers_x86_646jumptoEv) #ifdef __powerpc__ .hidden _ZN7_Unwind15Registers_ppc32C1Ev ENTRY(_ZN7_Unwind15Registers_ppc32C1Ev) + /* TODO: skip non-callee-safe registers */ stw %r0, 0(%r3) stw %r1, 4(%r3) stw %r2, 8(%r3) @@ -148,21 +149,82 @@ ENTRY(_ZN7_Unwind15Registers_ppc32C1Ev) stw %r29,116(%r3) stw %r30,120(%r3) stw %r31,124(%r3) - - mfcr %r0 - stw %r0, 128(%r3) /* CR */ mflr %r0 - stw %r0, 132(%r3) /* LR */ - stw %r0, 144(%r3) /* LR */ - mfctr %r0 - stw %r0, 136(%r3) /* CTR */ - mfxer %r0 - stw %r0, 140(%r3) /* XER */ + stw %r0, 136(%r3) /* SRR0 */ + mfcr %r0 + stw %r0, 132(%r3) /* CR */ + stfd %f0, 144(%r3) + stfd %f1, 152(%r3) + stfd %f2, 160(%r3) + stfd %f3, 168(%r3) + stfd %f4, 176(%r3) + stfd %f5, 184(%r3) + stfd %f6, 192(%r3) + stfd %f7, 200(%r3) + stfd %f8, 208(%r3) + stfd %f9, 216(%r3) + stfd %f10, 224(%r3) + stfd %f11, 232(%r3) + stfd %f12, 240(%r3) + stfd %f13, 248(%r3) + stfd %f14, 256(%r3) + stfd %f15, 264(%r3) + stfd %f16, 272(%r3) + stfd %f17, 280(%r3) + stfd %f18, 288(%r3) + stfd %f19, 296(%r3) + stfd %f20, 304(%r3) + stfd %f21, 312(%r3) + stfd %f22, 320(%r3) + stfd %f23, 328(%r3) + stfd %f24, 336(%r3) + stfd %f25, 344(%r3) + stfd %f26, 352(%r3) + stfd %f27, 360(%r3) + stfd %f28, 368(%r3) + stfd %f29, 376(%r3) + stfd %f30, 384(%r3) + stfd %f31, 392(%r3) + + /* LR is undefined */ blr .hidden _ZNK7_Unwind15Registers_ppc326jumptoEv ENTRY(_ZNK7_Unwind15Registers_ppc326jumptoEv) + lfd %f0, 144(%r3) + lfd %f1, 152(%r3) + lfd %f2, 160(%r3) + lfd %f3, 168(%r3) + lfd %f4, 176(%r3) + lfd %f5, 184(%r3) + lfd %f6, 192(%r3) + lfd %f7, 200(%r3) + lfd %f8, 208(%r3) + lfd %f9, 216(%r3) + lfd %f10, 224(%r3) + lfd %f11, 232(%r3) + lfd %f12, 240(%r3) + lfd %f13, 248(%r3) + lfd %f14, 256(%r3) + lfd %f15, 264(%r3) + lfd %f16, 272(%r3) + lfd %f17, 280(%r3) + lfd %f18, 288(%r3) + lfd %f19, 296(%r3) + lfd %f20, 304(%r3) + lfd %f21, 312(%r3) + lfd %f22, 320(%r3) + lfd %f23, 328(%r3) + lfd %f24, 336(%r3) + lfd %f25, 344(%r3) + lfd %f26, 352(%r3) + lfd %f27, 360(%r3) + lfd %f28, 368(%r3) + lfd %f29, 376(%r3) + lfd %f30, 384(%r3) + lfd %f31, 392(%r3) + lwz %r2, 8(%r3) /* skip r3 for now */ lwz %r4, 16(%r3) @@ -194,19 +256,931 @@ ENTRY(_ZNK7_Unwind15Registers_ppc326jumptoEv) lwz %r30,120(%r3) lwz %r31,124(%r3) - lwz %r0, 128(%r3) /* CR */ - mtcr %r0 - lwz %r0, 132(%r3) /* LR */ + lwz %r0, 128(%r3) /* LR */ mtlr %r0 - lwz %r0, 136(%r3) /* CTR */ - mtctr %r0 - lwz %r0, 140(%r3) /* XER */ - mtxer %r0 - lwz %r0, 144(%r3) /* SRR0 ? */ + lwz %r0, 132(%r3) /* CR */ + mtcr %r0 + lwz %r0, 136(%r3) /* SRR0 */ mtctr %r0 - lwz %r0, 0(%r3) /* do r0 now */ - lwz %r1,4(%r3) /* do sp now */ - lwz %r3,12(%r3) /* do r3 last */ + lwz %r0, 0(%r3) /* do r0 now */ + lwz %r1, 4(%r3) /* do sp now */ + lwz %r3, 12(%r3) /* do r3 last */ bctr #endif + +#if defined(__arm__) + .fpu vfpv3 + .hidden _ZN7_Unwind15Registers_arm32C1Ev +ENTRY(_ZN7_Unwind15Registers_arm32C1Ev) + stmia r0, {r0-r14} + str lr, [r0, #60] /* PC */ + mrs r1, cpsr + str r1, [r0, #64] /* CPSR */ + mov r1, #0 + str r1, [r0, #68] + RET +END(_ZN7_Unwind15Registers_arm32C1Ev) + + .hidden _ZN7_Unwind15Registers_arm328lazyVFP1Ev +ENTRY(_ZN7_Unwind15Registers_arm328lazyVFP1Ev) + add r0, #72 + vstmia r0, {d0-d15} + RET +END(_ZN7_Unwind15Registers_arm328lazyVFP1Ev) + + .hidden _ZN7_Unwind15Registers_arm328lazyVFP3Ev +ENTRY(_ZN7_Unwind15Registers_arm328lazyVFP3Ev) + add r0, #200 + vstmia r0, {d16-d31} + RET +END(_ZN7_Unwind15Registers_arm328lazyVFP3Ev) + + .hidden _ZNK7_Unwind15Registers_arm326jumptoEv +ENTRY(_ZNK7_Unwind15Registers_arm326jumptoEv) + ldrb r1, [r0, #68] + tst r1, #1 + beq .Lnovfp1 + add r2, r0, #72 + vldmia r2, {d0-d15} +.Lnovfp1: + tst r1, #2 + beq .Lnovfp3 + add r2, r0, #200 + vldmia r2, {d16-d31} +.Lnovfp3: + ldr r1, [r0, #64] + msr cpsr_sxc, r1 + ldmia r0, {r0-r15} +END(_ZNK7_Unwind15Registers_arm326jumptoEv) +#endif + +#if defined(__vax__) + .hidden _ZN7_Unwind13Registers_vaxC1Ev +ENTRY(_ZN7_Unwind13Registers_vaxC1Ev, R0) + subl2 $4, %sp + movl 4(%ap), %r0 + movl %r1, 4(%r0) + movl %r2, 8(%r0) + movl %r3, 12(%r0) + movl %r4, 16(%r0) + movl %r5, 20(%r0) + movl %r6, 24(%r0) + movl %r7, 28(%r0) + movl %r8, 32(%r0) + movl %r9, 36(%r0) + movl %r10, 40(%r0) + movl %r11, 44(%r0) + movl 8(%fp), 48(%r0) + movl 12(%fp), 52(%r0) + addl3 $36, %sp, 56(%r0) + /* Return PC */ + movl 16(%fp), 60(%r0) + /* Load saved value of r0 as r1 */ + movl 20(%fp), 0(%r0) + /* Saved PSW */ + movl 4(%fp), 64(%r0) + ret +END(_ZN7_Unwind13Registers_vaxC1Ev) + + .hidden _ZNK7_Unwind13Registers_vax6jumptoEv +ENTRY(_ZNK7_Unwind13Registers_vax6jumptoEv, 0) + subl2 $4, %sp + movl 4(%ap), %r0 + movl 4(%r0), %r1 + movl 8(%r0), %r2 + movl 12(%r0), %r3 + movl 16(%r0), %r4 + movl 20(%r0), %r5 + movl 24(%r0), %r6 + movl 28(%r0), %r7 + movl 32(%r0), %r8 + movl 36(%r0), %r9 + movl 40(%r0), %r10 + movl 44(%r0), %r11 + movl 48(%r0), %r12 + movl 52(%r0), %r13 + movl 56(%r0), %r14 + movl 60(%r0), -(%sp) + movl 0(%r0), %r0 + /* XXX restore PSW */ + rsb +END(_ZNK7_Unwind13Registers_vax6jumptoEv) +#endif + +#if defined(__m68k__) +ENTRY(_ZN7_Unwind14Registers_M68KC1Ev) + move.l 4(%sp), %a0 + movem.l %d0-%d7/%a0-%a7, (%a0) + fmovem %fp0-%fp7, 72(%a0) + move.l 0(%sp), %a1 + move.l %a1, 64(%a0) + addq.l #4, 60(%a0) + rts +END(_ZN7_Unwind14Registers_M68KC1Ev) + +ENTRY(_ZNK7_Unwind14Registers_M68K6jumptoEv) + move.l 4(%sp), %a0 + subq.l #4, 60(%a0) + move.l 64(%a0), %a1 + move.l 60(%a0), %a2 + move.l %a1, (%a2) + fmovem 72(%a0), %fp0-%fp7 + movem.l (%a0), %d0-%d7/%a0-%a7 + rts +END(_ZNK7_Unwind14Registers_M68K6jumptoEv) +#endif + +#if defined(__sh3__) + .hidden _ZN7_Unwind13Registers_SH3C1Ev +ENTRY(_ZN7_Unwind13Registers_SH3C1Ev) + add #64, r4 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov.l @r15+, r8 + mov.l r8, @r4 + mov.l @r15+, r8 + + mov.l r15, @-r4 + mov.l r14, @-r4 + mov.l r13, @-r4 + mov.l r12, @-r4 + mov.l r11, @-r4 + mov.l r10, @-r4 + mov.l r9, @-r4 + mov.l r8, @-r4 + mov.l r7, @-r4 + mov.l r6, @-r4 + mov.l r5, @-r4 + add #-4, r4 + mov.l r3, @-r4 + mov.l r2, @-r4 + mov.l r1, @-r4 + mov.l r0, @-r4 + rts + mov.l r4, @(16,r4) +SET_ENTRY_SIZE(_ZN7_Unwind13Registers_SH3C1Ev) + + .hidden _ZNK7_Unwind13Registers_SH36jumptoEv +ENTRY(_ZNK7_Unwind13Registers_SH36jumptoEv) + mov r4, r0 + add #4, r0 + mov.l @r0+, r1 + mov.l @r0+, r2 + mov.l @r0+, r3 + mov.l @r0+, r4 + mov.l @r0+, r5 + mov.l @r0+, r6 + mov.l @r0+, r7 + mov.l @r0+, r8 + mov.l @r0+, r9 + mov.l @r0+, r10 + mov.l @r0+, r11 + mov.l @r0+, r12 + mov.l @r0+, r13 + mov.l @(12, r0), r14 + lds r14, pr + mov.l @r0+, r14 + mov.l @r0+, r15 + mov.l @r0, r0 + jmp @r0 + nop +SET_ENTRY_SIZE(_ZNK7_Unwind13Registers_SH36jumptoEv) +#endif + +#if defined(__sparc64__) +#include + .register %g2, #ignore + .register %g3, #ignore + .register %g6, #ignore + .register %g7, #ignore + .hidden _ZN7_Unwind17Registers_SPARC64C1Ev +ENTRY(_ZN7_Unwind17Registers_SPARC64C1Ev) + t ST_FLUSHWIN + stx %g0, [%o0 + 0] + stx %g1, [%o0 + 8] + stx %g2, [%o0 + 16] + stx %g3, [%o0 + 24] + stx %g4, [%o0 + 32] + stx %g5, [%o0 + 40] + stx %g6, [%o0 + 48] + stx %g7, [%o0 + 56] + stx %o0, [%o0 + 64] + stx %o1, [%o0 + 72] + stx %o2, [%o0 + 80] + stx %o3, [%o0 + 88] + stx %o4, [%o0 + 96] + stx %o5, [%o0 + 104] + stx %o6, [%o0 + 112] + stx %o7, [%o0 + 120] + stx %l0, [%o0 + 128] + stx %l1, [%o0 + 136] + stx %l2, [%o0 + 144] + stx %l3, [%o0 + 152] + stx %l4, [%o0 + 160] + stx %l5, [%o0 + 168] + stx %l6, [%o0 + 176] + stx %l7, [%o0 + 184] + stx %i0, [%o0 + 192] + stx %i1, [%o0 + 200] + stx %i2, [%o0 + 208] + stx %i3, [%o0 + 216] + stx %i4, [%o0 + 224] + stx %i5, [%o0 + 232] + stx %i6, [%o0 + 240] + stx %i7, [%o0 + 248] + add %o7, 8, %g1 + retl + stx %g1, [%o0 + 256] +END(_ZN7_Unwind17Registers_SPARC64C1Ev) + + .hidden _ZNK7_Unwind17Registers_SPARC646jumptoEv +ENTRY(_ZNK7_Unwind17Registers_SPARC646jumptoEv) + t ST_FLUSHWIN + ldx [%o0 + 0], %g0 + ldx [%o0 + 8], %g1 + ldx [%o0 + 16], %g2 + ldx [%o0 + 24], %g3 + ldx [%o0 + 32], %g4 + ldx [%o0 + 40], %g5 + ldx [%o0 + 48], %g6 + ldx [%o0 + 56], %g7 + ldx [%o0 + 72], %o1 + ldx [%o0 + 80], %o2 + ldx [%o0 + 88], %o3 + ldx [%o0 + 96], %o4 + ldx [%o0 + 104], %o5 + ldx [%o0 + 112], %g1 + sub %g1, 2047, %o6 + ldx [%o0 + 120], %o7 + ldx [%o0 + 128], %l0 + ldx [%o0 + 136], %l1 + ldx [%o0 + 144], %l2 + ldx [%o0 + 152], %l3 + ldx [%o0 + 160], %l4 + ldx [%o0 + 168], %l5 + ldx [%o0 + 176], %l6 + ldx [%o0 + 184], %l7 + ldx [%o0 + 192], %i0 + ldx [%o0 + 200], %i1 + ldx [%o0 + 208], %i2 + ldx [%o0 + 216], %i3 + ldx [%o0 + 224], %i4 + ldx [%o0 + 232], %i5 + ldx [%o0 + 240], %i6 + ldx [%o0 + 248], %i7 + ldx [%o0 + 256], %g1 + jmpl %g1, %g0 + ldx [%o0 + 64], %o0 +END(_ZNK7_Unwind17Registers_SPARC646jumptoEv) +#elif defined(__sparc__) +#include + + .hidden _ZN7_Unwind15Registers_SPARCC1Ev +ENTRY(_ZN7_Unwind15Registers_SPARCC1Ev) + t ST_FLUSHWIN + st %g0, [%o0 + 0] + st %g1, [%o0 + 4] + st %g2, [%o0 + 8] + st %g3, [%o0 + 12] + st %g4, [%o0 + 16] + st %g5, [%o0 + 20] + st %g6, [%o0 + 24] + st %g7, [%o0 + 28] + st %o0, [%o0 + 32] + st %o1, [%o0 + 36] + st %o2, [%o0 + 40] + st %o3, [%o0 + 44] + st %o4, [%o0 + 48] + st %o5, [%o0 + 52] + st %o6, [%o0 + 56] + st %o7, [%o0 + 60] + st %l0, [%o0 + 64] + st %l1, [%o0 + 68] + st %l2, [%o0 + 72] + st %l3, [%o0 + 76] + st %l4, [%o0 + 80] + st %l5, [%o0 + 84] + st %l6, [%o0 + 88] + st %l7, [%o0 + 92] + st %i0, [%o0 + 96] + st %i1, [%o0 + 100] + st %i2, [%o0 + 104] + st %i3, [%o0 + 108] + st %i4, [%o0 + 112] + st %i5, [%o0 + 116] + st %i6, [%o0 + 120] + st %i7, [%o0 + 124 ] + add %o7, 8, %g1 + retl + st %g1, [%o0 + 128] +END(_ZN7_Unwind15Registers_SPARCC1Ev) + + .hidden _ZNK7_Unwind15Registers_SPARC6jumptoEv +ENTRY(_ZNK7_Unwind15Registers_SPARC6jumptoEv) + t ST_FLUSHWIN + ld [%o0 + 0], %g0 + ld [%o0 + 4], %g1 + ld [%o0 + 8], %g2 + ld [%o0 + 12], %g3 + ld [%o0 + 16], %g4 + ld [%o0 + 20], %g5 + ld [%o0 + 24], %g6 + ld [%o0 + 28], %g7 + ld [%o0 + 36], %o1 + ld [%o0 + 40], %o2 + ld [%o0 + 44], %o3 + ld [%o0 + 48], %o4 + ld [%o0 + 52], %o5 + ld [%o0 + 56], %o6 + ld [%o0 + 60], %o7 + ld [%o0 + 64], %l0 + ld [%o0 + 68], %l1 + ld [%o0 + 72], %l2 + ld [%o0 + 76], %l3 + ld [%o0 + 80], %l4 + ld [%o0 + 84], %l5 + ld [%o0 + 88], %l6 + ld [%o0 + 92], %l7 + ld [%o0 + 96], %i0 + ld [%o0 + 100], %i1 + ld [%o0 + 104], %i2 + ld [%o0 + 108], %i3 + ld [%o0 + 112], %i4 + ld [%o0 + 116], %i5 + ld [%o0 + 120], %i6 + ld [%o0 + 124], %i7 + ld [%o0 + 128], %g1 + jmpl %g1, %g0 + ld [%o0 + 32], %o0 +END(_ZNK7_Unwind15Registers_SPARC6jumptoEv) +#endif + +#if defined(__alpha__) + .set nomacro + .set noat + .hidden _ZN7_Unwind15Registers_AlphaC1Ev +LEAF_NOPROFILE(_ZN7_Unwind15Registers_AlphaC1Ev, 1) + stq $0, 0($16) + stq $1, 8($16) + stq $2, 16($16) + stq $3, 24($16) + stq $4, 32($16) + stq $5, 40($16) + stq $6, 48($16) + stq $7, 56($16) + stq $8, 64($16) + stq $9, 72($16) + stq $10, 80($16) + stq $11, 88($16) + stq $12, 96($16) + stq $13, 104($16) + stq $14, 112($16) + stq $15, 120($16) + stq $16, 128($16) + stq $17, 136($16) + stq $18, 144($16) + stq $19, 152($16) + stq $20, 160($16) + stq $21, 168($16) + stq $22, 176($16) + stq $23, 184($16) + stq $24, 192($16) + stq $25, 200($16) + stq $26, 208($16) + stq $27, 216($16) + stq $28, 224($16) + stq $29, 232($16) + stq $30, 240($16) + stq $26, 248($16) + + stt $f0, 256($16) + stt $f1, 264($16) + stt $f2, 272($16) + stt $f3, 280($16) + stt $f4, 288($16) + stt $f5, 296($16) + stt $f6, 304($16) + stt $f7, 312($16) + stt $f8, 320($16) + stt $f9, 328($16) + stt $f10, 336($16) + stt $f11, 344($16) + stt $f12, 352($16) + stt $f13, 360($16) + stt $f14, 368($16) + stt $f15, 376($16) + stt $f16, 384($16) + stt $f17, 392($16) + stt $f18, 400($16) + stt $f19, 408($16) + stt $f20, 416($16) + stt $f21, 424($16) + stt $f22, 432($16) + stt $f23, 440($16) + stt $f24, 448($16) + stt $f25, 456($16) + stt $f26, 464($16) + stt $f27, 472($16) + stt $f28, 480($16) + stt $f29, 488($16) + stt $f30, 496($16) + ret $31, ($26), 1 +END(_ZN7_Unwind15Registers_AlphaC1Ev) + + .set nomacro + .set noat + .hidden _ZNK7_Unwind15Registers_Alpha6jumptoEv +LEAF_NOPROFILE(_ZNK7_Unwind15Registers_Alpha6jumptoEv, 1) + ldq $0, 0($16) + ldq $1, 8($16) + ldq $2, 16($16) + ldq $3, 24($16) + ldq $4, 32($16) + ldq $5, 40($16) + ldq $6, 48($16) + ldq $7, 56($16) + ldq $8, 64($16) + ldq $9, 72($16) + ldq $10, 80($16) + ldq $11, 88($16) + ldq $12, 96($16) + ldq $13, 104($16) + ldq $14, 112($16) + ldq $15, 120($16) + ldq $17, 136($16) + ldq $18, 144($16) + ldq $19, 152($16) + ldq $20, 160($16) + ldq $21, 168($16) + ldq $22, 176($16) + ldq $23, 184($16) + ldq $24, 192($16) + ldq $25, 200($16) + ldq $27, 216($16) + ldq $28, 224($16) + ldq $29, 232($16) + ldq $30, 240($16) + ldq $26, 248($16) + + ldt $f0, 256($16) + ldt $f1, 264($16) + ldt $f2, 272($16) + ldt $f3, 280($16) + ldt $f4, 288($16) + ldt $f5, 296($16) + ldt $f6, 304($16) + ldt $f7, 312($16) + ldt $f8, 320($16) + ldt $f9, 328($16) + ldt $f10, 336($16) + ldt $f11, 344($16) + ldt $f12, 352($16) + ldt $f13, 360($16) + ldt $f14, 368($16) + ldt $f15, 376($16) + ldt $f16, 384($16) + ldt $f17, 392($16) + ldt $f18, 400($16) + ldt $f19, 408($16) + ldt $f20, 416($16) + ldt $f21, 424($16) + ldt $f22, 432($16) + ldt $f23, 440($16) + ldt $f24, 448($16) + ldt $f25, 456($16) + ldt $f26, 464($16) + ldt $f27, 472($16) + ldt $f28, 480($16) + ldt $f29, 488($16) + ldt $f30, 496($16) + ldq $16, 128($16) + ret $31, ($26), 1 +END(_ZNK7_Unwind15Registers_Alpha6jumptoEv) +#endif + +#if defined(__mips_n64) || defined(__mips_n32) + .set noat +LEAF(_ZN7_Unwind16Registers_MIPS64C1Ev) +#if 0 + FP_S $f0, 256($4) + FP_S $f1, 264($4) + FP_S $f2, 272($4) + FP_S $f3, 280($4) + FP_S $f4, 288($4) + FP_S $f5, 296($4) + FP_S $f6, 304($4) + FP_S $f7, 312($4) + FP_S $f8, 320($4) + FP_S $f9, 328($4) + FP_S $f10, 336($4) + FP_S $f11, 344($4) + FP_S $f12, 352($4) + FP_S $f13, 360($4) + FP_S $f14, 368($4) + FP_S $f15, 376($4) + FP_S $f16, 384($4) + FP_S $f17, 392($4) + FP_S $f18, 400($4) + FP_S $f19, 408($4) + FP_S $f20, 416($4) + FP_S $f21, 424($4) + FP_S $f22, 432($4) + FP_S $f23, 440($4) + FP_S $f24, 448($4) + FP_S $f25, 456($4) + FP_S $f26, 464($4) + FP_S $f27, 472($4) + FP_S $f28, 480($4) + FP_S $f29, 488($4) + FP_S $f30, 496($4) + FP_S $f31, 504($4) +#endif + sd $31, 0($4) + sd $1, 4($4) + sd $2, 8($4) + sd $3, 12($4) + sd $4, 16($4) + sd $5, 20($4) + sd $6, 24($4) + sd $7, 28($4) + sd $8, 32($4) + sd $9, 36($4) + sd $10, 40($4) + sd $11, 44($4) + sd $12, 48($4) + sd $13, 52($4) + sd $14, 56($4) + sd $15, 60($4) + sd $16, 64($4) + sd $17, 68($4) + sd $18, 72($4) + sd $19, 76($4) + sd $20, 80($4) + sd $21, 84($4) + sd $22, 88($4) + sd $23, 92($4) + sd $24, 96($4) + sd $25, 100($4) + sd $26, 104($4) + sd $27, 108($4) + sd $28, 112($4) + sd $29, 116($4) + sd $30, 120($4) + sd $31, 124($4) + jr $31 + nop +END(_ZN7_Unwind16Registers_MIPS64C1Ev) + +LEAF(_ZNK7_Unwind16Registers_MIPS646jumptoEv) +#if 0 + FP_L $f0, 256($4) + FP_L $f1, 264($4) + FP_L $f2, 272($4) + FP_L $f3, 280($4) + FP_L $f4, 288($4) + FP_L $f5, 296($4) + FP_L $f6, 304($4) + FP_L $f7, 312($4) + FP_L $f8, 320($4) + FP_L $f9, 328($4) + FP_L $f10, 336($4) + FP_L $f11, 344($4) + FP_L $f12, 352($4) + FP_L $f13, 360($4) + FP_L $f14, 368($4) + FP_L $f15, 376($4) + FP_L $f16, 384($4) + FP_L $f17, 392($4) + FP_L $f18, 400($4) + FP_L $f19, 408($4) + FP_L $f20, 416($4) + FP_L $f21, 424($4) + FP_L $f22, 432($4) + FP_L $f23, 440($4) + FP_L $f24, 448($4) + FP_L $f25, 456($4) + FP_L $f26, 464($4) + FP_L $f27, 472($4) + FP_L $f28, 480($4) + FP_L $f29, 488($4) + FP_L $f30, 496($4) + FP_L $f31, 504($4) +#endif + + ld $31, 0($4) + ld $1, 8($4) + ld $2, 16($4) + ld $3, 24($4) + ld $5, 40($4) + ld $6, 48($4) + ld $7, 56($4) + ld $8, 64($4) + ld $9, 72($4) + ld $10, 80($4) + ld $11, 88($4) + ld $12, 96($4) + ld $13, 104($4) + ld $14, 112($4) + ld $15, 120($4) + ld $16, 128($4) + ld $17, 136($4) + ld $18, 144($4) + ld $19, 152($4) + ld $20, 160($4) + ld $21, 168($4) + ld $22, 176($4) + ld $23, 184($4) + ld $24, 192($4) + ld $25, 200($4) + ld $26, 208($4) + ld $27, 216($4) + ld $28, 224($4) + ld $29, 232($4) + ld $30, 240($4) + ld $4, 32($4) + jr $31 + nop +END(_ZNK7_Unwind16Registers_MIPS646jumptoEv) +#elif defined(__mips__) + .set noat +LEAF(_ZN7_Unwind14Registers_MIPSC1Ev) +#if 0 +#if __mips > 1 + FP_S $f0, 128($4) + FP_S $f1, 136($4) + FP_S $f2, 144($4) + FP_S $f3, 152($4) + FP_S $f4, 160($4) + FP_S $f5, 168($4) + FP_S $f6, 176($4) + FP_S $f7, 184($4) + FP_S $f8, 192($4) + FP_S $f9, 200($4) + FP_S $f10, 208($4) + FP_S $f11, 216($4) + FP_S $f12, 224($4) + FP_S $f13, 232($4) + FP_S $f14, 240($4) + FP_S $f15, 248($4) + FP_S $f16, 256($4) + FP_S $f17, 264($4) + FP_S $f18, 272($4) + FP_S $f19, 280($4) + FP_S $f20, 288($4) + FP_S $f21, 296($4) + FP_S $f22, 304($4) + FP_S $f23, 312($4) + FP_S $f24, 320($4) + FP_S $f25, 328($4) + FP_S $f26, 336($4) + FP_S $f27, 344($4) + FP_S $f28, 352($4) + FP_S $f29, 360($4) + FP_S $f30, 368($4) + FP_S $f31, 376($4) +#endif +#endif + sw $31, 0($4) + sw $1, 4($4) + sw $2, 8($4) + sw $3, 12($4) + sw $4, 16($4) + sw $5, 20($4) + sw $6, 24($4) + sw $7, 28($4) + sw $8, 32($4) + sw $9, 36($4) + sw $10, 40($4) + sw $11, 44($4) + sw $12, 48($4) + sw $13, 52($4) + sw $14, 56($4) + sw $15, 60($4) + sw $16, 64($4) + sw $17, 68($4) + sw $18, 72($4) + sw $19, 76($4) + sw $20, 80($4) + sw $21, 84($4) + sw $22, 88($4) + sw $23, 92($4) + sw $24, 96($4) + sw $25, 100($4) + sw $26, 104($4) + sw $27, 108($4) + sw $28, 112($4) + sw $29, 116($4) + sw $30, 120($4) + sw $31, 124($4) + jr $31 + nop +END(_ZN7_Unwind14Registers_MIPSC1Ev) + +LEAF(_ZNK7_Unwind14Registers_MIPS6jumptoEv) +#if 0 +#if __mips > 1 + FP_L $f0, 128($4) + FP_L $f1, 136($4) + FP_L $f2, 144($4) + FP_L $f3, 152($4) + FP_L $f4, 160($4) + FP_L $f5, 168($4) + FP_L $f6, 176($4) + FP_L $f7, 184($4) + FP_L $f8, 192($4) + FP_L $f9, 200($4) + FP_L $f10, 208($4) + FP_L $f11, 216($4) + FP_L $f12, 224($4) + FP_L $f13, 232($4) + FP_L $f14, 240($4) + FP_L $f15, 248($4) + FP_L $f16, 256($4) + FP_L $f17, 264($4) + FP_L $f18, 272($4) + FP_L $f19, 280($4) + FP_L $f20, 288($4) + FP_L $f21, 296($4) + FP_L $f22, 304($4) + FP_L $f23, 312($4) + FP_L $f24, 320($4) + FP_L $f25, 328($4) + FP_L $f26, 336($4) + FP_L $f27, 344($4) + FP_L $f28, 352($4) + FP_L $f29, 360($4) + FP_L $f30, 368($4) + FP_L $f31, 376($4) +#endif +#endif + + lw $31, 0($4) + lw $1, 4($4) + lw $2, 8($4) + lw $3, 12($4) + lw $5, 20($4) + lw $6, 24($4) + lw $7, 28($4) + lw $8, 32($4) + lw $9, 36($4) + lw $10, 40($4) + lw $11, 44($4) + lw $12, 48($4) + lw $13, 52($4) + lw $14, 56($4) + lw $15, 60($4) + lw $16, 64($4) + lw $17, 68($4) + lw $18, 72($4) + lw $19, 76($4) + lw $20, 80($4) + lw $21, 84($4) + lw $22, 88($4) + lw $23, 92($4) + lw $24, 96($4) + lw $25, 100($4) + lw $26, 104($4) + lw $27, 108($4) + lw $28, 112($4) + lw $29, 116($4) + lw $30, 120($4) + lw $4, 16($4) + jr $31 + nop +END(_ZNK7_Unwind14Registers_MIPS6jumptoEv) +#endif + +#if defined(__hppa__) +LEAF_ENTRY_NOPROFILE(_ZN7_Unwind14Registers_HPPAC1Ev) + stw %r2, 0(%r26) + stw %r1, 4(%r26) + stw %r2, 8(%r26) + stw %r3, 12(%r26) + stw %r4, 16(%r26) + stw %r5, 20(%r26) + stw %r6, 24(%r26) + stw %r7, 28(%r26) + stw %r8, 32(%r26) + stw %r9, 36(%r26) + stw %r10, 40(%r26) + stw %r11, 44(%r26) + stw %r12, 48(%r26) + stw %r13, 52(%r26) + stw %r14, 56(%r26) + stw %r15, 60(%r26) + stw %r16, 64(%r26) + stw %r17, 68(%r26) + stw %r18, 72(%r26) + stw %r19, 76(%r26) + stw %r20, 80(%r26) + stw %r21, 84(%r26) + stw %r22, 88(%r26) + stw %r23, 92(%r26) + stw %r24, 96(%r26) + stw %r25, 100(%r26) + stw %r26, 104(%r26) + stw %r27, 108(%r26) + stw %r28, 112(%r26) + stw %r29, 116(%r26) + stw %r30, 120(%r26) + stw %r31, 124(%r26) + ldi 128, %r19 + addl %r19, %r26, %r19 + fstds,ma %fr4, 8(%r19) + fstds,ma %fr5, 8(%r19) + fstds,ma %fr6, 8(%r19) + fstds,ma %fr7, 8(%r19) + fstds,ma %fr8, 8(%r19) + fstds,ma %fr9, 8(%r19) + fstds,ma %fr10, 8(%r19) + fstds,ma %fr11, 8(%r19) + fstds,ma %fr12, 8(%r19) + fstds,ma %fr13, 8(%r19) + fstds,ma %fr14, 8(%r19) + fstds,ma %fr15, 8(%r19) + fstds,ma %fr16, 8(%r19) + fstds,ma %fr17, 8(%r19) + fstds,ma %fr18, 8(%r19) + fstds,ma %fr19, 8(%r19) + fstds,ma %fr20, 8(%r19) + fstds,ma %fr21, 8(%r19) + fstds,ma %fr22, 8(%r19) + fstds,ma %fr23, 8(%r19) + fstds,ma %fr24, 8(%r19) + fstds,ma %fr25, 8(%r19) + fstds,ma %fr19, 8(%r19) + fstds,ma %fr27, 8(%r19) + fstds,ma %fr28, 8(%r19) + fstds,ma %fr29, 8(%r19) + fstds,ma %fr30, 8(%r19) + fstds,ma %fr31, 8(%r19) + ldw 76(%r26), %r19 + bv,n %r0(%r2) +EXIT(_ZN7_Unwind14Registers_HPPAC1Ev) + +LEAF_ENTRY_NOPROFILE(_ZNK7_Unwind14Registers_HPPA6jumptoEv) + ldi 128, %r19 + addl %r19, %r26, %r19 + fldds,ma 8(%r19), %fr4 + fldds,ma 8(%r19), %fr5 + fldds,ma 8(%r19), %fr6 + fldds,ma 8(%r19), %fr7 + fldds,ma 8(%r19), %fr8 + fldds,ma 8(%r19), %fr9 + fldds,ma 8(%r19), %fr10 + fldds,ma 8(%r19), %fr11 + fldds,ma 8(%r19), %fr12 + fldds,ma 8(%r19), %fr13 + fldds,ma 8(%r19), %fr14 + fldds,ma 8(%r19), %fr15 + fldds,ma 8(%r19), %fr16 + fldds,ma 8(%r19), %fr17 + fldds,ma 8(%r19), %fr18 + fldds,ma 8(%r19), %fr19 + fldds,ma 8(%r19), %fr20 + fldds,ma 8(%r19), %fr21 + fldds,ma 8(%r19), %fr22 + fldds,ma 8(%r19), %fr23 + fldds,ma 8(%r19), %fr24 + fldds,ma 8(%r19), %fr25 + fldds,ma 8(%r19), %fr26 + fldds,ma 8(%r19), %fr27 + fldds,ma 8(%r19), %fr28 + fldds,ma 8(%r19), %fr29 + fldds,ma 8(%r19), %fr30 + fldds,ma 8(%r19), %fr31 + ldw 0(%r26), %r2 + ldw 4(%r26), %r1 + ldw 12(%r26), %r3 + ldw 16(%r26), %r4 + ldw 20(%r26), %r5 + ldw 24(%r26), %r6 + ldw 28(%r26), %r7 + ldw 32(%r26), %r8 + ldw 36(%r26), %r9 + ldw 40(%r26), %r10 + ldw 44(%r26), %r11 + ldw 48(%r26), %r12 + ldw 52(%r26), %r13 + ldw 56(%r26), %r14 + ldw 60(%r26), %r15 + ldw 64(%r26), %r16 + ldw 68(%r26), %r17 + ldw 72(%r26), %r18 + ldw 76(%r26), %r19 + ldw 80(%r26), %r20 + ldw 84(%r26), %r21 + ldw 88(%r26), %r22 + ldw 92(%r26), %r23 + ldw 96(%r26), %r24 + ldw 100(%r26), %r25 + ldw 108(%r26), %r27 + ldw 112(%r26), %r28 + ldw 116(%r26), %r29 + ldw 120(%r26), %r30 + ldw 124(%r26), %r31 + ldw 104(%r26), %r26 + bv,n %r0(%r2) +EXIT(_ZNK7_Unwind14Registers_HPPA6jumptoEv) +#endif