[PATCH v5 15/16] [gdb/testsuite] sme: Add SVE/SME testcases

Luis Machado via Gdb-patches
2023-09-07T15:24:04Z

v3:

- Additional documentation for some testcases based on upstream reviews.
- Addressed upstream review comments.

v2:
- Introduced a couple helper functions to determine the available SVE and SME
vector lengths.

- Before running a batch of tests, validate that the target supports a certain
SVE vector length or SME streaming vector length. If not supported, skip
that batch of tests.

- Fixed up native core file testing to remove generation of a spurious core
file, which later would be reported as unexpected by the testsuite.

- Fixed tpidr2 dump in core file tests.
--

Add 5 SVE/SME tests to exercise all the new features like reading/writing
registers, pseudo-registers, signal frames and core files.

- Sanity check for SME: Gives a brief smoke test to make sure the most basic
of features are working correctly.

- ZA unavailability tests: Validates the behavior/content of the ZA register
is correct when no payload is available. It also exercises changing the
vector lengths.

- ZA Availability tests: These tests exercise reading/writing to all the
possible ZA pseudo-registers, and validates the state is correct.

- Core file tests: Validates that core file reading and writing works
correctly and that all state dumped/loaded is sane. This is exercised for
both Linux Kernel core files and gcore core files.

- Signal frame tests: Validates the correct restoration of SME/SVE/FPSIMD
values across signal frames.

Since some of these tests are very lengthy and take a little while to run
(under QEMU at the moment), I decided to parallelize them into smaller
chunks so we can throw some more CPU power at them so they run faster.

I'd still like to add a few more tests to give the testsuite more coverage
in the areas of SME/SVE. Hopefully in the near future that will happen.

Just a reminder that most of these tests will FAIL when running against
gdbserver because all of the tests change the vector length mid-execution
in some way. Since gdbserver can't communicate the change of state over
RSP to GDB, we will always get wrong state from gdbserver.

Co-Authored-By: Ezra Sitorus <ezra.sitorus@arm.com>
---
gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp | 23 ++
gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp | 23 ++
gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp | 23 ++
gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp | 23 ++
gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp | 23 ++
gdb/testsuite/gdb.arch/aarch64-sme-core.c | 372 ++++++++++++++++++
.../gdb.arch/aarch64-sme-core.exp.tcl | 179 +++++++++
.../gdb.arch/aarch64-sme-regs-available-0.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available-1.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available-2.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available-3.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available-4.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available-5.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available-6.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available-7.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available-8.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available-9.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-available.c | 178 +++++++++
.../aarch64-sme-regs-available.exp.tcl | 237 +++++++++++
.../gdb.arch/aarch64-sme-regs-sigframe-0.exp | 23 ++
.../gdb.arch/aarch64-sme-regs-sigframe-1.exp | 23 ++
.../gdb.arch/aarch64-sme-regs-sigframe-2.exp | 23 ++
.../gdb.arch/aarch64-sme-regs-sigframe-3.exp | 23 ++
.../gdb.arch/aarch64-sme-regs-sigframe-4.exp | 23 ++
.../gdb.arch/aarch64-sme-regs-sigframe.c | 366 +++++++++++++++++
.../aarch64-sme-regs-sigframe.exp.tcl | 171 ++++++++
.../aarch64-sme-regs-unavailable-0.exp | 26 ++
.../aarch64-sme-regs-unavailable-1.exp | 26 ++
.../aarch64-sme-regs-unavailable-2.exp | 26 ++
.../aarch64-sme-regs-unavailable-3.exp | 26 ++
.../aarch64-sme-regs-unavailable-4.exp | 26 ++
.../aarch64-sme-regs-unavailable-5.exp | 26 ++
.../aarch64-sme-regs-unavailable-6.exp | 26 ++
.../aarch64-sme-regs-unavailable-7.exp | 26 ++
.../aarch64-sme-regs-unavailable-8.exp | 26 ++
.../aarch64-sme-regs-unavailable-9.exp | 26 ++
.../gdb.arch/aarch64-sme-regs-unavailable.c | 152 +++++++
.../aarch64-sme-regs-unavailable.exp.tcl | 204 ++++++++++
gdb/testsuite/gdb.arch/aarch64-sme-sanity.c | 249 ++++++++++++
gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp | 64 +++
gdb/testsuite/lib/aarch64-scalable.exp | 239 +++++++++++
gdb/testsuite/lib/aarch64-test-sme.c | 90 +++++
gdb/testsuite/lib/aarch64-test-sve.c | 90 +++++
gdb/testsuite/lib/aarch64.exp | 153 +++++++
gdb/testsuite/lib/gdb.exp | 249 ++++++++++++
45 files changed, 3743 insertions(+)
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-0.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-1.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-2.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-3.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-4.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-5.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-6.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-7.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-8.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-9.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-0.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-1.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-2.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-3.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-4.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-0.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-1.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-2.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-3.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-4.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-5.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-6.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-7.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-8.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-9.exp
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-sanity.c
create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp
create mode 100644 gdb/testsuite/lib/aarch64-scalable.exp
create mode 100644 gdb/testsuite/lib/aarch64-test-sme.c
create mode 100644 gdb/testsuite/lib/aarch64-test-sve.c
create mode 100644 gdb/testsuite/lib/aarch64.exp

diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp
new file mode 100644
index 00000000000..5a51bbd8a1d
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: FPSIMD
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (0 ~ 24) out of 125 tests.
+set id_start 0
+set id_end 24
+source $srcdir/$subdir/aarch64-sme-core.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp
new file mode 100644
index 00000000000..41e93b15834
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: SVE
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (25 ~ 49) out of 125 tests.
+set id_start 25
+set id_end 49
+source $srcdir/$subdir/aarch64-sme-core.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp
new file mode 100644
index 00000000000..05144d9f560
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: SSVE
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (50 ~ 74) out of 125 tests.
+set id_start 50
+set id_end 74
+source $srcdir/$subdir/aarch64-sme-core.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp
new file mode 100644
index 00000000000..fa8931a46d1
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: ZA only
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (75 ~ 99) out of 125 tests.
+set id_start 75
+set id_end 99
+source $srcdir/$subdir/aarch64-sme-core.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp
new file mode 100644
index 00000000000..8881898b370
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: ZA + SSVE
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (100 ~ 124) out of 125 tests.
+set id_start 100
+set id_end 124
+source $srcdir/$subdir/aarch64-sme-core.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core.c b/gdb/testsuite/gdb.arch/aarch64-sme-core.c
new file mode 100644
index 00000000000..d71d18ebd3b
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core.c
@@ -0,0 +1,372 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* Exercise AArch64's Scalable Vector/Matrix Extension core file generation
+ for GDB. This includes reading Linux Kernel-generated core files and
+ writing GDB core files via the gcore command and making sure the contents
+ are sane. */
+
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HWCAP_SVE
+#define HWCAP_SVE (1 << 22)
+#endif
+
+#ifndef HWCAP2_SME
+#define HWCAP2_SME (1 << 23)
+#endif
+
+#ifndef PR_SVE_SET_VL
+#define PR_SVE_SET_VL 50
+#define PR_SVE_GET_VL 51
+#define PR_SVE_VL_LEN_MASK 0xffff
+#endif
+
+#ifndef PR_SME_SET_VL
+#define PR_SME_SET_VL 63
+#define PR_SME_GET_VL 64
+#define PR_SME_VL_LEN_MASK 0xffff
+#endif
+
+static void
+enable_za ()
+{
+ /* smstart za */
+ __asm __volatile (".word 0xD503457F");
+}
+
+static void
+disable_za ()
+{
+ /* smstop za */
+ __asm __volatile (".word 0xD503447F");
+}
+
+static void
+enable_sm ()
+{
+ /* smstart sm */
+ __asm __volatile (".word 0xD503437F");
+}
+
+static void
+disable_sm ()
+{
+ /* smstop sm */
+ __asm __volatile (".word 0xD503427F");
+}
+
+static void
+initialize_fpsimd_state ()
+{
+ char buffer[16];
+
+ for (int i = 0; i < 16; i++)
+ buffer[i] = 0x55;
+
+ __asm __volatile ("mov x0, %0\n\t" \
+ : : "r" (buffer));
+
+ __asm __volatile ("ldr q0, [x0]");
+ __asm __volatile ("ldr q1, [x0]");
+ __asm __volatile ("ldr q2, [x0]");
+ __asm __volatile ("ldr q3, [x0]");
+ __asm __volatile ("ldr q4, [x0]");
+ __asm __volatile ("ldr q5, [x0]");
+ __asm __volatile ("ldr q6, [x0]");
+ __asm __volatile ("ldr q7, [x0]");
+ __asm __volatile ("ldr q8, [x0]");
+ __asm __volatile ("ldr q9, [x0]");
+ __asm __volatile ("ldr q10, [x0]");
+ __asm __volatile ("ldr q11, [x0]");
+ __asm __volatile ("ldr q12, [x0]");
+ __asm __volatile ("ldr q13, [x0]");
+ __asm __volatile ("ldr q14, [x0]");
+ __asm __volatile ("ldr q15, [x0]");
+ __asm __volatile ("ldr q16, [x0]");
+ __asm __volatile ("ldr q17, [x0]");
+ __asm __volatile ("ldr q18, [x0]");
+ __asm __volatile ("ldr q19, [x0]");
+ __asm __volatile ("ldr q20, [x0]");
+ __asm __volatile ("ldr q21, [x0]");
+ __asm __volatile ("ldr q22, [x0]");
+ __asm __volatile ("ldr q23, [x0]");
+ __asm __volatile ("ldr q24, [x0]");
+ __asm __volatile ("ldr q25, [x0]");
+ __asm __volatile ("ldr q26, [x0]");
+ __asm __volatile ("ldr q27, [x0]");
+ __asm __volatile ("ldr q28, [x0]");
+ __asm __volatile ("ldr q29, [x0]");
+ __asm __volatile ("ldr q30, [x0]");
+ __asm __volatile ("ldr q31, [x0]");
+}
+
+static void
+initialize_za_state ()
+{
+ /* zero za */
+ __asm __volatile (".word 0xC00800FF");
+
+ char buffer[256];
+
+ for (int i = 0; i < 256; i++)
+ buffer[i] = 0xaa;
+
+ __asm __volatile ("mov x0, %0\n\t" \
+ : : "r" (buffer));
+
+ /* Initialize loop boundaries. */
+ __asm __volatile ("mov w12, 0");
+ __asm __volatile ("mov w17, 256");
+
+ /* loop: ldr za[w12, 0], [x0] */
+ __asm __volatile ("loop: .word 0xe1000000");
+ __asm __volatile ("add w12, w12, 1");
+ __asm __volatile ("cmp w12, w17");
+ __asm __volatile ("bne loop");
+}
+
+static void
+initialize_tpidr2 ()
+{
+ __asm __volatile ("mov x0, #0xffffffffffffffff");
+
+ /* Write x0 to tpidr2. */
+ __asm __volatile (".word 0xd51bd0a0");
+}
+
+static void
+initialize_sve_state ()
+{
+ __asm __volatile ("dup z0.b, -1");
+ __asm __volatile ("dup z1.b, -1");
+ __asm __volatile ("dup z2.b, -1");
+ __asm __volatile ("dup z3.b, -1");
+ __asm __volatile ("dup z4.b, -1");
+ __asm __volatile ("dup z5.b, -1");
+ __asm __volatile ("dup z6.b, -1");
+ __asm __volatile ("dup z7.b, -1");
+ __asm __volatile ("dup z8.b, -1");
+ __asm __volatile ("dup z9.b, -1");
+ __asm __volatile ("dup z10.b, -1");
+ __asm __volatile ("dup z11.b, -1");
+ __asm __volatile ("dup z12.b, -1");
+ __asm __volatile ("dup z13.b, -1");
+ __asm __volatile ("dup z14.b, -1");
+ __asm __volatile ("dup z15.b, -1");
+ __asm __volatile ("dup z16.b, -1");
+ __asm __volatile ("dup z17.b, -1");
+ __asm __volatile ("dup z18.b, -1");
+ __asm __volatile ("dup z19.b, -1");
+ __asm __volatile ("dup z20.b, -1");
+ __asm __volatile ("dup z21.b, -1");
+ __asm __volatile ("dup z22.b, -1");
+ __asm __volatile ("dup z23.b, -1");
+ __asm __volatile ("dup z24.b, -1");
+ __asm __volatile ("dup z25.b, -1");
+ __asm __volatile ("dup z26.b, -1");
+ __asm __volatile ("dup z27.b, -1");
+ __asm __volatile ("dup z28.b, -1");
+ __asm __volatile ("dup z29.b, -1");
+ __asm __volatile ("dup z30.b, -1");
+ __asm __volatile ("dup z31.b, -1");
+ __asm __volatile ("ptrue p0.b");
+ __asm __volatile ("ptrue p1.b");
+ __asm __volatile ("ptrue p2.b");
+ __asm __volatile ("ptrue p3.b");
+ __asm __volatile ("ptrue p4.b");
+ __asm __volatile ("ptrue p5.b");
+ __asm __volatile ("ptrue p6.b");
+ __asm __volatile ("ptrue p7.b");
+ __asm __volatile ("ptrue p8.b");
+ __asm __volatile ("ptrue p9.b");
+ __asm __volatile ("ptrue p10.b");
+ __asm __volatile ("ptrue p11.b");
+ __asm __volatile ("ptrue p12.b");
+ __asm __volatile ("ptrue p13.b");
+ __asm __volatile ("ptrue p14.b");
+ __asm __volatile ("ptrue p15.b");
+ __asm __volatile ("setffr");
+}
+
+static int get_vl_size ()
+{
+ int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SVE_GET_VL (%d)", res);
+ return -1;
+ }
+ return (res & PR_SVE_VL_LEN_MASK);
+}
+
+static int get_svl_size ()
+{
+ int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SME_GET_VL (%d)\n", res);
+ return -1;
+ }
+ return (res & PR_SVE_VL_LEN_MASK);
+}
+
+static int set_vl_size (int new_vl)
+{
+ int res = prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SVE_SET_VL (%d)\n", res);
+ return -1;
+ }
+
+ res = get_vl_size ();
+ if (res != new_vl)
+ {
+ printf ("Unexpected VL value (%d)\n", res);
+ return -1;
+ }
+
+ return res;
+}
+
+static int set_svl_size (int new_svl)
+{
+ int res = prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SME_SET_VL (%d)\n", res);
+ return -1;
+ }
+
+ res = get_svl_size ();
+ if (res != new_svl)
+ {
+ printf ("Unexpected SVL value (%d)\n", res);
+ return -1;
+ }
+
+ return res;
+}
+
+/* Enable register states based on STATE.
+
+ 0 - FPSIMD
+ 1 - SVE
+ 2 - SSVE
+ 3 - ZA
+ 4 - ZA and SSVE. */
+
+void enable_states (int state)
+{
+ disable_za ();
+ disable_sm ();
+ initialize_fpsimd_state ();
+
+ if (state == 1)
+ {
+ initialize_sve_state ();
+ }
+ else if (state == 2)
+ {
+ enable_sm ();
+ initialize_sve_state ();
+ }
+ else if (state == 3)
+ {
+ enable_za ();
+ initialize_za_state ();
+ }
+ else if (state == 4)
+ {
+ enable_za ();
+ enable_sm ();
+ initialize_sve_state ();
+ initialize_za_state ();
+ }
+
+ return;
+}
+
+static int
+test_id_to_state (int id)
+{
+ return id / 25;
+}
+
+static int
+test_id_to_vl (int id)
+{
+ return 16 << ((id / 5) % 5);
+}
+
+static int
+test_id_to_svl (int id)
+{
+ return 16 << (id % 5);
+}
+
+static void
+dummy ()
+{
+}
+
+int
+main (int argc, char **argv)
+{
+ if (argc > 2)
+ printf ("Incorrect number of arguments passed to test.\n");
+
+ if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME)
+ {
+ long test_id = 0;
+
+ /* If we have a test id passed as argument, read it now. */
+ if (argc == 2)
+ test_id = strtol (argv[1], NULL, 0);
+
+ dummy (); /* stop to initialize test_id */
+
+ int state = test_id_to_state (test_id);
+ int vl = test_id_to_vl (test_id);
+ int svl = test_id_to_svl (test_id);
+
+ if (set_vl_size (vl) == -1 || set_svl_size (svl) == -1)
+ return -1;
+
+ enable_states (state);
+
+ /* Also set the TPIDR2 register so we can test dumping its contents
+ to a core file. */
+ initialize_tpidr2 ();
+
+ char *p = 0x0;
+ *p = 0xff; /* crash point */
+ }
+ else
+ {
+ printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl
new file mode 100644
index 00000000000..35e3d981e10
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl
@@ -0,0 +1,179 @@
+# Copyright (C) 2023 Free Software Foundation, Inc.
+
+# 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/>.
+#
+# Exercise core file reading/writing in the presence of SME support.
+# This test exercises GDB's dumping/loading capability for Linux
+# Kernel core files and for gcore core files.
+
+load_lib aarch64-scalable.exp
+
+#
+# Validate that CORE_FILENAME can be read correctly and that the register
+# state is sane.
+#
+proc check_sme_core_file { core_filename state vl svl } {
+ # Load the core file.
+ if [gdb_test "core $core_filename" \
+ [multi_line \
+ "Core was generated by.*\." \
+ "Program terminated with signal SIGSEGV, Segmentation fault\." \
+ "#0 ${::hex} in main \\(.*\\) at .*" \
+ ".*p = 0xff;.* crash point .*"] \
+ "load core file"] {
+ untested "failed to generate core file"
+ return -1
+ }
+
+ check_state $state $vl $svl
+
+ # Check the value of TPIDR2 in the core file.
+ gdb_test "print/x \$tpidr2" " = 0xffffffffffffffff" \
+ "tpidr2 contents from core file"
+}
+
+#
+# Generate two core files for EXECUTABLE, BINFILE with a test id of ID.
+# STATE is the register state, VL is the SVE vector length and SVL is the
+# SME vector length.
+# One of the core files is generated by the kernel and the other by the
+# gcore command.
+#
+proc generate_sme_core_files { executable binfile id state vl svl} {
+ # Run the program until the point where we need to adjust the
+ # test id.
+ set init_breakpoint "stop to initialize test_id"
+ gdb_breakpoint [gdb_get_line_number $init_breakpoint]
+ gdb_continue_to_breakpoint $init_breakpoint
+ gdb_test_no_output "set test_id = $id"
+
+ # Run the program until just before the crash.
+ set crash_breakpoint "crash point"
+ gdb_breakpoint [gdb_get_line_number $crash_breakpoint]
+ gdb_continue_to_breakpoint $crash_breakpoint
+ gdb_test_no_output "set print repeats 1" "adjust repeat count pre-crash"
+
+ # Adjust the register to custom values that we will check later when
+ # loading the core files.
+ check_state $state $vl $svl
+
+ # Continue until a crash.
+ gdb_test "continue" \
+ [multi_line \
+ "Program received signal SIGSEGV, Segmentation fault\." \
+ "${::hex} in main \\(.*\\) at .*" \
+ ".*p = 0xff;.* crash point .*"] \
+ "run to crash"
+
+ # Generate the gcore core file.
+ set gcore_filename [standard_output_file "${executable}-${id}-${state}-${vl}-${svl}.gcore"]
+ set gcore_generated [gdb_gcore_cmd "$gcore_filename" "generate gcore file"]
+
+# # Continue until the end.
+# gdb_test "continue" "Program terminated with signal SIGSEGV.*" \
+# "program terminated with SIGSEGV"
+
+ # Generate a native core file.
+ set core_filename [core_find ${binfile} {} $id]
+ set core_generated [expr {$core_filename != ""}]
+ set native_core_name "${binfile}-${id}-${state}-${vl}-${svl}.core"
+ remote_exec build "mv $core_filename ${native_core_name}"
+ set core_filename ${native_core_name}
+
+ # At this point we have a couple core files, the gcore one generated by GDB
+ # and the native one generated by the Linux Kernel. Make sure GDB can read
+ # both correctly.
+ if {$gcore_generated} {
+ clean_restart ${binfile}
+ gdb_test_no_output "set print repeats 1" \
+ "adjust repeat count post-crash gcore"
+
+ with_test_prefix "gcore corefile" {
+ check_sme_core_file $gcore_filename $state $vl $svl
+ }
+ } else {
+ fail "gcore corefile not generated"
+ }
+
+ if {$core_generated} {
+ clean_restart ${binfile}
+
+ gdb_test_no_output "set print repeats 1" \
+ "adjust repeat count post-crash native core"
+
+ with_test_prefix "native corefile" {
+ check_sme_core_file $core_filename $state $vl $svl
+ }
+ } else {
+ untested "native corefile not generated"
+ }
+}
+
+#
+# Exercise core file reading (kernel-generated core files) and writing
+# (gcore command) for test id's ID_START through ID_END.
+#
+proc test_sme_core_file { id_start id_end } {
+ set compile_flags {"debug" "macros" "additional_flags=-march=armv8.5-a+sve"}
+ standard_testfile ${::srcdir}/${::subdir}/aarch64-sme-core.c
+ set executable "${::testfile}"
+ if {[prepare_for_testing "failed to prepare" ${executable} ${::srcfile} ${compile_flags}]} {
+ return -1
+ }
+ set binfile [standard_output_file ${executable}]
+
+ for {set id $id_start} {$id <= $id_end} {incr id} {
+ set state [test_id_to_state $id]
+ set vl [test_id_to_vl $id]
+ set svl [test_id_to_svl $id]
+
+ set skip_unsupported 0
+ if {![aarch64_supports_sve_vl $vl]
+ || ![aarch64_supports_sme_svl $svl]} {
+ # We have a vector length or streaming vector length that
+ # is not supported by this target. Skip to the next iteration
+ # since it is no use running tests for an unsupported vector
+ # length.
+ if {![aarch64_supports_sve_vl $vl]} {
+ verbose -log "SVE vector length $vl not supported."
+ } elseif {![aarch64_supports_sme_svl $svl]} {
+ verbose -log "SME streaming vector length $svl not supported."
+ }
+ verbose -log "Skipping test."
+ set skip_unsupported 1
+ }
+
+ with_test_prefix "state=${state} vl=${vl} svl=${svl}" {
+ # If the SVE or SME vector length is not supported, just skip
+ # these next tests.
+ if {$skip_unsupported} {
+ untested "unsupported configuration on target"
+ continue
+ }
+
+ if ![runto_main] {
+ untested "could not run to main"
+ return -1
+ }
+
+ generate_sme_core_files ${executable} ${binfile} $id $state $vl $svl
+ }
+ }
+}
+
+require is_aarch64_target
+require allow_aarch64_sve_tests
+require allow_aarch64_sme_tests
+
+test_sme_core_file $id_start $id_end
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-0.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-0.exp
new file mode 100644
index 00000000000..2a4980171e7
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-0.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 16
+# SVL: 16, 32, 64, 128
+# This set covers 4 (0 ~ 3) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 0
+set id_end 3
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-1.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-1.exp
new file mode 100644
index 00000000000..a58e89caab3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-1.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 16
+# SVL: 256
+# This set covers 1 (4) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 4
+set id_end 4
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-2.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-2.exp
new file mode 100644
index 00000000000..8b78e9ec639
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-2.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 32
+# SVL: 16, 32, 64, 128
+# This set covers 4 (5 ~ 8) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 5
+set id_end 8
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-3.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-3.exp
new file mode 100644
index 00000000000..57941758870
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-3.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 32
+# SVL: 256
+# This set covers 1 (9) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 9
+set id_end 9
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-4.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-4.exp
new file mode 100644
index 00000000000..5d5e800d328
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-4.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 64
+# SVL: 16, 32, 64, 128
+# This set covers 4 (10 ~ 13) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 10
+set id_end 13
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-5.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-5.exp
new file mode 100644
index 00000000000..42410d4eb20
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-5.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 64
+# SVL: 256
+# This set covers 1 (14) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 14
+set id_end 14
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-6.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-6.exp
new file mode 100644
index 00000000000..36692ac31c1
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-6.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 128
+# SVL: 16, 32, 64, 128
+# This set covers 4 (15 ~ 18) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 15
+set id_end 18
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-7.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-7.exp
new file mode 100644
index 00000000000..a3149e7fcae
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-7.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 128
+# SVL: 256
+# This set covers 1 (19) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 19
+set id_end 19
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-8.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-8.exp
new file mode 100644
index 00000000000..1859eaf9960
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-8.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 256
+# SVL: 16, 32, 64, 128
+# This set covers 4 (20 ~ 23) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 20
+set id_end 23
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-9.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-9.exp
new file mode 100644
index 00000000000..cb30fc63724
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-9.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 256
+# SVL: 256
+# This set covers 1 (24) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 24
+set id_end 24
+source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.c b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.c
new file mode 100644
index 00000000000..58c01d0bf9a
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.c
@@ -0,0 +1,178 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* Exercise various cases of reading/writing ZA contents for AArch64's
+ Scalable Matrix Extension. */
+
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HWCAP_SVE
+#define HWCAP_SVE (1 << 22)
+#endif
+
+#ifndef HWCAP2_SME
+#define HWCAP2_SME (1 << 23)
+#endif
+
+#ifndef PR_SVE_SET_VL
+#define PR_SVE_SET_VL 50
+#define PR_SVE_GET_VL 51
+#define PR_SVE_VL_LEN_MASK 0xffff
+#endif
+
+#ifndef PR_SME_SET_VL
+#define PR_SME_SET_VL 63
+#define PR_SME_GET_VL 64
+#define PR_SME_VL_LEN_MASK 0xffff
+#endif
+
+static void
+enable_za ()
+{
+ /* smstart za */
+ __asm __volatile (".word 0xD503457F");
+}
+
+static void
+disable_za ()
+{
+ /* smstop za */
+ __asm __volatile (".word 0xD503447F");
+}
+
+static int get_vl_size ()
+{
+ int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SVE_GET_VL (%d)\n", res);
+ return -1;
+ }
+ return (res & PR_SVE_VL_LEN_MASK);
+}
+
+static int get_svl_size ()
+{
+ int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SME_GET_VL (%d)\n", res);
+ return -1;
+ }
+ return (res & PR_SVE_VL_LEN_MASK);
+}
+
+static int set_vl_size (int new_vl)
+{
+ int res = prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SVE_SET_VL (%d)\n", res);
+ return -1;
+ }
+
+ res = get_vl_size ();
+ if (res != new_vl)
+ {
+ printf ("Unexpected VL value (%d)\n", res);
+ return -1;
+ }
+
+ return res;
+}
+
+static int set_svl_size (int new_svl)
+{
+ int res = prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SME_SET_VL (%d)\n", res);
+ return -1;
+ }
+
+ res = get_svl_size ();
+ if (res != new_svl)
+ {
+ printf ("Unexpected SVL value (%d)\n", res);
+ return -1;
+ }
+
+ return res;
+}
+
+static int
+test_id_to_vl (int id)
+{
+ return 16 << ((id / 5) % 5);
+}
+
+static int
+test_id_to_svl (int id)
+{
+ return 16 << (id % 5);
+}
+
+static void
+dummy ()
+{
+}
+
+int
+main (int argc, char **argv)
+{
+ if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME)
+ {
+ int id_start = ID_START;
+ int id_end = ID_END;
+
+ for (int id = id_start; id <= id_end; id++)
+ {
+ int vl = test_id_to_vl (id);
+ int svl = test_id_to_svl (id);
+
+ if (set_vl_size (vl) == -1 || set_svl_size (svl) == -1)
+ continue;
+
+ enable_za ();
+ dummy (); /* stop 1 */
+ }
+
+ for (int id = id_start; id <= id_end; id++)
+ {
+ int vl = test_id_to_vl (id);
+ int svl = test_id_to_svl (id);
+
+ if (set_vl_size (vl) == -1 || set_svl_size (svl) == -1)
+ continue;
+
+ disable_za ();
+ dummy (); /* stop 2 */
+ }
+ }
+ else
+ {
+ printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl
new file mode 100644
index 00000000000..ad3f0ee1dcc
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl
@@ -0,0 +1,237 @@
+# Copyright (C) 2023 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Exercise reading/writing ZA registers when there is ZA state.
+
+load_lib aarch64-scalable.exp
+
+#
+# Cycle through all ZA registers and pseudo-registers and validate that their
+# contents are available for vector length SVL.
+#
+# Make sure reading/writing to ZA registers work as expected.
+#
+proc check_regs { mode vl svl } {
+ # Check VG to make sure it is correct
+ set expected_vg [expr $vl / 8]
+ gdb_test "print \$vg" "= ${expected_vg}"
+
+ # Check SVG to make sure it is correct
+ set expected_svg [expr $svl / 8]
+ gdb_test "print \$svg" "= ${expected_svg}"
+
+ # If svl is adjusted by prctl, we will have ZA enabled. If gdb is
+ # adjusting svl, ZA will not be enabled by default. It will only be
+ # enabled when ZA is written to.
+ set za_state "= \\\[ ZA \\\]"
+ if {$mode == "gdb"} {
+ set za_state "= \\\[ \\\]"
+ }
+
+ # Check SVCR.
+ if [gdb_test "print \$svcr" $za_state "svcr before assignments" ] {
+ fail "incorrect za state"
+ return -1
+ }
+
+ # Check the size of ZA.
+ set expected_za_size [expr $svl * $svl]
+ gdb_test "print sizeof \$za" " = $expected_za_size"
+
+ # Check the size of Z0.
+ gdb_test "print sizeof \$z0" " = $vl"
+
+ # Exercise reading/writing from/to ZA.
+ initialize_2d_array "\$za" 255 $svl $svl
+ set pattern [string_to_regexp [2d_array_value_pattern 255 $svl $svl]]
+ gdb_test "print \$za" " = $pattern" "read back from za"
+
+ # Exercise reading/writing from/to the tile pseudo-registers.
+ set last_tile 1
+ set expected_size [expr $svl * $svl]
+ set tile_svl $svl
+ set za_state "= \\\[ ZA \\\]"
+ foreach_with_prefix granularity {"b" "h" "s" "d" "q"} {
+ for {set tile 0} {$tile < $last_tile} {incr tile} {
+ set register_name "\$za${tile}${granularity}"
+
+ # Test the size.
+ gdb_test "print sizeof ${register_name}" " = ${expected_size}"
+
+ # Test reading/writing
+ initialize_2d_array $register_name 255 $tile_svl $tile_svl
+
+ # Make sure we have ZA state.
+ if [gdb_test "print \$svcr" $za_state "svcr after assignment to ${register_name}" ] {
+ fail "incorrect za state"
+ return -1
+ }
+
+ set pattern [string_to_regexp [2d_array_value_pattern 255 $tile_svl $tile_svl]]
+ gdb_test "print $register_name" " = $pattern" "read back from $register_name"
+ }
+ set last_tile [expr $last_tile * 2]
+ set expected_size [expr $expected_size / 2]
+ set tile_svl [expr $tile_svl / 2]
+ }
+
+ # Exercise reading/writing from/to the tile slice pseudo-registers.
+ set last_tile 1
+ set last_slice $svl
+ set expected_size $svl
+ set num_elements $svl
+ foreach_with_prefix granularity {"b" "h" "s" "d" "q"} {
+ for {set tile 0} {$tile < $last_tile} {incr tile} {
+ for {set slice 0} {$slice < $last_slice} {incr slice} {
+ foreach_with_prefix direction {"h" "v"} {
+ set register_name "\$za${tile}${direction}${granularity}${slice}"
+
+ # Test the size.
+ gdb_test "print sizeof ${register_name}" " = ${expected_size}"
+
+ # Test reading/writing
+ initialize_1d_array $register_name 255 $num_elements
+
+ # Make sure we have ZA state.
+ if [gdb_test "print \$svcr" $za_state "svcr after assignment of ${register_name}" ] {
+ fail "incorrect za state"
+ return -1
+ }
+
+ set pattern [string_to_regexp [1d_array_value_pattern 255 $num_elements]]
+ gdb_test "print $register_name" " = $pattern" "read back from $register_name"
+ }
+ }
+ }
+ set last_tile [expr $last_tile * 2]
+ set last_slice [expr ($last_slice / 2)]
+ set num_elements [expr $num_elements / 2]
+ }
+}
+
+#
+# Cycle through all ZA registers and pseudo-registers and validate their
+# contents.
+#
+proc test_sme_registers_available { id_start id_end } {
+
+ set compile_flags {"debug" "macros"}
+ lappend compile_flags "additional_flags=-DID_START=${id_start}"
+ lappend compile_flags "additional_flags=-DID_END=${id_end}"
+
+ standard_testfile ${::srcdir}/${::subdir}/aarch64-sme-regs-available.c
+ set executable "${::testfile}-${id_start}-${id_end}"
+ if {[prepare_for_testing "failed to prepare" ${executable} ${::srcfile} ${compile_flags}]} {
+ return -1
+ }
+ set binfile [standard_output_file ${executable}]
+
+ if ![runto_main] {
+ untested "could not run to main"
+ return -1
+ }
+
+ gdb_test_no_output "set print repeats 1"
+
+ set prctl_breakpoint "stop 1"
+ gdb_breakpoint [gdb_get_line_number $prctl_breakpoint]
+
+ for {set id $id_start} {$id <= $id_end} {incr id} {
+ set vl [test_id_to_vl $id]
+ set svl [test_id_to_svl $id]
+
+ set skip_unsupported 0
+ if {![aarch64_supports_sve_vl $vl]
+ || ![aarch64_supports_sme_svl $svl]} {
+ # We have a vector length or streaming vector length that
+ # is not supported by this target. Skip to the next iteration
+ # since it is no use running tests for an unsupported vector
+ # length.
+ if {![aarch64_supports_sve_vl $vl]} {
+ verbose -log "SVE vector length $vl not supported."
+ } elseif {![aarch64_supports_sme_svl $svl]} {
+ verbose -log "SME streaming vector length $svl not supported."
+ }
+ verbose -log "Skipping test."
+ set skip_unsupported 1
+ }
+
+ set mode "prctl"
+ with_test_prefix "$mode, vl=${vl} svl=${svl}" {
+ # If the SVE or SME vector length is not supported, just skip
+ # these next tests.
+ if {$skip_unsupported} {
+ untested "unsupported configuration on target"
+ continue
+ }
+
+ # Run the program until it has adjusted svl.
+ gdb_continue_to_breakpoint $prctl_breakpoint
+ check_regs $mode $vl $svl
+ }
+ }
+
+ set non_prctl_breakpoint "stop 2"
+ gdb_breakpoint [gdb_get_line_number $non_prctl_breakpoint]
+
+ for {set id $id_start} {$id <= $id_end} {incr id} {
+ set vl [test_id_to_vl $id]
+ set svl [test_id_to_svl $id]
+
+ set skip_unsupported 0
+ if {![aarch64_supports_sve_vl $vl]
+ || ![aarch64_supports_sme_svl $svl]} {
+ # We have a vector length or streaming vector length that
+ # is not supported by this target. Skip to the next iteration
+ # since it is no use running tests for an unsupported vector
+ # length.
+ if {![aarch64_supports_sve_vl $vl]} {
+ verbose -log "SVE vector length $vl not supported."
+ } elseif {![aarch64_supports_sme_svl $svl]} {
+ verbose -log "SME streaming vector length $svl not supported."
+ }
+ verbose -log "Skipping test."
+ set skip_unsupported 1
+ }
+
+ set mode "gdb"
+ with_test_prefix "$mode, vl=${vl} svl=${svl}" {
+ # If the SVE or SME vector length is not supported, just skip
+ # these next tests.
+ if {$skip_unsupported} {
+ untested "unsupported configuration on target"
+ continue
+ }
+
+ # Run the program until we stop at the point where gdb should
+ # adjust the SVE and SME vector lengths.
+ gdb_continue_to_breakpoint $non_prctl_breakpoint
+
+ # Adjust svl via gdb.
+ set vg_value [expr $vl / 8]
+ set svg_value [expr $svl / 8]
+ gdb_test_no_output "set \$vg = ${vg_value}"
+ gdb_test_no_output "set \$svg = ${svg_value}"
+
+ check_regs $mode $vl $svl
+ }
+ }
+}
+
+require is_aarch64_target
+require allow_aarch64_sve_tests
+require allow_aarch64_sme_tests
+
+test_sme_registers_available $id_start $id_end
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-0.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-0.exp
new file mode 100644
index 00000000000..ce8a7a703aa
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-0.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: FPSIMD
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (0 ~ 24) out of 125 tests.
+set id_start 0
+set id_end 24
+source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-1.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-1.exp
new file mode 100644
index 00000000000..092d4b20c48
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-1.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: SVE
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (25 ~ 49) out of 125 tests.
+set id_start 25
+set id_end 49
+source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-2.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-2.exp
new file mode 100644
index 00000000000..803d297f70d
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-2.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: SSVE
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (50 ~ 74) out of 125 tests.
+set id_start 50
+set id_end 74
+source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-3.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-3.exp
new file mode 100644
index 00000000000..d1307571bfa
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-3.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: ZA only
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (75 ~ 99) out of 125 tests.
+set id_start 75
+set id_end 99
+source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-4.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-4.exp
new file mode 100644
index 00000000000..2b84b5dcfc7
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-4.exp
@@ -0,0 +1,23 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# state: ZA + SSVE
+# VL: 16, 32, 64, 128, 256
+# SVL: 16, 32, 64, 128, 256
+# This set covers 25 (100 ~ 124) out of 125 tests.
+set id_start 100
+set id_end 124
+source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c
new file mode 100644
index 00000000000..9bc3e9c16fc
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c
@@ -0,0 +1,366 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* Exercise AArch64's Scalable Vector/Matrix Extension signal frame handling
+ for GDB. */
+
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+
+#ifndef HWCAP_SVE
+#define HWCAP_SVE (1 << 22)
+#endif
+
+#ifndef HWCAP2_SME
+#define HWCAP2_SME (1 << 23)
+#endif
+
+#ifndef PR_SVE_SET_VL
+#define PR_SVE_SET_VL 50
+#define PR_SVE_GET_VL 51
+#define PR_SVE_VL_LEN_MASK 0xffff
+#endif
+
+#ifndef PR_SME_SET_VL
+#define PR_SME_SET_VL 63
+#define PR_SME_GET_VL 64
+#define PR_SME_VL_LEN_MASK 0xffff
+#endif
+
+static int count = 0;
+
+static void
+handler (int sig)
+{
+ count++; /* handler */
+}
+
+static void
+enable_za ()
+{
+ /* smstart za */
+ __asm __volatile (".word 0xD503457F");
+}
+
+static void
+disable_za ()
+{
+ /* smstop za */
+ __asm __volatile (".word 0xD503447F");
+}
+
+static void
+enable_sm ()
+{
+ /* smstart sm */
+ __asm __volatile (".word 0xD503437F");
+}
+
+static void
+disable_sm ()
+{
+ /* smstop sm */
+ __asm __volatile (".word 0xD503427F");
+}
+
+static void
+initialize_fpsimd_state ()
+{
+ char buffer[16];
+
+ for (int i = 0; i < 16; i++)
+ buffer[i] = 0x55;
+
+ __asm __volatile ("mov x0, %0\n\t" \
+ : : "r" (buffer));
+
+ __asm __volatile ("ldr q0, [x0]");
+ __asm __volatile ("ldr q1, [x0]");
+ __asm __volatile ("ldr q2, [x0]");
+ __asm __volatile ("ldr q3, [x0]");
+ __asm __volatile ("ldr q4, [x0]");
+ __asm __volatile ("ldr q5, [x0]");
+ __asm __volatile ("ldr q6, [x0]");
+ __asm __volatile ("ldr q7, [x0]");
+ __asm __volatile ("ldr q8, [x0]");
+ __asm __volatile ("ldr q9, [x0]");
+ __asm __volatile ("ldr q10, [x0]");
+ __asm __volatile ("ldr q11, [x0]");
+ __asm __volatile ("ldr q12, [x0]");
+ __asm __volatile ("ldr q13, [x0]");
+ __asm __volatile ("ldr q14, [x0]");
+ __asm __volatile ("ldr q15, [x0]");
+ __asm __volatile ("ldr q16, [x0]");
+ __asm __volatile ("ldr q17, [x0]");
+ __asm __volatile ("ldr q18, [x0]");
+ __asm __volatile ("ldr q19, [x0]");
+ __asm __volatile ("ldr q20, [x0]");
+ __asm __volatile ("ldr q21, [x0]");
+ __asm __volatile ("ldr q22, [x0]");
+ __asm __volatile ("ldr q23, [x0]");
+ __asm __volatile ("ldr q24, [x0]");
+ __asm __volatile ("ldr q25, [x0]");
+ __asm __volatile ("ldr q26, [x0]");
+ __asm __volatile ("ldr q27, [x0]");
+ __asm __volatile ("ldr q28, [x0]");
+ __asm __volatile ("ldr q29, [x0]");
+ __asm __volatile ("ldr q30, [x0]");
+ __asm __volatile ("ldr q31, [x0]");
+}
+
+static void
+initialize_za_state ()
+{
+ /* zero za */
+ __asm __volatile (".word 0xC00800FF");
+
+ char buffer[256];
+
+ for (int i = 0; i < 256; i++)
+ buffer[i] = 0xaa;
+
+ __asm __volatile ("mov x0, %0\n\t" \
+ : : "r" (buffer));
+
+ /* Initialize loop boundaries. */
+ __asm __volatile ("mov w12, 0");
+ __asm __volatile ("mov w17, 256");
+
+ /* loop: ldr za[w12, 0], [x0] */
+ __asm __volatile ("loop: .word 0xe1000000");
+ __asm __volatile ("add w12, w12, 1");
+ __asm __volatile ("cmp w12, w17");
+ __asm __volatile ("bne loop");
+}
+
+static void
+initialize_sve_state ()
+{
+ __asm __volatile ("dup z0.b, -1");
+ __asm __volatile ("dup z1.b, -1");
+ __asm __volatile ("dup z2.b, -1");
+ __asm __volatile ("dup z3.b, -1");
+ __asm __volatile ("dup z4.b, -1");
+ __asm __volatile ("dup z5.b, -1");
+ __asm __volatile ("dup z6.b, -1");
+ __asm __volatile ("dup z7.b, -1");
+ __asm __volatile ("dup z8.b, -1");
+ __asm __volatile ("dup z9.b, -1");
+ __asm __volatile ("dup z10.b, -1");
+ __asm __volatile ("dup z11.b, -1");
+ __asm __volatile ("dup z12.b, -1");
+ __asm __volatile ("dup z13.b, -1");
+ __asm __volatile ("dup z14.b, -1");
+ __asm __volatile ("dup z15.b, -1");
+ __asm __volatile ("dup z16.b, -1");
+ __asm __volatile ("dup z17.b, -1");
+ __asm __volatile ("dup z18.b, -1");
+ __asm __volatile ("dup z19.b, -1");
+ __asm __volatile ("dup z20.b, -1");
+ __asm __volatile ("dup z21.b, -1");
+ __asm __volatile ("dup z22.b, -1");
+ __asm __volatile ("dup z23.b, -1");
+ __asm __volatile ("dup z24.b, -1");
+ __asm __volatile ("dup z25.b, -1");
+ __asm __volatile ("dup z26.b, -1");
+ __asm __volatile ("dup z27.b, -1");
+ __asm __volatile ("dup z28.b, -1");
+ __asm __volatile ("dup z29.b, -1");
+ __asm __volatile ("dup z30.b, -1");
+ __asm __volatile ("dup z31.b, -1");
+ __asm __volatile ("ptrue p0.b");
+ __asm __volatile ("ptrue p1.b");
+ __asm __volatile ("ptrue p2.b");
+ __asm __volatile ("ptrue p3.b");
+ __asm __volatile ("ptrue p4.b");
+ __asm __volatile ("ptrue p5.b");
+ __asm __volatile ("ptrue p6.b");
+ __asm __volatile ("ptrue p7.b");
+ __asm __volatile ("ptrue p8.b");
+ __asm __volatile ("ptrue p9.b");
+ __asm __volatile ("ptrue p10.b");
+ __asm __volatile ("ptrue p11.b");
+ __asm __volatile ("ptrue p12.b");
+ __asm __volatile ("ptrue p13.b");
+ __asm __volatile ("ptrue p14.b");
+ __asm __volatile ("ptrue p15.b");
+ __asm __volatile ("setffr");
+}
+
+static int get_vl_size ()
+{
+ int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SVE_GET_VL (%d)\n", res);
+ return -1;
+ }
+ return (res & PR_SVE_VL_LEN_MASK);
+}
+
+static int get_svl_size ()
+{
+ int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SME_GET_VL (%d)\n", res);
+ return -1;
+ }
+ return (res & PR_SVE_VL_LEN_MASK);
+}
+
+static int set_vl_size (int new_vl)
+{
+ int res = prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SVE_SET_VL (%d)\n", res);
+ return -1;
+ }
+
+ res = get_vl_size ();
+ if (res != new_vl)
+ {
+ printf ("Unexpected VL value (%d)\n", res);
+ return -1;
+ }
+
+ return res;
+}
+
+static int set_svl_size (int new_svl)
+{
+ int res = prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SME_SET_VL (%d)\n", res);
+ return -1;
+ }
+
+ res = get_svl_size ();
+ if (res != new_svl)
+ {
+ printf ("Unexpected SVL value (%d)\n", res);
+ return -1;
+ }
+
+ return res;
+}
+
+/* Enable register states based on STATE.
+
+ 0 - FPSIMD
+ 1 - SVE
+ 2 - SSVE
+ 3 - ZA
+ 4 - ZA and SSVE. */
+
+void enable_states (int state)
+{
+ disable_za ();
+ disable_sm ();
+ initialize_fpsimd_state ();
+
+ if (state == 1)
+ {
+ initialize_sve_state ();
+ }
+ else if (state == 2)
+ {
+ enable_sm ();
+ initialize_sve_state ();
+ }
+ else if (state == 3)
+ {
+ enable_za ();
+ initialize_za_state ();
+ }
+ else if (state == 4)
+ {
+ enable_za ();
+ enable_sm ();
+ initialize_sve_state ();
+ initialize_za_state ();
+ }
+
+ return;
+}
+
+static int
+test_id_to_state (int id)
+{
+ return (id / 25);
+}
+
+static int
+test_id_to_vl (int id)
+{
+ return 16 << ((id / 5) % 5);
+}
+
+static int
+test_id_to_svl (int id)
+{
+ return 16 << (id % 5);
+}
+
+static void
+dummy ()
+{
+}
+
+int
+main (int argc, char **argv)
+{
+ if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME)
+ {
+ int id_start = ID_START;
+ int id_end = ID_END;
+#ifdef SIGILL
+ signal (SIGILL, handler);
+#endif
+
+ int signal_count = 0;
+ for (int id = id_start; id <= id_end; id++)
+ {
+ int state = test_id_to_state (id);
+ int vl = test_id_to_vl (id);
+ int svl = test_id_to_svl (id);
+
+ if (set_vl_size (vl) == -1 || set_svl_size (svl) == -1)
+ continue;
+
+ signal_count++;
+ enable_states (state);
+ dummy (); /* stop before SIGILL */
+ __asm __volatile (".word 0xDEADBEEF"); /* illegal instruction */
+ while (signal_count != count);
+ }
+ }
+ else
+ {
+ printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl
new file mode 100644
index 00000000000..c2962417f70
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl
@@ -0,0 +1,171 @@
+# Copyright (C) 2023 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Exercise restoring SME/TPIDR2 state from a signal frame.
+
+load_lib aarch64-scalable.exp
+
+#
+# Validate the state of registers in the signal frame for various states.
+#
+proc test_sme_registers_sigframe { id_start id_end } {
+
+ set compile_flags {"debug" "macros"}
+ lappend compile_flags "additional_flags=-march=armv8.5-a+sve"
+ lappend compile_flags "additional_flags=-DID_START=${id_start}"
+ lappend compile_flags "additional_flags=-DID_END=${id_end}"
+
+ standard_testfile ${::srcdir}/${::subdir}/aarch64-sme-regs-sigframe.c
+ set executable "${::testfile}-${id_start}-${id_end}"
+ if {[prepare_for_testing "failed to prepare" ${executable} ${::srcfile} ${compile_flags}]} {
+ return -1
+ }
+ set binfile [standard_output_file ${executable}]
+
+ if ![runto_main] {
+ untested "could not run to main"
+ return -1
+ }
+
+ set sigill_breakpoint "stop before SIGILL"
+ set handler_breakpoint "handler"
+ gdb_breakpoint [gdb_get_line_number $sigill_breakpoint]
+ gdb_breakpoint [gdb_get_line_number $handler_breakpoint]
+
+ for {set id $id_start} {$id <= $id_end} {incr id} {
+ set state [test_id_to_state $id]
+ set vl [test_id_to_vl $id]
+ set svl [test_id_to_svl $id]
+
+ set skip_unsupported 0
+ if {![aarch64_supports_sve_vl $vl]
+ || ![aarch64_supports_sme_svl $svl]} {
+ # We have a vector length or streaming vector length that
+ # is not supported by this target. Skip to the next iteration
+ # since it is no use running tests for an unsupported vector
+ # length.
+ if {![aarch64_supports_sve_vl $vl]} {
+ verbose -log "SVE vector length $vl not supported."
+ } elseif {![aarch64_supports_sme_svl $svl]} {
+ verbose -log "SME streaming vector length $svl not supported."
+ }
+ verbose -log "Skipping test."
+ set skip_unsupported 1
+ }
+
+ with_test_prefix "state=${state} vl=${vl} svl=${svl}" {
+
+ # If the SVE or SME vector length is not supported, just skip
+ # these next tests.
+ if {$skip_unsupported} {
+ untested "unsupported configuration on target"
+ continue
+ }
+
+ # Run the program until it has adjusted the svl.
+ if [gdb_continue_to_breakpoint $sigill_breakpoint] {
+ return -1
+ }
+
+ # Check SVG to make sure it is correct
+ set expected_svg [expr $svl / 8]
+ gdb_test "print \$svg" "= ${expected_svg}"
+
+ # Check the size of ZA.
+ set expected_za_size [expr $svl * $svl]
+ gdb_test "print sizeof \$za" " = $expected_za_size"
+
+ # Check the value of SVCR.
+ gdb_test "print \$svcr" [get_svcr_value $state] "svcr before signal"
+
+ # Handle SME ZA initialization and state.
+ set byte 0
+ if { $state == "za" || $state == "za_ssve" } {
+ set byte 170
+ }
+
+ # Set the expected ZA pattern.
+ set za_pattern [string_to_regexp [2d_array_value_pattern $byte $svl $svl]]
+
+ # Handle SVE/SSVE initialization and state.
+ set sve_vl $svl
+ if { $state == "ssve" || $state == "za_ssve" } {
+ # SVE state comes from SSVE.
+ set sve_vl $svl
+ } else {
+ # SVE state comes from regular SVE.
+ set sve_vl $vl
+ }
+
+ # Initialize the SVE state.
+ set sve_pattern [string_to_regexp [sve_value_pattern $state $sve_vl 85 255]]
+ for {set row 0} {$row < 32} {incr row} {
+ set register_name "\$z${row}\.b\.u"
+ gdb_test "print sizeof $register_name" " = $sve_vl" "size of $register_name"
+ gdb_test "print $register_name" $sve_pattern "read back from $register_name"
+ }
+
+ # Print ZA to check its value.
+ gdb_test "print \$za" $za_pattern "read back from za"
+
+ # Test TPIDR2 restore from signal frame as well.
+ gdb_test_no_output "set \$tpidr2=0x0102030405060708"
+
+ # Run to the illegal instruction.
+ if [gdb_test "continue" "Continuing\.\r\n\r\nProgram received signal SIGILL, Illegal instruction\..*in main.*"] {
+ return
+ }
+
+ # Skip the illegal instruction. The signal handler will be called after we continue.
+ gdb_test_no_output "set \$pc=\$pc+4"
+ # Continue to the signal handler.
+ if [gdb_continue_to_breakpoint $handler_breakpoint] {
+ return -1
+ }
+
+ # Modify TPIDR2 so it is different from its value past the signal
+ # frame.
+ gdb_test_no_output "set \$tpidr2 = 0x0"
+
+ # Select the frame that contains "main".
+ gdb_test "frame 2" "#2.* main \\\(.*\\\) at.*"
+
+ for {set row 0} {$row < 32} {incr row} {
+ set register_name "\$z${row}\.b\.u"
+ gdb_test "print sizeof $register_name" " = $sve_vl" "size of $register_name in the signal frame"
+ gdb_test "print $register_name" $sve_pattern "$register_name contents from signal frame"
+ }
+
+ # Check the size of ZA in the signal frame.
+ set expected_za_size [expr $svl * $svl]
+ gdb_test "print sizeof \$za" " = $expected_za_size" "size of za in signal frame"
+
+ # Check the value of SVCR in the signal frame.
+ gdb_test "print \$svcr" [get_svcr_value $state] "svcr from signal frame"
+
+ # Check the value of ZA in the signal frame.
+ gdb_test "print \$za" $za_pattern "za contents from signal frame"
+
+ # Check the value of TPIDR2 in the signal frame.
+ gdb_test "print/x \$tpidr2" " = 0x102030405060708" "tpidr2 contents from signal frame"
+ }
+ }
+}
+
+require is_aarch64_target
+require allow_aarch64_sve_tests
+require allow_aarch64_sme_tests
+
+test_sme_registers_sigframe $id_start $id_end
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-0.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-0.exp
new file mode 100644
index 00000000000..835f28950df
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-0.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 16
+# SVL: 16, 32, 64, 128
+# This set covers 4 (0 ~ 3) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 0
+set id_end 3
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-1.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-1.exp
new file mode 100644
index 00000000000..73ec3f67269
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-1.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 16
+# SVL: 256
+# This set covers 1 (4) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 4
+set id_end 4
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-2.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-2.exp
new file mode 100644
index 00000000000..4d223ef4070
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-2.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 32
+# SVL: 16, 32, 64, 128
+# This set covers 4 (5 ~ 8) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 5
+set id_end 8
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-3.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-3.exp
new file mode 100644
index 00000000000..3a26cd36975
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-3.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 32
+# SVL: 256
+# This set covers 1 (9) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 9
+set id_end 9
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-4.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-4.exp
new file mode 100644
index 00000000000..c8e73b7cf73
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-4.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 64
+# SVL: 16, 32, 64, 128
+# This set covers 4 (10 ~ 13) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 10
+set id_end 13
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-5.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-5.exp
new file mode 100644
index 00000000000..7b9f908b256
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-5.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 64
+# SVL: 256
+# This set covers 1 (14) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 14
+set id_end 14
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-6.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-6.exp
new file mode 100644
index 00000000000..7a3d52f4333
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-6.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 128
+# SVL: 16, 32, 64, 128
+# This set covers 4 (15 ~ 18) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 15
+set id_end 18
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-7.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-7.exp
new file mode 100644
index 00000000000..03cff0a0fe8
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-7.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 128
+# SVL: 256
+# This set covers 1 (19) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 19
+set id_end 19
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-8.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-8.exp
new file mode 100644
index 00000000000..2379f3e79b4
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-8.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 256
+# SVL: 16, 32, 64, 128
+# This set covers 4 (20 ~ 23) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 20
+set id_end 23
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-9.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-9.exp
new file mode 100644
index 00000000000..623e75b1f64
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-9.exp
@@ -0,0 +1,26 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Exercise tests with the following parameters:
+# VL: 256
+# SVL: 256
+# This set covers 1 (24) out of 25 tests.
+#
+# These tests are split this way for parallelization and for performance
+# reasons.
+#
+set id_start 24
+set id_end 24
+source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.c b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.c
new file mode 100644
index 00000000000..9c844c91c7c
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.c
@@ -0,0 +1,152 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* Exercise various cases of ZA contents not being available for AArch64's
+ Scalable Matrix Extension. */
+
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifndef HWCAP_SVE
+#define HWCAP_SVE (1 << 22)
+#endif
+
+#ifndef HWCAP2_SME
+#define HWCAP2_SME (1 << 23)
+#endif
+
+#ifndef PR_SVE_SET_VL
+#define PR_SVE_SET_VL 50
+#define PR_SVE_GET_VL 51
+#define PR_SVE_VL_LEN_MASK 0xffff
+#endif
+
+#ifndef PR_SME_SET_VL
+#define PR_SME_SET_VL 63
+#define PR_SME_GET_VL 64
+#define PR_SME_VL_LEN_MASK 0xffff
+#endif
+
+static int get_vl_size ()
+{
+ int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SVE_GET_VL (%d)\n", res);
+ return -1;
+ }
+ return (res & PR_SVE_VL_LEN_MASK);
+}
+
+static int get_svl_size ()
+{
+ int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SME_GET_VL (%d)\n", res);
+ return -1;
+ }
+ return (res & PR_SVE_VL_LEN_MASK);
+}
+
+static int set_vl_size (int new_vl)
+{
+ int res = prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SVE_SET_VL (%d)\n", res);
+ return -1;
+ }
+
+ res = get_vl_size ();
+ if (res != new_vl)
+ {
+ printf ("Unexpected VL value (%d)\n", res);
+ return -1;
+ }
+
+ return res;
+}
+
+static int set_svl_size (int new_svl)
+{
+ int res = prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0);
+ if (res < 0)
+ {
+ printf ("FAILED to PR_SME_SET_VL (%d)\n", res);
+ return -1;
+ }
+
+ res = get_svl_size ();
+ if (res != new_svl)
+ {
+ printf ("Unexpected SVL value (%d)\n", res);
+ return -1;
+ }
+
+ return res;
+}
+
+static int
+test_id_to_vl (int id)
+{
+ return 16 << ((id / 5) % 5);
+}
+
+static int
+test_id_to_svl (int id)
+{
+ return 16 << (id % 5);
+}
+
+static void
+dummy ()
+{
+}
+
+int
+main (int argc, char **argv)
+{
+ if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME)
+ {
+ int id_start = ID_START;
+ int id_end = ID_END;
+
+ for (int id = id_start; id <= id_end; id++)
+ {
+ int vl = test_id_to_vl (id);
+ int svl = test_id_to_svl (id);
+
+ if (set_vl_size (vl) == -1 || set_svl_size (svl) == -1)
+ continue;
+
+ dummy (); /* stop 1 */
+ }
+
+ dummy (); /* stop 2 */
+ }
+ else
+ {
+ printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl
new file mode 100644
index 00000000000..41d65c523f3
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl
@@ -0,0 +1,204 @@
+# Copyright (C) 2023 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Exercise the following:
+# - Printing ZA registers when there is no ZA state.
+# - Setting values of ZA registers when there is no ZA state.
+# - Validating ZA state is activated when we write to ZA registers.
+
+load_lib aarch64-scalable.exp
+
+#
+# Validate that the ZA registers have the expected state.
+#
+proc_with_prefix check_regs { vl svl } {
+ # Check VG to make sure it is correct
+ set expected_vg [expr $vl / 8]
+ gdb_test "print \$vg" "= ${expected_vg}"
+
+ # Check SVG to make sure it is correct
+ set expected_svg [expr $svl / 8]
+ gdb_test "print \$svg" "= ${expected_svg}"
+
+ # Make sure there is no SM or ZA state.
+ if [gdb_test "print \$svcr" "= \\\[ \\\]"] {
+ fail "incorrect ZA state"
+ return -1
+ }
+
+ # Check the size of ZA.
+ set expected_za_size [expr $svl * $svl]
+ gdb_test "print sizeof \$za" " = $expected_za_size"
+
+ # Check the size of Z0.
+ gdb_test "print sizeof \$z0" " = $vl"
+
+ # Set the expected ZA pattern.
+ set za_pattern [string_to_regexp [2d_array_value_pattern 0 $svl $svl]]
+
+ # Check ZA.
+ gdb_test "print \$za" $za_pattern
+
+ # Exercise reading/writing the tile slice pseudo-registers.
+ set last_tile 1
+ set last_slice $svl
+ set elements $svl
+ set expected_size $svl
+ foreach_with_prefix granularity {"b" "h" "s" "d" "q"} {
+ set pattern [string_to_regexp [1d_array_value_pattern 0 $elements]]
+ for {set tile 0} {$tile < $last_tile} {incr tile} {
+ for {set slice 0} {$slice < $last_slice} {incr slice} {
+ foreach_with_prefix direction {"h" "v"} {
+ set register_name "\$za${tile}${direction}${granularity}${slice}"
+ # Test the size.
+ gdb_test "print sizeof ${register_name}" " = ${expected_size}"
+ gdb_test "print ${register_name}" $pattern
+ }
+ }
+ }
+ set last_tile [expr $last_tile * 2]
+ set last_slice [expr ($last_slice / 2)]
+ set elements [expr ($elements / 2)]
+ }
+
+ # Exercise reading/writing the tile pseudo-registers.
+ set last_tile 1
+ set elements $svl
+ set expected_size [expr $svl * $svl]
+ foreach_with_prefix granularity {"b" "h" "s" "d" "q"} {
+ set pattern [string_to_regexp [2d_array_value_pattern 0 $elements $elements]]
+ for {set tile 0} {$tile < $last_tile} {incr tile} {
+ set register_name "\$za${tile}${granularity}"
+ # Test the size.
+ gdb_test "print sizeof ${register_name}" " = ${expected_size}"
+ gdb_test "print ${register_name}" $pattern
+ }
+ set last_tile [expr $last_tile * 2]
+ set expected_size [expr $expected_size / 2]
+ set elements [expr ($elements / 2)]
+ }
+}
+
+#
+# Cycle through all ZA registers and pseudo-registers and validate that their
+# contents are unavailable (zeroed out) for vector length SVL.
+#
+proc test_sme_registers_unavailable { id_start id_end } {
+
+ set compile_flags {"debug" "macros"}
+ lappend compile_flags "additional_flags=-DID_START=${id_start}"
+ lappend compile_flags "additional_flags=-DID_END=${id_end}"
+
+ standard_testfile ${::srcdir}/${::subdir}/aarch64-sme-regs-unavailable.c
+ set executable "${::testfile}-${id_start}-${id_end}"
+ if {[prepare_for_testing "failed to prepare" ${executable} ${::srcfile} ${compile_flags}]} {
+ return -1
+ }
+ set binfile [standard_output_file ${executable}]
+
+ if ![runto_main] {
+ untested "could not run to main"
+ return -1
+ }
+
+ gdb_test_no_output "set print repeats 1"
+
+ set prctl_breakpoint "stop 1"
+ gdb_breakpoint [gdb_get_line_number $prctl_breakpoint]
+
+ for {set id $id_start} {$id <= $id_end} {incr id} {
+ set vl [test_id_to_vl $id]
+ set svl [test_id_to_svl $id]
+
+ set skip_unsupported 0
+ if {![aarch64_supports_sve_vl $vl]
+ || ![aarch64_supports_sme_svl $svl]} {
+ # We have a vector length or streaming vector length that
+ # is not supported by this target. Skip to the next iteration
+ # since it is no use running tests for an unsupported vector
+ # length.
+ if {![aarch64_supports_sve_vl $vl]} {
+ verbose -log "SVE vector length $vl not supported."
+ } elseif {![aarch64_supports_sme_svl $svl]} {
+ verbose -log "SME streaming vector length $svl not supported."
+ }
+ verbose -log "Skipping test."
+ set skip_unsupported 1
+ }
+
+ with_test_prefix "prctl, vl=${vl} svl=${svl}" {
+ # If the SVE or SME vector length is not supported, just skip
+ # these next tests.
+ if {$skip_unsupported} {
+ untested "unsupported configuration on target"
+ continue
+ }
+
+ # Run the program until it has adjusted svl.
+ gdb_continue_to_breakpoint $prctl_breakpoint
+
+ check_regs $vl $svl
+ }
+ }
+
+ set non_prctl_breakpoint "stop 2"
+ gdb_breakpoint [gdb_get_line_number $non_prctl_breakpoint]
+ gdb_continue_to_breakpoint $non_prctl_breakpoint
+
+ for {set id $id_start} {$id <= $id_end} {incr id} {
+ set vl [test_id_to_vl $id]
+ set svl [test_id_to_svl $id]
+
+ set skip_unsupported 0
+ if {![aarch64_supports_sve_vl $vl]
+ || ![aarch64_supports_sme_svl $svl]} {
+ # We have a vector length or streaming vector length that
+ # is not supported by this target. Skip to the next iteration
+ # since it is no use running tests for an unsupported vector
+ # length.
+ if {![aarch64_supports_sve_vl $vl]} {
+ verbose -log "SVE vector length $vl not supported."
+ } elseif {![aarch64_supports_sme_svl $svl]} {
+ verbose -log "SME streaming vector length $svl not supported."
+ }
+ verbose -log "Skipping test."
+ set skip_unsupported 1
+ }
+
+ with_test_prefix "gdb, vl=${vl} svl=${svl}" {
+
+ # If the SVE or SME vector length is not supported, just skip
+ # these next tests.
+ if {$skip_unsupported} {
+ untested "unsupported configuration on target"
+ continue
+ }
+
+ # Adjust vg and svg.
+ set vg_value [expr $vl / 8]
+ set svg_value [expr $svl / 8]
+ gdb_test_no_output "set \$vg = ${vg_value}"
+ gdb_test_no_output "set \$svg = ${svg_value}"
+
+ check_regs $vl $svl
+ }
+ }
+}
+
+require is_aarch64_target
+require allow_aarch64_sve_tests
+require allow_aarch64_sme_tests
+
+test_sme_registers_unavailable $id_start $id_end
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c
new file mode 100644
index 00000000000..694de0626d2
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c
@@ -0,0 +1,249 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* Sanity test to exercise AArch64's Scalable Vector/Matrix Extension basic
+ functionality. It cycles through different combinations of state and
+ initializes different register sets. */
+
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HWCAP_SVE
+#define HWCAP_SVE (1 << 22)
+#endif
+
+#ifndef HWCAP2_SME
+#define HWCAP2_SME (1 << 23)
+#endif
+
+static void
+enable_za ()
+{
+ /* smstart za */
+ __asm __volatile (".word 0xD503457F");
+}
+
+static void
+disable_za ()
+{
+ /* smstop za */
+ __asm __volatile (".word 0xD503447F");
+}
+
+static void
+enable_sm ()
+{
+ /* smstart sm */
+ __asm __volatile (".word 0xD503437F");
+}
+
+static void
+disable_sm ()
+{
+ /* smstop sm */
+ __asm __volatile (".word 0xD503427F");
+}
+
+static void
+initialize_fpsimd_state ()
+{
+ char buffer[16];
+
+ for (int i = 0; i < 16; i++)
+ buffer[i] = 0x55;
+
+ __asm __volatile ("mov x0, %0\n\t" \
+ : : "r" (buffer));
+
+ __asm __volatile ("ldr q0, [x0]");
+ __asm __volatile ("ldr q1, [x0]");
+ __asm __volatile ("ldr q2, [x0]");
+ __asm __volatile ("ldr q3, [x0]");
+ __asm __volatile ("ldr q4, [x0]");
+ __asm __volatile ("ldr q5, [x0]");
+ __asm __volatile ("ldr q6, [x0]");
+ __asm __volatile ("ldr q7, [x0]");
+ __asm __volatile ("ldr q8, [x0]");
+ __asm __volatile ("ldr q9, [x0]");
+ __asm __volatile ("ldr q10, [x0]");
+ __asm __volatile ("ldr q11, [x0]");
+ __asm __volatile ("ldr q12, [x0]");
+ __asm __volatile ("ldr q13, [x0]");
+ __asm __volatile ("ldr q14, [x0]");
+ __asm __volatile ("ldr q15, [x0]");
+ __asm __volatile ("ldr q16, [x0]");
+ __asm __volatile ("ldr q17, [x0]");
+ __asm __volatile ("ldr q18, [x0]");
+ __asm __volatile ("ldr q19, [x0]");
+ __asm __volatile ("ldr q20, [x0]");
+ __asm __volatile ("ldr q21, [x0]");
+ __asm __volatile ("ldr q22, [x0]");
+ __asm __volatile ("ldr q23, [x0]");
+ __asm __volatile ("ldr q24, [x0]");
+ __asm __volatile ("ldr q25, [x0]");
+ __asm __volatile ("ldr q26, [x0]");
+ __asm __volatile ("ldr q27, [x0]");
+ __asm __volatile ("ldr q28, [x0]");
+ __asm __volatile ("ldr q29, [x0]");
+ __asm __volatile ("ldr q30, [x0]");
+ __asm __volatile ("ldr q31, [x0]");
+}
+
+static void
+initialize_za_state ()
+{
+ /* zero za */
+ __asm __volatile (".word 0xC00800FF");
+
+ char buffer[256];
+
+ for (int i = 0; i < 256; i++)
+ buffer[i] = 0xaa;
+
+ __asm __volatile ("mov x0, %0\n\t" \
+ : : "r" (buffer));
+
+ /* Initialize loop boundaries. */
+ __asm __volatile ("mov w12, 0");
+ __asm __volatile ("mov w17, 256");
+
+ /* loop: ldr za[w12, 0], [x0] */
+ __asm __volatile ("loop: .word 0xe1000000");
+ __asm __volatile ("add w12, w12, 1");
+ __asm __volatile ("cmp w12, w17");
+ __asm __volatile ("bne loop");
+}
+
+static void
+initialize_sve_state ()
+{
+ __asm __volatile ("dup z0.b, -1");
+ __asm __volatile ("dup z1.b, -1");
+ __asm __volatile ("dup z2.b, -1");
+ __asm __volatile ("dup z3.b, -1");
+ __asm __volatile ("dup z4.b, -1");
+ __asm __volatile ("dup z5.b, -1");
+ __asm __volatile ("dup z6.b, -1");
+ __asm __volatile ("dup z7.b, -1");
+ __asm __volatile ("dup z8.b, -1");
+ __asm __volatile ("dup z9.b, -1");
+ __asm __volatile ("dup z10.b, -1");
+ __asm __volatile ("dup z11.b, -1");
+ __asm __volatile ("dup z12.b, -1");
+ __asm __volatile ("dup z13.b, -1");
+ __asm __volatile ("dup z14.b, -1");
+ __asm __volatile ("dup z15.b, -1");
+ __asm __volatile ("dup z16.b, -1");
+ __asm __volatile ("dup z17.b, -1");
+ __asm __volatile ("dup z18.b, -1");
+ __asm __volatile ("dup z19.b, -1");
+ __asm __volatile ("dup z20.b, -1");
+ __asm __volatile ("dup z21.b, -1");
+ __asm __volatile ("dup z22.b, -1");
+ __asm __volatile ("dup z23.b, -1");
+ __asm __volatile ("dup z24.b, -1");
+ __asm __volatile ("dup z25.b, -1");
+ __asm __volatile ("dup z26.b, -1");
+ __asm __volatile ("dup z27.b, -1");
+ __asm __volatile ("dup z28.b, -1");
+ __asm __volatile ("dup z29.b, -1");
+ __asm __volatile ("dup z30.b, -1");
+ __asm __volatile ("dup z31.b, -1");
+ __asm __volatile ("ptrue p0.b");
+ __asm __volatile ("ptrue p1.b");
+ __asm __volatile ("ptrue p2.b");
+ __asm __volatile ("ptrue p3.b");
+ __asm __volatile ("ptrue p4.b");
+ __asm __volatile ("ptrue p5.b");
+ __asm __volatile ("ptrue p6.b");
+ __asm __volatile ("ptrue p7.b");
+ __asm __volatile ("ptrue p8.b");
+ __asm __volatile ("ptrue p9.b");
+ __asm __volatile ("ptrue p10.b");
+ __asm __volatile ("ptrue p11.b");
+ __asm __volatile ("ptrue p12.b");
+ __asm __volatile ("ptrue p13.b");
+ __asm __volatile ("ptrue p14.b");
+ __asm __volatile ("ptrue p15.b");
+ __asm __volatile ("setffr");
+}
+
+/* Enable register states based on STATE.
+
+ 0 - FPSIMD
+ 1 - SVE
+ 2 - SSVE
+ 3 - ZA
+ 4 - ZA and SSVE. */
+
+void enable_states (int state)
+{
+ disable_za ();
+ disable_sm ();
+ initialize_fpsimd_state ();
+
+ if (state == 1)
+ {
+ initialize_sve_state ();
+ }
+ else if (state == 2)
+ {
+ enable_sm ();
+ initialize_sve_state ();
+ }
+ else if (state == 3)
+ {
+ enable_za ();
+ initialize_za_state ();
+ }
+ else if (state == 4)
+ {
+ enable_za ();
+ enable_sm ();
+ initialize_sve_state ();
+ initialize_za_state ();
+ }
+
+ return;
+}
+
+void dummy ()
+{
+}
+
+int
+main (int argc, char **argv)
+{
+ if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME)
+ {
+ for (int state = 0; state < 5; state++)
+ {
+ enable_states (state);
+ dummy (); /* stop here */
+ }
+ }
+ else
+ {
+ printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp
new file mode 100644
index 00000000000..7f965432b16
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp
@@ -0,0 +1,64 @@
+# Copyright (C) 2023 Free Software Foundation, Inc.
+
+# 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/>.
+#
+# Sanity check for AArch64 Scalable Vector/Matrix Extensions functionality.
+
+load_lib aarch64-scalable.exp
+
+#
+# Run a series of basic checks for SVE/SME states.
+#
+proc sanity_check { vl svl } {
+ # Run the program until the point where we start initializing the different
+ # register states.
+ set state_breakpoint "stop here"
+ gdb_breakpoint [gdb_get_line_number $state_breakpoint]
+
+ for {set id 0} {$id < 5} {incr id} {
+ set state [state_id_to_state_string $id]
+
+ with_test_prefix "state=${state} vl=${vl} svl=${svl}" {
+ gdb_continue_to_breakpoint $state_breakpoint
+ check_state $state $vl $svl
+ }
+ }
+}
+
+require is_aarch64_target
+require allow_aarch64_sve_tests
+require allow_aarch64_sme_tests
+
+set compile_flags {"debug" "macros" "additional_flags=-march=armv8.5-a+sve"}
+standard_testfile
+if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} ${compile_flags}]} {
+ return -1
+}
+
+if {![runto_main]} {
+ return -1
+}
+
+# Adjust the repeat count for the test.
+gdb_test_no_output "set print repeats 1" "adjust repeat count"
+
+# Fetch both the vector length and the streaming vector length the target
+# system is using. We do not force any vector lengths and do not change
+# it mid-execution.
+set vl [expr [get_valueof "" "\$vg" "0" "fetch value of vl"] * 8]
+set svl [expr [get_valueof "" "\$svg" "0" "fetch value of svl"] * 8]
+
+# Now we are at the point where we can start checking state and moving the
+# testcase forward.
+sanity_check $vl $svl
diff --git a/gdb/testsuite/lib/aarch64-scalable.exp b/gdb/testsuite/lib/aarch64-scalable.exp
new file mode 100644
index 00000000000..5512fcb9d1c
--- /dev/null
+++ b/gdb/testsuite/lib/aarch64-scalable.exp
@@ -0,0 +1,239 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Support routines for aarch64 scalable extension tests
+
+# Load generic aarch64 test dependencies.
+load_lib aarch64.exp
+
+#
+# Return a regular expression that matches what gdb would print for a
+# SVE Z register of length VL in state STATE. The Z register should be filled
+# with BYTE_SVE and the FPSIMD registers should be filled with BYTE_FPSIMD.
+#
+# The pattern is of the form
+#
+# {BYTE_FPSIMD <repeats 16 times>}
+#
+# or
+#
+# {BYTE_FPSIMD <repeats 16 times>, 0 <repeats ... times>}
+#
+# or
+#
+# {BYTE_SVE <repeats VL times>}
+#
+proc sve_value_pattern { state vl byte_fpsimd byte_sve } {
+ set brace_open "{"
+ set brace_close "}"
+
+ append data $brace_open
+ if { $state == "fpsimd" || $state == "za" } {
+ if { $vl > 16 } {
+ set sve_repeat_count [expr $vl - 16]
+ append data "$byte_fpsimd <repeats 16 times>, 0 <repeats $sve_repeat_count times>"
+ } else {
+ append data "$byte_fpsimd <repeats 16 times>"
+ }
+ } else {
+ append data "$byte_sve <repeats $vl times>"
+ }
+ append data $brace_close
+
+ verbose -log "sve_value_pattern pattern string is..."
+ verbose -log $data
+ return $data
+}
+
+#
+# Return the SVCR value based on STATE.
+# SVCR is only available when SME is available.
+#
+proc get_svcr_value { state } {
+ if { $state == "ssve" } {
+ return "= \\\[ SM \\\]"
+ } elseif { $state == "za" } {
+ return "= \\\[ ZA \\\]"
+ } elseif { $state == "za_ssve" } {
+ return "= \\\[ SM ZA \\\]"
+ }
+
+ return "= \\\[ \\\]"
+}
+
+#
+# Return the state string based on STATE
+#
+proc state_id_to_state_string { state } {
+ if {$state == 0} {
+ return "fpsimd"
+ } elseif {$state == 1} {
+ return "sve"
+ } elseif {$state == 2} {
+ return "ssve"
+ } elseif {$state == 3} {
+ return "za"
+ } elseif {$state == 4} {
+ return "za_ssve"
+ }
+}
+
+#
+# Given a test ID, return the string representing the register state.
+# The state is one of fpsimd, sve, ssve, za and za_ssve.
+#
+proc test_id_to_state { id } {
+ set state [expr $id / 25]
+
+ return [state_id_to_state_string $state]
+}
+
+#
+# Given a test ID, return the associated vector length.
+#
+proc test_id_to_vl { id } {
+ return [expr 16 << (($id / 5) % 5)]
+}
+
+#
+# Given a test ID, return the associated streaming vector length.
+#
+proc test_id_to_svl { id } {
+ return [expr 16 << ($id % 5)]
+}
+
+#
+# Validate the values of the SVE registers.
+#
+proc check_sve_regs { byte state vl svl } {
+
+ # If streaming mode is enabled, the vector length is the streaming
+ # vector length.
+ set z_pattern ""
+ set z_size 0
+ if {$state == "ssve" || $state == "za_ssve"} {
+ set z_pattern [string_to_regexp [1d_array_value_pattern $byte $svl]]
+ set z_size $svl
+ } else {
+ set z_size $vl
+
+ if {$state == "fpsimd" || $state == "za"} {
+ # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers
+ # are zero.
+ if {$vl == 16} {
+ set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]]
+ } else {
+ set z_repeats [expr $vl - 16]
+ set z_pattern [string_to_regexp "{$byte <repeats 16 times>, 0 <repeats $z_repeats times>}"]
+ }
+ } else {
+ set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]]
+ }
+ }
+ set p_size [expr $z_size / 8]
+
+ # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers
+ # are zero.
+ set p_byte $byte
+ if {$state == "fpsimd" || $state == "za"} {
+ set p_byte 0
+ }
+ set p_pattern [string_to_regexp [1d_array_value_pattern $p_byte $p_size]]
+
+ for {set number 0} {$number < 32} {incr number} {
+ set register_name "\$z${number}\.b\.u"
+ gdb_test "print sizeof $register_name" " = $z_size"
+ gdb_test "print $register_name" $z_pattern
+ }
+
+ for {set number 0} {$number < 16} {incr number} {
+ set register_name "\$p${number}"
+ gdb_test "print sizeof $register_name" " = $p_size"
+ gdb_test "print $register_name" $p_pattern
+ }
+
+ gdb_test "print \$ffr" $p_pattern
+}
+
+#
+# Validate the values of the SME registers.
+#
+proc check_sme_regs { byte state svl } {
+ # ZA contents are only available when the ZA state is enabled. Otherwise
+ # the ZA contents are unavailable (zeroed out).
+ set za_pattern ""
+ set expected_za_size [expr $svl * $svl]
+
+ if {$state != "za" && $state != "za_ssve"} {
+ set byte 0
+ }
+
+ set za_pattern [string_to_regexp [2d_array_value_pattern $byte $svl $svl]]
+
+ gdb_test "print sizeof \$za" " = $expected_za_size"
+ gdb_test "print \$za" $za_pattern
+}
+
+#
+# With register STATE, vector length VL and streaming vector length SVL,
+# run some register state checks to make sure the values are the expected
+# ones
+#
+proc check_state { state vl svl } {
+ # The FPSIMD registers are initialized with a value of 0x55 (85)
+ # for each byte.
+ #
+ # The SVE registers are initialized with a value of 0xff (255) for each
+ # byte, including the predicate registers and FFR.
+ #
+ # The SME (ZA) register is initialized with a value of 0xaa (170) for
+ # each byte.
+
+ # Check VG to make sure it is correct
+ set expected_vg [expr $vl / 8]
+ # If streaming mode is enabled, then vg is actually svg.
+ if {$state == "ssve" || $state == "za_ssve"} {
+ set expected_vg [expr $svl / 8]
+ }
+ gdb_test "print \$vg" " = ${expected_vg}"
+
+ # Check SVG to make sure it is correct
+ set expected_svg [expr $svl / 8]
+ gdb_test "print \$svg" " = ${expected_svg}"
+
+ # Check the value of SVCR.
+ gdb_test "print \$svcr" [get_svcr_value $state]
+
+ # When we have any SVE or SSVE state, the FPSIMD registers will have
+ # the same values as the SVE/SSVE Z registers.
+ set fpsimd_byte 85
+ if {$state == "sve" || $state == "ssve" || $state == "za_ssve"} {
+ set fpsimd_byte 255
+ }
+
+ set sve_byte 255
+ if {$state == "fpsimd" || $state == "za"} {
+ set sve_byte 85
+ }
+
+ # Check FPSIMD registers
+ check_fpsimd_regs $fpsimd_byte $state $vl $svl
+ # Check SVE registers
+ check_sve_regs $sve_byte $state $vl $svl
+ # Check SME registers
+ check_sme_regs 170 $state $svl
+}
+
+
diff --git a/gdb/testsuite/lib/aarch64-test-sme.c b/gdb/testsuite/lib/aarch64-test-sme.c
new file mode 100644
index 00000000000..c123f37e0df
--- /dev/null
+++ b/gdb/testsuite/lib/aarch64-test-sme.c
@@ -0,0 +1,90 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* AArch64 SME feature check. This test serves as a way for the GDB testsuite
+ to verify that a target supports SVE at runtime, and also reports data
+ about the various supported SME streaming vector lengths. */
+
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HWCAP2_SME
+#define HWCAP2_SME (1 << 23)
+#endif
+
+#ifndef PR_SME_SET_VL
+#define PR_SME_SET_VL 63
+#define PR_SME_GET_VL 64
+#define PR_SME_VL_LEN_MASK 0xffff
+#endif
+
+static int get_svl_size ()
+{
+ int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0);
+
+ if (res < 0)
+ return -1;
+
+ return (res & PR_SME_VL_LEN_MASK);
+}
+
+static int set_svl_size (int new_svl)
+{
+ if (prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0) < 0)
+ return -1;
+
+ if (get_svl_size () != new_svl)
+ return -1;
+
+ return 0;
+}
+
+static void
+dummy ()
+{
+}
+
+#define SVL_MIN 16
+#define SVL_MAX 256
+#define SVL_INCREMENT_POWER 1
+
+int
+main (int argc, char **argv)
+{
+ /* Number of supported SME streaming vector lengths. */
+ size_t supported_svl_count = 0;
+ /* Vector containing the various supported SME streaming vector lengths. */
+ size_t supported_svl[5];
+
+ if (getauxval (AT_HWCAP) & HWCAP2_SME)
+ {
+ for (int svl = SVL_MIN; svl <= SVL_MAX; svl <<= SVL_INCREMENT_POWER)
+ {
+ if (set_svl_size (svl) == 0)
+ {
+ supported_svl[supported_svl_count] = svl;
+ supported_svl_count++;
+ }
+ }
+ }
+
+ return 0; /* stop here */
+}
diff --git a/gdb/testsuite/lib/aarch64-test-sve.c b/gdb/testsuite/lib/aarch64-test-sve.c
new file mode 100644
index 00000000000..4673581b467
--- /dev/null
+++ b/gdb/testsuite/lib/aarch64-test-sve.c
@@ -0,0 +1,90 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2023 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* AArch64 SVE feature check. This test serves as a way for the GDB testsuite
+ to verify that a target supports SVE at runtime, and also reports data
+ about the various supported SVE vector lengths. */
+
+#include <stdio.h>
+#include <sys/auxv.h>
+#include <sys/prctl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef HWCAP_SVE
+#define HWCAP_SVE (1 << 22)
+#endif
+
+#ifndef PR_SVE_SET_VL
+#define PR_SVE_SET_VL 50
+#define PR_SVE_GET_VL 51
+#define PR_SVE_VL_LEN_MASK 0xffff
+#endif
+
+static int get_vl_size ()
+{
+ int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0);
+
+ if (res < 0)
+ return -1;
+
+ return (res & PR_SVE_VL_LEN_MASK);
+}
+
+static int set_vl_size (int new_vl)
+{
+ if (prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0) < 0)
+ return -1;
+
+ if (get_vl_size () != new_vl)
+ return -1;
+
+ return 0;
+}
+
+static void
+dummy ()
+{
+}
+
+#define VL_MIN 16
+#define VL_MAX 256
+#define VL_INCREMENT 16
+
+int
+main (int argc, char **argv)
+{
+ /* Number of supported SVE vector lengths. */
+ size_t supported_vl_count = 0;
+ /* Vector containing the various supported SVE vector lengths. */
+ size_t supported_vl[16];
+
+ if (getauxval (AT_HWCAP) & HWCAP_SVE)
+ {
+ for (int vl = VL_MIN; vl <= VL_MAX; vl += VL_INCREMENT)
+ {
+ if (set_vl_size (vl) == 0)
+ {
+ supported_vl[supported_vl_count] = vl;
+ supported_vl_count++;
+ }
+ }
+ }
+
+ return 0; /* stop here */
+}
diff --git a/gdb/testsuite/lib/aarch64.exp b/gdb/testsuite/lib/aarch64.exp
new file mode 100644
index 00000000000..cd43a4c4f77
--- /dev/null
+++ b/gdb/testsuite/lib/aarch64.exp
@@ -0,0 +1,153 @@
+# Copyright 2023 Free Software Foundation, Inc.
+
+# 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/>. */
+
+# Support routines for aarch64-specific tests
+
+#
+# Return a regular expression that matches what gdb would print for a
+# 1-dimension vector containing ELEMENTS elements of value BYTE.
+#
+# The pattern is of the form "{BYTE <repeats ELEMENTS times>".
+#
+proc 1d_array_value_pattern { byte elements } {
+ set brace_open "{"
+ set brace_close "}"
+
+ append data $brace_open $byte
+ if {$elements > 1} {
+ append data " <repeats $elements times>"
+ }
+ append data $brace_close
+
+ verbose -log "1d_array_value_pattern Pattern string is..."
+ verbose -log $data
+ return $data
+}
+
+#
+# Return a regular expression that matches what gdb would print for a
+# 2-dimension vector containing ROWS rows and COLUMNS columns of elements
+# of value BYTE.
+#
+# The pattern is of the form
+# "{{BYTE <repeats COLUMNS times>} <repeats ROWS times>}".
+#
+proc 2d_array_value_pattern { byte rows columns } {
+ set brace_open "{"
+ set brace_close "}"
+
+ append data $brace_open [1d_array_value_pattern $byte $columns]
+ if {$rows > 1} {
+ append data " <repeats $rows times>"
+ }
+ append data $brace_close
+
+ verbose -log "2d_array_value_pattern Pattern string is..."
+ verbose -log $data
+ return $data
+}
+
+#
+# Initialize register NAME, a 1-dimension vector, with ELEMENTS elements
+# by setting all elements to BYTE. ELEMENTS is limited at 256 for memory
+# usage purposes.
+#
+# The initialization is of the form "{BYTE, BYTE, BYTE ...}".
+#
+proc initialize_1d_array { name byte elements } {
+ set brace_open "{"
+ set brace_close "}"
+
+ append data $brace_open
+
+ # Build the assignment in a single shot.
+ for {set element 0} {$element < $elements} {incr element} {
+ # Construct the initializer by appending elements to it.
+ append data $byte
+
+ # If this isn't the last element, add a comma.
+ if {[expr $element + 1] < $elements} {
+ append data ", "
+ }
+ }
+ append data $brace_close
+
+ verbose -log "initialization string is..."
+ verbose -log $data
+ gdb_test_no_output "set $name = $data" "write to $name"
+}
+
+#
+# Return an initializer string for a 2-dimension vector with ROWS rows and
+# COLUMNS columns, initializing all elements to BYTE for register NAME.
+#
+# COLUMNS is limited to 256 elements for memory usage purposes.
+#
+# The initialization is of the form "{{BYTE, BYTE}, ..., {BYTE, BYTE}}}".
+#
+proc initialize_2d_array { name byte rows columns } {
+ set brace_open "{"
+ set brace_close "}"
+
+ if {[expr $rows * $columns] <= 256} {
+ # Build the assignment in a single shot, as we have a maximum of 256
+ # elements.
+ for {set row 0} {$row < $rows} {incr row} {
+ append data $brace_open
+ for {set column 0} {$column < $columns} {incr column} {
+ # Construct the initializer by appending elements to it.
+ append data $byte
+
+ # If this isn't the last column, add a comma.
+ if {[expr $column + 1] < $columns} {
+ append data ", "
+ }
+ }
+
+ append data $brace_close
+
+ # If this isn't the last row, add a comma.
+ if {[expr $row + 1] < $rows} {
+ append data ","
+ }
+ }
+
+ set data $brace_open$data
+ set data $data$brace_close
+
+ verbose -log "initialization string is..."
+ verbose -log $data
+ gdb_test_no_output "set $name = $data" "write to $name"
+ } else {
+ # There are too many elements to initialize (more than 256), so we
+ # will do the initialization row by row.
+ for {set row 0} {$row < $rows} {incr row} {
+ initialize_1d_array "$name\[$row\]" $byte $columns
+ }
+ }
+}
+
+#
+# Validate the values of the FPSIMD registers.
+#
+proc check_fpsimd_regs { byte state vl svl} {
+ set fpsimd_pattern [string_to_regexp [1d_array_value_pattern $byte 16]]
+
+ for {set number 0} {$number < 32} {incr number} {
+ set register_name "\$v${number}\.b\.u"
+ gdb_test "print sizeof $register_name" " = 16"
+ gdb_test "print $register_name" $fpsimd_pattern
+ }
+}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 1b9179401c4..cf1d4a90e55 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -4152,10 +4152,259 @@ gdb_caching_proc allow_aarch64_sve_tests {} {
gdb_exit
remote_file build delete $obj

+ # While testing for SVE support, also discover all the supported vector
+ # length values.
+ aarch64_initialize_sve_information
+
verbose "$me: returning $allow_sve_tests" 2
return $allow_sve_tests
}

