计算机系统开发与优化实战
上QQ阅读APP看书,第一时间看更新

1.2 AArch64寄存器堆

作为RISC架构,AArch64提供了大量的通用寄存器。除通用寄存器之外,本节还会介绍特殊寄存器、系统控制寄存器、处理器状态、函数调用标准。

1.2.1 通用寄存器

通用寄存器分为两类。其中一类寄存器包括X0~X30,用于普通的指令集,每个寄存器都有64位(Xn)和32位(Wn)两种表示形式。其中32位的表示形式是64位表示形式的低32位。另一类寄存器包括V0~V31,用于浮点运算、SIMD、crypto等领域。每个寄存器长度都是128位(Qn),它们有64位(Dn)、32位(Sn)、16位(Hn)、8位(Bn)这4种表示形式。

以X0和V0为例,X0是64位寄存器,它的低32位是W0。V0也称为Q0,Q0是一个128位的寄存器,它的低64位称为D0,它的低32位称为S0,它的低16位称为H0,它的低8位称为B0,如图1.1所示。

图1.1 寄存器的表示形式

1.2.2 特殊寄存器

XZR和WZR分别对应64位与32位的零寄存器。对这些寄存器进行读操作,将会获取到0;对这些寄存器进行的写操作将会被处理器忽略。与ARM的32位架构不同,PC寄存器已经不再是一个通用寄存器,无法直接访问。ARM指令的长度是4字节,因此对于ARMv8上的纯ARM指令来说,PC寄存器是按字节对齐的。SP寄存器也不再是一个通用寄存器,SP寄存器强制按16字节对齐。

1.2.3 系统控制寄存器

ARM的系统控制寄存器都以“_ELx”为后缀,其中“x”表示某异常级别(Exception Level,EL)的一个数字,如SCTLR_EL1。后缀的数字意味着能够访问该寄存器的最低异常级别,ARM的系统控制寄存器如表1.1所示。

表1.1 ARM的系统控制寄存器

MRS和MSR指令用于读写系统控制寄存器,示例代码如下。

MRS     X0, SCTLR_EL1          // X0 = SCTLR_EL1
MSR     SCTLR_EL1, X0          // SCTLR_EL1 = X0

常用的系统控制寄存器及其功能如表1.2所示。

表1.2 常用的系统控制寄存器及其功能

ARM的系统控制寄存器数量庞大,详细的介绍可以参考文档DDI0487F_b_ARMv8_arm.pdf。

1.2.4 处理器状态

AArch64通过PSTATE(process state)的标志位来保存处理器的状态,处理器执行指令的时候,可以读取和设置这些标志位。这些标志位既可以通过mrs/msr指令进行访问,也可以通过DAIFSet、DAIFClr、SPSel、PAN、UAO等指令直接访问。PSTATE寄存器的标志位如表1.3所示。

表1.3 PSTATE寄存器的标志位

1.2.5 函数调用标准

1.AArch64基本指令集函数调用规则

AArch64提供了31个64位的通用寄存器X0~X30,SP寄存器已经变成了一个专用寄存器。这些寄存器的描述如表1.4所示。

表1.4 AArch64寄存器的描述

值得注意的是,X16和X17寄存器在动态链接的时候,可能会被某些链接器用于实现特殊功能。X18寄存器在Darwin和Windows平台上会保留作为平台寄存器使用。在代码优化的时候,这3个寄存器要谨慎使用。

2.AArch64 NEON指令集函数调用规则

AArch64提供了32个128位的寄存器(V0~31),可以用来进行SIMD和浮点运算。

其中,V0~V7这8个寄存器用来传递参数和函数返回值,V8~V15这8个寄存器需要由被调函数保存(只需要保存这些寄存器的低64位即可)。

D8~D15是V8~V15寄存器的低64位,因此通过如下的代码片段保存D8~D15的内容,就可以在函数中使用V0~V31这32个寄存器了。

stp          d8, d9, [sp, -192]!

stp          d10, d11, [sp, 16]
stp          d12, d13, [sp, 32]
stp          d14, d15, [sp, 48]

3.AArch64 SVE指令集函数调用规则

如果平台支持SVE扩展,那么AArch64会提供32个可变长的向量寄存器Z0~Z31。每个寄存器都可以用来进行SIMD和浮点运算,其中Z0~Z7用来传递参数和函数返回值。Z8~Z15这8个寄存器需要由被调函数保存(只需要保存这些寄存器的低64位即可)。

AArch64还为SVE提供了16个断言寄存器P0~P15,其中P0~P3这4个寄存器用来传递参数和函数返回值。