[ARM] Add support for M-profile MVE extension
authorSrinath Parvathaneni <srinath.parvathaneni@arm.com>
Wed, 21 Jul 2021 15:33:44 +0000 (12:33 -0300)
committerLuis Machado <luis.machado@linaro.org>
Mon, 11 Oct 2021 19:03:56 +0000 (16:03 -0300)
This patch adds support for the M-profile MVE extension, which includes the
following:

- New M-profile XML feature m-profile-mve
- MVE vector predication status and control register (VPR)
- p0 pseudo register (contained in the VPR)
- q0 ~ q7 pseudo vector registers
- New feature bits
- Documentation update

Pseudo register p0 is the least significant bits of vpr and can be accessed
as $p0 or displayed through $vpr.  For more information about the register
layout, please refer to [1].

The q0 ~ q7 registers map back to the d0 ~ d15 registers, two d registers
per q register.

The register dump looks like this:

(gdb) info reg all
r0             0x0                 0
r1             0x0                 0
r2             0x0                 0
r3             0x0                 0
r4             0x0                 0
r5             0x0                 0
r6             0x0                 0
r7             0x0                 0
r8             0x0                 0
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x0                 0
sp             0x0                 0x0 <__Vectors>
lr             0xffffffff          -1
pc             0xd0c               0xd0c <Reset_Handler>
xpsr           0x1000000           16777216
d0             0                   (raw 0x0000000000000000)
d1             0                   (raw 0x0000000000000000)
d2             0                   (raw 0x0000000000000000)
d3             0                   (raw 0x0000000000000000)
d4             0                   (raw 0x0000000000000000)
d5             0                   (raw 0x0000000000000000)
d6             0                   (raw 0x0000000000000000)
d7             0                   (raw 0x0000000000000000)
d8             0                   (raw 0x0000000000000000)
d9             0                   (raw 0x0000000000000000)
d10            0                   (raw 0x0000000000000000)
d11            0                   (raw 0x0000000000000000)
d12            0                   (raw 0x0000000000000000)
d13            0                   (raw 0x0000000000000000)
d14            0                   (raw 0x0000000000000000)
d15            0                   (raw 0x0000000000000000)
fpscr          0x0                 0
vpr            0x0                 [ P0=0 MASK01=0 MASK23=0 ]
s0             0                   (raw 0x00000000)
s1             0                   (raw 0x00000000)
s2             0                   (raw 0x00000000)
s3             0                   (raw 0x00000000)
s4             0                   (raw 0x00000000)
s5             0                   (raw 0x00000000)
s6             0                   (raw 0x00000000)
s7             0                   (raw 0x00000000)
s8             0                   (raw 0x00000000)
s9             0                   (raw 0x00000000)
s10            0                   (raw 0x00000000)
s11            0                   (raw 0x00000000)
s12            0                   (raw 0x00000000)
s13            0                   (raw 0x00000000)
s14            0                   (raw 0x00000000)
s15            0                   (raw 0x00000000)
s16            0                   (raw 0x00000000)
s17            0                   (raw 0x00000000)
s18            0                   (raw 0x00000000)
s19            0                   (raw 0x00000000)
s20            0                   (raw 0x00000000)
s21            0                   (raw 0x00000000)
s22            0                   (raw 0x00000000)
s23            0                   (raw 0x00000000)
s24            0                   (raw 0x00000000)
s25            0                   (raw 0x00000000)
s26            0                   (raw 0x00000000)
s27            0                   (raw 0x00000000)
s28            0                   (raw 0x00000000)
s29            0                   (raw 0x00000000)
s30            0                   (raw 0x00000000)
s31            0                   (raw 0x00000000)
q0             {u8 = {0x0 <repeats 16 times>}, u16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, u32 = {0x0, 0x0, 0x0, 0x0}, u64 = {0x0, 0x0}, f32 = {0x0, 0x0, 0x0, 0x0}, f64 = {0x0, 0x0}}
q1             {u8 = {0x0 <repeats 16 times>}, u16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, u32 = {0x0, 0x0, 0x0, 0x0}, u64 = {0x0, 0x0}, f32 = {0x0, 0x0, 0x0, 0x0}, f64 = {0x0, 0x0}}
q2             {u8 = {0x0 <repeats 16 times>}, u16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, u32 = {0x0, 0x0, 0x0, 0x0}, u64 = {0x0, 0x0}, f32 = {0x0, 0x0, 0x0, 0x0}, f64 = {0x0, 0x0}}
q3             {u8 = {0x0 <repeats 16 times>}, u16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, u32 = {0x0, 0x0, 0x0, 0x0}, u64 = {0x0, 0x0}, f32 = {0x0, 0x0, 0x0, 0x0}, f64 = {0x0, 0x0}}
q4             {u8 = {0x0 <repeats 16 times>}, u16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, u32 = {0x0, 0x0, 0x0, 0x0}, u64 = {0x0, 0x0}, f32 = {0x0, 0x0, 0x0, 0x0}, f64 = {0x0, 0x0}}
q5             {u8 = {0x0 <repeats 16 times>}, u16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, u32 = {0x0, 0x0, 0x0, 0x0}, u64 = {0x0, 0x0}, f32 = {0x0, 0x0, 0x0, 0x0}, f64 = {0x0, 0x0}}
q6             {u8 = {0x0 <repeats 16 times>}, u16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, u32 = {0x0, 0x0, 0x0, 0x0}, u64 = {0x0, 0x0}, f32 = {0x0, 0x0, 0x0, 0x0}, f64 = {0x0, 0x0}}
q7             {u8 = {0x0 <repeats 16 times>}, u16 = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, u32 = {0x0, 0x0, 0x0, 0x0}, u64 = {0x0, 0x0}, f32 = {0x0, 0x0, 0x0, 0x0}, f64 = {0x0, 0x0}}
p0             0x0                 0

