AArch64执行状态提供31个64位通用寄存器,在所有的异常等级都可以访问。这31个寄存器被称为X0-X31。每个64位寄存器也有32位形式(W0-W30)。
32位W寄存器是64位的低半部分。从W寄存器读抛弃了X寄存器的高32位,并且不改变它们。
写W寄存器将X寄存器的高32位置0。
X29用作Frame pointer帧指针。X30用作Procedure link register。
除了31个寄存器外,还有几个特殊寄存器。
访问0寄存器时,所有的写被忽略,所有的读返回0。
Table 4-1 Special registers in AArch64
Name | Size | Description |
WZR | 32bits | Zero register |
XZR | 64bits | Zero register |
WSP | 32bits | Current stack pointer |
SP | 64bits | Current stack pointer |
PC | 64bits | Program counter |
当执行在AArch64时,异常返回状态存储在对应异常等级的下述寄存器中:
Exception Link Register (ELR)
Saved Processor State Register (SPSR)
每个异常状态都有对应的SP。
Table 4-2 Special registers by Exception level
EL0 | EL1 | EL2 | EL3 | |
Stack Pointer (SP) | SP_EL0 | SP_EL1 | SP_EL2 | SP_EL3 |
Exception Link Register (ELR) | ELR_EL1 | ELR_EL2 | ELR_EL3 | |
Saved Process Status Register (SPSR) | SPSR_EL1 | SPSR_EL2 | SPSR_EL3 |
Stack pointer
每个异常等级有它自己的栈指针。但是在AArch64时,一个非EL0的异常等级可以选择使用自己等级的栈指针,也可以使用EL0的栈指针。但是EL0只能访问SP_EL0.
大多数指令不能访问SP,但是ADD等一些算术指令可以。
Program Counter
ARMv7使用R15作为PC寄存器,但是ARMv8移除了对PC寄存器的直接访问。
Exception Link Register (ELR)
ELR存储异常状态的返回地址。
Saved Process Status Register
当发生异常时,处理器状态存储到对应的SPSR,这和ARMv7的CPSR类似。SPSR存储发生异常的PSTATE。
N Negative result
Z Zero result
C Carry out
V Overflow
SS Software Step
IL Illegal Execution State bit
D Process state Debug mask
A SError mask
I IRQ mask
F FIQ mask
M[4] Execution state, 0 表示AArch64
M[3:0] Mode or Exception level
AAarch64没有ARMv7 CPSR等价的寄存器。在AArch64里,传统的CPSR里对应的位可以单独访问,他们被称为Processor State (PSTATE).
在AArch64,通过ERET指令从异常返回。这把SPSR_ELn拷贝到PSTATE。
PSTATE.{N,Z,C,V}可以在所有的EL访问,其它位只能在高于EL0的等级访问。
在AArch64,系统配置通过系统寄存器控制,通过MSR和MRS指令访问。相反,ARMv7通过协处理寄存器15访问。寄存器的名字中包含最低可访问的异常等级,如TTBR0_EL1,可以在EL1/2/3访问。
访问寄存器的例子:
MRS x0, TTBR0_EL1 读取到x0
MSR TTBR0_EL1, x0 写
之前的ARM架构使用协处理来配置系统,但是AArch64不支持协处理器。
The system control register
SCTLR是用来控制标准内存,系统功能等的寄存器。包括控制大小端、开启MMU等。具体可查阅相关手册。
每个异常等级的大小端可以单端控制,通过SCTLR寄存器的EE位。EL1有一个额外的位,用来控制EL0的大小端。在AArch64执行状态,数据访问可以为LE或者BE,但是指令预取总是LE。
是否支持大小端,依赖于处理器的实现。
在AArch32执行状态,最好不要让CPSR.E和系统控制寄存器的EE不同含义,也不要使用ARMv7的SETEND指令。
从AArch32切换AArch64:
- AArch32可访问的寄存器的高32位的值为UNKNOWN。
- AArch32不可访问的寄存器值保持不变。
- 到EL3的异常点,如果EL2使用AArch32,ELR_EL2的高32位为UNKNOWN。
- AArch64 Stack Pointers (SPs) 和 Exception Link Registers (ELRs) 在AArch32执行状态不可访问。进入64位时会获取其对应的值。包括:SP_EL0/1/2 ELR_EL1
virtually identical to ARMv7,意味着AArch32必须匹配ARMv7的privilege levels。
ARMv7架构有16个32位通用寄存器(R0-R15),前15个用于通用数据存储,R15用于program counter (PC)。程序也可以访问CPSR和SPSR。发生异常时CPSR被拷贝到SPSR。
同时有banking特性,哪个寄存器被访问,依赖于当前的处理器模式:
Banking用来减小异常延迟,也意味着在一个时间点,更少的寄存器。
相反,AArch64执行状态有31个64位通用寄存器,任何时候都可以访问。在AArch64和AArch32执行状态间改变,意味着必须进行寄存器进行映射。
AArch32的SPSR和ELR_Hyp是额外的寄存器,只有系统指令可以访问,他们没有映射到AArch64的通用寄存器。其中一些映射关系为:
SPSR_svc maps to SPSR_EL1
SPSR_hyp maps to SPSR_EL2
ELR_hyp maps to ELR_EL2
下列寄存器只在AArch32执行状态使用。然而,因为EL1使用AArch64,他们保持住他们的状态。
SPSR_abt.
SPSR_und
SPSR_irq
SPSR_fiq
从AArch32切换到AArch64时,所有ELR_ELn寄存器的高32位为0
除了通用寄存器,ARMv8有32个128位浮点寄存器,labeled V0-V31,这32个寄存器用来存储标量浮点指令的浮点操作数,已及NEON操作的标量和向量操作数。
这些寄存器有64/32/16位形式,叫做双精度(Dn),单精度(Sn), 半精度(Hn)
半精度浮点数只用来转换,不用来做计算。
FADD Sd, Sn, Sm
FADD Dd, Dn, Dm
FCVT Sd, Hn // half precision to single precision
存储标量数据时的排列
Vector register sizes
指令如:
ADD Vd.4S, Vn.4S, Vm.4S
NEON in AArch32 execution state
映射到AArch64的FP和SIMD寄存器。AArch64的V16-v31 FP和NEON寄存器在AArch32不可访问。