+# Assuming SVE is supported by the target, run some checks to determine all
+# the supported vector length values and return an array containing all of those
+# values. Since this is a gdb_caching_proc, this proc will only be executed
+# once.
+#
+# To check if a particular SVE vector length is supported, the following code
+# can be used. For instance, for vl == 16:
+#
+# if {[aarch64_supports_sve_vl 16]} {
+# verbose -log "SVE vector length 16 is supported."
+# }
+#
+# This procedure should NEVER be called by hand, as it reinitializes the GDB
+# session and will derail a test. This should be called automatically as part
+# of the SVE support test routine allow_aarch64_sve_tests. Users should
+# restrict themselves to calling the helper proc aarch64_supports_sve_vl.
+
+gdb_caching_proc aarch64_initialize_sve_information { } {
+ global srcdir
+
+ set src "${srcdir}/lib/aarch64-test-sve.c"
+ set test_exec [standard_temp_file "aarch64-test-sve.x"]
+ set compile_flags "{additional_flags=-march=armv8-a+sve}"
+ array set supported_vl {}
+
+ # Compile the SVE vector length test.
+ set result [gdb_compile $src $test_exec executable [list debug ${compile_flags} nowarnings]]
+
+ if {$result != ""} {
+ verbose -log "Failed to compile SVE information gathering test."
+ return [array get supported_vl]
+ }
+
+ clean_restart $test_exec
+
+ if {![runto_main]} {
+ return [array get supported_vl]
+ }
+
+ set stop_breakpoint "stop here"
+ gdb_breakpoint [gdb_get_line_number $stop_breakpoint $src]
+ gdb_continue_to_breakpoint $stop_breakpoint
+
+ # Go through the data and extract the supported SVE vector lengths.
+ set vl_count [get_valueof "" "supported_vl_count" "0" \
+ "fetch value of supported_vl_count"]
+ verbose -log "Found $vl_count supported SVE vector length values"
+
+ for {set vl_index 0} {$vl_index < $vl_count} {incr vl_index} {
+ set test_vl [get_valueof "" "supported_vl\[$vl_index\]" "0" \
+ "fetch value of supported_vl\[$vl_index\]"]
+
+ # Mark this vector length as supported.
+ if {$test_vl != 0} {
+ verbose -log "Found supported SVE vector length $test_vl"
+ set supported_vl($test_vl) 1
+ }
+ }
+
+ gdb_exit
+ verbose -log "Cleaning up"
+ remote_file build delete $test_exec
+
+ verbose -log "Done gathering information about AArch64 SVE vector lengths."
+
+ # Return the array containing all of the supported SVE vl values.
+ return [array get supported_vl]
+}
+
+#
+# Return 1 if the target supports SVE vl LENGTH
+# Return 0 otherwise.
+#
+
+proc aarch64_supports_sve_vl { length } {
+
+ # Fetch the cached array of supported SVE vl values.
+ array set supported_vl [aarch64_initialize_sve_information]
+
+ # Do we have the global values cached?
+ if {![info exists supported_vl($length)]} {
+ verbose -log "Target does not support SVE vl $length"
+ return 0
+ }
+
+ # The target supports SVE vl LENGTH.
+ return 1
+}
+
+# Run a test on the target to see if it supports Aarch64 SME extensions.
+# Return 0 if so, 1 if it does not. Note this causes a restart of GDB.
+
+gdb_caching_proc allow_aarch64_sme_tests {} {
+ global srcdir subdir gdb_prompt inferior_exited_re
+
+ set me "allow_aarch64_sme_tests"
+
+ if { ![is_aarch64_target]} {
+ return 0
+ }
+
+ set compile_flags "{additional_flags=-march=armv8-a+sme}"
+
+ # Compile a test program containing SME instructions.
+ set src {
+ int main() {
+ asm volatile ("smstart za");
+ return 0;
+ }
+ }
+ if {![gdb_simple_compile $me $src executable $compile_flags]} {
+ # Try again, but with a raw hex instruction so we don't rely on
+ # assembler support for SME.
+
+ set compile_flags "{additional_flags=-march=armv8-a}"
+
+ # Compile a test program containing SME instructions.
+ set src {
+ int main() {
+ asm volatile (".word 0xD503457F");
+ return 0;
+ }
+ }
+
+ if {![gdb_simple_compile $me $src executable $compile_flags]} {
+ return 0
+ }
+ }
+
+ # Compilation succeeded so now run it via gdb.
+ clean_restart $obj
+ gdb_run_cmd
+ gdb_expect {
+ -re ".*Illegal instruction.*${gdb_prompt} $" {
+ verbose -log "\n$me sme support not detected"
+ set allow_sme_tests 0
+ }
+ -re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
+ verbose -log "\n$me: sme support detected"
+ set allow_sme_tests 1
+ }
+ default {
+ warning "\n$me: default case taken"
+ set allow_sme_tests 0
+ }
+ }
+ gdb_exit
+ remote_file build delete $obj
+
+ # While testing for SME support, also discover all the supported vector
+ # length values.
+ aarch64_initialize_sme_information
+
+ verbose "$me: returning $allow_sme_tests" 2
+ return $allow_sme_tests
+}
+
+# Assuming SME is supported by the target, run some checks to determine all
+# the supported streaming vector length values and return an array containing
+# all of those values. Since this is a gdb_caching_proc, this proc will only
+# be executed once.
+#
+# To check if a particular SME streaming vector length is supported, the
+# following code can be used. For instance, for svl == 32:
+#
+# if {[aarch64_supports_sme_svl 32]} {
+# verbose -log "SME streaming vector length 32 is supported."
+# }
+#
+# This procedure should NEVER be called by hand, as it reinitializes the GDB
+# session and will derail a test. This should be called automatically as part
+# of the SME support test routine allow_aarch64_sme_tests. Users should
+# restrict themselves to calling the helper proc aarch64_supports_sme_svl.
+
+gdb_caching_proc aarch64_initialize_sme_information { } {
+ global srcdir
+
+ set src "${srcdir}/lib/aarch64-test-sme.c"
+ set test_exec [standard_temp_file "aarch64-test-sme.x"]
+ set compile_flags "{additional_flags=-march=armv8-a+sme}"
+ array set supported_svl {}
+
+ # Compile the SME vector length test.
+ set result [gdb_compile $src $test_exec executable [list debug ${compile_flags} nowarnings]]
+
+ if {$result != ""} {
+ verbose -log "Failed to compile SME information gathering test."
+ return [array get supported_svl]
+ }
+
+ clean_restart $test_exec
+
+ if {![runto_main]} {
+ return [array get supported_svl]
+ }
+
+ set stop_breakpoint "stop here"
+ gdb_breakpoint [gdb_get_line_number $stop_breakpoint $src]
+ gdb_continue_to_breakpoint $stop_breakpoint
+
+ # Go through the data and extract the supported SME vector lengths.
+ set svl_count [get_valueof "" "supported_svl_count" "0" \
+ "fetch value of supported_svl_count"]
+ verbose -log "Found $svl_count supported SME vector length values"
+
+ for {set svl_index 0} {$svl_index < $svl_count} {incr svl_index} {
+ set test_svl [get_valueof "" "supported_svl\[$svl_index\]" "0" \
+ "fetch value of supported_svl\[$svl_index\]"]
+
+ # Mark this streaming vector length as supported.
+ if {$test_svl != 0} {
+ verbose -log "Found supported SME vector length $test_svl"
+ set supported_svl($test_svl) 1
+ }
+ }
+
+ gdb_exit
+ verbose -log "Cleaning up"
+ remote_file build delete $test_exec
+
+ verbose -log "Done gathering information about AArch64 SME vector lengths."
+
+ # Return the array containing all of the supported SME svl values.
+ return [array get supported_svl]
+}
+
+#
+# Return 1 if the target supports SME svl LENGTH
+# Return 0 otherwise.
+#
+
+proc aarch64_supports_sme_svl { length } {
+
+ # Fetch the cached array of supported SME svl values.
+ array set supported_svl [aarch64_initialize_sme_information]
+
+ # Do we have the global values cached?
+ if {![info exists supported_svl($length)]} {
+ verbose -log "Target does not support SME svl $length"
+ return 0
+ }
+
+ # The target supports SME svl LENGTH.
+ return 1
+}

# A helper that compiles a test case to see if __int128 is supported.
proc gdb_int128_helper {lang} {
--
2.25.1