Built and regtested with a simulator.

[1] https://developer.arm.com/documentation/ddi0553/bn

Co-Authored-By: Luis Machado <luis.machado@linaro.org>
gdb/NEWS
gdb/arch/arm.c
gdb/arch/arm.h
gdb/arm-tdep.c
gdb/arm-tdep.h
gdb/doc/gdb.texinfo
gdb/features/Makefile
gdb/features/arm/arm-m-profile-mve.c [new file with mode: 0644]
gdb/features/arm/arm-m-profile-mve.xml [new file with mode: 0644]

index 7ca1f842cb1e1ffaf91467a0a92160a1306175be..bd26d2b1ec2e012ad104b406d9ee1b7eb7157ae9 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -152,6 +152,10 @@ maint show internal-warning backtrace
   registers of a target.  The precise requirements of this register
   feature are documented in the GDB manual.
 
+* For ARM targets, the "org.gnu.gdb.arm.m-profile-mve" feature is now
+  supported by GDB and describes a new VPR register from the ARM MVE
+  (Helium) extension. See the GDB manual for more information.
+
 * TUI improvements
 
   ** TUI windows now support mouse actions.  The mouse wheel scrolls
index 7407c4a7dadd8358c5cd7ac779b0b7b70e054021..a18b38b9d8115be89e9780a7ffffac2624b212b6 100644 (file)
@@ -27,6 +27,7 @@
 #include "../features/arm/xscale-iwmmxt.c"
 #include "../features/arm/arm-m-profile.c"
 #include "../features/arm/arm-m-profile-with-fpa.c"
+#include "../features/arm/arm-m-profile-mve.c"
 
 /* See arm.h.  */
 
@@ -439,6 +440,12 @@ arm_create_mprofile_target_description (arm_m_profile_type m_type)
       regnum = create_feature_arm_arm_m_profile_with_fpa (tdesc, regnum);
       break;
 
+    case ARM_M_TYPE_MVE:
+      regnum = create_feature_arm_arm_m_profile (tdesc, regnum);
+      regnum = create_feature_arm_arm_vfpv2 (tdesc, regnum);
+      regnum = create_feature_arm_arm_m_profile_mve (tdesc, regnum);
+      break;
+
     default:
       error (_("Invalid Arm M type: %d"), m_type);
     }
