The main objective of this lab is to understand control structures in ARMv8. Before proceeding with this lab, you should be familiar with the different branch
and conditional branch instructions in ARMv8 (Sections 2.7, 2.8 and 2.10 of the textbook).
Flow Control
In previous labs, your programs have mostly been purely sequential (each instruction is executed in a sequential order); most programs, however, require
flow control. ARMv8 contains control instructions, which allow programs to execute in a non-sequential manner. In a high-level language, such as C, control
structures have the form if-then-else, goto, for,or do-while. In assembly language, the flow control statements are generally simpler and are of the following
forms: branch, call, and return. Each has the ability to alter the flow of the program.
The program counter (PC) register contains the address of current instruction to be executed. In sequential flow, the PC is incremented to the next
instruction (by 4) each time an instruction starts its execution. The PC register itself cannot be accessed directly by the program, but ARMv8 provides other
means to alter its value, and thus change the location where the program will continue its execution. There are 2 types of control instructions:
Conditional Branches - These control instructions may or may not change the PC depending on a certain condition. These instructions are generally
referred to as branch instructions, because the program flow will follow one of two possible paths (branches). A branch instruction must both specify
the condition on which it will branch, as well as the target address if the conditions are satisfied. If the conditions are not satisfied,the program
continues execution at the next instruction.
Unconditional Branches - These control instructions always change the PC without any conditions. An unconditional branch instruction must always
specify where to get it's the target address.
Conditional Branches
Conditional branch instructions are typically used to form loops. Since most loops tend to be small in size, the target address tends to be close to the branch
instruction. When the target instruction is close enough to the current instruction, then the target can be specified relative to the current instruction with a
small offset. A branch instruction could be described as the equivalent of “If X0 is not 0, then skip the next 5 instructions.” In addition to the offset being
positive (forward branch), the branch instruction also allows a negative offset (backwards branch). Such a branch would be useful in an instruction that does
the equivalent of “If the loop is not done, go back 100 instructions and execute it again.” This is called PC-relative addressing.
Note that all PC-relative addressing is in terms of instructions rather than bytes, so the offset encoded is always right shifted by two versus the true byte
offset of the target from the current PC.
There are two types of conditional branches, equality conditional branches and condition-code conditional branches. Equality conditional branches are the
simplest and only test for a register being equal to or not equal to zero. For example:
CBZ X0, label
// if X0 == 0 then go to label
CBNZ X0, label // if X0 != 0 then go to label
While equality branches are sufficient for many cases, they do not easily allow more complicated tests often used in higher-level languages. To deal with
these cases, ARMv8 also includes condition-code based branches. These branches use the processor state flags which are set by certain arithmetic
operations. In particular, ARMv8 has the following processor state condition flags as shown in Table 2.1:
Table 2.1. Condition flags
Flag
Name
Description
N
Negative
Set to the same value as bit[31] of the result. For a 32-bit signed integer, bit[31] being set indicates that the value
is negative.
Z
Zero
Set to 1 if the result is zero, otherwise it is set to 0.
C
Carry
Set to the carry-out value from result, or to the value of the last bit shifted out from a shift operation.
V
Overflow
Set to 1 if signed overflow or underflow occurred, otherwise it is set to 0.
These flags can be set by any arithmetic operation with the trailing "S" as described in the book (e.g. ADDS for add operation with flag
set). So for instance the following code:
SUBS X0, X1, X2 // Assume X1 = 1, and X2=1
Read More