ARMv8 用于描述整体架构,包括 32 位执行和 64 位执行。它使用 64 位位宽寄存器,同时保持向后兼容 v7。
二、通用寄存器
AArch64 执行状态提供了 31 × 64 位通用寄存器,在任何时候和所有异常级别都可以访问。每个寄存器是 64 位宽的,它们通常被称为寄存器 X0~X30。
从 W 寄存器读取时,忽略对应的 X 寄存器中较高的 32 位,并保持不变。写入 W 寄存器将 X 寄存器的高 32 位设置为零。也就是说,将 0xFFFFFFFF 写入 W0 会将 X0 设置为 0x00000000FFFFFFFF。
三、特殊寄存器
标志 | 描述 |
---|---|
N | 负数标志位。结果为负数则 N=1,否则 N=0 |
Z | 零标志位。如果结果为零,则 Z=1,否则 Z=0 |
C | 进位标志位。如果结果有进位,则 C=1,否则 C=0 |
V | 溢出标志位。如果结果有溢出,则 V=1,否则 V=0 |
SS | 软件单步调试。该位为1,表示在异常处理时使能了软件单步功能。 |
IL | 非法执行状态位。在异常处理之前立即显示 PSTATE.IL 的值。 |
D | 进程状态调试掩码。指示来自观察点、断点和软件单步调试事件的调试异常是否被屏蔽,这些事件的目标是发生的异常所在异常级别。 |
A | SError(系统错误)掩码。 |
I | IRQ 掩码位。 |
F | FIQ 掩码位。 |
M[4] | 异常发生所处的执行状态。取值为 0 表示 AArch64 |
M[3:0] | 异常发生时所处的模式或异常级别。 |
处理器状态 PSTATE
AArch64 没有直接等效于 ARMv7 当前程序状态寄存器(CPSR)。在 AArch64 中,传统 CPSR 的组件是作为字段提供的,可以独立访问。这些状态统称为处理器状态(PSTATE)。
AArch64 的处理器状态或 PSTATE 字段有以下定义:
名称 | 描述 |
---|---|
N | 负数标志位。 |
Z | 零标志位。 |
C | 进位标志位。 |
V | 溢出标志位。 |
D | 进程状态调试掩码。 |
A | SError(系统错误)掩码。 |
I | IRQ 掩码位。 |
F | FIQ 掩码位。 |
SS | 软件单步调试。 |
IL | 非法执行状态位。 |
EL (2) | 异常级别。 |
nRW | 执行状态:0 = 64-bit,1 = 32-bit |
SP | 栈指针选择:0 = SP_EL0,1 = SP_ELn |
在 AArch64 中,通过执行 ERET 指令从异常中返回,这将导致 SPSR_ELn 被复制到 PSTATE。这将恢复 ALU 标志、执行状态、异常级别和处理器分支。从这里开始,从 ELR_ELn 中的地址继续执行。
PSTATE.{N, Z, C, V} 字段可以在 EL0 访问。所有其他的 PSTATE 字段可以在 EL1 或更高的值访问,并且在 EL0 是未定义的。
四、系统寄存器
在 AArch64 中,系统配置通过系统寄存器控制,并使用 MSR 和 MRS 指令访问。这与 ARMv7-A 不同,在 ARMv7-A 中,这些寄存器通常是通过协处理器 15(CP15)操作访问的。寄存器的名称告诉你可以访问它的最低异常级别。例如:
- TTBR0_EL1 可通过 EL1、EL2、EL3 访问。
- TTBR0_EL2 可从 EL2 和 EL3 访问。
具有 _ELn 后缀的寄存器在某些或所有级别中具有单独的存储副本,尽管通常不是 EL0。很少有系统寄存器可以从 EL0 访问,尽管缓存类型寄存器(CTR_EL0)是一个可以访问的例子。
访问系统寄存器的代码采用以下形式:
以前版本的 ARM 架构使用协处理器进行系统配置。但是 AArch64 不支持。下表显示了每个寄存器的独立副本的异常级别。例如,ACTLR(辅助控制寄存器)以 ACTLR_EL1、ACTLR_EL2 和 ACTLR_EL3 的形式存在。
名称 | 寄存器 | 描述 | 允许的 n 值 |
---|---|---|---|
ACTLR_ELn | 辅助控制寄存器 | 控制特定于处理器的特性。 | 1, 2, 3 |
CCSIDR_ELn | 当前缓存大小 ID 寄存器 | 提供有关当前选定缓存的体系结构信息。 | 1 |
CLIDR_ELn | 缓存级 ID 寄存器 | 缓存的类型,或在每个级别实现的缓存。 | 1, 2, 3 |
CNTFRQ_ELn | 计数型计时器的频率寄存器 | 上 系统计时器的频率。 | 0 |
CNTPCT_ELn | 计数型计时器的物理计数寄存器 | 保存 64 位的当前计数值。 | 0 |
CNTKCTL_ELn | 计数型计时器的内核控制寄存器 | 控制从虚拟计数器生成事件流。还控制从 EL0 到物理计数器、虚拟计数器、EL1 物理计时器和虚拟计时器的访问。 | 1 |
CNTP_CVAL_ELn | 计数型计时器的物理计时器比较值寄存器 | 保存 EL1 物理计时器的比较值。 | 0 |
CPACR_ELn | 协处理器访问控制寄存器 | 控制对 Trace、浮点和 NEON 功能的访问。 | 1 |
CSSELR_ELn | 缓存大小选择寄存器 | 通过指定所需的缓存级别和缓存类型(指令缓存或数据缓存),选择当前的缓存大小 ID 寄存器 CCSIDR_EL1。 | 1 |
CNTP_CTL_ELn | 计数型计时器的物理控制寄存器 | 控制寄存器的 EL1 物理计时器。 | 0 |
CTR_ELn | 缓存类型寄存器 | 关于集成缓存架构的信息。 | 0 |
DCZID_ELn | 数据缓存零 ID 寄存器 | 由 DCZVA(Data Cache 0 by Virtual Address)系统指令写入的字节值为 0 的块大小。 | 0 |
ELR_ELn | 异常链接寄存器 | 保存导致异常指令的地址。 | 1, 2, 3 |
ESR_ELn | 异常诊断(Syndrome)寄存器 | 包括有关异常原因的信息。 | 1, 2, 3 |
FAR_ELn | 故障地址寄存器 | 保存虚拟故障地址。 | 1, 2, 3 |
FPCR | 浮点控制寄存器 | 控制浮点扩展行为。这个寄存器中的字段映射到 AArch32 FPSCR 中的等效字段。 | – |
FPSR | 浮点状态寄存器 | 提供浮点系统状态信息。这个寄存器中的字段映射到 AArch32 FPSCR 中的等效字段。 | – |
HCR_ELn | Hypervisor 配置寄存器 | 控制虚拟化设置和捕获 EL2 的异常。 | 2 |
MAIR_ELn | 内存属性间接寄存器 | 提供与 ELn 的阶段 1 转换的长描述格式转换表项中可能值对应的内存属性编码。 | 1, 2, 3 |
MIDR_ELn | 主 ID 寄存器 | 运行代码的处理器类型(部件 和版本 )。 | 1 |
MPIDR_ELn | 多处理器亲和性寄存器 | 多核或集群系统中的处理器和集群 ID。 | 1 |
SCR_ELn | 安全配置寄存器 | 控制 EL3 的安全状态和异常捕获。 | 3 |
SCTLR_ELn | 系统控制寄存器 | 控制架构特性,例如 MMU、缓存和对齐检查。 | 0, 1, 2, 3 |
SPSR_ELn | 保存程序状态寄存器 | 当此模式或异常级别发生异常时,保持已保存的处理器状态。 | abt, fiq, irq, und, 1,2, 3 |
TCR_ELn | 转换控制寄存器 | 确定哪个转换表基址寄存器定义了从 ELn 访问内存的阶段 1 转换所需的转换表遍历的基地址。还控制转换表格式并保存可缓存性和可共享性信息。 | 1, 2, 3 |
TPIDR_ELn | 用户读/写线程 ID 寄存器 | 提供在 ELn 处执行的软件可以存储线程标识信息的位置,以用于 OS 管理。 | 0, 1, 2, 3 |
TPIDRRO_ELn | 用户仅允许读线程 ID 寄存器 | 提供在 EL1 或更高版本执行的软件可以存储线程标识信息的位置。出于 OS 管理目的,此信息对在 EL0 处执行的软件可见。 | 0 |
TTBR0_ELn | 转换表基址寄存器 0 | 保存转换表 0 的基地址,以及有关它占用的内存的信息。这是 ELn 内存访问阶段 1 转换的转换表之一。 | 1, 2, 3 |
TTBR1_ELn | 转换表基址寄存器 1 | 保存转换表 1 的基地址,以及有关它占用的内存的信息。这是 EL0 和 EL1 内存访问的阶段 1 转换的转换表之一。 | 1 |
VBAR_ELn | 基于向量的地址寄存器 | 保存被带到 ELn 的任何异常的异常基地址。 | 1, 2, 3 |
VTCR_ELn | 虚拟化转换控制寄存器 | 控制从非安全 EL0 和 EL1 进行内存访问的第 2 阶段转换所需的转换表遍历。还保存访问的可缓存性和可共享性信息。 | 2 |
VTTBR_ELn | 虚拟化转换表基址寄存器 | 保存从非安全 EL0 和 EL1 进行内存访问的阶段 2 转换的转换表的基地址。 | 2 |
五、NEON 和浮点寄存器
除了通用寄存器,ARMv8 还有 32 个 128 位浮点寄存器,标记为 V0-V31。 32 个寄存器用于保存标量浮点指令的浮点操作数以及 NEON 操作的标量和向量操作数。
AArch64 中的浮点寄存器组织
在对标量数据进行操作的 NEON 和浮点指令中,浮点和 NEON 寄存器的行为类似于主要的通用整数寄存器。因此,仅访问低位,读取时忽略未使用的高位,写入时设置为零。标量浮点和 NEON 名称的限定名称表示有效位数如下,其中 n 是寄存器编 0-31。
不同大小的浮点数的操作数名称表
精度 | 大小(bits) | 名称 |
---|---|---|
Half(半) | 16 | Hn |
Single(单) | 32 | Sn |
Double(双) | 64 | Dn |
-
每个 Q 寄存器的底部 64 位也可以被视为 D0-D31, 32 位浮点和 NEON 使用的 64 位寄存器。
-
每个 Q 寄存器的底部 32 位也可以被视为 S0-S31, 32 位浮点和 NEON 使用的32 位宽寄存器。
-
每个 S 寄存器的底部 16 位也可以被视为 H0-H31, 32 个 16 位宽寄存器用于浮点和 NEON 使用。
-
每个 H 寄存器的底部 8 位也可以被视为 B0-B31, 32 个 8 位宽寄存器用于 NEON。
在每种情况下,仅使用每个寄存器组的低位。其余的寄存器空间读取时忽略,写入时填充零。
这种映射的结果是,如果在 AArch64 中执行的程序正在解释来自 AArch32 的 D 或 S 寄存器。那么,在使用 D 或 S 寄存器之前,程序必须将它们从 V 寄存器中解包。
对于标量 ADD 指令:
例如,如果大小为 32 位,则指令为:
不同尺寸标量操作数的名称见下表
字大小 | 大小(bits) | 名称 |
---|---|---|
Byte | 8 | Bn |
Halfword | 16 | Hn |
Word | 32 | Sn |
Doubleword | 64 | Dn |
Quadword | 128 | Qn |
向量寄存器大小
向量可以是 64 位宽,包含一个或多个元素,也可以是 128 位宽,包含两个或多个元素,如图所示:
《ARMv8-A-Programmer-Guide》
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!