x87
読み:エックスはちなな
外語:x87
米
Intel
の開発した
マイクロプロセッサー
である
x86
シリーズで使用できる浮動小数点演算(実数演算)機能の俗称。
目次
概要
機能
変遷
特徴
命令
製品
レジスター
80ビット
精度
仮数部
MMXとの関係
概要
機能
元々8086には浮動小数点演算機能は存在せず、別途コプロセッサーとして製品が販売されていた。これは、当時はそういった需要が殆ど無かったためである。
やがて浮動小数点演算機能が必要とされる時代になると、この機能はCPUに統合された。
CPUが認識する機械語は、CPUに統合された現在も、コプロセッサーだった当時のまま使われており、命令の互換性は維持されている。
変遷
x86 CPUの初期の時代、
8086
/
80186
/
80286
までの時代は、FPUは
コプロセッサー
であり、CPUとは別の製品として売られていたもので、必要な人は別途購入して基板上のソケットに差し込んで使用するものだった。
i386
の時代になると浮動小数点演算機能は内部に統合されて命令セットとなり、内蔵されたi386DXと、内蔵されていない廉価版のi386SXという製品展開をしていた。i386SXのユーザーは必要に応じてi387SXを基板上のソケットに差し込んで使用することができた。
i486
の時代になると、最初から浮動小数点演算機能が統合され命令セットとなったが、後に浮動小数点演算機能を省いた廉価版のi486SXが登場した。i486はコプロセッサーを必要としない設計であったので、i487SXはコプロセッサーではなくi486DXそのものであり、後のオーバードライブプロセッサーのようにCPUであるi486SXの動作を止めて代わりにi487SXが全機能を肩代わりする仕様となっていた。
Pentium
以降、これを著している時点で最新の
Core
シリーズまでは、浮動小数点演算機能は完全に統合され命令セットとなり、更に新たな命令セットとしてx87とは異なる、
MMX
、
SSE
/
SSE2
/
SSE3
/
SSE4
、
AVX
といったものが次々と搭載され現在に至っている。
特徴
命令
x87用の命令は、ESC命令として、1バイト目がD8からDFまでの命令で定義されていた。この命令は初期のCPUとしては無効命令になるが、代わりにコプロセッサーであるx87がこの命令を実行する。
x87機能がCPU時代に内蔵され命令セットとなった現在では、x87命令も当然ながらCPU自体がこれを実行する。
製品
8087 (8086/80188用)
80187 (80186用) 実質的に80387
80287 (80286用)
80287XL (80286用) IEEE 754対応
80387 (i386DX用) IEEE 754対応
80387SX (i386SX用) IEEE 754対応
i487SX (i486SX用) コプロセッサーというよりは、後のオーバードライブプロセッサーに近い製品
i487SX2 (i486SX2用) コプロセッサーというよりは、後のオーバードライブプロセッサーに近い製品
x86でFPU未対応のCPUはi486SX2が最後であり以降存在しないため、x86用の数値演算コプロセッサーは製品としては消滅した。
レジスター
x87は、CPUとは完全に独立したLSIだったので、CPUとは別のレジスターを持っている。
データレジスター(80ビット) R0〜R7の8本
制御レジスター(16ビット)
ステータスレジスター(16ビット)
タグレジスター(16ビット)
ラスト命令ポインター(48ビット)
ラストデータ(オペランド)ポインター(48ビット)
オペコード(11ビット)
x87はCPUとは異なり
スタックマシン
であり、8本のレジスターに直接代入するのではなく、スタックにPUSH/POPするようにしてメモリーと受け渡しをする。
80ビット
8本ある汎用レジスター(データレジスター)は80ビット長である。
一般的な浮動小数点数の32ビットの2倍(64ビット)と比較しても更に長い。
16ビットCPU
である8086で使うことを考えると64ビット長でも相当贅沢な仕様だったと思われるところ、更に贅沢な80ビット長となっている。
後継技術となるMMX/SSEシリーズ一式/AVXでも演算対象は
倍精度
(64ビット)迄であることを考えると、いかに贅沢な仕様であったかが分かる。
x87命令はロード/ストア命令で単精度(32ビット)/
倍精度
(64ビット)/
長倍精度
(80ビット)から選択できる。内部80ビット長である理由は定かではないが、64ビットの倍精度の演算を正確にしようとすると、誤差が生じさせないために内部のレジスターは少し長めに確保するのが望ましい。しかし長くすればするほど製造コストが上がり価格も上がってしまうので、+32ビットの96ビット長では長すぎると判断され、若干中途半端ながら+16ビットの80ビット長で折り合いが付いたのではないかと予想される。
C/C++
で扱う場合、
clang
や
GCC
では
long double
型で扱える、またGCC独自拡張で
__float80
型もあるが、
Visual C++
では未だに対応しておらず80ビット長をフルに扱うことはできない。
精度
レジスターの構成は、符号部1ビット+指数部15ビット+仮数部64ビット(実質65ビット)で、指数に+16383のゲタをはかせるバイアス方式、基数2の80ビット長である。
この場合、有効桁数は10進数表現で19桁程度である。
仮数部
80ビットの中に収められる仮数部の長さは64ビットだが、実際にはこの精度は65ビットとされている。
これは、0/NaN/∞などを除いて、正規化により「1.」の部分を暗黙的に定義することでビット数を稼ぎ、都合65ビット相当としているためである。この「1.」は、「暗黙の整数ビット」や「implicit」などと呼ばれている。
「1.」が存在するが、0は0で別途、指数部=仮数部=0の場合に0として定義されており、表現することが可能である。
MMXとの関係
x86シリーズとして初のSIMD命令セットとなる
MMX
は、64ビット幅のMMXレジスターを8本持っている。
x87命令は殆ど使われておらず、ゆえに殆ど使われていなかったx87レジスター用の内部メモリーの有効活用目的もあり、MMXで使うMMレジスターはx87のレジスターと共用で同じ内部物理レジスターにマッピングされている。MMXでは、80ビットあるうちの64ビットを使用する。
再検索