Arm defines a family of instruction set architectures (ISAs), not one processor implementation. The architecture specifies programmer-visible state, instruction semantics, exceptions, privilege, and memory ordering. A core’s pipeline, cache hierarchy, and branch predictor are microarchitectural choices.
Architecture profiles separate deployment requirements. A-profile targets application processors with virtual memory, R-profile targets real-time systems, and M-profile targets microcontrollers. The execution states and privilege model below describe A-profile systems unless stated otherwise.
Execution States and Instruction Sets #
AArch32 provides 32-bit general-purpose registers and can execute the A32
instruction set or the variable-length T32 instruction set historically called
Thumb. AArch64, introduced by Armv8-A, provides thirty-one 64-bit
general-purpose registers and the fixed-width A64 instruction set. X0 through
X30 name the 64-bit registers; W0 through W30 name their low 32 bits.
Writing a W register clears the upper half of its corresponding X register.
A processor can implement more than one execution state, but support cannot be inferred from a product’s 64-bit capability. Armv8-A permitted an AArch64 operating system to support AArch32 applications, while later architecture versions permit implementations without AArch32 at selected exception levels. Software must therefore use platform documentation and operating-system interfaces to determine which states are available.
An execution state includes more than register width. AArch32 and AArch64 have different instruction encodings, exception models, system registers, and ABIs. Code cannot switch state with an ordinary branch; an exception return or another architecturally defined transition must establish the destination state.
Registers and Procedure Calls #
A64 is a load-store ISA: arithmetic operates on registers, while explicit load and store instructions access memory.
ldr w0, [x1] // load a 32-bit value
add w0, w0, #1
str w0, [x1]Several register names have architectural or conventional roles:
| Register | AAPCS64 role |
|---|---|
X0-X7 | Integer arguments and results |
X8 | Indirect result location register |
X9-X15 | Caller-saved temporaries |
X16-X17 | Intra-procedure-call temporaries |
X18 | Platform register or temporary, depending on the platform ABI |
X19-X28 | Callee-saved registers |
X29 | Frame pointer by convention |
X30 | Link register |
SP | Stack pointer |
BL writes the return address to X30, and RET normally branches through
X30. The Procedure Call Standard for the Arm 64-bit Architecture (AAPCS64)
also defines floating-point/vector argument registers, aggregate passing,
callee-saved state, and 16-byte stack alignment. Those rules are ABI contracts,
not properties of the A64 instruction syntax. Hand-written assembly that
interoperates with compiled code must follow the platform’s complete ABI.
Exception Levels and Transitions #
A-profile systems use exception levels, where a larger number has greater privilege:
- EL0 runs unprivileged applications.
- EL1 normally runs an operating-system kernel.
- EL2 provides virtualization controls for a hypervisor.
- EL3 provides secure-monitor functionality on systems that implement it.
An implementation need not provide every level. Security states and virtualization also affect which resources an EL can access, so an EL number alone does not describe the complete protection domain.
Exceptions include synchronous exceptions, IRQs, FIQs, and system errors.
Taking an exception records a return address and saved processor state in
ELR_ELx and SPSR_ELx, selects an entry from the target EL’s vector table,
and masks or changes selected state. ERET restores the saved state after the
handler validates it. System calls commonly use SVC to enter EL1; hypervisor
and secure-monitor calls use HVC and SMC where enabled.
Translation tables and access-control registers enforce memory isolation. EL2 can add stage-two translation to an EL1 guest’s stage-one mapping, while TrustZone security states can impose another access boundary. Availability and exact register behavior depend on the implemented architecture version.
Memory Ordering, Barriers, and Atomics #
Arm uses a weakly ordered memory model. A core can observe independent loads and stores in an order different from program order when no architectural synchronization constrains them. Cache coherence ensures participating observers agree on the order of writes to one location; coherence alone does not order accesses to different locations.
Concurrent code should express the minimum ordering required by its protocol:
- Acquire loads prevent later accesses from moving before the acquire.
- Release stores prevent earlier accesses from moving after the release.
- Read-modify-write atomics provide indivisible updates with specified ordering.
DMBorders relevant memory observations within a selected shareability and access domain.DSBwaits for the specified memory effects to complete.ISBflushes the instruction pipeline so later instructions execute in the context established by preceding context-changing operations.
AArch64 supports load-exclusive/store-exclusive loops such as LDXR/STXR.
Systems with the Large System Extensions can also provide single-instruction
atomic read-modify-write operations. Both forms require retry or contention
handling, and neither repairs a language-level data race. C and C++ programs
should use their language atomic operations because compilers map those
semantics to the appropriate instructions and barriers.
Comments
Read or comment on GitHub (sign-in required to comment)