cpu - RISCV:如何计算分支指令?

标签 cpu cpu-architecture riscv alu riscv32

我试图了解现代CPU的工作原理。我专注于RISC-V。分支的类型很少:


BEQ
BNE
BLT
BGE
BLTU
BGEU


我使用venus模拟器对此进行了测试,并且我也尝试对其进行模拟,到目前为止,它仍然可以正常工作,但是我不明白分支的计算方式。
根据我的阅读,ALU单元只有一个信号输出-ZERO(除了其数学输出),只要输出为零,该信号就处于活动状态。但是,我如何确定是否应该仅基于ZERO输出来确定分支?以及如何计算?

示例代码:

addi t0, zero, 9
addi t1, zero, 10
blt t0, t1, end
end:


分支示例:

BEQ-减去2个数字,如果ZERO处于活动状态,则分支

BNE-减去2个数字,如果ZERO未激活,则分支

BLT-在这里,我有点困惑;我应该减去然后查看符号位,还是什么?

BGE / BGEU-以及如何区分这些?我应该使用什么数学指令?

谢谢

最佳答案

是的,ZERO输出为您提供等于/不等于。如果运行速度更快(在部分时钟周期中更早准备)和/或使用更少的功率(更少的晶体管开关),您也可以使用XOR而不是SUB进行相等比较。

有趣的事实:MIPS仅具有eq / ne和有符号比较-反对零条件,所有这些条件都可以快速进行测试,而无需进位传播或任何其他级联位。这很重要,因为它在与解码相同的阶段检查了分支条件,从而减少了分支等待时间。 (因此1个分支延迟插槽隐藏了延迟。)



为什么使用仅输出零的ALU?这使得除完全相等之外的其他比较无法使用。

您需要其他输出来从减法结果中确定GT / GE / LE / LT(及其无符号等效项)。

对于无符号条件,您所需要做的只是零和一个进位/借位(无符号溢出)标志。



结果本身的符号位不足以用于带符号的条件,因为可能发生带符号的溢出:(-1) - (-2) = +1-1 > -2(符号位清除)但(8位环绕)0x80 - 0x7F = +1(符号位也清除),但-128 < 127。仅当与零比较时,数字的符号位才有用。

如果扩大结果(通过对输入进行符号扩展并再做一点加法/加法运算),则将导致有符号溢出成为不可能,因此第33位是直接小于符号的结果。

您还可以从signed_overflow XOR signbit获得小于符号的结果,而不是实际上加宽+添加。如果RISC-V具有任何用于软件检查签名整数溢出的体系结构方式,则您可能还希望ALU输出用于签名溢出。

可以通过查看进位和从MSB(符号位)中执行进位来计算符号溢出。如果这些不同,则您溢出。即SF =这两个进位的XOR。另请参见http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt,以详细了解2位和4位示例的无符号进位与有符号溢出。



在具有FLAGS寄存器的CPU(例如x86和ARM)中,这些ALU输出实际上进入带有命名位的特殊寄存器中。您可以查看x86 manual for conditional-jump instructions来查看诸如l(小于符号)或b(以下未签名)之类的条件名称如何映射到这些标志:

签署条件:


jl(又名RISC-V blt):如果小于(SF≠ OF)则跳转。从减法/ cmp中得出的输出符号位不等于溢出标志
jle:小于或等于(ZF=1 or SF≠ OF)时跳转。
jge(又名RISC-V bge):如果大于或等于(SF=OF),则跳转。
jg(又名RISC-V bgt):如果较大,则跳短(ZF=0 and SF=OF)。


如果您决定让ALU只是产生一个“小于符号”输出,而不是单独的SF和OF输出,那很好。 SF==OF就是!(SF != OF)

(x86还为同一操作码提供了一些助记词同义词,例如jl = jnge。“只有” 16个FLAGS谓词,包括单独的OF=0(测试溢出,而不是比较结果)和奇偶校验标志。您只关心实际的有符号/无符号比较条件。)

如果您通过一些示例案例进行思考,例如测试INT_MAX > INT_MIN,您将了解这些条件为何有意义,就像我上面为8位数字显示的示例一样。

未签名:


jb(又名RISC-V bltu):如果低于(CF=1),则跳转。那只是测试进位标志。
jae(又名RISC-V bgeu):如果大于或等于(CF=0),则跳短。
ja(又名RISC-V bgtu):如果高于(CF=0 and ZF=0),则跳短。


(请注意,x86减法设置CF =借位输出,因此1 - 2设置CF = 1。其他一些ISA(例如ARM)会反转进位标志以进行减法。在实现RISC-V时,这将全部在CPU内部,而不是体系结构对软件可见)。

我不知道RISC-V是否实际上具有所有这些不同的分支条件,但是x86确实具有。

实现有符号或无符号比较器可能比进行减法更简单。

但是,如果您已经有一个加/减ALU并希望使用它,那么您可能只希望它生成“进位”和“小于符号”输出以及零。

这样,您就不需要单独的符号标志输出,也不需要获取整数结果的MSB。这只是ALU内部一个额外的XOR门,可以将这两件事结合在一起。

关于cpu - RISCV:如何计算分支指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57452447/

相关文章:

java - Tomcat 7 启动时无连接时 CPU 使用率较高

caching - 虚拟索引物理标记缓存同义词

assembly - 汇编中main函数开头的栈内存操作

verilog - RISC-V 异常与中断

assembly - 如何在 RISC-V 汇编中使用数组

c - 面向 C 程序员的 Intel Core

Java限制资源使用

python - 有没有办法用python获取本地机器的进程信息?

algorithm - 什么是冗余与非冗余数字格式?

assembly - Piledriver 架构中有哪些指令集不在 Bulldozer 中?