since 2007.8 by K-ichi


MSXturboRロゴ(MSX Wiki
40歳が見えてきたMSX。その最終形態であるMSX turboRに関するハードウェア資料が、ネット上でいくつか見られるらしい。

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テクニカルガイドブックのp16PDF)あたりが解りやすい。

とりあえずは既存のルーチンを見てみる。
拡張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 件のコメント:

コメントを投稿

.

関連記事


この記事へのリンク by 関連記事、被リンク記事をリストアップする」記事

ブログ アーカイブ