[v1,2/2] Support x86 ACE ISA

Message ID 20260627115338.1632761-1-Ganesh.Gopalasubramanian@amd.com
State New
Headers
Series Support AVX10_V2_AUX and x86 ACE ISA |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm fail Patch failed to apply

Commit Message

Ganesh Gopalasubramanian June 27, 2026, 11:53 a.m. UTC
  Adds assembler and disassembler support for ACE tile, block scale
register, outer product, and MX FP8/INT8/BF16 instructions including:
bsrinit, bsrmovf/h/l, tilemovcol, tilemovrow, top2bf16ps, top4bssd/bsud/
busd/buud, and top4mx* variants.

All ACE v1 instructions are enumerated under a single ACE feature flag
(CPUID.(EAX=07H,ECX=1):ECX[11]), matching the specification.

Key changes:
- opcodes/i386-opc.tbl: ACE instruction definitions with EVexMap6 macro
- opcodes/i386-gen.c: single ACE CPU feature and RegBS register class
- opcodes/i386-dis*.h: Disassembler dispatch tables for MAP6, 0F3A, 0F38
- gas/config/tc-i386.c: ACE operand validation with proper scoping to
  avoid interfering with AMX-AVX512 tilemovrow/tilemovcol variants
- gas/testsuite: ACE instruction test case

The generated tables (opcodes/i386-init.h, opcodes/i386-mnem.h and
opcodes/i386-tbl.h) are omitted from this mail to keep it within the
list size limit; they are regenerated from opcodes/i386-opc.tbl and
opcodes/i386-reg.tbl by i386-gen and are reflected in the diffstat.

Reference: AI Compute Extensions (ACE) Specification, v1.15
https://x86ecosystem.org/wp-content/uploads/2026/06/ACE_v1_Specification_public_1_15.pdf

gas/ChangeLog:

	* NEWS: Mention x86 ACE instruction support.
	* config/tc-i386.c (enum i386_error): Add unsupported_tile_index.
	(cpu_arch): Add ace.
	(_is_cpu): Handle CpuACE.
	(type_names): Add RegBS ("bsr") entry.
	(install_template): Handle CpuACE.
	(i386_assemble): Handle unsupported_tile_index.
	(check_ACE_operands): New function.
	(match_template): Call check_ACE_operands.
	(process_operands): Handle bsrinit like tilezero.
	(output_insn): Set GNU_PROPERTY_X86_FEATURE_2_TMM for ACE.
	(check_register): Allow TMM registers and the block scale
	register for ACE.
	* doc/c-i386.texi: Document .ace.
	* testsuite/gas/i386/x86-64.exp: Run ACE tests.
	* testsuite/gas/i386/x86-64-ace.d: New test.
	* testsuite/gas/i386/x86-64-ace-intel.d: Ditto.
	* testsuite/gas/i386/x86-64-ace.s: Ditto.

opcodes/ChangeLog:

	* i386-dis.c (OP_BSR): New function.
	(att_names_bsr): New.
	(bsr, zmm_mode): New enumerators.
	(REG_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3): New.
	(MOD_VEX_0F3849_X86_64_L_0_W_1): Ditto.
	(RM_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3_R_0): Ditto.
	(PREFIX_VEX_0F3849_X86_64_L_0_W_1_M_1): Ditto.
	(PREFIX_EVEX_0F384A, PREFIX_EVEX_0F384B, PREFIX_EVEX_0F385C): Ditto.
	(PREFIX_EVEX_0F385E, PREFIX_EVEX_0F3A07, PREFIX_EVEX_0F3A2F): Ditto.
	(PREFIX_EVEX_0F3A8D, PREFIX_EVEX_0F3A8F, PREFIX_EVEX_MAP6_95): Ditto.
	(EVEX_LEN_0F384B, EVEX_LEN_MAP6_95_P_0_W_1): Ditto.
	(EVEX_W_MAP6_95_P_0, EVEX_W_MAP6_95_P_1, EVEX_W_MAP6_95_P_3): Ditto.
	(BSR, EXzmm, Rzmm, VexGd): Define.
	(reg_table): Add REG_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3.
	(prefix_table): Add PREFIX_VEX_0F3849_X86_64_L_0_W_1_M_1.
	(vex_w_table): Add W_1 entry to VEX_W_0F3849_X86_64_L_0.
	(mod_table): Add MOD_VEX_0F3849_X86_64_L_0_W_1.
	(rm_table): Add RM_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3_R_0 (bsrinit).
	(intel_operand_size): Handle zmm_mode.
	(OP_E_memory): Handle zmm_mode.
	(print_vector_reg): Handle zmm_mode.
	(OP_VEX): Select 512-bit register names by bytemode.
	* i386-dis-evex.h: Add ACE entries to evex_table.
	* i386-dis-evex-len.h: Add EVEX_LEN_0F384B and
	EVEX_LEN_MAP6_95_P_0_W_1.
	* i386-dis-evex-prefix.h: Add PREFIX_EVEX_0F384A, PREFIX_EVEX_0F384B,
	PREFIX_EVEX_0F385C, PREFIX_EVEX_0F385E, PREFIX_EVEX_0F3A07,
	PREFIX_EVEX_0F3A2F, PREFIX_EVEX_0F3A8D, PREFIX_EVEX_0F3A8F and
	PREFIX_EVEX_MAP6_95.
	* i386-dis-evex-w.h: Add PREFIX_EVEX_0F384A and PREFIX_EVEX_0F3A07
	entries; add EVEX_W_MAP6_95_P_0, EVEX_W_MAP6_95_P_1 and
	EVEX_W_MAP6_95_P_3.
	* i386-gen.c (isa_dependencies): Add ACE.
	(cpu_flags): Add ACE.
	(operand_classes): Add RegBS.
	* i386-opc.h (CpuACE): New.
	(i386_cpu): Add cpuace.
	(operand_class): Add RegBS.
	* i386-opc.tbl: Add RegBS and EVexMap6 macros.  Add ACE
	instructions and enable the AMX tile, tcvtrow* and tilemovrow
	insns for ACE.
	* i386-reg.tbl: Add bsr0 block scale register.
	* i386-init.h: Regenerated.
	* i386-mnem.h: Ditto.
	* i386-tbl.h: Ditto.

Co-authored-by: Umesh Kalvakuntla
---
 gas/NEWS                                  |     4 +
 gas/config/tc-i386.c                      |    52 +-
 gas/doc/c-i386.texi                       |     3 +-
 gas/testsuite/gas/i386/x86-64-ace-intel.d |    43 +
 gas/testsuite/gas/i386/x86-64-ace.d       |    43 +
 gas/testsuite/gas/i386/x86-64-ace.s       |    45 +
 gas/testsuite/gas/i386/x86-64.exp         |     2 +
 opcodes/i386-dis-evex-len.h               |    13 +
 opcodes/i386-dis-evex-prefix.h            |    57 +
 opcodes/i386-dis-evex-w.h                 |    19 +-
 opcodes/i386-dis-evex.h                   |    14 +-
 opcodes/i386-dis.c                        |   115 +-
 opcodes/i386-gen.c                        |     4 +
 opcodes/i386-init.h                       |   608 +-
 opcodes/i386-mnem.h                       |  3093 ++--
 opcodes/i386-opc.h                        |     4 +
 opcodes/i386-opc.tbl                      |    68 +-
 opcodes/i386-reg.tbl                      |     4 +-
 opcodes/i386-tbl.h                        | 18961 ++++++++++----------
 19 files changed, 11964 insertions(+), 11188 deletions(-)
 create mode 100644 gas/testsuite/gas/i386/x86-64-ace-intel.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-ace.d
 create mode 100644 gas/testsuite/gas/i386/x86-64-ace.s
  

Comments

Jan Beulich June 29, 2026, 9:52 a.m. UTC | #1
On 27.06.2026 13:53, Ganesh Gopalasubramanian wrote:
> @@ -4253,6 +4257,7 @@ install_template (const insn_template *t)
>  	}
>  
>        if ((maybe_cpu (t, CpuCMPCCXADD) || maybe_cpu (t, CpuAMX_TILE)
> +	   || maybe_cpu (t, CpuACE)
>  	   || maybe_cpu (t, CpuAVX512F) || maybe_cpu (t, CpuAVX512DQ)
>  	   || maybe_cpu (t, CpuAVX512BW) || maybe_cpu (t, CpuBMI)
>  	   || maybe_cpu (t, CpuBMI2) || maybe_cpu (t, CpuUSER_MSR)

Please can you append to such conditionals, or at least insert based on
how many templates there are, and hence (very vaguely) how often one of
them would make it here? (The ordering here is far from great, but I
think ACE wants to at least go after AVX512*.)

> @@ -9323,6 +9331,29 @@ check_APX_operands (const insn_template *t)
>    return 0;
>  }
>  
> +/* Check if ACE operands are valid for the instruction.  */
> +static bool
> +check_ACE_operands (const insn_template *t)
> +{
> +  switch (t->mnem_off)
> +    {
> +    case MN_tilemovrow:
> +    case MN_tilemovcol:
> +      if (is_cpu (t, CpuACE)
> +	  && i.op[0].imms && i.op[0].imms->X_op == O_constant)

i.op[].imms is a member of a union. You can't check or deref it without first
checking that the corresponding operand actually is an immediate one.

That said, ...

> +	{
> +	  offsetT val = i.op[0].imms->X_add_number;
> +	  if (val < 0 || val > 15)
> +	    {
> +	      i.error = unsupported_tile_index;
> +	      return 1;
> +	    }
> +	}
> +      break;
> +    }
> +  return 0;
> +}

... do we need such a check, seeing that the respective AMX-AVX512 insn doesn't
have one? And if so, should it perhaps better be a warning?

And then function having a return type "bool" want to return "true" / "false",
not 0 / 1. The fact that many pre-existing ones don't (yet) has historical
reasons.

> @@ -16943,13 +16982,18 @@ static bool check_register (const reg_entry *r)
>      return false;
>  
>    if (r->reg_type.bitfield.tmmword
> -      && (!cpu_arch_flags.bitfield.cpuamx_tile
> -          || flag_code != CODE_64BIT))
> +      && ((!cpu_arch_flags.bitfield.cpuamx_tile
> +	   && !cpu_arch_flags.bitfield.cpuace)
> +	  || flag_code != CODE_64BIT))
>      return false;
>  
>    if (r->reg_type.bitfield.class == RegBND && !cpu_arch_flags.bitfield.cpumpx)
>      return false;
>  
> +  if (r->reg_type.bitfield.class == RegBS
> +      && !cpu_arch_flags.bitfield.cpuace)
> +    return false;

Juding from the earlier if(), this one also will fit on a single line, and
hence would better do so for uniformity.

