]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Convert Aarch64 SVE feature to use variable-size registers
authorThiago Jung Bauermann <thiago.bauermann@linaro.org>
Fri, 18 Apr 2025 02:21:28 +0000 (23:21 -0300)
committerThiago Jung Bauermann <thiago.bauermann@linaro.org>
Mon, 21 Apr 2025 03:16:45 +0000 (00:16 -0300)
gdb/aarch64-linux-nat.c
gdb/aarch64-linux-tdep.c
gdb/aarch64-tdep.c
gdb/aarch64-tdep.h
gdb/arch/aarch64.c
gdb/arch/aarch64.h
gdb/features/Makefile
gdb/features/aarch64-sve.c
gdb/features/aarch64-sve.xml [new file with mode: 0644]
gdbserver/linux-aarch64-low.cc
gdbserver/linux-aarch64-tdesc.cc

index b5caf004cafcc03ef5490f21484eb299ae5d0ff4..a9b02de99b029fc70d50b3b7bee68d153e4143ef 100644 (file)
@@ -586,7 +586,7 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
 
       /* We attempt to fetch SVE registers if there is support for either
         SVE or SME (due to the SSVE state of SME).  */
-      if (tdep->has_sve () || tdep->has_sme ())
+      if (tdep->has_sve || tdep->has_sme ())
        fetch_sveregs_from_thread (regcache);
       else
        fetch_fpregs_from_thread (regcache);
@@ -610,10 +610,10 @@ aarch64_fetch_registers (struct regcache *regcache, int regno)
   else if (regno < AARCH64_V0_REGNUM)
     fetch_gregs_from_thread (regcache);
   /* SVE register?  */
