Instruction
XRSTOR
Restores the state components that XCR0 and EDX:EAX select from an XSAVE area, setting those the area marks unused to their initial state.
- Extensions
- Mnemonics
- XRSTOR, XRSTOR64
- Forms
- 2 (2 Legacy)
- Data
- Intel XED v2026.08.23
XRSTOR loads state components back from an XSAVE area, the layout of which the XSAVE page describes. Which components it touches is the requested-feature bitmap, RFBM, XCR0 AND EDX:EAX. For each component i:
- RFBM bit i clear: the component stays as it is;
- RFBM bit i set and XSTATE_BV bit i set in the area’s header: the component is loaded from the area;
- RFBM bit i set and XSTATE_BV bit i clear: the component is put in its initial state.
XRSTOR64 differs only in the format of the x87 pointers, as FXRSTOR64 does (FXRSTOR).
Initial states
The initial state is zero for the vector and mask registers and PKRU. For the x87 it is what FNINIT gives, control word 037FH and every register empty, but XRSTOR also zeroes the eight registers, which FNINIT leaves alone; Zen 5 did so. MXCSR is the odd one out. In the standard format it is loaded from the area whenever RFBM asks for SSE or AVX, even with SSE’s XSTATE_BV bit clear; in the compacted format only with SSE’s data, and an initialized SSE component gets 1F80H, as on Zen 5.
Faults
XRSTOR raises #GP for:
- an address not aligned to 64 bytes (Zen 5: an address 16 bytes off);
- in the standard format, an XSTATE_BV bit for a component not enabled in XCR0 (Zen 5: bit 3, MPX’s, with XCR0 = 2E7H), or nonzero header bytes 8 to 23;
- in the compacted format, which bit 63 of XCOMP_BV selects, the same for XCOMP_BV, an XSTATE_BV bit outside XCOMP_BV, or nonzero header bytes 16 to 63;
- an MXCSR value with a bit set that MXCSR_MASK does not allow.
The compacted format is what XSAVEC writes, and XRSTOR accepts it where CPUID leaf 0DH, sub-leaf 1, reports XSAVEC; Zen 5 restored the opmask registers and PKRU from such an area.
Tracking
A component that XRSTOR loaded then counts as in use, one it initialized as not (XINUSE, which XGETBV with ECX = 1 reads), and one outside RFBM as modified; XSAVEOPT uses this to skip work. On Zen 5, SSE stayed in use after an initialization while MXCSR was not 1F80H.
_xrstor(p, mask) and _xrstor64 need -mxsave; GCC 14 and Clang 23
at -O2 split the mask into EDX:EAX and emit one XRSTOR. AMD’s Zen 5
guide lists XRSTOR as microcoded.
Forms
| Instruction | Encoding | Requires |
|---|---|---|
XRSTOR mem
XRSTOR_MEMmxsave | NP 0F AE /5 | XSAVE + OSXSAVE |
XRSTOR64 mem
XRSTOR64_MEMmxsave | REX.W 0F AE /5 | XSAVE + OSXSAVE |
Operation
What the forms do, in pseudocode that our tests run against results recorded on real processors. How to read.
a = mem.address
if a % 64:
fault(GP, 0)
rfbm = (edx << 32 | eax) & xcr0 # the components to restore
bv = load(a + 512, 64) # XSTATE_BV
c = load(a + 520, 64) # XCOMP_BV
std = c >> 63 == 0 # the standard format
if std: # bytes 23:8 of the header zeros
bad = bv & ~xcr0 or c
bad = bad or load(a + 528, 64)
else: # the compacted one: 63:16 zeros
bad = c & ~(xcr0 | 1 << 63) or bv & ~c
bad = bad or load(a + 528, 384)
if bad:
fault(GP, 0)
ld = rfbm & 6 if std else rfbm & bv & 2
mx = mxcsr
if ld: # MXCSR from the area: with SSE or
mx = load(a + 24, 32) # AVX in the standard format, with
if mx & ~mxcsr_mask: # SSE's data in the compacted
fault(GP, 0)
elif rfbm & 2 and not std:
mx = 0x1F80 # initial, with SSE's registers
mxcsr = mx
if rfbm & bv & 1: # x87 state, as FXRSTOR loads it
sw = load(a + 2, 16)
t = sw >> 11 & 7 # TOP from the area
for i in range(8):
v = load(a + 32 + 16 * i, 80)
st[(t - top + i) % 8] = v
tags = load(a + 4, 8)
tw = 0
for j in range(8): # Rj empty where its bit is clear
if not tags >> j & 1:
tw |= 3 << 2 * j
ftw = tw
fcw = load(a, 16)
fsw = sw
fop = load(a + 6, 16)
if OSIZE == 64: # REX.W: 64-bit offsets
fip = load(a + 8, 64)
fdp = load(a + 16, 64)
else:
fip = load(a + 8, 32)
fcs = load(a + 12, 16)
fdp = load(a + 16, 32)
fds = load(a + 20, 16)
elif rfbm & 1: # x87 state initialized
for i in range(8):
st[i] = 0
ftw = 0xFFFF # all empty
fcw = 0x037F
fsw = 0
fop = fip = fcs = fdp = fds = 0
if rfbm & 2: # XMM0 to XMM15, or zeros
b = a + 160
for i in range(16):
v = 0
if bv & 2:
v = load(b + 16 * i, 128)
xmm[i] = v
if rfbm & 4: # AVX: bits 255:128
b = a + xsave_offset(2, c)
for i in range(16):
v = 0
if bv & 4:
v = load(b + 16 * i, 128)
ymm[i].dq[1] = v
if rfbm & 0x20: # AVX-512: k0 to k7
b = a + xsave_offset(5, c)
for i in range(8):
v = 0
if bv & 0x20:
v = load(b + 8 * i, 64)
opmask[i] = v
if rfbm & 0x40: # bits 511:256 of zmm0-15
b = a + xsave_offset(6, c)
for i in range(16):
v = 0
if bv & 0x40:
v = load(b + 32 * i, 256)
zmm[i].qq[1] = v
if rfbm & 0x80: # zmm16 to zmm31
b = a + xsave_offset(7, c)
for i in range(16):
v = 0
if bv & 0x80:
v = load(b + 64 * i, 512)
zmm[16 + i] = v
if rfbm & 0x200: # PKRU
v = 0
if bv & 0x200:
v = load(a + xsave_offset(9, c), 32)
pkru = v
# MPX's and AMX's components (3, 4, 17, 18) likewise
u = xinuse & ~rfbm | bv & rfbm # XINUSE as Zen 5 keeps it, and
if mx != 0x1F80: # as XGETBV reads it: SSE in use
u |= 2 # while MXCSR is not 1F80H
xinuse = uRun on AMD Zen 5 (EPYC 9645): 6 cases.
Operands
| Operand | Kind | Action |
|---|---|---|
XRSTOR mem XRSTOR64 mem | ||
mem | explicit | read |
EDX | implicit | read |
EAX | implicit | read |
XCR0 | implicit | read |
Flags
None: XED records no flag that the forms test or change.
Attributes
What else XED records about the forms. How to read.
- All forms
- aligned memory operand; 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 |
|---|---|---|
XSAVE | XSAVE + OSXSAVE | Sandy Bridge, Ivy Bridge, Haswell, Broadwell, Skylake, Comet Lake, Cannon Lake, Ice Lake (client), Tiger Lake, Alder Lake, Arrow Lake, Panther Lake, Nova Lake, Skylake-SP, Cascade Lake, Cooper Lake, Ice Lake (server), Sapphire Rapids, Emerald Rapids, Granite Rapids, Diamond Rapids, Goldmont, Goldmont Plus, Tremont, Snow Ridge, Lakefield, Sierra Forest, Clearwater Forest, Knights Landing, Knights Mill, Bulldozer, Piledriver, Zen, Zen+, Zen 2, Zen 3, Zen 4, Zen 5, Zen 6 |
More XSAVE 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 2D, page 6-49 (XRSTOR)
- Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 1 (253665-093, September 2026)
- Linux kernel documentation: Using XSTATE features in user space applications
- Intel Advanced Performance Extensions (Intel APX) Architecture Specification, revision 7.0 (July 2025)
- 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.