Changeset View
Changeset View
Standalone View
Standalone View
src/Registers.hpp
Show All 18 Lines | |||||
#include "libunwind.h" | #include "libunwind.h" | ||||
#include "config.h" | #include "config.h" | ||||
namespace libunwind { | namespace libunwind { | ||||
// For emulating 128-bit registers | // For emulating 128-bit registers | ||||
struct v128 { uint32_t vec[4]; }; | struct v128 { uint32_t vec[4]; }; | ||||
enum { | |||||
REGISTERS_X86, | |||||
REGISTERS_X86_64, | |||||
REGISTERS_PPC, | |||||
REGISTERS_PPC64, | |||||
REGISTERS_ARM64, | |||||
REGISTERS_ARM, | |||||
REGISTERS_OR1K, | |||||
REGISTERS_MIPS_O32, | |||||
REGISTERS_MIPS_NEWABI, | |||||
REGISTERS_SPARC, | |||||
}; | |||||
#if defined(_LIBUNWIND_TARGET_I386) | #if defined(_LIBUNWIND_TARGET_I386) | ||||
/// Registers_x86 holds the register state of a thread in a 32-bit intel | /// Registers_x86 holds the register state of a thread in a 32-bit intel | ||||
/// process. | /// process. | ||||
class _LIBUNWIND_HIDDEN Registers_x86 { | class _LIBUNWIND_HIDDEN Registers_x86 { | ||||
public: | public: | ||||
Registers_x86(); | Registers_x86(); | ||||
Registers_x86(const void *registers); | Registers_x86(const void *registers); | ||||
bool validRegister(int num) const; | bool validRegister(int num) const; | ||||
uint32_t getRegister(int num) const; | uint32_t getRegister(int num) const; | ||||
void setRegister(int num, uint32_t value); | void setRegister(int num, uint32_t value); | ||||
bool validFloatRegister(int) const { return false; } | bool validFloatRegister(int) const { return false; } | ||||
double getFloatRegister(int num) const; | double getFloatRegister(int num) const; | ||||
void setFloatRegister(int num, double value); | void setFloatRegister(int num, double value); | ||||
bool validVectorRegister(int) const { return false; } | bool validVectorRegister(int) const { return false; } | ||||
v128 getVectorRegister(int num) const; | v128 getVectorRegister(int num) const; | ||||
void setVectorRegister(int num, v128 value); | void setVectorRegister(int num, v128 value); | ||||
static const char *getRegisterName(int num); | static const char *getRegisterName(int num); | ||||
void jumpto(); | void jumpto(); | ||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; } | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; } | ||||
static int getArch() { return REGISTERS_X86; } | |||||
uint32_t getSP() const { return _registers.__esp; } | uint32_t getSP() const { return _registers.__esp; } | ||||
void setSP(uint32_t value) { _registers.__esp = value; } | void setSP(uint32_t value) { _registers.__esp = value; } | ||||
uint32_t getIP() const { return _registers.__eip; } | uint32_t getIP() const { return _registers.__eip; } | ||||
void setIP(uint32_t value) { _registers.__eip = value; } | void setIP(uint32_t value) { _registers.__eip = value; } | ||||
uint32_t getEBP() const { return _registers.__ebp; } | uint32_t getEBP() const { return _registers.__ebp; } | ||||
void setEBP(uint32_t value) { _registers.__ebp = value; } | void setEBP(uint32_t value) { _registers.__ebp = value; } | ||||
uint32_t getEBX() const { return _registers.__ebx; } | uint32_t getEBX() const { return _registers.__ebx; } | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | public: | ||||
double getFloatRegister(int num) const; | double getFloatRegister(int num) const; | ||||
void setFloatRegister(int num, double value); | void setFloatRegister(int num, double value); | ||||
bool validVectorRegister(int) const; | bool validVectorRegister(int) const; | ||||
v128 getVectorRegister(int num) const; | v128 getVectorRegister(int num) const; | ||||
void setVectorRegister(int num, v128 value); | void setVectorRegister(int num, v128 value); | ||||
static const char *getRegisterName(int num); | static const char *getRegisterName(int num); | ||||
void jumpto(); | void jumpto(); | ||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; } | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; } | ||||
static int getArch() { return REGISTERS_X86_64; } | |||||
uint64_t getSP() const { return _registers.__rsp; } | uint64_t getSP() const { return _registers.__rsp; } | ||||
void setSP(uint64_t value) { _registers.__rsp = value; } | void setSP(uint64_t value) { _registers.__rsp = value; } | ||||
uint64_t getIP() const { return _registers.__rip; } | uint64_t getIP() const { return _registers.__rip; } | ||||
void setIP(uint64_t value) { _registers.__rip = value; } | void setIP(uint64_t value) { _registers.__rip = value; } | ||||
uint64_t getRBP() const { return _registers.__rbp; } | uint64_t getRBP() const { return _registers.__rbp; } | ||||
void setRBP(uint64_t value) { _registers.__rbp = value; } | void setRBP(uint64_t value) { _registers.__rbp = value; } | ||||
uint64_t getRBX() const { return _registers.__rbx; } | uint64_t getRBX() const { return _registers.__rbx; } | ||||
▲ Show 20 Lines • Show All 297 Lines • ▼ Show 20 Lines | public: | ||||
double getFloatRegister(int num) const; | double getFloatRegister(int num) const; | ||||
void setFloatRegister(int num, double value); | void setFloatRegister(int num, double value); | ||||
bool validVectorRegister(int num) const; | bool validVectorRegister(int num) const; | ||||
v128 getVectorRegister(int num) const; | v128 getVectorRegister(int num) const; | ||||
void setVectorRegister(int num, v128 value); | void setVectorRegister(int num, v128 value); | ||||
static const char *getRegisterName(int num); | static const char *getRegisterName(int num); | ||||
void jumpto(); | void jumpto(); | ||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; } | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; } | ||||
static int getArch() { return REGISTERS_PPC; } | |||||
uint64_t getSP() const { return _registers.__r1; } | uint64_t getSP() const { return _registers.__r1; } | ||||
void setSP(uint32_t value) { _registers.__r1 = value; } | void setSP(uint32_t value) { _registers.__r1 = value; } | ||||
uint64_t getIP() const { return _registers.__srr0; } | uint64_t getIP() const { return _registers.__srr0; } | ||||
void setIP(uint32_t value) { _registers.__srr0 = value; } | void setIP(uint32_t value) { _registers.__srr0 = value; } | ||||
private: | private: | ||||
struct ppc_thread_state_t { | struct ppc_thread_state_t { | ||||
▲ Show 20 Lines • Show All 549 Lines • ▼ Show 20 Lines | public: | ||||
double getFloatRegister(int num) const; | double getFloatRegister(int num) const; | ||||
void setFloatRegister(int num, double value); | void setFloatRegister(int num, double value); | ||||
bool validVectorRegister(int num) const; | bool validVectorRegister(int num) const; | ||||
v128 getVectorRegister(int num) const; | v128 getVectorRegister(int num) const; | ||||
void setVectorRegister(int num, v128 value); | void setVectorRegister(int num, v128 value); | ||||
static const char *getRegisterName(int num); | static const char *getRegisterName(int num); | ||||
void jumpto(); | void jumpto(); | ||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; } | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; } | ||||
static int getArch() { return REGISTERS_PPC64; } | |||||
uint64_t getSP() const { return _registers.__r1; } | uint64_t getSP() const { return _registers.__r1; } | ||||
void setSP(uint64_t value) { _registers.__r1 = value; } | void setSP(uint64_t value) { _registers.__r1 = value; } | ||||
uint64_t getIP() const { return _registers.__srr0; } | uint64_t getIP() const { return _registers.__srr0; } | ||||
void setIP(uint64_t value) { _registers.__srr0 = value; } | void setIP(uint64_t value) { _registers.__srr0 = value; } | ||||
private: | private: | ||||
struct ppc64_thread_state_t { | struct ppc64_thread_state_t { | ||||
▲ Show 20 Lines • Show All 626 Lines • ▼ Show 20 Lines | public: | ||||
double getFloatRegister(int num) const; | double getFloatRegister(int num) const; | ||||
void setFloatRegister(int num, double value); | void setFloatRegister(int num, double value); | ||||
bool validVectorRegister(int num) const; | bool validVectorRegister(int num) const; | ||||
v128 getVectorRegister(int num) const; | v128 getVectorRegister(int num) const; | ||||
void setVectorRegister(int num, v128 value); | void setVectorRegister(int num, v128 value); | ||||
static const char *getRegisterName(int num); | static const char *getRegisterName(int num); | ||||
void jumpto(); | void jumpto(); | ||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } | ||||
static int getArch() { return REGISTERS_ARM64; } | |||||
uint64_t getSP() const { return _registers.__sp; } | uint64_t getSP() const { return _registers.__sp; } | ||||
void setSP(uint64_t value) { _registers.__sp = value; } | void setSP(uint64_t value) { _registers.__sp = value; } | ||||
uint64_t getIP() const { return _registers.__pc; } | uint64_t getIP() const { return _registers.__pc; } | ||||
void setIP(uint64_t value) { _registers.__pc = value; } | void setIP(uint64_t value) { _registers.__pc = value; } | ||||
uint64_t getFP() const { return _registers.__fp; } | uint64_t getFP() const { return _registers.__fp; } | ||||
void setFP(uint64_t value) { _registers.__fp = value; } | void setFP(uint64_t value) { _registers.__fp = value; } | ||||
▲ Show 20 Lines • Show All 263 Lines • ▼ Show 20 Lines | public: | ||||
v128 getVectorRegister(int num) const; | v128 getVectorRegister(int num) const; | ||||
void setVectorRegister(int num, v128 value); | void setVectorRegister(int num, v128 value); | ||||
static const char *getRegisterName(int num); | static const char *getRegisterName(int num); | ||||
void jumpto() { | void jumpto() { | ||||
restoreSavedFloatRegisters(); | restoreSavedFloatRegisters(); | ||||
restoreCoreAndJumpTo(); | restoreCoreAndJumpTo(); | ||||
} | } | ||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; } | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; } | ||||
static int getArch() { return REGISTERS_ARM; } | |||||
uint32_t getSP() const { return _registers.__sp; } | uint32_t getSP() const { return _registers.__sp; } | ||||
void setSP(uint32_t value) { _registers.__sp = value; } | void setSP(uint32_t value) { _registers.__sp = value; } | ||||
uint32_t getIP() const { return _registers.__pc; } | uint32_t getIP() const { return _registers.__pc; } | ||||
void setIP(uint32_t value) { _registers.__pc = value; } | void setIP(uint32_t value) { _registers.__pc = value; } | ||||
void saveVFPAsX() { | void saveVFPAsX() { | ||||
assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); | assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); | ||||
▲ Show 20 Lines • Show All 461 Lines • ▼ Show 20 Lines | public: | ||||
double getFloatRegister(int num) const; | double getFloatRegister(int num) const; | ||||
void setFloatRegister(int num, double value); | void setFloatRegister(int num, double value); | ||||
bool validVectorRegister(int num) const; | bool validVectorRegister(int num) const; | ||||
v128 getVectorRegister(int num) const; | v128 getVectorRegister(int num) const; | ||||
void setVectorRegister(int num, v128 value); | void setVectorRegister(int num, v128 value); | ||||
static const char *getRegisterName(int num); | static const char *getRegisterName(int num); | ||||
void jumpto(); | void jumpto(); | ||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; } | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; } | ||||
static int getArch() { return REGISTERS_OR1K; } | |||||
uint64_t getSP() const { return _registers.__r[1]; } | uint64_t getSP() const { return _registers.__r[1]; } | ||||
void setSP(uint32_t value) { _registers.__r[1] = value; } | void setSP(uint32_t value) { _registers.__r[1] = value; } | ||||
uint64_t getIP() const { return _registers.__pc; } | uint64_t getIP() const { return _registers.__pc; } | ||||
void setIP(uint32_t value) { _registers.__pc = value; } | void setIP(uint32_t value) { _registers.__pc = value; } | ||||
private: | private: | ||||
struct or1k_thread_state_t { | struct or1k_thread_state_t { | ||||
▲ Show 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | public: | ||||
double getFloatRegister(int num) const; | double getFloatRegister(int num) const; | ||||
void setFloatRegister(int num, double value); | void setFloatRegister(int num, double value); | ||||
bool validVectorRegister(int num) const; | bool validVectorRegister(int num) const; | ||||
v128 getVectorRegister(int num) const; | v128 getVectorRegister(int num) const; | ||||
void setVectorRegister(int num, v128 value); | void setVectorRegister(int num, v128 value); | ||||
static const char *getRegisterName(int num); | static const char *getRegisterName(int num); | ||||
void jumpto(); | void jumpto(); | ||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } | ||||
static int getArch() { return REGISTERS_MIPS_O32; } | |||||
uint32_t getSP() const { return _registers.__r[29]; } | uint32_t getSP() const { return _registers.__r[29]; } | ||||
void setSP(uint32_t value) { _registers.__r[29] = value; } | void setSP(uint32_t value) { _registers.__r[29] = value; } | ||||
uint32_t getIP() const { return _registers.__pc; } | uint32_t getIP() const { return _registers.__pc; } | ||||
void setIP(uint32_t value) { _registers.__pc = value; } | void setIP(uint32_t value) { _registers.__pc = value; } | ||||
private: | private: | ||||
struct mips_o32_thread_state_t { | struct mips_o32_thread_state_t { | ||||
▲ Show 20 Lines • Show All 305 Lines • ▼ Show 20 Lines | public: | ||||
double getFloatRegister(int num) const; | double getFloatRegister(int num) const; | ||||
void setFloatRegister(int num, double value); | void setFloatRegister(int num, double value); | ||||
bool validVectorRegister(int num) const; | bool validVectorRegister(int num) const; | ||||
v128 getVectorRegister(int num) const; | v128 getVectorRegister(int num) const; | ||||
void setVectorRegister(int num, v128 value); | void setVectorRegister(int num, v128 value); | ||||
static const char *getRegisterName(int num); | static const char *getRegisterName(int num); | ||||
void jumpto(); | void jumpto(); | ||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } | ||||
static int getArch() { return REGISTERS_MIPS_NEWABI; } | |||||
uint64_t getSP() const { return _registers.__r[29]; } | uint64_t getSP() const { return _registers.__r[29]; } | ||||
void setSP(uint64_t value) { _registers.__r[29] = value; } | void setSP(uint64_t value) { _registers.__r[29] = value; } | ||||
uint64_t getIP() const { return _registers.__pc; } | uint64_t getIP() const { return _registers.__pc; } | ||||
void setIP(uint64_t value) { _registers.__pc = value; } | void setIP(uint64_t value) { _registers.__pc = value; } | ||||
private: | private: | ||||
struct mips_newabi_thread_state_t { | struct mips_newabi_thread_state_t { | ||||
▲ Show 20 Lines • Show All 252 Lines • ▼ Show 20 Lines | case UNW_MIPS_HI: | ||||
return "$hi"; | return "$hi"; | ||||
case UNW_MIPS_LO: | case UNW_MIPS_LO: | ||||
return "$lo"; | return "$lo"; | ||||
default: | default: | ||||
return "unknown register"; | return "unknown register"; | ||||
} | } | ||||
} | } | ||||
#endif // _LIBUNWIND_TARGET_MIPS_NEWABI | #endif // _LIBUNWIND_TARGET_MIPS_NEWABI | ||||
#if defined(_LIBUNWIND_TARGET_SPARC) | |||||
/// Registers_sparc holds the register state of a thread in a 32-bit Sparc | |||||
/// process. | |||||
compnerd: I guess as long as we don't care about async exceptions where the `%o7` is being twiddled… | |||||
class _LIBUNWIND_HIDDEN Registers_sparc { | |||||
public: | |||||
Registers_sparc(); | |||||
Registers_sparc(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); | |||||
static const char *getRegisterName(int num); | |||||
void jumpto(); | |||||
static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; } | |||||
static int getArch() { return REGISTERS_SPARC; } | |||||
uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; } | |||||
void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; } | |||||
uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; } | |||||
void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; } | |||||
private: | |||||
struct sparc_thread_state_t { | |||||
unsigned int __regs[32]; | |||||
}; | |||||
sparc_thread_state_t _registers; | |||||
}; | |||||
inline Registers_sparc::Registers_sparc(const void *registers) { | |||||
static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit), | |||||
"sparc registers do not fit into unw_context_t"); | |||||
Not Done ReplyInline ActionsSpurious empty line. compnerd: Spurious empty line. | |||||
memcpy(&_registers, static_cast<const uint8_t *>(registers), | |||||
sizeof(_registers)); | |||||
} | |||||
inline Registers_sparc::Registers_sparc() { | |||||
memset(&_registers, 0, sizeof(_registers)); | |||||
} | |||||
inline bool Registers_sparc::validRegister(int regNum) const { | |||||
if (regNum == UNW_REG_IP) | |||||
return true; | |||||
if (regNum == UNW_REG_SP) | |||||
return true; | |||||
if (regNum < 0) | |||||
return false; | |||||
Not Done ReplyInline ActionsSpurious empty line compnerd: Spurious empty line | |||||
if (regNum <= UNW_SPARC_I7) | |||||
return true; | |||||
return false; | |||||
} | |||||
inline uint32_t Registers_sparc::getRegister(int regNum) const { | |||||
if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { | |||||
return _registers.__regs[regNum]; | |||||
} | |||||
switch (regNum) { | |||||
case UNW_REG_IP: | |||||
return _registers.__regs[UNW_SPARC_O7]; | |||||
case UNW_REG_SP: | |||||
return _registers.__regs[UNW_SPARC_O6]; | |||||
} | |||||
_LIBUNWIND_ABORT("unsupported sparc register"); | |||||
} | |||||
inline void Registers_sparc::setRegister(int regNum, uint32_t value) { | |||||
if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { | |||||
_registers.__regs[regNum] = value; | |||||
return; | |||||
} | |||||
switch (regNum) { | |||||
case UNW_REG_IP: | |||||
_registers.__regs[UNW_SPARC_O7] = value; | |||||
return; | |||||
case UNW_REG_SP: | |||||
_registers.__regs[UNW_SPARC_O6] = value; | |||||
return; | |||||
} | |||||
_LIBUNWIND_ABORT("unsupported sparc register"); | |||||
} | |||||
inline bool Registers_sparc::validFloatRegister(int regNum) const { | |||||
return false; | |||||
} | |||||
inline double Registers_sparc::getFloatRegister(int regNum) const { | |||||
_LIBUNWIND_ABORT("no Sparc float registers"); | |||||
} | |||||
inline void Registers_sparc::setFloatRegister(int regNum, double value) { | |||||
_LIBUNWIND_ABORT("no Sparc float registers"); | |||||
} | |||||
inline bool Registers_sparc::validVectorRegister(int regNum) const { | |||||
return false; | |||||
} | |||||
inline v128 Registers_sparc::getVectorRegister(int regNum) const { | |||||
_LIBUNWIND_ABORT("no Sparc vector registers"); | |||||
} | |||||
inline void Registers_sparc::setVectorRegister(int regNum, v128 value) { | |||||
_LIBUNWIND_ABORT("no Sparc vector registers"); | |||||
} | |||||
inline const char *Registers_sparc::getRegisterName(int regNum) { | |||||
switch (regNum) { | |||||
case UNW_REG_IP: | |||||
return "pc"; | |||||
case UNW_SPARC_G0: | |||||
return "g0"; | |||||
case UNW_SPARC_G1: | |||||
return "g1"; | |||||
case UNW_SPARC_G2: | |||||
return "g2"; | |||||
case UNW_SPARC_G3: | |||||
return "g3"; | |||||
case UNW_SPARC_G4: | |||||
return "g4"; | |||||
case UNW_SPARC_G5: | |||||
return "g5"; | |||||
case UNW_SPARC_G6: | |||||
return "g6"; | |||||
case UNW_SPARC_G7: | |||||
return "g7"; | |||||
case UNW_SPARC_O0: | |||||
return "o0"; | |||||
case UNW_SPARC_O1: | |||||
return "o1"; | |||||
case UNW_SPARC_O2: | |||||
return "o2"; | |||||
case UNW_SPARC_O3: | |||||
return "o3"; | |||||
case UNW_SPARC_O4: | |||||
return "o4"; | |||||
case UNW_SPARC_O5: | |||||
return "o5"; | |||||
case UNW_REG_SP: | |||||
case UNW_SPARC_O6: | |||||
return "sp"; | |||||
case UNW_SPARC_O7: | |||||
return "o7"; | |||||
case UNW_SPARC_L0: | |||||
return "l0"; | |||||
case UNW_SPARC_L1: | |||||
return "l1"; | |||||
case UNW_SPARC_L2: | |||||
return "l2"; | |||||
case UNW_SPARC_L3: | |||||
return "l3"; | |||||
case UNW_SPARC_L4: | |||||
return "l4"; | |||||
case UNW_SPARC_L5: | |||||
return "l5"; | |||||
case UNW_SPARC_L6: | |||||
return "l6"; | |||||
case UNW_SPARC_L7: | |||||
return "l7"; | |||||
case UNW_SPARC_I0: | |||||
return "i0"; | |||||
case UNW_SPARC_I1: | |||||
return "i1"; | |||||
case UNW_SPARC_I2: | |||||
return "i2"; | |||||
case UNW_SPARC_I3: | |||||
return "i3"; | |||||
case UNW_SPARC_I4: | |||||
return "i4"; | |||||
case UNW_SPARC_I5: | |||||
return "i5"; | |||||
case UNW_SPARC_I6: | |||||
return "fp"; | |||||
case UNW_SPARC_I7: | |||||
return "i7"; | |||||
default: | |||||
return "unknown register"; | |||||
} | |||||
} | |||||
#endif // _LIBUNWIND_TARGET_SPARC | |||||
} // namespace libunwind | } // namespace libunwind | ||||
#endif // __REGISTERS_HPP__ | #endif // __REGISTERS_HPP__ |
I guess as long as we don't care about async exceptions where the %o7 is being twiddled around for a call or being used as a temporary, this should be okay (IIRC, %o7 needs to be saved before call on SPARC).