Index: lldb/include/lldb/Host/common/NativeRegisterContext.h =================================================================== --- lldb/include/lldb/Host/common/NativeRegisterContext.h +++ lldb/include/lldb/Host/common/NativeRegisterContext.h @@ -114,6 +114,10 @@ virtual NativeThreadProtocol &GetThread() { return m_thread; } + virtual const RegisterSet *GetExpeditedRegisterSet() const { + return nullptr; + }; + const RegisterInfo *GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx = 0); Index: lldb/include/lldb/Utility/RegisterValue.h =================================================================== --- lldb/include/lldb/Utility/RegisterValue.h +++ lldb/include/lldb/Utility/RegisterValue.h @@ -26,7 +26,7 @@ class RegisterValue { public: - enum { kMaxRegisterByteSize = 64u }; + enum { kMaxRegisterByteSize = 256u }; enum Type { eTypeInvalid, @@ -261,7 +261,7 @@ struct { uint8_t bytes[kMaxRegisterByteSize]; // This must be big enough to hold any // register for any supported target. - uint8_t length; + uint32_t length; lldb::ByteOrder byte_order; } buffer; }; Index: lldb/source/Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h @@ -0,0 +1,155 @@ +//===-- LinuxPtraceDefs_arm64.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 +// +//===----------------------------------------------------------------------===// + +// This file provides Linux specific defines to enable compilation with SVE +// ptrace support. These defines may later be removed once they get defined +// in Procfs.h and Ptrace.h. + +// References in Linux kernel source: +// 1) Documentation/arm64/sve.txt +// 2) arch/arm64/include/uapi/asm/ptrace.h +// 3) arch/arm64/include/uapi/asm/sve_context.h +#ifdef INCLUDE_LINUX_PTRACE_DEFINITIONS_FOR_SVE_ARM64 + +#ifndef lldb_LinuxPtraceDefs_arm64_h +#define lldb_LinuxPtraceDefs_arm64_h + +#include + +/* SVE/FP/SIMD state (NT_ARM_SVE) */ + +struct user_sve_header { + __u32 size; /* total meaningful regset content in bytes */ + __u32 max_size; /* maxmium possible size for this thread */ + __u16 vl; /* current vector length */ + __u16 max_vl; /* maximum possible vector length */ + __u16 flags; + __u16 __reserved; +}; + +/* Definitions for user_sve_header.flags: */ +#define SVE_PT_REGS_MASK (1 << 0) + +#define SVE_PT_REGS_FPSIMD 0 +#define SVE_PT_REGS_SVE SVE_PT_REGS_MASK + +/* + * Common SVE_PT_* flags: + * These must be kept in sync with prctl interface in + */ +#define SVE_PT_VL_INHERIT (PR_SVE_VL_INHERIT >> 16) +#define SVE_PT_VL_ONEXEC (PR_SVE_SET_VL_ONEXEC >> 16) + +/* + * The remainder of the SVE state follows struct user_sve_header. The + * total size of the SVE state (including header) depends on the + * metadata in the header: SVE_PT_SIZE(vq, flags) gives the total size + * of the state in bytes, including the header. + * + * Refer to for details of how to pass the correct + * "vq" argument to these macros. + */ + +/* Offset from the start of struct user_sve_header to the register data */ +#define SVE_PT_REGS_OFFSET \ + ((sizeof(struct sve_context) + (SVE_VQ_BYTES - 1)) / SVE_VQ_BYTES * \ + SVE_VQ_BYTES) + +/* + * The register data content and layout depends on the value of the + * flags field. + */ + +/* + * (flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD case: + * + * The payload starts at offset SVE_PT_FPSIMD_OFFSET, and is of type + * struct user_fpsimd_state. Additional data might be appended in the + * future: use SVE_PT_FPSIMD_SIZE(vq, flags) to compute the total size. + * SVE_PT_FPSIMD_SIZE(vq, flags) will never be less than + * sizeof(struct user_fpsimd_state). + */ + +#define SVE_PT_FPSIMD_OFFSET SVE_PT_REGS_OFFSET + +#define SVE_PT_FPSIMD_SIZE(vq, flags) (sizeof(struct user_fpsimd_state)) + +/* + * (flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE case: + * + * The payload starts at offset SVE_PT_SVE_OFFSET, and is of size + * SVE_PT_SVE_SIZE(vq, flags). + * + * Additional macros describe the contents and layout of the payload. + * For each, SVE_PT_SVE_x_OFFSET(args) is the start offset relative to + * the start of struct user_sve_header, and SVE_PT_SVE_x_SIZE(args) is + * the size in bytes: + * + * x type description + * - ---- ----------- + * ZREGS \ + * ZREG | + * PREGS | refer to + * PREG | + * FFR / + * + * FPSR uint32_t FPSR + * FPCR uint32_t FPCR + * + * Additional data might be appended in the future. + */ + +#define SVE_PT_SVE_ZREG_SIZE(vq) SVE_SIG_ZREG_SIZE(vq) +#define SVE_PT_SVE_PREG_SIZE(vq) SVE_SIG_PREG_SIZE(vq) +#define SVE_PT_SVE_FFR_SIZE(vq) SVE_SIG_FFR_SIZE(vq) +#define SVE_PT_SVE_FPSR_SIZE sizeof(__u32) +#define SVE_PT_SVE_FPCR_SIZE sizeof(__u32) + +#define __SVE_SIG_TO_PT(offset) \ + ((offset)-SVE_SIG_REGS_OFFSET + SVE_PT_REGS_OFFSET) + +#define SVE_PT_SVE_OFFSET SVE_PT_REGS_OFFSET + +#define SVE_PT_SVE_ZREGS_OFFSET __SVE_SIG_TO_PT(SVE_SIG_ZREGS_OFFSET) +#define SVE_PT_SVE_ZREG_OFFSET(vq, n) \ + __SVE_SIG_TO_PT(SVE_SIG_ZREG_OFFSET(vq, n)) +#define SVE_PT_SVE_ZREGS_SIZE(vq) \ + (SVE_PT_SVE_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_PT_SVE_ZREGS_OFFSET) + +#define SVE_PT_SVE_PREGS_OFFSET(vq) __SVE_SIG_TO_PT(SVE_SIG_PREGS_OFFSET(vq)) +#define SVE_PT_SVE_PREG_OFFSET(vq, n) \ + __SVE_SIG_TO_PT(SVE_SIG_PREG_OFFSET(vq, n)) +#define SVE_PT_SVE_PREGS_SIZE(vq) \ + (SVE_PT_SVE_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_PT_SVE_PREGS_OFFSET(vq)) + +#define SVE_PT_SVE_FFR_OFFSET(vq) __SVE_SIG_TO_PT(SVE_SIG_FFR_OFFSET(vq)) + +#define SVE_PT_SVE_FPSR_OFFSET(vq) \ + ((SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq) + \ + (SVE_VQ_BYTES - 1)) / \ + SVE_VQ_BYTES * SVE_VQ_BYTES) +#define SVE_PT_SVE_FPCR_OFFSET(vq) \ + (SVE_PT_SVE_FPSR_OFFSET(vq) + SVE_PT_SVE_FPSR_SIZE) + +/* + * Any future extension appended after FPCR must be aligned to the next + * 128-bit boundary. + */ + +#define SVE_PT_SVE_SIZE(vq, flags) \ + ((SVE_PT_SVE_FPCR_OFFSET(vq) + SVE_PT_SVE_FPCR_SIZE - SVE_PT_SVE_OFFSET + \ + (SVE_VQ_BYTES - 1)) / \ + SVE_VQ_BYTES * SVE_VQ_BYTES) + +#define SVE_PT_SIZE(vq, flags) \ + (((flags)&SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE \ + ? SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) \ + : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags)) + +#endif +#endif Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h =================================================================== --- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h +++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h @@ -31,6 +31,9 @@ // Invalidates cached values in register context data structures virtual void InvalidateAllRegisters(){} + // Configures register context based on target capabilities + virtual void ConfigureRegisterContext() {} + protected: lldb::ByteOrder GetByteOrder() const; Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h =================================================================== --- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -14,11 +14,25 @@ #include "Plugins/Process/Linux/NativeRegisterContextLinux.h" #include "Plugins/Process/Utility/lldb-arm64-register-enums.h" +#include + +#ifndef SVE_PT_REGS_SVE +#define INCLUDE_LINUX_PTRACE_DEFINITIONS_FOR_SVE_ARM64 +#include "Plugins/Process/Linux/LinuxPTraceDefines_arm64sve.h" +#endif + namespace lldb_private { namespace process_linux { class NativeProcessLinux; +enum class SVE_STATE { + SVE_STATE_UNKNOWN, + SVE_STATE_DISABLED, + SVE_STATE_FPSIMD, + SVE_STATE_FULL +}; + class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux { public: NativeRegisterContextLinux_arm64(const ArchSpec &target_arch, @@ -42,6 +56,10 @@ void InvalidateAllRegisters() override; + void ConfigureRegisterContext() override; + + const RegisterSet *GetExpeditedRegisterSet() const override; + // Hardware breakpoints/watchpoint management functions uint32_t NumSupportedHardwareBreakpoints() override; @@ -88,17 +106,34 @@ Status WriteFPR() override; + Status ReadAllSVE(); + + Status WriteAllSVE(); + + Status ReadSVEHeader(); + + Status WriteSVEHeader(); + void *GetGPRBuffer() override { return &m_gpr_arm64; } void *GetFPRBuffer() override { return &m_fpr; } size_t GetFPRSize() override { return sizeof(m_fpr); } + void *GetSVEBuffer() { return m_sve_data.get(); } + + void *GetSVEHeader() { return &m_sve_header; } + + size_t GetSVEHeaderSize() { return sizeof(m_sve_header); } + + size_t GetSVEBufferSize(); + private: 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; @@ -107,6 +142,9 @@ uint32_t first_fpr_v; uint32_t last_fpr_v; + uint32_t first_sve; + uint32_t last_sve; + uint32_t gpr_flags; }; @@ -129,13 +167,24 @@ uint64_t pstate; }; + typedef std::unique_ptr SVE_DATA; + bool m_gpr_is_valid; bool m_fpu_is_valid; + bool m_sve_data_is_valid; + + bool m_sve_header_is_valid; GPR m_gpr_arm64; // 64-bit general purpose registers. + RegInfo m_reg_info; FPU m_fpr; // floating-point registers including extended register sets. + struct user_sve_header m_sve_header; + SVE_DATA m_sve_data; + + mutable SVE_STATE m_sve_state; + // Debug register info for hardware breakpoints and watchpoints management. struct DREG { lldb::addr_t address; // Breakpoint/watchpoint address value. @@ -157,11 +206,17 @@ bool IsFPR(unsigned reg) const; + bool IsSVE(unsigned reg) const; + + bool IsVG(unsigned reg) const; + Status ReadHardwareDebugInfo(); Status WriteHardwareDebugRegs(int hwbType); uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const; + + uint32_t CalculateSVEOffset(const RegisterInfo *reg_info) const; }; } // namespace process_linux Index: lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp =================================================================== --- lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -28,8 +28,10 @@ #include // NT_PRSTATUS and NT_FPREGSET definition #include -// user_hwdebug_state definition -#include + +#ifndef NT_ARM_SVE +#define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */ +#endif #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) @@ -95,17 +97,65 @@ 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 }; } +// ARM64 general purpose registers. +static const uint32_t g_expedited_regnums_arm64_sve[] = { + gpr_x0_arm64, gpr_x1_arm64, gpr_x2_arm64, gpr_x3_arm64, + gpr_x4_arm64, gpr_x5_arm64, gpr_x6_arm64, gpr_x7_arm64, + gpr_x8_arm64, gpr_x9_arm64, gpr_x10_arm64, gpr_x11_arm64, + gpr_x12_arm64, gpr_x13_arm64, gpr_x14_arm64, gpr_x15_arm64, + gpr_x16_arm64, gpr_x17_arm64, gpr_x18_arm64, gpr_x19_arm64, + gpr_x20_arm64, gpr_x21_arm64, gpr_x22_arm64, gpr_x23_arm64, + gpr_x24_arm64, gpr_x25_arm64, gpr_x26_arm64, gpr_x27_arm64, + gpr_x28_arm64, gpr_fp_arm64, gpr_lr_arm64, gpr_sp_arm64, + gpr_pc_arm64, gpr_cpsr_arm64, sve_vg_arm64, LLDB_INVALID_REGNUM}; +static_assert( + ((sizeof g_expedited_regnums_arm64_sve / + sizeof g_expedited_regnums_arm64_sve[0]) - + 1) == k_num_expedited_registers_arm64_sve, + "g_expedited_regnums_arm64_sve has wrong number of register infos"); + // Register sets for ARM64. static const 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}}; + +// AArch64 SVE expedited registers set +static const RegisterSet g_expedited_reg_sets_arm64_sve = { + "General Purpose Registers", "expedited", + k_num_expedited_registers_arm64_sve, g_expedited_regnums_arm64_sve}; std::unique_ptr NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( @@ -131,12 +181,15 @@ 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: llvm_unreachable("Unhandled target architecture."); @@ -155,15 +208,26 @@ m_gpr_is_valid = false; m_fpu_is_valid = false; + m_sve_data_is_valid = false; + + m_sve_header_is_valid = false; + + // SVE is not enabled until we query user_sve_header + m_sve_state = SVE_STATE::SVE_STATE_UNKNOWN; } uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const { - return k_num_register_sets; + if (m_sve_state == SVE_STATE::SVE_STATE_FPSIMD || + m_sve_state == SVE_STATE::SVE_STATE_FULL) + + return k_num_register_sets; + else + return k_num_register_sets - 1; } const RegisterSet * NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const { - if (set_index < k_num_register_sets) + if (set_index < GetRegisterSetCount()) return &g_reg_sets_arm64[set_index]; return nullptr; @@ -171,7 +235,7 @@ uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const { uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) + for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) count += g_reg_sets_arm64[set_index].num_registers; return count; } @@ -217,6 +281,26 @@ offset = CalculateFprOffset(reg_info); assert(offset < GetFPRSize()); src = (uint8_t *)GetFPRBuffer() + offset; + } else if (IsVG(reg)) { + if (!m_sve_header_is_valid) { + + error = ReadSVEHeader(); + if (error.Fail()) + return error; + } + offset = CalculateSVEOffset(reg_info); + assert(offset < GetSVEHeaderSize()); + src = (uint8_t *)GetSVEHeader() + offset; + } else if (IsSVE(reg)) { + if (!m_sve_data_is_valid) { + + error = ReadAllSVE(); + if (error.Fail()) + return error; + } + offset = CalculateSVEOffset(reg_info); + assert(offset < GetSVEBufferSize()); + src = (uint8_t *)GetSVEBuffer() + offset; } else return Status("failed - register wasn't recognized to be a GPR or an FPR, " "write strategy unknown"); @@ -265,12 +349,34 @@ return error; } offset = CalculateFprOffset(reg_info); + assert(offset < GetSVEHeaderSize()); + dst = (uint8_t *)GetSVEHeader() + offset; + + ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); + + return WriteFPR(); + } else if (IsVG(reg)) { + + offset = CalculateSVEOffset(reg_info); assert(offset < GetFPRSize()); dst = (uint8_t *)GetFPRBuffer() + offset; ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); - return WriteFPR(); + return WriteSVEHeader(); + } else if (IsSVE(reg)) { + if (!m_fpu_is_valid) { + error = ReadFPR(); + if (error.Fail()) + return error; + } + offset = CalculateSVEOffset(reg_info); + assert(offset < GetSVEBufferSize()); + dst = (uint8_t *)GetSVEBuffer() + offset; + + ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); + + return WriteAllSVE(); } return error; @@ -351,6 +457,14 @@ return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); } +bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const { + return (m_reg_info.first_sve <= reg && reg <= m_reg_info.last_sve); +} + +bool NativeRegisterContextLinux_arm64::IsVG(unsigned reg) const { + return (m_reg_info.first_fpr == reg); +} + uint32_t NativeRegisterContextLinux_arm64::NumSupportedHardwareBreakpoints() { Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS)); @@ -893,15 +1007,120 @@ return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET); } +Status NativeRegisterContextLinux_arm64::ReadSVEHeader() { + Status error; + + struct iovec ioVec; + + ioVec.iov_base = GetSVEHeader(); + ioVec.iov_len = GetSVEHeaderSize(); + + error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); + + if (error.Success()) { + 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; + } else + m_sve_state = SVE_STATE::SVE_STATE_DISABLED; + + m_sve_header_is_valid = true; + + return error; +} + +Status NativeRegisterContextLinux_arm64::WriteSVEHeader() { + Status error; + + error = ReadSVEHeader(); + + if (ReadSVEHeader().Fail()) + return error; + + struct iovec ioVec; + + ioVec.iov_base = GetSVEHeader(); + ioVec.iov_len = GetSVEHeaderSize(); + + return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); +} + +Status NativeRegisterContextLinux_arm64::ReadAllSVE() { + Status error; + + struct iovec ioVec; + + ioVec.iov_base = GetSVEBuffer(); + ioVec.iov_len = GetSVEBufferSize(); + + error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); + + if (error.Success()) + m_sve_data_is_valid = true; + + return error; +} + +Status NativeRegisterContextLinux_arm64::WriteAllSVE() { + Status error; + + m_sve_header_is_valid = false; + m_sve_data_is_valid = false; + + error = ReadSVEHeader(); + + if (ReadSVEHeader().Fail()) + return error; + + struct iovec ioVec; + + ioVec.iov_base = GetSVEHeader(); + ioVec.iov_len = GetSVEHeaderSize(); + + return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE); +} + void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() { m_gpr_is_valid = false; m_fpu_is_valid = false; + m_sve_data_is_valid = false; + m_sve_header_is_valid = false; } +void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { + bool set_mode = false; + if (m_sve_state == SVE_STATE::SVE_STATE_UNKNOWN) + set_mode = true; + + if (!m_sve_header_is_valid && m_sve_state != SVE_STATE::SVE_STATE_DISABLED) + ReadSVEHeader(); + + if (set_mode && m_sve_state != SVE_STATE::SVE_STATE_DISABLED) + SetRegisterInfoMode(eRegisterInfoModeAArch64SVE); +} + +size_t NativeRegisterContextLinux_arm64::GetSVEBufferSize() { return 0; } + uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset( const RegisterInfo *reg_info) const { return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; } +uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset( + const RegisterInfo *reg_info) const { + return reg_info->byte_offset - + GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset; +} + +const RegisterSet * +NativeRegisterContextLinux_arm64::GetExpeditedRegisterSet() const { + if (m_sve_state == SVE_STATE::SVE_STATE_FPSIMD || + m_sve_state == SVE_STATE::SVE_STATE_FULL) + return &g_expedited_reg_sets_arm64_sve; + else + return &g_reg_sets_arm64[0]; +} + #endif // defined (__arm64__) || defined (__aarch64__) Index: lldb/source/Plugins/Process/Linux/NativeThreadLinux.h =================================================================== --- lldb/source/Plugins/Process/Linux/NativeThreadLinux.h +++ lldb/source/Plugins/Process/Linux/NativeThreadLinux.h @@ -39,6 +39,9 @@ std::string &description) override; NativeRegisterContextLinux &GetRegisterContext() override { + if (m_reg_context_up && IsStopped(nullptr)) + m_reg_context_up->ConfigureRegisterContext(); + return *m_reg_context_up; } Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h =================================================================== --- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -63,6 +63,8 @@ void Clear(); + bool IsPerThreadRegInfo(); + protected: // Classes that inherit from DynamicRegisterInfo can see and modify these typedef std::vector reg_collection; @@ -89,5 +91,6 @@ size_t m_reg_data_byte_size = 0u; // The number of bytes required to store // all registers bool m_finalized = false; + bool m_per_thread_reginfo = false; }; #endif // lldb_DynamicRegisterInfo_h_ Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -533,6 +533,17 @@ } } + // Create per thread reginfo to support AArch64 SVE dynamic register sizes. + if (arch.GetMachine() == llvm::Triple::aarch64 || + arch.GetMachine() == llvm::Triple::aarch64_be) { + for (const auto ® : m_regs) { + if (strcmp(reg.name, "vg") == 0) { + m_per_thread_reginfo = true; + break; + } + } + } + if (!generic_regs_specified) { switch (arch.GetMachine()) { case llvm::Triple::aarch64: @@ -682,9 +693,12 @@ m_invalidate_regs_map.clear(); m_dynamic_reg_size_map.clear(); m_reg_data_byte_size = 0; + m_per_thread_reginfo = false; m_finalized = false; } +bool DynamicRegisterInfo::IsPerThreadRegInfo() { return m_per_thread_reginfo; } + void DynamicRegisterInfo::Dump() const { StreamFile s(stdout, false); const size_t num_regs = m_regs.size(); 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/RegisterInfoInterface.h =================================================================== --- lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h +++ lldb/source/Plugins/Process/Utility/RegisterInfoInterface.h @@ -61,6 +61,10 @@ return nullptr; } + virtual uint32_t SetRegisterInfoMode(uint32_t mode) { 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 @@ -13,6 +13,13 @@ #include "lldb/Target/RegisterContext.h" #include "lldb/lldb-private.h" +// AArch64 Register set FP/SIMD feature configuration +enum { + eRegisterInfoModeAArch64, + eRegisterInfoModeAArch64SVE, + eRegisterInfoModeAArch64SVEMax = 256 +}; + class RegisterInfoPOSIX_arm64 : public lldb_private::RegisterInfoInterface { public: // based on RegisterContextDarwin_arm64.h @@ -61,7 +68,13 @@ uint32_t GetRegisterCount() const override; + uint32_t SetRegisterInfoMode(uint32_t mode) override; + + uint32_t GetRegisterInfoMode() const override; + private: + uint32_t m_reg_info_mode = UINT32_MAX; + std::vector d_register_infos; 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,6 +25,37 @@ (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm64::FPU, reg) + \ sizeof(RegisterInfoPOSIX_arm64::GPR)) +// This information is based on AArch64 with SVE architecture reference. +// Some parts are based on SVE implementation by Linux Ptrace interface. + +// 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. +#define SVE_NUM_ZREGS 32 +#define SVE_NUM_PREGS 16 + +// 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. +// We assume a default vector length of 1 for initializing register infos. +#define SVE_VECTOR_LENGTH_DEFAULT 1 + +#define SVE_ZREG_SIZE (SVE_VECTOR_LENGTH_DEFAULT * SVE_QUAD_WORD_BYTES) +#define SVE_PREG_SIZE (SVE_ZREG_SIZE / 8) + +// Linux defines a 16-byte header at the start of its SVE data payload. +// This header contains information about currently enabled SVE configuration. +// We declare a 16-byte header as the start of SVE data for sanity purpose. +// This will be updated once register context reads actual SVE configuration. +#define SVE_LINUX_USER_HEADER 16 +#define SVE_OFFSET_VG 0 +#define SVE_ZREGS_OFFSET SVE_LINUX_USER_HEADER +#define SVE_ZREG_OFFSET(idx) (SVE_ZREGS_OFFSET + (SVE_ZREG_SIZE * (idx))) +#define SVE_PREGS_OFFSET (SVE_ZREGS_OFFSET + (SVE_ZREG_SIZE * SVE_NUM_ZREGS)) +#define SVE_PREG_OFFSET(idx) (SVE_PREGS_OFFSET + (SVE_PREG_SIZE * (idx))) + #define EXC_OFFSET_NAME(reg) \ (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm64::EXC, reg) + \ sizeof(RegisterInfoPOSIX_arm64::GPR) + \ @@ -50,8 +81,11 @@ // Include RegisterInfos_arm64 to declare our g_register_infos_arm64 structure. #define DECLARE_REGISTER_INFOS_ARM64_STRUCT +#define DECLARE_REGISTER_INFOS_ARM64_SVE_STRUCT #include "RegisterInfos_arm64.h" +#include "RegisterInfos_arm64_sve.h" #undef DECLARE_REGISTER_INFOS_ARM64_STRUCT +#undef DECLARE_REGISTER_INFOS_ARM64_SVE_STRUCT static const lldb_private::RegisterInfo * GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { @@ -96,3 +130,54 @@ uint32_t RegisterInfoPOSIX_arm64::GetRegisterCount() const { return m_register_info_count; } + +uint32_t RegisterInfoPOSIX_arm64::SetRegisterInfoMode(uint32_t mode) { + // 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 (m_reg_info_mode == eRegisterInfoModeAArch64 || m_reg_info_mode == mode || + mode > eRegisterInfoModeAArch64SVEMax) + return m_reg_info_mode; + + // If this is first valid call to SetRegisterInfoMode, select SVE if needed. + if (m_reg_info_mode == UINT32_MAX) { + // SelectAArch64 without SVE and return with eRegisterInfoModeAArch64 + if (mode == eRegisterInfoModeAArch64) { + m_reg_info_mode = eRegisterInfoModeAArch64; + return m_reg_info_mode; + } + + m_register_info_count = + static_cast(sizeof(g_register_infos_arm64_sve_le) / + sizeof(g_register_infos_arm64_sve_le[0])); + d_register_infos = std::vector( + g_register_infos_arm64_sve_le, + g_register_infos_arm64_sve_le + m_register_info_count); + m_register_info_p = &d_register_infos[0]; + } + + m_reg_info_mode = mode; + + // Update Z registers size and offset + uint32_t offset = 0; + for (uint32_t it = sve_z0; it <= sve_z31; it++) { + d_register_infos[it].byte_size = mode * SVE_QUAD_WORD_BYTES; + d_register_infos[it].byte_offset = offset; + offset += d_register_infos[it].byte_size; + } + + // Update P registers and FFR size and offset + for (uint32_t it = sve_p0; it <= sve_ffr; it++) { + d_register_infos[it].byte_size = mode * SVE_QUAD_WORD_BYTES / 8; + d_register_infos[it].byte_offset = offset; + offset += d_register_infos[it].byte_size; + } + + 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,9 +294,98 @@ dbg_wcr14, dbg_wcr15, +#ifdef DECLARE_REGISTER_INFOS_ARM64_SVE_STRUCT + sve_fpsr = fpu_fpsr, + sve_fpcr = fpu_fpcr, + + sve_vg = dbg_wcr15 + 1, + + 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, + +#endif k_num_registers }; +static uint32_t g_x0_invalidates[] = {gpr_w0, LLDB_INVALID_REGNUM}; +static uint32_t g_x1_invalidates[] = {gpr_w1, LLDB_INVALID_REGNUM}; +static uint32_t g_x2_invalidates[] = {gpr_w2, LLDB_INVALID_REGNUM}; +static uint32_t g_x3_invalidates[] = {gpr_w3, LLDB_INVALID_REGNUM}; +static uint32_t g_x4_invalidates[] = {gpr_w4, LLDB_INVALID_REGNUM}; +static uint32_t g_x5_invalidates[] = {gpr_w5, LLDB_INVALID_REGNUM}; +static uint32_t g_x6_invalidates[] = {gpr_w6, LLDB_INVALID_REGNUM}; +static uint32_t g_x7_invalidates[] = {gpr_w7, LLDB_INVALID_REGNUM}; +static uint32_t g_x8_invalidates[] = {gpr_w8, LLDB_INVALID_REGNUM}; +static uint32_t g_x9_invalidates[] = {gpr_w9, LLDB_INVALID_REGNUM}; +static uint32_t g_x10_invalidates[] = {gpr_w10, LLDB_INVALID_REGNUM}; +static uint32_t g_x11_invalidates[] = {gpr_w11, LLDB_INVALID_REGNUM}; +static uint32_t g_x12_invalidates[] = {gpr_w12, LLDB_INVALID_REGNUM}; +static uint32_t g_x13_invalidates[] = {gpr_w13, LLDB_INVALID_REGNUM}; +static uint32_t g_x14_invalidates[] = {gpr_w14, LLDB_INVALID_REGNUM}; +static uint32_t g_x15_invalidates[] = {gpr_w15, LLDB_INVALID_REGNUM}; +static uint32_t g_x16_invalidates[] = {gpr_w16, LLDB_INVALID_REGNUM}; +static uint32_t g_x17_invalidates[] = {gpr_w17, LLDB_INVALID_REGNUM}; +static uint32_t g_x18_invalidates[] = {gpr_w18, LLDB_INVALID_REGNUM}; +static uint32_t g_x19_invalidates[] = {gpr_w19, LLDB_INVALID_REGNUM}; +static uint32_t g_x20_invalidates[] = {gpr_w20, LLDB_INVALID_REGNUM}; +static uint32_t g_x21_invalidates[] = {gpr_w21, LLDB_INVALID_REGNUM}; +static uint32_t g_x22_invalidates[] = {gpr_w22, LLDB_INVALID_REGNUM}; +static uint32_t g_x23_invalidates[] = {gpr_w23, LLDB_INVALID_REGNUM}; +static uint32_t g_x24_invalidates[] = {gpr_w24, LLDB_INVALID_REGNUM}; +static uint32_t g_x25_invalidates[] = {gpr_w25, LLDB_INVALID_REGNUM}; +static uint32_t g_x26_invalidates[] = {gpr_w26, LLDB_INVALID_REGNUM}; +static uint32_t g_x27_invalidates[] = {gpr_w27, LLDB_INVALID_REGNUM}; +static uint32_t g_x28_invalidates[] = {gpr_w28, LLDB_INVALID_REGNUM}; + static uint32_t g_contained_x0[] = {gpr_x0, LLDB_INVALID_REGNUM}; static uint32_t g_contained_x1[] = {gpr_x1, LLDB_INVALID_REGNUM}; static uint32_t g_contained_x2[] = {gpr_x2, LLDB_INVALID_REGNUM}; @@ -456,6 +545,38 @@ static uint32_t g_d30_invalidates[] = {fpu_v30, fpu_s30, LLDB_INVALID_REGNUM}; static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; +static uint32_t g_v0_invalidates[] = {fpu_d0, fpu_s0, LLDB_INVALID_REGNUM}; +static uint32_t g_v1_invalidates[] = {fpu_d1, fpu_s1, LLDB_INVALID_REGNUM}; +static uint32_t g_v2_invalidates[] = {fpu_d2, fpu_s2, LLDB_INVALID_REGNUM}; +static uint32_t g_v3_invalidates[] = {fpu_d3, fpu_s3, LLDB_INVALID_REGNUM}; +static uint32_t g_v4_invalidates[] = {fpu_d4, fpu_s4, LLDB_INVALID_REGNUM}; +static uint32_t g_v5_invalidates[] = {fpu_d5, fpu_s5, LLDB_INVALID_REGNUM}; +static uint32_t g_v6_invalidates[] = {fpu_d6, fpu_s6, LLDB_INVALID_REGNUM}; +static uint32_t g_v7_invalidates[] = {fpu_d7, fpu_s7, LLDB_INVALID_REGNUM}; +static uint32_t g_v8_invalidates[] = {fpu_d8, fpu_s8, LLDB_INVALID_REGNUM}; +static uint32_t g_v9_invalidates[] = {fpu_d9, fpu_s9, LLDB_INVALID_REGNUM}; +static uint32_t g_v10_invalidates[] = {fpu_d10, fpu_s10, LLDB_INVALID_REGNUM}; +static uint32_t g_v11_invalidates[] = {fpu_d11, fpu_s11, LLDB_INVALID_REGNUM}; +static uint32_t g_v12_invalidates[] = {fpu_d12, fpu_s12, LLDB_INVALID_REGNUM}; +static uint32_t g_v13_invalidates[] = {fpu_d13, fpu_s13, LLDB_INVALID_REGNUM}; +static uint32_t g_v14_invalidates[] = {fpu_d14, fpu_s14, LLDB_INVALID_REGNUM}; +static uint32_t g_v15_invalidates[] = {fpu_d15, fpu_s15, LLDB_INVALID_REGNUM}; +static uint32_t g_v16_invalidates[] = {fpu_d16, fpu_s16, LLDB_INVALID_REGNUM}; +static uint32_t g_v17_invalidates[] = {fpu_d17, fpu_s17, LLDB_INVALID_REGNUM}; +static uint32_t g_v18_invalidates[] = {fpu_d18, fpu_s18, LLDB_INVALID_REGNUM}; +static uint32_t g_v19_invalidates[] = {fpu_d19, fpu_s19, LLDB_INVALID_REGNUM}; +static uint32_t g_v20_invalidates[] = {fpu_d20, fpu_s20, LLDB_INVALID_REGNUM}; +static uint32_t g_v21_invalidates[] = {fpu_d21, fpu_s21, LLDB_INVALID_REGNUM}; +static uint32_t g_v22_invalidates[] = {fpu_d22, fpu_s22, LLDB_INVALID_REGNUM}; +static uint32_t g_v23_invalidates[] = {fpu_d23, fpu_s23, LLDB_INVALID_REGNUM}; +static uint32_t g_v24_invalidates[] = {fpu_d24, fpu_s24, LLDB_INVALID_REGNUM}; +static uint32_t g_v25_invalidates[] = {fpu_d25, fpu_s25, LLDB_INVALID_REGNUM}; +static uint32_t g_v26_invalidates[] = {fpu_d26, fpu_s26, LLDB_INVALID_REGNUM}; +static uint32_t g_v27_invalidates[] = {fpu_d27, fpu_s27, LLDB_INVALID_REGNUM}; +static uint32_t g_v28_invalidates[] = {fpu_d28, fpu_s28, LLDB_INVALID_REGNUM}; +static uint32_t g_v29_invalidates[] = {fpu_d29, fpu_s29, LLDB_INVALID_REGNUM}; +static uint32_t g_v30_invalidates[] = {fpu_d30, fpu_s30, LLDB_INVALID_REGNUM}; +static uint32_t g_v31_invalidates[] = {fpu_d31, fpu_s31, LLDB_INVALID_REGNUM}; // Generates register kinds array for 64-bit general purpose registers #define GPR64_KIND(reg, generic_kind) \ { \ @@ -470,38 +591,29 @@ LLDB_INVALID_REGNUM, lldb_kind \ } -// Generates register kinds array for vector registers -#define VREG_KIND(reg) \ +// Generates register kinds array with dwarf, ehframe, generic and lldb kind +#define MISC_KIND_GENERIC(reg, type, generic_kind) \ { \ - LLDB_INVALID_REGNUM, arm64_dwarf::reg, LLDB_INVALID_REGNUM, \ - LLDB_INVALID_REGNUM, fpu_##reg \ + arm64_ehframe::reg, arm64_dwarf::reg, generic_kind, LLDB_INVALID_REGNUM, \ + type##_##reg \ } // Generates register kinds array for cpsr -#define CPSR_KIND(lldb_kind) \ - { \ - arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, \ - LLDB_INVALID_REGNUM, lldb_kind \ - } +#define MISC_CPSR_KIND(lldb_kind) \ + MISC_KIND_GENERIC(cpsr, gpr, LLDB_REGNUM_GENERIC_FLAGS) +#define CPSR_OFFSET_NAME(reg) GPR_OFFSET_NAME(reg) #define MISC_GPR_KIND(lldb_kind) CPSR_KIND(lldb_kind) #define MISC_FPU_KIND(lldb_kind) MISC_KIND(lldb_kind) #define MISC_EXC_KIND(lldb_kind) MISC_KIND(lldb_kind) +#define VREG_KIND(vreg) MISC_KIND_GENERIC(vreg, fpu, LLDB_INVALID_REGNUM) // Defines a 64-bit general purpose register -#define DEFINE_GPR64(reg, generic_kind) \ +#define DEFINE_GPR64(reg, alt_name, generic_kind, invalidate_list) \ { \ - #reg, nullptr, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint, \ - lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr, nullptr, \ - nullptr, 0 \ - } - -// Defines a 64-bit general purpose register -#define DEFINE_GPR64_ALT(reg, alt, generic_kind) \ - { \ - #reg, #alt, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint, \ - lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr, nullptr, \ - nullptr, 0 \ + #reg, alt_name, 8, GPR_OFFSET(gpr_##reg), lldb::eEncodingUint, \ + lldb::eFormatHex, GPR64_KIND(reg, generic_kind), nullptr, \ + invalidate_list, nullptr, 0 \ } // Defines a 32-bit general purpose pseudo register @@ -517,8 +629,8 @@ #define DEFINE_VREG(reg) \ { \ #reg, nullptr, 16, FPU_OFFSET(fpu_##reg - fpu_v0), lldb::eEncodingVector, \ - lldb::eFormatVectorOfUInt8, VREG_KIND(reg), nullptr, nullptr, nullptr, \ - 0 \ + lldb::eFormatVectorOfUInt8, VREG_KIND(reg), nullptr, \ + g_##reg##_invalidates, nullptr, 0 \ } // Defines S and D pseudo registers mapping over correspondig vector register @@ -537,45 +649,48 @@ nullptr, 0 \ } +#define STRINGIZE2(x) #x +#define STRINGIZE(x) STRINGIZE2(x) + static lldb_private::RegisterInfo g_register_infos_arm64_le[] = { // 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(x0, nullptr, LLDB_REGNUM_GENERIC_ARG1, g_x0_invalidates), + DEFINE_GPR64(x1, nullptr, LLDB_REGNUM_GENERIC_ARG2, g_x1_invalidates), + DEFINE_GPR64(x2, nullptr, LLDB_REGNUM_GENERIC_ARG3, g_x2_invalidates), + DEFINE_GPR64(x3, nullptr, LLDB_REGNUM_GENERIC_ARG4, g_x3_invalidates), + DEFINE_GPR64(x4, nullptr, LLDB_REGNUM_GENERIC_ARG5, g_x4_invalidates), + DEFINE_GPR64(x5, nullptr, LLDB_REGNUM_GENERIC_ARG6, g_x5_invalidates), + DEFINE_GPR64(x6, nullptr, LLDB_REGNUM_GENERIC_ARG7, g_x6_invalidates), + DEFINE_GPR64(x7, nullptr, LLDB_REGNUM_GENERIC_ARG8, g_x7_invalidates), + DEFINE_GPR64(x8, nullptr, LLDB_INVALID_REGNUM, g_x8_invalidates), + DEFINE_GPR64(x9, nullptr, LLDB_INVALID_REGNUM, g_x9_invalidates), + DEFINE_GPR64(x10, nullptr, LLDB_INVALID_REGNUM, g_x10_invalidates), + DEFINE_GPR64(x11, nullptr, LLDB_INVALID_REGNUM, g_x11_invalidates), + DEFINE_GPR64(x12, nullptr, LLDB_INVALID_REGNUM, g_x12_invalidates), + DEFINE_GPR64(x13, nullptr, LLDB_INVALID_REGNUM, g_x13_invalidates), + DEFINE_GPR64(x14, nullptr, LLDB_INVALID_REGNUM, g_x14_invalidates), + DEFINE_GPR64(x15, nullptr, LLDB_INVALID_REGNUM, g_x15_invalidates), + DEFINE_GPR64(x16, nullptr, LLDB_INVALID_REGNUM, g_x16_invalidates), + DEFINE_GPR64(x17, nullptr, LLDB_INVALID_REGNUM, g_x17_invalidates), + DEFINE_GPR64(x18, nullptr, LLDB_INVALID_REGNUM, g_x18_invalidates), + DEFINE_GPR64(x19, nullptr, LLDB_INVALID_REGNUM, g_x19_invalidates), + DEFINE_GPR64(x20, nullptr, LLDB_INVALID_REGNUM, g_x20_invalidates), + DEFINE_GPR64(x21, nullptr, LLDB_INVALID_REGNUM, g_x21_invalidates), + DEFINE_GPR64(x22, nullptr, LLDB_INVALID_REGNUM, g_x22_invalidates), + DEFINE_GPR64(x23, nullptr, LLDB_INVALID_REGNUM, g_x23_invalidates), + DEFINE_GPR64(x24, nullptr, LLDB_INVALID_REGNUM, g_x24_invalidates), + DEFINE_GPR64(x25, nullptr, LLDB_INVALID_REGNUM, g_x25_invalidates), + DEFINE_GPR64(x26, nullptr, LLDB_INVALID_REGNUM, g_x26_invalidates), + DEFINE_GPR64(x27, nullptr, LLDB_INVALID_REGNUM, g_x27_invalidates), + DEFINE_GPR64(x28, nullptr, LLDB_INVALID_REGNUM, g_x28_invalidates), // 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_GPR64(fp, STRINGIZE(x29), LLDB_REGNUM_GENERIC_FP, nullptr), + DEFINE_GPR64(lr, STRINGIZE(x30), LLDB_REGNUM_GENERIC_RA, nullptr), + DEFINE_GPR64(sp, STRINGIZE(x31), LLDB_REGNUM_GENERIC_SP, nullptr), + DEFINE_GPR64(pc, nullptr, LLDB_REGNUM_GENERIC_PC, nullptr), // DEFINE_MISC_REGS(name, size, TYPE, lldb kind) - DEFINE_MISC_REGS(cpsr, 4, GPR, gpr_cpsr), + DEFINE_MISC_REGS(cpsr, 4, CPSR, gpr_cpsr), // DEFINE_GPR32(name, parent name) DEFINE_GPR32(w0, x0), Index: lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/Utility/RegisterInfos_arm64_sve.h @@ -0,0 +1,519 @@ +//===-- 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_SVE_STRUCT + +#ifndef SVE_ZREG_OFFSET +#error SVE_ZREG_OFFSET must be defined before including this header file +#endif + +#ifndef SVE_PREG_OFFSET +#error SVE_PREG_OFFSET must be defined before including this header file +#endif + +#ifndef SVE_OFFSET_VG +#error SVE_OFFSET_VG must be defined before including this header file +#endif + +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}; + +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}; + +#define VG_OFFSET_NAME(reg) SVE_OFFSET_VG + +#define SVE_REG_KIND(reg) MISC_KIND_GENERIC(reg, sve, LLDB_INVALID_REGNUM) +#define MISC_VG_KIND(lldb_kind) MISC_KIND_GENERIC(vg, sve, LLDB_INVALID_REGNUM) + +// Defines sve pseudo vector (V) register with 16-byte size +#define DEFINE_VREG_SVE(vreg, zreg) \ + { \ + #vreg, nullptr, 16, SVE_ZREG_OFFSET(sve_##zreg - sve_z0), \ + lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, VREG_KIND(vreg), \ + g_contained_##zreg, g_sve_##vreg##_invalidates, nullptr, 0 \ + } + +// Defines a Z vector register with 16-byte default size +#define DEFINE_ZREG(reg) \ + { \ + #reg, nullptr, SVE_ZREG_SIZE, SVE_ZREG_OFFSET(sve_##reg - sve_z0), \ + 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, SVE_PREG_SIZE, SVE_PREG_OFFSET(sve_##reg - sve_p0), \ + lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, SVE_REG_KIND(reg), \ + nullptr, nullptr, nullptr, 0 \ + } + +static lldb_private::RegisterInfo g_register_infos_arm64_sve_le[] = { + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64(x0, nullptr, LLDB_REGNUM_GENERIC_ARG1, g_x0_invalidates), + DEFINE_GPR64(x1, nullptr, LLDB_REGNUM_GENERIC_ARG2, g_x1_invalidates), + DEFINE_GPR64(x2, nullptr, LLDB_REGNUM_GENERIC_ARG3, g_x2_invalidates), + DEFINE_GPR64(x3, nullptr, LLDB_REGNUM_GENERIC_ARG4, g_x3_invalidates), + DEFINE_GPR64(x4, nullptr, LLDB_REGNUM_GENERIC_ARG5, g_x4_invalidates), + DEFINE_GPR64(x5, nullptr, LLDB_REGNUM_GENERIC_ARG6, g_x5_invalidates), + DEFINE_GPR64(x6, nullptr, LLDB_REGNUM_GENERIC_ARG7, g_x6_invalidates), + DEFINE_GPR64(x7, nullptr, LLDB_REGNUM_GENERIC_ARG8, g_x7_invalidates), + DEFINE_GPR64(x8, nullptr, LLDB_INVALID_REGNUM, g_x8_invalidates), + DEFINE_GPR64(x9, nullptr, LLDB_INVALID_REGNUM, g_x9_invalidates), + DEFINE_GPR64(x10, nullptr, LLDB_INVALID_REGNUM, g_x10_invalidates), + DEFINE_GPR64(x11, nullptr, LLDB_INVALID_REGNUM, g_x11_invalidates), + DEFINE_GPR64(x12, nullptr, LLDB_INVALID_REGNUM, g_x12_invalidates), + DEFINE_GPR64(x13, nullptr, LLDB_INVALID_REGNUM, g_x13_invalidates), + DEFINE_GPR64(x14, nullptr, LLDB_INVALID_REGNUM, g_x14_invalidates), + DEFINE_GPR64(x15, nullptr, LLDB_INVALID_REGNUM, g_x15_invalidates), + DEFINE_GPR64(x16, nullptr, LLDB_INVALID_REGNUM, g_x16_invalidates), + DEFINE_GPR64(x17, nullptr, LLDB_INVALID_REGNUM, g_x17_invalidates), + DEFINE_GPR64(x18, nullptr, LLDB_INVALID_REGNUM, g_x18_invalidates), + DEFINE_GPR64(x19, nullptr, LLDB_INVALID_REGNUM, g_x19_invalidates), + DEFINE_GPR64(x20, nullptr, LLDB_INVALID_REGNUM, g_x20_invalidates), + DEFINE_GPR64(x21, nullptr, LLDB_INVALID_REGNUM, g_x21_invalidates), + DEFINE_GPR64(x22, nullptr, LLDB_INVALID_REGNUM, g_x22_invalidates), + DEFINE_GPR64(x23, nullptr, LLDB_INVALID_REGNUM, g_x23_invalidates), + DEFINE_GPR64(x24, nullptr, LLDB_INVALID_REGNUM, g_x24_invalidates), + DEFINE_GPR64(x25, nullptr, LLDB_INVALID_REGNUM, g_x25_invalidates), + DEFINE_GPR64(x26, nullptr, LLDB_INVALID_REGNUM, g_x26_invalidates), + DEFINE_GPR64(x27, nullptr, LLDB_INVALID_REGNUM, g_x27_invalidates), + DEFINE_GPR64(x28, nullptr, LLDB_INVALID_REGNUM, g_x28_invalidates), + // DEFINE_GPR64(name, GENERIC KIND) + DEFINE_GPR64(fp, STRINGIZE(x29), LLDB_REGNUM_GENERIC_FP, nullptr), + DEFINE_GPR64(lr, STRINGIZE(x30), LLDB_REGNUM_GENERIC_RA, nullptr), + DEFINE_GPR64(sp, STRINGIZE(x31), LLDB_REGNUM_GENERIC_SP, nullptr), + DEFINE_GPR64(pc, nullptr, LLDB_REGNUM_GENERIC_PC, nullptr), + + // DEFINE_MISC_REGS(name, size, TYPE, lldb kind) + DEFINE_MISC_REGS(cpsr, 4, CPSR, 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(s0, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v0), + DEFINE_FPU_PSEUDO(s1, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v1), + DEFINE_FPU_PSEUDO(s2, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v2), + DEFINE_FPU_PSEUDO(s3, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v3), + DEFINE_FPU_PSEUDO(s4, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v4), + DEFINE_FPU_PSEUDO(s5, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v5), + DEFINE_FPU_PSEUDO(s6, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v6), + DEFINE_FPU_PSEUDO(s7, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v7), + DEFINE_FPU_PSEUDO(s8, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v8), + DEFINE_FPU_PSEUDO(s9, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v9), + DEFINE_FPU_PSEUDO(s10, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v10), + DEFINE_FPU_PSEUDO(s11, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v11), + DEFINE_FPU_PSEUDO(s12, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v12), + DEFINE_FPU_PSEUDO(s13, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v13), + DEFINE_FPU_PSEUDO(s14, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v14), + DEFINE_FPU_PSEUDO(s15, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v15), + DEFINE_FPU_PSEUDO(s16, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v16), + DEFINE_FPU_PSEUDO(s17, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v17), + DEFINE_FPU_PSEUDO(s18, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v18), + DEFINE_FPU_PSEUDO(s19, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v19), + DEFINE_FPU_PSEUDO(s20, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v20), + DEFINE_FPU_PSEUDO(s21, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v21), + DEFINE_FPU_PSEUDO(s22, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v22), + DEFINE_FPU_PSEUDO(s23, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v23), + DEFINE_FPU_PSEUDO(s24, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v24), + DEFINE_FPU_PSEUDO(s25, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v25), + DEFINE_FPU_PSEUDO(s26, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v26), + DEFINE_FPU_PSEUDO(s27, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v27), + DEFINE_FPU_PSEUDO(s28, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v28), + DEFINE_FPU_PSEUDO(s29, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v29), + DEFINE_FPU_PSEUDO(s30, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v30), + DEFINE_FPU_PSEUDO(s31, 4, FPU_S_PSEUDO_REG_ENDIAN_OFFSET, v31), + + DEFINE_FPU_PSEUDO(d0, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v0), + DEFINE_FPU_PSEUDO(d1, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v1), + DEFINE_FPU_PSEUDO(d2, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v2), + DEFINE_FPU_PSEUDO(d3, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v3), + DEFINE_FPU_PSEUDO(d4, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v4), + DEFINE_FPU_PSEUDO(d5, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v5), + DEFINE_FPU_PSEUDO(d6, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v6), + DEFINE_FPU_PSEUDO(d7, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v7), + DEFINE_FPU_PSEUDO(d8, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v8), + DEFINE_FPU_PSEUDO(d9, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v9), + DEFINE_FPU_PSEUDO(d10, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v10), + DEFINE_FPU_PSEUDO(d11, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v11), + DEFINE_FPU_PSEUDO(d12, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v12), + DEFINE_FPU_PSEUDO(d13, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v13), + DEFINE_FPU_PSEUDO(d14, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v14), + DEFINE_FPU_PSEUDO(d15, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v15), + DEFINE_FPU_PSEUDO(d16, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v16), + DEFINE_FPU_PSEUDO(d17, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v17), + DEFINE_FPU_PSEUDO(d18, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v18), + DEFINE_FPU_PSEUDO(d19, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v19), + DEFINE_FPU_PSEUDO(d20, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v20), + DEFINE_FPU_PSEUDO(d21, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v21), + DEFINE_FPU_PSEUDO(d22, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v22), + DEFINE_FPU_PSEUDO(d23, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v23), + DEFINE_FPU_PSEUDO(d24, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v24), + DEFINE_FPU_PSEUDO(d25, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v25), + DEFINE_FPU_PSEUDO(d26, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v26), + DEFINE_FPU_PSEUDO(d27, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v27), + DEFINE_FPU_PSEUDO(d28, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v28), + DEFINE_FPU_PSEUDO(d29, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v29), + DEFINE_FPU_PSEUDO(d30, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v30), + DEFINE_FPU_PSEUDO(d31, 8, FPU_D_PSEUDO_REG_ENDIAN_OFFSET, v31), + + // 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(far, 8, EXC, exc_far), + DEFINE_MISC_REGS(esr, 4, EXC, exc_esr), + DEFINE_MISC_REGS(exception, 4, EXC, exc_exception), + + {DEFINE_DBG(bvr, 0)}, + {DEFINE_DBG(bvr, 1)}, + {DEFINE_DBG(bvr, 2)}, + {DEFINE_DBG(bvr, 3)}, + {DEFINE_DBG(bvr, 4)}, + {DEFINE_DBG(bvr, 5)}, + {DEFINE_DBG(bvr, 6)}, + {DEFINE_DBG(bvr, 7)}, + {DEFINE_DBG(bvr, 8)}, + {DEFINE_DBG(bvr, 9)}, + {DEFINE_DBG(bvr, 10)}, + {DEFINE_DBG(bvr, 11)}, + {DEFINE_DBG(bvr, 12)}, + {DEFINE_DBG(bvr, 13)}, + {DEFINE_DBG(bvr, 14)}, + {DEFINE_DBG(bvr, 15)}, + + {DEFINE_DBG(bcr, 0)}, + {DEFINE_DBG(bcr, 1)}, + {DEFINE_DBG(bcr, 2)}, + {DEFINE_DBG(bcr, 3)}, + {DEFINE_DBG(bcr, 4)}, + {DEFINE_DBG(bcr, 5)}, + {DEFINE_DBG(bcr, 6)}, + {DEFINE_DBG(bcr, 7)}, + {DEFINE_DBG(bcr, 8)}, + {DEFINE_DBG(bcr, 9)}, + {DEFINE_DBG(bcr, 10)}, + {DEFINE_DBG(bcr, 11)}, + {DEFINE_DBG(bcr, 12)}, + {DEFINE_DBG(bcr, 13)}, + {DEFINE_DBG(bcr, 14)}, + {DEFINE_DBG(bcr, 15)}, + + {DEFINE_DBG(wvr, 0)}, + {DEFINE_DBG(wvr, 1)}, + {DEFINE_DBG(wvr, 2)}, + {DEFINE_DBG(wvr, 3)}, + {DEFINE_DBG(wvr, 4)}, + {DEFINE_DBG(wvr, 5)}, + {DEFINE_DBG(wvr, 6)}, + {DEFINE_DBG(wvr, 7)}, + {DEFINE_DBG(wvr, 8)}, + {DEFINE_DBG(wvr, 9)}, + {DEFINE_DBG(wvr, 10)}, + {DEFINE_DBG(wvr, 11)}, + {DEFINE_DBG(wvr, 12)}, + {DEFINE_DBG(wvr, 13)}, + {DEFINE_DBG(wvr, 14)}, + {DEFINE_DBG(wvr, 15)}, + + {DEFINE_DBG(wcr, 0)}, + {DEFINE_DBG(wcr, 1)}, + {DEFINE_DBG(wcr, 2)}, + {DEFINE_DBG(wcr, 3)}, + {DEFINE_DBG(wcr, 4)}, + {DEFINE_DBG(wcr, 5)}, + {DEFINE_DBG(wcr, 6)}, + {DEFINE_DBG(wcr, 7)}, + {DEFINE_DBG(wcr, 8)}, + {DEFINE_DBG(wcr, 9)}, + {DEFINE_DBG(wcr, 10)}, + {DEFINE_DBG(wcr, 11)}, + {DEFINE_DBG(wcr, 12)}, + {DEFINE_DBG(wcr, 13)}, + {DEFINE_DBG(wcr, 14)}, + {DEFINE_DBG(wcr, 15)}, + + 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)}; + +#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 @@ -255,9 +255,68 @@ dbg_wcr14_arm64, dbg_wcr15_arm64, + k_first_sve_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, + k_num_wgpr_registers_arm64 = gpr_w28_arm64 - gpr_w0_arm64 + 1, 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_num_sve_registers_arm64 = k_last_sve_arm64 - k_first_sve_arm64 + 1, + k_num_expedited_registers_arm64_sve = + k_num_gpr_registers_arm64 - k_num_wgpr_registers_arm64 + 1 }; } Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -713,11 +713,17 @@ // Grab the register context. NativeRegisterContext& reg_ctx = thread->GetRegisterContext(); - // Expedite all registers in the first register set (i.e. should be GPRs) - // that are not contained in other registers. - const RegisterSet *reg_set_p; - if (reg_ctx.GetRegisterSetCount() > 0 && - ((reg_set_p = reg_ctx.GetRegisterSet(0)) != nullptr)) { + const RegisterSet *reg_set_p = reg_ctx.GetExpeditedRegisterSet(); + + if (reg_set_p == nullptr) { + // Architecture does not specify an expedited register set. + // Expedite all registers in the first register set (i.e. should be GPRs) + // that are not contained in other registers. + if (reg_ctx.GetRegisterSetCount() > 0) + reg_set_p = reg_ctx.GetRegisterSet(0); + } + + if (reg_set_p != nullptr) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s expediting registers " "from set '%s' (registers set count: %zu)", Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -27,6 +27,10 @@ class ThreadGDBRemote; class ProcessGDBRemote; +class GDBRemoteDynamicRegisterInfo; + +typedef std::shared_ptr + GDBRemoteDynamicRegisterInfoSP; class GDBRemoteDynamicRegisterInfo : public DynamicRegisterInfo { public: @@ -35,12 +39,16 @@ ~GDBRemoteDynamicRegisterInfo() override = default; void HardcodeARMRegisters(bool from_scratch); + + bool UpdateARM64SVERegistersInfos(uint64_t vg); + + void CloneFrom(GDBRemoteDynamicRegisterInfoSP process_reginfo); }; class GDBRemoteRegisterContext : public RegisterContext { public: GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx, - GDBRemoteDynamicRegisterInfo ®_info, + GDBRemoteDynamicRegisterInfoSP reg_info, bool read_all_at_once, bool write_all_at_once); ~GDBRemoteRegisterContext() override; @@ -73,9 +81,13 @@ uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + bool UpdateDynamicRegisterInfo(); + protected: friend class ThreadGDBRemote; + void SetThreadRegisterInfo(GDBRemoteDynamicRegisterInfoSP process_reginfo); + bool ReadRegisterBytes(const RegisterInfo *reg_info, DataExtractor &data); bool WriteRegisterBytes(const RegisterInfo *reg_info, DataExtractor &data, @@ -110,7 +122,7 @@ m_reg_valid[reg] = valid; } - GDBRemoteDynamicRegisterInfo &m_reg_info; + GDBRemoteDynamicRegisterInfoSP m_reg_info_sp; std::vector m_reg_valid; DataExtractor m_reg_data; bool m_read_all_at_once; Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -31,19 +31,23 @@ // GDBRemoteRegisterContext constructor GDBRemoteRegisterContext::GDBRemoteRegisterContext( ThreadGDBRemote &thread, uint32_t concrete_frame_idx, - GDBRemoteDynamicRegisterInfo ®_info, bool read_all_at_once, + GDBRemoteDynamicRegisterInfoSP reg_info, bool read_all_at_once, bool write_all_at_once) - : RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info), - m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once), + : RegisterContext(thread, concrete_frame_idx), m_reg_valid(), m_reg_data(), + m_read_all_at_once(read_all_at_once), m_write_all_at_once(write_all_at_once) { // Resize our vector of bools to contain one bool for every register. We will // use these boolean values to know when a register value is valid in // m_reg_data. - m_reg_valid.resize(reg_info.GetNumRegisters()); + m_reg_valid.resize(reg_info->GetNumRegisters()); + + // At this point we can clone reg_info for architectures supporting + // run-time update to register sizes and offsets.. + SetThreadRegisterInfo(reg_info); // Make a heap based buffer that is big enough to store all registers DataBufferSP reg_data_sp( - new DataBufferHeap(reg_info.GetRegisterDataByteSize(), 0)); + new DataBufferHeap(reg_info->GetRegisterDataByteSize(), 0)); m_reg_data.SetData(reg_data_sp); m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder()); } @@ -51,6 +55,16 @@ // Destructor GDBRemoteRegisterContext::~GDBRemoteRegisterContext() {} +void GDBRemoteRegisterContext::SetThreadRegisterInfo( + GDBRemoteDynamicRegisterInfoSP process_reginfo) { + if (!process_reginfo->IsPerThreadRegInfo()) + m_reg_info_sp = process_reginfo; + else { + m_reg_info_sp = std::make_shared(); + m_reg_info_sp->CloneFrom(process_reginfo); + } +} + void GDBRemoteRegisterContext::InvalidateAllRegisters() { SetAllRegisterValid(false); } @@ -62,12 +76,12 @@ } size_t GDBRemoteRegisterContext::GetRegisterCount() { - return m_reg_info.GetNumRegisters(); + return m_reg_info_sp->GetNumRegisters(); } const RegisterInfo * GDBRemoteRegisterContext::GetRegisterInfoAtIndex(size_t reg) { - RegisterInfo *reg_info = m_reg_info.GetRegisterInfoAtIndex(reg); + RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfoAtIndex(reg); if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes) { const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture(); @@ -78,11 +92,11 @@ } size_t GDBRemoteRegisterContext::GetRegisterSetCount() { - return m_reg_info.GetNumRegisterSets(); + return m_reg_info_sp->GetNumRegisterSets(); } const RegisterSet *GDBRemoteRegisterContext::GetRegisterSet(size_t reg_set) { - return m_reg_info.GetRegisterSet(reg_set); + return m_reg_info_sp->GetRegisterSet(reg_set); } bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info, @@ -209,9 +223,10 @@ SetAllRegisterValid(true); return true; } else if (buffer_sp->GetByteSize() > 0) { - const int regcount = m_reg_info.GetNumRegisters(); + const int regcount = m_reg_info_sp->GetNumRegisters(); for (int i = 0; i < regcount; i++) { - struct RegisterInfo *reginfo = m_reg_info.GetRegisterInfoAtIndex(i); + struct RegisterInfo *reginfo = + m_reg_info_sp->GetRegisterInfoAtIndex(i); if (reginfo->byte_offset + reginfo->byte_size <= buffer_sp->GetByteSize()) { m_reg_valid[i] = true; @@ -506,7 +521,7 @@ // m_reg_data buffer } data_sp = std::make_shared( - m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize()); + m_reg_data.GetDataStart(), m_reg_info_sp->GetRegisterDataByteSize()); return true; } else { @@ -708,7 +723,53 @@ uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber( lldb::RegisterKind kind, uint32_t num) { - return m_reg_info.ConvertRegisterKindToRegisterNumber(kind, num); + return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num); +} + +bool GDBRemoteRegisterContext::UpdateDynamicRegisterInfo(void) { + if (!m_reg_info_sp || !m_reg_info_sp->IsPerThreadRegInfo()) + return false; + + const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture(); + if (arch.IsValid() && (arch.GetMachine() == llvm::Triple::aarch64)) { + uint8_t arm64_sve_vg_dwarf_regnum = 46; + uint32_t reg = ConvertRegisterKindToRegisterNumber( + eRegisterKindDWARF, arm64_sve_vg_dwarf_regnum); + uint64_t fail_value = LLDB_INVALID_ADDRESS; + uint64_t vg = ReadRegisterAsUnsigned(reg, fail_value); + + if (vg != fail_value && vg <= 32) { + return m_reg_info_sp->UpdateARM64SVERegistersInfos(vg); + } + } + return false; +} + +bool GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(uint64_t vg) { + for (auto ® : m_regs) { + if (reg.name[0] == 'z') + reg.byte_size = vg * 8; + else if (reg.name[0] == 'p') + reg.byte_size = vg; + else if (strcmp(reg.name, "ffr") == 0) + reg.byte_size = vg; + } + return true; +} + +void GDBRemoteDynamicRegisterInfo::CloneFrom( + GDBRemoteDynamicRegisterInfoSP proc_reginfo) { + m_regs = proc_reginfo->m_regs; + m_sets = proc_reginfo->m_sets; + m_set_reg_nums = proc_reginfo->m_set_reg_nums; + m_set_names = proc_reginfo->m_set_names; + m_value_regs_map = proc_reginfo->m_value_regs_map; + m_invalidate_regs_map = proc_reginfo->m_invalidate_regs_map; + m_dynamic_reg_size_map = proc_reginfo->m_dynamic_reg_size_map; + m_reg_data_byte_size = proc_reginfo->m_reg_data_byte_size; + + m_finalized = proc_reginfo->m_finalized; + m_per_thread_reginfo = proc_reginfo->m_per_thread_reginfo; } void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) { Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -251,7 +251,7 @@ // the last stop // packet variable std::recursive_mutex m_last_stop_packet_mutex; - GDBRemoteDynamicRegisterInfo m_register_info; + GDBRemoteDynamicRegisterInfoSP m_register_info_sp; Broadcaster m_async_broadcaster; lldb::ListenerSP m_async_listener_sp; HostThread m_async_thread; Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -258,7 +258,7 @@ ListenerSP listener_sp) : Process(target_sp, listener_sp), m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(), - m_register_info(), + m_register_info_sp(nullptr), m_async_broadcaster(nullptr, "lldb.process.gdb-remote.async-broadcaster"), m_async_listener_sp( Listener::MakeListener("lldb.process.gdb-remote.async-listener")), @@ -376,8 +376,8 @@ m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue(); } - if (m_register_info.SetRegisterInfo(*target_definition_sp, - GetTarget().GetArchitecture()) > 0) { + if (m_register_info_sp->SetRegisterInfo( + *target_definition_sp, GetTarget().GetArchitecture()) > 0) { return true; } } @@ -404,10 +404,13 @@ } void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { - if (!force && m_register_info.GetNumRegisters() > 0) + if (!m_register_info_sp) + m_register_info_sp = std::make_shared(); + + if (!force && m_register_info_sp->GetNumRegisters() > 0) return; - m_register_info.Clear(); + m_register_info_sp->Clear(); // Check if qHostInfo specified a specific packet timeout for this // connection. If so then lets update our setting so the user knows what the @@ -589,7 +592,7 @@ if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use)) abi_sp->AugmentRegisterInfo(reg_info); - m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name); + m_register_info_sp->AddRegister(reg_info, reg_name, alt_name, set_name); } else { break; // ensure exit before reg_num is incremented } @@ -598,8 +601,8 @@ } } - if (m_register_info.GetNumRegisters() > 0) { - m_register_info.Finalize(GetTarget().GetArchitecture()); + if (m_register_info_sp->GetNumRegisters() > 0) { + m_register_info_sp->Finalize(GetTarget().GetArchitecture()); return; } @@ -608,21 +611,21 @@ // updated debugserver down on the devices. On the other hand, if the // accumulated reg_num is positive, see if we can add composite registers to // the existing primordial ones. - bool from_scratch = (m_register_info.GetNumRegisters() == 0); + bool from_scratch = (m_register_info_sp->GetNumRegisters() == 0); if (!target_arch.IsValid()) { if (arch_to_use.IsValid() && (arch_to_use.GetMachine() == llvm::Triple::arm || arch_to_use.GetMachine() == llvm::Triple::thumb) && arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple) - m_register_info.HardcodeARMRegisters(from_scratch); + m_register_info_sp->HardcodeARMRegisters(from_scratch); } else if (target_arch.GetMachine() == llvm::Triple::arm || target_arch.GetMachine() == llvm::Triple::thumb) { - m_register_info.HardcodeARMRegisters(from_scratch); + m_register_info_sp->HardcodeARMRegisters(from_scratch); } // At this point, we can finalize our register info. - m_register_info.Finalize(GetTarget().GetArchitecture()); + m_register_info_sp->Finalize(GetTarget().GetArchitecture()); } Status ProcessGDBRemote::WillLaunch(lldb_private::Module *module) { @@ -1772,6 +1775,10 @@ gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData()); } + static_cast( + gdb_thread->GetRegisterContext().get()) + ->UpdateDynamicRegisterInfo(); + thread_sp->SetName(thread_name.empty() ? nullptr : thread_name.c_str()); gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr); @@ -4579,7 +4586,7 @@ // ABI is also potentially incorrect. ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use); for (auto &feature_node : feature_nodes) { - ParseRegisters(feature_node, target_info, this->m_register_info, + ParseRegisters(feature_node, target_info, *this->m_register_info_sp, abi_to_use_sp, cur_reg_num, reg_offset); } @@ -4608,9 +4615,9 @@ uint32_t cur_reg_num = 0; uint32_t reg_offset = 0; if (GetGDBServerRegisterInfoXMLAndProcess (arch_to_use, "target.xml", cur_reg_num, reg_offset)) - this->m_register_info.Finalize(arch_to_use); + this->m_register_info_sp->Finalize(arch_to_use); - return m_register_info.GetNumRegisters() > 0; + return m_register_info_sp->GetNumRegisters() > 0; } llvm::Expected ProcessGDBRemote::GetLoadedModuleList() { Index: lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -307,7 +307,7 @@ !pSupported || gdb_process->m_use_g_packet_for_reading; bool write_all_registers_at_once = !pSupported; reg_ctx_sp = std::make_shared( - *this, concrete_frame_idx, gdb_process->m_register_info, + *this, concrete_frame_idx, gdb_process->m_register_info_sp, read_all_registers_at_once, write_all_registers_at_once); } } else { 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/source/Utility/RegisterValue.cpp =================================================================== --- lldb/source/Utility/RegisterValue.cpp +++ lldb/source/Utility/RegisterValue.cpp @@ -810,7 +810,7 @@ if (buffer.length != rhs.buffer.length) return false; else { - uint8_t length = buffer.length; + uint32_t length = buffer.length; if (length > kMaxRegisterByteSize) length = kMaxRegisterByteSize; return memcmp(buffer.bytes, rhs.buffer.bytes, length) == 0;