BASIC_REG_TYPE(V) /* v[0-31] */ \
BASIC_REG_TYPE(Z) /* z[0-31] */ \
BASIC_REG_TYPE(P) /* p[0-15] */ \
+ BASIC_REG_TYPE(PN) /* pn[0-15] */ \
BASIC_REG_TYPE(ZA) /* za */ \
BASIC_REG_TYPE(ZAT) /* za[0-15] (ZA tile) */ \
BASIC_REG_TYPE(ZATH) /* za[0-15]h (ZA tile horizontal slice) */ \
BASIC_REG_TYPE(ZATV) /* za[0-15]v (ZA tile vertical slice) */ \
+ BASIC_REG_TYPE(ZT0) /* zt0 */ \
/* Typecheck: any 64-bit int reg (inc SP exc XZR). */ \
MULTI_REG_TYPE(R64_SP, REG_TYPE(R_64) | REG_TYPE(SP_64)) \
/* Typecheck: same, plus SVE registers. */ \
| REG_TYPE(FP_B) | REG_TYPE(FP_H) \
| REG_TYPE(FP_S) | REG_TYPE(FP_D) | REG_TYPE(FP_Q) \
| REG_TYPE(Z) | REG_TYPE(P)) \
+ /* Likewise, but with predicate-as-counter registers added. */ \
+ MULTI_REG_TYPE(R_ZR_SP_BHSDQ_VZP_PN, REG_TYPE(R_32) | REG_TYPE(R_64) \
+ | REG_TYPE(SP_32) | REG_TYPE(SP_64) \
+ | REG_TYPE(ZR_32) | REG_TYPE(ZR_64) | REG_TYPE(V) \
+ | REG_TYPE(FP_B) | REG_TYPE(FP_H) \
+ | REG_TYPE(FP_S) | REG_TYPE(FP_D) | REG_TYPE(FP_Q) \
+ | REG_TYPE(Z) | REG_TYPE(P) | REG_TYPE(PN)) \
/* Any integer register; used for error messages only. */ \
MULTI_REG_TYPE(R_N, REG_TYPE(R_32) | REG_TYPE(R_64) \
| REG_TYPE(SP_32) | REG_TYPE(SP_64) \
| reg_type_masks[REG_TYPE_ZATHV])))
return N_("expected 'za' rather than a ZA tile at operand %d");
+ if ((mask & reg_type_masks[REG_TYPE_PN])
+ && (seen & reg_type_masks[REG_TYPE_P]))
+ return N_("expected a predicate-as-counter rather than predicate-as-mask"
+ " register at operand %d");
+
+ if ((mask & reg_type_masks[REG_TYPE_P])
+ && (seen & reg_type_masks[REG_TYPE_PN]))
+ return N_("expected a predicate-as-mask rather than predicate-as-counter"
+ " register at operand %d");
+
/* Integer, zero and stack registers. */
if (mask == reg_type_masks[REG_TYPE_R_64])
return N_("expected a 64-bit integer register at operand %d");
return N_("expected an Advanced SIMD vector register at operand %d");
if (mask == reg_type_masks[REG_TYPE_Z])
return N_("expected an SVE vector register at operand %d");
- if (mask == reg_type_masks[REG_TYPE_P])
+ if (mask == reg_type_masks[REG_TYPE_P]
+ || mask == (reg_type_masks[REG_TYPE_P] | reg_type_masks[REG_TYPE_PN]))
+ /* Use this error for "predicate-as-mask only" and "either kind of
+ predicate". We report a more specific error if P is used where
+ PN is expected, and vice versa, so the issue at this point is
+ "predicate-like" vs. "not predicate-like". */
return N_("expected an SVE predicate register at operand %d");
+ if (mask == reg_type_masks[REG_TYPE_PN])
+ return N_("expected an SVE predicate-as-counter register at operand %d");
if (mask == reg_type_masks[REG_TYPE_VZ])
return N_("expected a vector register at operand %d");
if (mask == reg_type_masks[REG_TYPE_ZP])
if (mask == reg_type_masks[REG_TYPE_VZP])
return N_("expected a vector or predicate register at operand %d");
- /* ZA-related registers. */
+ /* SME-related registers. */
if (mask == reg_type_masks[REG_TYPE_ZA])
return N_("expected a ZA array vector at operand %d");
- if (mask == reg_type_masks[REG_TYPE_ZA_ZAT])
- return N_("expected 'za' or a ZA tile at operand %d");
+ if (mask == (reg_type_masks[REG_TYPE_ZA_ZAT] | reg_type_masks[REG_TYPE_ZT0]))
+ return N_("expected ZT0 or a ZA mask at operand %d");
if (mask == reg_type_masks[REG_TYPE_ZAT])
return N_("expected a ZA tile at operand %d");
if (mask == reg_type_masks[REG_TYPE_ZATHV])
return ch == '.';
case REG_TYPE_P:
+ case REG_TYPE_PN:
return ch == '.' || ch == '/';
default:
if (!(flags & PTR_FULL_REG) && skip_past_char (&str, '['))
{
/* Reject Sn[index] syntax. */
- if (!is_typed_vecreg)
+ if (reg->type != REG_TYPE_Z
+ && reg->type != REG_TYPE_PN
+ && reg->type != REG_TYPE_ZT0
+ && !is_typed_vecreg)
{
first_error (_("this type of register can't be indexed"));
return NULL;
&& e1.index == e2.index);
}
+/* Return the register number mask for registers of type REG_TYPE. */
+
+static inline int
+reg_type_mask (aarch64_reg_type reg_type)
+{
+ return reg_type == REG_TYPE_P ? 15 : 31;
+}
+
/* This function parses a list of vector registers of type TYPE.
On success, it returns the parsed register list information in the
following encoded format:
char *str = *ccp;
int nb_regs;
struct vector_type_el typeinfo, typeinfo_first;
- int val, val_range;
+ uint32_t val, val_range, mask;
int in_range;
int ret_val;
bool error = false;
typeinfo_first.element_size = 0;
typeinfo_first.index = 0;
ret_val = 0;
- val = -1;
- val_range = -1;
+ val = -1u;
+ val_range = -1u;
in_range = 0;
+ mask = reg_type_mask (type);
do
{
if (in_range)
(_("invalid range in vector register list"));
error = true;
}
- val_range = (val_range + 1) & 0x1f;
+ val_range = (val_range + 1) & mask;
}
else
{
if (! error)
for (;;)
{
- ret_val |= val_range << (5 * nb_regs);
+ ret_val |= val_range << ((5 * nb_regs) & 31);
nb_regs++;
if (val_range == val)
break;
- val_range = (val_range + 1) & 0x1f;
+ val_range = (val_range + 1) & mask;
}
in_range = 0;
ptr_flags |= PTR_GOOD_MATCH;
/* Parse a symbolic operand such as "pow2" at *STR. ARRAY is an array
of SIZE tokens in which index I gives the token for field value I,
- or is null if field value I is invalid. REG_TYPE says which register
- names should be treated as registers rather than as symbolic immediates.
+ or is null if field value I is invalid. If the symbolic operand
+ can also be given as a 0-based integer, REG_TYPE says which register
+ names should be treated as registers rather than as symbolic immediates
+ while parsing that integer. REG_TYPE is REG_TYPE_MAX otherwise.
Return true on success, moving *STR past the operand and storing the
field value in *VAL. */
return true;
}
+ if (reg_type == REG_TYPE_MAX)
+ return false;
+
if (!parse_immediate_expression (&p, &exp, reg_type))
return false;
return false;
}
+ if (skip_past_char (str, ':'))
+ {
+ int64_t end;
+ if (!parse_sme_immediate (str, &end))
+ {
+ set_syntax_error (_("expected a constant immediate offset"));
+ return false;
+ }
+ if (end < opnd->index.imm)
+ {
+ set_syntax_error (_("the last offset is less than the"
+ " first offset"));
+ return false;
+ }
+ if (end == opnd->index.imm)
+ {
+ set_syntax_error (_("the last offset is equal to the"
+ " first offset"));
+ return false;
+ }
+ opnd->index.countm1 = (uint64_t) end - opnd->index.imm;
+ }
+
+ opnd->group_size = 0;
+ if (skip_past_char (str, ','))
+ {
+ if (strncasecmp (*str, "vgx2", 4) == 0 && !ISALPHA ((*str)[4]))
+ {
+ *str += 4;
+ opnd->group_size = 2;
+ }
+ else if (strncasecmp (*str, "vgx4", 4) == 0 && !ISALPHA ((*str)[4]))
+ {
+ *str += 4;
+ opnd->group_size = 4;
+ }
+ else
+ {
+ set_syntax_error (_("invalid vector group size"));
+ return false;
+ }
+ }
+
if (!skip_past_char (str, ']'))
{
set_syntax_error (_("expected ']'"));
goto failure; \
} while (0)
+#define po_strict_enum_or_fail(array) do { \
+ if (!parse_enum_string (&str, &val, array, \
+ ARRAY_SIZE (array), REG_TYPE_MAX)) \
+ goto failure; \
+ } while (0)
+
#define po_misc_or_fail(expr) do { \
if (!expr) \
goto failure; \
"AARCH64_OPDE_SYNTAX_ERROR",
"AARCH64_OPDE_FATAL_SYNTAX_ERROR",
"AARCH64_OPDE_INVALID_VARIANT",
+ "AARCH64_OPDE_INVALID_VG_SIZE",
"AARCH64_OPDE_REG_LIST_LENGTH",
"AARCH64_OPDE_REG_LIST_STRIDE",
"AARCH64_OPDE_UNTIED_IMMS",
gas_assert (AARCH64_OPDE_SYNTAX_ERROR > AARCH64_OPDE_EXPECTED_A_AFTER_B);
gas_assert (AARCH64_OPDE_FATAL_SYNTAX_ERROR > AARCH64_OPDE_SYNTAX_ERROR);
gas_assert (AARCH64_OPDE_INVALID_VARIANT > AARCH64_OPDE_FATAL_SYNTAX_ERROR);
- gas_assert (AARCH64_OPDE_REG_LIST_LENGTH > AARCH64_OPDE_INVALID_VARIANT);
+ gas_assert (AARCH64_OPDE_INVALID_VG_SIZE > AARCH64_OPDE_INVALID_VARIANT);
+ gas_assert (AARCH64_OPDE_REG_LIST_LENGTH > AARCH64_OPDE_INVALID_VG_SIZE);
gas_assert (AARCH64_OPDE_REG_LIST_STRIDE > AARCH64_OPDE_REG_LIST_LENGTH);
gas_assert (AARCH64_OPDE_OUT_OF_RANGE > AARCH64_OPDE_REG_LIST_STRIDE);
gas_assert (AARCH64_OPDE_UNALIGNED > AARCH64_OPDE_OUT_OF_RANGE);
detail->data[0].i, idx + 1, str);
break;
+ case AARCH64_OPDE_INVALID_VG_SIZE:
+ if (detail->data[0].i == 0)
+ handler (_("unexpected vector group size at operand %d -- `%s'"),
+ idx + 1, str);
+ else
+ handler (_("operand %d must have a vector group size of %d -- `%s'"),
+ idx + 1, detail->data[0].i, str);
+ break;
+
case AARCH64_OPDE_REG_LIST_LENGTH:
if (detail->data[0].i == (1 << 1))
handler (_("expected a single-register list at operand %d -- `%s'"),
else if ((detail->data[0].i & -detail->data[0].i) == detail->data[0].i)
handler (_("expected a list of %d registers at operand %d -- `%s'"),
get_log2 (detail->data[0].i), idx + 1, str);
+ else if (detail->data[0].i == 0x14)
+ handler (_("expected a list of %d or %d registers at"
+ " operand %d -- `%s'"),
+ 2, 4, idx + 1, str);
else
handler (_("invalid number of registers in the list"
" at operand %d -- `%s'"), idx + 1, str);
if (detail->data[0].i == (1 << 1))
handler (_("the register list must have a stride of %d"
" at operand %d -- `%s'"), 1, idx + 1, str);
+ else if (detail->data[0].i == 0x12 || detail->data[0].i == 0x102)
+ handler (_("the register list must have a stride of %d or %d"
+ " at operand %d -- `%s`"), 1,
+ detail->data[0].i == 0x12 ? 4 : 8, idx + 1, str);
else
handler (_("invalid register stride at operand %d -- `%s'"),
idx + 1, str);
return reloc_ldst_lo12[inst.reloc.type - BFD_RELOC_AARCH64_LDST_LO12][logsz];
}
-/* Check whether a register list REGINFO is valid. The registers must be
- numbered in increasing order (modulo 32). They must also have a
- consistent stride.
+/* Check whether a register list REGINFO is valid. The registers have type
+ REG_TYPE and must be numbered in increasing order (modulo the register
+ bank size). They must have a consistent stride.
Return true if the list is valid, describing it in LIST if so. */
static bool
-reg_list_valid_p (uint32_t reginfo, struct aarch64_reglist *list)
+reg_list_valid_p (uint32_t reginfo, struct aarch64_reglist *list,
+ aarch64_reg_type reg_type)
{
- uint32_t i, nb_regs, prev_regno, incr;
+ uint32_t i, nb_regs, prev_regno, incr, mask;
+ mask = reg_type_mask (reg_type);
nb_regs = 1 + (reginfo & 0x3);
reginfo >>= 2;
uint32_t curr_regno, curr_incr;
reginfo >>= 5;
curr_regno = reginfo & 0x1f;
- curr_incr = (curr_regno - prev_regno) & 0x1f;
+ curr_incr = (curr_regno - prev_regno) & mask;
if (curr_incr == 0)
return false;
else if (i == 1)
clear_error ();
skip_whitespace (str);
- if (AARCH64_CPU_HAS_ANY_FEATURES (*opcode->avariant,
- AARCH64_FEATURE_SVE
- | AARCH64_FEATURE_SVE2))
+ if (AARCH64_CPU_HAS_FEATURE (*opcode->avariant, AARCH64_FEATURE_SME2))
+ imm_reg_type = REG_TYPE_R_ZR_SP_BHSDQ_VZP_PN;
+ else if (AARCH64_CPU_HAS_ANY_FEATURES (*opcode->avariant,
+ AARCH64_FEATURE_SVE
+ | AARCH64_FEATURE_SVE2))
imm_reg_type = REG_TYPE_R_ZR_SP_BHSDQ_VZP;
else
imm_reg_type = REG_TYPE_R_ZR_BHSDQ_V;
case AARCH64_OPND_SVE_Zm_16:
case AARCH64_OPND_SVE_Zn:
case AARCH64_OPND_SVE_Zt:
+ case AARCH64_OPND_SME_Zm:
reg_type = REG_TYPE_Z;
goto vector_reg;
+ case AARCH64_OPND_SVE_PNd:
+ case AARCH64_OPND_SVE_PNg4_10:
+ case AARCH64_OPND_SVE_PNn:
+ case AARCH64_OPND_SVE_PNt:
+ case AARCH64_OPND_SME_PNd3:
+ case AARCH64_OPND_SME_PNg3:
+ case AARCH64_OPND_SME_PNn:
+ reg_type = REG_TYPE_PN;
+ goto vector_reg;
+
case AARCH64_OPND_Va:
case AARCH64_OPND_Vd:
case AARCH64_OPND_Vn:
goto failure;
info->reg.regno = reg->number;
- if ((reg_type == REG_TYPE_P || reg_type == REG_TYPE_Z)
+ if ((reg_type == REG_TYPE_P
+ || reg_type == REG_TYPE_PN
+ || reg_type == REG_TYPE_Z)
&& vectype.type == NT_invtype)
/* Unqualified P and Z registers are allowed in certain
contexts. Rely on F_STRICT qualifier checking to catch
case AARCH64_OPND_SVE_Zm3_INDEX:
case AARCH64_OPND_SVE_Zm3_22_INDEX:
+ case AARCH64_OPND_SVE_Zm3_19_INDEX:
case AARCH64_OPND_SVE_Zm3_11_INDEX:
case AARCH64_OPND_SVE_Zm4_11_INDEX:
case AARCH64_OPND_SVE_Zm4_INDEX:
case AARCH64_OPND_SVE_Zn_INDEX:
+ case AARCH64_OPND_SME_Zm_INDEX1:
+ case AARCH64_OPND_SME_Zm_INDEX2:
+ case AARCH64_OPND_SME_Zm_INDEX3_1:
+ case AARCH64_OPND_SME_Zm_INDEX3_2:
+ case AARCH64_OPND_SME_Zm_INDEX3_10:
+ case AARCH64_OPND_SME_Zm_INDEX4_1:
+ case AARCH64_OPND_SME_Zm_INDEX4_10:
+ case AARCH64_OPND_SME_Zn_INDEX1_16:
+ case AARCH64_OPND_SME_Zn_INDEX2_15:
+ case AARCH64_OPND_SME_Zn_INDEX2_16:
+ case AARCH64_OPND_SME_Zn_INDEX3_14:
+ case AARCH64_OPND_SME_Zn_INDEX3_15:
+ case AARCH64_OPND_SME_Zn_INDEX4_14:
reg_type = REG_TYPE_Z;
goto vector_reg_index;
reg = aarch64_reg_parse (&str, reg_type, &vectype);
if (!reg)
goto failure;
- if (vectype.type == NT_invtype || !(vectype.defined & NTA_HASINDEX))
+ if (!(vectype.defined & NTA_HASINDEX))
goto failure;
+ if (reg->type == REG_TYPE_Z && vectype.type == NT_invtype)
+ /* Unqualified Zn[index] is allowed in LUTI2 instructions. */
+ info->qualifier = AARCH64_OPND_QLF_NIL;
+ else
+ {
+ if (vectype.type == NT_invtype)
+ goto failure;
+ info->qualifier = vectype_to_qualifier (&vectype);
+ if (info->qualifier == AARCH64_OPND_QLF_NIL)
+ goto failure;
+ }
+
info->reglane.regno = reg->number;
info->reglane.index = vectype.index;
- info->qualifier = vectype_to_qualifier (&vectype);
- if (info->qualifier == AARCH64_OPND_QLF_NIL)
- 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_Zmx2:
+ case AARCH64_OPND_SME_Zmx4:
+ case AARCH64_OPND_SME_Znx2:
+ case AARCH64_OPND_SME_Znx4:
+ case AARCH64_OPND_SME_Ztx2_STRIDED:
+ case AARCH64_OPND_SME_Ztx4_STRIDED:
reg_type = REG_TYPE_Z;
goto vector_reg_list;
+ case AARCH64_OPND_SME_Pdx2:
+ case AARCH64_OPND_SME_PdxN:
+ reg_type = REG_TYPE_P;
+ goto vector_reg_list;
+
case AARCH64_OPND_LVn:
case AARCH64_OPND_LVt:
case AARCH64_OPND_LVt_AL:
if (val == PARSE_FAIL)
goto failure;
- if (! reg_list_valid_p (val, &info->reglist))
+ if (! reg_list_valid_p (val, &info->reglist, reg_type))
{
set_fatal_syntax_error (_("invalid register list"));
goto failure;
}
- if (vectype.width != 0 && *str != ',')
+ if ((int) vectype.width > 0 && *str != ',')
{
set_fatal_syntax_error
(_("expected element type rather than vector type"));
goto failure;
if (!(vectype.defined & NTA_HASTYPE))
{
- if (reg_type == REG_TYPE_Z)
+ if (reg_type == REG_TYPE_Z || reg_type == REG_TYPE_P)
set_fatal_syntax_error (_("missing type suffix"));
goto failure;
}
case AARCH64_OPND_SVE_SHLIMM_PRED:
case AARCH64_OPND_SVE_SHLIMM_UNPRED:
case AARCH64_OPND_SVE_SHLIMM_UNPRED_22:
+ case AARCH64_OPND_SME_SHRIMM4:
+ case AARCH64_OPND_SME_SHRIMM5:
case AARCH64_OPND_SVE_SHRIMM_PRED:
case AARCH64_OPND_SVE_SHRIMM_UNPRED:
case AARCH64_OPND_SVE_SHRIMM_UNPRED_22:
inst.base.operands[i].prfop = aarch64_prfops + val;
break;
+ case AARCH64_OPND_RPRFMOP:
+ po_enum_or_fail (aarch64_rprfmop_array);
+ info->imm.value = val;
+ break;
+
case AARCH64_OPND_BARRIER_PSB:
val = parse_barrier_psb (&str, &(info->hint_option));
if (val == PARSE_FAIL)
goto failure;
break;
+ case AARCH64_OPND_SME_ZT0:
+ po_reg_or_fail (REG_TYPE_ZT0);
+ break;
+
+ case AARCH64_OPND_SME_ZT0_INDEX:
+ reg = aarch64_reg_parse (&str, REG_TYPE_ZT0, &vectype);
+ if (!reg || vectype.type != NT_invtype)
+ goto failure;
+ if (!(vectype.defined & NTA_HASINDEX))
+ {
+ set_syntax_error (_("missing register index"));
+ goto failure;
+ }
+ info->imm.value = vectype.index;
+ break;
+
+ case AARCH64_OPND_SME_ZT0_LIST:
+ if (*str != '{')
+ {
+ set_expected_reglist_error (REG_TYPE_ZT0, parse_reg (&str));
+ goto failure;
+ }
+ str++;
+ if (!parse_typed_reg (&str, REG_TYPE_ZT0, &vectype, PTR_IN_REGLIST))
+ goto failure;
+ if (*str != '}')
+ {
+ set_syntax_error (_("expected '}' after ZT0"));
+ goto failure;
+ }
+ str++;
+ break;
+
+ case AARCH64_OPND_SME_PNn3_INDEX1:
+ case AARCH64_OPND_SME_PNn3_INDEX2:
+ reg = aarch64_reg_parse (&str, REG_TYPE_PN, &vectype);
+ if (!reg)
+ goto failure;
+ if (!(vectype.defined & NTA_HASINDEX))
+ {
+ set_syntax_error (_("missing register index"));
+ goto failure;
+ }
+ info->reglane.regno = reg->number;
+ info->reglane.index = vectype.index;
+ if (vectype.type == NT_invtype)
+ info->qualifier = AARCH64_OPND_QLF_NIL;
+ else
+ info->qualifier = vectype_to_qualifier (&vectype);
+ break;
+
case AARCH64_OPND_BTI_TARGET:
val = parse_bti_operand (&str, &(info->hint_option));
if (val == PARSE_FAIL)
break;
case AARCH64_OPND_SME_ZA_HV_idx_src:
+ case AARCH64_OPND_SME_ZA_HV_idx_srcxN:
case AARCH64_OPND_SME_ZA_HV_idx_dest:
+ case AARCH64_OPND_SME_ZA_HV_idx_destxN:
case AARCH64_OPND_SME_ZA_HV_idx_ldstr:
if (operands[i] == AARCH64_OPND_SME_ZA_HV_idx_ldstr
? !parse_sme_za_hv_tiles_operand_with_braces (&str,
info->imm.value = val;
break;
+ case AARCH64_OPND_SME_ZA_array_off1x4:
+ case AARCH64_OPND_SME_ZA_array_off2x2:
+ case AARCH64_OPND_SME_ZA_array_off2x4:
+ case AARCH64_OPND_SME_ZA_array_off3_0:
+ case AARCH64_OPND_SME_ZA_array_off3_5:
+ case AARCH64_OPND_SME_ZA_array_off3x2:
case AARCH64_OPND_SME_ZA_array_off4:
if (!parse_dual_indexed_reg (&str, REG_TYPE_ZA,
&info->indexed_za, &qualifier, 0))
info->qualifier = qualifier;
break;
+ case AARCH64_OPND_SME_VLxN_10:
+ case AARCH64_OPND_SME_VLxN_13:
+ po_strict_enum_or_fail (aarch64_sme_vlxn_array);
+ info->imm.value = val;
+ break;
+
case AARCH64_OPND_MOPS_ADDR_Rd:
case AARCH64_OPND_MOPS_ADDR_Rs:
po_char_or_fail ('[');
/* SVE vector registers. */
REGSET (z, Z), REGSET (Z, Z),
- /* SVE predicate registers. */
+ /* SVE predicate(-as-mask) registers. */
REGSET16 (p, P), REGSET16 (P, P),
+ /* SVE predicate-as-counter registers. */
+ REGSET16 (pn, PN), REGSET16 (PN, PN),
+
/* SME ZA. We model this as a register because it acts syntactically
like ZA0H, supporting qualifier suffixes and indexing. */
REGDEF (za, 0, ZA), REGDEF (ZA, 0, ZA),
REGSET16S (za, h, ZATH), REGSET16S (ZA, H, ZATH),
/* SME ZA tile registers (vertical slice). */
- REGSET16S (za, v, ZATV), REGSET16S (ZA, V, ZATV)
+ REGSET16S (za, v, ZATV), REGSET16S (ZA, V, ZATV),
+
+ /* SME2 ZT0. */
+ REGDEF (zt0, 0, ZT0), REGDEF (ZT0, 0, ZT0)
};
#undef REGDEF
| AARCH64_FEATURE_MEMTAG
| AARCH64_FEATURE_SVE2_BITPERM),
"Cortex-A510"},
+ {"cortex-a520", AARCH64_FEATURE (AARCH64_ARCH_V9_2,
+ AARCH64_FEATURE_MEMTAG
+ | AARCH64_FEATURE_SVE2_BITPERM),
+ "Cortex-A520"},
{"cortex-a710", AARCH64_FEATURE (AARCH64_ARCH_V9,
AARCH64_FEATURE_BFLOAT16
| AARCH64_FEATURE_I8MM
| AARCH64_FEATURE_MEMTAG
| AARCH64_FEATURE_SVE2_BITPERM),
"Cortex-A710"},
+ {"cortex-a720", AARCH64_FEATURE (AARCH64_ARCH_V9_2,
+ AARCH64_FEATURE_MEMTAG
+ | AARCH64_FEATURE_PROFILE
+ | AARCH64_FEATURE_SVE2_BITPERM),
+ "Cortex-A720"},
{"ares", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16
| AARCH64_FEATURE_DOTPROD