2019-12-26 22:54 — asano
カテゴリー:
MC6800に続いて6502, MC6809についてもレジスタ命令を追加しましたので、その内側について書いてみたいと思います。
さて、レジスタ命令とはレジスタの値を表示・変更する機能なわけですが、CPUがある瞬間に実行できるプログラムは1つですからユーザプログラム実行中はモニタプログラムは実行できません。モニタプログラム自身の動作にもレジスタは必要です。
ではどうするか?
モニタプログラムには次の3つの機能が必要になります。
- ユーザプログラムからモニタに制御が渡ったときにレジスタ内容をメモリに退避する
- メモリに退避されている値を表示・変更する
- メモリに退避されている内容をレジスタに戻しユーザプログラムに制御を渡す
まず1.ですがプログラムカウンタPCの値を知る必要があるのでCALL
, BSR
(Branch Subroutine)のような命令が最低限必要です。さらにユーザプログラムを書き換えて埋め込むので通常短い命令が使われます。今回MC6800, MC6809ではSWI
(Software Interrupt)を、6502ではそのものズバリのBRK
を使いました。どちらも1バイト命令です。
これらの命令を実行すると割り込みベクタ経由でモニタに制御が渡ってきます。
スタックに積まれていないレジスタがあればそれを優先的に退避します。未退避のレジスタを壊さないよう注意が必要です。幸いSWI
はほとんどをスタックに積んでくれるので楽ですが、Z80などでは順序をよく考えないといけないでしょう。
プロセッサによっては(SC/MPとか)この処理が書けず、どうしても一部のレジスタを保存できません。
6502を例に見てみることにします。
716/ FC56 : ;; Interrupt / Break
717/ FC56 : IRQBRK:
718/ FC56 : =>TRUE IF USE_REGCMD
719/ FC56 : 48 PHA
720/ FC57 : 08 PHP
721/ FC58 : 68 PLA ; A <= PSR
722/ FC59 : 29 10 AND #$10 ; Check B flag
723/ FC5B : F0 2C BEQ IBIR
724/ FC5D : D8 CLD
725/ FC5E :
726/ FC5E : 68 PLA ; A
727/ FC5F : 85 1C STA REGA
728/ FC61 : 8A TXA ; X
729/ FC62 : 85 1D STA REGX
730/ FC64 : 98 TYA ; Y
731/ FC65 : 85 1E STA REGY
732/ FC67 : 68 PLA ; PSR (Pushed by BRK)
733/ FC68 : 85 22 STA REGPSR
734/ FC6A : 68 PLA ; PC(L) (Pushed by BRK)
735/ FC6B : 38 SEC
736/ FC6C : E9 02 SBC #2 ; Adjust PC to point BRK instruction
737/ FC6E : 85 20 STA REGPC
738/ FC70 : 68 PLA ; PC(H) (Pushed by BRK)
739/ FC71 : E9 00 SBC #0
740/ FC73 : 85 21 STA REGPC+1
741/ FC75 : BA TSX ; SP
742/ FC76 : 86 1F STX REGSP
743/ FC78 :
744/ FC78 : A9 ED LDA #low(BRKMSG)
745/ FC7A : 85 27 STA PT0
746/ FC7C : A9 FC LDA #high(BRKMSG)
747/ FC7E : 85 28 STA PT0+1
748/ FC80 : 20 88 FB JSR STROUT
749/ FC83 : 20 20 FB JSR RDUMP
750/ FC86 : 4C 36 F8 JMP WSTART
751/ FC89 :
752/ FC89 : IBIR:
753/ FC89 : 68 PLA
754/ FC8A : 40 RTI
755/ FC8B : =>FALSE ELSE ; USE_REGCMD
756/ FC8B : ;; Dummy
757/ FC8B : RTI
758/ FC8B : [718] ENDIF ; USE_REGCMD
6502は割り込みIRQとBRKでベクタを共有しているので719~723行目で分離します。
ユーザプログラム内でDフラグがどうなっているか不明なので724行目でクリアしておきます。これがセットされていると加減算がBCD処理になってしまうからです。
726~742行目で各レジスタをメモリに退避していきます。736行目付近でPCを-2しているのはBRK
命令のアドレスになるよう補正しているため、BRK
命令を本来の命令に戻して継続実行する際に便利なようにです。
その後BRK
が実行されたことを表示し、全レジスタをダンプします。もうレジスタの退避は完了しているのでレジスタは自由に使えます。
最後に750行目でモニタのコマンド待ちになります。今回モニタはユーザプログラムのスタックエリアをそのまま使う形になりますが、エリアを分ける(742行目の後でLDX #****
,TXS
などとする)ことも可能です。このモニタのスタック消費はそれほどでもないので分けることはしませんでした。
次回は表示・変更コマンドについて書きたいと思います。
コメントを追加