うさちゃんと一緒(19) Z80の魔改造?Rabbit4000のオペコードマップ その1

Joseph Halfmoon

Rabbitシリーズ(販売元Digi社)のプロセッサはZ80「オマージュ」製品といっていいでしょう。しかし、Z80の盲腸化した仕様をチマチマ活用して拡張していた3000シリーズまでと比べると、4000シリーズ以降では大胆に拡張してます。そのレベル、もはや魔改造。Z80大好きな「中の人」が好き勝手やり放題でなかったかと。

前回、Rabbit4000のレジスタ一覧を作成してみました。懐かしのZ80レジスタ(もっと言えばi8080レジスタ)に混じって、JKとかPWとか聞いたことの無いレジスタが混ざってました。

それらを活用するためには命令を追加することが必要です。しかし、ご存じのとおりZ80のオペコード(ファーストバイト)には隙間らしい隙間がありません。ビッチリ詰まっています。4つ(CB、DD、ED、FD)ある2バイトオペコードを使う部分には隙間があるので、その辺を拡張するのも手ですが、Rabbit4000の設計者はもっと過激な方針をとったようです。

    1. Z80で存在するがハード的にRabbitでは使わない(使えない)部分は回収して使用
    2. 2バイトオペコードの空いているところを活用
    3. ファーストバイトの一部を移転させて、「跡地」に新設命令を建てる

1は例えばリフレッシュ・カウンタ・レジスタ用のオペコードの再利用です。Z80のリフレッシュ・カウンタ内蔵は当時は便利と持て囃されたものですが、今となっては不要、使うことは考えられませぬ。このような部分を「回収」して再利用すると、これはZ80との表面的なオブジェクトコードの互換性を損ないますが普通は使っていない部分なので実質的な影響は無いでしょう。

2はもともと空いている部分に増設しているだけなのでこれまた問題ないかと思います。

過激なのは3です。完全にバイナリ互換性は損なわれます。しかし、「移転させられる」命令はオペコードは変わりますがアセンブリ言語命令コードとしては維持されます。アセンブラ書いている分には分からないっと。

第3の方法をとった理由を「移転させられた」命令から推測するに以下ではないかと。

    • 移転させられたのは8ビットレジスタ間の転送、演算命令群
    • Z80以前の8ビット(i8080互換)からひきずってきている命令
    • Cコンパイラにとってはあまり有難くない、多分ほとんど使わない
    • にも拘わらず「効率のよい」ファーストバイトを大量占拠
    • これらを移転させて跡地にCコンパイラ向けの命令を入れたら凄い!

移転先は、新たに設定されたファーストバイト0x7Fのページです。0x7FはもとはLD A, A で意味的にはNOP同等の命令だった場所です(Z80にはNOP専用の命令コードがあるのでLD A, Aを使う意味はありません。)また「移転」させても効率が落ちにくい理由としてRabbit 4000は16ビットのデータバスを持てる(実際、今回使用しているRCM4010モジュールでも16ビットデータバスです)ので、アライメントされていれば2バイト命令になっても一度でフェッチできるということも挙げられます。0x7Fにつづくセカンド・オペコードのマップを以下に掲げます。

OpcodeMap7F

上記をみると、100命令以上の8ビットレジスタ操作が移転させられていることが分かります。移転後の跡地はファーストバイトの一等地です。1バイトの短いコードをコンパイラ向けの命令で活用できるようになったと。

オペコードマップの凡例

今回は「自力作成途上」のRabbit4000オペコードマップの一部(ファーストバイト編)を掲げます。以下の資料の付録にもオペコードマップが存在するのにわざわざ自力で作っているのは、どの命令がZ80と同じでどの命令は新設、とか一目で分かるようにしたかったからです。

Rabbit Family of Microprocessor Instruction Reference Manual

以下のオペコードマップでは下記のような色で命令を分類しています。OpcodeMapLegend

Rabbit4000のオペコードマップ(ファーストバイト)左面

冒頭のアイキャッチ画像に16x16サイズのテーブルを掲げましたが、大きすぎて見ずらいので、左と右に分けました。まず左面です。

オペコード8ビットの上位4ビットが縦、下位4ビットが横です。

移転の結果、ポツポツと「空き」ができていることが分かります。さっそく1か所誤りを見つけてしまいました。0x90のSUB A, B のところです。本来は上の(ADD A, B)と同様の「空き」です。

MainMapL

上記をみると、Z80では非力だった16ビットレジスタのロード、ストア、ローテイトなどが大幅強化されているとともに、Z80では存在しない32ビットレジスタのロード、ストアも可能になっていることが分かります。

また、Rabbit4000は、フラグに関する部分もモダンになっていることが分かります。Z80での条件ジャンプは単純フラグのON/OFF判断でしたが、Rabbit4000では、複数の条件フラグを含めてGT(greater than)とかLT(less than)とかも判定できるようになっています。

一方、そのための専用フラグがあったDAA(10進補正命令)はフラグとともにバッサリ削られてます。もともと電卓用のチップであった80系は、電卓の10進計算のためにこの命令をもっていた(現代のx86/x64もその系譜を継ぐ)のですが、今や盲腸です。DAA不要としたことでフラグ(Z80でも条件判断には使えないフラグだったのでDAA使わなければ影響ないと思います)を削り、DAAの跡地はRabbitではコンパイラが必要そうなスタックポインタの即値加算になってます。

乗算命令やら、広いメモリ空間をサポートするための命令なども追加されております。コンパイラのコード生成上は効果大有りでないかと思います。

Rabbit4000のオペコードマップ(ファーストバイト)右面

移転の結果の「大きな空洞」の中に、Z80でも存在する LD E,E命令がポツリと残っています。ここは先ほどのような記述ミスがではなく、Rabbit4000は、このコードを別な目的(プロセッサモードの制御)にも使っているためです。プロセッサモードの話に深入りするのはまた後で。

右面で目立つのが、移転命令の跡地に建てられた2つのセカンドオペコードマップにつながる PAGE 6DとPAGE 7Fです。

さきほど述べたように、PAGE 7Fは、1等地からの「地上げ」の対象になったZ80の8ビットレジスタ操作の移転先として使われています。

これに対して PAGE 6Dは、Rabbit4000独自拡張の命令群が多数含まれています。

MainMapR

まあ、結構な大改造。魔改造といっていいレベルかと思います。しかし、Z80の「伝統」が息づいている感じがします。その昔、68系などと比べてZ80は命令セットが対称でない、などとディスられることが多かったです。このRabbit4000での大幅「改造」でも対称性などはどこ吹く風と見受けられます。本来 PAGE DDに押し込められていた筈のIXレジスタを使う命令がファーストバイトにも入ってきたり、そのくせ、IXと対になるはずのIYを使う命令はファーストバイトに無いなど「使うつもり」の命令優先、非対称になったって、美しくなくたって気にしない、というポリシー?が明らか(個人の感想です。)知らんけど。

次回はセカンドバイト以降の拡張を調べます。ますます泥沼。

うさちゃんと一緒(18) Rabbit4000のCPUレジスタを一覧にしてみた へ戻る

うさちゃんと一緒(20) Z80の魔改造?Rabbit4000のオペコードマップその2 へ進む