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.
This commit is contained in:
saurabh.jha@arm.com 2024-06-21 16:30:59 +01:00 committed by Richard Earnshaw
parent c702f1ad8a
commit adea87e275
20 changed files with 549 additions and 115 deletions

View file

@ -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.

View file

@ -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},
};

View file

@ -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}

View file

@ -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\]'

View file

@ -0,0 +1,3 @@
#as: -march=armv8-a+sme2
#source: sme2-lutv2.s
#error_output: sme2-lutv2-bad.l

View file

@ -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}'

View file

@ -0,0 +1,3 @@
#as: -march=armv8-a+sme2+sme2p1+sme-lutv2
#source: sme2-lutv2-illegal.s
#error_output: sme2-lutv2-illegal.l

View file

@ -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}'

View file

@ -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 }

View file

@ -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

View file

@ -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

View file

@ -240,6 +240,8 @@ enum aarch64_feature_bit {
AARCH64_FEATURE_LUT,
/* Branch Record Buffer Extension */
AARCH64_FEATURE_BRBE,
/* SME LUTv2 instructions. */
AARCH64_FEATURE_SME_LUTv2,
AARCH64_NUM_FEATURES
};
@ -760,10 +762,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. */
@ -812,6 +816,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]. */
@ -1003,6 +1008,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,

View file

