NEON
文章目录
1 neon窥探
1.1 neon用途
NEON 技术是适用于Arm Cortex-A 系列处理器的高级 SIMD(单指令多数据)架构。它可以加速多媒体和信号处理算法,例如视频编码器/解码器、2D/3D 图形、游戏、音频和语音处理、图像处理、电话和声音。
1.2 neon处理机制
NEON 指令执行“Packed SIMD”处理:
- 寄存器被视为相同数据类型元素的向量
- 数据类型可以是: ARM 32 位平台上的有符号/无符号 8 位、16 位、32 位、64 位、单精度浮点、单精度浮点和双精度浮点指向 ARM 64 位平台。
- 指令在所有通道中执行相同的操作
1.3 neon发展历程中的优缺点对比
Armv6:
- 在 32 位通用 ARM 寄存器上运行
- 8 位/16 位整数
- 每条指令 2x16 位/4x8 位操作
Armv7-A:
- 独立的寄存器组,32x64 位 NEON 寄存器
- 8/16/32/64 位整数
- 单精度浮点数
- 每条指令最多 16x8 位操作
Armv8-A AArch64:
- 独立的寄存器组,32x128 位 NEON 寄存器
- 8/16/32/64 位整数
- 单精度浮点数
- 双精度浮点,两者都符合IEEE
- 每条指令最多 16x8 位操作
1.4 为什么使用neon
- 对整数和浮点运算的支持确保了广泛的应用程序的适应性,从编解码器到高性能计算再到 3D 图形。
- 与 Arm 处理器的紧密耦合提供单一指令流和统一的内存视图,以更简单的工具流程呈现单一开发平台目标
1.5 Armv7/v8详细差异
Armv8-A 是对 Arm 架构的根本性改变。它支持称为“AArch64”的 64 位执行状态和新的 64 位指令集“A64”。为了提供与 Armv7-A(32 位架构)指令集的兼容性,提供了 Armv8-A“AArch32”的 32 位变体。大多数现有的 Armv7-A 代码都可以在 Armv8-A 的 AArch32 执行状态下运行。
本节比较了 Armv7-A 和 Armv8-A 架构的 NEON 相关特性。另外,NEON编程中经常用到的通用Arm寄存器和Arm指令也会被提及。但是,重点仍然是 NEON 技术。
1.6 Register寄存器
Armv7-A 和 AArch32 具有相同的通用 Arm 寄存器——16 x 32 位通用 Arm 寄存器 (R0-R15)。
Armv7-A 和 AArch32 具有 32 x 64 位 NEON 寄存器 (D0-D31)。这些寄存器也可以视为 16x128 位寄存器 (Q0-Q15)。每个 Q0-Q15 寄存器映射到一对 D 寄存器,如下图所示。
相比之下,AArch64 有 31 个 64 位通用 Arm 寄存器和 1 个具有不同名称的特殊寄存器,具体取决于使用它的上下文。这些寄存器可以被视为 31 x 64 位寄存器 (X0-X30) 或 31 x 32 位寄存器 (W0-W30)。
AArch64 有 32 x 128 位 NEON 寄存器 (V0-V31)。这些寄存器也可以被视为 32 位 Sn 寄存器或 64 位 Dn 寄存器。
1.7 指令系统间的关系与1.3相似
下图说明了 Armv7-A、Armv8-A AArch32 和 Armv8-A AArch64 指令集之间的关系。
Armv8-A AArch32指令集由A32(Arm指令集,32位定长指令集)和T32(Thumb指令集,16位定长指令集;Thumb2指令集,16或32位长指令集)组成指令系统)。它是 Armv7-A 指令集的超集,因此它保留了运行现有软件所需的向后兼容性。对 A32 和 T32 进行了一些添加以保持与 A64 指令集的对齐,包括 NEON 除法和加密扩展指令。还支持 NEON 双精度浮点(符合 IEEE)。
2 neon 使用
2.1 neon 指令格式
Armv7-A/AArch32 指令语法
Armv7-A/AAArch32 NEON 指令(与 VFP 一样)的所有助记符都以字母“V”开头。指令通常能够对不同的数据类型进行操作,这在指令编码中指定。尺寸用指令的后缀表示。元素的数量由指定的寄存器大小和操作的数据类型指示。指令具有以下一般格式:
指令具有以下一般格式:
V{<mod>}<op>{<shape>}{<cond>}{.<dt>}{<dest>}, src1, src2
其中:
== mod 修饰符
Q:指令采用饱和算法,使结果在指定数据类型范围内饱和,如VQABS、VQSHL等。
H:指令将结果减半。它通过右移一位(实际上是除以二并截断)来实现,例如 VHADD、VHSUB。
D:指令将结果加倍,如VQDMULL、VQDMLAL、VQDMLSL和VQ{R}DMULH
R:指令会对结果进行四舍五入,相当于在截断前给结果加0.5,如VRHADD、VRSHR。
op - 操作(例如,ADD、SUB、MUL)。==
<cond> - Condition, used with IT instruction
<.dt> - Data type, such as s8, u8, f32 etc.
<dest> - Destination
<src1> - Source operand 1
<src2> - Source operand 2
注: {} represents and optional parameter.代表可选参数。
Neon 数据处理指令通常有 Normal、Long、Wide 和 Narrow 变体。(注:vector对应32bit)
2.2 AArch64 NEON 指令语法
在 AArch64 执行状态下,NEON 指令的语法发生了变化。它可以描述如下:
{<prefix>}<op>{<suffix>} Vd.<T>, Vn.<T>, Vm.<T>
其中:
<prefix> - prefix, such as using S/U/F/P to represent signed/unsigned/float/bool data type.
<op> – operation, such as ADD, AND etc.
<suffix> - suffix
P: “pairwise” operations, such as ADDP.
V: the new reduction (across-all-lanes) operations, such as FMAXV.
2:new widening/narrowing “second part” instructions, such as ADDHN2, SADDL2.
ADDHN2:将两个 128 位向量相加,产生一个 64 位向量结果,作为 NEON 寄存器的高 64 位部分存储。
SADDL2:将NEON寄存器的两个高64位向量相加,产生128位向量结果。
<T> - 数据类型,8B/16B/4H/8H/2S/4S/2D。
B 代表字节(8 位)。H 代表半字(16 位)。S 代表字(32 位)。D 代表一个双字(64 位)。
将两个 128 位向量相加,产生一个 64 位向量结果,作为 NEON 寄存器的高 64 位部分存储。
例如:
UADDLP V0.8H, V0.16B
FADD V0.4S, V0.4S, V0.4S