index f6a155d6376acaa9324a1cb0fa951a469d5ddf18..eabcb434f1f4263c5ecc8068d5356678916e42c2 100644 (file)
@@ -59,6 +59,8 @@ enum gdb_regnum {
 
 /* Register count constants.  */
 enum arm_register_counts {
+  /* Number of Q registers for MVE.  */
+  ARM_MVE_NUM_Q_REGS = 8,
   /* Number of argument registers.  */
   ARM_NUM_ARG_REGS = 4,
   /* Number of floating point argument registers.  */
@@ -89,6 +91,7 @@ enum arm_m_profile_type {
    ARM_M_TYPE_M_PROFILE,
    ARM_M_TYPE_VFP_D16,
    ARM_M_TYPE_WITH_FPA,
+   ARM_M_TYPE_MVE,
    ARM_M_TYPE_INVALID
 };
 
index 11f5e87445af9daf5bbdc84834f89fcde091189a..d7493f15700a9472b59c825151d7080144db1fac 100644 (file)
@@ -4133,7 +4133,8 @@ is_q_pseudo (struct gdbarch *gdbarch, int regnum)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  /* Q pseudo registers are available for NEON (Q0~Q15).  */
+  /* Q pseudo registers are available for both NEON (Q0~Q15) and
+     MVE (Q0~Q7) features.  */
   if (tdep->have_q_pseudos
       && regnum >= tdep->q_pseudo_base
       && regnum < (tdep->q_pseudo_base + tdep->q_pseudo_count))
@@ -4161,6 +4162,25 @@ is_s_pseudo (struct gdbarch *gdbarch, int regnum)
   return false;
 }
 
+/* Return true if REGNUM is a MVE pseudo register (P0).  Return false
+   otherwise.
+
+   REGNUM is the raw register number and not a pseudo-relative register
+   number.  */
+
+static bool
+is_mve_pseudo (struct gdbarch *gdbarch, int regnum)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->have_mve
+      && regnum >= tdep->mve_pseudo_base
+      && regnum < tdep->mve_pseudo_base + tdep->mve_pseudo_count)
+    return true;
+
+  return false;
+}
+
 /* Return the GDB type object for the "standard" data type of data in
    register N.  */
 
@@ -4175,6 +4195,9 @@ arm_register_type (struct gdbarch *gdbarch, int regnum)
   if (is_q_pseudo (gdbarch, regnum))
     return arm_neon_quad_type (gdbarch);
 
+  if (is_mve_pseudo (gdbarch, regnum))
+    return builtin_type (gdbarch)->builtin_int16;
+
   /* If the target description has register information, we are only
      in this function so that we can override the types of
      double-precision registers for NEON.  */
@@ -8612,6 +8635,9 @@ arm_register_name (struct gdbarch *gdbarch, int i)
       return q_pseudo_names[i - tdep->q_pseudo_base];
     }
 
+  if (is_mve_pseudo (gdbarch, i))
+    return "p0";
+
   if (i >= ARRAY_SIZE (arm_register_names))
     /* These registers are only supported on targets which supply
        an XML description.  */
@@ -8745,6 +8771,19 @@ arm_neon_quad_read (struct gdbarch *gdbarch, readable_regcache *regcache,
   return REG_VALID;
 }
 
+/* Read the contents of the MVE pseudo register REGNUM and store it
+   in BUF.  */
+
+static enum register_status
+arm_mve_pseudo_read (struct gdbarch *gdbarch, readable_regcache *regcache,
+                    int regnum, gdb_byte *buf)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* P0 is the first 16 bits of VPR.  */
+  return regcache->raw_read_part (tdep->mve_vpr_regnum, 0, 2, buf);
+}
+
 static enum register_status
 arm_pseudo_read (struct gdbarch *gdbarch, readable_regcache *regcache,
                 int regnum, gdb_byte *buf)