> --- /dev/null
> +++ b/gas/testsuite/gas/i386/x86-64-ace.s
> @@ -0,0 +1,45 @@
> +# Check 64-bit ACE instructions
> +
> +	.text
> +start:
> +	bsrinit %bsr0
> +	bsrmovf %zmm3, %zmm1, %bsr0
> +
> +	bsrmovh %zmm10, %bsr0
> +	bsrmovl %zmm10, %bsr0
> +	bsrmovh (%eax), %bsr0
> +	bsrmovl (%eax), %bsr0
> +
> +	bsrmovh %bsr0, %zmm4
> +	bsrmovl %bsr0, %zmm4
> +	bsrmovh %bsr0, (%eax)
> +	bsrmovl %bsr0, (%eax)
> +
> +	tilemovcol $8, %zmm2, %tmm1
> +	tilemovrow $8, %zmm2, %tmm1
> +
> +	tilemovcol %ebx, %zmm2, %tmm1
> +	tilemovrow %ebx, %zmm2, %tmm1
> +
> +	top2bf16ps %zmm2, %zmm1, %tmm0
> +	top4bssd   %zmm2, %zmm1, %tmm0
> +	top4bsud   %zmm2, %zmm1, %tmm0
> +	top4busd   %zmm2, %zmm1, %tmm0
> +	top4buud   %zmm2, %zmm1, %tmm0
> +
> +	top4mxbf8ps  $7, %zmm2, %zmm1, %tmm1
> +	top4mxbhf8ps $7, %zmm2, %zmm1, %tmm1
> +	top4mxhbf8ps $7, %zmm2, %zmm1, %tmm1
> +	top4mxhf8ps  $7, %zmm2, %zmm1, %tmm1
> +	top4mxbssps  $7, %zmm2, %zmm1, %tmm1
> +
> +	tcvtrowd2ps     %edx, %tmm5, %zmm30
> +	tcvtrowd2ps     $0x7b, %tmm5, %zmm30
> +	tcvtrowps2bf16h %edx, %tmm5, %zmm30
> +	tcvtrowps2bf16h $0x7b, %tmm5, %zmm30
> +	tcvtrowps2bf16l %edx, %tmm5, %zmm30
> +	tcvtrowps2bf16l $0x7b, %tmm5, %zmm30
> +	tcvtrowps2phh   %edx, %tmm5, %zmm30
> +	tcvtrowps2phh   $0x7b, %tmm5, %zmm30
> +	tcvtrowps2phl   %edx, %tmm5, %zmm30
> +	tcvtrowps2phl   $0x7b, %tmm5, %zmm30

If you cover pre-existing, re-used insns in the testcase, please cover them
all. For this to be really useful you will want to have another variant of
the test with the same output expectations, but with the ISA limited to ACE
(i.e. in particular no AMX). Iirc you can achieve this by having two #as:
lines (specifying different options) in the respective .d file(s).

> --- a/opcodes/i386-dis-evex-len.h
> +++ b/opcodes/i386-dis-evex-len.h
> @@ -51,6 +51,13 @@ static const struct dis386 evex_len_table[][3] = {
>      { PREFIX_TABLE (PREFIX_EVEX_0F384A_X86_64_W_0_L_2) },
>    },
>  
> +  /* EVEX_LEN_0F384B */
> +  {
> +    { X86_64_EVEX_W_TABLE (VEX_W_0F384B_X86_64_L_0) },
> +    { Bad_Opcode },
> +    { PREFIX_TABLE (PREFIX_EVEX_0F384B) },

The referenced enumerator needs renaming, to carry in its name that L_2
was already decoded.

> --- a/opcodes/i386-dis-evex-prefix.h
> +++ b/opcodes/i386-dis-evex-prefix.h
> @@ -254,6 +254,18 @@
>      { "tcvtrowd2ps",	{ XM, Rtmm, VexGdq }, 0 },
>      { "tilemovrow",	{ XM, Rtmm, VexGdq }, 0 },
>    },
> +  /* PREFIX_EVEX_0F384A */
> +  {
> +    { Bad_Opcode },
> +    { Bad_Opcode },
> +    { "tilemovrow",	{ TMM, Rzmm, VexGd }, 0 },
> +  },
> +  /* PREFIX_EVEX_0F384B */
> +  {
> +    { Bad_Opcode },
> +    { Bad_Opcode },
> +    { "tilemovcol",	{ TMM, Rzmm, VexGd }, 0 },

As per above, the enumerators in the comments need to specify what was
already decoded. As it stands, this gives the impression that neither
L'L nor W were. (Also applies elsewhere.)

> --- a/opcodes/i386-dis.c
> +++ b/opcodes/i386-dis.c
> @@ -70,6 +70,7 @@ static bool OP_D (instr_info *, int, int);
>  static bool OP_T (instr_info *, int, int);
>  static bool OP_MMX (instr_info *, int, int);
>  static bool OP_XMM (instr_info *, int, int);
> +static bool OP_BSR (instr_info *, int, int);
>  static bool OP_EM (instr_info *, int, int);
>  static bool OP_EX (instr_info *, int, int);
>  static bool OP_EMC (instr_info *, int,int);
> @@ -513,6 +514,7 @@ fetch_error (const instr_info *ins)
>  #define RMBH { OP_REG, bh_reg }
>  #define RMAX { OP_REG, ax_reg }
>  #define RMDX { OP_REG, dx_reg }
> +#define BSR { OP_BSR, bsr }
>  
>  #define eAX { OP_IMREG, eAX_reg }
>  #define AL { OP_IMREG, al_reg }
> @@ -566,6 +568,7 @@ fetch_error (const instr_info *ins)
>  #define EXxS { OP_EX, x_swap_mode }
>  #define EXxmm { OP_EX, xmm_mode }
>  #define EXymm { OP_EX, ymm_mode }
> +#define EXzmm { OP_EX, zmm_mode }

Why would this be needed? You use it in places where ordinary EVEX.L'L-
controlled reg/mem operands (without broadcast) are used, i.e. EXEvexXNoBcst
should do there.

> @@ -583,6 +586,7 @@ fetch_error (const instr_info *ins)
>  #define Uxmm { OP_R, xmm_mode }
>  #define Rxmmq { OP_R, xmmq_mode }
>  #define Rymm { OP_R, ymm_mode }
> +#define Rzmm { OP_R, zmm_mode }
The R-prefixed constants here aren't quite correct. As you can see newer
ones use U instead, and so should you. We try to match the SDM nomenclature.
And we already have Uxmm, which (like EXx / EXEvexXNoBcst above) should fit
here.

> @@ -600,6 +604,7 @@ fetch_error (const instr_info *ins)
>  #define VexGatherQ { OP_VEX, vex_vsib_q_w_dq_mode }
>  #define VexGdq { OP_VEX, dq_mode }
>  #define VexGb { OP_VEX, b_mode }
> +#define VexGd { OP_VEX, d_mode }

This doesn't match the existing TILEMOVROW and TCVTROW*, which use VexGdq.
With EVEX.W now gaining a different meaning, that wants sorting first (and
preferably separately).

> @@ -821,6 +828,8 @@ enum
>    rSI_reg,
>    rDI_reg,
>  
> +  bsr,

Do we really need this when OP_BSR() is a separate routine anyway?

> --- a/opcodes/i386-gen.c
> +++ b/opcodes/i386-gen.c
> @@ -263,6 +263,8 @@ static const dependency isa_dependencies[] =
>      "RTM|HLE" },
>    { "TSXLDTRK",
>      "RTM" },
> +  { "ACE",
> +    "AVX512F|64" },

Isn't AVX512BW|AVX512_BF16 the minimally sensible prereq, seeing the element
types of the outer-product insns?

> --- a/opcodes/i386-opc.h
> +++ b/opcodes/i386-opc.h
> @@ -359,6 +359,8 @@ enum i386_cpu
>    CpuAVX10_2,
>    /* Intel AMX-TRANSPOSE Instructions support required.  */
>    CpuAMX_TRANSPOSE,
> +  /* ACE instructions support required.  */
> +  CpuACE,
>    /* Not supported in the 64bit mode  */
>    CpuNo64,
>  
> @@ -397,6 +399,7 @@ enum i386_cpu
>  		   cpuapx_f:1, \
>  		   cpuavx10_2:1, \
>  		   cpuamx_transpose:1, \
> +		   cpuace:1, \
>        /* NOTE: This field needs to remain last. */ \
>  		   cpuno64:1
>  
> @@ -889,6 +892,7 @@ enum operand_class
>    RegSIMD, /* XMM/YMM/ZMM registers, distinguished by operand size */
>    RegMask, /* Vector Mask register */
>    RegBND, /* Bound register */
> +  RegBS, /* Block scale register */

I think RegBSR would be a better name here.

> --- a/opcodes/i386-opc.tbl
> +++ b/opcodes/i386-opc.tbl
> @@ -62,6 +62,8 @@
>  
>  #define RegBND Class=RegBND
>  
> +#define RegBS Class=RegBS
> +
>  #define Mmword Qword
>  #define Oword  Xmmword
>  
> @@ -118,6 +120,7 @@
>  #define SpaceXOP0A OpcodeSpace=SPACE_XOP0A
>  
>  #define EVexMap4 OpcodeSpace=SPACE_MAP4|EVex128
> +#define EVexMap6 OpcodeSpace=SPACE_MAP6

Why, when this isn't any different from ...

>  #define Map5 OpcodeSpace=SPACE_MAP5
>  #define Map6 OpcodeSpace=SPACE_MAP6

... this?

> @@ -3288,22 +3297,51 @@ tdpbhf8ps, 0xf2fd, AMX_FP8, Modrm|Vex128|Map5|Src2VVVV|VexW0|NoSuf, { RegTMM, Re
>  tdphbf8ps, 0xf3fd, AMX_FP8, Modrm|Vex128|Map5|Src2VVVV|VexW0|NoSuf, { RegTMM, RegTMM, RegTMM }
>  tdphf8ps, 0x66fd, AMX_FP8, Modrm|Vex128|Map5|Src2VVVV|VexW0|NoSuf, { RegTMM, RegTMM, RegTMM }
>  
> -tcvtrowd2ps, 0xf34a, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> -tcvtrowd2ps, 0xf307, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> +tcvtrowd2ps, 0xf34a, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> +tcvtrowd2ps, 0xf307, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> +
> +tcvtrowps2bf16h, 0xf26d, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> +tcvtrowps2bf16h, 0xf207, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> +tcvtrowps2bf16l, 0xf36d, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> +tcvtrowps2bf16l, 0xf377, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> +tcvtrowps2phh, 0x6d, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> +tcvtrowps2phh, 0x07, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> +tcvtrowps2phl, 0x666d, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> +tcvtrowps2phl, 0xf277, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> +
> +tilemovrow, 0x664a, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> +tilemovrow, 0x6607, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> +
> +// AMX & ACE instructions end.
> +
> +// ACE instructions.
> +
> +bsrinit, 0xf249, ACE, Modrm|Vex128|Space0F38|VexW1|NoSuf, { RegBS }
> +bsrmovf, 0x95, ACE, Modrm|EVex512|EVexMap6|VexW1|Src1VVVV|NoSuf, { RegZMM|Unspecified|BaseIndex, RegZMM, RegBS }
> +bsrmovh, 0xf295, ACE, Modrm|EVex512|EVexMap6|VexW1|NoSuf, { RegZMM|Unspecified|BaseIndex, RegBS }
> +bsrmovh, 0xf295, ACE, RegMem|Modrm|EVex512|EVexMap6|VexW0|NoSuf, { RegBS, RegZMM|Unspecified|BaseIndex }
> +bsrmovl, 0xf395, ACE, Modrm|EVex512|EVexMap6|VexW1|NoSuf, { RegZMM|Unspecified|BaseIndex, RegBS }
> +bsrmovl, 0xf395, ACE, RegMem|Modrm|EVex512|EVexMap6|VexW0|NoSuf, { RegBS, RegZMM|Unspecified|BaseIndex }

These two pairs may want to use D, just like the FMA4 and XOP insns do (where
VEX.W has a similar purpose as EVEX.W here).

> +tilemovcol, 0x662f, ACE, Modrm|EVex512|Space0F3A|VexW1|NoSuf, { Imm8, RegZMM, RegTMM }
> +tilemovcol, 0x664b, ACE, Modrm|EVex512|Space0F38|VexW1|Src2VVVV|NoSuf, { Reg32, RegZMM, RegTMM }
> +tilemovrow, 0x6607, ACE, Modrm|EVex512|Space0F3A|VexW1|NoSuf, { Imm8, RegZMM, RegTMM }
> +tilemovrow, 0x664a, ACE, Modrm|EVex512|Space0F38|VexW1|Src2VVVV|NoSuf, { Reg32, RegZMM, RegTMM }
> +
> +top2bf16ps, 0xf35c, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }
>  
> -tcvtrowps2bf16h, 0xf26d, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> -tcvtrowps2bf16h, 0xf207, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> -tcvtrowps2bf16l, 0xf36d, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> -tcvtrowps2bf16l, 0xf377, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> -tcvtrowps2phh, 0x6d, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> -tcvtrowps2phh, 0x07, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> -tcvtrowps2phl, 0x666d, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> -tcvtrowps2phl, 0xf277, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> +top4bssd, 0xf25e, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }
> +top4bsud, 0xf35e, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }
> +top4busd, 0x665e, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }
> +top4buud, 0x5e, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }

