SSE

SSE（Streaming SIMD Extensions）是英特尔在AMD的3D Now!发布一年之后，在其计算机芯片Pentium III中引入的指令集，是继MMX的扩充指令集。SSE指令集提供了70条新指令。AMD后来在Athlon XP中加入了对这个新指令集的支持。

## SSE的暂存器

<image>

SSE加入新的8个128位元暂存器（XMM0～XMM7）。而AMD发表的x86-64延伸架构（又称AMD64）再加入额外8个暂存器。除此之外还有一个新的32位元的控制／状态暂存器（MXCSR）。不过只能在64位元的模式下才能使用额外8个暂存器。

每个暂存器可以容纳4个32位元单精度浮点数，或是2个64位元双精度浮点数，或是4个32位元整数，或是8个16位元短整数，或是16个字元。整数运算能够使用正负号运算。而整数SIMD运算可能仍然要与8个64位元MMX暂存器一起执行。

因为操作系统必须要在进程切换的时候保护这些128位元的暂存器状态，除非操作系统去启动这些暂存器，否则预设值是不会去启用的。这表示操作系统必须要知道如何使用FXSAVE与FXRSTOR指令才能储存x87与SSE暂存器的状态。而在当时IA-32的主流操作系统很快的都加入了此功能。

由于SSE加入了浮点支持，SSE就比MMX更加常用。而SSE2加入了整数运算支援之后让SSE更加的有弹性，当MMX变成是多余的指令集，SSE指令集甚至可以与MMX并行运作，在某些时候可以提供额外的性能增进。

第一个支援SSE的CPU是Pentium III，在FPU与SSE之间共用执行支援。当编译出来的软件能够交叉的同时以FPU与SSE运作，Pentium III并无法在同一个周期中同时执行FPU与SSE。这个限制降低了指令管线的有效性，不过XMM暂存器能够让SIMD与纯量浮点运算混合执行，而不会因为切换MMX／浮点模式而产生性能的折损。

## SSE指令表

SSE提供纯量与包裹式（packed）浮点指令。

### 浮点指令

- 内存到暂存器／暂存器到内存／暂存器之间的资料搬移
- 纯量– MOVSS
- 包裹式– MOVAPS, MOVUPS, MOVLPS, MOVHPS, MOVLHPS, MOVHLPS
- 数学运算
- 纯量– ADDSS, SUBSS, MULSS, DIVSS, RCPSS, SQRTSS, MAXSS, MINSS, RSQRTSS
- 包裹式– ADDPS, SUBPS, MULPS, DIVPS, RCPPS, SQRTPS, MAXPS, MINPS, RSQRTPS
- 比较
- 纯量– CMPSS, COMISS, UCOMISS
- 包裹式– CMPPS
- 资料拆包（unpack）与随机搬移（shuffle）
- 包裹式– SHUFPS, UNPCKHPS, UNPCKLPS
- 资料型态转换
- 纯量– CVTSI2SS, CVTSS2SI, CVTTSS2SI
- 包裹式– CVTPI2PS, CVTPS2PI, CVTTPS2PI
- 逐位逻辑运算
- 包裹式– ANDPS, ORPS, XORPS, ANDNPS

### 整数指令

- 数学运算
- PMULHUW, PSADBW, PAVGB, PAVGW, PMAXUB, PMINUB, PMAXSW, PMINSW
- 资料搬移
- PEXTRW, PINSRW
- 其他
- PMOVMSKB, PSHUFW

### 其他指令

- MXCSR管理
- LDMXCSR, STMXCSR
- 快取与内存管理
- MOVNTQ, MOVNTPS, MASKMOVQ, PREFETCH0, PREFETCH1, PREFETCH2, PREFETCHNTA, SFENCE

## 例子

下面这个例子演示了使用SSE的优点。向量加法在计算机图形中很常用，如果在x86平台上想将四对单精度浮点数相加，必须使用四对浮点相加指令。

```
vec_res.x = v1.x + v2.x;
vec_res.y = v1.y + v2.y;
vec_res.z = v1.z + v2.z;
vec_res.w = v1.w + v2.w;
```

上面这段代码会被编译成4条x86 FADD指令。下面的伪代码展示用128位包裹式相加（packed-add）指令替代4个纯量相加指令。

```asm
 movaps xmm0, [v1]          ;xmm0 = v1.w | v1.z | v1.y | v1.x 
 addps xmm0, [v2]           ;xmm0 = v1.w+v2.w | v1.z+v2.z | v1.y+v2.y | v1.x+v2.x               
 movaps [vec_res], xmm0
```

## 后续版本

### SSE2

SSE2是Intel在Pentium 4处理器的最初版本中引入的，但是AMD后来在Opteron和Athlon 64处理器中也加入了SSE2的支持。SSE2指令集添加了对64位双精度浮点数的支持，以及对整型数据的支持，也就是说这个指令集中所有的MMX指令都是多余的了，同时也避免了占用浮点数寄存器。这个指令集还增加了对CPU快取的控制指令。AMD对它的扩展增加了8个XMM寄存器，但是需要切换到64位模式（x86-64/AMD64）才可以使用这些寄存器。Intel后来在其Intel 64架构中也增加了对x86-64的支持。

### SSE3

SSE3是Intel在Pentium 4处理器的Prescott核心中引入的第三代SIMD指令集，AMD在Athlon 64的第五个版本，Venice核心中也加入了SSE3的支持。这个指令集扩展的指令包含寄存器的局部位之间的运算，例如高位和低位之间的加减运算；浮点数到整数的转换，以及对超线程技术的支持。

### SSSE3

SSSE3是Intel针对SSE3指令集的一次额外扩充，最早内建于Core 2 Duo处理器中。

### SSE4

SSE4是Intel在Penryn核心的Core 2 Duo与Core 2 Solo处理器时，新增的47条新多媒体指令集，现在SSE4版本更新至SSE4.2。

#### SSE4a

AMD也开发了属于自己的SSE4a多媒体指令集，并内建在Athlon II与Opteron等K10架构处理器中，不过SSE4a无法与Intel的SSE4系列指令集相容。目前AMD新一代处理器已支援Intel的SSE4.1、SSE4.2指令集。

### SSE5

SSE5是AMD为了打破Intel垄断在处理器指令集的独霸地位所提出的，SSE5初期规划将加入超过100条新指令，其中最引人注目的就是三算子指令（3-Operand Instructions）及熔合乘法累积（Fused Multiply Accumulate）。其中，三算子指令让处理器可将一个数学或逻辑函式库，套用到算子或输入资料。借由增加算子的数量，一个x86指令能处理二至三笔资料，SSE5允许将多个简单指令汇整成一个指令，达到更有效率的指令处理模式。提升为三运算指令的运算能力，是少数RISC架构的水准。熔合乘法累积让允许建立新的指令，有效率地执行各种复杂的运算。熔合乘法累积可结合乘法与加法运算，透过单一指令执行多笔重复计算。透过简化程式码，让系统能迅速执行绘图着色、快速相片着色、音场音效，以及复杂向量演算等效能密集的应用作业。目前AMD已放弃下一代Bulldozer核心内建SSE5指令集，改内建Intel授权SSE4系列指令集。

### AVX

AVX（Advanced Vector Extensions）是Intel的SSE延伸架构，如IA16至IA32般的把暂存器XMM 128bit提升至YMM 256bit，以增加一倍的运算效率。

### FMA

FMA是Intel的AVX扩充指令集，如名称上乘积累加运算（Fused Multiply Accumulate）的意思一样。