Learn Something Old Every Day, Part XVIII: How Does FPU Detection Work?
a day ago
- #FPU Detection
- #Historical Computing
- #x86 Architecture
- FPU detection on old PCs was necessary because math co-processors were often absent or expensive add-ons.
- The 8086/8087 used a generic co-processor interface with ESC instructions; detection required non-waiting forms like FNINIT/FNSTSW to avoid hangs on 8086 without an FPU.
- On 286 and later CPUs, Intel's documentation omitted ESC instructions, but the CPU still decoded them and handled FPU tasks, with memory accesses performed by the CPU even without an FPU.
- The 286/287 interface changed: the 287 used I/O ports, and the 286 managed BUSY line testing, eliminating the need for explicit WAIT instructions.
- Parallelism between CPU and FPU existed, with control and math instructions handled separately; synchronization was managed via WAIT or non-waiting forms.
- Without an FPU, 286/386/486 CPUs still execute some FPU instructions (e.g., FNSTSW writes to memory), relying on bus behavior for detection.
- Coprocessor Segment Overrun (Interrupt 9) was a non-restartable exception on 286/386, but removed in 486, indicating increased CPU knowledge of FPU operations.
- The 386 and 486SX track FPU state (e.g., instruction/data pointers) and validate memory operands, even without an FPU, showing the interface evolved to be FPU-specific.
- Safe FPU detection involves using FNINIT and FNSTCW with initialized memory, checking for specific values (e.g., high byte 0x03) to confirm presence.
- Differences exist between vendors (Intel, AMD, Cyrix) in behavior without an FPU, highlighting undocumented aspects of detection.