commit 55c65bba7017ce9c0533bbc60b5aa1e432f70362 Author: Brandon Bergren Date: Sun Mar 28 20:11:39 2021 -0500 WIP SPE UNWIND diff --git a/libunwind/include/__libunwind_config.h b/libunwind/include/__libunwind_config.h index a50ba053884b..6712f0d802c8 100644 --- a/libunwind/include/__libunwind_config.h +++ b/libunwind/include/__libunwind_config.h @@ -16,7 +16,7 @@ #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 32 -#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 112 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 148 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 116 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 95 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM 287 diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h index 0feecd7bd6fc..771c7d4bd1ac 100644 --- a/libunwind/include/libunwind.h +++ b/libunwind/include/libunwind.h @@ -256,7 +256,7 @@ enum { UNW_PPC_F29 = 61, UNW_PPC_F30 = 62, UNW_PPC_F31 = 63, - UNW_PPC_MQ = 64, + UNW_PPC_MQ = 64, // PPC601 only UNW_PPC_LR = 65, UNW_PPC_CTR = 66, UNW_PPC_AP = 67, @@ -304,7 +304,43 @@ enum { UNW_PPC_VRSAVE = 109, UNW_PPC_VSCR = 110, UNW_PPC_SPE_ACC = 111, - UNW_PPC_SPEFSCR = 112 + UNW_PPC_SPEFSCR = 112, + UNW_PPC_SOFT_FP = 113, + UNW_PPC_TFHAR = 114, + UNW_PPC_TFIAR = 115, + UNW_PPC_TEXASR = 116, + UNW_PPC_SPE_HI_R0 = 117, + UNW_PPC_SPE_HI_R1 = 118, + UNW_PPC_SPE_HI_R2 = 119, + UNW_PPC_SPE_HI_R3 = 120, + UNW_PPC_SPE_HI_R4 = 121, + UNW_PPC_SPE_HI_R5 = 122, + UNW_PPC_SPE_HI_R6 = 123, + UNW_PPC_SPE_HI_R7 = 124, + UNW_PPC_SPE_HI_R8 = 125, + UNW_PPC_SPE_HI_R9 = 126, + UNW_PPC_SPE_HI_R10 = 127, + UNW_PPC_SPE_HI_R11 = 128, + UNW_PPC_SPE_HI_R12 = 129, + UNW_PPC_SPE_HI_R13 = 130, + UNW_PPC_SPE_HI_R14 = 131, + UNW_PPC_SPE_HI_R15 = 132, + UNW_PPC_SPE_HI_R16 = 133, + UNW_PPC_SPE_HI_R17 = 134, + UNW_PPC_SPE_HI_R18 = 135, + UNW_PPC_SPE_HI_R19 = 136, + UNW_PPC_SPE_HI_R20 = 137, + UNW_PPC_SPE_HI_R21 = 138, + UNW_PPC_SPE_HI_R22 = 139, + UNW_PPC_SPE_HI_R23 = 140, + UNW_PPC_SPE_HI_R24 = 141, + UNW_PPC_SPE_HI_R25 = 142, + UNW_PPC_SPE_HI_R26 = 143, + UNW_PPC_SPE_HI_R27 = 144, + UNW_PPC_SPE_HI_R28 = 145, + UNW_PPC_SPE_HI_R29 = 146, + UNW_PPC_SPE_HI_R30 = 147, + UNW_PPC_SPE_HI_R31 = 148 }; // 64-bit ppc register numbers diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp index de0eb6de9d70..1fe14a54168c 100644 --- a/libunwind/src/DwarfParser.hpp +++ b/libunwind/src/DwarfParser.hpp @@ -96,6 +96,15 @@ public: if (IT == InitializeTime::kNormal) memset(this, 0, sizeof(*this)); } + bool convertToUnwindReg(uint64_t ®, int arch) { +#if defined(_LIBUNWIND_TARGET_PPC) + // Handle SPE high half of GPRs. + if (arch == REGISTERS_PPC && reg >= 1200 && reg <= 1231) { + reg = (reg - 1200 + UNW_PPC_SPE_HI_R0); + } +#endif + return (reg <= kMaxRegisterNumber); + } void checkSaveRegister(uint64_t reg, PrologInfo &initialState) { if (!savedRegisters[reg].initialStateSaved) { initialState.savedRegisters[reg] = savedRegisters[reg]; @@ -475,7 +484,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, reg = addressSpace.getULEB128(p, instructionsEnd); offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); return false; @@ -487,7 +496,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_restore_extended: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); return false; @@ -498,7 +507,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_undefined: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_undefined DWARF unwind, reg too big"); return false; @@ -508,7 +517,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_same_value: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_same_value DWARF unwind, reg too big"); return false; @@ -523,12 +532,12 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, case DW_CFA_register: reg = addressSpace.getULEB128(p, instructionsEnd); reg2 = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_register DWARF unwind, reg too big"); return false; } - if (reg2 > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg2, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_register DWARF unwind, reg2 too big"); return false; @@ -568,7 +577,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, case DW_CFA_def_cfa: reg = addressSpace.getULEB128(p, instructionsEnd); offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big"); return false; } @@ -580,7 +589,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_def_cfa_register: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big"); return false; @@ -606,7 +615,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_expression: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_expression DWARF unwind, reg too big"); return false; @@ -623,7 +632,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_offset_extended_sf: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big"); return false; @@ -639,7 +648,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, reg = addressSpace.getULEB128(p, instructionsEnd); offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big"); return false; @@ -659,7 +668,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_val_offset: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG( "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64 ") out of range\n", @@ -675,7 +684,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_val_offset_sf: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big"); return false; @@ -689,7 +698,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_val_expression: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0( "malformed DW_CFA_val_expression DWARF unwind, reg too big"); return false; @@ -711,7 +720,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_GNU_negative_offset_extended: reg = addressSpace.getULEB128(p, instructionsEnd); - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF " "unwind, reg too big"); return false; @@ -768,7 +777,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, switch (opcode & 0xC0) { case DW_CFA_offset: reg = operand; - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 ") out of range", reg); @@ -787,7 +796,7 @@ bool CFI_Parser::parseFDEInstructions(A &addressSpace, break; case DW_CFA_restore: reg = operand; - if (reg > kMaxRegisterNumber) { + if (!results->convertToUnwindReg(reg, arch)) { _LIBUNWIND_LOG( "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 ") out of range", diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp index aea84cc22721..41010fe63b87 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -565,6 +565,8 @@ inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) { #if defined(_LIBUNWIND_TARGET_PPC) +class _LIBUNWIND_HIDDEN Registers_ppc; +extern "C" void __libunwind_Registers_ppc_jumpto(Registers_ppc *); /// Registers_ppc holds the register state of a thread in a 32-bit PowerPC /// process. class _LIBUNWIND_HIDDEN Registers_ppc { @@ -582,7 +584,7 @@ public: v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); static const char *getRegisterName(int num); - void jumpto(); + void jumpto() { __libunwind_Registers_ppc_jumpto(this); } static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; } static int getArch() { return REGISTERS_PPC; } @@ -636,7 +638,13 @@ private: }; struct ppc_float_state_t { - double __fpregs[32]; + union ppc_spe_or_fpr_t { + double f; + struct spereg_s { + uint32_t speHi; + uint32_t __spe_pad; + } spe; + } __fpregs[32]; unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */ unsigned int __fpscr; /* floating point status register */ @@ -690,6 +698,8 @@ inline bool Registers_ppc::validRegister(int regNum) const { return true; if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7)) return true; + if ((UNW_PPC_SPE_HI_R0 <= regNum) && (regNum <= UNW_PPC_SPE_HI_R31)) + return true; return false; } @@ -783,6 +793,39 @@ inline uint32_t Registers_ppc::getRegister(int regNum) const { return (_registers.__cr & 0x0000000F); case UNW_PPC_VRSAVE: return _registers.__vrsave; + case UNW_PPC_SPE_HI_R0: + case UNW_PPC_SPE_HI_R1: + case UNW_PPC_SPE_HI_R2: + case UNW_PPC_SPE_HI_R3: + case UNW_PPC_SPE_HI_R4: + case UNW_PPC_SPE_HI_R5: + case UNW_PPC_SPE_HI_R6: + case UNW_PPC_SPE_HI_R7: + case UNW_PPC_SPE_HI_R8: + case UNW_PPC_SPE_HI_R9: + case UNW_PPC_SPE_HI_R10: + case UNW_PPC_SPE_HI_R11: + case UNW_PPC_SPE_HI_R12: + case UNW_PPC_SPE_HI_R13: + case UNW_PPC_SPE_HI_R14: + case UNW_PPC_SPE_HI_R15: + case UNW_PPC_SPE_HI_R16: + case UNW_PPC_SPE_HI_R17: + case UNW_PPC_SPE_HI_R18: + case UNW_PPC_SPE_HI_R19: + case UNW_PPC_SPE_HI_R20: + case UNW_PPC_SPE_HI_R21: + case UNW_PPC_SPE_HI_R22: + case UNW_PPC_SPE_HI_R23: + case UNW_PPC_SPE_HI_R24: + case UNW_PPC_SPE_HI_R25: + case UNW_PPC_SPE_HI_R26: + case UNW_PPC_SPE_HI_R27: + case UNW_PPC_SPE_HI_R28: + case UNW_PPC_SPE_HI_R29: + case UNW_PPC_SPE_HI_R30: + case UNW_PPC_SPE_HI_R31: + return _floatRegisters.__fpregs[regNum - UNW_PPC_SPE_HI_R0].spe.speHi; } _LIBUNWIND_ABORT("unsupported ppc register"); } @@ -946,6 +989,40 @@ inline void Registers_ppc::setRegister(int regNum, uint32_t value) { case UNW_PPC_SPEFSCR: // not saved return; + case UNW_PPC_SPE_HI_R0: + case UNW_PPC_SPE_HI_R1: + case UNW_PPC_SPE_HI_R2: + case UNW_PPC_SPE_HI_R3: + case UNW_PPC_SPE_HI_R4: + case UNW_PPC_SPE_HI_R5: + case UNW_PPC_SPE_HI_R6: + case UNW_PPC_SPE_HI_R7: + case UNW_PPC_SPE_HI_R8: + case UNW_PPC_SPE_HI_R9: + case UNW_PPC_SPE_HI_R10: + case UNW_PPC_SPE_HI_R11: + case UNW_PPC_SPE_HI_R12: + case UNW_PPC_SPE_HI_R13: + case UNW_PPC_SPE_HI_R14: + case UNW_PPC_SPE_HI_R15: + case UNW_PPC_SPE_HI_R16: + case UNW_PPC_SPE_HI_R17: + case UNW_PPC_SPE_HI_R18: + case UNW_PPC_SPE_HI_R19: + case UNW_PPC_SPE_HI_R20: + case UNW_PPC_SPE_HI_R21: + case UNW_PPC_SPE_HI_R22: + case UNW_PPC_SPE_HI_R23: + case UNW_PPC_SPE_HI_R24: + case UNW_PPC_SPE_HI_R25: + case UNW_PPC_SPE_HI_R26: + case UNW_PPC_SPE_HI_R27: + case UNW_PPC_SPE_HI_R28: + case UNW_PPC_SPE_HI_R29: + case UNW_PPC_SPE_HI_R30: + case UNW_PPC_SPE_HI_R31: + _floatRegisters.__fpregs[regNum - UNW_PPC_SPE_HI_R0].spe.speHi = value; + return; } _LIBUNWIND_ABORT("unsupported ppc register"); } @@ -960,12 +1037,12 @@ inline bool Registers_ppc::validFloatRegister(int regNum) const { inline double Registers_ppc::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); - return _floatRegisters.__fpregs[regNum - UNW_PPC_F0]; + return _floatRegisters.__fpregs[regNum - UNW_PPC_F0].f; } inline void Registers_ppc::setFloatRegister(int regNum, double value) { assert(validFloatRegister(regNum)); - _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value; + _floatRegisters.__fpregs[regNum - UNW_PPC_F0].f = value; } inline bool Registers_ppc::validVectorRegister(int regNum) const { @@ -1123,6 +1200,70 @@ inline const char *Registers_ppc::getRegisterName(int regNum) { return "fp31"; case UNW_PPC_LR: return "lr"; + case UNW_PPC_SPE_HI_R0: + return "Sr0"; + case UNW_PPC_SPE_HI_R1: + return "Sr1"; + case UNW_PPC_SPE_HI_R2: + return "Sr2"; + case UNW_PPC_SPE_HI_R3: + return "Sr3"; + case UNW_PPC_SPE_HI_R4: + return "Sr4"; + case UNW_PPC_SPE_HI_R5: + return "Sr5"; + case UNW_PPC_SPE_HI_R6: + return "Sr6"; + case UNW_PPC_SPE_HI_R7: + return "Sr7"; + case UNW_PPC_SPE_HI_R8: + return "Sr8"; + case UNW_PPC_SPE_HI_R9: + return "Sr9"; + case UNW_PPC_SPE_HI_R10: + return "Sr10"; + case UNW_PPC_SPE_HI_R11: + return "Sr11"; + case UNW_PPC_SPE_HI_R12: + return "Sr12"; + case UNW_PPC_SPE_HI_R13: + return "Sr13"; + case UNW_PPC_SPE_HI_R14: + return "Sr14"; + case UNW_PPC_SPE_HI_R15: + return "Sr15"; + case UNW_PPC_SPE_HI_R16: + return "Sr16"; + case UNW_PPC_SPE_HI_R17: + return "Sr17"; + case UNW_PPC_SPE_HI_R18: + return "Sr18"; + case UNW_PPC_SPE_HI_R19: + return "Sr19"; + case UNW_PPC_SPE_HI_R20: + return "Sr20"; + case UNW_PPC_SPE_HI_R21: + return "Sr21"; + case UNW_PPC_SPE_HI_R22: + return "Sr22"; + case UNW_PPC_SPE_HI_R23: + return "Sr23"; + case UNW_PPC_SPE_HI_R24: + return "Sr24"; + case UNW_PPC_SPE_HI_R25: + return "Sr25"; + case UNW_PPC_SPE_HI_R26: + return "Sr26"; + case UNW_PPC_SPE_HI_R27: + return "Sr27"; + case UNW_PPC_SPE_HI_R28: + return "Sr28"; + case UNW_PPC_SPE_HI_R29: + return "Sr29"; + case UNW_PPC_SPE_HI_R30: + return "Sr30"; + case UNW_PPC_SPE_HI_R31: + return "Sr31"; default: return "unknown register"; } diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index 6d12d93cb102..ec9a2d79676b 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -391,14 +391,54 @@ Lnovec: #elif defined(__ppc__) -DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) +DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_ppc_jumpto) // -// void libunwind::Registers_ppc::jumpto() +// extern "C" void __libunwind_Registers_ppc_jumpto(Registers_ppc *); // // On entry: // thread_state pointer is in r3 // +#if defined(__SPE__) +#define PPC_SPE_LD(n) \ + lwz %r0, (160 + (n * 8))(%r3); \ + evmergelo %r##n, %r0, %r##n; + + // Only changes the upper half of the GPRs. + // skip r0 for now + PPC_SPE_LD(1) + PPC_SPE_LD(2) + PPC_SPE_LD(3) + PPC_SPE_LD(4) + PPC_SPE_LD(5) + PPC_SPE_LD(6) + PPC_SPE_LD(7) + PPC_SPE_LD(8) + PPC_SPE_LD(9) + PPC_SPE_LD(10) + PPC_SPE_LD(11) + PPC_SPE_LD(12) + PPC_SPE_LD(13) + PPC_SPE_LD(14) + PPC_SPE_LD(15) + PPC_SPE_LD(16) + PPC_SPE_LD(17) + PPC_SPE_LD(18) + PPC_SPE_LD(19) + PPC_SPE_LD(20) + PPC_SPE_LD(21) + PPC_SPE_LD(22) + PPC_SPE_LD(23) + PPC_SPE_LD(24) + PPC_SPE_LD(25) + PPC_SPE_LD(26) + PPC_SPE_LD(27) + PPC_SPE_LD(28) + PPC_SPE_LD(29) + PPC_SPE_LD(30) + PPC_SPE_LD(31) +#endif + // restore integral registerrs // skip r0 for now // skip r1 for now @@ -549,14 +589,21 @@ Lnovec: mtcr %r0 lwz %r0, 148(%r3) // __ctr mtctr %r0 - lwz %r0, 0(%r3) // __ssr0 - mtctr %r0 + lwz %r0, 0(%r3) // __srr0 + mtlr %r0 + +#if defined(__SPE__) + lwz %r0, 160(%r3) + evmergelo %r0, %r0, %r0 // upper half of r0 + lwz %r0, 8(%r3) // lower half of r0 +#else lwz %r0, 8(%r3) // do r0 now +#endif lwz %r5, 28(%r3) // do r5 now lwz %r4, 24(%r3) // do r4 now lwz %r1, 12(%r3) // do sp now lwz %r3, 20(%r3) // do r3 last - bctr + blr #elif defined(__aarch64__) diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S index ef39ac1a9b6d..8008e3e3b87b 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -340,7 +340,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) // save GPRs PPC64_STR(0) mflr %r0 - std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0 + std %r0, PPC64_OFFS_SRR0(%r3) // store lr as srr0 PPC64_STR(1) PPC64_STR(2) PPC64_STR(3) @@ -567,7 +567,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) stw %r0, 8(%r3) mflr %r0 - stw %r0, 0(%r3) // store lr as ssr0 + stw %r0, 0(%r3) // store lr as srr0 stw %r1, 12(%r3) stw %r2, 16(%r3) stw %r3, 20(%r3) @@ -610,6 +610,45 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) mfctr %r0 stw %r0, 148(%r3) +#if defined(__SPE__) +#define PPC_SPE_STWHI(n) \ + evmergehi %r0, %r0, %r##n; \ + stw %r0, ((8 * n) + 160)(%r3); + + PPC_SPE_STWHI(0) + PPC_SPE_STWHI(1) + PPC_SPE_STWHI(2) + PPC_SPE_STWHI(3) + PPC_SPE_STWHI(4) + PPC_SPE_STWHI(5) + PPC_SPE_STWHI(6) + PPC_SPE_STWHI(7) + PPC_SPE_STWHI(8) + PPC_SPE_STWHI(9) + PPC_SPE_STWHI(10) + PPC_SPE_STWHI(11) + PPC_SPE_STWHI(12) + PPC_SPE_STWHI(13) + PPC_SPE_STWHI(14) + PPC_SPE_STWHI(15) + PPC_SPE_STWHI(16) + PPC_SPE_STWHI(17) + PPC_SPE_STWHI(18) + PPC_SPE_STWHI(19) + PPC_SPE_STWHI(20) + PPC_SPE_STWHI(21) + PPC_SPE_STWHI(22) + PPC_SPE_STWHI(23) + PPC_SPE_STWHI(24) + PPC_SPE_STWHI(25) + PPC_SPE_STWHI(26) + PPC_SPE_STWHI(27) + PPC_SPE_STWHI(28) + PPC_SPE_STWHI(29) + PPC_SPE_STWHI(30) + PPC_SPE_STWHI(31) +#endif + #if !defined(__NO_FPRS__) // save float registers stfd %f0, 160(%r3) diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h index f5ca35c0c189..3e08ccb33211 100644 --- a/libunwind/src/assembly.h +++ b/libunwind/src/assembly.h @@ -25,6 +25,9 @@ #define PPC64_OFFS_VRSAVE 304 #define PPC64_OFFS_FP 312 #define PPC64_OFFS_V 824 +#elif defined(__ppc__) +#define SEPARATOR ; +#define PPC_OFFS_SRR0 0 #elif defined(__APPLE__) && defined(__aarch64__) #define SEPARATOR %% #elif defined(__riscv)