Z80の16ビットI/Oアドレスについての考察
Tweet1981年発売のPC-8801(NEC)やFM-8(富士通)、BUBCOM80(システムズフォーミュレート)により、当時のハイ~ミドルクラスのパソコンのグラフィック表示は640×200ドット・8色がスタンダードとなったように思います。やや後れを取ったMZも翌1982年のMZ-2000でサポートしましたし、FP-1100(カシオ)、FM-7(富士通)、そしてX1と続きました。
しかし640×200ドット・8色の表示のためには48KBものグラフィックRAMが必要で、8bitマイコンのメモリ空間として一般的な64KBの領域にそのまま貼り付けたのではシステムもユーザープログラムも使いにくくてたまりません。多機能・高機能なシステムには相応のシステム領域が必要ですし、多機能・高機能なユーザープログラムのためにフリーエリアをできる限り広く確保しておく必要があります。
それをどう解決するかがアーキテクチャとしての要だったりするわけですけど、FM-8/7やFP-1100のようにサブCPUに全て預けてしまう(グラフィックターミナルを内蔵化するという発想だろうか)ような大胆なものはともかく、通常取られる手段は「バンク切り替え」ということになります。つまり一部のメモリをグラフィックRAMと取り替えられるようにするわけですが、
というデメリットを覚悟しなければなりません。
バンク方式はイヤだ…どのアドレスからでも自由にグラフィックを描画したい…! という思いを、X1ではI/Oアドレスを拡張して「16ビットI/Oアドレス」として使える方法を用い、グラフィックRAMをまるごとI/O空間に配置することでこれを解決しました。
このページでは、そんなZ80のI/O拡張についてのアレコレを探ります。
「16ビットI/Oアドレス」とは
まずは「16ビットI/Oアドレス」というものをおさらいしておきましょう。その「16ビットI/Oアドレス」というのも正式な用語ではなく、ここでの便宜的な呼び名です。
Z80の入出力命令は、アセンブリ言語でこう書かれます。
IN A,(n) OUT (n),A IN r,(C) OUT (C),r
前2つが直接I/Oアドレス、後2つが間接I/Oアドレスでの書き方です。nは8ビットの数値を意味し、つまり0~0xFF(255)のいずれかということになります。CとはCレジスタ、つまりこちらも0~0xFFまでの数値が収められている8ビットレジスタをアドレスとして参照するわけです。なおrとは任意の8ビットレジスタを指します。
こうして見るとI/Oアドレスとは8ビットの数値で表されるものであると理解できます。メモリアドレスは16ビット、0~0xFFFF(65535)の値をとりますから、幅として半分ですね。
しかし、Z80のマニュアル(引用したのはMZ-2200のオーナーズマニュアル)を見ると入出力命令の項に次のような文が書かれており、単純に8ビットアドレスというわけではないことがわかります。
直接I/Oアドレスの場合はAレジスタの内容が、間接I/OアドレスではBレジスタの内容がアドレスバスの上位に出力されます。なるほど、入出力命令で使われないアドレスバスの上位は何してるのかと思ったら、ちゃんと特定の動作をしているんですね。
特に間接I/Oアドレスの場合は、BCレジスタペアがそのままの姿でアドレスバスに出力されるわけですから、メモリアクセスと同じ感覚で便利に使えそうに思います。そして実際に、X1ではまるでもうひとつのメモリ空間のようにI/O空間にグラフィックRAMを割り付けて、BC間接アクセスにて図形を描画をするというアーキテクチャになっていました。
16ビットI/Oアドレスは隠し機能?
そんな「16ビットI/Oアドレス」ですが、Z80歴が長くてもこの機能が裏技や隠し命令や規定外動作だと思っている人がいて、マニュアルに掲載されていることをお教えすると令和の今でも驚かれることがあります。規定外動作というのは、代表的な例で言えばIX/IYレジスタの分割使用のように、構造上そのように動作するが公式に保証しないというものです。
かなり昔…それもいつのことだったか、さらにどこで見たものか(自分でそう思ったのか)わからないのですけど、「シャープはセカンドソーサなので中身をよく知っている。だからこの動作は、本来は隠し機能なのだけどメーカー保証できるのだ」とX1のGRAMがI/O空間に置かれていることを指して評した人がいました。確かにユーザーが経験として使えるだろうと判断するのと、そのように作ってあるのだからちゃんと動くことを知っているのとは大きな差があります。
雑誌の投稿欄には、「GRAMをI/Oに置いてるなどというウソをつくメーカーなんて信用しない」という友人のことを書いたものがありました。それくらい、16ビットI/Oアドレスというものが知られていなかったということなのです。
さきに紹介したマニュアルの文言というのはセカンドソーサであるシャープのマニュアルからの抜粋なので、「セカンドソーサの責任で規定外動作を公認している」とか「利用者が多いので追認している」という可能性も考えられます。ラトルズ刊「ザイログZ80伝説」にも、この動作を後で補足したという記述があるくらいです。
ではその本家ザイログのドキュメントを見てみましょう…Internet Archiveに1976年発行と思しきTechnical Manualがあります。その38ページには…
と、同じ内容の文章があります。そりゃまぁシャープのマニュアルはザイログのを和訳したものですから当たり前なのですが…ポイントはザイログのマニュアルの発行年が1976年、つまりZ80が発表されたまさにその年ということ。そう、本当に最初から16ビットI/Oアドレスはマニュアルに記述された、メーカー公認の機能だったというわけです。
なお、同じくInternet ArchiveにあるProduct SpecificationはTechnical Manualより新しいようなのですが、16ビットI/Oアドレスに関する記述がありません。この資料に対応するシャープ発行の資料も手元にあるのですが、そちらも同様です。おそらく細かい動作についての説明をTechnical Manualに譲って、概要だけに留めた結果省略されたのではないかと思います。Procuct Specificationも後の時代のものには命令一覧に注釈されるようになりました(型番がZ8400と表記された/CMOS版が並記されるようになったあたりと推測)。
ということで、16ビットI/Oアドレスはメーカーとして公認している動作だし、マニュアルにも記述してあるので隠しているわけでもないということがわかっていただけたと思います。
なぜ「16ビットI/Oアドレス」が隠し機能だと思われたのか?
まぁしかし、「マニュアルに書いてある」といっても総まとめ的な機能説明の箇所じゃなくて命令の解説のところに注釈されてる風だったりするわけで、気づかなくても仕方ないような気はします。それに、他にも「I/Oアドレスは8ビット」と思い込む原因と思われるものはあります。
まずやっぱりニーモニック表記ですよね。本来意識されるアドレッシングを無視したことですっきりわかりやすくなったZ80のニーモニックの、そのシンプルな表記ルールからすればI/Oアドレスは8ビットであるとしか理解できません。
IN A,(n) OUT (n),A IN r,(C) OUT (C),r
nというのは8ビット即値(イミディエイト)を指します。16ビットならnnとかlmとか書かれます。Cレジスタ間接でもBCと書かれてない以上Cレジスタでのみ表すことのできる数値になるはずです。こういう表記をして「アドレスは16ビットで指定できます」とか連想する方が無茶です。
もうひとつ、マニュアルにある落とし穴がI/Oサイクルを説明した図です。この図のポートアドレスはA0~A7であるとされているのです。
この図は先の日本語の説明文が載っていたのと同じMZ-2200のオーナーズマニュアルにあるものです。一方ではアドレスバスが16本とも意味があるとし、もう一方では8本にしか意味はないと読める図があったわけです。意外にもこの表記はかなり長く使われ続けたようで、ネットで探したところでは1984年のドキュメントにも見ることができます。NECのuPD70008ACでも同様で、1990年版のマニュアルで確認しました。なお最近のザイログのマニュアルでは修正されてA15まで書かれており…気づいたのか指摘されたのか…。
とは言うものの、今でこそメーカー自身が自社のWebサイトでドキュメントを配布しているおかげでその内容を楽々確かめることができますが、当時はマニュアルが有償頒布だったりして、特に一般のパソコンユーザーには縁遠いものでした。ある時期まで本体や純正アセンブラを買うとZ80マニュアルが含まれていたMZユーザーは特殊な環境だったわけですが、堅い文章と専門的な基礎知識を要するマニュアルはさすがに全員が熟読するとは限らず…。
そんなわけで当時のホビイストが専ら情報源としたのはZ80を易しく解説してくれる書籍や雑誌記事でした。改めてその内容を確認して、16ビットI/Oアドレスに関する記述がどうなっていたか表にまとめてみました。まだ確認していない本もありますし、確認したといっても簡易的なもので見落としがあるかもしれません。
まずは単行本。題についているリンクは一部を除き国立国会図書館デジタルコレクションにて個人向け送信サービスに対応したものです。無料の会員登録を行うと国会図書館に行かなくても中身を読むことができます。
題 | 出版社 | 初版発行日 | 確認した版数と日付 | 直接 | 間接 | 備考 |
Z-80マイクロコンピュータ | 丸善 | 1979年6月30日 | 第13刷 1995年2月25日 | × | ○ | |
図解マイコン入門 | 産報出版/秋葉出版 | 1979年9月25日 | 新装版 1986年2月10日 | △ | △ | ※1 |
Z80マイコンプログラム テクニック |
電波新聞社 | 1980年4月30日 | 第2版 1981年2月20日 | × | × | |
図解マイクロコンピュータ Z-80の使い方 |
オーム社 | 1981年5月20日 | 第1版第6刷 1982年6月10日 | × | × | |
BASIC+Z80 アセンブラプログラミング |
工学図書 | 1982年4月20日 | 初版 | × | × | |
演習マイクロコンピュータZ80 | 昭晃堂 | 1982年7月31日 | 初版 | ○ | ○ | |
マイクロコンピュータの基礎 8085・Z-80・6800 |
日刊工業新聞社 | 1982年9月30日 | 初版 | 表 | 表 | ※2 |
BASIC to ASSEMBLER | CQ出版社 | 1983年5月30日 | 初版 | × | × | |
図解マイコンアセンブラ入門 | オーム社 | 1983年10月25日 | 初版 | 表 | 表 | ※2 |
Z80サブルーチンズ | マグロウヒル出版 | 1984年4月10日 | 初版 | 表 | 表 | ※2 |
Z80アセンブラと制御入門 | 啓学出版 | 1984年5月31日 | 初版 | × | × | |
画像処理システムの 基礎と設計・制作 |
CQ出版社 | 1984年8月1日 | 初版 | × | ○ | |
CP/Mによる マシン語(Z80)開発法 |
ナツメ社 | 1984年11月25日 | 初版 | × | × | |
Z80ファミリ・ハンドブック | CQ出版社 | 1985年1月10日 | 第9版 1989年8月10日 | ○ | ○ | |
Z80マシン語入門 | 工学社 | 1985年1月20日 | 第3版第2刷 1985年4月25日 | × | ○ | ※3 |
インタフェースの 周辺回路とプログラミング |
日刊工業新聞社 | 1985年2月28日 | 初版 | × | × | |
Z80マシン語ランド | ラジオ技術社 | 1985年5月25日 | 初版 | × | × | |
Z80プログラミングデザイン | 秀和システムトレーディング | 1985年12月18日 | 初版 | ○ | ○ | |
はじめてのアセンブラ | ナツメ社 | 1985年12月25日 | 初版 | × | × | |
実験で学ぶ Z80/8085メカトロ制御 |
総合電子出版社 | 1986年1月20日 | 初版 | × | × | |
例解Z80マイコンの ハードとソフト |
東京電機大学出版局 | 1987年9月21日 | 初版 | × | × | |
※1:8080/8085と共にZ80を解説した本で、8080と8085は上位アドレスに下位アドレスと同じ値が出るがZ80は「他のレジスタの値」が出るとされ、厳密な説明にはなっていない ※2:本文には記載がないが、命令一覧表に記述がある。多くの場合一覧表はデータシートの転載であり、転載元の表に記述があったのが反映されていると思われる ※3:囲み記事にて、X1の事例を引用して説明。 |
こうしてみると、記述のない本が多いですね…特に早い時期に発行されてベストセラーと言って差し支えないであろう「Z-80の使い方」に記述がない影響は大きい気がします。「使い方」はその後たくさんのCPU向けに展開されたシリーズで、それはZ80のものがよく売れたからに他ならないと思われるだけに…。
次に雑誌。
掲載誌 | 出版社 | 発行号 | 記事名 | 直接 | 間接 | 備考 |
トランジスタ技術 | CQ出版社 | 1980年11月号 | 保存版・Z80の徹底研究 | ○ | ○ |
注釈しておきますが、書かれてないからといってそれが著者のマニュアル読み込み不足を指しているとは限りません。解説の方針として、16ビットI/Oアドレスの説明は不要だと判断したということもあるでしょう。プログラム例として特定の機種を想定したサンプルを掲載するなら、その機種で16ビットI/Oアドレスが使われていない限りわざわざ書く必要はありませんからね。
ただそういった事情を読者がわかっているとは限らず、そして似たような本を何冊も買うことはあまりないでしょうから、その人にとって手にしたその本がバイブルとなってしまうことも否めないんですよね。16ビットI/Oアドレスのことが書いてなければそんなものはないor正式な命令ではないと思ってしまうのも仕方ないことでしょう。
16ビットI/Oアドレスを採用したパソコンとそのレビュー記事
次に、16ビットI/Oアドレスの機構を用いたパソコンの、その当時のレビュー記事を探っていきましょう。ホビイストの情報源はZ80の解説本だけに限らず、いやむしろ雑誌記事の方がウェイトが大きかったりもしたはずです。
そして雑誌記事での取り上げ方にはZ80解説本のような技術的視点だけでなく、営業的視点も影響を与えていることが推測されます。営業的視点については追々。
●X1
X1は後継機種のX1turboを含めてユーザー数が最も多い16ビットI/Oアドレス採用マシンだと思います。次に「試験に出るX1」に掲載されたI/Oマップを示します。
1982年10月発表の初代X1は、翌11月に発売された各誌12月号にてその登場を速報されました。それぞれ新製品ニュース程度の軽い扱いだったり1ページ割いたりなど対応はさまざまでしたが、共通していたのはスーパーインポーズやPCG・PSGなど特徴的な機能を紹介した以外は基本スペックを並べる程度の内容となっていたことです。
月刊マイコン誌はその12月号にて「最新パソコン大紹介」と銘打って、5機種について全38ページにわたる解説記事を特集で掲載しました。X1も8ページを割いて詳しく報じています(他の4機種はMZ-700/JR-200/PASOPIA
mini/PC-9800)。
しかしその記事でもグラフィックRAMがどのように実装されているのかの説明はありません。他機種のBASICにない命令を紹介するなど、BASICの使い心地を解説したりはするのですが、いわゆる低レイヤーに関する技術的な話題がないのです。これはどういうことなのか?
実は各雑誌がまず参考にできるのはプレスリリースで、そこにはグラフィックRAMをどう実装しているかの説明がないのです。マイコン誌の記事では試作機を触っている旨の記述はありますが、おそらく製品に添付されたマニュアル程度の資料しかなかったものと推測されます。
つまりこれが、先ほど触れた「営業的視点」というやつです。末端のユーザーにしてみれば、それがどれだけの表現力を持つかが重要であって、その表現力をいかにして実現したかということは割とどうでも良いわけです。ほとんどのユーザーはBASIC言語を触るか市販のゲームを買うかしかしないですから、そういう人がその機種を選ぼうというインセンティブになる情報…グラフィックの解像度や色数、音楽、ジョイスティックなどのI/Fという表面的なスペックばかりを強調するのです。例えばLINE命令で命令通り線が引けるのならグラフィックRAMがどのように実装されているか知らなくても支障はありませんからね。
ではどのあたりで16ビットI/Oアドレスが使われていることが明らかになったのでしょうか。月刊アスキー誌は1983年8月号にてX1のLOAD TESTを掲載し、その中で「I/O制御」の項にて
"これは,Z80Aのレジスタ間接モードを利用した,I/OデバイスとZ80A内部レジスタ間とのデータ転送のことで,X1ではCレジスタを使用したI/O命令を実行すると,アドレスバス上にBCレジスタの内容が出力され,このBCレジスタによってI/O空間のアドレス配置を決定している.この方法により,ビデオRAMアクセス時は,単なる入出力命令でアクセスが可能となり,バンク切り換え方式に比べてソフトウェアの負担を軽減できる."
と16ビットI/Oアドレスの採用について紹介しています。技術的に突っ込んだ記事であるLOAD TESTならではの、Z80の機能をそのまま素直に説明した文章です。
月刊Oh!MZ誌はまず82年12月号で半ページを使って新製品情報としてX1を紹介。翌83年1月号では「パソコンテレビX1登場」としてカラー2ページを含む計9ページでかなり詳しく報じていますがI/Oに関する内容はありません。しかしその後実機を入手したとのことで、翌2月号でももう一度X1についての解説記事が「続報 パソコンテレビX1登場」として掲載されます。そこにはこのような記述で16ビットI/Oアドレスのことが書かれています。
"X1のCPUはZ-80Aですが,8bit CPUの64KBの他にI/O用として64KB分のエリアをとってあります。このI/O用エリアをメモリエリアに転用して,128KBを使用できるようにしているわけです。アブノーマルな方法ですからいろいろとソフト的に問題がでてくるのではという不安がありますが,これも入念に計画が進められたらしく,見事にソフトウェアで乗り切っています。"
予備知識がないと何のことを言っているのかわかりにくい文章ですね。マシン語をよく知らない読者に向けて、詳細な動作の説明を避けながら背景を紹介しているということなのでしょう。
比較的詳細な紹介記事として最も早かったのが月刊ソフトメディア誌です。それもそのはず、ソフトメディア誌はハドソンが発行していた雑誌なのでX1については「中の人」から直接情報を得ることができた立場だったと思われるからです。他誌がプレスリリースしか情報源のなかった82年12月号にて、「パソコンテレビX1特集」としてわりと突っ込んだ内容の紹介記事が掲載されています。16ビットI/Oアドレスに関する記述はこうなっています。
"こういう具合に、バンク切り替えにたよるくらいなら、いっそのこと、I/O空間として持っている64Kバイト分の容量もメモリ空間に転用しようという発想がこのCZ-800Cのスタートなのだ。
(略)
そのZ-80Aでは、I/O空間の中に、直接CPUがアクセスできる容量が256バイト。実に全体の256分の1にしかならない。
(略)実際にZ-80Aの取扱いマニュアルでも、I/O空間の使用は、256バイトにしておいて、あとの256分の255はあけておくように指示されている。
しかし、このあいている「空室」を利用しない手はない。(略)
ただし、本来使わないはずの空間を利用するわけだから、そこはそれだけの工夫も要求されてくる。いってみれば、本来的にこのCPUを作ったザイログのティピカルなつかい方ではないだけに、自由にどんなコマンドでも扱えるとはいかなくなる。こういった特殊な使い方に見合うよう、決められたコマンドを有効に使うという技術がなくては、このような発想は生まれてこない。"
なんだか記事ではそもそもI/O空間は64KBあって、理由は定かではないですがザイログが256バイトまでしか使わないように推奨していると、これまでの認識からすると逆の表現になっているのですが…。まぁイリーガルな使い方であることは認識しているようでもあります。
●SMC-70
実はソニーのSMC-70も、16ビットI/Oアドレスを活用したマシンです。後継機であるSMC-777も含んだI/Oマップが、すーぱーたーぼさんのサイト「X1リソースセンター」でご覧になれます。
SMC-70の新製品情報が各誌に掲載されたのは1982年7月号ですが、月刊アスキー誌のみなぜか6月号に掲載されています。しかも、早速16ビットI/Oアドレスについての記述があります。
"SMC-70ではZ-80Aの特性を利用してI/O空間を64Kに増し,その空間にはビデオRAMを配置している.Z-80AのCレジスタを介した入出力命令ではBレジスタの内容がアドレスバスの上位8bitに出力される訳であり,そのアーキテクチャを十分に活用した方法である.これにより,64kByteのユーザーメモリを持ちながら,入出力命令を用いることに依ってビデオRAMを直接アクセスできることになる."
他誌と比較しても内容の粒度が違いすぎるのですよね…おそらく他誌はプレスリリースに基づいた記事を書いたのだと思うのですが、アスキーのはソニーの担当者から直接情報を得ている気がします。
アスキーは翌7月号にも「続報」としてレビュー記事を掲載しています。SMC-70はまず米国で発売される(この時点で日本国内投入は未定)とのことで、アメリカ向け仕様のマシンを評価しています。そしてこの記事にも、16ビットI/Oアドレスに関する記述があります。
"Z-80Aは64KBのメモリ容量を持つが,SMC-70ではさらにI/Oアドレス空間を64KBに増し,メモリ空間を倍増している.これはCレジスタを介した入出力命令を利用するものだが,(略)"
(本当はもうちょっとアーキテクチャに関わる記述が続くのだが、それは後ほど)
12月に国内販売が開始されると、早速月刊マイコン誌が83年1月号で「最新パソコン紹介 SONY Micro Computer SMC-70」と題したレビュー記事を掲載しました。内容的にもそれなりに踏み込んでおり、16ビットI/Oアドレスについての言及もあります。
"Z-80の特性をうまく利用しI/O空間を64Kに増して,そこにVRAMを配置していますので入出力命令を用い直接VRAMをアクセス出来るので高速の画面制御が簡単に行えます。"
月刊I/O誌の83年2月号では「SMC-70 高速PUTサブルーチン[グラフィック・データ転送ルーチン]」としてマシン語によるグラフィックRAMへの転送ルーチンのサンプルを掲載しています。ここでもその変わったアクセス方法について少し言及があります。
そして1983年5月号のアスキー誌掲載「LOAD TEST」にてSMC-70が取り上げられた際にも、ビデオRAMの項での実装方法の解説に絡んで16ビットI/Oアドレスについての説明があります。もちろんこれはSMC-70のアーキテクチャに関わる大事な部分だからですね。
"Z-80Aでは,Cレジスタを介してのI/O命令を実行した場合,Bレジスタの内容がアドレスの上位に,Cレジスタの内容が下位アドレスに出力される.つまり,16ビットのアドレスがバスに出力されることになり,64Kバイト分のI/Oをアクセスすることが可能となる."
アスキー誌はちょっと特別な背景がありそうですが、マイコン誌やI/O誌でも早々に技術的な内容の記事が掲載されている要因として、別売りながら詳細に内部を解説したマニュアルの存在が挙げられると思います。後発メーカーの策として、有志や雑誌のライターによる解析記事を待たずに技術情報を提供してソフト作品の登場を喚起しようとしたものなのでしょう。
●BUBCOM80
知る人ぞ知る「謎のマシン」はまたスペックも知られているわけではありません。武田さんがeBUBCOM80を制作するために解析した資料のとおり、BUBCOM80も16ビットI/Oアドレスを活用したパソコンでした。
PET-2001の代理店やパソコン教室の運営で名を馳せたベンチャーであるシステムズフォーミュレートが、自らパソコンを開発・販売するというのは当時かなり評判になったようです。
特にアスキー誌では、社長の渡辺氏が海外の展示会のレポート記事を寄稿するなど以前から関係が深かったせいか、発表直後の1981年6月号に速報にしてはわりと詳細なレポート記事が掲載されました。そしてそこには16ビットI/Oアドレスに関する記述があります。
"Z80AがCレジスタ間接モードでI/Oアドレスをアクセスする際(IN (C),OUT (C)など),アドレスの高位8bitにBレジスタの内容が出力されることを利用して,I/Oのアドレスを16bitフルデコードし,64Kbyteに拡大するというものです.これによりグラフィックメモリ等はすべてI/Oアドレスに割り付けることができ,メインメモリの侵食は防止されています."
新しい記憶デバイス「磁気バブルメモリ」採用などで話題をさらうかと思いきや…製造を担った富士通からCPUは違うけどカラーリングがそっくりで磁気バブルメモリカセットも使えるというFM-8が直後(発表ベースでは3日後とか)に登場して、すっかり陰が薄くなってしまいました。高価なことも手伝って一般ユーザーが増えにくく、雑誌記事にもならなかったりしたので、16ビットI/Oアドレスを採用したことも広まらなかったのでしょう。
16ビットI/Oアドレスは偶然か? 意図した設計か?
もう一つ疑問が残っています。それはこの「16ビットI/Oアドレス」というものがなぜ存在(機能)しているのか…です。マニュアルに書いてあるのですから、公認されている機能である=仕様として存在している、ということではあるんですが、その割には制約が多いのです。
直接アドレスの場合、OUT命令ではデータバスとアドレスバスの上位とに同じAレジスタの内容が出力されます。これが許される使い方は限定されますよね。書き込み信号をトリガとして使いたいだけでデータの中身はどうでもよいとかでないと使い途はないでしょう。
間接アドレスの場合はもっとで、リピート命令でのカウント値がアドレスバスに出てしまうのですから、OTIR/OTDR/INIR/INDRは使えません(と言うか、使えないわけではないが、使うための前提条件がある)。あらかじめ準備をしておかなければ使えない命令とか、RST命令なんかもそうなのでそれほど例外的なものではないですけど、それでもリピート命令はZ80の目玉のひとつですから使えなくなるというのはいかがなものか…。
そう考えると公認はしているけれどそもそもは偶然の産物だったのではないか? という気がしてきます。偶然の産物というのは、IX/IYの分割使用がHLの回路を流用したせいで可能になったというように、構造上そのように動くけれど狙ったわけではない動作のことです。
この考察には、命令の成り立ちに注目する必要があるでしょう。それは直接と間接のアドレッシングの違いのことで、前者は8080互換命令であり、後者はZ80オリジナル命令であるということです。
●直接アドレスI/O命令
直接アドレスにて入出力を行う命令とは、次の2つです。
IN A,(n) OUT (n),A
これは8080に存在する命令で、Z80は8080と互換をとりつつ機能向上を図るというコンセプトからすれば、Z80での直接アドレスI/O命令の動作は全て8080のものから引き継がれていると想像できます。
では8080が実際にどう動いているか見てみましょう。MCS-80 FAMILY USER'S MANUALのChapter 2.にTHE 8080 CENTRAL PROCESSING UNITという、かなり詳細に内部情報を記述した章があります。その機能ブロック図を示します。
レジスタのところに、見慣れぬWとZというのが並んでいます。拡大したのがこちら。
WとZはそれぞれ8ビットのレジスタで、ペアで16ビットとして扱えそうな表記になっています。またTEMP REG.とあるようにテンポラリとして使われるもので、プログラムから明示的に使用することはできません。
データシートではブロック図にしかWZレジスタの記述を見ることができませんが、ユーザーズマニュアルではマシンサイクル毎の内部動作まで説明されていて、そこでWとZはアドレスバスを介して外部にアドレス値を出力するためのテンポラリ用であることが示されています。
そのマシンサイクル毎の動作、I/Oについてはこんな感じで書かれています。
M2サイクルのT2ステートからT3ステートにかけて「B2→Z,W」、つまり命令の2バイト目(I/Oアドレス)をWとZに転送するとあり、M3サイクルのT1にて「WZ OUT STATUS」、つまりI/Oアドレスが外部に出力されるとあります。
WZ OUT STATUSには注釈18が付与されています。注釈18にはこんなことが書いてあります。
I/Oポートの8ビット選択コード=I/Oアドレスはアドレス信号の0-7(下位)と8-15(上位)に複製される…上位と下位とで同じ値が出力されるということですね。
WZレジスタは、通常メモリアドレスが一時的に入るレジスタなので常に16ビット分が有効(出力される)なのだと思われます。そこに8ビット分しか必要のない入出力命令でWZレジスタを使うならば、不要な上位ビットにも何らかの値をセットしなければ仕様上は不定値ということになり、外部の回路が誤動作を起こすかもしれません。
この時、ソフト的には0x0とか0xFなどわかりやすいシンプルな値が入っている方がいいのでしょうが、値をセットするのにも回路が必要で、そのスペースや検証の手間を考えればどこかに配線をつなぐだけにする方が簡単だ…という事情があると推測します。それゆえに固定値を出力するようにはなっていないのでしょう。
ということはこれ、Z80の動作とは違うじゃないですか…。Z80にもW,Zレジスタに相当するものがあるそうで(そりゃそうだろうなとは思う)、回路設計上の事情は8080とZ80に共通していると思われますし、同じ構造になっていても不思議はないのですが…。
以上から、直接アドレスでの入出力命令の動作は8080に倣ったものであるという仮説は間違いということになります。意外なところに8080とZ80の非互換部分を発見してしまった格好ですが、ではなぜ変えたのでしょうか。
次のような理由があるのではないかと考えます。
Z80の開発者である嶋正利氏の著作「マイクロコンピュータの誕生 我が青春の4004」に、次のような文章があります(141ページ)。
”Z80マイクロプロセッサを設計するに当たり,最も苦労したのは,いかに8080と異なるように論理を設計するかであった.8080を知っているからZ80の論理は組めるのだが,インテル社で開発した論理を避けて新しい方法を見つけるのは決してやさしくはなかった.”
いくら8080の開発者達がスピンアウトしたからといって、彼らの技術を行使した結果生まれたもの=8080を製造する権利は前の会社にあるわけで、スピンアウト先で同じ回路を使った製品を作ればコピーしたのと変わりません。技術を行使する権利が人についてまわるとだけ考えていると陥りやすい落とし穴になりそうです。
後に互換製品を作る場合はデータシートなど公開された仕様書や外部から観察可能な範囲での解析情報以外を参照しないようにする「クリーンルーム設計」を徹底することが求められるようになるのですが、時代背景云々以前に、8080開発チームが直接Z80を開発していたこのケースでは内部を詳細に解析されたとしてもコピーしたとは捉えられないくらいに違ったものにする必要があったということなのかもしれません。
●間接アドレスI/O命令
間接アドレスにて入出力を行う命令とは、次の10個です。
IN r,(C) OUT (C),r OUTI OTIR OUTD OTDR INI INIR IND INDR
ここにはブロック命令も含まれます。
間接アドレスの場合、上位8ビットにBレジスタの内容が出力されるのはなぜかという疑問の前に、そもそもの話としてなぜCレジスタが間接指定用に選ばれたのかという謎があります。いろいろ考えてみたのですが、これは先にブロック命令があったからとする方がしっくりくるのではないかと思いました。以下がその内容です。
ブロック転送命令(LDI/LDIR/LDD/LDDR)では、BCレジスタがカウンタとして使用されます。ですから、ブロック入出力命令でもBCレジスタをカウンタとして使うのは自然な流れと言えます。ただどうやらポート入出力においてブロックの長さが255を超えないという想定をしたようで、カウンタとして動作するのはBレジスタのみということになりました。外部デバイスに連続して出力/入力するというのは今ではストリームデータという捉え方ができると思うのですが、この当時にはそんな発想はなかったということなんでしょう(プログラムでループさせればいくらでも増やせますしね)。
いやしかしカウンタならCレジスタを割り当て(ブロック転送命令でのBCカウンタの下位側を使うというイメージ)、ポートアドレスにはEレジスタを使っても良かったような…それでは乱雑すぎますか。ひとつの命令を使うのにBCもDEも汚すのはムダですね。
ではカウンタはCレジスタとしてポートアドレスをBレジスタにする…? アドレスバスの上位・下位にはレジスタペアの上位・下位が割り当たっているのが転送命令での姿でしたから、もしBレジスタをポートアドレスにするなら上位バイトを下位アドレス線につなぐルートがここにだけ必要になるわけですよね。それもそれでまたムダというもの…。
と考えていくと、「レジスタを有効活用する」「他の命令との調和を図る」ことでムダを省いた結果Cレジスタをポートアドレスに、Bレジスタをカウンタに使用するという現実の結果が一番良いということになりますね。そして本当はCレジスタにしか用事はないのだけれど、アドレスバスに出力するとレジスタペアとしてBレジスタがセットで出力されてしまうメモリアクセス用の仕組みはそのままなので、I/Oにも16ビットアドレスとして使えてしまうということになったのでしょう。カウント値までアドレスバスに出ちゃうのは目を瞑るとして。
ブロック命令ではない間接アドレスの入出力命令でもCレジスタがポートアドレスになっているのは、ブロック命令の機構を共有(利用)しているからだと推測できます(もしかしたらブロック命令でのインクリメント/デクリントを働かせない状態で動かしているのかも)。ここだけ別のレジスタを使ったり、直交性を意識して汎用的に他のレジスタでもポートアドレスにできるようにしてもムダとかやり過ぎとかになってしまうのでしょう。
ここまでいろいろ考察してきましたが、ちょっと面白い結果になりました。
嶋氏は著作でもここまで細かい点について解説していたりはしません。ひとまず、ここでの結論はこういうことにしておきましょう。
●別の視点
現在ザイログのサイトからダウンロードできるZ80ユーザーズマニュアルは1976年当時の物とは構成が変わっており、命令一つずつを1ページ単位で丁寧に解説するなど全面的に改められています。その中のI/O命令の説明について、指摘を下さった方がいらっしゃいました。
まずは「IN A,(n)」のページ。
動作の説明で、アキュムレータ(Aレジスタ)の内容がappear、つまり「現れる」と表現されています。あまり能動的じゃないというか、たまたまぽっかり浮かび上がってるみたいな、そんな雰囲気です。
次に「IN r,(C)」のページ。
こちらはBレジスタの内容がare placed、つまり置かれるとありますね。現れるのとは結構な違いがあるようにも思えます。それに、どちらもデータについてはis placed、つまり選択されたポートからデータバスにデータが置かれるとあるので、appearとare placedの書き方の違いは意図したものの可能性があると考えてしまいます。
指摘を下さった方は、AFレジスタペアを考えれば、Aレジスタが上位側なので他の16ビットレジスタと同様にアドレスバスに出力されるのも上位側になるとの示唆も下さいました。確かにAレジスタの内容が上位に出る理由にはなります。Fレジスタをアドレス下位側に出すわけにはいかないので、こちらだけ命令のオペランドにすげ替える処置をして、Aレジスタはスルーした…?
それと、直接/間接関係なくどちらもI/Oデバイスの選択はアドレスバス下位8ビットで行うように書かれていて、上位8ビットはただそれぞれのレジスタの値が出るだけでアドレスを16ビット幅で使えるような意味にはなっていないように見えます。あくまでI/Oアドレスは8ビット幅なんですね。
注意しておきたいのは、マニュアルが新たに書き改められたからといって、それが本来の設計の意図を反映したものであるとは限らないということです。もちろん「この際本来の意図を反映したものにしよう」と考えた可能性もあれば、「設計の意図はともかくあらためて定義し直そう」と考えた可能性もあるからです。現状では何やら書き分けた意味があるらしい…というところに留まります。
結局、マニュアルも含めて書いた人(作った人)に聞かないとわからないじゃないか、というお話ですね…。
16ビットI/Oアドレスの使い方
意図的と言えば意図的、偶然といえば偶然、しかし少なくとも何らかの利用シーンを想定した設計とは考えられない16ビットI/Oアドレスの使い方を考えます。そこに「正しい使い方」とかあるわけはないんですが、ハード・ソフト共にいろいろな思想がありましたしね。
●X1、BUBCOM80のケース
I/O空間を、シンプルに「もう一つのメモリ空間」として使用している場合です。これは、
と言えます。
リピートしないものなら、ブロック入出力命令は使いようがあります。例えば、次の例はHLアドレスからBCポートへDEバイト分ブロック出力するプログラムです。
LD HL,8000H LD BC,3000H LD DE,0800H LOOP:INC B OUTI INC BC DEC DE LD A,D OR E JR NZ,LOOP
OUTIは、
DEC B LD r,(HL) OUT (C),r INC HL
をひとつの命令で実行してくれる複合命令です。事前の「INC B」が余計に必要ですが、それでも2バイト・5クロックは短縮してくれます。
●MZ-1500/2500のケース
X1のようにアーキテクチャとして全面的に採用していたわけではないのですが、MZシリーズにも一部に16ビットI/Oアドレスが応用されています。
紅茶羊羹さんのサイト「We Love MZ-700」にあるMZ-1500のI/Oマップのうち、RAMファイル(MZ-1R18)と漢字ROM(MZ-1R23)/辞書ROM(MZ-1R24)を抜粋してみます。RAMファイルは64KBの外部RAMボード、漢字ROMは第一水準の16ドットフォントなので128KB、辞書ROMは256KBの外部ROMボードということで、いずれもバンク切り替えを前提とせず大容量のメモリをアクセスする要求があるわけです。
アドレス | R/W | 説明 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
RAMファイル (MZ-1R18) |
EAh | R | データ読み出し・アドレスカウンタ+1 | |||||||||||||||||||||||||||
W | データ書き込み・アドレスカウンタ+1 | |||||||||||||||||||||||||||||
EBh | W | アドレスカウンタの書き込み 上位バイト={A15-A8}, 下位バイト={D7-D0} |
||||||||||||||||||||||||||||
漢字ROM (MZ-1R23) 辞書ROM (MZ-1R24) |
B8h | W | 制御ポート
|
|||||||||||||||||||||||||||
B9h | W | 漢字パターン番号 / 辞書ROMアドレス 上位バイト={A15-A8}, 下位バイト={D7-D0} |
||||||||||||||||||||||||||||
R |
データ読み出し(オートインクリメント) パターンは左上→左下、右上→右下の順に読み出される |
RAMファイルではポートEBhのアドレスカウンタの書き込み、漢字ROM・辞書ROMではポートB9hの漢字パターン番号/辞書ROMアドレスにおいて、16ビットI/Oアドレスが使われています。いずれも、I/Oアドレスの上位バイト側に設定するアドレスまたは番号の上位バイトをセットし、下位側はデータバスを通じて出力しています。つまり16ビットの値を一度に出力するためのテクニックですね。
過去の製品では、16ビット以上の値をセットする必要がある場合、8ビット単位に分けて別々のポートへ出力するようになっていました。上記の方法はそれに比べてポートアドレスを節約できますし、セットしたいアドレスをBCレジスタに入れてあるとすると
LD A,C LD C,EBh OUT (C),A
とすっきり表現できます。上位下位をそれぞれ出力するのに比べて1バイト縮められます。
同じく紅茶羊羹さんの「大深海水淵亭」にあるMZ-2500のI/Oマップの方から、EMM(RAMディスク、MZ-1R37)とROMディスク(HDD I/FのブートROM部)を挙げましょう。EMMは640KBのRAMディスク、ROMディスクはEMMと同構造のメモリディスクとなります。
アドレス | R/W | 説明 | |
---|---|---|---|
EMM (MZ-1R37) |
ACh | W | アドレスラッチの書き込み EMMアドレス[19:16]={A15-A8}, EMMアドレス[15:8]={D7-D0} |
ADh | R | データ読み出し EMMアドレス[7:0]={A15-A8}, データ={D7-D0} |
|
W | データ書き込み EMMアドレス[7:0]={A15-A8}, データ={D7-D0} |
||
ROMディスク | A8h | W | BIOS ROM アドレスラッチの書き込み ROMアドレス[19:16]={A15-A8}, ROMアドレス[15:8]={D7-D0} |
A9h | R | BIOS ROM データ読み出し ROMアドレス[7:0]={A15-A8}, データ={D7-D0} |
MZ-1500のRAMファイルなどと同様に、アドレスの設定を16ビット値で出力しています。さらに、データの読み書きについてもI/Oアドレスの上位バイトを使用していますね。
MZ-1500の時はボード上のアドレスレジスタがカウンタで構成されていたので、読み書きのたびにオートインクリメントされていたのですが、MZ-2500のEMMなんかでは全20ビット中上位12ビットのみがレジスタで、カウンタではなく、下位8ビットは読み書きポートアクセス時のI/Oアドレスの上位バイトで指定するわけです。下位なのに上位とかややこしいですが。
こういう構造になっていることで、OTIR/OTDR/INIR/INDRのリピートつきブロックI/O命令でアクセスできるようになっています。カウント値がアドレスバスに出力されるのを逆に利用しているわけですね。
ハード的にはメモリ容量が10倍になったにもかかわらずアドレスレジスタを増やさずに済んでいるというメリットがあります。ソフト的には逆にちょっとややこしくなった印象もあるかと思いますけど、あくまでこれらを「ディスクメディア」として捉えると、フロッピーと同じく256バイト/レコードで構成されているとも解釈できて、アドレスの上位・中位バイトは合わせて「レコード番号」と読み替えられるとすれば、これはこれでわかりやすいかもしれません。
●SMC-70/777のケース
さきに紹介したX1リソースセンターにあるI/Oマップの一部を抜粋してみます。
ADDR | RW | device | label | function |
--18 --19 |
RW RW |
CRTC | ARPORT ADPORT |
HD460505SP Register port HD460505SP Data port |
--1A --1B --1B |
RW R W |
KEYBOARD | CDATA CSTAT |
M5M8041A-077P : Data M5M8041A-077P : Status & Handshake flag M5M8041A-077P : Control |
aa80 : aaFF |
RW | GRAPHIC | GVRAM | Graphic VRAM A[15:8]=GA[7:0] A[ 6:0]=GA[14:8] |
グラフィックRAMをI/O空間に配置するために16ビットI/Oアドレスを利用しているのはX1などと同じなのですが、アドレスの値が妙な書き方になっています。そしてfunctionのところをよく見てみると、ちょっとおかしなことになっています。アクセスしたいグラフィックRAMのアドレスGAの、下位がZ80のアドレスバスの上位と、GAの上位がアドレスバスの下位と結びつけられています。そして想像のとおり、この結びつけのままI/Oアドレスとして出力されます。
アドレスの上位と下位が逆転! 何が起こっているのかわけがわからなくなりそうですが、これが実に考え抜かれたアーキテクチャなのです。これは次の2つのメリットをもたらします。
I/Oアドレスの上位側には対象デバイスの下位アドレスが出力される。これはOTIR/OTDR/INIR/INDR命令でカウンタであるBレジスタがデバイスの下位アドレスとして表せるということです。つまりリピートつきブロック入出力命令で効率の良い転送ができるのです。
デバイスの上位アドレスをI/Oアドレスの下位に出力しないといけないわけですが、レジスタrの値をグラフィックRAMに書き込むのに
LD A,B OR 80H LD B,C LD C,A OUT (C),r
とするぐらいでできますから、たいして大きなコストでもないでしょう。
そしてグラフィックRAMを含めI/Oアドレスのデコードは下位だけで行われており、上の表で言うとCRTCやキーボードは特定のアドレスのみが判別できれば十分ということになっています。X1なんかのように16ビットデコードで統一せず、必要なところだけ16ビットI/Oアドレスで実装しているわけで、なかなかスマートだと思います。
まぁ結果的にはMZ-1500/2500のケースと同じようになっているわけですが、デバイスが増えていく中で16ビットI/Oアドレスを採用したMZと、16ビットI/Oアドレスを採用する方針ではありながらそれを最小限にしたSMCという、逆のアプローチになっているということなのでしょう。
●X1turboのケース
X1シリーズとフルコンパチを謳うX1turboですから、X1でのメリット・デメリットはそのまま引き継がれています。しかしX1turboにはZ80DMAが搭載されているという大きな違いがあります。
DMAとはCPUの代わりにメモリどうし・I/Oどうし・メモリとI/Oの間で高速にデータ転送をしてくれるLSIです。普段CPUが使用しているアドレスバス・データバスをCPUに成り代わってコントロールするので、当然ながらメモリやI/Oに関する制約はCPUと同じということになります。
しかしながらDMAは、CPUのような「メモリアクセス」「I/Oアクセス」といった明確な動作の違いというものはなくて、送り側と受け側のアドレスのカウンタがあって、それぞれがメモリ向けなのかI/O向けなのかを切り替えられるだけという仕組みになっています。つまりメモリ向けだろうがI/O向けだろうがアドレスカウンタは16ビットなのです。
実に平等な造りです。DMA的にはI/O空間は16ビットであると言わんばかりです。おそらくDMAの設計の方が後なので、CPUがI/Oアクセスも16ビットアドレス可能ならばDMAで制限する必要はないと判断したのでしょう。
そしてその機能がX1turboには幸いしました。I/O空間をメモリ空間のごとく使ってビデオRAMを割り付けたX1シリーズにはI/O空間をメモリ空間のようにアクセスするDMAはまさに鬼に金棒です。「試験に出るX1」ではEMMからグラフィックRAMに連続してデータ転送することでアニメーションを表示するプログラムを紹介したり、Oh!MZ/X誌ではテキスト画面をDMAで高速にスクロールする用例が掲載されたりしました。
ちなみにDMAにはCPUよりも短いサイクルでアクセスするよう設定できる機能があります(X1turboでは使えない)。CPUのI/Oサイクルが1クロック余計にあるのを解消できる可能性があるというわけですね。
互換CPUの対応について
最後に、Z80と互換性を持ち機能向上を図ったマイコン製品が16ビットI/Oアドレスについてどう対応したのか見てみましょう。ここでは、元のZ80をそのまま周辺LSIと共に複合化するなどの機能的に変化のないものは対象外としています。
●Z280
新世代Z80として一度Z800としてアナウンスされた後、仕切り直して24ビットアドレスバス・16ビットデータバス・MMU・キャッシュなど新機軸を搭載したZ280として登場しました。
従来とコンパチのZ80-BUSモードとZ8000と同じZ-BUSモードを備えたり、アドレスとデータの時分割方式に変わるなどハード面でもかなり様相が異なってきていますが、これでもZ80の上位互換MPUと謳われています。
I/Oは、新たにI/Oページレジスタというものが追加され、ここにセットした値がアドレスバスのA23~A16に出力されて、従来のA7~A0と合わせて16ビット・64KBのI/O空間が定義されました。では間のA15~A8はどうなったかというと…これまで同様直接アドレスではAレジスタ、間接アドレスではBレジスタの値が出力されるので、都合24ビット・16MBの空間として使うことも可能です。I/Oページレジスタを0x00のままにしておけば、従来通りの動作が維持されていると言えるでしょう。
●NSC800
ナショナル・セミコンダクターが手がけたCMOS版Z80。Z80のCMOS化は日本のメーカー(特に東芝)が多く出荷するようになって移行が進んだと思うのですが、それまでの低消費電力システム用途にそれなりに使われた互換CPUです。
NSC800は8085を彷彿とさせるアドレスとデータの時分割方式バスが特徴で、こちらの印象が強すぎて趣味者にはCMOS化が霞んで見える程です。しかし彷彿とさせるだけで8085とも端子配列互換ではないところが、どうにも解せないというか惜しいというか…。
そしてなんとZ80互換でありながら16ビットI/Oアドレスには非対応で、8085と同じく下位8ビットのI/Oアドレスが上位にも出力されるとユーザーズマニュアルには記述されています。いやここまで8085そっくりならなんで端子互換にしなかったんでしょうね…。
●HD64180/Z180
CP/M-68K開発中の雑談からCP/M3に最適なCPUの構想が生まれ、64180として具現化。ワイヤードロジックではなくマイクロコード式という話もあり、未定義命令に対してはトラップが発生するほどの厳しさ(トラップ先で未定義命令をソフトで記述するのが目的ではなく、ROM/RAMのリードエラーと見做してリセットするためにあるらしい)。
では16ビットI/Oアドレスも同様にトラップされるのかと思いきやむしろ逆で、I/O空間は64KBあることになっています。内蔵している周辺機能は0x0000~0x00FFの範囲にマッピングされており(64バイト単位で移動可能)、これらを楽にアクセス可能にするため上位アドレスが0x00で固定されるOUT0/IN0命令が追加されています。いちいちBレジスタをスタックにPUSHして0を入れて…とかの必要がないのはいいですね。
なお64180にはMMUが搭載されてアドレスバスが20~24本に増やされていますが、I/Oアクセス時はMMUは働かず、16ビットを超えるアドレス信号は0で固定されます。
●R800
MSXturboRシリーズで採用された、高速Z80。ALUが16ビットなので、分類の方法によっては16ビットマイコンと言えなくもない? DRAMコントローラとメモリマッパを内蔵し、28MHzの高クロックで処理します。
メモリマッパを経由することでアドレス空間は24ビットに広がりますが、MMUなどと同じくバンクメモリのような拡張方法なので、プログラム的なアドレスバスは16ビットのままです。R800ではメモリマッパ経由と経由しないものの両方のアドレスバスが出力されており、経由しないものは普通に16ビットになっています。
そのI/Oですが、ユーザーズマニュアルをいくら読んでも16ビットI/Oアドレスの機能があるかどうかハッキリしません。命令表にアドレス上位に関する動作説明はなく、それっぽいのは唯一タイミングチャートなのですが、メモリアクセスと兼用の図になっているために果たしてI/Oアクセス時もアドレスは16ビット全部が有効と理解していいのか判断がつきません。
なおMSXのI/Oマップは8ビットで表せられるものであり、ユーザーがわざわざそのように作らない限りは16ビットI/Oアドレスを使用する必要がない文化のようです。それゆえにR800でI/Oアクセス時のアドレスバス上位の状態を説明する必要もなかったのでしょう。
●Z380
お世辞にもZ280は商業的に成功したとは言えなかったのですが…ザイログは性懲りもなく、Z80を32ビット化してしまいました。物理的なデータバスこそ16ビット幅ですがダイナミックサイジングに対応し、CPUレジスタもほとんどが32ビットに拡張されています。IX/IYにも裏レジスタが追加され、その表裏をセットにしたレジスタが4バンク・計40本の32ビットレジスタを備える狂気の設計です。
アドレスバスも32ビットに拡張されており、4GBのアドレス空間があります。そしてこれはI/O空間も同様で、32ビット・4GBの空間がI/O用にあるわけです。アドレシングによって様々に変化しますが、32ビットに拡張されたBCレジスタで32ビットアドレスを指定できるかと思えば、従来の8ビットアドレスを直接指定する命令では上位16ビットが0固定され、昔と同じくAレジスタの内容がA15~A8に出るなど、もう何でもアリですね。
●KC80
川崎製鉄が、当時流行していたRISCプロセッサの仕組みを取り入れ高速化したCPU。周辺機能やMMUなどを内蔵していることから、64180と似た性格のプロセッサと言えます。
追加された命令もなく、16ビットI/Oアドレスもオリジナル同様に使用可能です。ただ内部レジスタが割り当てられたI/Oアドレスは下位8ビットのみデコードされているので、256バイト毎にイメージが見える構造になっています。上位8ビットのアドレスバスを気にする必要がないことから、64180のようなIN0/OUT0命令がなくても前準備なしに内部レジスタにアクセス可能です。
またMMUによって拡張されたアドレスバスA19~A16は、I/Oアクセス時には0が出力されます。
●KC160
川崎製鉄がZ280とは違うアプローチで16ビット化したZ80互換プロセッサ。MMUではなく、新たに設けられたページレジスタが従来のCPUレジスタにくっついてアドレスを24ビットに拡張します。24ビットアドレスをレジスタに収めて取り扱う関係上、一部の加減算は24ビットに対応しているなど命令も拡張されています。
I/OについてはKC80と同じで、また24ビットへの拡張は行われていません。Cレジスタ間接でBレジスタが、直接アドレスでAレジスタがバス上位に現れる関係で使用されるI/Oアドレスバス信号はA15~A0と定義されていますが、拡張されたA23~A16についてはコメントされていません。
●eZ80
KC160の登場はザイログにかなりのインパクトがあったようで…これをセカンドソースする派とあくまでZ380で頑張る派に分かれて揉めたとかなんとか…しかし、最終的に出した答えはKC160の影響は受けつつもそのどちらでもない新CPU・eZ80でした。
メモリアドレスは24ビットに拡張され、間接アクセスに用いられるレジスタもそれぞれ別個に24ビットに拡張されています。MMUではないのでリニアにアクセス可能です(KC160もそういう謳い文句だけど、ページレジスタはセグメントのような仕組みなので)。
そしてI/Oは、こちらも24ビット中最上位8ビットが未定義とされていて、残りの16ビットでアドレスを表します。従来通り直接アドレスではAレジスタが、間接アドレスではBレジスタが中位8ビットに現れます。Z180互換でもあるのでIN0/OUT0命令も健在です。ちなみに、IN r,(BC)/OUT (BC),rというニーモニック表記によって実態通りにBCレジスタ間接指定であることを表現してよいことになりました。
◇
以上のように、16ビットI/Oアドレスが後に現れたZ80互換マイコンの多くで受け継がれているのは大変興味深いことだと思います。マニュアルに一言断り書きがあるとはいえ、どう考えても成り行きのような16ビットI/Oアドレスの動作を「バグのようなもの」と考えて消してしまう可能性すらあったものが、これを利用したシステムが多すぎたがゆえに、互換性を維持すべき基本機能に格上げされたことになるからです。NSC800のように、仕様を引き継がないという選択肢もあり得たはずなのに…。
コンピュータのハード・ソフトの設計は時にOSやチップ設計者との化かしあいとなる場面に出会うことがあり…80286以降でのA20ラインの取扱いとかもそうですが、設計ミスやバグ・特に意図せず体裁だけ整えた箇所などが発見されて便利に使われてしまうというのは、まぁ原設計者からは困りものだとしても、コンピュータ趣味者には痛快愉快で面白い出来事ですね。
メーカーが互換性の維持に腐心するのはユーザー本位であることの証明ですが、そもそも互換にしなかった機能が以後互換を守られていくのだから、ややこしいことこの上ありません。そんなに深くは考えなかったのかもしれない、配慮か偶然かも不確かなしょうもない回路が以後こんなことになるなんて、嶋氏以下ザイログチームは想像だにしてなかったでしょうねぇ…。