[PATCH 1/8] Add Aarch64 SVE target description

Alan Hayward
2018-05-11T10:53:14Z

This patch adds the SVE target description. However, no code will
yet use it - that comes in the later patches.

The create_feature_aarch64_sve function is not generated from XML.
This is because we need to know the sve vector size (VQ) in order
to size the registers correctly.

A VQ of 0 is used when the hardware does not support SVE.
(SVE hardware will always have a valid vector size). I considered
using a bool to indicate SVE in addition to the VQ. Whilst this
may be slightly more readable initially, I think it's a little
odd to have two variables, eg:
aarch64_create_target_description (bool sve_supported, long vq)

Alan.

2018-05-11 Alan Hayward <alan.hayward@arm.com>

gdb/
* aarch64-linux-nat.c (aarch64_linux_read_description):
Add parmeter zero.
* aarch64-linux-tdep.c (aarch64_linux_core_read_description):
Likewise.
* aarch64-tdep.c (tdesc_aarch64_list): Add.
(aarch64_read_description): Use VQ to index tdesc_aarch64_list.
(aarch64_gdbarch_init): Add parmeter zero.
* aarch64-tdep.h (aarch64_read_description): Add VQ parmeter.
* arch/aarch64.c (aarch64_create_target_description): Check VQ.
* arch/aarch64.h (aarch64_create_target_description): Add VQ.
parmeter.
* doc/gdb.texinfo: Describe SVE feature
* features/aarch64-sve.c: New file.

gdbserver/
* linux-aarch64-tdesc.c (aarch64_linux_read_description): Add
null VQ.
---
gdb/aarch64-linux-nat.c | 3 +-
gdb/aarch64-linux-tdep.c | 5 +-
gdb/aarch64-tdep.c | 30 +++++--
gdb/aarch64-tdep.h | 2 +-
gdb/arch/aarch64.c | 12 ++-
gdb/arch/aarch64.h | 5 +-
gdb/doc/gdb.texinfo | 4 +
gdb/features/aarch64-sve.c | 158 ++++++++++++++++++++++++++++++++++++
gdb/gdbserver/linux-aarch64-tdesc.c | 3 +-
9 files changed, 204 insertions(+), 18 deletions(-)
create mode 100644 gdb/features/aarch64-sve.c

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 908b83a49a..9a6ee91d2d 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -541,7 +541,8 @@ aarch64_linux_nat_target::read_description ()
if (ret == 0)
return tdesc_arm_with_neon;
else
- return aarch64_read_description ();
+ /* SVE not yet supported. */
+ return aarch64_read_description (0);
}

/* Convert a native/host siginfo object, into/from the siginfo in the
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 1f3e888e40..b84dcfa9ed 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -233,7 +233,8 @@ aarch64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
NULL, cb_data);
}

-/* Implement the "core_read_description" gdbarch method. */
+/* Implement the "core_read_description" gdbarch method. SVE not yet
+ supported. */

static const struct target_desc *
aarch64_linux_core_read_description (struct gdbarch *gdbarch,
@@ -244,7 +245,7 @@ aarch64_linux_core_read_description (struct gdbarch *gdbarch,
if (target_auxv_search (target, AT_HWCAP, &aarch64_hwcap) != 1)
return NULL;

- return aarch64_read_description ();
+ return aarch64_read_description (0);
}

/* Implementation of `gdbarch_stap_is_single_operand', as defined in
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 01566b475f..806a3dac55 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -70,6 +70,9 @@
#define AARCH64_H0_REGNUM (AARCH64_S0_REGNUM + 32)
#define AARCH64_B0_REGNUM (AARCH64_H0_REGNUM + 32)

+/* All possible aarch64 target descriptors. */
+struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1];
+
/* The standard register names, and all the valid aliases for them. */
static const struct
{
@@ -2827,18 +2830,26 @@ aarch64_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
return 1;
}

-/* Get the correct target description. */
+/* Get the correct target description for the given VQ value.
+ If VQ is zero then it is assumed SVE is not supported.
+ (It is not possible to set VQ to zero on an SVE system). */

const target_desc *
-aarch64_read_description ()
+aarch64_read_description (long vq)
{
- static target_desc *aarch64_tdesc = NULL;
- target_desc **tdesc = &aarch64_tdesc;
+ if (vq > AARCH64_MAX_SVE_VQ)
+ error (_("VQ is %ld, maximum supported value is %d"), vq,
+ AARCH64_MAX_SVE_VQ);
+
+ struct target_desc *tdesc = tdesc_aarch64_list[vq];

- if (*tdesc == NULL)
- *tdesc = aarch64_create_target_description ();
+ if (tdesc == NULL)
+ {
+ tdesc = aarch64_create_target_description (vq);
+ tdesc_aarch64_list[vq] = tdesc;
+ }

- return *tdesc;
+ return tdesc;
}

