[followups set to c.arch which I read]
Robert said:
They do! How else would you propagate an FDIV-like bugfix?
You cannot in fact fix any errors of the FDIV kind.
This is because FDIV is/was a non-priviledged opcode, with no way for
the OS/kernel to trap attempts to divide (by good or bad divisors).
I wrote the FDIV workaround code, and the way it worked was by replacing
all FDIV opcodes generated by nearly all x86 compilers:
Instead of a regular FDIV it would generate a call to a fixup function.
This function would first check if the current cpu actually had the bug
or not.
If not, then the CALL FIXUP instruction could be back-patched into a
normal FDIV followed by a few NOPs to make the size work out correctly.
If the bug was present, then the fixup function would go through a
number of steps to make everything work out:
- Store the (64-bit) divisor in memory, then inspect the top 10 bits of
the mantissa. If this number in the [0-1023] range did not correspond to
one of the 5 values which could trigger the bug, then the fixup function
would just jump to a regular FDIV opcode and return. This entire
operation took less than twice as long as a normal inline FDIV, so the
actual overhead was pretty reasonable since very few programs do nothing
but back-to-back FDIVs.
- If the mantissa turned out to be problematical (odds of 5:1024), then
more work was needed:
-- Save the current fp control word, then set the FPU to extended
(80-bit) mode.
-- Multiply both dividend and divisor by 15/16. Since this happened in
extended mode, both operations were exact.
-- Restore the original (64-bit) control word
- Finally, do the FDIV (with 80-bit inputs and 64-bit result!) and
return with the result.
Terje