Menu Close

RISC-V指令集讲解(5)条件和无条件跳转指令

1.控制转移指令

 

相关参考文章:

RISC-V教学教案

 

RV32I中控制转移指令主要有两类:无条件跳转和有条件跳转。

 

2.无条件跳转

无条件跳转指令均使用PC相对寻址。无条件跳转主要包括两条指令:JAL 和 JALR。

 

2.1 JAL

JAL指令是用J-type格式(JAL是RV32I中唯一J-type的指令)。

JAL的指令格式为 JAL rd,offset。x[rd] = pc+4; pc += sext(offset)

其机器码格式如图1所示。其opcode为110_1111。该指令把下一条指令的地址(PC + 4)存入rd寄存器中,然后把PC设置为当前值加上符号位扩展的偏移量。

JAL机器码图1 JAL机器编码格式 [1]

注意偏移量是带符号扩展的。可以看到偏移量是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。

示例:

JAL x1,main 

伪指令:JAL main,对应的真实指令:JAL x1,main

伪指令:J main,对应的真实指令:JAL x0,main

跳转到main函数,并将下一条指令存在x1寄存器中

注意:

  1. x5寄存器被选为备用的链接寄存器有两个原因:
    1. 在标准调用约定中被用作临时变量
    2. 它和常规链接器x1只有1 bit的区别 0_0001 –> 0_0101
  2. 当JAL指令省略rd时,默认rd即为x1。
  3. 伪指令J中rd为x0。

JAL机器码

图1 JAL机器编码格式 [1]

 

2.2 JALR

间接跳转指令JALR用I-type编码类型。指令格式为JALR rd,offset(rs1)

t = pc + 4;  pc = (x[rs1]+sext(offset)) & ~1;  x[rd]=t 相当于:

t = pc + 4;  pc = (x[rs1]+sext(offset)) & 0xffff_fffe;  x[rd]=t   // RV32I

其机器码如图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寄存器中。

其他伪指令示例:

JR  x1    =>  JALR x0, x1, 0

RET       => JALR x0, x1, 0

JALR x13   => JALR x1, x13, 0

一般来说,LUI和JALR配合使用可以跳转32位绝对地址范围,AUIPC和JALR配合可以跳转32位相对于PC的地址范围。

JALR机器码

图2 JALR机器编码格式 [1]

 

3.有条件分支跳转

所有的分支指令都是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机器码

图3 branch指令机器编码格式 [1]

 

3.1 BEQ

BEQ(branch if equal,相等时分支),其指令格式为BEQ rs1,rs2,offset。if (rs1 == rs2)   pc += sext(offset)

如图4所示,其opcode为110_0011,funct3为000。该指令是判断rs1寄存器和rs2寄存器里的值是否相等,如果相等,将PC的值设为当前值加上符号位扩展的偏移量offset。

示例:

BEQ x12,x13,LOOP

比较x12和x13寄存器中的值是否相等,如果相等,跳到LOOP(标签)。

BEQ机器码

图4 BEQ机器编码格式 [2]

 

3.2 BNE

BNE(branch if not equal,不相等时分支),其指令格式为BNE rs1,rs2,offset。if (rs1 ≠ rs2) pc += sext(offset)

如图5所示,其opcode为110_0011,funct3为001。该指令是判断rs1寄存器和rs2寄存器里的值是否不相等,如果不相等,将PC的值设为当前值加上符号位扩展的偏移量offset。

示例:

BNE x12,x13,LOOP

比较x12和x13寄存器中的值是否相等,如果不相等,跳到LOOP(标签)。

BNE机器码

图5 BNE机器编码格式 [2]

 

3.3 BLT

BLT(branch if less than,小于时分支),其指令格式为BLT rs1,rs2,offset。if (rs1 <s rs2) pc += sext(offset)

如图6所示,其opcode为110_0011,funct3为100。该指令是判断rs1寄存器的值是否小于rs2寄存器里的值(都视为有符号数),如果是,将PC的值设为当前值加上符号位扩展的偏移量offset。

示例:

BLT x12,x13,LOOP

有符号比较x12和x13寄存器中的值,如果x12寄存器中的值小于x13,跳到LOOP(标签)。

BLT机器码

图6 BLT机器编码格式 [2]

 

3.4 BLTU

BLTU(branch if less than,unsigned,无符号小于时分支),其指令格式为BLTU rs1,rs2,offset。if (rs1 <u rs2) pc += sext(offset)

如图7所示,其opcode为110_0011,funct3为110。该指令是判断rs1寄存器的值是否小于rs2寄存器里的值(都视为无符号数),如果是,将PC的值设为当前值加上符号位扩展的偏移量offset。

示例:

BLTU x12,x13,LOOP

无符号比较x12和x13寄存器中的值,如果x12寄存器中的值小于x13,跳到LOOP(标签)。

BLTU机器码

图7 BLTU机器编码格式 [2]

 

3.5 BGE

BGE(branch if greater than or equal,大于等于时分支),其指令格式为BGE rs1,rs2,offset。if (rs1 ≥s rs2) pc += sext(offset)

如图8所示,其opcode为110_0011,funct3为101。该指令是判断rs1寄存器的值是否大于等于rs2寄存器里的值(都视为有符号数),如果是,将PC的值设为当前值加上符号位扩展的偏移量offset。

示例:

BGE x12,x13,LOOP

有符号比较x12和x13寄存器中的值,如果x12寄存器中的值大于等于x13,跳到LOOP(标签)。

BGE机器码

图8 BGE机器编码格式 [2]

 

3.6 BGEU

BGEU(branch if greater than or equal,unsigned,大于等于时分支),其指令格式为BGEU rs1,rs2,offset。if (rs1 ≥u rs2) pc += sext(offset)

如图9所示,其opcode为110_0011,funct3为111。该指令是判断rs1寄存器的值是否大于等于rs2寄存器里的值(都视为无符号数),如果是,将PC的值设为当前值加上符号位扩展的偏移量offset。

示例:

BGEU x12,x13,LOOP

无符号比较x12和x13寄存器中的值,如果x12寄存器中的值大于等于x13,跳到LOOP(标签)。

BGEU机器码

图9 BGEU机器编码格式 [2]

 

4.文章参考

[1] Riscv.org, 2021. [Online]. Available: https://riscv.org/wp-content/uploads/2019/12/riscv-spec-20191213.pdf. [Accessed: 22- Feb- 2021].

[2] D. Patterson and A. Waterman, The RISC-V reader. Berkeley: Strawberry Canyon LLC, 2018.

Posted in FPGA, RISC-V, RISC-V, RISC-V 教案, 开发板, 指令集, 教材与教案, 文章
0 0 投票数
Article Rating
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论

相关链接