Microcode in Intel's 8087 floating-point chip: the scale instruction
Analysis of Microcode in the Intel 8087: The FSCALE Instruction
By Ken Shirriff (via his blog on computer history and IC reverse engineering)
During the 1970s, the state of floating-point arithmetic was organized a complete disaster. Computer vendors utilized a plethora of incompatible standards, and most systems prioritized hardware simplicity over mathematical precision, which frequently resulted in poor numerical stability.
This landscape shifted dramatically in 1980 with the release of the Intel 8087 floating-point coprocessor. This chip was engineered for maximum accuracy, even when dealing with extreme corner cases. Its popularity surged because it could be added to the IBM PC, accelerating floating-point tasks—such as CAD software and spreadsheets—by as much as 100 times. More significantly, the 8087 established the floating-point standard that remains prevalent in modern computing.
The Architecture of Microcode
The 8087 does not execute instructions directly in hardware; instead, it uses microcode—a complex, low-level internal language.
I am currently collaborating with the Opcode Collective to reverse-engineer this microcode. My recent focus has been on the
FSCALE(Floating-point Scale) instruction.
The FSCALE instruction is designed to scale a number by a power of two, which is computationally "cheaper" than performing a full multiplication. While it initially seemed like a trivial operation, the reality is far more complex:
- It requires over 140 micro-instructions.
- It utilizes three levels of subroutine calls to manage various edge cases.
Despite this complexity, FSCALE serves as a perfect window into the 8087's inner workings, specifically its shifter, adder, and exponent converter.
Hardware Exploration
To analyze the chip, I used a microscope to capture high-resolution imagery of the 8087 die.

The chip's layout can be summarized as follows:
- Microcode ROM: Located centrally, containing 1,648 micro-instructions.
- Microcode Engine: Situated on the left; it manages the execution flow, including jumps and subroutines.
- Datapath: The bottom section, divided into:
- A 16-bit path for exponents.
- A 64-bit path for the significand (fractional part).

Key Datapath Components
- Exponent Converter: Handles format conversion and detects special exponent values.
- Shifter: A massive component capable of shifting 64-bit values left or right by any amount.
- Adder: The core of the chip, used iteratively for square roots, division, and multiplication.
- B Register: Provides one of the primary inputs to the adder.
- Registers: Includes eight stack registers and several temporary registers.
Technical Specifications of the 8087
To understand FSCALE, one must understand how the 8087 handles data.
Register Management
The 8087 uses a stack of eight internal registers. To boost efficiency, each register has an associated tag:
- Special: Indicates the value is NaN, infinity, or denormalized.
- Empty: Indicates the register has been popped and contains no valid data.
Internally, the chip uses temporary registers: tmpA, tmpB, and tmpC. While the 8087 supports various data types (integers, BCD, etc.), it converts everything internally to an 80-bit "temporary real" format.
The "Temporary Real" Format
A temporary real consists of a sign bit, a 15-bit exponent, and a 64-bit significand. Mathematically, the value is represented as:
The significand is normalized as (a leading 1 followed by the binary point).

Crucial Detail: The Exponent Bias The exponent ranges from to . To avoid storing negative numbers, the 8087 adds a bias of 16383.
Stored Exponent = Actual Exponent + 16383
Special Values and Exceptions
The 8087 uses specific exponent patterns to represent non-standard numbers:
| Value Type | Exponent Bits | Significand Bits | Description |
|---|---|---|---|
| NaN | High | Variable | "Not a Number" (e.g., ) |
| Denormal | Zero | Non-zero | Extremely small values (no leading 1) |
| Unnormalized | Low | Variable | Values where the leading bit is 0 |

The chip also implements a robust exception system with six distinct error types. The most critical is the "invalid operation" exception, which triggers when a mathematically undefined operation is attempted.
