diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h index 7e4f266fab372aaa93d11f99ba1fdfbc110e0e9f..b01348d8c92937eb295cc2bef1cbb830464b2125 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__) && !defined(__SEH__) 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 fcfaf34f1a772888429e6039b40221783afed10a..5cf7e44665e727cdd29136e16fbec773f2bed27a 100644 --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -176,6 +176,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) @@ -185,6 +186,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 394448dc44677883dfa543bd4f8e2cef0a37af4c..613ca83cd901b538898e3765bd58f38e8bce1cb8 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); @@ -119,7 +121,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 9c1f4c93610289d7f3690a9ecb85a8a1d9a2543d..ac9d8f9086022e25af58648db79ec4cc64e28bae 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -63,8 +63,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); @@ -242,11 +242,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"); } @@ -281,8 +281,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); @@ -545,11 +545,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"); } @@ -600,8 +600,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); @@ -986,12 +986,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; } @@ -1170,8 +1174,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); @@ -1536,12 +1540,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; } @@ -1819,8 +1827,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); @@ -2070,12 +2078,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_AARCH64_V0]; } +// OHOS_LOCAL begin inline void Registers_arm64::setFloatRegister(int regNum, unw_fpreg_t value) { +// OHOS_LOCAL end assert(validFloatRegister(regNum)); _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value; } @@ -2613,8 +2625,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); @@ -2704,12 +2716,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"); } @@ -2802,9 +2818,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. @@ -2812,21 +2830,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); @@ -2836,9 +2846,11 @@ public: 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; } @@ -2851,58 +2863,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)); } @@ -2921,6 +2911,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; } @@ -2928,6 +2919,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: @@ -2947,6 +2939,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; @@ -2964,44 +2958,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); @@ -3009,25 +3021,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; @@ -3199,8 +3214,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); @@ -3222,12 +3237,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) { @@ -3310,21 +3328,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; @@ -3496,8 +3518,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); @@ -3577,11 +3599,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"); } @@ -3867,8 +3889,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); @@ -3943,12 +3965,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"); } @@ -4082,8 +4108,8 @@ public: reg_t getRegister(int num) const; void setRegister(int num, reg_t value); bool validFloatRegister(int num) const; - fp_t getFloatRegister(int num) const; - void setFloatRegister(int num, fp_t value); + fp_t getFloatRegister(int num) const; // OHOS_LOCAL + void setFloatRegister(int num, fp_t value); // OHOS_LOCAL bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); @@ -4325,8 +4351,10 @@ inline bool Registers_riscv::validFloatRegister(int regNum) const { # endif } -inline unw_fpreg_t Registers_riscv::getFloatRegister(int regNum) const { -# if defined(__riscv_flen) +// OHOS_LOCAL begin +inline fp_t Registers_riscv::getFloatRegister(int regNum) const { +// OHOS_LOCAL end +#if defined(__riscv_flen) assert(validFloatRegister(regNum)); return _floats[regNum - UNW_RISCV_F0]; # else @@ -4335,8 +4363,10 @@ inline unw_fpreg_t Registers_riscv::getFloatRegister(int regNum) const { # endif } -inline void Registers_riscv::setFloatRegister(int regNum, unw_fpreg_t value) { -# if defined(__riscv_flen) +// OHOS_LOCAL begin +inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) { +// OHOS_LOCAL end +#if defined(__riscv_flen) assert(validFloatRegister(regNum)); _floats[regNum - UNW_RISCV_F0] = value; # else @@ -4370,8 +4400,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); @@ -4476,12 +4506,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 894b5f60a1555c8e21c21bb126885117eccc7282..749db2357159d37e5e4015a269803c388b16ffeb 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -917,7 +917,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) @@ -934,7 +934,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) @@ -967,13 +967,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) @@ -1006,8 +1026,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) @@ -1024,11 +1047,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 2b79f448507f2e2fad979fdd35be581d2d3e80b9..c5bfd128cdf60a950c39f74b33183c7bfda6ccd9 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -135,8 +135,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) @@ -153,7 +154,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) @@ -186,13 +187,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) @@ -225,8 +232,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) @@ -243,11 +253,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) @@ -286,6 +299,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 0f67d15dc935937a24be050b8f562ec6e11bb760..491ba882891d51509f8775a01db574136087aa8e 100644 --- a/libunwind/src/libunwind.cpp +++ b/libunwind/src/libunwind.cpp @@ -157,7 +157,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