[libunwind] Add support for OpenRISC 1000.
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
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: ce4c5c9849f4b3c5d882d1466b0790ea56eb5904
diff --git a/src/Registers.hpp b/src/Registers.hpp
index 0269bf7..38ce066 100644
--- a/src/Registers.hpp
+++ b/src/Registers.hpp
@@ -1711,7 +1711,187 @@
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__
diff --git a/src/UnwindCursor.hpp b/src/UnwindCursor.hpp
index 59924f0..040d13e 100644
--- a/src/UnwindCursor.hpp
+++ b/src/UnwindCursor.hpp
@@ -556,6 +556,10 @@
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
diff --git a/src/UnwindRegistersRestore.S b/src/UnwindRegistersRestore.S
index 7d21953..3a4ea62 100644
--- a/src/UnwindRegistersRestore.S
+++ b/src/UnwindRegistersRestore.S
@@ -427,4 +427,55 @@
#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
diff --git a/src/UnwindRegistersSave.S b/src/UnwindRegistersSave.S
index fed295a..1275c2a 100644
--- a/src/UnwindRegistersSave.S
+++ b/src/UnwindRegistersSave.S
@@ -413,4 +413,45 @@
#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
diff --git a/src/libunwind.cpp b/src/libunwind.cpp
index 1552101..a23dfcf 100644
--- a/src/libunwind.cpp
+++ b/src/libunwind.cpp
@@ -61,6 +61,9 @@
#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