Along the lines of the existing <dpb> for AVX-VNNI-INT, the tile dot product
insns will want templatizing, for that template then to be re-use here.

> -tilemovrow, 0x664a, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
> -tilemovrow, 0x6607, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
> +top4mxbf8ps, 0x8d, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
> +top4mxbhf8ps, 0xf28d, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
> +top4mxhbf8ps, 0xf38d, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
> +top4mxhf8ps, 0x668d, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
> +top4mxbssps, 0xf28f, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
>  
> -// AMX instructions end.
> +// ACE instructions end.

Overall: Might be nice to split things - 1st patch to re-use pre-existing insns,
2nd one to add new ones.

> --- a/opcodes/i386-reg.tbl
> +++ b/opcodes/i386-reg.tbl
> @@ -344,7 +344,7 @@ zmm28, Class=RegSIMD|Zmmword, RegVRex|RegRex, 4, Dw2Inval, 79
>  zmm29, Class=RegSIMD|Zmmword, RegVRex|RegRex, 5, Dw2Inval, 80
>  zmm30, Class=RegSIMD|Zmmword, RegVRex|RegRex, 6, Dw2Inval, 81
>  zmm31, Class=RegSIMD|Zmmword, RegVRex|RegRex, 7, Dw2Inval, 82
> -// TMM registers for AMX
> +// TMM registers for AMX/ACE
>  tmm0, Class=RegSIMD|Tmmword, 0, 0, Dw2Inval, Dw2Inval
>  tmm1, Class=RegSIMD|Tmmword, 0, 1, Dw2Inval, Dw2Inval
>  tmm2, Class=RegSIMD|Tmmword, 0, 2, Dw2Inval, Dw2Inval
> @@ -353,6 +353,8 @@ tmm4, Class=RegSIMD|Tmmword, 0, 4, Dw2Inval, Dw2Inval
>  tmm5, Class=RegSIMD|Tmmword, 0, 5, Dw2Inval, Dw2Inval
>  tmm6, Class=RegSIMD|Tmmword, 0, 6, Dw2Inval, Dw2Inval
>  tmm7, Class=RegSIMD|Tmmword, 0, 7, Dw2Inval, Dw2Inval
> +// Block scale register for ACE
> +bsr0, Class=RegBS, 0, 0, Dw2Inval, Dw2Inval

Again a new register without the ability to represent it in Dwarf / EH-frame?

Jan
  
Jiang, Haochen June 30, 2026, 8:42 a.m. UTC | #2
> From: Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
> Sent: Saturday, June 27, 2026 7:54 PM
>

Besides the comments Jan and Lin has given,

> diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
> index d82ed061a78..f6f40589d11 100644
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -1200,6 +1201,7 @@ static const arch_entry cpu_arch[] =
>    SUBARCH (pconfig, PCONFIG, PCONFIG, false),
>    SUBARCH (waitpkg, WAITPKG, WAITPKG, false),
>    SUBARCH (cldemote, CLDEMOTE, CLDEMOTE, false),
> +  SUBARCH (ace, ACE, ACE, false),
>    SUBARCH (amx_int8, AMX_INT8, ANY_AMX_INT8, false),
>    SUBARCH (amx_bf16, AMX_BF16, ANY_AMX_BF16, false),
>    SUBARCH (amx_fp16, AMX_FP16, ANY_AMX_FP16, false),

Should we call it as ACEV1 instead of ACE? Documentation mentioned
it as ACEv1.

> @@ -7498,6 +7503,9 @@ i386_assemble (char *line)
>  	case unsupported_rsp_register:
>  	  err_msg = _("'rsp' register cannot be used");
>  	  break;
> +	case unsupported_tile_index:
> +	  err_msg = _("immediate value must be in range 0-15");
> +	  break;

I also think this might not be needed. If I read the pseudocode correctly,
it will read last 4 bit.

> diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
> index 11cc4ff19dc..dded2d906e6 100644
> --- a/opcodes/i386-gen.c
> +++ b/opcodes/i386-gen.c
> @@ -263,6 +263,8 @@ static const dependency isa_dependencies[] =
>      "RTM|HLE" },
>    { "TSXLDTRK",
>      "RTM" },
> +  { "ACE",
> +    "AVX512F|64" },

I have different opinion on this implication. I suppose it should
directly use AVX10_V2_AUX according to documentation CPUID
emulation part. That part clearly showed AVX10_V2_AUX is a must.

Thx,
Haochen
  
Jan Beulich June 30, 2026, 9:17 a.m. UTC | #3
On 30.06.2026 10:42, Jiang, Haochen wrote:
>> From: Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com>
>> Sent: Saturday, June 27, 2026 7:54 PM
>>
>> --- a/gas/config/tc-i386.c
>> +++ b/gas/config/tc-i386.c
>> @@ -1200,6 +1201,7 @@ static const arch_entry cpu_arch[] =
>>    SUBARCH (pconfig, PCONFIG, PCONFIG, false),
>>    SUBARCH (waitpkg, WAITPKG, WAITPKG, false),
>>    SUBARCH (cldemote, CLDEMOTE, CLDEMOTE, false),
>> +  SUBARCH (ace, ACE, ACE, false),
>>    SUBARCH (amx_int8, AMX_INT8, ANY_AMX_INT8, false),
>>    SUBARCH (amx_bf16, AMX_BF16, ANY_AMX_BF16, false),
>>    SUBARCH (amx_fp16, AMX_FP16, ANY_AMX_FP16, false),
> 
> Should we call it as ACEV1 instead of ACE? Documentation mentioned
> it as ACEv1.

Perhaps. We have "avx10.1" and "avx10.2" as .arch specifiers as well. So
perhaps "ace_v1" as counterpart ("acev1" being a little odd without
separator)?

>> --- a/opcodes/i386-gen.c
>> +++ b/opcodes/i386-gen.c
>> @@ -263,6 +263,8 @@ static const dependency isa_dependencies[] =
>>      "RTM|HLE" },
>>    { "TSXLDTRK",
>>      "RTM" },
>> +  { "ACE",
>> +    "AVX512F|64" },
> 
> I have different opinion on this implication. I suppose it should
> directly use AVX10_V2_AUX according to documentation CPUID
> emulation part. That part clearly showed AVX10_V2_AUX is a must.

+1

Jan
  
Jiang, Haochen July 1, 2026, 3:22 a.m. UTC | #4
> From: Jan Beulich <jbeulich@suse.com>
> Sent: Tuesday, June 30, 2026 5:17 PM
> 
> On 30.06.2026 10:42, Jiang, Haochen wrote:
> >> From: Ganesh Gopalasubramanian
> <Ganesh.Gopalasubramanian@amd.com>
> >> Sent: Saturday, June 27, 2026 7:54 PM
> >>
> >> --- a/gas/config/tc-i386.c
> >> +++ b/gas/config/tc-i386.c
> >> @@ -1200,6 +1201,7 @@ static const arch_entry cpu_arch[] =
> >>    SUBARCH (pconfig, PCONFIG, PCONFIG, false),
> >>    SUBARCH (waitpkg, WAITPKG, WAITPKG, false),
> >>    SUBARCH (cldemote, CLDEMOTE, CLDEMOTE, false),
> >> +  SUBARCH (ace, ACE, ACE, false),
> >>    SUBARCH (amx_int8, AMX_INT8, ANY_AMX_INT8, false),
> >>    SUBARCH (amx_bf16, AMX_BF16, ANY_AMX_BF16, false),
> >>    SUBARCH (amx_fp16, AMX_FP16, ANY_AMX_FP16, false),
> >
> > Should we call it as ACEV1 instead of ACE? Documentation mentioned
> > it as ACEv1.
> 
> Perhaps. We have "avx10.1" and "avx10.2" as .arch specifiers as well. So
> perhaps "ace_v1" as counterpart ("acev1" being a little odd without
> separator)?
> 

I am ok with ace_v1 or acev1 in binutils since both are reasonable.

Thx,
Haochen
  

Patch

diff --git a/gas/NEWS b/gas/NEWS
index ef4bd048e4b..a02f11a46ed 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,9 @@ 
 -*- text -*-
 
+* Add support for the x86 ACE (AI Compute Extensions) instructions,
+  including tile data movement, block scale register operations and tile
+  outer products.
+
 * Add support for the x86 AVX10_V2_AUX instructions, providing FP8, FP4
   and FP6 format conversion instructions.
 
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index d82ed061a78..f6f40589d11 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -272,6 +272,7 @@  enum i386_error
     unsupported_rc_sae,
     unsupported_vector_size,
     unsupported_rsp_register,
+    unsupported_tile_index,
     internal_error,
   };
 
@@ -1200,6 +1201,7 @@  static const arch_entry cpu_arch[] =
   SUBARCH (pconfig, PCONFIG, PCONFIG, false),
   SUBARCH (waitpkg, WAITPKG, WAITPKG, false),
   SUBARCH (cldemote, CLDEMOTE, CLDEMOTE, false),
+  SUBARCH (ace, ACE, ACE, false),
   SUBARCH (amx_int8, AMX_INT8, ANY_AMX_INT8, false),
   SUBARCH (amx_bf16, AMX_BF16, ANY_AMX_BF16, false),
   SUBARCH (amx_fp16, AMX_FP16, ANY_AMX_FP16, false),
@@ -1894,6 +1896,7 @@  _is_cpu (const i386_cpu_attr *a, enum i386_cpu cpu)
     case CpuAPX_F:    return a->bitfield.cpuapx_f;
     case CpuAVX10_2:  return a->bitfield.cpuavx10_2;
     case CpuAMX_TRANSPOSE:  return a->bitfield.cpuamx_transpose;
