如果有的话,intel 和 amd 的 ISA 之间到底有什么区别?

What EXACTLY is the difference between intel's and amd's ISA, if any?

我知道以前有人问过类似的问题,但是有太多相互矛盾的信息,我真的很想一劳永逸地把它弄清楚。我将尝试通过明确区分指令集体系结构 (ISA) 和实际硬件实现来做到这一点。首先我尝试澄清:

1.) 目前有 intel64 和 amd64 CPU(除其他外,但这些是重点)

2.) 鉴于 ISA 是 1 个或多个 CPU 指令的二进制表示,这意味着 ISA 完全独立于它的实际硬件实现。

我的问题:

intel 64 和 amd64 CPU 之间的差异是否与不同或扩展的 x86-64 ISA 有关?或者 x86-64 ISA 的不同硬件实现?或者两者兼而有之?

是的,ISA 是文档/规范,而不是硬件。正确实现所有这些才能使某些东西成为 x86 CPU,而不仅仅是与 x86 相似的东西。

请参阅 标签 wiki 以获取官方文档(英特尔手册)的链接。

英特尔和 AMD 的 implementations of the x86 ISA differ 主要在性能方面,以及它们支持的指令集扩展。软件可以使用CPUID指令查询支持的内容。

也存在非性能差异,例如 指令语义偶尔会出现细微差异,尤其是操作系统需要使用的特权指令


这里的主要分歧之一是 Intel、AMD 和 VIA each have their own hardware-virtualization extensions,它们甚至不尝试兼容。因此,像 Xen 这样的 VM 需要为这些扩展中的每一个单独的“驱动程序”或“后端”代码。但这些仍然是扩展,不是基线 x86 的一部分。

供用户使用的 SIMD 扩展-space 程序最终在两者上都可用,由于 Intel's efforts to screw over AMD with anti-competitive practices,通常会有延迟。这会浪费其他人的时间,并且通常不利于整个 x86 生态系统(例如,SSSE3 现在可能被假定为更多软件的基准),但有助于英特尔的底线。这里有一个很好的例子:AMD Bulldozer 支持 FMA4,但英特尔在最后一刻改变了主意,在 Haswell 中实现了 FMA3。 AMD 直到他们的下一个微架构 (Piledriver) 才支持它。


Given that an ISA is the binary representation of 1 or more CPU instructions.

不,ISA 远不止于此。英特尔记录在所有 x86 CPUs 中得到保证的所有内容都是 ISA 的一部分。这不仅仅是每条指令的详细行为,还有诸如哪个控制寄存器做什么以及内存排序规则之类的东西。基本上英特尔和 AMD 发布的手册中的所有内容都没有以“CPU 的某某特定型号”开头。

我预计在某些情况下,Intel 和 AMD 的系统编程指南在 x86 的工作方式上存在差异。 (如果威盛为他们的 x86 CPUs 发布了他们自己的)。我没有检查过,但我很确定 user-space 不会受此影响:如果存在差异,它们仅限于仅在内核 运行s 时才有效的特权指令他们。无论如何,在那种情况下,我猜你可以说 x86 ISA 是 Intel 和 AMD 文档的通用子集。


请注意,尝试找出真实硬件在实践中的作用有助于理解文档,但不能代替阅读文档。您不希望您的代码依赖于指令在您测试的 CPU 上的行为方式。

但是,英特尔确实使用真实软件测试了他们的新设计,因为无法 运行 现有版本的 Windows 在商业上是不利的。例如Windows9x doesn't invalidate a TLB entry that could only have been filled speculatively(此示例的所有其余部分只是对该非常详细的博客 post 的总结和推断)。这要么是基于它是安全的(并且当时在硬件上是安全的)假设的性能黑客攻击,要么是一个未被注意到的错误。当时在硬件上测试是检测不到的。

现代 Intel CPUs 进行推测性页面走动,但即使最近 Haswell 检测并击落错误推测,因此假设这种情况不会发生的代码仍然有效。

这意味着真正的硬件比 ISA 提供了更强的排序保证,即:

The processor may cache translations required for prefetches and for accesses that are a result of speculative execution that would never actually occur in the executed code path.

不过,依赖于这种更强的行为将是一个错误,除非你只在已知的微体系结构上这样做。 AMD K8/K10 就像 Intel,但 Bulldozer 系列推测没有任何检测+回滚机制来提供一致性,因此 Win9x 内核代码在该硬件上不安全。未来的英特尔硬件也可能会放弃检测+回滚机制。

TL:DR: 所有的 uarches 都实现了 x86 ISA 所说的,但有些提供了更强的保证。如果您和 Microsoft 一样大,Intel 和 AMD 将设计 CPU 来重现您的代码所依赖的非 ISA 保证行为。 至少在该软件早已过时之前是这样。不能真正保证未来的 Intel uarches 将保留回滚机制。如果英特尔从头开始进行另一次重新设计(例如 P4 / NetBurst,而不是仅仅在其现有的 Sandybridge uarch 系列上构建),那么他们可能会做出合理的改变。


另一个例子:输入为零的bsf指令未定义其输出,according to the paper spec in Intel's insn ref manual.

但对于任何特定的 CPU,都会有一些行为模式,例如将输出设置为零,或保持不变。从理论上讲,由于不同的微体系结构状态,乱序执行 CPU 真正给出对于相同输入不同的不可预测的结果是有效的。

但是 英特尔选择在芯片中实现的行为是当 bsfbsr 输入为零 时始终保持目的地不变。 AMD 也这样做,甚至 记录 行为。这基本上是一个非官方的保证 mov eax,32 / bsf eax, ebx 将像 tzcnt 一样工作(标志设置除外,例如 ZF 基于输入为 0,而不是输出)。

这就是为什么 popcnt / lzcnt / tzcnt have a false dependency on the output register in Intel CPUs!.

CPU 供应商通常会超越纸质 ISA 规范,以避免破坏某些依赖于此行为的现有代码(例如,如果该代码是 Windows 的一部分,或其他Intel / AMD 在其新 CPU 设计上测试的主要软件。

As Andy Glew said in a comment thread关于上面提到的连贯页面遍历,以及关于自修改代码:

It is pretty common that a particular implementation has to implement rules compatible with but stronger than the architectural statement. But not all implementations have to do it the same way.