@jalf的回答涵盖了大多数原因,但是没有提及一个有趣的细节:内部类似RISC的内核并未设计为运行诸如ARM / PPC / MIPS之类的指令集。x86税不仅在耗电的解码器中支付,而且在整个内核中都有一定程度的支付。即,不仅是x86指令编码;这是每条带有奇怪语义的指令。
假设英特尔确实创建了一种操作模式,其中指令流不是x86,而是指令直接映射到uops。我们还假设每个CPU型号在此模式下都有自己的ISA,因此它们仍然可以在需要时自由更改内部结构,并使用最少数量的晶体管来暴露它们,以用于这种替代格式的指令解码。
假定您仍然只有相同数量的寄存器,映射到x86体系结构状态,因此x86 OS可以在上下文切换上保存/恢复它,而无需使用特定于CPU的指令集。但是,如果排除了实际的限制,是的,我们可以有更多的寄存器,因为我们可以使用通常为微码1保留的隐藏临时寄存器。
如果我们只有备用解码器,而对后续的流水线阶段(执行单元)没有任何更改,则此ISA仍然会有很多x86偏心率。 它将不是一个很好的RISC体系结构。没有任何一条指令会非常复杂,但是x86的其他疯狂之处仍然存在。
例如:左/右移位使上溢标志不确定,除非移位计数为1,在这种情况下OF =通常的有符号溢出检测。类似的疯狂旋转。但是,公开的RISC指令可以提供无标志的移位,依此类推(允许仅使用某些复杂的x86指令通常使用的多个微指令中的一两个)。因此,这并不是真正的主要反驳。
如果您打算为RISC ISA制作全新的解码器,则可以让它选择x86指令的一部分作为RISC指令公开。这在某种程度上减轻了内核的x86专业化。
指令编码可能不是固定大小的,因为单个uop可以容纳很多数据。如果所有insn大小都相同,那么数据量就不那么有意义了。一个微融合的uop可以添加一个32位立即数和一个内存操作数,该操作数使用具有2个寄存器和32位位移的寻址模式。(在SnB及更高版本中,只有单寄存器寻址模式才能与ALU ops进行微熔丝连接)。
uops非常大,与固定宽度的ARM指令不太相似。固定宽度的32位指令集一次只能加载16位立即数,因此加载32位地址需要立即加载低半/立即加载高对。x86不必这样做,这仅凭15个GP寄存器限制了在寄存器中保持常数的能力,因此不会很糟糕。(我认为有些模拟发现,15个对7个寄存器有很大帮助,但再加倍至31个对您的帮助就少得多。RSP通常不是通用的,因此更像15个GP寄存器和一个堆栈。)
TL; DR摘要:
无论如何,这个答案归结为“ x86指令集可能是对必须能够快速运行x86指令的CPU进行编程的最佳方法”,但希望可以阐明一些原因。
前端和后端的内部uop格式
另请参阅微融合和寻址模式,以获取前端和后端uop格式在Intel CPU上可以表示的差异的一种情况。
脚注1:有些“隐藏”寄存器被微码用作临时寄存器。就像x86体系结构寄存器一样,这些寄存器也被重命名,因此多uop指令可能会无序执行。
例如,xchg eax, ecx
在Intel CPU上,解码为3微码(为什么?),而我们最好的猜测是,它们是类似MOV的微码tmp = eax; ecx=eax ; eax=tmp;
。按照这种顺序,因为我测量的是dst-> src方向在〜1个周期内的等待时间,而在2个周期中则是2个。而且,这些动作不像常规mov
指令那样。他们似乎不是零延迟运动消除的候选者。
另请参见http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/,其中提到尝试通过实验方式测量PRF大小,并且必须考虑用于保持架构状态的物理寄存器,包括隐藏寄存器。
在解码器之后但在将寄存器重命名到物理寄存器文件的发布/重命名阶段之前的前端中,内部uop格式使用类似于x86 reg编号的寄存器编号,但是有空间来寻址这些隐藏的寄存器。
uop格式在乱序内核(ROB和RS)(也称为后端)(在Issue / rename阶段之后)内有所不同。int / FP物理寄存器文件在Haswell中每个都有168个条目,因此uop中的每个寄存器字段都必须足够宽以解决这么多寄存器。
由于重命名器位于硬件中,因此我们最好使用它,而不是将静态调度的指令直接提供给后端。因此,我们将使用与x86体系结构寄存器+微代码临时性一样大的一组寄存器,而不是更多。
后端旨在与前端重命名器一起使用,以避免WAW / WAR危害,因此即使我们愿意,也不能像有序CPU那样使用它。它没有互锁来检测那些依赖关系。由问题/重命名处理。
如果我们可以将uops送入后端而没有问题/重命名阶段的瓶颈(现代Intel管道中的最窄点,例如Skylake上的4宽vs. 4 ALU + 2负载+ 1的存储端口)后端)。但是,如果您这样做了,我认为您不能静态地调度代码来避免寄存器重用,并且避免由于高速缓存未命中使负载长时间停顿而仍然需要的结果。
因此,我们非常需要将uops输入到issue / rename阶段,可能仅绕过解码,而不是uop缓存或IDQ。然后我们得到了具有健全危害检测功能的普通OoO执行程序。寄存器分配表仅用于将16 +一些整数寄存器重命名为168个条目的整数PRF。我们不能期望硬件将大量的逻辑寄存器重命名为相同数量的物理寄存器。那将需要更大的RAT。