ARMv8寄存器(1)
ARMv8寄存器实在太多了,本节主要针对系统软件常用的寄存器作为重点介绍。
1.ARMv8寄存器介绍
ARMv8架构(针对Core来说)至少有上千个寄存器,更别提Core外SOC级外设寄存器。这两类寄存器的区别是:前者(不管通用寄存器还是系统寄存器)不占用地址空间,而后者是和内存统一编制的,要占用地址空间。
下面我们主要针对ARM Core内寄存器进行介绍。ARM核心寄存器可以分为:
- 通用寄存器。这类寄存器主要是用来暂存数据和参与运算。通过load\store指令操作。
- 状态寄存器。AArch64体系结构使用PSTATE寄存器表示当前处理器状态。
- 特殊寄存器。有专门的用途,用于控制处理器的行为,或表示CPU的状态。
- 系统寄存器。除了以上寄存器,ARMv8体系结构还定义了很多系统寄存器,用来完成对处理器不同功能的配置。对应ARMv7的cp15寄存器。
而系统寄存器,根据其功能又可以分为11种:
- 基本系统寄存器。
- 特殊目的寄存器。3个ELR, 4个SP, 8个SPSR。
- VMSA(虚拟内存架构)特殊寄存器。
- ID寄存器。
- 性能监控寄存器。
- DEBUG寄存器。
- RAS寄存器。
- 通用定时器寄存器。
- Cache维护相关寄存器。
- 地址转换寄存器。
- TLB维护寄存器。
- 分支预测寄存器。
2.重点寄存器
这么多寄存器很难记得住,我们只需要重点关注以下寄存器,其余寄存器用到时候再查手册。
寄存器 | 描述 |
---|---|
PSTATE | 程序状态寄存器 |
SP_ELx(x>0) | 在EL1/EL2/EL3 level中,如果spsel=0,则使用SP_ELx(x>0) |
SP_EL0 | 在所有level中,如果spsel=1, 则使用SP_EL0 |
SPSR | 备份的程序状态寄存器 |
ELR_ELx(x>0) | 异常链接寄存器,记录着异常时程序的返回地 |
ESR_ELx(x>0) | 同步异常, 异常特征寄存器 |
VBAR_ELx(x>0) | 向量表基地址寄存器 |
TTBRn_ELx(n=1,2、x>0) | 地址翻译基地址寄存器,存放页表地址。 |
MAIR_ELx(x>0) | 内存属性寄存器 |
PAR_EL1 | 物理地址寄存器, 当使用指令操作MMU进行VA到PA的转换时,物理地址由PAR_EL1输出 |
SCR_EL3 | 安全控制寄存器 |
HCR_EL2 | Hypvisor控制寄存器 |
SCTLR_ELx(x>0) | 系统控制寄存器 |
TCR_ELx(x>0) | 地址翻译控制寄存器 |
3.通用寄存器
AArch64执行状态提供了31个在任何时间任何特权级下都可访问的64位的通用寄存器,分别是X0-X30。而AArch32状态支持16个32位的通用寄存器。
每个AArch64 64位通用寄存器(X0-X30)也具有32位(W0-W30)形式。
32位W寄存器取自相应的64位X寄存器的低32位。也就是说,W0映射到X0的低32位,W1映射到X1的低32位。
从W寄存器读取时,忽略相应X寄存器高32位,并保持其它不变。写入W寄存器时,将X寄存器的高32位设置为零。也就是说,将0xFFFFFFFF写入W0会将X0设置为0x00000000FFFFFFFF。
通用寄存器在ACPS中用法
除了用于数据运算和存储外,通用寄存器还在函数的调用过程中起到特殊作用,ARM64体系结构的函数调用标准和规范对此有约定,如下图所示。
说明:
- X0-X7 用于参数传递
- - [ ] X9-X15 在子函数中使用这些寄存器时,直接使用即可, 无需save/restore. 在汇编代码中x9-x15出现的频率极低。在子函数中使用这些寄存器时,直接使用即可, 无需save/restore.。在汇编代码中x9-x15出现的频率极低。
- X19-X29 在callee子函数中使用这些寄存器时,需要先save这些寄存器,在退出子函数时再resotre。在callee子函数中使用这些寄存器时,需要先save这些寄存器,在退出子函数时再resotre。
- X8, X16-X18, X29, X30 这些都是特殊用途的寄存器。
- – X8: 用于返回结果
- – X16、X17 :进程内临时寄存器
- – X18 :resrved for ABI
- – X29 :FP(frame pointer register)
- – X30 :LR
4.处理器状态 (PSTATE)
ARMv7中使用当前程序状态寄存器(CPSR)表示处理器当前状态。AArch64没有直接与之等价的寄存器。
在AArch64中,传统CPSR的组件作为可以独立访问的字段提供。这些状态被统称为处理器状态(PSTATE)。
该程序和备份程序状态寄存器(SPSR_ELx)是一对。当异常发生时,处理器会将PSTATE寄存器的值保存到当前异常级别对应的SPSR_ELx寄存器;当异常返回时(eret),处理器会将SPSR_ELx寄存器的值恢复到PSTATE寄存器。这是硬件自动行为,不需要编程人员操作。
AArch64的处理器状态或PSTATE字段有以下定义:
上面的图不好,且容我从别处找个图。
条件判断相关的域
如cmp指令,tst指令,条件判断时用到这些标志位;还有像sbc等运算指令,会将标志位一并加入运算。
异常掩码标志位
- 1:表示屏蔽了这个异常
- 0:表示没有屏蔽这个异常
执行状态控制位
部分字段有专门对应的寄存器,如NZCV寄存器、CurrentEL寄存器。注意:EL0级别只能访问PSTATE.{N, Z, C, V}和PSTATE.{D, A, I, F}字段。
5.特殊寄存器
ARMv8支持的特殊寄存器:
部分寄存器还可以当作32位的使用:
5.1 备份程序状态寄存器(SPSR_ELx)
当异常发生时,处理器会将PSTATE寄存器的值保存到当前异常级别对应的SPSR_ELx寄存器;当异常返回时(eret),处理器会将SPSR_ELx寄存器的值恢复到PSTATE寄存器。这是硬件自动行为,不需要编程人员操作。
AArch64下各域的含义:
- N 负数标志位,如果结果为负数,则N=1;如果结果为非负数,则N=0。
- Z 零标志位,如果结果为零,Z=1,否则Z=0。
- C 进位标志位
- V 溢出标志位
- SS 是否是能软件单步功能 ,若为1,说明在异常处理中软件单步功能开启
- IL 非法执行状态位
- D 程序状态调试掩码,在异常发生时的异常级别下,来自监视点、断点和软件单步调试事件中的调试异常是否被屏蔽。
- A SError(系统错误)掩码位
- I IRQ掩码位
- F FIQ掩码位
- M[4] 异常发生时的执行状态 ,0表示AArch64状态
- M[3:0] 异常发生时的模式或异常级别
在ARMv8中,写入的SPSR依赖于异常级别。如果异常发生在EL1,则使用SPSR_EL1。如果异常发生在EL2,则使用SPSR_EL2,如果异常发生在EL3,则使用SPSR_EL3。处理器核会在异常发生时填充SPSR。
注意: 与异常级别相关联的寄存器对ELR_ELn和SPSR_ELn保存着在较低异常级别执行期间的状态。
5.2 异常链接寄存器(ELR)
异常链接寄存器保存异常返回地址。在执行eret指令后,会将该寄存器的值赋值给PC。
5.3 CurrentEL寄存器
该寄存器表示PSTATE中的EL字段,其中保存了当前异常级别。使用MRS指令可以读取该寄存器。
- 0:表示EL0.
- 1:表示EL1
- 2:表示EL2.
- 3:表示EL3.
5.4 DAIF寄存器
该寄存器表示PSTATE中的{D, A, I, F}字段。使用MRS指令可以读取该寄存器。
5.5 SPSel寄存器
该寄存器表示PSTATE中的SP字段,用于在SP_EL0和SP_ELx中选择使用哪个。
5.6 PAN寄存器
该寄存器表示PSTATE中的PAN(Privileged Access Never, 特权禁止访问)字段。可以通过MSR和MRS指令读取和设置寄存器。这是ARMv8.1新增特性,为了防止内核态恶意访问用户态内存。
PAN寄存器的值如下:
- 0: 表示内核态可以访问用户态内存。
- 1:表示内核态访问用户态内存会触发一个访问权限异常。
5.7 UAO寄存器
该寄存器表示PSTATE中的UAO(User Access Override, 用户访问覆盖)字段。可以通过MSR和MRS指令读取和设置寄存器。
UAO值为1 ,表示在EL1和EL2执行非特权指令(如LDTR、STTR)的效果和特权指令(例如LDR、STR)是一样的。
5.8 NACV寄存器
该寄存器表示PSTATE中的{N, Z, C, V}字段。
5.9 PC (Program Counter,程序计数器) 寄存器
PC寄存器通常用来指向当前运行指令的下一条指令的地址。
在原来的ARMv7体系结构中,将通用寄存器R15作为程序计数器(PC),同时作为一个通用寄存器使用。编程人员可以通过修改PC寄存器的值控制程序中指令的运行顺序。但这增加了编译器和复杂的流水线的设计困难。
在ARMv8中,PC不再作为一个命名的寄存器来访问,编程人员无法通过指令来直接访问它。但是,可以在某些指令中隐式的使用PC,如PC相对加载和地址生成(adrp等指令)。
5.10 零寄存器(WZR/XZR)
XZR:64位
WZR: 32位
当访问零寄存器时,所有写操作都被忽略(用于将一个结果丢弃),所有读操作返回0。
5.11 栈指针寄存器(SP)
在ARMv8体系结构中,4个异常级别各有一个SP寄存器SP_ELn。认情况下,发生异常时会选择目标异常级别的SP_ELn作为栈指针。文章来源:https://www.toymoban.com/news/detail-474527.html
- SP_EL0:程序在EL0时栈指针寄存器,EL0时只能使用此寄存器存放栈地址。
- SP_EL1:程序在EL1时默认栈指针寄存器。
- SP_EL2:程序在EL2时默认栈指针寄存器。
- SP_EL3:程序在EL3时默认栈指针寄存器。
EL0永远只能访问SP_EL0。其他异常级别ELx:文章来源地址https://www.toymoban.com/news/detail-474527.html
- 发生异常时,使用自己的SP_ELx寄存器存放栈地址;
- 可以将SP_EL0寄存器作为临时寄存器来使用,例如Linux内核使用该寄存器存放进程中task_struct数据结构指针。
到了这里,关于基础篇(二).ARMv8寄存器(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!