[1/2] aarch64: Add FEAT_MOPS_GO instructions
Commit Message
---
gas/config/tc-aarch64.c | 1 +
include/opcode/aarch64.h | 2 +
opcodes/aarch64-dis-2.c | 128 +++++++++++++++++++++++++++++++++++++--
opcodes/aarch64-opc.c | 53 ++++++++++++----
opcodes/aarch64-tbl-2.h | 12 ++++
opcodes/aarch64-tbl.h | 32 ++++++++++
6 files changed, 213 insertions(+), 15 deletions(-)
Comments
On Tue, Dec 02, 2025 at 12:44:16PM +0000, Yury Khrustalev wrote:
> ---
> gas/config/tc-aarch64.c | 1 +
> include/opcode/aarch64.h | 2 +
> opcodes/aarch64-dis-2.c | 128 +++++++++++++++++++++++++++++++++++++--
> opcodes/aarch64-opc.c | 53 ++++++++++++----
> opcodes/aarch64-tbl-2.h | 12 ++++
> opcodes/aarch64-tbl.h | 32 ++++++++++
> 6 files changed, 213 insertions(+), 15 deletions(-)
>
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index 0ca54c3bd40..a8921c8be9e 100644
> --- a/gas/config/tc-aarch64.c
> +++ b/gas/config/tc-aarch64.c
> @@ -10905,6 +10905,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
> {"ssve-fexpa", AARCH64_FEATURE (SSVE_FEXPA), AARCH64_FEATURE (SME2)},
> {"sme-tmop", AARCH64_FEATURE (SME_TMOP), AARCH64_FEATURE (SME2)},
> {"sme-mop4", AARCH64_FEATURE (SME_MOP4), AARCH64_FEATURE (SME2)},
> + {"mops-go", AARCH64_FEATURE (MOPS_GO), AARCH64_FEATURE (MOPS)},
> {NULL, AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
> };
>
> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index e65b61c3f9c..e9e1a6d9650 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -290,6 +290,8 @@ enum aarch64_feature_bit {
> AARCH64_FEATURE_SVE2p1_SME2p1,
> /* +sve2p2 or +sme2p2 */
> AARCH64_FEATURE_SVE2p2_SME2p2,
> + /* +mops-go */
> + AARCH64_FEATURE_MOPS_GO,
This should be inserted before the comment beginning "Virtual features" -
everything at the end of the enum is a virtual feature bit with no
corresponding command line flag.
> AARCH64_NUM_FEATURES
> };
>
> diff --git a/opcodes/aarch64-dis-2.c b/opcodes/aarch64-dis-2.c
> index ecaea2d2fdb..e2a8c16ca3b 100644
> --- a/opcodes/aarch64-dis-2.c
> +++ b/opcodes/aarch64-dis-2.c
> @@ -27898,10 +27898,130 @@ aarch64_opcode_lookup_1 (uint32_t word)
> {
> if (((word >> 10) & 0x1) == 0)
> {
> - /* 33222222222211111111110000000000
> - 10987654321098765432109876543210
> - xx011101x1xxxxxxxxxxx0xxxxxxxxxx. */
> - return A64_OPID_1d400800_ldapur_Ft_RCPC3_ADDR_OFFSET;
> + if (((word >> 11) & 0x1) == 0)
> + {
> + if (((word >> 12) & 0x1) == 0)
> + {
> + if (((word >> 13) & 0x1) == 0)
> + {
> + if (((word >> 14) & 0x1) == 0)
> + {
> + if (((word >> 15) & 0x1) == 0)
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxx000000xxxxxxxxxx. */
> + return A64_OPID_1ddf0000_setgop_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + else
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxx100000xxxxxxxxxx. */
> + return A64_OPID_1ddf8000_setgoe_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + }
> + else
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxxx10000xxxxxxxxxx. */
> + return A64_OPID_1ddf4000_setgom_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + }
> + else
> + {
> + if (((word >> 14) & 0x1) == 0)
> + {
> + if (((word >> 15) & 0x1) == 0)
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxx001000xxxxxxxxxx. */
> + return A64_OPID_1ddf2000_setgopn_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + else
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxx101000xxxxxxxxxx. */
> + return A64_OPID_1ddfa000_setgoen_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + }
> + else
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxxx11000xxxxxxxxxx. */
> + return A64_OPID_1ddf6000_setgomn_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + }
> + }
> + else
> + {
> + if (((word >> 13) & 0x1) == 0)
> + {
> + if (((word >> 14) & 0x1) == 0)
> + {
> + if (((word >> 15) & 0x1) == 0)
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxx000100xxxxxxxxxx. */
> + return A64_OPID_1ddf1000_setgopt_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + else
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxx100100xxxxxxxxxx. */
> + return A64_OPID_1ddf9000_setgoet_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + }
> + else
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxxx10100xxxxxxxxxx. */
> + return A64_OPID_1ddf5000_setgomt_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + }
> + else
> + {
> + if (((word >> 14) & 0x1) == 0)
> + {
> + if (((word >> 15) & 0x1) == 0)
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxx001100xxxxxxxxxx. */
> + return A64_OPID_1ddf3000_setgoptn_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + else
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxx101100xxxxxxxxxx. */
> + return A64_OPID_1ddfb000_setgoetn_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + }
> + else
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxxx11100xxxxxxxxxx. */
> + return A64_OPID_1ddf7000_setgomtn_MOPS_ADDR_Rd_MOPS_WB_Rn;
> + }
> + }
> + }
> + }
> + else
> + {
> + /* 33222222222211111111110000000000
> + 10987654321098765432109876543210
> + xx011101x1xxxxxxxxxx10xxxxxxxxxx. */
> + return A64_OPID_1d400800_ldapur_Ft_RCPC3_ADDR_OFFSET;
> + }
> }
> else
> {
> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
> index b074765920e..ef03dd1cfdb 100644
> --- a/opcodes/aarch64-opc.c
> +++ b/opcodes/aarch64-opc.c
> @@ -5587,6 +5587,22 @@ verify_elem_sd (const struct aarch64_inst *inst, const aarch64_insn insn,
> return ERR_OK;
> }
>
> +
> +static enum err_type
> +verify_three_different_regs_impl (int rx, int ry, int rz,
> + aarch64_operand_error *mismatch_detail,
> + const char *error)
> +{
> + if (rx == ry || rx == rz || ry == rz)
> + {
> + mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
> + mismatch_detail->error = error;
> + mismatch_detail->index = -1;
> + return ERR_UND;
> + }
> + return ERR_OK;
> +}
> +
> /* Check an instruction that takes three register operands and that
> requires the register numbers to be distinct from one another. */
>
> @@ -5595,8 +5611,7 @@ verify_three_different_regs (const struct aarch64_inst *inst,
> const aarch64_insn insn ATTRIBUTE_UNUSED,
> bfd_vma pc ATTRIBUTE_UNUSED,
> bool encoding ATTRIBUTE_UNUSED,
> - aarch64_operand_error *mismatch_detail
> - ATTRIBUTE_UNUSED,
> + aarch64_operand_error *mismatch_detail,
> aarch64_instr_sequence *insn_sequence
> ATTRIBUTE_UNUSED)
> {
> @@ -5605,16 +5620,32 @@ verify_three_different_regs (const struct aarch64_inst *inst,
> rd = inst->operands[0].reg.regno;
> rs = inst->operands[1].reg.regno;
> rn = inst->operands[2].reg.regno;
> - if (rd == rs || rd == rn || rs == rn)
> - {
> - mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
> - mismatch_detail->error
> - = _("the three register operands must be distinct from one another");
> - mismatch_detail->index = -1;
> - return ERR_UND;
> - }
>
> - return ERR_OK;
> + return verify_three_different_regs_impl (rd, rs, rn, mismatch_detail,
> + _("the three register operands must be distinct from one another"));
> +}
This change makes the code less readable. The two verifiers are sufficiently
different that I don't think it's worth trying to share part of the
implementation.
> +
> +
> +/* Check an instruction that takes two register operands and that
> + requires the register numbers to be distinct from one another
> + and also different from 31. */
> +
> +static enum err_type
> +verify_two_diff_regs_not_31 (const struct aarch64_inst *inst,
> + const aarch64_insn insn ATTRIBUTE_UNUSED,
> + bfd_vma pc ATTRIBUTE_UNUSED,
> + bool encoding ATTRIBUTE_UNUSED,
> + aarch64_operand_error *mismatch_detail,
> + aarch64_instr_sequence *insn_sequence
> + ATTRIBUTE_UNUSED)
> +{
> + int rd, rn;
> +
> + rd = inst->operands[0].reg.regno;
> + rn = inst->operands[1].reg.regno;
> +
> + return verify_three_different_regs_impl (rd, rn, 31, mismatch_detail,
> + _("the two register operands must be distinct from each other"));
This would give the wrong error message if rd or rn were 31, but I think that
possibility is already ruled out by the existing choice of operand. The only
necessary check here is for (rd != rn).
> }
>
> /* Add INST to the end of INSN_SEQUENCE. */
> diff --git a/opcodes/aarch64-tbl-2.h b/opcodes/aarch64-tbl-2.h
> index 1263f1f9bd8..993bffa7673 100644
> --- a/opcodes/aarch64-tbl-2.h
> +++ b/opcodes/aarch64-tbl-2.h
> @@ -3395,6 +3395,18 @@ enum aarch64_opcode_idx
> A64_OPID_1dc03400_setgptn_MOPS_ADDR_Rd_MOPS_WB_Rn_Rm,
> A64_OPID_1dc07400_setgmtn_MOPS_ADDR_Rd_MOPS_WB_Rn_Rm,
> A64_OPID_1dc0b400_setgetn_MOPS_ADDR_Rd_MOPS_WB_Rn_Rm,
> + A64_OPID_1ddf0000_setgop_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddf4000_setgom_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddf8000_setgoe_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddf1000_setgopt_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddf5000_setgomt_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddf9000_setgoet_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddf2000_setgopn_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddf6000_setgomn_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddfa000_setgoen_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddf3000_setgoptn_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddf7000_setgomtn_MOPS_ADDR_Rd_MOPS_WB_Rn,
> + A64_OPID_1ddfb000_setgoetn_MOPS_ADDR_Rd_MOPS_WB_Rn,
> A64_OPID_54000010_bc_c_ADDR_PCREL19,
> A64_OPID_11c00000_smax_Rd_Rn_CSSC_SIMM8,
> A64_OPID_11c40000_umax_Rd_Rn_CSSC_UIMM8,
> diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
> index 2fc69c27791..e596a2c54ee 100644
> --- a/opcodes/aarch64-tbl.h
> +++ b/opcodes/aarch64-tbl.h
> @@ -2927,6 +2927,8 @@ static const aarch64_feature_set aarch64_feature_mops =
> AARCH64_FEATURE (MOPS);
> static const aarch64_feature_set aarch64_feature_mops_memtag =
> AARCH64_FEATURES (2, MOPS, MEMTAG);
> +static const aarch64_feature_set aarch64_feature_mops_go_memtag =
> + AARCH64_FEATURES (2, MOPS_GO, MEMTAG);
> static const aarch64_feature_set aarch64_feature_hbc =
> AARCH64_FEATURE (HBC);
> static const aarch64_feature_set aarch64_feature_cssc =
> @@ -3116,6 +3118,7 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
> #define WFXT &aarch64_feature_wfxt
> #define MOPS &aarch64_feature_mops
> #define MOPS_MEMTAG &aarch64_feature_mops_memtag
> +#define MOPS_GO_MEMTAG &aarch64_feature_mops_go_memtag
> #define HBC &aarch64_feature_hbc
> #define CSSC &aarch64_feature_cssc
> #define CHK &aarch64_feature_chk
> @@ -3371,6 +3374,9 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
> #define MOPS_MEMTAG_INSN(NAME, OPCODE, MASK, CLASS, OPS, QUALS, FLAGS, CONSTRAINTS, VERIFIER) \
> { NAME, OPCODE, MASK, CLASS, 0, MOPS_MEMTAG, OPS, QUALS, FLAGS, \
> CONSTRAINTS, 0, VERIFIER }
> +#define MOPS_GO_MEMTAG_INSN(NAME, OPCODE, MASK, CLASS, OPS, QUALS, FLAGS, CONSTRAINTS, VERIFIER) \
> + { NAME, OPCODE, MASK, CLASS, 0, MOPS_GO_MEMTAG, OPS, QUALS, FLAGS, \
> + CONSTRAINTS, 0, VERIFIER }
> #define HBC_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
> { NAME, OPCODE, MASK, CLASS, 0, HBC, OPS, QUALS, FLAGS, 0, 0, NULL }
> #define CSSC_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
> @@ -3543,6 +3549,11 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
> OP3 (MOPS_ADDR_Rd, MOPS_WB_Rn, Rm), QL_I3SAMEX, FLAGS, \
> CONSTRAINTS, VERIFIER (three_different_regs))
>
> +#define MOPS_GO_SET_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS, ISA) \
> + ISA (NAME, OPCODE, MASK, 0, \
> + OP2 (MOPS_ADDR_Rd, MOPS_WB_Rn), QL_I2SAMEX, FLAGS, \
> + CONSTRAINTS, VERIFIER (two_diff_regs_not_31))
> +
> /* These instructions must remain consecutive, since we rely on the order
> when detecting invalid sequences. */
> #define MOPS_SET_OP1_OP2_INSN(NAME, SUFFIX, OPCODE, MASK, ISA) \
> @@ -3553,12 +3564,28 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
> MOPS_SET_OP1_OP2_PME_INSN (NAME "e" SUFFIX, OPCODE | 0x8000, MASK, \
> 0, C_SCAN_MOPS_E, ISA)
>
> +/* These instructions must remain consecutive, since we rely on the order
> + when detecting invalid sequences. */
> +#define MOPS_GO_SET_OP1_OP2_INSN(NAME, SUFFIX, OPCODE, MASK, ISA) \
> + MOPS_GO_SET_OP1_OP2_PME_INSN (NAME "p" SUFFIX, OPCODE, MASK, \
> + F_SCAN, C_SCAN_MOPS_P, ISA), \
> + MOPS_GO_SET_OP1_OP2_PME_INSN (NAME "m" SUFFIX, OPCODE | 0x4000, MASK, \
> + 0, C_SCAN_MOPS_M, ISA), \
> + MOPS_GO_SET_OP1_OP2_PME_INSN (NAME "e" SUFFIX, OPCODE | 0x8000, MASK, \
> + 0, C_SCAN_MOPS_E, ISA)
> +
> #define MOPS_SET_INSN(NAME, OPCODE, MASK, ISA) \
> MOPS_SET_OP1_OP2_INSN (NAME, "", OPCODE, MASK, ISA), \
> MOPS_SET_OP1_OP2_INSN (NAME, "t", OPCODE | 0x1000, MASK, ISA), \
> MOPS_SET_OP1_OP2_INSN (NAME, "n", OPCODE | 0x2000, MASK, ISA), \
> MOPS_SET_OP1_OP2_INSN (NAME, "tn", OPCODE | 0x3000, MASK, ISA)
>
> +#define MOPS_GO_SET_INSN(NAME, OPCODE, MASK, ISA) \
> + MOPS_GO_SET_OP1_OP2_INSN (NAME, "", OPCODE, MASK, ISA), \
> + MOPS_GO_SET_OP1_OP2_INSN (NAME, "t", OPCODE | 0x1000, MASK, ISA), \
> + MOPS_GO_SET_OP1_OP2_INSN (NAME, "n", OPCODE | 0x2000, MASK, ISA), \
> + MOPS_GO_SET_OP1_OP2_INSN (NAME, "tn", OPCODE | 0x3000, MASK, ISA)
> +
> #define PREDRES2_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
> { NAME, OPCODE, MASK, CLASS, 0, PREDRES2, OPS, QUALS, FLAGS, 0, 0, NULL }
>
> @@ -7031,6 +7058,11 @@ const struct aarch64_opcode aarch64_opcode_table[] =
> setge setget setgen setgetn */
> MOPS_SET_INSN ("setg", 0x1dc00400, 0xffe0fc00, MOPS_MEMTAG_INSN),
>
> + /* setgop setgopt setgopn setgoptn
> + setgom setgomt setgomn setgomtn
> + setgoe setgoet setgoen setgoetn */
> + MOPS_GO_SET_INSN ("setgo", 0x1ddf0000, 0x3ffffc00, MOPS_GO_MEMTAG_INSN),
> +
> HBC_INSN ("bc.c", 0x54000010, 0xff000010, condbranch, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_COND),
>
> /* CSSC with immediates. */
> --
> 2.47.3
>
On Tue, Dec 02, 2025 at 12:44:16PM +0000, Yury Khrustalev wrote:
One more comment - I think there should be a dependency from +mops-go ->
+memtag, and the instructions would then only need to depend directly upon
MOPS_GO (although I haven't yet confirmed this with the LLVM team). In that
case, as well as adjusting the feature dependencies, we could drop '_memtag'
from the names below and remove '+memtag' from the tests.
Also, could you combine these two patches please? I think it's better to add
the tests for new instruction as part of the patch that introduces those
instructions.
Alice
> diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
> index 2fc69c27791..e596a2c54ee 100644
> --- a/opcodes/aarch64-tbl.h
> +++ b/opcodes/aarch64-tbl.h
> @@ -2927,6 +2927,8 @@ static const aarch64_feature_set aarch64_feature_mops =
> AARCH64_FEATURE (MOPS);
> static const aarch64_feature_set aarch64_feature_mops_memtag =
> AARCH64_FEATURES (2, MOPS, MEMTAG);
> +static const aarch64_feature_set aarch64_feature_mops_go_memtag =
> + AARCH64_FEATURES (2, MOPS_GO, MEMTAG);
> static const aarch64_feature_set aarch64_feature_hbc =
> AARCH64_FEATURE (HBC);
> static const aarch64_feature_set aarch64_feature_cssc =
> @@ -3116,6 +3118,7 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
> #define WFXT &aarch64_feature_wfxt
> #define MOPS &aarch64_feature_mops
> #define MOPS_MEMTAG &aarch64_feature_mops_memtag
> +#define MOPS_GO_MEMTAG &aarch64_feature_mops_go_memtag
> #define HBC &aarch64_feature_hbc
> #define CSSC &aarch64_feature_cssc
> #define CHK &aarch64_feature_chk
> @@ -3371,6 +3374,9 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
> #define MOPS_MEMTAG_INSN(NAME, OPCODE, MASK, CLASS, OPS, QUALS, FLAGS, CONSTRAINTS, VERIFIER) \
> { NAME, OPCODE, MASK, CLASS, 0, MOPS_MEMTAG, OPS, QUALS, FLAGS, \
> CONSTRAINTS, 0, VERIFIER }
> +#define MOPS_GO_MEMTAG_INSN(NAME, OPCODE, MASK, CLASS, OPS, QUALS, FLAGS, CONSTRAINTS, VERIFIER) \
> + { NAME, OPCODE, MASK, CLASS, 0, MOPS_GO_MEMTAG, OPS, QUALS, FLAGS, \
> + CONSTRAINTS, 0, VERIFIER }
> #define HBC_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
> { NAME, OPCODE, MASK, CLASS, 0, HBC, OPS, QUALS, FLAGS, 0, 0, NULL }
> #define CSSC_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
@@ -10905,6 +10905,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"ssve-fexpa", AARCH64_FEATURE (SSVE_FEXPA), AARCH64_FEATURE (SME2)},
{"sme-tmop", AARCH64_FEATURE (SME_TMOP), AARCH64_FEATURE (SME2)},
{"sme-mop4", AARCH64_FEATURE (SME_MOP4), AARCH64_FEATURE (SME2)},
+ {"mops-go", AARCH64_FEATURE (MOPS_GO), AARCH64_FEATURE (MOPS)},
{NULL, AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
};
@@ -290,6 +290,8 @@ enum aarch64_feature_bit {
AARCH64_FEATURE_SVE2p1_SME2p1,
/* +sve2p2 or +sme2p2 */
AARCH64_FEATURE_SVE2p2_SME2p2,
+ /* +mops-go */
+ AARCH64_FEATURE_MOPS_GO,
AARCH64_NUM_FEATURES
};
@@ -27898,10 +27898,130 @@ aarch64_opcode_lookup_1 (uint32_t word)
{
if (((word >> 10) & 0x1) == 0)
{
- /* 33222222222211111111110000000000
- 10987654321098765432109876543210
- xx011101x1xxxxxxxxxxx0xxxxxxxxxx. */
- return A64_OPID_1d400800_ldapur_Ft_RCPC3_ADDR_OFFSET;
+ if (((word >> 11) & 0x1) == 0)
+ {
+ if (((word >> 12) & 0x1) == 0)
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxx000000xxxxxxxxxx. */
+ return A64_OPID_1ddf0000_setgop_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxx100000xxxxxxxxxx. */
+ return A64_OPID_1ddf8000_setgoe_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxxx10000xxxxxxxxxx. */
+ return A64_OPID_1ddf4000_setgom_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxx001000xxxxxxxxxx. */
+ return A64_OPID_1ddf2000_setgopn_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxx101000xxxxxxxxxx. */
+ return A64_OPID_1ddfa000_setgoen_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxxx11000xxxxxxxxxx. */
+ return A64_OPID_1ddf6000_setgomn_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ }
+ }
+ else
+ {
+ if (((word >> 13) & 0x1) == 0)
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxx000100xxxxxxxxxx. */
+ return A64_OPID_1ddf1000_setgopt_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxx100100xxxxxxxxxx. */
+ return A64_OPID_1ddf9000_setgoet_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxxx10100xxxxxxxxxx. */
+ return A64_OPID_1ddf5000_setgomt_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ }
+ else
+ {
+ if (((word >> 14) & 0x1) == 0)
+ {
+ if (((word >> 15) & 0x1) == 0)
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxx001100xxxxxxxxxx. */
+ return A64_OPID_1ddf3000_setgoptn_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxx101100xxxxxxxxxx. */
+ return A64_OPID_1ddfb000_setgoetn_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxxx11100xxxxxxxxxx. */
+ return A64_OPID_1ddf7000_setgomtn_MOPS_ADDR_Rd_MOPS_WB_Rn;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* 33222222222211111111110000000000
+ 10987654321098765432109876543210
+ xx011101x1xxxxxxxxxx10xxxxxxxxxx. */
+ return A64_OPID_1d400800_ldapur_Ft_RCPC3_ADDR_OFFSET;
+ }
}
else
{
@@ -5587,6 +5587,22 @@ verify_elem_sd (const struct aarch64_inst *inst, const aarch64_insn insn,
return ERR_OK;
}
+
+static enum err_type
+verify_three_different_regs_impl (int rx, int ry, int rz,
+ aarch64_operand_error *mismatch_detail,
+ const char *error)
+{
+ if (rx == ry || rx == rz || ry == rz)
+ {
+ mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
+ mismatch_detail->error = error;
+ mismatch_detail->index = -1;
+ return ERR_UND;
+ }
+ return ERR_OK;
+}
+
/* Check an instruction that takes three register operands and that
requires the register numbers to be distinct from one another. */
@@ -5595,8 +5611,7 @@ verify_three_different_regs (const struct aarch64_inst *inst,
const aarch64_insn insn ATTRIBUTE_UNUSED,
bfd_vma pc ATTRIBUTE_UNUSED,
bool encoding ATTRIBUTE_UNUSED,
- aarch64_operand_error *mismatch_detail
- ATTRIBUTE_UNUSED,
+ aarch64_operand_error *mismatch_detail,
aarch64_instr_sequence *insn_sequence
ATTRIBUTE_UNUSED)
{
@@ -5605,16 +5620,32 @@ verify_three_different_regs (const struct aarch64_inst *inst,
rd = inst->operands[0].reg.regno;
rs = inst->operands[1].reg.regno;
rn = inst->operands[2].reg.regno;
- if (rd == rs || rd == rn || rs == rn)
- {
- mismatch_detail->kind = AARCH64_OPDE_SYNTAX_ERROR;
- mismatch_detail->error
- = _("the three register operands must be distinct from one another");
- mismatch_detail->index = -1;
- return ERR_UND;
- }
- return ERR_OK;
+ return verify_three_different_regs_impl (rd, rs, rn, mismatch_detail,
+ _("the three register operands must be distinct from one another"));
+}
+
+
+/* Check an instruction that takes two register operands and that
+ requires the register numbers to be distinct from one another
+ and also different from 31. */
+
+static enum err_type
+verify_two_diff_regs_not_31 (const struct aarch64_inst *inst,
+ const aarch64_insn insn ATTRIBUTE_UNUSED,
+ bfd_vma pc ATTRIBUTE_UNUSED,
+ bool encoding ATTRIBUTE_UNUSED,
+ aarch64_operand_error *mismatch_detail,
+ aarch64_instr_sequence *insn_sequence
+ ATTRIBUTE_UNUSED)
+{
+ int rd, rn;
+
+ rd = inst->operands[0].reg.regno;
+ rn = inst->operands[1].reg.regno;
+
+ return verify_three_different_regs_impl (rd, rn, 31, mismatch_detail,
+ _("the two register operands must be distinct from each other"));
}
/* Add INST to the end of INSN_SEQUENCE. */
@@ -3395,6 +3395,18 @@ enum aarch64_opcode_idx
A64_OPID_1dc03400_setgptn_MOPS_ADDR_Rd_MOPS_WB_Rn_Rm,
A64_OPID_1dc07400_setgmtn_MOPS_ADDR_Rd_MOPS_WB_Rn_Rm,
A64_OPID_1dc0b400_setgetn_MOPS_ADDR_Rd_MOPS_WB_Rn_Rm,
+ A64_OPID_1ddf0000_setgop_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddf4000_setgom_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddf8000_setgoe_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddf1000_setgopt_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddf5000_setgomt_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddf9000_setgoet_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddf2000_setgopn_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddf6000_setgomn_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddfa000_setgoen_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddf3000_setgoptn_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddf7000_setgomtn_MOPS_ADDR_Rd_MOPS_WB_Rn,
+ A64_OPID_1ddfb000_setgoetn_MOPS_ADDR_Rd_MOPS_WB_Rn,
A64_OPID_54000010_bc_c_ADDR_PCREL19,
A64_OPID_11c00000_smax_Rd_Rn_CSSC_SIMM8,
A64_OPID_11c40000_umax_Rd_Rn_CSSC_UIMM8,
@@ -2927,6 +2927,8 @@ static const aarch64_feature_set aarch64_feature_mops =
AARCH64_FEATURE (MOPS);
static const aarch64_feature_set aarch64_feature_mops_memtag =
AARCH64_FEATURES (2, MOPS, MEMTAG);
+static const aarch64_feature_set aarch64_feature_mops_go_memtag =
+ AARCH64_FEATURES (2, MOPS_GO, MEMTAG);
static const aarch64_feature_set aarch64_feature_hbc =
AARCH64_FEATURE (HBC);
static const aarch64_feature_set aarch64_feature_cssc =
@@ -3116,6 +3118,7 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
#define WFXT &aarch64_feature_wfxt
#define MOPS &aarch64_feature_mops
#define MOPS_MEMTAG &aarch64_feature_mops_memtag
+#define MOPS_GO_MEMTAG &aarch64_feature_mops_go_memtag
#define HBC &aarch64_feature_hbc
#define CSSC &aarch64_feature_cssc
#define CHK &aarch64_feature_chk
@@ -3371,6 +3374,9 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
#define MOPS_MEMTAG_INSN(NAME, OPCODE, MASK, CLASS, OPS, QUALS, FLAGS, CONSTRAINTS, VERIFIER) \
{ NAME, OPCODE, MASK, CLASS, 0, MOPS_MEMTAG, OPS, QUALS, FLAGS, \
CONSTRAINTS, 0, VERIFIER }
+#define MOPS_GO_MEMTAG_INSN(NAME, OPCODE, MASK, CLASS, OPS, QUALS, FLAGS, CONSTRAINTS, VERIFIER) \
+ { NAME, OPCODE, MASK, CLASS, 0, MOPS_GO_MEMTAG, OPS, QUALS, FLAGS, \
+ CONSTRAINTS, 0, VERIFIER }
#define HBC_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
{ NAME, OPCODE, MASK, CLASS, 0, HBC, OPS, QUALS, FLAGS, 0, 0, NULL }
#define CSSC_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
@@ -3543,6 +3549,11 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
OP3 (MOPS_ADDR_Rd, MOPS_WB_Rn, Rm), QL_I3SAMEX, FLAGS, \
CONSTRAINTS, VERIFIER (three_different_regs))
+#define MOPS_GO_SET_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS, ISA) \
+ ISA (NAME, OPCODE, MASK, 0, \
+ OP2 (MOPS_ADDR_Rd, MOPS_WB_Rn), QL_I2SAMEX, FLAGS, \
+ CONSTRAINTS, VERIFIER (two_diff_regs_not_31))
+
/* These instructions must remain consecutive, since we rely on the order
when detecting invalid sequences. */
#define MOPS_SET_OP1_OP2_INSN(NAME, SUFFIX, OPCODE, MASK, ISA) \
@@ -3553,12 +3564,28 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
MOPS_SET_OP1_OP2_PME_INSN (NAME "e" SUFFIX, OPCODE | 0x8000, MASK, \
0, C_SCAN_MOPS_E, ISA)
+/* These instructions must remain consecutive, since we rely on the order
+ when detecting invalid sequences. */
+#define MOPS_GO_SET_OP1_OP2_INSN(NAME, SUFFIX, OPCODE, MASK, ISA) \
+ MOPS_GO_SET_OP1_OP2_PME_INSN (NAME "p" SUFFIX, OPCODE, MASK, \
+ F_SCAN, C_SCAN_MOPS_P, ISA), \
+ MOPS_GO_SET_OP1_OP2_PME_INSN (NAME "m" SUFFIX, OPCODE | 0x4000, MASK, \
+ 0, C_SCAN_MOPS_M, ISA), \
+ MOPS_GO_SET_OP1_OP2_PME_INSN (NAME "e" SUFFIX, OPCODE | 0x8000, MASK, \
+ 0, C_SCAN_MOPS_E, ISA)
+
#define MOPS_SET_INSN(NAME, OPCODE, MASK, ISA) \
MOPS_SET_OP1_OP2_INSN (NAME, "", OPCODE, MASK, ISA), \
MOPS_SET_OP1_OP2_INSN (NAME, "t", OPCODE | 0x1000, MASK, ISA), \
MOPS_SET_OP1_OP2_INSN (NAME, "n", OPCODE | 0x2000, MASK, ISA), \
MOPS_SET_OP1_OP2_INSN (NAME, "tn", OPCODE | 0x3000, MASK, ISA)
+#define MOPS_GO_SET_INSN(NAME, OPCODE, MASK, ISA) \
+ MOPS_GO_SET_OP1_OP2_INSN (NAME, "", OPCODE, MASK, ISA), \
+ MOPS_GO_SET_OP1_OP2_INSN (NAME, "t", OPCODE | 0x1000, MASK, ISA), \
+ MOPS_GO_SET_OP1_OP2_INSN (NAME, "n", OPCODE | 0x2000, MASK, ISA), \
+ MOPS_GO_SET_OP1_OP2_INSN (NAME, "tn", OPCODE | 0x3000, MASK, ISA)
+
#define PREDRES2_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
{ NAME, OPCODE, MASK, CLASS, 0, PREDRES2, OPS, QUALS, FLAGS, 0, 0, NULL }
@@ -7031,6 +7058,11 @@ const struct aarch64_opcode aarch64_opcode_table[] =
setge setget setgen setgetn */
MOPS_SET_INSN ("setg", 0x1dc00400, 0xffe0fc00, MOPS_MEMTAG_INSN),
+ /* setgop setgopt setgopn setgoptn
+ setgom setgomt setgomn setgomtn
+ setgoe setgoet setgoen setgoetn */
+ MOPS_GO_SET_INSN ("setgo", 0x1ddf0000, 0x3ffffc00, MOPS_GO_MEMTAG_INSN),
+
HBC_INSN ("bc.c", 0x54000010, 0xff000010, condbranch, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_COND),
/* CSSC with immediates. */