RISCV:如何计算分支指令?

Kra*_*011 5 cpu cpu-architecture alu riscv riscv32

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

  • BEQ
  • BNE
  • BLT
  • BGE
  • BLTU
  • BGEU

我使用金星模拟器来测试这个,我也在尝试模拟它,到目前为止它工作得很好,但我不明白,分支是如何计算的。从我读到的内容来看,ALU 单元只有一个信号输出—— ZERO(除了它的数学输出),只要输出为零,它就处于活动状态。但是,我如何仅根据ZERO输出来确定是否应该采用分支?它们是如何计算的?

示例代码:

addi t0, zero, 9
addi t1, zero, 10
blt t0, t1, end
end:
Run Code Online (Sandbox Code Playgroud)

分支示例:

BEQ- 减去 2 个数字,如果ZERO是活动的,则分支

BNE- 减去 2 个数字,如果ZERO不是活动的,则分支

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

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

谢谢

Pet*_*des 5

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

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


为什么使用只有零输出的 ALU?这使得它无法用于除完全相等之外的比较。

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

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


结果的符号位本身对于有符号条件是不够的,因为有符号溢出是可能的:(-1) - (-2)= +1: -1 > -2(signbit clear) but (8-bit wraparound) 0x80 - 0x7F = +1(signbit also clear) but -128 < 127. 数字的符号位本身仅在与零比较时才有用。

如果您扩大结果(通过对输入进行符号扩展并再执行一位加/减),则会导致有符号溢出不可能,因此第 33 位直接是有符号小于结果。

您还可以通过signed_overflow XOR signbit而不是实际扩大 + 添加来获得带符号的小于结果。如果 RISC-V 有任何用于软件检查有符号整数溢出的架构方法,您可能还需要 ALU 输出用于有符号溢出。

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


在带有 FLAGS 寄存器的 CPU(例如 x86 和 ARM)中,这些 ALU 输出实际上进入具有指定位的特殊寄存器。您可以查看x86 手册中的条件跳转指令,以了解条件名称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 门来组合这两件事。