@@ -41,6 +41,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.
@@ -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,12 @@ 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);
if (!reg)
{
set_first_syntax_error (_("invalid vector register in list"));
@@ -3893,6 +3903,54 @@ 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 index 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.
@@ -6858,10 +6916,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:
@@ -6899,7 +6973,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;
@@ -7966,6 +8040,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 != '{')
{
@@ -10551,6 +10630,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"faminmax", AARCH64_FEATURE (FAMINMAX), AARCH64_FEATURE (SIMD)},
{"fp8", AARCH64_FEATURE (FP8), AARCH64_FEATURE (SIMD)},
{"lut", AARCH64_FEATURE (LUT), AARCH64_FEATURE (SIMD)},
+ {"sme-lutv2", AARCH64_FEATURE (SME_LUTv2), AARCH64_FEATURE (SME2)},
{NULL, AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
};
@@ -267,6 +267,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}
@@ -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\]'
new file mode 100644
@@ -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
new file mode 100644
@@ -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}'
new file mode 100644
@@ -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
new file mode 100644
@@ -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}'
new file mode 100644
@@ -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 }
new file mode 100644
@@ -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
new file mode 100644
@@ -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
@@ -238,6 +238,8 @@ enum aarch64_feature_bit {
AARCH64_FEATURE_FP8,
/* LUT instructions. */
AARCH64_FEATURE_LUT,
+ /* SME LUTv2 instructions. */
+ AARCH64_FEATURE_SME_LUTv2,
AARCH64_NUM_FEATURES
};
@@ -755,10 +757,12 @@ enum aarch64_opnd
AARCH64_OPND_SVE_ZtxN, /* SVE vector register list in Zt. */
AARCH64_OPND_SME_Zdnx2, /* SVE vector register list from [4:1]*2. */
AARCH64_OPND_SME_Zdnx4, /* SVE vector register list from [4:2]*4. */
+ AARCH64_OPND_SME_Zdnx4_STRIDED, /* SVE vector register list from [4:2]*4. */
AARCH64_OPND_SME_Zm, /* SVE vector register list in 4-bit Zm. */
AARCH64_OPND_SME_Zmx2, /* SVE vector register list from [20:17]*2. */
AARCH64_OPND_SME_Zmx4, /* SVE vector register list from [20:18]*4. */
AARCH64_OPND_SME_Znx2, /* SVE vector register list from [9:6]*2. */
+ AARCH64_OPND_SME_Znx2_BIT_INDEX, /* SVE vector register list encoding a bit index from [9:6]*2. */
AARCH64_OPND_SME_Znx4, /* SVE vector register list from [9:7]*4. */
AARCH64_OPND_SME_Ztx2_STRIDED, /* SVE vector register list in [4:0]&23. */
AARCH64_OPND_SME_Ztx4_STRIDED, /* SVE vector register list in [4:0]&19. */
@@ -807,6 +811,7 @@ enum aarch64_opnd
AARCH64_OPND_SME_VLxN_13, /* VLx2 or VLx4, in bit 13. */
AARCH64_OPND_SME_ZT0, /* The fixed token zt0/ZT0 (not encoded). */
AARCH64_OPND_SME_ZT0_INDEX, /* ZT0[<imm>], bits [14:12]. */
+ AARCH64_OPND_SME_ZT0_INDEX2_12, /* ZT0[<imm>], bits [13:12]. */
AARCH64_OPND_SME_ZT0_LIST, /* { zt0/ZT0 } (not encoded). */
AARCH64_OPND_TME_UIMM16, /* TME unsigned 16-bit immediate. */
AARCH64_OPND_SM3_IMM2, /* SM3 encodes lane in bits [13, 14]. */
@@ -998,6 +1003,7 @@ enum aarch64_insn_class
sme_shift,
sme_size_12_bhs,
sme_size_12_hs,
+ sme_size_12_b,
sme_size_22,
sme_size_22_hsd,
sme_sz_23,
@@ -2145,6 +2145,7 @@ aarch64_encode_variant_using_iclass (struct aarch64_inst *inst)
break;
case sme_size_12_bhs:
+ case sme_size_12_b:
insert_field (FLD_SME_size_12, &inst->value,
aarch64_get_variant (inst), 0);
break;
@@ -3415,6 +3415,12 @@ aarch64_decode_variant_using_iclass (aarch64_inst *inst)
variant -= 1;
break;
+ case sme_size_12_b:
+ variant = extract_field (FLD_SME_size_12, inst->value, 0);
+ if (variant != 0)
+ return false;
+ break;
+
case sme_size_22:
variant = extract_field (FLD_SME_size_22, inst->value, 0);
break;
@@ -252,7 +252,9 @@ const aarch64_field fields[] =
{ 13, 1 }, /* SME_VL_13: VLx2 or VLx4, bit [13]. */
{ 0, 2 }, /* SME_ZAda_2b: tile ZA0-ZA3. */
{ 0, 3 }, /* SME_ZAda_3b: tile ZA0-ZA7. */
+ { 4, 1 }, /* SME_ZdnT: upper bit of Zt, bit [4]. */
{ 1, 4 }, /* SME_Zdn2: Z0-Z31, multiple of 2, bits [4:1]. */
+ { 0, 2 }, /* SME_Zdn2_0: lower 2 bits of Zt, bits [1:0]. */
{ 2, 3 }, /* SME_Zdn4: Z0-Z31, multiple of 4, bits [4:2]. */
{ 16, 4 }, /* SME_Zm: Z0-Z15, bits [19:16]. */
{ 17, 4 }, /* SME_Zm2: Z0-Z31, multiple of 2, bits [20:17]. */
@@ -1912,6 +1914,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
case AARCH64_OPND_SME_Zmx2:
case AARCH64_OPND_SME_Zmx4:
case AARCH64_OPND_SME_Znx2:
+ case AARCH64_OPND_SME_Znx2_BIT_INDEX:
case AARCH64_OPND_SME_Znx4:
case AARCH64_OPND_SME_Zt2:
case AARCH64_OPND_SME_Zt3:
@@ -1927,6 +1930,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
}
break;
+ case AARCH64_OPND_SME_Zdnx4_STRIDED:
case AARCH64_OPND_SME_Ztx2_STRIDED:
case AARCH64_OPND_SME_Ztx4_STRIDED:
/* 2-register lists have a stride of 8 and 4-register lists
@@ -3146,6 +3150,14 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
}
break;
+ case AARCH64_OPND_SME_ZT0_INDEX2_12:
+ if (!value_in_range_p (opnd->imm.value, 0, 3))
+ {
+ set_elem_idx_out_of_range_error (mismatch_detail, idx, 0, 3);
+ return 0;
+ }
+ break;
+
default:
break;
}
@@ -3738,9 +3750,14 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
&& ((opnd->type != AARCH64_OPND_SME_Zt2)
&& (opnd->type != AARCH64_OPND_SME_Zt3)
&& (opnd->type != AARCH64_OPND_SME_Zt4)))
- snprintf (buf, size, "{%s-%s}%s",
- style_reg (styler, "%s%d.%s", prefix, first_reg, qlf_name),
- style_reg (styler, "%s%d.%s", prefix, last_reg, qlf_name), tb);
+ if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
+ snprintf (buf, size, "{%s-%s}%s",
+ style_reg (styler, "%s%d", prefix, first_reg),
+ style_reg (styler, "%s%d", prefix, last_reg), tb);
+ else
+ snprintf (buf, size, "{%s-%s}%s",
+ style_reg (styler, "%s%d.%s", prefix, first_reg, qlf_name),
+ style_reg (styler, "%s%d.%s", prefix, last_reg, qlf_name), tb);
else
{
const int reg0 = first_reg;
@@ -4199,9 +4216,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
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_Zmx2:
case AARCH64_OPND_SME_Zmx4:
case AARCH64_OPND_SME_Znx2:
+ case AARCH64_OPND_SME_Znx2_BIT_INDEX:
case AARCH64_OPND_SME_Znx4:
case AARCH64_OPND_SME_Ztx2_STRIDED:
case AARCH64_OPND_SME_Ztx4_STRIDED:
@@ -4882,6 +4901,11 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
snprintf (buf, size, "%s[%s]", style_reg (styler, "zt0"),
style_imm (styler, "%d", (int) opnd->imm.value));
break;
+ case AARCH64_OPND_SME_ZT0_INDEX2_12:
+ snprintf (buf, size, "%s[%s, %s]", style_reg (styler, "zt0"),
+ style_imm (styler, "%d", (int) opnd->imm.value),
+ style_sub_mnem (styler, "mul vl"));
+ break;
case AARCH64_OPND_SME_ZT0_LIST:
snprintf (buf, size, "{%s}", style_reg (styler, "zt0"));
@@ -62,7 +62,9 @@ enum aarch64_field_kind
FLD_SME_VL_13,
FLD_SME_ZAda_2b,
FLD_SME_ZAda_3b,
+ FLD_SME_ZdnT,
FLD_SME_Zdn2,
+ FLD_SME_Zdn2_0,
FLD_SME_Zdn4,
FLD_SME_Zm,
FLD_SME_Zm2,
@@ -1809,6 +1809,13 @@
{ \
QLF2(S_S,NIL), \
}
+/* e.g. movt ZT0{[<offs>, MUL VL]}, <Zt> */
+/* The second operand doesn't have a qualifier and
+ is checked separetely during encoding. */
+#define OP_SVE_SU_Q \
+{ \
+ QLF2(S_Q,NIL), \
+}
#define OP_SVE_SUS \
{ \
QLF3(S_S,NIL,S_S), \
@@ -2045,6 +2052,13 @@
QLF3(S_S,NIL,W), \
QLF3(S_D,NIL,X), \
}
+/* e.g. luti4 { <Zd1>.B-<Zd4>.B }, ZT0, { <Zn1>-<Zn2> } */
+/* The second and third operands don't have qualifiers and
+ are checked separetely during encoding. */
+#define OP_SVE_VUU_B \
+{ \
+ QLF3(S_B,NIL,NIL), \
+}
#define OP_SVE_VUU_BHS \
{ \
QLF3(S_B,NIL,NIL), \
@@ -2745,6 +2759,8 @@ static const aarch64_feature_set aarch64_feature_lut =
AARCH64_FEATURE (LUT);
static const aarch64_feature_set aarch64_feature_lut_sve2 =
AARCH64_FEATURES (2, LUT, SVE2);
+static const aarch64_feature_set aarch64_feature_sme_lutv2 =
+ AARCH64_FEATURES (3, SME_LUTv2, SME2, SME2p1);
#define CORE &aarch64_feature_v8
#define FP &aarch64_feature_fp
@@ -2821,6 +2837,7 @@ static const aarch64_feature_set aarch64_feature_lut_sve2 =
#define FP8_SME2 &aarch64_feature_fp8_sme2
#define LUT &aarch64_feature_lut
#define LUT_SVE2 &aarch64_feature_lut_sve2
+#define LUTv2_SME2 &aarch64_feature_sme_lutv2
#define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
{ NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
@@ -3019,6 +3036,9 @@ static const aarch64_feature_set aarch64_feature_lut_sve2 =
#define LUT_SVE2_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS,CONSTRAINTS) \
{ NAME, OPCODE, MASK, lut, 0, LUT_SVE2, OPS, QUALS, \
FLAGS, CONSTRAINTS, 0, NULL }
+#define LUTv2_SME2_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
+ { NAME, OPCODE, MASK, CLASS, 0, LUTv2_SME2, OPS, QUALS, \
+ FLAGS, 0, 0, NULL }
#define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \
MOPS_INSN (NAME, OPCODE, MASK, 0, \
@@ -6604,6 +6624,11 @@ const struct aarch64_opcode aarch64_opcode_table[] =
LUT_SVE2_INSN ("luti4", 0x4520b400, 0xff20fc00, OP3 (SVE_Zd, SVE_ZnxN, SVE_Zm2_22_INDEX), OP_SVE_HHU, F_OD(2), 0),
LUT_SVE2_INSN ("luti4", 0x4520bc00, 0xff20fc00, OP3 (SVE_Zd, SVE_ZnxN, SVE_Zm2_22_INDEX), OP_SVE_HHU, F_OD(1), 0),
+ /* SME2 lutv2. */
+ LUTv2_SME2_INSN ("luti4", 0xc08b0000, 0xffffcc23, sme_size_12_b, OP3 (SME_Zdnx4, SME_ZT0, SME_Znx2_BIT_INDEX), OP_SVE_VUU_B, F_STRICT | 0),
+ LUTv2_SME2_INSN ("luti4", 0xc09b0000, 0xffffcc2c, sme_size_12_b, OP3 (SME_Zdnx4_STRIDED, SME_ZT0, SME_Znx2_BIT_INDEX), OP_SVE_VUU_B, F_STRICT | 0),
+ LUTv2_SME2_INSN ("movt", 0xc04f03e0, 0xffffcfe0, sme_misc, OP2 (SME_ZT0_INDEX2_12, SVE_Zt), {}, 0),
+
{0, 0, 0, 0, 0, 0, {}, {}, 0, 0, 0, NULL},
};
@@ -7124,6 +7149,9 @@ const struct aarch64_opcode aarch64_opcode_table[] =
F(FLD_SME_Zdn2), "a list of SVE vector registers") \
Y(SVE_REGLIST, sve_aligned_reglist, "SME_Zdnx4", 4 << OPD_F_OD_LSB, \
F(FLD_SME_Zdn4), "a list of SVE vector registers") \
+ Y(SVE_REGLIST, sve_strided_reglist, "SME_Zdnx4_STRIDED", \
+ 4 << OPD_F_OD_LSB, F(FLD_SME_ZdnT, FLD_SME_Zdn2_0), \
+ "a list of SVE vector registers") \
Y(SVE_REG, regno, "SME_Zm", 0, F(FLD_SME_Zm), \
"an SVE vector register") \
Y(SVE_REGLIST, sve_aligned_reglist, "SME_Zmx2", 2 << OPD_F_OD_LSB, \
@@ -7132,6 +7160,9 @@ const struct aarch64_opcode aarch64_opcode_table[] =
F(FLD_SME_Zm4), "a list of SVE vector registers") \
Y(SVE_REGLIST, sve_aligned_reglist, "SME_Znx2", 2 << OPD_F_OD_LSB, \
F(FLD_SME_Zn2), "a list of SVE vector registers") \
+ Y(SVE_REGLIST, sve_aligned_reglist, "SME_Znx2_BIT_INDEX", \
+ 2 << OPD_F_OD_LSB, F(FLD_SME_Zn2), \
+ "a list of SVE vector registers") \
Y(SVE_REGLIST, sve_aligned_reglist, "SME_Znx4", 4 << OPD_F_OD_LSB, \
F(FLD_SME_Zn4), "a list of SVE vector registers") \
Y(SVE_REGLIST, sve_strided_reglist, "SME_Ztx2_STRIDED", \
@@ -7242,6 +7273,8 @@ const struct aarch64_opcode aarch64_opcode_table[] =
Y(SYSTEM, none, "SME_ZT0", 0, F (), "ZT0") \
Y(IMMEDIATE, imm, "SME_ZT0_INDEX", OPD_F_SHIFT_BY_3, \
F (FLD_imm3_12), "a ZT0 index") \
+ Y(IMMEDIATE, imm, "SME_ZT0_INDEX2_12", 0, \
+ F (FLD_imm3_12), "a ZT0 index") \
Y(SYSTEM, none, "SME_ZT0_LIST", 0, F (), "{ ZT0 }") \
Y(IMMEDIATE, imm, "TME_UIMM16", 0, F(FLD_imm16_5), \
"a 16-bit unsigned immediate for TME tcancel") \