プチコンで遊ぼう! (はてなブログ版)

任天堂3DSのプチコンで遊ぼう! [twitter:@eida_s]

はてなダイアリーから移行しました。 はてなダイアリーのURLを開いても自動的にこちらにリダイレクトされますのでご了承ください。

デコーダの設計

仕事が忙しかったりで進捗が停滞していたプチZ80ですが、多少進捗しました。

レジスタ、メモリ等の定義についてはすでにしていたのですが、命令のデコード部分の実装ですごく紆余曲折がありました。

まず、以前に書いたとおり、1バイトのオペコードを3ビットごとに分けて読むとよい、という情報を読んだので、上位2ビットを命令の大分類として、その後の3ビットずつを読み取り、命令を体系化しようと試みていました。
が、結果からいうと失敗。

分岐した命令の中で例外のパターンについて調べてまた別命令に分岐するなど、訳がわからないプログラムができかけました。

理想的には、上位2ビットの大分類から枝分かれしたツリー構造になればよかったのですが、実際のZ80の命令体系は8ビットの中に命令群を詰め込むために、そんな単純な構造はとれなかったようです。


そんな時、 http://tomocyan.net/~kagurazaka/html/z80_cpu_00.html にある命令表を眺めていたら、やっぱり表にしちゃった方が単純だな、と思えてきました。
そこで完全に方向転換し、オペコードに対応するアセンブリコードを表で持ち、共通のアセンブリコードを一つのサブルーチンに分ける、ということにしました。

アセンブリコードの底本は、amazonnで見つけた「Z80アセンブラ入門」(東京電機大学出版局)とすることにしました。
この本の巻末付録にZ80命令セットがわかりやすくまとめられています。
この本を底本とすると、アセンブリコードは147種類にまとめられそうです。

例えば、オペコード 01、11、21、31は “LD dd,nn” という一つのアセンブリコードに帰着するので、これらのオペコードの対応表に“LD dd,nn”にあたるラベルを割り当てて、実行フェーズでそのラベルを呼び出します。

ということで、アセンブリコードのラベル表はLB_IS$()として定義します。
ついでに命令長とクロック数を、IS_LN()、 IS_CL()で定義しておきます。
1バイト目をフェッチし、CB、DD、ED、FDのいずれかでなければ、1命令で動作が確定するので、GOSUB LB_IS$(オペコード)でルーチンに処理を飛ばして、実際のオペコードの動作を実行します。

仮に1バイトで命令が確定しない場合には、命令長には0が入っているようにします。この場合、1バイト目のオペコードに応じて続く2バイト目の命令表が分岐するようにします。
命令が確定するまで、次の命令表を読みいくようにし、これを繰り返します。
ビット操作、ローテイト・シフトは4バイト目まで読まないと命令が確定しませんが、上記の仕組みでうまくいけそうです。


これで方針がはっきりし、また、見通しがかなりよくなりましたので、作業の分量もかなり事前に把握できるようになりました。
ただし、表がかなりのボリュームになるので、これを効率的にデバッグする方法が必要そうですが、それは後で考えることに。


残りの重要なものとしては、ペアレジスタとフラグがありますが、ペアレジスタについては次回に扱うことにします。


ここまで全く画面とか出てこなくてつまらないので、とりあえずHelloWorldしてみることにします。

そこで非常に簡単な仮想マシンを考えることにします。
プチコンGRPは256*192=49152=48Kbytesですので、&H0000〜&HBFFFまでのメモリ空間があります。
(あとでGRPを2枚つなげて64Kbytesをサポートするようにします。)
とりあえず、&H8000からの3072bytesを仮想マシンのテキストVRAMとして、ここにキャラコードを書き込むとプチコンの画面にテキストキャラとして表示するようにします。


後はHelloWorldを出すプログラムだけです。
アセンブリで作ったプログラムをハンドアセンブルして、BEDITで16進コードを入力しGRPファイルに書き込みました。

'' Z80アセンブリでHelloWorld
LD HL,&H8000 21 00 80
LD (HL),'H' 36 48
INC HL 34
LD (HL),'e' 36 65
INC HL 34
LD (HL),'l' 36 6C
INC HL 34
LD (HL),'l' 36 6C
INC HL 34
LD (HL),'o' 36 6F
INC HL 34
LD (HL),',' 36 2C
INC HL 34
LD (HL),'w' 36 77
INC HL 34
LD (HL),'o' 36 6F
INC HL 34
LD (HL),'r' 36 72
INC HL 34
LD (HL),'l' 36 6C
INC HL 34
LD (HL),'d' 36 64
INC HL 34
LD (HL),'!' 36 21
HALT 76

これでHello,world!と表示されました。