summaryrefslogtreecommitdiff
path: root/opcodes
diff options
context:
space:
mode:
authorSrinath Parvathaneni <srinath.parvathaneni@arm.com>2024-01-15 09:34:41 +0000
committerNick Clifton <nickc@redhat.com>2024-01-15 11:45:41 +0000
commit89e06ec1521898892e27615714f51d30703d5139 (patch)
tree2f51b8db85375d158020794c4a4fcbb63033fcd9 /opcodes
parent7e8d2d875701971c77224079056a0c8272d63109 (diff)
aarch64: Add support for FEAT_SME2p1 instructions.
Hi, This patch add support for FEAT_SME2p1 and "movaz" instructions along with the optional flag +sme2p1. Following "movaz" instructions are add: Move and zero two ZA tile slices to vector registers. Move and zero four ZA tile slices to vector registers. Regression testing for aarch64-none-elf target and found no regressions. Ok for binutils-master? Regards, Srinath.
Diffstat (limited to 'opcodes')
-rw-r--r--opcodes/aarch64-asm.c71
-rw-r--r--opcodes/aarch64-asm.h2
-rw-r--r--opcodes/aarch64-dis.c79
-rw-r--r--opcodes/aarch64-dis.h2
-rw-r--r--opcodes/aarch64-opc.c77
-rw-r--r--opcodes/aarch64-opc.h7
-rw-r--r--opcodes/aarch64-tbl.h36
7 files changed, 274 insertions, 0 deletions
diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
index 1db290eea7e..3fac127a589 100644
--- a/opcodes/aarch64-asm.c
+++ b/opcodes/aarch64-asm.c
@@ -1375,6 +1375,76 @@ aarch64_ins_sve_float_zero_one (const aarch64_operand *self,
return true;
}
+bool
+aarch64_ins_sme_za_vrs1 (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int za_reg = info->indexed_za.regno;
+ int regno = info->indexed_za.index.regno & 3;
+ int imm = info->indexed_za.index.imm;
+ int v = info->indexed_za.v;
+ int countm1 = info->indexed_za.index.countm1;
+
+ insert_field (self->fields[0], code, v, 0);
+ insert_field (self->fields[1], code, regno, 0);
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_B:
+ insert_field (self->fields[2], code, imm / (countm1 + 1), 0);
+ break;
+ case AARCH64_OPND_QLF_S_H:
+ case AARCH64_OPND_QLF_S_S:
+ insert_field (self->fields[2], code, za_reg, 0);
+ insert_field (self->fields[3], code, imm / (countm1 + 1), 0);
+ break;
+ case AARCH64_OPND_QLF_S_D:
+ insert_field (self->fields[2], code, za_reg, 0);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool
+aarch64_ins_sme_za_vrs2 (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int za_reg = info->indexed_za.regno;
+ int regno = info->indexed_za.index.regno & 3;
+ int imm = info->indexed_za.index.imm;
+ int v = info->indexed_za.v;
+ int countm1 = info->indexed_za.index.countm1;
+
+ insert_field (self->fields[0], code, v, 0);
+ insert_field (self->fields[1], code, regno, 0);
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_B:
+ insert_field (self->fields[2], code, imm / (countm1 + 1), 0);
+ break;
+ case AARCH64_OPND_QLF_S_H:
+ insert_field (self->fields[2], code, za_reg, 0);
+ insert_field (self->fields[3], code, imm / (countm1 + 1), 0);
+ break;
+ case AARCH64_OPND_QLF_S_S:
+ case AARCH64_OPND_QLF_S_D:
+ insert_field (self->fields[2], code, za_reg, 0);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
/* Encode in SME instruction such as MOVA ZA tile vector register number,
vector indicator, vector selector and immediate. */
bool
@@ -2011,6 +2081,7 @@ aarch64_encode_variant_using_iclass (struct aarch64_inst *inst)
break;
case sme_misc:
+ case sme2_movaz:
case sve_misc:
/* These instructions have only a single variant. */
break;
diff --git a/opcodes/aarch64-asm.h b/opcodes/aarch64-asm.h
index a3bf7bda013..d4b6407dc5d 100644
--- a/opcodes/aarch64-asm.h
+++ b/opcodes/aarch64-asm.h
@@ -100,6 +100,8 @@ AARCH64_DECL_OPD_INSERTER (ins_sve_strided_reglist);
AARCH64_DECL_OPD_INSERTER (ins_sve_scale);
AARCH64_DECL_OPD_INSERTER (ins_sve_shlimm);
AARCH64_DECL_OPD_INSERTER (ins_sve_shrimm);
+AARCH64_DECL_OPD_INSERTER (ins_sme_za_vrs1);
+AARCH64_DECL_OPD_INSERTER (ins_sme_za_vrs2);
AARCH64_DECL_OPD_INSERTER (ins_sme_za_hv_tiles);
AARCH64_DECL_OPD_INSERTER (ins_sme_za_hv_tiles_range);
AARCH64_DECL_OPD_INSERTER (ins_sme_za_list);
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 7e088a93c10..a14b2ca02d2 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -1929,6 +1929,84 @@ aarch64_ext_sme_za_array (const aarch64_operand *self,
return true;
}
+/* Decode two ZA tile slice (V, Rv, off3| ZAn ,off2 | ZAn, ol| ZAn) feilds. */
+bool
+aarch64_ext_sme_za_vrs1 (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int v = extract_field (self->fields[0], code, 0);
+ int regno = 12 + extract_field (self->fields[1], code, 0);
+ int imm, za_reg, num_offset = 2;
+
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_B:
+ imm = extract_field (self->fields[2], code, 0);
+ info->indexed_za.index.imm = imm * num_offset;
+ break;
+ case AARCH64_OPND_QLF_S_H:
+ case AARCH64_OPND_QLF_S_S:
+ za_reg = extract_field (self->fields[2], code, 0);
+ imm = extract_field (self->fields[3], code, 0);
+ info->indexed_za.index.imm = imm * num_offset;
+ info->indexed_za.regno = za_reg;
+ break;
+ case AARCH64_OPND_QLF_S_D:
+ za_reg = extract_field (self->fields[2], code, 0);
+ info->indexed_za.regno = za_reg;
+ break;
+ default:
+ return false;
+ }
+
+ info->indexed_za.index.regno = regno;
+ info->indexed_za.index.countm1 = num_offset - 1;
+ info->indexed_za.v = v;
+ info->indexed_za.group_size = get_opcode_dependent_value (inst->opcode);
+ return true;
+}
+
+/* Decode four ZA tile slice (V, Rv, off3| ZAn ,off2 | ZAn, ol| ZAn) feilds. */
+bool
+aarch64_ext_sme_za_vrs2 (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int v = extract_field (self->fields[0], code, 0);
+ int regno = 12 + extract_field (self->fields[1], code, 0);
+ int imm, za_reg, num_offset =4;
+
+ switch (info->qualifier)
+ {
+ case AARCH64_OPND_QLF_S_B:
+ imm = extract_field (self->fields[2], code, 0);
+ info->indexed_za.index.imm = imm * num_offset;
+ break;
+ case AARCH64_OPND_QLF_S_H:
+ za_reg = extract_field (self->fields[2], code, 0);
+ imm = extract_field (self->fields[3], code, 0);
+ info->indexed_za.index.imm = imm * num_offset;
+ info->indexed_za.regno = za_reg;
+ break;
+ case AARCH64_OPND_QLF_S_S:
+ case AARCH64_OPND_QLF_S_D:
+ za_reg = extract_field (self->fields[2], code, 0);
+ info->indexed_za.regno = za_reg;
+ break;
+ default:
+ return false;
+ }
+
+ info->indexed_za.index.regno = regno;
+ info->indexed_za.index.countm1 = num_offset - 1;
+ info->indexed_za.v = v;
+ info->indexed_za.group_size = get_opcode_dependent_value (inst->opcode);
+ return true;
+}
+
bool
aarch64_ext_sme_addr_ri_u4xvl (const aarch64_operand *self,
aarch64_opnd_info *info, aarch64_insn code,
@@ -3160,6 +3238,7 @@ aarch64_decode_variant_using_iclass (aarch64_inst *inst)
variant = 3;
break;
+ case sme2_movaz:
case sme_misc:
case sve_misc:
/* These instructions have only a single variant. */
diff --git a/opcodes/aarch64-dis.h b/opcodes/aarch64-dis.h
index 20387db7b39..9a38c1ab50f 100644
--- a/opcodes/aarch64-dis.h
+++ b/opcodes/aarch64-dis.h
@@ -124,6 +124,8 @@ AARCH64_DECL_OPD_EXTRACTOR (ext_sve_strided_reglist);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_scale);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shlimm);
AARCH64_DECL_OPD_EXTRACTOR (ext_sve_shrimm);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sme_za_vrs1);
+AARCH64_DECL_OPD_EXTRACTOR (ext_sme_za_vrs2);
AARCH64_DECL_OPD_EXTRACTOR (ext_sme_za_hv_tiles);
AARCH64_DECL_OPD_EXTRACTOR (ext_sme_za_hv_tiles_range);
AARCH64_DECL_OPD_EXTRACTOR (ext_sme_za_list);
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index e3ad32f5a1e..cf76871930f 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -400,6 +400,16 @@ const aarch64_field fields[] =
{ 22, 1 }, /* sz: 1-bit element size select. */
{ 22, 2 }, /* type: floating point type field in fp data inst. */
{ 10, 2 }, /* vldst_size: size field in the AdvSIMD load/store inst. */
+ { 5, 3 }, /* off3: immediate offset used to calculate slice number in a
+ ZA tile. */
+ { 5, 2 }, /* off2: immediate offset used to calculate slice number in
+ a ZA tile. */
+ { 7, 1 }, /* ZAn_1: name of the 1bit encoded ZA tile. */
+ { 5, 1 }, /* ol: immediate offset used to calculate slice number in a ZA
+ tile. */
+ { 6, 2 }, /* ZAn_2: name of the 2bit encoded ZA tile. */
+ { 5, 3 }, /* ZAn_3: name of the 3bit encoded ZA tile. */
+ { 6, 1 }, /* ZAn: name of the bit encoded ZA tile. */
};
enum aarch64_operand_class
@@ -1938,6 +1948,49 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
return 0;
break;
+ case AARCH64_OPND_SME_ZA_array_vrsb_1:
+ if (!check_za_access (opnd, mismatch_detail, idx, 12, 7, 2,
+ get_opcode_dependent_value (opcode)))
+ return 0;
+ break;
+
+ case AARCH64_OPND_SME_ZA_array_vrsh_1:
+ if (!check_za_access (opnd, mismatch_detail, idx, 12, 3, 2,
+ get_opcode_dependent_value (opcode)))
+ return 0;
+ break;
+
+ case AARCH64_OPND_SME_ZA_array_vrss_1:
+ if (!check_za_access (opnd, mismatch_detail, idx, 12, 1, 2,
+ get_opcode_dependent_value (opcode)))
+ return 0;
+ break;
+
+ case AARCH64_OPND_SME_ZA_array_vrsd_1:
+ if (!check_za_access (opnd, mismatch_detail, idx, 12, 0, 2,
+ get_opcode_dependent_value (opcode)))
+ return 0;
+ break;
+
+ case AARCH64_OPND_SME_ZA_array_vrsb_2:
+ if (!check_za_access (opnd, mismatch_detail, idx, 12, 3, 4,
+ get_opcode_dependent_value (opcode)))
+ return 0;
+ break;
+
+ case AARCH64_OPND_SME_ZA_array_vrsh_2:
+ if (!check_za_access (opnd, mismatch_detail, idx, 12, 1, 4,
+ get_opcode_dependent_value (opcode)))
+ return 0;
+ break;
+
+ case AARCH64_OPND_SME_ZA_array_vrss_2:
+ case AARCH64_OPND_SME_ZA_array_vrsd_2:
+ if (!check_za_access (opnd, mismatch_detail, idx, 12, 0, 4,
+ get_opcode_dependent_value (opcode)))
+ return 0;
+ break;
+
case AARCH64_OPND_SME_ZA_HV_idx_srcxN:
case AARCH64_OPND_SME_ZA_HV_idx_destxN:
size = aarch64_get_qualifier_esize (opnd->qualifier);
@@ -4103,6 +4156,30 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
? style_sub_mnem (styler, "vgx4") : "");
break;
+ case AARCH64_OPND_SME_ZA_array_vrsb_1:
+ case AARCH64_OPND_SME_ZA_array_vrsh_1:
+ case AARCH64_OPND_SME_ZA_array_vrss_1:
+ case AARCH64_OPND_SME_ZA_array_vrsd_1:
+ case AARCH64_OPND_SME_ZA_array_vrsb_2:
+ case AARCH64_OPND_SME_ZA_array_vrsh_2:
+ case AARCH64_OPND_SME_ZA_array_vrss_2:
+ case AARCH64_OPND_SME_ZA_array_vrsd_2:
+ snprintf (buf, size, "%s [%s, %s%s%s]",
+ style_reg (styler, "za%d%c%s%s",
+ opnd->indexed_za.regno,
+ opnd->indexed_za.v ? 'v': 'h',
+ opnd->qualifier == AARCH64_OPND_QLF_NIL ? "" : ".",
+ (opnd->qualifier == AARCH64_OPND_QLF_NIL
+ ? ""
+ : aarch64_get_qualifier_name (opnd->qualifier))),
+ style_reg (styler, "w%d", opnd->indexed_za.index.regno),
+ style_imm (styler, "%" PRIi64, opnd->indexed_za.index.imm),
+ opnd->indexed_za.index.countm1 ? ":" : "",
+ opnd->indexed_za.index.countm1 ? style_imm (styler, "%d",
+ opnd->indexed_za.index.imm
+ + opnd->indexed_za.index.countm1):"");
+ break;
+
case AARCH64_OPND_SME_SM_ZA:
snprintf (buf, size, "%s",
style_reg (styler, opnd->reg.regno == 's' ? "sm" : "za"));
diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
index f193a90ecc5..587775152e3 100644
--- a/opcodes/aarch64-opc.h
+++ b/opcodes/aarch64-opc.h
@@ -210,6 +210,13 @@ enum aarch64_field_kind
FLD_sz,
FLD_type,
FLD_vldst_size,
+ FLD_off3,
+ FLD_off2,
+ FLD_ZAn_1,
+ FLD_ol,
+ FLD_ZAn_2,
+ FLD_ZAn_3,
+ FLD_ZAn
};
/* Field description. */
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index a8ccdafd044..9c7648b0a6d 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -1497,6 +1497,10 @@
{ \
QLF2(S_B,S_B), \
}
+#define OP_SVE_HH \
+{ \
+ QLF2(S_H,S_H), \
+}
#define OP_SVE_BBU \
{ \
QLF3(S_B,S_B,NIL), \
@@ -2614,6 +2618,8 @@ static const aarch64_feature_set aarch64_feature_d128_the =
AARCH64_FEATURES (2, D128, THE);
static const aarch64_feature_set aarch64_feature_b16b16 =
AARCH64_FEATURE (B16B16);
+static const aarch64_feature_set aarch64_feature_sme2p1 =
+ AARCH64_FEATURE (SME2p1);
#define CORE &aarch64_feature_v8
#define FP &aarch64_feature_fp
@@ -2677,6 +2683,7 @@ static const aarch64_feature_set aarch64_feature_b16b16 =
#define THE &aarch64_feature_the
#define D128_THE &aarch64_feature_d128_the
#define B16B16 &aarch64_feature_b16b16
+#define SME2p1 &aarch64_feature_sme2p1
#define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
{ NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
@@ -2743,6 +2750,9 @@ static const aarch64_feature_set aarch64_feature_b16b16 =
#define SVE2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
{ NAME, OPCODE, MASK, CLASS, OP, SVE2, OPS, QUALS, \
FLAGS | F_STRICT, 0, TIED, NULL }
+#define SME2p1_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,TIED) \
+ { NAME, OPCODE, MASK, CLASS, OP, SME2p1, OPS, QUALS, \
+ FLAGS | F_STRICT, 0, TIED, NULL }
#define SVE2_INSNC(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS,CONSTRAINTS,TIED) \
{ NAME, OPCODE, MASK, CLASS, OP, SVE2, OPS, QUALS, \
FLAGS | F_STRICT, CONSTRAINTS, TIED, NULL }
@@ -6289,6 +6299,16 @@ const struct aarch64_opcode aarch64_opcode_table[] =
B16B16_INSN("bfmls", 0x64200c00, 0xffa0fc00, sve_misc, 0, OP3 (SVE_Zd, SVE_Zn, SVE_Zm3_11_INDEX), OP_SVE_VVV_H, 0, 0),
B16B16_INSN("bfmul", 0x64202800, 0xffa0fc00, sve_misc, 0, OP3 (SVE_Zd, SVE_Zn, SVE_Zm3_11_INDEX), OP_SVE_VVV_H, 0, 0),
+/* SME2.1 movaz instructions. */
+ SME2p1_INSN ("movaz", 0xc0060600, 0xffff1f83, sme2_movaz, 0, OP2 (SME_Zdnx4, SME_ZA_array_vrsb_2), OP_SVE_BB, 0, 0),
+ SME2p1_INSN ("movaz", 0xc0460600, 0xffff1f83, sme2_movaz, 0, OP2 (SME_Zdnx4, SME_ZA_array_vrsh_2), OP_SVE_HH, 0, 0),
+ SME2p1_INSN ("movaz", 0xc0860600, 0xffff1f83, sme2_movaz, 0, OP2 (SME_Zdnx4, SME_ZA_array_vrss_2), OP_SVE_SS, 0, 0),
+ SME2p1_INSN ("movaz", 0xc0c60600, 0xffff1f03, sme2_movaz, 0, OP2 (SME_Zdnx4, SME_ZA_array_vrsd_2), OP_SVE_DD, 0, 0),
+
+ SME2p1_INSN ("movaz", 0xc0060200, 0xffff1f01, sme2_movaz, 0, OP2 (SME_Zdnx2, SME_ZA_array_vrsb_1), OP_SVE_BB, 0, 0),
+ SME2p1_INSN ("movaz", 0xc0460200, 0xffff1f01, sme2_movaz, 0, OP2 (SME_Zdnx2, SME_ZA_array_vrsh_1), OP_SVE_HH, 0, 0),
+ SME2p1_INSN ("movaz", 0xc0860200, 0xffff1f01, sme2_movaz, 0, OP2 (SME_Zdnx2, SME_ZA_array_vrss_1), OP_SVE_SS, 0, 0),
+ SME2p1_INSN ("movaz", 0xc0c60200, 0xffff1f01, sme2_movaz, 0, OP2 (SME_Zdnx2, SME_ZA_array_vrsd_1), OP_SVE_DD, 0, 0),
{0, 0, 0, 0, 0, 0, {}, {}, 0, 0, 0, NULL},
};
@@ -6726,6 +6746,22 @@ const struct aarch64_opcode aarch64_opcode_table[] =
Y(SIMD_REG, regno, "SVE_Vd", 0, F(FLD_SVE_Vd), "a SIMD register") \
Y(SIMD_REG, regno, "SVE_Vm", 0, F(FLD_SVE_Vm), "a SIMD register") \
Y(SIMD_REG, regno, "SVE_Vn", 0, F(FLD_SVE_Vn), "a SIMD register") \
+ Y(ZA_ACCESS, sme_za_vrs1, "SME_ZA_array_vrsb_1", 0, \
+ F(FLD_SME_V,FLD_SME_Rv,FLD_off3), "ZA0 tile") \
+ Y(ZA_ACCESS, sme_za_vrs1, "SME_ZA_array_vrsh_1", 0, \
+ F(FLD_SME_V,FLD_SME_Rv,FLD_ZAn_1,FLD_off2), "1 bit ZA tile") \
+ Y(ZA_ACCESS, sme_za_vrs1, "SME_ZA_array_vrss_1", 0, \
+ F(FLD_SME_V,FLD_SME_Rv,FLD_ZAn_2,FLD_ol), "2 ZA tile") \
+ Y(ZA_ACCESS, sme_za_vrs1, "SME_ZA_array_vrsd_1", 0, \
+ F(FLD_SME_V,FLD_SME_Rv,FLD_ZAn_3), "3 ZA tile") \
+ Y(ZA_ACCESS, sme_za_vrs2, "SME_ZA_array_vrsb_2", 0, \
+ F(FLD_SME_V,FLD_SME_Rv,FLD_off2), "ZA0 tile") \
+ Y(ZA_ACCESS, sme_za_vrs2, "SME_ZA_array_vrsh_2", 0, \
+ F(FLD_SME_V,FLD_SME_Rv,FLD_ZAn,FLD_ol), "1 bit ZA tile") \
+ Y(ZA_ACCESS, sme_za_vrs2, "SME_ZA_array_vrss_2", 0, \
+ F(FLD_SME_V,FLD_SME_Rv,FLD_off2), "2 bit ZA tile") \
+ Y(ZA_ACCESS, sme_za_vrs2, "SME_ZA_array_vrsd_2", 0, \
+ F(FLD_SME_V,FLD_SME_Rv,FLD_ZAn_3), "3 bit ZA tile") \
Y(SVE_REG, regno, "SVE_Za_5", 0, F(FLD_SVE_Za_5), \
"an SVE vector register") \
Y(SVE_REG, regno, "SVE_Za_16", 0, F(FLD_SVE_Za_16), \