@@ -8764,6 +8803,8 @@ arm_pseudo_read (struct gdbarch *gdbarch, readable_regcache *regcache,
       return arm_neon_quad_read (gdbarch, regcache,
                                 regnum - tdep->q_pseudo_base, buf);
     }
+  else if (is_mve_pseudo (gdbarch, regnum))
+    return arm_mve_pseudo_read (gdbarch, regcache, regnum, buf);
   else
     {
       enum register_status status;
@@ -8818,6 +8859,18 @@ arm_neon_quad_write (struct gdbarch *gdbarch, struct regcache *regcache,
   regcache->raw_write (double_regnum + 1, buf + offset);
 }
 
+/* Store the contents of BUF to the MVE pseudo register REGNUM.  */
+
+static void
+arm_mve_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
+                     int regnum, const gdb_byte *buf)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* P0 is the first 16 bits of VPR.  */
+  regcache->raw_write_part (tdep->mve_vpr_regnum, 0, 2, buf);
+}
+
 static void
 arm_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
                  int regnum, const gdb_byte *buf)
@@ -8837,6 +8890,8 @@ arm_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
       arm_neon_quad_write (gdbarch, regcache,
                           regnum - tdep->q_pseudo_base, buf);
     }
+  else if (is_mve_pseudo (gdbarch, regnum))
+    arm_mve_pseudo_write (gdbarch, regcache, regnum, buf);
   else
     {
       regnum -= tdep->s_pseudo_base;
@@ -8935,6 +8990,11 @@ arm_register_g_packet_guesses (struct gdbarch *gdbarch)
       register_remote_g_packet_guess (gdbarch,
                                      ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
                                      tdesc);
+      /* M-profile plus MVE.  */
+      tdesc = arm_read_mprofile_description (ARM_M_TYPE_MVE);
+      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE
+                                     + ARM_VFP2_REGS_SIZE
+                                     + ARM_INT_REGISTER_SIZE, tdesc);
     }
 
   /* Otherwise we don't have a useful guess.  */
@@ -8991,6 +9051,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   bool have_neon = false;
   bool have_fpa_registers = true;
   const struct target_desc *tdesc = info.target_desc;
+  bool have_vfp = false;
+  bool have_mve = false;
+  int mve_vpr_regnum = -1;
   int register_count = ARM_NUM_REGS;
 
   /* If we have an object to base this architecture on, try to determine
@@ -9106,6 +9169,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
              if (!tdesc_has_registers (tdesc)
                  && (attr_arch == TAG_CPU_ARCH_V6_M
                      || attr_arch == TAG_CPU_ARCH_V6S_M
+                     || attr_arch == TAG_CPU_ARCH_V8_1M_MAIN
                      || attr_profile == 'M'))
                is_m = true;
 #endif
@@ -9275,6 +9339,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          if (!valid_p)
            return NULL;
 
+         have_vfp = true;
+
          if (tdesc_unnumbered_register (feature, "s0") == 0)
            have_s_pseudos = true;
 
@@ -9296,8 +9362,41 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                 the default type.  */
              if (tdesc_unnumbered_register (feature, "q0") == 0)
                have_q_pseudos = true;
+           }
+       }
+
+      /* Check for MVE after all the checks for GPR's, VFP and Neon.
+        MVE (Helium) is an M-profile extension.  */
+      if (is_m)
+       {
+         /* Do we have the MVE feature?  */
+         feature = tdesc_find_feature (tdesc,"org.gnu.gdb.arm.m-profile-mve");
+
+         if (feature != nullptr)
+           {
+             /* If we have MVE, we must always have the VPR register.  */
+             valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+                                                 register_count, "vpr");
+             if (!valid_p)
+               {
+                 warning (_("MVE feature is missing required register vpr."));
+                 return nullptr;
+               }
 
-             have_neon = true;
+             have_mve = true;
+             mve_vpr_regnum = register_count;
+             register_count++;
+
+             /* We can't have Q pseudo registers available here, as that
+                would mean we have NEON features, and that is only available
+                on A and R profiles.  */
+             gdb_assert (!have_q_pseudos);
+
+             /* Given we have a M-profile target description, if MVE is
+                enabled and there are VFP registers, we should have Q
+                pseudo registers (Q0 ~ Q7).  */
+             if (have_vfp)
+               have_q_pseudos = true;
            }
        }
     }
