Streaming_SIMD_Extensions

**SSE**（英語：Streaming SIMD Extensions）是英特爾在 AMD 的 3D Now! 發布一年之後，在其電腦晶片 Pentium III 中引入的指令集，是繼 MMX 的擴充指令集。SSE 指令集提供了 70 條新指令。AMD 後來在 Athlon XP 中加入了對這個新指令集的支援。

## SSE 的暫存器

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 個純量相加指令。

## 後續版本

### 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）的意思一樣。

## 參見

* AltiVec
* 組合語言
* MMX
* 3DNow!
* Pentium III