[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
This revision was automatically updated to reflect the committed changes. Closed by commit rL332414: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs. (authored by jhb, committed by ). Herald added a subscriber: llvm-commits. Repository: rL LLVM https://reviews.llvm.org/D41968 Files: libunwind/trunk/include/__libunwind_config.h libunwind/trunk/include/libunwind.h libunwind/trunk/src/Registers.hpp libunwind/trunk/src/UnwindRegistersRestore.S libunwind/trunk/src/UnwindRegistersSave.S libunwind/trunk/src/libunwind.cpp Index: libunwind/trunk/src/Registers.hpp === --- libunwind/trunk/src/Registers.hpp +++ libunwind/trunk/src/Registers.hpp @@ -2718,6 +2718,14 @@ }; 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) { @@ -2744,13 +2752,28 @@ 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: @@ -2770,6 +2793,18 @@ _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: @@ -2788,17 +2823,31 @@ _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 { @@ -2879,6 +2928,70 @@ 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
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
sdardis accepted this revision. sdardis added a comment. This revision is now accepted and ready to land. Herald added a subscriber: chrib. Sorry for the delay. LGTM. Repository: rUNW libunwind https://reviews.llvm.org/D41968 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
bsdjhb added a comment. Ping @sdardis @compnerd Repository: rUNW libunwind https://reviews.llvm.org/D41968 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
bsdjhb added a comment. @sdardis ping. I think the approach I've used for O32 is probably the right one in that it matches what DWARF expects (DWARF doesn't treat the 32-bit floating point registers as pairs but as individual registers). I think the question is if I O32 with 32-bit FP registers should use an array of float[]s instead of an array of double[]s though (which adds an extra #ifdef for context size) vs keeping the current layout. Repository: rUNW libunwind https://reviews.llvm.org/D41968 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
bsdjhb marked 2 inline comments as done. bsdjhb added a comment. This version follows the suggestion I made earlier of treating 32-bit floating point registers as a "plain" register for O32 rather than a floating-point register. It seems to work for me though for O32 I've only tested with 32-bit floating point registers. If we stick with this approach for 32-bit floating point it might be simpler and/or more readable to make _floats[] an array of uint32_t for that case and just use different context sizes for the O32 with 32-bit fp vs O32 with 64-bit fp. This version works in my testing on FreeBSD for O32 with 32-bit FPR, N32, and N64. Repository: rUNW libunwind https://reviews.llvm.org/D41968 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
bsdjhb updated this revision to Diff 137085. bsdjhb added a comment. - Add a comment about using a single FP layout for O32. - Treat 32-bit floating point registers on O32 as plain registers. Repository: rUNW libunwind https://reviews.llvm.org/D41968 Files: include/__libunwind_config.h include/libunwind.h src/Registers.hpp src/UnwindRegistersRestore.S src/UnwindRegistersSave.S src/libunwind.cpp Index: src/libunwind.cpp === --- src/libunwind.cpp +++ src/libunwind.cpp @@ -61,10 +61,9 @@ # define REGISTER_KIND Registers_arm #elif defined(__or1k__) # define REGISTER_KIND Registers_or1k -#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 && \ -defined(__mips_soft_float) +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 # define REGISTER_KIND Registers_mips_o32 -#elif defined(__mips64) && defined(__mips_soft_float) +#elif defined(__mips64) # define REGISTER_KIND Registers_mips_newabi #elif defined(__mips__) # warning The MIPS architecture is not supported with this ABI and environment! Index: src/UnwindRegistersSave.S === --- src/UnwindRegistersSave.S +++ src/UnwindRegistersSave.S @@ -116,8 +116,7 @@ xorl %eax, %eax# return UNW_ESUCCESS ret -#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 && \ -defined(__mips_soft_float) +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 # # extern int unw_getcontext(unw_context_t* thread_state) @@ -168,12 +167,65 @@ sw$8, (4 * 33)($4) mflo $8 sw$8, (4 * 34)($4) +#ifdef __mips_hard_float +#if __mips_fpr == 32 + sdc1 $f0, (4 * 36 + 8 * 0)($4) + sdc1 $f2, (4 * 36 + 8 * 2)($4) + sdc1 $f4, (4 * 36 + 8 * 4)($4) + sdc1 $f6, (4 * 36 + 8 * 6)($4) + sdc1 $f8, (4 * 36 + 8 * 8)($4) + sdc1 $f10, (4 * 36 + 8 * 10)($4) + sdc1 $f12, (4 * 36 + 8 * 12)($4) + sdc1 $f14, (4 * 36 + 8 * 14)($4) + sdc1 $f16, (4 * 36 + 8 * 16)($4) + sdc1 $f18, (4 * 36 + 8 * 18)($4) + sdc1 $f20, (4 * 36 + 8 * 20)($4) + sdc1 $f22, (4 * 36 + 8 * 22)($4) + sdc1 $f24, (4 * 36 + 8 * 24)($4) + sdc1 $f26, (4 * 36 + 8 * 26)($4) + sdc1 $f28, (4 * 36 + 8 * 28)($4) + sdc1 $f30, (4 * 36 + 8 * 30)($4) +#else + sdc1 $f0, (4 * 36 + 8 * 0)($4) + sdc1 $f1, (4 * 36 + 8 * 1)($4) + sdc1 $f2, (4 * 36 + 8 * 2)($4) + sdc1 $f3, (4 * 36 + 8 * 3)($4) + sdc1 $f4, (4 * 36 + 8 * 4)($4) + sdc1 $f5, (4 * 36 + 8 * 5)($4) + sdc1 $f6, (4 * 36 + 8 * 6)($4) + sdc1 $f7, (4 * 36 + 8 * 7)($4) + sdc1 $f8, (4 * 36 + 8 * 8)($4) + sdc1 $f9, (4 * 36 + 8 * 9)($4) + sdc1 $f10, (4 * 36 + 8 * 10)($4) + sdc1 $f11, (4 * 36 + 8 * 11)($4) + sdc1 $f12, (4 * 36 + 8 * 12)($4) + sdc1 $f13, (4 * 36 + 8 * 13)($4) + sdc1 $f14, (4 * 36 + 8 * 14)($4) + sdc1 $f15, (4 * 36 + 8 * 15)($4) + sdc1 $f16, (4 * 36 + 8 * 16)($4) + sdc1 $f17, (4 * 36 + 8 * 17)($4) + sdc1 $f18, (4 * 36 + 8 * 18)($4) + sdc1 $f19, (4 * 36 + 8 * 19)($4) + sdc1 $f20, (4 * 36 + 8 * 20)($4) + sdc1 $f21, (4 * 36 + 8 * 21)($4) + sdc1 $f22, (4 * 36 + 8 * 22)($4) + sdc1 $f23, (4 * 36 + 8 * 23)($4) + sdc1 $f24, (4 * 36 + 8 * 24)($4) + sdc1 $f25, (4 * 36 + 8 * 25)($4) + sdc1 $f26, (4 * 36 + 8 * 26)($4) + sdc1 $f27, (4 * 36 + 8 * 27)($4) + sdc1 $f28, (4 * 36 + 8 * 28)($4) + sdc1 $f29, (4 * 36 + 8 * 29)($4) + sdc1 $f30, (4 * 36 + 8 * 30)($4) + sdc1 $f31, (4 * 36 + 8 * 31)($4) +#endif +#endif jr $31 # return UNW_ESUCCESS or$2, $0, $0 .set pop -#elif defined(__mips64) && defined(__mips_soft_float) +#elif defined(__mips64) # # extern int unw_getcontext(unw_context_t* thread_state) @@ -224,6 +276,40 @@ sd$8, (8 * 33)($4) mflo $8 sd$8, (8 * 34)($4) +#ifdef __mips_hard_float + sdc1 $f0, (8 * 35)($4) + sdc1 $f1, (8 * 36)($4) + sdc1 $f2, (8 * 37)($4) + sdc1 $f3, (8 * 38)($4) + sdc1 $f4, (8 * 39)($4) + sdc1 $f5, (8 * 40)($4) + sdc1 $f6, (8 * 41)($4) + sdc1 $f7, (8 * 42)($4) + sdc1 $f8, (8 * 43)($4) + sdc1 $f9, (8 * 44)($4) + sdc1 $f10, (8 * 45)($4) + sdc1 $f11, (8 * 46)($4) + sdc1 $f12, (8 * 47)($4) + sdc1 $f13, (8 * 48)($4) + sdc1 $f14, (8 * 49)($4) + sdc1 $f15, (8 * 50)($4) + sdc1 $f16, (8 * 51)($4) + sdc1 $f17, (8 * 52)($4) + sdc1 $f18, (8 * 53)($4) + sdc1 $f19, (8 * 54)($4) + sdc1 $f20, (8 * 55)($4) + sdc1 $f21, (8 * 56)($4) + sdc1 $f22, (8 * 57)($4) + sdc1 $f23, (8 * 58)($4) + sdc1 $f24, (8 * 59)($4) + sdc1 $f25, (8 * 60)($4) + sdc1 $f26, (8 * 61)($4) + sdc1 $f27, (8 * 62)($4) + sdc1 $f28, (8 * 63)($4) + sdc1 $f29, (8 * 64)($4) + sdc1 $f30, (8 * 65)($4) + sdc1 $f31, (8 * 66)($4) +#endif jr $31 # return UNW_ESUCCESS or$2, $0, $0 Index: src/UnwindRegistersRestore.S === --- src/UnwindRegistersRestore.S +++ src/UnwindRegistersRestore.S @@ -799,8 +799,7 @@ l.jr r9
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
bsdjhb updated this revision to Diff 136164. bsdjhb added a comment. Herald added a subscriber: christof. - Rebase after N32 commit. - Use ldc1/sdc1 rather than l.d and s.d. Repository: rUNW libunwind https://reviews.llvm.org/D41968 Files: include/__libunwind_config.h include/libunwind.h src/Registers.hpp src/UnwindRegistersRestore.S src/UnwindRegistersSave.S src/libunwind.cpp Index: src/libunwind.cpp === --- src/libunwind.cpp +++ src/libunwind.cpp @@ -61,10 +61,9 @@ # define REGISTER_KIND Registers_arm #elif defined(__or1k__) # define REGISTER_KIND Registers_or1k -#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 && \ -defined(__mips_soft_float) +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 # define REGISTER_KIND Registers_mips_o32 -#elif defined(__mips64) && defined(__mips_soft_float) +#elif defined(__mips64) # define REGISTER_KIND Registers_mips_newabi #elif defined(__mips__) # warning The MIPS architecture is not supported with this ABI and environment! Index: src/UnwindRegistersSave.S === --- src/UnwindRegistersSave.S +++ src/UnwindRegistersSave.S @@ -116,8 +116,7 @@ xorl %eax, %eax# return UNW_ESUCCESS ret -#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 && \ -defined(__mips_soft_float) +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 # # extern int unw_getcontext(unw_context_t* thread_state) @@ -168,12 +167,65 @@ sw$8, (4 * 33)($4) mflo $8 sw$8, (4 * 34)($4) +#ifdef __mips_hard_float +#if __mips_fpr == 32 + sdc1 $f0, (4 * 36 + 8 * 0)($4) + sdc1 $f2, (4 * 36 + 8 * 2)($4) + sdc1 $f4, (4 * 36 + 8 * 4)($4) + sdc1 $f6, (4 * 36 + 8 * 6)($4) + sdc1 $f8, (4 * 36 + 8 * 8)($4) + sdc1 $f10, (4 * 36 + 8 * 10)($4) + sdc1 $f12, (4 * 36 + 8 * 12)($4) + sdc1 $f14, (4 * 36 + 8 * 14)($4) + sdc1 $f16, (4 * 36 + 8 * 16)($4) + sdc1 $f18, (4 * 36 + 8 * 18)($4) + sdc1 $f20, (4 * 36 + 8 * 20)($4) + sdc1 $f22, (4 * 36 + 8 * 22)($4) + sdc1 $f24, (4 * 36 + 8 * 24)($4) + sdc1 $f26, (4 * 36 + 8 * 26)($4) + sdc1 $f28, (4 * 36 + 8 * 28)($4) + sdc1 $f30, (4 * 36 + 8 * 30)($4) +#else + sdc1 $f0, (4 * 36 + 8 * 0)($4) + sdc1 $f1, (4 * 36 + 8 * 1)($4) + sdc1 $f2, (4 * 36 + 8 * 2)($4) + sdc1 $f3, (4 * 36 + 8 * 3)($4) + sdc1 $f4, (4 * 36 + 8 * 4)($4) + sdc1 $f5, (4 * 36 + 8 * 5)($4) + sdc1 $f6, (4 * 36 + 8 * 6)($4) + sdc1 $f7, (4 * 36 + 8 * 7)($4) + sdc1 $f8, (4 * 36 + 8 * 8)($4) + sdc1 $f9, (4 * 36 + 8 * 9)($4) + sdc1 $f10, (4 * 36 + 8 * 10)($4) + sdc1 $f11, (4 * 36 + 8 * 11)($4) + sdc1 $f12, (4 * 36 + 8 * 12)($4) + sdc1 $f13, (4 * 36 + 8 * 13)($4) + sdc1 $f14, (4 * 36 + 8 * 14)($4) + sdc1 $f15, (4 * 36 + 8 * 15)($4) + sdc1 $f16, (4 * 36 + 8 * 16)($4) + sdc1 $f17, (4 * 36 + 8 * 17)($4) + sdc1 $f18, (4 * 36 + 8 * 18)($4) + sdc1 $f19, (4 * 36 + 8 * 19)($4) + sdc1 $f20, (4 * 36 + 8 * 20)($4) + sdc1 $f21, (4 * 36 + 8 * 21)($4) + sdc1 $f22, (4 * 36 + 8 * 22)($4) + sdc1 $f23, (4 * 36 + 8 * 23)($4) + sdc1 $f24, (4 * 36 + 8 * 24)($4) + sdc1 $f25, (4 * 36 + 8 * 25)($4) + sdc1 $f26, (4 * 36 + 8 * 26)($4) + sdc1 $f27, (4 * 36 + 8 * 27)($4) + sdc1 $f28, (4 * 36 + 8 * 28)($4) + sdc1 $f29, (4 * 36 + 8 * 29)($4) + sdc1 $f30, (4 * 36 + 8 * 30)($4) + sdc1 $f31, (4 * 36 + 8 * 31)($4) +#endif +#endif jr $31 # return UNW_ESUCCESS or$2, $0, $0 .set pop -#elif defined(__mips64) && defined(__mips_soft_float) +#elif defined(__mips64) # # extern int unw_getcontext(unw_context_t* thread_state) @@ -224,6 +276,40 @@ sd$8, (8 * 33)($4) mflo $8 sd$8, (8 * 34)($4) +#ifdef __mips_hard_float + sdc1 $f0, (8 * 35)($4) + sdc1 $f1, (8 * 36)($4) + sdc1 $f2, (8 * 37)($4) + sdc1 $f3, (8 * 38)($4) + sdc1 $f4, (8 * 39)($4) + sdc1 $f5, (8 * 40)($4) + sdc1 $f6, (8 * 41)($4) + sdc1 $f7, (8 * 42)($4) + sdc1 $f8, (8 * 43)($4) + sdc1 $f9, (8 * 44)($4) + sdc1 $f10, (8 * 45)($4) + sdc1 $f11, (8 * 46)($4) + sdc1 $f12, (8 * 47)($4) + sdc1 $f13, (8 * 48)($4) + sdc1 $f14, (8 * 49)($4) + sdc1 $f15, (8 * 50)($4) + sdc1 $f16, (8 * 51)($4) + sdc1 $f17, (8 * 52)($4) + sdc1 $f18, (8 * 53)($4) + sdc1 $f19, (8 * 54)($4) + sdc1 $f20, (8 * 55)($4) + sdc1 $f21, (8 * 56)($4) + sdc1 $f22, (8 * 57)($4) + sdc1 $f23, (8 * 58)($4) + sdc1 $f24, (8 * 59)($4) + sdc1 $f25, (8 * 60)($4) + sdc1 $f26, (8 * 61)($4) + sdc1 $f27, (8 * 62)($4) + sdc1 $f28, (8 * 63)($4) + sdc1 $f29, (8 * 64)($4) + sdc1 $f30, (8 * 65)($4) + sdc1 $f31, (8 * 66)($4) +#endif jr $31 # return UNW_ESUCCESS or$2, $0, $0 Index: src/UnwindRegistersRestore.S === --- src/UnwindRegistersRestore.S +++ src/UnwindRegistersRestore.S @@ -799,8 +799,7 @@ l.jr r9 l.nop
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
bsdjhb added a comment. Hmmm, so I was somewhat mistaken as DwarfInstructions.hpp::stepWithDwarf() does use the Register class's setFloatRegister(), however, it assumes that the floating point register is always a double (DwarfInstructions.hpp::getSavedFloatRegister() uses AddressSpace::getDouble() to read a double from memory). So I think that means that the NEWABI cases work as-is. O32 with 64-bit FP registers should also work as-is. However, O32 with 32-bit FP registers will not quite work. The DWARF info for O32 with 32-bit registers does save/restore individual 32-bit registers: 06dc 0034 06e0 FDE cie= pc=d384..d46c DW_CFA_advance_loc4: 16 to d394 DW_CFA_def_cfa_offset: 56 DW_CFA_advance_loc4: 20 to d3a8 DW_CFA_offset: r31 at cfa-12 DW_CFA_offset: r17 at cfa-16 DW_CFA_offset: r16 at cfa-20 DW_CFA_offset: r52 at cfa-4 DW_CFA_offset: r53 at cfa-8 ... If the compiler happens to always save and restore them in pairs then the current approach will work. If we don't want to assume that they are saved and restored in pairs, then we could instead perhaps claim that 32-bit FP registers aren't really floating point but are just plain 32-bit registers. This would make unwinding work (I believe), but would mean that one would need to use unw_get_reg() instead of unw_get_fpreg() to fetch individual 32-bit FP registers. https://reviews.llvm.org/D41968 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
bsdjhb added a comment. After thinking about this some more, I need to rework this a bit. The choice of how to expose the floating point registers via getFloatingPointRegister / setFloatingPointRegister only affects consumers of the libunwind unw_get_fpreg/unw_set_fpreg. I think a bigger factor is that we need to honor unwind rules in frames that describe the saved location of FP registers on the stack (which this patchset doesn't do). I think that's fairly trivial for the case where an FP register is the same size as a GP register, and it probably argues for storing 32-bit FP registers as individual 'float' if that is how the unwind information is encoded. I haven't yet looked to see what the implications would be for O32 MIPS with 64-bit FP registers. It may be that I punt on that configuration for now. https://reviews.llvm.org/D41968 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
sdardis added a reviewer: compnerd. sdardis added a comment. I am not sure what the answer is. There's a slightly different issue in that returning the contents of a floating point register on MIPS and expecting it to be a double is not necessarily correct. For a 64bit FPU, the result of lwc1/mtc1 leaves the upper 32bits of an floating point register as **UNPREDICTABLE** by the architecture definition. It's entirely possible for the application being unwound to be operating on single precision values, but the contents of the register in it's entirety are a signalling nan. I think the least worst option for registers is to always present the data as double values and to only permit access to the sets of double registers for O32, and leave the API user to determine how to proceed. Unfortunately this complicates unwinding in the case of https://reviews.llvm.org/source/compiler-rt/ in strict fp32 mode as that doesn't have double precision at all. But there's more work to be done for https://reviews.llvm.org/source/compiler-rt/ support anyway, so it can be deferred. Some nits inlined. Also, watch out for ABI guards such as (defined(_ABIN32) || defined(_ABI64), these can be replaced with __mips64. Comment at: src/Registers.hpp:2659 + uint32_t _padding; + double _floats[32]; +#endif bsdjhb wrote: > I chose to always use double here to avoid having different context sizes for > the 32-bit vs 64-bit FPR cases. Add a comment highlighting that design choice. Comment at: src/UnwindRegistersRestore.S:647 +#if __mips_fpr == 32 + l.d $f0, (4 * 36 + 8 * 0)($4) + l.d $f2, (4 * 36 + 8 * 2)($4) Use ldc1 instead of l.d . l.d is an alias of ldc1. Comment at: src/UnwindRegistersRestore.S:755 +#ifdef __mips_hard_float + l.d $f0, (8 * 35)($4) + l.d $f1, (8 * 36)($4) ldc1 here too. Comment at: src/UnwindRegistersSave.S:119 -#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float) +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 Comment at: src/UnwindRegistersSave.S:172 +#if __mips_fpr == 32 + s.d $f0, (4 * 36 + 8 * 0)($4) + s.d $f2, (4 * 36 + 8 * 2)($4) Use sdc1 rather than s.d. Comment at: src/UnwindRegistersSave.S:228 -#elif defined(__mips__) && (defined(_ABI64) || defined(_ABIN32)) && \ -defined(__mips_soft_float) +#elif defined(__mips__) && (defined(_ABI64) || defined(_ABIN32)) defined(__mips64) rather than the checking if the ABI names are defined. Comment at: src/UnwindRegistersSave.S:280 +#ifdef __mips_hard_float + s.d $f0, (8 * 35)($4) + s.d $f1, (8 * 36)($4) sdc1 rather s.d Comment at: src/libunwind.cpp:64 # define REGISTER_KIND Registers_or1k -#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float) +#elif defined(__mips__) && defined(_ABIO32) # define REGISTER_KIND Registers_mips_o32 Check for that _MIPS_SIM == _ABIO32 as well. Comment at: src/libunwind.cpp:66 # define REGISTER_KIND Registers_mips_o32 -#elif defined(__mips__) && (defined(_ABIN32) || defined(_ABI64)) && \ -defined(__mips_soft_float) +#elif defined(__mips__) && (defined(_ABIN32) || defined(_ABI64)) # define REGISTER_KIND Registers_mips_newabi Check for __mips64 rather than defined(_ABIXXX). https://reviews.llvm.org/D41968 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
bsdjhb added inline comments. Comment at: src/Registers.hpp:2659 + uint32_t _padding; + double _floats[32]; +#endif I chose to always use double here to avoid having different context sizes for the 32-bit vs 64-bit FPR cases. https://reviews.llvm.org/D41968 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41968: [libunwind][MIPS] Support MIPS floating-point registers for hard-float ABIs.
bsdjhb created this revision. bsdjhb added a reviewer: sdardis. Herald added a subscriber: arichardson. For newabi this is fairly simple as we just save/restore the 32 floating-point registers as doubles. For O32 MIPS provides a variety of floating-point ABIs. For O32 MIPS with 64-bit floating-point registers, save/restore the 32 floating-point registers as doubles. For O32 MIPS with 32-bit floating-point registers, save/restore the 16 even registers as doubles. This probably isn't correct but does match the existing libunwind ABI that expects to save/restore floating point registers as doubles. For O32 with 32-bit FPRs the sticky point is trying to distinguish if a user of unw_get_fpreg() or unw_set_fpreg() is trying to operate on a float or a double. It's not clear to me what the right thing here is. If the goal is just to save/restore individual registers then perhaps the FPRs should always be stored as floats that get converted to doubles when returned from unw_get_fpreg() and vice versa? https://reviews.llvm.org/D41968 Files: include/__libunwind_config.h include/libunwind.h src/Registers.hpp src/UnwindRegistersRestore.S src/UnwindRegistersSave.S src/libunwind.cpp Index: src/libunwind.cpp === --- src/libunwind.cpp +++ src/libunwind.cpp @@ -61,10 +61,9 @@ # define REGISTER_KIND Registers_arm #elif defined(__or1k__) # define REGISTER_KIND Registers_or1k -#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float) +#elif defined(__mips__) && defined(_ABIO32) # define REGISTER_KIND Registers_mips_o32 -#elif defined(__mips__) && (defined(_ABIN32) || defined(_ABI64)) &&\ -defined(__mips_soft_float) +#elif defined(__mips__) && (defined(_ABIN32) || defined(_ABI64)) # define REGISTER_KIND Registers_mips_newabi #elif defined(__mips__) # warning The MIPS architecture is not supported with this ABI and environment! Index: src/UnwindRegistersSave.S === --- src/UnwindRegistersSave.S +++ src/UnwindRegistersSave.S @@ -116,7 +116,7 @@ xorl %eax, %eax# return UNW_ESUCCESS ret -#elif defined(__mips__) && defined(_ABIO32) && defined(__mips_soft_float) +#elif defined(__mips__) && defined(_ABIO32) # # extern int unw_getcontext(unw_context_t* thread_state) @@ -167,13 +167,65 @@ sw$8, (4 * 33)($4) mflo $8 sw$8, (4 * 34)($4) +#ifdef __mips_hard_float +#if __mips_fpr == 32 + s.d $f0, (4 * 36 + 8 * 0)($4) + s.d $f2, (4 * 36 + 8 * 2)($4) + s.d $f4, (4 * 36 + 8 * 4)($4) + s.d $f6, (4 * 36 + 8 * 6)($4) + s.d $f8, (4 * 36 + 8 * 8)($4) + s.d $f10, (4 * 36 + 8 * 10)($4) + s.d $f12, (4 * 36 + 8 * 12)($4) + s.d $f14, (4 * 36 + 8 * 14)($4) + s.d $f16, (4 * 36 + 8 * 16)($4) + s.d $f18, (4 * 36 + 8 * 18)($4) + s.d $f20, (4 * 36 + 8 * 20)($4) + s.d $f22, (4 * 36 + 8 * 22)($4) + s.d $f24, (4 * 36 + 8 * 24)($4) + s.d $f26, (4 * 36 + 8 * 26)($4) + s.d $f28, (4 * 36 + 8 * 28)($4) + s.d $f30, (4 * 36 + 8 * 30)($4) +#else + s.d $f0, (4 * 36 + 8 * 0)($4) + s.d $f1, (4 * 36 + 8 * 1)($4) + s.d $f2, (4 * 36 + 8 * 2)($4) + s.d $f3, (4 * 36 + 8 * 3)($4) + s.d $f4, (4 * 36 + 8 * 4)($4) + s.d $f5, (4 * 36 + 8 * 5)($4) + s.d $f6, (4 * 36 + 8 * 6)($4) + s.d $f7, (4 * 36 + 8 * 7)($4) + s.d $f8, (4 * 36 + 8 * 8)($4) + s.d $f9, (4 * 36 + 8 * 9)($4) + s.d $f10, (4 * 36 + 8 * 10)($4) + s.d $f11, (4 * 36 + 8 * 11)($4) + s.d $f12, (4 * 36 + 8 * 12)($4) + s.d $f13, (4 * 36 + 8 * 13)($4) + s.d $f14, (4 * 36 + 8 * 14)($4) + s.d $f15, (4 * 36 + 8 * 15)($4) + s.d $f16, (4 * 36 + 8 * 16)($4) + s.d $f17, (4 * 36 + 8 * 17)($4) + s.d $f18, (4 * 36 + 8 * 18)($4) + s.d $f19, (4 * 36 + 8 * 19)($4) + s.d $f20, (4 * 36 + 8 * 20)($4) + s.d $f21, (4 * 36 + 8 * 21)($4) + s.d $f22, (4 * 36 + 8 * 22)($4) + s.d $f23, (4 * 36 + 8 * 23)($4) + s.d $f24, (4 * 36 + 8 * 24)($4) + s.d $f25, (4 * 36 + 8 * 25)($4) + s.d $f26, (4 * 36 + 8 * 26)($4) + s.d $f27, (4 * 36 + 8 * 27)($4) + s.d $f28, (4 * 36 + 8 * 28)($4) + s.d $f29, (4 * 36 + 8 * 29)($4) + s.d $f30, (4 * 36 + 8 * 30)($4) + s.d $f31, (4 * 36 + 8 * 31)($4) +#endif +#endif jr $31 # return UNW_ESUCCESS or$2, $0, $0 .set pop -#elif defined(__mips__) && (defined(_ABI64) || defined(_ABIN32)) &&\ -defined(__mips_soft_float) +#elif defined(__mips__) && (defined(_ABI64) || defined(_ABIN32)) # # extern int unw_getcontext(unw_context_t* thread_state) @@ -224,6 +276,40 @@ sd$8, (8 * 33)($4) mflo $8 sd$8, (8 * 34)($4) +#ifdef __mips_hard_float + s.d $f0, (8 * 35)($4) + s.d $f1, (8 * 36)($4) + s.d $f2, (8 * 37)($4) + s.d $f3, (8 * 38)($4) + s.d $f4, (8 * 39)($4) + s.d $f5, (8 * 40)($4) + s.d $f6, (8 * 41)($4) + s.d $f7, (8 * 42)($4) + s.d $f8, (8 * 43)($4) + s.d $f9, (8 * 44)($4) + s.d $f10, (8