[PATCH v2] AArch64 v9.7 extensions: FEAT_F16MM

Alice Carlotti alice.carlotti@arm.com
Fri Dec 19 16:28:45 GMT 2025


On Wed, Dec 17, 2025 at 05:22:55PM +0000, Sivan Shani wrote:
> This patch includes:
>   - Feature flag for FEAT_F16MM
>   - Instructions:
> 	- FMMLA (non-widening) Half-precision matrix multiply-accumulate
> 	- FMMLA (non-widening) Floating-point matrix multiply-accumulate
> ---
>  gas/config/tc-aarch64.c                  |  1 +
>  gas/doc/c-aarch64.texi                   |  2 ++
>  gas/testsuite/gas/aarch64/f16mm-simd.d   | 12 +++++++
>  gas/testsuite/gas/aarch64/f16mm-simd.s   |  4 +++
>  gas/testsuite/gas/aarch64/f16mm-sve2p2.d | 12 +++++++
>  gas/testsuite/gas/aarch64/f16mm-sve2p2.s |  4 +++
>  include/opcode/aarch64.h                 |  2 ++
>  opcodes/aarch64-dis-2.c                  | 42 +++++++++++++++++-------
>  opcodes/aarch64-tbl-2.h                  |  2 ++
>  opcodes/aarch64-tbl.h                    | 20 +++++++++++
>  10 files changed, 90 insertions(+), 11 deletions(-)
>  create mode 100644 gas/testsuite/gas/aarch64/f16mm-simd.d
>  create mode 100644 gas/testsuite/gas/aarch64/f16mm-simd.s
>  create mode 100644 gas/testsuite/gas/aarch64/f16mm-sve2p2.d
>  create mode 100644 gas/testsuite/gas/aarch64/f16mm-sve2p2.s
> 
> diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
> index 0ca54c3bd40..598b45c5199 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)},
> +  {"f16mm",		AARCH64_FEATURE (F16MM), AARCH64_FEATURE (SIMD)},

This should also depend upon fp16.

>    {NULL,		AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
>  };
>  
> diff --git a/gas/doc/c-aarch64.texi b/gas/doc/c-aarch64.texi
> index 9683d411ce9..269d8e8d3d6 100644
> --- a/gas/doc/c-aarch64.texi
> +++ b/gas/doc/c-aarch64.texi
> @@ -219,6 +219,8 @@ automatically cause those extensions to be disabled.
>   @tab Enable Armv8.2 16-bit floating-point multiplication variant support.
>  @item @code{fp16} @tab @code{fp}
>   @tab Enable Armv8.2 16-bit floating-point support.
> +@item @code{f16mm} @tab @code{simd}
> + @tab Enable support f16mm instructions.

(update to add fp16 dependency)

