現在地

Z8000セグメントモード対応(その1)


カテゴリー:

Z8001を動かすで非セグメントモードで動くことがわかりました。動作する石も複数確保できましたので、本来のセグメントモードで動かすことにします。

Z8000ファミリにはセグメントモードでも動作するZ8001(とZ8003)と非セグメントモード専用のZ8002(とZ8004)があります。両者はリセット時のPC, PSWの初期値を格納する形式が異なる上にアドレスが重なるので同一バイナリで両方に対応することはできません。

どちらの形式で読んでも辻褄の合う値を設定することは不可能ではありませんがメモリマップの制約が大きくなります。

Z8001(とZ8003)はセグメントモードでも非セグメントモードでも動作させることができます。これは同一バイナリで両対応するのは可能ですが、ほぼすべてのルーチンを2つ持つようなことになってしまいます。

結局3種類のバイナリを作ることになります。

  1. セグメント対応CPUをセグメントモードで使うもの
  2. セグメント対応CPUを非セグメントモードで使うもの
  3. セグメント非対応CPU用のもの

2.と3.はリセット時のPC, PSW初期値とPSA(Program Status Area)の形式が異なります。

2.を実際には使うことはないと思います。1.のセグメントモードで動作しているモニタから非セグメントモードのユーザプログラムを実行することは可能ですから。ただ開発中に非セグメントモードの動作を壊していないか確認するのにデバイスを挿し替えずにできて便利なので残しておきます。

これらを同一のソースから生成したいので以下の変数を用意して条件アセンブルすることにします。

  1. SEG_CPU:Z8001, Z8003用の場合に1にします
  2. SEG_MODE:セグメントモードで動作させる場合に1にします

これだけですとソースがIFELSEENDIFだらけになってしまいますので次のような工夫をしています。

まずPSAのエントリは以下のようにマクロを切り替えています。

	IF SEG_CPU

SPAENT	MACRO	PC,FCW=0C000H
	DW	0		; Dummy
	DW	FCW
	DW	segment(PC) << 8
	DW	offset(PC)
	ENDM

	ELSE			; !SEG_CPU

SPAENT	MACRO	PC,FCW=4000H
	DW	FCW
	DW	PC
	ENDM

	ENDIF

ちなみに使っているアセンブラASではセグメントとオフセットをつなげた23ビットのアドレスとして扱いますが、実際のCPUは32ビットのロングワードのビット30~24にセグメントを入れます。8ビットのシフトがあるのはこの変換のためです。

もう一つ厄介なのはレジスタ間接に使うレジスタです。非セグメントモードでは16ビットのレジスタ(R1など)を使いますが、セグメントモードでは32ビットのロングワードレジスタ(RR2など)を使います。これは頻出するので以下のように切り替えています。

	IF SEG_MODE

AR1	REG	RR0
AR3	REG	RR2
AR5	REG	RR4
AR7	REG	RR6
AR9	REG	RR8
AR11	REG	RR10
AR13	REG	RR12
AR15	REG	RR14
ASP	REG	RR14

	ELSE

AR1	REG	R1
AR3	REG	R3
AR5	REG	R5
AR7	REG	R7
AR9	REG	R9
AR11	REG	R11
AR13	REG	R13
AR15	REG	R15
ASP	REG	R15

	ENDIF

AR0ではなくAR1としているのはオフセットをインクリメントなどするときにINC R1などとするのでそれに合わせているためです。

(続く)

参考文献・関連図書: 
『Z8000ユーザーズ・マニュアル [1]CPU/MMU編』, シャープ.
関連項目: 

コメントを追加

Plain text

  • HTMLタグは利用できません。
  • ウェブページアドレスとメールアドレスは、自動的にハイパーリンクに変換されます。
  • 行と段落は自動的に折り返されます。
※ コメントは原則公開です。個別のご相談などは「ご意見・ご要望」からお願いします。