@ -679,19 +679,19 @@ aarch64_insert_operand (const aarch64_operand *self,
case 226:
case 237:
case 241:
case 245:
case 252:
case 253:
case 260:
case 261:
case 246:
case 254:
case 255:
case 262:
case 263:
case 264:
case 265:
return aarch64_ins_regno (self, info, code, inst, errors);
case 6:
case 118:
case 119:
case 295:
case 297:
case 300:
return aarch64_ins_none (self, info, code, inst, errors);
case 17:
return aarch64_ins_reg_extended (self, info, code, inst, errors);
@ -705,7 +705,7 @@ aarch64_insert_operand (const aarch64_operand *self,
case 36:
case 37:
case 38:
case 299:
case 302:
return aarch64_ins_reglane (self, info, code, inst, errors);
case 39:
case 40:
@ -713,10 +713,8 @@ aarch64_insert_operand (const aarch64_operand *self,
case 227:
case 228:
case 231:
case 264:
case 265:
case 280:
case 281:
case 266:
case 267:
case 282:
case 283:
case 284:
@ -728,6 +726,8 @@ aarch64_insert_operand (const aarch64_operand *self,
case 290:
case 291:
case 292:
case 293:
case 294:
return aarch64_ins_simple_index (self, info, code, inst, errors);
case 42:
return aarch64_ins_reglist (self, info, code, inst, errors);
@ -776,13 +776,14 @@ aarch64_insert_operand (const aarch64_operand *self,
case 207:
case 208:
case 209:
case 266:
case 293:
case 294:
case 268:
case 295:
case 296:
case 298:
case 303:
case 304:
case 299:
case 301:
case 306:
case 307:
return aarch64_ins_imm (self, info, code, inst, errors);
case 51:
case 52:
@ -930,7 +931,7 @@ aarch64_insert_operand (const aarch64_operand *self,
case 199:
case 200:
case 201:
case 279:
case 281:
return aarch64_ins_sve_shrimm (self, info, code, inst, errors);
case 214:
case 215:
@ -956,55 +957,57 @@ aarch64_insert_operand (const aarch64_operand *self,
return aarch64_ins_sve_index (self, info, code, inst, errors);
case 240:
case 242:
case 259:
case 305:
case 306:
case 307:
case 261:
case 308:
case 309:
case 310:
return aarch64_ins_sve_reglist (self, info, code, inst, errors);
case 243:
case 244:
case 246:
case 247:
case 248:
case 249:
case 258:
return aarch64_ins_sve_aligned_reglist (self, info, code, inst, errors);
case 250:
case 251:
case 260:
return aarch64_ins_sve_aligned_reglist (self, info, code, inst, errors);
case 245:
case 252:
case 253:
return aarch64_ins_sve_strided_reglist (self, info, code, inst, errors);
case 254:
case 256:
case 267:
return aarch64_ins_sme_za_hv_tiles (self, info, code, inst, errors);
case 255:
case 257:
return aarch64_ins_sme_za_hv_tiles_range (self, info, code, inst, errors);
case 268:
case 258:
case 269:
return aarch64_ins_sme_za_hv_tiles (self, info, code, inst, errors);
case 257:
case 259:
return aarch64_ins_sme_za_hv_tiles_range (self, info, code, inst, errors);
case 270:
case 271:
case 272:
case 273:
case 274:
return aarch64_ins_sme_za_array (self, info, code, inst, errors);
case 275:
return aarch64_ins_sme_addr_ri_u4xvl (self, info, code, inst, errors);
case 276:
return aarch64_ins_sme_sm_za (self, info, code, inst, errors);
return aarch64_ins_sme_za_array (self, info, code, inst, errors);
case 277:
return aarch64_ins_sme_pred_reg_with_index (self, info, code, inst, errors);
return aarch64_ins_sme_addr_ri_u4xvl (self, info, code, inst, errors);
case 278:
return aarch64_ins_sme_sm_za (self, info, code, inst, errors);
case 279:
return aarch64_ins_sme_pred_reg_with_index (self, info, code, inst, errors);
case 280:
return aarch64_ins_plain_shrimm (self, info, code, inst, errors);
case 300:
case 301:
case 302:
case 303:
case 304:
case 305:
return aarch64_ins_x0_to_x30 (self, info, code, inst, errors);
case 308:
case 309:
case 310:
case 311:
return aarch64_ins_rcpc3_addr_opt_offset (self, info, code, inst, errors);
case 312:
case 313:
case 314:
return aarch64_ins_rcpc3_addr_opt_offset (self, info, code, inst, errors);
case 315:
return aarch64_ins_rcpc3_addr_offset (self, info, code, inst, errors);
default: assert (0); abort ();
}

View file

@ -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;

View file

@ -204,32 +204,54 @@ aarch64_opcode_lookup_1 (uint32_t word)
}
else
{
if (((word >> 22) & 0x1) == 0)
if (((word >> 20) & 0x1) == 0)
{
if (((word >> 14) & 0x1) == 0)
if (((word >> 22) & 0x1) == 0)
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000x00x101xx0xxxxxxxxxxxxxx
luti4. */
return 2671;
if (((word >> 14) & 0x1) == 0)
{
if (((word >> 15) & 0x1) == 0)
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000x000101x00xxxxxxxxxxxxxx
luti4. */
return 3394;
}
else
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000x000101x10xxxxxxxxxxxxxx
luti4. */
return 2671;
}
}
else
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000x000101xx1xxxxxxxxxxxxxx
luti4. */
return 2670;
}
}
else
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000x00x101xx1xxxxxxxxxxxxxx
x1000000x100101xxxxxxxxxxxxxxxxx
luti4. */
return 2670;
return 2669;
}
}
else
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000x10x101xxxxxxxxxxxxxxxxx
x1000000xx01101xxxxxxxxxxxxxxxxx
luti4. */
return 2669;
return 3395;
}
}
}
@ -328,21 +350,32 @@ aarch64_opcode_lookup_1 (uint32_t word)
{
if (((word >> 23) & 0x1) == 0)
{
if (((word >> 17) & 0x1) == 0)
if (((word >> 16) & 0x1) == 0)
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000010x110xxxxx00xxxxxxxxxx
movt. */
return 2689;
if (((word >> 17) & 0x1) == 0)
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000010x1100xxxx00xxxxxxxxxx
movt. */
return 2689;
}
else
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000010x1110xxxx00xxxxxxxxxx
movt. */
return 2688;
}
}
else
{
/* 33222222222211111111110000000000
10987654321098765432109876543210
x1000000010x111xxxxx00xxxxxxxxxx
x1000000010x11x1xxxx00xxxxxxxxxx
movt. */
return 2688;
return 3396;
}
}
else
@ -33676,19 +33709,19 @@ aarch64_extract_operand (const aarch64_operand *self,
case 226:
case 237:
case 241:
case 245:
case 252:
case 253:
case 260:
case 261:
case 246:
case 254:
case 255:
case 262:
case 263:
case 264:
case 265:
return aarch64_ext_regno (self, info, code, inst, errors);
case 6:
case 118:
case 119:
case 295:
case 297:
case 300:
return aarch64_ext_none (self, info, code, inst, errors);
case 11:
return aarch64_ext_regrt_sysins (self, info, code, inst, errors);
@ -33707,7 +33740,7 @@ aarch64_extract_operand (const aarch64_operand *self,
case 36:
case 37:
case 38:
case 299:
case 302:
return aarch64_ext_reglane (self, info, code, inst, errors);
case 39:
case 40:
@ -33715,10 +33748,8 @@ aarch64_extract_operand (const aarch64_operand *self,
case 227:
case 228:
case 231:
case 264:
case 265:
case 280:
case 281:
case 266:
case 267:
case 282:
case 283:
case 284:
@ -33730,6 +33761,8 @@ aarch64_extract_operand (const aarch64_operand *self,
case 290:
case 291:
case 292:
case 293:
case 294:
return aarch64_ext_simple_index (self, info, code, inst, errors);
case 42:
return aarch64_ext_reglist (self, info, code, inst, errors);
@ -33779,13 +33812,14 @@ aarch64_extract_operand (const aarch64_operand *self,
case 207:
case 208:
case 209:
case 266:
case 293:
case 294:
case 268:
case 295:
case 296:
case 298:
case 303:
case 304:
case 299:
case 301:
case 306:
case 307:
return aarch64_ext_imm (self, info, code, inst, errors);
case 51:
case 52:
@ -33935,7 +33969,7 @@ aarch64_extract_operand (const aarch64_operand *self,
case 199:
case 200:
case 201:
case 279:
case 281:
return aarch64_ext_sve_shrimm (self, info, code, inst, errors);
case 214:
case 215:
@ -33961,56 +33995,58 @@ aarch64_extract_operand (const aarch64_operand *self,
return aarch64_ext_sve_index (self, info, code, inst, errors);
case 240:
case 242:
case 259:
case 261:
return aarch64_ext_sve_reglist (self, info, code, inst, errors);
case 243:
case 244:
case 246:
case 247:
case 248:
case 249:
case 258:
return aarch64_ext_sve_aligned_reglist (self, info, code, inst, errors);
case 250:
case 251:
case 260:
return aarch64_ext_sve_aligned_reglist (self, info, code, inst, errors);
case 245:
case 252:
case 253:
return aarch64_ext_sve_strided_reglist (self, info, code, inst, errors);
case 254:
case 256:
case 267:
return aarch64_ext_sme_za_hv_tiles (self, info, code, inst, errors);
case 255:
case 257:
return aarch64_ext_sme_za_hv_tiles_range (self, info, code, inst, errors);
case 268:
case 258:
case 269:
return aarch64_ext_sme_za_hv_tiles (self, info, code, inst, errors);
case 257:
case 259:
return aarch64_ext_sme_za_hv_tiles_range (self, info, code, inst, errors);
case 270:
case 271:
case 272:
case 273:
case 274:
return aarch64_ext_sme_za_array (self, info, code, inst, errors);
case 275:
return aarch64_ext_sme_addr_ri_u4xvl (self, info, code, inst, errors);
case 276:
return aarch64_ext_sme_sm_za (self, info, code, inst, errors);
return aarch64_ext_sme_za_array (self, info, code, inst, errors);
case 277:
return aarch64_ext_sme_pred_reg_with_index (self, info, code, inst, errors);
return aarch64_ext_sme_addr_ri_u4xvl (self, info, code, inst, errors);
case 278:
return aarch64_ext_sme_sm_za (self, info, code, inst, errors);
case 279:
return aarch64_ext_sme_pred_reg_with_index (self, info, code, inst, errors);
case 280:
return aarch64_ext_plain_shrimm (self, info, code, inst, errors);
case 300:
case 301:
case 302:
return aarch64_ext_x0_to_x30 (self, info, code, inst, errors);
case 303:
case 304:
case 305:
case 306:
case 307:
return aarch64_ext_sve_reglist_zt (self, info, code, inst, errors);
return aarch64_ext_x0_to_x30 (self, info, code, inst, errors);
case 308:
case 309:
case 310:
return aarch64_ext_sve_reglist_zt (self, info, code, inst, errors);
case 311:
return aarch64_ext_rcpc3_addr_opt_offset (self, info, code, inst, errors);
case 312:
case 313:
case 314:
return aarch64_ext_rcpc3_addr_opt_offset (self, info, code, inst, errors);
case 315:
return aarch64_ext_rcpc3_addr_offset (self, info, code, inst, errors);
default: assert (0); abort ();
}

View file

@ -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;

View file

@ -269,10 +269,12 @@ const struct aarch64_operand aarch64_operands[] =
{AARCH64_OPND_CLASS_SVE_REGLIST, "SVE_ZtxN", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SVE_Zt}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Zdnx2", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_Zdn2}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Zdnx4", 4 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_Zdn4}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Zdnx4_STRIDED", 4 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_ZdnT, FLD_SME_Zdn2_0}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REG, "SME_Zm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_Zm}, "an SVE vector register"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Zmx2", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_Zm2}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Zmx4", 4 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_Zm4}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Znx2", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_Zn2}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Znx2_BIT_INDEX", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_Zn2}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Znx4", 4 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_Zn4}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Ztx2_STRIDED", 2 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_ZtT, FLD_SME_Zt3}, "a list of SVE vector registers"},
{AARCH64_OPND_CLASS_SVE_REGLIST, "SME_Ztx4_STRIDED", 4 << OPD_F_OD_LSB | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_ZtT, FLD_SME_Zt2}, "a list of SVE vector registers"},
@ -321,6 +323,7 @@ const struct aarch64_operand aarch64_operands[] =
{AARCH64_OPND_CLASS_IMMEDIATE, "SME_VLxN_13", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SME_VL_13}, "VLx2 or VLx4"},
{AARCH64_OPND_CLASS_SYSTEM, "SME_ZT0", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "ZT0"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SME_ZT0_INDEX", OPD_F_SHIFT_BY_3 | OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm3_12}, "a ZT0 index"},
{AARCH64_OPND_CLASS_IMMEDIATE, "SME_ZT0_INDEX2_12", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm3_12}, "a ZT0 index"},
{AARCH64_OPND_CLASS_SYSTEM, "SME_ZT0_LIST", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "{ ZT0 }"},
{AARCH64_OPND_CLASS_IMMEDIATE, "TME_UIMM16", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_imm16_5}, "a 16-bit unsigned immediate for TME tcancel"},
{AARCH64_OPND_CLASS_SIMD_ELEMENT, "SM3_IMM2", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_SM3_imm2}, "an indexed SM3 vector immediate"},