+    case CpuACE:      return a->bitfield.cpuace;
     case Cpu64:       return a->bitfield.cpu64;
     case CpuNo64:     return a->bitfield.cpuno64;
     default:
@@ -3933,6 +3936,7 @@  const type_names[] =
   { { .bitfield = { .class = RegSIMD, .zmmword = 1 } }, "rZMM" },
   { { .bitfield = { .class = RegSIMD, .tmmword = 1 } }, "rTMM" },
   { { .bitfield = { .class = RegMask } }, "Mask reg" },
+  { { .bitfield = { .class = RegBS } }, "bsr" },
 };
 
 static void
@@ -4253,6 +4257,7 @@  install_template (const insn_template *t)
 	}
 
       if ((maybe_cpu (t, CpuCMPCCXADD) || maybe_cpu (t, CpuAMX_TILE)
+	   || maybe_cpu (t, CpuACE)
 	   || maybe_cpu (t, CpuAVX512F) || maybe_cpu (t, CpuAVX512DQ)
 	   || maybe_cpu (t, CpuAVX512BW) || maybe_cpu (t, CpuBMI)
 	   || maybe_cpu (t, CpuBMI2) || maybe_cpu (t, CpuUSER_MSR)
@@ -7498,6 +7503,9 @@  i386_assemble (char *line)
 	case unsupported_rsp_register:
 	  err_msg = _("'rsp' register cannot be used");
 	  break;
+	case unsupported_tile_index:
+	  err_msg = _("immediate value must be in range 0-15");
+	  break;
 	case internal_error:
 	  err_msg = _("internal error");
 	  break;
@@ -9323,6 +9331,29 @@  check_APX_operands (const insn_template *t)
   return 0;
 }
 
+/* Check if ACE operands are valid for the instruction.  */
+static bool
+check_ACE_operands (const insn_template *t)
+{
+  switch (t->mnem_off)
+    {
+    case MN_tilemovrow:
+    case MN_tilemovcol:
+      if (is_cpu (t, CpuACE)
+	  && i.op[0].imms && i.op[0].imms->X_op == O_constant)
+	{
+	  offsetT val = i.op[0].imms->X_add_number;
+	  if (val < 0 || val > 15)
+	    {
+	      i.error = unsupported_tile_index;
+	      return 1;
+	    }
+	}
+      break;
+    }
+  return 0;
+}
+
 /* Check if the instruction use the REX registers or REX prefix.  */
 static bool
 check_Rex_required (void)
@@ -9905,6 +9936,13 @@  match_template (char mnem_suffix)
 	  continue;
 	}
 
+      /* Check if ACE operands are valid.  */
+      if (check_ACE_operands (t))
+	{
+	  specific_error = progress (i.error);
+	  continue;
+	}
+
       /* Check whether to use the shorter VEX encoding for certain insns where
 	 the EVEX encoding comes first in the table.  This requires the respective
 	 AVX-* feature to be explicitly enabled.
@@ -10994,7 +11032,7 @@  process_operands (void)
      not ModR/M.rm.  To avoid special casing this in build_modrm_byte(), fake a
      new destination operand here, while converting the source one to register
      number 0.  */
-  if (i.tm.mnem_off == MN_tilezero)
+  if (i.tm.mnem_off == MN_tilezero || i.tm.mnem_off == MN_bsrinit)
     {
       copy_operand (1, 0);
       i.op[0].regs -= i.op[0].regs->reg_num;
@@ -12475,7 +12513,8 @@  output_insn (const struct last_insn *last_insn)
       unsigned int feature_2_used = 0;
 
       if ((i.xstate & xstate_tmm) == xstate_tmm
-	  || is_cpu (&i.tm, CpuAMX_TILE))
+	  || is_cpu (&i.tm, CpuAMX_TILE)
+	  || is_cpu (&i.tm, CpuACE))
 	feature_2_used |= GNU_PROPERTY_X86_FEATURE_2_TMM;
 
       if (is_cpu (&i.tm, Cpu8087)
@@ -16943,13 +16982,18 @@  static bool check_register (const reg_entry *r)
     return false;
 
   if (r->reg_type.bitfield.tmmword
-      && (!cpu_arch_flags.bitfield.cpuamx_tile
-          || flag_code != CODE_64BIT))
+      && ((!cpu_arch_flags.bitfield.cpuamx_tile
+	   && !cpu_arch_flags.bitfield.cpuace)
+	  || flag_code != CODE_64BIT))
     return false;
 
   if (r->reg_type.bitfield.class == RegBND && !cpu_arch_flags.bitfield.cpumpx)
     return false;
 
+  if (r->reg_type.bitfield.class == RegBS
+      && !cpu_arch_flags.bitfield.cpuace)
+    return false;
+
   /* Don't allow fake index register unless allow_index_reg isn't 0. */
   if (!allow_index_reg && r->reg_num == RegIZ)
     return false;
diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi
index 9f6e8da443d..5d1e15816af 100644
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -242,6 +242,7 @@  accept various extension mnemonics.  For example,
 @code{amx_movrs},
 @code{amx_avx512},
 @code{amx_tile},
+@code{ace},
 @code{vmx},
 @code{vmfunc},
 @code{smx},
@@ -1731,7 +1732,7 @@  supported on the CPU specified.  The choices for @var{cpu_type} are:
 @item @samp{.amx_int8} @tab @samp{.amx_bf16} @tab @samp{.amx_fp16}
 @item @samp{.amx_complex} @tab @samp{.amx_transpose} @tab @samp{.amx_tf32}
 @item @samp{.amx_fp8} @tab @samp{.amx_movrs} @tab @samp{.amx_avx512}
-@item @samp{.amx_tile}
+@item @samp{.amx_tile} @tab @samp{.ace}
 @item @samp{.kl} @tab @samp{.widekl} @tab @samp{.uintr} @tab @samp{.hreset}
 @item @samp{.3dnow} @tab @samp{.3dnowa} @tab @samp{.sse4a} @tab @samp{.sse5}
 @item @samp{.syscall} @tab @samp{.rdtscp} @tab @samp{.svme}
