Overview Why you should care about the ISA Instruction sets in the Arm architecture Instruction set resources Simple sequential execution Registers in AArch64 - general-purpose registers Registers in AArch64 - other registers Registers in AArch64 - system registers Data processing - arithmetic and logic operations Data processing - floating point Data processing - bit manipulation Data processing - extension and saturation Data processing - format conversion Data processing - vector data Loads and stores Loads and stores - size Loads and stores - zero and sign extension Loads and stores - addressing Loads and stores - load pair and store pair Loads and stores - using floating point registers Program flow Program flow - loops and decisions Program flow - generating condition code Program flow - conditional select instructions Function calls Procedure Call Standard System calls Check your knowledge Related information Next steps
Function calls
When calling a function or sub-routine, we need a way to get back to the caller when finished. Adding an L
to the B
or BR
instructions turns them into a branch with link. This means that a return address is written into LR
(X30
) as part of the branch.
Note: The names LR
and X30
are interchangeable. An assembler, such as GNU GAS or armclang, will accept both.
There is a specialist function return instruction, RET
. This performs an indirect branch to the address in the link register. Together, this means that we get:

Note: The figure shows the function foo()
written in GAS syntax assembler. The keyword .global
exports the symbol and .type
indicates that the exported symbol is a function.
Why do we need a special function return instruction? Functionally, BR LR
would do the same job as RET
. Using RET
tells the processor that this is a function return. Most modern processors, and all Cortex-A processors, support branch prediction. Knowing
that this is a function return allows processors to more accurately predict the branch.
Branch predictors guess the direction the program flow will take across branches. The guess is used to decide what to load into a pipeline with instructions waiting to be processed. If the branch predictor guesses correctly, the pipeline has the correct instructions and the processor does not have to wait for instructions to be loaded from memory.