Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.h =================================================================== --- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.h +++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.h @@ -30,6 +30,8 @@ uint32_t GetRegisterSetCount() const override; + uint32_t GetUserRegisterCount() const override; + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; Status ReadRegister(const RegisterInfo *reg_info, @@ -42,7 +44,22 @@ Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + void InvalidateAllRegisters() override; + + std::vector + GetExpeditedRegisters(ExpeditedRegs expType) const override; + + bool RegisterOffsetIsDynamic() const override { return true; } + protected: + Status ReadGPR() override; + + Status WriteGPR() override; + + Status ReadFPR() override; + + Status WriteFPR() override; + void *GetGPRBuffer() override { return &m_gpr; } void *GetFPRBuffer() override { return &m_fpr; } @@ -52,10 +69,19 @@ size_t GetFPRSize() override { return GetRegisterInfo().GetFPRSize(); } private: + bool m_gpr_is_valid; + bool m_fpu_is_valid; + RegisterInfoPOSIX_loongarch64::GPR m_gpr; RegisterInfoPOSIX_loongarch64::FPR m_fpr; + bool IsGPR(unsigned reg) const; + + bool IsFPR(unsigned reg) const; + + uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; + const RegisterInfoPOSIX_loongarch64 &GetRegisterInfo() const; }; Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.cpp =================================================================== --- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.cpp +++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_loongarch64.cpp @@ -18,6 +18,15 @@ #include "Plugins/Process/Linux/NativeProcessLinux.h" #include "Plugins/Process/Linux/Procfs.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h" +#include "Plugins/Process/Utility/lldb-loongarch-register-enums.h" + +// struct iovec definition +#include +// NT_PRSTATUS and NT_FPREGSET definition +#include + +#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) using namespace lldb; using namespace lldb_private; @@ -52,6 +61,9 @@ NativeRegisterContextLinux(native_thread) { ::memset(&m_fpr, 0, sizeof(m_fpr)); ::memset(&m_gpr, 0, sizeof(m_gpr)); + + m_gpr_is_valid = false; + m_fpu_is_valid = false; } const RegisterInfoPOSIX_loongarch64 & @@ -69,24 +81,258 @@ return GetRegisterInfo().GetRegisterSet(set_index); } +uint32_t NativeRegisterContextLinux_loongarch64::GetUserRegisterCount() const { + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) + count += GetRegisterSet(set_index)->num_registers; + return count; +} + Status NativeRegisterContextLinux_loongarch64::ReadRegister( const RegisterInfo *reg_info, RegisterValue ®_value) { - return Status("Failed to read register value"); + Status error; + + if (!reg_info) { + error.SetErrorString("reg_info NULL"); + return error; + } + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + + if (reg == LLDB_INVALID_REGNUM) + return Status("no lldb regnum for %s", reg_info && reg_info->name + ? reg_info->name + : ""); + + uint8_t *src = nullptr; + uint32_t offset = LLDB_INVALID_INDEX32; + + if (IsGPR(reg)) { + error = ReadGPR(); + if (error.Fail()) + return error; + + offset = reg_info->byte_offset; + assert(offset < GetGPRSize()); + src = (uint8_t *)GetGPRBuffer() + offset; + + } else if (IsFPR(reg)) { + error = ReadFPR(); + if (error.Fail()) + return error; + + offset = CalculateFprOffset(reg_info); + assert(offset < GetFPRSize()); + src = (uint8_t *)GetFPRBuffer() + offset; + } else + return Status("failed - register wasn't recognized to be a GPR or an FPR, " + "write strategy unknown"); + + reg_value.SetFromMemoryData(*reg_info, src, reg_info->byte_size, + eByteOrderLittle, error); + + return error; } Status NativeRegisterContextLinux_loongarch64::WriteRegister( const RegisterInfo *reg_info, const RegisterValue ®_value) { + Status error; + + if (!reg_info) + return Status("reg_info NULL"); + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + + if (reg == LLDB_INVALID_REGNUM) + return Status("no lldb regnum for %s", reg_info->name != nullptr + ? reg_info->name + : ""); + + uint8_t *dst = nullptr; + uint32_t offset = LLDB_INVALID_INDEX32; + + if (IsGPR(reg)) { + error = ReadGPR(); + if (error.Fail()) + return error; + + assert(reg_info->byte_offset < GetGPRSize()); + dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset; + ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); + + return WriteGPR(); + } else if (IsFPR(reg)) { + error = ReadFPR(); + if (error.Fail()) + return error; + + offset = CalculateFprOffset(reg_info); + assert(offset < GetFPRSize()); + dst = (uint8_t *)GetFPRBuffer() + offset; + ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); + + return WriteFPR(); + } + return Status("Failed to write register value"); } Status NativeRegisterContextLinux_loongarch64::ReadAllRegisterValues( lldb::WritableDataBufferSP &data_sp) { - return Status("Failed to read all register values"); + Status error; + + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + + error = ReadGPR(); + if (error.Fail()) + return error; + + error = ReadFPR(); + if (error.Fail()) + return error; + + uint8_t *dst = const_cast(data_sp->GetBytes()); + ::memcpy(dst, GetGPRBuffer(), GetGPRSize()); + dst += GetGPRSize(); + ::memcpy(dst, GetFPRBuffer(), GetFPRSize()); + + return error; } Status NativeRegisterContextLinux_loongarch64::WriteAllRegisterValues( const lldb::DataBufferSP &data_sp) { - return Status("Failed to write all register values"); + Status error; + + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_loongarch64::%s invalid data_sp provided", + __FUNCTION__); + return error; + } + + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_loongarch64::%s data_sp contained " + "mismatched data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = const_cast(data_sp->GetBytes()); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_loongarch64::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + ::memcpy(GetGPRBuffer(), src, GetRegisterInfoInterface().GetGPRSize()); + + error = WriteGPR(); + if (error.Fail()) + return error; + + src += GetRegisterInfoInterface().GetGPRSize(); + ::memcpy(GetFPRBuffer(), src, GetFPRSize()); + + error = WriteFPR(); + if (error.Fail()) + return error; + + return error; +} + +bool NativeRegisterContextLinux_loongarch64::IsGPR(unsigned reg) const { + return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_loongarch64::GPRegSet; +} + +bool NativeRegisterContextLinux_loongarch64::IsFPR(unsigned reg) const { + return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_loongarch64::FPRegSet; +} + +Status NativeRegisterContextLinux_loongarch64::ReadGPR() { + Status error; + + if (m_gpr_is_valid) + return error; + + struct iovec ioVec; + ioVec.iov_base = GetGPRBuffer(); + ioVec.iov_len = GetGPRSize(); + + error = ReadRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS); + + if (error.Success()) + m_gpr_is_valid = true; + + return error; +} + +Status NativeRegisterContextLinux_loongarch64::WriteGPR() { + Status error = ReadGPR(); + if (error.Fail()) + return error; + + struct iovec ioVec; + ioVec.iov_base = GetGPRBuffer(); + ioVec.iov_len = GetGPRSize(); + + m_gpr_is_valid = false; + + return WriteRegisterSet(&ioVec, GetGPRSize(), NT_PRSTATUS); +} + +Status NativeRegisterContextLinux_loongarch64::ReadFPR() { + Status error; + + if (m_fpu_is_valid) + return error; + + struct iovec ioVec; + ioVec.iov_base = GetFPRBuffer(); + ioVec.iov_len = GetFPRSize(); + + error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); + + if (error.Success()) + m_fpu_is_valid = true; + + return error; +} + +Status NativeRegisterContextLinux_loongarch64::WriteFPR() { + Status error = ReadFPR(); + if (error.Fail()) + return error; + + struct iovec ioVec; + ioVec.iov_base = GetFPRBuffer(); + ioVec.iov_len = GetFPRSize(); + + m_fpu_is_valid = false; + + return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); +} + +void NativeRegisterContextLinux_loongarch64::InvalidateAllRegisters() { + m_gpr_is_valid = false; + m_fpu_is_valid = false; +} + +uint32_t NativeRegisterContextLinux_loongarch64::CalculateFprOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - GetGPRSize(); +} + +std::vector +NativeRegisterContextLinux_loongarch64::GetExpeditedRegisters( + ExpeditedRegs expType) const { + std::vector expedited_reg_nums = + NativeRegisterContext::GetExpeditedRegisters(expType); + + return expedited_reg_nums; } #endif // defined(__loongarch__) && __loongarch_grlen == 64 Index: lldb/source/Plugins/Process/Utility/CMakeLists.txt =================================================================== --- lldb/source/Plugins/Process/Utility/CMakeLists.txt +++ lldb/source/Plugins/Process/Utility/CMakeLists.txt @@ -38,6 +38,7 @@ RegisterContextOpenBSD_x86_64.cpp RegisterContextPOSIX_arm.cpp RegisterContextPOSIX_arm64.cpp + RegisterContextPOSIX_loongarch64.cpp RegisterContextPOSIX_mips64.cpp RegisterContextPOSIX_powerpc.cpp RegisterContextPOSIX_ppc64le.cpp Index: lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.h =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.h @@ -0,0 +1,63 @@ +//===-- RegisterContextPOSIX_loongarch64.h ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_LOONGARCH64_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_LOONGARCH64_H + +#include "RegisterInfoInterface.h" +#include "RegisterInfoPOSIX_loongarch64.h" +#include "lldb-loongarch-register-enums.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/Log.h" + +class RegisterContextPOSIX_loongarch64 : public lldb_private::RegisterContext { +public: + RegisterContextPOSIX_loongarch64( + lldb_private::Thread &thread, + std::unique_ptr register_info); + + ~RegisterContextPOSIX_loongarch64() override; + + void invalidate(); + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + virtual size_t GetGPRSize(); + + virtual unsigned GetRegisterSize(unsigned reg); + + virtual unsigned GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const lldb_private::RegisterSet *GetRegisterSet(size_t set) override; + +protected: + std::unique_ptr m_register_info_up; + + virtual const lldb_private::RegisterInfo *GetRegisterInfo(); + + bool IsGPR(unsigned reg); + + bool IsFPR(unsigned reg); + + size_t GetFPRSize() { return sizeof(RegisterInfoPOSIX_loongarch64::FPR); } + + uint32_t GetRegNumFCSR() const { return fpr_fcsr_loongarch; } + + virtual bool ReadGPR() = 0; + virtual bool ReadFPR() = 0; + virtual bool WriteGPR() = 0; + virtual bool WriteFPR() = 0; +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTPOSIX_LOONGARCH64_H Index: lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.cpp =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_loongarch64.cpp @@ -0,0 +1,82 @@ +//===-- RegisterContextPOSIX_loongarch64.cpp --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Endian.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Scalar.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterContextPOSIX_loongarch64.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextPOSIX_loongarch64::RegisterContextPOSIX_loongarch64( + lldb_private::Thread &thread, + std::unique_ptr register_info) + : lldb_private::RegisterContext(thread, 0), + m_register_info_up(std::move(register_info)) {} + +RegisterContextPOSIX_loongarch64::~RegisterContextPOSIX_loongarch64() = default; + +void RegisterContextPOSIX_loongarch64::invalidate() {} + +void RegisterContextPOSIX_loongarch64::InvalidateAllRegisters() {} + +size_t RegisterContextPOSIX_loongarch64::GetRegisterCount() { + return m_register_info_up->GetRegisterCount(); +} + +size_t RegisterContextPOSIX_loongarch64::GetGPRSize() { + return m_register_info_up->GetGPRSize(); +} + +unsigned RegisterContextPOSIX_loongarch64::GetRegisterSize(unsigned int reg) { + return m_register_info_up->GetRegisterInfo()[reg].byte_size; +} + +unsigned RegisterContextPOSIX_loongarch64::GetRegisterOffset(unsigned int reg) { + return m_register_info_up->GetRegisterInfo()[reg].byte_offset; +} + +const lldb_private::RegisterInfo * +RegisterContextPOSIX_loongarch64::GetRegisterInfoAtIndex(size_t reg) { + if (reg < GetRegisterCount()) + return &GetRegisterInfo()[reg]; + + return nullptr; +} + +size_t RegisterContextPOSIX_loongarch64::GetRegisterSetCount() { + return m_register_info_up->GetRegisterCount(); +} + +const lldb_private::RegisterSet * +RegisterContextPOSIX_loongarch64::GetRegisterSet(size_t set) { + return m_register_info_up->GetRegisterSet(set); +} + +const lldb_private::RegisterInfo * +RegisterContextPOSIX_loongarch64::GetRegisterInfo() { + return m_register_info_up->GetRegisterInfo(); +} + +bool RegisterContextPOSIX_loongarch64::IsGPR(unsigned int reg) { + return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_loongarch64::GPRegSet; +} + +bool RegisterContextPOSIX_loongarch64::IsFPR(unsigned int reg) { + return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) == + RegisterInfoPOSIX_loongarch64::FPRegSet; +} Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h +++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h @@ -23,6 +23,11 @@ GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch); public: + enum RegSetKind { + GPRegSet, + FPRegSet, + }; + struct GPR { uint64_t gpr[32]; Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.cpp +++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.cpp @@ -15,10 +15,23 @@ #include "RegisterInfoPOSIX_loongarch64.h" +#define GPR_OFFSET(idx) ((idx)*8 + 0) +#define FPR_OFFSET(idx) ((idx)*8 + sizeof(RegisterInfoPOSIX_loongarch64::GPR)) + +#define REG_CONTEXT_SIZE \ + (sizeof(RegisterInfoPOSIX_loongarch64::GPR) + \ + sizeof(RegisterInfoPOSIX_loongarch64::FPR)) + +#define DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT +#include "RegisterInfos_loongarch64.h" +#undef DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT + const lldb_private::RegisterInfo * RegisterInfoPOSIX_loongarch64::GetRegisterInfoPtr( const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { + case llvm::Triple::loongarch64: + return g_register_infos_loongarch64; default: assert(false && "Unhandled target architecture."); return nullptr; @@ -28,19 +41,85 @@ uint32_t RegisterInfoPOSIX_loongarch64::GetRegisterInfoCount( const lldb_private::ArchSpec &target_arch) { switch (target_arch.GetMachine()) { + case llvm::Triple::loongarch64: + return static_cast(sizeof(g_register_infos_loongarch64) / + sizeof(g_register_infos_loongarch64[0])); default: assert(false && "Unhandled target architecture."); return 0; } } +// Number of register sets provided by this context. +enum { + k_num_gpr_registers = gpr_last_loongarch - gpr_first_loongarch + 1, + k_num_fpr_registers = fpr_last_loongarch - fpr_first_loongarch + 1, + k_num_register_sets = 2 +}; + +// LoongArch64 general purpose registers. +static const uint32_t g_gpr_regnums_loongarch64[] = { + gpr_r0_loongarch, gpr_r1_loongarch, gpr_r2_loongarch, + gpr_r3_loongarch, gpr_r4_loongarch, gpr_r5_loongarch, + gpr_r6_loongarch, gpr_r7_loongarch, gpr_r8_loongarch, + gpr_r9_loongarch, gpr_r10_loongarch, gpr_r11_loongarch, + gpr_r12_loongarch, gpr_r13_loongarch, gpr_r14_loongarch, + gpr_r15_loongarch, gpr_r16_loongarch, gpr_r17_loongarch, + gpr_r18_loongarch, gpr_r19_loongarch, gpr_r20_loongarch, + gpr_r21_loongarch, gpr_r22_loongarch, gpr_r23_loongarch, + gpr_r24_loongarch, gpr_r25_loongarch, gpr_r26_loongarch, + gpr_r27_loongarch, gpr_r28_loongarch, gpr_r29_loongarch, + gpr_r30_loongarch, gpr_r31_loongarch, gpr_orig_a0_loongarch, + gpr_pc_loongarch, gpr_badv_loongarch, gpr_reserved0_loongarch, + gpr_reserved1_loongarch, gpr_reserved2_loongarch, gpr_reserved3_loongarch, + gpr_reserved4_loongarch, gpr_reserved5_loongarch, gpr_reserved6_loongarch, + gpr_reserved7_loongarch, gpr_reserved8_loongarch, gpr_reserved9_loongarch, + LLDB_INVALID_REGNUM}; + +static_assert(((sizeof g_gpr_regnums_loongarch64 / + sizeof g_gpr_regnums_loongarch64[0]) - + 1) == k_num_gpr_registers, + "g_gpr_regnums_loongarch64 has wrong number of register infos"); + +// LoongArch64 floating point registers. +static const uint32_t g_fpr_regnums_loongarch64[] = { + fpr_f0_loongarch, fpr_f1_loongarch, fpr_f2_loongarch, + fpr_f3_loongarch, fpr_f4_loongarch, fpr_f5_loongarch, + fpr_f6_loongarch, fpr_f7_loongarch, fpr_f8_loongarch, + fpr_f9_loongarch, fpr_f10_loongarch, fpr_f11_loongarch, + fpr_f12_loongarch, fpr_f13_loongarch, fpr_f14_loongarch, + fpr_f15_loongarch, fpr_f16_loongarch, fpr_f17_loongarch, + fpr_f18_loongarch, fpr_f19_loongarch, fpr_f20_loongarch, + fpr_f21_loongarch, fpr_f22_loongarch, fpr_f23_loongarch, + fpr_f24_loongarch, fpr_f25_loongarch, fpr_f26_loongarch, + fpr_f27_loongarch, fpr_f28_loongarch, fpr_f29_loongarch, + fpr_f30_loongarch, fpr_f31_loongarch, fpr_fcc0_loongarch, + fpr_fcc1_loongarch, fpr_fcc2_loongarch, fpr_fcc3_loongarch, + fpr_fcc4_loongarch, fpr_fcc5_loongarch, fpr_fcc6_loongarch, + fpr_fcc7_loongarch, fpr_fcsr_loongarch, LLDB_INVALID_REGNUM}; + +static_assert(((sizeof g_fpr_regnums_loongarch64 / + sizeof g_fpr_regnums_loongarch64[0]) - + 1) == k_num_fpr_registers, + "g_fpr_regnums_loongarch64 has wrong number of register infos"); + +// Register sets for LoongArch64. +static const lldb_private::RegisterSet + g_reg_sets_loongarch64[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers, + g_gpr_regnums_loongarch64}, + {"Floating Point Registers", "fpr", k_num_fpr_registers, + g_fpr_regnums_loongarch64}}; + RegisterInfoPOSIX_loongarch64::RegisterInfoPOSIX_loongarch64( const lldb_private::ArchSpec &target_arch, lldb_private::Flags flags) : lldb_private::RegisterInfoAndSetInterface(target_arch), m_register_info_p(GetRegisterInfoPtr(target_arch)), m_register_info_count(GetRegisterInfoCount(target_arch)) {} -uint32_t RegisterInfoPOSIX_loongarch64::GetRegisterCount() const { return 0; } +uint32_t RegisterInfoPOSIX_loongarch64::GetRegisterCount() const { + return m_register_info_count; +} size_t RegisterInfoPOSIX_loongarch64::GetGPRSize() const { return sizeof(struct RegisterInfoPOSIX_loongarch64::GPR); @@ -55,14 +134,23 @@ return m_register_info_p; } -size_t RegisterInfoPOSIX_loongarch64::GetRegisterSetCount() const { return 0; } +size_t RegisterInfoPOSIX_loongarch64::GetRegisterSetCount() const { + return k_num_register_sets - 1; +} size_t RegisterInfoPOSIX_loongarch64::GetRegisterSetFromRegisterIndex( uint32_t reg_index) const { + // coverity[unsigned_compare] + if (reg_index >= gpr_first_loongarch && reg_index <= gpr_last_loongarch) + return GPRegSet; + if (reg_index >= fpr_first_loongarch && reg_index <= fpr_last_loongarch) + return FPRegSet; return LLDB_INVALID_REGNUM; } const lldb_private::RegisterSet * RegisterInfoPOSIX_loongarch64::GetRegisterSet(size_t set_index) const { + if (set_index < GetRegisterSetCount()) + return &g_reg_sets_loongarch64[set_index]; return nullptr; } Index: lldb/source/Plugins/Process/Utility/RegisterInfos_loongarch64.h =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/Utility/RegisterInfos_loongarch64.h @@ -0,0 +1,157 @@ +//===-- RegisterInfos_loongarch64.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifdef DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT + +#include + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private.h" + +#include "Utility/LoongArch_DWARF_Registers.h" +#include "lldb-loongarch-register-enums.h" + +#ifndef GPR_OFFSET +#error GPR_OFFSET must be defined before including this header file +#endif + +#ifndef FPR_OFFSET +#error FPR_OFFSET must be defined before including this header file +#endif + +using namespace loongarch_dwarf; + +// clang-format off + +// I suppose EHFrame and DWARF are the same. +#define KIND_HELPER(reg, generic_kind) \ + { \ + loongarch_dwarf::dwarf_##reg, loongarch_dwarf::dwarf_##reg, generic_kind, \ + LLDB_INVALID_REGNUM, reg##_loongarch \ + } + +// Generates register kinds array for vector registers +#define GPR64_KIND(reg, generic_kind) KIND_HELPER(reg, generic_kind) + +// FPR register kinds array for vector registers +#define FPR64_KIND(reg, generic_kind) KIND_HELPER(reg, generic_kind) + +// Defines a 64-bit general purpose register +#define DEFINE_GPR64(reg, generic_kind) DEFINE_GPR64_ALT(reg, reg, generic_kind) + +// Defines a 64-bit general purpose register +#define DEFINE_GPR64_ALT(reg, alt, generic_kind) \ + { \ + #reg, #alt, 8, GPR_OFFSET(gpr_##reg##_loongarch - gpr_first_loongarch), \ + lldb::eEncodingUint, lldb::eFormatHex, \ + GPR64_KIND(gpr_##reg, generic_kind), nullptr, nullptr \ + } + +#define DEFINE_FPR64(reg, generic_kind) \ + { \ + #reg, nullptr, 8, FPR_OFFSET(fpr_##reg##_loongarch - fpr_first_loongarch), \ + lldb::eEncodingUint, lldb::eFormatHex, \ + FPR64_KIND(fpr_##reg, generic_kind), nullptr, nullptr \ + } + +// clang-format on + +static lldb_private::RegisterInfo g_register_infos_loongarch64[] = { + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64(r0, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(ra, r1, LLDB_REGNUM_GENERIC_RA), + DEFINE_GPR64(r2, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(sp, r3, LLDB_REGNUM_GENERIC_SP), + DEFINE_GPR64(r4, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GPR64(r5, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GPR64(r6, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GPR64(r7, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GPR64(r8, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GPR64(r9, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GPR64(r10, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GPR64(r11, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_GPR64(r12, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r13, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r14, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r15, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r16, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r17, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r18, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r19, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r20, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r21, LLDB_INVALID_REGNUM), + DEFINE_GPR64_ALT(fp, r22, LLDB_REGNUM_GENERIC_FP), + DEFINE_GPR64(r23, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r24, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r25, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r26, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r27, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r28, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r29, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r30, LLDB_INVALID_REGNUM), + DEFINE_GPR64(r31, LLDB_INVALID_REGNUM), + DEFINE_GPR64(orig_a0, LLDB_INVALID_REGNUM), + DEFINE_GPR64(pc, LLDB_REGNUM_GENERIC_PC), + DEFINE_GPR64(badv, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved0, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved1, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved2, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved3, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved4, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved5, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved6, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved7, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved8, LLDB_INVALID_REGNUM), + DEFINE_GPR64(reserved9, LLDB_INVALID_REGNUM), + + DEFINE_FPR64(f0, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f1, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f2, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f3, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f4, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f5, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f6, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f7, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f8, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f9, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f10, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f11, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f12, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f13, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f14, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f15, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f16, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f17, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f18, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f19, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f20, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f21, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f22, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f23, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f24, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f25, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f26, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f27, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f28, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f29, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f30, LLDB_INVALID_REGNUM), + DEFINE_FPR64(f31, LLDB_INVALID_REGNUM), + + DEFINE_FPR64(fcc0, LLDB_INVALID_REGNUM), + DEFINE_FPR64(fcc1, LLDB_INVALID_REGNUM), + DEFINE_FPR64(fcc2, LLDB_INVALID_REGNUM), + DEFINE_FPR64(fcc3, LLDB_INVALID_REGNUM), + DEFINE_FPR64(fcc4, LLDB_INVALID_REGNUM), + DEFINE_FPR64(fcc5, LLDB_INVALID_REGNUM), + DEFINE_FPR64(fcc6, LLDB_INVALID_REGNUM), + DEFINE_FPR64(fcc7, LLDB_INVALID_REGNUM), + DEFINE_FPR64(fcsr, LLDB_INVALID_REGNUM), +}; + +#endif // DECLARE_REGISTER_INFOS_LOONGARCH64_STRUCT Index: lldb/source/Plugins/Process/Utility/lldb-loongarch-register-enums.h =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/Utility/lldb-loongarch-register-enums.h @@ -0,0 +1,116 @@ +//===-- lldb-loongarch-register-enums.h -------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_LOONGARCH_REGISTER_ENUMS_H +#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_LOONGARCH_REGISTER_ENUMS_H + +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) + +// Internal codes for all loongarch registers. +enum { + // The same order as user_regs_struct in + // note: these enum values are used as byte_offset + gpr_first_loongarch = 0, + gpr_r0_loongarch = gpr_first_loongarch, + gpr_r1_loongarch, + gpr_r2_loongarch, + gpr_r3_loongarch, + gpr_r4_loongarch, + gpr_r5_loongarch, + gpr_r6_loongarch, + gpr_r7_loongarch, + gpr_r8_loongarch, + gpr_r9_loongarch, + gpr_r10_loongarch, + gpr_r11_loongarch, + gpr_r12_loongarch, + gpr_r13_loongarch, + gpr_r14_loongarch, + gpr_r15_loongarch, + gpr_r16_loongarch, + gpr_r17_loongarch, + gpr_r18_loongarch, + gpr_r19_loongarch, + gpr_r20_loongarch, + gpr_r21_loongarch, + gpr_r22_loongarch, + gpr_r23_loongarch, + gpr_r24_loongarch, + gpr_r25_loongarch, + gpr_r26_loongarch, + gpr_r27_loongarch, + gpr_r28_loongarch, + gpr_r29_loongarch, + gpr_r30_loongarch, + gpr_r31_loongarch, + gpr_orig_a0_loongarch, + gpr_pc_loongarch, + gpr_badv_loongarch, + gpr_reserved0_loongarch, + gpr_reserved1_loongarch, + gpr_reserved2_loongarch, + gpr_reserved3_loongarch, + gpr_reserved4_loongarch, + gpr_reserved5_loongarch, + gpr_reserved6_loongarch, + gpr_reserved7_loongarch, + gpr_reserved8_loongarch, + gpr_reserved9_loongarch, + gpr_last_loongarch = 44, + gpr_ra_loongarch = gpr_r1_loongarch, + gpr_sp_loongarch = gpr_r3_loongarch, + gpr_fp_loongarch = gpr_r22_loongarch, + + fpr_first_loongarch = 45, + fpr_f0_loongarch = fpr_first_loongarch, + fpr_f1_loongarch, + fpr_f2_loongarch, + fpr_f3_loongarch, + fpr_f4_loongarch, + fpr_f5_loongarch, + fpr_f6_loongarch, + fpr_f7_loongarch, + fpr_f8_loongarch, + fpr_f9_loongarch, + fpr_f10_loongarch, + fpr_f11_loongarch, + fpr_f12_loongarch, + fpr_f13_loongarch, + fpr_f14_loongarch, + fpr_f15_loongarch, + fpr_f16_loongarch, + fpr_f17_loongarch, + fpr_f18_loongarch, + fpr_f19_loongarch, + fpr_f20_loongarch, + fpr_f21_loongarch, + fpr_f22_loongarch, + fpr_f23_loongarch, + fpr_f24_loongarch, + fpr_f25_loongarch, + fpr_f26_loongarch, + fpr_f27_loongarch, + fpr_f28_loongarch, + fpr_f29_loongarch, + fpr_f30_loongarch, + fpr_f31_loongarch, + fpr_fcc0_loongarch, + fpr_fcc1_loongarch, + fpr_fcc2_loongarch, + fpr_fcc3_loongarch, + fpr_fcc4_loongarch, + fpr_fcc5_loongarch, + fpr_fcc6_loongarch, + fpr_fcc7_loongarch, + fpr_fcsr_loongarch, + fpr_last_loongarch = fpr_fcsr_loongarch, + + k_num_registers_loongarch +}; + +#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LLDB_LOONGARCH_REGISTER_ENUMS_H Index: lldb/source/Utility/LoongArch_DWARF_Registers.h =================================================================== --- /dev/null +++ lldb/source/Utility/LoongArch_DWARF_Registers.h @@ -0,0 +1,117 @@ +//===-- LoongArch_DWARF_Registers.h -----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_UTILITY_LOONGARCH_DWARF_REGISTERS_H +#define LLDB_SOURCE_UTILITY_LOONGARCH_DWARF_REGISTERS_H + +#include "lldb/lldb-private.h" + +namespace loongarch_dwarf { + +enum { + dwarf_gpr_r0 = 0, + dwarf_gpr_r1, + dwarf_gpr_r2, + dwarf_gpr_r3, + dwarf_gpr_r4, + dwarf_gpr_r5, + dwarf_gpr_r6, + dwarf_gpr_r7, + dwarf_gpr_r8, + dwarf_gpr_r9, + dwarf_gpr_r10, + dwarf_gpr_r11, + dwarf_gpr_r12, + dwarf_gpr_r13, + dwarf_gpr_r14, + dwarf_gpr_r15, + dwarf_gpr_r16, + dwarf_gpr_r17, + dwarf_gpr_r18, + dwarf_gpr_r19, + dwarf_gpr_r20, + dwarf_gpr_r21, + dwarf_gpr_r22, + dwarf_gpr_r23, + dwarf_gpr_r24, + dwarf_gpr_r25, + dwarf_gpr_r26, + dwarf_gpr_r27, + dwarf_gpr_r28, + dwarf_gpr_r29, + dwarf_gpr_r30, + dwarf_gpr_r31 = 31, + + dwarf_gpr_orig_a0, + dwarf_gpr_pc, + dwarf_gpr_badv, + + dwarf_gpr_reserved0 = 35, + dwarf_gpr_reserved1, + dwarf_gpr_reserved2, + dwarf_gpr_reserved3, + dwarf_gpr_reserved4, + dwarf_gpr_reserved5, + dwarf_gpr_reserved6, + dwarf_gpr_reserved7, + dwarf_gpr_reserved8, + dwarf_gpr_reserved9, + + dwarf_fpr_f0 = 45, + dwarf_fpr_f1, + dwarf_fpr_f2, + dwarf_fpr_f3, + dwarf_fpr_f4, + dwarf_fpr_f5, + dwarf_fpr_f6, + dwarf_fpr_f7, + dwarf_fpr_f8, + dwarf_fpr_f9, + dwarf_fpr_f10, + dwarf_fpr_f11, + dwarf_fpr_f12, + dwarf_fpr_f13, + dwarf_fpr_f14, + dwarf_fpr_f15, + dwarf_fpr_f16, + dwarf_fpr_f17, + dwarf_fpr_f18, + dwarf_fpr_f19, + dwarf_fpr_f20, + dwarf_fpr_f21, + dwarf_fpr_f22, + dwarf_fpr_f23, + dwarf_fpr_f24, + dwarf_fpr_f25, + dwarf_fpr_f26, + dwarf_fpr_f27, + dwarf_fpr_f28, + dwarf_fpr_f29, + dwarf_fpr_f30, + dwarf_fpr_f31 = 76, + + dwarf_fpr_fcc0, + dwarf_fpr_fcc1, + dwarf_fpr_fcc2, + dwarf_fpr_fcc3, + dwarf_fpr_fcc4, + dwarf_fpr_fcc5, + dwarf_fpr_fcc6, + dwarf_fpr_fcc7, + dwarf_fpr_fcsr, + + // register name alias + dwarf_gpr_ra = dwarf_gpr_r1, + dwarf_gpr_sp = dwarf_gpr_r3, + dwarf_gpr_fp = dwarf_gpr_r22, + +}; + +} // namespace loongarch_dwarf + +#endif // LLDB_SOURCE_UTILITY_LOONGARCH_DWARF_REGISTERS_H