うさちゃんRabbit4000のDynamic Cのライブラリを読んでいるとインライン・アセンブラ・コードに迷いこみます。RabbitシリーズはZ80愛に溢れているCPU、Z80上位互換です。Z80のつもりで大体読めますが、時々「知らない」レジスタなどに遭遇します。今回はCPUレジスタを図にまとめてみました。
※「うさちゃんと一緒」投稿順indexはこちら
RabbitシリーズCPUの開発言語である Dynamic Cは、ほぼほぼ標準C(といってANSI C90)互換といいつつ、他のどのC言語処理系よりもインラインアセンブラの敷居が低い処理系じゃないかと思います(個人の感想です。)他の処理系だとここからインラインアセンブラだぞ、と身構える感じがあるのです。しかしDynamic Cの場合「いつの間にか」インラインアセンブラ部分に突入してます。Rabbit4000のドキュメント類はこちら
そしてZ80「ほぼほぼ上位」互換であるので、Z80と同じところもあれば「拡張されている」「変更されている」部分もありです。
CPUレジスタの全貌
今回はCPUレジスタに絞って図にしてみました。これ以外にもメモリやIOの管理のために多くの制御レジスタがあります。またCPUレジスタの保持する値でもメモリアドレスは第10回、第11回で説明した内容と合わせないと実際の物理アドレスには到達できないかと思います。
Z80の伝統に基づき Rabbit 4000 にも 表 と 裏 の両レジスタセットがあります。茶道みたいなものか?知らんけど。
まずは「表」のレジスタから
以下の図での色分けは以下のとおりです。
-
- 緑 Z80と互換性のあるレジスタ
- 青 Z80にも存在するけれど、ちょっと意味が変わっていたりするレジスタ
- 赤 Z80には存在しないレジスタ
また背景の罫線の小さい横一マスが1ビット幅です。
8ビット汎用レジスタは、Z80(もっと言えばインテル8080)以来の、A、B、C、D、E、H、Lの7本が使用できます。また、8ビットアキュムレータAが、フラグレジスタFと組み合わされて16ビットレジスタとして、また、BC、DE、HLの各ペアが16ビットレジスタとなるところも一緒です。
ここにRabbit4000では、見慣れぬJKなる16ビットレジスタが追加されています。JKは16ビットレジスタですが、HLなどと比べると限定的な操作しかできません。しかし、Rabbit4000では、32ビットのオペランドの操作が追加されており、JKHLという組み合わせで32ビット操作が可能です。同様にBCDEで32ビット操作もできます。
同様に中央右側をみると赤い32ビットレジスタPW、PX、PY、PZという4本があります。これらはZ80には存在しないレジスタ群で、機能的にはZ80のインデックスレジスタIX、IYの32ビット版という役割です。主にアドレスを保持してメモリアクセスに使うのだと思います。さきほど出て来たBCDEやJKHLの方はメモリアクセスにも32ビットの演算にも使えるのでちょいと差があります。
その左側に目を転じると、青色の8ビットレジスタIIR、EIRが目につきます。ここはZ80ではI、Rレジスタがあった場所です。Z80のIは割り込みベクタテーブルのアドレス上位8ビットを保持するためのレジスタ、RはDRAMリフレッシュアドレスを保持するレジスタです。Z80が登場した当初は自分でDRAMリフレッシュアドレスを出力してくれるZ80便利、という評価でしたが今日では不要。その「跡地」をRabbit4000では、EIRとしています。Rabbit4000のIIRとEIRの機能はZ80のIと同様、割り込みベクタテーブルのアドレス上位8ビット保持ですが、Rabbit4000では内部割込み用のIIRと、外部割込み用のEIRの2つに分かれています。またEIR側はZ80同様に128エントリですが、IIR側のテーブルは256エントリに拡張されています。
IX、IYは、Z80が「8080にはインデックス・レジスタが無い」という批判にこたえるために追加されたインデックスレジスタです。古い話ですが。うさちゃんの中の人たちはガチZ80勢なので、結構多用している感じです。8080のつもりでZ80を使っていた私のようなものはおよびもつきませぬ。
SPはスタックポインタ、PCはプログラムカウンタです。ここもZ80コンパチの16bit幅ですが、Rabbit4000は16bitアドレスに収まらない物理メモリが使えるのでその辺の仕組みは、第10回、第11回も参照してくだされ。
プログラムカウンタPCの16ビットに対する上位アドレスを保持するのがXPC(およびLXPC)レジスタです。ある命令ではXPCとして8ビットで扱われますが、他の命令ではLXPCという名で4ビット拡張されて12ビットになっています。これはRabbitシリーズ中でのメモリ拡張の歴史により幅が広くなってきたみたいです。知らんけど。
残りのIP(インタラプト・プライリティ)、SU(システム/ユーザ)、HTR(ハンドル・テーブル・レジスタ)の3本の8ビット・レジスタはすべてZ80には存在しないものでRabbit独特です。この辺はまた改めて調べたいと思います。
裏レジスタ
Z80の特徴の一つが裏レジスタの存在です。これはZ80登場時、高速なインタラプトハンドリングを実現するために導入された機構です。ただし、割り込みネストしたらどうよ、みたいな批判は当時からあったような気がします。
当然Rabbit4000でも裏レジスタ(Alternate Registers)は存在しています。以下の図のように、汎用レジスタ群およびPW、PX、PY、PZは裏(´付)レジスタ使えます。
ここでもRabbitには一工夫あります。プリフィックスというとx86/x64を思い出しますが、Rabbitにも以下のプリフィックスがあります。
ALTD
これにより、Z80で不便なところ、裏レジスタへの切り替えはAFレジスタまたはBCDEHLレジスタをまとめてひっくり返すことしかできなかった、を解消しています。ALTD直後の命令では「裏」をデスティネーションにできるので、まとめてBCDEHLをひっくり返さなくても一部書き込みすることができます。
フラグ
フラグレジスタFのビットについては、以下のようにZ80とRabbit4000の間には差異があります。
Z80で存在していたH(ハーフ・キャリー)、N(減算)が無い
上の2つのフラグはZ80でも条件分岐には使えず、もっぱらDAA(10進補正命令)でのみ有効でした。Rabbit4000のニーモニックを探してもDAAは無く、盲腸のようなDAA(電卓でのBCD演算用)を削除し、フラグも取り除いてしまったみたいです。この部分については、Z80および8080との上位互換性はありませぬな。
さらっと、レジスタを撫でるつもりが結構長くなりました。