aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
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