View file

@ -258,7 +258,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]. */
@ -1919,6 +1921,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:
@ -1934,6 +1937,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
@ -3153,6 +3157,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;
}
@ -3745,9 +3757,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;
@ -4216,9 +4233,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:
@ -4906,6 +4925,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"));

View file

@ -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,

View file

@ -1814,6 +1814,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), \
@ -2050,6 +2057,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), \
@ -2752,6 +2766,8 @@ static const aarch64_feature_set aarch64_feature_lut_sve2 =
AARCH64_FEATURES (2, LUT, SVE2);
static const aarch64_feature_set aarch64_feature_brbe =
AARCH64_FEATURE (BRBE);
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
@ -2829,6 +2845,7 @@ static const aarch64_feature_set aarch64_feature_brbe =
#define LUT &aarch64_feature_lut
#define LUT_SVE2 &aarch64_feature_lut_sve2
#define BRBE &aarch64_feature_brbe
#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 }
@ -3029,6 +3046,9 @@ static const aarch64_feature_set aarch64_feature_brbe =
FLAGS, CONSTRAINTS, 0, NULL }
#define BRBE_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
{ NAME, OPCODE, MASK, ic_system, 0, BRBE, OPS, QUALS, FLAGS, 0, 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, \
@ -6615,6 +6635,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},
};
@ -7139,6 +7164,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, \
@ -7147,6 +7175,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", \
@ -7257,6 +7288,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") \