[libunwind] Add support for OpenRISC 1000.
authorPeter Zotov <whitequark@whitequark.org>
Mon, 31 Aug 2015 05:26:37 +0000 (05:26 +0000)
committerPeter Zotov <whitequark@whitequark.org>
Mon, 31 Aug 2015 05:26:37 +0000 (05:26 +0000)
This patch makes no assumptions on ABI past the ABI defined in
the OpenRISC 1000 spec except that the DWARF register numbers will
be 0-31 for registers r0-r31, which is true for both gcc and
clang at the moment.

llvm-svn: 246413

libunwind/include/libunwind.h
libunwind/src/Registers.hpp
libunwind/src/UnwindCursor.hpp
libunwind/src/UnwindRegistersRestore.S
libunwind/src/UnwindRegistersSave.S
libunwind/src/libunwind.cpp

index 4a75a7b..6045bec 100644 (file)
@@ -497,4 +497,40 @@ enum {
   // 8192-16383 -- Unspecified vendor co-processor register.
 };
 
+// OpenRISC1000 register numbers
+enum {
+  UNW_OR1K_R0  = 0,
+  UNW_OR1K_R1  = 1,
+  UNW_OR1K_R2  = 2,
+  UNW_OR1K_R3  = 3,
+  UNW_OR1K_R4  = 4,
+  UNW_OR1K_R5  = 5,
+  UNW_OR1K_R6  = 6,
+  UNW_OR1K_R7  = 7,
+  UNW_OR1K_R8  = 8,
+  UNW_OR1K_R9  = 9,
+  UNW_OR1K_R10 = 10,
+  UNW_OR1K_R11 = 11,
+  UNW_OR1K_R12 = 12,
+  UNW_OR1K_R13 = 13,
+  UNW_OR1K_R14 = 14,
+  UNW_OR1K_R15 = 15,
+  UNW_OR1K_R16 = 16,
+  UNW_OR1K_R17 = 17,
+  UNW_OR1K_R18 = 18,
+  UNW_OR1K_R19 = 19,
+  UNW_OR1K_R20 = 20,
+  UNW_OR1K_R21 = 21,
+  UNW_OR1K_R22 = 22,
+  UNW_OR1K_R23 = 23,
+  UNW_OR1K_R24 = 24,
+  UNW_OR1K_R25 = 25,
+  UNW_OR1K_R26 = 26,
+  UNW_OR1K_R27 = 27,
+  UNW_OR1K_R28 = 28,
+  UNW_OR1K_R29 = 29,
+  UNW_OR1K_R30 = 30,
+  UNW_OR1K_R31 = 31,
+};
+
 #endif
index 0269bf7..38ce066 100644 (file)
@@ -1711,7 +1711,187 @@ inline v128 Registers_arm::getVectorRegister(int) const {
 inline void Registers_arm::setVectorRegister(int, v128) {
   _LIBUNWIND_ABORT("ARM vector support not implemented");
 }
+/// Registers_or1k holds the register state of a thread in an OpenRISC1000
+/// process.
+class _LIBUNWIND_HIDDEN Registers_or1k {
+public:
+  Registers_or1k();
+  Registers_or1k(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 31; }
+
+  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; }
+
+private:
+  struct or1k_thread_state_t {
+    unsigned int __r[32];
+  };
+
+  or1k_thread_state_t _registers;
+};
+
+inline Registers_or1k::Registers_or1k(const void *registers) {
+  static_assert(sizeof(Registers_or1k) < sizeof(unw_context_t),
+                    "or1k registers do not fit into unw_context_t");
+  memcpy(&_registers, static_cast<const uint8_t *>(registers),
+         sizeof(_registers));
+}
+
+inline Registers_or1k::Registers_or1k() {
+  memset(&_registers, 0, sizeof(_registers));
+}
 
