background image

8-32 Vol. 1

PROGRAMMING WITH THE X87 FPU

Synchronization problems occur in the time between the moment when the exception is signaled and when it is 
actually handled. Because of concurrent execution, integer or system instructions can be executed during this 
time. It is thus possible for the source or destination operands for a floating-point instruction that faulted to be 
overwritten in memory, making it impossible for the exception handler to analyze or recover from the exception.
To solve this problem, an exception synchronizing instruction (either a floating-point instruction or a WAIT/FWAIT 
instruction) can be placed immediately after any floating-point instruction that might present a situation where 
state information pertaining to a floating-point exception might be lost or corrupted. Floating-point instructions 
that store data in memory are prime candidates for synchronization. For example, the following three lines of code 
have the potential for exception synchronization problems:

FILD COUNT 

;Floating-point instruction

INC COUNT 

;Integer instruction

FSQRT 

;Subsequent floating-point instruction

In this example, the INC instruction modifies the source operand of the floating-point instruction, FILD. If an 
exception is signaled during the execution of the FILD instruction, the INC instruction would be allowed to overwrite 
the value stored in the COUNT memory location before the floating-point exception handler is called. With the 
COUNT variable modified, the floating-point exception handler would not be able to recover from the error.
Rearranging the instructions, as follows, so that the FSQRT instruction follows the FILD instruction, synchronizes 
floating-point exception handling and eliminates the possibility of the COUNT variable being overwritten before the 
floating-point exception handler is invoked.

FILD COUNT 

;Floating-point instruction

FSQRT      

;Subsequent floating-point instruction synchronizes

           

;any exceptions generated by the FILD instruction.

INC COUNT  

;Integer instruction

The FSQRT instruction does not require any synchronization, because the results of this instruction are stored in 
the x87 FPU data registers and will remain there, undisturbed, until the next floating-point or WAIT/FWAIT instruc-
tion is executed. To absolutely insure that any exceptions emanating from the FSQRT instruction are handled (for 
example, prior to a procedure call), a WAIT instruction can be placed directly after the FSQRT instruction.
Note that some floating-point instructions (non-waiting instructions) do not check for pending unmasked excep-
tions (see Section 8.3.11, “x87 FPU Control Instructions”). They include the FNINIT, FNSTENV, FNSAVE, FNSTSW, 
FNSTCW, and FNCLEX instructions. When an FNINIT, FNSTENV, FNSAVE, or FNCLEX instruction is executed, all 
pending exceptions are essentially lost (either the x87 FPU status register is cleared or all exceptions are masked). 
The FNSTSW and FNSTCW instructions do not check for pending interrupts, but they do not modify the x87 FPU 
status and control registers. A subsequent “waiting” floating-point instruction can then handle any pending excep-
tions.

8.7 

HANDLING X87 FPU EXCEPTIONS IN SOFTWARE

The x87 FPU in Pentium and later IA-32 processors provides two different modes of operation for invoking a soft-
ware exception handler for floating-point exceptions: native mode and MS-DOS compatibility mode. The mode of 
operation is selected by CR0.NE[bit 5]. (See Chapter 2, “System Architecture Overview,” in the Intel® 64 and 
IA-32 Architectures Software Developer’s Manual, Volume 3A,
 for more information about the NE flag.)

8.7.1 Native 

Mode

The native mode for handling floating-point exceptions is selected by setting CR0.NE[bit 5] to 1. In this mode, if the 
x87 FPU detects an exception condition while executing a floating-point instruction and the exception is unmasked 
(the mask bit for the exception is cleared), the x87 FPU sets the flag for the exception and the ES flag in the x87 
FPU status word. It then invokes the software exception handler through the floating-point-error exception (#MF, 
exception vector 16), immediately before execution of any of the following instructions in the processor’s instruc-
tion stream:

The next floating-point instruction, unless it is one of the non-waiting instructions (FNINIT, FNCLEX, FNSTSW, 
FNSTCW, FNSTENV, and FNSAVE).