ARMV7架构包含:
- 16个32位通用寄存器,R0-R15
- 16个128位NEON寄存器,Q0-Q15(同时也可以被视为32个64bit的寄存器,D0-D31)
- 16个32位VFP寄存器,S0-S15
ARMV8架构包含:
- 31个64位通用寄存器,X0-X30
- 32个128位NEON寄存器,V0-V31
NEON指令按照操作数类型可以分为正常指令、宽指令、窄指令、饱和指令、长指令。
- 正常指令:生成大小相同且类型通常与操作数向量相同的结果向量。
- 长指令:对双字向量操作数执行运算,生成四字向量的结果。生成的元素一般是操作数元素宽度的两倍,并属于同一类型。L标记,如VMOVL。
- 宽指令:一个双字向量操作数和一个四字向量操作数执行运算,生成四字向量结果。W标记,如VADDW。
- 窄指令:四字向量操作数执行运算,并生成双字向量结果,所生成的元素一般是操作数元素宽度的一半。N标记,如VMOVN。
- 饱和指令:当超过数据类型指定到范围则自动限制在该范围内。Q标记,如VQSHRUN
命名规则:<基本数据类型>x<lane个数>x<向量个数>_t
- 基本数据类型: int8,int16,int32,int64,uint8,uint16,uint32,uint64,float16,float32
- lane个数:表示并行处理的基本类型数据的个数。
- 向量个数如果省略表示只有一个。
举例:int8x8_t、int8x8x3_t
命名规则:v<指令名><后缀>_<基本数据类型简写>
-
指令名:描述进行的操作
-
后缀:代表指令的类型。如果没有,表示64位并行;如果后缀是q,表示128位并行;如果后缀是l,表示长指令;如果后缀是n,表示窄指令。
-
基本数据类型简写:s8,s16,s32,s64,u8,u16,u32,u64,f16,f32。
基本数据类型 类型简写 int8 s8 uint8 u8 int16 s16 uint16 u16 int32 s32 uint32 u32 int64 s64 uint64 u64 float16 f16 float32 f32
举例:
- vadd_u8:两个uint8x8相加为一个uint8x8
- vaddq_u8:两个uint8x16相加为一个uint8x16
- vaddl_u8:两个uint8x8相加为一个uint16x8
1. vadd_<类型简写> / vaddq_<类型简写>
说明: 64位/128位整型或浮点型数据相加。
函数原型:
int8x8_t vadd_s8(int8x8_t a, int8x8_t b);
int16x4_t vadd_s16(int16x4_t a, int16x4_t b);
int32x2_t vadd_s32(int32x2_t a, int32x2_t b);
int64x1_t vadd_s64(int64x1_t a, int64x1_t b);
uint8x8_t vadd_u8(uint8x8_t a, uint8x8_t b);
uint16x4_t vadd_u16(uint16x4_t a, uint16x4_t b);
uint32x2_t vadd_u32(uint32x2_t a, uint32x2_t b);
uint64x1_t vadd_u64(uint64x1_t a, uint64x1_t b);
float32x2_t vadd_f32(float32x2_t a, float32x2_t b);
float64x1_t vadd_f64(float64x1_t a, float64x1_t b);
int8x16_t vaddq_s8(int8x16_t a, int8x16_t b);
int16x8_t vaddq_s16(int16x8_t a, int16x8_t b);
int32x4_t vaddq_s32(int32x4_t a, int32x4_t b);
int64x2_t vaddq_s64(int64x2_t a, int64x2_t b);
uint8x16_t vaddq_u8(uint8x16_t a, uint8x16_t b);
uint16x8_t vaddq_u16(uint16x8_t a, uint16x8_t b);
uint32x4_t vaddq_u32(uint32x4_t a, uint32x4_t b);
uint64x2_t vaddq_u64(uint64x2_t a, uint64x2_t b);
float32x4_t vaddq_f32(float32x4_t a, float32x4_t b);
float64x2_t vaddq_f64(float64x2_t a, float64x2_t b);
调用示例:
int8x16_t result = vaddq_s8(a, b);
a: 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
b: 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
result: 120 122 124 126 -128 -126 -124 -122 -120 -118 -116 -114 -112 -110 -108 -106
2. vaddl_<类型简写>
说明: 长指令;64位整型数据相加,结果数据是操作数位数的两倍。
函数原型:
int16x8_t vaddl_s8(int8x8_t a, int8x8_t b);
int32x4_t vaddl_s16(int16x4_t a, int16x4_t b);
int64x2_t vaddl_s32(int32x2_t a, int32x2_t b);
uint16x8_t vaddl_u8(uint8x8_t a, uint8x8_t b);
uint32x4_t vaddl_u16(uint16x4_t a, uint16x4_t b);
uint64x2_t vaddl_u32(uint32x2_t a, uint32x2_t b);
调用示例:
int16x8_t result = vaddl_s8(a, b);
a: 60 61 62 63 64 65 66 67
b: 60 61 62 63 64 65 66 67
result: 120 122 124 126 128 130 132 134
3. vaddl_high_<类型简写>
说明: 长指令;a和b的后半部分元素相加,结果位数扩大两倍存储。
函数原型:
int16x8_t vaddl_high_s8(int8x16_t a, int8x16_t b);
int32x4_t vaddl_high_s16(int16x8_t a, int16x8_t b);
int64x2_t vaddl_high_s32(int32x4_t a, int32x4_t b);
uint16x8_t vaddl_high_u8(uint8x16_t a, uint8x16_t b);
uint32x4_t vaddl_high_u16(uint16x8_t a, uint16x8_t b);
uint64x2_t vaddl_high_u32(uint32x4_t a, uint32x4_t b);
调用示例:
int16x8_t result = vaddl_high_s8(a, b);
a: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
b: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
result: 16 18 20 22 24 26 28 30
4. vaddw_<类型简写>
说明: 宽指令;a和b相加(a的数据位数是b的两倍,通道数相同,结果位数与a相同)。
函数原型:
int16x8_t vaddw_s8(int16x8_t a, int8x8_t b);
int32x4_t vaddw_s16(int32x4_t a, int16x4_t b);
int64x2_t vaddw_s32(int64x2_t a, int32x2_t b);
uint16x8_t vaddw_u8(uint16x8_t a, uint8x8_t b);
uint32x4_t vaddw_u16(uint32x4_t a, uint16x4_t b);
uint64x2_t vaddw_u32(uint64x2_t a, uint32x2_t b);
调用示例:
int16x8_t result = vaddw_s8(a, b);
a: 256 257 258 259 260 261 262 263
b: 120 121 122 123 124 125 126 127
result: 376 378 380 382 384 386 388 390
5. vaddw_high_<类型简写>
说明: 宽指令;a的元素加上b的后半部分对应位置元素。
函数原型:
int16x8_t vaddw_high_s8(int16x8_t a, int8x16_t b);
int32x4_t vaddw_high_s16(int32x4_t a, int16x8_t b);
int64x2_t vaddw_high_s32(int64x2_t a, int32x4_t b);
uint16x8_t vaddw_high_u8(uint16x8_t a, uint8x16_t b);
uint32x4_t vaddw_high_u16(uint32x4_t a, uint16x8_t b);
uint64x2_t vaddw_high_u32(uint64x2_t a, uint32x4_t b);
调用示例:
int16x8_t result = vaddw_high_s8(a, b);
a: 0 1 2 3 4 5 6 7
b: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
result: 8 10 12 14 16 18 20 22
6. vhadd_<类型简写> / vhaddq_<类型简写>
说明: a和b对应通道元素相加,并将所加结果右移一位存储,向下取整。
函数原型:
int8x8_t vhadd_s8(int8x8_t a, int8x8_t b);
int16x4_t vhadd_s16(int16x4_t a, int16x4_t b);
int32x2_t vhadd_s32(int32x2_t a, int32x2_t b);
uint8x8_t vhadd_u8(uint8x8_t a, uint8x8_t b);
uint16x4_t vhadd_u16(uint16x4_t a, uint16x4_t b);
uint32x2_t vhadd_u32(uint32x2_t a, uint32x2_t b);
int8x16_t vhaddq_s8(int8x16_t a, int8x16_t b);
int16x8_t vhaddq_s16(int16x8_t a, int16x8_t b);
int32x4_t vhaddq_s32(int32x4_t a, int32x4_t b);
uint8x16_t vhaddq_u8(uint8x16_t a, uint8x16_t b);
uint16x8_t vhaddq_u16(uint16x8_t a, uint16x8_t b);
uint32x4_t vhaddq_u32(uint32x4_t a, uint32x4_t b);
调用示例:
int8x16_t result = vhaddq_s8(a, b);
a: 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
b: 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
result: 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
7. vrhadd_<类型简写> / vrhaddq_<类型简写>
说明: a和b对应通道元素相加,并将所加结果右移一位存储,向上取整。
函数原型:
int8x8_t vrhadd_s8(int8x8_t a, int8x8_t b);
int16x4_t vrhadd_s16(int16x4_t a, int16x4_t b);
int32x2_t vrhadd_s32(int32x2_t a, int32x2_t b);
uint8x8_t vrhadd_u8(uint8x8_t a, uint8x8_t b);
uint16x4_t vrhadd_u16(uint16x4_t a, uint16x4_t b);
uint32x2_t vrhadd_u32(uint32x2_t a, uint32x2_t b);
int8x16_t vrhaddq_s8(int8x16_t a, int8x16_t b);
int16x8_t vrhaddq_s16(int16x8_t a, int16x8_t b);
int32x4_t vrhaddq_s32(int32x4_t a, int32x4_t b);
uint8x16_t vrhaddq_u8(uint8x16_t a, uint8x16_t b);
uint16x8_t vrhaddq_u16(uint16x8_t a, uint16x8_t b);
uint32x4_t vrhaddq_u32(uint32x4_t a, uint32x4_t b);
调用示例:
int8x16_t result = vrhaddq_s8(a, b);
a: 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
b: 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
result: 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
8. vqadd_<类型简写> / vqaddq_<类型简写>
说明: 饱和指令;a和b对应通道元素相加,超出范围则自动限制在该数据类型表示范围内。
函数原型:
int8x8_t vqadd_s8(int8x8_t a, int8x8_t b);
int16x4_t vqadd_s16(int16x4_t a, int16x4_t b);
int32x2_t vqadd_s32(int32x2_t a, int32x2_t b);
int64x1_t vqadd_s64(int64x1_t a, int64x1_t b);
uint8x8_t vqadd_u8 (uint8x8_t a, uint8x8_t b);
uint16x4_t vqadd_u16(uint16x4_t a, uint16x4_t b);
uint32x2_t vqadd_u32(uint32x2_t a, uint32x2_t b);
uint64x1_t vqadd_u64(uint64x1_t a, uint64x1_t b);
int8x16_t vqaddq_s8(int8x16_t a, int8x16_t b);
int16x8_t vqaddq_s16(int16x8_t a, int16x8_t b);
int32x4_t vqaddq_s32(int32x4_t a, int32x4_t b);
int64x2_t vqaddq_s64(int64x2_t a, int64x2_t b);
uint8x16_t vqaddq_u8(uint8x16_t a, uint8x16_t b);
uint16x8_t vqaddq_u16(uint16x8_t a, uint16x8_t b);
uint32x4_t vqaddq_u32(uint32x4_t a, uint32x4_t b);
uint64x2_t vqaddq_u64(uint64x2_t a, uint64x2_t b);
调用示例:
int8x16_t result = vqaddq_s8(a, b);
a: 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
b: 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
result: 123 125 127 127 127 127 127 127 127 127 127 127 127 127 127 127
9. vuqadd_<类型简写> / vuqaddq_<类型简写>
说明: 饱和指令;有符号数a和无符合数b对应通道元素相加,超出范围的自动限制在有符号数表示范围内。
函数原型:
int8x8_t vuqadd_s8(int8x8_t a, uint8x8_t b);
int16x4_t vuqadd_s16(int16x4_t a, uint16x4_t b);
int32x2_t vuqadd_s32(int32x2_t a, uint32x2_t b);
int64x1_t vuqadd_s64(int64x1_t a, uint64x1_t b);
int8x16_t vuqaddq_s8(int8x16_t a, uint8x16_t b);
int16x8_t vuqaddq_s16(int16x8_t a, uint16x8_t b);
int32x4_t vuqaddq_s32(int32x4_t a, uint32x4_t b);
int64x2_t vuqaddq_s64(int64x2_t a, uint64x2_t b);
调用示例:
int8x16_t result = vuqaddq_s8(a, b);
a: 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
b: 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
result: 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127 127
10. vsqadd_<类型简写> / vsqaddq_<类型简写>
说明: 饱和指令;无符号数a和有符号数b对应通道元素相加,超出范围自动限制在无符号数表示范围内。
函数原型:
uint8x8_t vsqadd_u8(uint8x8_t a, int8x8_t b);
uint16x4_t vsqadd_u16(uint16x4_t a, int16x4_t b);
uint32x2_t vsqadd_u32(uint32x2_t a, int32x2_t b);
uint64x1_t vsqadd_u64(uint64x1_t a, int64x1_t b);
uint8x16_t vsqaddq_u8(uint8x16_t a, int8x16_t b);
uint16x8_t vsqaddq_u16(uint16x8_t a, int16x8_t b);
uint32x4_t vsqaddq_u32(uint32x4_t a, int32x4_t b);
uint64x2_t vsqaddq_u64(uint64x2_t a, int64x2_t b);
调用示例:
uint8x16_t result = vsqaddq_u8(a, b);
a: 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
b: -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11 12
result: 207 209 211 213 215 217 219 221 223 225 227 229 231 233 235 237
11. vaddhn_<类型简写>
说明: 窄指令;两个向量的相应元素相加,并返回每个和的最高有效位的一半,结果被截断。
函数原型:
int8x8_t vaddhn_s16(int16x8_t a, int16x8_t b);
int16x4_t vaddhn_s32(int32x4_t a, int32x4_t b);
int32x2_t vaddhn_s64(int64x2_t a, int64x2_t b);
uint8x8_t vaddhn_u16(uint16x8_t a, uint16x8_t b);
uint16x4_t vaddhn_u32(uint32x4_t a, uint32x4_t b);
uint32x2_t vaddhn_u64(uint64x2_t a, uint64x2_t b);
调用示例:
int8x8_t result = vaddhn_s16(a, b);
a: 254 255 256 257 258 259 260 261
b: 253 254 255 256 257 258 259 260
result: 1 1 1 2 2 2 2 2
12. vaddhn_high_<类型简写>
说明: 窄指令;向量r的值存放到结果数据的前半段;向量a和b的相应元素相加,并返回每个和的最高有效位的一半存储到结果数据的后半段,结果被截断。
函数原型:
int8x16_t vaddhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b);
int16x8_t vaddhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b);
int32x4_t vaddhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b);
uint8x16_t vaddhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b);
uint16x8_t vaddhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b);
uint32x4_t vaddhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b);
调用示例:
int8x16_t result = vaddhn_high_s16(r, a, b);
r: 120 121 122 123 124 125 126 127
a: 254 255 256 257 258 259 260 261
b: 253 254 255 256 257 258 259 260
result: 120 121 122 123 124 125 126 127 1 1 1 2 2 2 2 2
13. vraddhn_<类型简写>
说明: 窄指令;两个向量的相应元素相加,并返回每个和的最高有效位的一半,结果四舍五入。
函数原型:
int8x8_t vraddhn_s16(int16x8_t a, int16x8_t b);
int16x4_t vraddhn_s32(int32x4_t a, int32x4_t b);
int32x2_t vraddhn_s64(int64x2_t a, int64x2_t b);
uint8x8_t vraddhn_u16(uint16x8_t a, uint16x8_t b);
uint16x4_t vraddhn_u32(uint32x4_t a, uint32x4_t b);
uint32x2_t vraddhn_u64(uint64x2_t a, uint64x2_t b);
调用示例:
int8x8_t result = vraddhn_s16(a, b);
a: 254 255 256 257 258 259 260 261
b: 253 254 255 256 257 258 259 260
result: 2 2 2 2 2 2 2 2
14. vraddhn_high_<类型简写>
说明: 窄指令;向量r的值存放到结果数据的前半段;向量a和b的相应元素相加,并返回每个和的最高有效位的一半存储到结果数据的后半段,结果四舍五入。
函数原型:
int8x16_t vraddhn_high_s16(int8x8_t r, int16x8_t a, int16x8_t b);
int16x8_t vraddhn_high_s32(int16x4_t r, int32x4_t a, int32x4_t b);
int32x4_t vraddhn_high_s64(int32x2_t r, int64x2_t a, int64x2_t b);
uint8x16_t vraddhn_high_u16(uint8x8_t r, uint16x8_t a, uint16x8_t b);
uint16x8_t vraddhn_high_u32(uint16x4_t r, uint32x4_t a, uint32x4_t b);
uint32x4_t vraddhn_high_u64(uint32x2_t r, uint64x2_t a, uint64x2_t b);
调用示例:
int8x16_t result = vraddhn_high_s16(r, a, b);
r: 120 121 122 123 124 125 126 127
a: 623 624 625 626 627 628 629 630
b: 50 51 52 53 54 55 56 57
result: 120 121 122 123 124 125 126 127 3 3 3 3 3 3 3 3
1. vmul_<类型简写> / vmulq_<类型简写>
说明: 两个向量对应通道的数据相乘。
函数原型:
int8x8_t vmul_s8(int8x8_t a, int8x8_t b);
int16x4_t vmul_s16(int16x4_t a, int16x4_t b);
int32x2_t vmul_s32(int32x2_t a, int32x2_t b);
uint8x8_t vmul_u8(uint8x8_t a, uint8x8_t b);
uint16x4_t vmul_u16(uint16x4_t a, uint16x4_t b);
uint32x2_t vmul_u32(uint32x2_t a, uint32x2_t b);
float32x2_t vmul_f32(float32x2_t a, float32x2_t b);
float64x1_t vmul_f64(float64x1_t a, float64x1_t b);
int8x16_t vmulq_s8(int8x16_t a, int8x16_t b);
int16x8_t vmulq_s16(int16x8_t a, int16x8_t b);
int32x4_t vmulq_s32(int32x4_t a, int32x4_t b);
uint8x16_t vmulq_u8(uint8x16_t a, uint8x16_t b);
uint16x8_t vmulq_u16(uint16x8_t a, uint16x8_t b);
uint32x4_t vmulq_u32(uint32x4_t a, uint32x4_t b);
float32x4_t vmulq_f32(float32x4_t a, float32x4_t b);
float64x2_t vmulq_f64(float64x2_t a, float64x2_t b);
调用示例:
int8x16_t result = vmulq_s8(a, b);
a: 4 5 6 7 8 9 10 11
b: 5 6 7 8 9 10 11 12
result: 20 30 42 56 72 90 110 -124
2. vmulx_<数据类型> / vmulxq_<类型简写>
说明: 两个向量对应通道的浮点数相乘。
函数原型:
float32x2_t vmulx_f32(float32x2_t a, float32x2_t b);
float64x1_t vmulx_f64(float64x1_t a, float64x1_t b);
float32x4_t vmulxq_f32(float32x4_t a, float32x4_t b);
float64x2_t vmulxq_f64(float64x2_t a, float64x2_t b);
调用示例:
float32x4_t vmulxq_f32(float32x4_t a, float32x4_t b)
a: 10 11 12 13
b: 11 12 13 14
result: 110 132 156 182
3. vmulx_lane_<类型简写> / vmulxq_lane_<类型简写>
说明: 向量a的元素和向量b中指定通道的元素相乘。
函数原型:
float32x2_t vmulx_lane_f32(float32x2_t a, float32x2_t v, const int lane);
float64x1_t vmulx_lane_f64(float64x1_t a, float64x1_t v, const int lane);
float32x4_t vmulxq_lane_f32(float32x4_t a, float32x2_t v, const int lane);
float64x2_t vmulxq_lane_f64(float64x2_t a, float64x1_t v, const int lane);
调用示例:
float32x4_t result = vmulxq_lane_f32(a, b, 1);
a: 10 11 12 13
b: 11 12
result: 120 132 144 156
vdiv_<数据类型简写> (64bit)/ vdivq_<数据类型简写> (128bit)
说明: 浮点数相除。
调用示例:
float32x4_t vdivq_f32(float32x4_t a, float32x4_t b)
a: 320 321 322 323
b: 11 12 13 14
result: 29.090910 26.750000 24.769230 23.071428
1. vmla_<数据类型简写> (64bit)/ vmlaq_<数据类型简写> (128bit)
说明: b和c对应通道元素相乘,结果再与a对应通道元素相加。
调用示例:
int8x16_t vmlaq_s8(int8x16_t a, int8x16_t b, int8x16_t c)
a: 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
b: 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
c: 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
result: 34 47 62 79 98 119 -114 -89 -62 -33 -2 31 66 103 -114 -73
2. vmlal_<数据类型简写>
说明: b和c对应通道元素相乘,结果再与a对应通道元素相加(操作数a的位数是操作数b/c的两倍,通道数相同)。
调用示例:
int16x8_t vmlal_s8(int16x8_t a, int8x8_t b, int8x8_t c)
a: 4 5 6 7 8 9 10 11
b: 5 6 7 8 9 10 11 12
c: 6 7 8 9 10 11 12 13
result: 34 47 62 79 98 119 142 167
3. vmlal_high_<数据类型简写>
说明: b和c的后半部分(高位)对应通道元素相乘,结果再与a对应通道元素相加。(a的位数是b和c的两倍,通道数是其一半)
调用示例:
int16x8_t vmlal_high_s8(int16x8_t a, int8x16_t b, int8x16_t c)
a: 4 5 6 7 8 9 10 11
b: 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
c: 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
result: 186 215 246 279 314 351 390 431
4. vmls_<数据类型简写> / vmlsq_<数据类型简写>
说明: b和c对应通道元素相乘,再用a减去对应通道数相乘结果。
调用示例:
int8x16_t vmls_s8(int8x8_t a, int8x8_t b, int8x8_t c)
a: 4 5 6 7 8 9 10 11
b: 5 6 7 8 9 10 11 12
c: 6 7 8 9 10 11 12 13
result: -26 -37 -50 -65 -82 -101 -122 111
数据处理指令
比较指令
归约指令