/* Initialize the current architecture based on INFO. If possible,
@@ -2864,7 +2875,8 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)

/* Ensure we always have a target descriptor. */
if (!tdesc_has_registers (tdesc))
- tdesc = aarch64_read_description ();
+ /* SVE is not yet supported. */
+ tdesc = aarch64_read_description (0);

gdb_assert (tdesc);

@@ -3077,7 +3089,7 @@ When on, AArch64 specific debugging is enabled."),
selftests::register_test ("aarch64-process-record",
selftests::aarch64_process_record_test);
selftests::record_xml_tdesc ("aarch64.xml",
- aarch64_create_target_description ());
+ aarch64_create_target_description (0));
#endif
}

diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index c806125fb7..c9fd7b3578 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -75,7 +75,7 @@ struct gdbarch_tdep
int (*aarch64_syscall_record) (struct regcache *regcache, unsigned long svc_number);
};

-const target_desc *aarch64_read_description ();
+const target_desc *aarch64_read_description (long vq);

extern int aarch64_process_record (struct gdbarch *gdbarch,
struct regcache *regcache, CORE_ADDR addr);
diff --git a/gdb/arch/aarch64.c b/gdb/arch/aarch64.c
index b85e460b6b..d1ec5cedf8 100644
--- a/gdb/arch/aarch64.c
+++ b/gdb/arch/aarch64.c
@@ -21,11 +21,13 @@

#include "../features/aarch64-core.c"
#include "../features/aarch64-fpu.c"
+#include "../features/aarch64-sve.c"

-/* Create the aarch64 target description. */
+/* Create the aarch64 target description. A non zero VQ value indicates both
+ the presence of SVE and the SVE vector quotient. */

target_desc *
-aarch64_create_target_description ()
+aarch64_create_target_description (long vq)
{
target_desc *tdesc = allocate_target_description ();

@@ -36,7 +38,11 @@ aarch64_create_target_description ()
long regnum = 0;

regnum = create_feature_aarch64_core (tdesc, regnum);
- regnum = create_feature_aarch64_fpu (tdesc, regnum);
+
+ if (vq == 0)
+ regnum = create_feature_aarch64_fpu (tdesc, regnum);
+ else
+ regnum = create_feature_aarch64_sve (tdesc, regnum, vq);

return tdesc;
}
diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
index 86185f596a..1846e04163 100644
--- a/gdb/arch/aarch64.h
+++ b/gdb/arch/aarch64.h
@@ -22,7 +22,7 @@

#include "common/tdesc.h"

-target_desc *aarch64_create_target_description ();
+target_desc *aarch64_create_target_description (long vq);

/* Register numbers of various important registers. */
enum aarch64_regnum
@@ -48,4 +48,7 @@ enum aarch64_regnum
#define AARCH64_V_REGS_NUM 32
#define AARCH64_NUM_REGS AARCH64_FPCR_REGNUM + 1

+/* Maximum supported VQ value. Increase if required. */
+#define AARCH64_MAX_SVE_VQ 16
+
#endif /* ARCH_AARCH64_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 28f083f96e..04f811032a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -42134,6 +42134,10 @@ The @samp{org.gnu.gdb.aarch64.fpu} feature is optional. If present,
it should contain registers @samp{v0} through @samp{v31}, @samp{fpsr},
and @samp{fpcr}.

