Volume 1 Basic Architecture (794100), страница 58
Текст из файла (страница 58)
If floating-pointexceptions are pending, the x87 FPU makes an implicit call (traps) to the floatingpoint software exception handler. The exception handler can then execute recoveryprocedures for selected or all floating-point exceptions.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 forthe source or destination operands for a floating-point instruction that faulted to beoverwritten in memory, making it impossible for the exception handler to analyze orrecover from the exception.To solve this problem, an exception synchronizing instruction (either a floating-pointinstruction or a WAIT/FWAIT instruction) can be placed immediately after anyfloating-point instruction that might present a situation where state informationpertaining to a floating-point exception might be lost or corrupted. Floating-pointinstructions that store data in memory are prime candidates for synchronization. Forexample, the following three lines of code have the potential for exception synchronization problems:FILD COUNTINC COUNTFSQRT;Floating-point instruction;Integer instruction;Subsequent floating-point instructionIn this example, the INC instruction modifies the source operand of the floating-pointinstruction, 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 COUNTmemory location before the floating-point exception handler is called. With theCOUNT variable modified, the floating-point exception handler would not be able torecover from the error.Rearranging the instructions, as follows, so that the FSQRT instruction follows theFILD instruction, synchronizes floating-point exception handling and eliminates thepossibility of the COUNT variable being overwritten before the floating-point exception handler is invoked.FILD COUNTFSQRTINC COUNT;Floating-point instruction;Subsequent floating-point instruction synchronizes;any exceptions generated by the FILD instruction.;Integer instructionThe FSQRT instruction does not require any synchronization, because the results ofthis instruction are stored in the x87 FPU data registers and will remain there, undisturbed, until the next floating-point or WAIT/FWAIT instruction 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 directlyafter the FSQRT instruction.8-44 Vol. 1PROGRAMMING WITH THE X87 FPUNote that some floating-point instructions (non-waiting instructions) do not check forpending unmasked exceptions (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, allpending exceptions are essentially lost (either the x87 FPU status register is clearedor all exceptions are masked). The FNSTSW and FNSTCW instructions do not checkfor pending interrupts, but they do not modify the x87 FPU status and control registers. A subsequent “waiting” floating-point instruction can then handle any pendingexceptions.8.7HANDLING X87 FPU EXCEPTIONS IN SOFTWAREThe x87 FPU in Pentium and later IA-32 processors provides two different modes ofoperation for invoking a software exception handler for floating-point exceptions:native mode and MS-DOS compatibility mode. The mode of operation is selected byCR0.NE[bit 5].
(See Chapter 2, “System Architecture Overview,” in the Intel® 64 andIA-32 Architectures Software Developer’s Manual, Volume 3A, for more informationabout the NE flag.)8.7.1Native ModeThe native mode for handling floating-point exceptions is selected by settingCR0.NE[bit 5] to 1. In this mode, if the x87 FPU detects an exception condition whileexecuting a floating-point instruction and the exception is unmasked (the mask bitfor the exception is cleared), the x87 FPU sets the flag for the exception and the ESflag in the x87 FPU status word.
It then invokes the software exception handlerthrough the floating-point-error exception (#MF, vector 16), immediately beforeexecution of any of the following instructions in the processor’s instruction stream:•The next floating-point instruction, unless it is one of the non-waiting instructions(FNINIT, FNCLEX, FNSTSW, FNSTCW, FNSTENV, and FNSAVE).••The next WAIT/FWAIT instruction.The next MMX instruction.If the next floating-point instruction in the instruction stream is a non-waitinginstruction, the x87 FPU executes the instruction without invoking the softwareexception handler.8.7.2MS-DOS* Compatibility Sub-modeIf CR0.NE[bit 5] is 0, the MS-DOS compatibility mode for handling floating-pointexceptions is selected.
In this mode, the software exception handler for floatingpoint exceptions is invoked externally using the processor’s FERR#, INTR, andIGNNE# pins. This method of reporting floating-point errors and invoking an excep-Vol. 1 8-45PROGRAMMING WITH THE X87 FPUtion handler is provided to support the floating-point exception handling mechanismused in PC systems that are running the MS-DOS or Windows* 95 operating system.The MS-DOS compatibility mode is typically used as follows to invoke the floatingpoint exception handler:1. If the x87 FPU detects an unmasked floating-point exception, it sets the flag forthe exception and the ES flag in the x87 FPU status word.2.
If the IGNNE# pin is deasserted, the x87 FPU then asserts the FERR# pin eitherimmediately, or else delayed (deferred) until just before the execution of the nextwaiting floating-point instruction or MMX instruction. Whether the FERR# pin isasserted immediately or delayed depends on the type of processor, theinstruction, and the type of exception.3. If a preceding floating-point instruction has set the exception flag for anunmasked x87 FPU exception, the processor freezes just before executing thenext WAIT instruction, waiting floating-point instruction, or MMX instruction.Whether the FERR# pin was asserted at the preceding floating-point instructionor is just now being asserted, the freezing of the processor assures that the x87FPU exception handler will be invoked before the new floating-point (or MMX)instruction gets executed.4. The FERR# pin is connected through external hardware to IRQ13 of a cascaded,programmable interrupt controller (PIC).
When the FERR# pin is asserted, thePIC is programmed to generate an interrupt 75H.5. The PIC asserts the INTR pin on the processor to signal the interrupt 75H.6. The BIOS for the PC system handles the interrupt 75H by branching to theinterrupt 02H (NMI) interrupt handler.7. The interrupt 02H handler determines if the interrupt is the result of an NMIinterrupt or a floating-point exception.8.
If a floating-point exception is detected, the interrupt 02H handler branches tothe floating-point exception handler.If the IGNNE# pin is asserted, the processor ignores floating-point error conditions.This pin is provided to inhibit floating-point exceptions from being generated whilethe floating-point exception handler is servicing a previously signaled floating-pointexception.Appendix D, “Guidelines for Writing x87 FPU Exception Handlers,” describes theMS-DOS compatibility mode in much greater detail. This mode is somewhat morecomplicated in the Intel486 and Pentium processor implementations, as described inAppendix D.8.7.3Handling x87 FPU Exceptions in SoftwareSection 4.9.3, “Typical Actions of a Floating-Point Exception Handler,” shows actionsthat may be carried out by a floating-point exception handler. The state of the x878-46 Vol. 1PROGRAMMING WITH THE X87 FPUFPU can be saved with the FSTENV/FNSTENV or FSAVE/FNSAVE instructions (seeSection 8.1.10, “Saving the x87 FPU’s State with FSTENV/FNSTENV andFSAVE/FNSAVE”).If the faulting floating-point instruction is followed by one or more non-floating-pointinstructions, it may not be useful to re-execute the faulting instruction.
See Section8.6, “x87 FPU Exception Synchronization,” for more information on synchronizingfloating-point exceptions.In cases where the handler needs to restart program execution with the faultinginstruction, the IRET instruction cannot be used directly. The reason for this is thatbecause the exception is not generated until the next floating-point or WAIT/FWAITinstruction following the faulting floating-point instruction, the return instructionpointer on the stack may not point to the faulting instruction. To restart programexecution at the faulting instruction, the exception handler must obtain a pointer tothe instruction from the saved x87 FPU state information, load it into the returninstruction pointer location on the stack, and then execute the IRET instruction.See Section D.3.4, “x87 FPU Exception Handling Examples,” for general examples offloating-point exception handlers and for specific examples of how to write a floatingpoint exception handler when using the MS-DOS compatibility mode.Vol.