Instruction
FNSTENV
Stores the x87 environment to memory, then masks all x87 exceptions; FSTENV is FWAIT followed by it.
- Extensions
- Mnemonics
- FNSTENV, FSTENV
- Forms
- 2 (2 Legacy)
- Data
- Intel XED v2026.08.23
FNSTENV stores the x87 environment, everything but the eight data registers, and then masks every exception. The environment is the control word, the status word, the tag word, the last instruction pointer with its opcode, and the last data pointer. With a 32-bit or 64-bit operand size it takes 28 bytes, seven doublewords in that order; with the 66 prefix, 14 bytes of words, without the opcode. FLDENV loads it back, and FSTENV, listed on this page, is FWAIT followed by FNSTENV. FNSAVE stores the same environment followed by the registers.
What the image holds
- The tag word in full, two bits per register (valid, zero, special, empty), worked out from the contents; FXSAVE keeps only one bit per register.
- The status word as it was, a pending exception (ES) included.
- Only 32 bits of each pointer, even in 64-bit mode: AMD’s manual tells 64-bit code to use FXSAVE for them instead.
- Zen 5 filled bits 31:16 of the control, status and tag doublewords and of the data selector’s with ones; the layout in Intel’s manual leaves them blank. The 11-bit opcode shares a doubleword with the code selector, in bits 26:16.
Then every exception is masked
After the store the control word has its six mask bits set; nothing else changes in it. With an exception pending, Zen 5 also cleared ES and the busy bit in the live status word, so no #MF followed, while the stored copy kept them. Both manuals name the reason: an exception handler saves the environment, including the pointers to the faulting instruction and its operand, and can then use the x87 without being interrupted by the same exception. FLDENV restores the masks, and an unmasked flag still set in the loaded status word raises #MF at the next waiting instruction.
In compiled code
GCC 14 at -O2 uses FNSTENV for C11 atomic compound assignment on
floats: for ad += y on an _Atomic double it stores the environment
and clears the flags with FNCLEX (and does the same to
MXCSR) before the LOCK CMPXCHG loop, clears them again before each
retry, and at the end reloads the environment with FLDENV and raises
only the exceptions of the attempt that succeeded. Clang 23 emits just
the loop. AMD’s Zen 5 guide lists FNSTENV and FLDENV as microcoded.
Forms
Operation
What the forms do, in pseudocode that our tests run against results recorded on real processors. How to read.
FNSTENV m28bytea = dest.address
store(a, 32, 0xFFFF0000 | fcw) # bits 31:16 of four of the
store(a + 4, 32, 0xFFFF0000 | fsw) # doublewords: all ones
store(a + 8, 32, 0xFFFF0000 | ftw) # tags from the contents
store(a + 12, 32, fip) # the offset's low 32 bits
store(a + 16, 32, fop << 16 | fcs)
store(a + 20, 32, fdp)
store(a + 24, 32, 0xFFFF0000 | fds)
fcw = fcw | 0x3F # then every exception masked: an
# exception pending (ES) is stored
# as such, and no longer pending
c0 = c1 = c2 = c3 = UNDEFINED # Zen 5 keeps them
Run on AMD Zen 5 (EPYC 9645): 6 cases.
FNSTENV m14bytea = dest.address
store(a, 16, fcw)
store(a + 2, 16, fsw)
store(a + 4, 16, ftw) # tags from the contents
store(a + 6, 16, fip) # the offsets' low 16 bits; the
store(a + 8, 16, fcs) # opcode is left out
store(a + 10, 16, fdp)
store(a + 12, 16, fds)
fcw = fcw | 0x3F # then every exception masked
c0 = c1 = c2 = c3 = UNDEFINED # Zen 5 keeps them
Run on AMD Zen 5 (EPYC 9645): 4 cases.
Operands
| Operand | Kind | Action |
|---|---|---|
FNSTENV m14byte FNSTENV m28byte | ||
m14/28byte | explicit | write |
x87 status word | implicit | write |
Flags
| C0 | C1 | C2 | C3 |
|---|---|---|---|
| All forms | |||
| U | U | U | U |
Attributes
What else XED records about the forms. How to read.
- All forms
- may abort a TSX transaction
CPUID and processors
Each form belongs to an XED ISA set. A form can be used when the processor reports every CPUID bit of one of its ISA set's alternatives.
| ISA set | CPUID | Processors |
|---|---|---|
X87 | FPU | Every x86-64 processor in XED’s model and Zen 3 to Zen 6 |
More x87 instructions
Sources
- Intel XED v2026.08.23 (commit
0bcb6237345c): forms, encodings, operands, flags, exception classes, attributes, 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): Volume 2A, page 3-390 (FSTENV/
FNSTENV) - Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 1 (253665-093, September 2026)
- AMD64 Architecture Programmer's Manual, Volume 5: 64-Bit Media and x87 Floating-Point Instructions (26569, rev. 3.16, November 2021), Wayback Machine copy of AMD's PDF
- Software Optimization Guide for the AMD Zen5 Microarchitecture (58455, rev. 1.00, August 2024), Wayback Machine copy of AMD's ZIP
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.