>  @item @code{fprcvt} @tab @code{fp}
>   @tab Enable Armv9.6 fprcvt instructions.
>  @item @code{frintts} @tab @code{fp}
> diff --git a/gas/testsuite/gas/aarch64/f16mm-simd.d b/gas/testsuite/gas/aarch64/f16mm-simd.d
> new file mode 100644
> index 00000000000..0643339af61
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/f16mm-simd.d
> @@ -0,0 +1,12 @@
> +#as: -march=armv8-a+f16mm
> +#objdump: -dr
> +
> +.*:     file format .*
> +
> +Disassembly of section \.text:
> +
> +0+ <\.text>:
> + *[0-9a-f]+:	4ec0ec00 	fmmla	v0.8h, v0.8h, v0.8h
> + *[0-9a-f]+:	4ec0ec1f 	fmmla	v31.8h, v0.8h, v0.8h
> + *[0-9a-f]+:	4ec0efe0 	fmmla	v0.8h, v31.8h, v0.8h
> + *[0-9a-f]+:	4edfec00 	fmmla	v0.8h, v0.8h, v31.8h
> diff --git a/gas/testsuite/gas/aarch64/f16mm-simd.s b/gas/testsuite/gas/aarch64/f16mm-simd.s
> new file mode 100644
> index 00000000000..359cc207e23
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/f16mm-simd.s
> @@ -0,0 +1,4 @@
> +fmmla v0.8h,v0.8h, v0.8h
> +fmmla v31.8h,v0.8h, v0.8h
> +fmmla v0.8h,v31.8h, v0.8h
> +fmmla v0.8h,v0.8h, v31.8h
> diff --git a/gas/testsuite/gas/aarch64/f16mm-sve2p2.d b/gas/testsuite/gas/aarch64/f16mm-sve2p2.d
> new file mode 100644
> index 00000000000..d4d4a524399
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/f16mm-sve2p2.d
> @@ -0,0 +1,12 @@
> +#as: -march=armv8-a+sve2p2+f16mm
> +#objdump: -dr
> +
> +.*:     file format .*
> +
> +Disassembly of section \.text:
> +
> +0+ <\.text>:
> + *[0-9a-f]+:	64a0e000 	fmmla	z0.h, z0.h, z0.h
> + *[0-9a-f]+:	64a0e01f 	fmmla	z31.h, z0.h, z0.h
> + *[0-9a-f]+:	64a0e3e0 	fmmla	z0.h, z31.h, z0.h
> + *[0-9a-f]+:	64bfe000 	fmmla	z0.h, z0.h, z31.h
> diff --git a/gas/testsuite/gas/aarch64/f16mm-sve2p2.s b/gas/testsuite/gas/aarch64/f16mm-sve2p2.s
> new file mode 100644
> index 00000000000..59ec90a8961
> --- /dev/null
> +++ b/gas/testsuite/gas/aarch64/f16mm-sve2p2.s
> @@ -0,0 +1,4 @@
> +fmmla z0.h, z0.h, z0.h
> +fmmla z31.h, z0.h, z0.h
> +fmmla z0.h, z31.h, z0.h
> +fmmla z0.h, z0.h, z31.h
> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
> index e65b61c3f9c..5a8e14898f6 100644
> --- a/include/opcode/aarch64.h
> +++ b/include/opcode/aarch64.h
> @@ -263,6 +263,8 @@ enum aarch64_feature_bit {
>    AARCH64_FEATURE_SME_TMOP,
>    /* SME MOP4 instructions.  */
>    AARCH64_FEATURE_SME_MOP4,
> +  /* F16MM instructions.  */
> +  AARCH64_FEATURE_F16MM,
>  
>    /* Virtual features.  These are used to gate instructions that are enabled
>       by either of two (or more) sets of command line flags.  */
> diff --git a/opcodes/aarch64-dis-2.c b/opcodes/aarch64-dis-2.c
> index ecaea2d2fdb..faeb72d1e7a 100644
> --- a/opcodes/aarch64-dis-2.c
> +++ b/opcodes/aarch64-dis-2.c
> @@ -20079,10 +20079,20 @@ aarch64_opcode_lookup_1 (uint32_t word)
>                                                  {
>                                                    if (((word >> 31) & 0x1) == 0)
>                                                      {
> -                                                      /* 33222222222211111111110000000000
> -                                                         10987654321098765432109876543210
> -                                                         011001x0101xxxxx111xxxxxxxxxxxxx.  */
> -                                                      return A64_OPID_64a0e400_fmmla_SVE_Zd_SVE_Zn_SVE_Zm_16;
> +                                                      if (((word >> 10) & 0x1) == 0)
> +                                                        {
> +                                                          /* 33222222222211111111110000000000
> +                                                             10987654321098765432109876543210
> +                                                             011001x0101xxxxx111xx0xxxxxxxxxx.  */
> +                                                          return A64_OPID_64a0e000_fmmla_SVE_Zd_SVE_Zn_SVE_Zm_16;
> +                                                        }
> +                                                      else
> +                                                        {
> +                                                          /* 33222222222211111111110000000000
> +                                                             10987654321098765432109876543210
> +                                                             011001x0101xxxxx111xx1xxxxxxxxxx.  */
> +                                                          return A64_OPID_64a0e400_fmmla_SVE_Zd_SVE_Zn_SVE_Zm_16;
> +                                                        }
>                                                      }
>                                                    else
>                                                      {
> @@ -28523,19 +28533,29 @@ aarch64_opcode_lookup_1 (uint32_t word)
>                                                  }
>                                                else
>                                                  {
> -                                                  if (((word >> 15) & 0x1) == 0)
> +                                                  if (((word >> 14) & 0x1) == 0)
>                                                      {
> -                                                      /* 33222222222211111111110000000000
> -                                                         10987654321098765432109876543210
> -                                                         0x001110xx0xxxxx0x1011xxxxxxxxxx.  */
> -                                                      return A64_OPID_0e002c00_smov_Rd_En;
> +                                                      if (((word >> 15) & 0x1) == 0)
> +                                                        {
> +                                                          /* 33222222222211111111110000000000
> +                                                             10987654321098765432109876543210
> +                                                             0x001110xx0xxxxx001011xxxxxxxxxx.  */
> +                                                          return A64_OPID_0e002c00_smov_Rd_En;
> +                                                        }
> +                                                      else
> +                                                        {
> +                                                          /* 33222222222211111111110000000000
> +                                                             10987654321098765432109876543210
> +                                                             0x001110xx0xxxxx101011xxxxxxxxxx.  */
> +                                                          return A64_OPID_4e80ac00_usmmla_Vd_Vn_Vm;
> +                                                        }
>                                                      }
>                                                    else
>                                                      {
>                                                        /* 33222222222211111111110000000000
>                                                           10987654321098765432109876543210
> -                                                         0x001110xx0xxxxx1x1011xxxxxxxxxx.  */
> -                                                      return A64_OPID_4e80ac00_usmmla_Vd_Vn_Vm;
> +                                                         0x001110xx0xxxxxx11011xxxxxxxxxx.  */
> +                                                      return A64_OPID_4ec0ec00_fmmla_Vd_Vn_Vm;
>                                                      }
>                                                  }
>                                              }
> diff --git a/opcodes/aarch64-tbl-2.h b/opcodes/aarch64-tbl-2.h
> index 1263f1f9bd8..bf03106ca6b 100644
> --- a/opcodes/aarch64-tbl-2.h
> +++ b/opcodes/aarch64-tbl-2.h
> @@ -3995,5 +3995,7 @@ enum aarch64_opcode_idx
>    A64_OPID_a1c00018_usmop4s_SME_ZAda_3b_SME_Zn_6_3_SME_Zm_17_3,
>    A64_OPID_a1c00218_usmop4s_SME_ZAda_3b_SME_Znx2_6_3_SME_Zm_17_3,
>    A64_OPID_a1d00218_usmop4s_SME_ZAda_3b_SME_Znx2_6_3_SME_Zmx2_17_3,
> +  A64_OPID_4ec0ec00_fmmla_Vd_Vn_Vm,
> +  A64_OPID_64a0e000_fmmla_SVE_Zd_SVE_Zn_SVE_Zm_16,
>    A64_OPID_MAX,
>  };
> diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
> index e7b17061d82..453e44e3206 100644
> --- a/opcodes/aarch64-tbl.h
> +++ b/opcodes/aarch64-tbl.h
> @@ -2808,6 +2808,12 @@
>  {		      \
>    QLF3(V_4S, V_8H, S_H),	\
>  }
> +
> +/* e.g. FMMLA <Vd>.8s, <Vn>.8h, <Vm>.8h */
> +#define QL_VF16      \
> +{		      \
> +  QLF3 (V_8H, V_8H, V_8H),	\
> +}

