--- nono/debugger/debugger.cpp 2026/04/29 17:05:54 1.1.1.21 +++ nono/debugger/debugger.cpp 2026/04/29 17:05:58 1.1.1.22 @@ -37,7 +37,6 @@ #include "debugger_m680x0.h" #include "debugger_m88xx0.h" #include "ascii_ctype.h" -#include "event.h" #include "hostcom.h" #include "mainapp.h" #include "memdump.h" @@ -66,7 +65,7 @@ Debugger::Debugger() // ブレークポイントモニタ bpoint_monitor = gMonitorManager->Regist(ID_MONITOR_BREAKPOINT, this); - bpoint_monitor->func = ToMonitorCallback(&Debugger::MonitorUpdateBpoint); + bpoint_monitor->SetCallback(&Debugger::MonitorScreenBpoint); bpoint_monitor->SetSize(59, 9); // メモリダンプモニタ @@ -217,8 +216,6 @@ Debugger::Init() bp.mask = 0xffff0000; bp.md = curmd; AddBreakpoint(bp); - // 今登録されている命令ブレークの必要命令長を再計算 - RecalcInstMask(); } // 入出力を FILE で扱う @@ -277,7 +274,7 @@ Debugger::ThreadRun() } } - LeavePrompt(false); + QuitPrompt(); Close(); } @@ -466,7 +463,7 @@ Debugger::Input(int c) break; case CmdAct::Quit: // アプリケーション自体を終了 - LeavePrompt(false); + QuitPrompt(); gMainApp.GetUIMessage()->Post(UIMessage::APPEXIT); } } else if (c < ' ' || c == 0x07f) { @@ -502,6 +499,16 @@ Debugger::EnterPrompt() PrintPrompt(); } +// コマンドモード(プロンプト)から出る。終了用。 +void +Debugger::QuitPrompt() +{ + // 終了までの間 VM の実行が進んでしまわないよう停止指示を出しておく。 + scheduler->Terminate(); + + LeavePrompt(false); +} + // コマンドモード(プロンプト)から出る。 // trace はプロンプトから抜ける際のトレース状態の指示。 // スレッド終了時は false を指定すること。 @@ -759,15 +766,11 @@ Debugger::CheckAllBreakpoints(DebuggerMD { bool is_break = false; int vector; - - // 命令ごとにクリアする - bi_inst = 0; - bi_inst_bytes = 0; + uint32 inst = 0; + int instbytes = 0; // 例外はここでローカルにコピーしてから、クリアする。 - // 厳密には atomic exchange すべきのような。 - vector = md->bv_vector; - md->bv_vector = -1; + vector = md->GetAndResetLastVector(); // 1つの条件でマッチしても(そこでブレークすること自体は確定するのだが) // 残りの他の条件も成立すればカウントを進める必要があるため、 @@ -804,7 +807,15 @@ Debugger::CheckAllBreakpoints(DebuggerMD continue; case BreakpointType::Instruction: - if (CheckBreakpointInst(bp)) { + if (instbytes < bp.instbytes) { + uint64 data = ReadBreakpointInst(bp); + if ((int64)data < 0) { + continue; + } + inst = data; + instbytes = bp.instbytes; + } + if ((inst & bp.mask) == bp.inst) { break; } continue; @@ -855,8 +866,7 @@ Debugger::CheckAllBreakpoints(DebuggerMD } case BreakpointType::Instruction: desc += string_format("inst=%0*x", - bi_inst_bytes * 2, - bi_inst >> ((4 - bi_inst_bytes) * 8)); + instbytes * 2, inst >> ((4 - instbytes) * 8)); break; default: assert(false); @@ -875,57 +885,21 @@ Debugger::CheckAllBreakpoints(DebuggerMD return is_break; } -// 命令ブレークポイントが成立するか調べる。 -bool -Debugger::CheckBreakpointInst(breakpoint_t& bp) +// 命令ブレークポイントの位置の命令を読み込む。 +uint64 +Debugger::ReadBreakpointInst(breakpoint_t& bp) { - // uint32 bi_inst が現在の PC 位置の命令データ (左詰め) - // bi_inst_bytes が読み込んだバイト数(bi_inst の左からの有効バイト数)。 - // bi_need_bytes が現在のブレークポイントで読み込む必要のあるバイト数。 - busaddr laddr = busaddr(bp.md->GetPC()) | BusAddr::Fetch | busaddr::SU(bp.md->IsSuper()); DebuggerMemoryStream mem(bp.md, laddr); - - // 必要なバイト数に達するまで読み足す - bi_inst = 0; - while (bi_inst_bytes < bi_need_bytes) { - uint64 data = mem.Read(bp.md->inst_bytes); - if ((int64)data < 0) { - return false; - } - - bi_inst <<= bp.md->inst_bytes * 8; - bi_inst |= data; - bi_inst_bytes += bp.md->inst_bytes; + uint64 inst = mem.Read(bp.instbytes); + if ((int64)inst < 0) { + return inst; } - // 左詰めにする - bi_inst <<= (4 - bi_inst_bytes) * 8; - - // 必要なバイト数取得できたので比較 - if ((bi_inst & bp.mask) == bp.inst) { - return true; - } - return false; -} - -// 例外通知 (メイン CPU) -void -Debugger::NotifyExceptionMain(int vector) -{ - auto md = md_mpu.get(); - md->bv_vector = vector; -} - -// 例外通知 (XP)。 -// ベクタとして割り込み優先順位 (Intmap*) を使う。 -void -Debugger::NotifyExceptionXP(int vector) -{ - auto md = md_xp.get(); - md->bv_vector = vector; + inst <<= (4 - bp.instbytes) * 8; + return (uint32)inst; } // コマンド一覧。 @@ -953,6 +927,8 @@ Debugger::NotifyExceptionXP(int vector) { "mpu", &Debugger::cmd_mpu, }, { "n", &Debugger::cmd_n, }, { "nt", &Debugger::cmd_nt, }, + { "pe", &Debugger::cmd_pe, }, + { "pf", &Debugger::cmd_pf, }, { "q", &Debugger::cmd_q, }, { "quit", &Debugger::cmd_q, }, { "reset", &Debugger::cmd_reset, }, @@ -1091,13 +1067,14 @@ Debugger::HelpListMain = { { "b*", "Set/show Breakpoints (Type \"hb\" for details)" }, { "brhist", "Show branch history" }, { "c/ct", "Continue" }, - { "d/dt/D", "Disassemble" }, + { "d/D", "Disassemble" }, { "disp", "Set register group to show" }, { "exhist", "Show exception history" }, { "help", "Show this message" }, { "L", "Set log level" }, - { "m/mt/M", "Memory dump" }, + { "m/M", "Memory dump" }, { "n/nt", "Step until next instruction (Skip subroutines)" }, + { "pe/pf", "Print exception frame / floating-point state frame" }, { "quit", "Quit" }, { "r*", "Show registers (Type \"hr\" for details)" }, { "reset", "Reset the VM" }, @@ -1334,6 +1311,21 @@ Debugger::HelpDetails = { { "nt", "=n" }, //----- + { "pe", R"**( + Command: pe [
] + + Print an exception frame starting with . If the is + omitted, %sp is used. + )**" }, + + //----- + { "pf", R"**( + Command: pf + + Print a floating-point state frame starting with . + )**" }, + + //----- { "quit", R"**( Command: quit (or q) @@ -1606,8 +1598,6 @@ Debugger::cmd_b_delete() fprintf(cons, "Breakpoint #%d removed.\n", n); bp.type = BreakpointType::Unused; - // 今登録されている命令ブレークの必要命令長を再計算 - RecalcInstMask(); return CmdAct::Stay; } @@ -1704,6 +1694,7 @@ Debugger::AddBreakInst(const std::string { DebuggerMD *md; breakpoint_t bp; + std::string hexstr; std::string inststr; std::string maskstr; int instlen; @@ -1719,19 +1710,19 @@ Debugger::AddBreakInst(const std::string // 命令部。 // ニーモニックが指定できたら便利。 - inststr = md->ParseInst(argstr); - if (inststr.empty() == false) { + hexstr = md->ParseInst(argstr); + if (hexstr.empty()) { masklen = -1; } else { - auto pos = argstr.find(':'); + auto pos = hexstr.find(':'); if (pos == std::string::npos) { // マスク指定なし。 - inststr = argstr; + inststr = hexstr; masklen = -1; } else { // マスク指定あり。 - inststr = argstr.substr(0, pos); - maskstr = argstr.substr(pos + 1); + inststr = hexstr.substr(0, pos); + maskstr = hexstr.substr(pos + 1); masklen = maskstr.size(); } } @@ -1764,6 +1755,7 @@ Debugger::AddBreakInst(const std::string bp.inst <<= 32 - instlen * 4; bp.mask <<= 32 - instlen * 4; } + bp.instbytes = instlen / 2; //