[ARM] Add support for M-profile MVE extension

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>
This commit is contained in:
Srinath Parvathaneni
2021-07-21 12:33:44 -03:00
committed by Luis Machado
parent ecbf5d4f9b
commit ae66a8f19e
9 changed files with 206 additions and 4 deletions

View File

@ -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

View 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);
}

View 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
};

View 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;
}
}
have_neon = 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_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);
}

View 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. */

View 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},

View 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 \

View File

@ -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;
}

View File

@ -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>