是否所有 x86-64 实现都支持 CMOVcc 指令?
Do all x86-64 implementations support the CMOVcc instructions?
在我对问题 的回答中,我提出了一个使用 cmovcc
指令的替代方案。我在那里说:
The cmov
instruction seems to be supported by all AMD64 CPUs.
然而,当时我还没有找到确凿的消息来源来支持这一说法。所以我想post这个问题来问那个。
在 Whosebug 上,我确实找到了 Generating CMOV instructions using Microsoft compilers 的答案,它在两个地方解决了我的问题。就是这样:
However, the documentation does confirm that, as one might expect, enabling SSE or SSE2 code generation implicitly enables the use of conditional-move instructions and anything else that was introduced before SSE:
In addition to using the SSE and SSE2 instructions, the compiler also uses other instructions that are present on the processor revisions that support SSE and SSE2. An example is the CMOV instruction that first appeared on the Pentium Pro revision of the Intel processors.
还有这个:
No special compiler flags or other considerations are necessary here, since all processors that support 64-bit mode support conditional moves.
关于第一个引用塔,如果 SSE2 支持意味着 cmov
支持,那么 64 位 ISA 扩展也意味着 cmov
,因为众所周知 x86-64 始终支持 SSE2,因为表示 in the Wikipedia article:
The AMD64 architecture supports the IA-32 as a compatibility mode and includes the SSE2 in its specification.
是的,实际上所有 x86-64 CPUs 都支持 cmovcc
并且人们普遍认为不检查它的 [=84] 就可以安全使用=]ID 特征位。 IE。支持长模式的功能位暗示了这一点。
cmovcc
是和Intel P6 (PPro and so on) which predates x86-64, and supported on all later Intel CPUs (except Quark and KNC which were non-general-purpose designs based on P5一起引入的,但是这两个都不是x86-641) cmovcc
也是AMD的第一个支持的AMD64 CPUs (K8),以及之前的 K7,但不是 K6。 Via 的 x86-64 CPUs 也支持 CMOV。没有其他 x86-64 硬件供应商 AFAIK,并且软件仿真器都将 CMOV 作为 x86-64 的一部分启用。
许多其他供应商出售支持 CMOV 的 32 位 CPUs,包括 Cyrix 6x86MX/MII,可能是 Transmeta Crusoe 二进制翻译层的一些更新,以及 Via C3 Nehemiah
各种 CPU 上 32 位 CMOV 支持的来源:comments on Agner Fog's Stop the Instruction Set War blog post, reactOS compat list, and discussion on a fedora bug。
脚注 1:Quark 和 KNC 均已停产。 Quark was a plain 32-bit microcontroller. KNF/KNC powered first-gen Xeon Phi and is its own thing: not full x86-64 compatibility, e.g. no CMOV or SSE, only the predecessor of AVX512 that it supported. I assume it had some way to address more than 4GiB of RAM. The next gen Xeon Phi KNL/KNM 是真正的 x86-64(源自 Silvermont),具有 cmov 和普通 AVX + AVX512F。而且也已经停产了。)
x86-64 的编译器都假定在制作 64 位代码时使用 cmov
是安全的。
这很重要,因为像 gcc 这样的编译器 不会 假设 x86-64 的一些早期添加,除非您使用特殊选项。例如lock cmpxchg16b
(早期 AMD 缺失)或 lahf
长模式(早期 Intel P4 缺失,支持 64 位)。 GCC 确实假设cmov
和默认-march=x86-64
这一事实表明假设普遍支持。
(假设 Pentium Pro,GCC 通常配置有 32 位模式代码生成器,不过,也使用 cmov
但不使用 SSE1。例如 return a ? b:c;
使用 gcc -m32
编译为 cmov as old as 4.6 on Godbolt。这绝对是 不是 32 位模式的基线,并且会在 P5 Pentium 和更早版本上出错。GCC 通常配置为在 32 位模式下以 "i686" 为目标,但真正是 64 位模式的基线 x86-64,因为它仍然功能齐全,不会太糟糕。)
虽然我不知道你在哪里可以找到官方确认它是基线;英特尔的手册 (https://www.felixcloutier.com/x86/cmovcc) 确实是这样说的:
The CMOVcc instructions were introduced in P6 family processors; however, these instructions may not be supported by all IA-32 processors. Software can determine if the CMOVcc instructions are supported by checking the processor’s feature information with the CPUID instruction (see “CPUID—CPU Identification” in this chapter).
(相关的 CPUID 功能位是 cpuid[EAX=1].EDX.bit15
(sandpile 或使用 EAX=8000_0000h),这也表明支持其他 P6 功能,如 fcomi
和 fcmovcc
如果存在 x87 FPU,即设置了相同 EDX 输出的位 0
。)
我认为 IA-32 的措辞意味着没有 IA-32e 处理器(英特尔对 x86-64 的名称)缺少它,只有一些 IA-32 处理器。但这不是一个非常明确的陈述,基于我知道这在实践中是正确的事实,我可能会过度解读。
这个问题的另一个答案指出了 SSE2。实际上,所有支持 SSE2 的 CPU 也支持 cmov
,但 cmov
不是 "part of SSE2"。它们有单独的 CPUID 特征位。 (并且两者都是 x86-64 的基线,因此 64 位代码不需要检查功能位。)
没有什么可以阻止某人使用 SSE2 构建 CPU 而不是 cmov
... 除了没有人会购买它,因为它不能 运行 正常的二进制文件。许多现代编译器即使在 32 位模式下也使用 CMOV,即使它们 不 默认使用 SSE1。 (这可能看起来有点傻;仍在使用的 PPro / PII CPUs 的数量可能不会比 P5 Pentium 和兼容的 CPUs 高多少。但是半现代的 AMD Geode 有 CMOV 而没有 SSE1 .https://bugzilla.redhat.com/show_bug.cgi?id=538268#c9)
在我对问题 cmovcc
指令的替代方案。我在那里说:
The
cmov
instruction seems to be supported by all AMD64 CPUs.
然而,当时我还没有找到确凿的消息来源来支持这一说法。所以我想post这个问题来问那个。
在 Whosebug 上,我确实找到了 Generating CMOV instructions using Microsoft compilers 的答案,它在两个地方解决了我的问题。就是这样:
However, the documentation does confirm that, as one might expect, enabling SSE or SSE2 code generation implicitly enables the use of conditional-move instructions and anything else that was introduced before SSE:
In addition to using the SSE and SSE2 instructions, the compiler also uses other instructions that are present on the processor revisions that support SSE and SSE2. An example is the CMOV instruction that first appeared on the Pentium Pro revision of the Intel processors.
还有这个:
No special compiler flags or other considerations are necessary here, since all processors that support 64-bit mode support conditional moves.
关于第一个引用塔,如果 SSE2 支持意味着 cmov
支持,那么 64 位 ISA 扩展也意味着 cmov
,因为众所周知 x86-64 始终支持 SSE2,因为表示 in the Wikipedia article:
The AMD64 architecture supports the IA-32 as a compatibility mode and includes the SSE2 in its specification.
是的,实际上所有 x86-64 CPUs 都支持 cmovcc
并且人们普遍认为不检查它的 [=84] 就可以安全使用=]ID 特征位。 IE。支持长模式的功能位暗示了这一点。
cmovcc
是和Intel P6 (PPro and so on) which predates x86-64, and supported on all later Intel CPUs (except Quark and KNC which were non-general-purpose designs based on P5一起引入的,但是这两个都不是x86-641) cmovcc
也是AMD的第一个支持的AMD64 CPUs (K8),以及之前的 K7,但不是 K6。 Via 的 x86-64 CPUs 也支持 CMOV。没有其他 x86-64 硬件供应商 AFAIK,并且软件仿真器都将 CMOV 作为 x86-64 的一部分启用。
许多其他供应商出售支持 CMOV 的 32 位 CPUs,包括 Cyrix 6x86MX/MII,可能是 Transmeta Crusoe 二进制翻译层的一些更新,以及 Via C3 Nehemiah
各种 CPU 上 32 位 CMOV 支持的来源:comments on Agner Fog's Stop the Instruction Set War blog post, reactOS compat list, and discussion on a fedora bug。
脚注 1:Quark 和 KNC 均已停产。 Quark was a plain 32-bit microcontroller. KNF/KNC powered first-gen Xeon Phi and is its own thing: not full x86-64 compatibility, e.g. no CMOV or SSE, only the predecessor of AVX512 that it supported. I assume it had some way to address more than 4GiB of RAM. The next gen Xeon Phi KNL/KNM 是真正的 x86-64(源自 Silvermont),具有 cmov 和普通 AVX + AVX512F。而且也已经停产了。)
x86-64 的编译器都假定在制作 64 位代码时使用 cmov
是安全的。
这很重要,因为像 gcc 这样的编译器 不会 假设 x86-64 的一些早期添加,除非您使用特殊选项。例如lock cmpxchg16b
(早期 AMD 缺失)或 lahf
长模式(早期 Intel P4 缺失,支持 64 位)。 GCC 确实假设cmov
和默认-march=x86-64
这一事实表明假设普遍支持。
(假设 Pentium Pro,GCC 通常配置有 32 位模式代码生成器,不过,也使用 cmov
但不使用 SSE1。例如 return a ? b:c;
使用 gcc -m32
编译为 cmov as old as 4.6 on Godbolt。这绝对是 不是 32 位模式的基线,并且会在 P5 Pentium 和更早版本上出错。GCC 通常配置为在 32 位模式下以 "i686" 为目标,但真正是 64 位模式的基线 x86-64,因为它仍然功能齐全,不会太糟糕。)
虽然我不知道你在哪里可以找到官方确认它是基线;英特尔的手册 (https://www.felixcloutier.com/x86/cmovcc) 确实是这样说的:
The CMOVcc instructions were introduced in P6 family processors; however, these instructions may not be supported by all IA-32 processors. Software can determine if the CMOVcc instructions are supported by checking the processor’s feature information with the CPUID instruction (see “CPUID—CPU Identification” in this chapter).
(相关的 CPUID 功能位是 cpuid[EAX=1].EDX.bit15
(sandpile 或使用 EAX=8000_0000h),这也表明支持其他 P6 功能,如 fcomi
和 fcmovcc
如果存在 x87 FPU,即设置了相同 EDX 输出的位 0
。)
我认为 IA-32 的措辞意味着没有 IA-32e 处理器(英特尔对 x86-64 的名称)缺少它,只有一些 IA-32 处理器。但这不是一个非常明确的陈述,基于我知道这在实践中是正确的事实,我可能会过度解读。
这个问题的另一个答案指出了 SSE2。实际上,所有支持 SSE2 的 CPU 也支持 cmov
,但 cmov
不是 "part of SSE2"。它们有单独的 CPUID 特征位。 (并且两者都是 x86-64 的基线,因此 64 位代码不需要检查功能位。)
没有什么可以阻止某人使用 SSE2 构建 CPU 而不是 cmov
... 除了没有人会购买它,因为它不能 运行 正常的二进制文件。许多现代编译器即使在 32 位模式下也使用 CMOV,即使它们 不 默认使用 SSE1。 (这可能看起来有点傻;仍在使用的 PPro / PII CPUs 的数量可能不会比 P5 Pentium 和兼容的 CPUs 高多少。但是半现代的 AMD Geode 有 CMOV 而没有 SSE1 .https://bugzilla.redhat.com/show_bug.cgi?id=538268#c9)