为什么CPU体系结构使用标志寄存器(优点?)


15

某些CPU具有标志寄存器(ARM,x86,...),而其他则没有(MIPS,...)。使用CMP指令更新标志寄存器后再执行分支指令,而不是使用零寄存器和条件分支来检查符号,溢出等的好处是什么?

Answers:


11

在寄存器重命名的现代微体系结构中,标记或不标记的实现成本非常相似。我可以想到的主要区别是,某些标志指示值的特征(值是否为负?值是否为零?该值具有偶校验还是奇校验?),而有些标志则表示在上一个操作期间发生的事件(添加指令执行了还是溢出了?)当您想在32位体系结构上模拟64位加法(或在32位体系结构上模拟 128位加法)导致MIPS的情况不太理想。 64位体系结构。)在大多数带有进位标志的体系结构上,都有一个特殊的add-with-carry指令,其中包括前一条加法指令中的进位标志。这使得在具有标志寄存器的许多体系结构上模拟多精度算术相对便宜。

在另一方面,测试一个N位寄存器是否为零或非零实际上是非常昂贵的。要测试N位寄存器是否为零,您需要执行N位NOR运算,这需要逻辑电平进行计算。在带有标志的体系结构上注册寄存器时,在ALU阶段结束时用于零/非零计算的额外逻辑会导致时钟运行速度变慢(或迫使ALU进行两次循环操作。)因此,我认为有些像SPARC这样的体系结构,每个算术运算都有两种版本,一种用于设置标志,而另一种则没有。Ø日志ñ

但是MIPS不会在这里保存任何内容。他们只是将问题转移到其他地方。在MIPS上有一条branch-on-equal说明。这意味着分支指令实际上必须具有ALU阶段(包括按位xor运算之类的操作,后跟a,nor以减小到单个相等/不相等位),然后才能确定分支的执行方式。

DEC Alpha架构试图通过技巧来分散差异。DEC Alpha没有标志寄存器,但是也没有branch-on-equal指令。相反,分支指令全部查看单个通用寄存器的状态。还有就是branch-on-zerobranch-on-not-zerobranch-on-less-than-zero,等诀窍是,你可以给每一个通用寄存器额外的65位,告诉你其他64位是否都为零。这使它更像是具有标志寄存器:所有分支指令仅查看单个位(已经计算出)来做出决定,但是现在您要回头弄清楚如何在正常ALU期间计算该额外的零指示符位周期。(而且,仅通过查看上一个操作中的进位标志,您仍然无法执行多精度算术。)


2
根据我的理解,非CC设置操作是编译器优化,从而使编译器可以尽早安排CC设置指令,而不会浪费后面的指令的值。PowerPC750将条件寄存器(8个4位寄存器)放置在更靠近前端的位置,以使采用分支到达分支目标指令高速缓存并且具有足够早的可用条件,可以解决采用分支而不会带来任何损失。(AT&T的CRISP还利用了早期的分支机构解决方案。)CC的数量少且专业化使得这更加实用。
保罗·克莱顿

详细信息:所有标志的计算均不相等。假设您的CPU具有传统的NZVC标志。如果所有的ALU指令都被允许更新标志,则必须将标志生成放置在加法器/减法器和几个多路复用器之后。Negative标志很容易,它只是MSB,而Zero标志则很昂贵,并且取决于每个位。现在,如果将标志限制为比较(和位测试)指令,则可以在源操作数上使用并行XOR来计算零标志,而无需等待减法结果。加法后计算Z标志几乎没有用。
TEMLIB

7

