[libunwind] r320528 - [libunwind][MIPS]: Add support for unwinding in O32 and N64 processes.

John Baldwin via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 12 13:43:37 PST 2017


Author: jhb
Date: Tue Dec 12 13:43:36 2017
New Revision: 320528

URL: http://llvm.org/viewvc/llvm-project?rev=320528&view=rev
Log:
[libunwind][MIPS]: Add support for unwinding in O32 and N64 processes.

This supports the soft-float ABI only and has been tested with both clang
and gcc on FreeBSD.

Reviewed By: sdardis, compnerd

Differential Revision: https://reviews.llvm.org/D38110

Modified:
    libunwind/trunk/include/__libunwind_config.h
    libunwind/trunk/include/libunwind.h
    libunwind/trunk/src/Registers.hpp
    libunwind/trunk/src/UnwindCursor.hpp
    libunwind/trunk/src/UnwindRegistersRestore.S
    libunwind/trunk/src/UnwindRegistersSave.S
    libunwind/trunk/src/config.h
    libunwind/trunk/src/libunwind.cpp

Modified: libunwind/trunk/include/__libunwind_config.h
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/include/__libunwind_config.h?rev=320528&r1=320527&r2=320528&view=diff
==============================================================================
--- libunwind/trunk/include/__libunwind_config.h (original)
+++ libunwind/trunk/include/__libunwind_config.h Tue Dec 12 13:43:36 2017
@@ -21,6 +21,7 @@
 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64     95
 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM       287
 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K      31
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS      65
 
 #if defined(_LIBUNWIND_IS_NATIVE_ONLY)
 # if defined(__i386__)
@@ -63,6 +64,19 @@
 #  define _LIBUNWIND_CONTEXT_SIZE 16
 #  define _LIBUNWIND_CURSOR_SIZE 24
 #  define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K
+# elif defined(__mips__)
+#  if defined(_ABIO32) && defined(__mips_soft_float)
+#    define _LIBUNWIND_TARGET_MIPS_O32 1
+#    define _LIBUNWIND_CONTEXT_SIZE 18
+#    define _LIBUNWIND_CURSOR_SIZE 24
+#  elif defined(_ABI64) && defined(__mips_soft_float)
+#    define _LIBUNWIND_TARGET_MIPS_N64 1
+#    define _LIBUNWIND_CONTEXT_SIZE 35
+#    define _LIBUNWIND_CURSOR_SIZE 47
+#  else
+#    error "Unsupported MIPS ABI and/or environment"
+#  endif
+#  define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS
 # else
 #  error "Unsupported architecture."
 # endif
@@ -73,6 +87,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_N64 1
 # define _LIBUNWIND_CONTEXT_SIZE 128
 # define _LIBUNWIND_CURSOR_SIZE 140
 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287

Modified: libunwind/trunk/include/libunwind.h
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/include/libunwind.h?rev=320528&r1=320527&r2=320528&view=diff
==============================================================================
--- libunwind/trunk/include/libunwind.h (original)
+++ libunwind/trunk/include/libunwind.h Tue Dec 12 13:43:36 2017
@@ -563,4 +563,42 @@ enum {
   UNW_OR1K_R31 = 31,
 };
 
+// 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_HI = 64,
+  UNW_MIPS_LO = 65,
+};
+
 #endif

Modified: libunwind/trunk/src/Registers.hpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/Registers.hpp?rev=320528&r1=320527&r2=320528&view=diff
==============================================================================
--- libunwind/trunk/src/Registers.hpp (original)
+++ libunwind/trunk/src/Registers.hpp Tue Dec 12 13:43:36 2017
@@ -2041,6 +2041,418 @@ inline const char *Registers_or1k::getRe
 
 }
 #endif // _LIBUNWIND_TARGET_OR1K
+
+#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 _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
+
+  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;
+};
+
+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;
+  // FIXME: Hard float, 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];
+
+  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;
+  }
+
+  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 {
+  return false;
+}
+
+inline double Registers_mips_o32::getFloatRegister(int /* regNum */) const {
+  _LIBUNWIND_ABORT("mips_o32 float support not implemented");
+}
+
+inline void Registers_mips_o32::setFloatRegister(int /* regNum */,
+                                                 double /* value */) {
+  _LIBUNWIND_ABORT("mips_o32 float support not implemented");
+}
+
+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_HI:
+    return "$hi";
+  case UNW_MIPS_LO:
+    return "$lo";
+  default:
+    return "unknown register";
+  }
+}
+#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 {
+public:
+  Registers_mips_n64();
+  Registers_mips_n64(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 _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
+
+  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_n64_thread_state_t {
+    uint64_t __r[32];
+    uint64_t __pc;
+    uint64_t __hi;
+    uint64_t __lo;
+  };
+
+  mips_n64_thread_state_t _registers;
+};
+
+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");
+  memcpy(&_registers, static_cast<const uint8_t *>(registers),
+         sizeof(_registers));
+}
+
+inline Registers_mips_n64::Registers_mips_n64() {
+  memset(&_registers, 0, sizeof(_registers));
+}
+
+inline bool Registers_mips_n64::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_n64::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_n64 register");
+}
+
+inline void Registers_mips_n64::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_n64 register");
+}
+
+inline bool Registers_mips_n64::validFloatRegister(int /* regNum */) const {
+  return false;
+}
+
+inline double Registers_mips_n64::getFloatRegister(int /* regNum */) const {
+  _LIBUNWIND_ABORT("mips_n64 float support not implemented");
+}
+
+inline void Registers_mips_n64::setFloatRegister(int /* regNum */,
+                                                 double /* value */) {
+  _LIBUNWIND_ABORT("mips_n64 float support not implemented");
+}
+
+inline bool Registers_mips_n64::validVectorRegister(int /* regNum */) const {
+  return false;
+}
+
+inline v128 Registers_mips_n64::getVectorRegister(int /* regNum */) const {
+  _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
+}
+
+inline void Registers_mips_n64::setVectorRegister(int /* regNum */, v128 /* value */) {
+  _LIBUNWIND_ABORT("mips_n64 vector support not implemented");
+}
+
+inline const char *Registers_mips_n64::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_HI:
+    return "$hi";
+  case UNW_MIPS_LO:
+    return "$lo";
+  default:
+    return "unknown register";
+  }
+}
+#endif // _LIBUNWIND_TARGET_MIPS_N64
 } // namespace libunwind
 
 #endif // __REGISTERS_HPP__

