
2026/10/19 1:20
Intel 8087 チップによる浮動小数点加算と減算
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
インテルがIBM PC向けに1980年に発表したIntel 8087プロセッサーは、先行モデルである8086のように整数演算のみが可能なプラットフォーム上で高速な浮動小数点数学計算を可能にし、コンピューティングの分野を変革しました。チップの物理的な分析(カバーを開けて顕微鏡でダイをイメージする)により、複雑な回路構造と1648個のマクロ指令を含むマイクロコードROMが発見されました。これらは加算処理において整数プロセッサに比べて約100倍もの性能向上を実現しています。8087は高度な内部形式(15ビットの指数部と64ビットの有効数字を持つ80ビットの「仮の実数」)を採用しており、10^4932までの値を表すことができます。また、スタックベース型の独自アーキテクチャにより、有効な数値や無窮大などの特殊ケースを追跡するためのタグを管理し、機能ブロックがバイナリポイントを揃えながら上位のゼロ数をカウントすることで結果を正規化し、正確な演算を実現しています。このハードウェアは業界標準を確立し、ソフトウェアが高精度タスクのために数学ライブラリを活用することを可能にし、当時16ビットマイクロプロセッサでは不可能だったコンピューターグラフィックスや科学モデリングなどの能力を付与しました。
Text to translate:
The Intel 8087 processor, introduced by Intel in 1980 for the IBM PC, revolutionized computing by enabling fast floating-point mathematics on a platform previously limited to integer-only operations like its predecessor, the 8086. Physical analysis of the chip—popping the lid and imaging the die with a microscope—revealed sophisticated circuitry and a microcode ROM containing 1648 micro-instructions that together achieve performance nearly 100 times faster for additions than integer processors. The 8087 uses an advanced internal format (an 80-bit "temporary real" with a 15-bit exponent and 64-bit significand) capable of representing values up to 10^4932, far beyond standard integers. Its unique stack-based architecture tracks valid numbers and special cases (like infinity) via tags, while functional blocks align binary points and count leading zeros to normalize results accurately. The hardware established a new industry standard, allowing software to leverage mathematical libraries for high-precision tasks in computer graphics and scientific modeling, capabilities once impossible on 16-bit microprocessors of the era.
本文
インテル 8087:浮動小数点加減算の実装とマイクロコード解析
1980 年、インテルは IBM PC やその他のシステムにおける浮動小数点演算の大幅な高速化を実現するためのチップ 8087 を発表しました。本稿では、正接や平方根などの高度な演算ではなく、加減算といった基本的な算術操作に焦点を当てて解説します。
- 8086 プロセッサと比較し、加算は約 100 倍 のスピードアップを示し、複雑な演算ではそれ以上の高速化を実現しました¹。
- 本記事では、8087 のマイクロコードと回路の解析結果に基づき、無限大や NaN(Not a Number)などの特殊値を含むケースも含めて、浮動小数点加減算の実装方法を詳しく解説します²³。
チップの内部構造とデータパス
外部のカバーを剥ぎ顕微鏡撮影により取得した高解像度画像から、8087 の回路構造を探る手がかりが得られました⁴。
- マイクロコード ROM: 中央にある大きな長方形領域です。チップを制御する 1,648 個のマイクロ指令 を格納しています²。
- データパス: チップの下半分(赤い枠部分)であり、80 ビット値に対して浮動小数点計算を実行する回路です³。
データパスの拡大図では、加減算に使用される主要な機能ブロックが確認できます。この画像をクリックすることで拡大表示が可能です。
主要な機能ブロック
データパスの中心には以下の重要なコンポーネントがあります。
- 整数演算子: 中央に位置する最も重要なコンポーネントです。
- B レジスタから一つの実数を受け取り、一時レジスタやスタックレジスタなどからもう一つを受け取ります。
- 出力は和レジスタ(sum register)に格納されます。
- シフタ: 回路図上で多くのスペースを占めます。
- 任意の桁数のビットで値を高速に左または右にシフトする機能を持ちます。
- 浮動小数点演算では、値の対齐(align) に多用されます。
- Leading zero circuitry:
- 値の左側のゼロビットやゼロバイトの数を数えます。
- これらのゼロをシフト対象から除くために使用されます。
- 指数変換器:
- 指数を処理し、オーバーフローとアンダーフローを検出します。
浮動小数点数の基礎知識
コンピュータは整数を基本表現として使用しますが、1.23 のように小数点以下を持つ数を扱うアプリケーションでは、整数のみでは不十分です。
- 整数の限界: 32 ビット整数は約 -20 億から +20 億 の範囲しか表現できません³。
- 浮動小数点数の導入: これらの問題を解決するため、膨大な範囲で小数を含む数値を提供する浮動小数点数が実装されます⁴。
表現形式:符号×有効数字×2 の指数
多くの場合、浮動小数点数は以下の形式で表されます。
符号 × 有効数字(significand)× 2 の指数
-
有効数字:
という形式の二進数です(先頭の 1 を隠れたビットとし、その後ろに小数点と残りのビットがあります)。1.bbb…- 各ビットは 2 のべき乗を表します。
- 小数部分については、二進点以降に $2^{-1}, 2^{-2}$ などという負のべき乗が使われます。
- 例:
- 2 進数
→ $1 + 1/2 = \mathbf{1.5}$(十進法)1.1 - 2 进数
→ $1 + 1/8 + 1/16 = \mathbf{1.1875}$(十進法)1.0011
- 2 進数
-
指数の役割: 有効数字の範囲を超えた値を表現可能です。
- 例:(2 進)
= $\mathbf{384}$1.1 × 2⁸ - たとえ 32 ビットの短縮版であっても、$10^{-36}$ から $10^{38}$ を超える範囲をカバーできます。
- 例:(2 進)
加減算の複雑さ:対齐と正規化
浮動小数点の加減算は整数演算よりも複雑です。以下のステップが必要です。
- 対齐(Alignment): 計算前に二進点を一致させます(十進数の小数点合わせと同じ)。
- 演算: 有効数字同士を加算または減算します。
- 結果の正規化: 指数を調整し、有効数字が
ビットで始まるように戻します。1
加算の手順(例:13.5 + 3.5)
- 第二の引数は、第一の引数の指数と一致するように右にシフトされます(対齐)。
- 対齐された有効数字に対して整数加算を実行します。
- オーバーフローが発生し、左側に「余分な」ビットが生まれる場合があります。
- この場合、結果を 1 つ右にシフト し、指数を 1 増やす ことで正規化します。
減算の手順(例:8 - 7.5)
- 加算と同様に第二の引数を右にシフトして対齐します。
- 有効数字同士で整数減算を実行します。
- 結果を左にシフトし、上位ビットが
になるように正規化します。1- 加算と異なり、大きなシフトが必要な場合があります(例:4 ビットシフト)。
- 符号ビットの反転や、ゼロの場合の特殊処理(+0 または -0)も考慮されます。
8087 のハードウェア詳細
8087 は多様なデータタイプをサポートしていますが、内部ではすべて 「一時実数」(temporary real) という 80 ビット形式 で数字を格納します⁵。
- 構成: 符号ビット (1 ビット)、指数 (15 ビット)、有効数字 (64 ビット)。
- 指数のバイアス: 指数にはバイアスが加えられて格納され、実数の指数が負でも格納される指数は常に正になります(例:指数 -16 は
と表されます)。0x3fef
レジスタとタグ
8087 は 8 つの内部レジスタを持ち、これらはスタックとして組織されています。パフォーマンス最適化のため、各値に関連する 「タグ」 が割り当てられています⁶。
- ゼロ: 値がゼロの場合。
- 有効(valid): 通常の浮動小数点値の場合。
- 特殊(special): 無限大、NaN、非正規化値の場合。
- 空(empty): レジスタに値を持たない場合。スタックアンダーフローやオーバーフローの検出に利用されます。
内部一時レジスタ
演算処理のための特別な一時レジスタもあります。
- tmpA / tmpB: 80 ビットで、タグビット 2 つを持ちます。
- tmpC: 異なります。符号、指数、またはタグを持たず、有効数字は 68 ビット です(オーバーフロー防止のための 3 つの低位ビット「guard, round, sticky」を含んでいます)。
マイクロコードと演算子
16 ビットの各マイクロ指令が一つの低レベル操作を行います。多くの操作はデータ移動ですが、条件分岐やサブルーチン呼び出しも提供します⁷。
- 整数演算子: 8087 の心臓部である 69 ビットの整数演算子を使用します(64 ビット + 3 つの丸めビット + オーバーフロー検出用の追加ビット)。
- 整数加算には 2 つのマイクロ指令が必要です(1 番目は加算とオプション設定、2 番目は結果の移動)。
- 浮動小数点演算も同様に、大規模なビットシフタと 2 つのマイクロ指令を使用します。
加減算のマイクロコード解析
8087 はほぼ全ての操作を マイクロコード で実装しています⁸。
- すべての基本的な数学演算(加算、減算、乗算、除算)は、マイクロコード #0001 から同じ手順で開始します。
- 引数を一時レジスタ
とtmpA
へ移動し、その後特定の実演操作タイプに対応するマイクロサブルーチンにジャンプします。tmpB
マイクロサブルーチンの構造
加算/減算の処理は、主に以下の 2 つのパスに分かれます(アドレス #0232 で開始)⁹:
- 無符号加算パス(Unsigned addition): 二つの数の大きさを足し合わせます。
- 無符号減算パス(Unsigned subtraction): 二つの数の大きさから相引数をひきます(結果の符号は別途処理)。
マイクロコードフローの概要 (#0232 〜 #0298)
制御フローは非常に複雑であり、以下の主要ステップで構成されています¹⁰:
- 対齐(Alignment):
をシフトして二進点を一致させます(サブルーチンtmpB
を使用)。CREATE_DENORM - 加算/減算の実行:
- 無符号加算パス (
): 単純な整数加算。オーバーフロー時は右シフトと指数調整。#0269 - 無符号減算パス (
):#0251
を実行し、結果の符号を判定。tmpA - tmpB
- 無符号加算パス (
- 正規化(Normalization):
- オーバーフロー発生時:右にシフトし、指数を増加(
)。expAdj++ - アンダーフローやゼロ検出時:左への大規模シフトまたは特殊処理。
- オーバーフロー発生時:右にシフトし、指数を増加(
- 特殊値の判定と保存:
- 非正規化値への遷移チェック。
- 結果の指数計算(初期指数 - 調整値 + expAdj - 1)。
- 結果を適切なスタックレジスタへプッシュし、タグ更新。
特殊ケースの処理:無限大とゼロ
8087 は数学的に正確な結果を得るため、多くの特殊ケースを慎重に処理します⁶。これによりマイクロコードは複雑化しますが(「スパゲッティコード」と呼ばれるほど連なる条件分岐を含む)、IEEE-754 標準の基盤となりました¹¹。
- NaN (Not a Number):
- 定義不能な演算(例:
,∞ × 0
,∞ - ∞
)に対して返されます。0 ÷ 0 - マイクロコード #0008 で、引数が「空」や特殊値であると検出された場合、
サブルーチンが呼び出され処理されます。SPECIAL_TMPS
- 定義不能な演算(例:
- 無限大(Infinity):
- 2 つのモードあり:有符号の「Affine closure」と無符号の「Projective closure」。
- マイクロコードは、
や∞ + ∞ = ∞
など、8 つのパターンに応じて正しい無限大(および符号)を返します。n ÷ 0 = ∞
- ゼロの結果:
や0 ÷ denorm
の場合、引数の符号に基づいて正しい符号を持つn ÷ ∞
または+0
を生成します。-0
Leading zero circuitry(上位ゼロ検出回路)
減算などでは、桁が相殺されて残った上位のゼロをシフトして削除する必要があります。これには Leading-zero circuitry が使用されます¹²。
- 機能:最初の
ビットより左にあるゼロの数を数え、これを 2 進値に変換してシフト量として出力します。1 - 実装手法:8087 は簡素化されたパスを採用しました(木構造による階層的手法ではなく)。
- ステップ 1: バイト単位で上位ゼロを検出し排除。
- ステップ 2: 残りの 0〜7 ビットで上位ゼロを検出し排除。
- 回路構成:各ステップは独立した 8 入力の Leading zero 検出器を使用し、高速かつ単純な設計を実現しました。
結論と展望
インテル 8087 は、コンピュータの加減算という基本的な操作にも多くのアルゴリズムと特殊ケースが存在することを示す象徴的な製品です。
- 歴史的意義: 正負ゼロや無限大を扱う複雑なルールは現代コンピュータの一部となり、IEEE-754 浮動小数点標準の基盤となりました。
- 限界と進化: 8087 は特殊ケース処理に少しやりすぎ(Projective infinity, unnormals など)ましたが、その多くは後の標準から削除され、コスト効率の良い設計へと移行しました¹³。
著者によるリバースエンジニアリングは続行されており、最新情報は Bluesky や Mastodon などで共有されています。GitHub の 8087 リポジトリも参照可能です¹⁴。
※本稿は AI を使用せず、Opcode Collective が収集した情報と ML アルゴリズムによる解析に基づいています¹⁵。