APU

マイクロコンピュータは計算を行うのに使われることもあります。おっと、そもそもは電卓向けでしたから計算用のLSIでしたか。しかし、大半の応用は、何かスイッチが入ったら対応する動作をするとか、その程度の機器制御に使われることが多かったはずです。
たとえば1980年ごろの自動販売機の制御を考えてください。当時は紙幣を受け付ける自動販売機はありませんで、数種類の硬貨の入力と、商品の選択スイッチあたりを監視するだけで良いわけです。硬貨の分別は機械的に行われるので、単に個数を数えるだけ。せいぜい200円程度の投入金額を積算して、商品選択スイッチが押されたら対応するメカニズムを駆動して、つり銭を計算して、それを戻す機械を駆動する程度ですね。その場合、せいぜい8 bitか16 bitの整数演算があればなんとかなります。10円単位で200円程度の計算だから、8 bitでも平気ですね。なお、当時は500円硬貨に対応する必要はありませんし、自動販売機で扱う商品の代表であるたばこや飲料なんかは今ほど高くありませんでした。
しかし、たまには浮動小数点演算を高速で行えるとありがたいという応用に出会うこともあるでしょう。浮動小数点演算命令は当時のマイクロプロセッサには存在しません。ソフトウェアで実現するのが普通でした。しかし、その演算サブルーチン群を作るのも面倒で、仮に2 KByteの長さに納まったとしてもそれを格納するROMが1万円では手に入らないかもしれません。演算速度もそれほど速くありませんし。マイクロプログラム制御で浮動小数点演算を実行する演算基板が存在しましたが、多数の部品を使っていて、サイズが大きく電気を大食いして高価でした。

初期にはNational Semiconductor社のMM57109のように、電卓用のLSIの入出力部をマイクロコンピュータのバスに接続できるように改造したようなチップもありました。比較的安価(1万円しないという意味で)ですが、中身が電卓用なので、四則演算でも0.1秒くらいかかってしまいます。

本格的な高速浮動小数点演算用周辺チップとして開発されたのがAMD社のAm9511です。AMD社はこのほかにもユニークで高性能な8080周辺チップを開発しています。DMAコントローラのAm9517なんかもAm9511と同じ時期の製品ですね。このAm9511も8080の周辺チップで、2 MHzクロックで8080バスにI/Oポートとしてそのまま接続できるようになっています。CPUからI/Oポートにアクセスする形で演算対象のデータやコマンドを書き込んで、結果を読み出します。
32 bit長の単精度浮動小数点演算と16 bit整数と32 bit整数の演算が行えます。四則演算の他、初等関数の計算もできます。浮動小数点の四則演算なら100 us程度で実行できます。sinやcos関数なら2 ms、logなら3 msで計算可能です。当時の8 bitのマイクロプロセッサを用いてソフトウェアで四則演算を行わせると、1 msから10 msくらい必要でしたから、一応は桁違いの性能を実現できます。逆にこれ以上高速でも、当時の8080Aの速度では浮動小数点数をAm9511とメモリ間で転送する時間が40 usくらいかかりますから、データをマイクロプロセッサが与えて演算指令を書き込み結果をメモリに戻すなんてのに必要な時間の方が長くなってしまい、トータルの計算時間を短縮できないので、無意味です。連続した計算なら、前回の計算結果はAm9511の中にありますから、次の数値をひとつとコマンドを与えるだけでよいのですが、それでも50 usくらいはCPUが消費するので、トータルの計算時間は約150 us。仮にAm9511が2倍の速度になっても100 usだし、1 usで計算を終えることができたとしても約50 usで、努力の程度ほどトータルの速度はあがりません。そのくらいに高速なLSIが実現できたとすれば、CPUを介さずにLSIの側でDMAを用いてデータと命令をメモリから勝手に読み込んで次々と演算を行っていくような形にしなくては効率があがらず、結局はそれって新しいCPUを開発するのと変わりませんから、8 bit CPU用の周辺LSIとしては大規模になりすぎて、労力をつぎ込まれなかったのでしょう。すでに次世代16 bit CPUの開発が行われつつありましたから。