Modified: libunwind/trunk/src/UnwindCursor.hpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/UnwindCursor.hpp?rev=320528&r1=320527&r2=320528&view=diff
==============================================================================
--- libunwind/trunk/src/UnwindCursor.hpp (original)
+++ libunwind/trunk/src/UnwindCursor.hpp Tue Dec 12 13:43:36 2017
@@ -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_N64)
+  int stepWithCompactEncoding(Registers_mips_n64 &) {
+    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_N64)
+  bool compactSaysUseDwarf(Registers_mips_n64 &, uint32_t *) const {
+    return true;
+  }
+#endif
 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
 
 #if defined(_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_N64)
+  compact_unwind_encoding_t dwarfEncoding(Registers_mips_n64 &) const {
+    return 0;
+  }
+#endif
 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
 
 

Modified: libunwind/trunk/src/UnwindRegistersRestore.S
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/UnwindRegistersRestore.S?rev=320528&r1=320527&r2=320528&view=diff
==============================================================================
--- libunwind/trunk/src/UnwindRegistersRestore.S (original)
+++ libunwind/trunk/src/UnwindRegistersRestore.S Tue Dec 12 13:43:36 2017
@@ -534,6 +534,118 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9li
   l.jr     r9
    l.nop
 
+#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+
+//
+// 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
+  // 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(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+
+//
+// void libunwind::Registers_mips_n64::jumpto()
+//
+// On entry:
+//  thread state pointer is in a0 ($4)
+//
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_n646jumptoEv)
+  .set push
+  .set noat
+  .set noreorder
+  .set nomacro
+  // 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
 
 #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */

Modified: libunwind/trunk/src/UnwindRegistersSave.S
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/UnwindRegistersSave.S?rev=320528&r1=320527&r2=320528&view=diff
==============================================================================
--- libunwind/trunk/src/UnwindRegistersSave.S (original)
+++ libunwind/trunk/src/UnwindRegistersSave.S Tue Dec 12 13:43:36 2017
@@ -116,6 +116,118 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext
   xorl  %eax, %eax    # return UNW_ESUCCESS
   ret
 
+#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+
+#
+# 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)
+  jr	$31
+  # return UNW_ESUCCESS
+  or    $2, $0, $0
+  .set pop
+
+#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+
+#
+# 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)
+  jr	$31
+  # return UNW_ESUCCESS
+  or    $2, $0, $0
+  .set pop
+
 # elif defined(__mips__)
 
 #

Modified: libunwind/trunk/src/config.h
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/config.h?rev=320528&r1=320527&r2=320528&view=diff
==============================================================================
--- libunwind/trunk/src/config.h (original)
+++ libunwind/trunk/src/config.h Tue Dec 12 13:43:36 2017
@@ -71,7 +71,7 @@
     defined(__ppc__) || defined(__ppc64__) ||                                  \
     (!defined(__APPLE__) && defined(__arm__)) ||                               \
     (defined(__arm64__) || defined(__aarch64__)) ||                            \
-    (defined(__APPLE__) && defined(__mips__))
+    defined(__mips__)
 #define _LIBUNWIND_BUILD_ZERO_COST_APIS
 #endif
 

Modified: libunwind/trunk/src/libunwind.cpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/libunwind.cpp?rev=320528&r1=320527&r2=320528&view=diff
==============================================================================
--- libunwind/trunk/src/libunwind.cpp (original)
+++ libunwind/trunk/src/libunwind.cpp Tue Dec 12 13:43:36 2017
@@ -59,8 +59,12 @@ _LIBUNWIND_EXPORT int unw_init_local(unw
 # define REGISTER_KIND Registers_arm
 #elif defined(__or1k__)
 # define REGISTER_KIND Registers_or1k
+#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float)
+# define REGISTER_KIND Registers_mips_o32
+#elif defined(__mips__) && defined(_ABI64) && defined(__mips_soft_float)
+# define REGISTER_KIND Registers_mips_n64
 #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




More information about the cfe-commits mailing list