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
@@ -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.
@@ -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;
@@ -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}
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
@@ -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*"]
@@ -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 },
+ },
};
@@ -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 },
@@ -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 },
+ },
@@ -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 */
@@ -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;
@@ -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
@@ -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. */
@@ -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.
@@ -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