diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index aee16705676d02a4fc19ed178da3edf66b5d823d..a4f96a97991ea2d94473631730102d4cd08f4e88 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -278,7 +278,6 @@ def err_target_unsupported_abi_for_triple : Error< def err_unsupported_abi_for_opt : Error<"'%0' can only be used with the '%1' ABI">; def err_mips_fp64_req : Error< "'%0' can only be used if the target supports the mfhc1 and mthc1 instructions">; -def err_unsupported_fpxx_ohos : Error<"fpxx is currently unsupported on OHOS">; def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">; def err_target_unsupported_fpmath : Error< "the '%0' unit is not supported with this instruction set">; diff --git a/clang/lib/Basic/Targets/Mips.cpp b/clang/lib/Basic/Targets/Mips.cpp index 37110d8da9b682485ab7ec3ff89f81b215ade3a5..3a32fd492c6bb4ef32a1b11a660a8f77acf4eff0 100644 --- a/clang/lib/Basic/Targets/Mips.cpp +++ b/clang/lib/Basic/Targets/Mips.cpp @@ -269,12 +269,6 @@ bool MipsTargetInfo::validateTarget(DiagnosticsEngine &Diags) const { return false; } - // TODO: remove this if entry when fpxx is supported on OHOS - if (getTriple().isOpenHOS() && FPMode == FPXX) { - Diags.Report(diag::err_unsupported_fpxx_ohos); - return false; - } - // -fpxx is valid only for the o32 ABI if (FPMode == FPXX && (ABI == "n32" || ABI == "n64")) { Diags.Report(diag::err_unsupported_abi_for_opt) << "-mfpxx" << "o32"; diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 82cdaf7047161bd18f2cc918ded62257a260070c..b475c03889a177c75738dd3a90d5b7bb9973c95f 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -86,10 +86,7 @@ public: } bool isFP64Default() const { - // TODO: remove getTriple().isOpenHOS() case - // when fpxx is supported on OHOS - return getTriple().isOpenHOS() || CPU == "mips32r6" || - ABI == "n32" || ABI == "n64" || ABI == "64"; + return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64"; } bool isNan2008() const override { return IsNan2008; } diff --git a/clang/lib/Driver/ToolChains/Arch/Mips.cpp b/clang/lib/Driver/ToolChains/Arch/Mips.cpp index 889a983f2257cd06f19847e3b01acd3035e1fab6..5a509dbb2bd319498224d40b632f754089531e09 100644 --- a/clang/lib/Driver/ToolChains/Arch/Mips.cpp +++ b/clang/lib/Driver/ToolChains/Arch/Mips.cpp @@ -362,9 +362,6 @@ void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, } else if (mips::isFP64ADefault(Triple, CPUName)) { Features.push_back("+fp64"); Features.push_back("+nooddspreg"); - } else if (Triple.isOpenHOS()) { - // TODO: remove this else if entry when fpxx is supported on OHOS - Features.push_back("+fp64"); } AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, @@ -469,10 +466,6 @@ bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) { bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, StringRef ABIName, mips::FloatABI FloatABI) { - // TODO: remove this if entry when fpxx is supported on OHOS - if (Triple.isOpenHOS()) - return false; - if (Triple.getVendor() != llvm::Triple::ImaginationTechnologies && Triple.getVendor() != llvm::Triple::MipsTechnologies && !Triple.isAndroid()) diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h index 5bae8d02f7999ff57476c62ed96c9dd898486adf..1f46590827e9d17e11bfff16f310df17d3ef53cb 100644 --- a/libunwind/include/libunwind.h +++ b/libunwind/include/libunwind.h @@ -84,7 +84,19 @@ typedef uintptr_t unw_word_t; #if defined(__arm__) && !defined(__ARM_DWARF_EH__) typedef uint64_t unw_fpreg_t; #else -typedef double unw_fpreg_t; + #if defined(_LIBUNWIND_TARGET_MIPS_O32) && defined(__mips_hard_float) + #if __mips_fpr == 0 + typedef uint64_t unw_fpreg_t; + #elif __mips_fpr == 32 + typedef float unw_fpreg_t; + #elif __mips_fpr == 64 + typedef double unw_fpreg_t; + #else + #error "Unknown __mips_fpr value" + #endif + #else + typedef double unw_fpreg_t; + #endif #endif struct unw_proc_info_t { diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp index 171318ff6370c658f548093deca3a94727b105d3..578f383f1d3b1f89de6e07a496fecd131084f372 100644 --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -169,9 +169,13 @@ public: memcpy(&val, (void *)addr, sizeof(val)); return val; } - double getDouble(pint_t addr) { - double val; + unw_fpreg_t getDouble(pint_t addr) { + unw_fpreg_t val; +#if defined(_LIBUNWIND_TARGET_MIPS_O32) + memcpy(&val, (void *)addr, Registers_mips_o32::getFpuRegsSize()); +#else memcpy(&val, (void *)addr, sizeof(val)); +#endif return val; } v128 getVector(pint_t addr) { diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index c39cabe1f7830de334332e24ffe10bc33a258ef9..9a88577eb06b735f56c84774ccd9814bac1cce8b 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -56,7 +56,7 @@ private: pint_t initialStackValue); static pint_t getSavedRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); - static double getSavedFloatRegister(A &addressSpace, const R ®isters, + static unw_fpreg_t getSavedFloatRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); @@ -104,7 +104,7 @@ typename A::pint_t DwarfInstructions::getSavedRegister( } template -double DwarfInstructions::getSavedFloatRegister( +unw_fpreg_t DwarfInstructions::getSavedFloatRegister( A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg) { switch (savedReg.location) { diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp index efeaf435591e410bae3f67fbbed4b319f5c2f153..d2a0fa69a0bc3df81cef4e32ee5f9fabfdb78ed2 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -53,8 +53,8 @@ public: uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int) const { return false; } - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int) const { return false; } v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -230,11 +230,11 @@ inline const char *Registers_x86::getRegisterName(int regNum) { } } -inline double Registers_x86::getFloatRegister(int) const { +inline unw_fpreg_t Registers_x86::getFloatRegister(int) const { _LIBUNWIND_ABORT("no x86 float registers"); } -inline void Registers_x86::setFloatRegister(int, double) { +inline void Registers_x86::setFloatRegister(int, unw_fpreg_t) { _LIBUNWIND_ABORT("no x86 float registers"); } @@ -262,8 +262,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int) const { return false; } - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -521,11 +521,11 @@ inline const char *Registers_x86_64::getRegisterName(int regNum) { } } -inline double Registers_x86_64::getFloatRegister(int) const { +inline unw_fpreg_t Registers_x86_64::getFloatRegister(int) const { _LIBUNWIND_ABORT("no x86_64 float registers"); } -inline void Registers_x86_64::setFloatRegister(int, double) { +inline void Registers_x86_64::setFloatRegister(int, unw_fpreg_t) { _LIBUNWIND_ABORT("no x86_64 float registers"); } @@ -576,8 +576,8 @@ public: 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); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -958,12 +958,12 @@ inline bool Registers_ppc::validFloatRegister(int regNum) const { return true; } -inline double Registers_ppc::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_ppc::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); return _floatRegisters.__fpregs[regNum - UNW_PPC_F0]; } -inline void Registers_ppc::setFloatRegister(int regNum, double value) { +inline void Registers_ppc::setFloatRegister(int regNum, unw_fpreg_t value) { assert(validFloatRegister(regNum)); _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value; } @@ -1142,8 +1142,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -1504,12 +1504,12 @@ inline bool Registers_ppc64::validFloatRegister(int regNum) const { return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31; } -inline double Registers_ppc64::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_ppc64::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f; } -inline void Registers_ppc64::setFloatRegister(int regNum, double value) { +inline void Registers_ppc64::setFloatRegister(int regNum, unw_fpreg_t value) { assert(validFloatRegister(regNum)); _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value; } @@ -1787,8 +1787,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -2026,12 +2026,12 @@ inline bool Registers_arm64::validFloatRegister(int regNum) const { return true; } -inline double Registers_arm64::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_arm64::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); return _vectorHalfRegisters[regNum - UNW_ARM64_D0]; } -inline void Registers_arm64::setFloatRegister(int regNum, double value) { +inline void Registers_arm64::setFloatRegister(int regNum, unw_fpreg_t value) { assert(validFloatRegister(regNum)); _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value; } @@ -2545,8 +2545,8 @@ public: 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); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -2634,12 +2634,12 @@ inline bool Registers_or1k::validFloatRegister(int /* regNum */) const { return false; } -inline double Registers_or1k::getFloatRegister(int /* regNum */) const { +inline unw_fpreg_t Registers_or1k::getFloatRegister(int /* regNum */) const { _LIBUNWIND_ABORT("or1k float support not implemented"); } inline void Registers_or1k::setFloatRegister(int /* regNum */, - double /* value */) { + unw_fpreg_t /* value */) { _LIBUNWIND_ABORT("or1k float support not implemented"); } @@ -2731,19 +2731,32 @@ inline const char *Registers_or1k::getRegisterName(int regNum) { #endif // _LIBUNWIND_TARGET_OR1K #if defined(_LIBUNWIND_TARGET_MIPS_O32) + +// TODO: check the following for FPU with 32-bit registers: +// - fpxx code works properly +// - fp32 code remains working properly + /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS /// process. class _LIBUNWIND_HIDDEN Registers_mips_o32 { public: Registers_mips_o32(); Registers_mips_o32(const void *registers); +#ifdef __mips_hard_float + Registers_mips_o32(const Registers_mips_o32&) = default; + Registers_mips_o32& operator=(const Registers_mips_o32& src) { + memcpy(&_registers, &src._registers, sizeof(_registers)); + memcpy(&_floatsBuffer, &src._floatsBuffer, sizeof(_floatsBuffer)); + return *this; + } +#endif 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); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -2751,6 +2764,9 @@ public: void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } static int getArch() { return REGISTERS_MIPS_O32; } +#ifdef __mips_hard_float + static uint32_t getFpuRegsSize(); +#endif uint32_t getSP() const { return _registers.__r[29]; } void setSP(uint32_t value) { _registers.__r[29] = value; } @@ -2771,19 +2787,51 @@ private: /// 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]; + const uint32_t _fpuRegsSize; + char _floatsBuffer[32 * 8] = { 0 }; + + char *getFpuRegLocation(int regNum); + const char *getFpuRegLocation(int regNum) const; #endif }; -inline Registers_mips_o32::Registers_mips_o32(const void *registers) { +inline Registers_mips_o32::Registers_mips_o32(const void *registers) +#ifdef __mips_hard_float + : _fpuRegsSize(getFpuRegsSize()) +#endif +{ static_assert((check_fit::does_fit), "mips_o32 registers do not fit into unw_context_t"); memcpy(&_registers, static_cast(registers), sizeof(_registers)); } -inline Registers_mips_o32::Registers_mips_o32() { +#ifdef __mips_hard_float +inline uint32_t Registers_mips_o32::getFpuRegsSize() { +#if __mips_fpr == 32 + return 4; +#elif __mips_fpr == 64 + return 8; +#elif __mips_fpr == 0 + unsigned fpuID; + __asm__ __volatile__( + " .set push \n" + " cfc1 %0,$0 \n" + " .set pop \n" + : "=r" (fpuID)); + constexpr unsigned MIPS_FPIR_F64 = (1 << 22); + return (fpuID & MIPS_FPIR_F64) ? 8 : 4; +#else +#error "Unknown __mips_fpr value" +#endif +} +#endif + +inline Registers_mips_o32::Registers_mips_o32() +#ifdef __mips_hard_float + : _fpuRegsSize(getFpuRegsSize()) +#endif +{ memset(&_registers, 0, sizeof(_registers)); } @@ -2801,10 +2849,6 @@ inline bool Registers_mips_o32::validRegister(int regNum) const { return true; if (regNum == UNW_MIPS_LO) return true; -#endif -#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; @@ -2813,17 +2857,6 @@ inline bool Registers_mips_o32::validRegister(int regNum) const { 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: @@ -2843,19 +2876,6 @@ 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: _registers.__pc = value; @@ -2873,20 +2893,51 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { _LIBUNWIND_ABORT("unsupported mips_o32 register"); } +#ifdef __mips_hard_float +inline const char *Registers_mips_o32::getFpuRegLocation(int regNum) const { + const char *regLocation = _floatsBuffer; + int fpuRegNum = regNum - UNW_MIPS_F0; + if (_fpuRegsSize == 4 && fpuRegNum % 2 == 1) + regLocation += (fpuRegNum - 1) * 8 + 4; + else + regLocation += fpuRegNum * 8; + return regLocation; +} + +inline char *Registers_mips_o32::getFpuRegLocation(int regNum) { + char *regLocation = _floatsBuffer; + int fpuRegNum = regNum - UNW_MIPS_F0; + if (_fpuRegsSize == 4 && fpuRegNum % 2 == 1) + regLocation += (fpuRegNum - 1) * 8 + 4; + else + regLocation += fpuRegNum * 8; + return regLocation; +} +#endif + 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; +#if defined(__mips_hard_float) + return (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31); #else (void)regNum; -#endif return false; +#endif } -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]; +inline unw_fpreg_t Registers_mips_o32::getFloatRegister(int regNum) const { +#if defined(__mips_hard_float) +assert(validFloatRegister(regNum)); +#if __mips_fpr == 0 + const char *regLocation = getFpuRegLocation(regNum); + unw_fpreg_t regValue = 0; + memcpy(reinterpret_cast(®Value), regLocation, _fpuRegsSize); + return regValue; +#elif __mips_fpr == 32 || __mips_fpr == 64 + const char *regLocation = getFpuRegLocation(regNum); + return *reinterpret_cast(regLocation); +#else +#error "Unknown __mips_fpr value" +#endif #else (void)regNum; _LIBUNWIND_ABORT("mips_o32 float support not implemented"); @@ -2894,10 +2945,18 @@ inline double Registers_mips_o32::getFloatRegister(int regNum) const { } inline void Registers_mips_o32::setFloatRegister(int regNum, - double value) { -#if defined(__mips_hard_float) && __mips_fpr == 64 + unw_fpreg_t value) { +#if defined(__mips_hard_float) assert(validFloatRegister(regNum)); - _floats[regNum - UNW_MIPS_F0] = value; +#if __mips_fpr == 0 + char *regLocation = getFpuRegLocation(regNum); + memcpy(regLocation, reinterpret_cast(&value), _fpuRegsSize); +#elif __mips_fpr == 32 || __mips_fpr == 64 + char *regLocation = getFpuRegLocation(regNum); + *reinterpret_cast(regLocation) = value; +#else +#error "Unknown __mips_fpr value" +#endif #else (void)regNum; (void)value; @@ -3069,8 +3128,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3178,7 +3237,7 @@ inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { return false; } -inline double Registers_mips_newabi::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_mips_newabi::getFloatRegister(int regNum) const { #ifdef __mips_hard_float assert(validFloatRegister(regNum)); return _floats[regNum - UNW_MIPS_F0]; @@ -3189,7 +3248,7 @@ inline double Registers_mips_newabi::getFloatRegister(int regNum) const { } inline void Registers_mips_newabi::setFloatRegister(int regNum, - double value) { + unw_fpreg_t value) { #ifdef __mips_hard_float assert(validFloatRegister(regNum)); _floats[regNum - UNW_MIPS_F0] = value; @@ -3364,8 +3423,8 @@ public: 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); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3443,11 +3502,11 @@ inline void Registers_sparc::setRegister(int regNum, uint32_t value) { inline bool Registers_sparc::validFloatRegister(int) const { return false; } -inline double Registers_sparc::getFloatRegister(int) const { +inline unw_fpreg_t Registers_sparc::getFloatRegister(int) const { _LIBUNWIND_ABORT("no Sparc float registers"); } -inline void Registers_sparc::setFloatRegister(int, double) { +inline void Registers_sparc::setFloatRegister(int, unw_fpreg_t) { _LIBUNWIND_ABORT("no Sparc float registers"); } @@ -3548,8 +3607,8 @@ public: 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); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3622,12 +3681,12 @@ inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const { return false; } -inline double Registers_hexagon::getFloatRegister(int /* regNum */) const { +inline unw_fpreg_t Registers_hexagon::getFloatRegister(int /* regNum */) const { _LIBUNWIND_ABORT("hexagon float support not implemented"); } inline void Registers_hexagon::setFloatRegister(int /* regNum */, - double /* value */) { + unw_fpreg_t /* value */) { _LIBUNWIND_ABORT("hexagon float support not implemented"); } @@ -3729,8 +3788,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3951,7 +4010,7 @@ inline bool Registers_riscv::validFloatRegister(int regNum) const { return true; } -inline double Registers_riscv::getFloatRegister(int regNum) const { +inline unw_fpreg_t Registers_riscv::getFloatRegister(int regNum) const { #if defined(__riscv_flen) && __riscv_flen == 64 assert(validFloatRegister(regNum)); return _floats[regNum - UNW_RISCV_F0]; @@ -3961,7 +4020,7 @@ inline double Registers_riscv::getFloatRegister(int regNum) const { #endif } -inline void Registers_riscv::setFloatRegister(int regNum, double value) { +inline void Registers_riscv::setFloatRegister(int regNum, unw_fpreg_t value) { #if defined(__riscv_flen) && __riscv_flen == 64 assert(validFloatRegister(regNum)); _floats[regNum - UNW_RISCV_F0] = value; @@ -3996,8 +4055,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - double getFloatRegister(int num) const; - void setFloatRegister(int num, double value); + unw_fpreg_t getFloatRegister(int num) const; + void setFloatRegister(int num, unw_fpreg_t value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -4100,12 +4159,12 @@ inline bool Registers_ve::validFloatRegister(int /* regNum */) const { return false; } -inline double Registers_ve::getFloatRegister(int /* regNum */) const { +inline unw_fpreg_t Registers_ve::getFloatRegister(int /* regNum */) const { _LIBUNWIND_ABORT("VE doesn't have float registers"); } inline void Registers_ve::setFloatRegister(int /* regNum */, - double /* value */) { + unw_fpreg_t /* value */) { _LIBUNWIND_ABORT("VE doesn't have float registers"); } diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index 289afe98b0b2ac05fb8cf987324b6d829a273e7d..43902767ab308f611b235ebf4d499d96685f9a39 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -865,7 +865,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) .set noreorder .set nomacro #ifdef __mips_hard_float -#if __mips_fpr != 64 +#if __mips_fpr == 32 ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) ldc1 $f4, (4 * 36 + 8 * 4)($4) @@ -882,7 +882,46 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) ldc1 $f26, (4 * 36 + 8 * 26)($4) ldc1 $f28, (4 * 36 + 8 * 28)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) -#else +#elif __mips_fpr == 64 + ldc1 $f0, (4 * 36 + 8 * 0)($4) + ldc1 $f1, (4 * 36 + 8 * 1)($4) + ldc1 $f2, (4 * 36 + 8 * 2)($4) + ldc1 $f3, (4 * 36 + 8 * 3)($4) + ldc1 $f4, (4 * 36 + 8 * 4)($4) + ldc1 $f5, (4 * 36 + 8 * 5)($4) + ldc1 $f6, (4 * 36 + 8 * 6)($4) + ldc1 $f7, (4 * 36 + 8 * 7)($4) + ldc1 $f8, (4 * 36 + 8 * 8)($4) + ldc1 $f9, (4 * 36 + 8 * 9)($4) + ldc1 $f10, (4 * 36 + 8 * 10)($4) + ldc1 $f11, (4 * 36 + 8 * 11)($4) + ldc1 $f12, (4 * 36 + 8 * 12)($4) + ldc1 $f13, (4 * 36 + 8 * 13)($4) + ldc1 $f14, (4 * 36 + 8 * 14)($4) + ldc1 $f15, (4 * 36 + 8 * 15)($4) + ldc1 $f16, (4 * 36 + 8 * 16)($4) + ldc1 $f17, (4 * 36 + 8 * 17)($4) + ldc1 $f18, (4 * 36 + 8 * 18)($4) + ldc1 $f19, (4 * 36 + 8 * 19)($4) + ldc1 $f20, (4 * 36 + 8 * 20)($4) + ldc1 $f21, (4 * 36 + 8 * 21)($4) + ldc1 $f22, (4 * 36 + 8 * 22)($4) + ldc1 $f23, (4 * 36 + 8 * 23)($4) + ldc1 $f24, (4 * 36 + 8 * 24)($4) + ldc1 $f25, (4 * 36 + 8 * 25)($4) + ldc1 $f26, (4 * 36 + 8 * 26)($4) + ldc1 $f27, (4 * 36 + 8 * 27)($4) + ldc1 $f28, (4 * 36 + 8 * 28)($4) + ldc1 $f29, (4 * 36 + 8 * 29)($4) + ldc1 $f30, (4 * 36 + 8 * 30)($4) + ldc1 $f31, (4 * 36 + 8 * 31)($4) +#elif __mips_fpr == 0 + cfc1 $t0, $0 + li $t1, 1 + sll $t1, $t1, 22 + and $t0, $t0, $t1 + beq $t0, $0, _fp32 +_fp64: ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f1, (4 * 36 + 8 * 1)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) @@ -915,8 +954,29 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) ldc1 $f29, (4 * 36 + 8 * 29)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) ldc1 $f31, (4 * 36 + 8 * 31)($4) + j _after_float +_fp32: + ldc1 $f0, (4 * 36 + 8 * 0)($4) + ldc1 $f2, (4 * 36 + 8 * 2)($4) + ldc1 $f4, (4 * 36 + 8 * 4)($4) + ldc1 $f6, (4 * 36 + 8 * 6)($4) + ldc1 $f8, (4 * 36 + 8 * 8)($4) + ldc1 $f10, (4 * 36 + 8 * 10)($4) + ldc1 $f12, (4 * 36 + 8 * 12)($4) + ldc1 $f14, (4 * 36 + 8 * 14)($4) + ldc1 $f16, (4 * 36 + 8 * 16)($4) + ldc1 $f18, (4 * 36 + 8 * 18)($4) + ldc1 $f20, (4 * 36 + 8 * 20)($4) + ldc1 $f22, (4 * 36 + 8 * 22)($4) + ldc1 $f24, (4 * 36 + 8 * 24)($4) + ldc1 $f26, (4 * 36 + 8 * 26)($4) + ldc1 $f28, (4 * 36 + 8 * 28)($4) + ldc1 $f30, (4 * 36 + 8 * 30)($4) +#else +#error "Unknown __mips_fpr value" #endif #endif +_after_float: // restore hi and lo lw $8, (4 * 33)($4) mthi $8 diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S index 94fc8365455df08c17477dc48295141f920e42d7..bfaf3530166aba4e8bc9914dbf5b1e0597abce1d 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -128,46 +128,8 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) .set noat .set noreorder .set nomacro - sw $1, (4 * 1)($4) - sw $2, (4 * 2)($4) - sw $3, (4 * 3)($4) - sw $4, (4 * 4)($4) - sw $5, (4 * 5)($4) - sw $6, (4 * 6)($4) - sw $7, (4 * 7)($4) - sw $8, (4 * 8)($4) - sw $9, (4 * 9)($4) - sw $10, (4 * 10)($4) - sw $11, (4 * 11)($4) - sw $12, (4 * 12)($4) - sw $13, (4 * 13)($4) - sw $14, (4 * 14)($4) - sw $15, (4 * 15)($4) - sw $16, (4 * 16)($4) - sw $17, (4 * 17)($4) - sw $18, (4 * 18)($4) - sw $19, (4 * 19)($4) - sw $20, (4 * 20)($4) - sw $21, (4 * 21)($4) - sw $22, (4 * 22)($4) - sw $23, (4 * 23)($4) - sw $24, (4 * 24)($4) - sw $25, (4 * 25)($4) - sw $26, (4 * 26)($4) - sw $27, (4 * 27)($4) - sw $28, (4 * 28)($4) - sw $29, (4 * 29)($4) - sw $30, (4 * 30)($4) - sw $31, (4 * 31)($4) - # Store return address to pc - sw $31, (4 * 32)($4) - # hi and lo - mfhi $8 - sw $8, (4 * 33)($4) - mflo $8 - sw $8, (4 * 34)($4) #ifdef __mips_hard_float -#if __mips_fpr != 64 +#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) @@ -184,7 +146,46 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) sdc1 $f26, (4 * 36 + 8 * 26)($4) sdc1 $f28, (4 * 36 + 8 * 28)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) -#else +#elif __mips_fpr == 64 + 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) +#elif __mips_fpr == 0 + cfc1 $t0, $0 + li $t1, 1 + sll $t1, $t1, 22 + and $t0, $t0, $t1 + beq $t0, $0, _fp32 +_fp64: sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f1, (4 * 36 + 8 * 1)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) @@ -217,8 +218,67 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) sdc1 $f29, (4 * 36 + 8 * 29)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) sdc1 $f31, (4 * 36 + 8 * 31)($4) + j _after_float +_fp32: + 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 +#error "Unknown __mips_fpr value" #endif #endif +_after_float: + sw $1, (4 * 1)($4) + sw $2, (4 * 2)($4) + sw $3, (4 * 3)($4) + sw $4, (4 * 4)($4) + sw $5, (4 * 5)($4) + sw $6, (4 * 6)($4) + sw $7, (4 * 7)($4) + sw $8, (4 * 8)($4) + sw $9, (4 * 9)($4) + sw $10, (4 * 10)($4) + sw $11, (4 * 11)($4) + sw $12, (4 * 12)($4) + sw $13, (4 * 13)($4) + sw $14, (4 * 14)($4) + sw $15, (4 * 15)($4) + sw $16, (4 * 16)($4) + sw $17, (4 * 17)($4) + sw $18, (4 * 18)($4) + sw $19, (4 * 19)($4) + sw $20, (4 * 20)($4) + sw $21, (4 * 21)($4) + sw $22, (4 * 22)($4) + sw $23, (4 * 23)($4) + sw $24, (4 * 24)($4) + sw $25, (4 * 25)($4) + sw $26, (4 * 26)($4) + sw $27, (4 * 27)($4) + sw $28, (4 * 28)($4) + sw $29, (4 * 29)($4) + sw $30, (4 * 30)($4) + sw $31, (4 * 31)($4) + # Store return address to pc + sw $31, (4 * 32)($4) + # hi and lo + mfhi $8 + sw $8, (4 * 33)($4) + mflo $8 + sw $8, (4 * 34)($4) jr $31 # return UNW_ESUCCESS or $2, $0, $0 diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp index c21461b1f4802ef46902b2e46614e7a1caf8bd8a..c3861f3abed0fa2526b6f48060417e5e2e6d14a3 100644 --- a/libunwind/src/libunwind.cpp +++ b/libunwind/src/libunwind.cpp @@ -144,7 +144,7 @@ _LIBUNWIND_WEAK_ALIAS(__unw_get_fpreg, unw_get_fpreg) /// Set value of specified float register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, unw_fpreg_t value) { -#if defined(_LIBUNWIND_ARM_EHABI) +#if defined(_LIBUNWIND_ARM_EHABI) || (defined(__mips__) && __mips_fpr == 0) _LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)", static_cast(cursor), regNum, value); #else