+inline bool Registers_or1k::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_OR1K_R31)
+    return true;
+  return false;
+}
+
+inline uint32_t Registers_or1k::getRegister(int regNum) const {
+  if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)
+    return _registers.__r[regNum - UNW_OR1K_R0];
+
+  switch (regNum) {
+  case UNW_REG_IP:
+    return _registers.__r[9];
+  case UNW_REG_SP:
+    return _registers.__r[1];
+  }
+  _LIBUNWIND_ABORT("unsupported or1k register");
+}
+
+inline void Registers_or1k::setRegister(int regNum, uint32_t value) {
+  if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {
+    _registers.__r[regNum - UNW_OR1K_R0] = value;
+    return;
+  }
+
+  switch (regNum) {
+  case UNW_REG_IP:
+    _registers.__r[9] = value;
+    return;
+  case UNW_REG_SP:
+    _registers.__r[1] = value;
+    return;
+  }
+  _LIBUNWIND_ABORT("unsupported or1k register");
+}
+
+inline bool Registers_or1k::validFloatRegister(int regNum) const {
+  return false;
+}
+
+inline double Registers_or1k::getFloatRegister(int regNum) const {
+  _LIBUNWIND_ABORT("or1k float support not implemented");
+}
+
+inline void Registers_or1k::setFloatRegister(int regNum, double value) {
+  _LIBUNWIND_ABORT("or1k float support not implemented");
+}
+
+inline bool Registers_or1k::validVectorRegister(int regNum) const {
+  return false;
+}
+
+inline v128 Registers_or1k::getVectorRegister(int regNum) const {
+  _LIBUNWIND_ABORT("or1k vector support not implemented");
+}
+
+inline void Registers_or1k::setVectorRegister(int regNum, v128 value) {
+  _LIBUNWIND_ABORT("or1k vector support not implemented");
+}
+
+inline const char *Registers_or1k::getRegisterName(int regNum) {
+  switch (regNum) {
+  case UNW_OR1K_R0:
+    return "r0";
+  case UNW_OR1K_R1:
+    return "r1";
+  case UNW_OR1K_R2:
+    return "r2";
+  case UNW_OR1K_R3:
+    return "r3";
+  case UNW_OR1K_R4:
+    return "r4";
+  case UNW_OR1K_R5:
+    return "r5";
+  case UNW_OR1K_R6:
+    return "r6";
+  case UNW_OR1K_R7:
+    return "r7";
+  case UNW_OR1K_R8:
+    return "r8";
+  case UNW_OR1K_R9:
+    return "r9";
+  case UNW_OR1K_R10:
+    return "r10";
+  case UNW_OR1K_R11:
+    return "r11";
+  case UNW_OR1K_R12:
+    return "r12";
+  case UNW_OR1K_R13:
+    return "r13";
+  case UNW_OR1K_R14:
+    return "r14";
+  case UNW_OR1K_R15:
+    return "r15";
+  case UNW_OR1K_R16:
+    return "r16";
+  case UNW_OR1K_R17:
+    return "r17";
+  case UNW_OR1K_R18:
+    return "r18";
+  case UNW_OR1K_R19:
+    return "r19";
+  case UNW_OR1K_R20:
+    return "r20";
+  case UNW_OR1K_R21:
+    return "r21";
+  case UNW_OR1K_R22:
+    return "r22";
+  case UNW_OR1K_R23:
+    return "r23";
+  case UNW_OR1K_R24:
+    return "r24";
+  case UNW_OR1K_R25:
+    return "r25";
+  case UNW_OR1K_R26:
+    return "r26";
+  case UNW_OR1K_R27:
+    return "r27";
+  case UNW_OR1K_R28:
+    return "r28";
+  case UNW_OR1K_R29:
+    return "r29";
+  case UNW_OR1K_R30:
+    return "r30";
+  case UNW_OR1K_R31:
+    return "r31";
+  default:
+    return "unknown register";
+  }
+
+}
 } // namespace libunwind
 
 #endif // __REGISTERS_HPP__
index 59924f0..040d13e 100644 (file)
@@ -556,6 +556,10 @@ private:
   compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
     return UNWIND_ARM64_MODE_DWARF;
   }
+
+  compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {
+    return 0;
+  }
 #endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
 
 
