概要
- いにしえの 8bit CPU NS製 SC/MP-III に関する記事です。
- C言語で書かれたSC/MP-III CPUエミュレータ上で、円周率を計算してみました
- ソースコードは公開です。
https://github.com/iruka-git/SCMP3_Calc_Pi
計算方法の概要
- ごく普通にマチンの公式を用いています。
- arctan()の計算はマクローリン級数を固定小数点の多倍長演算で計算していきます
- C言語で記述した、Linux上で動作するソースも同梱しています。(SC/MP-IIIでは動きません)
- それをSC/MP-IIIのCPUに落とし込んだものが本題です。
SC/MP-III は SC/MP-IIとどこが違うの?
- SC/MP-IIIは EレジスタとAレジスタを連結して16bitレジスタとして使えるようになりました。
- ポインタオフセットが0x80(-128)だったときに、オフセット値をEレジスタの内容に読み替える処理は、無くなりました。
- 6800/6502系のゼロページアドレッシングに近い、FFxxページの256バイトを直接参照するダイレクトアドレッシングが出来るようになりました。
- ポインタ P1 がスタックポインタになり、16bit 絶対番地指定のJSR命令やJMP命令 が追加されました。
- 乗除算用にTレジスタ(16bit)が追加され、16bitの乗算/除算命令がそれぞれ追加されています。
独自言語Asmpp3 を公開(同梱)しています。
- C言語風の記述、どちらかというとFORTHに近いかも。
- サブルーチン関数は定義できます。
- 変数や戻り値などの型はありません。
- 関数引数はありません。暗黙的にはレジスタ(A,E,EA,P2,P3など)をそのまま使います
- asm の表現と混在できます。
SC/MP-IIIのどこがだめ?
-
SC/MP-III エミュレータとか、独自言語を入れてみて、だめだったことを記述します。
-
比較命令(cmp) がない。減算で代用。(できるか!A regが毎回壊れる。)
-
大小比較の結果の取得や分岐が大変面倒。条件分岐命令が A regの内容でしか分岐できない。しかも条件分岐命令は BZ、BNZ、BP (Aregが正) の3個のみ。
-
さらに 16bitレジスタ EA の値を大小比較しようとすると、もっと面倒なことに・・・
-
キャリーフラグを含む加減算命令が(SC/MP-IIにはあったのに)抜かれている。
-
多倍長演算を行うには限りなく不利。
-
まあ、それ以外は、可もなく不可もなく、16bit同士の乗除算命令がある8bitレガシーCPUは珍しいんですけどね。・・・
円周率1万桁の計算時間
-
軽く見積もったところ55時間という結果が出ました。
-
ウェィトを設けないエミュレータ上では3分で計算できています。
-
最適化をいくつか実施すれば数分の1に短縮できるかも。
-
(収束した級数は最初にずっとゼロが続いているので、除算をスキップできる)
-
(除数が8bitに収まっている条件ではCPUのDIV命令を使って多倍長除算を構成できる可能性)