文章目录
- SVE 汇编语法
- SVE 单通道谓词
- SVE 测试代码
- SVE 软件和库支持
- SVE 编译参数配置
- -march=armv8-a
- +lse
- +profile
- +memtag
- +sve2-aes
- +sve2-bitperm
- +crypto
- +sve2
- +sve2-sha3
- +sve2-sm4
SVE 汇编语法
在介绍 SVE 汇编指令语法之前,先介绍下如何判断自己所使用的芯片是否实现了SVE功能,如下图所示,可以通过寄存器ID_AA64PFR0_EL1
来判断是否实现了 SVE 功能,可以看到通过这个寄存器也可以查看 AMU, MPAM 等功能的信息。
可以通过下面汇编代码判断SVE是否实现:
mrs x0, ID_AA64PFR0_EL1
ubfx x5, x0, #32, #4 // Extract the sve field
and x5, x5, #0xff
cmp x5, #1 // sve not present
b.ne sve_not_present
SVE 引入了以下重要的架构特性:
- 单通道谓词(per-lane predication)
- 聚集加载和分散存储(gather-load and scatter-store)
- 谓词驱动的循环控制和管理
- 用于软件控制的投机的向量分区
- 扩展的浮点和水平归约
SVE 单通道谓词
SVE(Scalable Vector Extension)扩展提供了灵活的向量处理能力。SVE引入了谓词寄存器(如p0
到p15
),这些寄存器用于控制向量操作的执行。谓词寄存器中的每一位对应向量寄存器中的一个元素,指示该元素是否应该参与到特定的向量操作中。
ADD Z0.D, P0/M, Z0.D, Z1.D
活动元素 Z0
和 Z1
相加并将结果放入 Z0
。P0
指示操作数的哪些元素是活动的和非活动的。 P0
后面的 “M” 表示 Merging,表示将非活动元素合并,因此 Z0
的非活动元素在ADD
操作后将保持其原始值。
如果在 P0
之后是“Z
”,即归零,则目标寄存器的非活动元素将在操作后归零。
SVE 测试代码
下面测试代码将向量寄存器z0.d
赋值0x5555555511111111
, 将z1.d
赋值0x4444444422222222
, 然后两者相加再赋值给z1.d
,最后将结果通过x0
返回给调用函数,通过 ptrue p0.d
将谓词寄存器p0
中所有元素的控制位都设为1
。然后通过st1d
将计算结果写入到地址0xB0000000
处。
.type sve_test %function
.global sve_test
sve_test:
stp x29, x30, [sp, #-0x10 * 1]!
/* define a element as 64bits and fully true */
ptrue p0.d
ldr x0, =0x5555555511111111
/* duplicate value to all elements */
dup z0.d, x0
ldr x1, =0x4444444422222222
dup z1.d, x1
add z1.d, p0/m, z1.d, z0.d
ldr x1, =0xB0000000
st1d {z1.d}, p0, [x1]
ldr x0, [x1]
ldp x29, x30, [sp], #0x10
ret
测试效果:
可以看到向量寄存器 z0.d
+ z1.d
的值为0x9999999933333333
SVE 软件和库支持
要构建 SVE 应用程序,须选择支持 SVE 功能的编译器,例如:
- GNU 工具 8.0+ 版支持 C/C++/Fortran 的 SVE 优化。
- Arm Compiler for Linux,Arm Linux 的原生编译器。 Arm Compiler for Linux 18.0+ 版支持 C、C++ 和 Fortran 代码的 SVE 代码生成。 Arm Compiler for Linux 是 Arm Linux 用户空间工具解决方案 Arm Allinea Studio 的一部分。
- Arm Compiler 6 是一个用于裸机应用程序开发的跨平台编译器,也支持从 6.12 版本开始的 SVE 代码生成。 除了编译器之外,您还可以依赖一些高度优化的 SVE 库,例如:
- Arm 性能库是一组高度优化的数学例程,可以链接到您的应用程序。 Arm 性能库版本 19.3+ 支持 SVE 的数学库。 Arm 性能库是 Arm Compiler for Linux 的一部分。
- 其他第三方数学库。
同时还需要配置相对应的编译参数,如下节内容。
SVE 编译参数配置
-march=armv8-a
这个参数指定了目标架构是 ARMv8-A。-march
选项用于指定GCC应该为哪个架构生成代码,而ARMv8-A是ARM第八代架构,支持64位处理器,引入了很多新的特性和指令集,其中就包括
+lse
LSE(Large System Extension)扩展增加了一组针对原子操作的改进,有助于提高多核处理器上的同步性能。
+profile
这个选项可能是指启用对性能监控和分析特性的支持,但标准GCC文档中并未明确列出+profile
作为一个独立的功能。通常,性能分析可以通过其他工具和编译器选项(如-pg
用于gprof)来启用。
+memtag
启用内存标签扩展(Memory Tagging Extension, MTE),这是一种用于检测和预防内存相关错误(如越界访问和使用后释放)的安全特性。关于ARMv9 MTE 见文章:【ARM Cache 与 MMU 系列文章 7.5 – ARMv8/v9 MMU FEAT_XS(XS Attribute)与 FEAT_MTE2 介绍】。
+sve2-aes
启用支持 SVE2(Scalable Vector Extension 2)中的AES(Advanced Encryption Standard)指令。SVE2 是 SVE 的扩展,增加了更多的向量化操作,而AES指令用于加密算法。
+sve2-bitperm
启用SVE2中的位置换(Bit Permutation)指令,这些指令用于高效的位级操作和数据重组。
+crypto
启用加密指令支持,这通常指的是AES、SHA(Secure Hash Algorithm)和其他密码学相关的指令集。关于 AES
和 SHA
详细介绍见文章【ARM 安全系列介绍 3-- Openssl 常用加密算法】。
+sve2
启用SVE2指令集支持。SVE2是对原始SVE指令集的扩展,提供了更广泛的向量操作和数据类型支持。
+sve2-sha3
启用SVE2中支持SHA-3加密哈希函数的指令。关于SHA
摘要算法见文章:【ARM 安全系列介绍 3.5 – 常见的摘要算法并应用举例】。
+sve2-sm4
启用SVE2中支持SM4(一种块加密标准,广泛用于中国的密码学应用)的指令。关于 SM4 加密算法见文章:【ARM 安全系列介绍 3.7 – SM4 对称加密算】
关于ARM GCC 编译的更多内容, 推荐阅读: ARM GCC 编译系列专栏
在综合这些编译参数后,GCC将生成针对具有上述所有特性的ARMv8-A架构的代码。这通常意味着编译出的程序能够在支持这些特性的硬件上运行得更快、更安全。然而,如果目标硬件不支持某些特性(如SVE2或MTE),则生成的程序可能无法在该硬件上运行。因此,选择这些编译参数时需要确保目标环境与之兼容。