投稿日: Mar 13, 2017 12:4:32 PM
c8aなんてものを作ってますが、他がどうしてるのか知りたかったりしてz80のエミュレータなど探っていました。
で、Arduinoで動くAltair8800シミュレータに出会います。
uSDをドライブに、シリアルSRAM外付けして動くという構造自体はc8aとまったく一緒。
コードも共通点が多くてCPU部分だけ差し替えればそのまま動きそうな勢いです。
しかしとりあえずi8080がArduinoで動作可能という点だけを頂いてソースコードは参照せず自分でi8080を作ろうと思います。他人のソースは見づらかったり直すのに手間がかかったりするのでメンテナンス性も考えて。ね。
偉そうに言えることでもないけど。しかも速度を考えると通常のやり方の方がいいかもしれないのだけど。
今回はヴァーチャルマシンのバイナリサイズを小さくする狙いがあります。
すでにi8080が通常のやり方でArduino上で動いてる実例を見ているので無理する必要はないんですけれど、要するにオペコードで分岐して命令を256個実行するんじゃなくて、CPUのデコーダを模したコードを作って隠れた命令すらも実行できたらいいなぁ。なんていう妄想をもくもくしながら考えた方法なんです。
256個の命令のビットを洗いざらい調べました。
隠れた命令なんてi8080には無い(無いのか明らかになっちゃってただけなのか)ので意味ないんですが、コードはとても小さくなります。
i8080の命令の1/4を占めるMOV命令をまず作ってみました。
これだけ。 そうこれだけ。 (一行変なところがあるけど目をつむること)
基本的には最初の1行だけで実現できてるのですけども、(HL)を参照する命令が挟まっているのでそのためにswitch caseが続いています。
レジスタはB C D E H L M A Fの9バイトの配列。
OPCODEの頭2byteが01ならMOV命令、続く3バイトづつにどのレジスタを参照するかというデータが入っているのでそのまま配列に当てはめればうごいちゃうわけです。
i8080のオペコードをしっかり見てみると AABBBCCCと2ビット、3ビット、3ビットでいい感じに命令が分かれています。これはi8085もZ80も似たようなもんなので、そういう点踏まえるとこういうコードが書けるわけです。
たのしいですね。
たのしくなってきました。
とはいえ、こんなに短く書けるのはMOV命令だけなんですけど。
次に短くかけるのがi8080の命令のこれまた1/4を占めるビット演算式です。
次はその辺やってみましょうかねー。
LD M,Mに相当する0x76はHLTだという指摘が。ほんまやー↓ 何でこんな所にそんな命令つけたのですか設計者さん。しかたがないのでコード追加。
ださい。
ついでに気づいた。case 0x110じゃなくて0b110ですね。0x6でいいじゃん。ってことでこの辺も直した。