@@ -9349,6 +9448,13 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->have_q_pseudos = have_q_pseudos;
   tdep->have_neon = have_neon;
 
+  /* Adjust the MVE feature settings.  */
+  if (have_mve)
+    {
+      tdep->have_mve = true;
+      tdep->mve_vpr_regnum = mve_vpr_regnum;
+    }
+
   arm_register_g_packet_guesses (gdbarch);
 
   /* Breakpoints.  */
@@ -9530,21 +9636,39 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     }
 
   /* Initialize the pseudo register data.  */
+  int num_pseudos = 0;
   if (tdep->have_s_pseudos)
     {
       /* VFP single precision pseudo registers (S0~S31).  */
       tdep->s_pseudo_base = register_count;
       tdep->s_pseudo_count = 32;
-      int num_pseudos = tdep->s_pseudo_count;
+      num_pseudos += tdep->s_pseudo_count;
 
       if (tdep->have_q_pseudos)
        {
          /* NEON quad precision pseudo registers (Q0~Q15).  */
          tdep->q_pseudo_base = register_count + num_pseudos;
-         tdep->q_pseudo_count = 16;
+
+         if (have_neon)
+           tdep->q_pseudo_count = 16;
+         else if (have_mve)
+           tdep->q_pseudo_count = ARM_MVE_NUM_Q_REGS;
+
          num_pseudos += tdep->q_pseudo_count;
        }
+    }
 
+  /* Do we have any MVE pseudo registers?  */
+  if (have_mve)
+    {
+      tdep->mve_pseudo_base = register_count + num_pseudos;
+      tdep->mve_pseudo_count = 1;
+      num_pseudos += tdep->mve_pseudo_count;
+    }
+
+  /* Set some pseudo register hooks, if we have pseudo registers.  */
+  if (tdep->have_s_pseudos || have_mve)
+    {
       set_gdbarch_num_pseudo_regs (gdbarch, num_pseudos);
       set_gdbarch_pseudo_register_read (gdbarch, arm_pseudo_read);
       set_gdbarch_pseudo_register_write (gdbarch, arm_pseudo_write);
@@ -9595,6 +9719,14 @@ arm_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
                      (int) tdep->q_pseudo_count);
   fprintf_unfiltered (file, _("arm_dump_tdep: have_neon = %i\n"),
                      (int) tdep->have_neon);
+  fprintf_unfiltered (file, _("arm_dump_tdep: have_mve = %s\n"),
+                     tdep->have_mve? "yes" : "no");
+  fprintf_unfiltered (file, _("arm_dump_tdep: mve_vpr_regnum = %i\n"),
+                     tdep->mve_vpr_regnum);
+  fprintf_unfiltered (file, _("arm_dump_tdep: mve_pseudo_base = %i\n"),
+                     tdep->mve_pseudo_base);
+  fprintf_unfiltered (file, _("arm_dump_tdep: mve_pseudo_count = %i\n"),
+                     tdep->mve_pseudo_count);
   fprintf_unfiltered (file, _("arm_dump_tdep: Lowest pc = 0x%lx\n"),
                      (unsigned long) tdep->lowest_pc);
 }
index 63b89520c898fabbe50f1fffbb5c6dc86707e142..705aa77a0ed65f4f6f008152e8fdf2b12f8759a4 100644 (file)
@@ -114,6 +114,11 @@ struct gdbarch_tdep
                                   registers.  */
   bool have_neon;              /* Do we have a NEON unit?  */
 
+  bool have_mve;               /* Do we have a MVE extension?  */
+  int mve_vpr_regnum;          /* MVE VPR register number.  */
+  int mve_pseudo_base;         /* Number of the first MVE pseudo register.  */
+  int mve_pseudo_count;                /* Total number of MVE pseudo registers.  */
+
   bool is_m;                   /* Does the target follow the "M" profile.  */
   CORE_ADDR lowest_pc;         /* Lowest address at which instructions 
                                   will appear.  */
