JAL
有一个 20 位偏移量和一个寄存器作为操作数。
其操作是pc := pc + sxt ( imm20 << 1 )
.
从公式中可以看出,分支是与 pc 相关的。立即数可以达到 +/- 1 MBJAL
本身。立即数移位一位,真正的 LSB 始终为零,因此不进行编码。
由于 RISC V 支持 16 位倍数(两个字节)的指令,因此我们不能假设下一个 LSB 也为零,就像 MIPS(具有 32 位指令)一样。
寄存器操作数在JAL
除了执行分支之外,还可以选择用于捕获返回地址。
JAL
的功能是使用其 20 位范围执行相对较远的 pc 分支或调用。 (与 RISC V 条件分支指令相比,RISC V 条件分支指令只有 12 位,范围为 +/- 4 KB。)
JALR
有一个 12 位偏移量和两个寄存器作为操作数。
其操作是pc := ( rs1 + sxt ( imm12 ) ) & -2
.
从公式中可以看出,分支是寄存器间接的,相对于中的值rs1
.
Like JAL
, JALR
还可以捕获返回地址。
JALR
用于从函数返回(又名RET
在装配中。在这种形式中,$ra 用作源寄存器,并且不捕获返回地址)。这使用零作为偏移量(即不需要偏移量)。
JALR
还用于执行间接函数调用:通过函数指针、虚拟方法分派等进行调用。这些用途也使用零作为偏移量。
JALR
也可以依次使用AUIPC
.
AUIPC
有一个 20 位偏移量和一个寄存器作为操作数。
其操作是rd := pc + ( imm20 << 12 )
.
它计算 pc 相对立即数的上半部分(同时还提供非相对 pc 的下半部分)。
结合JALR
,这可以完成 32 位 pc 相关的分支或调用。
AUIPC r5, labelFarAway # AUIPC encodes upper 20 bits of label's distance from pc
JALR r5, $ra, labelFarAway # JALR encodes the lower 12 bits of same