diff --git a/gas/testsuite/gas/i386/x86-64-ace-intel.d b/gas/testsuite/gas/i386/x86-64-ace-intel.d
new file mode 100644
index 00000000000..b116845d240
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-ace-intel.d
@@ -0,0 +1,43 @@ 
+#objdump: -dw -Mintel
+#name: 64-bit ACE insns (Intel disassembly)
+#source: x86-64-ace.s
+
+.*: +file format .*
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <start>:
+[\s]*[a-f0-9]+:[\s]*c4 e2 fb 49 c0[\s]*bsrinit bsr0
+[\s]*[a-f0-9]+:[\s]*62 f6 f4 48 95 c3[\s]*bsrmovf bsr0,zmm1,zmm3
+[\s]*[a-f0-9]+:[\s]*62 d6 ff 48 95 c2[\s]*bsrmovh bsr0,zmm10
+[\s]*[a-f0-9]+:[\s]*62 d6 fe 48 95 c2[\s]*bsrmovl bsr0,zmm10
+[\s]*[a-f0-9]+:[\s]*67 62 f6 ff 48 95 00[\s]*bsrmovh bsr0,ZMMWORD PTR \[eax\]
+[\s]*[a-f0-9]+:[\s]*67 62 f6 fe 48 95 00[\s]*bsrmovl bsr0,ZMMWORD PTR \[eax\]
+[\s]*[a-f0-9]+:[\s]*62 f6 7f 48 95 c4[\s]*bsrmovh zmm4,bsr0
+[\s]*[a-f0-9]+:[\s]*62 f6 7e 48 95 c4[\s]*bsrmovl zmm4,bsr0
+[\s]*[a-f0-9]+:[\s]*67 62 f6 7f 48 95 00[\s]*bsrmovh ZMMWORD PTR \[eax\],bsr0
+[\s]*[a-f0-9]+:[\s]*67 62 f6 7e 48 95 00[\s]*bsrmovl ZMMWORD PTR \[eax\],bsr0
+[\s]*[a-f0-9]+:[\s]*62 f3 fd 48 2f ca 08[\s]*tilemovcol tmm1,zmm2,0x8
+[\s]*[a-f0-9]+:[\s]*62 f3 fd 48 07 ca 08[\s]*tilemovrow tmm1,zmm2,0x8
+[\s]*[a-f0-9]+:[\s]*62 f2 e5 48 4b ca[\s]*tilemovcol tmm1,zmm2,ebx
+[\s]*[a-f0-9]+:[\s]*62 f2 e5 48 4a ca[\s]*tilemovrow tmm1,zmm2,ebx
+[\s]*[a-f0-9]+:[\s]*62 f2 6e 48 5c c1[\s]*top2bf16ps tmm0,zmm1,zmm2
+[\s]*[a-f0-9]+:[\s]*62 f2 6f 48 5e c1[\s]*top4bssd tmm0,zmm1,zmm2
+[\s]*[a-f0-9]+:[\s]*62 f2 6e 48 5e c1[\s]*top4bsud tmm0,zmm1,zmm2
+[\s]*[a-f0-9]+:[\s]*62 f2 6d 48 5e c1[\s]*top4busd tmm0,zmm1,zmm2
+[\s]*[a-f0-9]+:[\s]*62 f2 6c 48 5e c1[\s]*top4buud tmm0,zmm1,zmm2
+[\s]*[a-f0-9]+:[\s]*62 f3 6c 48 8d c9 07[\s]*top4mxbf8ps tmm1,zmm1,zmm2,0x7
+[\s]*[a-f0-9]+:[\s]*62 f3 6f 48 8d c9 07[\s]*top4mxbhf8ps tmm1,zmm1,zmm2,0x7
+[\s]*[a-f0-9]+:[\s]*62 f3 6e 48 8d c9 07[\s]*top4mxhbf8ps tmm1,zmm1,zmm2,0x7
+[\s]*[a-f0-9]+:[\s]*62 f3 6d 48 8d c9 07[\s]*top4mxhf8ps tmm1,zmm1,zmm2,0x7
+[\s]*[a-f0-9]+:[\s]*62 f3 6f 48 8f c9 07[\s]*top4mxbssps tmm1,zmm1,zmm2,0x7
+[\s]*[a-f0-9]+:[\s]*62 62 6e 48 4a f5[\s]*tcvtrowd2ps zmm30,tmm5,edx
+[\s]*[a-f0-9]+:[\s]*62 63 7e 48 07 f5 7b[\s]*tcvtrowd2ps zmm30,tmm5,0x7b
+[\s]*[a-f0-9]+:[\s]*62 62 6f 48 6d f5[\s]*tcvtrowps2bf16h zmm30,tmm5,edx
+[\s]*[a-f0-9]+:[\s]*62 63 7f 48 07 f5 7b[\s]*tcvtrowps2bf16h zmm30,tmm5,0x7b
+[\s]*[a-f0-9]+:[\s]*62 62 6e 48 6d f5[\s]*tcvtrowps2bf16l zmm30,tmm5,edx
+[\s]*[a-f0-9]+:[\s]*62 63 7e 48 77 f5 7b[\s]*tcvtrowps2bf16l zmm30,tmm5,0x7b
+[\s]*[a-f0-9]+:[\s]*62 62 6c 48 6d f5[\s]*tcvtrowps2phh zmm30,tmm5,edx
+[\s]*[a-f0-9]+:[\s]*62 63 7c 48 07 f5 7b[\s]*tcvtrowps2phh zmm30,tmm5,0x7b
+[\s]*[a-f0-9]+:[\s]*62 62 6d 48 6d f5[\s]*tcvtrowps2phl zmm30,tmm5,edx
+[\s]*[a-f0-9]+:[\s]*62 63 7f 48 77 f5 7b[\s]*tcvtrowps2phl zmm30,tmm5,0x7b
diff --git a/gas/testsuite/gas/i386/x86-64-ace.d b/gas/testsuite/gas/i386/x86-64-ace.d
new file mode 100644
index 00000000000..cc91aa7fede
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-ace.d
@@ -0,0 +1,43 @@ 
+#objdump: -dw
+#name: 64-bit ACE insns
+#source: x86-64-ace.s
+
+.*: +file format .*
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <start>:
+[\s]*[a-f0-9]+:[\s]*c4 e2 fb 49 c0[\s]*bsrinit %bsr0
+[\s]*[a-f0-9]+:[\s]*62 f6 f4 48 95 c3[\s]*bsrmovf %zmm3,%zmm1,%bsr0
+[\s]*[a-f0-9]+:[\s]*62 d6 ff 48 95 c2[\s]*bsrmovh %zmm10,%bsr0
+[\s]*[a-f0-9]+:[\s]*62 d6 fe 48 95 c2[\s]*bsrmovl %zmm10,%bsr0
+[\s]*[a-f0-9]+:[\s]*67 62 f6 ff 48 95 00[\s]*bsrmovh \(%eax\),%bsr0
+[\s]*[a-f0-9]+:[\s]*67 62 f6 fe 48 95 00[\s]*bsrmovl \(%eax\),%bsr0
+[\s]*[a-f0-9]+:[\s]*62 f6 7f 48 95 c4[\s]*bsrmovh %bsr0,%zmm4
+[\s]*[a-f0-9]+:[\s]*62 f6 7e 48 95 c4[\s]*bsrmovl %bsr0,%zmm4
+[\s]*[a-f0-9]+:[\s]*67 62 f6 7f 48 95 00[\s]*bsrmovh %bsr0,\(%eax\)
+[\s]*[a-f0-9]+:[\s]*67 62 f6 7e 48 95 00[\s]*bsrmovl %bsr0,\(%eax\)
+[\s]*[a-f0-9]+:[\s]*62 f3 fd 48 2f ca 08[\s]*tilemovcol \$0x8,%zmm2,%tmm1
+[\s]*[a-f0-9]+:[\s]*62 f3 fd 48 07 ca 08[\s]*tilemovrow \$0x8,%zmm2,%tmm1
+[\s]*[a-f0-9]+:[\s]*62 f2 e5 48 4b ca[\s]*tilemovcol %ebx,%zmm2,%tmm1
+[\s]*[a-f0-9]+:[\s]*62 f2 e5 48 4a ca[\s]*tilemovrow %ebx,%zmm2,%tmm1
+[\s]*[a-f0-9]+:[\s]*62 f2 6e 48 5c c1[\s]*top2bf16ps %zmm2,%zmm1,%tmm0
+[\s]*[a-f0-9]+:[\s]*62 f2 6f 48 5e c1[\s]*top4bssd %zmm2,%zmm1,%tmm0
+[\s]*[a-f0-9]+:[\s]*62 f2 6e 48 5e c1[\s]*top4bsud %zmm2,%zmm1,%tmm0
+[\s]*[a-f0-9]+:[\s]*62 f2 6d 48 5e c1[\s]*top4busd %zmm2,%zmm1,%tmm0
+[\s]*[a-f0-9]+:[\s]*62 f2 6c 48 5e c1[\s]*top4buud %zmm2,%zmm1,%tmm0
+[\s]*[a-f0-9]+:[\s]*62 f3 6c 48 8d c9 07[\s]*top4mxbf8ps \$0x7,%zmm2,%zmm1,%tmm1
+[\s]*[a-f0-9]+:[\s]*62 f3 6f 48 8d c9 07[\s]*top4mxbhf8ps \$0x7,%zmm2,%zmm1,%tmm1
+[\s]*[a-f0-9]+:[\s]*62 f3 6e 48 8d c9 07[\s]*top4mxhbf8ps \$0x7,%zmm2,%zmm1,%tmm1
+[\s]*[a-f0-9]+:[\s]*62 f3 6d 48 8d c9 07[\s]*top4mxhf8ps \$0x7,%zmm2,%zmm1,%tmm1
+[\s]*[a-f0-9]+:[\s]*62 f3 6f 48 8f c9 07[\s]*top4mxbssps \$0x7,%zmm2,%zmm1,%tmm1
+[\s]*[a-f0-9]+:[\s]*62 62 6e 48 4a f5[\s]*tcvtrowd2ps %edx,%tmm5,%zmm30
+[\s]*[a-f0-9]+:[\s]*62 63 7e 48 07 f5 7b[\s]*tcvtrowd2ps \$0x7b,%tmm5,%zmm30
+[\s]*[a-f0-9]+:[\s]*62 62 6f 48 6d f5[\s]*tcvtrowps2bf16h %edx,%tmm5,%zmm30
+[\s]*[a-f0-9]+:[\s]*62 63 7f 48 07 f5 7b[\s]*tcvtrowps2bf16h \$0x7b,%tmm5,%zmm30
+[\s]*[a-f0-9]+:[\s]*62 62 6e 48 6d f5[\s]*tcvtrowps2bf16l %edx,%tmm5,%zmm30
+[\s]*[a-f0-9]+:[\s]*62 63 7e 48 77 f5 7b[\s]*tcvtrowps2bf16l \$0x7b,%tmm5,%zmm30
+[\s]*[a-f0-9]+:[\s]*62 62 6c 48 6d f5[\s]*tcvtrowps2phh %edx,%tmm5,%zmm30
+[\s]*[a-f0-9]+:[\s]*62 63 7c 48 07 f5 7b[\s]*tcvtrowps2phh \$0x7b,%tmm5,%zmm30
+[\s]*[a-f0-9]+:[\s]*62 62 6d 48 6d f5[\s]*tcvtrowps2phl %edx,%tmm5,%zmm30
+[\s]*[a-f0-9]+:[\s]*62 63 7f 48 77 f5 7b[\s]*tcvtrowps2phl \$0x7b,%tmm5,%zmm30
diff --git a/gas/testsuite/gas/i386/x86-64-ace.s b/gas/testsuite/gas/i386/x86-64-ace.s
new file mode 100644
index 00000000000..9c7bf8a2214
--- /dev/null
+++ b/gas/testsuite/gas/i386/x86-64-ace.s
@@ -0,0 +1,45 @@ 
+# Check 64-bit ACE instructions
+
+	.text
+start:
+	bsrinit %bsr0
+	bsrmovf %zmm3, %zmm1, %bsr0
+
+	bsrmovh %zmm10, %bsr0
+	bsrmovl %zmm10, %bsr0
+	bsrmovh (%eax), %bsr0
+	bsrmovl (%eax), %bsr0
+
+	bsrmovh %bsr0, %zmm4
+	bsrmovl %bsr0, %zmm4
+	bsrmovh %bsr0, (%eax)
+	bsrmovl %bsr0, (%eax)
+
+	tilemovcol $8, %zmm2, %tmm1
+	tilemovrow $8, %zmm2, %tmm1
+
+	tilemovcol %ebx, %zmm2, %tmm1
+	tilemovrow %ebx, %zmm2, %tmm1
+
+	top2bf16ps %zmm2, %zmm1, %tmm0
+	top4bssd   %zmm2, %zmm1, %tmm0
+	top4bsud   %zmm2, %zmm1, %tmm0
+	top4busd   %zmm2, %zmm1, %tmm0
+	top4buud   %zmm2, %zmm1, %tmm0
+
+	top4mxbf8ps  $7, %zmm2, %zmm1, %tmm1
+	top4mxbhf8ps $7, %zmm2, %zmm1, %tmm1
+	top4mxhbf8ps $7, %zmm2, %zmm1, %tmm1
+	top4mxhf8ps  $7, %zmm2, %zmm1, %tmm1
+	top4mxbssps  $7, %zmm2, %zmm1, %tmm1
+
+	tcvtrowd2ps     %edx, %tmm5, %zmm30
+	tcvtrowd2ps     $0x7b, %tmm5, %zmm30
+	tcvtrowps2bf16h %edx, %tmm5, %zmm30
+	tcvtrowps2bf16h $0x7b, %tmm5, %zmm30
+	tcvtrowps2bf16l %edx, %tmm5, %zmm30
+	tcvtrowps2bf16l $0x7b, %tmm5, %zmm30
+	tcvtrowps2phh   %edx, %tmm5, %zmm30
+	tcvtrowps2phh   $0x7b, %tmm5, %zmm30
+	tcvtrowps2phl   %edx, %tmm5, %zmm30
+	tcvtrowps2phl   $0x7b, %tmm5, %zmm30
diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp
index d0d3cb47117..ae5d8bff1ba 100644
--- a/gas/testsuite/gas/i386/x86-64.exp
+++ b/gas/testsuite/gas/i386/x86-64.exp
@@ -689,6 +689,8 @@  run_list_test "x86-64-amx-inval"
 run_dump_test "x86-64-amx"
 run_dump_test "x86-64-amx-intel"
 run_dump_test "x86-64-amx-bad"
+run_dump_test "x86-64-ace"
+run_dump_test "x86-64-ace-intel"
 
 if { ![istarget "*-*-aix*"]
      && ![istarget "*-*-beos*"]
diff --git a/opcodes/i386-dis-evex-len.h b/opcodes/i386-dis-evex-len.h
index 370710915de..273c6d40d12 100644
--- a/opcodes/i386-dis-evex-len.h
+++ b/opcodes/i386-dis-evex-len.h
@@ -51,6 +51,13 @@  static const struct dis386 evex_len_table[][3] = {
     { PREFIX_TABLE (PREFIX_EVEX_0F384A_X86_64_W_0_L_2) },
   },
 
+  /* EVEX_LEN_0F384B */
+  {
+    { X86_64_EVEX_W_TABLE (VEX_W_0F384B_X86_64_L_0) },
+    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_0F384B) },
+  },
+
   /* EVEX_LEN_0F385A */
   {
     { Bad_Opcode },
@@ -207,4 +214,10 @@  static const struct dis386 evex_len_table[][3] = {
     { "vbmacxor16x16x16", { XM, Vex, EXx }, NO_PREFIX },
     { "vbmacxor16x16x16", { XM, Vex, EXx }, NO_PREFIX },
   },
+  /* EVEX_LEN_MAP6_95_P_0_W_1 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "bsrmovf", { BSR, Vex, EXx }, 0 },
+  },
 };
diff --git a/opcodes/i386-dis-evex-prefix.h b/opcodes/i386-dis-evex-prefix.h
index ffecef5e796..f3b031470df 100644
--- a/opcodes/i386-dis-evex-prefix.h
+++ b/opcodes/i386-dis-evex-prefix.h
@@ -254,6 +254,18 @@ 
     { "tcvtrowd2ps",	{ XM, Rtmm, VexGdq }, 0 },
     { "tilemovrow",	{ XM, Rtmm, VexGdq }, 0 },
   },
+  /* PREFIX_EVEX_0F384A */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "tilemovrow",	{ TMM, Rzmm, VexGd }, 0 },
+  },
+  /* PREFIX_EVEX_0F384B */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "tilemovcol",	{ TMM, Rzmm, VexGd }, 0 },
+  },
   /* PREFIX_EVEX_0F3852 */
   {
     { "vdpphp%XS",	{ XM, Vex, EXx }, 0 },
@@ -268,6 +280,18 @@ 
     { VEX_W_TABLE (VEX_W_0F3853) },
     { "vp4dpws%XSds",	{ XM, Vex, Mxmm }, 0 },
   },
