[PATCH 1/4] x86: sub-divide APX_F - NCI
Jan Beulich
jbeulich@suse.com
Fri Nov 28 08:59:31 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.
While adjusting CMOVcc and CFCMOVcc, drop the bogus CpuCMOV dependencies.
Such a requirement was never specified in any public doc revision.
Note also that the EVEX-encoded forms of TEST were lacking CpuAPX_F so
far.
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -1239,7 +1239,8 @@ static const arch_entry cpu_arch[] =
SUBARCH (pbndkb, PBNDKB, PBNDKB, false),
VECARCH (avx10.1, AVX10_1, ANY_AVX512F, set),
SUBARCH (user_msr, USER_MSR, USER_MSR, false),
- SUBARCH (apx_f, APX_F, APX_F, false),
+ SUBARCH (apx_f, APX_F, ANY_APX_F, false),
+ SUBARCH (apx_nci, APX_NCI, ANY_APX_NCI, false),
VECARCH (avx10.2, AVX10_2, ANY_AVX10_2, set),
SUBARCH (gmism2, GMISM2, GMISM2, false),
SUBARCH (gmiccs, GMICCS, GMICCS, false),
--- a/gas/doc/c-i386.texi
+++ b/gas/doc/c-i386.texi
@@ -220,6 +220,7 @@ accept various extension mnemonics. For
@code{user_msr},
@code{msr_imm},
@code{apx_f},
+@code{apx_nci},
@code{avx10.2},
@code{avx10.2/512},
@code{avx10.2/256},
@@ -1732,6 +1733,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{.gmism2} @tab @samp{.gmiccs} @tab @samp{.padlockrng2} @tab @samp{.padlockphe2}
@item @samp{.padlockxmodx}
--- a/opcodes/i386-gen.c
+++ b/opcodes/i386-gen.c
@@ -299,6 +299,8 @@ static const dependency isa_dependencies
"64" },
{ "APX_F",
"XSAVE|64" },
+ { "APX_NCI",
+ "APX_F" },
{ "PadLock",
"FXSR" },
{ "PadLockRNG2",
@@ -480,6 +482,7 @@ static bitfield cpu_flags[] =
BITFIELD (SNP),
BITFIELD (RMPQUERY),
BITFIELD (RMPREAD),
+ BITFIELD (APX_NCI),
BITFIELD (64),
BITFIELD (No64),
#ifdef CpuUnused
--- a/opcodes/i386-opc.h
+++ b/opcodes/i386-opc.h
@@ -320,6 +320,8 @@ enum i386_cpu
CpuRMPQUERY,
/* RMPREAD instruction required */
CpuRMPREAD,
+ /* Intel APX New Conditional Instructions support required. */
+ CpuAPX_NCI,
/* 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. */
@@ -371,7 +373,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 \
@@ -555,6 +557,7 @@ typedef union i386_cpu_flags
unsigned int cpusnp:1;
unsigned int cpurmpquery:1;
unsigned int cpurmpread:1;
+ unsigned int cpuapx_nci:1;
CPU_FLAGS_COMMON;
#ifdef CpuUnused
unsigned int unused:(CpuNumOfBits - CpuUnused);
--- a/opcodes/i386-opc.tbl
+++ b/opcodes/i386-opc.tbl
@@ -346,25 +346,25 @@ cmp, 0x38, 0, D|W|CheckOperandSize|Modrm
cmp, 0x83/7, 0, Modrm|No_bSuf|No_sSuf, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
cmp, 0x3c, 0, W|No_sSuf, { Imm8|Imm16|Imm32|Imm32S, Acc|Byte|Word|Dword|Qword }
cmp, 0x80/7, 0, W|Modrm|No_sSuf, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-cmp, 0x380a, APX_F, D|W|CheckOperandSize|EVexMap4|Scc|Modrm|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-cmp, 0x830a/7, APX_F, Modrm|EVexMap4|Scc|No_bSuf|No_sSuf, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-cmp, 0x800a/7, APX_F, W|Modrm|EVexMap4|Scc|No_sSuf, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+cmp, 0x380a, APX_NCI, D|W|CheckOperandSize|EVexMap4|Scc|Modrm|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+cmp, 0x830a/7, APX_NCI, Modrm|EVexMap4|Scc|No_bSuf|No_sSuf, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+cmp, 0x800a/7, APX_NCI, W|Modrm|EVexMap4|Scc|No_sSuf, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<scc:opc, o:0, no:1, b:2, c:2, nae:2, nb:3, nc:3, ae:3, e:4, z:4, ne:5, nz:5, be:6, na:6, nbe:7, a:7, +
s:8, ns:9, t:a, f:b, l:c, nge:c, nl:d, ge:d, le:e, ng:e, nle:f, g:f>
-ccmp<scc>, 0x380<scc:opc>, APX_F, D|W|CheckOperandSize|Modrm|EVexMap4|Scc|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-ccmp<scc>, 0x830<scc:opc>/7, APX_F, Modrm|EVexMap4|Scc|No_bSuf|No_sSuf, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-ccmp<scc>, 0x800<scc:opc>/7, APX_F, W|Modrm|EVexMap4|Scc|No_sSuf, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+ccmp<scc>, 0x380<scc:opc>, APX_NCI, D|W|CheckOperandSize|Modrm|EVexMap4|Scc|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+ccmp<scc>, 0x830<scc:opc>/7, APX_NCI, Modrm|EVexMap4|Scc|No_bSuf|No_sSuf, { Imm8S, Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+ccmp<scc>, 0x800<scc:opc>/7, APX_NCI, W|Modrm|EVexMap4|Scc|No_sSuf, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
test, 0x84, 0, D|W|C|CheckOperandSize|Modrm|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
test, 0xa8, 0, W|No_sSuf|Optimize, { Imm8|Imm16|Imm32|Imm32S, Acc|Byte|Word|Dword|Qword }
test, 0xf6/0, 0, W|Modrm|No_sSuf|Optimize, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-test, 0x840a, 0, D|W|C|CheckOperandSize|Modrm|EVexMap4|Scc|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-test, 0xf60a/0, 0, W|Modrm|EVexMap4|Scc|No_sSuf|Optimize, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+test, 0x840a, APX_NCI, D|W|C|CheckOperandSize|Modrm|EVexMap4|Scc|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+test, 0xf60a/0, APX_NCI, W|Modrm|EVexMap4|Scc|No_sSuf|Optimize, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-ctest<scc>, 0x840<scc:opc>, APX_F, D|W|C|CheckOperandSize|Modrm|EVexMap4|Scc|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
-ctest<scc>, 0xf60<scc:opc>/0, APX_F, W|Modrm|EVexMap4|Scc|No_sSuf|Optimize, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+ctest<scc>, 0x840<scc:opc>, APX_NCI, D|W|C|CheckOperandSize|Modrm|EVexMap4|Scc|No_sSuf, { Reg8|Reg16|Reg32|Reg64, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
+ctest<scc>, 0xf60<scc:opc>/0, APX_NCI, W|Modrm|EVexMap4|Scc|No_sSuf|Optimize, { Imm8|Imm16|Imm32|Imm32S, Reg8|Reg16|Reg32|Reg64|Unspecified|BaseIndex }
<scc>
@@ -561,11 +561,11 @@ loopne, 0xe0, x64, JumpByte|No_bSuf|No_w
// Set byte on flag instructions.
set<cc>, 0xf9<cc:opc>/0, i386, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf, { Reg8|Unspecified|BaseIndex }
-set<cc>, 0xf24<cc:opc>/0, APX_F, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4, { Reg8|Unspecified|BaseIndex }
-setzu<cc>, 0xf24<cc:opc>/0, APX_F, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4|ZU, { Reg8 }
+set<cc>, 0xf24<cc:opc>/0, APX_NCI, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4, { Reg8|Unspecified|BaseIndex }
+setzu<cc>, 0xf24<cc:opc>/0, APX_NCI, Modrm|No_wSuf|No_lSuf|No_sSuf|No_qSuf|VexWIG|EVexMap4|ZU, { Reg8 }
// As an extension, allow SETcc without the ZU infix, instead taking the full
// register as operand.
-set<cc>, 0xf24<cc:opc>/0, APX_F, Modrm|No_bSuf|No_wSuf|No_sSuf|EVexMap4|ZU, { Reg32|Reg64 }
+set<cc>, 0xf24<cc:opc>/0, APX_NCI, Modrm|No_bSuf|No_wSuf|No_sSuf|EVexMap4|ZU, { Reg32|Reg64 }
salc, 0xd6, No64, No_wSuf|No_lSuf|No_sSuf|No_qSuf, {}
// String manipulation.
@@ -1001,11 +1001,11 @@ udb, 0xd6, x64, NoSuf, {}
// C (commutative) isn't quite correct here on its own; the condition also
// needs inverting when source operands are swapped in order to convert to
// legacy encoding. The assembler will take care of that.
-cmov<cc>, 0x4<cc:opc>, CMOV&APX_F, C|Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|Optimize, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64 }
+cmov<cc>, 0x4<cc:opc>, APX_NCI, C|Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|Optimize, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64 }
cmov<cc>, 0xf4<cc:opc>, CMOV, Modrm|CheckOperandSize|No_bSuf|No_sSuf, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
-cfcmov<cc>, 0x4<cc:opc>, CMOV&APX_F, Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|EVexNF|Optimize, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64 }
-cfcmov<cc>, 0x4<cc:opc>, CMOV&APX_F, D|Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
+cfcmov<cc>, 0x4<cc:opc>, APX_NCI, Modrm|CheckOperandSize|No_bSuf|No_sSuf|DstVVVV|EVexMap4|EVexNF|Optimize, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64, Reg16|Reg32|Reg64 }
+cfcmov<cc>, 0x4<cc:opc>, APX_NCI, D|Modrm|CheckOperandSize|No_bSuf|No_sSuf|EVexMap4, { Reg16|Reg32|Reg64|Unspecified|BaseIndex, Reg16|Reg32|Reg64 }
fcmovb, 0xda/0, i687, Modrm|NoSuf, { FloatReg, FloatAcc }
fcmovnae, 0xda/0, i687, Modrm|NoSuf, { FloatReg, FloatAcc }
More information about the Binutils
mailing list