summaryrefslogtreecommitdiffstats
path: root/lib/libunwind/src
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-02-04 17:04:33 +0000
committerpatrick <patrick@openbsd.org>2019-02-04 17:04:33 +0000
commit71d9f34297ef5b8104aac6236e8dc7c95ff5da15 (patch)
tree92fdcc887ac1b153c5e7da9cb557e6207705d89e /lib/libunwind/src
parentImport libc++ 7.0.1. (diff)
downloadwireguard-openbsd-71d9f34297ef5b8104aac6236e8dc7c95ff5da15.tar.xz
wireguard-openbsd-71d9f34297ef5b8104aac6236e8dc7c95ff5da15.zip
Merge libc++, libc++abi and libunwind version 7.0.1.
Tested by visa on octeon Tested by kettenis on arm64, armv7 and sparc64 "go for it" deraadt and sthen
Diffstat (limited to 'lib/libunwind/src')
-rw-r--r--lib/libunwind/src/AddressSpace.hpp29
-rw-r--r--lib/libunwind/src/DwarfInstructions.hpp4
-rw-r--r--lib/libunwind/src/Registers.hpp329
-rw-r--r--lib/libunwind/src/UnwindCursor.hpp14
-rw-r--r--lib/libunwind/src/UnwindRegistersRestore.S332
-rw-r--r--lib/libunwind/src/UnwindRegistersSave.S294
-rw-r--r--lib/libunwind/src/libunwind.cpp20
7 files changed, 717 insertions, 305 deletions
diff --git a/lib/libunwind/src/AddressSpace.hpp b/lib/libunwind/src/AddressSpace.hpp
index 17145755747..7d1c5249cc9 100644
--- a/lib/libunwind/src/AddressSpace.hpp
+++ b/lib/libunwind/src/AddressSpace.hpp
@@ -18,7 +18,15 @@
#include <stdlib.h>
#include <string.h>
-#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+#ifndef _LIBUNWIND_USE_DLADDR
+ #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+ #define _LIBUNWIND_USE_DLADDR 1
+ #else
+ #define _LIBUNWIND_USE_DLADDR 0
+ #endif
+#endif
+
+#if _LIBUNWIND_USE_DLADDR
#include <dlfcn.h>
#endif
@@ -207,6 +215,7 @@ public:
return val;
}
uintptr_t getP(pint_t addr);
+ uint64_t getRegister(pint_t addr);
static uint64_t getULEB128(pint_t &addr, pint_t end);
static int64_t getSLEB128(pint_t &addr, pint_t end);
@@ -228,6 +237,14 @@ inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
#endif
}
+inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
+#if __SIZEOF_POINTER__ == 8 || defined(__mips64)
+ return get64(addr);
+#else
+ return get32(addr);
+#endif
+}
+
/// Read a ULEB128 into a 64-bit word.
inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
const uint8_t *p = (uint8_t *)addr;
@@ -571,7 +588,7 @@ inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
size_t bufLen,
unw_word_t *offset) {
-#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+#if _LIBUNWIND_USE_DLADDR
Dl_info dyldInfo;
if (dladdr((void *)addr, &dyldInfo)) {
if (dyldInfo.dli_sname != NULL) {
@@ -604,6 +621,7 @@ public:
uint32_t get32(pint_t addr);
uint64_t get64(pint_t addr);
pint_t getP(pint_t addr);
+ uint64_t getRegister(pint_t addr);
uint64_t getULEB128(pint_t &addr, pint_t end);
int64_t getSLEB128(pint_t &addr, pint_t end);
pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
@@ -640,7 +658,12 @@ typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) {
}
template <typename P>
-uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
+typename P::uint_t OtherAddressSpace<P>::getRegister(pint_t addr) {
+ return P::getRegister(*(uint64_t *)localCopy(addr));
+}
+
+template <typename P>
+uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) {
uintptr_t size = (end - addr);
LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr);
LocalAddressSpace::pint_t sladdr = laddr;
diff --git a/lib/libunwind/src/DwarfInstructions.hpp b/lib/libunwind/src/DwarfInstructions.hpp
index eff054e7a06..93de0c0ea57 100644
--- a/lib/libunwind/src/DwarfInstructions.hpp
+++ b/lib/libunwind/src/DwarfInstructions.hpp
@@ -82,14 +82,14 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
const RegisterLocation &savedReg) {
switch (savedReg.location) {
case CFI_Parser<A>::kRegisterInCFA:
- return addressSpace.getP(cfa + (pint_t)savedReg.value);
+ return addressSpace.getRegister(cfa + (pint_t)savedReg.value);
case CFI_Parser<A>::kRegisterInCFADecrypt:
return addressSpace.getP(
cfa + (pint_t)savedReg.value) ^ registers.getWCookie();
case CFI_Parser<A>::kRegisterAtExpression:
- return addressSpace.getP(
+ return addressSpace.getRegister(
evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa));
diff --git a/lib/libunwind/src/Registers.hpp b/lib/libunwind/src/Registers.hpp
index 6676daa1b09..5696357855d 100644
--- a/lib/libunwind/src/Registers.hpp
+++ b/lib/libunwind/src/Registers.hpp
@@ -1110,7 +1110,7 @@ inline const char *Registers_ppc::getRegisterName(int regNum) {
#endif // _LIBUNWIND_TARGET_PPC
#if defined(_LIBUNWIND_TARGET_PPC64)
-/// Registers_ppc holds the register state of a thread in a 64-bit PowerPC
+/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC
/// process.
class _LIBUNWIND_HIDDEN Registers_ppc64 {
public:
@@ -1137,8 +1137,8 @@ public:
private:
struct ppc64_thread_state_t {
- uint64_t __srr0; /* Instruction address register (PC) */
- uint64_t __srr1; /* Machine state register (supervisor) */
+ uint64_t __srr0; // Instruction address register (PC)
+ uint64_t __srr1; // Machine state register (supervisor)
uint64_t __r0;
uint64_t __r1;
uint64_t __r2;
@@ -1171,21 +1171,25 @@ private:
uint64_t __r29;
uint64_t __r30;
uint64_t __r31;
- uint64_t __cr; /* Condition register */
- uint64_t __xer; /* User's integer exception register */
- uint64_t __lr; /* Link register */
- uint64_t __ctr; /* Count register */
- uint64_t __vrsave; /* Vector Save Register */
+ uint64_t __cr; // Condition register
+ uint64_t __xer; // User's integer exception register
+ uint64_t __lr; // Link register
+ uint64_t __ctr; // Count register
+ uint64_t __vrsave; // Vector Save Register
};
- struct ppc64_float_state_t {
- double __fpregs[32];
- uint64_t __fpscr; /* floating point status register */
+ union ppc64_vsr_t {
+ struct asfloat_s {
+ double f;
+ uint64_t v2;
+ } asfloat;
+ v128 v;
};
ppc64_thread_state_t _registers;
- ppc64_float_state_t _floatRegisters;
- v128 _vectorRegisters[32];
+ ppc64_vsr_t _vectorScalarRegisters[64];
+
+ static int getVectorRegNum(int num);
};
inline Registers_ppc64::Registers_ppc64(const void *registers) {
@@ -1193,32 +1197,29 @@ inline Registers_ppc64::Registers_ppc64(const void *registers) {
"ppc64 registers do not fit into unw_context_t");
memcpy(&_registers, static_cast<const uint8_t *>(registers),
sizeof(_registers));
- static_assert(sizeof(ppc64_thread_state_t) == 312,
- "expected float register offset to be 312");
- memcpy(&_floatRegisters,
- static_cast<const uint8_t *>(registers) + sizeof(ppc64_thread_state_t),
- sizeof(_floatRegisters));
- static_assert(sizeof(ppc64_thread_state_t) + sizeof(ppc64_float_state_t) == 576,
- "expected vector register offset to be 576 bytes");
- memcpy(_vectorRegisters,
- static_cast<const uint8_t *>(registers) + sizeof(ppc64_thread_state_t) +
- sizeof(ppc64_float_state_t),
- sizeof(_vectorRegisters));
+ static_assert(sizeof(_registers) == 312,
+ "expected vector scalar register offset to be 312");
+ memcpy(&_vectorScalarRegisters,
+ static_cast<const uint8_t *>(registers) + sizeof(_registers),
+ sizeof(_vectorScalarRegisters));
+ static_assert(sizeof(_registers) +
+ sizeof(_vectorScalarRegisters) == 1336,
+ "expected vector register offset to be 1336 bytes");
}
inline Registers_ppc64::Registers_ppc64() {
memset(&_registers, 0, sizeof(_registers));
- memset(&_floatRegisters, 0, sizeof(_floatRegisters));
- memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
+ memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));
}
inline bool Registers_ppc64::validRegister(int regNum) const {
switch (regNum) {
case UNW_REG_IP:
case UNW_REG_SP:
- case UNW_PPC64_VRSAVE:
+ case UNW_PPC64_XER:
case UNW_PPC64_LR:
case UNW_PPC64_CTR:
+ case UNW_PPC64_VRSAVE:
return true;
}
@@ -1234,11 +1235,10 @@ inline uint64_t Registers_ppc64::getRegister(int regNum) const {
switch (regNum) {
case UNW_REG_IP:
return _registers.__srr0;
- case UNW_REG_SP:
- return _registers.__r1;
case UNW_PPC64_R0:
return _registers.__r0;
case UNW_PPC64_R1:
+ case UNW_REG_SP:
return _registers.__r1;
case UNW_PPC64_R2:
return _registers.__r2;
@@ -1300,10 +1300,6 @@ inline uint64_t Registers_ppc64::getRegister(int regNum) const {
return _registers.__r30;
case UNW_PPC64_R31:
return _registers.__r31;
- case UNW_PPC64_LR:
- return _registers.__lr;
- case UNW_PPC64_CTR:
- return _registers.__ctr;
case UNW_PPC64_CR0:
return (_registers.__cr & 0xF0000000);
case UNW_PPC64_CR1:
@@ -1320,10 +1316,14 @@ inline uint64_t Registers_ppc64::getRegister(int regNum) const {
return (_registers.__cr & 0x000000F0);
case UNW_PPC64_CR7:
return (_registers.__cr & 0x0000000F);
+ case UNW_PPC64_XER:
+ return _registers.__xer;
+ case UNW_PPC64_LR:
+ return _registers.__lr;
+ case UNW_PPC64_CTR:
+ return _registers.__ctr;
case UNW_PPC64_VRSAVE:
return _registers.__vrsave;
- case UNW_PPC64_FPSCR:
- return _floatRegisters.__fpscr;
}
_LIBUNWIND_ABORT("unsupported ppc64 register");
}
@@ -1333,13 +1333,11 @@ inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
case UNW_REG_IP:
_registers.__srr0 = value;
return;
- case UNW_REG_SP:
- _registers.__r1 = value;
- return;
case UNW_PPC64_R0:
_registers.__r0 = value;
return;
case UNW_PPC64_R1:
+ case UNW_REG_SP:
_registers.__r1 = value;
return;
case UNW_PPC64_R2:
@@ -1432,12 +1430,6 @@ inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
case UNW_PPC64_R31:
_registers.__r31 = value;
return;
- case UNW_PPC64_LR:
- _registers.__lr = value;
- return;
- case UNW_PPC64_CTR:
- _registers.__ctr = value;
- return;
case UNW_PPC64_CR0:
_registers.__cr &= 0x0FFFFFFF;
_registers.__cr |= (value & 0xF0000000);
@@ -1470,54 +1462,65 @@ inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
_registers.__cr &= 0xFFFFFFF0;
_registers.__cr |= (value & 0x0000000F);
return;
- case UNW_PPC64_VRSAVE:
- _registers.__vrsave = value;
- return;
case UNW_PPC64_XER:
_registers.__xer = value;
return;
- case UNW_PPC64_VSCR:
- // not saved
+ case UNW_PPC64_LR:
+ _registers.__lr = value;
+ return;
+ case UNW_PPC64_CTR:
+ _registers.__ctr = value;
+ return;
+ case UNW_PPC64_VRSAVE:
+ _registers.__vrsave = value;
return;
}
_LIBUNWIND_ABORT("unsupported ppc64 register");
}
inline bool Registers_ppc64::validFloatRegister(int regNum) const {
- if (regNum < UNW_PPC64_F0)
- return false;
- if (regNum > UNW_PPC64_F31)
- return false;
- return true;
+ return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;
}
inline double Registers_ppc64::getFloatRegister(int regNum) const {
assert(validFloatRegister(regNum));
- return _floatRegisters.__fpregs[regNum - UNW_PPC64_F0];
+ return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;
}
inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
assert(validFloatRegister(regNum));
- _floatRegisters.__fpregs[regNum - UNW_PPC64_F0] = value;
+ _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;
}
inline bool Registers_ppc64::validVectorRegister(int regNum) const {
- if (regNum < UNW_PPC64_V0)
- return false;
- if (regNum > UNW_PPC64_V31)
- return false;
- return true;
+#ifdef PPC64_HAS_VMX
+ if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)
+ return true;
+ if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)
+ return true;
+#else
+ if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)
+ return true;
+#endif
+ return false;
+}
+
+inline int Registers_ppc64::getVectorRegNum(int num)
+{
+ if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)
+ return num - UNW_PPC64_VS0;
+ else
+ return num - UNW_PPC64_VS32 + 32;
}
inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
assert(validVectorRegister(regNum));
- v128 result = _vectorRegisters[regNum - UNW_PPC64_V0];
- return result;
+ return _vectorScalarRegisters[getVectorRegNum(regNum)].v;
}
inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
assert(validVectorRegister(regNum));
- _vectorRegisters[regNum - UNW_PPC64_V0] = value;
+ _vectorScalarRegisters[getVectorRegNum(regNum)].v = value;
}
inline const char *Registers_ppc64::getRegisterName(int regNum) {
@@ -1590,6 +1593,30 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {
return "r30";
case UNW_PPC64_R31:
return "r31";
+ case UNW_PPC64_CR0:
+ return "cr0";
+ case UNW_PPC64_CR1:
+ return "cr1";
+ case UNW_PPC64_CR2:
+ return "cr2";
+ case UNW_PPC64_CR3:
+ return "cr3";
+ case UNW_PPC64_CR4:
+ return "cr4";
+ case UNW_PPC64_CR5:
+ return "cr5";
+ case UNW_PPC64_CR6:
+ return "cr6";
+ case UNW_PPC64_CR7:
+ return "cr7";
+ case UNW_PPC64_XER:
+ return "xer";
+ case UNW_PPC64_LR:
+ return "lr";
+ case UNW_PPC64_CTR:
+ return "ctr";
+ case UNW_PPC64_VRSAVE:
+ return "vrsave";
case UNW_PPC64_F0:
return "fp0";
case UNW_PPC64_F1:
@@ -1654,35 +1681,72 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {
return "fp30";
case UNW_PPC64_F31:
return "fp31";
- case UNW_PPC64_LR:
- return "lr";
- case UNW_PPC64_CTR:
- return "ctr";
- case UNW_PPC64_CR0:
- return "cr0";
- case UNW_PPC64_CR1:
- return "cr1";
- case UNW_PPC64_CR2:
- return "cr2";
- case UNW_PPC64_CR3:
- return "cr3";
- case UNW_PPC64_CR4:
- return "cr4";
- case UNW_PPC64_CR5:
- return "cr5";
- case UNW_PPC64_CR6:
- return "cr6";
- case UNW_PPC64_CR7:
- return "cr7";
- case UNW_PPC64_XER:
- return "xer";
- case UNW_PPC64_VRSAVE:
- return "vrsave";
- case UNW_PPC64_FPSCR:
- return "fpscr";
- default:
- return "unknown register";
+ case UNW_PPC64_V0:
+ return "v0";
+ case UNW_PPC64_V1:
+ return "v1";
+ case UNW_PPC64_V2:
+ return "v2";
+ case UNW_PPC64_V3:
+ return "v3";
+ case UNW_PPC64_V4:
+ return "v4";
+ case UNW_PPC64_V5:
+ return "v5";
+ case UNW_PPC64_V6:
+ return "v6";
+ case UNW_PPC64_V7:
+ return "v7";
+ case UNW_PPC64_V8:
+ return "v8";
+ case UNW_PPC64_V9:
+ return "v9";
+ case UNW_PPC64_V10:
+ return "v10";
+ case UNW_PPC64_V11:
+ return "v11";
+ case UNW_PPC64_V12:
+ return "v12";
+ case UNW_PPC64_V13:
+ return "v13";
+ case UNW_PPC64_V14:
+ return "v14";
+ case UNW_PPC64_V15:
+ return "v15";
+ case UNW_PPC64_V16:
+ return "v16";
+ case UNW_PPC64_V17:
+ return "v17";
+ case UNW_PPC64_V18:
+ return "v18";
+ case UNW_PPC64_V19:
+ return "v19";
+ case UNW_PPC64_V20:
+ return "v20";
+ case UNW_PPC64_V21:
+ return "v21";
+ case UNW_PPC64_V22:
+ return "v22";
+ case UNW_PPC64_V23:
+ return "v23";
+ case UNW_PPC64_V24:
+ return "v24";
+ case UNW_PPC64_V25:
+ return "v25";
+ case UNW_PPC64_V26:
+ return "v26";
+ case UNW_PPC64_V27:
+ return "v27";
+ case UNW_PPC64_V28:
+ return "v28";
+ case UNW_PPC64_V29:
+ return "v29";
+ case UNW_PPC64_V30:
+ return "v30";
+ case UNW_PPC64_V31:
+ return "v31";
}
+ return "unknown register";
}
#endif // _LIBUNWIND_TARGET_PPC64
@@ -2462,13 +2526,15 @@ public:
uint64_t getSP() const { return _registers.__r[1]; }
void setSP(uint32_t value) { _registers.__r[1] = value; }
- uint64_t getIP() const { return _registers.__r[9]; }
- void setIP(uint32_t value) { _registers.__r[9] = value; }
+ uint64_t getIP() const { return _registers.__pc; }
+ void setIP(uint32_t value) { _registers.__pc = value; }
uint64_t getWCookie() const { return 0; }
private:
struct or1k_thread_state_t {
- unsigned int __r[32];
+ unsigned int __r[32]; // r0-r31
+ unsigned int __pc; // Program counter
+ unsigned int __epcr; // Program counter at exception
};
or1k_thread_state_t _registers;
@@ -2494,6 +2560,8 @@ inline bool Registers_or1k::validRegister(int regNum) const {
return false;
if (regNum <= UNW_OR1K_R31)
return true;
+ if (regNum == UNW_OR1K_EPCR)
+ return true;
return false;
}
@@ -2503,9 +2571,11 @@ inline uint32_t Registers_or1k::getRegister(int regNum) const {
switch (regNum) {
case UNW_REG_IP:
- return _registers.__r[9];
+ return _registers.__pc;
case UNW_REG_SP:
return _registers.__r[1];
+ case UNW_OR1K_EPCR:
+ return _registers.__epcr;
}
_LIBUNWIND_ABORT("unsupported or1k register");
}
@@ -2518,11 +2588,14 @@ inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
switch (regNum) {
case UNW_REG_IP:
- _registers.__r[9] = value;
+ _registers.__pc = value;
return;
case UNW_REG_SP:
_registers.__r[1] = value;
return;
+ case UNW_OR1K_EPCR:
+ _registers.__epcr = value;
+ return;
}
_LIBUNWIND_ABORT("unsupported or1k register");
}
@@ -2618,6 +2691,8 @@ inline const char *Registers_or1k::getRegisterName(int regNum) {
return "r30";
case UNW_OR1K_R31:
return "r31";
+ case UNW_OR1K_EPCR:
+ return "EPCR";
default:
return "unknown register";
}
@@ -3088,13 +3163,13 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {
}
#endif // _LIBUNWIND_TARGET_MIPS_O32
-#if defined(_LIBUNWIND_TARGET_MIPS_N64)
-/// Registers_mips_n64 holds the register state of a thread in a 64-bit MIPS
-/// process.
-class _LIBUNWIND_HIDDEN Registers_mips_n64 {
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+/// Registers_mips_newabi holds the register state of a thread in a
+/// MIPS process using NEWABI (the N32 or N64 ABIs).
+class _LIBUNWIND_HIDDEN Registers_mips_newabi {
public:
- Registers_mips_n64();
- Registers_mips_n64(const void *registers);
+ Registers_mips_newabi();
+ Registers_mips_newabi(const void *registers);
bool validRegister(int num) const;
uint64_t getRegister(int num) const;
@@ -3116,31 +3191,31 @@ public:
uint32_t getWCookie() const { return 0; }
private:
- struct mips_n64_thread_state_t {
+ struct mips_newabi_thread_state_t {
uint64_t __r[32];
uint64_t __pc;
uint64_t __hi;
uint64_t __lo;
};
- mips_n64_thread_state_t _registers;
+ mips_newabi_thread_state_t _registers;
#ifdef __mips_hard_float
double _floats[32];
#endif
};
-inline Registers_mips_n64::Registers_mips_n64(const void *registers) {
- static_assert((check_fit<Registers_mips_n64, unw_context_t>::does_fit),
- "mips_n64 registers do not fit into unw_context_t");
+inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {
+ static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),
+ "mips_newabi registers do not fit into unw_context_t");
memcpy(&_registers, static_cast<const uint8_t *>(registers),
sizeof(_registers));
}
-inline Registers_mips_n64::Registers_mips_n64() {
+inline Registers_mips_newabi::Registers_mips_newabi() {
memset(&_registers, 0, sizeof(_registers));
}
-inline bool Registers_mips_n64::validRegister(int regNum) const {
+inline bool Registers_mips_newabi::validRegister(int regNum) const {
if (regNum == UNW_REG_IP)
return true;
if (regNum == UNW_REG_SP)
@@ -3157,7 +3232,7 @@ inline bool Registers_mips_n64::validRegister(int regNum) const {
return false;
}
-inline uint64_t Registers_mips_n64::getRegister(int regNum) const {
+inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
return _registers.__r[regNum - UNW_MIPS_R0];
@@ -3171,10 +3246,10 @@ inline uint64_t Registers_mips_n64::getRegister(int regNum) const {
case UNW_MIPS_LO:
return _registers.__lo;
}
- _LIBUNWIND_ABORT("unsupported mips_n64 register");
+ _LIBUNWIND_ABORT("unsupported mips_newabi register");
}
-inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) {
+inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
_registers.__r[regNum - UNW_MIPS_R0] = value;
return;
@@ -3194,10 +3269,10 @@ inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) {
_registers.__lo = value;
return;
}
- _LIBUNWIND_ABORT("unsupported mips_n64 register");
+ _LIBUNWIND_ABORT("unsupported mips_newabi register");
}
-inline bool Registers_mips_n64::validFloatRegister(int regNum) const {
+inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
#ifdef __mips_hard_float
if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
return true;
@@ -3205,38 +3280,38 @@ inline bool Registers_mips_n64::validFloatRegister(int regNum) const {
return false;
}
-inline double Registers_mips_n64::getFloatRegister(int regNum) const {
+inline double Registers_mips_newabi::getFloatRegister(int regNum) const {
#ifdef __mips_hard_float
assert(validFloatRegister(regNum));
return _floats[regNum - UNW_MIPS_F0];
#else
- _LIBUNWIND_ABORT("mips_n64 float support not implemented");
+ _LIBUNWIND_ABORT("mips_newabi float support not implemented");
#endif
}
-inline void Registers_mips_n64::setFloatRegister(int regNum,
- double value) {
+inline void Registers_mips_newabi::setFloatRegister(int regNum,
+ double value) {
#ifdef __mips_hard_float
assert(validFloatRegister(regNum));
_floats[regNum - UNW_MIPS_F0] = value;
#else
- _LIBUNWIND_ABORT("mips_n64 float support not implemented");
+ _LIBUNWIND_ABORT("mips_newabi float support not implemented");
#endif
}
-inline bool Registers_mips_n64::validVectorRegister(int /* regNum */) const {
+inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
return false;
}
-inline v128 Registers_mips_n64::getVectorRegister(int /* regNum */) const {
- _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
+inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
+ _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
}
-inline void Registers_mips_n64::setVectorRegister(int /* regNum */, v128 /* value */) {
- _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
+inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {
+ _LIBUNWIND_ABORT("mips_newabi vector support not implemented");
}
-inline const char *Registers_mips_n64::getRegisterName(int regNum) {
+inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
switch (regNum) {
case UNW_MIPS_R0:
return "$0";
@@ -3374,7 +3449,7 @@ inline const char *Registers_mips_n64::getRegisterName(int regNum) {
return "unknown register";
}
}
-#endif // _LIBUNWIND_TARGET_MIPS_N64
+#endif // _LIBUNWIND_TARGET_MIPS_NEWABI
} // namespace libunwind
#endif // __REGISTERS_HPP__
diff --git a/lib/libunwind/src/UnwindCursor.hpp b/lib/libunwind/src/UnwindCursor.hpp
index df12a16d5d7..3268bbbedcc 100644
--- a/lib/libunwind/src/UnwindCursor.hpp
+++ b/lib/libunwind/src/UnwindCursor.hpp
@@ -521,8 +521,8 @@ private:
}
#endif
-#if defined(_LIBUNWIND_TARGET_MIPS_N64)
- int stepWithCompactEncoding(Registers_mips_n64 &) {
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+ int stepWithCompactEncoding(Registers_mips_newabi &) {
return UNW_EINVAL;
}
#endif
@@ -583,8 +583,8 @@ private:
}
#endif
-#if defined(_LIBUNWIND_TARGET_MIPS_N64)
- bool compactSaysUseDwarf(Registers_mips_n64 &, uint32_t *) const {
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+ bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {
return true;
}
#endif
@@ -644,8 +644,8 @@ private:
}
#endif
-#if defined (_LIBUNWIND_TARGET_MIPS_N64)
- compact_unwind_encoding_t dwarfEncoding(Registers_mips_n64 &) const {
+#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
+ compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {
return 0;
}
#endif
@@ -1417,8 +1417,6 @@ int UnwindCursor<A, R>::step() {
this->setInfoBasedOnIPRegister(true);
if (_unwindInfoMissing)
return UNW_STEP_END;
- if (_info.gp)
- setReg(UNW_REG_SP, getReg(UNW_REG_SP) + _info.gp);
}
return result;
diff --git a/lib/libunwind/src/UnwindRegistersRestore.S b/lib/libunwind/src/UnwindRegistersRestore.S
index f73b51acf46..92a3f8bb433 100644
--- a/lib/libunwind/src/UnwindRegistersRestore.S
+++ b/lib/libunwind/src/UnwindRegistersRestore.S
@@ -138,89 +138,259 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
// thread_state pointer is in r3
//
+// load register (GPR)
+#define PPC64_LR(n) \
+ ld %r##n, (8 * (n + 2))(%r3)
+
// restore integral registers
// skip r0 for now
// skip r1 for now
- ld %r2, 32(%r3)
+ PPC64_LR(2)
// skip r3 for now
// skip r4 for now
// skip r5 for now
- ld %r6, 64(%r3)
- ld %r7, 72(%r3)
- ld %r8, 80(%r3)
- ld %r9, 88(%r3)
- ld %r10, 96(%r3)
- ld %r11, 104(%r3)
- ld %r12, 112(%r3)
- ld %r13, 120(%r3)
- ld %r14, 128(%r3)
- ld %r15, 136(%r3)
- ld %r16, 144(%r3)
- ld %r17, 152(%r3)
- ld %r18, 160(%r3)
- ld %r19, 168(%r3)
- ld %r20, 176(%r3)
- ld %r21, 184(%r3)
- ld %r22, 192(%r3)
- ld %r23, 200(%r3)
- ld %r24, 208(%r3)
- ld %r25, 216(%r3)
- ld %r26, 224(%r3)
- ld %r27, 232(%r3)
- ld %r28, 240(%r3)
- ld %r29, 248(%r3)
- ld %r30, 256(%r3)
- ld %r31, 264(%r3)
-
- //restore float registers
- lfd %f0, 312(%r3)
- lfd %f1, 320(%r3)
- lfd %f2, 328(%r3)
- lfd %f3, 336(%r3)
- lfd %f4, 344(%r3)
- lfd %f5, 352(%r3)
- lfd %f6, 360(%r3)
- lfd %f7, 368(%r3)
- lfd %f8, 376(%r3)
- lfd %f9, 384(%r3)
- lfd %f10, 392(%r3)
- lfd %f11, 400(%r3)
- lfd %f12, 408(%r3)
- lfd %f13, 416(%r3)
- lfd %f14, 424(%r3)
- lfd %f15, 432(%r3)
- lfd %f16, 440(%r3)
- lfd %f17, 448(%r3)
- lfd %f18, 456(%r3)
- lfd %f19, 464(%r3)
- lfd %f20, 472(%r3)
- lfd %f21, 480(%r3)
- lfd %f22, 488(%r3)
- lfd %f23, 496(%r3)
- lfd %f24, 504(%r3)
- lfd %f25, 512(%r3)
- lfd %f26, 520(%r3)
- lfd %f27, 528(%r3)
- lfd %f28, 536(%r3)
- lfd %f29, 544(%r3)
- lfd %f30, 552(%r3)
- lfd %f31, 560(%r3)
-
- //TODO: restore vector registers
-
- // Lnovec:
- ld %r0, 272(%r3) // __cr
+ PPC64_LR(6)
+ PPC64_LR(7)
+ PPC64_LR(8)
+ PPC64_LR(9)
+ PPC64_LR(10)
+ PPC64_LR(11)
+ PPC64_LR(12)
+ PPC64_LR(13)
+ PPC64_LR(14)
+ PPC64_LR(15)
+ PPC64_LR(16)
+ PPC64_LR(17)
+ PPC64_LR(18)
+ PPC64_LR(19)
+ PPC64_LR(20)
+ PPC64_LR(21)
+ PPC64_LR(22)
+ PPC64_LR(23)
+ PPC64_LR(24)
+ PPC64_LR(25)
+ PPC64_LR(26)
+ PPC64_LR(27)
+ PPC64_LR(28)
+ PPC64_LR(29)
+ PPC64_LR(30)
+ PPC64_LR(31)
+
+#ifdef PPC64_HAS_VMX
+
+ // restore VS registers
+ // (note that this also restores floating point registers and V registers,
+ // because part of VS is mapped to these registers)
+
+ addi %r4, %r3, PPC64_OFFS_FP
+
+// load VS register
+#define PPC64_LVS(n) \
+ lxvd2x %vs##n, 0, %r4 ;\
+ addi %r4, %r4, 16
+
+ // restore the first 32 VS regs (and also all floating point regs)
+ PPC64_LVS(0)
+ PPC64_LVS(1)
+ PPC64_LVS(2)
+ PPC64_LVS(3)
+ PPC64_LVS(4)
+ PPC64_LVS(5)
+ PPC64_LVS(6)
+ PPC64_LVS(7)
+ PPC64_LVS(8)
+ PPC64_LVS(9)
+ PPC64_LVS(10)
+ PPC64_LVS(11)
+ PPC64_LVS(12)
+ PPC64_LVS(13)
+ PPC64_LVS(14)
+ PPC64_LVS(15)
+ PPC64_LVS(16)
+ PPC64_LVS(17)
+ PPC64_LVS(18)
+ PPC64_LVS(19)
+ PPC64_LVS(20)
+ PPC64_LVS(21)
+ PPC64_LVS(22)
+ PPC64_LVS(23)
+ PPC64_LVS(24)
+ PPC64_LVS(25)
+ PPC64_LVS(26)
+ PPC64_LVS(27)
+ PPC64_LVS(28)
+ PPC64_LVS(29)
+ PPC64_LVS(30)
+ PPC64_LVS(31)
+
+ // use VRSAVE to conditionally restore the remaining VS regs,
+ // that are where the V regs are mapped
+
+ ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave
+ cmpwi %r5, 0
+ beq Lnovec
+
+// conditionally load VS
+#define PPC64_CLVS_BOTTOM(n) \
+ beq Ldone##n ;\
+ addi %r4, %r3, PPC64_OFFS_FP + n * 16 ;\
+ lxvd2x %vs##n, 0, %r4 ;\
+Ldone##n:
+
+#define PPC64_CLVSl(n) \
+ andis. %r0, %r5, (1<<(47-n)) ;\
+PPC64_CLVS_BOTTOM(n)
+
+#define PPC64_CLVSh(n) \
+ andi. %r0, %r5, (1<<(63-n)) ;\
+PPC64_CLVS_BOTTOM(n)
+
+ PPC64_CLVSl(32)
+ PPC64_CLVSl(33)
+ PPC64_CLVSl(34)
+ PPC64_CLVSl(35)
+ PPC64_CLVSl(36)
+ PPC64_CLVSl(37)
+ PPC64_CLVSl(38)
+ PPC64_CLVSl(39)
+ PPC64_CLVSl(40)
+ PPC64_CLVSl(41)
+ PPC64_CLVSl(42)
+ PPC64_CLVSl(43)
+ PPC64_CLVSl(44)
+ PPC64_CLVSl(45)
+ PPC64_CLVSl(46)
+ PPC64_CLVSl(47)
+ PPC64_CLVSh(48)
+ PPC64_CLVSh(49)
+ PPC64_CLVSh(50)
+ PPC64_CLVSh(51)
+ PPC64_CLVSh(52)
+ PPC64_CLVSh(53)
+ PPC64_CLVSh(54)
+ PPC64_CLVSh(55)
+ PPC64_CLVSh(56)
+ PPC64_CLVSh(57)
+ PPC64_CLVSh(58)
+ PPC64_CLVSh(59)
+ PPC64_CLVSh(60)
+ PPC64_CLVSh(61)
+ PPC64_CLVSh(62)
+ PPC64_CLVSh(63)
+
+#else
+
+// load FP register
+#define PPC64_LF(n) \
+ lfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
+
+ // restore float registers
+ PPC64_LF(0)
+ PPC64_LF(1)
+ PPC64_LF(2)
+ PPC64_LF(3)
+ PPC64_LF(4)
+ PPC64_LF(5)
+ PPC64_LF(6)
+ PPC64_LF(7)
+ PPC64_LF(8)
+ PPC64_LF(9)
+ PPC64_LF(10)
+ PPC64_LF(11)
+ PPC64_LF(12)
+ PPC64_LF(13)
+ PPC64_LF(14)
+ PPC64_LF(15)
+ PPC64_LF(16)
+ PPC64_LF(17)
+ PPC64_LF(18)
+ PPC64_LF(19)
+ PPC64_LF(20)
+ PPC64_LF(21)
+ PPC64_LF(22)
+ PPC64_LF(23)
+ PPC64_LF(24)
+ PPC64_LF(25)
+ PPC64_LF(26)
+ PPC64_LF(27)
+ PPC64_LF(28)
+ PPC64_LF(29)
+ PPC64_LF(30)
+ PPC64_LF(31)
+
+ // restore vector registers if any are in use
+ ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave
+ cmpwi %r5, 0
+ beq Lnovec
+
+ subi %r4, %r1, 16
+ // r4 is now a 16-byte aligned pointer into the red zone
+ // the _vectorScalarRegisters may not be 16-byte aligned
+ // so copy via red zone temp buffer
+
+#define PPC64_CLV_UNALIGNED_BOTTOM(n) \
+ beq Ldone##n ;\
+ ld %r0, (PPC64_OFFS_V + n * 16)(%r3) ;\
+ std %r0, 0(%r4) ;\
+ ld %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3) ;\
+ std %r0, 8(%r4) ;\
+ lvx %v##n, 0, %r4 ;\
+Ldone ## n:
+
+#define PPC64_CLV_UNALIGNEDl(n) \
+ andis. %r0, %r5, (1<<(15-n)) ;\
+PPC64_CLV_UNALIGNED_BOTTOM(n)
+
+#define PPC64_CLV_UNALIGNEDh(n) \
+ andi. %r0, %r5, (1<<(31-n)) ;\
+PPC64_CLV_UNALIGNED_BOTTOM(n)
+
+ PPC64_CLV_UNALIGNEDl(0)
+ PPC64_CLV_UNALIGNEDl(1)
+ PPC64_CLV_UNALIGNEDl(2)
+ PPC64_CLV_UNALIGNEDl(3)
+ PPC64_CLV_UNALIGNEDl(4)
+ PPC64_CLV_UNALIGNEDl(5)
+ PPC64_CLV_UNALIGNEDl(6)
+ PPC64_CLV_UNALIGNEDl(7)
+ PPC64_CLV_UNALIGNEDl(8)
+ PPC64_CLV_UNALIGNEDl(9)
+ PPC64_CLV_UNALIGNEDl(10)
+ PPC64_CLV_UNALIGNEDl(11)
+ PPC64_CLV_UNALIGNEDl(12)
+ PPC64_CLV_UNALIGNEDl(13)
+ PPC64_CLV_UNALIGNEDl(14)
+ PPC64_CLV_UNALIGNEDl(15)
+ PPC64_CLV_UNALIGNEDh(16)
+ PPC64_CLV_UNALIGNEDh(17)
+ PPC64_CLV_UNALIGNEDh(18)
+ PPC64_CLV_UNALIGNEDh(19)
+ PPC64_CLV_UNALIGNEDh(20)
+ PPC64_CLV_UNALIGNEDh(21)
+ PPC64_CLV_UNALIGNEDh(22)
+ PPC64_CLV_UNALIGNEDh(23)
+ PPC64_CLV_UNALIGNEDh(24)
+ PPC64_CLV_UNALIGNEDh(25)
+ PPC64_CLV_UNALIGNEDh(26)
+ PPC64_CLV_UNALIGNEDh(27)
+ PPC64_CLV_UNALIGNEDh(28)
+ PPC64_CLV_UNALIGNEDh(29)
+ PPC64_CLV_UNALIGNEDh(30)
+ PPC64_CLV_UNALIGNEDh(31)
+
+#endif
+
+Lnovec:
+ ld %r0, PPC64_OFFS_CR(%r3)
mtcr %r0
- ld %r0, 296(%r3) // __ctr
- mtctr %r0
- ld %r0, 0(%r3) // __ssr0
+ ld %r0, PPC64_OFFS_SRR0(%r3)
mtctr %r0
- ld %r0, 16(%r3)
- ld %r5, 56(%r3)
- ld %r4, 48(%r3)
- ld %r1, 24(%r3)
- ld %r3, 40(%r3)
+ PPC64_LR(0)
+ PPC64_LR(5)
+ PPC64_LR(4)
+ PPC64_LR(1)
+ PPC64_LR(3)
bctr
#elif defined(__ppc__)
@@ -588,7 +758,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
# thread_state pointer is in r3
#
- # restore integral registerrs
+ # restore integral registers
l.lwz r0, 0(r3)
l.lwz r1, 4(r3)
l.lwz r2, 8(r3)
@@ -598,7 +768,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
l.lwz r6, 24(r3)
l.lwz r7, 28(r3)
l.lwz r8, 32(r3)
- l.lwz r9, 36(r3)
+ # skip r9
l.lwz r10, 40(r3)
l.lwz r11, 44(r3)
l.lwz r12, 48(r3)
@@ -625,6 +795,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
# at last, restore r3
l.lwz r3, 12(r3)
+ # load new pc into ra
+ l.lwz r9, 128(r3)
# jump to pc
l.jr r9
l.nop
@@ -672,7 +844,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind17Registers_sparc646jumptoEv)
jmpl %o7 + 8, %g0
ldx [%o0 + 0x40], %o0
-#elif defined(__mips__) && defined(_ABIO32)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
//
// void libunwind::Registers_mips_o32::jumpto()
@@ -781,15 +953,15 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
lw $4, (4 * 4)($4)
.set pop
-#elif defined(__mips__) && defined(_ABI64)
+#elif defined(__mips64)
//
-// void libunwind::Registers_mips_n64::jumpto()
+// void libunwind::Registers_mips_newabi::jumpto()
//
// On entry:
// thread state pointer is in a0 ($4)
//
-DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_n646jumptoEv)
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
.set push
.set noat
.set noreorder
diff --git a/lib/libunwind/src/UnwindRegistersSave.S b/lib/libunwind/src/UnwindRegistersSave.S
index bf951d642c1..0df3d5b17a2 100644
--- a/lib/libunwind/src/UnwindRegistersSave.S
+++ b/lib/libunwind/src/UnwindRegistersSave.S
@@ -116,7 +116,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
xorl %eax, %eax # return UNW_ESUCCESS
ret
-#elif defined(__mips__) && defined(_ABIO32)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
#
# extern int unw_getcontext(unw_context_t* thread_state)
@@ -225,7 +225,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
or $2, $0, $0
.set pop
-#elif defined(__mips__) && defined(_ABI64)
+#elif defined(__mips64)
#
# extern int unw_getcontext(unw_context_t* thread_state)
@@ -333,95 +333,223 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
// thread_state pointer is in r3
//
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
- std %r0, 16(%r3)
+
+// store register (GPR)
+#define PPC64_STR(n) \
+ std %r##n, (8 * (n + 2))(%r3)
+
+ // save GPRs
+ PPC64_STR(0)
mflr %r0
- std %r0, 0(%r3) // store lr as ssr0
- std %r1, 24(%r3)
- std %r2, 32(%r3)
- std %r3, 40(%r3)
- std %r4, 48(%r3)
- std %r5, 56(%r3)
- std %r6, 64(%r3)
- std %r7, 72(%r3)
- std %r8, 80(%r3)
- std %r9, 88(%r3)
- std %r10, 96(%r3)
- std %r11, 104(%r3)
- std %r12, 112(%r3)
- std %r13, 120(%r3)
- std %r14, 128(%r3)
- std %r15, 136(%r3)
- std %r16, 144(%r3)
- std %r17, 152(%r3)
- std %r18, 160(%r3)
- std %r19, 168(%r3)
- std %r20, 176(%r3)
- std %r21, 184(%r3)
- std %r22, 192(%r3)
- std %r23, 200(%r3)
- std %r24, 208(%r3)
- std %r25, 216(%r3)
- std %r26, 224(%r3)
- std %r27, 232(%r3)
- std %r28, 240(%r3)
- std %r29, 248(%r3)
- std %r30, 256(%r3)
- std %r31, 264(%r3)
+ std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0
+ PPC64_STR(1)
+ PPC64_STR(2)
+ PPC64_STR(3)
+ PPC64_STR(4)
+ PPC64_STR(5)
+ PPC64_STR(6)
+ PPC64_STR(7)
+ PPC64_STR(8)
+ PPC64_STR(9)
+ PPC64_STR(10)
+ PPC64_STR(11)
+ PPC64_STR(12)
+ PPC64_STR(13)
+ PPC64_STR(14)
+ PPC64_STR(15)
+ PPC64_STR(16)
+ PPC64_STR(17)
+ PPC64_STR(18)
+ PPC64_STR(19)
+ PPC64_STR(20)
+ PPC64_STR(21)
+ PPC64_STR(22)
+ PPC64_STR(23)
+ PPC64_STR(24)
+ PPC64_STR(25)
+ PPC64_STR(26)
+ PPC64_STR(27)
+ PPC64_STR(28)
+ PPC64_STR(29)
+ PPC64_STR(30)
+ PPC64_STR(31)
mfcr %r0
- std %r0, 272(%r3)
-
+ std %r0, PPC64_OFFS_CR(%r3)
mfxer %r0
- std %r0, 280(%r3)
-
+ std %r0, PPC64_OFFS_XER(%r3)
mflr %r0
- std %r0, 288(%r3)
-
+ std %r0, PPC64_OFFS_LR(%r3)
mfctr %r0
- std %r0, 296(%r3)
-
+ std %r0, PPC64_OFFS_CTR(%r3)
mfvrsave %r0
- std %r0, 304(%r3)
+ std %r0, PPC64_OFFS_VRSAVE(%r3)
+
+#ifdef PPC64_HAS_VMX
+ // save VS registers
+ // (note that this also saves floating point registers and V registers,
+ // because part of VS is mapped to these registers)
+
+ addi %r4, %r3, PPC64_OFFS_FP
+
+// store VS register
+#define PPC64_STVS(n) \
+ stxvd2x %vs##n, 0, %r4 ;\
+ addi %r4, %r4, 16
+
+ PPC64_STVS(0)
+ PPC64_STVS(1)
+ PPC64_STVS(2)
+ PPC64_STVS(3)
+ PPC64_STVS(4)
+ PPC64_STVS(5)
+ PPC64_STVS(6)
+ PPC64_STVS(7)
+ PPC64_STVS(8)
+ PPC64_STVS(9)
+ PPC64_STVS(10)
+ PPC64_STVS(11)
+ PPC64_STVS(12)
+ PPC64_STVS(13)
+ PPC64_STVS(14)
+ PPC64_STVS(15)
+ PPC64_STVS(16)
+ PPC64_STVS(17)
+ PPC64_STVS(18)
+ PPC64_STVS(19)
+ PPC64_STVS(20)
+ PPC64_STVS(21)
+ PPC64_STVS(22)
+ PPC64_STVS(23)
+ PPC64_STVS(24)
+ PPC64_STVS(25)
+ PPC64_STVS(26)
+ PPC64_STVS(27)
+ PPC64_STVS(28)
+ PPC64_STVS(29)
+ PPC64_STVS(30)
+ PPC64_STVS(31)
+ PPC64_STVS(32)
+ PPC64_STVS(33)
+ PPC64_STVS(34)
+ PPC64_STVS(35)
+ PPC64_STVS(36)
+ PPC64_STVS(37)
+ PPC64_STVS(38)
+ PPC64_STVS(39)
+ PPC64_STVS(40)
+ PPC64_STVS(41)
+ PPC64_STVS(42)
+ PPC64_STVS(43)
+ PPC64_STVS(44)
+ PPC64_STVS(45)
+ PPC64_STVS(46)
+ PPC64_STVS(47)
+ PPC64_STVS(48)
+ PPC64_STVS(49)
+ PPC64_STVS(50)
+ PPC64_STVS(51)
+ PPC64_STVS(52)
+ PPC64_STVS(53)
+ PPC64_STVS(54)
+ PPC64_STVS(55)
+ PPC64_STVS(56)
+ PPC64_STVS(57)
+ PPC64_STVS(58)
+ PPC64_STVS(59)
+ PPC64_STVS(60)
+ PPC64_STVS(61)
+ PPC64_STVS(62)
+ PPC64_STVS(63)
+
+#else
+
+// store FP register
+#define PPC64_STF(n) \
+ stfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3)
// save float registers
- stfd %f0, 312(%r3)
- stfd %f1, 320(%r3)
- stfd %f2, 328(%r3)
- stfd %f3, 336(%r3)
- stfd %f4, 344(%r3)
- stfd %f5, 352(%r3)
- stfd %f6, 360(%r3)
- stfd %f7, 368(%r3)
- stfd %f8, 376(%r3)
- stfd %f9, 384(%r3)
- stfd %f10, 392(%r3)
- stfd %f11, 400(%r3)
- stfd %f12, 408(%r3)
- stfd %f13, 416(%r3)
- stfd %f14, 424(%r3)
- stfd %f15, 432(%r3)
- stfd %f16, 440(%r3)
- stfd %f17, 448(%r3)
- stfd %f18, 456(%r3)
- stfd %f19, 464(%r3)
- stfd %f20, 472(%r3)
- stfd %f21, 480(%r3)
- stfd %f22, 488(%r3)
- stfd %f23, 496(%r3)
- stfd %f24, 504(%r3)
- stfd %f25, 512(%r3)
- stfd %f26, 520(%r3)
- stfd %f27, 528(%r3)
- stfd %f28, 536(%r3)
- stfd %f29, 544(%r3)
- stfd %f30, 552(%r3)
- stfd %f31, 560(%r3)
-
- mffs %f0
- stfd %f0, 568(%r3)
-
- //TODO: save vector registers
+ PPC64_STF(0)
+ PPC64_STF(1)
+ PPC64_STF(2)
+ PPC64_STF(3)
+ PPC64_STF(4)
+ PPC64_STF(5)
+ PPC64_STF(6)
+ PPC64_STF(7)
+ PPC64_STF(8)
+ PPC64_STF(9)
+ PPC64_STF(10)
+ PPC64_STF(11)
+ PPC64_STF(12)
+ PPC64_STF(13)
+ PPC64_STF(14)
+ PPC64_STF(15)
+ PPC64_STF(16)
+ PPC64_STF(17)
+ PPC64_STF(18)
+ PPC64_STF(19)
+ PPC64_STF(20)
+ PPC64_STF(21)
+ PPC64_STF(22)
+ PPC64_STF(23)
+ PPC64_STF(24)
+ PPC64_STF(25)
+ PPC64_STF(26)
+ PPC64_STF(27)
+ PPC64_STF(28)
+ PPC64_STF(29)
+ PPC64_STF(30)
+ PPC64_STF(31)
+
+ // save vector registers
+
+ // Use 16-bytes below the stack pointer as an
+ // aligned buffer to save each vector register.
+ // Note that the stack pointer is always 16-byte aligned.
+ subi %r4, %r1, 16
+
+#define PPC64_STV_UNALIGNED(n) \
+ stvx %v##n, 0, %r4 ;\
+ ld %r5, 0(%r4) ;\
+ std %r5, (PPC64_OFFS_V + n * 16)(%r3) ;\
+ ld %r5, 8(%r4) ;\
+ std %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3)
+
+ PPC64_STV_UNALIGNED(0)
+ PPC64_STV_UNALIGNED(1)
+ PPC64_STV_UNALIGNED(2)
+ PPC64_STV_UNALIGNED(3)
+ PPC64_STV_UNALIGNED(4)
+ PPC64_STV_UNALIGNED(5)
+ PPC64_STV_UNALIGNED(6)
+ PPC64_STV_UNALIGNED(7)
+ PPC64_STV_UNALIGNED(8)
+ PPC64_STV_UNALIGNED(9)
+ PPC64_STV_UNALIGNED(10)
+ PPC64_STV_UNALIGNED(11)
+ PPC64_STV_UNALIGNED(12)
+ PPC64_STV_UNALIGNED(13)
+ PPC64_STV_UNALIGNED(14)
+ PPC64_STV_UNALIGNED(15)
+ PPC64_STV_UNALIGNED(16)
+ PPC64_STV_UNALIGNED(17)
+ PPC64_STV_UNALIGNED(18)
+ PPC64_STV_UNALIGNED(19)
+ PPC64_STV_UNALIGNED(20)
+ PPC64_STV_UNALIGNED(21)
+ PPC64_STV_UNALIGNED(22)
+ PPC64_STV_UNALIGNED(23)
+ PPC64_STV_UNALIGNED(24)
+ PPC64_STV_UNALIGNED(25)
+ PPC64_STV_UNALIGNED(26)
+ PPC64_STV_UNALIGNED(27)
+ PPC64_STV_UNALIGNED(28)
+ PPC64_STV_UNALIGNED(29)
+ PPC64_STV_UNALIGNED(30)
+ PPC64_STV_UNALIGNED(31)
+#endif
li %r3, 0 // return UNW_ESUCCESS
blr
@@ -810,6 +938,10 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
l.sw 116(r3), r29
l.sw 120(r3), r30
l.sw 124(r3), r31
+ # store ra to pc
+ l.sw 128(r3), r9
+ # zero epcr
+ l.sw 132(r3), r0
#elif defined(__sparc__) && defined(__arch64__)
diff --git a/lib/libunwind/src/libunwind.cpp b/lib/libunwind/src/libunwind.cpp
index 632535ac470..20067994e7a 100644
--- a/lib/libunwind/src/libunwind.cpp
+++ b/lib/libunwind/src/libunwind.cpp
@@ -61,10 +61,10 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
# define REGISTER_KIND Registers_arm
#elif defined(__or1k__)
# define REGISTER_KIND Registers_or1k
-#elif defined(__mips__) && defined(_ABIO32)
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
# define REGISTER_KIND Registers_mips_o32
-#elif defined(__mips__) && defined(_ABI64)
-# define REGISTER_KIND Registers_mips_n64
+#elif defined(__mips64)
+# define REGISTER_KIND Registers_mips_newabi
#elif defined(__mips__)
# warning The MIPS architecture is not supported with this ABI and environment!
#elif defined(__sparc__) && defined(__arch64__)
@@ -190,8 +190,20 @@ _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
co->setReg(regNum, (pint_t)value);
// specical case altering IP to re-find info (being called by personality
// function)
- if (regNum == UNW_REG_IP)
+ if (regNum == UNW_REG_IP) {
+ unw_proc_info_t info;
+ // First, get the FDE for the old location and then update it.
+ co->getInfo(&info);
co->setInfoBasedOnIPRegister(false);
+ // If the original call expects stack adjustment, perform this now.
+ // Normal frame unwinding would have included the offset already in the
+ // CFA computation.
+ // Note: for PA-RISC and other platforms where the stack grows up,
+ // this should actually be - info.gp. LLVM doesn't currently support
+ // any such platforms and Clang doesn't export a macro for them.
+ if (info.gp)
+ co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp);
+ }
return UNW_ESUCCESS;
}
return UNW_EBADREG;