+  /* PREFIX_EVEX_0F385C */
+  {
+    { Bad_Opcode },
+    { "top2bf16ps",	{ TMM, Rzmm, Vex }, 0 },
+  },
+  /* PREFIX_EVEX_0F385E */
+  {
+    { "top4buud",	{ TMM, Rzmm, Vex }, 0 },
+    { "top4bsud",	{ TMM, Rzmm, Vex }, 0 },
+    { "top4busd",	{ TMM, Rzmm, Vex }, 0 },
+    { "top4bssd",	{ TMM, Rzmm, Vex }, 0 },
+  },
   /* PREFIX_EVEX_0F3868 */
   {
     { Bad_Opcode },
@@ -331,6 +355,12 @@ 
     { "tilemovrow",	{ XM, Rtmm, Ib }, 0 },
     { "tcvtrowps2bf16h",	{ XM, Rtmm, Ib }, 0 },
   },
+  /* PREFIX_EVEX_0F3A07 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "tilemovrow", { TMM, Rzmm, Ib }, 0 },
+  },
   /* PREFIX_EVEX_0F3A08 */
   {
     { "vrndscalep%XH",  { XM, EXxh, EXxEVexS, Ib }, 0 },
@@ -357,6 +387,12 @@ 
     { Bad_Opcode },
     { "vgetmants%XW",	{ XMScalar, VexScalar, EXdq, EXxEVexS, Ib }, 0 },
   },
+  /* PREFIX_EVEX_0F3A2F */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "tilemovcol", { TMM, Rzmm, Ib }, 0 },
+  },
   /* PREFIX_EVEX_0F3A42_W_0 */
   {
     { Bad_Opcode },
@@ -409,6 +445,20 @@ 
     { Bad_Opcode },
     { "tcvtrowps2phl",	{ XM, Rtmm, Ib }, 0 },
   },
+  /* PREFIX_EVEX_0F3A8D */
+  {
+    { "top4mxbf8ps",	{ TMM, Rzmm, Vex, Ib }, 0 },
+    { "top4mxhbf8ps",	{ TMM, Rzmm, Vex, Ib }, 0 },
+    { "top4mxhf8ps",	{ TMM, Rzmm, Vex, Ib }, 0 },
+    { "top4mxbhf8ps",	{ TMM, Rzmm, Vex, Ib }, 0 },
+  },
+  /* PREFIX_EVEX_0F3A8F */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { "top4mxbssps",	{ TMM, Rzmm, Vex, Ib }, 0 },
+  },
   /* PREFIX_EVEX_0F3AC2 */
   {
     { "vcmpp%XH", { MaskG, Vex, EXxh, EXxEVexS, CMP }, 0 },
@@ -833,6 +883,13 @@ 
     { Bad_Opcode },
     { "vfnmsub231p%XH",	{ XM, Vex, EXxh, EXxEVexR }, 0 },
   },
+  /* PREFIX_EVEX_MAP6_95 */
+  {
+    { VEX_W_TABLE (EVEX_W_MAP6_95_P_0) },
+    { VEX_W_TABLE (EVEX_W_MAP6_95_P_1) },
+    { Bad_Opcode },
+    { VEX_W_TABLE (EVEX_W_MAP6_95_P_3) },
+  },
   /* PREFIX_EVEX_MAP6_D6 */
   {
     { Bad_Opcode },
diff --git a/opcodes/i386-dis-evex-w.h b/opcodes/i386-dis-evex-w.h
index 6e94bc45fe1..8e0529e1a08 100644
--- a/opcodes/i386-dis-evex-w.h
+++ b/opcodes/i386-dis-evex-w.h
@@ -349,6 +349,7 @@ 
   /* EVEX_W_0F384A_X86_64 */
   {
     { EVEX_LEN_TABLE (EVEX_LEN_0F384A_X86_64_W_0) },
+    { PREFIX_TABLE (PREFIX_EVEX_0F384A) },
   },
   /* EVEX_W_0F3859 */
   {
@@ -395,6 +396,7 @@ 
   /* EVEX_W_0F3A07_X86_64 */
   {
     { EVEX_LEN_TABLE (EVEX_LEN_0F3A07_X86_64_W_0) },
+    { PREFIX_TABLE (PREFIX_EVEX_0F3A07) },
   },
   /* EVEX_W_0F3A18_L_n */
   {
@@ -553,4 +555,19 @@ 
   {
     { "vbitrevb", { XM, EXx }, NO_PREFIX },
     { Bad_Opcode }
-  }
+  },
+  /* EVEX_W_MAP6_95_P_0 */
+  {
+    { Bad_Opcode },
+    { EVEX_LEN_TABLE (EVEX_LEN_MAP6_95_P_0_W_1) },
+  },
+  /* EVEX_W_MAP6_95_P_1 */
+  {
+    { "bsrmovl", { EXzmm, BSR }, 0 },
+    { "bsrmovl", { BSR, EXzmm }, 0 },
+  },
+  /* EVEX_W_MAP6_95_P_3 */
+  {
+    { "bsrmovh", { EXzmm, BSR }, 0 },
+    { "bsrmovh", { BSR, EXzmm }, 0 },
+  },
diff --git a/opcodes/i386-dis-evex.h b/opcodes/i386-dis-evex.h
index 7d555aa9e11..9ad57912231 100644
--- a/opcodes/i386-dis-evex.h
+++ b/opcodes/i386-dis-evex.h
@@ -377,7 +377,7 @@  static const struct dis386 evex_table[][256] = {
     { Bad_Opcode },
     { X86_64_EVEX_MEM_W_TABLE (VEX_W_0F3849_X86_64_L_0) },
     { X86_64_TABLE (X86_64_EVEX_0F384A) },
-    { X86_64_EVEX_MEM_W_TABLE (VEX_W_0F384B_X86_64_L_0) },
+    { EVEX_LEN_TABLE (EVEX_LEN_0F384B) },
     { "vrcp14p%XW",	{ XM, EXx }, PREFIX_DATA },
     { "vrcp14s%XW",	{ XMScalar, VexScalar, EXdq }, PREFIX_DATA },
     { "vrsqrt14p%XW",	{ XM, EXx }, 0 },
@@ -396,9 +396,9 @@  static const struct dis386 evex_table[][256] = {
     { VEX_W_TABLE (EVEX_W_0F3859) },
     { EVEX_LEN_TABLE (EVEX_LEN_0F385A) },
     { EVEX_LEN_TABLE (EVEX_LEN_0F385B) },
+    { PREFIX_TABLE (PREFIX_EVEX_0F385C) },
     { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_0F385E) },
     { Bad_Opcode },
     /* 60 */
     { Bad_Opcode },
@@ -636,7 +636,7 @@  static const struct dis386 evex_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_0F3A2F) },
     /* 30 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -742,9 +742,9 @@  static const struct dis386 evex_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_0F3A8D) },
     { Bad_Opcode },
-    { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_0F3A8F) },
     /* 90 */
     { Bad_Opcode },
     { Bad_Opcode },
@@ -1624,7 +1624,7 @@  static const struct dis386 evex_table[][256] = {
     { Bad_Opcode },
     { Bad_Opcode },
     { Bad_Opcode },
-    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_EVEX_MAP6_95) },
     { "vfmaddsub132p%XH",  { XM, Vex, EXxh, EXxEVexR }, PREFIX_DATA },
     { "vfmsubadd132p%XH",  { XM, Vex, EXxh, EXxEVexR }, PREFIX_DATA },
     /* 98 */
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index 5643cfe55d5..f39774f2a83 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -70,6 +70,7 @@  static bool OP_D (instr_info *, int, int);
 static bool OP_T (instr_info *, int, int);
 static bool OP_MMX (instr_info *, int, int);
 static bool OP_XMM (instr_info *, int, int);
+static bool OP_BSR (instr_info *, int, int);
 static bool OP_EM (instr_info *, int, int);
 static bool OP_EX (instr_info *, int, int);
 static bool OP_EMC (instr_info *, int,int);
@@ -513,6 +514,7 @@  fetch_error (const instr_info *ins)
 #define RMBH { OP_REG, bh_reg }
 #define RMAX { OP_REG, ax_reg }
 #define RMDX { OP_REG, dx_reg }
+#define BSR { OP_BSR, bsr }
 
 #define eAX { OP_IMREG, eAX_reg }
 #define AL { OP_IMREG, al_reg }
@@ -566,6 +568,7 @@  fetch_error (const instr_info *ins)
 #define EXxS { OP_EX, x_swap_mode }
 #define EXxmm { OP_EX, xmm_mode }
 #define EXymm { OP_EX, ymm_mode }
+#define EXzmm { OP_EX, zmm_mode }
 #define EXxmmq { OP_EX, xmmq_mode }
 #define EXxmmqh { OP_EX, evex_half_bcst_xmmqh_mode }
 #define EXEvexHalfBcstXmmq { OP_EX, evex_half_bcst_xmmq_mode }
@@ -583,6 +586,7 @@  fetch_error (const instr_info *ins)
 #define Uxmm { OP_R, xmm_mode }
 #define Rxmmq { OP_R, xmmq_mode }
 #define Rymm { OP_R, ymm_mode }
+#define Rzmm { OP_R, zmm_mode }
 #define Rtmm { OP_R, tmm_mode }
 #define EMCq { OP_EMC, q_mode }
 #define MXC { OP_MXC, 0 }
@@ -600,6 +604,7 @@  fetch_error (const instr_info *ins)
 #define VexGatherQ { OP_VEX, vex_vsib_q_w_dq_mode }
 #define VexGdq { OP_VEX, dq_mode }
 #define VexGb { OP_VEX, b_mode }
+#define VexGd { OP_VEX, d_mode }
 #define VexGv { OP_VEX, v_mode }
 #define VexTmm { OP_VEX, tmm_mode }
 #define XMVexI4 { OP_REG_VexI4, x_mode }
@@ -720,6 +725,8 @@  enum
   ymm_mode,
   /* quad word, ymmword or zmmword memory operand.  */
   ymmq_mode,
+  /* 64-byte ZMM operand */
+  zmm_mode,
   /* TMM operand */
   tmm_mode,
   /* d_mode in 32bit, q_mode in 64bit mode.  */
@@ -821,6 +828,8 @@  enum
   rSI_reg,
   rDI_reg,
 
+  bsr,
+
   z_mode_ax_reg,
   indir_dx_reg
 };
