beq
beq
rs1, rs2, label
if (rs1 == rs2) goto label
R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

beq is how a program makes a decision. Normally the processor runs your instructions in order, one after the next, straight down the list. On its own that can never choose or repeat anything. A branch breaks the straight line: it checks a condition and, if the condition holds, tells the processor to continue somewhere else instead of at the next line. Every if and every loop is built from this.

The somewhere else is named by a label — a name followed by a colon, like done:, that marks a position in your code. beq (branch if equal) compares two registers and, when they hold the same value, jumps to the labelled spot; when they differ, it does nothing special and execution simply continues with the next instruction. The form is beq rs1, rs2, label.

Underneath, the processor tracks where it is with a hidden register called the program counter, which holds the address of the instruction currently running. Taking a branch just changes that address so the next instruction is fetched from the label instead of the following line.

A very common use compares a register against zero (the always-zero register) to ask has this reached zero — for ending countdown loops or checking a result. The example branches to done when a0 has counted down to zero. With nothing more than beq and labels you can build every decision and loop in a program.

beq a0, zero, done   # if a0 == 0, jump to 'done'