为什么英特尔在其处理器中隐藏内部RISC内核?

时间:2011-04-27 15:27:25

标签: x86 intel cpu-architecture

从Pentium Pro(P6微体系结构)开始,英特尔重新设计了它的微处理器,并在旧的CISC指令下使用了内部RISC内核。由于Pentium Pro所有CISC指令都分为较小的部分(uops),然后由RISC内核执行。

一开始我很清楚英特尔决定隐藏新的内部架构并强迫程序员使用“CISC shell”。由于这一决定,英特尔可以在不破坏兼容性的情况下完全重新设计微处理器架构,这是合理的。

但是我不明白一件事,为什么英特尔仍然保留了多年隐藏的内部RISC指令集?为什么他们不让程序员使用RISC指令,比如使用旧的x86 CISC指令集?

如果英特尔长期保持向后兼容性(我们在64位模式旁边仍然具有虚拟8086模式),为什么它们不允许我们编译程序以便它们绕过CISC指令并直接使用RISC核心?这将开启自然的方式来缓慢放弃x86指令集,现在已弃用(这是英特尔决定在内部使用RISC核心的主要原因,对吧?)。

看看新的英特尔'酷睿i'系列我看,他们只扩展了CISC指令集,增加了AVX,SSE4等。

6 个答案:

答案 0 :(得分:84)

不,x86指令集肯定不会被弃用。它一如既往地受欢迎。英特尔在内部使用一组类似RISC的微指令的原因是因为它们可以更有效地处理。

所以x86 CPU的工作原理是在前端有一个非常重的解码器,接受x86指令,并将它们转换为优化的内部格式,后端可以处理。

至于将此格式暴露给“外部”程序,有两点:

  • 它不是一个稳定的格式。英特尔可以在CPU型号之间进行更改,以最好地适应特定架构。这使他们能够最大限度地提高效率,如果他们不得不采用固定,稳定的指令格式供内部使用和外部使用,这种优势就会丧失。
  • 这样做没有任何好处。对于今天庞大而复杂的CPU,解码器只占CPU的一小部分。必须解码x86指令会使其变得更加复杂,但CPU的其余部分不会受到影响,因此总体来说,只能获得很少的内容,尤其是因为x86前端仍然必须存在,以便执行“遗留”代码。因此,您甚至不会保存当前在x86前端使用的晶体管。

这不是一个完美的安排,但成本相当小,而且比设计CPU以支持两个完全不同的指令集更好。 (在这种情况下,他们可能最终发明了一套用于内部使用的第三个​​微操作,只是因为那些可以自由调整以最适合CPU的内部架构)

答案 1 :(得分:17)

真正的答案很简单。

实施RISC处理器背后的主要因素是降低复杂性和提高速度。 RISC的缺点是指令密度降低,这意味着以RISC格式表示的相同代码需要比等效CISC代码更多的指令。

如果你的CPU以与内存相同的速度运行,或者至少如果它们以相当相似的速度运行,那么这种副作用并不意味着什么。

目前,与CPU速度相比,内存速度显示时钟差异很大。当前的CPU有时比主存储器快五倍或更多。

这种技术状态有利于更密集的代码,这是CISC提供的。

您可以认为缓存可以加速RISC CPU。但关于CISC cpus也是如此。

使用CISC和缓存比RISC和缓存更快地提高了速度,因为相同大小的缓存对CISC提供的高密度代码有更大的影响。

另一个副作用是RISC在编译器实现上更难。它更容易优化CISC cpu的编译器。等

英特尔知道他们在做什么。

这是真的,ARM具有更高的代码密度模式,称为Thumb。

答案 2 :(得分:15)

  

如果英特尔保持向后兼容性   这么久(我们还有虚拟的   8086模式旁边的64位模式),为什么   他们不允许我们编译程序   所以他们将绕过CISC指令   并直接使用RISC核心?这将   开放自然的方式慢慢放弃x86   指令集,已弃用   如今(这是主要原因   英特尔决定在内部使用RISC核心,   右?)。

你需要看看这个的商业角度。英特尔实际上试图摆脱x86,但它是为公司带来金蛋的鹅。 XScale和Itanium从未达到其核心x86业务所取得的成功水平。

你基本上要求英特尔切开手腕以换取开发人员的温暖模糊。破坏x86不符合他们的利益。任何使更多开发人员不必选择以x86为目标的东西都会破坏x86。反过来,这会破坏它们。

答案 3 :(得分:4)

答案很简单。英特尔不为开发人员开发CPU!他们正在为那些做出购买决策的人开发它们,BTW是世界上每家公司都做的决定!

英特尔很久以前承诺,(当然,在合理范围内),他们的CPU将保持向后兼容。人们想知道,当他们购买新的基于英特尔的计算机时,他们当前软件的 所有 将与旧计算机上的完全相同。 (虽然,希望更快!)

此外,英特尔知道完全承诺的重要性,因为他们曾试图以不同的方式行事。究竟有多少人知道Itanium CPU??

你可能不喜欢它,但是决定使用x86,是英特尔成为世界上最知名的商业名称之一!

答案 4 :(得分:3)

@ jalf的答案涵盖了大多数原因,但是它没有提到一个有趣的细节:类似内部RISC的核心并不是为运行指令集而设计的像ARM / PPC / MIPS这样的东西。 x86税不仅仅是在耗电量大的解码器中支付,而是在整个核心中在某种程度上支付。即它不仅仅是x86指令编码;它的每条指令都有奇怪的语义。