@@ -908,6 +917,7 @@  enum
   REG_VEX_0F73,
   REG_VEX_0FAE,
   REG_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0,
+  REG_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3,
   REG_VEX_0F38F3_L_0_P_0,
   REG_VEX_MAP7_F6_L_0_W_0,
   REG_VEX_MAP7_F8_L_0_W_0,
@@ -971,6 +981,7 @@  enum
   MOD_0F38F8,
 
   MOD_VEX_0F3849_X86_64_L_0_W_0,
+  MOD_VEX_0F3849_X86_64_L_0_W_1,
 
   MOD_EVEX_MAP4_60,
   MOD_EVEX_MAP4_61,
@@ -995,6 +1006,7 @@  enum
 
   RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0_R_0,
   RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_3,
+  RM_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3_R_0,
 };
 
 enum
@@ -1141,6 +1153,7 @@  enum
   PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_0,
   PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_1,
   PREFIX_VEX_0F384A_X86_64_W_0_L_0,
+  PREFIX_VEX_0F3849_X86_64_L_0_W_1_M_1,
   PREFIX_VEX_0F384B_X86_64_L_0_W_0,
   PREFIX_VEX_0F3850_W_0,
   PREFIX_VEX_0F3851_W_0,
@@ -1213,8 +1226,12 @@  enum
   PREFIX_EVEX_0F383A,
   PREFIX_EVEX_0F3841,
   PREFIX_EVEX_0F384A_X86_64_W_0_L_2,
+  PREFIX_EVEX_0F384A,
+  PREFIX_EVEX_0F384B,
   PREFIX_EVEX_0F3852,
   PREFIX_EVEX_0F3853,
+  PREFIX_EVEX_0F385C,
+  PREFIX_EVEX_0F385E,
   PREFIX_EVEX_0F3868,
   PREFIX_EVEX_0F386D_X86_64_W_0_L_2,
   PREFIX_EVEX_0F3872,
@@ -1225,10 +1242,12 @@  enum
   PREFIX_EVEX_0F38AB,
 
   PREFIX_EVEX_0F3A07_X86_64_W_0_L_2,
+  PREFIX_EVEX_0F3A07,
   PREFIX_EVEX_0F3A08,
   PREFIX_EVEX_0F3A0A,
   PREFIX_EVEX_0F3A26,
   PREFIX_EVEX_0F3A27,
+  PREFIX_EVEX_0F3A2F,
   PREFIX_EVEX_0F3A42_W_0,
   PREFIX_EVEX_0F3A52,
   PREFIX_EVEX_0F3A53,
@@ -1237,6 +1256,8 @@  enum
   PREFIX_EVEX_0F3A66,
   PREFIX_EVEX_0F3A67,
   PREFIX_EVEX_0F3A77_X86_64_W_0_L_2,
+  PREFIX_EVEX_0F3A8D,
+  PREFIX_EVEX_0F3A8F,
   PREFIX_EVEX_0F3AC2,
 
   PREFIX_EVEX_MAP4_4x,
@@ -1310,6 +1331,7 @@  enum
   PREFIX_EVEX_MAP6_BA,
   PREFIX_EVEX_MAP6_BC,
   PREFIX_EVEX_MAP6_BE,
+  PREFIX_EVEX_MAP6_95,
   PREFIX_EVEX_MAP6_D6,
   PREFIX_EVEX_MAP6_D7,
 };
@@ -1601,6 +1623,7 @@  enum
   EVEX_LEN_0F381B,
   EVEX_LEN_0F3836,
   EVEX_LEN_0F384A_X86_64_W_0,
+  EVEX_LEN_0F384B,
   EVEX_LEN_0F385A,
   EVEX_LEN_0F385B,
   EVEX_LEN_0F386D_X86_64_W_0,
@@ -1625,6 +1648,7 @@  enum
   EVEX_LEN_MAP5_7E,
   EVEX_LEN_MAP6_80_W_0,
   EVEX_LEN_MAP6_80_W_1,
+  EVEX_LEN_MAP6_95_P_0_W_1,
 };
 
 enum
@@ -1884,6 +1908,9 @@  enum
   EVEX_W_MAP5_7E_P_1,
   EVEX_W_MAP6_80,
   EVEX_W_MAP6_81,
+  EVEX_W_MAP6_95_P_0,
+  EVEX_W_MAP6_95_P_1,
+  EVEX_W_MAP6_95_P_3,
 };
 
 typedef bool (*op_rtn) (instr_info *ins, int bytemode, int sizeflag);
@@ -2709,6 +2736,10 @@  static const char att_names_tmm[][8] = {
   "%tmm4", "%tmm5", "%tmm6", "%tmm7"
 };
 
+static const char att_names_bsr[][8] = {
+  "%bsr0"
+};
+
 static const char att_names_mask[][8] = {
   "%k0", "%k1", "%k2", "%k3", "%k4", "%k5", "%k6", "%k7"
 };
@@ -3095,6 +3126,10 @@  static const struct dis386 reg_table[][8] = {
   {
     { RM_TABLE (RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0_R_0) },
   },
+  /* REG_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3 */
+  {
+    { RM_TABLE (RM_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3_R_0) },
+  },
   /* REG_VEX_0F38F3_L_0_P_0 */
   {
     { Bad_Opcode },
@@ -4176,6 +4211,14 @@  static const struct dis386 prefix_table[][4] = {
     { "tileloaddrs",	{ TMM, MVexSIBMEM }, 0 },
   },
 
+  /* PREFIX_VEX_0F3849_X86_64_L_0_W_1_M_1 */
+  {
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { Bad_Opcode },
+    { REG_TABLE (REG_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3) },
+  },
+
   /* PREFIX_VEX_0F384B_X86_64_L_0_W_0 */
   {
     { Bad_Opcode },
@@ -8107,6 +8150,7 @@  static const struct dis386 vex_w_table[][2] = {
   {
     /* VEX_W_0F3849_X86_64_L_0 */
     { MOD_TABLE (MOD_VEX_0F3849_X86_64_L_0_W_0) },
+    { MOD_TABLE (MOD_VEX_0F3849_X86_64_L_0_W_1) },
   },
   {
     /* VEX_W_0F384A_X86_64 */
@@ -8683,6 +8727,11 @@  static const struct dis386 mod_table[][2] = {
     { PREFIX_TABLE (PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_0) },
     { PREFIX_TABLE (PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_1) },
   },
+  {
+    /* MOD_VEX_0F3849_X86_64_L_0_W_1 */
+    { Bad_Opcode },
+    { PREFIX_TABLE (PREFIX_VEX_0F3849_X86_64_L_0_W_1_M_1) },
+  },
 
 #include "i386-dis-evex-mod.h"
 };
@@ -8793,6 +8842,10 @@  static const struct dis386 rm_table[][8] = {
     /* RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_3 */
     { "tilezero",	{ TMM, Skip_MODRM }, 0 },
   },
+  {
+    /* RM_VEX_0F3849_X86_64_L_0_W_1_M_1_P_3_R_0 */
+    { "bsrinit",	{ BSR, Skip_MODRM }, 0 },
+  },
 };
 
 #define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
@@ -11920,6 +11973,9 @@  intel_operand_size (instr_info *ins, int bytemode, int sizeflag)
     case ymm_mode:
       oappend (ins, "YMMWORD PTR ");
       break;
+    case zmm_mode:
+      oappend (ins, "ZMMWORD PTR ");
+      break;
     case xmmq_mode:
     case evex_half_bcst_xmmqh_mode:
     case evex_half_bcst_xmmq_mode:
@@ -12357,6 +12413,9 @@  OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
 	  else if (bytemode == xmmdw_mode)
 	    shift -= 3;
 	  break;
+	case zmm_mode:
+	  shift = 6;
+	  break;
 	case ymm_mode:
 	  shift = 5;
 	  break;
@@ -13407,6 +13466,8 @@  print_vector_reg (instr_info *ins, unsigned int reg, int bytemode)
 	  abort ();
 	}
     }
+  else if (bytemode == zmm_mode)
+    names = att_names_zmm;
   else if (bytemode == ymm_mode)
     names = att_names_ymm;
   else if (bytemode == tmm_mode)
@@ -13482,6 +13543,18 @@  OP_XMM (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
   return true;
 }
 
+static bool
+OP_BSR (instr_info *ins, int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+  if (ins->modrm.reg)
+    {
+      oappend (ins, "(bad)");
+      return false;
+    }
+  oappend_register (ins, att_names_bsr[0]);
+  return true;
+}
+
 static bool
 OP_EM (instr_info *ins, int bytemode, int sizeflag)
 {
@@ -14252,9 +14325,45 @@  OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
 	}
       break;
     case 512:
-      names = att_names_zmm;
-      ins->evex_used |= EVEX_len_used;
-      break;
+      switch (bytemode)
+	{
+	case x_mode:
+	case v_mode:
+	  names = att_names_zmm;
+	  ins->evex_used |= EVEX_len_used;
+	  break;
+	case dq_mode:
+	  if (ins->rex & REX_W)
+	    names = att_names64;
+	  else if (bytemode == v_mode
+		   && !(sizeflag & DFLAG))
+	    names = att_names16;
+	  else
+	    names = att_names32;
+	  break;
+	case b_mode:
+	  names = att_names8rex;
+	  break;
+	case d_mode:
+	  names = att_names32;
+	  break;
+	case q_mode:
+	  names = att_names64;
+	  break;
+	case mask_bd_mode:
+	case mask_mode:
+	  if (reg > 0x7)
+	    {
+	      oappend (ins, "(bad)");
+	      return true;
+	    }
+	  names = att_names_mask;
+	  break;
+	default:
+	  abort ();
+	  return true;
+	}
+	break;
     default:
       abort ();
       break;
diff --git a/opcodes/i386-gen.c b/opcodes/i386-gen.c
index 11cc4ff19dc..dded2d906e6 100644
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -263,6 +263,8 @@  static const dependency isa_dependencies[] =
     "RTM|HLE" },
   { "TSXLDTRK",
     "RTM" },
+  { "ACE",
+    "AVX512F|64" },
   { "AMX_TILE",
     "XSAVE|64" },
   { "AMX_INT8",
@@ -470,6 +472,7 @@  static bitfield cpu_flags[] =
   BITFIELD (WAITPKG),
   BITFIELD (UINTR),
   BITFIELD (CLDEMOTE),
+  BITFIELD (ACE),
   BITFIELD (AMX_INT8),
   BITFIELD (AMX_BF16),
   BITFIELD (AMX_FP16),
@@ -571,6 +574,7 @@  static const struct {
   CLASS (RegSIMD),
   CLASS (RegMask),
   CLASS (RegBND),
+  CLASS (RegBS),
 };
 
 #undef CLASS
diff --git a/opcodes/i386-opc.h b/opcodes/i386-opc.h
index 0c5f7747ed2..a8d9ac59c8b 100644
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -359,6 +359,8 @@  enum i386_cpu
   CpuAVX10_2,
   /* Intel AMX-TRANSPOSE Instructions support required.  */
   CpuAMX_TRANSPOSE,
+  /* ACE instructions support required.  */
+  CpuACE,
   /* Not supported in the 64bit mode  */
   CpuNo64,
 
@@ -397,6 +399,7 @@  enum i386_cpu
 		   cpuapx_f:1, \
 		   cpuavx10_2:1, \
 		   cpuamx_transpose:1, \
+		   cpuace:1, \
       /* NOTE: This field needs to remain last. */ \
 		   cpuno64:1
 
@@ -889,6 +892,7 @@  enum operand_class
   RegSIMD, /* XMM/YMM/ZMM registers, distinguished by operand size */
   RegMask, /* Vector Mask register */
   RegBND, /* Bound register */
+  RegBS, /* Block scale register */
 };
 
 /* Special operand instances.  */