1从ISA的角度

  1. 具有仅设置标志的测试指令只是减少寄存器匮乏架构中寄存器压力的一种方法。如果您有足够的寄存器,则只需修改其中之一,然后忽略结果即可。使用寄存器0输入值0的技巧只是一种编码技巧,当您有足够多的寄存器将它们之一固定为0比增加指令数更好时,这很方便。然后,也可以方便地将其用作目标(它减少了虚假依赖项的数量)。

  2. 再次编码。如果用跳转对条件进行编码,则会有3个操作数的跳转(两个要比较的对象和跳转目标),其中两个您希望成为立即值,一个您希望与之一样大可能(跳转通常具有自己的编码格式,以便目标可以使用尽可能多的位)。或者,您放弃可能性。

  3. 使用标志为您提供了更多设置它们的机会。不仅可以设置标志的比较操作,还可以设置任何标志。(请注意,设置标志的操作越多,确保设置标志的最后一个操作就是您想要的操作就越需要谨慎)。如果有标志,则可以测试条件数(通常为16)乘以能够设置标志的指令数(如果不使用标志,则最终的条件跳转数与有需要测试的东西,或者有些不允许您轻松测试的东西(例如携带或溢出)。

2从实施者的角度

  1. 测试标志很容易并且可以很快完成。测试越复杂,它将对周期时间(或流水线结构,如果您是流水线)产生更大的影响。对于更简单的实现而言,尤其如此,当您使用本书的所有技巧进入高端处理器时,效果几乎是最小的。

  2. 具有标志意味着很多指令具有多个结果(自然结果和每个修改后的标志)。从微体系结构POV来看,多个结果是不好的(您必须跟踪它们的关联)。当只有一组标志时,会引入依赖关系(如果不使用该标志则不需要),则必须处理方式。同样,对于更简单的实现尤其如此,当您使用本书的所有技巧进入高端处理器时,其他处理器所面临的其他困难将相形见difficulties。


2

在32位计算机上,用作多精度加法序列的一部分的“带进位加法”指令需要接受价值65位的操作数并计算33位总和。源寄存器规范将标识64个操作数位应来自何处,而目标寄存器规范将说明结果的低32位应到达何处,但如何处理“加一个额外的”操作数或高位?结果?作为指令的一部分,可以指定额外的操作数应来自何处以及额外的结果位应位于何处,这会适度有用,但通常不会有用到无法证明操作码中有额外的字段。从指令调度的角度来看,有一个固定的“位置”来处理进位标志可能有点尴尬,但是

如果有人试图设计一种指令集以允许多精度算术,但每条指令限于两个32位操作数和一个32位目标操作数,则可以在四个指令中实现一个64位“加”:如果r0 + r2携带进位,则r5变为1,否则为零;计算r4 = r1 + r3;计算r5 = r4 + r5;计算r4 = r0 + r2”,但要超出此范围,每个附加字需要三条指令。将进位标志用作补充源和目标可将成本降低到每个字一个指令。

顺便说一句,具有指令位来控制指令是否更新标志寄存器可能会促进乱序执行,因为使用或修改标志位的指令必须保持彼此相对的顺序,但两者都不执行自由地重新安排。给定顺序:

ldr  r0,[r1]
add  r0,r0,r2
eors r4,r5,r6

执行单元可以很容易地识别出第三条指令可以执行而不必等待读取数据[r1],但是如果第二条指令已经adds r0,r0,r2执行,则只有在执行单元可以确保尝试使用任何东西的情况下,这才有可能。在这些标志中,零标志将保留在第三条指令中建立的值,而进位标志将在第二条指令中保留该值。


1
“指令位控制指令是否更新标志寄存器”:例如在PowerPC,SPARC中可用。
TEMLIB

MIPS使用“ r5 = r1 + r2;如果r6小于r1,则设置r6; r7 = r3 + r4; r5 = R5 + R6;”。某些SIMD扩展可以使用将所有位设置为零或一(即零或-1二进制补码整数)的比较来找到进位和减法以应用进位。
Paul A. Clayton,2015年

@ PaulA.Clayton:我认为您的意思是“如果r5小于r1”。MIPS如何处理更长的数学时间?每个字是否需要三个,三个或三个以上的指令?
supercat

@supercat是的,应该已经“如果r5小于r1则设置r6”!
保罗·克莱顿

@ PaulA.Clayton:如何在32位MIPS上添加例如两个64字(2048位)数字?有什么有效的方法来处理进出中间阶段的进位?
超级猫

0

简单的答案...快速廉价的内存操作,除指令本身外,完全不需要内部总线使用。它可以用作没有堆栈或进程位,没有内存的堆栈布尔。


1
这个答案在细节上相当轻。不一定需要很长的答案,但是更加充实的东西将是一个明显的改进。
David Richerby,2015年

设置标志或比较标志值是一条指令,没有任何其他信息,这些信息的形式包括在汇编代码中。标志也是微处理器处理或测试的结果,可以有效地用于分支。它们是在寄存器中比较两个值时切换或设置的实际位。
SkipBerne 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.