除了通用寄存器,ARMv8也有32个128bit浮点寄存器标号位V0~V31。这32个寄存器用来保持标量浮点指令的浮点操作符以及NEON操作的同时标量和向量操作符。NEON和浮点寄存器也在Chapter 7 AArch64 Floating-point and NEON中覆盖。
在运行在标量数据上的NEON和浮点指令,NEON寄存器的行为与主通用数字寄存器类似。因此,仅最低位可被访问,在读时不使用的高位被忽略,在写时被设置为0。
标量浮点和NEON名字表明最重要的位数,如下所示,n位寄存器number 0~31。
Precision | Size(bits) | Name |
Half | 16 | Hn |
Single | 32 | Sn |
Double | 64 | Dn |
NOTE: 16位浮点已经支持,但仅作为一种格式被转化。它不支持数据处理操作。
F前缀和浮点大小由浮点ADD指令指明:
FADD Sd,Sn,Sm
FADD Dd,Dn,Dm
半精度浮点指令用于不同大小间的转换:
FCVT Sd,Hn
FCVT Dd,Hn
FCVT Hd,Sn
FCVT Hd,Dn
在AArch64中,整数标量的映射已经从ARMv7-A到下图显示的映射中:
上图中S0为D0的下半部分,S0为Q0的下半部分。S1为D1的下半部分,S1为Q1的下半部分,依次类推。这减少了编译器在自动矢量高级别代码中的很多问题。
(1)Q寄存器的低64位可以被看作D0~D31,32个64位寄存器用于浮点和NEON。
(2)Q寄存器的低32位可以被看作S0~S31,32个32位寄存器用于浮点和NEON。
(3)S寄存器的低16位可以被看作H0~H31,32个16位寄存器用于浮点和NEON。
(4)H寄存器的低8位可以被看作B0~B31,32个8位寄存器用于浮点和NEON。
NOTE: 这些寄存器组的低位在这种情况被使用。寄存器空间的其他的部分在读时被忽略,当写时被填0。
这种映射的一个结果是如果运行在AArch64上的程序被从AArch32执行中解析为D或S寄存器。然后程序必须在使用之前从V寄存器中拆分出D或S寄存器。
对于标量ADD指令:
ADD Vd,Vn,Vm
比如,大小为32位,指令可以为:
ADD Sd,Sn,Sm
Word size | Size | Name |
Byte | 8 | Bn |
Halfword | 16 | Hn |
Word | 32 | Sn |
DoubleWord | 64 | Dn |
Quadword | 128 | Qn |
矢量可以为一个或多个element的64bit宽或二个或多个element的128bit宽如下图所示:
对于ADD矢量指令:
ADD Vd.T,Vn.T,Vm.T
对于32位矢量,带4lane,指令变成:
Name | Shape |
Vn.8B | 8lane,每个包含8bit element |
Vn.16B | 16lane,每个包含8bit element |
Vn.4H | 4lane,每个包含16bit element |
Vn.8H | 8lane,每个包含16bit element |
Vn.2S | 2lane,每个包含32bit element |
Vn.4S | 4lane,每个包含32bit element |
Vn.1D | 1lane,每个包含64bit element |
Vn.2D | 2lane,每个包含64bit element |
当这些寄存器被用于某种指令格式时,名称必须能够值得表明数据形状。更特殊的是,这意味着在它们中的数据element大小和element个数或lane。
在AArch32z中,更小的寄存器被组合成更大的寄存器(D0和D1组合形成Q1)。这引入了tricky循环依赖可以减少编译器矢量化循环结构。
在AArch32中的浮点和更先进的SIMD寄存器被映射到AArch64 FP和SIMD寄存器。这允许一个应用或虚拟机的浮点和NEON寄存器被更高级别的系统软件解析,比如,OS或hypervisor。
AArch64 V16~V31 FP和NEON寄存器不能从AArch32进行访问。与通用寄存器,在异常级别使用AArch32执行这些寄存器保持着之前使用AArch32的执行。