diff --git a/opcodes/i386-opc.tbl b/opcodes/i386-opc.tbl
index 3d3e37b09aa..b85afcf5720 100644
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -62,6 +62,8 @@ 
 
 #define RegBND Class=RegBND
 
+#define RegBS Class=RegBS
+
 #define Mmword Qword
 #define Oword  Xmmword
 
@@ -118,6 +120,7 @@ 
 #define SpaceXOP0A OpcodeSpace=SPACE_XOP0A
 
 #define EVexMap4 OpcodeSpace=SPACE_MAP4|EVex128
+#define EVexMap6 OpcodeSpace=SPACE_MAP6
 
 #define Map5 OpcodeSpace=SPACE_MAP5
 #define Map6 OpcodeSpace=SPACE_MAP6
@@ -3234,10 +3237,12 @@  xresldtrk, 0xf20f01e9, TSXLDTRK, NoSuf, {}
 
 // TSXLDTRK instructions end.
 
-// AMX instructions.
+// AMX & ACE instructions.
 
 ldtilecfg, 0x49/0, APX_F(AMX_TILE), Modrm|Vex128|EVex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex }
+ldtilecfg, 0x49/0, ACE, Modrm|Vex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex }
 sttilecfg, 0x6649/0, APX_F(AMX_TILE), Modrm|Vex128|EVex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex }
+sttilecfg, 0x6649/0, ACE, Modrm|Vex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex }
 
 tcmmimfp16ps, 0x666c, AMX_COMPLEX, Modrm|Vex128|Space0F38|Src2VVVV|VexW0|NoSuf, { RegTMM, RegTMM, RegTMM }
 tcmmrlfp16ps, 0x6c, AMX_COMPLEX, Modrm|Vex128|Space0F38|Src2VVVV|VexW0|NoSuf, { RegTMM, RegTMM, RegTMM }
@@ -3250,14 +3255,18 @@  tdpbusd, 0x665e, AMX_INT8, Modrm|Vex128|Space0F38|Src2VVVV|VexW0|NoSuf, { RegTMM
 tdpbsud, 0xf35e, AMX_INT8, Modrm|Vex128|Space0F38|Src2VVVV|VexW0|NoSuf, { RegTMM, RegTMM, RegTMM }
 
 tileloadd, 0xf24b, APX_F(AMX_TILE), Sibmem|Vex128|EVex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex, RegTMM }
+tileloadd, 0xf24b, ACE, Sibmem|Vex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex, RegTMM }
 tileloaddt1, 0x664b, APX_F(AMX_TILE), Sibmem|Vex128|EVex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex, RegTMM }
+tileloaddt1, 0x664b, ACE, Sibmem|Vex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex, RegTMM }
 tileloaddrs, 0xf24a, APX_F(AMX_MOVRS), Sibmem|Vex128|EVex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex, RegTMM }
 tileloaddrst1, 0x664a, APX_F(AMX_MOVRS), Sibmem|Vex128|EVex128|Space0F38|VexW0|NoSuf, { Unspecified|BaseIndex, RegTMM }
 tilestored, 0xf34b, APX_F(AMX_TILE), Sibmem|Vex128|EVex128|Space0F38|VexW0|NoSuf, { RegTMM, Unspecified|BaseIndex }
+tilestored, 0xf34b, ACE, Sibmem|Vex128|Space0F38|VexW0|NoSuf, { RegTMM, Unspecified|BaseIndex }
 
 tilerelease, 0x49c0, AMX_TILE, Vex128|Space0F38|VexW0|NoSuf, {}
+tilerelease, 0x49c0, ACE, Vex128|Space0F38|VexW0|NoSuf, {}
 
-tilezero, 0xf249, AMX_TILE, Modrm|Vex128|Space0F38|VexW0|NoSuf, { RegTMM }
+tilezero, 0xf249, AMX_TILE|ACE, Modrm|Vex128|Space0F38|VexW0|NoSuf, { RegTMM }
 
 <z:pfx, z0:, z1:66>
 
@@ -3288,22 +3297,51 @@  tdpbhf8ps, 0xf2fd, AMX_FP8, Modrm|Vex128|Map5|Src2VVVV|VexW0|NoSuf, { RegTMM, Re
 tdphbf8ps, 0xf3fd, AMX_FP8, Modrm|Vex128|Map5|Src2VVVV|VexW0|NoSuf, { RegTMM, RegTMM, RegTMM }
 tdphf8ps, 0x66fd, AMX_FP8, Modrm|Vex128|Map5|Src2VVVV|VexW0|NoSuf, { RegTMM, RegTMM, RegTMM }
 
-tcvtrowd2ps, 0xf34a, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
-tcvtrowd2ps, 0xf307, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
+tcvtrowd2ps, 0xf34a, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
+tcvtrowd2ps, 0xf307, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
+
+tcvtrowps2bf16h, 0xf26d, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
+tcvtrowps2bf16h, 0xf207, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
+tcvtrowps2bf16l, 0xf36d, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
+tcvtrowps2bf16l, 0xf377, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
+tcvtrowps2phh, 0x6d, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
+tcvtrowps2phh, 0x07, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
+tcvtrowps2phl, 0x666d, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
+tcvtrowps2phl, 0xf277, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
+
+tilemovrow, 0x664a, AMX_AVX512|ACE, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
+tilemovrow, 0x6607, AMX_AVX512|ACE, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
+
+// AMX & ACE instructions end.
+
+// ACE instructions.
+
+bsrinit, 0xf249, ACE, Modrm|Vex128|Space0F38|VexW1|NoSuf, { RegBS }
+bsrmovf, 0x95, ACE, Modrm|EVex512|EVexMap6|VexW1|Src1VVVV|NoSuf, { RegZMM|Unspecified|BaseIndex, RegZMM, RegBS }
+bsrmovh, 0xf295, ACE, Modrm|EVex512|EVexMap6|VexW1|NoSuf, { RegZMM|Unspecified|BaseIndex, RegBS }
+bsrmovh, 0xf295, ACE, RegMem|Modrm|EVex512|EVexMap6|VexW0|NoSuf, { RegBS, RegZMM|Unspecified|BaseIndex }
+bsrmovl, 0xf395, ACE, Modrm|EVex512|EVexMap6|VexW1|NoSuf, { RegZMM|Unspecified|BaseIndex, RegBS }
+bsrmovl, 0xf395, ACE, RegMem|Modrm|EVex512|EVexMap6|VexW0|NoSuf, { RegBS, RegZMM|Unspecified|BaseIndex }
+
+tilemovcol, 0x662f, ACE, Modrm|EVex512|Space0F3A|VexW1|NoSuf, { Imm8, RegZMM, RegTMM }
+tilemovcol, 0x664b, ACE, Modrm|EVex512|Space0F38|VexW1|Src2VVVV|NoSuf, { Reg32, RegZMM, RegTMM }
+tilemovrow, 0x6607, ACE, Modrm|EVex512|Space0F3A|VexW1|NoSuf, { Imm8, RegZMM, RegTMM }
+tilemovrow, 0x664a, ACE, Modrm|EVex512|Space0F38|VexW1|Src2VVVV|NoSuf, { Reg32, RegZMM, RegTMM }
+
+top2bf16ps, 0xf35c, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }
 
-tcvtrowps2bf16h, 0xf26d, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
-tcvtrowps2bf16h, 0xf207, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
-tcvtrowps2bf16l, 0xf36d, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
-tcvtrowps2bf16l, 0xf377, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
-tcvtrowps2phh, 0x6d, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
-tcvtrowps2phh, 0x07, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
-tcvtrowps2phl, 0x666d, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
-tcvtrowps2phl, 0xf277, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
+top4bssd, 0xf25e, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }
+top4bsud, 0xf35e, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }
+top4busd, 0x665e, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }
+top4buud, 0x5e, ACE, Modrm|EVex512|Space0F38|VexW0|Src2VVVV|NoSuf, { RegZMM, RegZMM, RegTMM }
 
-tilemovrow, 0x664a, AMX_AVX512, Modrm|EVex512|Space0F38|Src2VVVV|VexW0|NoSuf, { Reg32, RegTMM, RegZMM }
-tilemovrow, 0x6607, AMX_AVX512, Modrm|EVex512|Space0F3A|VexW0|NoSuf, { Imm8, RegTMM, RegZMM }
+top4mxbf8ps, 0x8d, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
+top4mxbhf8ps, 0xf28d, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
+top4mxhbf8ps, 0xf38d, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
+top4mxhf8ps, 0x668d, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
+top4mxbssps, 0xf28f, ACE, Modrm|EVex512|Space0F3A|VexW0|Src2VVVV|NoSuf, { Imm8, RegZMM, RegZMM, RegTMM }
 
-// AMX instructions end.
+// ACE instructions end.
 
 // KEYLOCKER instructions.
 
diff --git a/opcodes/i386-reg.tbl b/opcodes/i386-reg.tbl
index 74234c503d6..ee6923252c9 100644
--- a/opcodes/i386-reg.tbl
+++ b/opcodes/i386-reg.tbl
@@ -344,7 +344,7 @@  zmm28, Class=RegSIMD|Zmmword, RegVRex|RegRex, 4, Dw2Inval, 79
 zmm29, Class=RegSIMD|Zmmword, RegVRex|RegRex, 5, Dw2Inval, 80
 zmm30, Class=RegSIMD|Zmmword, RegVRex|RegRex, 6, Dw2Inval, 81
 zmm31, Class=RegSIMD|Zmmword, RegVRex|RegRex, 7, Dw2Inval, 82
-// TMM registers for AMX
+// TMM registers for AMX/ACE
 tmm0, Class=RegSIMD|Tmmword, 0, 0, Dw2Inval, Dw2Inval
 tmm1, Class=RegSIMD|Tmmword, 0, 1, Dw2Inval, Dw2Inval
 tmm2, Class=RegSIMD|Tmmword, 0, 2, Dw2Inval, Dw2Inval
@@ -353,6 +353,8 @@  tmm4, Class=RegSIMD|Tmmword, 0, 4, Dw2Inval, Dw2Inval
 tmm5, Class=RegSIMD|Tmmword, 0, 5, Dw2Inval, Dw2Inval
 tmm6, Class=RegSIMD|Tmmword, 0, 6, Dw2Inval, Dw2Inval
 tmm7, Class=RegSIMD|Tmmword, 0, 7, Dw2Inval, Dw2Inval
+// Block scale register for ACE
+bsr0, Class=RegBS, 0, 0, Dw2Inval, Dw2Inval
 // Bound registers for MPX
 bnd0, Class=RegBND, 0, 0, Dw2Inval, 126
 bnd1, Class=RegBND, 0, 1, Dw2Inval, 127