Ken Shirriff opened up an Intel 8087 with a microscope and reverse-engineered the microcode for FSCALE, the instruction that scales a floating-point number by a power of two by adding to its exponent. He expected something close to trivial. It is not: FSCALE runs 140+ micro-instructions and three levels of subroutine calls, almost all of it handling special cases.
What the chip has to cope with:
- 80-bit “temporary real” values: sign, 15-bit biased exponent, 64-bit significand
- Hidden tags per register — valid, special (inf/NaN/denorm), zero, empty
- Four rounding modes, signed zeros, projective/affine infinity, denorms, and an entire family of NaNs
- Exceptions that can be masked (keep computing, return best-effort value) or unmasked (interrupt)
The actual work is small. The normal path is about 22 micro-instructions: bail if either argument is zero, convert the scale argument from float to integer by shifting right 0x403e - exponent bits (the exponent is biased by 16383, hence the constant from a dedicated exponent constant ROM), add that integer to the other operand’s exponent, then let the exponent converter check for overflow. Everything else is edge cases, and they are shared machinery:
SPECIAL_TMPSis a general subroutine used by arithmetic ops,FSCALE,FTST, andFPREM— it converts denorms to unnorms, catches empty-stack access, and prioritizes competing special cases.- If both operands are NaN, the microcode compares them and returns the larger. That is deliberate: NaN payloads are a channel programmers can use, so a “larger NaN wins” rule preserves some information.
NONNORMAL_RESULTdelegates overflow/underflow detection to the exponent converter, so a whole algorithm becomes one micro-instruction.- On an unmasked interrupt, the stored exponent is nudged by ±
0x6000so the handler can recover the value that did not fit.
Two details worth the click. A conditional jump on “round up” quietly updates the programmer-visible CC1 condition code — behavior Intel did not document until the 387SX in 1987. And complexity has a price tag: the 8087 uses 3.3K of microcode where Intel’s software emulator for 8086 machines needed 16K.
The lesson generalizes past silicon. The instruction is simple; the contract is not. Whether complexity lands in hardware, firmware, or a library, someone has to pay for every corner case — and the 8087 paid in microcode so that programmers could stop thinking about floating-point.