5 ms·
How does an FPU get out of sync with a CPU? Wouldn't the CPU automatically wait for the FPU logic to complete (just like with every other instruction)?
by Varriount 3y ago
How does an FPU get out of sync with a CPU? Wouldn't the CPU automatically wait for the FPU logic to complete (just like with every other instruction)?
- winternewt 3y agoNope. That's why the FWAIT instruction exists.
- projektfu 3y agoThis is the Intel recommended exception handler: • Store the NPX environment (control, status, and tag words, operand and instruction pointers) as it existed at the time of the exception. • Clear the exception bits in the status word. • Enable interrupts on the CPU. • Identify the exception by examining the status and control words in the save environment. • Take some system-dependent action to rectify the exception. • Return to the interrupted program and resume normal execution. and one of the examples for writing the handler is this: SAVE_ENVIRONMENT PROC ; ; SAVE CPU REGISTERS, ALLOCATE STACK SPACE FOR 80287 ENVIRONMENT PUSH BP MOV BP,SP SUB SP, 14 ; SAVE ENVIRONMENT, WAIT FOR COMPLETION, ; ENABLE CPU INTERRUPTS FNSTENV [BP-14] FWAIT STI ; ; APPLICATION EXCEPTION-HANDLING CODE GOES HERE ; ; CLEAR EXCEPTION FLAGS IN STATUS WORD ; RESTORE MODIFIED ; ENVIRONMENT IMAGE MOV BYTE PTR [BP-12] , 0H FLDENV [BP-14] ; DE-ALLOCATE STACK SPACE, RESTORE CPU REGISTERS MOV SP,BP POP BP ; ; RETURN TO INTERRUPTED CALCULATION IRET SAVE_ENVIRONMENT ENDP Make of that as you like. I am somewhat curious about what happened here.
- peterfirefly 3y agoThe 8087 and 8086/8088 (and 80287/80286) perform a complicated dance to cooperate on the execution of FPU instructions. The (2)87 has an output pin that is active when the FPU is busy. It is connected to an input pin on the CPU and the WAIT/FWAIT instruction waits until that pin isn't active anymore. The 80386 with the 80287 or 80387 did the same thing. The dance also involves the FPU snooping on the address and data buses (multiplexed on the same pins on the 8086/8088). The FPU can see which memory reads are instruction fetches + the CPU helpfully tells the world what it does with the instruction prefetch queue (it gets flushed sometimes). The FPU maintains its own copy of the prefetch queue so it sees the same instruction bytes as the CPU and in the same order. The CPU also helpfully says when it gets the first byte from the queue. This is how the FPU knows when to look for an ESC opcode (all the 80(2)87 opcodes are ESC opcodes -- the CPU doesn't know what they are). If the ESC opcode has a memory operand, the CPU performs a dummy read. The FPU snoops on that -- and sees what address the CPU uses. If the FPU instruction involves reading from memory, it also stores whatever data the memory returns. If the FPU needs to write to memory or it needs to read more memory, it will request bus access from the CPU. When it gets it, it will issue the memory requests it needs and then relinquish the bus again. The 486 had the FPU integrated and no longer had to do any of that. This also opened up the possibility of fp comparison instructions that set the CPU flags directly -- prior to that, you would execute an fp comparison instruction on the FPU, write the FPU status flags to memory with another fp instruction, read them back to the AX register with a CPU instruction, use the SAHF instruction to write them to the CPU flags, and only then do a conditional branch. The Pentium Pro introduced the FCOMI/FCOMIP/FUCOMI/FUCOMIP instructions that short-circuited that: it's just the FCOMI/... instruction directly followed by the conditional branch. Much better.