summaryrefslogtreecommitdiffstats
path: root/lib/libunwind/src/Registers.hpp
diff options
context:
space:
mode:
authorvisa <visa@openbsd.org>2018-10-21 05:08:35 +0000
committervisa <visa@openbsd.org>2018-10-21 05:08:35 +0000
commitdef71959deb2deb81d76c49c6917229abc5ea77b (patch)
tree9bb3be5704bd5174cbbdfd0929668756991eef8a /lib/libunwind/src/Registers.hpp
parentEnable the integrated assembler on mips64. (diff)
downloadwireguard-openbsd-def71959deb2deb81d76c49c6917229abc5ea77b.tar.xz
wireguard-openbsd-def71959deb2deb81d76c49c6917229abc5ea77b.zip
Backport libunwind hardware floating point handling for mips64.
Upstream reference: https://reviews.llvm.org/D41968 OK kettenis@
Diffstat (limited to 'lib/libunwind/src/Registers.hpp')
-rw-r--r--lib/libunwind/src/Registers.hpp214
1 files changed, 205 insertions, 9 deletions
diff --git a/lib/libunwind/src/Registers.hpp b/lib/libunwind/src/Registers.hpp
index 888d07be5b2..9aadaf4caf5 100644
--- a/lib/libunwind/src/Registers.hpp
+++ b/lib/libunwind/src/Registers.hpp
@@ -2793,6 +2793,7 @@ public:
void setSP(uint32_t value) { _registers.__r[29] = value; }
uint32_t getIP() const { return _registers.__pc; }
void setIP(uint32_t value) { _registers.__pc = value; }
+ uint32_t getWCookie() const { return 0; }
private:
struct mips_o32_thread_state_t {
@@ -2803,6 +2804,14 @@ private:
};
mips_o32_thread_state_t _registers;
+#ifdef __mips_hard_float
+ /// O32 with 32-bit floating point registers only uses half of this
+ /// space. However, using the same layout for 32-bit vs 64-bit
+ /// floating point registers results in a single context size for
+ /// O32 with hard float.
+ uint32_t _padding;
+ double _floats[32];
+#endif
};
inline Registers_mips_o32::Registers_mips_o32(const void *registers) {
@@ -2829,13 +2838,28 @@ inline bool Registers_mips_o32::validRegister(int regNum) const {
return true;
if (regNum == UNW_MIPS_LO)
return true;
- // FIXME: Hard float, DSP accumulator registers, MSA registers
+#if defined(__mips_hard_float) && __mips_fpr == 32
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+ return true;
+#endif
+ // FIXME: 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];
+#if defined(__mips_hard_float) && __mips_fpr == 32
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
+ uint32_t *p;
+
+ if (regNum % 2 == 0)
+ p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
+ else
+ p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
+ return *p;
+ }
+#endif
switch (regNum) {
case UNW_REG_IP:
@@ -2855,6 +2879,18 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
_registers.__r[regNum - UNW_MIPS_R0] = value;
return;
}
+#if defined(__mips_hard_float) && __mips_fpr == 32
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {
+ uint32_t *p;
+
+ if (regNum % 2 == 0)
+ p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];
+ else
+ p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;
+ *p = value;
+ return;
+ }
+#endif
switch (regNum) {
case UNW_REG_IP:
@@ -2873,17 +2909,31 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
_LIBUNWIND_ABORT("unsupported mips_o32 register");
}
-inline bool Registers_mips_o32::validFloatRegister(int /* regNum */) const {
+inline bool Registers_mips_o32::validFloatRegister(int regNum) const {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+ return true;
+#endif
return false;
}
-inline double Registers_mips_o32::getFloatRegister(int /* regNum */) const {
+inline double Registers_mips_o32::getFloatRegister(int regNum) const {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+ assert(validFloatRegister(regNum));
+ return _floats[regNum - UNW_MIPS_F0];
+#else
_LIBUNWIND_ABORT("mips_o32 float support not implemented");
+#endif
}
-inline void Registers_mips_o32::setFloatRegister(int /* regNum */,
- double /* value */) {
+inline void Registers_mips_o32::setFloatRegister(int regNum,
+ double value) {
+#if defined(__mips_hard_float) && __mips_fpr == 64
+ assert(validFloatRegister(regNum));
+ _floats[regNum - UNW_MIPS_F0] = value;
+#else
_LIBUNWIND_ABORT("mips_o32 float support not implemented");
+#endif
}
inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {
@@ -2964,6 +3014,70 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {
return "$30";
case UNW_MIPS_R31:
return "$31";
+ case UNW_MIPS_F0:
+ return "$f0";
+ case UNW_MIPS_F1:
+ return "$f1";
+ case UNW_MIPS_F2:
+ return "$f2";
+ case UNW_MIPS_F3:
+ return "$f3";
+ case UNW_MIPS_F4:
+ return "$f4";
+ case UNW_MIPS_F5:
+ return "$f5";
+ case UNW_MIPS_F6:
+ return "$f6";
+ case UNW_MIPS_F7:
+ return "$f7";
+ case UNW_MIPS_F8:
+ return "$f8";
+ case UNW_MIPS_F9:
+ return "$f9";
+ case UNW_MIPS_F10:
+ return "$f10";
+ case UNW_MIPS_F11:
+ return "$f11";
+ case UNW_MIPS_F12:
+ return "$f12";
+ case UNW_MIPS_F13:
+ return "$f13";
+ case UNW_MIPS_F14:
+ return "$f14";
+ case UNW_MIPS_F15:
+ return "$f15";
+ case UNW_MIPS_F16:
+ return "$f16";
+ case UNW_MIPS_F17:
+ return "$f17";
+ case UNW_MIPS_F18:
+ return "$f18";
+ case UNW_MIPS_F19:
+ return "$f19";
+ case UNW_MIPS_F20:
+ return "$f20";
+ case UNW_MIPS_F21:
+ return "$f21";
+ case UNW_MIPS_F22:
+ return "$f22";
+ case UNW_MIPS_F23:
+ return "$f23";
+ case UNW_MIPS_F24:
+ return "$f24";
+ case UNW_MIPS_F25:
+ return "$f25";
+ case UNW_MIPS_F26:
+ return "$f26";
+ case UNW_MIPS_F27:
+ return "$f27";
+ case UNW_MIPS_F28:
+ return "$f28";
+ case UNW_MIPS_F29:
+ return "$f29";
+ case UNW_MIPS_F30:
+ return "$f30";
+ case UNW_MIPS_F31:
+ return "$f31";
case UNW_MIPS_HI:
return "$hi";
case UNW_MIPS_LO:
@@ -2999,6 +3113,7 @@ public:
void setSP(uint64_t value) { _registers.__r[29] = value; }
uint64_t getIP() const { return _registers.__pc; }
void setIP(uint64_t value) { _registers.__pc = value; }
+ uint32_t getWCookie() const { return 0; }
private:
struct mips_n64_thread_state_t {
@@ -3009,6 +3124,9 @@ private:
};
mips_n64_thread_state_t _registers;
+#ifdef __mips_hard_float
+ double _floats[32];
+#endif
};
inline Registers_mips_n64::Registers_mips_n64(const void *registers) {
@@ -3079,17 +3197,31 @@ inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) {
_LIBUNWIND_ABORT("unsupported mips_n64 register");
}
-inline bool Registers_mips_n64::validFloatRegister(int /* regNum */) const {
+inline bool Registers_mips_n64::validFloatRegister(int regNum) const {
+#ifdef __mips_hard_float
+ if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)
+ return true;
+#endif
return false;
}
-inline double Registers_mips_n64::getFloatRegister(int /* regNum */) const {
+inline double Registers_mips_n64::getFloatRegister(int regNum) const {
+#ifdef __mips_hard_float
+ assert(validFloatRegister(regNum));
+ return _floats[regNum - UNW_MIPS_F0];
+#else
_LIBUNWIND_ABORT("mips_n64 float support not implemented");
+#endif
}
-inline void Registers_mips_n64::setFloatRegister(int /* regNum */,
- double /* value */) {
+inline void Registers_mips_n64::setFloatRegister(int regNum,
+ double value) {
+#ifdef __mips_hard_float
+ assert(validFloatRegister(regNum));
+ _floats[regNum - UNW_MIPS_F0] = value;
+#else
_LIBUNWIND_ABORT("mips_n64 float support not implemented");
+#endif
}
inline bool Registers_mips_n64::validVectorRegister(int /* regNum */) const {
@@ -3170,6 +3302,70 @@ inline const char *Registers_mips_n64::getRegisterName(int regNum) {
return "$30";
case UNW_MIPS_R31:
return "$31";
+ case UNW_MIPS_F0:
+ return "$f0";
+ case UNW_MIPS_F1:
+ return "$f1";
+ case UNW_MIPS_F2:
+ return "$f2";
+ case UNW_MIPS_F3:
+ return "$f3";
+ case UNW_MIPS_F4:
+ return "$f4";
+ case UNW_MIPS_F5:
+ return "$f5";
+ case UNW_MIPS_F6:
+ return "$f6";
+ case UNW_MIPS_F7:
+ return "$f7";
+ case UNW_MIPS_F8:
+ return "$f8";
+ case UNW_MIPS_F9:
+ return "$f9";
+ case UNW_MIPS_F10:
+ return "$f10";
+ case UNW_MIPS_F11:
+ return "$f11";
+ case UNW_MIPS_F12:
+ return "$f12";
+ case UNW_MIPS_F13:
+ return "$f13";
+ case UNW_MIPS_F14:
+ return "$f14";
+ case UNW_MIPS_F15:
+ return "$f15";
+ case UNW_MIPS_F16:
+ return "$f16";
+ case UNW_MIPS_F17:
+ return "$f17";
+ case UNW_MIPS_F18:
+ return "$f18";
+ case UNW_MIPS_F19:
+ return "$f19";
+ case UNW_MIPS_F20:
+ return "$f20";
+ case UNW_MIPS_F21:
+ return "$f21";
+ case UNW_MIPS_F22:
+ return "$f22";
+ case UNW_MIPS_F23:
+ return "$f23";
+ case UNW_MIPS_F24:
+ return "$f24";
+ case UNW_MIPS_F25:
+ return "$f25";
+ case UNW_MIPS_F26:
+ return "$f26";
+ case UNW_MIPS_F27:
+ return "$f27";
+ case UNW_MIPS_F28:
+ return "$f28";
+ case UNW_MIPS_F29:
+ return "$f29";
+ case UNW_MIPS_F30:
+ return "$f30";
+ case UNW_MIPS_F31:
+ return "$f31";
case UNW_MIPS_HI:
return "$hi";
case UNW_MIPS_LO: