Function:
FSTENV saves the FPU environment to the memory operand.
See <FPU environment image layout>.
This environment does not include the FPU stack, but does include
Control Word, Status Word, Tag Word and exception pointers.
The FPU does not execute this instruction until all pending FPU
operations have completed (decoded instructions have been processed).
After completion, FSTENV initializes the FPU as if it had executed FINIT.
Apparently on all FPUs, the contents of the data pointer field is
undefined if the last FPU arithmetic instruction did not use a memory
operand.
On some 386s operating in Real or V86 mode, the opcode saved is incorrect.
The linear address saved for the opcode's address however is correct and
can be used to retrieve the opcode. No opcode is saved in Protected mode.
If either of the two last bytes of the image being saved by FSTENV cannot
be accessed for whatever reason, the instruction cannot be restarted on
some 387s.
A workaround is to attempt to write to those bytes before the FSTENV is
executed or to align the image on a 128 byte boundary so it is
unlikely to fall outside a segment or page boundary.
Should that be the case, the integer unit can cause an exception or
make sure the page (in case of a swapped page) is read into memory
before FSTENV starts.
Layout of environment & state stored by FSTENV and FSAVE
──────────────────────────────────────────────────────────────────────────────
The environment area saved by <FSTENV> and loaded by <FLDENV> depends on the
current operating mode of the FPU. Apart from the mode, the current
default addressing mode within the operating mode is also important.
The state information saved by <FSAVE> and loaded by <FRSTOR>
consists of the environment mentioned above but also has the eight FPU
stack registers appended to it in temporary real format starting with the
current ST register. Note that which register represents ST depends on
the values in the Control Word.
There are four states in which the 387+ FPU can operate
16-bit real or V86 mode (like in DOS)
16-bit Protected Mode (16-bit code segment)
32-bit real or V86 mode (using 66h and 67h prefixes)
32-bit Protected Mode (32-bit code segment)
16-bit real or V86 mode:
15 12 8 4 0
┌─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬┴┐
│d│d│d│d│0│0│0│0│0│0│0│0│0│0│0│0│ d = Data pointer bits 16 - 19
├─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┤
│ Data pointer bits 0-15 │
├─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┤ bit 11 is zero, not a typo.
│i│i│i│i│0│o│o│o│o│o│o│o│o│o│o│o│ i = Instruction pointer bits 16 - 19
├─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┤ o = Opcode highest 11 bits
│ Instruction pointer bits 0-15 │
├───────────────────────────────┤
│ Tag Word (16 bit) │
├───────────────────────────────┤
│ Status Word (16 bit) │
├───────────────────────────────┤
│ Control Word (16 bit) │ Low memory
└───────────────────────────────┛
16-bit Protected Mode:
15 12 8 4 0
┌─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬┴┐
│ Data selector │
├───────────────────────────────┤
│ Data offset │
├───────────────────────────────┤
│ Instruction selector │
├───────────────────────────────┤
│ Instruction offset │
├───────────────────────────────┤
│ Tag Word (16 bit) │
├───────────────────────────────┤
│ Status Word (16 bit) │
├───────────────────────────────┤
│ Control Word (16 bit) │ Low memory
└───────────────────────────────┛
32-bit Real Mode:
31 28 24 20 15 12 8 4 0
┌─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┬┴┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬┴┐
│0│0│0│0│ Data pointer bits 16-31 │0│0│0│0│0│0│0│0│0│0│0│0│
├─┴─┴─┴─┼───────────────────────┼───────┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┤
│- - - - - - - - - - - - - - - -│ Data pointer bits 0-15 │
├─┬─┬─┬─┼───────────────────────┼───────┼─┼─────────────────────┤
│0│0│0│0│ Instruction pointer bits 16-31│0│ Opcode top 11 bits │
├─┴─┴─┴─┴───────────────────────┼───────┴─┴─────────────────────┤
│- - - - - - - - - - - - - - - -│ Instruction pointer 0-15 │
├───────────────────────────────┼───────────────────────────────┤
│- - - - - - - - - - - - - - - -│ Tag Word (16 bit) │
├───────────────────────────────┼───────────────────────────────┤
│- - - - - - - - - - - - - - - -│ Status Word (16 bit) │
├───────────────────────────────┼───────────────────────────────┤
│- - - - - - - - - - - - - - - -│ Control Word (16 bit) │
└───────────────────────────────┴───────────────────────────────┛
Low memory
32-bit Protected Mode:
31 28 24 20 15 12 8 4 0
┌─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┬┴┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬─┼─┬─┬─┬┴┐
│- - - - - - - - - - - - - - - -│ Data selector │
├───────────────────────────────┼───────────────────────────────┤
│ Data offset (32-bit) │
├───────────────────────────────┼───────────────────────────────┤
│- - - - - - - - - - - - - - - -│ Instruction selector │
├───────────────────────────────┼───────────────────────────────┤
│ Instruction offset (32-bit) │
├───────────────────────────────┼───────────────────────────────┤
│- - - - - - - - - - - - - - - -│ Tag Word (16 bit) │
├───────────────────────────────┼───────────────────────────────┤
│- - - - - - - - - - - - - - - -│ Status Word (16 bit) │
├───────────────────────────────┼───────────────────────────────┤
│- - - - - - - - - - - - - - - -│ Control Word (16 bit) │
└───────────────────────────────┴───────────────────────────────┛
Low memory