RISC-V 跳转指令¶
转载于RISC-V指令集讲解(5)条件和无条件跳转指令 - 知乎 (zhihu.com)
RV32I中控制转移指令主要有两类:无条件跳转和有条件跳转。
1 无条件跳转¶
无条件跳转指令均使用PC相对寻址。无条件跳转主要包括两条指令:JAL 和 JALR。
1.1 JAL¶
JAL指令是用J-type格式(JAL是RV32I中唯一J-type的指令)。
JAL的指令格式为 JAL rd,offset
其机器码格式如图1所示。其opcode为110_1111。该指令把下一条指令的地址(PC + 4)存入rd寄存器中,然后把PC设置为当前值加上符号位扩展的偏移量。
下图为JAL机器编码格式
注意偏移量是带符号扩展的。可以看到偏移量是2字节对齐的(offset [20:1]),虽然RV32I中所有的指令地址都是4字节对齐的,但是JAL还可能被用于兼容C扩展指令集(详情见RISC-V 简介(4)RISC-V指令集编码结构中对其的描述),所以就默认offset bit 0为0(即2字节对齐)。
因此,JAL跳转的地址有+/- 1MB的范围。(2^21 = 2MB = +/- 1MB)。
标准的软件调用约定(calling convention)用x1寄存器作为返回地址寄存器(rd),也可以用x5作为备用的链接寄存器(link register)。因为JAL指令中的offset是相对于PC的偏移量,在编写时需要精确的地址差值,且任意添加/删除一条汇编指令,JAL中的偏移量可能就需要再次修改,这给JAL指令的使用带来了很大的负担,所以,一般在用JAL指令时,多用JAL rd,label而不是JAL rd,offset。
JAL rd,label中的label是标签,用来标注某段程序的位置,为程序中跳转及分支语句提供的跳转入口(label使用实例可以点击这里)。编译器会自动计算出标签和当前指令的offset。
1.2 JALR¶
间接跳转指令JALR用I-type编码类型。指令格式为JALR rd,offset(rs1)。
相当于:
其机器码如图2所示,其opcode为110_0111,funct3为000。
该指令将PC设置为rs1寄存器中的值加上符号位扩展的偏移量,把计算出地址的最低有效位设为0,并将原PC + 4的值写入rd寄存器。如果不需要目的寄存器,可以将rd设置为x0。
JALR的offset也是带符号位扩展的,JALR偏移的地址范围在rs1寄存器中存储地址的+/- 2KB(2 ^ 12 = 4096 = 4 KB = +/- 2KB)。定义JALR指令是为了使两个指令序列可以在32位绝对地址范围内的任意位置跳转(因为JAL指令的跳转范围不够大)。
示例:
JALR x13,0(x1)
跳到x1寄存器里存储的地址,并将下一条指令存在x13寄存器中。
一般来说,LUI和JALR配合使用可以跳转32位绝对地址范围,AUIPC和JALR配合可以跳转32位相对于PC的地址范围。
下图是JALR机器编码格式
2 有条件分支跳转¶
所有的分支指令都是B-type编码格式,其机器码如图3所示。12位的立即数以2字节的倍数编码带符号的偏移量(offset[12:1])。
虽然RV32I中所有的指令地址都是4字节对齐的,但是JAL还可能被用于兼容C扩展指令集,所以就默认offset bit 0为0(即2字节对齐)。
目标地址由分支指令的地址加上符号位扩展的偏移量组成,范围是2^13 = 8192 = 8 KB = +/- 4 KB。
与JAL类似,Branch指令常见用法也可以用标签代替偏移量,比如BEQ rs1,rs2,label。
branch指令机器编码格式如下图:
2.1 BEQ¶
BEQ(branch if equal,相等时分支)
其指令格式为
2.2BNE¶
BNE(branch if not equal,不相等时分支)
其指令格式为
2.3 BLT¶
BLT(branch if less than,小于时分支)
其指令格式为
2.4 BLTU¶
BLTU(branch if less than,unsigned,无符号小于时分支)
其指令格式为
2.5 BGE¶
BGE(branch if greater than or equal,大于等于时分支)
其指令格式为
2.6 BGEU¶
BGEU(branch if greater than or equal,unsigned,大于等于时分支)
其指令格式为