姉妹品として倍精度浮動小数点の四則演算専用の(初等関数はできない)Am9512がありました。共に大変に高価なLSIでした。たとえば1979年4月ごろの秋葉原店頭での価格は79000円だったりしました。しかしCPUとデータをやり取りして、せいぜい演算終了時割り込みを発生させるだけですから、ピン数は少なくて済み、このように24ピンのコンパクトなパッケージです。

AM9511

電源は+5 Vの他、+12 Vも必要。

では実際の使い方と性能について見ていきます。
CPUからAm9511を眺めると、読み書き可能なデータレジスタと書き込み専用のコマンドレジスタと読み出し専用のステータスレジスタだけがアドレス空間に割り当てられています。コマンドレジスタは演算命令を指示するのに使用します。ステータスレジスタは演算が完了したかとか符号やゼロや演算エラーなどのフラグ類を読み出すためのものです。
さて、データレジスタは実際には16 Byte分のスタックのへの読み書き窓口になります。浮動小数点数データや32 bit長整数データの場合には4レベルのスタック、16 bit長整数データの場合には8レベルのスタックにデータを配置できることになります。そうして、単項演算命令の場合にはスタックトップのデータに対して、2項演算命令の場合にはスタックトップとそのすぐ下のデータに対して、演算を行うのが原則です。
すると、ある程度の複雑さの数式ならば、逆ポーランド記法の順序でデータと命令を与えてやれば計算ができそうですが、実際にはそんなに簡単に行きません。後で詳細な命令表を掲載しますが、そこからわかるように関数の類の演算の作業領域として同じスタックが使われてしまうことがあるのです。たとえば逆三角関数のASIN命令の場合には、スタックトップのデータをポップしてからそのASINを求めて、その結果をスタックトップにプッシュしなおすのですが、他の3レベルのスタックのデータがすべて失われてしまいます。というわけで、内蔵スタック領域をCPUが活用するのは命令実行の細部まですべて理解する必要があり、結構面倒なことになります。
結果的に、一般的な使い方というと、1ないし2個のデータをプッシュしてから演算命令を発行し、演算結果が得られたらスタックからポップするということになります。せいぜい一連の演算を連続実行する場合に、結果をいちいちポップするのをやめて、追加のデータをひとつプッシュしてから2項演算命令を発行するのを繰り返すくらいの使い方しかできなさそうです。

具体的な命令については、浮動小数点数命令、32 bit整数命令、16 bit整数命令の順に説明します。

まずは浮動小数点数に対する命令です。

