2021-3-30 第十二天
指令集学习
Intel->指令集->MMX
网址:
https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=MMX&cats=Arithmetic&expand=210,132
MMX指令集学习
(重点看 加载、导出、逻辑运算、移位运算、shuffle洗牌指令)
头文件:#include <mmintrin.h>
__m64的定义为:
typedef union __declspec(intrin_type) _CRT_ALIGN(8) __m64
{
unsigned __int64 m64_u64;
float m64_f32[2];
__int8 m64_i8[8];
__int16 m64_i16[4];
__int32 m64_i32[2];
__int64 m64_i64;
unsigned __int8 m64_u8[8];
unsigned __int16 m64_u16[4];
unsigned __int32 m64_u32[2];
} __m64;
正常指令:生成大小相同且类型通常与操作数向量相同的结果向量
宽指令:一个双字操作数和一个四字操作数执行运算,生成四字向量结果
窄指令:四字向量操作数执行运算,生成双字向量结果(减半)
饱和指令:当超过数据类型指定到范围则自动限制在该范围内
长指令:对双字向量操作数执行运算,生成四字向量结果(加倍)
//1、Application-Targeted 以应用为目标
2、Arithmetic 算术
1)__m64 _mm_add_pi16(__m64 a, __m64 b)
FOR j := 0 to 3
i := j*16
dst[i+15:i] := a[i+15:i] + b[i+15:i]
ENDFOR
2)__m64 _mm_add_pi32(__m64 a, __m64 b)
FOR j := 0 to 1
i := j*32
dst[i+31:i] := a[i+31:i] + b[i+31:i]
ENDFOR
3)__m64 _mm_add_pi8(__m64 a, __m64 b)
FOR j := 0 to 7
i := j*8
dst[i+7:i] := a[i+7:i] + b[i+7:i]
ENDFOR
4)__m64 _mm_adds_pi16(__m64 a, __m64 b)
注:saturation(add) 饱和(加法)指令:如果结果超过255,则就赋为255
FOR j := 0 to 3
i := j*16
dst[i+15:i] := Saturate16( a[i+15:i] + b[i+15:i] )
ENDFOR
- __m64 _mm_adds_pi8(__m64 a, __m64 b)
FOR j := 0 to 7
i := j*8
dst[i+7:i] := Saturate8( a[i+7:i] + b[i+7:i] )
ENDFOR
- __m64 _mm_adds_pu16(__m64 a, __m64 b)
FOR j := 0 to 3
i := j*16
dst[i+15:i] := SaturateU16( a[i+15:i] + b[i+15:i] )
ENDFOR
- __m64 _mm_adds_pu8(__m64 a, __m64 b)
FOR j := 0 to 7
i := j*8
dst[i+7:i] := SaturateU8( a[i+7:i] + b[i+7:i] )
ENDFOR
- __m64 _mm_madd_pi16(__m64 a, __m64 b)
FOR j := 0 to 1
i := j*32
dst[i+31:i] := SignExtend32(a[i+31:i+16]*b[i+31:i+16]) + SignExtend32(a[i+15:i]*b[i+15:i])
ENDFOR
#SignExtend32:32位符合扩展
- __m64 _mm_mulhi_pi16(__m64 a, __m64 b)
FOR j := 0 to 3
i := j*16
tmp[31:0] := SignExtend32(a[i+15:i]) * SignExtend32(b[i+15:i])
dst[i+15:i] := tmp[31:16]
ENDFOR
- __m64 _mm_mullo_pi16(__m64 a, __m64 b)
FOR j := 0 to 3
i := j*16
tmp[31:0] := a[i+15:i] * b[i+15:i]
dst[i+15:i] := tmp[15:0]
ENDFOR
- __m64 _m_paddb(__m64 a, __m64 b) 同3)
- __m64 _m_paddd(__m64 a, __m64 b) 同2)
- __m64 _m_paddsb(__m64 a, __m64 b) 同5)
- __m64 _m_paddsw(__m64 a, __m64 b) 同4)
15)__m64 _m_paddusb(__m64 a, __m64 b) 同7) - __m64 _m_paddusw(__m64 a, __m64 b) 同6)
- __m64 _m_paddw(__m64 a, __m64 b) 同1)
- __m64 _m_pmaddwd(__m64 a, __m64 b) 同8)
- __m64 _m_pmulhw(__m64 a, __m64 b) 同9)
- __m64 _m_pmullw(__m64 a, __m64 b) 同10)
- __m64 _m_psubb(__m64 a, __m64 b)
- __m64 _m_psubd(__m64 a, __m64 b)
- __m64 _m_psubsb(__m64 a, __m64 b)
- __m64 _m_psubsw(__m64 a, __m64 b)
- __m64 _m_psubusb(__m64 a, __m64 b)
- __m64 _m_psubusw(__m64 a, __m64 b)
- __m64 _m_psubw(__m64 a, __m64 b)
。。。
总结:
b:byte–8bit
w:word–16bit
d:double–32bit
u:unsigned–无符号数
s:saturate–饱和指令
p:packed–压缩
hi:high–高位
lo:low–低位
wd:word double–字转双字
每个指令,两种格式 ①_mm_ ②_m_p
例:
_mm_add_pi16 _m_paddw
_mm_mulhi_pi16 _m_pmulhw
_mm_adds_pu8 _m_paddusb
_mm_madd_pi16 _m_pmaddwd
//
//3、Bit Manipulation 位操作
//4、Cast
5、Compare 比较
1)__m64 _mm_cmpeq_pi16 (__m64 a, __m64 b)
FOR j := 0 to 3
i := j*16
dst[i+15:i] := ( a[i+15:i] == b[i+15:i] ) ? 0xFFFF : 0
ENDFOR
- __m64 _mm_cmpgt_pi32 (__m64 a, __m64 b)
- __m64 _m_pcmpeqb (__m64 a, __m64 b)
总结:
eq:equip 等于
gt:greater 大于
6、Convert 转变
- __int64 _mm_cvtm64_si64 (__m64 a)
dst[63:0] := a[63:0]
- __m64 _mm_cvtsi32_si64 (int a)
dst[31:0] := a[31:0]
dst[63:32] := 0
- __m64 _mm_cvtsi64_m64 (__int64 a)
dst[63:0] := a[63:0]
- int _mm_cvtsi64_si32(__m64 a)
dst[31:0] := a[31:0]
- __m64 _m_from_int(int a)
- __m64 _m_from_int64(__int64 a)
- int _m_to_int(__m64 a)
- __int64 _m_to_int64(__m64 a)
//7、Cryptography 密码学
//8、Elementary Math 基本数学函数
函数
1、General Support
1)void _m_empty (void)
2)void _mm_empty (void)
//2、Load 加载
3、Logical 逻辑运算
1)__m64 _mm_and_si64 (__m64 a, __m64 b)
dst[63:0] := (a[63:0] AND b[63:0])
2)__m64 _mm_andnot_si64 (__m64 a, __m64 b)
dst[63:0] := ((NOT a[63:0]) AND b[63:0])
3)__m64 _mm_or_si64 (__m64 a, __m64 b)
dst[63:0] := (a[63:0] OR b[63:0])
4)__m64 _m_pand (__m64 a, __m64 b) 同1)
5)__m64 _m_pandn (__m64 a, __m64 b) 同2)
6)__m64 _m_por (__m64 a, __m64 b) 同3)
7)__m64 _m_pxor (__m64 a, __m64 b)
dst[63:0] := (a[63:0] XOR b[63:0])
8)__m64 _mm_xor_si64 (__m64 a, __m64 b) 同7)
//4、Mask
5、Miscellaneous
- __m64 _mm_packs_pi16 (__m64 a, __m64 b)
注:字转字节(符号饱和)
dst[7:0] := Saturate8(a[15:0])
dst[15:8] := Saturate8(a[31:16])
dst[23:16] := Saturate8(a[47:32])
dst[31:24] := Saturate8(a[63:48])
dst[39:32] := Saturate8(b[15:0])
dst[47:40] := Saturate8(b[31:16])
dst[55:48] := Saturate8(b[47:32])
dst[63:56] := Saturate8(b[63:48])
- __m64 _mm_packs_pi32 双字转字(符号饱和)
dst[15:0] := Saturate16(a[31:0])
dst[31:16] := Saturate16(a[63:32])
dst[47:32] := Saturate16(b[31:0])
dst[63:48] := Saturate16(b[63:32])
- __m64 _mm_packs_pu16 无符号字转字节(符号饱和)
4)__m64 _m_packssdw (__m64 a, __m64 b) 同2) - __m64 _m_packsswb (__m64 a, __m64 b) 同1)
- __m64 _m_packuswb (__m64 a, __m64 b) 同3)
//6、Move 移动
//7、OS-Targeted 以操作系统为目标
//8、Probability/Statistics 概率/统计
//9、Random 随机
10、Set 设置
1)__m64 _mm_set_pi16 (short e3, short e2, short e1, short e0)
dst[15:0] := e0
dst[31:16] := e1
dst[47:32] := e2
dst[63:48] := e3
- __m64 _mm_set_pi32 (int e1, int e0)
dst[31:0] := e0
dst[63:32] := e1
- __m64 _mm_set_pi8 (char e7, char e6, …, char e0)
dst[7:0] := e0
dst[15:8] := e1
dst[23:16] := e2
dst[31:24] := e3
dst[39:32] := e4
dst[47:40] := e5
dst[55:48] := e6
dst[63:56] := e7
- __m64 _mm_set1_pi16 (short a)
FOR j := 0 to 3
i := j*16
dst[i+15:i] := a[15:0]
ENDFOR
- __m64 _mm_set1_pi32 (int a)
FOR j := 0 to 1
i := j*32
dst[i+31:i] := a[31:0]
ENDFOR
- __m64 _mm_set1_pi8 (char a)
FOR j := 0 to 7
i := j*8
dst[i+7:i] := a[7:0]
ENDFOR
- __m64 _mm_setr_pi16 (short e3, short e2, short e1, short e0)
注:与set指令赋值顺序相反
dst[15:0] := e3
dst[31:16] := e2
dst[47:32] := e1
dst[63:48] := e0
- __m64 _mm_setr_pi32 (int e1, int e0)
dst[31:0] := e1
dst[63:32] := e0
- __m64 _mm_setr_pi8 (char e7, char e6, …, char e0)
dst[7:0] := e7
dst[15:8] := e6
dst[23:16] := e5
dst[31:24] := e4
dst[39:32] := e3
dst[47:40] := e2
dst[55:48] := e1
dst[63:56] := e0
- __m64 _mm_setzero_pi64 (void)
#全部赋值为0
dst[MAX:0] := 0
11、Shift 转移
_m_ps(l/r)l(d/q/w)
- __m64 _m_pslld (__m64 a, __m64 count)
#左移(32bit寄存器)
FOR j := 0 to 1
i := j*32
IF count[63:0] > 31
dst[i+31:i] := 0
ELSE
dst[i+31:i] := ZeroExtend32(a[i+31:i] << count[63:0])
FI
ENDFOR
2) __m64 _m_pslldi (__m64 a, int imm8)
3) __m64 _m_psllq (__m64 a, __m64 count)
#左移(64bit寄存器)
IF count[63:0] > 63
dst[63:0] := 0
ELSE
dst[63:0] := ZeroExtend64(a[63:0] << count[63:0])
FI
- __m64 _m_psllqi (__m64 a, int imm8)
- __m64 _m_psllw (__m64 a, __m64 count)
- __m64 _m_psllwi (__m64 a, int imm8)
_m_psr(a/l)(d/w/q)
#a与l的填充方式不同,a为。。,l为填0
7) __m64 _m_psrad (__m64 a, __m64 count)
FOR j := 0 to 1
i := j*32
IF count[63:0] > 31
dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0)
ELSE
dst[i+31:i] := SignExtend32(a[i+31:i] >> count[63:0])
FI
ENDFOR
总结:
①每个指令,两种格式:m mm
例:_m_pslld _mm_sll_pi32
_m_psraw _mm_sra_pi16
②l代表左移,r代表右移
③左移均为全0填充,右移有两种填充方式
ra为全1填充(SignExtend)符号扩展
rl为全0填充(ZeroExtend)无符号扩展
//12、Special Math Functions 特殊数学功能
//13、Store
//14、String Compare 字符串比较
15、Swizzle
- __m64 _m_punpckhbw (__m64 a, __m64 b)
#每8bit一交替,使用a、b的高位
DEFINE INTERLEAVE_HIGH_BYTES(src1[63:0], src2[63:0]) {
dst[7:0] := src1[39:32]
dst[15:8] := src2[39:32]
dst[23:16] := src1[47:40]
dst[31:24] := src2[47:40]
dst[39:32] := src1[55:48]
dst[47:40] := src2[55:48]
dst[55:48] := src1[63:56]
dst[63:56] := src2[63:56]
RETURN dst[63:0]
}
dst[63:0] := INTERLEAVE_HIGH_BYTES(a[63:0], b[63:0])
- __m64 _m_punpckhdq (__m64 a, __m64 b)
#每32bit一交替,使用a、b的高位
dst[31:0] := a[63:32]
dst[63:32] := b[63:32]
- __m64 _m_punpckhwd (__m64 a, __m64 b)
#每16bit一交替,使用a、b的高位
DEFINE INTERLEAVE_HIGH_WORDS(src1[63:0], src2[63:0]) {
dst[15:0] := src1[47:32]
dst[31:16] := src2[47:32]
dst[47:32] := src1[63:48]
dst[63:48] := src2[63:48]
RETURN dst[63:0]
}
dst[63:0] := INTERLEAVE_HIGH_WORDS(a[63:0], b[63:0])
- __m64 _m_punpcklbw (__m64 a, __m64 b)
#每8bit一交替,使用a、b的低位 - __m64 _m_punpckldq (__m64 a, __m64 b)
#每32bit一交替,使用a、b的低位 - __m64 _m_punpcklwd (__m64 a, __m64 b)
#每16bit一交替,使用a、b的低位 - __m64 _mm_unpackhi_pi16 (__m64 a, __m64 b) 同1)
- __m64 _mm_unpackhi_pi32 (__m64 a, __m64 b) 同2)
- __m64 _mm_unpackhi_pi8 (__m64 a, __m64 b) 同3)
- __m64 _mm_unpacklo_pi16 (__m64 a, __m64 b) 同4)
- __m64 _mm_unpacklo_pi32 (__m64 a, __m64 b) 同5)
- __m64 _mm_unpacklo_pi8 (__m64 a, __m64 b) 同6)
//16、Trigonometry 三角