Ken Shirriff has published another die-level deep dive, this time reverse-engineering how the Intel 8087 computes tangents. The 8087 was Intel’s 1980 floating-point coprocessor for the 8086 and 8088, the chip you soldered into an empty socket on an IBM PC motherboard to make spreadsheets and CAD stop crawling. It computed a tangent in about 90 microseconds, versus roughly 13,000 microseconds emulated in software on the 8086. A hundredfold speedup, and the way it got there is more interesting than the headline number.
CORDIC: trig without a multiplier
The natural assumption is that the chip used CORDIC, and it partly did. CORDIC, short for COordinate Rotation DIgital Computer, was invented by Jack Volder in 1956 for the B-58 Hustler bomber’s navigation computer. The idea is that you can compute trig functions using only shifts, adds, and a small table of constants, with no multiplication or division at all. You decompose an angle into a sum of special angles of the form arctan(2^-n) and rotate a vector by each one. Every iteration buys you one more bit of accuracy, and 1980-era silicon could handle shifts and adds cheaply while a hardware multiplier was expensive.
The 8087 uses a binary variant where each CORDIC step either applies a rotation or skips it, decided bit by bit, with the decisions recorded in a 16-bit shift register.
Why pure CORDIC was not enough
Here is the surprise. The 8087 needs 64-bit accuracy, and pure CORDIC would take 64 iterations plus a 64-entry constant table to get there. The 8087 does neither. It runs 16 bits of CORDIC, leaving a small residual angle below 2^-16, then finishes with a rational polynomial approximation, 3x/(3-x^2), on that residual. Because the polynomial’s error scales with x^4 and the residual is tiny, the total error stays under 2^-64. Sixteen CORDIC steps and one cheap rational correction replace sixty-four steps and a big ROM.
That trade is the heart of the design. Half the algorithm is the classic shift-and-add rotation engine; the other half is a Pade approximant that would be pointless on hardware without a working multiplier, and the 8087 has one, used sparingly.
The three phases
Shirriff traces the full pipeline through the microcode. FPTAN runs in three phases: pseudo-division, which produces the CORDIC decision bits; the rational polynomial step; and pseudo-multiplication, which applies the rotations. The rotations are applied smallest-first, which keeps rounding error down. The one genuinely expensive operation is squaring the angle in the polynomial phase, a full 64-bit multiply done with Booth’s algorithm in radix 4, two bits at a time, with the shift-and-add loop built into hardware rather than microcode.
The timing breakdown is worth a look. FPTAN averages about 450 clock cycles, ranging from 30 to 540 depending on the input. For a typical 0.95 radian input, 47% of the time goes to CORDIC pseudo-multiplication, 33% to pseudo-division, 15% to the rational polynomial, and the rest to overhead. Three separate microcode paths handle tiny, small, and normal inputs, so very small arguments skip CORDIC entirely and jump straight to the approximation.
The free division trick
One quirk that confused a generation of assembly programmers: FPTAN does not return the tangent. It returns two values, a numerator and a denominator, whose ratio is the tangent. That sounds like an inconvenience, but it is a deliberate optimization. Division was the slowest operation on the chip, and by handing back the pair the polynomial’s denominator never needs an explicit division at all. The cost lands on the caller, who usually wanted the ratio anyway. The same shape shows up in FPATAN, which computes arctan of a ratio of two stack registers and exists largely for rectangular-to-polar conversion.
Die space explains another limitation people forget. The 8087 supported only tangent and arctangent natively, not sine and cosine. Programmers derived those from identities, because there simply was no room for more transcendental units on the die. The microcode ROM holds 1,648 micro-instructions, and the constant ROM carries 16 arctan constants plus 14 log2 constants for the other transcendental functions. Even the constant 3 in the polynomial comes for free, produced by special-purpose transistors rather than a ROM entry.
What happened next
The design did not last. Once fast multipliers became cheap, Intel dropped CORDIC for polynomial approximations, starting around the Pentium era, as Intel’s own documentation describes. Modern math libraries such as MKL and SVML evaluate polynomials with SIMD instructions, and x87 with its 80-bit floats is deprecated on 64-bit platforms. CORDIC survives in places where multipliers are still expensive: FPGAs, DSPs, and low-power silicon.
What makes the piece worth reading is the method as much as the result. Shirriff extracts the microcode ROM from die photographs, two bits per transistor, then traces the instruction’s execution path step by step. He also published an interactive demo of the hybrid algorithm if you want to poke at the numbers yourself. It is a good reminder that the algorithms inside old chips were not obvious choices handed down from on high. They were engineering tradeoffs, worked out under die-area pressure, by people who had to make one multiplier count.