This is an old revision of the document!
The CPU registers are the closest place to the processor to store the data. However, not all registers are meant to store data. There might be more specialised registers to configure the processor, or additional modules for it. Microcontrollers have integrated special peripherals to perform communication tasks, convert analogue voltage signals into digital values, and vice versa, and many other peripherals. Each of them has its dedicated registers to store configuration and data. These registers are not located near the CPU but rather in memory, primarily in the specified RAM address range. Information about these peripheral module registers can be found in the reference manuals and/or the programmers' manuals. Some microcontrollers store all information in the datasheets. This section will focus on the CPU and the registers closest to it in the ARMv8 architecture.
AArch64 provides 31 general-purpose registers (R0..R30) with 64 bits. A 64-bit general-purpose register is named X0 to X30, and a 32-bit register is named W0 to W30, like in the picture above. The name ‘Rn’ is used to describe architectural registers.
IMAGE
Note that by accessing the W0 or W1 register, we cannot access the rest of the most significant 32 bits. Also, when the W register is written in a 32-bit register, the top 32 bits (most significant bits of the 64-bit register) are zeroed. And there are no registers named R0 or R1, so if we need to access the 64-bit register result, we need to address it with X0 or X1 (or others), and similarly with 32-bit registers – W0, W1 and so on are used to address general-purpose registers. These examples perform single 32-bit arithmetic operations:
IMAGE
These examples perform single 64-bit arithmetic operations:
IMAGE
Special registers like the Stack Pointer (SP), Link Register (LR), and Program Counter (PC) are available. The Link Register (LR) is stored in the X30 register. The Stack Pointer SP and the Program Counter PC registers are no longer available as regular general-purpose registers. Using the SP register with a limited set of data processing instructions through the WSP register name is still possible. Unlike ARMv7, the PC register is no longer accessible through data processing instructions. The PC register can be read by ‘ADR’ instruction, i.e. ‘ ADR, X17, . ’ – the dot ‘.’ means “here” and register X17 will be written with the exact PC register value. Some branch instructions and some load/store operations implicitly use the value of the PC register. Note that the PC and SP are general-purpose registers in the A32 and T32 instruction sets, but this is not the case in the A64 instruction set. Someone may have noticed that for A64 instructions, 32 registers in total can be addressed, but there are only 31 general-purpose registers. By accessing the value of the X31 register, the result will be either the current stack pointer or the zero register, depending on the instruction. Writing to R31 will not have any effect. The register X31 is called the Zero Register. The Zero Register, ZXR and WZR (64 or 32 bit wide), are always read as zero and ignore writes.
TABLE{ General purpose registers Dedicated registers notes Architectural name R0, R1, R2, R3, .., R29, R30 SP, ZR These names are mainly used in documentation about architecture, instruction sets. 64-bit X0, X1, X2, X3, .., X29, X30 SP, XZR The ‘x’ stands for extended word All 64 bits are used 32-bit W0, W1, W2, W3, .., W29, W30 WSP, WZR The ‘w’ stands for word Only the bottom (least significant) 32 bits are used }
IMAGE
ARMv8 has an additional 32 register set for floating point and vector operations like general-purpose registers. These registers are 128 bits wide, and like general-purpose registers, they can be accessed in several ways. The letters for these registers identify byte (Bx), half-word (Hx), single-word (Sx), double-word (Dx) and quad-word (Qx) access.
IMAGE
Similar instructions are performed with these examples, which perform single 32-bit floating-point arithmetic operations:
IMAGE (code example)
These examples perform single 64-bit floating-point arithmetic operations, and the last instruction is meant for 128-bit floating-point multiplication:
IMAGE (code example)
These registers operate like general-purpose registers; writing one byte to one of those registers will zero out the rest of the most significant bits. To save all the data in these registers, a different access method must be used: these registers can be treated as vectors using the Vx register. This means it is treated as though it contains multiple independent values, instead of a single value. Operations with vector registers are a bit complex; to make it easier to understand, let's divide those instructions that operate with vector registers into several groups. One group is meant to load and store the values of vector registers, and another group is for performing arithmetical operations on vector registers. LD1 LD1R LDAP1 LDAPUR The first group of instructions to work with vectors: the load instructions load the data into the vector register by identifying the result register for the instruction as a vector register. There are several load instructions to perform this operation
–Subsection NOT FINISHED –
For Raspberry PI 5, the ARM Cortex-A76 processor has four CPU cores. Each core has its own stack pointers, status registers and other registers. Before looking at CPU registers, some specifics must be explained. The core has several execution levels named EL0, EL1, EL2 and EL3. These execution levels in datasheets are called Exception Levels – the level at which the processor resources are managed. EL0 is the lowest level; all user applications are executed at this level. EL1 level is meant for operating systems, EL3 is intended for a Hypervisor application to control the resources for OS and the lower levels of exception layers. The CPU's general-purpose registers are independent of Exception levels, but it is essential to understand which Exception Level executes the code.
IMAGE IMAGE
We will look only at AArch64 registers to narrow the number of registers. There are a lot of registers dedicated to the CPU. Specialised registers will be left aside again to narrow the amount of information, and only those registers meant for program execution will be reviewed. As there is more than one core, each core must have a dedicated status register. All registers that store some status on AArch64 CPU cores are collected in the table below. Don’t get confused by many of these listed status registers. The registers with a green background are relevant to the programming, because only those registers store the actual instruction execution status.
TABLE