[PATCH 2/4] x86: sub-divide APX_F - NDD
Jan Beulich
jbeulich@suse.com
Fri Nov 28 09:00:14 GMT 2025
While spec version 007 introduced the three-way APX-NCI-NDD-NF, let's
split the three aspects (NCI, NDD, and NF) in gas. Note that NDD also
applies to a number of EVEX-encoded insns with EVEX.ndd clear.
Some extra logic is needed in cpu_flags_match() to avoid the need to
add APX_NDD to CPU_FLAGS_COMMON.
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1241,6 +1241,7 @@ static const arch_entry cpu_arch[] =
SUBARCH (user_msr, USER_MSR, USER_MSR, false),
SUBARCH (apx_f, APX_F, ANY_APX_F, false),
SUBARCH (apx_nci, APX_NCI, ANY_APX_NCI, false),
+ SUBARCH (apx_ndd, APX_NDD, ANY_APX_NDD, false),
VECARCH (avx10.2, AVX10_2, ANY_AVX10_2, set),
SUBARCH (gmism2, GMISM2, GMISM2, false),
SUBARCH (gmiccs, GMICCS, GMICCS, false),
@@ -1944,6 +1945,10 @@ cpu_flags_all_zero (const union i386_cpu
{
switch (ARRAY_SIZE(x->array))
{
+ case 6:
+ if (x->array[5])
+ return 0;
+ /* Fall through. */
case 5:
if (x->array[4])
return 0;
@@ -1973,6 +1978,10 @@ cpu_flags_equal (const union i386_cpu_fl
{
switch (ARRAY_SIZE(x->array))
{
+ case 6:
+ if (x->array[5] != y->array[5])
+ return 0;
+ /* Fall through. */
case 5:
if (x->array[4] != y->array[4])
return 0;
@@ -2010,6 +2019,9 @@ cpu_flags_and (i386_cpu_flags x, i386_cp
{
switch (ARRAY_SIZE (x.array))
{
+ case 6:
+ x.array [5] &= y.array [5];
+ /* Fall through. */
case 5:
x.array [4] &= y.array [4];
/* Fall through. */
@@ -2036,6 +2048,9 @@ cpu_flags_or (i386_cpu_flags x, i386_cpu
{
switch (ARRAY_SIZE (x.array))
{
+ case 6:
+ x.array [5] |= y.array [5];
+ /* Fall through. */
case 5:
x.array [4] |= y.array [4];
/* Fall through. */
@@ -2062,6 +2077,9 @@ cpu_flags_and_not (i386_cpu_flags x, i38
{
switch (ARRAY_SIZE (x.array))
{
+ case 6:
+ x.array [5] &= ~y.array [5];
+ /* Fall through. */
case 5:
x.array [4] &= ~y.array [4];
/* Fall through. */
@@ -2330,6 +2348,17 @@ cpu_flags_match (const insn_template *t)
memset (&any, 0, sizeof (any));
}
}
+ else if (t->opcode_modifier.evex
+ /* Implicitly !t->opcode_modifier.vex. */
+ && all.bitfield.cpuapx_f
+ && (t->opcode_modifier.nf
+ || (all.bitfield.cpuadx && t->opcode_modifier.vexvvvv)))
+ {
+ /* APX_NDD can't be combined with other ISAs in the opcode table.
+ Respective entries (ADCX, ADOX, LZCNT, POPCNT, and TZCNT) use APX_F
+ instead, which are amended here. No need to clear cpuapx_f, though. */
+ all.bitfield.cpuapx_ndd = true;
+ }
if (flag_code != CODE_64BIT)
active = cpu_flags_and_not (cpu_arch_flags, cpu_64_flags);
@@ -2670,11 +2699,11 @@ operand_size_match (const insn_template
{
unsigned int given = i.operands - j - 1;
- /* For FMA4 and XOP insns VEX.W controls just the first two
- register operands. And APX_F insns just swap the two source operands,
+ /* For FMA4 and XOP insns VEX.W controls just the first two register
+ operands. And APX_F / APX_NDD insns just swap the two source operands,
with the 3rd one being the destination. */
if (is_cpu (t, CpuFMA4) || is_cpu (t, CpuXOP)
- || is_cpu (t, CpuAPX_F))
+ || is_cpu (t, CpuAPX_F)|| is_cpu (t, CpuAPX_NDD))
given = j < 2 ? 1 - j : j;
if (i.types[given].bitfield.class == Reg
@@ -9598,12 +9627,13 @@ match_template (char mnem_suffix)
/* Try reversing direction of operands. */
j = is_cpu (t, CpuFMA4)
|| is_cpu (t, CpuXOP)
- || is_cpu (t, CpuAPX_F) ? 1 : i.operands - 1;
+ || is_cpu (t, CpuAPX_F)
+ || is_cpu (t, CpuAPX_NDD) ? 1 : i.operands - 1;
overlap0 = operand_type_and (i.types[0], operand_types[j]);
overlap1 = operand_type_and (i.types[j], operand_types[0]);
overlap2 = operand_type_and (i.types[1], operand_types[1]);
gas_assert (t->operands != 3 || !check_register
- || is_cpu (t, CpuAPX_F));
+ || is_cpu (t, CpuAPX_F) || is_cpu (t, CpuAPX_NDD));
if (!operand_type_match (overlap0, i.types[0])
|| !operand_type_match (overlap1, i.types[j])
|| (t->operands == 3
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -221,6 +221,7 @@ accept various extension mnemonics. For
@code{msr_imm},
@code{apx_f},
@code{apx_nci},
+@code{apx_ndd},
@code{avx10.2},
@code{avx10.2/512},
@code{avx10.2/256},
@@ -1733,7 +1734,7 @@ supported on the CPU specified. The cho
@item @samp{.padlock} @tab @samp{.clzero} @tab @samp{.mwaitx} @tab @samp{.rdpru}
@item @samp{.mcommit} @tab @samp{.sev_es} @tab @samp{.snp} @tab @samp{.invlpgb}
@item @samp{.tlbsync} @tab @samp{.rmpquery} @tab @samp{.rmpread} @tab @samp{.apx_f}
-@item @samp{.apx_nci}
+@item @samp{.apx_nci} @tab @samp{.apx_ndd}
@item @samp{.gmism2} @tab @samp{.gmiccs} @tab @samp{.padlockrng2} @tab @samp{.padlockphe2}
@item @samp{.padlockxmodx}
--- a/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.l
+++ b/gas/testsuite/gas/i386/x86-64-apx-egpr-inval.l
@@ -202,8 +202,8 @@
.*:211: Error: no VEX/XOP encoding for `and'
.*:212: Error: no VEX/XOP encoding for `and'
.*:213: Error: .* `and'
-.*:214: Error: no VEX/XOP encoding for `and'
-.*:215: Error: no VEX/XOP encoding for `and'
+.*:214: Error: .* `and'
+.*:215: Error: .* `and'
.*:216: Error: .* `and'
.*:219: Error: .* `andn'
#pass
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -301,6 +301,8 @@ static const dependency isa_dependencies
"XSAVE|64" },
{ "APX_NCI",
"APX_F" },
+ { "APX_NDD",
+ "APX_F" },
{ "PadLock",
"FXSR" },
{ "PadLockRNG2",
@@ -483,6 +485,7 @@ static bitfield cpu_flags[] =
BITFIELD (RMPQUERY),
BITFIELD (RMPREAD),
BITFIELD (APX_NCI),
+ BITFIELD (APX_NDD),
BITFIELD (64),
BITFIELD (No64),
#ifdef CpuUnused
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -322,6 +322,8 @@ enum i386_cpu
CpuRMPREAD,
/* Intel APX New Conditional Instructions support required. */
CpuAPX_NCI,
+ /* Intel APX Non-Destructive Destination support required. */
+ CpuAPX_NDD,
/* NOTE: These items, which can be combined with other ISA flags above, need
to remain second to last and in sync with CPU_FLAGS_COMMON. */
@@ -373,7 +375,7 @@ enum i386_cpu
/* If you get a compiler error for zero width of an unused field,
comment the respective one out. */
-/* #define CpuUnused (CpuMax + 1) */
+#define CpuUnused (CpuMax + 1)
#define CpuAttrUnused (CpuIsaBits + CpuMax + 1 - CpuAttrEnums)
#define CPU_FLAGS_COMMON \
@@ -558,6 +560,7 @@ typedef union i386_cpu_flags
unsigned int cpurmpquery:1;
unsigned int cpurmpread:1;
unsigned int cpuapx_nci:1;
+ unsigned int cpuapx_ndd:1;
CPU_FLAGS_COMMON;
#ifdef CpuUnused
unsigned int unused:(CpuNumOfBits - CpuUnused);
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -325,22 +325,22 @@ sti, 0xfb, 0, NoSuf, {}
sub:5::Optimize:::Optimize:NF, +
xor:6:C:Optimize::::NF>
-<alu2>, <alu2:opc> << 3, APX_F, D|<alu2:c>|W|CheckOperandSize|Modrm|No_sSuf|DstVVVV|EVexMap4|<alu2:nf>|<alu2:optz>, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
+<alu2>, <alu2:opc> << 3, APX_NDD, D|<alu2:c>|W|CheckOperandSize|Modrm|No_sSuf|DstVVVV|EVexMap4|<alu2:nf>|<alu2:optz>, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
<alu2>, <alu2:opc> << 3, 0, D|W|CheckOperandSize|Modrm|No_sSuf|HLEPrefixLock|<alu2:optz>|<alu2:optt>, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<alu2>, <alu2:opc> << 3, APX_F, D|W|CheckOperandSize|Modrm|No_sSuf|EVexMap4|<alu2:nf>, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<alu2>, 0x83/<alu2:opc>, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|<alu2:nf>|<alu2:optiE>, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+<alu2>, <alu2:opc> << 3, APX_NDD, D|W|CheckOperandSize|Modrm|No_sSuf|EVexMap4|<alu2:nf>, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+<alu2>, 0x83/<alu2:opc>, APX_NDD, Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|<alu2:nf>|<alu2:optiE>, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
<alu2>, 0x83/<alu2:opc>, 0, Modrm|No_bSuf|No_sSuf|HLEPrefixLock|<alu2:opti>, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<alu2>, 0x83/<alu2:opc>, APX_F, Modrm|No_bSuf|No_sSuf|EVexMap4|<alu2:nf>|<alu2:optiE>, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+<alu2>, 0x83/<alu2:opc>, APX_NDD, Modrm|No_bSuf|No_sSuf|EVexMap4|<alu2:nf>|<alu2:optiE>, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<alu2>, 0x04 | (<alu2:opc> << 3), 0, W|No_sSuf|<alu2:opti>, { Imm8|Imm16|Imm32|Imm32S, Acc|Byte|Word|Dword|Qword }
-<alu2>, 0x80/<alu2:opc>, APX_F, W|Modrm|CheckOperandSize|No_sSuf|DstVVVV|EVexMap4|<alu2:nf>|<alu2:optiE>, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
+<alu2>, 0x80/<alu2:opc>, APX_NDD, W|Modrm|CheckOperandSize|No_sSuf|DstVVVV|EVexMap4|<alu2:nf>|<alu2:optiE>, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
<alu2>, 0x80/<alu2:opc>, 0, W|Modrm|No_sSuf|HLEPrefixLock|<alu2:opti>, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<alu2>, 0x80/<alu2:opc>, APX_F, W|Modrm|EVexMap4|No_sSuf|<alu2:nf>|<alu2:optiE>, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+<alu2>, 0x80/<alu2:opc>, APX_NDD, W|Modrm|EVexMap4|No_sSuf|<alu2:nf>|<alu2:optiE>, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<alu2>
// clr with 1 operand is really xor with 2 operands.
clr, 0x30, 0, W|Modrm|No_sSuf|RegKludge|Optimize, { Reg8|Reg16|Reg32|Reg64 }
-clr, 0x30, APX_F, W|Modrm|No_sSuf|RegKludge|EVexMap4|NF, { Reg8|Reg16|Reg32|Reg64 }
+clr, 0x30, APX_NDD, W|Modrm|No_sSuf|RegKludge|EVexMap4|NF, { Reg8|Reg16|Reg32|Reg64 }
cmp, 0x38, 0, D|W|CheckOperandSize|Modrm|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
cmp, 0x83/7, 0, Modrm|No_bSuf|No_sSuf, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
@@ -371,17 +371,17 @@ ctest<scc>, 0xf60<scc:opc>/0, APX_NCI, W
<incdec:opc, inc:0, dec:1>
<incdec>, 0x40 | (<incdec:opc> << 3), No64, No_bSuf|No_sSuf|No_qSuf, { Reg16|Reg32 }
-<incdec>, 0xfe/<incdec:opc>, APX_F, W|Modrm|No_sSuf|CheckOperandSize|DstVVVV|EVexMap4|NF, {Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64}
+<incdec>, 0xfe/<incdec:opc>, APX_NDD, W|Modrm|No_sSuf|CheckOperandSize|DstVVVV|EVexMap4|NF, {Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64}
<incdec>, 0xfe/<incdec:opc>, 0, W|Modrm|No_sSuf|HLEPrefixLock, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<incdec>, 0xfe/<incdec:opc>, APX_F, W|Modrm|No_sSuf|EVexMap4|NF, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+<incdec>, 0xfe/<incdec:opc>, APX_NDD, W|Modrm|No_sSuf|EVexMap4|NF, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<incdec>
<alu1:opc:nf, not:2:, neg:3:NF>
-<alu1>, 0xf6/<alu1:opc>, APX_F, W|Modrm|CheckOperandSize|No_sSuf|DstVVVV|EVexMap4|<alu1:nf>, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
+<alu1>, 0xf6/<alu1:opc>, APX_NDD, W|Modrm|CheckOperandSize|No_sSuf|DstVVVV|EVexMap4|<alu1:nf>, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
<alu1>, 0xf6/<alu1:opc>, 0, W|Modrm|No_sSuf|HLEPrefixLock, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<alu1>, 0xf6/<alu1:opc>, APX_F, W|Modrm|No_sSuf|EVexMap4|<alu1:nf>, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+<alu1>, 0xf6/<alu1:opc>, APX_NDD, W|Modrm|No_sSuf|EVexMap4|<alu1:nf>, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<alu1>
@@ -417,36 +417,36 @@ cqto, 0x99, x64, Size64|NoSuf, {}
<mul:opc:opt, mul:4:Optimize, imul:5:>
<mul>, 0xf6/<mul:opc>, 0, W|Modrm|No_sSuf, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<mul>, 0xf6/<mul:opc>, APX_F, W|Modrm|No_sSuf|EVexMap4|NF|<mul:opt>, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-imul, 0xaf, APX_F, C|Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|NF, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64 }
+<mul>, 0xf6/<mul:opc>, APX_NDD, W|Modrm|No_sSuf|EVexMap4|NF|<mul:opt>, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+imul, 0xaf, APX_NDD, C|Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|NF, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64 }
imul, 0xfaf, i386, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
-imul, 0xaf, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+imul, 0xaf, APX_NDD, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
imul, 0x6b, i186, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
-imul, 0x6b, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF|Optimize, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
-imulzu, 0x6b, APX_F, Modrm|No_bSuf|No_sSuf|EVexMap4|NF|ZU|Optimize, { Imm8S, Reg16|Unspecified|BaseIndex, Reg16 }
+imul, 0x6b, APX_NDD, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF|Optimize, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+imulzu, 0x6b, APX_NDD, Modrm|No_bSuf|No_sSuf|EVexMap4|NF|ZU|Optimize, { Imm8S, Reg16|Unspecified|BaseIndex, Reg16 }
imul, 0x69, i186, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
-imul, 0x69, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF|Optimize, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
-imulzu, 0x69, APX_F, Modrm|No_bSuf|No_sSuf|EVexMap4|NF|ZU|Optimize, { Imm16, Reg16|Unspecified|BaseIndex, Reg16 }
+imul, 0x69, APX_NDD, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF|Optimize, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+imulzu, 0x69, APX_NDD, Modrm|No_bSuf|No_sSuf|EVexMap4|NF|ZU|Optimize, { Imm16, Reg16|Unspecified|BaseIndex, Reg16 }
// imul with 2 operands mimics imul with 3 by putting the register in
// both i.rm.reg & i.rm.regmem fields. RegKludge enables this
// transformation.
imul, 0x6b, i186, Modrm|No_bSuf|No_sSuf|RegKludge, { Imm8S, Reg16|Reg32|Reg64 }
-imul, 0x6b, APX_F, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF|Optimize, { Imm8S, Reg16|Reg32|Reg64 }
+imul, 0x6b, APX_NDD, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF|Optimize, { Imm8S, Reg16|Reg32|Reg64 }
imul, 0x69, i186, Modrm|No_bSuf|No_sSuf|RegKludge, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64 }
-imul, 0x69, APX_F, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF|Optimize, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64 }
+imul, 0x69, APX_NDD, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF|Optimize, { Imm16|Imm32|Imm32S, Reg16|Reg32|Reg64 }
// ZU is omitted here, for colliding with RegKludge. process_operands() will
// replace the constraint value after processing RegKludge.
-imulzu, 0x6b, APX_F, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF/*|ZU*/|Optimize, { Imm8S, Reg16 }
-imulzu, 0x69, APX_F, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF/*|ZU*/|Optimize, { Imm16, Reg16 }
+imulzu, 0x6b, APX_NDD, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF/*|ZU*/|Optimize, { Imm8S, Reg16 }
+imulzu, 0x69, APX_NDD, Modrm|No_bSuf|No_sSuf|RegKludge|EVexMap4|NF/*|ZU*/|Optimize, { Imm16, Reg16 }
<mul>
<div:opc, div:6, idiv:7>
<div>, 0xf6/<div:opc>, 0, W|Modrm|No_sSuf, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<div>, 0xf6/<div:opc>, APX_F, W|Modrm|No_sSuf|EVexMap4|NF, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+<div>, 0xf6/<div:opc>, APX_NDD, W|Modrm|No_sSuf|EVexMap4|NF, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<div>, 0xf6/<div:opc>, 0, W|CheckOperandSize|Modrm|No_sSuf, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Acc|Byte|Word|Dword|Qword }
-<div>, 0xf6/<div:opc>, APX_F, W|CheckOperandSize|Modrm|No_sSuf|EVexMap4|NF, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Acc|Byte|Word|Dword|Qword }
+<div>, 0xf6/<div:opc>, APX_NDD, W|CheckOperandSize|Modrm|No_sSuf|EVexMap4|NF, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Acc|Byte|Word|Dword|Qword }
<div>
@@ -460,27 +460,27 @@ imulzu, 0x69, APX_F, Modrm|No_bSuf|No_sS
shr:5:Imm8:::Optimize:NF, +
sar:7:Imm8:::Optimize:NF>
-<sr>, 0xd0/<sr:opc>, APX_F, W|Modrm|No_sSuf|CheckOperandSize|DstVVVV|EVexMap4|<sr:opt1>|<sr:nf>, { Imm1, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
+<sr>, 0xd0/<sr:opc>, APX_NDD, W|Modrm|No_sSuf|CheckOperandSize|DstVVVV|EVexMap4|<sr:opt1>|<sr:nf>, { Imm1, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
<sr>, 0xd0/<sr:opc>, 0, W|Modrm|No_sSuf|<sr:opt1>, { Imm1, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<sr>, 0xd0/<sr:opc>, APX_F, W|Modrm|No_sSuf|EVexMap4|<sr:opt1>|<sr:nf>, { Imm1, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<sr>, 0xc0/<sr:opc>, APX_F, W|Modrm|No_sSuf|CheckOperandSize|DstVVVV|EVexMap4|<sr:opti>|<sr:nf>, { <sr:imm8>, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
+<sr>, 0xd0/<sr:opc>, APX_NDD, W|Modrm|No_sSuf|EVexMap4|<sr:opt1>|<sr:nf>, { Imm1, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+<sr>, 0xc0/<sr:opc>, APX_NDD, W|Modrm|No_sSuf|CheckOperandSize|DstVVVV|EVexMap4|<sr:opti>|<sr:nf>, { <sr:imm8>, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
<sr>, 0xc0/<sr:opc>, i186, W|Modrm|No_sSuf, { <sr:imm8>, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<sr>, 0xc0/<sr:opc>, APX_F, W|Modrm|No_sSuf|EVexMap4|<sr:opti>|<sr:nf>, { <sr:imm8>, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<sr>, 0xd2/<sr:opc>, APX_F, W|Modrm|No_sSuf|CheckOperandSize|DstVVVV|EVexMap4|<sr:optc>|<sr:nf>, { ShiftCount, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
+<sr>, 0xc0/<sr:opc>, APX_NDD, W|Modrm|No_sSuf|EVexMap4|<sr:opti>|<sr:nf>, { <sr:imm8>, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+<sr>, 0xd2/<sr:opc>, APX_NDD, W|Modrm|No_sSuf|CheckOperandSize|DstVVVV|EVexMap4|<sr:optc>|<sr:nf>, { ShiftCount, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg8|Reg16|Reg32|Reg64 }
<sr>, 0xd2/<sr:opc>, 0, W|Modrm|No_sSuf|<sr:optc>, { ShiftCount, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-<sr>, 0xd2/<sr:opc>, APX_F, W|Modrm|No_sSuf|EVexMap4|<sr:optc>|<sr:nf>, { ShiftCount, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+<sr>, 0xd2/<sr:opc>, APX_NDD, W|Modrm|No_sSuf|EVexMap4|<sr:optc>|<sr:nf>, { ShiftCount, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<sr>, 0xd0/<sr:opc>, 0, W|Modrm|No_sSuf|<sr:opt1>, { Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<sr>
<shd:opc, l:0, r:8>
-sh<shd>d, 0x24 | <shd:opc>, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|NF, { Imm8, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+sh<shd>d, 0x24 | <shd:opc>, APX_NDD, Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|NF, { Imm8, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
sh<shd>d, 0x0fa4 | <shd:opc>, i386, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Imm8, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-sh<shd>d, 0x24 | <shd:opc>, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Imm8, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-sh<shd>d, 0xa5 | <shd:opc>, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|NF, { ShiftCount, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+sh<shd>d, 0x24 | <shd:opc>, APX_NDD, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Imm8, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+sh<shd>d, 0xa5 | <shd:opc>, APX_NDD, Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|NF, { ShiftCount, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
sh<shd>d, 0x0fa5 | <shd:opc>, i386, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { ShiftCount, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-sh<shd>d, 0xa5 | <shd:opc>, APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { ShiftCount, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+sh<shd>d, 0xa5 | <shd:opc>, APX_NDD, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { ShiftCount, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
sh<shd>d, 0x0fa5 | <shd:opc>, i386, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<shd>
@@ -2039,6 +2039,9 @@ blsi, 0xf3/3, APX_F(BMI), Modrm|CheckOpe
blsmsk, 0xf3/2, APX_F(BMI), Modrm|CheckOperandSize|Vex128|EVex128|Space0F38|DstVVVV|No_bSuf|No_wSuf|No_sSuf|NF, { Reg32|Reg64|Unspecified|BaseIndex, Reg32|Reg64 }
blsr, 0xf3/1, APX_F(BMI), Modrm|CheckOperandSize|Vex128|EVex128|Space0F38|DstVVVV|No_bSuf|No_wSuf|No_sSuf|NF, { Reg32|Reg64|Unspecified|BaseIndex, Reg32|Reg64 }
tzcnt, 0xf30fbc, BMI, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+// EVEX-encoded ADCX, ADOX, LZCNT, POPCNT, and TZCNT require APX-NCI-NDD-NF
+// even with EVEX.nf clear, yet we don't reflect this here. cpu_flags_match()
+// takes care of these cases.
tzcnt, 0xf4, BMI&APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
// TBM instructions
@@ -2117,10 +2120,12 @@ insertq, 0xf20f78, SSE4a, Modrm|NoSuf, {
// LZCNT instruction
lzcnt, 0xf30fbd, LZCNT, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+// See comment ahead of the APX form of TZCNT.
lzcnt, 0xf5, LZCNT&APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
// POPCNT instruction
popcnt, 0xf30fb8, POPCNT, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+// See comment ahead of the APX form of TZCNT.
popcnt, 0x88, POPCNT&APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4|NF, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
// VIA PadLock extensions.
@@ -2163,6 +2168,7 @@ xmodexp, 0xf30fa6f8, PadLockXMODX, NoSuf
// Multy-precision Add Carry, rdseed instructions.
<adx:pfx, c:66, o:f3>
+// See comment ahead of the APX form of TZCNT.
ad<adx>x, 0x<adx:pfx>66, ADX&APX_F, C|Modrm|CheckOperandSize|No_bSuf|No_wSuf|No_sSuf|DstVVVV|EVexMap4, { Reg32|Reg64|Unspecified|BaseIndex, Reg32|Reg64, Reg32|Reg64 }
ad<adx>x, 0x<adx:pfx>0f38f6, ADX, Modrm|CheckOperandSize|IgnoreSize|No_bSuf|No_wSuf|No_sSuf, { Reg32|Reg64|Unspecified|BaseIndex, Reg32|Reg64 }
ad<adx>x, 0x<adx:pfx>66, ADX&APX_F, Modrm|CheckOperandSize|No_bSuf|No_wSuf|No_sSuf|EVexMap4, { Reg32|Reg64|Unspecified|BaseIndex, Reg32|Reg64 }
More information about the Binutils
mailing list