4.ARMv8寄存器
AArch64执行状态提供了31个64位通用寄存器,可以在所有异常级别中随时使用。每个寄存器的位宽都为64 bits,当使用全部64 bits时,称为X0-X30,当使用低32 bits时,称为W0-W30。AArch64过程(函数)调用使用X30寄存器保存返回地址,而异常的返回地址由ELR寄存器保存,而在AArch32中,过程调用和异常的返回地址都由LR寄存器保存。
32位W寄存器使用对应64位X寄存器的低32位,即W0对应X0的低32位,W1对应X1的低32位,以此类推。读取W寄存器时,将会舍弃高32位的数据。写入W寄存器时,会将高32位清0,例如将0xFFFFFFFF写入W0后,X0中的值位0x00000000FFFFFFFF。
4.1.AArch64特殊寄存器
除了31个通用寄存器,还有几个特殊寄存器。
没有寄存器叫X31或W31。许多指令被编码为数字31来表示zero寄存器(ZR(WZR/XZR))。还有一个受限的指令组,其中一个或多个参数被编码,使数字31表示堆栈指针(SP)。
当访问zero寄存器,所有的写入都被忽略,所有的读取都返回0,AArch32执行状态使用WZR指令访问zero寄存器,AArch64执行状态使用XZR访问zero寄存器。AArch32执行状态使用WSP访问当前栈指针寄存器,AArch64执行状态使用SP访问当前栈指针寄存器。AArch32执行状态和AArch64执行状态使用PC访问程序计数寄存器。注意:64位形式的SP寄存器不使用X前缀。
在ARMv8架构中,当处于AArch64为执行状态时,异常的返回状态保留在以下每个异常级别的专用寄存器中:
- Exception Link Register (ELR)
- Saved Processor State Register (SPSR)
每个异常级别中都有专用的SP寄存器,退出该异常级别时不用保存。
4.1.1.Zero register(WZR,XZR)
将Zero寄存器当作源寄存器读取时,会得到0值,将Zero寄存器当作目的寄存器写入时,写入的值被丢弃。可以在大多数指令(但不是所有指令)中使用zero寄存器。
4.1.2.Stack pointer(WSP,SP)
在ARMv8架构中,每个异常级别都拥有栈指针寄存器,即拥有4个栈指针寄存器。默认情况下,异常级别ELn对应的栈指针寄存器为SP_ELn,如EL0对应SP_EL0,EL1对应SP_EL1,EL2对应SP_EL2,EL3对应SP_EL3。当处理器的执行状态为AArch64且不处于异常级别EL0,则可以使用与异常级别相关的专用64位堆栈指针(SP_ELn)和与异常级别EL0相关的栈指针寄存器(SP_EL0)。 EL0只能访问SP_EL0栈指针寄存器。 各个异常级别与可使用的栈寄存器对关系如下图所示。软件可以在目标异常级别执行的时候通过更新PSTATE.SP来指向SP_EL0的堆栈指针。t表明使用SP_EL0堆栈指针,h表明使用SP_ELx堆栈指针,t和h后缀基于线程(thread)和处理程序(handler)的首字母。
栈指针寄存器SP不能被大多数指令引用,但可以被一些算数指令引用,如ADD 指令,可以读写当前栈指针寄存器以调整函数的栈指针。 ADD SP, SP, #0x10 // Adjust SP to be 0x10 bytes before its current value
4.1.3.Program Counter(PC)
早期的ARMv7将通用寄存器R15作为PC寄存器。PC使一些巧妙的编程技巧成为可能,但它给编译器和复杂流水线的设计带来了困难。ARMv8架构中删除了对PC寄存器的直接访问,这使得返回预测更容易,并简化了ABI规范。PC寄存器不能作为命名寄存器访问,而是通过确定的指令隐含的访问,如相对PC的加载和产生地址。PC寄存器不能明确的作为数据处理指令或加载指令的目的寄存器。
4.1.4.Exception Link Register(ELR)
ELR寄存器保存了异常返回地址,ARMv8定义了3个ELR寄存器,分别对应异常级别EL1、EL2、EL3。
4.1.5.Saved Process Status Register(SPSR)
当异常发生时,处理器的状态将会被保存到相关的SPSR寄存器中。异常发生后,在处理异常之前,处理器会自动的将PSTATE寄存器的内容保存到SPSR中,异常返回时,会将SPSR保存的处理器状态恢复到PSTATE中。ARMv8定义的SPSR寄存器如下,兼容ARMv7中的SPSR寄存器,只使用低32位。
各个位域定义如下:
- N 符号位(N flag)
- Z 0标志(Z flag)
- C 操作进位(C flag)
- V 溢出标志(V flag)
- SS 用于软件调试。异常发生的时候,通过设置MDSCR_EL1.SS为1启动单步调试机制
- IL 不合法的执行状态(非法异常),保存自PSTATE.IL
- D 处理器状态调试掩码。指示是否屏蔽来自观察点、断点和软件步骤调试事件的调试异常
- A 软件错误掩码位
- I IRQ掩码位
- F FIQ掩码位
- M[4] 发生异常时处理器的执行状态,0表示AArch64
- M[3:0] M[3:2]发生异常的级别;M[1]保留;M[0]根据此选择栈指针寄存器,0表示t,1表示h。
可以通过异常级别的栈指针后缀表明所选的栈指针,M[3:0]可参考下面的图:
在ARMv8架构中,有3个SPSR寄存器,分别为SPSR_EL1、SPSR_EL2、SPSR_EL3。使用那个SPSR寄存器依赖于异常级别。若异常级别为EL1,则使用SPSR_EL1,若异常级别为EL2,则使用SPSR_EL2,若异常级别为EL3,则使用SPSR_EL3。 ELR_ELn和SPSR_ELn寄存器和异常级别相关联,始终保存着低于当前异常级别的处理器状态。
4.2.Processor state(PSTATE)
AArch64没有和ARMv7 Current Program Status Register(CPSR)寄存器一样的寄存器。在AArch64执行状态中,处理器的状态使用PSTATE描述,但PSTATE不是寄存器,而是处理器状态各个位域的总称。PSTATE的大部分位域和传统CPSR寄存器中的位域相同。PSTATE的位域如下图所示。EL0可以访问PSTATE的N、Z、C、V位域,其他域只能在EL1及更高的异常级别中访问。
在AArch64执行状态中,使用ERET命令从异常中返回,即将SPSR_ELn寄存器中保存的发生异常时的处理器状态恢复到PSTATE中。SPSR_ELn中保存了发生异常时ALU的标志、执行状态、异常级别及处理器branches。处理器从异常返回后的执行地址保存在ELR_ELn中。
4.3.System registers
在AArch64中,通过MSR和MRS指令访问系统寄存器,以此来控制系统。系统寄存器名称后缀反应了访问该寄存器所需的最低异常级别,如下所示。。
- TTBR0_EL1可以访问的异常级别为EL1、EL2、EL3,EL0无法访问
- TTBR0_EL2可以访问的异常级别为EL2、EL3,EL0和EL1无法访问
大部分系统寄存器所需的访问异常级别都大于EL1。只有少部分寄存器可以在EL0级别中访问,如Cache Type Register (CTR_EL0)。
系统寄存器访问的形式如下图所示,使用MRS和MSR指令。
MRS x0, TTBR0_EL1 // Move TTBR0_EL1 into x0
MSR TTBR0_EL1,x0 // Move x0 into TTBR0_EL1
下表是部分系统寄存器,详细的系统寄存器列表参考《ARM Architecture Reference Manual - ARMv8, for ARMv8-A architecture profile》。
名称 | 寄存器 | 描述 | 允许的异常级别 |
---|
ACTLR_ELn | 辅助控制寄存器 | 控制处理器详细的特性 | 1,2,3 | CCSIDR_ELn | 当前Cache Size ID寄存器 | 当前架构所选择cache的信息 | 1 | CLIDR_ELn | Cache Level ID寄存器 | 每个级别的cache类型及实现 | 1,2,3 | CNTFRQ_ELn | 计时器频率寄存器 | 反应了系统定时器的频率 | 0 | CNTPCT_ELn | 计时器物理计数寄存器 | 保存了当前64位计数值 | 0 | CNTKCTL_ELn | 内核计时器控制寄存器 | 控制从虚拟计数器生成事件流 | 1 | CPACR_ELn | 协处理器访问控制寄存器 | 控制访问Trace、 floating-point及NEON | 1 | CSSELR_ELn | Cache Size选择寄存器 | 定义了要求的cache级别、cache类型及指令cache或数据cache | 1 | CNTP_CTL_ELn | 物理计时器控制寄存器 | EL1物理计时器的控制寄存器 | 0 | ELR_ELn | Exception Link Register | 保存异常返回地址 | 1,2,3 | ESR_ELn | Exception Syndrome Register | 保存了发生异常的原因 | 1,2,3 | FAR_ELn | Fault Address Register | 保存了virtual faulting address | 1,2,3 | SCTLR_ELn | 系统控制寄存器 | 控制架构特性,如MMU、caches及对齐检查 | 0,1,2,3 | SPSR_ELn | Saved Program Status Registe | 发生异常时,保存处理器的状态 | abt,fiq,irq, und,1,2,3 | | | | |
参考资料
- ARM? Cortex ? -A Series - Programmer’s Guide for ARMv8-A
- https://blog.csdn.net/tanli20090506/article/details/71487570
- https://cloud.tencent.com/developer/article/1695507
|