x87, MMX and 3DNow!
x87 floating-point instructions
The x87 floating-point unit computes in 80-bit extended precision on a stack of eight registers; x86-64 code still uses it for long double.
- CPUID
- FPU
CPUID.01H:EDX[0] - Instructions
- 90 mnemonics
- Processors
- Every x86-64 processor in XED’s model and Zen 3 to Zen 6
- Linux flag
fpu
The x87 floating-point unit began as the 8087 coprocessor and has been built into the processor since the 486DX. Its eight 80-bit data registers form a stack: most instructions work on the top, ST(0), and another register ST(i) or a memory operand, and FLD and FSTP push and pop. Arithmetic runs in extended precision, with a 64-bit significand, unless the precision control of the control word asks for less, and the unit has its own control, status and tag words, saved by FXSAVE and XSAVE or, in the older layout, by FNSAVE.
On x86-64, SSE2 replaced the x87 unit for float and double, but it
still matters in three places. long double is the 80-bit x87 format
in the System V ABI, so arithmetic on it compiles
to these instructions and results come back in ST(0). The 32-bit
ABIs return float and double in ST(0) as well,
so 32-bit code uses the stack even when it computes with SSE. And
binaries built for processors without SSE2 do all their floating-point
work here. The conditional moves (FCMOVB and the rest) and the
comparisons that set EFLAGS (FCOMI and relatives) came
with the Pentium Pro and have ISA sets of their own; the FCMOVcc forms
need the CMOV bit too.
A few encodings on these pages are aliases that Intel’s manual does not list but XED decodes as the instruction shown, such as DF D0+i for FSTP; they are tagged “undocumented”.
Instructions
| Mnemonic | Summary | Forms |
|---|---|---|
| F2XM1 | Replaces ST(0), which must lie between -1 and +1, with 2 to the power ST(0), minus 1. | 1 |
| FABS | Clears the sign bit of ST(0), leaving its absolute value. | 1 |
| FADD | Adds a 32- or 64-bit float from memory to ST(0), or adds ST(0) and ST(i) into either of them. | 4 |
| FADDP | Adds ST(0) to ST(i), stores the sum in ST(i) and pops the register stack. | 1 |
| FBLD | Converts an 18-digit packed BCD integer from 10 bytes of memory to extended precision and pushes it. | 1 |
| FBSTP | Rounds ST(0) to an integer, stores it as 18-digit packed BCD in 10 bytes of memory and pops the register stack. | 1 |
| FCHS | Inverts the sign bit of ST(0). | 1 |
| FCMOVB | Copies ST(i) to ST(0) if CF is set (below, after FCOMI or an integer compare). | 1 |
| FCMOVBE | Copies ST(i) to ST(0) if CF or ZF is set (below or equal). | 1 |
| FCMOVE | Copies ST(i) to ST(0) if ZF is set (equal). | 1 |
| FCMOVNB | Copies ST(i) to ST(0) if CF is clear (not below). | 1 |
| FCMOVNBE | Copies ST(i) to ST(0) if both CF and ZF are clear (above). | 1 |
| FCMOVNE | Copies ST(i) to ST(0) if ZF is clear (not equal). | 1 |
| FCMOVNU | Copies ST(i) to ST(0) if PF is clear, which after FCOMI means the operands were ordered (neither was a NaN). | 1 |
| FCMOVU | Copies ST(i) to ST(0) if PF is set, which after FCOMI means the comparison was unordered (a NaN). | 1 |
| FCOM | Compares ST(0) with ST(i) or a 32- or 64-bit float in memory and sets C0, C2 and C3 of the x87 status word; any NaN is an invalid operation. | 4 |
| FCOMI | Compares ST(0) with ST(i) and sets ZF, PF and CF in EFLAGS directly; any NaN is an invalid operation. | 1 |
| FCOMIP | Compares ST(0) with ST(i) like FCOMI, setting ZF, PF and CF, then pops the register stack. | 1 |
| FCOMP | Compares ST(0) with ST(i) or a float in memory like FCOM, then pops the register stack. | 5 |
| FCOMPP | Compares ST(0) with ST(1) like FCOM, then pops the register stack twice. | 1 |
| FCOS | Replaces ST(0), an angle in radians of magnitude below 2^63, with its cosine; C2 reports an operand out of range. | 1 |
| FDECSTP | Subtracts one from the TOP field of the x87 status word, rotating the register stack without moving any data. | 1 |
| FDIV | Divides ST(0) by a float from memory, or ST(0) by ST(i) or ST(i) by ST(0), into the dividend's register. | 4 |
| FDIVP | Divides ST(i) by ST(0), stores the quotient in ST(i) and pops the register stack. | 1 |
| FDIVR | Divides a float from memory by ST(0), or ST(i) by ST(0) into ST(0), or ST(0) by ST(i) into ST(i): FDIV with the operands swapped. | 4 |
| FDIVRP | Divides ST(0) by ST(i), stores the quotient in ST(i) and pops the register stack. | 1 |
| FFREE | Marks ST(i) as empty in the x87 tag word, without changing the stack top. | 1 |
| FFREEP | Marks ST(i) as empty and pops the register stack; Intel's manual does not list it, but XED decodes it. | 1 |
| FIADD | Adds a 16- or 32-bit signed integer from memory to ST(0). | 2 |
| FICOM | Compares ST(0) with a 16- or 32-bit signed integer in memory and sets C0, C2 and C3 of the x87 status word. | 2 |
| FICOMP | Compares ST(0) with a 16- or 32-bit signed integer in memory like FICOM, then pops the register stack. | 2 |
| FIDIV | Divides ST(0) by a 16- or 32-bit signed integer from memory. | 2 |
| FIDIVR | Divides a 16- or 32-bit signed integer from memory by ST(0), into ST(0). | 2 |
| FILD | Converts a 16-, 32- or 64-bit signed integer from memory to extended precision and pushes it. | 3 |
| FIMUL | Multiplies ST(0) by a 16- or 32-bit signed integer from memory. | 2 |
| FINCSTP | Adds one to the TOP field of the x87 status word, rotating the register stack without freeing a register. | 1 |
| FIST | Converts ST(0) to a 16- or 32-bit signed integer, rounded as the control word says, and stores it in memory. | 2 |
| FISTP | Converts ST(0) to a 16-, 32- or 64-bit signed integer as the rounding control says, stores it and pops the register stack. | 3 |
| FISUB | Subtracts a 16- or 32-bit signed integer in memory from ST(0). | 2 |
| FISUBR | Subtracts ST(0) from a 16- or 32-bit signed integer in memory, into ST(0). | 2 |
| FLD | Pushes a 32-, 64- or 80-bit float from memory, or a copy of ST(i), onto the x87 register stack. | 4 |
| FLD1 | Pushes the constant +1.0 onto the x87 register stack. | 1 |
| FLDCW | Loads the x87 control word (exception masks, precision and rounding control) from 16 bits of memory. | 1 |
| FLDENV | Loads the x87 environment (control, status and tag words and the last instruction and operand pointers) from memory. | 2 |
| FLDL2E | Pushes the constant log2(e) onto the x87 register stack. | 1 |
| FLDL2T | Pushes the constant log2(10) onto the x87 register stack. | 1 |
| FLDLG2 | Pushes the constant log10(2) onto the x87 register stack. | 1 |
| FLDLN2 | Pushes the constant ln(2) onto the x87 register stack. | 1 |
| FLDPI | Pushes the constant pi onto the x87 register stack. | 1 |
| FLDZ | Pushes the constant +0.0 onto the x87 register stack. | 1 |
| FMUL | Multiplies ST(0) by a float from memory, or ST(0) and ST(i) into either of them. | 4 |
| FMULP | Multiplies ST(i) by ST(0), stores the product in ST(i) and pops the register stack. | 1 |
| FNCLEX | Clears the x87 exception flags without first handling pending exceptions; FCLEX is FWAIT followed by it. | 1 |
| FNDISI | An 8087 instruction that masked the coprocessor's interrupt; later x87 units ignore it, and XED decodes it as a no-op. | 1 |
| FNENI | An 8087 instruction that unmasked the coprocessor's interrupt; later x87 units ignore it, and XED decodes it as a no-op. | 1 |
| FNINIT | Resets the x87 unit to its default state without first handling pending exceptions; FINIT is FWAIT followed by it. | 1 |
| FNOP | Does nothing apart from updating the x87 instruction pointer. | 1 |
| FNSAVE | Stores the x87 environment and the eight data registers to memory, then resets the unit like FNINIT; FSAVE is FWAIT followed by it. | 2 |
| FNSETPM | An 80287 instruction that put the coprocessor in protected mode; later x87 units ignore it, and XED decodes it as a no-op. | 1 |
| FNSTCW | Stores the x87 control word to 16 bits of memory; FSTCW is FWAIT followed by it. | 1 |
| FNSTENV | Stores the x87 environment to memory, then masks all x87 exceptions; FSTENV is FWAIT followed by it. | 2 |
| FNSTSW | Stores the x87 status word to 16 bits of memory or to AX; FSTSW is FWAIT followed by it. | 2 |
| FPATAN | Stores the arctangent of ST(1) divided by ST(0), in radians, in ST(1) and pops the register stack. | 1 |
| FPREM | Stores in ST(0) the partial remainder of ST(0) divided by ST(1) with a truncated quotient, as C's fmod gives; C2 says whether to repeat. | 1 |
| FPREM1 | Stores in ST(0) the partial IEEE 754 remainder of ST(0) divided by ST(1), with the quotient rounded to nearest; C2 says whether to repeat. | 1 |
| FPTAN | Replaces ST(0), an angle in radians of magnitude below 2^63, with its tangent and then pushes 1.0. | 1 |
| FRNDINT | Rounds ST(0) to an integral value in the rounding mode of the x87 control word. | 1 |
| FRSTOR | Loads the x87 environment and data registers from memory that FSAVE or FNSAVE stored. | 2 |
| FSCALE | Multiplies ST(0) by 2 to the power of ST(1) truncated to an integer. | 1 |
| FSIN | Replaces ST(0), an angle in radians of magnitude below 2^63, with its sine; C2 reports an operand out of range. | 1 |
| FSINCOS | Replaces ST(0), an angle in radians, with its sine and pushes its cosine, so that ST(0) holds the cosine and ST(1) the sine. | 1 |
| FSQRT | Replaces ST(0) with its square root. | 1 |
| FST | Copies ST(0) to a 32- or 64-bit float in memory, rounding it, or to ST(i). | 3 |
| FSTP | Copies ST(0) to a 32-, 64- or 80-bit float in memory or to ST(i) and pops the register stack. | 7 |
| FSUB | Subtracts a float in memory from ST(0), or ST(i) from ST(0) or ST(0) from ST(i), into the minuend's register. | 4 |
| FSUBP | Subtracts ST(0) from ST(i), stores the difference in ST(i) and pops the register stack. | 1 |
| FSUBR | Subtracts ST(0) from a float in memory, or ST(0) from ST(i) into ST(0), or ST(i) from ST(0) into ST(i): FSUB with the operands swapped. | 4 |
| FSUBRP | Subtracts ST(i) from ST(0), stores the difference in ST(i) and pops the register stack. | 1 |
| FTST | Compares ST(0) with 0.0 and sets C0, C2 and C3 of the x87 status word. | 1 |
| FUCOM | Compares ST(0) with ST(i) and sets C0, C2 and C3 of the x87 status word; only a signaling NaN is an invalid operation. | 1 |
| FUCOMI | Compares ST(0) with ST(i) and sets ZF, PF and CF in EFLAGS; only a signaling NaN is an invalid operation. | 1 |
| FUCOMIP | Compares ST(0) with ST(i) like FUCOMI, setting ZF, PF and CF, then pops the register stack. | 1 |
| FUCOMP | Compares ST(0) with ST(i) like FUCOM, then pops the register stack. | 1 |
| FUCOMPP | Compares ST(0) with ST(1) like FUCOM, then pops the register stack twice. | 1 |
| FWAIT | Waits for the x87 unit and raises any pending unmasked x87 exception; WAIT is another name for it. | 1 |
| FXAM | Classifies ST(0) as empty, zero, normal, denormal, infinity, NaN or unsupported in C0, C2 and C3, with its sign in C1. | 1 |
| FXCH | Exchanges ST(0) with ST(i), ST(1) if no operand is given. | 3 |
| FXTRACT | Splits ST(0) into its exponent, left in ST(1), and its significand, pushed as the new ST(0). | 1 |
| FYL2X | Stores ST(1) times log2(ST(0)) in ST(1) and pops the register stack. | 1 |
| FYL2XP1 | Stores ST(1) times log2(ST(0) + 1) in ST(1) and pops; for ST(0) near zero, where it is more accurate than FYL2X. | 1 |
CPUID and processors
XED splits x87 into 3 ISA sets. Software can use a form when the processor reports every CPUID bit of one alternative of the form's ISA set.
| ISA set | CPUID | Processors |
|---|---|---|
FCMOV | CMOV + FPU | Every x86-64 processor in XED’s model and Zen 3 to Zen 6 |
FCOMI | CMOV + FPU | Every x86-64 processor in XED’s model and Zen 3 to Zen 6 |
X87 | FPU | Every x86-64 processor in XED’s model and Zen 3 to Zen 6 |
Sources
- Intel XED v2026.08.23 (commit
0bcb6237345c): forms, encodings, ISA sets, CPUID bits and chip model. - The CPU data of x86-64.net: Zen 3 to Zen 6, from GCC’s
-marchfeature sets and AMD’s Processor Programming References, which the page of each processor cites. - Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 2 (325383-093, September 2026)
- Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 1 (253665-093, September 2026)
The tables are derived from Intel XED, Copyright Intel Corporation, licensed under the Apache License 2.0; x86-64.net converted and reformatted them. The text is our own.