From cf139909273a6ba4d1bab1caa5f6732ab1d3de33 Mon Sep 17 00:00:00 2001 From: Oleg Kuptsov Date: Wed, 30 Nov 2022 05:04:06 +0300 Subject: [PATCH 1/3] [OHOS][MIPS][libunwind] Annotate OHOS-local changes Change-Id: I4c6be63ff60372534f5722549f577d1ca472e853 Signed-off-by: Oleg Kuptsov --- libunwind/include/libunwind.h | 18 +-- libunwind/src/AddressSpace.hpp | 2 + libunwind/src/DwarfInstructions.hpp | 4 +- libunwind/src/Registers.hpp | 152 ++++++++++++++++--------- libunwind/src/UnwindRegistersRestore.S | 8 +- libunwind/src/UnwindRegistersSave.S | 11 +- libunwind/src/libunwind.cpp | 2 + 7 files changed, 132 insertions(+), 65 deletions(-) diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h index c36a94e8754d..ab8e3994d4e1 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 578f383f1d3b..33cf75c77a54 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 9a88577eb06b..590c013fb4b8 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 d2e2ac86cb0d..6bb7b92fd86c 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,6 +2760,7 @@ class _LIBUNWIND_HIDDEN Registers_mips_o32 { public: Registers_mips_o32(); Registers_mips_o32(const void *registers); + // OHOS_LOCAL begin #ifdef __mips_hard_float Registers_mips_o32(const Registers_mips_o32 &) = default; Registers_mips_o32 &operator=(const Registers_mips_o32 &src) { @@ -2750,13 +2769,14 @@ public: return *this; } #endif + // OHOS_LOCAL end 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 +2784,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(); #endif + // OHOS_LOCAL end uint32_t getSP() const { return _registers.__r[29]; } void setSP(uint32_t value) { _registers.__r[29] = value; } @@ -2787,11 +2809,13 @@ 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. + // OHOS_LOCAL begin const uint32_t _fpuRegsSize; char _floatsBuffer[32 * 8] = {0}; char *getFpuRegLocation(int regNum); const char *getFpuRegLocation(int regNum) const; + // OHOS_LOCAL end #endif }; @@ -2806,26 +2830,6 @@ inline Registers_mips_o32::Registers_mips_o32(const void *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()) @@ -2849,6 +2853,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 +2861,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 +2881,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,7 +2900,26 @@ 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 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 +} + inline const char *Registers_mips_o32::getFpuRegLocation(int regNum) const { const char *regLocation = _floatsBuffer; int fpuRegNum = regNum - UNW_MIPS_F0; @@ -2913,16 +2940,20 @@ inline char *Registers_mips_o32::getFpuRegLocation(int regNum) { return regLocation; } #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)); @@ -2937,12 +2968,14 @@ 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) @@ -2956,6 +2989,7 @@ inline void Registers_mips_o32::setFloatRegister(int regNum, #else #error "Unknown __mips_fpr value" #endif +// OHOS_LOCAL end #else (void)regNum; (void)value; @@ -3127,8 +3161,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); @@ -3236,7 +3270,9 @@ 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]; @@ -3246,11 +3282,13 @@ inline unw_fpreg_t Registers_mips_newabi::getFloatRegister(int regNum) const { #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; + _floats[regNum - UNW_MIPS_F0] = value; // OHOS_LOCAL #else (void)regNum; (void)value; @@ -3422,8 +3460,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 +3539,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 +3644,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 +3718,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 +3829,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 +4051,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 +4063,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 +4100,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 +4204,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 43902767ab30..180419f2d8a5 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,6 +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) +// OHOS_LOCAL begin #elif __mips_fpr == 64 ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f1, (4 * 36 + 8 * 1)($4) @@ -922,6 +923,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) and $t0, $t0, $t1 beq $t0, $0, _fp32 _fp64: +// OHOS_LOCAL end ldc1 $f0, (4 * 36 + 8 * 0)($4) ldc1 $f1, (4 * 36 + 8 * 1)($4) ldc1 $f2, (4 * 36 + 8 * 2)($4) @@ -954,6 +956,7 @@ _fp64: ldc1 $f29, (4 * 36 + 8 * 29)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) ldc1 $f31, (4 * 36 + 8 * 31)($4) +// OHOS_LOCAL begin j _after_float _fp32: ldc1 $f0, (4 * 36 + 8 * 0)($4) @@ -974,9 +977,10 @@ _fp32: ldc1 $f30, (4 * 36 + 8 * 30)($4) #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 bfaf3530166a..960726e76259 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,6 +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) +// OHOS_LOCAL begin #elif __mips_fpr == 64 sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f1, (4 * 36 + 8 * 1)($4) @@ -186,6 +188,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) and $t0, $t0, $t1 beq $t0, $0, _fp32 _fp64: +// OHOS_LOCAL end sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f1, (4 * 36 + 8 * 1)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) @@ -218,6 +221,7 @@ _fp64: sdc1 $f29, (4 * 36 + 8 * 29)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) sdc1 $f31, (4 * 36 + 8 * 31)($4) +// OHOS_LOCAL begin j _after_float _fp32: sdc1 $f0, (4 * 36 + 8 * 0)($4) @@ -238,9 +242,11 @@ _fp32: sdc1 $f30, (4 * 36 + 8 * 30)($4) #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 +285,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 c3861f3abed0..92936a3aa69c 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 -- Gitee From dd6ff12fb328c93e38d3dd23fbb8770adc91b038 Mon Sep 17 00:00:00 2001 From: Oleg Kuptsov Date: Wed, 30 Nov 2022 04:55:41 +0300 Subject: [PATCH 2/3] [OHOS][MIPS][libunwind] Fix filling floating point registers buffer Previously, a buffer for saving floating point registers was defined separately from the srtuct mips_ABINAME_thread_state_t. This struct is filled in the constructor from the buffer obtained with __unw_getcontext containing all the registers values (including floating-point ones). But the buffer containing floating-point registers was not filled and remained default-initialized. It led to having callee-saved floating point registers unrestored after a call throwing an exception. This patch moves the floating point buffer definition to the thread state struct so copying the buffer obtained with __unw_getcontext to this struct also copies floating point registers values. Change-Id: I9cff5c2d11044686e45ab70fd5554f376f8bbae2 Signed-off-by: Oleg Kuptsov --- libunwind/src/Registers.hpp | 98 ++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 57 deletions(-) diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp index 6bb7b92fd86c..c6434e91ae50 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -2760,16 +2760,6 @@ class _LIBUNWIND_HIDDEN Registers_mips_o32 { public: Registers_mips_o32(); Registers_mips_o32(const void *registers); - // OHOS_LOCAL begin -#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 - // OHOS_LOCAL end bool validRegister(int num) const; uint32_t getRegister(int num) const; @@ -2786,7 +2776,7 @@ public: 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 @@ -2801,40 +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. // OHOS_LOCAL begin - const uint32_t _fpuRegsSize; - char _floatsBuffer[32 * 8] = {0}; - + 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)); } -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)); } @@ -2902,42 +2888,37 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { // OHOS_LOCAL begin #ifdef __mips_hard_float -inline uint32_t Registers_mips_o32::getFpuRegsSize() { +inline bool Registers_mips_o32::areFpuRegs64Bit() { #if __mips_fpr == 32 - return 4; + return false; #elif __mips_fpr == 64 - return 8; + return true; #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; + 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 @@ -2960,7 +2941,7 @@ inline unw_fpreg_t Registers_mips_o32::getFloatRegister(int regNum) const { #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); @@ -2982,7 +2963,7 @@ inline void Registers_mips_o32::setFloatRegister(int regNum, 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; @@ -3182,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) { @@ -3275,7 +3259,7 @@ 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"); @@ -3288,7 +3272,7 @@ inline void Registers_mips_newabi::setFloatRegister(int regNum, // OHOS_LOCAL end #ifdef __mips_hard_float assert(validFloatRegister(regNum)); - _floats[regNum - UNW_MIPS_F0] = value; // OHOS_LOCAL + _registers.__f[regNum - UNW_MIPS_F0] = value; // OHOS_LOCAL #else (void)regNum; (void)value; -- Gitee From cace924173c62f02c6cef9d7c330be64ade8f09d Mon Sep 17 00:00:00 2001 From: Oleg Kuptsov Date: Wed, 30 Nov 2022 09:48:20 +0300 Subject: [PATCH 3/3] [OHOS][MIPS][libunwind] Fix various floating-point-related issues - For fpxx, we determine the FPU register size at runtime. To use odd registers in case of 64-bit size, we have to specify `.set fp=64` assembly directive. Otherwise, clang will emit duplicated loads/stores of $f0, $f2, ..., $f30 instead of $f1, $f3, ..., $f31. - Even when FPU register size is 64-bit, the FPU can run in 32-bit compatibility mode. We cannot determine it at runtime since the status register containing the corresponding bit is only available in kernel mode. As a workaround, we change the order of FP regs load in `libunwind::Registers_mips_o32::jumpto()`. Change-Id: I614ac65d837ae6ea1610087c0b5092d9aa82669e Signed-off-by: Oleg Kuptsov --- libunwind/src/UnwindRegistersRestore.S | 29 ++++++++++++++++++++++---- libunwind/src/UnwindRegistersSave.S | 15 +++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index 180419f2d8a5..45280feafd5d 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -882,8 +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) -// OHOS_LOCAL begin -#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) @@ -916,14 +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: -// OHOS_LOCAL end + .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) @@ -956,9 +974,11 @@ _fp64: ldc1 $f29, (4 * 36 + 8 * 29)($4) ldc1 $f30, (4 * 36 + 8 * 30)($4) ldc1 $f31, (4 * 36 + 8 * 31)($4) -// OHOS_LOCAL begin + .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) @@ -975,6 +995,7 @@ _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 diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S index 960726e76259..95a0d342f749 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -147,8 +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) -// OHOS_LOCAL begin -#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) @@ -181,14 +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: -// OHOS_LOCAL end + .set fp=64 sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f1, (4 * 36 + 8 * 1)($4) sdc1 $f2, (4 * 36 + 8 * 2)($4) @@ -221,9 +225,11 @@ _fp64: sdc1 $f29, (4 * 36 + 8 * 29)($4) sdc1 $f30, (4 * 36 + 8 * 30)($4) sdc1 $f31, (4 * 36 + 8 * 31)($4) -// OHOS_LOCAL begin + .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) @@ -240,6 +246,7 @@ _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 -- Gitee