Extensions
Mnemonics
FNSAVE, FSAVE
Forms
2 (2 Legacy)
Data
Intel XED v2026.08.23

FNSAVE stores the whole x87 state to memory and then reinitializes the unit. The image is the environment that FNSTENV stores, followed by the eight data registers, ten bytes each in stack order, ST(0) first: 108 bytes with a 32- or 64-bit operand size, 94 with the 66 prefix, whose environment is seven words with 16-bit pointers and no opcode. FRSTOR loads it back. FSAVE, listed on this page, is FWAIT followed by FNSAVE.

A save that leaves a clean unit

After the store, Zen 5 left the x87 as FNINIT does: control word 037FH, status word 0 with TOP at 0, every register tagged empty, the opcode and the data pointer 0. The values stayed in the physical registers, only tagged empty, and with TOP moved they show up as other ST(i). So code that saves the state in order to use the x87 for something else needs no FNINIT of its own, and gets its values back only by FRSTOR. Each slot of the image holds what its register held, an empty register’s stale bits included; the tag word says which slots count.

No wait

FNSAVE does not check for a pending exception first. In Zen 5’s case with an unmasked IE pending (ES and B set), it wrote the image without a #MF, and the status word in the image kept ES and B while the live one went to 0. FRSTOR of that image makes the exception pending again, as FRSTOR’s page describes. FSAVE’s FWAIT would deliver the #MF before anything is saved.

Beside FXSAVE

FNSAVE saves neither the XMM registers nor MXCSR, and in 64-bit mode only 32 bits of each pointer. FXSAVE’s page lists how the two differ, and FRSTOR’s says where Intel’s manual still prefers the older pair. GCC 14 and Clang 23 have no intrinsic for FNSAVE. AMD’s Zen 5 guide lists it as microcoded.

Forms

Every encoding of FNSAVE that Intel XED knows, one row per XED instruction form (iform). How to read the notation.
InstructionEncodingRequires
FNSAVE m94byte FNSAVE_MEMmem9466 DD /6FPU
FNSAVE m108byte FNSAVE_MEMmem108REX.W DD /6
DD /6
FPU

Operation

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

FNSAVE m108byte
a = dest.address
store(a, 32, 0xFFFF0000 | fcw)   # the environment, as FNSTENV
store(a + 4, 32, 0xFFFF0000 | fsw)   # stores it
store(a + 8, 32, 0xFFFF0000 | ftw)
store(a + 12, 32, fip)
store(a + 16, 32, fop << 16 | fcs)
store(a + 20, 32, fdp)
store(a + 24, 32, 0xFFFF0000 | fds)
for i in range(8):
    v = st[i]                    # ST(0) first; an empty register
    store(a + 28 + 10 * i, 80, v)    # too, with what it holds
fcw = 0x037F                     # then as FNINIT: every exception
fsw = 0                          # masked, 64 bits to nearest; TOP,
ftw = 0xFFFF                     # codes and flags 0; every register
fip = fcs = fop = 0              # empty, holding its value
fdp = fds = 0

Run on AMD Zen 5 (EPYC 9645): 6 cases.

FNSAVE m94byte
a = dest.address
store(a, 16, fcw)                # the environment, as FNSTENV
store(a + 2, 16, fsw)            # stores it
store(a + 4, 16, ftw)
store(a + 6, 16, fip)
store(a + 8, 16, fcs)
store(a + 10, 16, fdp)
store(a + 12, 16, fds)
for i in range(8):
    v = st[i]                    # ST(0) first; an empty register
    store(a + 14 + 10 * i, 80, v)    # too, with what it holds
fcw = 0x037F                     # then as FNINIT
fsw = 0
ftw = 0xFFFF
fip = fcs = fop = 0
fdp = fds = 0

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
FNSAVE m94byte FNSAVE m108byte
m94/108byteexplicitwrite
x87 control wordimplicitread, write
x87 tag wordimplicitread, write
x87 status wordimplicitread, write

Flags

M modified; blank: not affected. How to read.
C0C1C2C3
All forms
MMMM

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-375 (FSAVE/FNSAVE)
  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.