ARM NEON 编程系列2 - 基本指令集
前言
本系列博文用于介绍ARM CPU下NEON指令优化。
博文github地址:github
相关代码github地址:github
NEON指令集
主流支持目标平台为ARM CPU的编译器基本都支持NEON指令。可以通过在代码中嵌入NEON汇编来使用NEON,但是更加常见的方式是通过类似C函数的NEON Instrinsic来编写NEON代码。就如同NEON hello world一样。NEON Instrinsic是编译器支持的一种buildin类型和函数的集合,基本涵盖NEON的所有指令,通常这些Instrinsic包含在arm_neon.h头文件中。
本文以android-ndk-r11c中armv7的arm_neon.h为例,讲解NEON的指令类型。
寄存器
ARMV7架构包含:
16个通用寄存器(32bit),R0-R15
16个NEON寄存器(128bit),Q0-Q15(同时也可以被视为32个64bit的寄存器,D0-D31)
16个VFP寄存器(32bit),S0-S15
NEON和VFP的区别在于VFP是加速浮点计算的硬件不具备数据并行能力,同时VFP更尽兴双精度浮点数(double)的计算,NEON只有单精度浮点计算能力。更多请参考stackoverflow:neon vs vfp
基本数据类型
64bit数据类型,映射至寄存器即为D0-D31
相应的c/c++语言类型(stdint.h或者csdtint头文件中类型)在注释中说明。
//typedef int8_t[8] int8x8_t;
typedef __builtin_neon_qi int8x8_t__attribute__ ((__vector_size__ (8)));
//typedef int16_t[4] int16x4_t;
typedef __builtin_neon_hi int16x4_t__attribute__ ((__vector_size__ (8)));
//typedef int32_t[2] int32x2_t;
typedef __builtin_neon_si int32x2_t__attribute__ ((__vector_size__ (8)));
//typedef int64_t[1] int64x1_t;
typedef __builtin_neon_di int64x1_t;
//typedef float16_t[4] float16x4_t;
//(注:该类型为半精度,在部分新的CPU上支持,c/c++语言标注中尚无此基本数据类型)
typedef __builtin_neon_hf float16x4_t__attribute__ ((__vector_size__ (8)));
//typedef float32_t[2] float32x2_t;
typedef __builtin_neon_sf float32x2_t__attribute__ ((__vector_size__ (8)));
//poly8以及poly16类型在常用算法中基本不会使用
//详细解释见:
//http://stackoverflow.com/questions/22224282/arm-neon-and-poly8-t-and-poly16-t
typedef __builtin_neon_poly8 poly8x8_t__attribute__ ((__vector_size__ (8)));
typedef __builtin_neon_poly16 poly16x4_t__attribute__ ((__vector_size__ (8)));
#ifdef __ARM_FEATURE_CRYPTO
typedef __builtin_neon_poly64 poly64x1_t;
#endif
//typedef uint8_t[8] uint8x8_t;
typedef __builtin_neon_uqi uin