-  else if ((tdep->has_sve () || tdep->has_sme ())
+  else if ((tdep->has_sve || tdep->has_sme ())
           && regno < AARCH64_SVE_VG_REGNUM)
     fetch_sveregs_from_thread (regcache);
-  else if (tdep->has_sve () && regno == AARCH64_SVE_VG_REGNUM)
+  else if (tdep->has_sve && regno == AARCH64_SVE_VG_REGNUM)
     fetch_sve_vg_from_thread (regcache);
   /* FPSIMD register?  */
   else if (regno <= AARCH64_FPCR_REGNUM)
@@ -694,7 +694,7 @@ aarch64_store_registers (struct regcache *regcache, int regno)
 
       /* We attempt to store SVE registers if there is support for either
         SVE or SME (due to the SSVE state of SME).  */
-      if (tdep->has_sve () || tdep->has_sme ())
+      if (tdep->has_sve || tdep->has_sme ())
        store_sveregs_to_thread (regcache);
       else
        store_fpregs_to_thread (regcache);
@@ -715,10 +715,10 @@ aarch64_store_registers (struct regcache *regcache, int regno)
   else if (regno < AARCH64_V0_REGNUM)
     store_gregs_to_thread (regcache);
   /* SVE register?  */
-  else if ((tdep->has_sve () || tdep->has_sme ())
+  else if ((tdep->has_sve || tdep->has_sme ())
           && regno < AARCH64_SVE_VG_REGNUM)
     store_sveregs_to_thread (regcache);
-  else if (tdep->has_sve () && regno == AARCH64_SVE_VG_REGNUM)
+  else if (tdep->has_sve && regno == AARCH64_SVE_VG_REGNUM)
     store_sve_vg_to_thread (regcache);
   /* FPSIMD register?  */
   else if (regno <= AARCH64_FPCR_REGNUM)
@@ -911,7 +911,7 @@ aarch64_linux_nat_target::read_description ()
   /* SVE/SSVE check.  Reading VQ may return either the regular vector length
      or the streaming vector length, depending on whether streaming mode is
      active or not.  */
-  features.vq = aarch64_sve_get_vq (tid);
+  features.sve = aarch64_sve_get_vq (tid) != 0;
   features.pauth = hwcap & AARCH64_HWCAP_PACA;
   features.mte = hwcap2 & HWCAP2_MTE;
   features.tls = aarch64_tls_register_count (tid);
@@ -1025,19 +1025,19 @@ aarch64_linux_nat_target::thread_architecture (ptid_t ptid)
      the tdep.  */
   aarch64_gdbarch_tdep *tdep
     = gdbarch_tdep<aarch64_gdbarch_tdep> (inf->arch ());
-  uint64_t vq = aarch64_sve_get_vq (ptid.lwp ());
+  bool sve = aarch64_sve_get_vq (ptid.lwp ()) != 0;
   uint64_t svq = aarch64_za_get_svq (ptid.lwp ());
-  if (vq == tdep->vq && svq == tdep->sme_svq)
+  if (sve == tdep->has_sve && svq == tdep->sme_svq)
     return inf->arch ();
 
   /* We reach here if any vector length for the thread is different from its
      value at process start.  Lookup gdbarch via info (potentially creating a
-     new one) by using a target description that corresponds to the new vq/svq
-     value and the current architecture features.  */
+     new one) by using a target description that corresponds to the new
+     vector/matrix state and the current architecture features.  */
 
   const struct target_desc *tdesc = gdbarch_target_desc (inf->arch ());
   aarch64_features features = aarch64_features_from_target_desc (tdesc);
-  features.vq = vq;
+  features.sve = sve;
   features.svq = svq;
 
   /* Check for the SME2 feature.  */
index 9cee35541875b808d6d51ccc51ed34bd59b5a678..2ddbebba78c8df60626f71518cce13fee60eb838 100644 (file)
@@ -60,6 +60,7 @@
 #include "elf/common.h"
 #include "elf/aarch64.h"
 #include "arch/aarch64-insn.h"
+#include "target-descriptions.h"
 
 /* For std::pow */
 #include <cmath>
@@ -275,7 +276,8 @@ read_aarch64_ctx (CORE_ADDR ctx_addr, enum bfd_endian byte_order,
 static void
 aarch64_linux_restore_vregs (struct gdbarch *gdbarch,
                             struct trad_frame_cache *cache,
-                            CORE_ADDR fpsimd_context)
+                            CORE_ADDR fpsimd_context,
+                            ULONGEST vl)
 {
   /* WARNING: SIMD state is laid out in memory in target-endian format.
 
@@ -335,7 +337,7 @@ aarch64_linux_restore_vregs (struct gdbarch *gdbarch,
                                          num_regs + AARCH64_B0_REGNUM
                                          + i, {buf, B_REGISTER_SIZE});
 
-         if (tdep->has_sve ())
+         if (tdep->has_sve)
            trad_frame_set_reg_value_bytes (cache,
                                            num_regs + AARCH64_SVE_V0_REGNUM
                                            + i, {buf, V_REGISTER_SIZE});
@@ -356,22 +358,22 @@ aarch64_linux_restore_vregs (struct gdbarch *gdbarch,
          trad_frame_set_reg_addr (cache, num_regs + AARCH64_B0_REGNUM + i,
                                   offset);
 
-         if (tdep->has_sve ())
+         if (tdep->has_sve)
            trad_frame_set_reg_addr (cache, num_regs + AARCH64_SVE_V0_REGNUM
                                     + i, offset);
        }
 
-      if (tdep->has_sve ())
+      if (tdep->has_sve)
        {
          /* If SVE is supported for this target, zero out the Z
             registers then copy the first 16 bytes of each of the V
             registers to the associated Z register.  Otherwise the Z
             registers will contain uninitialized data.  */
-         std::vector<gdb_byte> z_buffer (tdep->vq * 16);
+         std::vector<gdb_byte> z_buffer (vl);
 
          /* We have already handled the endianness swap above, so we don't need
             to worry about it here.  */
-         memcpy (z_buffer.data (), buf, V_REGISTER_SIZE);
+         memcpy (z_buffer.data (), buf, vl);
          trad_frame_set_reg_value_bytes (cache,
                                          AARCH64_SVE_Z0_REGNUM + i,
                                          z_buffer);
@@ -403,8 +405,8 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame,
   CORE_ADDR section_end = signal_frame.section_end;
   uint32_t size, magic;
   bool extra_found = false;
-  enum bfd_endian byte_order
-    = gdbarch_byte_order (get_frame_arch (this_frame));
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   while ((magic = read_aarch64_ctx (section, byte_order, &size)) != 0
         && size != 0)
@@ -423,6 +425,11 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame,
            /* Check if the section is followed by a full SVE dump, and set
               sve_regs if it is.  */
            gdb_byte buf[4];
+           aarch64_gdbarch_tdep *tdep
+             = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
+
+           if (!tdep->has_sve)
+             break;
 
            /* Extract the vector length.  */
            if (target_read_memory (section + AARCH64_SVE_CONTEXT_VL_OFFSET,
@@ -436,6 +443,10 @@ aarch64_linux_read_signal_frame_info (const frame_info_ptr &this_frame,
 
            signal_frame.vl = extract_unsigned_integer (buf, 2, byte_order);
 
+           if (signal_frame.vl == 0)
+             error (_ ("Invalid vector length in signal frame %" PRIu64 "."),
+                    signal_frame.vl);
+
            /* Extract the flags to check if we are in streaming mode.  */
            if (target_read_memory (section
                                    + AARCH64_SVE_CONTEXT_FLAGS_OFFSET,
@@ -598,7 +609,7 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self,
   aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
 
   /* Restore the SVE / FPSIMD registers.  */
-  if (tdep->has_sve () && signal_frame.sve_section != 0)
+  if (tdep->has_sve && signal_frame.sve_section != 0)
     {
       ULONGEST vq = sve_vq_from_vl (signal_frame.vl);
       CORE_ADDR sve_regs = signal_frame.sve_section;
@@ -648,8 +659,9 @@ aarch64_linux_sigframe_init (const struct tramp_frame *self,
                               fpsimd + AARCH64_FPSIMD_FPCR_OFFSET);
 
       /* If there was no SVE section then set up the V registers.  */
-      if (!tdep->has_sve () || signal_frame.sve_section == 0)
-       aarch64_linux_restore_vregs (gdbarch, this_cache, fpsimd);
+      if (!tdep->has_sve || signal_frame.sve_section == 0)
+       aarch64_linux_restore_vregs (gdbarch, this_cache, fpsimd,
+                                    tdep->has_sve ? signal_frame.vl : 0);
     }
 
   /* Restore the SME registers.  */
@@ -726,7 +738,7 @@ aarch64_linux_sigframe_prev_arch (const frame_info_ptr &this_frame,
   const struct target_desc *tdesc
     = gdbarch_target_desc (get_frame_arch (this_frame));
   aarch64_features features = aarch64_features_from_target_desc (tdesc);
-  features.vq = sve_vq_from_vl (signal_frame.vl);
+  features.sve = signal_frame.vl != 0;
   features.svq = (uint8_t) sve_vq_from_vl (signal_frame.svl);
 
   struct gdbarch_info info;
@@ -735,6 +747,46 @@ aarch64_linux_sigframe_prev_arch (const frame_info_ptr &this_frame,
   return gdbarch_find_by_info (info);
 }
 
+/* Implements the "prev_tdesc_parameter" method of struct tramp_frame.  */
+
+static value *
+aarch64_linux_sigframe_prev_tdesc_parameter (const frame_info_ptr &this_frame,
+                                            void **this_frame_cache,
+                                            unsigned int parameter_id)
+{
+  gdbarch *gdbarch = get_frame_arch (this_frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
+  struct aarch64_linux_sigframe signal_frame;
+  ULONGEST parameter_value;
+
+  aarch64_linux_read_signal_frame_info (this_frame, signal_frame);
+
+  if (tdep->param_sve_vector_length != UINT_MAX
+      && parameter_id == tdep->param_sve_vector_length)
+    {
+      /* In the XML, vector_length is used in bitsize fields, but internally
+        GDB expects the size in bytes.  */
+      parameter_value = signal_frame.vl;
+    }
+  else if (tdep->param_sve_predicate_length != UINT_MAX
+          && parameter_id == tdep->param_sve_predicate_length)
+    {
+      /* In the XML, predicate_length is used in bitsize fields, but internally
+        GDB expects the size in bytes.  */
+      parameter_value = sve_vg_from_vl (signal_frame.vl);
+    }
+  else
+    return nullptr;
+
+  value *result = value::allocate (tdesc_parameter_type (gdbarch,
+                                                        parameter_id));
+
+  store_unsigned_integer (result->contents_raw (), byte_order, parameter_value);
+
+  return result;
+}
+
 static const struct tramp_frame aarch64_linux_rt_sigframe =
 {
   SIGTRAMP_FRAME,
@@ -752,6 +804,7 @@ static const struct tramp_frame aarch64_linux_rt_sigframe =
   aarch64_linux_sigframe_init,
   nullptr, /* validate */
   aarch64_linux_sigframe_prev_arch, /* prev_arch */
+  aarch64_linux_sigframe_prev_tdesc_parameter,
 };
 
 /* Register maps.  */
@@ -1053,9 +1106,12 @@ collect_sve_regset (const struct regset *regset,
   gdb_byte *header = (gdb_byte *) buf;
   struct gdbarch *gdbarch = regcache->arch ();
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
-  uint64_t vq = tdep->vq;
+  ULONGEST vg;
+  // FIXME: Remove this cast.
+  enum register_status vg_status
+    = const_cast<struct regcache *> (regcache)->raw_read (AARCH64_SVE_VG_REGNUM, &vg);
 
+  gdb_assert (vg_status == REG_VALID);
   gdb_assert (buf != NULL);
   gdb_assert (size > SVE_HEADER_SIZE);
 
@@ -1067,7 +1123,7 @@ collect_sve_regset (const struct regset *regset,
   store_unsigned_integer (header + SVE_HEADER_MAX_SIZE_OFFSET,
                          SVE_HEADER_MAX_SIZE_LENGTH, byte_order, max_size);
   store_unsigned_integer (header + SVE_HEADER_VL_OFFSET, SVE_HEADER_VL_LENGTH,
-                         byte_order, sve_vl_from_vq (vq));
+                         byte_order, sve_vl_from_vg (vg));
   uint16_t max_vl = SVE_CORE_DUMMY_MAX_VL;
   store_unsigned_integer (header + SVE_HEADER_MAX_VL_OFFSET,
                          SVE_HEADER_MAX_VL_LENGTH, byte_order,
@@ -1434,14 +1490,15 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
   cb (".reg", AARCH64_LINUX_SIZEOF_GREGSET, AARCH64_LINUX_SIZEOF_GREGSET,
       &aarch64_linux_gregset, NULL, cb_data);
 
-  if (tdep->has_sve ())
+  if (tdep->has_sve)
     {
       /* Create this on the fly in order to handle vector register sizes.  */
+      // FIXME: Don't use maximum VQ.
       const struct regcache_map_entry sve_regmap[] =
        {
-         { 32, AARCH64_SVE_Z0_REGNUM, (int) (tdep->vq * 16) },
-         { 16, AARCH64_SVE_P0_REGNUM, (int) (tdep->vq * 16 / 8) },
-         { 1, AARCH64_SVE_FFR_REGNUM, (int) (tdep->vq * 16 / 8) },
+         { 32, AARCH64_SVE_Z0_REGNUM, (int)(AARCH64_MAX_SVE_VQ * 16) },
+         { 16, AARCH64_SVE_P0_REGNUM, (int)(AARCH64_MAX_SVE_VQ * 16 / 8) },
+         { 1, AARCH64_SVE_FFR_REGNUM, (int)(AARCH64_MAX_SVE_VQ * 16 / 8) },
          { 1, AARCH64_FPSR_REGNUM, 4 },
          { 1, AARCH64_FPCR_REGNUM, 4 },
          { 0 }
@@ -1624,7 +1681,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
      Otherwise the SVE section is considered active.  This guarantees we will
      have the correct target description with the correct SVE vector
      length.  */
-  features.vq = aarch64_linux_core_read_vq_from_sections (gdbarch, abfd);
+  features.sve = aarch64_linux_core_read_vq_from_sections (gdbarch, abfd) != 0;
   features.pauth = hwcap & AARCH64_HWCAP_PACA;
   features.mte = hwcap2 & HWCAP2_MTE;
 
index 19d9f1d745c7d8cc104f0f8959b89bc7eb8f3e68..b72a3d5aa9f8e1c6264bb07b1b4684aca149b1c3 100644 (file)
@@ -2994,7 +2994,7 @@ aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
   if (is_w_pseudo_register (gdbarch, regnum))
     return w_name[regnum - tdep->w_pseudo_base];
 
-  if (tdep->has_sve ())
+  if (tdep->has_sve)
     {
       static const char *const sve_v_name[] =
        {
@@ -3050,7 +3050,7 @@ aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
   if (p_regnum >= AARCH64_B0_REGNUM && p_regnum < AARCH64_B0_REGNUM + 32)
     return aarch64_vnb_type (gdbarch);
 
-  if (tdep->has_sve () && p_regnum >= AARCH64_SVE_V0_REGNUM
+  if (tdep->has_sve && p_regnum >= AARCH64_SVE_V0_REGNUM
       && p_regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
     return aarch64_vnv_type (gdbarch);
 
@@ -3090,7 +3090,7 @@ aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
     return group == all_reggroup || group == vector_reggroup;
   else if (p_regnum >= AARCH64_B0_REGNUM && p_regnum < AARCH64_B0_REGNUM + 32)
     return group == all_reggroup || group == vector_reggroup;
-  else if (tdep->has_sve () && p_regnum >= AARCH64_SVE_V0_REGNUM
+  else if (tdep->has_sve && p_regnum >= AARCH64_SVE_V0_REGNUM
           && p_regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM)
     return group == all_reggroup || group == vector_reggroup;
   else if (is_sme_pseudo_register (gdbarch, regnum))
@@ -3285,7 +3285,7 @@ aarch64_pseudo_read_value (gdbarch *gdbarch, const frame_info_ptr &next_frame,
     return aarch64_pseudo_read_value_1 (next_frame, pseudo_reg_num,
                                        pseudo_offset - AARCH64_B0_REGNUM);
 
-  if (tdep->has_sve () && pseudo_offset >= AARCH64_SVE_V0_REGNUM
+  if (tdep->has_sve && pseudo_offset >= AARCH64_SVE_V0_REGNUM
       && pseudo_offset < AARCH64_SVE_V0_REGNUM + 32)
     return aarch64_pseudo_read_value_1 (next_frame, pseudo_reg_num,
                                        pseudo_offset - AARCH64_SVE_V0_REGNUM);
@@ -3428,7 +3428,7 @@ aarch64_pseudo_write (gdbarch *gdbarch, const frame_info_ptr &next_frame,
     return aarch64_pseudo_write_1 (gdbarch, next_frame,
                                   pseudo_offset - AARCH64_B0_REGNUM, buf);
 
-  if (tdep->has_sve () && pseudo_offset >= AARCH64_SVE_V0_REGNUM
+  if (tdep->has_sve && pseudo_offset >= AARCH64_SVE_V0_REGNUM
       && pseudo_offset < AARCH64_SVE_V0_REGNUM + 32)
     return aarch64_pseudo_write_1 (gdbarch, next_frame,
                                   pseudo_offset - AARCH64_SVE_V0_REGNUM, buf);
@@ -3944,10 +3944,6 @@ aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch)
 const target_desc *
 aarch64_read_description (const aarch64_features &features)
 {
-  if (features.vq > AARCH64_MAX_SVE_VQ)
-    error (_("VQ is %" PRIu64 ", maximum supported value is %d"), features.vq,
-          AARCH64_MAX_SVE_VQ);
-
   struct target_desc *tdesc = tdesc_aarch64_map[features];
 
   if (tdesc == NULL)
@@ -3959,27 +3955,6 @@ aarch64_read_description (const aarch64_features &features)
   return tdesc;
 }
 
-/* Return the VQ used when creating the target description TDESC.  */
-
-static uint64_t
-aarch64_get_tdesc_vq (const struct target_desc *tdesc)
-{
-  const struct tdesc_feature *feature_sve;
-
-  if (!tdesc_has_registers (tdesc))
-    return 0;
-
-  feature_sve = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sve");
-
-  if (feature_sve == nullptr)
-    return 0;
-
-  uint64_t vl = tdesc_register_bitsize (feature_sve,
-                                       aarch64_sve_register_names[0]) / 8;
-  return sve_vq_from_vl (vl);
-}
-
-
 /* Return the svq (streaming vector quotient) used when creating the target
    description TDESC.  */
 
@@ -4016,7 +3991,8 @@ aarch64_features_from_target_desc (const struct target_desc *tdesc)
   if (tdesc == nullptr)
     return features;
 
-  features.vq = aarch64_get_tdesc_vq (tdesc);
+  features.sve
+      = tdesc_find_feature (tdesc, "org.gnu.gdb.aarch64.sve") != nullptr;
 
   /* We need to look for a couple pauth feature name variations.  */
   features.pauth
@@ -4315,6 +4291,52 @@ aarch64_remove_non_address_bits (struct gdbarch *gdbarch, CORE_ADDR pointer)
   return aarch64_remove_top_bits (pointer, mask);
 }
 
+static void
+aarch64_fetch_tdesc_parameter (gdbarch *gdbarch, readable_regcache *regcache,
+                              unsigned int parameter_id)
+{
+  aarch64_gdbarch_tdep *tdep = gdbarch_tdep<aarch64_gdbarch_tdep> (gdbarch);
+
+  if (tdep->param_sve_vector_length != UINT_MAX
+      && parameter_id == tdep->param_sve_vector_length)
+    {
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      register_status status;
+      gdb_byte buf[8];
+
+      status = regcache->raw_read (AARCH64_SVE_VG_REGNUM, buf);
+      if (status != REG_VALID)
+       return;
+
+      ULONGEST vg = extract_unsigned_integer (buf, byte_order);
+      ULONGEST vl = sve_vl_from_vg (vg);
+
+      /* In the XML, vector_length is used in bitsize fields, but internally
+        GDB expects the size in bytes.  */
+      store_unsigned_integer (buf, byte_order, vl);
+      regcache->supply_parameter (parameter_id, buf);
+    }
+  else if (tdep->param_sve_predicate_length != UINT_MAX
+          && parameter_id == tdep->param_sve_predicate_length)
+    {
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      register_status status;
+      gdb_byte buf[8];
+
+      status = regcache->raw_read (AARCH64_SVE_VG_REGNUM, buf);
+      if (status != REG_VALID)
+       return;
+
+      ULONGEST vg = extract_unsigned_integer (buf, byte_order);
+      ULONGEST predicate_length = vg;
+
+      /* In the XML, predicate_length is used in bitsize fields, but internally
+        GDB expects the size in bytes.  */
+      store_unsigned_integer (buf, byte_order, predicate_length);
+      regcache->supply_parameter (parameter_id, buf);
+    }
+}
+
 /* Given NAMES, a vector of strings, initialize it with all the SME
    pseudo-register names for the current streaming vector length.  */
 
@@ -4360,13 +4382,11 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   int i, num_regs = 0, num_pseudo_regs = 0;
   int first_pauth_regnum = -1, ra_sign_state_offset = -1;
   int first_mte_regnum = -1, first_tls_regnum = -1;
-  uint64_t vq = aarch64_get_tdesc_vq (info.target_desc);
+  bool has_sve = (info.target_desc == nullptr ? false
+                 : tdesc_find_feature (info.target_desc,
+                                       "org.gnu.gdb.aarch64.sve") != nullptr);
   uint64_t svq = aarch64_get_tdesc_svq (info.target_desc);
 
-  if (vq > AARCH64_MAX_SVE_VQ)
-    internal_error (_("VQ out of bounds: %s (max %d)"),
-                   pulongest (vq), AARCH64_MAX_SVE_VQ);
-
   if (svq > AARCH64_MAX_SVE_VQ)
     internal_error (_("Streaming vector quotient (svq) out of bounds: %s"
                      " (max %d)"),
@@ -4379,18 +4399,17 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     {
       aarch64_gdbarch_tdep *tdep
        = gdbarch_tdep<aarch64_gdbarch_tdep> (best_arch->gdbarch);
-      if (tdep && tdep->vq == vq && tdep->sme_svq == svq)
+      if (tdep && tdep->has_sve == has_sve && tdep->sme_svq == svq)
        return best_arch->gdbarch;
     }
 
   /* Ensure we always have a target descriptor, and that it is for the given VQ
      value.  */
   const struct target_desc *tdesc = info.target_desc;
-  if (!tdesc_has_registers (tdesc) || vq != aarch64_get_tdesc_vq (tdesc)
-      || svq != aarch64_get_tdesc_svq (tdesc))
+  if (!tdesc_has_registers (tdesc))
     {
       aarch64_features features;
-      features.vq = vq;
+      features.sve = has_sve;
       features.svq = svq;
       tdesc = aarch64_read_description (features);
     }
@@ -4605,7 +4624,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->lowest_pc = 0x20;
   tdep->jb_pc = -1;            /* Longjump support not enabled by default.  */
   tdep->jb_elt_size = 8;
-  tdep->vq = vq;
+  tdep->has_sve = feature_sve != nullptr;
   tdep->pauth_reg_base = first_pauth_regnum;
   tdep->pauth_reg_count = pauth_masks;
   tdep->ra_sign_state_regnum = -1;
@@ -4851,6 +4870,19 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   register_aarch64_ravenscar_ops (gdbarch);
 
+  tdesc_setup_parameters (gdbarch, tdesc);
+
+  std::optional<unsigned int> param_id
+    = tdesc_parameter_id (gdbarch, "org.gnu.gdb.aarch64.sve", "vector_length");
+  if (param_id.has_value ())
+    tdep->param_sve_vector_length = *param_id;
+  param_id = tdesc_parameter_id (gdbarch, "org.gnu.gdb.aarch64.sve",
+                                "predicate_length");
+  if (param_id.has_value ())
+    tdep->param_sve_predicate_length = *param_id;
+
+  set_gdbarch_fetch_tdesc_parameter (gdbarch, aarch64_fetch_tdesc_parameter);
+
   return gdbarch;
 }
 
@@ -4865,6 +4897,9 @@ aarch64_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
   gdb_printf (file, _("aarch64_dump_tdep: Lowest pc = 0x%s\n"),
              paddress (gdbarch, tdep->lowest_pc));
 
+  gdb_printf (file, _ ("aarch64_dump_tdep: has_sve = %s\n"),
+             tdep->has_sve ? "true" : "false");
+
   /* SME fields.  */
   gdb_printf (file, _("aarch64_dump_tdep: sme_tile_type_q = %s\n"),
              host_address_to_string (tdep->sme_tile_type_q));
index 3b8dcc26545b5365f8abdd8d58db7059c247b482..4e5a71598f6480980e2565a3e8cbc5c802a6507a 100644 (file)
@@ -100,14 +100,14 @@ struct aarch64_gdbarch_tdep : gdbarch_tdep_base
   int (*aarch64_syscall_record) (struct regcache *regcache,
                                 unsigned long svc_number) = nullptr;
 
-  /* The VQ value for SVE targets, or zero if SVE is not supported.  */
-  uint64_t vq = 0;
+  /* Whether SVE is supported.  */
+  bool has_sve = false;
 
-  /* Returns true if the target supports SVE.  */
-  bool has_sve () const
-  {
-    return vq != 0;
-  }
+  /* Internal ID of tdesc parameter for SVE vector_length, in bits.  */
+  unsigned int param_sve_vector_length = UINT_MAX;
+
+  /* Internal ID of tdesc parameter for SVE predicate_length, in bits.  */
+  unsigned int param_sve_predicate_length = UINT_MAX;
 
   int pauth_reg_base = 0;
   /* Number of pauth masks.  */
index 3e1ca0547340d536971cd9ec23bc27b74f22acc0..cbf897d2838ea734cff64fc7e92972c5b324bf33 100644 (file)
@@ -42,10 +42,10 @@ aarch64_create_target_description (const aarch64_features &features)
 
   regnum = create_feature_aarch64_core (tdesc.get (), regnum);
 
-  if (features.vq == 0)
-    regnum = create_feature_aarch64_fpu (tdesc.get (), regnum);
+  if (features.sve)
+    regnum = create_feature_aarch64_sve (tdesc.get (), regnum);
   else
-    regnum = create_feature_aarch64_sve (tdesc.get (), regnum, features.vq);
+    regnum = create_feature_aarch64_fpu (tdesc.get (), regnum);
 
   if (features.pauth)
     regnum = create_feature_aarch64_pauth (tdesc.get (), regnum);
index ee18b74b80f58161fba1eeb9a6d799ab49a315fa..f7c89e7aeae9e76506a16d40217cd917bc5d24d5 100644 (file)
    used to select register sets.  */
 struct aarch64_features
 {
-  /* A non zero VQ value indicates both the presence of SVE and the
-     Vector Quotient - the number of 128-bit chunks in an SVE Z
-     register.
-
-     The maximum value for VQ is 16 (5 bits).  */
-  uint64_t vq = 0;
+  bool sve = false;
   bool pauth = false;
   bool mte = false;
 
@@ -55,7 +50,7 @@ struct aarch64_features
 
 inline bool operator==(const aarch64_features &lhs, const aarch64_features &rhs)
 {
-  return lhs.vq == rhs.vq
+  return lhs.sve == rhs.sve
     && lhs.pauth == rhs.pauth
     && lhs.mte == rhs.mte
     && lhs.tls == rhs.tls
@@ -72,7 +67,7 @@ namespace std
     {
       std::size_t h;
 
-      h = features.vq;
+      h = features.sve;
       h = h << 1 | features.pauth;
       h = h << 1 | features.mte;
       /* Shift by two bits for now.  We may need to increase this in the future
index 7a8c7999733ac7cfa30e2ae1db138688bc825db5..bd3a7fd492e45596167e7a01e251bb352ea08b78 100644 (file)
@@ -203,6 +203,7 @@ FEATURE_XMLFILES = aarch64-core.xml \
        aarch64-fpu.xml \
        aarch64-pauth.xml \
        aarch64-mte.xml \
+       aarch64-sve.xml \
        arc/v1-core.xml \
        arc/v1-aux.xml \
        arc/v2-core.xml \
index 0b15881f073a1e8afdef16c621308c4a38b8cd7e..af82084e71447f78e96f951b9960267cf30e26cc 100644 (file)
@@ -1,76 +1,62 @@
-/* Copyright (C) 2018-2025 Free Software Foundation, Inc.
-
-   This file is part of GDB.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: aarch64-sve.xml */
 
 #include "gdbsupport/tdesc.h"
 
-/* This function is NOT auto generated from xml.  Create the aarch64 with SVE
-   feature into RESULT, where SCALE is the number of 128 bit chunks in a Z
-   register.  */
-
 static int
-create_feature_aarch64_sve (struct target_desc *result, long regnum,
-                           uint64_t scale)
+create_feature_aarch64_sve (struct target_desc *result, long regnum)
 {
   struct tdesc_feature *feature;
-  tdesc_type *element_type, *field_type;
-  tdesc_type_with_fields *type_with_fields;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.aarch64.sve");
-
+  tdesc_type *param_type;
+  param_type = tdesc_named_type (feature, "uint64");
+  const tdesc_parameter &param_vector_length = tdesc_create_parameter (*feature, "vector_length", param_type);
+  param_type = tdesc_named_type (feature, "uint64");
+  const tdesc_parameter &param_predicate_length = tdesc_create_parameter (*feature, "predicate_length", param_type);
+  tdesc_type *element_type;
   element_type = tdesc_named_type (feature, "uint128");
-  tdesc_create_vector (feature, "svevqu", element_type, scale);
+  tdesc_create_vector (feature, "svevqu", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "int128");
-  tdesc_create_vector (feature, "svevqs", element_type, scale);
+  tdesc_create_vector (feature, "svevqs", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "ieee_double");
-  tdesc_create_vector (feature, "svevdf", element_type, 2 * scale);
+  tdesc_create_vector (feature, "svevdf", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "uint64");
-  tdesc_create_vector (feature, "svevdu", element_type, 2 * scale);
+  tdesc_create_vector (feature, "svevdu", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "int64");
-  tdesc_create_vector (feature, "svevds", element_type, 2 * scale);
+  tdesc_create_vector (feature, "svevds", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "ieee_single");
-  tdesc_create_vector (feature, "svevsf", element_type, 4 * scale);
+  tdesc_create_vector (feature, "svevsf", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "uint32");
-  tdesc_create_vector (feature, "svevsu", element_type, 4 * scale);
+  tdesc_create_vector (feature, "svevsu", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "int32");
-  tdesc_create_vector (feature, "svevss", element_type, 4 * scale);
+  tdesc_create_vector (feature, "svevss", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "ieee_half");
-  tdesc_create_vector (feature, "svevhf", element_type, 8 * scale);
+  tdesc_create_vector (feature, "svevhf", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "uint16");
-  tdesc_create_vector (feature, "svevhu", element_type, 8 * scale);
+  tdesc_create_vector (feature, "svevhu", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "int16");
-  tdesc_create_vector (feature, "svevhs", element_type, 8 * scale);
+  tdesc_create_vector (feature, "svevhs", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "uint8");
-  tdesc_create_vector (feature, "svevbu", element_type, 16 * scale);
+  tdesc_create_vector (feature, "svevbu", element_type, param_vector_length);
 
   element_type = tdesc_named_type (feature, "int8");
-  tdesc_create_vector (feature, "svevbs", element_type, 16 * scale);
+  tdesc_create_vector (feature, "svevbs", element_type, param_vector_length);
 
+  tdesc_type_with_fields *type_with_fields;
   type_with_fields = tdesc_create_union (feature, "svevnq");
+  tdesc_type *field_type;
   field_type = tdesc_named_type (feature, "svevqu");
   tdesc_add_field (type_with_fields, "u", field_type);
   field_type = tdesc_named_type (feature, "svevqs");
@@ -118,10 +104,9 @@ create_feature_aarch64_sve (struct target_desc *result, long regnum,
   field_type = tdesc_named_type (feature, "svevnb");
   tdesc_add_field (type_with_fields, "b", field_type);
 
-  field_type = tdesc_named_type (feature, "uint8");
-  tdesc_create_vector (feature, "svep", field_type, 2 * scale);
+  element_type = tdesc_named_type (feature, "uint8");
+  tdesc_create_vector (feature, "svep", element_type, param_predicate_length);
 
-  /* FPSR register type */
   type_with_fields = tdesc_create_flags (feature, "fpsr_flags", 4);
   tdesc_add_flag (type_with_fields, 0, "IOC");
   tdesc_add_flag (type_with_fields, 1, "DZC");
@@ -135,7 +120,6 @@ create_feature_aarch64_sve (struct target_desc *result, long regnum,
   tdesc_add_flag (type_with_fields, 30, "Z");
   tdesc_add_flag (type_with_fields, 31, "N");
 
-  /* FPCR register type */
   type_with_fields = tdesc_create_flags (feature, "fpcr_flags", 4);
   tdesc_add_flag (type_with_fields, 0, "FIZ");
   tdesc_add_flag (type_with_fields, 1, "AH");
@@ -155,57 +139,58 @@ create_feature_aarch64_sve (struct target_desc *result, long regnum,
   tdesc_add_flag (type_with_fields, 25, "DN");
   tdesc_add_flag (type_with_fields, 26, "AHP");
 
-  tdesc_create_reg (feature, "z0", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z1", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z2", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z3", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z4", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z5", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z6", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z7", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z8", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z9", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z10", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z11", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z12", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z13", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z14", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z15", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z16", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z17", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z18", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z19", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z20", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z21", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z22", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z23", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z24", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z25", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z26", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z27", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z28", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z29", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z30", regnum++, 1, NULL, 128 * scale, "svev");
-  tdesc_create_reg (feature, "z31", regnum++, 1, NULL, 128 * scale, "svev");
+  regnum = 34;
+  tdesc_create_reg (feature, "z0", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z1", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z2", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z3", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z4", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z5", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z6", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z7", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z8", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z9", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z10", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z11", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z12", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z13", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z14", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z15", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z16", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z17", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z18", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z19", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z20", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z21", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z22", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z23", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z24", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z25", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z26", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z27", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z28", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z29", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z30", regnum++, 1, NULL, param_vector_length, "svev");
+  tdesc_create_reg (feature, "z31", regnum++, 1, NULL, param_vector_length, "svev");
   tdesc_create_reg (feature, "fpsr", regnum++, 1, NULL, 32, "fpsr_flags");
   tdesc_create_reg (feature, "fpcr", regnum++, 1, NULL, 32, "fpcr_flags");
-  tdesc_create_reg (feature, "p0", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p1", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p2", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p3", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p4", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p5", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p6", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p7", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p8", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p9", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p10", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p11", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p12", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p13", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p14", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "p15", regnum++, 1, NULL, 16 * scale, "svep");
-  tdesc_create_reg (feature, "ffr", regnum++, 1, NULL, 16 * scale, "svep");
+  tdesc_create_reg (feature, "p0", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p1", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p2", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p3", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p4", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p5", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p6", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p7", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p8", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p9", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p10", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p11", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p12", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p13", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p14", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "p15", regnum++, 1, NULL, param_predicate_length, "svep");
+  tdesc_create_reg (feature, "ffr", regnum++, 1, NULL, param_predicate_length, "svep");
   tdesc_create_reg (feature, "vg", regnum++, 1, NULL, 64, "int");
   return regnum;
 }
diff --git a/gdb/features/aarch64-sve.xml b/gdb/features/aarch64-sve.xml
new file mode 100644 (file)
index 0000000..6ced6d5
--- /dev/null
@@ -0,0 +1,141 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2025 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.aarch64.sve">
+  <parameter name="vector_length" type="uint64"/>
+  <parameter name="predicate_length" type="uint64"/>
+
+  <vector id="svevqu" type="uint128" bitsize="$vector_length"/>
+  <vector id="svevqs" type="int128" bitsize="$vector_length"/>
+  <vector id="svevdf" type="ieee_double" bitsize="$vector_length"/>
+  <vector id="svevdu" type="uint64" bitsize="$vector_length"/>
+  <vector id="svevds" type="int64" bitsize="$vector_length"/>
+  <vector id="svevsf" type="ieee_single" bitsize="$vector_length"/>
+  <vector id="svevsu" type="uint32" bitsize="$vector_length"/>
+  <vector id="svevss" type="int32" bitsize="$vector_length"/>
+  <vector id="svevhf" type="ieee_half" bitsize="$vector_length"/>
+  <vector id="svevhu" type="uint16" bitsize="$vector_length"/>
+  <vector id="svevhs" type="int16" bitsize="$vector_length"/>
+  <vector id="svevbu" type="uint8" bitsize="$vector_length"/>
+  <vector id="svevbs" type="int8" bitsize="$vector_length"/>
+  <union id="svevnq">
+    <field name="u" type="svevqu"/>
+    <field name="s" type="svevqs"/>
+  </union>
+  <union id="svevnd">
+    <field name="f" type="svevdf"/>
+    <field name="u" type="svevdu"/>
+    <field name="s" type="svevds"/>
+  </union>
+  <union id="svevns">
+    <field name="f" type="svevsf"/>
+    <field name="u" type="svevsu"/>
+    <field name="s" type="svevss"/>
+  </union>
+  <union id="svevnh">
+    <field name="f" type="svevhf"/>
+    <field name="u" type="svevhu"/>
+    <field name="s" type="svevhs"/>
+  </union>
+  <union id="svevnb">
+    <field name="u" type="svevbu"/>
+    <field name="s" type="svevbs"/>
+  </union>
+  <union id="svev">
+    <field name="q" type="svevnq"/>
+    <field name="d" type="svevnd"/>
+    <field name="s" type="svevns"/>
+    <field name="h" type="svevnh"/>
+    <field name="b" type="svevnb"/>
+  </union>
+  <vector id="svep" type="uint8" bitsize="$predicate_length"/>
+  <flags id="fpsr_flags" size="4">
+    <field name="IOC" start="0" end="0" type="bool"/>
+    <field name="DZC" start="1" end="1" type="bool"/>
+    <field name="OFC" start="2" end="2" type="bool"/>
+    <field name="UFC" start="3" end="3" type="bool"/>
+    <field name="IXC" start="4" end="4" type="bool"/>
+    <field name="IDC" start="7" end="7" type="bool"/>
+    <field name="QC" start="27" end="27" type="bool"/>
+    <field name="V" start="28" end="28" type="bool"/>
+    <field name="C" start="29" end="29" type="bool"/>
+    <field name="Z" start="30" end="30" type="bool"/>
+    <field name="N" start="31" end="31" type="bool"/>
+  </flags>
+  <flags id="fpcr_flags" size="4">
+    <field name="FIZ" start="0" end="0" type="bool"/>
+    <field name="AH" start="1" end="1" type="bool"/>
+    <field name="NEP" start="2" end="2" type="bool"/>
+    <field name="IOE" start="8" end="8" type="bool"/>
+    <field name="DZE" start="9" end="9" type="bool"/>
+    <field name="OFE" start="10" end="10" type="bool"/>
+    <field name="UFE" start="11" end="11" type="bool"/>
+    <field name="IXE" start="12" end="12" type="bool"/>
+    <field name="EBF" start="13" end="13" type="bool"/>
+    <field name="IDE" start="15" end="15" type="bool"/>
+    <field name="Len" start="16" end="18" type="uint32"/>
+    <field name="FZ16" start="19" end="19" type="bool"/>
+    <field name="Stride" start="20" end="21" type="uint32"/>
+    <field name="RMode" start="22" end="23" type="uint32"/>
+    <field name="FZ" start="24" end="24" type="bool"/>
+    <field name="DN" start="25" end="25" type="bool"/>
+    <field name="AHP" start="26" end="26" type="bool"/>
+  </flags>
+  <reg name="z0" bitsize="$vector_length" type="svev" regnum="34"/>
+  <reg name="z1" bitsize="$vector_length" type="svev" regnum="35"/>
+  <reg name="z2" bitsize="$vector_length" type="svev" regnum="36"/>
+  <reg name="z3" bitsize="$vector_length" type="svev" regnum="37"/>
+  <reg name="z4" bitsize="$vector_length" type="svev" regnum="38"/>
+  <reg name="z5" bitsize="$vector_length" type="svev" regnum="39"/>
+  <reg name="z6" bitsize="$vector_length" type="svev" regnum="40"/>
+  <reg name="z7" bitsize="$vector_length" type="svev" regnum="41"/>
+  <reg name="z8" bitsize="$vector_length" type="svev" regnum="42"/>
+  <reg name="z9" bitsize="$vector_length" type="svev" regnum="43"/>
+  <reg name="z10" bitsize="$vector_length" type="svev" regnum="44"/>
+  <reg name="z11" bitsize="$vector_length" type="svev" regnum="45"/>
+  <reg name="z12" bitsize="$vector_length" type="svev" regnum="46"/>
+  <reg name="z13" bitsize="$vector_length" type="svev" regnum="47"/>
+  <reg name="z14" bitsize="$vector_length" type="svev" regnum="48"/>
+  <reg name="z15" bitsize="$vector_length" type="svev" regnum="49"/>
+  <reg name="z16" bitsize="$vector_length" type="svev" regnum="50"/>
+  <reg name="z17" bitsize="$vector_length" type="svev" regnum="51"/>
+  <reg name="z18" bitsize="$vector_length" type="svev" regnum="52"/>
+  <reg name="z19" bitsize="$vector_length" type="svev" regnum="53"/>
+  <reg name="z20" bitsize="$vector_length" type="svev" regnum="54"/>
+  <reg name="z21" bitsize="$vector_length" type="svev" regnum="55"/>
+  <reg name="z22" bitsize="$vector_length" type="svev" regnum="56"/>
+  <reg name="z23" bitsize="$vector_length" type="svev" regnum="57"/>
+  <reg name="z24" bitsize="$vector_length" type="svev" regnum="58"/>
+  <reg name="z25" bitsize="$vector_length" type="svev" regnum="59"/>
+  <reg name="z26" bitsize="$vector_length" type="svev" regnum="60"/>
+  <reg name="z27" bitsize="$vector_length" type="svev" regnum="61"/>
+  <reg name="z28" bitsize="$vector_length" type="svev" regnum="62"/>
+  <reg name="z29" bitsize="$vector_length" type="svev" regnum="63"/>
+  <reg name="z30" bitsize="$vector_length" type="svev" regnum="64"/>
+  <reg name="z31" bitsize="$vector_length" type="svev" regnum="65"/>
+  <reg name="fpsr" bitsize="32" type="fpsr_flags" regnum="66"/>
+  <reg name="fpcr" bitsize="32" type="fpcr_flags" regnum="67"/>
+  <reg name="p0" bitsize="$predicate_length" type="svep" regnum="68"/>
+  <reg name="p1" bitsize="$predicate_length" type="svep" regnum="69"/>
+  <reg name="p2" bitsize="$predicate_length" type="svep" regnum="70"/>
+  <reg name="p3" bitsize="$predicate_length" type="svep" regnum="71"/>
+  <reg name="p4" bitsize="$predicate_length" type="svep" regnum="72"/>
+  <reg name="p5" bitsize="$predicate_length" type="svep" regnum="73"/>
+  <reg name="p6" bitsize="$predicate_length" type="svep" regnum="74"/>
+  <reg name="p7" bitsize="$predicate_length" type="svep" regnum="75"/>
+  <reg name="p8" bitsize="$predicate_length" type="svep" regnum="76"/>
+  <reg name="p9" bitsize="$predicate_length" type="svep" regnum="77"/>
+  <reg name="p10" bitsize="$predicate_length" type="svep" regnum="78"/>
+  <reg name="p11" bitsize="$predicate_length" type="svep" regnum="79"/>
+  <reg name="p12" bitsize="$predicate_length" type="svep" regnum="80"/>
+  <reg name="p13" bitsize="$predicate_length" type="svep" regnum="81"/>
+  <reg name="p14" bitsize="$predicate_length" type="svep" regnum="82"/>
+  <reg name="p15" bitsize="$predicate_length" type="svep" regnum="83"/>
+  <reg name="ffr" bitsize="$predicate_length" type="svep" regnum="84"/>
+  <reg name="vg" bitsize="64" type="int" regnum="85"/>
+</feature>
index 2eb3af659ad19671a7997437c57a50963c05ddca..0aa626c5414dab101a8ce6abae59c78a9571f399 100644 (file)
@@ -882,11 +882,11 @@ aarch64_adjust_register_sets (const struct aarch64_features &features)
          break;
        case NT_FPREGSET:
          /* This is unavailable when SVE is present.  */
-         if (features.vq == 0)
+         if (!features.sve)
            regset->size = sizeof (struct user_fpsimd_state);
          break;
        case NT_ARM_SVE:
-         if (features.vq > 0)
+         if (features.sve)
            regset->size = SVE_PT_SIZE (AARCH64_MAX_SVE_VQ, SVE_PT_REGS_SVE);
          break;
        case NT_ARM_PAC_MASK:
@@ -934,7 +934,7 @@ aarch64_target::low_arch_setup ()
       struct aarch64_features features;
       int pid = current_thread->id.pid ();
 
-      features.vq = aarch64_sve_get_vq (tid);
+      features.sve = aarch64_sve_get_vq (tid) != 0;
       /* A-profile PAC is 64-bit only.  */
       features.pauth = linux_get_hwcap (pid, 8) & AARCH64_HWCAP_PACA;
       /* A-profile MTE is 64-bit only.  */
index cbd049dbd244c7cdaa8a528136f2554e1ec7262f..84cd8712f25b08bef6104afbbe0b959f45fb8c64 100644 (file)
@@ -37,10 +37,6 @@ aarch64_linux_read_description (const aarch64_features &features)
      initialised.  */
   static gdb::unordered_map<aarch64_features, target_desc *> tdesc_aarch64_map;
 
-  if (features.vq > AARCH64_MAX_SVE_VQ)
-    error (_("VQ is %" PRIu64 ", maximum supported value is %d"), features.vq,
-          AARCH64_MAX_SVE_VQ);
-
   if (features.svq > AARCH64_MAX_SVE_VQ)
     error (_("Streaming svq is %" PRIu8 ", maximum supported value is %d"),
           features.svq,
@@ -60,7 +56,7 @@ aarch64_linux_read_description (const aarch64_features &features)
       expedited_registers.push_back ("sp");
       expedited_registers.push_back ("pc");
 
-      if (features.vq > 0)
+      if (features.sve)
        expedited_registers.push_back ("vg");
       if (features.svq > 0)
        expedited_registers.push_back ("svg");