MSXは代々、Z80をCPUとして搭載してきた。turboRは、R800というZ80バイナリコンパチの16bitCPUも載せている。
R800は実質MSX専用CPUで、データシートの類は見たことがなかった。これが当時の半導体情報誌には掲載されていたらしい。
CQ出版のDatumという月刊誌('91廃刊)で、1990年10月号に「R800ユーザーズマニュアル暫定版」が載ったとのこと。
ネット上には、国立国会図書館に蔵書があり、複写の申請をしたblog記事とか、1477円だったというレポートTweetとかがある。
データシートそのものではないが、その内容と思しきものを公開しているページもあった。裕之氏のサイトにありページタイトルはそのまま。一部加筆修正がしてある。原著にはあったであろうインストラクション表は無い。
Internet Archiveサイトには、MSX turboRテクニカルハンドブックが公開されていて、件の表はここで見られる。Z80のニモニックと異なるのは著作権の問題らしい。後にザイログがセカンドソーサになったことで、ザイログニモニックが解禁されたとも聞いている。
このほかにMSX Datapack wiki化計画というプロジェクトもあるのだが、turboR版のインストラクション表は現在は書きかけ。
氏のページでは「FS-A1ST/GTの回路図」に触れている。FS-A1STの全回路図が存在する、というTweetもあった。
これらはInternet Archiveサイト上にある、テクニカルガイドと銘打たれているもののよう。分解手順、測定波形、回路図、構造図などが含まれていて、サービスマニュアル的なものに見える。
回路図は、Panasonic FS A 1 S Technical Guide(FS-A1STテクニカルガイド)、Panasonic FS-A1GT Technical Guide (JP)、あたりで拝める。解像度が低く文字が潰れているのが残念。
ちなみにそのページ下方には類似候補が挙げられ、辿っていくと、ソニー、ヤマハ、フィリップスなど他メーカの資料もみつかる。
せっかくR800などの資料が手に入ったので読んでみた。なおR800に関しては、裕之氏のページのものを情報源としている。
雑誌の受け売りでは解りづらかったのだが、やっとモヤモヤが晴れた感。
R800というチップは、CPUコアに、割り込み制御、メモリマッパ(MMU)、DMA、DRAMコントローラなどをひとまとめに収めたもののよう。
CPUコアはZ80互換で、内部バスを広げてあり28MHzで動作する。通常は28.63636MHz(最大動作周波数でもある)で動作させ、これをMCK(main clock)と呼んでいる。これを4分周した7.15909MHzをSYSCLKと称して出力しており、外部とのやり取りはこれを基準に行う。turboRに於いては、これがシステムクロックになる。
このカラクリにより、命令あたりのクロック数が大幅に減った! などという魔法じみた呪文が唱えられることとなった。
CPU以外の機能は、turboRではほとんど使われない。ただしDRAMコントローラは別で、Z80モードでもここは使っている。
CPUにバスを明け渡させて、アドレスやERASなどを与えると、R800に接続されたDRAMにアクセスができる。CPUべったりの周辺回路と思いきや、外部から単独で使えてしまう。
R800のブロック図は以下のとおり。裕之氏のページより拝借。
赤字は氏による加筆修正。緑と水色でさらに追記してある。
Z80相当と周辺ペリフェラルとをオンチップにする、そんな製品は古くからある。一部のMSXに搭載されたHD64180(日立)や、ボードマイコンでよく見かけたTMPZ84C0xx(東芝)、鉄屋さんのKL5C80xx(川崎製鉄)なんてものもあった。
余談だが、日立や東芝は常識的なZ80+ペリフェラル構成だったが、川鉄のはR800風に内外クロックが別になっていたと記憶する。CPU単体は33MHzまで動作可能だが、ペリフェラル同梱チップは10MHzとかそのあたり。従来クロック比で3倍速ぐらいになる計算。これを流用してMSXturboKとかできないものか……などと妄想したこともある。
これらに共通するのは、搭載した追加機能をI/O空間にマッピングしているということ。デコーダも内蔵することで、物理的に追加する回路は減る。
一方でR800は、同様にペリフェラルは持ちながらも、CPUからはアクセスできない状態になっている。I/O空間もメモリ空間もまっさらなまま。8086のセグメント機構のような、CPU機能に取り込むこともしていない。
代わりにCSREGという信号が追加されている。解りづらい説明で混乱している人もいたようだが、マッピングはユーザが自由にやってね、という意味だと想像する。デコード回路は必須になるが、ガチガチに規定された既存システムへの組み込みはやりやすい仕様といえる。
MSXのI/O空間には、システム予約という空きがある。仮にR800の内蔵機能を使っていたら、ということで、メモリマッパの直前に内部拡張レジスタをマッピングしてみた。
内部拡張レジスタは、いくつかのペリフェラルをコントロールする。R800には「メモリマッパ」と名づけられたMMUが搭載され、これも件のレジスタで操作する。これをMSXのメモリマッパとして使うことはできないか、頭の体操をしてみた。
接続回路は上記のものとする。既存のMSXのマッパレジスタは、I/O空間の0FCh~0FFhに置かれている。これらはページ0~3に対応する。
R800のメモリマッパは、8KBセグメントで総容量16MBまで扱える。MSXのは16KBで4MB、アドレスは3本増えるのでレジスタは8bitでは収まらない。マッパアクセスは拡張BIOSで行うこととなっているので、その変換を伴うルーチンを考えてみる。
なお、拡張BIOSによるメモリマッパアクセスの方法は、MSXテクニカルガイドブックのp16(PDF)あたりが解りやすい。
とりあえずは既存のルーチンを見てみる。
拡張BIOSでマッパアクセス用のジャンプテーブルを取得し、その先にあるルーチンを抜き出す。手ごろなところで、WR_SEG(インターセグメントライト:セグメント指定1バイト書き込み)を扱うこととする。
このルーチンは、WebMSXで日本版turboRを選択して得た。アンダースコアで始まるラベルは、置かれていたアドレスをあらわしているが、固定アドレスではない可能性もある。
;original 'wr_seg' routine on webMSX turboR(JPN) ;entry: ; a = segment number ; hl = address(14bit valid) ; e = data ;return: ; - ;lost: ; af wr_seg: _edbf: di push hl push bc ld b,a call _ee40 ld c,a ld a,b call _ee3a res 6,h set 7,h ld (hl),e ld a,c call _ee3a pop bc pop hl ret _ee3a: ld (_f2c7+2),a out (0feh),a ret _ee40: ld a,(_f2c7+2) ret _f2c7: ds 4 ;mapper reg. save area
_f2c7は、実際は0F2C9hを使っているだけだが、全レジスタの退避場所であろうと想像してこのようにしてある。
ちなみにこのルーチンが使われる前、システム初期化の段階で、以下と同等のルーチンが実行されているはず。
;MSX-MMS initialize init_mms: di ld de,_f2c7+3 ld hl,def_mms+3 ld bc,04ffh init_mms_l: ld a,(hl) out (c),a ldd djnz init_mms_l ret def_mms: db 3,2,1,0
wr_segルーチンを眺めて思ったが、もっと高速化ができる。よく使うであろうルーチンなのだから、カツカツに削ってほしいところ。
公式にも「これらのルーチンは非常に高速ですので、プログラムの性能が犠牲になることはありません」と言ってるわけだし。
;more fast ver. with original subroutine wr_seg_fast: _edbf: di call _ee3a+3 ld a,h res 6,h set 7,h ld (hl),e ld h,a call _ee40 jp _ee3a+3 _ee3a: ld (_f2c7+2),a out (0feh),a ret _ee40: ld a,(_f2c7+2) ret _f2c7: ds 4 ;mapper reg. save area
さて、R800のメモリマッパを使うとどうなるか。
セグメントサイズ、アドレス本数の違いを変換し、レジスタへのアクセス方法も変わることになる。
;using R800 mapper ver. (R800 ext.reg. is mapped on 0FAh..0FBh) wr_seg_r800: di push bc push hl rrca rrca ld b,a ;b=(MA15 MA14 MA21 MA20 MA19 MA18 MA17 MA16) ld a,8 out (0fah),a ;set R800 ext.reg address(mapper reg. for 8000h..9fffh) ld a,b and 0c0h ld c,a ;c=(MA15 MA14 0 0 0 0 0 0) out (0fbh),a ;set reg.08h (MA15 MA14 0 - - - - -) ld a,b and 3fh ld b,a ;b=(0 0 MA21 MA20 MA19 MA18 MA17 MA16) out (0fbh),a ;set reg.09h (0 0 MA21 MA20 MA19 MA18 MA17 MA16) ld a,c or 20h out (0fbh),a ;set reg.0ah (MA15 MA14 1 - - - - -) ld a,b out (0fbh),a ;set reg.0bh (0 0 MA21 MA20 MA19 MA18 MA17 MA16) set 7,h res 6,h ld (hl),e ld a,8 out (0fah),a ld hl,savreg+4*2 ld bc,04fbh otir pop hl pop bc ret savreg: ds 8*2 ;R800 mapper reg. save area, 8pages*2bytes
内部拡張レジスタ書き込みの際にはポインタが自動的にインクリメントされる、など配慮があるが、それでもなかなかコストが高い。
従前ルーチンに似せて、ページ2に16KB分割り付けてから書き込んでいる。
A13で条件分岐させればいくらかは速くなる。でもやっぱり重い。
;using R800 mapper fast ver. wr_seg_r800f: di push bc rrca rrca ld b,a ld a,8 out (0fah),a ld a,b and 0ch bit 5,h jr z,$+4 or 20h out (0fbh),a ld a,b and 3fh out (0fbh),a ld b,h ld a,h and 1fh ld h,a ld (hl),e ld h,b ld a,8 out (0fah),a ld a,(savreg+4*2) out (0fbh),a ld a,(savreg+4*2+1) out (0fbh),a pop bc ret savreg: ds 8*2
お約束だが、以下のような初期化があらかじめ行われていることとする。
init_seg_r800: di xor a out (0fah),a ld hl,init_reg ld bc,10fbh otir ld hl,init_reg ld de,savreg ld bc,8*2 ldir ret init_reg: db 11000000b,0,11100000b,0 db 10000000b,0,10100000b,0 db 01000000b,0,01100000b,0 db 00000000b,0,00100000b,0
R800モードではなんとかなるとしても、Z80モードとの整合性も考えなくてはならない。Z80モードではバスを開放させているため、外部でマッパーアドレスを生成しなくてはならない。
ルーチン内で、従来のマッパレジスタにも書き込めばいいか……であれば、R800モードでも外部で生成すればいいよね、という話になる。
そういえばスロット機構もあったっけ……これもA14/A15でアクセス先が変わる、メモリマッパとは別の機構。DRAMとかいう信号があるから、そのあたりで上手くやれるんだろうか。
ともあれ、現実味の薄い頭の体操でした。
0 件のコメント:
コメントを投稿
.