chibicc compiler を6800向けに改造する (6) IEEE754 float (2)

BASICMASTER, 昔のパソコン

「chibicc 6800 には、IEEE754形式の32bit floatを実装している。オールアセンブラなので、割と速い」などと書いたのだけど、それでも遅いのである。


printfを実装する

そろそろテストのときに printf が欲しくなったので簡単なものを実装してみた。

floatも表示したいので、%f, %e も実装。表示幅指定や精度指定はとりあえずサボって最低限表示できれば良い(精度が必要なら16進ダンプする)。

int, long 用に _itoa, _ltoa を作り、 %f,%e 用に truncf(切り捨て)、modff (floatの整数部と小数部を取り出す)を実装した。

実装中にうすうすこれは遅い気がしたので、適当に速度を測ってみた。以下は、ループ1000回のサイクル数。試した数はπ。

テスト項目サイクル数
signed long = float985,060
float = truncf(float)727,060
float = floorf(float)717,060
float = ceilf(float)1,580,060
float = modff(float,&float)679,060
float = float-trunc(float)1,714,060
float = floor by modff(float)1,106,063
float = ceil by modff(float)2,558,063

ceilf が遅いのは、正の数ばかりで測定したため。

trunc は切り捨て、floorも正の数なら切り捨てなのだが、正の数の場合のceilは 小数部があれば切り捨てて+1.0する操作が発生する。

+1.0は整数なら簡単だが、実数だと桁合わせが必要だし、足した後に丸めやノーマライズ処理が発生するので遅くなる。+1をビット演算で行う方法もあるようなので、そのうち実装したい。

実数演算1回1msの世界

上記はサイクル数なので、実機に当てはめると1MHzのCPUで、1回1-2ms前後の時間がかかっていることになる。実に遅い。

試しに三角関数の sinf をCで実装してみたが、1000回で 37,619,060サイクルかかった。1回で40ms近くかかるので、100回で4秒である。
(ちなみに 7次のtailor展開。これでも最小桁に誤差がでる)

とにかくシフトが遅いのをなんとかしないといけない。

0ページ上に32bitデータを置いているのだが、ASL/LSL/ASRでシフトすると(0ページなのに)6サイクルかかる。
計算の片方はスタックにあるので、こちらは7サイクル。

32bitデータを1ビットシフトするだけで、24〜28サイクルかかり、それを何十回とループするので遅くなる。8bit以上のシフトを最適化すべきだけど、小さいシフトだと逆に不利になるし。

どうしたもんか(modffは頑張ったので、ちょっと速いです)