2021-4-1 第十四天
指令集学习
Intel->指令集->SSE2
网址:
https://software.intel.com/sites/landingpage/IntrinsicsGuide/#expand=210,132,831,2823,2822,5999,401,5961,85,157,605,5320,5292,3671,6173,154,2177,4853,602,4853,3505,4853,3896,1941,1292&techs=SSE2
SSE2指令集学习
(重点看 加载、导出、逻辑运算、移位运算、shuffle洗牌指令)
头文件:#include <emmintrin.h>
MMX:
pi8:__m64/char
pi16:__m64/short
pi32:__m64/int
pu(8/16):__m64
si(32/64):__m64
SSE:
pi(8/16/32):__m64
pu(8/16):__m64
si32:int
si64:__int64/__m64
ps/ps1:__m128/float (32bit)
ss:_m128 (32bit)
SSE2:
si32:int/__m128i
si64:__int64/__m64
si128:__m128i
epi(8/16/32/64):__m128i
epu(8/16/32):__m128i
ps:__m128
pi32/su32:__m64
pd/pd1/sd:__m128d (64bit)
1、Application-Targeted 以应用为目标
2、Arithmetic 算术
1)mm(add/sub)(s)_(pd/sd/si64/epi(8/16/32/64)/epu(8/16))
#Saturate 饱和指令:如果超过寄存器最大值,则赋值为全1
#(add/sub)/(adds/subs)
add :正常相加 sub :正常相减
adds:饱和相加 subs:饱和相减
2)_mm_madd_epi16
#将a、b的高16位、低16位分别作乘法,再加到一起
FOR j := 0 to 3
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
3)mm_div(pd/sd)
#pd/sd
pd:64bit一组,执行除法
sd:仅低位64bit执行除法,其他位直接赋值为a
4)mm_mul( /hi/lo)(pd/sd/su/epi16/epu16)
#hi/lo
hi:执行乘法,保留结果的高位
lo:执行乘法,保留结果的低位
5)_mm_sad_epu8
#每8bit一组,计算a、b差的绝对值
#将这些值累加到dst的低16bit,dst的其他位赋0
FOR j := 0 to 15
i := j*8
tmp[i+7:i] := ABS(a[i+7:i] - b[i+7:i])
ENDFOR
FOR j := 0 to 1
i := j*64
dst[i+15:i] := tmp[i+7:i] + tmp[i+15:i+8] + tmp[i+23:i+16] + tmp[i+31:i+24] +
tmp[i+39:i+32] + tmp[i+47:i+40] + tmp[i+55:i+48] + tmp[i+63:i+56]
dst[i+63:i+16] := 0
ENDFOR
//3、Bit Manipulation
4、Cast (MMX和SSE没有)
#强制转换(数据类型)
mm_cast(pd/ps/si128)(pd/ps/si128)
#对pd(__m128d)、ps(__m128i)、si128(m128)三组数据类型进行相互转换
5、Compare(比较)
1)mm_cmp( /n)(eq/ge/gt/le/lt)(pd/sd/epi(8/16/32))
2)mm_cmp( /un)ord(pd/sd)
#判断a、b是否为NaN
3)mm( /u)comi(eq/ge/gt/le/lt/neq)
6、Convert(转换)
mm_cvt(t)(pd/sd/ss/si(32/64/128)/epi32)_(pd/ps/si(32/64/128)/epi32)
#t:截断指令
//7、Cryptography
8、Elementary Math
mm_sqrt(pd/sd)
函数:
1、General Support
2、Load (加载)
#从指定内存中加载数据到dst
mm_load( /1/h/l/r/u)(pd/sd/si128/si32/epi64)
注:_mm_loadu_si32 :仅赋值低位32bit,其他赋0 而不是每32bit一组
3、Logical(逻辑运算)
mm(and/andnot/or/xor)_(pd/si128)
//4、Mask(掩码)
5、Miscellaneous
1)mm_movemast(pd/epi8)
#从a中每个(8/64)bit的最高有效位创建掩码,存在dst中
2)_mm_movepi64_pi64
#将a中低64bit赋给dst
dst[63:0] := a[63:0]
3)_mm_pack(u)s_epi(16/32)
#每16/32bit一组,分别将a、b压缩为8/16bit,a在低位,b在高位
#packs/packus
packs:Saturate
packus:SaturateU
4)_mm_sad_epu8 #与Arithmetic中是同一个函数
6、Move(数据传送)
1)_mm_move_epi64
dst[63:0] := a[63:0]
dst[127:64] := 0
2)_mm_move_sd
dst[63:0] := b[63:0]
dst[127:64] := a[127:64]
3)_mm_movpi64_epi64
dst[63:0] := a[63:0]
dst[127:64] := 0
//7、OS-Targeted
8、Probability/Statistics(概率/统计)
_mm_avg_epu(8/16)
//9、Random
10、Set(设置(赋值))
mm_set(1/r/zero)(pd/sd/si128/epi(8/16/32/64))
11、Shift(移位运算)
mm(b)s(l/r)(l/a)(i)_(epi/si)(16/32/64)
b:imm8的值*8
l/r:左移/右移
l/a:无符号填充/符号填充
i:使用imm8
12、Special Math Functions(特殊数学函数)
mm(max/min)_(pd/sd/(ep(u/i)(8/16)))
max/min:最大值/最小值
pd/sd:每64bit float/仅64bit float 低位
13、Store (存储)
1)_mm_maskmoveu_si128
#每8bit,有条件存储数据到内存
#条件:掩码 (mask[i+7])
2)mm_store(h/l/u/ )(pd/pd1/sd/si(32/128)/epi64)
#pd/pd1/sd:
pd:正常存储
pd1:每64bit,均存储数据的低位64bit
sd:仅存储数据的低位64bit,其他位存0
#h/l/r/u
h:仅存储高位64bit
l:仅存储低位64bit
r:高位64bit和低位64bit,交换位置存储
u:正常存储
3)mm_stream(pd/si(32/64/128))
#pd/si(32/64/128)
pd:存储128bit,地址指针为double类型
si32:存储32bit,地址指针为int类型
si64: 存储64bit,地址指针为__int64类型
si128: 存储128bit,地址指针为__m128i类型
//14、String Compare
15、Swizzle(交替)
1)_mm_extract_epi16
#用imm8从a选取16bit数据,放在低位16bit,高位16bit赋0
dst[15:0] := (a[127:0] >> (imm8[2:0] * 16))[15:0]
dst[31:16] := 0
2)_mm_inset_epi16
#在imm8指定的位置将16位整数i插入a,结果赋值给dst
dst[127:0] := a[127:0]
sel := imm8[2:0]*16
dst[sel+15:sel] := i[15:0]
3)mm_shuffle( /hi/lo)(pd/epi16/epi32)
#重点,洗牌指令
#根据imm8中的值对a进行洗牌,结果赋值给dst
#hi/lo
hi:仅对高位洗牌,低位不变
lo:仅对低位洗牌,高位不变
#pd/epi16/epi32
pd:洗牌时,每64bit一组
epi16: 洗牌时,每16bit一组
epi32洗牌时,每32bit一组
4)mm_unpack(hi/lo)(pd/epi(8/16/32/64))
#交替存储a、b各组的数据
#hi/lo
hi:仅使用a、b的高位进行交替存储
lo:仅使用a、b的低位进行交替存储
#pd/epi
pd:输入、输出的数据类型为__m128d
epi: 输入、输出的数据类型为__m128i
#epi(8/16/32/64)
epi8 :每8 bit一组,进行交替存储
epi16:每16bit一组,进行交替存储
epi32:每32bit一组,进行交替存储
epi64:每64bit一组,进行交替存储
//16、Trigonometry