让我们假设英特尔确实创建了一种操作模式,其中指令流不是x86,其指令更直接映射到uop。让我们假设每个CPU型号都有自己的ISA用于这种模式,因此他们仍然可以随心所欲地更改内部,并用最少量的晶体管对它们进行指令解码。替代格式。

据推测,您仍然只有相同数量的寄存器,映射到x86架构状态,因此x86操作系统可以在上下文切换中保存/恢复它,而无需使用特定于CPU的指令集。但是如果我们抛弃那个实际的限制,是的,我们可以有更多的寄存器,因为我们可以使用通常为微码 1 保留的隐藏临时寄存器。

如果我们只有备用解码器而后续流水线阶段(执行单元)没有变化,那么这个ISA仍然会有很多x86怪癖。这不是一个非常好的RISC架构。没有一条指令会非常复杂,但x86的其他一些疯狂仍然存在。

例如:左/右移位保持溢出标志未定义,除非移位计数为1,在这种情况下OF =通常的有符号溢出检测。类似的旋转疯狂。但是,暴露的RISC指令可以提供无标记移位等等(允许使用通常进入某些复杂x86指令的多个uop中的一个或两个)。所以这并没有成为主要的反驳论点。

如果您要为RISC ISA创建一个全新的解码器,您可以选择部分x86指令作为RISC指令公开。这在一定程度上减轻了核心的x86专业化。

指令编码可能不是固定大小的,因为单个uop可以容纳大量数据。如果所有insn都是相同的大小,那么更多的数据是有意义的。单个微融合uop可以添加32位立即数和一个内存操作数,该操作数使用具有2个寄存器和32位移位的寻址模式。 (在SnB及更高版本中,只有单寄存器寻址模式可以与ALU操作微熔合。)

uops非常大,与固定宽度的ARM指令不太相似。固定宽度的32位指令集一次只能加载16位立即数,因此加载32位地址需要一个加载即时低半/高负载立即对。 x86并不是必须这样做,这有助于它只有15个GP寄存器限制在寄存器中保持常量的能力并不可怕。 (15对7个寄存器来说是一个很大的帮助,但是再次加倍到31可以帮助少得多,我认为有些模拟发现.RSP通常不是通用的,所以它更像15个GP寄存器和堆栈。)< / p>

TL; DR摘要:

无论如何,这个答案归结为&#34; x86指令集可能是编程必须能够快速运行x86指令的CPU的最佳方式,但希望能够解释原因。

前端与后端的内部uop格式

另请参阅Micro fusion and addressing modes,了解前端与后端uop格式在英特尔CPU上的差异。

脚注1 :有一些&#34;隐藏&#34;寄存器用作微码的临时用户。这些寄存器与x86架构寄存器一样被重命名,因此多uop指令可以无序执行。

e.g。英特尔CPU上的xchg eax, ecx解码为3 uops(why?),我们最好的猜测是这些类似MOV的uop执行tmp = eax; ecx=eax ; eax=tmp;。按此顺序,因为我在~1周期测量dst-> src方向的等待时间,而用另一种方式测量为2。而这些移动不像常规mov指令那样;他们似乎不是零延迟移动消除的候选者。

另见http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/提及试图通过实验测量PRF大小,并且必须考虑用于保存架构状态的物理寄存器,包括隐藏寄存器。

在解码器之后的前端,但在将寄存器重命名为物理寄存器文件的发布/重命名阶段之前,内部uop格式使用类似于x86注册号的寄存器编号,但有足够的空间来解决这些问题隐藏的寄存器。

uop格式在无序核心(ROB和RS)内部有所不同,即后端(在发布/重命名阶段之后)。 int / FP物理寄存器文件each have 168 entries in Haswell,因此uop中的每个寄存器字段都需要足够宽以解决那么多。

由于重命名器在HW中,我们可能最好不要使用它,而不是直接向后端提供静态调度指令。因此,我们可以使用一组与x86架构寄存器+微码临时值一样大的寄存器,而不是更多。

后端设计用于与前端重命名器配合使用,可避免WAW / WAR危险,因此即使我们愿意,也无法像有序CPU一样使用它。它没有互锁来检测这些依赖关系;这是由发行/重命名处理的。

如果我们能够在没有问题/重命名阶段的瓶颈(现代英特尔管道中的最窄点,例如Skylake上的4宽与4 ALU + 2负载+ 1)的情况下将uops输入后端,这可能会很简洁在后端存储端口)。但是如果你这样做,我认为你不能静态地安排代码以避免寄存器重用,并且如果缓存未命中长时间停止加载,那么踩到仍然需要的结果。

因此我们非常需要将uops提供给问题/重命名阶段,可能只绕过解码,而不是uop缓存或IDQ。然后我们得到正常的OoO执行官,并进行健全的危险检测。寄存器分配表仅用于将16 +几个整数寄存器重命名为168项整数PRF。我们无法期望HW将更大的逻辑寄存器重命名为相同数量的物理寄存器;这将需要更大的RAT。

答案 5 :(得分:-3)

  

为什么它们不允许我们编译程序以便它们绕过CISC指令并直接使用RISC核心?

除了之前的答案,另一个原因是市场细分。一些指令被认为是用微代码而不是硬件实现的,因此允许任何人执行任意微操作都会破坏新cpu的销售,并使用“新的”更高性能的CISC指令。