为什么80486执行简单指令的时间比执行复杂指令的时间长?

2020-05-22 16:25:08

80486处理器可以在单个周期内执行许多指令,例如寄存器到寄存器相加指令(例如,ADDEAX、EBX),人们通常认为这是相当复杂的,需要读取两个寄存器、完整的32位算术逻辑单元操作以及寄存器和标志写入。

然而,人们自然会认为相对简单的其他指令需要多个周期,包括各种标志操作指令,如STC和CLC,它们是加法指令所需操作的严格子集(仅将预先计算的值加载到标志中,而不必实际基于输入确定要加载的值,并且根本不需要寄存器更新),但需要2个周期。

80486包含用于解码、操作数提取、执行和回写的并行操作级。因此,虽然加法确实需要3个时钟才能执行,但与第一个8086一样,它的执行与上一次/下一次操作重叠,因此CPU可以在每个时钟上执行一个加法。

(请注意,在这一阶段还有很多事情要做,所以我可能不记得所有的细节了)。

两个时钟是自8088以来任何指令的最小执行时间。由于寄存器/寄存器确实需要3个周期,因此添加(或类似)。使用286,由于优化了微码和路由(*1),它们的运行速度加快到两个周期。虽然386确实由于更好的地址生成而加快了执行速度,但基本执行方案与3级指令预取保持不变。

486确实进一步调整了地址生成,但更重要的是重做了指令提取体系结构。这是通过一条5级管道完成的。

解码1-主指令解码-这里只检查了前1..3个字节。

这些级的操作是有条件的,但将始终采取(通过)操作以保持恒定的时钟速率。

FETCH总是一次将一个16字节的高速缓存(内存)行放入它的两个缓冲区之一。因此,平均每4-5条指令它只需要这样做。该时间可用于预填满第二缓冲器。因此,只要代码是线性的,即使没有高速缓存,486也可以保持快速执行。

译码1查看操作码和寻址字段以确定要采取的动作,将实际指令长度反馈到提取级(以便它可以前进),它设置D2执行的操作。这里值得注意的是,每个前缀字节被作为其自己的指令来处理,占用另一个时钟周期(*2,3)。类似于双字节操作码的第一个字节(例如0Fh)。

解码2解码操作数访问,从提取级的缓冲区获取偏移量或立即值。它也可以进行地址计算。简单的需要两个周期,复杂的需要两个周期。

行刑。如果所有数据都以即时方式存在,或存在于高速缓存中,或来自寄存器堆,则执行将在单个周期内执行。

写回将读取值(内存、高速缓存或提取缓冲区)或锁存的执行结果存储到寄存器和/或内存写入缓冲区中。

因此,单个ADD REG,REG仍然需要3个周期,但是由于流水线的原因,CPU每个时钟可以完成一个周期。

但是等等,如果有两个add,第二个需要前一个的结果,会发生什么呢?比如ADD AX,BX;ADD CX,AX。这不是意味着第二个必须等到第一个的回写完成才能执行吗?

嗯,是的,除了工程师在回写和执行之间增加了一个快捷方式/反馈。WB输入,即前一次执行的结果,不仅写入寄存器组,而且还提供作为备用输入(用目标是什么标记)返回执行。因此,如果一条指令需要读取前一条指令的结果寄存器,则甚至在写入实数寄存器之前就可以读取该寄存器。

很酷,不是吗?但这会变得更加棘手。在EXECUTE中完成的任何操作的标志也从写回中提供回来,以便在下一条指令中使用。这样做是为了在诸如比较或减法之类的标志修改操作之后启用一个周期未采取的跳转。

尽管有这样的优化,状态寄存器操作指令并没有从这个避免暗示的快捷方式中受益。直接状态寄存器操作不通过WB,而是直接处理状态寄存器的两步微指令。这一点很重要,因为状态寄存器设置不仅会改变所有操作行为,还会产生各种异常。

记住,80486不是RISC CPU,也不会在内部转换为RISC(类似)指令,但继续像它们的前身一样运行,这是有益的。只需要非常巧妙地设计流水线,在各级之间进行反馈,并并行操作地址计算单元。虽然奔腾(P5)引入了超卡操作(应该是并行流水线),但直到P6(奔腾Pro)才将代码翻译成(有点)类似RISC的内核--但即使在那时,也使用了许多非RISCy侧通道。

随后的设计真的超越了他们自己,一条管道在奔腾III中增长到10级,第一台奔腾4级增长到20级,IIRC管道增长到40级(!)。在返回到更简单但大规模的并行设计(如P6)之前,上一次网络突发的各个阶段已经.。但这也是另一回事了。

*1-80286速度的主要收益是专用地址计算单元,但这是另一回事。

*2-这就是为什么一个锁在286/386上需要零个周期,而在486上只需要一个周期。

*3-在某个地方,我确实读到了英特尔(IIRC)关于前缀和管道的一项很好的研究。一个真正值得注意的部分是Unix程序平均只使用DOS程序的一半前缀。这证明了用段值计算地址是多么愚蠢。

感谢您抽出时间来写这份信息量很大的答案。我确实从中学到了很多。--盖尔奎斯特

首先,486在单个周期内执行指令是不正确的。80486是流水线架构,因此更准确地说,大多数指令可以在前一条指令开始后一个周期开始。AFAIK,80486的管道长度为5级(如果ID1ID2ex WB)。这意味着进入该流水线的指令具有5个周期的等待时间。

这些1周期指令属于所谓的RISC子集:生产软件中通常存在的指令子集,因为生成该软件的编译器使用它们最多。

其他指令,尽管和第一条指令一样简单,但不属于RISC子集,必须通过微码执行,就像它在以前的体系结构中是如何执行的一样。

我明白了,所以处理器有两个完全独立的执行路径,那些更常见的指令通过更优化的路径,但是其他指令(即使它们由于是简单的指令可以很容易地在优化的路径上实现)使用较不优化的机制,因此花费更长的时间?-occipita。

除了围绕微码和快速路径指令的各种优化之外,x86上的标志也很特殊,因为所有指令都不会以相同的方式更新标志(INC/DEC不会像ADD/SUB那样更新CF)。也许英特尔更喜欢使用一种复杂的方法来仅更改CF(例如将标志寄存器读取到临时存储器,应用掩码.)。不是添加信号来仅更新CF并跟踪相关性:如果CF更新是特定的,则CPU可能需要停止流水线以避免危险。--TEMLIB。

点击“发布您的答案”,即表示您同意我们的服务条款、隐私政策和Cookie政策。

不是你想要的答案吗?浏览标记的其他问题或提出您自己的问题。