/*
* 2019/5/20 15:04 yin
*/
ARM64 有34个寄存器,包括31个通用寄存器、SP、PC、CPSR。
NEON寄存器是V0~V31共计32个。AArch32状态下的NEON寄存器组,Q0~Q15,同时对应D0~D32,一个Q分为两个D,这两个D是可以单独操作的;
寄存器 位数 描述
x0-x30 64bit 通用寄存器,如果有需要可以当做32bit使用:WO-W30
FP(x29) 64bit 保存栈帧地址(栈底指针)
LR(x30) 64bit 通常称X30为程序链接寄存器,保存子程序结束后需要执行的下一条指令
SP(x31) 64bit 保存栈指针,使用 SP/WSP来进行对SP寄存器的访问。
PC 64bit 程序计数器,俗称PC指针,总是指向即将要执行的下一条指令,在arm64中,软件是不能改写PC寄存器的。
CPSR 64bit 状态寄存器
'x0-x7: 用于子程序调用时的参数传递,X0还用于返回值传递
AArch拥有31个通用寄存器,系统运行在64位状态下的时候名字叫Xn,运行在32位的时候就叫Wn;
R0 - R30 31 general-purpose registers, R0 to R30. Each register can be accessed as:
. A 64-bit general-purpose register named X0 to X30
. A 32-bit general-purpose register named W0 to W30
寄存器类型 Bit 描述
X0-X30 64bit 通用寄存器,如果有需要可以当做32bit使用:WO-W30
LR (X30) 64bit 通常称X30为程序链接寄存器,保存跳转返回信息地址
SP_ELx 64bit 若PSTATE.M[0] ==1,则每个ELx选择SP_ELx,否则选择同一个SP_EL0
ELR_ELx 64bit 异常链接寄存器,保存异常进入ELx的异常地址(x={0,1,2,3})
PC 64bit 程序计数器,俗称PC指针,总是指向即将要执行的下一条指令
SPSR_ELx 32bit 寄存器,保存进入ELx的PSTATE状态信息
NZCV 32bit 允许访问的符号标志位
DAIF 32bit 中断使能位:D-Debug,I-IRQ,A-SError,F-FIQ ,逻辑0允许
CurrentEL 32bit 记录当前处于哪个Exception level
SPSel 32bit 记录当前使用SP_EL0还是SP_ELx,x= {1,2,3}
HCR_EL2 32bit HCR_EL2.{TEG,AMO,IMO,FMO,RW}控制EL0/EL1的异常路由 逻辑1允许
SCR_EL3 32bit SCR_EL3.{EA,IRQ,FIQ,RW}控制EL0/EL1/EL2的异常路由 逻辑1允许
ESR_ELx 32bit 保存异常进入ELx时的异常综合信息,包含异常类型EC等.
VBAR_ELx 64bit 保存任意异常进入ELx的跳转向量基地址 x={0,1,2,3}
PSTATE 不是一个寄存器,是保存当前PE状态的一组寄存器统称,
其中可访问寄存器有:PSTATE.{NZCV,DAIF,CurrentEL,SPSel},属于ARMv8新增内容,64bit下代替CPSR
32位W寄存器构成相应的64位X寄存器的下半部分。 即W0形成X0的低位字,W1形成X1的低位字。
从W寄存器中读取时,忽略对应的X寄存器的高32位并且保持他们不变。 写入W寄存器将X寄存器的高32位设置为零。
因此,将0xFFFFFFFF写入W0会将X0设置为0x00000000FFFFFFFF。
注意
有时Rn用来指定一个ARMv8-A寄存器。 这意味着寄存器可以是Xn或Wn。
V0 – V31 128bit 向量寄存器,也可以说是浮点型寄存器。它的特点是每个寄存器的大小是 128 位的。
分别可以用Bn Hn Sn Dn Qn的方式来访问不同的位数。
/*
* 通用寄存器
*/
(General-purpose register use in the ABI):
1.parameter and result register
x0 x1 x2 x3 x4 x5 x6 x7
2.indirect result location register
x8(xr)
3.caller saved temporary registers
x9 x10 x11 x12 x13 x14 x15
4.intra-procedure call scratch registers
x16(ip0) x17(ip1)
5.platform register
x18(pr)
6.callee saved registers
x19 x20 x21 x22 x23 x24 x25 x26 x27 x28
7.frame pointer
x29(fp)
8.procedure link register
x30(lr)
参数寄存器(X0-X7): 用作临时寄存器或可以保存的调用者保存的寄存器变量函数内的中间值,调用其他函数之间的值(8个寄存器可用于传递参数)
来电保存的临时寄存器(X9-X15): 如果调用者要求在任何这些寄存器中保留值调用另一个函数,调用者必须将受影响的寄存器保存在自己的堆栈中帧。
它们可以通过被调用的子程序进行修改,而无需保存并在返回调用者之前恢复它们。
被调用者保存的寄存器(X19-X29): 这些寄存器保存在被调用者帧中。 它们可以被被调用者修改子程序,只要它们在返回之前保存并恢复。
特殊用途寄存器(X8,X16-X18,X29,X30):
X8: 是间接结果寄存器,用于保存子程序返回地址, '尽量不使用
X16和X17: 程序内调用临时寄存器
X18: 平台寄存器,保留用于平台ABI, '尽量不使用
X29: 帧指针寄存器(FP)
X30: 链接寄存器(LR)
X31: 堆栈指针寄存器SP或零寄存器ZXR
/*
* The A64 Register
*/
A64 has 31 general-purpose registers (integer) more the zero register and the current stack pointer register, here all the registers:
Wn 32 bits General-purpose register: n can be 0-30
Xn 64 bits General-purpose register: n can be 0-30
WZR 32 bits Zero register
XZR 64 bits Zero register
WSP 32 bits Current stack pointer
SP 64 bits Current stack pointer
How registers should be using by compilers and programmers:
r30 (LR): The Link Register, is used as the subroutine link register (LR) and stores the return address when Branch with Link operations are performed.
r29 (FP): The Frame Pointer
r19…r28: Callee-saved registers
r18: The Platform Register, if needed; otherwise a temporary register.
r17 (IP1): The second intra-procedure-call temporary register (can be used by call veneers and PLT code); at other times may be used as
a temporary register.
r16 (IP0): The first intra-procedure-call scratch register (can be used by call veneers and PLT code); at other times may be used as
a temporary register.
r9…r15: Temporary registers
r8: Indirect result location register
r0…r7: Parameter/result registers
The PC (program counter) has a limited access, only few instructions, as BL and ADL, can modify it.
/*
* 32 个 SIMD&FP 寄存器
*/
32 个 SIMD&FP 寄存器,V0 - V31, 每个寄存器可以以如下格式引用
Q0 - Q31, 128 bits 寄存器
D0 - D31, 64 bits 寄存器
S0 - S31z, 32 bits 寄存器
H0 - H31, 16 bits 寄存器
B0 - B31, 8 bits 寄存器
/*
* Data types
*/
Data types are simply these:
Byte: 8 bits.
Halfword: 16 bits.
Word: 32 bits.
Doubleword: 64 bits.
Quadword: 128 bits.
/*
* CPSR(状态寄存器)
*/
NZCV是状态寄存器的条件标志位,分别代表运算过程中产生的状态,其中:
N, negative condition flag,一般代表运算结果是负数
Z, zero condition flag, 指令结果为0时Z=1,否则Z=0;
C, carry condition flag, 无符号运算有溢出时,C=1。
V, oVerflow condition flag 有符号运算有溢出时,V=1。
/*
* 特殊寄存器
*/
除了31个(X0到X30)个ARMv8-A核心寄存器之外,还有几个特殊的寄存器。
注意
没有名为X31或W31的寄存器。 一些指令被编码了,以使数字31代表零寄存器ZR(WZR / XZR)。
还有一组受限制的指令,其中一个或多个参数被编码,以使数字31代表堆栈指针(SP)。
名字 大小 描述
WZR 32 bits 零寄存器
XZR 64 bits 零寄存器
WSP 32 bits 当前栈指针
SP 64 bits 当前栈指针
PC 64 bits 程序计数器
注意
64位格式的堆栈指针不使用X前缀。
在AArch64中执行时,对于每个异常级别,异常返回状态将保存在以下专用寄存器中:
异常链接寄存器(ELR)。
保存的处理器状态寄存器(SPSR)。
下表按异常级别标识特殊寄存器:
EL0 EL1 EL2 EL3
栈指针 (SP) SP_EL0 SP_EL1 SP_EL2 SP_EL3
异常链接寄存器 (ELR) - ELR_EL1 ELR_EL2 ELR_EL3
保存的处理器状态寄存器 (SPSR) - SPSR_EL1 SPSR_EL2 SPSR_EL3
/*
* Execution State的条件
*/
SPSR_EL1.M[4] 决定EL0的执行状态,为0 =>64bit ,否则=>32bit
HCR_EL2.RW 决定EL1的执行状态,为1 =>64bit ,否则=>32bit
SCR_EL3.RW确定EL2 or EL1的执行状态,为1 =>64bit ,否则=>32bit
AArch32和AArch64之间的切换只能通过发生异常或者系统Reset来实现.(A32 -> T32之间是通过BX指令切换的)
/*
* ELx
*/
ARMv8定义EL0-EL3共 4个Exception Level来控制PE的行为.
ELx(x<4),x越大等级越高,权限越大
执行在EL0称为非特权执行
EL2 没有Secure state,只有Non-secure state
EL3 只有Secure state,实现EL0/EL1的Secure 和Non-secure之间的切换
EL0 & EL1 必须要实现,EL2/EL3则是可选实现
// Exception Level
EL0 Application
EL1 Linux kernel- OS
EL2 Hypervisor (可以理解为上面跑多个虚拟OS)
EL3 Secure Monitor(ARM Trusted Firmware)
// Security
Non-secure EL0/EL1/EL2, 只能访问Non-secure memory
Secure EL0/EL1/EL3, 可以访问Non-secure memory & Secure memory,可起到物理屏障安全隔离作用
/*
* SPSR
*/
SPSR状态寄存器:之前也有说过当运行在EL0层的时候,所用的是sp_el0,当在更高级ELx运行的时候同时可以使用
spsr_el0或者spsr_elx,所以这里用t,h后缀来区分,SPSR_ELx保存了进入ELx的PSTATE状态信息:
FPSR FPCR是浮点型运算时的状态寄存器
/*
* Process State
*/
PSTATE不是一个寄存器,它表示的是保存当前process状态信息的一组寄存器或者一些标志位信息的统称,
当异常发生的时候这些信息就会保存到EL所对应的SPSR寄存器当中;
PSTATE (process state, CPSR on AArch32) holds process state related information, his flags will be change with compare instructions,
for example, so it is used by processor to see if make a branch (jump in Intel terminology) or not.
N, Negative condition flag
Z, Zero condition flag
C, Carry condition flag
V, oVerflow condition flag
D, Debug mask bit [AArch64 only]
A, Asynchronous abort mask bit
I, IRQ mask bit
F, FIQ mask bit
SS, Software step bit
IL, Illegal execution state bit
EL, Exception Level (see above)
nRW,not Register Width: 0=64, 1=32
SP, Stack pointer select: 0=SP0, 1=SPx [AArch32 only]
Q, Cumulative saturation flag [AArch32 only]
GE, Greater than or Equal flags [AArch32 only]
IT, If-then execution state bits [AArch32 only]
J, J execution state bit [AArch32 only]
T, T32 execution state bit [AArch632 only]
E, Endian execution state bit [AArch32 only]
M Mode field (see above) [AArch32 only]
The first four flags are the Condition flags (NZCV), and they are the mostly used by processors:
N: Negative condition flag. If the result is regarded as a two’s complement signed integer, then the PE sets N to 1 if the result
is negative, and sets N to 0 if it is positive or zero.
Z: Zero condition flag. Set to 1 if the result of the instruction is zero, and to 0 otherwise. A result of zero often indicates an
equal result from a comparison.
C: Carry condition flag. Set to 1 if the instruction results in a carry condition, for example an unsigned overflow that is the
result of an addition.
V: Overflow condition flag. Set to 1 if the instruction results in an overflow condition, for example a signed overflow that is
the result of an addition