[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
This commit is contained in:
Peter Zotov 2015-08-31 05:26:37 +00:00
parent afeac301b1
commit ce4c5c9849
6 changed files with 315 additions and 0 deletions

View 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

View 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__

View 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

View 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

View 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

View 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