2021-11-20 23:25 — asano
カテゴリー:
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
コマンドで実行開始した直後に止まってしまいます。
考えられるのは次のような状況です。
- 未定義命令に遭遇すると内部フラグが立つ
- 内部フラグが立った状態で割り込みが許可されていると割り込みが発生(ハンドラに制御が移る)
- このフラグをクリアしないまま再度割り込みを許可すると再び割り込みが発生
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のようにセグメントを意識させるのか、どちらもメリット・デメリットがあるので悩ましいところです。
コメントを追加