🐢

昔のFPUはCPUと別チップだったという話

2023/02/27に公開

「CPUで浮動小数点演算はFPUで行います。」と書かれていたとして、これをFPUって何?と思う若者がいるかもしれません。FPU( Floating-Point Unit)は昔はCPUとは別のチップになっていて、FPUコプロセッサと呼ばれていました。

https://en.wikipedia.org/wiki/Floating-point_unit

組み込み用のマイクロコントローラを除いては、現代ではFPUはCPUに内蔵されているが普通です。FPUコプロセッサのチップはもうすっかり見なくなりました。

以下、記憶の範囲内で書いています。不正確なところがあったらごめんなさい。

パソコン向けCPUでの話

パソコン用のCPUではFPUが内蔵されたのはintelのCPUで言うと80486からです。それまでのパソコンのマザーボードにはFPUを挿すためソケットが用意されていて、必要な人は別途FPUコプロサッサを買って取り付けるということをしていました。
その頃に、FPUコプロサッサをつけると〇〇のアプリの動作が早くなるをいう話を聞いたことがありますが、自分では体験していないので真偽はわかりません。   本当だとしたら、FPUコプロサッサの有無をチェックして、それぞれ別の演算ライブラリを使用するようになっていたということですよね。

** 2023/03/01 修正 **
最初は上記の〇〇のアプリのところをExcelと書いていたのですが、私の記憶違いであることがわかりました。
Excelが普及したのはWindows3.1以降ですが、この話を聞いたのはNECのPC-9801シリーズが主流だった頃の話でした。なので、〇〇に該当するのは、その頃に有名だったソフトだと思います。可能性があるのは一太郎、松、ロータス1-2-3 などです。

同期の仲間に一緒に思い出してもらったのですが、ドロー/ペイント系ソフトはFPUコプロサッサの追加の効果がありそうです。花子/Canvas/CorelDrawなど。あとDTPのQuarkExpressなどです。
ビジネスソフトでは、Lotus 1-2-3, AutoCADはFPUコプロサッサ対応していたそうです。
** 2023/03/01 修正 ここまで **

486シリーズも最初の頃は486SXというFPU無しで値段の安いものがありました。それを採用したパソコンはそれまで通りCPUのすぐ隣にFPUのソケットがついていました。FPUコプロセッサは487という型番でした。
486SXと区別するために、FPUを内蔵している本来の486は486DXと呼ばれるようになりました。でも実際には487と486DXはほぼ同じものだったらしいです。ソケットに487を挿すと元々ついていた486SXは動作を停止して、全て487(実態はCPU+FPU)が処理をするようになっていたそうです。486DXを製造してテストしたときにFPUにエラーがあったけどそれ以外は大丈夫だったものをFPUを無効化して486SXとして売り物にしたのではないかと思っています。

ちなみに486DX2というのは入力のクロックに対して内部が2倍のクロックで動くようになっているものです。(なんでそんなことができるのかさっぱり理解できませんが、これはそういうものだと割り切ります w)
私が買った最初のWindowsパソコンは486DX2 66MHz(クリスタルは33MHz), メモリ16MB。
電源を入れるとまずPC-DOS/V 6.3が起動して、そこからwinというコマンドでWindows 3.1 が起動しました。1994年くらいでしょうか。

Armの話

組み込み向けのCPU、例えばArmのシリーズで言うとFPU内蔵が一般的になったのは ARM11の頃からです。
このCPUは3Gの携帯電話(NTTドコモならFOMAシリーズ)などで使われました。

先ほど出た「FPUの有無をチェックして、それぞれ別の演算ライブラリを使用する」という話ですが、けっこう面倒です。組み込みシステムの場合はFPUを後から追加するというのはまれなので、システム構築の時点でFPUの有無は決め打ちにしてしまいます。しかし、中にはFPUがある前提でコンパイルされた外部ライブラリをそのまま利用したいということがまれにありました。そのためARM用のLinuxカーネルのビルドオプションにはCONFIG_FPE_NWFPEというものがあり、これを=yにしてビルドすると、FPUが無いのにFPU命令を実行したときに発生するFPU例外の中でソフトウェアによるエミュレーションをしてから戻るということができました。
ただしこれはオーバーヘッドが大きいために非常に遅いし、実際にこれを使う人はほとんどいないということで、2015年に調べた時点でDeprecated(非推奨)になっていました。現在のカーネルのソースではすでに削除されています。

Go言語のARMの浮動小数点演算のトリッキーなコード生成

2015年の話なので、今は違っているかもしれません。
https://embedded.hatenadiary.org/entry/20150224/p1

要するに、FPUのないARMv5(=ARM9)向けであってもコンパイラは浮動小数点演算はFPUをつかったコードを生成し、リンカーがその直前にFPU命令をエミュレーションするライブラリに飛ぶコードを挿入するということでした。
先ほどのカーネルでのFPUエミュレーションと違って、ユーザーランド側だけで完結します。また、FPU命令は塊として連続で使用されるようにコードが生成され、それらはまとめてエミュレーションされていたので、エミュレーションモードへの出入りのオーバーヘッドは抑えられるようになっていました。

AArch64の話

AArch64(Armの64bitアーキテクチャ)ではFPUは必須となりました。つまりOSやコンパイラ、ライブラリ開発者はFPUが無い場合というのを一切考慮する必要がなくなりました。古いしがらみを断ち切ったのでこういう英断をすることができました。

SH4の話(2023/02/27追記)

SH4は組み込み分野で使われるわりには早い時期からFPUを内蔵していました。(ゲーム機ドリームキャストで採用されていました)
SH4が出たばかりの頃だと思うのですが、整数の除算を書いてgccでコンパイルして生成されたコードを見てみると、一度フロートに変換してからFPUで除算を行い、結果をまた整数に変換するというコードが生成されていました。当時は整数の除算の命令がなかったか、非常に遅かったためだと思います。
当時OSを書いていた立場からすると、FPUを使わないと思っていた場面で突如FPUを使われて驚いた記憶があります。[1]

https://twitter.com/tetsu_koba/status/1630114673403252738?conversation=none

同じように感じた人がいたのかわかりませんが、その後のバージョンのgccでは整数の除算で勝手にFPUを使うことはしなくなったと記憶しています。

関連

https://zenn.dev/tetsu_koba/articles/40b6a6badae77e
https://zenn.dev/tetsu_koba/articles/732279afbb1759
https://embedded.hatenadiary.org/entry/20140527/p1

脚注
  1. Twitterでこれの裏付けとなるリンクを教えてもらいました。2005年頃のことでした。https://www.toppers.jp/TOPPERS-USERS/200511/msg00005.html ↩︎

Discussion