[PATCH] aarch64: Add support for FEAT_CMH
Alice Carlotti
alice.carlotti@arm.com
Wed Jan 14 04:39:36 GMT 2026
On Fri, Jan 09, 2026 at 11:42:52AM +0000, richard.ball@arm.com wrote:
> From: Richard Ball <Richard.Ball@arm.com>
>
> This patch adds the new instructions from FEAT_CMH
> These new instructions are hints, STCPH and SHUH.
> SHUH can have an operand PH or no operand.
> ---
> gas/config/tc-aarch64.c | 6 +++++-
> gas/testsuite/gas/aarch64/cmh-bad.d | 4 ++++
> gas/testsuite/gas/aarch64/cmh-bad.l | 3 +++
> gas/testsuite/gas/aarch64/cmh-bad.s | 3 +++
> gas/testsuite/gas/aarch64/cmh.d | 11 +++++++++++
> gas/testsuite/gas/aarch64/cmh.s | 4 ++++
> gas/testsuite/gas/aarch64/system.d | 6 +++---
> include/opcode/aarch64.h | 2 ++
> opcodes/aarch64-asm-2.c | 3 +++
> opcodes/aarch64-dis-2.c | 7 +++++++
> opcodes/aarch64-opc-2.c | 1 +
> opcodes/aarch64-opc.c | 8 ++++++++
> opcodes/aarch64-opc.h | 3 +++
> opcodes/aarch64-tbl-2.h | 2 ++
> opcodes/aarch64-tbl.h | 4 ++++
> 15 files changed, 63 insertions(+), 4 deletions(-)
> create mode 100644 gas/testsuite/gas/aarch64/cmh-bad.d
> create mode 100644 gas/testsuite/gas/aarch64/cmh-bad.l
> create mode 100644 gas/testsuite/gas/aarch64/cmh-bad.s
> create mode 100644 gas/testsuite/gas/aarch64/cmh.d
> create mode 100644 gas/testsuite/gas/aarch64/cmh.s
>
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index 6a03dfe41ec..e768625062a 100644
> --- a/gas/config/tc-aarch64.c
> +++ b/gas/config/tc-aarch64.c
> @@ -4618,7 +4618,9 @@ parse_hint_opt (const char *name, char **str,
> && (o->value != HINT_OPD_C && o->value != HINT_OPD_J
> && o->value != HINT_OPD_JC && o->value != HINT_OPD_R))
> || ((strcmp ("stshh", name) == 0)
> - && (o->value != HINT_OPD_KEEP && o->value != HINT_OPD_STRM)))
> + && (o->value != HINT_OPD_KEEP && o->value != HINT_OPD_STRM))
> + || ((strcmp ("shuh", name) == 0)
> + && (o->value != HINT_OPD_PHINT)))
> return false;
>
> *str = q;
> @@ -6435,6 +6437,7 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
> break;
>
> case AARCH64_OPND_BTI_TARGET:
> + case AARCH64_OPND_SHUH_PHINT:
> operand->hint_option = aarch64_hint_options + default_value;
> break;
>
> @@ -8308,6 +8311,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
> break;
>
> case AARCH64_OPND_BTI_TARGET:
> + case AARCH64_OPND_SHUH_PHINT:
> if (!parse_hint_opt (opcode->name, &str, &(info->hint_option)))
> goto failure;
> break;
> diff --git a/gas/testsuite/gas/aarch64/cmh-bad.d b/gas/testsuite/gas/aarch64/cmh-bad.d
> new file mode 100644
> index 00000000000..c68620add61
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmh-bad.d
> @@ -0,0 +1,4 @@
> +#name: Negative test of CMH instructions.
> +#as: -march=armv8-a
> +#source: cmh-bad.s
> +#error_output: cmh-bad.l
> diff --git a/gas/testsuite/gas/aarch64/cmh-bad.l b/gas/testsuite/gas/aarch64/cmh-bad.l
> new file mode 100644
> index 00000000000..303fb28829e
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmh-bad.l
> @@ -0,0 +1,3 @@
> +[^ :]+: Assembler messages:
> +[^ :]+:[0-9]+: Error: operand 1 must be a priority hint \(ph\) -- `shuh p'
> +[^ :]+:[0-9]+: Error: unexpected characters following instruction -- `stcph ph'
> diff --git a/gas/testsuite/gas/aarch64/cmh-bad.s b/gas/testsuite/gas/aarch64/cmh-bad.s
> new file mode 100644
> index 00000000000..eed46a4ff06
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmh-bad.s
> @@ -0,0 +1,3 @@
> +a:
> + shuh p
> + stcph ph
> diff --git a/gas/testsuite/gas/aarch64/cmh.d b/gas/testsuite/gas/aarch64/cmh.d
> new file mode 100644
> index 00000000000..3a9f143cbde
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmh.d
> @@ -0,0 +1,11 @@
> +#as: -march=armv8-a
> +#objdump: -dr
> +
> +.*: file format .*
> +
> +Disassembly of section \.text:
> +
> +0+ <.*>:
> +.*: d503265f shuh
> +.*: d503267f shuh ph
> +.*: d503269f stcph
> diff --git a/gas/testsuite/gas/aarch64/cmh.s b/gas/testsuite/gas/aarch64/cmh.s
> new file mode 100644
> index 00000000000..0045c8ade17
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/cmh.s
> @@ -0,0 +1,4 @@
> +a:
> + shuh
> + shuh ph
> + stcph
> diff --git a/gas/testsuite/gas/aarch64/system.d b/gas/testsuite/gas/aarch64/system.d
> index 6d90420d539..11498317e66 100644
> --- a/gas/testsuite/gas/aarch64/system.d
> +++ b/gas/testsuite/gas/aarch64/system.d
> @@ -68,9 +68,9 @@ Disassembly of section \.text:
> .*: d50325ff hint #0x2f
> .*: d503261f (hint #0x30|stshh keep)
> .*: d503263f (hint #0x31|stshh strm)
> -.*: d503265f hint #0x32
> -.*: d503267f hint #0x33
> -.*: d503269f hint #0x34
> +.*: d503265f (hint #0x32|shuh)
> +.*: d503267f (hint #0x33|shuh ph)
> +.*: d503269f (hint #0x34|stcph)
> .*: d50326bf hint #0x35
> .*: d50326df hint #0x36
> .*: d50326ff hint #0x37
> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index b885a06f526..27fad8d1095 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -759,6 +759,7 @@ enum aarch64_opnd
> AARCH64_OPND_BARRIER_GCSB, /* Barrier operand for GCSB. */
> AARCH64_OPND_BTI_TARGET, /* BTI {<target>}. */
> AARCH64_OPND_STSHH_POLICY, /* STSHH {<policy>}. */
> + AARCH64_OPND_SHUH_PHINT, /* SHUH Priority Hint. */
> AARCH64_OPND_BRBOP, /* BRB operation IALL or INJ in bit 5. */
> AARCH64_OPND_Rt_IN_SYS_ALIASES, /* Defaulted and omitted Rt used in SYS aliases such as brb. */
> AARCH64_OPND_LSE128_Rt, /* LSE128 <Xt1>. */
> @@ -1890,6 +1891,7 @@ struct aarch64_inst
> #define HINT_OPD_JC 0x26
> #define HINT_OPD_KEEP 0x30
> #define HINT_OPD_STRM 0x31
> +#define HINT_OPD_PHINT 0x33
> #define HINT_OPD_NULL 0x00
>
>
> diff --git a/opcodes/aarch64-asm-2.c b/opcodes/aarch64-asm-2.c
> index ca2c939d5b2..8e8cbf43d18 100644
> --- a/opcodes/aarch64-asm-2.c
> +++ b/opcodes/aarch64-asm-2.c
> @@ -543,6 +543,8 @@ aarch64_find_real_opcode (const aarch64_opcode *opcode)
> case A64_OPID_d503241f_bti_BTI_TARGET:
> case A64_OPID_d503229f_csdb:
> case A64_OPID_d503201f_nop:
> + case A64_OPID_d503265f_shuh_SHUH_PHINT:
> + case A64_OPID_d503269f_stcph:
> case A64_OPID_d503261f_stshh_STSHH_POLICY:
> case A64_OPID_d503201f_hint_UIMM7:
> value = A64_OPID_d503201f_hint_UIMM7;
> @@ -1035,6 +1037,7 @@ aarch64_insert_operand (const aarch64_operand *self,
> return aarch64_ins_prfop (self, info, code, inst, errors);
> case AARCH64_OPND_BTI_TARGET:
> case AARCH64_OPND_STSHH_POLICY:
> + case AARCH64_OPND_SHUH_PHINT:
> return aarch64_ins_hint (self, info, code, inst, errors);
> case AARCH64_OPND_SVE_ADDR_RI_S4x16:
> case AARCH64_OPND_SVE_ADDR_RI_S4x32:
> diff --git a/opcodes/aarch64-dis-2.c b/opcodes/aarch64-dis-2.c
> index 9dcb83fefac..9aeb3df19b2 100644
> --- a/opcodes/aarch64-dis-2.c
> +++ b/opcodes/aarch64-dis-2.c
> @@ -37534,6 +37534,12 @@ aarch64_find_next_alias_opcode (const aarch64_opcode *opcode)
> value = A64_OPID_d503201f_nop;
> break;
> case A64_OPID_d503201f_nop:
> + value = A64_OPID_d503265f_shuh_SHUH_PHINT;
> + break;
> + case A64_OPID_d503265f_shuh_SHUH_PHINT:
> + value = A64_OPID_d503269f_stcph;
> + break;
> + case A64_OPID_d503269f_stcph:
> value = A64_OPID_d503261f_stshh_STSHH_POLICY;
> break;
> case A64_OPID_d503261f_stshh_STSHH_POLICY:
> @@ -38017,6 +38023,7 @@ aarch64_extract_operand (const aarch64_operand *self,
> return aarch64_ext_prfop (self, info, code, inst, errors);
> case AARCH64_OPND_BTI_TARGET:
> case AARCH64_OPND_STSHH_POLICY:
> + case AARCH64_OPND_SHUH_PHINT:
> return aarch64_ext_hint (self, info, code, inst, errors);
> case AARCH64_OPND_SVE_ADDR_RI_S4x16:
> case AARCH64_OPND_SVE_ADDR_RI_S4x32:
> diff --git a/opcodes/aarch64-opc-2.c b/opcodes/aarch64-opc-2.c
> index 4f447aef78f..0456c267066 100644
> --- a/opcodes/aarch64-opc-2.c
> +++ b/opcodes/aarch64-opc-2.c
> @@ -154,6 +154,7 @@ const struct aarch64_operand aarch64_operands[] =
> {AARCH64_OPND_CLASS_SYSTEM, "BARRIER_GCSB", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "the GCSB option name DSYNC"},
> {AARCH64_OPND_CLASS_SYSTEM, "BTI_TARGET", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "BTI targets r/j/c/jc"},
> {AARCH64_OPND_CLASS_SYSTEM, "STSHH_POLICY", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "an STSHH policy (keep/strm)"},
> + {AARCH64_OPND_CLASS_SYSTEM, "SHUH_PHINT", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {}, "a priority hint (ph)"},
> {AARCH64_OPND_CLASS_SYSTEM, "BRBOP", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_brbop}, "Branch Record Buffer operation operand"},
> {AARCH64_OPND_CLASS_INT_REG, "Rt_IN_SYS_ALIASES", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rt}, "Rt register with defaults for SYS aliases"},
> {AARCH64_OPND_CLASS_INT_REG, "LSE128_Rt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_LSE128_Rt}, "an integer register"},
> diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
> index e4ce347bdc9..e033151deda 100644
> --- a/opcodes/aarch64-opc.c
> +++ b/opcodes/aarch64-opc.c
> @@ -599,6 +599,7 @@ const struct aarch64_name_value_pair aarch64_hint_options[] =
> {
> /* BTI. This is also the F_DEFAULT entry for AARCH64_OPND_BTI_TARGET. */
> { "r", HINT_OPD_R }, /* BTI R. */
> + { " ", HINT_ENCODE (HINT_OPD_F_NOPRINT, 0x32) }, /* SHUH. */
> { "csync", HINT_OPD_CSYNC }, /* PSB CSYNC. */
> { "dsync", HINT_OPD_DSYNC }, /* GCSB DSYNC. */
> { "c", HINT_OPD_C }, /* BTI C. */
> @@ -606,6 +607,7 @@ const struct aarch64_name_value_pair aarch64_hint_options[] =
> { "jc", HINT_OPD_JC }, /* BTI JC. */
> { "keep", HINT_OPD_KEEP }, /* STSHH KEEP */
> { "strm", HINT_OPD_STRM }, /* STSHH STRM */
> + { "ph", HINT_OPD_PHINT }, /* SHUH PH. */
> { NULL, HINT_OPD_NULL },
> };
>
> @@ -5178,6 +5180,12 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
> snprintf (buf, size, "%s", style_sub_mnem (styler, opnd->hint_option->name));
> break;
>
> + case AARCH64_OPND_SHUH_PHINT:
> + if ((HINT_FLAG (opnd->hint_option->value) & HINT_OPD_F_NOPRINT) == 0)
> + snprintf (buf, size, "%s",
> + style_sub_mnem (styler, opnd->hint_option->name));
> + break;
> +
> case AARCH64_OPND_MOPS_ADDR_Rd:
> case AARCH64_OPND_MOPS_ADDR_Rs:
> snprintf (buf, size, "[%s]!",
> diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h
> index a612c3a3db9..57eb7198538 100644
> --- a/opcodes/aarch64-opc.h
> +++ b/opcodes/aarch64-opc.h
> @@ -392,6 +392,9 @@ verify_constraints (const struct aarch64_inst *, const aarch64_insn, bfd_vma,
> #define F_REG_MAX_VALUE(X) ((X) << 15)
> #define F_GET_REG_MAX_VALUE(X) (((X) >> 15) & 0x0f)
>
> +/* HINT operand flags. */
> +#define HINT_OPD_F_NOPRINT (1 << 0) /* Should not be printed. */
> +
Rather than reintroducing this flag, can we instead use an empty string in the table and test for that?
> /* Encode 7-bit HINT #imm in the lower 8 bits. Use higher bits for flags. */
> #define HINT_ENCODE(flag, val) ((flag << 8) | val)
> #define HINT_FLAG(val) (val >> 8)
> diff --git a/opcodes/aarch64-tbl-2.h b/opcodes/aarch64-tbl-2.h
> index e9bc188c69f..64e79d709d5 100644
> --- a/opcodes/aarch64-tbl-2.h
> +++ b/opcodes/aarch64-tbl-2.h
> @@ -1368,6 +1368,8 @@ enum aarch64_opcode_idx
> A64_OPID_d503407f_smstop_SME_SM_ZA,
> A64_OPID_d503251f_chkfeat_X16,
> A64_OPID_d503261f_stshh_STSHH_POLICY,
> + A64_OPID_d503269f_stcph,
> + A64_OPID_d503265f_shuh_SHUH_PHINT,
> A64_OPID_d500401f_msr_PSTATEFIELD_UIMM4,
> A64_OPID_d503201f_hint_UIMM7,
> A64_OPID_d503201f_nop,
> diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
> index 82b3e9dd2ce..3f0d82a1ee9 100644
> --- a/opcodes/aarch64-tbl.h
> +++ b/opcodes/aarch64-tbl.h
> @@ -5098,6 +5098,8 @@ const struct aarch64_opcode aarch64_opcode_table[] =
> /* System. */
> CHK_INSN ("chkfeat", 0xd503251f, 0xffffffff, OP1 (X16), QL_I1X, 0),
> CORE_INSN ("stshh", 0xd503261f, 0xffffffdf, ic_system, 0, OP1 (STSHH_POLICY), {}, F_ALIAS),
> + CORE_INSN ("stcph", 0xd503269f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
> + CORE_INSN ("shuh", 0xd503265f, 0xffffffdf, ic_system, 0, OP1 (SHUH_PHINT), {}, F_ALIAS | F_OPD0_OPT | F_DEFAULT (0x0)),
This F_DEFAULT value is used to reference an entry in the aarch64_hint_options
array. The zeroth entry is for BTI R. It happens to give the correct encoding
in this case, because BTI R is hint #0x20, which is a subset of the bits in
used in hint #0x32 (SHUH).
This whole way we handle hint instructions is quite messy, but fixing that
isn't a job for days before the branch. So for now I'd suggest making this
F_DEFAULT (0x1), and adding comments to the table stating that "bti r" and
"shuh" need to be the first and second entries to match the F_DEFAULT values.
> CORE_INSN ("msr", 0xd500401f, 0xfff8f01f, ic_system, 0, OP2 (PSTATEFIELD, UIMM4), {}, F_SYS_WRITE),
> CORE_INSN ("hint",0xd503201f, 0xfffff01f, ic_system, 0, OP1 (UIMM7), {}, F_HAS_ALIAS),
> CORE_INSN ("nop", 0xd503201f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
> @@ -8162,6 +8164,8 @@ const struct aarch64_opcode aarch64_opcode_table[] =
> "BTI targets r/j/c/jc") \
> Y(SYSTEM, hint, "STSHH_POLICY", 0, F(), \
> "an STSHH policy (keep/strm)") \
> + Y(SYSTEM, hint, "SHUH_PHINT", 0, F(), \
> + "a priority hint (ph)") \
I think the error message would be slightly better with the word "optional"
added - i.e. "an optional priority hint (ph)".
> Y(SYSTEM, imm, "BRBOP", 0, F(FLD_brbop), \
> "Branch Record Buffer operation operand") \
> Y(INT_REG, regno, "Rt_IN_SYS_ALIASES", 0, F(FLD_Rt), \
> --
> 2.34.1
>
More information about the Binutils
mailing list