命令 Code スタック SZOCE クロック数 意味
ACOS  06  R U U U  **  *    7734    Inverse Cosine of A
ASIN  05  R U U U  **  *    7668    Inverse Sine of A
ATAN  07  R B U U  **       6006    Inverse Tangent of A
CHSF  15  R B C D  **        18     Sign Change of A
COS   03  R B U U  **       4118    Cosine of A
EXP   0A  R B U U  **  * 3794-4878  Exp(A) function
FADD  10  R C D U  **  *   54-368   Add A and B
FDIV  13  R C D U  **  *  154-184   Divide B by A
FLTD  1C  R B C U  **      98-378   32 bit Integer to Floating point conversion
FLTS  1D  R B C U  **      98-186   16 bit Integer to Floating point conversion
FMUL  12  R C D U  **  *  146-168   Multiply A and B
FSUB  11  R C D U  **  *   70-370   Subtract A from B
LOG   08  R B U U  **  * 4474-7132  Common Logarithm of A
LN    09  R B U U  **  * 4298-6956  Natural Logarithm of A
POPF  18  B C D A  **        12     Stack Pop
PTOF  17  A A B C  **        20     Stack Push
PUPI  1A  R A B C  **        16     Push Pi onto Stack
PWR   0B  R C U U  **  * 8290-12032 B**A power function
SIN   02  R B U U  **       4464    Sine of A
SQRT  01  R B C U  **  *     800    Square Root of A
TAN   04  R B U U  **  *    5764    Tangent of A
XCHF  19  B A C D  **        26     Exchange A and B
この表で、命令はニーモニック、Codeはコマンドレジスタに書き込むべき命令コードの下位7 bitを16進数表示したものです。命令コードはすべて1 Byteです。ただし最上位ビットに関しては終了割り込みの有無を指示するために使われているので、表ではすべてMSBを0にしてあります。
スタックの欄は、命令実行前にスタックトップのデータをA、そのすぐ下のデータをB、さらにその下のデータをC、底のデータをDとしたとき、命令実行後のスタックの状態がどうなっているかを表します。ただしRは演算結果のデータ、Uは不定データを意味します。たとえばFADDはAとBをポップして加算した結果をプッシュしますから、スタックトップから順にR C Dとなりスタックの底には不定値のUが入ることになります。ただし前述の注意のようにたとえばACOS命令ではR以外はすべて不定値になったりしますので、APUへの命令を自分で最適化しようとする場合にはスタックの状態表を正確に把握する必要があります。
SZOCEはステータスレジスタへの影響を意味します。Sは符号フラグ、Zはゼロフラグ、Oはオーバーフロー、Cはキャリーフラグ、Eはエラー発生の可能性を意味します。影響を受ける欄には'*'を入れてあります。空白になっている場合は命令実行の影響を受けません。ただしOとCは整数演算にだけ関係するため、この浮動小数点演算命令ではすべて空白になっています。
クロック数は命令実行に必要なクロック数です。普通のAm9511ですと最高クロック周波数が2 MHzで、その場合にはたとえばACOS命令は3867 usの実行時間であることがわかります。EXP命令のように3794-4878と書かれている場合、データによって命令実行クロック数が変化し、その最小値が3794で最大値が4878であることを意味します。
FADD, FSUB, FMUL, FDIV命令はそれぞれ加減乗除の四則演算です。SQRT命令は平方根を求めます。
ACOS, ASIN, ATAN命令は逆三角関数で、COS, SIN, TAN命令は一般の三角関数です。ともに角度はラジアン単位です。
EXP命令は指数関数で、LN命令とLOG命令が対数関数になります。LOG命令のほうは常用対数でLN命令が自然対数ですね。PWR命令はBのA乗を求めるための命令です。
CHSF命令は浮動小数点数の符号を反転させるものです。
FLTD命令とFLTS命令はそれぞれ32 bit整数と16 bit整数を浮動小数点数に変換する命令です。一般に入出力に伴って文字列で表現された数値を浮動小数点数に変換したり、浮動小数点数を文字列表現に変換したりする必要がありますが、その作業の一部にこれらの命令を利用できます。
POPF, PTOF, PUPI, XCHFの各命令はスタック操作のための命令です。POPF命令はスタックトップの浮動小数点データを読み捨てるもので、PTOF命令はスタックトップを複製してプッシュする命令です。PUPIは円周率の定数値をスタックにプッシュするもので、XCHF命令はスタックトップとその直下のデータを入れ換えるものです。たとえばFDIV命令はB/Aを求める命令ですが、すでにスタックに納められているAとBに対してA/Bを求めたい場合、まずXCHF命令でAとBを入れ換えてからFDIV命令を発行するのが効率的です。このほか、CPUがAm9511のデータレジスタを読み書きすることによって、データをプッシュしたりポップしたりすることができます。

次は32 bit長整数演算命令です。

命令 Code スタック SZOCE クロック数 意味
CHSD  34  R B C D  ***       27     Sign Change of A
DADD  2C  R C D A  ** **     21     Add A and B
DDIV  2F  R C D U  **  *    208     Divide B by A
DMUL  2E  R C D U  ***    194-210   Multiply A and B (R = lower 32 bit)
DMUU  36  R C D U  ***    182-218   Multiply A and B (R = upper 32 bit)
DSUB  2D  R C D A  ****      38     Subtract A from B
FIXD  1E  R B C U  ***    100-346   Floating point to Integer conversion
POPD  38  B C D A  **        12     Stack Pop
PTOD  27  A A B C  **        20     Stack Push
XCHD  39  B A C D  **        26     Exchang A and B
DADD, DSUB, DMUL, DMUU, DDIV命令が四則演算です。ただし乗算だけは演算結果が64 bitになってしまいますから、結果の上位32 bitを得るか下位32 bitを得るかで別々の命令が用意されています。
FIXD命令は浮動小数点数から32 bit整数への変換命令です。
CHSD命令は符号の反転命令で、POPD, PTOD, XCHD命令はスタック操作命令になります。

