MMX指令集共47个指令,分为以下几类:
• Data transfer
• Arithmetic
• Comparison
• Conversion
• Unpacking
• Logical
• Shift
• Empty MMX state instruction (EMMS)
1. Data Transfer(数据转移)
从内存到MMX寄存器/ 从MMX寄存器到内存/ 从通用寄存器到MMX寄存器/ 从MMX寄存器到通用寄存器
- MOVD 指令(32位)——4个
指令 | 函数 | 指令描述 |
---|---|---|
movd | __m64 _mm_cvtsi32_si64(int a) __m64 _m_from_int(int a) | 变量a的32位拷贝到MMX寄存器的低32位,高32位置零 |
movd | int _mm_cvtsi64_si32 (__m64 a) int _m_to_int(__m64 a) | MMX变量的低32位拷贝到int类型中 |
根据 https://msdn.microsoft.com/zh-cn/8w48hs3e(v=vs.80) 所属 _mm_cvtsi32_si64 与 _m_from_int 应相同。(请指点)
+MOVQ指令(64位)——4个
指令 | 函数 | 指令描述 |
---|---|---|
movq | __int64 _mm_cvtm64_si64(__m64 a) __int64 _m_to_int64(__m64 a) | 拷贝64位整型a到结果 |
movq | __m64 _mm_cvtsi64_m64 (__int64 a) __m64 _m_from_int64(__int64 a) | 拷贝64位整型a到结果 |
2.Arithmetic(数值计算)
进行压缩整数的加减乘以及multiply/add计算。
加法(7个指令,14个函数):
指令 | 函数 | 指令描述 |
---|---|---|
paddw | __m64 _mm_add_pi16(__m64 a, __m64 b) __m64 _m_paddw(__m64 a, __m64 b) | Add packed word integers(16位) with wraparound 使用wraparound截断溢出方式进行压缩字整数的加运算 |
paddd | __m64 _mm_add_pi32(__m64 a, __m64 b) __m64 _m_paddd (__m64a, __m64 b) | Add packed doubleword integers(32位) with wraparound 使用wraparound截断溢出方式进行压缩双字整数的加运算 |
paddb | __m64 _mm_add_pi8(__m64 a, __m64 b) __m64 _m_paddb (__m64a, __m64 b) | Add packed byte integers(8位) with wraparound 使用wraparound截断溢出方式进行压缩字节整数的加运算 |
paddsw | __m64 _mm_adds_pi16(__m64 a, __m64 b) __m64 _m_paddsw(__m64 a, __m64 b) | Add packed word integers with signed saturation 压缩字整数的有符号饱和加运算 |
paddsb | __m64 _mm_adds_pi8(__m64 a, __m64 b) __m64 _m_paddsb(__m64 a, __m64 b) | Add packed byte integers with signed saturation 压缩字节整数的有符号饱和加运算 |
paddusw | __m64 _mm_adds_pu16(__m64 a, __m64 b) __m64 _m_paddusw(__m64 a, __m64 b) | Add packed word integers with unsigned saturation 压缩字整数的无符号饱和加运算 |
paddusb | __m64 _mm_adds_pu8(__m64 a, __m64 b) __m64 _m_paddusb(__m64 a, __m64 b) | Add packed byte integers with unsigned saturation 压缩字节整数的无符号饱和加运算 |
减法(7个指令,14个函数):
指令 | 函数 | 指令描述 |
---|---|---|
psubw | __m64 _mm_sub_pi16(__m64 a, __m64 b) __m64 _m_psubw(__m64 a, __m64 b) | sub packed word integers(16位) with wraparound 使用wraparound截断溢出方式进行压缩字整数的减运算 |
psubd | __m64 _mm_sub_pi32(__m64 a, __m64 b) __m64 _m_psubd (__m64a, __m64 b) | sub packed doubleword integers(32位) with wraparound 使用wraparound截断溢出方式进行压缩双字整数的减运算 |
psubb | __m64 _mm_sub_pi8(__m64 a, __m64 b) __m64 _m_psubb (__m64a, __m64 b) | sub packed byte integers(8位) with wraparound 使用wraparound截断溢出方式进行压缩字节整数的减运算 |
psubsw | __m64 _mm_subs_pi16(__m64 a, __m64 b) __m64 _m_psubsw(__m64 a, __m64 b) | sub packed word integers with signed saturation 压缩字整数的有符号饱和减运算 |
psubsb | __m64 _mm_subs_pi8(__m64 a, __m64 b) __m64 _m_psubsb(__m64 a, __m64 b) | sub packed byte integers with signed saturation 压缩字节整数的有符号饱和减运算 |
psubusw | __m64 _mm_subs_pu16(__m64 a, __m64 b) __m64 _m_psubusw(__m64 a, __m64 b) | sub packed word integers with unsigned saturation 压缩字整数的无符号饱和减运算 |
psubusb | __m64 _mm_subs_pu8(__m64 a, __m64 b) __m64 _m_psubusb(__m64 a, __m64 b) | sub packed byte integers with unsigned saturation 压缩字节整数的无符号饱和减运算 |
乘法(2个指令,4个函数)
指令 | 函数 | 指令描述 |
---|---|---|
pmulhw | __m64 _mulhi_pi16(__m64 a, __m64 b) __m64 _m_pmulhw (__m64 a,__m64 b) | 压缩16位字整数a和b相乘会产生32位双字整数,将32位整数的高16位存储在结果中 |
pmullw | __m64_mullo_pi16(__m64 a, __m64 b) __m64 _m_pmullw(__m64 a,__m64 b) | 压缩16位字整数a和b相乘会产生32位双字整数,将32位整数的低16位存储在结果中 |
具体的执行方式请参考下图,若使用pmulhw则乘法结果中的高16位存储在C中,若使用pmullw则乘法结果中的低16位存储在C中。
multiply/add(乘法加和,1个指令,2个函数)
指令 | 函数 | 指令描述 |
---|---|---|
pmaddwd | __m64 _madd_pi16(__m64 a, __m64 b) __m64 _m_pmaddwd (__m64 a,__m64 b) | 压缩16位字整数a和b相乘会产生32位双字整数,a和b中后2个8位的相乘结果的和保存在结果的低32位,前2个16位相乘结果的和保存在结果的高32位中 |
具体的执行情况参考下图:
3. Comparision(比较操作)
指令 | 函数 | 指令描述 |
---|---|---|
pcmpeqb | __m64 _mm_cmpeq_pi8 (__m64 a, __m64 b) __m64 _m_pcmpeqb (__m64 a, __m64 b) | 比较a和b里的8位字节整数值进行比较,判断它们是否相等,相等返回OxFFFF,否则返回0 |
pcmpeqw | __m64 _mm_cmpeq_pi16 (__m64 a, __m64 b) __m64 _m_pcmpeqw (__m64 a, __m64 b) | 比较a和b里的16位字整数值进行比较,判断它们是否相等,相等返回OxFFFF,否则返回0 |
pcmpeqd | __m64 _mm_cmpeq_pi32 (__m64 a, __m64 b) __m64 _m_pcmpeqd (__m64 a, __m64 b) | 比较a和b里的32位双字整数值进行比较,判断它们是否相等,相等返回OxFFFF,否则返回0 |
pcmpgtb | __m64 _mm_cmpgt_pi8 (__m64 a, __m64 b) __m64 _m_pcmpgtb (__m64 a, __m64 b) | 比较a和b里的8位字节整数值,如果a中>b中,放回OxFFFF,否则返回0 |
pcmpgtw | __m64 _mm_cmpgt_pi16 (__m64 a, __m64 b) __m64 _m_pcmpgtw (__m64 a, __m64 b) | 比较a和b里的16位字整数值,如果a中>b中,放回OxFFFF,否则返回0 |
pcmpgtd | __m64 _mm_cmpgt_pi32 (__m64 a, __m64 b) __m64 _m_pcmpgtd (__m64 a, __m64 b) | 比较a和b里的32位双字整数值,如果a中>b中,放回OxFFFF,否则返回0 |
4. Conversion(打包指令)
指令 | 函数 | 指令描述 |
---|---|---|
packsswb | __m64 _mm_packs_pi16 (__m64 a, __m64 b) __m64 _m_packsswb (__m64 a, __m64 b) | 将压缩16位字整数a和bpack成8位字节整数使用有符号饱和运算,保存到结果中 |
packssdw | __m64 _mm_packs_pi32 (__m64 a, __m64 b) __m64 _m_packssdw (__m64 a, __m64 b) | 将压缩32位双字整数a和b pack成16位字整数使用有符号饱和运算,保存到结果中 |
packuswb | __m64 _mm_packs_pu16 (__m64 a, __m64 b) __m64 _m_packuswb (__m64 a, __m64 b) | 将压缩16位字整数a和b pack成8位字节整数使用无符号饱和运算,保存到结果中 |
packsswb:
dst[7:0] := Saturate_Int16_To_Int8 (a[15:0])
dst[15:8] := Saturate_Int16_To_Int8 (a[31:16])
dst[23:16] := Saturate_Int16_To_Int8 (a[47:32])
dst[31:24] := Saturate_Int16_To_Int8 (a[63:48])
dst[39:32] := Saturate_Int16_To_Int8 (b[15:0])
dst[47:40] := Saturate_Int16_To_Int8 (b[31:16])
dst[55:48] := Saturate_Int16_To_Int8 (b[47:32])
dst[63:56] := Saturate_Int16_To_Int8 (b[63:48])
packssdw:
dst[15:0] := Saturate_Int32_To_Int16 (a[31:0])
dst[31:16] := Saturate_Int32_To_Int16 (a[63:32])
dst[47:32] := Saturate_Int32_To_Int16 (b[31:0])
dst[63:48] := Saturate_Int32_To_Int16 (b[63:32])
packuswb:
dst[7:0] := Saturate_Int16_To_UnsignedInt8 (a[15:0])
dst[15:8] := Saturate_Int16_To_UnsignedInt8 (a[31:16])
dst[23:16] := Saturate_Int16_To_UnsignedInt8 (a[47:32])
dst[31:24] := Saturate_Int16_To_UnsignedInt8 (a[63:48])
dst[39:32] := Saturate_Int16_To_UnsignedInt8 (b[15:0])
dst[47:40] := Saturate_Int16_To_UnsignedInt8 (b[31:16])
dst[55:48] := Saturate_Int16_To_UnsignedInt8 (b[47:32])
dst[63:56] := Saturate_Int16_To_UnsignedInt8 (b[63:48])
5.Unpack(解包指令)
指令 | 函数 | 指令描述 |
---|---|---|
punpckhbw | __m64 _m_punpckhbw (__m64 a, __m64 b) __m64 _mm_unpackhi_pi8 (__m64 a, __m64 b) | 64位a和b数据的高一半位数数据(32位)保存到结果中,具体保存方式参考如下描述 |
punpckhwd | ||
punpckhdq | ||
punpcklbw | ||
punpcklwd | ||
punpckldq |
packsswb:
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])
6. Logical(逻辑运算)
指令 | 函数 | 指令描述 |
---|---|---|
pand | ||
pandn | ||
por | ||
pxor |
7. Shift(移位)
指令 | 函数 | 指令描述 |
---|---|---|
psllw | ||
pslld | ||
psllq | ||
psrlw | ||
psrld | ||
psrlq | ||
psraw | ||
psrad |
8. EMMS
指令 | 函数 | 指令描述 |
---|---|---|
emms | void _m_empty (void)void _mm_empty (void) | 使用 EMMS 命令与空容器以容纳新目录 |
EMMS使用方法:
1. 如果下一条命令是浮点命令,请在MMX指令后使用_mm_empty(例如在进行float,double和long double 类型的计算前)
2. 当寄存器中不存在MMX寄存时,不要使用EMMS指令。如果下一个命令使用MMX寄存器,使用EMMS没有好处(不会进行优化)
3.