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.

InstructionCondition
beq src1, src2, LABELbranch if src1 == src2
bne src1, src2, LABELbranch if src1 != src2
bgt src1, src2, LABELbranch if src1 > src2 (signed)
bge src1, src2, LABELbranch if src1 >= src2 (signed)
blt src1, src2, LABELbranch if src1 < src2 (signed)
ble src1, src2, LABELbranch if src1 <= src2 (signed)
bgtu, bgeu, bltu, bleuunsigned 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.