+The @samp{org.gnu.gdb.aarch64.sve} feature is optional. If present,
+it should contain registers @samp{z0} through @samp{z31}, @samp{p0}
+through @samp{p15}, @samp{ffr} and @samp{vg}.
+
@node ARC Features
@subsection ARC Features
@cindex target descriptions, ARC Features
diff --git a/gdb/features/aarch64-sve.c b/gdb/features/aarch64-sve.c
new file mode 100644
index 0000000000..6442640a73
--- /dev/null
+++ b/gdb/features/aarch64-sve.c
@@ -0,0 +1,158 @@
+/* Copyright (C) 2017 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/>. */
+
+#include "common/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,
+ int scale)
+{
+ 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");
+
+ element_type = tdesc_named_type (feature, "ieee_double");
+ tdesc_create_vector (feature, "svevdf", element_type, 2 * scale);
+
+ element_type = tdesc_named_type (feature, "uint64");
+ tdesc_create_vector (feature, "svevdu", element_type, 2 * scale);
+
+ element_type = tdesc_named_type (feature, "int64");
+ tdesc_create_vector (feature, "svevds", element_type, 2 * scale);
+
+ element_type = tdesc_named_type (feature, "ieee_single");
+ tdesc_create_vector (feature, "svevsf", element_type, 4 * scale);
+
+ element_type = tdesc_named_type (feature, "uint32");
+ tdesc_create_vector (feature, "svevsu", element_type, 4 * scale);
+
+ element_type = tdesc_named_type (feature, "int32");
+ tdesc_create_vector (feature, "svevss", element_type, 4 * scale);
+
+ element_type = tdesc_named_type (feature, "uint16");
+ tdesc_create_vector (feature, "svevhu", element_type, 8 * scale);
+
+ element_type = tdesc_named_type (feature, "int16");
+ tdesc_create_vector (feature, "svevhs", element_type, 8 * scale);
+
+ element_type = tdesc_named_type (feature, "uint8");
+ tdesc_create_vector (feature, "svevbu", element_type, 16 * scale);
+
+ element_type = tdesc_named_type (feature, "int8");
+ tdesc_create_vector (feature, "svevbs", element_type, 16 * scale);
+
+ type_with_fields = tdesc_create_union (feature, "svevnd");
+ field_type = tdesc_named_type (feature, "svevdf");
+ tdesc_add_field (type_with_fields, "f", field_type);
+ field_type = tdesc_named_type (feature, "svevdu");
+ tdesc_add_field (type_with_fields, "u", field_type);
+ field_type = tdesc_named_type (feature, "svevds");
+ tdesc_add_field (type_with_fields, "s", field_type);
+
+ type_with_fields = tdesc_create_union (feature, "svevns");
+ field_type = tdesc_named_type (feature, "svevsf");
+ tdesc_add_field (type_with_fields, "f", field_type);
+ field_type = tdesc_named_type (feature, "svevsu");
+ tdesc_add_field (type_with_fields, "u", field_type);
+ field_type = tdesc_named_type (feature, "svevss");
+ tdesc_add_field (type_with_fields, "s", field_type);
+
+ type_with_fields = tdesc_create_union (feature, "svevnh");
+ field_type = tdesc_named_type (feature, "svevhu");
+ tdesc_add_field (type_with_fields, "u", field_type);
+ field_type = tdesc_named_type (feature, "svevhs");
+ tdesc_add_field (type_with_fields, "s", field_type);
+
+ type_with_fields = tdesc_create_union (feature, "svevnb");
+ field_type = tdesc_named_type (feature, "svevbu");
+ tdesc_add_field (type_with_fields, "u", field_type);
+ field_type = tdesc_named_type (feature, "svevbs");
+ tdesc_add_field (type_with_fields, "s", field_type);
+
+ type_with_fields = tdesc_create_union (feature, "svev");
+ field_type = tdesc_named_type (feature, "svevnd");
+ tdesc_add_field (type_with_fields, "d", field_type);
+ field_type = tdesc_named_type (feature, "svevns");
+ tdesc_add_field (type_with_fields, "s", field_type);
+ field_type = tdesc_named_type (feature, "svevnh");
+ tdesc_add_field (type_with_fields, "h", field_type);
+ 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);
+
+ 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");
+ tdesc_create_reg (feature, "fpsr", regnum++, 1, NULL, 32, "int");
+ tdesc_create_reg (feature, "fpcr", regnum++, 1, NULL, 32, "int");
+ 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, "vg", regnum++, 1, NULL, 64, "int");
+ return regnum;
+}
diff --git a/gdb/gdbserver/linux-aarch64-tdesc.c b/gdb/gdbserver/linux-aarch64-tdesc.c
index 9f7b9e5c85..3b36c47cfa 100644
--- a/gdb/gdbserver/linux-aarch64-tdesc.c
+++ b/gdb/gdbserver/linux-aarch64-tdesc.c
@@ -32,7 +32,8 @@ aarch64_linux_read_description ()

if (*tdesc == NULL)
{
- *tdesc = aarch64_create_target_description ();
+ /* SVE not yet supported. */
+ *tdesc = aarch64_create_target_description (0);

init_target_desc (*tdesc);

--
2.15.1 (Apple Git-101)