aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2018-03-20 15:44:17 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2018-03-20 15:44:17 +0000
commit1e18e7d203af281fa6441cbb96e3d90eda9398e5 (patch)
tree9c304a2f5e6e44f097372782bcb3a3dc539e38ac /contrib/llvm
parentf6d1be178981716122e4ad4cea13a696b819ccc9 (diff)
downloadsrc-1e18e7d203af281fa6441cbb96e3d90eda9398e5.tar.gz
src-1e18e7d203af281fa6441cbb96e3d90eda9398e5.zip
Add support for MIPS to LLVM's libunwind.
This is originally based on a patch from David Chisnall for soft-float N64 but has since been updated to support O32, N32, and hard-float ABIs. The soft-float O32, N32, and N64 support has been committed upstream. The hard-float changes are still in review upstream. Enable LLVM_LIBUNWIND on mips when building with a suitable (C+11-capable) toolchain. This has been tested with external GCC for all ABIs and O32 and N64 with clang. Reviewed by: emaste Obtained from: CheriBSD (original N64 patch) Sponsored by: DARPA / AFRL Differential Revision: https://reviews.freebsd.org/D14701
Notes
Notes: svn path=/head/; revision=331244
Diffstat (limited to 'contrib/llvm')
-rw-r--r--contrib/llvm/projects/libunwind/include/__libunwind_config.h34
-rw-r--r--contrib/llvm/projects/libunwind/include/libunwind.h70
-rw-r--r--contrib/llvm/projects/libunwind/src/AddressSpace.hpp15
-rw-r--r--contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp4
-rw-r--r--contrib/llvm/projects/libunwind/src/Registers.hpp606
-rw-r--r--contrib/llvm/projects/libunwind/src/UnwindCursor.hpp36
-rw-r--r--contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S199
-rw-r--r--contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S199
-rw-r--r--contrib/llvm/projects/libunwind/src/config.h2
-rw-r--r--contrib/llvm/projects/libunwind/src/libunwind.cpp6
10 files changed, 1167 insertions, 4 deletions
diff --git a/contrib/llvm/projects/libunwind/include/__libunwind_config.h b/contrib/llvm/projects/libunwind/include/__libunwind_config.h
index 750d3317d546..2ce9adf7b5e0 100644
--- a/contrib/llvm/projects/libunwind/include/__libunwind_config.h
+++ b/contrib/llvm/projects/libunwind/include/__libunwind_config.h
@@ -53,6 +53,38 @@
# define _LIBUNWIND_CONTEXT_SIZE 64
# define _LIBUNWIND_CURSOR_SIZE 76
# define _LIBUNWIND_MAX_REGISTER 96
+# elif defined(__mips__)
+# if defined(_ABIO32) && _MIPS_SIM == _ABIO32
+# define _LIBUNWIND_TARGET_MIPS_O32 1
+# if defined(__mips_hard_float)
+# define _LIBUNWIND_CONTEXT_SIZE 50
+# define _LIBUNWIND_CURSOR_SIZE 61
+# else
+# define _LIBUNWIND_CONTEXT_SIZE 18
+# define _LIBUNWIND_CURSOR_SIZE 29
+# endif
+# elif defined(_ABIN32) && _MIPS_SIM == _ABIN32
+# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
+# if defined(__mips_hard_float)
+# define _LIBUNWIND_CONTEXT_SIZE 67
+# define _LIBUNWIND_CURSOR_SIZE 78
+# else
+# define _LIBUNWIND_CONTEXT_SIZE 35
+# define _LIBUNWIND_CURSOR_SIZE 46
+# endif
+# elif defined(_ABI64) && _MIPS_SIM == _ABI64
+# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
+# if defined(__mips_hard_float)
+# define _LIBUNWIND_CONTEXT_SIZE 67
+# define _LIBUNWIND_CURSOR_SIZE 79
+# else
+# define _LIBUNWIND_CONTEXT_SIZE 35
+# define _LIBUNWIND_CURSOR_SIZE 47
+# endif
+# else
+# error "Unsupported MIPS ABI and/or environment"
+# endif
+# define _LIBUNWIND_MAX_REGISTER 66
# else
# error "Unsupported architecture."
# endif
@@ -63,6 +95,8 @@
# define _LIBUNWIND_TARGET_AARCH64 1
# define _LIBUNWIND_TARGET_ARM 1
# define _LIBUNWIND_TARGET_OR1K 1
+# define _LIBUNWIND_TARGET_MIPS_O32 1
+# define _LIBUNWIND_TARGET_MIPS_NEWABI 1
# define _LIBUNWIND_CONTEXT_SIZE 128
# define _LIBUNWIND_CURSOR_SIZE 140
# define _LIBUNWIND_MAX_REGISTER 120
diff --git a/contrib/llvm/projects/libunwind/include/libunwind.h b/contrib/llvm/projects/libunwind/include/libunwind.h
index f583f530fac9..efeb9e8610e8 100644
--- a/contrib/llvm/projects/libunwind/include/libunwind.h
+++ b/contrib/llvm/projects/libunwind/include/libunwind.h
@@ -604,4 +604,74 @@ enum {
UNW_RISCV_D31 = 95,
};
+// MIPS registers
+enum {
+ UNW_MIPS_R0 = 0,
+ UNW_MIPS_R1 = 1,
+ UNW_MIPS_R2 = 2,
+ UNW_MIPS_R3 = 3,
+ UNW_MIPS_R4 = 4,
+ UNW_MIPS_R5 = 5,
+ UNW_MIPS_R6 = 6,
+ UNW_MIPS_R7 = 7,
+ UNW_MIPS_R8 = 8,
+ UNW_MIPS_R9 = 9,
+ UNW_MIPS_R10 = 10,
+ UNW_MIPS_R11 = 11,
+ UNW_MIPS_R12 = 12,
+ UNW_MIPS_R13 = 13,
+ UNW_MIPS_R14 = 14,
+ UNW_MIPS_R15 = 15,
+ UNW_MIPS_R16 = 16,
+ UNW_MIPS_R17 = 17,
+ UNW_MIPS_R18 = 18,
+ UNW_MIPS_R19 = 19,
+ UNW_MIPS_R20 = 20,
+ UNW_MIPS_R21 = 21,
+ UNW_MIPS_R22 = 22,
+ UNW_MIPS_R23 = 23,
+ UNW_MIPS_R24 = 24,
+ UNW_MIPS_R25 = 25,
+ UNW_MIPS_R26 = 26,
+ UNW_MIPS_R27 = 27,
+ UNW_MIPS_R28 = 28,
+ UNW_MIPS_R29 = 29,
+ UNW_MIPS_R30 = 30,
+ UNW_MIPS_R31 = 31,
+ UNW_MIPS_F0 = 32,
+ UNW_MIPS_F1 = 33,
+ UNW_MIPS_F2 = 34,
+ UNW_MIPS_F3 = 35,
+ UNW_MIPS_F4 = 36,
+ UNW_MIPS_F5 = 37,
+ UNW_MIPS_F6 = 38,
+ UNW_MIPS_F7 = 39,
+ UNW_MIPS_F8 = 40,
+ UNW_MIPS_F9 = 41,
+ UNW_MIPS_F10 = 42,
+ UNW_MIPS_F11 = 43,
+ UNW_MIPS_F12 = 44,
+ UNW_MIPS_F13 = 45,
+ UNW_MIPS_F14 = 46,
+ UNW_MIPS_F15 = 47,
+ UNW_MIPS_F16 = 48,
+ UNW_MIPS_F17 = 49,
+ UNW_MIPS_F18 = 50,
+ UNW_MIPS_F19 = 51,
+ UNW_MIPS_F20 = 52,
+ UNW_MIPS_F21 = 53,
+ UNW_MIPS_F22 = 54,
+ UNW_MIPS_F23 = 55,
+ UNW_MIPS_F24 = 56,
+ UNW_MIPS_F25 = 57,
+ UNW_MIPS_F26 = 58,
+ UNW_MIPS_F27 = 59,
+ UNW_MIPS_F28 = 60,
+ UNW_MIPS_F29 = 61,
+ UNW_MIPS_F30 = 62,
+ UNW_MIPS_F31 = 63,
+ UNW_MIPS_HI = 64,
+ UNW_MIPS_LO = 65,
+};
+
#endif
diff --git a/contrib/llvm/projects/libunwind/src/AddressSpace.hpp b/contrib/llvm/projects/libunwind/src/AddressSpace.hpp
index d9ea3db36c26..afd2c05a0ea2 100644
--- a/contrib/llvm/projects/libunwind/src/AddressSpace.hpp
+++ b/contrib/llvm/projects/libunwind/src/AddressSpace.hpp
@@ -148,6 +148,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);
@@ -169,6 +170,14 @@ inline uintptr_t LocalAddressSpace::getP(pint_t addr) {
#endif
}
+inline uint64_t LocalAddressSpace::getRegister(pint_t addr) {
+#if defined(__LP64__) || 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;
@@ -496,6 +505,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,
@@ -532,6 +542,11 @@ typename P::uint_t OtherAddressSpace<P>::getP(pint_t addr) {
}
template <typename P>
+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);
diff --git a/contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp b/contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp
index ce90aa05f534..8382ac6f8ede 100644
--- a/contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp
+++ b/contrib/llvm/projects/libunwind/src/DwarfInstructions.hpp
@@ -83,10 +83,10 @@ 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>::kRegisterAtExpression:
- return addressSpace.getP(
+ return addressSpace.getRegister(
evaluateExpression((pint_t)savedReg.value, addressSpace,
registers, cfa));
diff --git a/contrib/llvm/projects/libunwind/src/Registers.hpp b/contrib/llvm/projects/libunwind/src/Registers.hpp
index e17629801ffb..7762414cacc1 100644
--- a/contrib/llvm/projects/libunwind/src/Registers.hpp
+++ b/contrib/llvm/projects/libunwind/src/Registers.hpp
@@ -2168,6 +2168,612 @@ inline void Registers_riscv::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("no riscv vector register support yet");
}
#endif // _LIBUNWIND_TARGET_RISCV
+
+#if defined(_LIBUNWIND_TARGET_MIPS_O32)
+/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS
+/// process.
+class _LIBUNWIND_HIDDEN Registers_mips_o32 {
+public:
+ Registers_mips_o32();
+ Registers_mips_o32(const void *registers);
+
+ bool validRegister(int num) const;
+ uint32_t getRegister(int num) const;
+ void setRegister(int num, uint32_t value);
+ bool validFloatRegister(int num) const;
+ double getFloatRegister(int num) const;
+ void setFloatRegister(int num, double value);
+ bool validVectorRegister(int num) const;
+ v128 getVectorRegister(int num) const;
+ void setVectorRegister(int num, v128 value);
+ const char *getRegisterName(int num);
+ void jumpto();
+ static int lastDwarfRegNum() { return 65; }
+
+ uint32_t getSP() const { return _registers.__r[29]; }
+ void setSP(uint32_t value) { _registers.__r[29] = value; }
+ uint32_t getIP() const { return _registers.__pc; }
+ void setIP(uint32_t value) { _registers.__pc = value; }
+
+private:
+ struct mips_o32_thread_state_t {
+ uint32_t __r[32];
+ uint32_t __pc;
+ uint32_t __hi;
+ uint32_t __lo;
+ };
+
+ mips_o32_thread_state_t _registers;
+#ifdef __mips_hard_float
+ /// O32 with 32-bit floating point registers only uses half of this
+ /// space. However, using the same layout for 32-bit vs 64-bit
+ /// floating point registers results in a single context size for
+ /// O32 with hard float.
+ uint32_t _padding;
+ double _floats[32];
+#endif
+};
+
+inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
+ static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),
+ "mips_o32 registers do not fit into unw_context_t");
+ memcpy(&_registers, static_cast<const uint8_t *>(registers),
+ sizeof(_registers));
+}
+
+inline Registers_mips_o32::Registers_mips_o32() {
+ memset(&_registers, 0, sizeof(_registers));
+}
+
+inline bool Registers_mips_o32::validRegister(int regNum) const {
+ if (regNum == UNW_REG_IP)
+ return true;
+ if (regNum == UNW_REG_SP)
+ return true;
+ if (regNum < 0)
+ return false;
+ if (regNum <= UNW_MIPS_R31)
+ return true;
+ if (regNum == UNW_MIPS_HI)
+ return true;
+ if (regNum == UNW_MIPS_LO)
+ return true;
+#if defined(__mips_hard_float) && __mips_fpr == 32
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+ return true;
+#endif
+ // FIXME: DSP accumulator registers, MSA registers
+ return false;
+}
+
+inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
+ if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)
+ return _registers.__r[regNum - UNW_MIPS_R0];
+#if defined(__mips_hard_float) && __mips_fpr == 32
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
+ uint32_t *p;
+
+ if (regNum % 2 == 0)
+ p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
+ else
+ p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
+ return *p;
+ }
+#endif
+
+ switch (regNum) {
+ case UNW_REG_IP:
+ return _registers.__pc;
+ case UNW_REG_SP:
+ return _registers.__r[29];
+ case UNW_MIPS_HI:
+ return _registers.__hi;
+ case UNW_MIPS_LO:
+ return _registers.__lo;
+ }
+ _LIBUNWIND_ABORT("unsupported mips_o32 register");
+}
+
+inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
+ if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {
+ _registers.__r[regNum - UNW_MIPS_R0] = value;
+ return;
+ }
+#if defined(__mips_hard_float) && __mips_fpr == 32
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
+ uint32_t *p;
+
+ if (regNum % 2 == 0)
+ p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
+ else
+ p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
+ *p = value;
+ return;
+ }
+#endif
+
+ switch (regNum) {
+ case UNW_REG_IP:
+ _registers.__pc = value;
+ return;
+ case UNW_REG_SP:
+ _registers.__r[29] = value;
+ return;
+ case UNW_MIPS_HI:
+ _registers.__hi = value;
+ return;
+ case UNW_MIPS_LO:
+ _registers.__lo = value;
+ return;
+ }
+ _LIBUNWIND_ABORT("unsupported mips_o32 register");
+}
+
+inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+ return true;
+#endif
+ return false;
+}
+
+inline double Registers_mips_o32::getFloatRegister(int regNum) const {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+ assert(validFloatRegister(regNum));
+ return _floats[regNum - UNW_MIPS_F0];
+#else
+ _LIBUNWIND_ABORT("mips_o32 float support not implemented");
+#endif
+}
+
+inline void Registers_mips_o32::setFloatRegister(int regNum,
+ double value) {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+ assert(validFloatRegister(regNum));
+ _floats[regNum - UNW_MIPS_F0] = value;
+#else
+ _LIBUNWIND_ABORT("mips_o32 float support not implemented");
+#endif
+}
+
+inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
+ return false;
+}
+
+inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {
+ _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
+}
+
+inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {
+ _LIBUNWIND_ABORT("mips_o32 vector support not implemented");
+}
+
+inline const char *Registers_mips_o32::getRegisterName(int regNum) {
+ switch (regNum) {
+ case UNW_MIPS_R0:
+ return "$0";
+ case UNW_MIPS_R1:
+ return "$1";
+ case UNW_MIPS_R2:
+ return "$2";
+ case UNW_MIPS_R3:
+ return "$3";
+ case UNW_MIPS_R4:
+ return "$4";
+ case UNW_MIPS_R5:
+ return "$5";
+ case UNW_MIPS_R6:
+ return "$6";
+ case UNW_MIPS_R7:
+ return "$7";
+ case UNW_MIPS_R8:
+ return "$8";
+ case UNW_MIPS_R9:
+ return "$9";
+ case UNW_MIPS_R10:
+ return "$10";
+ case UNW_MIPS_R11:
+ return "$11";
+ case UNW_MIPS_R12:
+ return "$12";
+ case UNW_MIPS_R13:
+ return "$13";
+ case UNW_MIPS_R14:
+ return "$14";
+ case UNW_MIPS_R15:
+ return "$15";
+ case UNW_MIPS_R16:
+ return "$16";
+ case UNW_MIPS_R17:
+ return "$17";
+ case UNW_MIPS_R18:
+ return "$18";
+ case UNW_MIPS_R19:
+ return "$19";
+ case UNW_MIPS_R20:
+ return "$20";
+ case UNW_MIPS_R21:
+ return "$21";
+ case UNW_MIPS_R22:
+ return "$22";
+ case UNW_MIPS_R23:
+ return "$23";
+ case UNW_MIPS_R24:
+ return "$24";
+ case UNW_MIPS_R25:
+ return "$25";
+ case UNW_MIPS_R26:
+ return "$26";
+ case UNW_MIPS_R27:
+ return "$27";
+ case UNW_MIPS_R28:
+ return "$28";
+ case UNW_MIPS_R29:
+ return "$29";
+ case UNW_MIPS_R30:
+ return "$30";
+ case UNW_MIPS_R31:
+ return "$31";
+ case UNW_MIPS_F0:
+ return "$f0";
+ case UNW_MIPS_F1:
+ return "$f1";
+ case UNW_MIPS_F2:
+ return "$f2";
+ case UNW_MIPS_F3:
+ return "$f3";
+ case UNW_MIPS_F4:
+ return "$f4";
+ case UNW_MIPS_F5:
+ return "$f5";
+ case UNW_MIPS_F6:
+ return "$f6";
+ case UNW_MIPS_F7:
+ return "$f7";
+ case UNW_MIPS_F8:
+ return "$f8";
+ case UNW_MIPS_F9:
+ return "$f9";
+ case UNW_MIPS_F10:
+ return "$f10";
+ case UNW_MIPS_F11:
+ return "$f11";
+ case UNW_MIPS_F12:
+ return "$f12";
+ case UNW_MIPS_F13:
+ return "$f13";
+ case UNW_MIPS_F14:
+ return "$f14";
+ case UNW_MIPS_F15:
+ return "$f15";
+ case UNW_MIPS_F16:
+ return "$f16";
+ case UNW_MIPS_F17:
+ return "$f17";
+ case UNW_MIPS_F18:
+ return "$f18";
+ case UNW_MIPS_F19:
+ return "$f19";
+ case UNW_MIPS_F20:
+ return "$f20";
+ case UNW_MIPS_F21:
+ return "$f21";
+ case UNW_MIPS_F22:
+ return "$f22";
+ case UNW_MIPS_F23:
+ return "$f23";
+ case UNW_MIPS_F24:
+ return "$f24";
+ case UNW_MIPS_F25:
+ return "$f25";
+ case UNW_MIPS_F26:
+ return "$f26";
+ case UNW_MIPS_F27:
+ return "$f27";
+ case UNW_MIPS_F28:
+ return "$f28";
+ case UNW_MIPS_F29:
+ return "$f29";
+ case UNW_MIPS_F30:
+ return "$f30";
+ case UNW_MIPS_F31:
+ return "$f31";
+ case UNW_MIPS_HI:
+ return "$hi";
+ case UNW_MIPS_LO:
+ return "$lo";
+ default:
+ return "unknown register";
+ }
+}
+#endif // _LIBUNWIND_TARGET_MIPS_O32
+
+#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_newabi();
+ Registers_mips_newabi(const void *registers);
+
+ bool validRegister(int num) const;
+ uint64_t getRegister(int num) const;
+ void setRegister(int num, uint64_t value);
+ bool validFloatRegister(int num) const;
+ double getFloatRegister(int num) const;
+ void setFloatRegister(int num, double value);
+ bool validVectorRegister(int num) const;
+ v128 getVectorRegister(int num) const;
+ void setVectorRegister(int num, v128 value);
+ const char *getRegisterName(int num);
+ void jumpto();
+ static int lastDwarfRegNum() { return 65; }
+
+ uint64_t getSP() const { return _registers.__r[29]; }
+ void setSP(uint64_t value) { _registers.__r[29] = value; }
+ uint64_t getIP() const { return _registers.__pc; }
+ void setIP(uint64_t value) { _registers.__pc = value; }
+
+private:
+ struct mips_newabi_thread_state_t {
+ uint64_t __r[32];
+ uint64_t __pc;
+ uint64_t __hi;
+ uint64_t __lo;
+ };
+
+ mips_newabi_thread_state_t _registers;
+#ifdef __mips_hard_float
+ double _floats[32];
+#endif
+};
+
+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_newabi::Registers_mips_newabi() {
+ memset(&_registers, 0, sizeof(_registers));
+}
+
+inline bool Registers_mips_newabi::validRegister(int regNum) const {
+ if (regNum == UNW_REG_IP)
+ return true;
+ if (regNum == UNW_REG_SP)
+ return true;
+ if (regNum < 0)
+ return false;
+ if (regNum <= UNW_MIPS_R31)
+ return true;
+ if (regNum == UNW_MIPS_HI)
+ return true;
+ if (regNum == UNW_MIPS_LO)
+ return true;
+ // FIXME: Hard float, DSP accumulator registers, MSA registers
+ return false;
+}
+
+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];
+
+ switch (regNum) {
+ case UNW_REG_IP:
+ return _registers.__pc;
+ case UNW_REG_SP:
+ return _registers.__r[29];
+ case UNW_MIPS_HI:
+ return _registers.__hi;
+ case UNW_MIPS_LO:
+ return _registers.__lo;
+ }
+ _LIBUNWIND_ABORT("unsupported mips_newabi register");
+}
+
+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;
+ }
+
+ switch (regNum) {
+ case UNW_REG_IP:
+ _registers.__pc = value;
+ return;
+ case UNW_REG_SP:
+ _registers.__r[29] = value;
+ return;
+ case UNW_MIPS_HI:
+ _registers.__hi = value;
+ return;
+ case UNW_MIPS_LO:
+ _registers.__lo = value;
+ return;
+ }
+ _LIBUNWIND_ABORT("unsupported mips_newabi register");
+}
+
+inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {
+#ifdef __mips_hard_float
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+ return true;
+#endif
+ return false;
+}
+
+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_newabi float support not implemented");
+#endif
+}
+
+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_newabi float support not implemented");
+#endif
+}
+
+inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {
+ return false;
+}
+
+inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {
+ _LIBUNWIND_ABORT("mips_newabi 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_newabi::getRegisterName(int regNum) {
+ switch (regNum) {
+ case UNW_MIPS_R0:
+ return "$0";
+ case UNW_MIPS_R1:
+ return "$1";
+ case UNW_MIPS_R2:
+ return "$2";
+ case UNW_MIPS_R3:
+ return "$3";
+ case UNW_MIPS_R4:
+ return "$4";
+ case UNW_MIPS_R5:
+ return "$5";
+ case UNW_MIPS_R6:
+ return "$6";
+ case UNW_MIPS_R7:
+ return "$7";
+ case UNW_MIPS_R8:
+ return "$8";
+ case UNW_MIPS_R9:
+ return "$9";
+ case UNW_MIPS_R10:
+ return "$10";
+ case UNW_MIPS_R11:
+ return "$11";
+ case UNW_MIPS_R12:
+ return "$12";
+ case UNW_MIPS_R13:
+ return "$13";
+ case UNW_MIPS_R14:
+ return "$14";
+ case UNW_MIPS_R15:
+ return "$15";
+ case UNW_MIPS_R16:
+ return "$16";
+ case UNW_MIPS_R17:
+ return "$17";
+ case UNW_MIPS_R18:
+ return "$18";
+ case UNW_MIPS_R19:
+ return "$19";
+ case UNW_MIPS_R20:
+ return "$20";
+ case UNW_MIPS_R21:
+ return "$21";
+ case UNW_MIPS_R22:
+ return "$22";
+ case UNW_MIPS_R23:
+ return "$23";
+ case UNW_MIPS_R24:
+ return "$24";
+ case UNW_MIPS_R25:
+ return "$25";
+ case UNW_MIPS_R26:
+ return "$26";
+ case UNW_MIPS_R27:
+ return "$27";
+ case UNW_MIPS_R28:
+ return "$28";
+ case UNW_MIPS_R29:
+ return "$29";
+ case UNW_MIPS_R30:
+ return "$30";
+ case UNW_MIPS_R31:
+ return "$31";
+ case UNW_MIPS_F0:
+ return "$f0";
+ case UNW_MIPS_F1:
+ return "$f1";
+ case UNW_MIPS_F2:
+ return "$f2";
+ case UNW_MIPS_F3:
+ return "$f3";
+ case UNW_MIPS_F4:
+ return "$f4";
+ case UNW_MIPS_F5:
+ return "$f5";
+ case UNW_MIPS_F6:
+ return "$f6";
+ case UNW_MIPS_F7:
+ return "$f7";
+ case UNW_MIPS_F8:
+ return "$f8";
+ case UNW_MIPS_F9:
+ return "$f9";
+ case UNW_MIPS_F10:
+ return "$f10";
+ case UNW_MIPS_F11:
+ return "$f11";
+ case UNW_MIPS_F12:
+ return "$f12";
+ case UNW_MIPS_F13:
+ return "$f13";
+ case UNW_MIPS_F14:
+ return "$f14";
+ case UNW_MIPS_F15:
+ return "$f15";
+ case UNW_MIPS_F16:
+ return "$f16";
+ case UNW_MIPS_F17:
+ return "$f17";
+ case UNW_MIPS_F18:
+ return "$f18";
+ case UNW_MIPS_F19:
+ return "$f19";
+ case UNW_MIPS_F20:
+ return "$f20";
+ case UNW_MIPS_F21:
+ return "$f21";
+ case UNW_MIPS_F22:
+ return "$f22";
+ case UNW_MIPS_F23:
+ return "$f23";
+ case UNW_MIPS_F24:
+ return "$f24";
+ case UNW_MIPS_F25:
+ return "$f25";
+ case UNW_MIPS_F26:
+ return "$f26";
+ case UNW_MIPS_F27:
+ return "$f27";
+ case UNW_MIPS_F28:
+ return "$f28";
+ case UNW_MIPS_F29:
+ return "$f29";
+ case UNW_MIPS_F30:
+ return "$f30";
+ case UNW_MIPS_F31:
+ return "$f31";
+ case UNW_MIPS_HI:
+ return "$hi";
+ case UNW_MIPS_LO:
+ return "$lo";
+ default:
+ return "unknown register";
+ }
+}
+#endif // _LIBUNWIND_TARGET_MIPS_NEWABI
} // namespace libunwind
#endif // __REGISTERS_HPP__
diff --git a/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp b/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp
index 6d1cfaa03003..f661d9395ef3 100644
--- a/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp
+++ b/contrib/llvm/projects/libunwind/src/UnwindCursor.hpp
@@ -508,6 +508,18 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_MIPS_O32)
+ int stepWithCompactEncoding(Registers_mips_o32 &) {
+ return UNW_EINVAL;
+ }
+#endif
+
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+ int stepWithCompactEncoding(Registers_mips_newabi &) {
+ return UNW_EINVAL;
+ }
+#endif
+
bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
R dummy;
return compactSaysUseDwarf(dummy, offset);
@@ -551,6 +563,18 @@ private:
return false;
}
#endif
+
+#if defined(_LIBUNWIND_TARGET_MIPS_O32)
+ bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const {
+ return true;
+ }
+#endif
+
+#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
+ bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {
+ return true;
+ }
+#endif
#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
@@ -594,6 +618,18 @@ private:
return 0;
}
#endif
+
+#if defined (_LIBUNWIND_TARGET_MIPS_O32)
+ compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const {
+ return 0;
+ }
+#endif
+
+#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
+ compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {
+ return 0;
+ }
+#endif
#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
diff --git a/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S b/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S
index 2330fc2adb5f..9c38623a4384 100644
--- a/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S
+++ b/contrib/llvm/projects/libunwind/src/UnwindRegistersRestore.S
@@ -526,6 +526,205 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv)
ret // jump to ra
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
+
+//
+// void libunwind::Registers_mips_o32::jumpto()
+//
+// On entry:
+// thread state pointer is in a0 ($4)
+//
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
+ .set push
+ .set noat
+ .set noreorder
+ .set nomacro
+#ifdef __mips_hard_float
+#if __mips_fpr == 32
+ ldc1 $f0, (4 * 36 + 8 * 0)($4)
+ ldc1 $f2, (4 * 36 + 8 * 2)($4)
+ ldc1 $f4, (4 * 36 + 8 * 4)($4)
+ ldc1 $f6, (4 * 36 + 8 * 6)($4)
+ ldc1 $f8, (4 * 36 + 8 * 8)($4)
+ ldc1 $f10, (4 * 36 + 8 * 10)($4)
+ ldc1 $f12, (4 * 36 + 8 * 12)($4)
+ ldc1 $f14, (4 * 36 + 8 * 14)($4)
+ ldc1 $f16, (4 * 36 + 8 * 16)($4)
+ ldc1 $f18, (4 * 36 + 8 * 18)($4)
+ ldc1 $f20, (4 * 36 + 8 * 20)($4)
+ ldc1 $f22, (4 * 36 + 8 * 22)($4)
+ ldc1 $f24, (4 * 36 + 8 * 24)($4)
+ ldc1 $f26, (4 * 36 + 8 * 26)($4)
+ ldc1 $f28, (4 * 36 + 8 * 28)($4)
+ ldc1 $f30, (4 * 36 + 8 * 30)($4)
+#else
+ ldc1 $f0, (4 * 36 + 8 * 0)($4)
+ ldc1 $f1, (4 * 36 + 8 * 1)($4)
+ ldc1 $f2, (4 * 36 + 8 * 2)($4)
+ ldc1 $f3, (4 * 36 + 8 * 3)($4)
+ ldc1 $f4, (4 * 36 + 8 * 4)($4)
+ ldc1 $f5, (4 * 36 + 8 * 5)($4)
+ ldc1 $f6, (4 * 36 + 8 * 6)($4)
+ ldc1 $f7, (4 * 36 + 8 * 7)($4)
+ ldc1 $f8, (4 * 36 + 8 * 8)($4)
+ ldc1 $f9, (4 * 36 + 8 * 9)($4)
+ ldc1 $f10, (4 * 36 + 8 * 10)($4)
+ ldc1 $f11, (4 * 36 + 8 * 11)($4)
+ ldc1 $f12, (4 * 36 + 8 * 12)($4)
+ ldc1 $f13, (4 * 36 + 8 * 13)($4)
+ ldc1 $f14, (4 * 36 + 8 * 14)($4)
+ ldc1 $f15, (4 * 36 + 8 * 15)($4)
+ ldc1 $f16, (4 * 36 + 8 * 16)($4)
+ ldc1 $f17, (4 * 36 + 8 * 17)($4)
+ ldc1 $f18, (4 * 36 + 8 * 18)($4)
+ ldc1 $f19, (4 * 36 + 8 * 19)($4)
+ ldc1 $f20, (4 * 36 + 8 * 20)($4)
+ ldc1 $f21, (4 * 36 + 8 * 21)($4)
+ ldc1 $f22, (4 * 36 + 8 * 22)($4)
+ ldc1 $f23, (4 * 36 + 8 * 23)($4)
+ ldc1 $f24, (4 * 36 + 8 * 24)($4)
+ ldc1 $f25, (4 * 36 + 8 * 25)($4)
+ ldc1 $f26, (4 * 36 + 8 * 26)($4)
+ ldc1 $f27, (4 * 36 + 8 * 27)($4)
+ ldc1 $f28, (4 * 36 + 8 * 28)($4)
+ ldc1 $f29, (4 * 36 + 8 * 29)($4)
+ ldc1 $f30, (4 * 36 + 8 * 30)($4)
+ ldc1 $f31, (4 * 36 + 8 * 31)($4)
+#endif
+#endif
+ // restore hi and lo
+ lw $8, (4 * 33)($4)
+ mthi $8
+ lw $8, (4 * 34)($4)
+ mtlo $8
+ // r0 is zero
+ lw $1, (4 * 1)($4)
+ lw $2, (4 * 2)($4)
+ lw $3, (4 * 3)($4)
+ // skip a0 for now
+ lw $5, (4 * 5)($4)
+ lw $6, (4 * 6)($4)
+ lw $7, (4 * 7)($4)
+ lw $8, (4 * 8)($4)
+ lw $9, (4 * 9)($4)
+ lw $10, (4 * 10)($4)
+ lw $11, (4 * 11)($4)
+ lw $12, (4 * 12)($4)
+ lw $13, (4 * 13)($4)
+ lw $14, (4 * 14)($4)
+ lw $15, (4 * 15)($4)
+ lw $16, (4 * 16)($4)
+ lw $17, (4 * 17)($4)
+ lw $18, (4 * 18)($4)
+ lw $19, (4 * 19)($4)
+ lw $20, (4 * 20)($4)
+ lw $21, (4 * 21)($4)
+ lw $22, (4 * 22)($4)
+ lw $23, (4 * 23)($4)
+ lw $24, (4 * 24)($4)
+ lw $25, (4 * 25)($4)
+ lw $26, (4 * 26)($4)
+ lw $27, (4 * 27)($4)
+ lw $28, (4 * 28)($4)
+ lw $29, (4 * 29)($4)
+ lw $30, (4 * 30)($4)
+ // load new pc into ra
+ lw $31, (4 * 32)($4)
+ // jump to ra, load a0 in the delay slot
+ jr $31
+ lw $4, (4 * 4)($4)
+ .set pop
+
+#elif defined(__mips64)
+
+//
+// void libunwind::Registers_mips_newabi::jumpto()
+//
+// On entry:
+// thread state pointer is in a0 ($4)
+//
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
+ .set push
+ .set noat
+ .set noreorder
+ .set nomacro
+#ifdef __mips_hard_float
+ ldc1 $f0, (8 * 35)($4)
+ ldc1 $f1, (8 * 36)($4)
+ ldc1 $f2, (8 * 37)($4)
+ ldc1 $f3, (8 * 38)($4)
+ ldc1 $f4, (8 * 39)($4)
+ ldc1 $f5, (8 * 40)($4)
+ ldc1 $f6, (8 * 41)($4)
+ ldc1 $f7, (8 * 42)($4)
+ ldc1 $f8, (8 * 43)($4)
+ ldc1 $f9, (8 * 44)($4)
+ ldc1 $f10, (8 * 45)($4)
+ ldc1 $f11, (8 * 46)($4)
+ ldc1 $f12, (8 * 47)($4)
+ ldc1 $f13, (8 * 48)($4)
+ ldc1 $f14, (8 * 49)($4)
+ ldc1 $f15, (8 * 50)($4)
+ ldc1 $f16, (8 * 51)($4)
+ ldc1 $f17, (8 * 52)($4)
+ ldc1 $f18, (8 * 53)($4)
+ ldc1 $f19, (8 * 54)($4)
+ ldc1 $f20, (8 * 55)($4)
+ ldc1 $f21, (8 * 56)($4)
+ ldc1 $f22, (8 * 57)($4)
+ ldc1 $f23, (8 * 58)($4)
+ ldc1 $f24, (8 * 59)($4)
+ ldc1 $f25, (8 * 60)($4)
+ ldc1 $f26, (8 * 61)($4)
+ ldc1 $f27, (8 * 62)($4)
+ ldc1 $f28, (8 * 63)($4)
+ ldc1 $f29, (8 * 64)($4)
+ ldc1 $f30, (8 * 65)($4)
+ ldc1 $f31, (8 * 66)($4)
+#endif
+ // restore hi and lo
+ ld $8, (8 * 33)($4)
+ mthi $8
+ ld $8, (8 * 34)($4)
+ mtlo $8
+ // r0 is zero
+ ld $1, (8 * 1)($4)
+ ld $2, (8 * 2)($4)
+ ld $3, (8 * 3)($4)
+ // skip a0 for now
+ ld $5, (8 * 5)($4)
+ ld $6, (8 * 6)($4)
+ ld $7, (8 * 7)($4)
+ ld $8, (8 * 8)($4)
+ ld $9, (8 * 9)($4)
+ ld $10, (8 * 10)($4)
+ ld $11, (8 * 11)($4)
+ ld $12, (8 * 12)($4)
+ ld $13, (8 * 13)($4)
+ ld $14, (8 * 14)($4)
+ ld $15, (8 * 15)($4)
+ ld $16, (8 * 16)($4)
+ ld $17, (8 * 17)($4)
+ ld $18, (8 * 18)($4)
+ ld $19, (8 * 19)($4)
+ ld $20, (8 * 20)($4)
+ ld $21, (8 * 21)($4)
+ ld $22, (8 * 22)($4)
+ ld $23, (8 * 23)($4)
+ ld $24, (8 * 24)($4)
+ ld $25, (8 * 25)($4)
+ ld $26, (8 * 26)($4)
+ ld $27, (8 * 27)($4)
+ ld $28, (8 * 28)($4)
+ ld $29, (8 * 29)($4)
+ ld $30, (8 * 30)($4)
+ // load new pc into ra
+ ld $31, (8 * 32)($4)
+ // jump to ra, load a0 in the delay slot
+ jr $31
+ ld $4, (8 * 4)($4)
+ .set pop
+
#endif
NO_EXEC_STACK_DIRECTIVE
diff --git a/contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S b/contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S
index 9b66a7657fe4..e5a2935fbcca 100644
--- a/contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S
+++ b/contrib/llvm/projects/libunwind/src/UnwindRegistersSave.S
@@ -87,6 +87,205 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
xorl %eax, %eax # return UNW_ESUCCESS
ret
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
+
+#
+# extern int unw_getcontext(unw_context_t* thread_state)
+#
+# On entry:
+# thread_state pointer is in a0 ($4)
+#
+DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+ .set push
+ .set noat
+ .set noreorder
+ .set nomacro
+ sw $1, (4 * 1)($4)
+ sw $2, (4 * 2)($4)
+ sw $3, (4 * 3)($4)
+ sw $4, (4 * 4)($4)
+ sw $5, (4 * 5)($4)
+ sw $6, (4 * 6)($4)
+ sw $7, (4 * 7)($4)
+ sw $8, (4 * 8)($4)
+ sw $9, (4 * 9)($4)
+ sw $10, (4 * 10)($4)
+ sw $11, (4 * 11)($4)
+ sw $12, (4 * 12)($4)
+ sw $13, (4 * 13)($4)
+ sw $14, (4 * 14)($4)
+ sw $15, (4 * 15)($4)
+ sw $16, (4 * 16)($4)
+ sw $17, (4 * 17)($4)
+ sw $18, (4 * 18)($4)
+ sw $19, (4 * 19)($4)
+ sw $20, (4 * 20)($4)
+ sw $21, (4 * 21)($4)
+ sw $22, (4 * 22)($4)
+ sw $23, (4 * 23)($4)
+ sw $24, (4 * 24)($4)
+ sw $25, (4 * 25)($4)
+ sw $26, (4 * 26)($4)
+ sw $27, (4 * 27)($4)
+ sw $28, (4 * 28)($4)
+ sw $29, (4 * 29)($4)
+ sw $30, (4 * 30)($4)
+ sw $31, (4 * 31)($4)
+ # Store return address to pc
+ sw $31, (4 * 32)($4)
+ # hi and lo
+ mfhi $8
+ sw $8, (4 * 33)($4)
+ mflo $8
+ sw $8, (4 * 34)($4)
+#ifdef __mips_hard_float
+#if __mips_fpr == 32
+ sdc1 $f0, (4 * 36 + 8 * 0)($4)
+ sdc1 $f2, (4 * 36 + 8 * 2)($4)
+ sdc1 $f4, (4 * 36 + 8 * 4)($4)
+ sdc1 $f6, (4 * 36 + 8 * 6)($4)
+ sdc1 $f8, (4 * 36 + 8 * 8)($4)
+ sdc1 $f10, (4 * 36 + 8 * 10)($4)
+ sdc1 $f12, (4 * 36 + 8 * 12)($4)
+ sdc1 $f14, (4 * 36 + 8 * 14)($4)
+ sdc1 $f16, (4 * 36 + 8 * 16)($4)
+ sdc1 $f18, (4 * 36 + 8 * 18)($4)
+ sdc1 $f20, (4 * 36 + 8 * 20)($4)
+ sdc1 $f22, (4 * 36 + 8 * 22)($4)
+ sdc1 $f24, (4 * 36 + 8 * 24)($4)
+ sdc1 $f26, (4 * 36 + 8 * 26)($4)
+ sdc1 $f28, (4 * 36 + 8 * 28)($4)
+ sdc1 $f30, (4 * 36 + 8 * 30)($4)
+#else
+ sdc1 $f0, (4 * 36 + 8 * 0)($4)
+ sdc1 $f1, (4 * 36 + 8 * 1)($4)
+ sdc1 $f2, (4 * 36 + 8 * 2)($4)
+ sdc1 $f3, (4 * 36 + 8 * 3)($4)
+ sdc1 $f4, (4 * 36 + 8 * 4)($4)
+ sdc1 $f5, (4 * 36 + 8 * 5)($4)
+ sdc1 $f6, (4 * 36 + 8 * 6)($4)
+ sdc1 $f7, (4 * 36 + 8 * 7)($4)
+ sdc1 $f8, (4 * 36 + 8 * 8)($4)
+ sdc1 $f9, (4 * 36 + 8 * 9)($4)
+ sdc1 $f10, (4 * 36 + 8 * 10)($4)
+ sdc1 $f11, (4 * 36 + 8 * 11)($4)
+ sdc1 $f12, (4 * 36 + 8 * 12)($4)
+ sdc1 $f13, (4 * 36 + 8 * 13)($4)
+ sdc1 $f14, (4 * 36 + 8 * 14)($4)
+ sdc1 $f15, (4 * 36 + 8 * 15)($4)
+ sdc1 $f16, (4 * 36 + 8 * 16)($4)
+ sdc1 $f17, (4 * 36 + 8 * 17)($4)
+ sdc1 $f18, (4 * 36 + 8 * 18)($4)
+ sdc1 $f19, (4 * 36 + 8 * 19)($4)
+ sdc1 $f20, (4 * 36 + 8 * 20)($4)
+ sdc1 $f21, (4 * 36 + 8 * 21)($4)
+ sdc1 $f22, (4 * 36 + 8 * 22)($4)
+ sdc1 $f23, (4 * 36 + 8 * 23)($4)
+ sdc1 $f24, (4 * 36 + 8 * 24)($4)
+ sdc1 $f25, (4 * 36 + 8 * 25)($4)
+ sdc1 $f26, (4 * 36 + 8 * 26)($4)
+ sdc1 $f27, (4 * 36 + 8 * 27)($4)
+ sdc1 $f28, (4 * 36 + 8 * 28)($4)
+ sdc1 $f29, (4 * 36 + 8 * 29)($4)
+ sdc1 $f30, (4 * 36 + 8 * 30)($4)
+ sdc1 $f31, (4 * 36 + 8 * 31)($4)
+#endif
+#endif
+ jr $31
+ # return UNW_ESUCCESS
+ or $2, $0, $0
+ .set pop
+
+#elif defined(__mips64)
+
+#
+# extern int unw_getcontext(unw_context_t* thread_state)
+#
+# On entry:
+# thread_state pointer is in a0 ($4)
+#
+DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+ .set push
+ .set noat
+ .set noreorder
+ .set nomacro
+ sd $1, (8 * 1)($4)
+ sd $2, (8 * 2)($4)
+ sd $3, (8 * 3)($4)
+ sd $4, (8 * 4)($4)
+ sd $5, (8 * 5)($4)
+ sd $6, (8 * 6)($4)
+ sd $7, (8 * 7)($4)
+ sd $8, (8 * 8)($4)
+ sd $9, (8 * 9)($4)
+ sd $10, (8 * 10)($4)
+ sd $11, (8 * 11)($4)
+ sd $12, (8 * 12)($4)
+ sd $13, (8 * 13)($4)
+ sd $14, (8 * 14)($4)
+ sd $15, (8 * 15)($4)
+ sd $16, (8 * 16)($4)
+ sd $17, (8 * 17)($4)
+ sd $18, (8 * 18)($4)
+ sd $19, (8 * 19)($4)
+ sd $20, (8 * 20)($4)
+ sd $21, (8 * 21)($4)
+ sd $22, (8 * 22)($4)
+ sd $23, (8 * 23)($4)
+ sd $24, (8 * 24)($4)
+ sd $25, (8 * 25)($4)
+ sd $26, (8 * 26)($4)
+ sd $27, (8 * 27)($4)
+ sd $28, (8 * 28)($4)
+ sd $29, (8 * 29)($4)
+ sd $30, (8 * 30)($4)
+ sd $31, (8 * 31)($4)
+ # Store return address to pc
+ sd $31, (8 * 32)($4)
+ # hi and lo
+ mfhi $8
+ sd $8, (8 * 33)($4)
+ mflo $8
+ sd $8, (8 * 34)($4)
+#ifdef __mips_hard_float
+ sdc1 $f0, (8 * 35)($4)
+ sdc1 $f1, (8 * 36)($4)
+ sdc1 $f2, (8 * 37)($4)
+ sdc1 $f3, (8 * 38)($4)
+ sdc1 $f4, (8 * 39)($4)
+ sdc1 $f5, (8 * 40)($4)
+ sdc1 $f6, (8 * 41)($4)
+ sdc1 $f7, (8 * 42)($4)
+ sdc1 $f8, (8 * 43)($4)
+ sdc1 $f9, (8 * 44)($4)
+ sdc1 $f10, (8 * 45)($4)
+ sdc1 $f11, (8 * 46)($4)
+ sdc1 $f12, (8 * 47)($4)
+ sdc1 $f13, (8 * 48)($4)
+ sdc1 $f14, (8 * 49)($4)
+ sdc1 $f15, (8 * 50)($4)
+ sdc1 $f16, (8 * 51)($4)
+ sdc1 $f17, (8 * 52)($4)
+ sdc1 $f18, (8 * 53)($4)
+ sdc1 $f19, (8 * 54)($4)
+ sdc1 $f20, (8 * 55)($4)
+ sdc1 $f21, (8 * 56)($4)
+ sdc1 $f22, (8 * 57)($4)
+ sdc1 $f23, (8 * 58)($4)
+ sdc1 $f24, (8 * 59)($4)
+ sdc1 $f25, (8 * 60)($4)
+ sdc1 $f26, (8 * 61)($4)
+ sdc1 $f27, (8 * 62)($4)
+ sdc1 $f28, (8 * 63)($4)
+ sdc1 $f29, (8 * 64)($4)
+ sdc1 $f30, (8 * 65)($4)
+ sdc1 $f31, (8 * 66)($4)
+#endif
+ jr $31
+ # return UNW_ESUCCESS
+ or $2, $0, $0
+ .set pop
+
# elif defined(__mips__)
#
diff --git a/contrib/llvm/projects/libunwind/src/config.h b/contrib/llvm/projects/libunwind/src/config.h
index 1e765cbdff18..78526855501e 100644
--- a/contrib/llvm/projects/libunwind/src/config.h
+++ b/contrib/llvm/projects/libunwind/src/config.h
@@ -70,7 +70,7 @@
#if defined(__i386__) || defined(__x86_64__) || \
(!defined(__APPLE__) && defined(__arm__)) || \
(defined(__arm64__) || defined(__aarch64__)) || \
- (defined(__APPLE__) && defined(__mips__)) || \
+ (defined(__mips__)) || \
defined(__riscv)
#define _LIBUNWIND_BUILD_ZERO_COST_APIS 1
#else
diff --git a/contrib/llvm/projects/libunwind/src/libunwind.cpp b/contrib/llvm/projects/libunwind/src/libunwind.cpp
index 495dd5a40a70..44ceb98c1e96 100644
--- a/contrib/llvm/projects/libunwind/src/libunwind.cpp
+++ b/contrib/llvm/projects/libunwind/src/libunwind.cpp
@@ -59,8 +59,12 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
# define REGISTER_KIND Registers_or1k
#elif defined(__riscv)
# define REGISTER_KIND Registers_riscv
+#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32
+# define REGISTER_KIND Registers_mips_o32
+#elif defined(__mips64)
+# define REGISTER_KIND Registers_mips_newabi
#elif defined(__mips__)
-# warning The MIPS architecture is not supported.
+# warning The MIPS architecture is not supported with this ABI and environment!
#else
# error Architecture not supported
#endif