--- nono/debugger/branchhistory.cpp 2026/04/29 17:04:43 1.1 +++ nono/debugger/branchhistory.cpp 2026/04/29 17:05:13 1.1.1.6 @@ -4,17 +4,32 @@ // Licensed under nono-license.txt // +// // ブランチ履歴 +// #include "branchhistory.h" #include "m68030core.h" #include "m88100.h" -#include "mystring.h" +#include "vectortable.h" // コンストラクタ -BranchHistory::BranchHistory() +BranchHistory::BranchHistory(bool is_exhist_) + : inherited(is_exhist_ ? "(ExceptionHistory)" : "(BranchHistory)") { - monitor_size = nnSize(55, 33); + is_exhist = is_exhist_; + + // ログは不要 + ClearAlias(); + + monitor.func = ToMonitorCallback(&BranchHistory::MonitorUpdate); + monitor.SetSize(55, 1 + 32); // ヘッダ1行とエントリ数 + monitor.SetMaxHeight(1 + 256); + if (is_exhist) { + monitor.Regist(ID_SUBWIN_EXHIST); + } else { + monitor.Regist(ID_SUBWIN_BRHIST); + } } // デストラクタ @@ -53,7 +68,7 @@ BranchHistory::GetUsed() const // モニタ更新 void -BranchHistory::MonitorUpdate(TextScreen& monitor) +BranchHistory::MonitorUpdate(Monitor *, TextScreen& screen) { uint8 t; int y; @@ -62,13 +77,10 @@ BranchHistory::MonitorUpdate(TextScreen& // userdata は表示開始位置と各種フラグ。 // 下位 32bit が表示開始位置で、0 なら先頭のエントリから、1 なら先頭の - // 一つ次のエントリから、…を表す (表示行数は monitor の高さ分)。 - // ExHist が %1 なら例外履歴、%0 ならブランチ履歴。これによって - // ヘッダを変えたい。 + // 一つ次のエントリから、…を表す (表示行数は screen の高さ分)。 // BottomToTop が %1 なら並び順を下から上に変える (コンソール用)。 - bool is_exhist = (monitor.userdata & ExHist); - bool bottom_to_top = (monitor.userdata & BottomToTop); - int pos = (int)monitor.userdata; + bool bottom_to_top = (screen.userdata & BottomToTop); + int pos = (int)screen.userdata; // 0 1 2 3 4 5 6 // 0123456789012345678901234567890123456789012345678901234567890123456789 @@ -79,16 +91,16 @@ BranchHistory::MonitorUpdate(TextScreen& // 002 S:01234567< 69> MFP Timer-C // 01234567890123456789012 - monitor.Clear(); - row = monitor.GetRow(); + screen.Clear(); + row = screen.GetRow(); // 最初の1行は常にヘッダ if (is_exhist) { - monitor.Print(0, 0, "No. FromAddr Vec. Exception"); - monitor.Print(45, 0, "Iteration"); + screen.Print(0, 0, "No. FromAddr Vec. Exception"); + screen.Print(45, 0, "Iteration"); } else { - monitor.Print(0, 0, "No. FromAddr Instruction"); - monitor.Print(35, 0, "ToAddr Iteration"); + screen.Print(0, 0, "No. FromAddr Instruction"); + screen.Print(35, 0, "ToAddr Iteration"); } // pos は最新を 0 とした通し番号。(スクロールしてたら開始が 0 とは限らない) @@ -109,9 +121,9 @@ BranchHistory::MonitorUpdate(TextScreen& continue; } std::string str = FormatEntry(e); - monitor.Print(0, y, "%3d %s", pos, str.c_str()); + screen.Print(0, y, "%3d %s", pos, str.c_str()); if (e.count > 1) { - monitor.Print(45, y, "x%9u", e.count); + screen.Print(45, y, "x%9u", e.count); } } } @@ -126,11 +138,14 @@ BranchHistory::MonitorUpdate(TextScreen& // ジャンプの3つを区別する。 // // 通常の分岐: -// from は分岐元 PC、to は分岐先 PC、inst の上位16ビットに命令の1ワード目。 +// from は上位31ビットが分岐元 PC、最下位ビットが S/U、 +// to は32ビット全体が分岐先 PC、 +// inst の上位16ビットに命令の1ワード目。 // inst の $8000 が立っていないことで区別する。 // // 例外発生: -// from は例外発生時の PC、to は不問(通常 0 をセットすること)、 +// from は上位31ビットが例外発生時の PC、最下位ビットが S/U、 +// to は不問(通常 0 をセットすること)、 // inst は $00008LVV で $8000 が例外フラグ、VV がベクタ番号である。 // ベクタ番号が $00 だと次項(ベクタによる分岐)と区別つかなくなってしまう // ため、リセット例外 (ベクタ番号0) は V=$01 で記録する。 @@ -138,11 +153,14 @@ BranchHistory::MonitorUpdate(TextScreen& // inst に $8000 が立っていて、かつ $8000 と一致しないことで区別する。 // // 例外ベクタによる分岐 (例外処理の最後に起きる): -// from はベクタアドレス、to は分岐先 (0 も起こりえる)、inst は $00008000。 +// from はベクタアドレス、 +// to は分岐先 (0 も起こりえる)、 +// inst は $00008000。 // inst が $00008000 と一致することで区別する (ビットが立っているではない)。 // コンストラクタ -BranchHistory_m680x0::BranchHistory_m680x0() +BranchHistory_m680x0::BranchHistory_m680x0(bool mode_) + : inherited(mode_) { } @@ -168,8 +186,8 @@ BranchHistory_m680x0::FormatEntry(const vector = 0; } // とりあえず - desc += string_format("<%3d> %s", vector, - m68030_get_exception_name(vector)); + const char *name = gVectorTable->GetExceptionName(vector); + desc += string_format("<%3d> %s", vector, name ?: ""); // XXX TODO 割り込みレベル } else { // 例外ベクタフェッチしてジャンプ @@ -221,14 +239,19 @@ BranchHistory_m680x0::FormatEntry(const // m88k は例外ベクタを直接実行するのでそれは不要。 // // 通常の分岐: -// from は分岐元 XIP、to は分岐先アドレス、inst は命令ワード。 +// from は上位30ビットが分岐元 XIP、最下位ビットが S/U、 +// to は32ビット全体が分岐先アドレス、 +// inst は命令ワード。 // // 例外発生: -// from は例外発生時の XIP、to は 0。inst は $fc000VVV で VVV (9ビット)が -// ベクタ番号。命令ワードとは衝突しない (instruction.txt 参照)。 +// from は上位30ビットが例外発生時の XIP、最下位ビットが S/U、 +// to は 0。 +// inst は $fc000VVV で VVV (9ビット)がベクタ番号。 +// 命令ワードとは衝突しない (instruction.txt 参照)。 // コンストラクタ -BranchHistory_m88xx0::BranchHistory_m88xx0() +BranchHistory_m88xx0::BranchHistory_m88xx0(bool mode_) + : inherited(mode_) { } @@ -249,7 +272,7 @@ BranchHistory_m88xx0::FormatEntry(const // 例外発生記録 // 発生アドレスとベクタを表示 uint32 vector = e.inst & 0x1ff; - const char *name = m88kcpu::GetExceptionName(vector); + const char *name = gVectorTable->GetExceptionName(vector); desc += string_format("<%3d> %s", vector, name ?: ""); if (vector == 450) { // OpenBSD のシステムコール番号 @@ -266,7 +289,7 @@ BranchHistory_m88xx0::FormatEntry(const case 3: mnemonic = ":bsr.n"; break; case 4: mnemonic = ":bb0"; break; case 5: mnemonic = ":bb0.n"; break; - case 6: mnemonic = ":bb1"; break; + case 6: mnemonic = ":bb1"; break; case 7: mnemonic = ":bb1.n"; break; case 0xa: mnemonic = ":bcnd"; break;