jal 使用半绝对目标编码(替换 PC 的低 28 位),而 bgezal / bltzal 是相对的(添加 18 位有符号位移,imm16<<2)。 How to Calculate Jump Target Address and Branch Target Address?
它们是经典 MIPS 唯一的分支和链接(而不是跳转和链接),因此对于与位置无关的可重定位代码很重要。(您甚至可以使用一个来获取当前将 PC 放入一个寄存器并找出你从哪里执行,这与 jal 不同)。
您可以将bal(无条件相对函数调用)编码为bgezal $zero, target。
您无需任何其他设置即可获得$ra=PC 和未采用的bltzal $zero, anywhere。 使用bgezal 进行此操作将需要一个小于零的输入寄存器,该寄存器需要一个insn 创建。 b...al 指令 总是 写入 $ra,即使分支未被采用。对于 PC 相关代码,您需要此功能,直到 MIPS32r6 为我们提供 addiupc 以更好地生成 PC 相关地址。
由于它们像其他 branch 指令一样使用 I 型指令格式,因此在一个寄存器的编码中有空间,因此将其设为可选条件而不是 只是 bal 指令。执行“和链接”的硬件逻辑已经存在,所有其他相关分支指令都是有条件的。另外,对于 $zero 而言,具有未采用的条件可能会方便阅读 pc。
请记住,MIPS 指令编码在早期 MIPS 硬件中直接用作内部控制信号,因此它们之间不同的编码中的一位可能被连接到一个异或门,该异或门反转(或不反转)对符号位的检查. (正如 Konrad 的回答所指出的,这些分支条件仅取决于寄存器的 MSB,因为它总是反对零,因此等待 32 位加法器产生比较结果没有延迟。)
来自http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html
0000 01ss sss1 0001 iiii iiii iiii iiii BGEZAL
0000 01ss sss1 0000 iiii iiii iiii iiii BLTZAL
指令编码缺乏灵活性(因为它直接驱动内部控制信号,而不需要在解码中进行大量转换)可能是为什么不只有一个具有 28 位范围的bal(从 26 -位相对位移)。相关分支的硬件是为 16 位立即数的 I 型指令设置的。
TL:DR:有 2 个条件分支和链接指令,因为其中一个实现无条件 bal 是很自然的,而另一个几乎是免费的。
MIPS b(无链接的无条件相对分支)也是beq $zero, $zero, target 的伪指令,或者由汇编程序选择,用于bgez $zero, target。 (What is the difference between unconditional branch and unconditional jump (instructions in MIPS)?)。 MIPS R3000 manual 建议 beq $zero,$zero。 (并且更清楚地记录了$ra=PC 无论分支如何都会发生;这在我最初编写此答案时正在查看的快速参考表中并不清楚。)
比较零编码只有一个 5 位寄存器字段,因此它们消耗的编码空间比beq / bne 少。这可能是选择 bgezal 而不是 beqal 作为要提供的一对条件分支之一的一个可能原因。