diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h index c36a94e8754dd0c838578498e1146be523d89943..ab8e3994d4e1ddec8dc87e138a4cf5550b06b47b 100644 --- a/libunwind/include/libunwind.h +++ b/libunwind/include/libunwind.h @@ -83,20 +83,20 @@ typedef int unw_regnum_t; typedef uintptr_t unw_word_t; #if defined(__arm__) && !defined(__ARM_DWARF_EH__) typedef uint64_t unw_fpreg_t; -#else -# if defined(_LIBUNWIND_TARGET_MIPS_O32) && defined(__mips_hard_float) -# if __mips_fpr == 0 +// OHOS_LOCAL begin +#elif defined(_LIBUNWIND_TARGET_MIPS_O32) && defined(__mips_hard_float) +# if __mips_fpr == 0 typedef uint64_t unw_fpreg_t; -# elif __mips_fpr == 32 +# elif __mips_fpr == 32 typedef float unw_fpreg_t; -# elif __mips_fpr == 64 +# elif __mips_fpr == 64 typedef double unw_fpreg_t; -# else -# error "Unknown __mips_fpr value" -# endif # else -typedef double unw_fpreg_t; +# error "Unknown __mips_fpr value" # endif +// OHOS_LOCAL end +#else +typedef double unw_fpreg_t; #endif struct unw_proc_info_t { diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp index 578f383f1d3b1f89de6e07a496fecd131084f372..33cf75c77a541fdb89bd9fd779c50bfa8a0bed4d 100644 --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -169,6 +169,7 @@ public: memcpy(&val, (void *)addr, sizeof(val)); return val; } + // OHOS_LOCAL begin unw_fpreg_t getDouble(pint_t addr) { unw_fpreg_t val; #if defined(_LIBUNWIND_TARGET_MIPS_O32) @@ -178,6 +179,7 @@ public: #endif return val; } + // OHOS_LOCAL end v128 getVector(pint_t addr) { v128 val; memcpy(&val, (void *)addr, sizeof(val)); diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index 9a88577eb06b735f56c84774ccd9814bac1cce8b..590c013fb4b82383f2b39e085a09910e991add84 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -56,8 +56,10 @@ private: pint_t initialStackValue); static pint_t getSavedRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); + // OHOS_LOCAL begin static unw_fpreg_t getSavedFloatRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); + // OHOS_LOCAL end static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); @@ -104,7 +106,7 @@ typename A::pint_t DwarfInstructions::getSavedRegister( } template -unw_fpreg_t DwarfInstructions::getSavedFloatRegister( +unw_fpreg_t DwarfInstructions::getSavedFloatRegister( // OHOS_LOCAL 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 d2e2ac86cb0de838737063615d96658deb3e4bba..c6434e91ae505775420879cd2384534e4584d7c3 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; } - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL 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 unw_fpreg_t Registers_x86::getFloatRegister(int) const { +inline unw_fpreg_t Registers_x86::getFloatRegister(int) const { // OHOS_LOCAL _LIBUNWIND_ABORT("no x86 float registers"); } -inline void Registers_x86::setFloatRegister(int, unw_fpreg_t) { +inline void Registers_x86::setFloatRegister(int, unw_fpreg_t) { // OHOS_LOCAL _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; } - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL 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 unw_fpreg_t Registers_x86_64::getFloatRegister(int) const { +inline unw_fpreg_t Registers_x86_64::getFloatRegister(int) const { // OHOS_LOCAL _LIBUNWIND_ABORT("no x86_64 float registers"); } -inline void Registers_x86_64::setFloatRegister(int, unw_fpreg_t) { +inline void Registers_x86_64::setFloatRegister(int, unw_fpreg_t) { // OHOS_LOCAL _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; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -958,12 +958,16 @@ inline bool Registers_ppc::validFloatRegister(int regNum) const { return true; } +// OHOS_LOCAL begin inline unw_fpreg_t Registers_ppc::getFloatRegister(int regNum) const { +// OHOS_LOCAL end assert(validFloatRegister(regNum)); return _floatRegisters.__fpregs[regNum - UNW_PPC_F0]; } +// OHOS_LOCAL begin inline void Registers_ppc::setFloatRegister(int regNum, unw_fpreg_t value) { +// OHOS_LOCAL end assert(validFloatRegister(regNum)); _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value; } @@ -1142,8 +1146,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -1504,12 +1508,16 @@ inline bool Registers_ppc64::validFloatRegister(int regNum) const { return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31; } +// OHOS_LOCAL begin inline unw_fpreg_t Registers_ppc64::getFloatRegister(int regNum) const { +// OHOS_LOCAL end assert(validFloatRegister(regNum)); return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f; } +// OHOS_LOCAL begin inline void Registers_ppc64::setFloatRegister(int regNum, unw_fpreg_t value) { +// OHOS_LOCAL end assert(validFloatRegister(regNum)); _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value; } @@ -1787,8 +1795,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -2026,12 +2034,16 @@ inline bool Registers_arm64::validFloatRegister(int regNum) const { return true; } +// OHOS_LOCAL begin inline unw_fpreg_t Registers_arm64::getFloatRegister(int regNum) const { +// OHOS_LOCAL end assert(validFloatRegister(regNum)); return _vectorHalfRegisters[regNum - UNW_ARM64_D0]; } +// OHOS_LOCAL begin inline void Registers_arm64::setFloatRegister(int regNum, unw_fpreg_t value) { +// OHOS_LOCAL end assert(validFloatRegister(regNum)); _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value; } @@ -2545,8 +2557,8 @@ public: uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -2634,12 +2646,16 @@ inline bool Registers_or1k::validFloatRegister(int /* regNum */) const { return false; } +// OHOS_LOCAL begin inline unw_fpreg_t Registers_or1k::getFloatRegister(int /* regNum */) const { +// OHOS_LOCAL end _LIBUNWIND_ABORT("or1k float support not implemented"); } +// OHOS_LOCAL begin inline void Registers_or1k::setFloatRegister(int /* regNum */, unw_fpreg_t /* value */) { +// OHOS_LOCAL end _LIBUNWIND_ABORT("or1k float support not implemented"); } @@ -2732,9 +2748,11 @@ inline const char *Registers_or1k::getRegisterName(int regNum) { #if defined(_LIBUNWIND_TARGET_MIPS_O32) +// OHOS_LOCAL begin // TODO: check the following for FPU with 32-bit registers: // - fpxx code works properly // - fp32 code remains working properly +// OHOS_LOCAL end /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS /// process. @@ -2742,21 +2760,13 @@ 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; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -2764,9 +2774,11 @@ public: void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; } static int getArch() { return REGISTERS_MIPS_O32; } + // OHOS_LOCAL begin #ifdef __mips_hard_float - static uint32_t getFpuRegsSize(); + static uint32_t getFpuRegsSize() { return (areFpuRegs64Bit() ? 8 : 4); } #endif + // OHOS_LOCAL end uint32_t getSP() const { return _registers.__r[29]; } void setSP(uint32_t value) { _registers.__r[29] = value; } @@ -2779,58 +2791,36 @@ private: uint32_t __pc; uint32_t __hi; uint32_t __lo; + // OHOS_LOCAL begin +#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; + char __f[32 * 8]; +#endif + // OHOS_LOCAL end }; 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. - const uint32_t _fpuRegsSize; - char _floatsBuffer[32 * 8] = {0}; - + // OHOS_LOCAL begin + static bool areFpuRegs64Bit(); char *getFpuRegLocation(int regNum); const char *getFpuRegLocation(int regNum) const; + // OHOS_LOCAL end #endif }; -inline Registers_mips_o32::Registers_mips_o32(const void *registers) -#ifdef __mips_hard_float - : _fpuRegsSize(getFpuRegsSize()) -#endif -{ +inline Registers_mips_o32::Registers_mips_o32(const void *registers) { static_assert((check_fit::does_fit), "mips_o32 registers do not fit into unw_context_t"); memcpy(&_registers, static_cast(registers), sizeof(_registers)); } -#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 -{ +inline Registers_mips_o32::Registers_mips_o32() { memset(&_registers, 0, sizeof(_registers)); } @@ -2849,6 +2839,7 @@ inline bool Registers_mips_o32::validRegister(int regNum) const { if (regNum == UNW_MIPS_LO) return true; #endif + // OHOS_LOCAL delete code block // FIXME: DSP accumulator registers, MSA registers return false; } @@ -2856,6 +2847,7 @@ 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]; + // OHOS_LOCAL delete code block switch (regNum) { case UNW_REG_IP: @@ -2875,6 +2867,8 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { _registers.__r[regNum - UNW_MIPS_R0] = value; return; } + // OHOS_LOCAL delete code block + switch (regNum) { case UNW_REG_IP: _registers.__pc = value; @@ -2892,44 +2886,62 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { _LIBUNWIND_ABORT("unsupported mips_o32 register"); } +// OHOS_LOCAL begin #ifdef __mips_hard_float +inline bool Registers_mips_o32::areFpuRegs64Bit() { +#if __mips_fpr == 32 + return false; +#elif __mips_fpr == 64 + return true; +#elif __mips_fpr == 0 + uint32_t fpuID; + asm("cfc1 %0, $0" : "=r"(fpuID)); + constexpr uint32_t MIPS_FPIR_F64 = (1 << 22); + return (fpuID & MIPS_FPIR_F64); +#else +#error "Unknown __mips_fpr value" +#endif +} + 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; + int offset, fpuRegNum = regNum - UNW_MIPS_F0; + if (!areFpuRegs64Bit() && fpuRegNum % 2 == 1) + offset = (fpuRegNum - 1) * 8 + 4; else - regLocation += fpuRegNum * 8; - return regLocation; + offset = fpuRegNum * 8; + return _registers.__f + offset; } 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; + int offset, fpuRegNum = regNum - UNW_MIPS_F0; + if (!areFpuRegs64Bit() && fpuRegNum % 2 == 1) + offset = (fpuRegNum - 1) * 8 + 4; else - regLocation += fpuRegNum * 8; - return regLocation; + offset = fpuRegNum * 8; + return _registers.__f + offset; } #endif +// OHOS_LOCAL end inline bool Registers_mips_o32::validFloatRegister(int regNum) const { +// OHOS_LOCAL begin #if defined(__mips_hard_float) return (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31); #else (void)regNum; return false; #endif +// OHOS_LOCAL end } +// OHOS_LOCAL begin 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); + memcpy(reinterpret_cast(®Value), regLocation, getFpuRegsSize()); return regValue; #elif __mips_fpr == 32 || __mips_fpr == 64 const char *regLocation = getFpuRegLocation(regNum); @@ -2937,25 +2949,28 @@ inline unw_fpreg_t Registers_mips_o32::getFloatRegister(int regNum) const { #else #error "Unknown __mips_fpr value" #endif +// OHOS_LOCAL end #else (void)regNum; _LIBUNWIND_ABORT("mips_o32 float support not implemented"); #endif } +// OHOS_LOCAL begin inline void Registers_mips_o32::setFloatRegister(int regNum, unw_fpreg_t value) { #if defined(__mips_hard_float) assert(validFloatRegister(regNum)); #if __mips_fpr == 0 char *regLocation = getFpuRegLocation(regNum); - memcpy(regLocation, reinterpret_cast(&value), _fpuRegsSize); + memcpy(regLocation, reinterpret_cast(&value), getFpuRegsSize()); #elif __mips_fpr == 32 || __mips_fpr == 64 char *regLocation = getFpuRegLocation(regNum); *reinterpret_cast(regLocation) = value; #else #error "Unknown __mips_fpr value" #endif +// OHOS_LOCAL end #else (void)regNum; (void)value; @@ -3127,8 +3142,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3148,12 +3163,15 @@ private: uint64_t __pc; uint64_t __hi; uint64_t __lo; + // OHOS_LOCAL begin +#ifdef __mips_hard_float + double __f[32]; +#endif + // OHOS_LOCAL end }; + // OHOS_LOCAL delete code block mips_newabi_thread_state_t _registers; -#ifdef __mips_hard_float - double _floats[32]; -#endif }; inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) { @@ -3236,21 +3254,25 @@ inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { return false; } +// OHOS_LOCAL begin inline unw_fpreg_t Registers_mips_newabi::getFloatRegister(int regNum) const { +// OHOS_LOCAL end #ifdef __mips_hard_float assert(validFloatRegister(regNum)); - return _floats[regNum - UNW_MIPS_F0]; + return _registers.__f[regNum - UNW_MIPS_F0]; // OHOS_LOCAL #else (void)regNum; _LIBUNWIND_ABORT("mips_newabi float support not implemented"); #endif } +// OHOS_LOCAL begin inline void Registers_mips_newabi::setFloatRegister(int regNum, unw_fpreg_t value) { +// OHOS_LOCAL end #ifdef __mips_hard_float assert(validFloatRegister(regNum)); - _floats[regNum - UNW_MIPS_F0] = value; + _registers.__f[regNum - UNW_MIPS_F0] = value; // OHOS_LOCAL #else (void)regNum; (void)value; @@ -3422,8 +3444,8 @@ public: uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3501,11 +3523,11 @@ inline void Registers_sparc::setRegister(int regNum, uint32_t value) { inline bool Registers_sparc::validFloatRegister(int) const { return false; } -inline unw_fpreg_t Registers_sparc::getFloatRegister(int) const { +inline unw_fpreg_t Registers_sparc::getFloatRegister(int) const { // OHOS_LOCAL _LIBUNWIND_ABORT("no Sparc float registers"); } -inline void Registers_sparc::setFloatRegister(int, unw_fpreg_t) { +inline void Registers_sparc::setFloatRegister(int, unw_fpreg_t) { // OHOS_LOCAL _LIBUNWIND_ABORT("no Sparc float registers"); } @@ -3606,8 +3628,8 @@ public: uint32_t getRegister(int num) const; void setRegister(int num, uint32_t value); bool validFloatRegister(int num) const; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -3680,12 +3702,16 @@ inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const { return false; } +// OHOS_LOCAL begin inline unw_fpreg_t Registers_hexagon::getFloatRegister(int /* regNum */) const { +// OHOS_LOCAL end _LIBUNWIND_ABORT("hexagon float support not implemented"); } +// OHOS_LOCAL begin inline void Registers_hexagon::setFloatRegister(int /* regNum */, unw_fpreg_t /* value */) { +// OHOS_LOCAL end _LIBUNWIND_ABORT("hexagon float support not implemented"); } @@ -3787,8 +3813,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -4009,7 +4035,9 @@ inline bool Registers_riscv::validFloatRegister(int regNum) const { return true; } +// OHOS_LOCAL begin inline unw_fpreg_t Registers_riscv::getFloatRegister(int regNum) const { +// OHOS_LOCAL end #if defined(__riscv_flen) && __riscv_flen == 64 assert(validFloatRegister(regNum)); return _floats[regNum - UNW_RISCV_F0]; @@ -4019,7 +4047,9 @@ inline unw_fpreg_t Registers_riscv::getFloatRegister(int regNum) const { #endif } +// OHOS_LOCAL begin inline void Registers_riscv::setFloatRegister(int regNum, unw_fpreg_t value) { +// OHOS_LOCAL end #if defined(__riscv_flen) && __riscv_flen == 64 assert(validFloatRegister(regNum)); _floats[regNum - UNW_RISCV_F0] = value; @@ -4054,8 +4084,8 @@ public: uint64_t getRegister(int num) const; void setRegister(int num, uint64_t value); bool validFloatRegister(int num) const; - unw_fpreg_t getFloatRegister(int num) const; - void setFloatRegister(int num, unw_fpreg_t value); + unw_fpreg_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, unw_fpreg_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -4158,12 +4188,16 @@ inline bool Registers_ve::validFloatRegister(int /* regNum */) const { return false; } +// OHOS_LOCAL begin inline unw_fpreg_t Registers_ve::getFloatRegister(int /* regNum */) const { +// OHOS_LOCAL end _LIBUNWIND_ABORT("VE doesn't have float registers"); } +// OHOS_LOCAL begin inline void Registers_ve::setFloatRegister(int /* regNum */, unw_fpreg_t /* value */) { +// OHOS_LOCAL end _LIBUNWIND_ABORT("VE doesn't have float registers"); } diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index 43902767ab308f611b235ebf4d499d96685f9a39..45280feafd5d49d8ea0d009d5d88939a449fe9b6 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 == 32 +#if __mips_fpr == 32 // OHOS_LOCAL ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) ldc1 $f4, (4 * 36 + 8 * 4)($4) @@ -882,7 +882,7 @@ 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) -#elif __mips_fpr == 64 +#elif __mips_fpr == 64 // OHOS_LOCAL ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f1, (4 * 36 + 8 * 1)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) @@ -915,13 +915,33 @@ 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) +// OHOS_LOCAL begin #elif __mips_fpr == 0 + // Check the register size in runtime + // Load the FIR control register value cfc1 $t0, $0 + // Test F64 bit of the FIR control register li $t1, 1 sll $t1, $t1, 22 and $t0, $t0, $t1 beq $t0, $0, _fp32 + nop _fp64: + .set fp=64 + // The order of loads here is important. Even if the F64 bit of the FIR status + // register is set, it only means that the FPU has 64-bit FPRs. But it also + // can operate in 32-bit compatibility mode. We are not able to determine if + // such mode is enable because the corresponding FR bit of the CP0 Status + // register is only available for read in the kernel mode. So, we use the + // following order of loads as a workaround. + // - If FR=0 (32-bit compat mode), double-precision operations have no + // documented behavior. Here we assume that such loads just corrupt the + // corresponding registers and do not raise an exception (which is true for + // QEMU). Since $f_{2k+1} is a higher part of $f_{2k} in FR=0 mode, we need + // to perform operation on the odd register first so it won't corrupt the + // even register value when it's treated as 64-bit. + // - If FR=1 (64-bit native mode), the order does not matter since the + // registers do not overlap. ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f1, (4 * 36 + 8 * 1)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) @@ -954,8 +974,11 @@ _fp64: ldc1 $f29, (4 * 36 + 8 * 29)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) ldc1 $f31, (4 * 36 + 8 * 31)($4) + .set fp=xx j _after_float + nop _fp32: + .set fp=32 ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) ldc1 $f4, (4 * 36 + 8 * 4)($4) @@ -972,11 +995,13 @@ _fp32: ldc1 $f26, (4 * 36 + 8 * 26)($4) ldc1 $f28, (4 * 36 + 8 * 28)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) + .set fp=xx #else #error "Unknown __mips_fpr value" +// OHOS_LOCAL end #endif #endif -_after_float: +_after_float: // OHOS_LOCAL // restore hi and lo lw $8, (4 * 33)($4) mthi $8 diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S index bfaf3530166aba4e8bc9914dbf5b1e0597abce1d..95a0d342f749624eee03d72cbeff7748f0664318 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -128,8 +128,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) .set noat .set noreorder .set nomacro +// OHOS_LOCAL move code block #ifdef __mips_hard_float -#if __mips_fpr == 32 +#if __mips_fpr == 32 // OHOS_LOCAL sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) sdc1 $f4, (4 * 36 + 8 * 4)($4) @@ -146,7 +147,7 @@ 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) -#elif __mips_fpr == 64 +#elif __mips_fpr == 64 // OHOS_LOCAL sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f1, (4 * 36 + 8 * 1)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) @@ -179,13 +180,19 @@ 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) +// OHOS_LOCAL begin #elif __mips_fpr == 0 + // Check the register size in runtime + // Load the FIR control register value cfc1 $t0, $0 + // Test F64 bit of the FIR control register li $t1, 1 sll $t1, $t1, 22 and $t0, $t0, $t1 beq $t0, $0, _fp32 + nop _fp64: + .set fp=64 sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f1, (4 * 36 + 8 * 1)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) @@ -218,8 +225,11 @@ _fp64: sdc1 $f29, (4 * 36 + 8 * 29)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) sdc1 $f31, (4 * 36 + 8 * 31)($4) + .set fp=xx j _after_float + nop _fp32: + .set fp=32 sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) sdc1 $f4, (4 * 36 + 8 * 4)($4) @@ -236,11 +246,14 @@ _fp32: sdc1 $f26, (4 * 36 + 8 * 26)($4) sdc1 $f28, (4 * 36 + 8 * 28)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) + .set fp=xx #else #error "Unknown __mips_fpr value" +// OHOS_LOCAL end #endif #endif -_after_float: +_after_float: // OHOS_LOCAL +// OHOS_LOCAL begin moved code block sw $1, (4 * 1)($4) sw $2, (4 * 2)($4) sw $3, (4 * 3)($4) @@ -279,6 +292,7 @@ _after_float: sw $8, (4 * 33)($4) mflo $8 sw $8, (4 * 34)($4) +// OHOS_LOCAL end moved code block jr $31 # return UNW_ESUCCESS or $2, $0, $0 diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp index c3861f3abed0fa2526b6f48060417e5e2e6d14a3..92936a3aa69cead156b5acd2a6bac0556296568a 100644 --- a/libunwind/src/libunwind.cpp +++ b/libunwind/src/libunwind.cpp @@ -144,7 +144,9 @@ _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) { +// OHOS_LOCAL begin #if defined(_LIBUNWIND_ARM_EHABI) || (defined(__mips__) && __mips_fpr == 0) +// OHOS_LOCAL end _LIBUNWIND_TRACE_API("__unw_set_fpreg(cursor=%p, regNum=%d, value=%llX)", static_cast(cursor), regNum, value); #else