index 7d21953..3a4ea62 100644 (file)
@@ -427,4 +427,55 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm19restoreiWMMXCont
 #endif
   JMP(lr)
 
+#elif defined(__or1k__)
+
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
+#
+# void libunwind::Registers_or1k::jumpto()
+#
+# On entry:
+#  thread_state pointer is in r3
+#
+
+  # restore integral registerrs
+  l.lwz     r0,  0(r3)
+  l.lwz     r1,  4(r3)
+  l.lwz     r2,  8(r3)
+  # skip r3 for now
+  l.lwz     r4, 16(r3)
+  l.lwz     r5, 20(r3)
+  l.lwz     r6, 24(r3)
+  l.lwz     r7, 28(r3)
+  l.lwz     r8, 32(r3)
+  l.lwz     r9, 36(r3)
+  l.lwz    r10, 40(r3)
+  l.lwz    r11, 44(r3)
+  l.lwz    r12, 48(r3)
+  l.lwz    r13, 52(r3)
+  l.lwz    r14, 56(r3)
+  l.lwz    r15, 60(r3)
+  l.lwz    r16, 64(r3)
+  l.lwz    r17, 68(r3)
+  l.lwz    r18, 72(r3)
+  l.lwz    r19, 76(r3)
+  l.lwz    r20, 80(r3)
+  l.lwz    r21, 84(r3)
+  l.lwz    r22, 88(r3)
+  l.lwz    r23, 92(r3)
+  l.lwz    r24, 96(r3)
+  l.lwz    r25,100(r3)
+  l.lwz    r26,104(r3)
+  l.lwz    r27,108(r3)
+  l.lwz    r28,112(r3)
+  l.lwz    r29,116(r3)
+  l.lwz    r30,120(r3)
+  l.lwz    r31,124(r3)
+
+  # at last, restore r3
+  l.lwz    r3,  12(r3)
+
+  # jump to pc
+  l.jr     r9
+   l.nop
+
 #endif
index fed295a..1275c2a 100644 (file)
@@ -413,4 +413,45 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_arm16saveiWMMXControl
 #endif
   JMP(lr)
 
+#elif defined(__or1k__)
+
+#
+# extern int unw_getcontext(unw_context_t* thread_state)
+#
+# On entry:
+#  thread_state pointer is in r3
+#
+DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+  l.sw       0(r3), r0
+  l.sw       4(r3), r1
+  l.sw       8(r3), r2
+  l.sw      12(r3), r3
+  l.sw      16(r3), r4
+  l.sw      20(r3), r5
+  l.sw      24(r3), r6
+  l.sw      28(r3), r7
+  l.sw      32(r3), r8
+  l.sw      36(r3), r9
+  l.sw      40(r3), r10
+  l.sw      44(r3), r11
+  l.sw      48(r3), r12
+  l.sw      52(r3), r13
+  l.sw      56(r3), r14
+  l.sw      60(r3), r15
+  l.sw      64(r3), r16
+  l.sw      68(r3), r17
+  l.sw      72(r3), r18
+  l.sw      76(r3), r19
+  l.sw      80(r3), r20
+  l.sw      84(r3), r21
+  l.sw      88(r3), r22
+  l.sw      92(r3), r23
+  l.sw      96(r3), r24
+  l.sw     100(r3), r25
+  l.sw     104(r3), r26
+  l.sw     108(r3), r27
+  l.sw     112(r3), r28
+  l.sw     116(r3), r29
+  l.sw     120(r3), r30
+  l.sw     124(r3), r31
 #endif
index 1552101..a23dfcf 100644 (file)
@@ -61,6 +61,9 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
 #elif _LIBUNWIND_ARM_EHABI
   new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_arm>(
                                  context, LocalAddressSpace::sThisAddressSpace);
+#elif defined(__or1k__)
+  new ((void *)cursor) UnwindCursor<LocalAddressSpace, Registers_or1k>(
+                                 context, LocalAddressSpace::sThisAddressSpace);
 #else
 #error Architecture not supported
 #endif