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

Every encoding of FNSTENV that Intel XED knows, one row per XED instruction form (iform). How to read the notation.
InstructionEncodingRequires
FNSTENV m14byte FNSTENV_MEMmem1466 D9 /6FPU
FNSTENV m28byte FNSTENV_MEMmem28REX.W D9 /6
D9 /6
FPU

Operation

What the forms do, in pseudocode that our tests run against results recorded on real processors. How to read.

FNSTENV m28byte
a = 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 m14byte
a = 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

What each form reads and writes, as Intel XED records it: the operands of its syntax, in order, and the implicit ones that the syntax does not name. How to read.
OperandKindAction
FNSTENV m14byte FNSTENV m28byte
m14/28byteexplicitwrite
x87 status wordimplicitwrite

Flags

U undefined; blank: not affected. How to read.
C0C1C2C3
All forms
UUUU

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.

CPUID requirements and processors of the XED ISA sets above. Alternatives are separated by “or”; processors follow XED’s chip model, whose AMD processors end with Zen 2, and the CPU data of this site for Zen 3 to Zen 6.
ISA setCPUIDProcessors
X87

FPU
CPUID.01H:EDX[0] FPU

Every x86-64 processor in XED’s model and Zen 3 to Zen 6

More x87 instructions

All 90 x87 instructions

Sources

  1. Intel XED v2026.08.23 (commit 0bcb6237345c): forms, encodings, operands, flags, exception classes, attributes, ISA sets, CPUID bits and chip model.
  2. The CPU data of x86-64.net: Zen 3 to Zen 6, from GCC’s -march feature sets and AMD’s Processor Programming References, which the page of each processor cites.
  3. Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 2 (325383-093, September 2026): Volume 2A, page 3-390 (FSTENV/FNSTENV)
  4. Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 1 (253665-093, September 2026)
  5. 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
  6. 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.