Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h @@ -33,6 +33,9 @@ uint32_t GetRegisterSetCount () const override; + const RegisterInfo * + GetRegisterInfoAtIndex (uint32_t reg_index) const override; + lldb::addr_t GetPCfromBreakpointLocation (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS) override; @@ -113,6 +116,9 @@ bool IsFR0(); + void + IsFR1_FRE (bool &fr1, bool &fre) const; + bool IsFRE(); Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -483,6 +483,34 @@ return k_num_register_sets; } + +const RegisterInfo * +NativeRegisterContextLinux_mips64::GetRegisterInfoAtIndex (uint32_t reg_index) const +{ + if (reg_index <= GetRegisterCount ()) + { + const RegisterInfoInterface& reg_info_interface = GetRegisterInfoInterface (); + RegisterInfo* reg_info = const_cast(reg_info_interface.GetRegisterInfo ()) + reg_index; + + // We need to skip fcsr, fir and config5 register + // since they all have 32 bit register size irrespective of FR bit + if (m_reg_info.first_fpr <= reg_index && reg_index < (m_reg_info.last_fpr -2)) + { + bool fre; + bool fr1; + IsFR1_FRE (fr1, fre); + + // fr1 fre fpu_reg_size + // 1 0 64 + // 1 1 32 + // 0 0 32 + reg_info->byte_size = (fr1 ^ fre) ? 8 : 4; + } + return const_cast(reg_info); + } + return nullptr; +} + lldb::addr_t NativeRegisterContextLinux_mips64::GetPCfromBreakpointLocation (lldb::addr_t fail_value) { @@ -901,6 +929,42 @@ return (!(value & SR_FR)); } +void +NativeRegisterContextLinux_mips64::IsFR1_FRE (bool& fr1, bool& fre) const +{ + GPR_linux_mips regs; + RegisterValue reg_value; + const RegisterInfoInterface& reg_info_interface = GetRegisterInfoInterface (); + const RegisterInfo* reg_info_sr = reg_info_interface.GetRegisterInfo () + gpr_sr_mips64 ; + const RegisterInfo* reg_info_config5 = reg_info_interface.GetRegisterInfo () + gpr_config5_mips; + lldb_private::ArchSpec arch; + ::memset (®s, 0, sizeof(GPR_linux_mips)); + + fre = 0; + if (!(m_thread.GetProcess ()->GetArchitecture (arch))) + assert (false && "Failed to get Architecture."); + + errno = 0; + + // Reading SR/Config5 using PTRACE_PEEKUSER is not supported + Error error = NativeProcessLinux::PtraceWrapper (PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); + if (!error.Success()) + assert (false && "Unable to Read Register"); + + void* target_address = ((uint8_t*)®s) + reg_info_sr->byte_offset + 4 * (arch.GetMachine () == llvm::Triple::mips); + reg_value.SetBytes (target_address, 4, arch.GetByteOrder()); + fr1 = reg_value.GetAsUInt32() & SR_FR; + + // FRE is valid only when FR bit is set + if (fr1) + { + target_address = ((uint8_t*)®s) + reg_info_config5->byte_offset + + 4 * (arch.GetMachine () == llvm::Triple::mips); + reg_value.SetBytes(target_address, 4, arch.GetByteOrder ()); + fre = reg_value.GetAsUInt32() & CONFIG5_FRE; + } +} + bool NativeRegisterContextLinux_mips64::IsFRE() { Index: source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -67,6 +67,9 @@ const RegisterInfo * GetRegisterInfoAtIndex (size_t reg) override; + const RegisterInfo * + GetMipsFRRegisterInfoAtIndex (size_t reg); + size_t GetRegisterSetCount () override; Index: source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -27,6 +27,9 @@ #include "ThreadGDBRemote.h" #include "Utility/ARM_DWARF_Registers.h" #include "Utility/ARM_ehframe_Registers.h" +#include "Plugins/Process/Utility/lldb-mips-linux-register-enums.h" +#define SR_FR (1 << 26) +#define CONFIG5_FRE (1 << 8) using namespace lldb; using namespace lldb_private; @@ -89,6 +92,11 @@ const RegisterInfo * GDBRemoteRegisterContext::GetRegisterInfoAtIndex (size_t reg) { + const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture(); + if (arch.IsValid() && arch.IsMIPS() && (lldb_private::k_first_fpr_mips64 <= reg + && reg < lldb_private::fpr_fcsr_mips64)) + return GetMipsFRRegisterInfoAtIndex(reg); + return m_reg_info.GetRegisterInfoAtIndex (reg); } @@ -939,6 +947,35 @@ return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num); } +const RegisterInfo * +GDBRemoteRegisterContext::GetMipsFRRegisterInfoAtIndex (size_t reg) +{ + // Read SR Register. + RegisterInfo* reg_info = const_cast(m_reg_info.GetRegisterInfoAtIndex (gpr_sr_mips64)); + DataExtractor data; + if (ReadRegisterBytes (reg_info, data)) + { + lldb::offset_t offset = 0; + uint32_t fr1 = data.GetU32(&offset) & SR_FR; + uint32_t fre = 0; + reg_info = const_cast(m_reg_info.GetRegisterInfoAtIndex (gpr_config5_mips64)); + + // Fre is only valid when fr1 is 1 + if (fr1 && ReadRegisterBytes (reg_info, data)) + fre = data.GetU32(&offset) & CONFIG5_FRE; + + reg_info = const_cast(m_reg_info.GetRegisterInfoAtIndex (reg)); + + // fr1 fre FPU_size + // 1 0 64 + // 1 1 32 + // 0 0 32 + reg_info->byte_size = (fr1 ^ fre) ? 8: 4; + return const_cast(reg_info); + } + assert(false && "Unable to Fetch SR Value"); + return NULL; +} void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)