Naming this QL_V3SAME8H would be more consistent with existing naming
patterns (and is a more precise name as well).

Ok with these changes, thanks.

>  
>  /* Opcode table.  */
>  
> @@ -3057,6 +3063,10 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_f8f32 =
>    AARCH64_FEATURES (2, SME_MOP4, SME_F8F32);
>  static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
>    AARCH64_FEATURES (2, SME_MOP4, SME_I16I64);
> +static const aarch64_feature_set aarch64_feature_f16mm =
> +  AARCH64_FEATURE (F16MM);
> +static const aarch64_feature_set aarch64_feature_f16mm_sve2p2 =
> +  AARCH64_FEATURES (2, F16MM, SVE2p2);
>  
>  #define CORE		&aarch64_feature_v8
>  #define FP		&aarch64_feature_fp
> @@ -3181,6 +3191,8 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
>  #define SME_MOP4_F8F16	&aarch64_feature_sme_mop4_f8f16
>  #define SME_MOP4_F8F32	&aarch64_feature_sme_mop4_f8f32
>  #define SME_MOP4_I16I64	&aarch64_feature_sme_mop4_i16i64
> +#define F16MM	&aarch64_feature_f16mm
> +#define F16MM_SVE2p2	&aarch64_feature_f16mm_sve2p2
>  
>  #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
>    { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS | F_INVALID_IMM_SYMS_1, 0, 0, NULL }
> @@ -3510,6 +3522,10 @@ static const aarch64_feature_set aarch64_feature_sme_mop4_i16i64 =
>  #define SME_MOP4_I16I64_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS,TIED) \
>    { NAME, OPCODE, MASK, CLASS, 0, SME_MOP4_I16I64, OPS, QUALS, \
>      FLAGS | F_STRICT, 0, TIED, NULL }
> +#define F16MM_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
> +  { NAME, OPCODE, MASK, CLASS, 0, F16MM, OPS, QUALS, FLAGS, 0, 0, NULL }
> +#define F16MM_SVE2p2_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \
> +  { NAME, OPCODE, MASK, CLASS, 0, F16MM, OPS, QUALS, FLAGS | F_STRICT, 0, 0, NULL }
>  
>  #define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \
>    MOPS_INSN (NAME, OPCODE, MASK, 0, \
> @@ -7738,6 +7754,10 @@ const struct aarch64_opcode aarch64_opcode_table[] =
>    SME_MOP4_I16I64_INSN ("usmop4s", 0xa1c00218, 0xfff1fe38, sme_misc, OP3 (SME_ZAda_3b, SME_Znx2_6_3, SME_Zm_17_3), OP_SVE_DHH, 0, 0),
>    SME_MOP4_I16I64_INSN ("usmop4s", 0xa1d00218, 0xfff1fe38, sme_misc, OP3 (SME_ZAda_3b, SME_Znx2_6_3, SME_Zmx2_17_3), OP_SVE_DHH, 0, 0),
>  
> +  /* F16MM instructions.  */
> +  F16MM_INSN ("fmmla", 0x4ec0ec00, 0xffe0fc00, asimdmisc, OP3 (Vd, Vn, Vm), QL_VF16, 0),
> +  F16MM_SVE2p2_INSN ("fmmla", 0x64a0e000, 0xffe0fc00, sve_misc, OP3 (SVE_Zd, SVE_Zn, SVE_Zm_16), OP_SVE_HHH, 0),
> +
>    {0, 0, 0, 0, 0, 0, {}, {}, 0, 0, 0, NULL},
>  };
>  
> -- 
> 2.43.0
> 


More information about the Binutils mailing list