SIMD
Table of Contents
- 1. 指令集
- 2. 基本概念
- 3. 指令
- 3.1. Data Transfer Instructions
- 3.2. Arithmetic Instructions
- 3.3. Comparison Instructions
- 3.4. Conversion Instructions
- 3.5. Insert & Unpack Instructions
- 3.6. Logical Instructions
- 3.7. Shift Instructions
- 3.8. Shuffle Instructions
- 3.9. Blending Instructions
- 3.10. String Instructions
- 3.11. MISC Instructions
从Pentium II和Pentium MMX处理器系列开始,芯片开始支持SIMD操作. SIMD全称是Single Instruction Multiple Data,即单指令多数据, 可以在一个周期内操作多个数据.
1 指令集
1.1 MMX
- Multimedia Extensions.[PII & PMMX]
- (CPUID.01H:EDX.MMX[bit 23]=1)
1.2 SSE.
- Streaming SIMD Extensions.[PIII]
- (CPUID.01H:EDX.SSE[bit 25]=1)
1.3 SSE2
- Streaming SIMD Extensions2.[P4 & Xeon]
- (CPUID.01H:EDX.SSE2[bit 26]=1)
1.4 SSE3
- Streaming SIMD Extensions3.[P4(HT)]
- (CPUID.01H:ECX.SSE3[bit 0]=1)
1.5 SSSE3
- Supplemental Stream SIMD Extensions3.[Xeon(5100) & Core2]
- (CPUID.01H:ECX.SSSE3[bit 9]=1)
1.6 SSE4
- Streaming SIMD Extensions4.[Xeon(5400) & Core2Ex(QX9650)]
- SSE4.1.(CPUID.01H:ECX.SSE4_1[bit 19]=1)
- SSE4.2.(CPUID.01H:ECX.SSE4_2[bit 20]=1)
1.7 检测代码
/*************************************************************************** * * Copyright (c) Baidu.com, Inc. All Rights Reserved * **************************************************************************/ /** * @file detect.c * @author zhangyan04(@baidu.com) * @brief * */ #include <stdio.h> int check_support_mmx(){ int res=0; __asm__ __volatile__( "movl $1,%%eax\n\t" "cpuid\n\t" "test $0x800000,%%edx\n\t" "jz 1f\n\t" "movl $1,%0\n\t" "1:\n\t" :"=m"(res) ::"eax","edx"); return res; } int check_support_sse(){ int res=0; __asm__ __volatile__( "movl $1,%%eax\n\t" "cpuid\n\t" "test $0x02000000,%%edx\n\t" "jz 1f\n\t" "movl $1,%0\n\t" "1:\n\t" :"=m"(res) ::"eax","edx"); return res; } int check_support_sse2(){ int res=0; __asm__ __volatile__( "movl $1,%%eax\n\t" "cpuid\n\t" "test $0x04000000,%%edx\n\t" "jz 1f\n\t" "movl $1,%0\n\t" "1:\n\t" :"=m"(res) ::"eax","edx"); return res; } int check_support_sse3(){ int res=0; __asm__ __volatile__( "movl $1,%%eax\n\t" "cpuid\n\t" "test $0x1,%%ecx\n\t" "jz 1f\n\t" "movl $1,%0\n\t" "1:\n\t" :"=m"(res) ::"eax","edx"); return res; } int check_support_ssse3(){ int res=0; __asm__ __volatile__( "movl $1,%%eax\n\t" "cpuid\n\t" "test $0x0200,%%ecx\n\t" "jz 1f\n\t" "movl $1,%0\n\t" "1:\n\t" :"=m"(res) ::"eax","edx"); return res; } int check_support_sse4_1(){ int res=0; __asm__ __volatile__( "movl $1,%%eax\n\t" "cpuid\n\t" "test $0x80000,%%ecx\n\t" "jz 1f\n\t" "movl $1,%0\n\t" "1:\n\t" :"=m"(res) ::"eax","edx"); return res; } int check_support_sse4_2(){ int res=0; __asm__ __volatile__( "movl $1,%%eax\n\t" "cpuid\n\t" "test $0x0100000,%%ecx\n\t" "jz 1f\n\t" "movl $1,%0\n\t" "1:\n\t" :"=m"(res) ::"eax","edx"); return res; } int main(){ printf("MMX[%s]\n",check_support_mmx()?"OK":"FAILED"); printf("SSE[%s]\n",check_support_sse()?"OK":"FAILED"); printf("SSE2[%s]\n",check_support_sse2()?"OK":"FAILED"); printf("SSE3[%s]\n",check_support_sse3()?"OK":"FAILED"); printf("SSSE3[%s]\n",check_support_ssse3()?"OK":"FAILED"); printf("SSE4.1[%s]\n",check_support_sse4_1()?"OK":"FAILED"); printf("SSE4.2[%s]\n",check_support_sse4_2()?"OK":"FAILED"); return 0; }
2 基本概念
2.1 %mm寄存器
%mm寄存器是64bit,共有8个%mm寄存器.需要注意的是,%mm0-%mm7是X87 FPU寄存器的alias, 分别对应%r0-%r7.所以对%mm0-%mm7的操作会覆盖X87 FPU的内容.使用%mm寄存器的时候, 效果是这样的.
- TOS(Top Of Stack)会被置为0,也就是FPU registers的顶部会置0.
- 整个FPU tag word会被置为valid(0x0).如果后续想使用的话,需要使用EMMS指令.
- FPU register有80位,但是%mm寄存器只是用了64位,因此其余位填充(0xff).
因此如果在使用%mm寄存器之后,想使用FPU指令的话,那么应该
- fsave/fxsave保存FPU状态.
- 执行EMMS指令.
- 可选地使用frstore/fxstore载入之前FPU状态.
- 执行FPU指令.
如果使用FPU指令之后,想切换回%mm寄存器的话.
- fsave/fxsave保存FPU状态.
- 可选地使用frstore/fxrstore载入之前FPU状态.
- 操作%mm寄存器.
EMMS指令会清除MMX的状态,将FPU tag word进行清空,表示所有的FPU registers都已经清空. 我们必须在执行完成MMX指令之后,如果之后需要使用FPU registers的话,那么需要执行这个指令.
2.2 %xmm寄存器
%xmm寄存器是128bit. Intel64架构下允许访问16个%xmm寄存器. IA-32架构下只允许访问8个%xmm寄存器.
2.3 %mxcsr寄存器
%mxcsr是32bit.%mxcsr寄存器是在SSE指令集引入的,用来控制作用在%xmm寄存器操作的行为, 所有的这些行为都是和浮点相关的,在某种程度上非常类似于X87 FPU tag word. 关于%mxcsr寄存器各个位所表示的意思在这里不细说,可以查看Intel手册得到详细解释. 可以查看Intel Vol.1 10.2.3.%mxcrs默认值是0x1f80.
| 指令 | 说明 |
|---|---|
| LDMXCSR | mem->%mxcsr.32bit |
| STMXCSR | %mxcsr->mem.32bit |
2.4 Saturation & Wraparound
在进行整数运算的时候,可能会存在out-of-range的情况,结果不能够被目标数所表示.对于 这种溢出处理有下面3种方式.
- Wraparound Arithmetic.
回绕模式.比如8个字节表示257的话,那么就是257-256=1.
- Signed Saturation Arithmetic.
符号位溢出模式.比如8个字节表示257的话,那么会是0x7f=127.
- Unsigned Saturation Arithmetic.
无符号溢出模式.比如8个字节表示257的话,那么会是0xff=255.
对于溢出模式对于一些计算是非常重要的.假设256色的像素如果两个像素相叠加的话, 当然不希望像素值发生回绕.如果溢出的话,通常这个像素保持纯黑或者是纯白.
2.5 General Purpose Register(GPR)
通用寄存器,包括EAX/RAX,EBX/RBX,ECX/RCX等.这些通用寄存器和%mm和%xmm之间的差别是, %mm和%xmm不能够用来存放地址,也就是说不能够将内存地址存放在%mm和%xmm里面然后进行引用.
2.6 X87 FPU
X87 FPU是浮点运算部件,共有8个寄存器,组织方式是堆栈.通常来说对于SIMD并不需要关心 X87 FPU这个部件.但是因为SIMD使用的%mm寄存器是FPU寄存器的alias,所以我们这里需要了解. 后面我们把X87 FPU都称为FPU.
对于FPU会有一个状态,状态包括执行环境和寄存器内容.每个寄存器80bit.在操作%mm寄存器 和执行FPU指令切换之间,我们可能需要保存状态.那么下面就是关于FPU操作状态的指令.
| 指令 | 说明 |
|---|---|
| FSAVE | 保存FPU状态,然后重新初始化FPU.84/108字节 |
| FRSTORE | FSAVE逆操作. |
| FXSAVE | 保存FPU状态/%mm寄存器,%xmm寄存器,%mxscr寄存器.512字节. |
| FXRSTORE | FXSAVE逆操作. |
关于如何协调%mm寄存器和FPU寄存器的使用,在%mm寄存器这节有解释.
2.7 Packed & Scalar Instructions
对于SIMD提供了操作packed和scalar指令.我们假设存在两个操作数, 假设是(f00,f01,f02,f03)和(f10,f11,f12,f13)的话,那么
- 如果是packed操作的话,那么操作是(f00 op f01,f01 op f11,f02 op f12,f03 op f13).
- 如果是scalar操作的话,那么操作是(f00,f01,f03,f03 op f13).
也就是说,如果在scalar操作的话,仅仅是操作最后面一个单元,其他单元全部复制.
需要注意的是,在Scalar操作下面
- 单精度浮点是24-bit significand + 8-bit exponent.
- 双精度浮点是53-bit significand + 11-bit exponent.
而在IEEE-754和FPU操作环境下面的的话
- 单精度浮点是24-bit significand + 15-bit exponent.
- 双精度浮点是52-bit significand + 15-bit exponent.
此外SIMD操作浮点数和FPU操作浮点数有些不同,SIMD是直接操作浮点数的Native Format, 而FPU是首先在更高的精度上面操作,然后取舍到Native Format.
2.8 Temporal & NonTemporal Data
待续.需要阅读Intel Vol.3A Memory & Cache Control这节.在Intel Vol.1 10.4.6.2也有介绍.
2.9 Alignment
关于对齐方面,如果使用128bit Memory Operand必须进行16字节的对齐.但是有些例外
- 使用UnAlign的Data Transfer操作,比如MOVUPS/MOVUPD.
- 如果是Scalar Memory Float的话,必须是4字节对齐.
- 如果是Scalar Memory Double的话,必须是8字节对齐.
- 此外还有部分指令字节对齐存在例外,会在响应的指令部分说明.
2.10 Asymmetric & Horizontal Processing
分别是对称处理和水平处理.假设存在操作数(a0,a1,a2,a3)以及(b0,b1,b2,b3). 对于大部分SIMD指令处理都是对称处理,也就是(a0 op b0,a1 op b1,a2 op b2,a3 op b3). 相邻处理就是(a0 op a1,a2 op a3,b0 op b1,b2 op b3).
2.11 Zero Fill & Truncated
对于从内存/寄存器载入到寄存器的话,如果位数不够,通常是占用寄存器的低字节, 除非显式指定.对于寄存器中没有使用的高字节,通常是采用0填充,也就是Zero Fill.:).
而另外一个方面,如果从寄存器传输到内存/寄存器,如果寄存器位数过多的话,那么也 通常只是传输寄存器的低字节,而保留寄存器的高字节,也就是Truncated.:).
3 指令
为了方便表示,我们定义下面缩写和操作.
| 助记符 | 含义 | 其他 |
|---|---|---|
| A | Aligned | |
| U | UnAligned | |
| L | Low | |
| H | High/Horizontal | |
| B | Byte | |
| SB | Signed Byte | |
| UB | Unsigned Byte | |
| W | Word | |
| SW | Signed Word | |
| UW | Unsigned Word | |
| Q | Quad Word | |
| DQ | Double Quad Word | |
| F | Float | |
| D | Double | |
| PS | Packed Single Precision Floating Point | |
| SS | Scalar Single Precision Floating Point | |
| PD | Packed Double Precision Floating Point | |
| SD | Scalar Double Precision Floating Point | |
| CMP | Compare | |
| STR | String | |
| EQ | Equal | |
| GT | Greater | |
| SLL | Shift Left Logical | |
| SRL | Shift Right Logical | |
| SRA | Shift Right Arithmetic | |
| DUP | Duplicate | |
| WAM | Wraparound Mode | |
| SSM | Signed Saturation Mode | |
| USM | Unsigned Saturation Mode | |
| RCP | Reciprocal.RCP(x)=1/x | |
| SQRT | Square Root | |
| RSQRT | Reciprocal Square Root | |
| MSK | Mask | |
| CVT | Convert | |
| SX | Signed Extend | |
| ZX | Zero Extend | |
| ROUND | ||
| UNPCK | Unpack | |
| EXTR | Extract | |
| INSR | Insert | |
| AND | a && b | |
| OR | a or b | |
| NAND | !(a && b) | |
| XOR | a ^ b | |
| SAD | Sum of Absolute Difference. | |
| SIGN | SIGN(src,dst)=if(src<0):dst=-dst | |
| MADD | MADD((a00,a01),(b00,b01))=(a00*b00)+(a01*b01) | |
| ALIGNR | ALIGNR(src,dst,imm)=(src,dst) >> imm | |
| AVG | Average | |
| ABS | Absolute | |
| NT | NonTemporal | |
| CVTT | Convert With Truncate | |
| UNPCKH | UNPCKH((s00,s01),(d00,d01))=(d01,s01) | |
| UNPCKL | UNPCKL((s00,s01),(d00,d01))=(d00,s00) | |
| MSB | Most Significant Bit | |
| LF | Lowest Float | |
| LF2 | Lower 2 Floats | |
| LF4 | Lower 4 Floats | |
| HF | Highest Float | |
| HF2 | Higher 2 Floats | |
| LD | Lowest Double | |
| HD | Highest Double | |
| LDW | Lower Double Word | |
| LDW2 | Lower 2 Double Words | |
| LDW4 | Lower 4 Double Words | |
| LW | Lower Word | |
| HW | Higher Wword | |
| GPR | General Purpose Resgister |
这里有几点需要注意的
- 对于Move如果使用了错误类型指令的话,会产生性能消耗.Vol.1 11.6.9
- 对于使用SIMD来说,推荐使用caller-save.Vol.1 11.6.10.3
3.1 Data Transfer Instructions
3.1.1 Move Mask Instructions
对于每一个data element的MSB移到GRP.这些指令通常用于分支判定.
| 指令 | 说明 |
|---|---|
| PMOVMSKB | |
| MOVMSKPS | |
| MOVMSKPD |
3.1.2 Move Integer Instructions
| 指令 | 说明 |
|---|---|
| MOVD | |
| MOVQ | |
| MOVDQA | |
| MOVDQU | |
| LDDQU | 功能和MOVDQU相同 |
关于LDDQU和MOVDQU的差别,可以参看Intel关于LDDQU指令描述,主要还是在某些场景 下面的性能差别,功能上没有任何区别.
3.1.3 Move Float Instructions
| 指令 | 说明 |
|---|---|
| MOVAPS | |
| MOVUPS | |
| MOVSS | |
| MOVLPS | 2PS<->LF2(%xmm) |
| MOVHPS | 2PS<->HF2(%xmm) |
| MOVLHPS | LF2(%xmm1)->HF2(%xmm2) |
| MOVHLPS | HF2(%xmm1)->LF2(%xmm1) |
3.1.4 Move Double Instructions
| 指令 | 说明 |
|---|---|
| MOVAPD | |
| MOVUPD | |
| MOVSD | |
| MOVLPD | PD<->LD(%xmm) |
| MOVHPD | PD<->HD(%xmm) |
3.1.5 Move Duplication Instructions
| 指令 | 说明 |
|---|---|
| MOVDDUP | (d0,d1)->(d0,d0) |
| MOVSHDUP | (f0,f1,f2,f3)->(f1,f1,f3,f3) |
| MOVSLDUP | (f0,f1,f2,f3)->(f0,f0,f2,f2) |
3.1.6 Move NonTemporal Instructions
| 指令 | 说明 |
|---|---|
| MOVNTI | |
| MOVNTQ | |
| MOVNTDQ | |
| MOVNTDQA | |
| MOVNTPS | |
| MOVNTPD | |
| MASKMOVQ | @@TODO |
| MASKMOVDQU | @@TODO |
3.2 Arithmetic Instructions
3.2.1 ADD Instructions
3.2.2 SUB Instructions
3.2.3 MUL Instructions
| 指令 | 说明 |
|---|---|
| PMULLW | (w00,w01,..),(w10,w11,..)->(LW(w00*w10),LW(w01*w11),..) |
| PMULHW | (w00,w01,..),(w10,w11,..)->(HW(w00*w10),HW(w01*w11),..) |
| PMULHUW | 同上,Unsigned方式. |
| PMULLD | (dw00,dw01,..),(dw10,dw11,..)->(LDW(dw00*dw10),LDW(dw01*dw11),..) |
| PMULDQ | (dw00,dw01,..),(dw10,dw11,..)->(dw00*dw10,dw01*dw11,..) |
| PMULUDQ | 同上,Unsigned方式. |
| MULPS | |
| MULSS | |
| MULPD | |
| MULSD |
3.2.4 DIV Instructions
| 指令 | 说明 |
|---|---|
| DIVPS | |
| DIVSS | |
| DIVPD | |
| DIVSD |
3.2.5 M?X Instructions
3.2.6 Math Instructions
| 指令 | 说明 |
|---|---|
| PABSB | |
| PABSW | |
| PABSD | |
| PAVGB | |
| PAVGW | |
| PSIGNB | |
| PSIGNW | |
| PSIGND | |
| PMADDUBSW | UB->W.SSM |
| PMADDWD | W->DW |
| PALIGNR | |
| PMULHRSW | @@TODO |
| PSADBW | |
| MPSADBW | @@TODO |
| DPPS | |
| DPPD | |
| ADDSUBPS | (f00,f01,..),(f10,f11,..)->(f00-f10,f01+f11,..) |
| ADDSUBPD | (d00,d01,..),(d10,d11,..)->(d00-d10,d01+d11,..) |
| RCPPS | |
| RCPSS | |
| RSQRTPS | |
| RSQRTSS | |
| SQRTPS | |
| SQRTSS | |
| SQRTSD |
3.3 Comparison Instructions
需要注意的是,如果没有特殊说明,比较结果是直接存放在结果数里面的, 不会影响EFLAGS这个寄存器内容.如果比较结果影响了EFLAGS寄存器的话, 那么会使用%EFLAGS来标记.
如果每个比较结果是符合预期的话, 那么目的数对应位数会置0xff,否则会置0x0.
对于CMP的指令,会使用立即数来决定具体使用什么比较方式.关于立即数对应 什么比较方式,可以查看具体指令里面的说明,比如CMPPS,CMPSS,CMPPD,CMPSD.
| 指令 | 说明 |
|---|---|
| PCMPEQB | |
| PCMPEQW | |
| PCMPEQD | |
| PCMPEQQ | |
| PCMPGTB | |
| PCMPGTW | |
| PCMPGTD | |
| PCMPGTQ | |
| CMPPS | |
| CMPSS | |
| CMPPD | |
| CMPSD | |
| COMISS | %EFLAGS |
| UCOMISS | %EFLAGS |
| COMISD | %EFLAGS |
| UCOMISD | %EFLAGS |
| PTEST |
3.4 Conversion Instructions
对于涉及到浮点数的精度取舍问题,使用%mxccsr寄存器来判断.
如果精度取舍是采用截断方式来进行处理的话,那么指令前缀通常是CVTT.
| 指令 | 说明 |
|---|---|
| PACKSSWB | SSM |
| PACKSSDW | SSM |
| PACKUSDW | USM |
| 指令 | 说明 |
|---|---|
| CVTPS2PD | |
| CVTPD2PS | |
| CVTSS2SD | |
| CVTSD2SS | |
| CVTPI2PS | |
| CVTPS2PI | |
| CVTTPS2PI | |
| CVTSI2SS | |
| CVTSS2SI | |
| CVTTSS2SI | |
| CVTPI2PD | |
| CVTPD2PI | |
| CVTTPD2PI | |
| CVTSI2SD | |
| CVTSD2SI | |
| CVTTSD2SI | |
| CVTDQ2PS | |
| CVTPS2DQ | |
| CVTTPS2DQ | |
| CVTDQ2PD | |
| CVTPD2DQ | |
| CVTTPD2DQ |
| 指令 | 说明 |
|---|---|
| MOVQ2DQ | |
| MOVDQ2Q | |
| PMOVSXBW | |
| PMOVZXBW | |
| PMOVSXBD | |
| PMOVZXBD | |
| PMOVSXWD | |
| PMOVZXWD | |
| PMOVSXBQ | |
| PMOVZXBQ | |
| PMOVSXWQ | |
| PMOVZXWQ | |
| PMOVSXDQ | |
| PMOVZXDQ |
| 指令 | 说明 |
|---|---|
| ROUNDPS | |
| ROUNDPD | |
| ROUNDSS | |
| ROUNDSD |
3.5 Insert & Unpack Instructions
| 指令 | 说明 |
|---|---|
| PUNPCKHBW | |
| PUNPCKHWD | |
| PUNPCKHDQ | |
| PUNPCKHQDQ | |
| PUNPCKLBW | |
| PUNPCKLWD | |
| PUNPCKLDQ | |
| PUNPCKLQDQ | |
| UNPCKHPS | |
| UNPCKLPS | |
| UNPCKHPD | |
| UNPCKLPD |
| 指令 | 说明 |
|---|---|
| PEXTRB | |
| PEXTRW | |
| PEXTRD | |
| PEXTRQ | |
| PINSRB | |
| PINSRW | |
| PINSRD | |
| PINSRQ | |
| EXTRACTPS | ->GPR |
| INSERTPS |
3.6 Logical Instructions
| 指令 | 说明 |
|---|---|
| PAND | |
| PANDN | |
| POR | |
| PXOR | |
| ANDPS | |
| ANDNPS | |
| ORPS | |
| XORPS | |
| ANDPD | |
| ANDNPD | |
| ORPD | |
| XORPD |
3.7 Shift Instructions
| 指令 | 说明 |
|---|---|
| PSLLW | |
| PSLLD | |
| PSLLQ | |
| PSLLDQ | |
| PSRLW | |
| PSRLD | |
| PSRLQ | |
| PSRLDQ | |
| PSRAW | |
| PSRAD |
3.8 Shuffle Instructions
SHUF操作根据imm来决定,dst每个位置的element应该是由 src的哪个位置的element来进行填充的.
| 指令 | 说明 |
|---|---|
| PSHUFB | |
| PSHUFW | |
| PSHUFLW | |
| PSHUFHW | |
| PSHUFD | |
| SHUFPS | |
| SHUFPD |
3.9 Blending Instructions
BLEND操作是根据imm来决定,dst每个位置的element应该是从src里面对应位置取出, 还是应该从dst里面对应位置取出.
BLENDV操作和BLEND操作过程一样的,不同的是由%xmm0来决定的而不是由imm来决定.
| 指令 | 说明 |
|---|---|
| BLENDPS | |
| BLENDPD | |
| BLENDVPS | |
| BLENDVPD | |
| PBLENDVB | |
| PBLENDW |
3.10 String Instructions
- 内存操作数不要求字节对齐.
- CMPE/I的E表示explicit显式指定长度,I表示implicit隐式指定长度.
- STRI/STRM的I表示结果是Index,M表示结果是Mask.
| 指令 | 说明 |
|---|---|
| PCMPESTRI | |
| PCMPESTRM | |
| PCMPISTRI | |
| PCMPISTRM |
3.11 MISC Instructions
3.11.1 Cache Control Instructions
- CLFLUSH
CLFLUSH是cache line flush,能够将某个内存地址的cache line全部失效.
3.11.2 Prefetch Instructions
对于预取指令的话不会影响程序行为,通常来说会预取32个对齐的字节,但是具体 还是依赖于实现.对于NT数据的话,依然会尽可能地减少Cache的污染.
- PREFETCH0
预取到所有Cache层次.
- PREFETCH1
预取到1级缓存.
- PREFETCH2
预取到2级缓存.
- PREFETCHNTA
???
3.11.3 Memory Ordering Instructions
- SFENCE
在SFENCE之前的Store操作,从全局视图来看,一定在SFENCE之后的Store操作之前完成.
- LFENCE
在LFENCE之前的Load操作,从全局视图来看,一定在LFENCE之后的Load操作之前完成.
- MFENCE
MFENCE结合了SFENCE和LFENCE两个功能.
3.11.4 X87 FPU Instructions
- FISTTP
这条指令非常类似FISTP,是将FPU TOS的浮点数转换成为整数,精度处理使用截断. FISTP需要修改FPU Tag Word设置为截断处理才会有这样的效果,
3.11.5 Thread Sync Instructions
需要注意的是,这些指令都只能够在ring0级别下面运行,对于<ring0的界别是可选运行的.
- MONITOR
设置一块地址区域来监视是否存在write-back-stores的操作.
- MWAIT
等待某块地址区域发生write-back-stores.这块地址区域必须经过MONITOR设置.在等待 这块地址区域写入的时候Logical Processor能够进入optimized state.
3.11.6 其他
- PAUSE
PAUSE指令能够显著改善自旋锁的循环等待期间的性能,同时减少机器的耗能.
- Branch Hints
对于Jcc这样的指令,允许在之前加上2EH,3EH作为Prefix能够进行预取提示. 这个没有特别的助记符,只是在生成的机器代码二进制上略有不同.
- CRC32
CRC32算法的有效实现.
- POPCNT
计算操作数的bit表示中存在多少个1.