index a6f207a41a7fdee1bcd8798a982ec22e682a37a9..631a7c03b31e39404a71e1668b87278ea1b6e05b 100644 (file)
@@ -46212,6 +46212,17 @@ and @samp{xpsr}.
 The @samp{org.gnu.gdb.arm.fpa} feature is optional.  If present, it
 should contain registers @samp{f0} through @samp{f7} and @samp{fps}.
 
+The @samp{org.gnu.gdb.arm.m-profile-mve} feature is optional.  If present, it
+must contain register @samp{vpr}.
+
+If the @samp{org.gnu.gdb.arm.m-profile-mve} feature is available, @value{GDBN}
+will synthesize the @samp{p0} pseudo register from @samp{vpr} contents.
+
+If the @samp{org.gnu.gdb.arm.vfp} feature is available alongside the
+@samp{org.gnu.gdb.arm.m-profile-mve} feature, @value{GDBN} will
+synthesize the @samp{q} pseudo registers from @samp{d} register
+contents.
+
 The @samp{org.gnu.gdb.xscale.iwmmxt} feature is optional.  If present,
 it should contain at least registers @samp{wR0} through @samp{wR15} and
 @samp{wCGR0} through @samp{wCGR3}.  The @samp{wCID}, @samp{wCon},
index aa38d176539fbb2d5f03d9cb6e3d8d4fd36f0215..e478bf838b7844191c0580c3a742d5da82fbaed8 100644 (file)
@@ -203,6 +203,7 @@ FEATURE_XMLFILES = aarch64-core.xml \
        arm/arm-core.xml \
        arm/arm-fpa.xml \
        arm/arm-m-profile.xml \
+       arm/arm-m-profile-mve.xml \
        arm/arm-m-profile-with-fpa.xml \
        arm/arm-vfpv2.xml \
        arm/arm-vfpv3.xml \
diff --git a/gdb/features/arm/arm-m-profile-mve.c b/gdb/features/arm/arm-m-profile-mve.c
new file mode 100644 (file)
index 0000000..532ae3b
--- /dev/null
@@ -0,0 +1,20 @@
+/* THIS FILE IS GENERATED.  -*- buffer-read-only: t -*- vi:set ro:
+  Original: arm-m-profile-mve.xml */
+
+#include "gdbsupport/tdesc.h"
+
+static int
+create_feature_arm_arm_m_profile_mve (struct target_desc *result, long regnum)
+{
+  struct tdesc_feature *feature;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.m-profile-mve");
+  tdesc_type_with_fields *type_with_fields;
+  type_with_fields = tdesc_create_flags (feature, "vpr_reg", 4);
+  tdesc_add_bitfield (type_with_fields, "P0", 0, 15);
+  tdesc_add_bitfield (type_with_fields, "MASK01", 16, 19);
+  tdesc_add_bitfield (type_with_fields, "MASK23", 20, 23);
+
+  tdesc_create_reg (feature, "vpr", regnum++, 1, NULL, 32, "vpr_reg");
+  return regnum;
+}
diff --git a/gdb/features/arm/arm-m-profile-mve.xml b/gdb/features/arm/arm-m-profile-mve.xml
new file mode 100644 (file)
index 0000000..cba664c
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2021 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.arm.m-profile-mve">
+  <flags id="vpr_reg" size="4">
+    <!-- ARMv8.1-M and MVE: Unprivileged and privileged Access.  -->
+    <field name="P0" start="0" end="15"/>
+    <!-- ARMv8.1-M: Privileged Access only.  -->
+    <field name="MASK01" start="16" end="19"/>
+    <!-- ARMv8.1-M: Privileged Access only.  -->
+    <field name="MASK23" start="20" end="23"/>
+  </flags>
+  <reg name="vpr" bitsize="32" type="vpr_reg"/>
+</feature>