| //===----------------------------------------------------------------------===// | |
| // | |
| // 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 "RegisterInfoPOSIXDynamic_riscv32.h" | |
| #include "lldb-riscv-register-enums.h" | |
| #include "lldb/lldb-defines.h" | |
| #include "llvm/ADT/StringMap.h" | |
| #include "llvm/Support/Compiler.h" | |
| #include <stddef.h> | |
| #define GPR_OFFSET(idx) ((idx) * sizeof(uint32_t)) | |
| #define FPR_OFFSET(idx) ((idx) * sizeof(uint32_t)) | |
| #define DECLARE_REGISTER_INFOS_RISCV32_STRUCT | |
| #include "Plugins/Process/Utility/RegisterInfos_riscv32.h" | |
| #undef DECLARE_REGISTER_INFOS_RISCV32_STRUCT | |
| RegisterInfoPOSIXDynamic_riscv32::RegisterInfoPOSIXDynamic_riscv32( | |
| const lldb_private::ArchSpec &target_arch) | |
| : lldb_private::RegisterInfoAndSetInterface(target_arch), | |
| m_target_arch(target_arch) {} | |
| uint32_t RegisterInfoPOSIXDynamic_riscv32::GetRegisterCount() const { | |
| return m_dyn_reg_infos.GetNumRegisters(); | |
| } | |
| size_t RegisterInfoPOSIXDynamic_riscv32::GetGPRSize() const { | |
| for (uint32_t set_idx = 0; set_idx < GetRegisterSetCount(); ++set_idx) { | |
| const lldb_private::RegisterSet *set = | |
| m_dyn_reg_infos.GetRegisterSet(set_idx); | |
| if (strcmp(set->name, "GPR") == 0) | |
| return set->num_registers; | |
| } | |
| return 0; | |
| } | |
| size_t RegisterInfoPOSIXDynamic_riscv32::GetFPRSize() const { | |
| for (uint32_t set_idx = 0; set_idx < GetRegisterSetCount(); ++set_idx) { | |
| const lldb_private::RegisterSet *set = | |
| m_dyn_reg_infos.GetRegisterSet(set_idx); | |
| if (strcmp(set->name, "FPR") == 0) | |
| return set->num_registers; | |
| } | |
| return 0; | |
| } | |
| const lldb_private::RegisterInfo * | |
| RegisterInfoPOSIXDynamic_riscv32::GetRegisterInfo() const { | |
| return &*m_dyn_reg_infos | |
| .registers<lldb_private::DynamicRegisterInfo:: | |
| reg_collection_const_range>() | |
| .begin(); | |
| } | |
| size_t RegisterInfoPOSIXDynamic_riscv32::GetRegisterSetCount() const { | |
| return m_dyn_reg_infos.GetNumRegisterSets(); | |
| } | |
| size_t RegisterInfoPOSIXDynamic_riscv32::GetRegisterSetFromRegisterIndex( | |
| uint32_t reg_index) const { | |
| for (size_t set_index = 0; set_index < m_dyn_reg_infos.GetNumRegisterSets(); | |
| ++set_index) { | |
| const lldb_private::RegisterSet *reg_set = | |
| m_dyn_reg_infos.GetRegisterSet(set_index); | |
| for (uint32_t idx = 0; idx < reg_set->num_registers; ++idx) | |
| if (reg_set->registers[idx] == reg_index) | |
| return set_index; | |
| } | |
| return LLDB_INVALID_REGNUM; | |
| } | |
| const lldb_private::RegisterSet * | |
| RegisterInfoPOSIXDynamic_riscv32::GetRegisterSet(size_t set_index) const { | |
| if (set_index < GetRegisterSetCount()) | |
| return m_dyn_reg_infos.GetRegisterSet(set_index); | |
| return nullptr; | |
| } | |
| size_t RegisterInfoPOSIXDynamic_riscv32::SetRegisterInfo( | |
| std::vector<lldb_private::DynamicRegisterInfo::Register> regs) { | |
| return m_dyn_reg_infos.SetRegisterInfo(std::move(regs), m_target_arch); | |
| } | |
| const lldb_private::RegisterInfo * | |
| RegisterInfoPOSIXDynamic_riscv32::GetRegisterInfo( | |
| llvm::StringRef reg_name) const { | |
| return m_dyn_reg_infos.GetRegisterInfo(reg_name); | |
| } | |
| void RegisterInfoPOSIXDynamic_riscv32::BuildCSRegInfos( | |
| llvm::ArrayRef<std::string> features, | |
| llvm::SmallVectorImpl<lldb_private::RegisterInfo> &cs_reg_infos) { | |
| cs_reg_infos.clear(); | |
| // Sort and deduplicate to make the list independent of caller ordering. | |
| llvm::SmallVector<llvm::StringRef> normalized_features(features.begin(), | |
| features.end()); | |
| llvm::sort(normalized_features); | |
| normalized_features.erase(llvm::unique(normalized_features), | |
| normalized_features.end()); | |
| const uint32_t k_num_csr_registers = csr_last_riscv - csr_first_riscv + 1; | |
| cs_reg_infos.reserve(k_num_csr_registers); | |
| // Construct default CS register information. CS register information entries | |
| // are stored in CSR-address order. | |
| for (uint32_t reg = 0; reg < k_num_csr_registers; ++reg) { | |
| lldb_private::RegisterInfo csr{}; | |
| for (auto &kind : csr.kinds) | |
| kind = LLDB_INVALID_REGNUM; | |
| lldb_private::ConstString name(llvm::formatv("csr_{0:x}", reg).str()); | |
| csr.name = name.GetCString(); | |
| csr.alt_name = csr.name; | |
| csr.byte_size = 4; | |
| csr.byte_offset = 0; | |
| csr.encoding = lldb::eEncodingUint; | |
| csr.format = lldb::eFormatHex; | |
| csr.kinds[lldb::eRegisterKindEHFrame] = riscv_dwarf::dwarf_first_csr + reg; | |
| csr.kinds[lldb::eRegisterKindDWARF] = riscv_dwarf::dwarf_first_csr + reg; | |
| csr.kinds[lldb::eRegisterKindGeneric] = LLDB_INVALID_REGNUM; | |
| csr.kinds[lldb::eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM; | |
| csr.kinds[lldb::eRegisterKindLLDB] = csr_first_riscv + reg; | |
| csr.value_regs = nullptr; | |
| csr.invalidate_regs = nullptr; | |
| csr.register_type = nullptr; | |
| cs_reg_infos.push_back(csr); | |
| } | |
| // Patch application is order-dependent; later patches override earlier ones | |
| // for the same CSR address. | |
| ConfigureCSRegInfos("default", cs_reg_infos); | |
| for (const auto &feature : normalized_features) | |
| ConfigureCSRegInfos(feature, cs_reg_infos); | |
| } | |
| void RegisterInfoPOSIXDynamic_riscv32::ConfigureCSRegInfos( | |
| llvm::StringRef feature, | |
| llvm::SmallVectorImpl<lldb_private::RegisterInfo> &cs_reg_infos) { | |
| // Initialized on first use so that the patch set does not depend on the | |
| // initialization order of globals in other translation units. | |
| static const llvm::StringMap<llvm::ArrayRef<lldb_private::RegisterInfo>> | |
| g_register_infos_riscv32_csr_patches = { | |
| {"default", llvm::ArrayRef(g_register_infos_riscv32_csr_patch)}, | |
| {"xqci", llvm::ArrayRef(g_register_infos_riscv32_csr_xqci_patch)}, | |
| {"xqciint", | |
| llvm::ArrayRef(g_register_infos_riscv32_csr_xqciint_patch)}}; | |
| auto it = g_register_infos_riscv32_csr_patches.find(feature); | |
| if (it == g_register_infos_riscv32_csr_patches.end()) | |
| return; | |
| for (const auto &csr : it->second) { | |
| const uint32_t lldb_reg = csr.kinds[lldb::eRegisterKindLLDB]; | |
| if (lldb_reg < csr_first_riscv || lldb_reg > csr_last_riscv) | |
| continue; | |
| uint32_t idx = lldb_reg - csr_first_riscv; | |
| if (idx < cs_reg_infos.size()) | |
| cs_reg_infos[idx] = csr; | |
| } | |
| } |