Loops and decisions

In this section, we will examine how loops and decisions let you change the flow of your program code using branch instructions. There are two types of branch instructions: unconditional and conditional.

Unconditional branch instructions 

The unconditional branch instruction B <label> performs a direct, PC-relative, branch to <label>. The offset from the current PC to the destination is encoded within the instruction. The range is limited by the space available within the instruction to record the offset and is +/-128MB.

When you use BR <Xn>, BR performs an indirect, or absolute, branch to the address specified in Xn.

Conditional branch instructions 

The conditional branch instruction B.<cond> <label> is the conditional version of the B instruction. The branch is only taken if the condition <cond> is true. The range is limited to +/-1MB.

The condition is tested against the ALU flags stored in PSTATE and needs to be generated by a previous instruction such as a compare (CMP).

CBZ <Xn> <label> and CBNZ <Xn> <label>

This instruction branches to <label> if Xn contains 0 (CBZ), and branches to label if Xn does not contain 0 (CBNZ).

TBZ <Xn>, #<imm>, <label> and TBNZ <Xn>, #<imm>, <label>

TBX works in a similar way to CBZ/CBNZ, but tests the bit specified by <imm>.

Note: The direct, or PC-relative, branches store the offset to the destination within the instruction. The conditional branches have a smaller range. This is because some bits are needed to store the condition itself, which leaves fewer bits for the offset.

Mapping these on to what you might write in C, this table shows examples of using branches for loops and decisions:

C Typical output from a compiler

if (a == 5)
  b = 5;

  CMP W0, #5
  B.NE skip
  MOV W8, #5
 skip:
 …

 while (a != 0)
 {
  b = b + c;
  a = a - 1;
 }

loop:
 CBZ W8, skip
 ADD W9, W9, W10
 SUB W8, W8, #1
 B loop
skip:
 …

Note: The labels shown in the output would not be created by a compiler. They are included here to aid readability.

Previous Next