16 bit長整数演算命令は次のようなものが用意されています。

命令 Code スタック SZOCE クロック数 意味
CHSS  74  RBCDEFGH ***       23     Sign Change of A
FIXS  1F  RCDEFUUU ***     92-216   Floating point to Integer conversion
POPS  78  BCDEFGHA **        10     Stack Pop
PTOS  77  AABCDEFG **        16     Stack Push
SADD  6C  RCDEFGHA ** **     17     Add A and B
SDIV  6F  RCDEFGHU **  *   84-94    Divide B by A
SMUL  6E  RCDEFGHU **  *   84-94    Multiply A and B (R = lower 16 bit)
SMUU  76  RCDEFGHU **  *   80-98    Multiply A and B (R = upper 16 bit)
SSUB  6D  RCDEFGHA ** **     30     Subtract A from B
XCHS  79  BACDEFGH **        18     Exchang A and B
NOP   00  ABCDEFGH            4     No Operation
だいたい32 bit整数演算命令と同じですね。ただ、スタックが8レベルとなるので、そこだけに注意してください。スタックの初期値はABCDEFGHとしてあります。
それとNOP命令は例によって何もしない命令ということで。

総じて、演算に必要なクロック数が、現在では考えられないくらい多いことに気づくと思います。浮動小数点数の四則演算で100クロックとか200クロックくらい必要で、関数計算にいたっては10000クロックを越える場合すら存在します。これらは、当時のコンピュータでアセンブリ言語で浮動小数点演算ルーチンを作成したことのある人なら納得できる程度のクロック数だと思いますが、最近の1 - 2クロックで浮動小数点演算をこなすマイクロプロセッサからすれば、大変な違いですね。
このAm9511は標準的な8 bitマイクロプロセッサが数千トランジスタ程度で実装され、最先端の16 bitマイクロプロセッサが数万トランジスタ規模で開発されつつあった時代に開発されました。つまり、浮動小数点演算専用LSIといっても、Z-80 CPUとかMC6809と大差ない規模のLSIだということです。実際、Intel社はAm9511のセカンドソースとして8231という名前で同等品を販売していましたが、その資料によると、内部データパスは16 bit幅であり、算術演算ユニット(ALU)も入出力とも16 bit幅となっています。しかも、整数乗除算のクロック数から類推して、このALUは乗除算を直接実行する能力はなく、加算程度しかできないもののようです。乗算は、多桁の乗算を筆算で行うときのように、一桁ずつ1か0を掛けて桁をずらしながら加えていく方式で、数クロックで1桁分の積和を行っていくために多数のクロックが必要となるのでしょう。浮動小数点数の加算は、仮数部の加算に先立って仮数部の小数点位置桁合わせでシフト操作が必要となり、現在の高性能プロセッサで行われているように任意のビット数シフトを1クロックで実行する回路ではなく、1 bitずつシフトする操作を繰り返しているため、必要クロック数が多くなり、しかも入力数値によって必要クロック数が変化すると考えられます。
結局、加算やシフト演算しか内蔵していない16 bitマイクロプロセッサでソフトウェアで浮動小数点演算を行うのと同じことを、内部マイクロプログラムで一般のマイクロプロセッサよりは高速に実行しているわけです。
このAm9511はIntel社から8086用の浮動小数点演算コプロセッサ8087が発売されるまで、特に数値計算を高速に実行するために必要なLSIとして有名でした。しかし、演算速度では8087に負け、コスト面ではソフトウェアによる浮動小数点演算にかなわなくなると(ROMなどプログラムを格納するメモリは急激に安くなりますから)、使われなくなっていきます。意外なほど旬が短かったLSIでもありました。

Return to IC Collection