是的,零输出给你相等/不相等。如果运行速度更快(在部分时钟周期中更早准备好)和/或使用更少的功率(更少的晶体管开关),您也可以使用 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 = 这两个进位的 XOR。另请参阅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 门来结合这两个东西。