Control Flow Instructions

instrdescription
beq rs1, rs2, imm[12:1]Branch to pc + sext(imm) if rs1 = rs2
bne rs1, rs2, imm[12:1]Branch to pc + sext(imm) if rs1rs2
blt rs1, rs2, imm[12:1]Branch to pc + sext(imm) if (int)rs1 < (int)rs2_
bltu rs1, rs2, imm[12:1]Branch to pc + sext(imm) if (uint)rs1 < (uint)rs2
bge rs1, rs2, imm[12:1]Branch to pc + sext(imm) if (int)rs1 >= (int)rs2_
bgeu rs1, rs2, imm[12:1]Branch to pc + sext(imm) if (uint)rs1 >= (uint)rs2
jal rd, imm[20:1]Jump and link
jalr rd, rs1, imm[11:0]Jump and link register

Conditional branches

A conditional jump to anywhere in range of ±4 KiB (1K instructions) relative to pc (at 16 bit boundary).

jal rd, imm[20:1] (jump-and-link):

  • writes the address of the subsequent instruction (pc + 4) to rd
  • sets pc to pc + sext(imm), allowing for jumps in a ±1MiB range.

Note: a one-way "goto" can be jal x0, offset to discard the "return" address.

"Long jumps" (to an arbitrary 32-bit offset) can be done with:

    auipc x1, offset[31:12]
    jalr  x0, offset[11:0](x1)

jalr rd, rs1, imm[11:0] allows for indirect jumps (switch statements, function returns, indirect function calls, vtable dispatch, etc):

  • write the address of the next instruction (pc + 4) into rd
  • set pc to pc + rs1 + sext(imm)

TODO: if rd is rs1, does it use the original value?

Encoding

jal is UJ-type.

imm[20,10:1,11,19:12]rdopcode
jal11 011 11

jalr is I-type.

imm[11:0]rs1funct3rdopcode
jalr00011 001 11

Conditional branches are SB-type

imm[12,10:5]rs2rs1funct3imm[4:1,11]opcode
beq00011 000 11
bne00111 000 11
blt10011 000 11
bge10111 000 11
bltu11011 000 11
bgeu11111 000 11

Least significant byte 6_/E_ encodes a branch instruction:

  • 63/E3 for conditional jumps
  • 67/E7 for jalr
  • 6F/EF for jal