Introduction
SSE (Streaming SIMD Extensions) came with Intel’s Pentium III in 1999. It does arithmetic on four single-precision (32-bit) floating-point numbers at once. AMD added it with the Athlon XP in 2001.
SSE brought new registers and state:
- eight 128-bit registers, XMM0 to XMM7, each holding four single-precision values. In 64-bit mode a REX prefix reaches eight more, XMM8 to XMM15;
- MXCSR, a 32-bit control and status register. It holds the rounding mode, the flush-to-zero bit, the six exception masks and the six exception flags. Later processors added the denormals-are-zero bit.
Each arithmetic instruction has a packed form, whose name ends in ps
and which works on all four values, and a scalar form, ending in ss,
which works on the lowest value only and leaves the other three unchanged. SSE also
added integer instructions on the 64-bit MMX registers (pavgb,
pshufw and the rest) and cacheability instructions such as
movntq. Its prefetch instructions and sfence are described
on the cache and memory ordering
page; the double-precision and 128-bit integer forms came with
SSE2.
A program checks for SSE with CPUID leaf 1: EDX bit 25. The operating system must also have enabled it: it sets CR4.OSFXSR (bit 9) to say that it saves the XMM registers with FXSAVE, and CR4.OSXMMEXCPT (bit 10) to take SIMD floating-point exceptions as #XM. Without OSFXSR the SSE instructions raise #UD.
Most of these instructions also have a VEX form, which came with AVX: its name
starts with v, it takes a separate destination and it is described on
the AVX page. Each row below links to it.
The instructions
In the forms, xmm1 is the ModRM.reg operand and
xmm2/m128 the ModRM.r/m operand. NP means that no 66, F2 or
F3 prefix may be present: with one, the same opcode is another instruction.
Moves
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
movaps | xmm1, xmm2/m128xmm2/m128, xmm1 | NP 0F 28 /rNP 0F 29 /r | Moves four packed single-precision values. A memory operand must be 16-byte aligned. VEX form: vmovaps. | SSE (Intel Pentium III, 1999) |
movups | xmm1, xmm2/m128xmm2/m128, xmm1 | NP 0F 10 /rNP 0F 11 /r | Moves four packed single-precision values; memory need not be aligned. VEX form: vmovups. | SSE (Intel Pentium III, 1999) |
movss | xmm1, xmm2/m32xmm2/m32, xmm1 | F3 0F 10 /rF3 0F 11 /r | Moves the low single-precision value. A load from memory zeroes bits 127:32; a move between registers leaves them unchanged. VEX form: vmovss. | SSE (Intel Pentium III, 1999) |
movlps | xmm1, m64m64, xmm1 | NP 0F 12 /rNP 0F 13 /r | Loads or stores the low two values (bits 63:0); the high half of the register is unchanged. Memory only: the register form of 0F 12 is movhlps. VEX form: vmovlps. | SSE (Intel Pentium III, 1999) |
movhps | xmm1, m64m64, xmm1 | NP 0F 16 /rNP 0F 17 /r | Loads or stores the high two values (bits 127:64); the low half is unchanged. Memory only: the register form of 0F 16 is movlhps. VEX form: vmovhps. | SSE (Intel Pentium III, 1999) |
movhlps | xmm1, xmm2 | NP 0F 12 /r (ModRM.mod 11) | Copies the high two values of xmm2 to the low half of xmm1; the high half of xmm1 is unchanged. VEX form: vmovhlps. | SSE (Intel Pentium III, 1999) |
movlhps | xmm1, xmm2 | NP 0F 16 /r (ModRM.mod 11) | Copies the low two values of xmm2 to the high half of xmm1; the low half of xmm1 is unchanged. VEX form: vmovlhps. | SSE (Intel Pentium III, 1999) |
movmskps | r32, xmm | NP 0F 50 /r | Copies the sign bits of the four values to bits 3:0 of a general register and zeroes the rest of it. VEX form: vmovmskps. | SSE (Intel Pentium III, 1999) |
Arithmetic
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
addps | xmm1, xmm2/m128 | NP 0F 58 /r | Adds four packed single-precision values. VEX form: vaddps. | SSE (Intel Pentium III, 1999) |
addss | xmm1, xmm2/m32 | F3 0F 58 /r | Adds the low single-precision values. VEX form: vaddss. | SSE (Intel Pentium III, 1999) |
subps | xmm1, xmm2/m128 | NP 0F 5C /r | Subtracts the second operand’s values from the first’s. VEX form: vsubps. | SSE (Intel Pentium III, 1999) |
subss | xmm1, xmm2/m32 | F3 0F 5C /r | Subtracts the low values. VEX form: vsubss. | SSE (Intel Pentium III, 1999) |
mulps | xmm1, xmm2/m128 | NP 0F 59 /r | Multiplies four packed values. VEX form: vmulps. | SSE (Intel Pentium III, 1999) |
mulss | xmm1, xmm2/m32 | F3 0F 59 /r | Multiplies the low values. VEX form: vmulss. | SSE (Intel Pentium III, 1999) |
divps | xmm1, xmm2/m128 | NP 0F 5E /r | Divides the first operand’s values by the second’s. VEX form: vdivps. | SSE (Intel Pentium III, 1999) |
divss | xmm1, xmm2/m32 | F3 0F 5E /r | Divides the low values. VEX form: vdivss. | SSE (Intel Pentium III, 1999) |
sqrtps | xmm1, xmm2/m128 | NP 0F 51 /r | Square roots of the four source values. VEX form: vsqrtps. | SSE (Intel Pentium III, 1999) |
sqrtss | xmm1, xmm2/m32 | F3 0F 51 /r | Square root of the low source value. VEX form: vsqrtss. | SSE (Intel Pentium III, 1999) |
rcpps | xmm1, xmm2/m128 | NP 0F 53 /r | Approximate reciprocals of the four values, with a relative error of at most 1.5 × 2−12. VEX form: vrcpps. | SSE (Intel Pentium III, 1999) |
rcpss | xmm1, xmm2/m32 | F3 0F 53 /r | Approximate reciprocal of the low value. VEX form: vrcpss. | SSE (Intel Pentium III, 1999) |
rsqrtps | xmm1, xmm2/m128 | NP 0F 52 /r | Approximate reciprocal square roots of the four values, with a relative error of at most 1.5 × 2−12. VEX form: vrsqrtps. | SSE (Intel Pentium III, 1999) |
rsqrtss | xmm1, xmm2/m32 | F3 0F 52 /r | Approximate reciprocal square root of the low value. VEX form: vrsqrtss. | SSE (Intel Pentium III, 1999) |
maxps | xmm1, xmm2/m128 | NP 0F 5F /r | The larger of each pair of values. If both are zero, or either is a NaN, the second operand’s value is returned. VEX form: vmaxps. | SSE (Intel Pentium III, 1999) |
maxss | xmm1, xmm2/m32 | F3 0F 5F /r | The larger of the low values, with the same rule. VEX form: vmaxss. | SSE (Intel Pentium III, 1999) |
minps | xmm1, xmm2/m128 | NP 0F 5D /r | The smaller of each pair of values. If both are zero, or either is a NaN, the second operand’s value is returned. VEX form: vminps. | SSE (Intel Pentium III, 1999) |
minss | xmm1, xmm2/m32 | F3 0F 5D /r | The smaller of the low values, with the same rule. VEX form: vminss. | SSE (Intel Pentium III, 1999) |
Comparisons
CMPPS and CMPSS write a mask: all ones in each element where the comparison is
true, all zeros where it is false. The immediate picks the comparison. LLVM, and so
the disassembler, shows the eight legacy predicates (0 to 7) as their own names,
such as cmpltps, and shows any other immediate as a number; the legacy
instructions use only bits 2:0 of it.
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
cmpps | xmm1, xmm2/m128, imm8 | NP 0F C2 /r ib | Compares four pairs of values with the predicate in imm8: 0 equal, 1 less than, 2 less or equal, 3 unordered, 4 not equal, 5 not less than, 6 not less or equal, 7 ordered. 1, 2, 5 and 6 signal invalid on a quiet NaN. Predicate names: cmpeqps (0), cmpltps (1), cmpleps (2), cmpunordps (3), cmpneqps (4), cmpnltps (5), cmpnleps (6), cmpordps (7).VEX form: vcmpps, with 32 predicates. | SSE (Intel Pentium III, 1999) |
cmpss | xmm1, xmm2/m32, imm8 | F3 0F C2 /r ib | Compares the low values the same way and writes the mask to the low element; the other three are unchanged. Predicate names: cmpeqss (0), cmpltss (1), cmpless (2), cmpunordss (3), cmpneqss (4), cmpnltss (5), cmpnless (6), cmpordss (7).VEX form: vcmpss. | SSE (Intel Pentium III, 1999) |
comiss | xmm1, xmm2/m32 | NP 0F 2F /r | Compares the low values and sets ZF, PF and CF (all three for unordered); clears OF, SF and AF. Signals invalid on any NaN. VEX form: vcomiss. | SSE (Intel Pentium III, 1999) |
ucomiss | xmm1, xmm2/m32 | NP 0F 2E /r | As comiss, but signals invalid only on a signalling NaN. VEX form: vucomiss. | SSE (Intel Pentium III, 1999) |
Logic
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
andps | xmm1, xmm2/m128 | NP 0F 54 /r | Bitwise AND of 128 bits. VEX form: vandps. | SSE (Intel Pentium III, 1999) |
andnps | xmm1, xmm2/m128 | NP 0F 55 /r | Bitwise AND of the inverted first operand with the second. VEX form: vandnps. | SSE (Intel Pentium III, 1999) |
orps | xmm1, xmm2/m128 | NP 0F 56 /r | Bitwise OR. VEX form: vorps. | SSE (Intel Pentium III, 1999) |
xorps | xmm1, xmm2/m128 | NP 0F 57 /r | Bitwise exclusive OR; xorps xmm0, xmm0 is the usual way to clear a register. VEX form: vxorps. | SSE (Intel Pentium III, 1999) |
Shuffles and unpacking
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
shufps | xmm1, xmm2/m128, imm8 | NP 0F C6 /r ib | Builds the result from two values of the first operand (low half) and two of the second (high half), each chosen by a 2-bit field of imm8. VEX form: vshufps. | SSE (Intel Pentium III, 1999) |
unpcklps | xmm1, xmm2/m128 | NP 0F 14 /r | Interleaves the low two values of each operand: a0, b0, a1, b1. VEX form: vunpcklps. | SSE (Intel Pentium III, 1999) |
unpckhps | xmm1, xmm2/m128 | NP 0F 15 /r | Interleaves the high two values of each operand: a2, b2, a3, b3. VEX form: vunpckhps. | SSE (Intel Pentium III, 1999) |
Conversions
Conversions to integers round by MXCSR.RC; the cvtt forms truncate
towards zero. A value out of range, or a NaN, gives the integer indefinite value,
80000000h (8000000000000000h for 64 bits).
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
cvtpi2ps | xmm, mm/m64 | NP 0F 2A /r | Converts two signed 32-bit integers to the low two single-precision values; the high two are unchanged. | SSE (Intel Pentium III, 1999) |
cvtps2pi | mm, xmm/m64 | NP 0F 2D /r | Converts the low two single-precision values to two signed 32-bit integers in an MMX register. | SSE (Intel Pentium III, 1999) |
cvttps2pi | mm, xmm/m64 | NP 0F 2C /r | As cvtps2pi, truncating. | SSE (Intel Pentium III, 1999) |
cvtsi2ss | xmm1, r/m32xmm1, r/m64 | F3 0F 2A /rF3 REX.W 0F 2A /r | Converts a signed integer to the low single-precision value; the other three are unchanged. The 64-bit form is for 64-bit mode only. VEX form: vcvtsi2ss. | SSE (Intel Pentium III, 1999) |
cvtss2si | r32, xmm1/m32r64, xmm1/m32 | F3 0F 2D /rF3 REX.W 0F 2D /r | Converts the low single-precision value to a signed integer. VEX form: vcvtss2si. | SSE (Intel Pentium III, 1999) |
cvttss2si | r32, xmm1/m32r64, xmm1/m32 | F3 0F 2C /rF3 REX.W 0F 2C /r | As cvtss2si, truncating. VEX form: vcvttss2si. | SSE (Intel Pentium III, 1999) |
MXCSR
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
ldmxcsr | m32 | NP 0F AE /2 | Loads MXCSR from memory. Setting a reserved bit raises #GP. VEX form: vldmxcsr. | SSE (Intel Pentium III, 1999) |
stmxcsr | m32 | NP 0F AE /3 | Stores MXCSR to memory. VEX form: vstmxcsr. | SSE (Intel Pentium III, 1999) |
Integer instructions on MMX registers
These work on the 64-bit MMX registers, like the MMX instructions, and share their state with the x87 registers. SSE2 gave each of them a 128-bit form with a 66 prefix, on the SSE2 page.
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
pavgb | mm1, mm2/m64 | NP 0F E0 /r | Rounded average of unsigned bytes: (a + b + 1) >> 1. 128-bit form: pavgb (SSE2). | SSE (Intel Pentium III, 1999) |
pavgw | mm1, mm2/m64 | NP 0F E3 /r | Rounded average of unsigned words. 128-bit form: pavgw (SSE2). | SSE (Intel Pentium III, 1999) |
pmaxsw | mm1, mm2/m64 | NP 0F EE /r | Maximum of signed words. 128-bit form: pmaxsw (SSE2). | SSE (Intel Pentium III, 1999) |
pmaxub | mm1, mm2/m64 | NP 0F DE /r | Maximum of unsigned bytes. 128-bit form: pmaxub (SSE2). | SSE (Intel Pentium III, 1999) |
pminsw | mm1, mm2/m64 | NP 0F EA /r | Minimum of signed words. 128-bit form: pminsw (SSE2). | SSE (Intel Pentium III, 1999) |
pminub | mm1, mm2/m64 | NP 0F DA /r | Minimum of unsigned bytes. 128-bit form: pminub (SSE2). | SSE (Intel Pentium III, 1999) |
pmulhuw | mm1, mm2/m64 | NP 0F E4 /r | Multiplies unsigned words and keeps the high 16 bits of each 32-bit product. 128-bit form: pmulhuw (SSE2). | SSE (Intel Pentium III, 1999) |
psadbw | mm1, mm2/m64 | NP 0F F6 /r | Sums the absolute differences of eight pairs of unsigned bytes into the low word; the upper three words are zeroed. 128-bit form: psadbw (SSE2). | SSE (Intel Pentium III, 1999) |
pshufw | mm1, mm2/m64, imm8 | NP 0F 70 /r ib | Shuffles four words: each 2-bit field of imm8 picks the source word for one destination word. | SSE (Intel Pentium III, 1999) |
pextrw | r32, mm, imm8 | NP 0F C5 /r ib | Copies the word selected by imm8[1:0] to a general register, zero-extended. 128-bit form: pextrw (SSE2). | SSE (Intel Pentium III, 1999) |
pinsrw | mm, r32/m16, imm8 | NP 0F C4 /r ib | Writes the low word of the source into the word selected by imm8[1:0]. 128-bit form: pinsrw (SSE2). | SSE (Intel Pentium III, 1999) |
pmovmskb | r32, mm | NP 0F D7 /r | Copies the top bit of each of the eight bytes to bits 7:0 of a general register and zeroes the rest. 128-bit form: pmovmskb (SSE2). | SSE (Intel Pentium III, 1999) |
Non-temporal stores
These store without bringing the line into the caches, through write-combining.
The stores are weakly ordered: sfence
orders them with later stores.
| Instruction | Forms | Encoding | What it does | Set |
|---|---|---|---|---|
movntps | m128, xmm1 | NP 0F 2B /r | Stores four single-precision values with a non-temporal hint. Memory must be 16-byte aligned. VEX form: vmovntps. | SSE (Intel Pentium III, 1999) |
movntq | m64, mm | NP 0F E7 /r | Stores an MMX register with a non-temporal hint. | SSE (Intel Pentium III, 1999) |
maskmovq | mm1, mm2 | NP 0F F7 /r | Stores the bytes of mm1 whose mask byte in mm2 has its top bit set, to DS:[DI], [EDI] or [RDI] by the address size, with a non-temporal hint. | SSE (Intel Pentium III, 1999) |
Notes
- Alignment. In the legacy encodings a 128-bit memory operand must
be 16-byte aligned, or the instruction raises #GP.
movupsand the 64-bit and 32-bit memory operands are the exceptions. The VEX forms drop the rule, except forvmovapsandvmovntps. - Exceptions. The arithmetic, comparisons and conversions set the exception flags in MXCSR. An unmasked exception raises #XM when CR4.OSXMMEXCPT is set, and #UD when it is not.
- Upper bits. A legacy SSE instruction leaves bits 255:128 of the
YMM register (and above) unchanged; a VEX form zeroes them. Mixing the two on
processors with AVX can cost a state transition, which is why compilers use
vzeroupper. - Decoding. 0F 12 and 0F 16 with a 66 prefix and a register
operand have no
movlpdormovhpdform; the disassembler, as LLVM does, shows them asmovhlpsandmovlhps.
Links
Reference
- Intel 64 and IA-32 Architectures Software Developer’s Manuals – Intel’s manuals; volume 2 describes each instruction, volume 1 chapter 10 describes SSE
- AMD64 Architecture Programmer’s Manual, Volume 4 – AMD’s reference to the 128-bit, 256-bit and 512-bit media instructions
- x86 and amd64 instruction reference – Félix Cloutier’s web copy of the instruction pages of Intel’s manual