Index: lldb/include/lldb/Target/RegisterContext.h =================================================================== --- lldb/include/lldb/Target/RegisterContext.h +++ lldb/include/lldb/Target/RegisterContext.h @@ -140,8 +140,8 @@ virtual Thread &GetThread() { return m_thread; } - const RegisterInfo *GetRegisterInfoByName(llvm::StringRef reg_name, - uint32_t start_idx = 0); + virtual const RegisterInfo *GetRegisterInfoByName(llvm::StringRef reg_name, + uint32_t start_idx = 0); const RegisterInfo *GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num); Index: lldb/source/Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h =================================================================== --- lldb/source/Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h +++ lldb/source/Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h @@ -6,9 +6,20 @@ // //===----------------------------------------------------------------------===// +#ifdef INCLUDE_LINUX_PTRACE_DEFINITIONS_FOR_SVE_ARM64 + #ifndef lldb_LinuxPTraceDefines_arm64sve_h #define lldb_LinuxPTraceDefines_arm64sve_h +#include + +#if !defined(__arm64__) && !defined(__aarch64__) +struct _aarch64_ctx { + __u32 magic; + __u32 size; +}; +#endif + #define SVE_MAGIC 0x53564501 struct sve_context { @@ -251,3 +262,4 @@ : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags)) #endif +#endif Index: lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h =================================================================== --- lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h +++ lldb/source/Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h @@ -33,6 +33,10 @@ const RegisterInfoInterface &GetRegisterInfoInterface() const; + uint32_t SetRegisterInfoMode(uint32_t mode) { + return m_register_info_interface_up->SetRegisterInfoMode(mode); + } + private: std::unique_ptr m_register_info_interface_up; }; Index: lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h +++ lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h @@ -44,11 +44,16 @@ const char *GetRegisterName(unsigned reg); + const lldb_private::RegisterInfo * + GetRegisterInfoByName(llvm::StringRef reg_name, + uint32_t start_idx = 0) override; + protected: struct RegInfo { uint32_t num_registers; uint32_t num_gpr_registers; uint32_t num_fpr_registers; + uint32_t num_sve_registers; uint32_t last_gpr; uint32_t first_fpr; @@ -57,6 +62,9 @@ uint32_t first_fpr_v; uint32_t last_fpr_v; + uint32_t first_sve; + uint32_t last_sve; + uint32_t gpr_flags; }; @@ -82,6 +90,7 @@ std::unique_ptr m_register_info_up; // Register Info Interface (FreeBSD or Linux) + bool m_sve_enabled; // Determines if an extended register set is supported on the processor // running the inferior process. virtual bool IsRegisterSetAvailable(size_t set_index); @@ -92,6 +101,14 @@ bool IsFPR(unsigned reg); + bool IsSVE(unsigned reg) const; + + bool IsSVEZReg(unsigned reg) const; + + bool IsSVEPReg(unsigned reg) const; + + bool IsSVERegVG(unsigned reg) const; + virtual bool ReadGPR() = 0; virtual bool ReadFPR() = 0; virtual bool WriteGPR() = 0; Index: lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -83,15 +83,43 @@ 1) == k_num_fpr_registers_arm64, "g_fpu_regnums_arm64 has wrong number of register infos"); +// ARM64 SVE registers. +static const uint32_t g_sve_regnums_arm64[] = { + sve_vg_arm64, + + sve_z0_arm64, sve_z1_arm64, sve_z2_arm64, sve_z3_arm64, + sve_z4_arm64, sve_z5_arm64, sve_z6_arm64, sve_z7_arm64, + sve_z8_arm64, sve_z9_arm64, sve_z10_arm64, sve_z11_arm64, + sve_z12_arm64, sve_z13_arm64, sve_z14_arm64, sve_z15_arm64, + sve_z16_arm64, sve_z17_arm64, sve_z18_arm64, sve_z19_arm64, + sve_z20_arm64, sve_z21_arm64, sve_z22_arm64, sve_z23_arm64, + sve_z24_arm64, sve_z25_arm64, sve_z26_arm64, sve_z27_arm64, + sve_z28_arm64, sve_z29_arm64, sve_z30_arm64, sve_z31_arm64, + + sve_p0_arm64, sve_p1_arm64, sve_p2_arm64, sve_p3_arm64, + sve_p4_arm64, sve_p5_arm64, sve_p6_arm64, sve_p7_arm64, + sve_p8_arm64, sve_p9_arm64, sve_p10_arm64, sve_p11_arm64, + sve_p12_arm64, sve_p13_arm64, sve_p14_arm64, sve_p15_arm64, + + sve_ffr_arm64, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert(((sizeof g_sve_regnums_arm64 / sizeof g_sve_regnums_arm64[0]) - + 1) == k_num_sve_registers_arm64, + "g_sve_regnums_arm64 has wrong number of register infos"); + +namespace { // Number of register sets provided by this context. -enum { k_num_register_sets = 2 }; +enum { k_num_register_sets = 3 }; +} // namespace // Register sets for ARM64. static const lldb_private::RegisterSet g_reg_sets_arm64[k_num_register_sets] = { {"General Purpose Registers", "gpr", k_num_gpr_registers_arm64, g_gpr_regnums_arm64}, {"Floating Point Registers", "fpu", k_num_fpr_registers_arm64, - g_fpu_regnums_arm64}}; + g_fpu_regnums_arm64}, + {"SVE Registers", "sve", k_num_sve_registers_arm64, g_sve_regnums_arm64}}; bool RegisterContextPOSIX_arm64::IsGPR(unsigned reg) { return reg <= m_reg_info.last_gpr; // GPR's come first. @@ -101,6 +129,46 @@ return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } +bool RegisterContextPOSIX_arm64::IsSVE(unsigned reg) const { + return (m_reg_info.first_sve <= reg && reg <= m_reg_info.last_sve); +} + +bool RegisterContextPOSIX_arm64::IsSVEZReg(unsigned reg) const { + return (sve_z0_arm64 <= reg && reg <= sve_z31_arm64); +} + +bool RegisterContextPOSIX_arm64::IsSVEPReg(unsigned reg) const { + return (sve_p0_arm64 <= reg && reg <= sve_p15_arm64); +} + +bool RegisterContextPOSIX_arm64::IsSVERegVG(unsigned reg) const { + return (m_reg_info.first_sve == reg); +} + +const lldb_private::RegisterInfo * +RegisterContextPOSIX_arm64::GetRegisterInfoByName(llvm::StringRef reg_name, + uint32_t start_idx) { + if (reg_name.empty()) + return nullptr; + + uint32_t num_register_sets = GetRegisterSetCount(); + for (uint32_t set_idx = 0; set_idx < num_register_sets; ++set_idx) { + const RegisterSet *const reg_set = GetRegisterSet(set_idx); + const size_t num_registers = reg_set->num_registers; + + for (size_t reg_idx = 0; reg_idx < num_registers; ++reg_idx) { + const uint32_t reg = reg_set->registers[reg_idx]; + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); + + if (reg_name.equals_lower(reg_info->name) || + reg_name.equals_lower(reg_info->alt_name)) + return reg_info; + } + } + + return nullptr; +} + RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64( lldb_private::Thread &thread, uint32_t concrete_frame_idx, lldb_private::RegisterInfoInterface *register_info) @@ -113,18 +181,23 @@ m_reg_info.num_registers = k_num_registers_arm64; m_reg_info.num_gpr_registers = k_num_gpr_registers_arm64; m_reg_info.num_fpr_registers = k_num_fpr_registers_arm64; + m_reg_info.num_sve_registers = k_num_sve_registers_arm64; + m_reg_info.last_gpr = k_last_gpr_arm64; m_reg_info.first_fpr = k_first_fpr_arm64; m_reg_info.last_fpr = k_last_fpr_arm64; m_reg_info.first_fpr_v = fpu_v0_arm64; m_reg_info.last_fpr_v = fpu_v31_arm64; m_reg_info.gpr_flags = gpr_cpsr_arm64; + m_reg_info.first_sve = sve_vg_arm64; + m_reg_info.last_sve = sve_ffr_arm64; break; default: assert(false && "Unhandled target architecture."); break; } + m_sve_enabled = false; ::memset(&m_fpr, 0, sizeof m_fpr); } @@ -147,6 +220,8 @@ size_t RegisterContextPOSIX_arm64::GetRegisterCount() { size_t num_registers = m_reg_info.num_gpr_registers + m_reg_info.num_fpr_registers; + if (m_sve_enabled) + return num_registers + m_reg_info.num_sve_registers; return num_registers; } @@ -181,7 +256,10 @@ } bool RegisterContextPOSIX_arm64::IsRegisterSetAvailable(size_t set_index) { - return set_index < k_num_register_sets; + if (m_sve_enabled) + return set_index < k_num_register_sets; + else + return set_index < (k_num_register_sets - 1); } const lldb_private::RegisterSet * Index: lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -61,6 +61,13 @@ return nullptr; } + virtual uint32_t SetRegisterInfoMode(uint32_t mode, uint32_t offset = 0) { + return 0; + } + + virtual uint32_t GetRegisterInfoMode() const { return 0; } + +public: // FIXME make private. lldb_private::ArchSpec m_target_arch; }; Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h +++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h @@ -12,6 +12,14 @@ #include "RegisterInfoInterface.h" #include "lldb/Target/RegisterContext.h" #include "lldb/lldb-private.h" +#include + +// AArch64 Register set FP/SIMD feature configuration +enum { + eRegisterInfoModeAArch64, + eRegisterInfoModeAArch64SVE, + eRegisterInfoModeAArch64SVEMax = 256 +}; class RegisterInfoPOSIX_arm64 : public lldb_private::RegisterInfoInterface { public: @@ -61,7 +69,26 @@ uint32_t GetRegisterCount() const override; + uint32_t SetRegisterInfoMode(uint32_t mode, uint32_t offset = 0) override; + + uint32_t GetRegisterInfoMode() const override; + + bool RegisterInfoModeIsValid(uint32_t mode) { + if (mode >= eRegisterInfoModeAArch64 && + mode <= eRegisterInfoModeAArch64SVEMax) + return true; + return false; + } + private: + typedef std::vector dynamic_register_infos; + typedef std::map per_mode_register_infos; + + dynamic_register_infos m_dynamic_register_infos = {}; + per_mode_register_infos m_per_vl_reg_infos; + + uint32_t m_reg_info_mode = eRegisterInfoModeAArch64; + const lldb_private::RegisterInfo *m_register_info_p; uint32_t m_register_info_count; }; Index: lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -25,10 +25,29 @@ (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm64::FPU, reg) + \ sizeof(RegisterInfoPOSIX_arm64::GPR)) +// This information is based on AArch64 with SVE architecture reference manual. +// AArch64 with SVE has 32 Z and 16 P vector registers. There is also an FFR +// (First Fault) register and a VG (Vector Granule) pseudo register. + +// SVE 16-byte quad word is the basic unit of expansion in vector length. +#define SVE_QUAD_WORD_BYTES 16 + +// Vector length is the multiplier which decides the no of quad words, +// (multiples of 128-bits or 16-bytes) present in a Z register. Vector length +// is decided during execution and can change at runtime. SVE AArch64 register +// infos have modes one for each valid value of vector length. A change in +// vector length requires register context to update sizes of SVE Z, P and FFR. +// Also register context needs to update byte offsets of all registers affected +// by the change in vector length. +#define SVE_REGS_DEFAULT_OFFSET_LINUX sizeof(RegisterInfoPOSIX_arm64::GPR) + +#define SVE_OFFSET_VG SVE_REGS_DEFAULT_OFFSET_LINUX + #define EXC_OFFSET_NAME(reg) \ (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm64::EXC, reg) + \ sizeof(RegisterInfoPOSIX_arm64::GPR) + \ sizeof(RegisterInfoPOSIX_arm64::FPU)) + #define DBG_OFFSET_NAME(reg) \ (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm64::DBG, reg) + \ sizeof(RegisterInfoPOSIX_arm64::GPR) + \ @@ -51,6 +70,7 @@ // Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure. #define DECLARE_REGISTER_INFOS_ARM64_STRUCT #include "RegisterInfos_arm64.h" +#include "RegisterInfos_arm64_sve.h" #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT static const lldb_private::RegisterInfo * @@ -96,3 +116,87 @@ uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const { return m_register_info_count; } + +uint32_t RegisterInfoPOSIX_arm64::SetRegisterInfoMode(uint32_t mode, + uint32_t offset) { + // Register info mode denotes SVE vector length in context of AArch64. + // Register info mode once set to zero permanently selects default static + // AArch64 register info and cannot be changed to SVE. Also if an invalid + // or previously set vector length is passed to this function then it will + // exit immediately with previously set vector length. + if (!RegisterInfoModeIsValid(mode) || m_reg_info_mode == mode) + return m_reg_info_mode; + + if (mode == eRegisterInfoModeAArch64 && + m_reg_info_mode > eRegisterInfoModeAArch64) + mode = eRegisterInfoModeAArch64SVE; + + m_reg_info_mode = mode; + + if (mode == eRegisterInfoModeAArch64) { + m_register_info_count = + static_cast(sizeof(g_register_infos_arm64_le) / + sizeof(g_register_infos_arm64_le[0])); + m_register_info_p = g_register_infos_arm64_le; + + return m_reg_info_mode; + } + + m_dynamic_register_infos.clear(); + + m_register_info_count = + static_cast(sizeof(g_register_infos_arm64_sve_le) / + sizeof(g_register_infos_arm64_sve_le[0])); + + if (m_per_vl_reg_infos.count(mode)) { + m_dynamic_register_infos = m_per_vl_reg_infos.at(mode); + m_register_info_p = &m_dynamic_register_infos[0]; + return m_reg_info_mode; + } + + m_dynamic_register_infos = std::vector( + g_register_infos_arm64_sve_le, + g_register_infos_arm64_sve_le + m_register_info_count); + m_register_info_p = &m_dynamic_register_infos[0]; + + if (!offset) + offset = SVE_REGS_DEFAULT_OFFSET_LINUX; + + m_dynamic_register_infos[sve_vg].byte_offset = offset; + offset += m_dynamic_register_infos[sve_vg].byte_size; + + // Update Z registers size and offset + uint32_t s_reg_base = fpu_s0; + uint32_t d_reg_base = fpu_d0; + uint32_t v_reg_base = fpu_v0; + uint32_t z_reg_base = sve_z0; + + for (uint32_t index = 0; index < 32; index++) { + m_dynamic_register_infos[s_reg_base + index].byte_offset = offset; + m_dynamic_register_infos[d_reg_base + index].byte_offset = offset; + m_dynamic_register_infos[v_reg_base + index].byte_offset = offset; + m_dynamic_register_infos[z_reg_base + index].byte_offset = offset; + + m_dynamic_register_infos[z_reg_base + index].byte_size = + mode * SVE_QUAD_WORD_BYTES; + offset += m_dynamic_register_infos[z_reg_base + index].byte_size; + } + + // Update P registers and FFR size and offset + for (uint32_t it = sve_p0; it <= sve_ffr; it++) { + m_dynamic_register_infos[it].byte_offset = offset; + m_dynamic_register_infos[it].byte_size = mode * SVE_QUAD_WORD_BYTES / 8; + offset += m_dynamic_register_infos[it].byte_size; + } + + m_dynamic_register_infos[fpu_fpsr].byte_offset = offset; + m_dynamic_register_infos[fpu_fpcr].byte_offset = offset + 4; + + m_per_vl_reg_infos.insert(std::make_pair(mode, m_dynamic_register_infos)); + + return m_reg_info_mode; +} + +uint32_t RegisterInfoPOSIX_arm64::GetRegisterInfoMode() const { + return m_reg_info_mode; +} Index: lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -294,7 +294,7 @@ dbg_wcr14, dbg_wcr15, - k_num_registers + k_num_registers, }; static uint32_t g_contained_x0[] = {gpr_x0, LLDB_INVALID_REGNUM}; Index: lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h @@ -0,0 +1,640 @@ +//===-- RegisterInfos_arm64_sve.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_ARM64_STRUCT + +enum { + sve_fpsr = fpu_fpsr, + sve_fpcr = fpu_fpcr, + + sve_vg = exc_far, + + sve_z0, + sve_z1, + sve_z2, + sve_z3, + sve_z4, + sve_z5, + sve_z6, + sve_z7, + sve_z8, + sve_z9, + sve_z10, + sve_z11, + sve_z12, + sve_z13, + sve_z14, + sve_z15, + sve_z16, + sve_z17, + sve_z18, + sve_z19, + sve_z20, + sve_z21, + sve_z22, + sve_z23, + sve_z24, + sve_z25, + sve_z26, + sve_z27, + sve_z28, + sve_z29, + sve_z30, + sve_z31, + + sve_p0, + sve_p1, + sve_p2, + sve_p3, + sve_p4, + sve_p5, + sve_p6, + sve_p7, + sve_p8, + sve_p9, + sve_p10, + sve_p11, + sve_p12, + sve_p13, + sve_p14, + sve_p15, + + sve_ffr, +}; + +#ifndef SVE_OFFSET_VG +#error SVE_OFFSET_VG must be defined before including this header file +#endif + +static uint32_t g_sve_s0_invalidates[] = {sve_z0, fpu_v0, fpu_d0, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s1_invalidates[] = {sve_z1, fpu_v1, fpu_d1, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s2_invalidates[] = {sve_z2, fpu_v2, fpu_d2, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s3_invalidates[] = {sve_z3, fpu_v3, fpu_d3, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s4_invalidates[] = {sve_z4, fpu_v4, fpu_d4, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s5_invalidates[] = {sve_z5, fpu_v5, fpu_d5, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s6_invalidates[] = {sve_z6, fpu_v6, fpu_d6, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s7_invalidates[] = {sve_z7, fpu_v7, fpu_d7, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s8_invalidates[] = {sve_z8, fpu_v8, fpu_d8, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s9_invalidates[] = {sve_z9, fpu_v9, fpu_d9, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s10_invalidates[] = {sve_z10, fpu_v10, fpu_d10, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s11_invalidates[] = {sve_z11, fpu_v11, fpu_d11, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s12_invalidates[] = {sve_z12, fpu_v12, fpu_d12, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s13_invalidates[] = {sve_z13, fpu_v13, fpu_d13, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s14_invalidates[] = {sve_z14, fpu_v14, fpu_d14, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s15_invalidates[] = {sve_z15, fpu_v15, fpu_d15, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s16_invalidates[] = {sve_z16, fpu_v16, fpu_d16, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s17_invalidates[] = {sve_z17, fpu_v17, fpu_d17, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s18_invalidates[] = {sve_z18, fpu_v18, fpu_d18, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s19_invalidates[] = {sve_z19, fpu_v19, fpu_d19, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s20_invalidates[] = {sve_z20, fpu_v20, fpu_d20, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s21_invalidates[] = {sve_z21, fpu_v21, fpu_d21, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s22_invalidates[] = {sve_z22, fpu_v22, fpu_d22, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s23_invalidates[] = {sve_z23, fpu_v23, fpu_d23, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s24_invalidates[] = {sve_z24, fpu_v24, fpu_d24, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s25_invalidates[] = {sve_z25, fpu_v25, fpu_d25, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s26_invalidates[] = {sve_z26, fpu_v26, fpu_d26, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s27_invalidates[] = {sve_z27, fpu_v27, fpu_d27, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s28_invalidates[] = {sve_z28, fpu_v28, fpu_d28, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s29_invalidates[] = {sve_z29, fpu_v29, fpu_d29, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s30_invalidates[] = {sve_z30, fpu_v30, fpu_d30, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_s31_invalidates[] = {sve_z31, fpu_v31, fpu_d31, + LLDB_INVALID_REGNUM}; + +static uint32_t g_sve_d0_invalidates[] = {sve_z0, fpu_v0, fpu_s0, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d1_invalidates[] = {sve_z1, fpu_v1, fpu_s1, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d2_invalidates[] = {sve_z2, fpu_v2, fpu_s2, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d3_invalidates[] = {sve_z3, fpu_v3, fpu_s3, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d4_invalidates[] = {sve_z4, fpu_v4, fpu_s4, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d5_invalidates[] = {sve_z5, fpu_v5, fpu_s5, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d6_invalidates[] = {sve_z6, fpu_v6, fpu_s6, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d7_invalidates[] = {sve_z7, fpu_v7, fpu_s7, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d8_invalidates[] = {sve_z8, fpu_v8, fpu_s8, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d9_invalidates[] = {sve_z9, fpu_v9, fpu_s9, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d10_invalidates[] = {sve_z10, fpu_v10, fpu_s10, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d11_invalidates[] = {sve_z11, fpu_v11, fpu_s11, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d12_invalidates[] = {sve_z12, fpu_v12, fpu_s12, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d13_invalidates[] = {sve_z13, fpu_v13, fpu_s13, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d14_invalidates[] = {sve_z14, fpu_v14, fpu_s14, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d15_invalidates[] = {sve_z15, fpu_v15, fpu_s15, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d16_invalidates[] = {sve_z16, fpu_v16, fpu_s16, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d17_invalidates[] = {sve_z17, fpu_v17, fpu_s17, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d18_invalidates[] = {sve_z18, fpu_v18, fpu_s18, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d19_invalidates[] = {sve_z19, fpu_v19, fpu_s19, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d20_invalidates[] = {sve_z20, fpu_v20, fpu_s20, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d21_invalidates[] = {sve_z21, fpu_v21, fpu_s21, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d22_invalidates[] = {sve_z22, fpu_v22, fpu_s22, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d23_invalidates[] = {sve_z23, fpu_v23, fpu_s23, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d24_invalidates[] = {sve_z24, fpu_v24, fpu_s24, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d25_invalidates[] = {sve_z25, fpu_v25, fpu_s25, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d26_invalidates[] = {sve_z26, fpu_v26, fpu_s26, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d27_invalidates[] = {sve_z27, fpu_v27, fpu_s27, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d28_invalidates[] = {sve_z28, fpu_v28, fpu_s28, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d29_invalidates[] = {sve_z29, fpu_v29, fpu_s29, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d30_invalidates[] = {sve_z30, fpu_v30, fpu_s30, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_d31_invalidates[] = {sve_z31, fpu_v31, fpu_s31, + LLDB_INVALID_REGNUM}; + +static uint32_t g_sve_v0_invalidates[] = {sve_z0, fpu_d0, fpu_s0, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v1_invalidates[] = {sve_z1, fpu_d1, fpu_s1, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v2_invalidates[] = {sve_z2, fpu_d2, fpu_s2, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v3_invalidates[] = {sve_z3, fpu_d3, fpu_s3, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v4_invalidates[] = {sve_z4, fpu_d4, fpu_s4, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v5_invalidates[] = {sve_z5, fpu_d5, fpu_s5, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v6_invalidates[] = {sve_z6, fpu_d6, fpu_s6, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v7_invalidates[] = {sve_z7, fpu_d7, fpu_s7, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v8_invalidates[] = {sve_z8, fpu_d8, fpu_s8, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v9_invalidates[] = {sve_z9, fpu_d9, fpu_s9, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v10_invalidates[] = {sve_z10, fpu_d10, fpu_s10, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v11_invalidates[] = {sve_z11, fpu_d11, fpu_s11, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v12_invalidates[] = {sve_z12, fpu_d12, fpu_s12, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v13_invalidates[] = {sve_z13, fpu_d13, fpu_s13, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v14_invalidates[] = {sve_z14, fpu_d14, fpu_s14, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v15_invalidates[] = {sve_z15, fpu_d15, fpu_s15, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v16_invalidates[] = {sve_z16, fpu_d16, fpu_s16, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v17_invalidates[] = {sve_z17, fpu_d17, fpu_s17, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v18_invalidates[] = {sve_z18, fpu_d18, fpu_s18, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v19_invalidates[] = {sve_z19, fpu_d19, fpu_s19, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v20_invalidates[] = {sve_z20, fpu_d20, fpu_s20, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v21_invalidates[] = {sve_z21, fpu_d21, fpu_s21, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v22_invalidates[] = {sve_z22, fpu_d22, fpu_s22, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v23_invalidates[] = {sve_z23, fpu_d23, fpu_s23, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v24_invalidates[] = {sve_z24, fpu_d24, fpu_s24, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v25_invalidates[] = {sve_z25, fpu_d25, fpu_s25, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v26_invalidates[] = {sve_z26, fpu_d26, fpu_s26, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v27_invalidates[] = {sve_z27, fpu_d27, fpu_s27, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v28_invalidates[] = {sve_z28, fpu_d28, fpu_s28, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v29_invalidates[] = {sve_z29, fpu_d29, fpu_s29, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v30_invalidates[] = {sve_z30, fpu_d30, fpu_s30, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_v31_invalidates[] = {sve_z31, fpu_d31, fpu_s31, + LLDB_INVALID_REGNUM}; + +static uint32_t g_sve_z0_invalidates[] = {fpu_v0, fpu_d0, fpu_s0, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z1_invalidates[] = {fpu_v1, fpu_d1, fpu_s1, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z2_invalidates[] = {fpu_v2, fpu_d2, fpu_s2, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z3_invalidates[] = {fpu_v3, fpu_d3, fpu_s3, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z4_invalidates[] = {fpu_v4, fpu_d4, fpu_s4, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z5_invalidates[] = {fpu_v5, fpu_d5, fpu_s5, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z6_invalidates[] = {fpu_v6, fpu_d6, fpu_s6, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z7_invalidates[] = {fpu_v7, fpu_d7, fpu_s7, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z8_invalidates[] = {fpu_v8, fpu_d8, fpu_s8, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z9_invalidates[] = {fpu_v9, fpu_d9, fpu_s9, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z10_invalidates[] = {fpu_v10, fpu_d10, fpu_s10, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z11_invalidates[] = {fpu_v11, fpu_d11, fpu_s11, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z12_invalidates[] = {fpu_v12, fpu_d12, fpu_s12, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z13_invalidates[] = {fpu_v13, fpu_d13, fpu_s13, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z14_invalidates[] = {fpu_v14, fpu_d14, fpu_s14, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z15_invalidates[] = {fpu_v15, fpu_d15, fpu_s15, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z16_invalidates[] = {fpu_v16, fpu_d16, fpu_s16, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z17_invalidates[] = {fpu_v17, fpu_d17, fpu_s17, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z18_invalidates[] = {fpu_v18, fpu_d18, fpu_s18, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z19_invalidates[] = {fpu_v19, fpu_d19, fpu_s19, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z20_invalidates[] = {fpu_v20, fpu_d20, fpu_s20, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z21_invalidates[] = {fpu_v21, fpu_d21, fpu_s21, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z22_invalidates[] = {fpu_v22, fpu_d22, fpu_s22, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z23_invalidates[] = {fpu_v23, fpu_d23, fpu_s23, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z24_invalidates[] = {fpu_v24, fpu_d24, fpu_s24, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z25_invalidates[] = {fpu_v25, fpu_d25, fpu_s25, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z26_invalidates[] = {fpu_v26, fpu_d26, fpu_s26, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z27_invalidates[] = {fpu_v27, fpu_d27, fpu_s27, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z28_invalidates[] = {fpu_v28, fpu_d28, fpu_s28, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z29_invalidates[] = {fpu_v29, fpu_d29, fpu_s29, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z30_invalidates[] = {fpu_v30, fpu_d30, fpu_s30, + LLDB_INVALID_REGNUM}; +static uint32_t g_sve_z31_invalidates[] = {fpu_v31, fpu_d31, fpu_s31, + LLDB_INVALID_REGNUM}; + +static uint32_t g_contained_z0[] = {sve_z0, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z1[] = {sve_z1, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z2[] = {sve_z2, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z3[] = {sve_z3, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z4[] = {sve_z4, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z5[] = {sve_z5, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z6[] = {sve_z6, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z7[] = {sve_z7, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z8[] = {sve_z8, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z9[] = {sve_z9, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z10[] = {sve_z10, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z11[] = {sve_z11, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z12[] = {sve_z12, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z13[] = {sve_z13, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z14[] = {sve_z14, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z15[] = {sve_z15, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z16[] = {sve_z16, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z17[] = {sve_z17, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z18[] = {sve_z18, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z19[] = {sve_z19, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z20[] = {sve_z20, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z21[] = {sve_z21, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z22[] = {sve_z22, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z23[] = {sve_z23, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z24[] = {sve_z24, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z25[] = {sve_z25, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z26[] = {sve_z26, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z27[] = {sve_z27, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z28[] = {sve_z28, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z29[] = {sve_z29, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z30[] = {sve_z30, LLDB_INVALID_REGNUM}; +static uint32_t g_contained_z31[] = {sve_z31, LLDB_INVALID_REGNUM}; + +#define VG_OFFSET_NAME(reg) SVE_OFFSET_VG + +#define SVE_REG_KIND(reg) MISC_KIND(reg, sve, LLDB_INVALID_REGNUM) +#define MISC_VG_KIND(lldb_kind) MISC_KIND(vg, sve, LLDB_INVALID_REGNUM) + +// Default offset SVE Z registers and all corresponding pseudo registers +// ( S, D and V registers) is zero and will be configured during execution. + +// Defines sve pseudo vector (V) register with 16-byte size +#define DEFINE_VREG_SVE(vreg, zreg) \ + { \ + #vreg, nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, \ + VREG_KIND(vreg), g_contained_##zreg, g_sve_##vreg##_invalidates, \ + nullptr, 0 \ + } + +// Defines S and D pseudo registers mapping over corresponding vector register +#define DEFINE_FPU_PSEUDO_SVE(reg, size, zreg) \ + { \ + #reg, nullptr, size, 0, lldb::eEncodingIEEE754, lldb::eFormatFloat, \ + LLDB_KIND(fpu_##reg), g_contained_##zreg, g_sve_##reg##_invalidates, \ + nullptr, 0 \ + } + +// Defines a Z vector register with 16-byte default size +#define DEFINE_ZREG(reg) \ + { \ + #reg, nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, \ + SVE_REG_KIND(reg), nullptr, g_sve_##reg##_invalidates, nullptr, 0 \ + } + +// Defines a P vector register with 2-byte default size +#define DEFINE_PREG(reg) \ + { \ + #reg, nullptr, 2, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, \ + SVE_REG_KIND(reg), nullptr, nullptr, nullptr, 0 \ + } + +static lldb_private::RegisterInfo g_register_infos_arm64_sve_le[] = { + // clang-format off + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64(x0, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GPR64(x1, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GPR64(x2, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GPR64(x3, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GPR64(x4, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GPR64(x5, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GPR64(x6, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GPR64(x7, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_GPR64(x8, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x9, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x10, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x11, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x12, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x13, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x14, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x15, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x16, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x17, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x18, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x19, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x20, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x21, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x22, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x23, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x24, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x25, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x26, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x27, LLDB_INVALID_REGNUM), + DEFINE_GPR64(x28, LLDB_INVALID_REGNUM), + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64_ALT(fp, x29, LLDB_REGNUM_GENERIC_FP), + DEFINE_GPR64_ALT(lr, x30, LLDB_REGNUM_GENERIC_RA), + DEFINE_GPR64_ALT(sp, x31, LLDB_REGNUM_GENERIC_SP), + DEFINE_GPR64(pc, LLDB_REGNUM_GENERIC_PC), + + // DEFINE_MISC_REGS(name, size, TYPE, lldb kind) + DEFINE_MISC_REGS(cpsr, 4, GPR, gpr_cpsr), + + // DEFINE_GPR32(name, parent name) + DEFINE_GPR32(w0, x0), + DEFINE_GPR32(w1, x1), + DEFINE_GPR32(w2, x2), + DEFINE_GPR32(w3, x3), + DEFINE_GPR32(w4, x4), + DEFINE_GPR32(w5, x5), + DEFINE_GPR32(w6, x6), + DEFINE_GPR32(w7, x7), + DEFINE_GPR32(w8, x8), + DEFINE_GPR32(w9, x9), + DEFINE_GPR32(w10, x10), + DEFINE_GPR32(w11, x11), + DEFINE_GPR32(w12, x12), + DEFINE_GPR32(w13, x13), + DEFINE_GPR32(w14, x14), + DEFINE_GPR32(w15, x15), + DEFINE_GPR32(w16, x16), + DEFINE_GPR32(w17, x17), + DEFINE_GPR32(w18, x18), + DEFINE_GPR32(w19, x19), + DEFINE_GPR32(w20, x20), + DEFINE_GPR32(w21, x21), + DEFINE_GPR32(w22, x22), + DEFINE_GPR32(w23, x23), + DEFINE_GPR32(w24, x24), + DEFINE_GPR32(w25, x25), + DEFINE_GPR32(w26, x26), + DEFINE_GPR32(w27, x27), + DEFINE_GPR32(w28, x28), + + // DEFINE_VREG_SVE(v register, z register) + DEFINE_VREG_SVE(v0, z0), + DEFINE_VREG_SVE(v1, z1), + DEFINE_VREG_SVE(v2, z2), + DEFINE_VREG_SVE(v3, z3), + DEFINE_VREG_SVE(v4, z4), + DEFINE_VREG_SVE(v5, z5), + DEFINE_VREG_SVE(v6, z6), + DEFINE_VREG_SVE(v7, z7), + DEFINE_VREG_SVE(v8, z8), + DEFINE_VREG_SVE(v9, z9), + DEFINE_VREG_SVE(v10, z10), + DEFINE_VREG_SVE(v11, z11), + DEFINE_VREG_SVE(v12, z12), + DEFINE_VREG_SVE(v13, z13), + DEFINE_VREG_SVE(v14, z14), + DEFINE_VREG_SVE(v15, z15), + DEFINE_VREG_SVE(v16, z16), + DEFINE_VREG_SVE(v17, z17), + DEFINE_VREG_SVE(v18, z18), + DEFINE_VREG_SVE(v19, z19), + DEFINE_VREG_SVE(v20, z20), + DEFINE_VREG_SVE(v21, z21), + DEFINE_VREG_SVE(v22, z22), + DEFINE_VREG_SVE(v23, z23), + DEFINE_VREG_SVE(v24, z24), + DEFINE_VREG_SVE(v25, z25), + DEFINE_VREG_SVE(v26, z26), + DEFINE_VREG_SVE(v27, z27), + DEFINE_VREG_SVE(v28, z28), + DEFINE_VREG_SVE(v29, z29), + DEFINE_VREG_SVE(v30, z30), + DEFINE_VREG_SVE(v31, z31), + + // DEFINE_FPU_PSEUDO(name, size, ENDIAN OFFSET, parent register) + DEFINE_FPU_PSEUDO_SVE(s0, 4, z0), + DEFINE_FPU_PSEUDO_SVE(s1, 4, z1), + DEFINE_FPU_PSEUDO_SVE(s2, 4, z2), + DEFINE_FPU_PSEUDO_SVE(s3, 4, z3), + DEFINE_FPU_PSEUDO_SVE(s4, 4, z4), + DEFINE_FPU_PSEUDO_SVE(s5, 4, z5), + DEFINE_FPU_PSEUDO_SVE(s6, 4, z6), + DEFINE_FPU_PSEUDO_SVE(s7, 4, z7), + DEFINE_FPU_PSEUDO_SVE(s8, 4, z8), + DEFINE_FPU_PSEUDO_SVE(s9, 4, z9), + DEFINE_FPU_PSEUDO_SVE(s10, 4, z10), + DEFINE_FPU_PSEUDO_SVE(s11, 4, z11), + DEFINE_FPU_PSEUDO_SVE(s12, 4, z12), + DEFINE_FPU_PSEUDO_SVE(s13, 4, z13), + DEFINE_FPU_PSEUDO_SVE(s14, 4, z14), + DEFINE_FPU_PSEUDO_SVE(s15, 4, z15), + DEFINE_FPU_PSEUDO_SVE(s16, 4, z16), + DEFINE_FPU_PSEUDO_SVE(s17, 4, z17), + DEFINE_FPU_PSEUDO_SVE(s18, 4, z18), + DEFINE_FPU_PSEUDO_SVE(s19, 4, z19), + DEFINE_FPU_PSEUDO_SVE(s20, 4, z20), + DEFINE_FPU_PSEUDO_SVE(s21, 4, z21), + DEFINE_FPU_PSEUDO_SVE(s22, 4, z22), + DEFINE_FPU_PSEUDO_SVE(s23, 4, z23), + DEFINE_FPU_PSEUDO_SVE(s24, 4, z24), + DEFINE_FPU_PSEUDO_SVE(s25, 4, z25), + DEFINE_FPU_PSEUDO_SVE(s26, 4, z26), + DEFINE_FPU_PSEUDO_SVE(s27, 4, z27), + DEFINE_FPU_PSEUDO_SVE(s28, 4, z28), + DEFINE_FPU_PSEUDO_SVE(s29, 4, z29), + DEFINE_FPU_PSEUDO_SVE(s30, 4, z30), + DEFINE_FPU_PSEUDO_SVE(s31, 4, z31), + + DEFINE_FPU_PSEUDO_SVE(d0, 8, z0), + DEFINE_FPU_PSEUDO_SVE(d1, 8, z1), + DEFINE_FPU_PSEUDO_SVE(d2, 8, z2), + DEFINE_FPU_PSEUDO_SVE(d3, 8, z3), + DEFINE_FPU_PSEUDO_SVE(d4, 8, z4), + DEFINE_FPU_PSEUDO_SVE(d5, 8, z5), + DEFINE_FPU_PSEUDO_SVE(d6, 8, z6), + DEFINE_FPU_PSEUDO_SVE(d7, 8, z7), + DEFINE_FPU_PSEUDO_SVE(d8, 8, z8), + DEFINE_FPU_PSEUDO_SVE(d9, 8, z9), + DEFINE_FPU_PSEUDO_SVE(d10, 8, z10), + DEFINE_FPU_PSEUDO_SVE(d11, 8, z11), + DEFINE_FPU_PSEUDO_SVE(d12, 8, z12), + DEFINE_FPU_PSEUDO_SVE(d13, 8, z13), + DEFINE_FPU_PSEUDO_SVE(d14, 8, z14), + DEFINE_FPU_PSEUDO_SVE(d15, 8, z15), + DEFINE_FPU_PSEUDO_SVE(d16, 8, z16), + DEFINE_FPU_PSEUDO_SVE(d17, 8, z17), + DEFINE_FPU_PSEUDO_SVE(d18, 8, z18), + DEFINE_FPU_PSEUDO_SVE(d19, 8, z19), + DEFINE_FPU_PSEUDO_SVE(d20, 8, z20), + DEFINE_FPU_PSEUDO_SVE(d21, 8, z21), + DEFINE_FPU_PSEUDO_SVE(d22, 8, z22), + DEFINE_FPU_PSEUDO_SVE(d23, 8, z23), + DEFINE_FPU_PSEUDO_SVE(d24, 8, z24), + DEFINE_FPU_PSEUDO_SVE(d25, 8, z25), + DEFINE_FPU_PSEUDO_SVE(d26, 8, z26), + DEFINE_FPU_PSEUDO_SVE(d27, 8, z27), + DEFINE_FPU_PSEUDO_SVE(d28, 8, z28), + DEFINE_FPU_PSEUDO_SVE(d29, 8, z29), + DEFINE_FPU_PSEUDO_SVE(d30, 8, z30), + DEFINE_FPU_PSEUDO_SVE(d31, 8, z31), + + // DEFINE_MISC_REGS(name, size, TYPE, lldb kind) + DEFINE_MISC_REGS(fpsr, 4, FPU, fpu_fpsr), + DEFINE_MISC_REGS(fpcr, 4, FPU, fpu_fpcr), + + DEFINE_MISC_REGS(vg, 8, VG, sve_vg), + // DEFINE_ZREG(name) + DEFINE_ZREG(z0), + DEFINE_ZREG(z1), + DEFINE_ZREG(z2), + DEFINE_ZREG(z3), + DEFINE_ZREG(z4), + DEFINE_ZREG(z5), + DEFINE_ZREG(z6), + DEFINE_ZREG(z7), + DEFINE_ZREG(z8), + DEFINE_ZREG(z9), + DEFINE_ZREG(z10), + DEFINE_ZREG(z11), + DEFINE_ZREG(z12), + DEFINE_ZREG(z13), + DEFINE_ZREG(z14), + DEFINE_ZREG(z15), + DEFINE_ZREG(z16), + DEFINE_ZREG(z17), + DEFINE_ZREG(z18), + DEFINE_ZREG(z19), + DEFINE_ZREG(z20), + DEFINE_ZREG(z21), + DEFINE_ZREG(z22), + DEFINE_ZREG(z23), + DEFINE_ZREG(z24), + DEFINE_ZREG(z25), + DEFINE_ZREG(z26), + DEFINE_ZREG(z27), + DEFINE_ZREG(z28), + DEFINE_ZREG(z29), + DEFINE_ZREG(z30), + DEFINE_ZREG(z31), + + // DEFINE_PREG(name) + DEFINE_PREG(p0), + DEFINE_PREG(p1), + DEFINE_PREG(p2), + DEFINE_PREG(p3), + DEFINE_PREG(p4), + DEFINE_PREG(p5), + DEFINE_PREG(p6), + DEFINE_PREG(p7), + DEFINE_PREG(p8), + DEFINE_PREG(p9), + DEFINE_PREG(p10), + DEFINE_PREG(p11), + DEFINE_PREG(p12), + DEFINE_PREG(p13), + DEFINE_PREG(p14), + DEFINE_PREG(p15), + + // DEFINE FFR + DEFINE_PREG(ffr) + // clang-format on +}; + +#endif // DECLARE_REGISTER_INFOS_ARM64_SVE_STRUCT Index: lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h =================================================================== --- lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h +++ lldb/source/Plugins/Process/Utility/lldb-arm64-register-enums.h @@ -257,7 +257,66 @@ k_num_registers_arm64, k_num_gpr_registers_arm64 = k_last_gpr_arm64 - k_first_gpr_arm64 + 1, - k_num_fpr_registers_arm64 = k_last_fpr_arm64 - k_first_fpr_arm64 + 1 + k_num_fpr_registers_arm64 = k_last_fpr_arm64 - k_first_fpr_arm64 + 1, + + k_first_sve_arm64 = exc_far_arm64, + sve_vg_arm64 = k_first_sve_arm64, + sve_z0_arm64, + sve_z1_arm64, + sve_z2_arm64, + sve_z3_arm64, + sve_z4_arm64, + sve_z5_arm64, + sve_z6_arm64, + sve_z7_arm64, + sve_z8_arm64, + sve_z9_arm64, + sve_z10_arm64, + sve_z11_arm64, + sve_z12_arm64, + sve_z13_arm64, + sve_z14_arm64, + sve_z15_arm64, + sve_z16_arm64, + sve_z17_arm64, + sve_z18_arm64, + sve_z19_arm64, + sve_z20_arm64, + sve_z21_arm64, + sve_z22_arm64, + sve_z23_arm64, + sve_z24_arm64, + sve_z25_arm64, + sve_z26_arm64, + sve_z27_arm64, + sve_z28_arm64, + sve_z29_arm64, + sve_z30_arm64, + sve_z31_arm64, + + sve_p0_arm64, + sve_p1_arm64, + sve_p2_arm64, + sve_p3_arm64, + sve_p4_arm64, + sve_p5_arm64, + sve_p6_arm64, + sve_p7_arm64, + sve_p8_arm64, + sve_p9_arm64, + sve_p10_arm64, + sve_p11_arm64, + sve_p12_arm64, + sve_p13_arm64, + sve_p14_arm64, + sve_p15_arm64, + + sve_ffr_arm64, + k_last_sve_arm64 = sve_ffr_arm64, + + k_num_registers_arm64_sve, + k_num_sve_registers_arm64 = k_last_sve_arm64 - k_first_sve_arm64 + 1 + }; } Index: lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h =================================================================== --- lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h +++ lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h @@ -14,6 +14,20 @@ #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/DataExtractor.h" +#include + +#ifndef SVE_PT_REGS_SVE +#define INCLUDE_LINUX_PTRACE_DEFINITIONS_FOR_SVE_ARM64 +#include "Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h" +#endif + +enum class SVE_STATE { + SVE_STATE_UNKNOWN, + SVE_STATE_DISABLED, + SVE_STATE_FPSIMD, + SVE_STATE_FULL +}; + class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 { public: RegisterContextCorePOSIX_arm64( @@ -36,6 +50,10 @@ bool HardwareSingleStep(bool enable) override; + void ConfigureRegisterContext(); + + uint32_t CalculateSVEOffset(uint32_t reg_num) const; + protected: bool ReadGPR() override; @@ -45,10 +63,19 @@ bool WriteFPR() override; + uint64_t GetSVERegVG() { return m_sve_header.vl / 8; } + + void *GetSVEBuffer(); + private: lldb::DataBufferSP m_gpr_buffer; lldb_private::DataExtractor m_gpr; lldb_private::DataExtractor m_fpregset; + lldb_private::DataExtractor m_sveregset; + + mutable SVE_STATE m_sve_state; + struct user_sve_header m_sve_header; + std::vector m_sve_note_payload; }; #endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_ARM64_H Index: lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp =================================================================== --- lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp +++ lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp @@ -27,10 +27,70 @@ m_fpregset = getRegset( notes, register_info->GetTargetArchitecture().GetTriple(), FPR_Desc); + + m_sveregset = + getRegset(notes, register_info->GetTargetArchitecture().GetTriple(), + AARCH64_SVE_Desc); + + ConfigureRegisterContext(); } RegisterContextCorePOSIX_arm64::~RegisterContextCorePOSIX_arm64() {} +void *RegisterContextCorePOSIX_arm64::GetSVEBuffer() { + if (m_sve_state == SVE_STATE::SVE_STATE_FPSIMD) + return m_sve_note_payload.data() + SVE_PT_FPSIMD_OFFSET; + return m_sve_note_payload.data(); +} + +void RegisterContextCorePOSIX_arm64::ConfigureRegisterContext() { + if (m_sveregset.GetByteSize() > sizeof(m_sve_header)) { + m_sve_note_payload.resize(m_sveregset.GetByteSize()); + ::memcpy(GetSVEBuffer(), m_sveregset.GetDataStart(), + m_sveregset.GetByteSize()); + ::memcpy(&m_sve_header, m_sveregset.GetDataStart(), sizeof(m_sve_header)); + + if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD) + m_sve_state = SVE_STATE::SVE_STATE_FPSIMD; + else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE) + m_sve_state = SVE_STATE::SVE_STATE_FULL; + + if (sve_vl_valid(m_sve_header.vl)) { + size_t vq = sve_vq_from_vl(m_sve_header.vl); + m_register_info_up->SetRegisterInfoMode(vq); + m_sve_enabled = true; + m_reg_info.num_registers = k_num_registers_arm64_sve; + } else + m_sve_state = SVE_STATE::SVE_STATE_DISABLED; + } else + m_sve_state = SVE_STATE::SVE_STATE_DISABLED; +} + +uint32_t +RegisterContextCorePOSIX_arm64::CalculateSVEOffset(uint32_t reg_num) const { + if (m_sve_state == SVE_STATE::SVE_STATE_FPSIMD) { + if (IsSVEZReg(reg_num)) + return (reg_num - sve_z0_arm64) * 16; + else if (reg_num == fpu_fpsr_arm64) + return 32 * 16; + else if (reg_num == fpu_fpcr_arm64) + return (32 * 16) + 4; + } else if (m_sve_state == SVE_STATE::SVE_STATE_FULL) { + size_t vq = sve_vq_from_vl(m_sve_header.vl); + if (IsSVEZReg(reg_num)) + return SVE_PT_SVE_ZREG_OFFSET(vq, reg_num - sve_z0_arm64); + else if (IsSVEPReg(reg_num)) + return SVE_PT_SVE_PREG_OFFSET(vq, reg_num - sve_p0_arm64); + else if (reg_num == sve_ffr_arm64) + return SVE_PT_SVE_FFR_OFFSET(vq); + else if (reg_num == fpu_fpsr_arm64) + return SVE_PT_SVE_FPSR_OFFSET(vq); + else if (reg_num == fpu_fpcr_arm64) + return SVE_PT_SVE_FPCR_OFFSET(vq); + } + return 0; +} + bool RegisterContextCorePOSIX_arm64::ReadGPR() { return true; } bool RegisterContextCorePOSIX_arm64::ReadFPR() { return false; } @@ -47,7 +107,13 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) { - lldb::offset_t offset = reg_info->byte_offset; + Status error; + uint8_t *src; + lldb::offset_t offset; + uint64_t sve_vg; + std::vector sve_reg_non_live; + + offset = reg_info->byte_offset; if (offset + reg_info->byte_size <= GetGPRSize()) { uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); if (offset == reg_info->byte_offset + reg_info->byte_size) { @@ -60,15 +126,62 @@ if (reg == LLDB_INVALID_REGNUM) return false; - offset -= GetGPRSize(); - if (IsFPR(reg) && offset + reg_info->byte_size <= sizeof(FPU)) { - Status error; - value.SetFromMemoryData(reg_info, m_fpregset.GetDataStart() + offset, - reg_info->byte_size, lldb::eByteOrderLittle, error); - return error.Success(); - } + if (IsFPR(reg)) { + if (m_sve_state == SVE_STATE::SVE_STATE_DISABLED) { + // SVE is disabled take legacy route for FPU register access + offset -= GetGPRSize(); + if (IsFPR(reg) && offset < m_fpregset.GetByteSize()) { + value.SetFromMemoryData(reg_info, m_fpregset.GetDataStart() + offset, + reg_info->byte_size, lldb::eByteOrderLittle, + error); + return error.Success(); + } + } else { + // Extract SVE Z register value register number for this reg_info + uint32_t sve_reg_num = LLDB_INVALID_REGNUM; + if (reg_info->value_regs && + reg_info->value_regs[0] != LLDB_INVALID_REGNUM) + sve_reg_num = reg_info->value_regs[0]; + else if (reg == fpu_fpcr_arm64 || reg == fpu_fpsr_arm64) + sve_reg_num = reg; + if (sve_reg_num != LLDB_INVALID_REGNUM) { + offset = CalculateSVEOffset(sve_reg_num); + assert(offset < m_sveregset.GetByteSize()); + src = (uint8_t *)GetSVEBuffer() + offset; + } + } + } else if (IsSVERegVG(reg)) { + sve_vg = GetSVERegVG(); + src = (uint8_t *)&sve_vg; + } else if (IsSVE(reg)) { + if (m_sve_state == SVE_STATE::SVE_STATE_DISABLED) + return false; + else { + if (m_sve_state == SVE_STATE::SVE_STATE_FPSIMD) { + sve_reg_non_live.resize(reg_info->byte_size, 0); + // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so just + // copy 16 bytes of v register to the start of z register. All other + // SVE register will be set to zero. + if (IsSVEZReg(reg)) { + offset = CalculateSVEOffset(reg); + assert(offset < m_sveregset.GetByteSize()); + ::memcpy(sve_reg_non_live.data(), + (const uint8_t *)GetSVEBuffer() + offset, 16); + } + src = sve_reg_non_live.data(); + } else if (m_sve_state == SVE_STATE::SVE_STATE_FULL) { + offset = CalculateSVEOffset(reg); + assert(offset < m_sveregset.GetByteSize()); + src = (uint8_t *)GetSVEBuffer() + offset; + } + } + } else + return false; - return false; + value.SetFromMemoryData(reg_info, src, reg_info->byte_size, + lldb::eByteOrderLittle, error); + + return error.Success(); } bool RegisterContextCorePOSIX_arm64::ReadAllRegisterValues( Index: lldb/source/Plugins/Process/elf-core/RegisterUtilities.h =================================================================== --- lldb/source/Plugins/Process/elf-core/RegisterUtilities.h +++ lldb/source/Plugins/Process/elf-core/RegisterUtilities.h @@ -107,6 +107,10 @@ {llvm::Triple::OpenBSD, llvm::Triple::UnknownArch, OPENBSD::NT_FPREGS}, }; +constexpr RegsetDesc AARCH64_SVE_Desc[] = { + {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_SVE}, +}; + constexpr RegsetDesc PPC_VMX_Desc[] = { {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX}, Index: lldb/source/Utility/ARM64_DWARF_Registers.h =================================================================== --- lldb/source/Utility/ARM64_DWARF_Registers.h +++ lldb/source/Utility/ARM64_DWARF_Registers.h @@ -51,7 +51,31 @@ sp = x31, pc = 32, cpsr = 33, - // 34-63 reserved + // 34-45 reserved + + // 64-bit SVE Vector granule pseudo register + vg = 46, + + // VG ́8-bit SVE first fault register + ffr = 47, + + // VG x ́8-bit SVE predicate registers + p0 = 48, + p1, + p2, + p3, + p4, + p5, + p6, + p7, + p8, + p9, + p10, + p11, + p12, + p13, + p14, + p15, // V0-V31 (128 bit vector registers) v0 = 64, @@ -85,9 +109,41 @@ v28, v29, v30, - v31 + v31, - // 96-127 reserved + // VG ́64-bit SVE vector registers + z0 = 96, + z1, + z2, + z3, + z4, + z5, + z6, + z7, + z8, + z9, + z10, + z11, + z12, + z13, + z14, + z15, + z16, + z17, + z18, + z19, + z20, + z21, + z22, + z23, + z24, + z25, + z26, + z27, + z28, + z29, + z30, + z31 }; } // namespace arm64_dwarf Index: lldb/source/Utility/ARM64_ehframe_Registers.h =================================================================== --- lldb/source/Utility/ARM64_ehframe_Registers.h +++ lldb/source/Utility/ARM64_ehframe_Registers.h @@ -49,10 +49,34 @@ lr, // aka x30 sp, // aka x31 aka wzr pc, // value is 32 - cpsr -}; + cpsr, + // 34-45 reserved -enum { + // 64-bit SVE Vector granule pseudo register + vg = 46, + + // VG ́8-bit SVE first fault register + ffr = 47, + + // VG x ́8-bit SVE predicate registers + p0 = 48, + p1, + p2, + p3, + p4, + p5, + p6, + p7, + p8, + p9, + p10, + p11, + p12, + p13, + p14, + p15, + + // V0-V31 (128 bit vector registers) v0 = 64, v1, v2, @@ -84,7 +108,41 @@ v28, v29, v30, - v31 // 95 + v31, + + // VG ́64-bit SVE vector registers + z0 = 96, + z1, + z2, + z3, + z4, + z5, + z6, + z7, + z8, + z9, + z10, + z11, + z12, + z13, + z14, + z15, + z16, + z17, + z18, + z19, + z20, + z21, + z22, + z23, + z24, + z25, + z26, + z27, + z28, + z29, + z30, + z31 }; } Index: lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py =================================================================== --- lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py +++ lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -269,7 +269,7 @@ self.dbg.DeleteTarget(target) @skipIf(triple='^mips') - @skipIfLLVMTargetMissing("AArch64") + #@skipIfLLVMTargetMissing("AArch64") def test_aarch64_regs(self): # check 64 bit ARM core files target = self.dbg.CreateTarget(None) @@ -323,6 +323,47 @@ self.expect("register read --all") + #@skipIf(triple='^mips') + #@skipIfLLVMTargetMissing("AArch64") + def test_aarch64_sve_regs(self): + # check 64 bit ARM core files + target = self.dbg.CreateTarget(None) + self.assertTrue(target, VALID_TARGET) + process = target.LoadCore("linux-aarch64-sve.core") + + values = {} + values["fp"] = "0x0000fffffc1ff4f0" + values["lr"] = "0x0000000000400170" + values["sp"] = "0x0000fffffc1ff4d0" + values["pc"] = "0x000000000040013c" + values["v0"] = "{0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40}" + values["v1"] = "{0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41}" + values["v2"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}" + values["v3"] = "{0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41}" + values["s0"] = "7.5" + values["s1"] = "11.5" + values["s2"] = "0" + values["s3"] = "15.5" + values["d0"] = "65536.0158538818" + values["d1"] = "1572864.25476074" + values["d2"] = "0" + values["d3"] = "25165828.0917969" + values["vg"] = "0x0000000000000004" + values["z0"] = "{0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40 0x00 0x00 0xf0 0x40}" + values["z1"] = "{0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41 0x00 0x00 0x38 0x41}" + values["z2"] = "{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00}" + values["z3"] = "{0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41 0x00 0x00 0x78 0x41}" + values["p0"] = "{0x11 0x11 0x11 0x11}" + values["p1"] = "{0x11 0x11 0x11 0x11}" + values["p2"] = "{0x00 0x00 0x00 0x00}" + values["p3"] = "{0x11 0x11 0x11 0x11}" + values["p4"] = "{0x00 0x00 0x00 0x00}" + + for regname, value in values.items(): + self.expect("register read {}".format(regname), substrs=["{} = {}".format(regname, value)]) + + self.expect("register read --all") + @skipIf(triple='^mips') @skipIfLLVMTargetMissing("ARM") def test_arm_core(self): Index: lldb/test/API/functionalities/postmortem/elf-core/linux-aarch64-sve.c =================================================================== --- /dev/null +++ lldb/test/API/functionalities/postmortem/elf-core/linux-aarch64-sve.c @@ -0,0 +1,24 @@ +// compile with -march=armv8-a+sve on compatible aarch64 compiler +// linux-aarch64-sve.core was generated by: aarch64-linux-gnu-gcc-8 +// commandline: -march=armv8-a+sve -nostdlib -static -g linux-aarch64-sve.c +static void bar(char *boom) { + char F = 'b'; + asm volatile("ptrue p0.s\n\t"); + asm volatile("fcpy z0.s, p0/m, #7.5\n\t"); + asm volatile("ptrue p1.s\n\t"); + asm volatile("fcpy z1.s, p1/m, #11.5\n\t"); + asm volatile("ptrue p3.s\n\t"); + asm volatile("fcpy z3.s, p3/m, #15.5\n\t"); + + *boom = 47; // Frame bar +} + +static void foo(char *boom, void (*boomer)(char *)) { + char F = 'f'; + boomer(boom); // Frame foo +} + +void _start(void) { + char F = '_'; + foo(0, bar); // Frame _start +}