aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorsaurabh.jha@arm.com <saurabh.jha@arm.com>2024-06-21 16:30:59 +0100
committerRichard Earnshaw <rearnsha@arm.com>2024-06-24 15:00:40 +0100
commitadea87e275802fb7afe7acefae1477f692c48969 (patch)
tree8b7ef7d13df4366cfb917425a09bb3e95cd14ce9 /gas
parentc702f1ad8a6a51b9c74445c77e1f6e822ba9293b (diff)
downloadgdb-adea87e275802fb7afe7acefae1477f692c48969.zip
gdb-adea87e275802fb7afe7acefae1477f692c48969.tar.gz
gdb-adea87e275802fb7afe7acefae1477f692c48969.tar.bz2
gas, aarch64: Add SME2 lutv2 extension
Introduces instructions for the SME2 lutv2 extension for AArch64. They are documented in the following document: * ARM DDI0602 For both luti4 instructions, we introduced an operand called SME_Znx2_BIT_INDEX. We use the existing function parse_vector_reg_list for parsing but modified that function so that it can accept operands without qualifiers and rejects instructions that have operands with qualifiers but are not supposed to have operands with qualifiers. For disassembly, we modified print_register_list so that it could accept register lists without qualifiers. For one luti4 instruction, we introduced a SME_Zdnx4_STRIDED. It is similar to SME_Ztx4_STRIDED and we could use existing code for parsing, encoding, and disassembly. For movt instruction, we introduced an operand called SME_ZT0_INDEX2_12. This is a ZT0 register with a bit index encoded in [13:12]. It is similar to SME_ZT0_INDEX. We also introduced an iclass named sme_size_12_b so that we can encode size bits [13:12] correctly when only 'b' is allowed as qualifier.
Diffstat (limited to 'gas')
-rw-r--r--gas/NEWS2
-rw-r--r--gas/config/tc-aarch64.c92
-rw-r--r--gas/doc/c-aarch64.texi2
-rw-r--r--gas/testsuite/gas/aarch64/sme2-8-invalid.l14
-rw-r--r--gas/testsuite/gas/aarch64/sme2-lutv2-bad.d3
-rw-r--r--gas/testsuite/gas/aarch64/sme2-lutv2-bad.l15
-rw-r--r--gas/testsuite/gas/aarch64/sme2-lutv2-illegal.d3
-rw-r--r--gas/testsuite/gas/aarch64/sme2-lutv2-illegal.l70
-rw-r--r--gas/testsuite/gas/aarch64/sme2-lutv2-illegal.s95
-rw-r--r--gas/testsuite/gas/aarch64/sme2-lutv2.d24
-rw-r--r--gas/testsuite/gas/aarch64/sme2-lutv2.s22
11 files changed, 331 insertions, 11 deletions
diff --git a/gas/NEWS b/gas/NEWS
index 096400d..332ad1e 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -50,6 +50,8 @@
* Add support for the AArch64 Lookup Table Extension (LUT).
+* Add support for the AArch64 Lookup Table Extension v2 (LUTv2).
+
Changes in 2.42:
* Add support for AMD znver5 processor.
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 885ea65..dad8f86 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -1365,6 +1365,11 @@ reg_type_mask (aarch64_reg_type reg_type)
It returns PARSE_FAIL if the register list is invalid.
+ If HAS_QUALIFIER is true, the registers in the list must have qualifiers
+ or the list is invalid.
+ If HAS_QUALIFIER is false, the registers in the list must not have
+ qualifiers or the list is invalid.
+
The list contains one to four registers.
Each register can be one of:
<Vt>.<T>[<index>]
@@ -1376,7 +1381,8 @@ reg_type_mask (aarch64_reg_type reg_type)
static int
parse_vector_reg_list (char **ccp, aarch64_reg_type type,
- struct vector_type_el *vectype)
+ struct vector_type_el *vectype,
+ bool has_qualifier)
{
char *str = *ccp;
int nb_regs;
@@ -1413,8 +1419,15 @@ parse_vector_reg_list (char **ccp, aarch64_reg_type type,
str++; /* skip over '-' */
val_range = val;
}
- const reg_entry *reg = parse_typed_reg (&str, type, &typeinfo,
- ptr_flags);
+
+ const reg_entry *reg;
+ if (has_qualifier)
+ reg = parse_typed_reg (&str, type, &typeinfo, ptr_flags);
+ else
+ {
+ reg = parse_reg (&str);
+ typeinfo.defined = 0;
+ }
if (!reg)
{
set_first_syntax_error (_("invalid vector register in list"));
@@ -3893,6 +3906,55 @@ parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
return parse_shifter_operand (str, operand, mode);
}
+/* Parse a ZT0 vector with an optional bit index and a shifter operand.
+ zt0
+ zt0[0, mul vl]
+ zt0[2, mul vl]
+
+ We only support 'mul vl' as shifter operand and it is handled by
+ parse_shift.
+
+ Return TRUE on success; otherwise return FALSE. */
+
+static bool
+parse_shifter_zt0_with_bit_index (char **str,
+ aarch64_opnd_info *operand,
+ enum parse_shift_mode mode)
+{
+ const reg_entry *reg = parse_reg (str);
+ if (reg == NULL)
+ return false;
+
+ if (reg->type != REG_TYPE_ZT0)
+ return false;
+
+ operand->reglane.regno = reg->number;
+
+ if (!skip_past_char (str, '['))
+ {
+ // It is not an error if the index is not present.
+ // Default to 0.
+ operand->imm.value = 0;
+ return true;
+ }
+
+ int64_t index;
+ if (!parse_index_expression (str, &index))
+ return false;
+ operand->imm.value = index;
+
+ if (!skip_past_comma (str))
+ return true;
+
+ if (!parse_shift (str, operand, mode))
+ return false;
+
+ if (!skip_past_char (str, ']'))
+ return false;
+
+ return true;
+}
+
/* Parse all forms of an address expression. Information is written
to *OPERAND and/or inst.reloc.
@@ -6860,10 +6922,26 @@ parse_operands (char *str, const aarch64_opcode *opcode)
info->reglane.index = vectype.index;
break;
+ case AARCH64_OPND_SME_Znx2_BIT_INDEX:
+ // A vector register list encoding a bit index.
+ reg_type = REG_TYPE_Z;
+ val = parse_vector_reg_list (&str, reg_type, &vectype, false);
+ if (val == PARSE_FAIL)
+ goto failure;
+
+ if (! reg_list_valid_p (val, &info->reglist, reg_type))
+ {
+ set_fatal_syntax_error (_("invalid register list"));
+ goto failure;
+ }
+
+ break;
+
case AARCH64_OPND_SVE_ZnxN:
case AARCH64_OPND_SVE_ZtxN:
case AARCH64_OPND_SME_Zdnx2:
case AARCH64_OPND_SME_Zdnx4:
+ case AARCH64_OPND_SME_Zdnx4_STRIDED:
case AARCH64_OPND_SME_Zt2:
case AARCH64_OPND_SME_Zt3:
case AARCH64_OPND_SME_Zt4:
@@ -6901,7 +6979,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
}
else
{
- val = parse_vector_reg_list (&str, reg_type, &vectype);
+ val = parse_vector_reg_list (&str, reg_type, &vectype, true);
if (val == PARSE_FAIL)
goto failure;
@@ -7968,6 +8046,11 @@ parse_operands (char *str, const aarch64_opcode *opcode)
info->imm.value = vectype.index;
break;
+ case AARCH64_OPND_SME_ZT0_INDEX2_12:
+ po_misc_or_fail (parse_shifter_zt0_with_bit_index
+ (&str, info, SHIFTED_MUL_VL));
+ break;
+
case AARCH64_OPND_SME_ZT0_LIST:
if (*str != '{')
{
@@ -10597,6 +10680,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"fp8", AARCH64_FEATURE (FP8), AARCH64_FEATURE (SIMD)},
{"lut", AARCH64_FEATURE (LUT), AARCH64_FEATURE (SIMD)},
{"brbe", AARCH64_FEATURE (BRBE), AARCH64_NO_FEATURES},
+ {"sme-lutv2", AARCH64_FEATURE (SME_LUTv2), AARCH64_FEATURE (SME2)},
{NULL, AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
};
diff --git a/gas/doc/c-aarch64.texi b/gas/doc/c-aarch64.texi
index b29da1f..41a8d7e 100644
--- a/gas/doc/c-aarch64.texi
+++ b/gas/doc/c-aarch64.texi
@@ -269,6 +269,8 @@ automatically cause those extensions to be disabled.
@tab Enable SME F64F64 Extension.
@item @code{sme-i16i64} @tab @code{sme}
@tab Enable SME I16I64 Extension.
+@item @code{sme-lutv2} @tab
+ @tab Enable SME Lookup Table v2 (LUTv2) extension.
@item @code{sme2} @tab @code{sme}
@tab Enable SME2.
@item @code{sme2p1} @tab @code{sme2}
diff --git a/gas/testsuite/gas/aarch64/sme2-8-invalid.l b/gas/testsuite/gas/aarch64/sme2-8-invalid.l
index aa39365..aef9b1a 100644
--- a/gas/testsuite/gas/aarch64/sme2-8-invalid.l
+++ b/gas/testsuite/gas/aarch64/sme2-8-invalid.l
@@ -9,9 +9,9 @@
[^ :]+:[0-9]+: Error: expected '}' after ZT0 at operand 1 -- `zero {zt0'
[^ :]+:[0-9]+: Error: expected '}' after ZT0 at operand 1 -- `zero {zt0\.b}'
[^ :]+:[0-9]+: Error: expected '}' after ZT0 at operand 1 -- `zero {zt0,zt0}'
-[^ :]+:[0-9]+: Error: expected a register at operand 1 -- `movt 0,zt0\[0\]'
+[^ :]+:[0-9]+: Error: operand 1 must be an integer register -- `movt 0,zt0\[0\]'
[^ :]+:[0-9]+: Error: expected a register at operand 2 -- `movt x0,0'
-[^ :]+:[0-9]+: Error: missing register index at operand 1 -- `movt zt0,x0'
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `movt zt0,x0'
[^ :]+:[0-9]+: Error: unexpected register type at operand 1 -- `movt za\[0\],x0'
[^ :]+:[0-9]+: Error: unexpected register type at operand 1 -- `movt za0\[0\],x0'
[^ :]+:[0-9]+: Error: bad expression at operand 1 -- `movt zt0\[#0\],x0'
@@ -26,17 +26,17 @@
[^ :]+:[0-9]+: Error: register element index out of range 0 to 56 at operand 1 -- `movt zt0\[57\],x0'
[^ :]+:[0-9]+: Error: register element index out of range 0 to 56 at operand 1 -- `movt zt0\[64\],x0'
[^ :]+:[0-9]+: Error: register element index out of range 0 to 56 at operand 1 -- `movt zt0\[1<<32\],x0'
-[^ :]+:[0-9]+: Error: missing register index at operand 1 -- `movt zt0\.b\[0\],x0'
-[^ :]+:[0-9]+: Error: missing register index at operand 1 -- `movt zt0/z\[0\],x0'
-[^ :]+:[0-9]+: Error: expected an integer or zero register at operand 2 -- `movt zt0\[0\],sp'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `movt zt0\.b\[0\],x0'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `movt zt0/z\[0\],x0'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `movt zt0\[0\],sp'
[^ :]+:[0-9]+: Error: operand mismatch -- `movt zt0\[0\],w0'
[^ :]+:[0-9]+: Info: did you mean this\?
[^ :]+:[0-9]+: Info: movt zt0\[0\], x0
-[^ :]+:[0-9]+: Error: expected an integer or zero register at operand 2 -- `movt zt0\[0\],wsp'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `movt zt0\[0\],wsp'
[^ :]+:[0-9]+: Error: operand mismatch -- `movt zt0\[0\],wzr'
[^ :]+:[0-9]+: Info: did you mean this\?
[^ :]+:[0-9]+: Info: movt zt0\[0\], xzr
-[^ :]+:[0-9]+: Error: expected an integer or zero register at operand 2 -- `movt zt0\[0\],0'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `movt zt0\[0\],0'
[^ :]+:[0-9]+: Error: expected a register at operand 1 -- `ldr 0,\[x0\]'
[^ :]+:[0-9]+: Error: invalid addressing mode at operand 2 -- `ldr zt0,0'
[^ :]+:[0-9]+: Error: operand 2 must be an address with base register \(no offset\) -- `ldr zt0,\[x0,#0\]'
diff --git a/gas/testsuite/gas/aarch64/sme2-lutv2-bad.d b/gas/testsuite/gas/aarch64/sme2-lutv2-bad.d
new file mode 100644
index 0000000..0e6e2b7
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sme2-lutv2-bad.d
@@ -0,0 +1,3 @@
+#as: -march=armv8-a+sme2
+#source: sme2-lutv2.s
+#error_output: sme2-lutv2-bad.l \ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/sme2-lutv2-bad.l b/gas/testsuite/gas/aarch64/sme2-lutv2-bad.l
new file mode 100644
index 0000000..7883722
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sme2-lutv2-bad.l
@@ -0,0 +1,15 @@
+[^ :]+: Assembler messages:
+.*: Error: selected processor does not support `movt zt0,z0'
+.*: Error: selected processor does not support `movt zt0\[0,mul vl\],z31'
+.*: Error: selected processor does not support `movt zt0\[3,mul vl\],z0'
+.*: Error: selected processor does not support `movt zt0\[3,mul vl\],z31'
+.*: Error: selected processor does not support `movt zt0\[2,mul vl\],z25'
+.*: Error: selected processor does not support `luti4 {z0.b-z3.b},zt0,{z0-z1}'
+.*: Error: selected processor does not support `luti4 {z28.b-z31.b},zt0,{z0-z1}'
+.*: Error: selected processor does not support `luti4 {z0.b-z3.b},zt0,{z30-z31}'
+.*: Error: selected processor does not support `luti4 {z20.b-z23.b},zt0,{z12-z13}'
+.*: Error: selected processor does not support `luti4 {z0.b,z4.b,z8.b,z12.b},zt0,{z0-z1}'
+.*: Error: selected processor does not support `luti4 {z19.b,z23.b,z27.b,z31.b},zt0,{z0-z1}'
+.*: Error: selected processor does not support `luti4 {z0.b,z4.b,z8.b,z12.b},zt0,{z30-z31}'
+.*: Error: selected processor does not support `luti4 {z17.b,z21.b,z25.b,z29.b},zt0,{z12-z13}'
+.*: Error: selected processor does not support `luti4 {z20.b,z21.b,z22.b,z23.b},zt0,{z12-z13}'
diff --git a/gas/testsuite/gas/aarch64/sme2-lutv2-illegal.d b/gas/testsuite/gas/aarch64/sme2-lutv2-illegal.d
new file mode 100644
index 0000000..401bbb7
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sme2-lutv2-illegal.d
@@ -0,0 +1,3 @@
+#as: -march=armv8-a+sme2+sme2p1+sme-lutv2
+#source: sme2-lutv2-illegal.s
+#error_output: sme2-lutv2-illegal.l \ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/sme2-lutv2-illegal.l b/gas/testsuite/gas/aarch64/sme2-lutv2-illegal.l
new file mode 100644
index 0000000..4495a9a
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sme2-lutv2-illegal.l
@@ -0,0 +1,70 @@
+[^ :]+: Assembler messages:
+[^ :]+:[0-9]+: Error: start register out of range at operand 3 -- `luti4 {z20.b-z23.h},zt0,{z13-z14}'
+[^ :]+:[0-9]+: Error: type mismatch in vector register list at operand 1 -- `luti4 {z19.b,z23.b,z27.b,z31.h},zt0,{z13-z14}'
+[^ :]+:[0-9]+: Error: unexpected register type at operand 1 -- `movt z3,zt0'
+[^ :]+:[0-9]+: Error: unexpected register type at operand 1 -- `movt z3\[0\],zt0'
+[^ :]+:[0-9]+: Error: operand 1 must be an integer register -- `movt zt1,z25'
+[^ :]+:[0-9]+: Error: expected a vector register at operand 1 -- `luti4 zt0,\{z0.b-z3.b\},\{z0-z1\}'
+[^ :]+:[0-9]+: Error: expected a register at operand 2 -- `luti4 \{z0.b-z3.b\},\{z0.b-z1.b\}\{z0-z1\}'
+[^ :]+:[0-9]+: Error: syntax error in register list at operand 1 -- `luti4 \{\},zt0,\{z12-z13\}'
+[^ :]+:[0-9]+: Error: invalid vector register in list at operand 3 -- `luti4 \{z20.b-z23.b\},zt0,\{\}'
+[^ :]+:[0-9]+: Error: unexpected register type at operand 2 -- `luti4 \{z20.b-z23.b\},z3,\{z12-z13\}'
+[^ :]+:[0-9]+: Error: start register out of range at operand 1 -- `luti4 \{z19.b-z22.b\},zt0,\{z12-z13\}'
+[^ :]+:[0-9]+: Error: start register out of range at operand 3 -- `luti4 \{z20.b-z23.b\},zt0,\{z13-z14\}'
+[^ :]+:[0-9]+: Error: expected a vector register at operand 1 -- `luti4 zt0,{z0.b,z4.b,z8.b,z12.b},{z0-z1}'
+[^ :]+:[0-9]+: Error: expected a register at operand 2 -- `luti4 {z0.b,z4.b,z8.b,z12.b},{z0.b-z1.b}{z0-z1}'
+[^ :]+:[0-9]+: Error: invalid vector register in list at operand 3 -- `luti4 {z19.b,z23.b,z27.b,z31.b},zt0,{}'
+[^ :]+:[0-9]+: Error: unexpected register type at operand 2 -- `luti4 {z19.b,z23.b,z27.b,z31.b},z3,{z12-z13}'
+[^ :]+:[0-9]+: Error: start register out of range at operand 3 -- `luti4 {z19.b,z23.b,z27.b,z31.b},zt0,{z13-z14}'
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 \{z20.s-z23.s\},zt0,\{z20-z21\}'
+[^ :]+:[0-9]+: Info: did you mean this\?
+[^ :]+:[0-9]+: Info: luti4 {z20.b-z23.b}, zt0, {z20-z21}
+[^ :]+:[0-9]+: Error: operand mismatch -- `luti4 {z19.s,z23.s,z27.s,z31.s},zt0,{z20-z21}'
+[^ :]+:[0-9]+: Info: did you mean this\?
+[^ :]+:[0-9]+: Info: luti4 {z19.b, z23.b, z27.b, z31.b}, zt0, {z20-z21}
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `movt zt0.b,z31'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `movt zt0.b\[0,mul vl\],z31'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `movt zt0'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `movt zt0\[1,mul vl\]'
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 2 -- `movt zt0,z23,z31'
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 2 -- `movt zt0\[1,mul vl\],z23,z31'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti4 \{z20.b-z23.b\}'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 3 -- `luti4 \{z20.b-z23.b\},zt0'
+[^ :]+:[0-9]+: Error: unexpected characters following instruction at operand 3 -- `luti4 \{z20.b-z23.b\},zt0,\{z12-z13\},\{z20-z21\}'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 2 -- `luti4 {z19.b,z23.b,z27.b,z31.b}'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 3 -- `luti4 {z19.b,z23.b,z27.b,z31.b},zt0'
+[^ :]+:[0-9]+: Error: comma expected between operands at operand 3 -- `luti4 {z19.b,z23.b,z27.b,z31.b},zt0{z12-z13},{z20-z21}'
+[^ :]+:[0-9]+: Error: operand 1 must be an integer register -- `movt zy0,z16'
+[^ :]+:[0-9]+: Error: operand 1 must be an integer register -- `movt zt1,z16'
+[^ :]+:[0-9]+: Error: operand 1 must be an integer register -- `movt zy0\[1,mul vl\],z16'
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `movt zt0,y16'
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `movt zt0\[1,mul vl\],y16'
+[^ :]+:[0-9]+: Error: operand 1 must be a list of SVE vector registers -- `luti4 \{z20.b-y23.b\},zt0,\{z12-z13\}'
+[^ :]+:[0-9]+: Error: unexpected character `x' in element size at operand 1 -- `luti4 \{z20.x-z23.b\},zt0,\{z12-z13\}'
+[^ :]+:[0-9]+: Error: expected a register at operand 2 -- `luti4 \{z20.b-z23.b\},zy0,\{z12-z13\}'
+[^ :]+:[0-9]+: Error: operand 1 must be a list of SVE vector registers -- `luti4 \{z20.b-y23.b\},zt0,\{y12-z13\}'
+[^ :]+:[0-9]+: Error: operand 1 must be a list of SVE vector registers -- `luti4 {z19.b,z23.b,z27.b,y31.b},zt0,{z12-z13}'
+[^ :]+:[0-9]+: Error: unexpected character `x' in element size at operand 1 -- `luti4 {z19.x,z23.b,z27.b,z31.b},zt0,{z12-z13}'
+[^ :]+:[0-9]+: Error: expected a register at operand 2 -- `luti4 {z19.b,z23.b,z27.b,z31.b},zy0,{z12-z13}'
+[^ :]+:[0-9]+: Error: invalid vector register in list at operand 3 -- `luti4 {z19.b,z23.b,z27.b,z31.b},zt0,{y12-z13}'
+[^ :]+:[0-9]+: Error: missing type suffix at operand 1 -- `luti4 \{z20-z23.b\},zt0,\{z12-z13\}'
+[^ :]+:[0-9]+: Error: type mismatch in vector register list at operand 1 -- `luti4 {z19.b,z23,z27.b,z31.b},zt0,{z12-z13}'
+[^ :]+:[0-9]+: Error: operand 1 must be an integer register -- `movt zt,z25.b'
+[^ :]+:[0-9]+: Error: end of vector register list not found at operand 3 -- `luti4 {z20.b-z23.b},zt0,{z12.b-z13.b}'
+[^ :]+:[0-9]+: Error: end of vector register list not found at operand 3 -- `luti4 {z19.b,z23.b,z27.b,z31.b},zt0,{z12.b-z13.b}'
+[^ :]+:[0-9]+: Error: operand 2 must be an SVE vector register -- `movt zt0,z25\[1\]'
+[^ :]+:[0-9]+: Error: operand 2 must be an SVE vector register -- `movt zt0,z25\[1,mul vl\]'
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `movt zt0\[2,mul vl\],z32'
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 1 -- `movt zt0\[4,mul vl\],z25'
+[^ :]+:[0-9]+: Error: register element index out of range 0 to 3 at operand 1 -- `movt zt0\[-1,mul vl\],z25'
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 1 -- `luti4 {z32.b-z36.b},zt0,{z12-z13}'
+[^ :]+:[0-9]+: Error: invalid vector register in list at operand 3 -- `luti4 {z20.b-z23.b},zt0,{z32-z33}'
+[^ :]+:[0-9]+: Error: expected an SVE vector register at operand 1 -- `luti4 {z32.b,z36.b,z40.b,z44.b},zt0,{z12-z13}'
+[^ :]+:[0-9]+: Error: invalid vector register in list at operand 3 -- `luti4 {z19.b,z23.b,z27.b,z31.b},zt0,{z32-z33}'
+[^ :]+:[0-9]+: Error: too many registers in vector register list at operand 1 -- `luti4 {z20.b-z24.b},zt0,{z12-z13}'
+[^ :]+:[0-9]+: Error: expected a list of 4 registers at operand 1 -- `luti4 {z20.b-z22.b},zt0,{z12-z13}'
+[^ :]+:[0-9]+: Error: invalid register stride at operand 1 -- `luti4 {z20.b-z23.b},zt0,{z12-z14}'
+[^ :]+:[0-9]+: Error: invalid range in vector register list at operand 3 -- `luti4 {z20.b-z23.b},zt0,{z12-z12}'
+[^ :]+:[0-9]+: Error: invalid register list at operand 1 -- `luti4 {z19.b,z24.b,z27.b,z31.b},zt0,{z12-z13}'
+[^ :]+:[0-9]+: Error: invalid register list at operand 1 -- `luti4 {z19.b,z22.b,z27.b,z31.b},zt0,{z12-z13}'
+[^ :]+:[0-9]+: Error: the register list must have a stride of 1 at operand 1 -- `luti4 {z19.b,z23.b,z27.b,z31.b},zt0,{z12-z14}'
diff --git a/gas/testsuite/gas/aarch64/sme2-lutv2-illegal.s b/gas/testsuite/gas/aarch64/sme2-lutv2-illegal.s
new file mode 100644
index 0000000..4e36ef6
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sme2-lutv2-illegal.s
@@ -0,0 +1,95 @@
+ // Operand mismatch
+ luti4 { z20.b - z23.h }, zt0, { z13 - z14 }
+ luti4 { z19.b, z23.b, z27.b, z31.h }, zt0, { z13 - z14 }
+
+ // Incorrect operands
+ movt z3, zt0
+ movt z3[0], zt0
+ movt zt1, z25
+
+ luti4 zt0, { z0.b - z3.b }, { z0 - z1 }
+ luti4 { z0.b - z3.b }, { z0.b - z1.b } { z0 - z1 }
+ luti4 { }, zt0, { z12 - z13 }
+ luti4 { z20.b - z23.b }, zt0, { }
+ luti4 { z20.b - z23.b }, z3, { z12 - z13 }
+ luti4 { z19.b - z22.b }, zt0, { z12 - z13 }
+ luti4 { z20.b - z23.b }, zt0, { z13 - z14 }
+
+ luti4 zt0, { z0.b, z4.b, z8.b, z12.b }, { z0 - z1 }
+ luti4 { z0.b, z4.b, z8.b, z12.b }, { z0.b - z1.b } { z0 - z1 }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zt0, { }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, z3, { z12 - z13 }
+ luti4 { z18.b, z22.b, z26.b, z30.b }, zt0, { z12 - z13 }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zt0, { z13 - z14 }
+
+ // Disallowed types
+ luti4 { z20.s - z23.s }, zt0, { z20 - z21 }
+ luti4 { z19.s, z23.s, z27.s, z31.s }, zt0, { z20 - z21 }
+
+ // Index with qualifiers
+ movt zt0.b, z31
+ movt zt0.b[0, mul vl], z31
+
+ // Incorrect number of operands
+ movt zt0
+ movt zt0[1, mul vl]
+ movt zt0, z23, z31
+ movt zt0[1, mul vl], z23, z31
+
+ luti4 { z20.b - z23.b }
+ luti4 { z20.b - z23.b }, zt0
+ luti4 { z20.b - z23.b }, zt0, { z12 - z13 }, { z20 - z21 }
+
+ luti4 { z19.b, z23.b, z27.b, z31.b }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zt0
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zt0 { z12 - z13 }, { z20 - z21 }
+
+ // Spelling mistakes
+ movt zy0, z16
+ movt zt1, z16
+ movt zy0[1, mul vl], z16
+ movt zt0, y16
+ movt zt0[1, mul vl], y16
+
+ luti4 { z20.b - y23.b }, zt0, { z12 - z13 }
+ luti4 { z20.x - z23.b }, zt0, { z12 - z13 }
+ luti4 { z20.b - z23.b }, zy0, { z12 - z13 }
+ luti4 { z20.b - y23.b }, zt0, { y12 - z13 }
+
+ luti4 { z19.b, z23.b, z27.b, y31.b }, zt0, { z12 - z13 }
+ luti4 { z19.x, z23.b, z27.b, z31.b }, zt0, { z12 - z13 }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zy0, { z12 - z13 }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zt0, { y12 - z13 }
+
+ // Missing qualifiers
+ luti4 { z20 - z23.b }, zt0, { z12 - z13 }
+ luti4 { z19.b, z23, z27.b, z31.b }, zt0, { z12 - z13 }
+
+ // Qualifier on the wrong operand
+ movt zt, z25.b
+ luti4 { z20.b - z23.b }, zt0, { z12.b - z13.b }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zt0, { z12.b - z13.b }
+
+ // Index on the wrong operand
+ movt zt0, z25[1]
+ movt zt0, z25[1, mul vl]
+
+ // Out of range numbers
+ movt zt0[2, mul vl], z32
+ movt zt0[4, mul vl], z25
+ movt zt0[-1, mul vl], z25
+
+ luti4 { z32.b - z36.b }, zt0, { z12 - z13 }
+ luti4 { z20.b - z23.b }, zt0, { z32 - z33 }
+
+ luti4 { z32.b, z36.b, z40.b, z44.b }, zt0, { z12 - z13 }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zt0, { z32 - z33 }
+
+ // Incorrect stride
+ luti4 { z20.b - z24.b }, zt0, { z12 - z13 }
+ luti4 { z20.b - z22.b }, zt0, { z12 - z13 }
+ luti4 { z20.b - z23.b }, zt0, { z12 - z14 }
+ luti4 { z20.b - z23.b }, zt0, { z12 - z12 }
+ luti4 { z19.b, z24.b, z27.b, z31.b }, zt0, { z12 - z13 }
+ luti4 { z19.b, z22.b, z27.b, z31.b }, zt0, { z12 - z13 }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zt0, { z12 - z14 }
diff --git a/gas/testsuite/gas/aarch64/sme2-lutv2.d b/gas/testsuite/gas/aarch64/sme2-lutv2.d
new file mode 100644
index 0000000..f671982
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sme2-lutv2.d
@@ -0,0 +1,24 @@
+#objdump: -dr
+#as: -march=armv8-a+sme2+sme2p1+sme-lutv2
+
+.*: file format .*
+
+Disassembly of section \.text:
+
+0+ <.*>:
+[^:]+: c04f03e0 movt zt0\[0, mul vl\], z0
+[^:]+: c04f03ff movt zt0\[0, mul vl\], z31
+[^:]+: c04f33e0 movt zt0\[3, mul vl\], z0
+[^:]+: c04f33ff movt zt0\[3, mul vl\], z31
+[^:]+: c04f23f9 movt zt0\[2, mul vl\], z25
+[^:]+: c08b0000 luti4 {z0.b-z3.b}, zt0, {z0-z1}
+[^:]+: c08b001c luti4 {z28.b-z31.b}, zt0, {z0-z1}
+[^:]+: c08b03c0 luti4 {z0.b-z3.b}, zt0, {z30-z31}
+[^:]+: c08b0194 luti4 {z20.b-z23.b}, zt0, {z12-z13}
+[^:]+: c09b0000 luti4 {z0.b, z4.b, z8.b, z12.b}, zt0, {z0-z1}
+[^:]+: c09b0013 luti4 {z19.b, z23.b, z27.b, z31.b}, zt0, {z0-z1}
+[^:]+: c09b03c0 luti4 {z0.b, z4.b, z8.b, z12.b}, zt0, {z30-z31}
+[^:]+: c09b0191 luti4 {z17.b, z21.b, z25.b, z29.b}, zt0, {z12-z13}
+[^:]+: c08b0194 luti4 {z20.b-z23.b}, zt0, {z12-z13}
+[^:]+: c08b2194 .inst 0xc08b2194 ; undefined
+[^:]+: c09b2191 .inst 0xc09b2191 ; undefined
diff --git a/gas/testsuite/gas/aarch64/sme2-lutv2.s b/gas/testsuite/gas/aarch64/sme2-lutv2.s
new file mode 100644
index 0000000..cba9ad9
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/sme2-lutv2.s
@@ -0,0 +1,22 @@
+ movt zt0, z0
+ movt zt0[0, mul vl], z31
+ movt zt0[3, mul vl], z0
+ movt zt0[3, mul vl], z31
+ movt zt0[2, mul vl], z25
+
+ luti4 { z0.b - z3.b }, zt0, { z0 - z1 }
+ luti4 { z28.b - z31.b }, zt0, { z0 - z1 }
+ luti4 { z0.b - z3.b }, zt0, { z30 - z31 }
+ luti4 { z20.b - z23.b }, zt0, { z12 - z13 }
+
+ luti4 { z0.b, z4.b, z8.b, z12.b }, zt0, { z0 - z1 }
+ luti4 { z19.b, z23.b, z27.b, z31.b }, zt0, { z0 - z1 }
+ luti4 { z0.b, z4.b, z8.b, z12.b }, zt0, { z30 - z31 }
+ luti4 { z17.b, z21.b, z25.b, z29.b }, zt0, { z12 - z13 }
+
+ // Explicitly listing registers in stride 1 variant
+ luti4 { z20.b, z21.b, z22.b, z23.b }, zt0, { z12 - z13 }
+
+ // Invalid instructions because sz != 00
+ .inst 0xc08b2194
+ .inst 0xc09b2191