Branch instructions in Nios II alter the PC to redirect execution — either unconditionally or based on a comparison between two registers. They’re how loops, if-statements, and early returns are implemented.
Unconditional branch
br LABEL
Jump to LABEL no matter what.
br myloop
The assembler resolves LABEL to a PC-relative offset, encoded in the instruction. The processor adds that offset to PC + 4 (the next instruction) to get the target address.
Branch range is limited to a 16-bit signed byte offset — roughly to bytes from the next instruction, which is about instructions (since each instruction is 4 bytes). For longer jumps, use jmp with a register holding the full target address.
Conditional branches
All conditional branches take two source registers and a label. They compare the two registers; if the condition is true, branch to LABEL; otherwise, fall through to the next instruction.
| Instruction | Condition |
|---|---|
beq src1, src2, LABEL | branch if src1 == src2 |
bne src1, src2, LABEL | branch if src1 != src2 |
bgt src1, src2, LABEL | branch if src1 > src2 (signed) |
bge src1, src2, LABEL | branch if src1 >= src2 (signed) |
blt src1, src2, LABEL | branch if src1 < src2 (signed) |
ble src1, src2, LABEL | branch if src1 <= src2 (signed) |
bgtu, bgeu, bltu, bleu | unsigned versions |
Examples:
beq r3, r4, equal_path # if r3 == r4, jump
bgt r5, r0, positive # if r5 > 0, jump (using r0 as constant 0)
ble r6, r7, end_loop # if r6 <= r7, exit loop
r0 is the always-zero register, so comparisons against it test sign or zero conditions:
beq r3, r0, ...— branch if r3 is zero.bne r3, r0, ...— branch if r3 is nonzero.bgt r3, r0, ...— branch if r3 is positive.blt r3, r0, ...— branch if r3 is negative.
Loops
The standard loop idiom:
movi r3, 10 # counter = 10
loop:
# ... loop body ...
subi r3, r3, 1 # counter--
bgt r3, r0, loop # while counter > 0
The branch sits at the bottom; falling through past it ends the loop. This is a test-at-end loop — guaranteed to execute the body at least once. To get test-at-top behavior, branch to a check first:
movi r3, 10
br loop_check
loop:
# ... body ...
subi r3, r3, 1
loop_check:
bgt r3, r0, loop
If-then-else
Inverted comparison: jump past the then-branch if the condition is false.
# if (r3 >= avg) count = count + 1
blt r3, r4, else_path # if r3 < avg, skip the then
addi r6, r6, 1 # then: count++
br end_if # skip past else
else_path:
# else clause (empty in this case)
end_if:
# rest of code
The pattern: branch on the opposite condition to skip the matching code. If the condition is “if r3 >= r4 do X”, the assembly inverts it to “branch over X if r3 < r4.”
How branches affect PC
Each branch updates PC differently from the default PC + 4:
- Branch taken: .
- Branch not taken: (normal).
The offset is signed, so branches can go forward or backward. Loops branch backward; if-skips branch forward.
For the related call/return mechanism — which is also a branch but with extra side effects — see Subroutine.