条件分支指令(Conditional Branch Instructions)

指令 格式 语法 描述 例子
BEQ B-type BEQ RS1,RS2,IMM Branch if EQual,比较 RS1 和 RS2 的值,如果相等,则执行路径跳转到一个新的地址 beq x5, x6, 100
BNE B-type BNE RS1,RS2,IMM Branch if Not Equal,比较 RS1 和 RS2 的值,如果相等,则执行路径跳转到一个新的地址 bne x5, x6, 100
BLT B-type BLT RS1,RS2,IMM Branch if Less Than,按照有符号方式比较 RS1 和 RS2 的值,如果 RS1 < RS2,则执行路径跳转到一个新的地址 blt x5, x6, 100
BLTU B-type BLTU RS1,RS2,IMM Branch if Less Than(Unsigned),按照无符号方式比较 RS1 和 RS2 的值,如果 RS1 < RS2,则执行路径跳转到一个新的地址 bltu x5, x6, 100
BGE B-type BGE RS1,RS2,IMM Branch if Greater than or Equal,按照有符号方式比较 RS1 和 RS2 的值,如果 RS1 >= RS2,则执行路径跳转到一个新的地址 bge x5, x6, 100
BGEU B-type BGEU RS1,RS2,IMM Branch if Greater than of Equal(Unsigned),按照无符号方式比较 RS1 和 RS2 的值,如果 RS1 >= RS2,则执行路径跳转到一个新的地址 bgeu x5, x6, 100
  • 跳转的目标地址计算方法:先将 IMM × 2,符号扩展后和 PC 相加得到最终的目标地址,所以跳转范围是以 PC 为基准,+/-4KB 左右([-4096,4094])
  • 具体编程时,不会直接写 IMM,而是用标号代替,交由链接器来最终决定 IMM 的值

无条件跳转指令(Unconditional Jump Instructions)

JAL(Jump and Link)

  • 语法:JAL RD, LABEL
  • 示例:jal x1, label
  • 格式:J-type
  • jal 指令用于调用子过程(subroutine/function)
  • 子过程的地址计算方法:首先对 20 bits 宽的 IMM × 2 后进行 sign-extended,然后将符号扩展后的值和 PC 值相加,因此该函数跳转的范围是以 PC 为基准,上下 ~+/- 1MB
  • jal 指令的下一条指令的地址写入 rd,保存为返回地址
  • 实际编程时,用 label 给出跳转的目标,具体 IMM 值由编译器和链接器最终负责生成
  • 语法:JALR RD, IMM(RS1)
  • 示例:jalr x0, 0(x5)
    • 此示例中,x0 其实是可以的,在这个位置写 x0 代表不想跳转回来
  • 格式:I-type
  • 子过程的地址计算方法:首先对 12 bits 宽的 IMM 进行 sign-extended,然后将符号扩展后的值和 RS1 值相加,得到最终的结果后将最低位设置为0(确保地址按 2 字节对齐),因此该函数跳转的范围是以 RS1 为基准,上下 ~+/- 2KB
  • jalr 指令的下一条指令的地址写入 rd,保存为返回地址

如果跳转后不需要返回,那么可以利用 x0 代替 jal 和 jalr 中的 rd

伪指令 语法 等价指令 例子
j j offset jal x0, offset j leap
jr jr rs jalr x0, 0(rs) jr x2

RISC-V 指令寻址模式总结

  • 所谓寻址模式指的是指令中定位操作数(operand)或者地址的方式
  • 立即数寻址
    • 解释:操作数是指令本身的一部分
    • 例子:addi x5, x6, 20
  • 寄存器寻址
    • 解释:操作数存放在寄存器中,指令中访问指定的寄存器从而获取该操作数
    • 例子:add x5, x6, x7
  • 基址寻址
    • 解释:操作数在内存中,指令中通过指定寄存器(基址 base)和立即数(偏移量 offset),通过 base + offset 的方式获得操作数在内存中的地址从而获取该操作数
    • 例子:sw x5, 40(x6)
  • PC 相对寻址
    • 解释:在指令中通过 PC 和指令中的立即数相加获得目标地址的值
    • 例子:beq x5, x6, 100