現在地

Universal Monitor MN1610の拡張(その2)


カテゴリー:

HEXファイルの入出力ができるようになったら、次はブレークとレジスタの操作が欲しいところです。

MN1613は未定義のコードを実行しようとするとレベル0の内部割込みが発生するらしいのでこれを利用することにします。これが発生するとSTRとICをOSPW0(アドレスX'0000', X'0001')に保存し、NSPW0(アドレスX'0100', X'0101')から新しいSTRとICを読み込みます。OSPW, NPSWは外部割込みと共用ですが,内部割込みの場合はIISRというレジスタのビット15が立つので区別が可能です。

NSPW0にハンドラのアドレスを設定し、ハンドラではR0~R4, SPを保存しSTR, ICはOPSW0から取り出して表示させます。

これで試しにX'0800'番地にX'0000'を書き込んで実行させてみます。これは未定義命令なのでレジスタが表示されるかと思いきや何も起こりません。

この状態でステップ動作に切り替えてみたところ、X'0800', X'0801', X'0802'番地から順に命令フェッチを繰り返しているようです。

もしかして割り込み許可しておかないといけないのかなと思って実行時にSTRのM0(レベル0割り込みの許可)ビットを立ててみたところ無事にレジスタ表示してモニタのコマンド待ちに戻ってきました。OPSW0に保存されたICはX'0801'ではなく原因となった命令のアドレスX'0800'でした。

次にNOP(正確にはMV R0,R0)をいくつか並べたあとに未定義命令を置いてみます。するとなぜか最初のNOPでブレークがかかってしまいます。

どうやらリセット直後は正しく未定義命令で止まるものの、二度目以降はGコマンドで実行開始した直後に止まってしまいます。

考えられるのは次のような状況です。

  1. 未定義命令に遭遇すると内部フラグが立つ
  2. 内部フラグが立った状態で割り込みが許可されていると割り込みが発生(ハンドラに制御が移る)
  3. このフラグをクリアしないまま再度割り込みを許可すると再び割り込みが発生

Gコマンドでユーザプログラムに制御を渡すときにM0ビットを立てているのでこの時に割り込みが発生してしまったのでしょう。試してはいませんがNSPW0のSTRのM0ビットを立てておくと無限ループになってしまうのかもしれません。

そうなるとこのフラグをリセットする方法を探さなくてはなりません。

資料の乏しいMN1613、そのものずばりの情報は見つかりませんでしたが、レジスタの一覧を見る限りIISR以外に関係ありそうなレジスタが見当たりません。そこでIISRに0(このレジスタはビット15のみ有効)を書いてみましたが状況は変わりません。

割り込み要因レジスタでは1を書き込んだビットがクリアされるパターンがあるのを思い出し、内部割り込みか判定するためにIISRから読んだ値をそのままIISRに書き戻してみたところ二度目以降も正常に実行できるようになりました。

ということで最終形のハンドラはこんな感じになりました。

    1118/     41B : =>TRUE               	IF CPU_MN1613
    1119/     41B :                     IRQ0H:
    1120/     41B : 2001                	PUSH	R0
    1121/     41C : 3FE0                	CPYH	R0,IISR
    1122/     41D : 285F                	TBIT	R0,15,NZ
    1123/     41E : CF11                	B	IRQ0HR
    1124/     41F : 3F60                	SETH	R0,IISR		; Clear IISR
    1125/     420 :                     
    1126/     420 : 2002                	POP	R0
    1127/     421 : 8038                	ST	R0,REGR0
    1128/     422 : 8139                	ST	R1,REGR1
    1129/     423 : 823A                	ST	R2,REGR2
    1130/     424 : 833B                	ST	R3,REGR3
    1131/     425 : 843C                	ST	R4,REGR4
    1132/     426 : 853D                	ST	SP,REGSP
    1133/     427 : C000                	L	R0,OPSW0
    1134/     428 : 803E                	ST	R0,REGSTR
    1135/     429 : C001                	L	R0,OPSW0+1
    1136/     42A : 803F                	ST	R0,REGIC
    1137/     42B :                     
    1138/     42B : [1118]               	ENDIF			; CPU_MN1613
    1139/     42B :                     IRQ0HD:	
    1140/     42B : CB13                	L	X0,IRQ0C0
    1141/     42C : 9713                	BAL	(C_STROUT)
    1142/     42D : 9F12                	BAL	(IRQ0C1)
    1143/     42E : D711                	B	(C_WSTART)
    1144/     42F :                     
    1145/     42F :                     IRQ0HR:
    1146/     42F : 2002                	POP	R0
    1147/     430 : 2004                	LPSW	0

1121~1123行ではIISRのビットをチェックして立っていなかったら外部割込みなので飛ばします。

1124行がクリアのためにIISRに書き戻しているところ。

1126~1132行では各レジスタを保存していきます。保存先がゼロページならそのまま保存できるので簡単ですね。

1133~1136行ではOSPW0からSTR, ICをコピーします。

1140~1143ではブレークが発生したこととレジスタ内容を表示してモニタのコマンド待ちへ戻しています。

1146, 1147行は外部割込みだった場合にそのまま戻します。

この他に未定義命令割り込みの使えないMN1610/1611向けにBAL命令で呼び出すための類似のルーチンも用意しました。相違点としては、IISRの処理が無いこと、STRを直接保存すること、ICもOPSW0からではなくスタックから取り出すことなどがあります。MN1610/1611は持っていないのでテストできませんが、MN1613では動作しました。

Gコマンドでレジスタを設定するのはこのハンドラの逆を行なうだけです。Rコマンドの処理も他のプロセッサの場合と大差は無いので詳細は省略します。

次は大容量メモリ対応を考えていたのですが... うちのボードが4kWしか積んでいないこともあってまだ着手していません。やるとしたらユーザにリニアな空間として見せるのか、8086のようにセグメントを意識させるのか、どちらもメリット・デメリットがあるので悩ましいところです。


コメントを追加

Plain text

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