--- nono/debugger/debugger.cpp 2026/04/29 17:05:16 1.1.1.13 +++ nono/debugger/debugger.cpp 2026/04/29 17:05:41 1.1.1.18 @@ -63,13 +63,13 @@ Debugger::Debugger() pVectorTable.reset(new VectorTable(gMainApp.GetVMType())); // ブレークポイントモニタ - bpoint_monitor.func = ToMonitorCallback(&Debugger::MonitorUpdateBpoint); - bpoint_monitor.SetSize(60, 9); - bpoint_monitor.Regist(ID_MONITOR_BREAKPOINT); + bpoint_monitor = gMonitorManager->Regist(ID_MONITOR_BREAKPOINT, this); + bpoint_monitor->func = ToMonitorCallback(&Debugger::MonitorUpdateBpoint); + bpoint_monitor->SetSize(60, 9); // メモリダンプモニタ for (int i = 0, end = memdump_monitor.size(); i < end; i++) { - int objid = OBJ_MPU_MEMDUMP(i); + uint objid = OBJ_MPU_MEMDUMP(i); int monid = ID_MONITOR_MEMDUMP(i); memdump_monitor[i].reset(new MemdumpMonitor(objid, monid)); } @@ -77,7 +77,7 @@ Debugger::Debugger() if (gMainApp.Has(VMCap::LUNA)) { // XP 空間のメモリダンプモニタ for (int i = 0, end = xpmemdump_monitor.size(); i < end; i++) { - int objid = OBJ_XP_MEMDUMP(i); + uint objid = OBJ_XP_MEMDUMP(i); int monid = ID_MONITOR_XPMEMDUMP(i); xpmemdump_monitor[i].reset(new MemdumpMonitor(objid, monid)); } @@ -92,7 +92,8 @@ Debugger::~Debugger() Close(); if ((bool)hostcom) { - hostcom->SetCallbackDevice(NULL); + hostcom->SetRxCallback(NULL); + hostcom->SetAcceptCallback(NULL); } TerminateThread(); @@ -103,14 +104,15 @@ Debugger::Create() { // ホストドライバを作成 try { - hostcom.reset(new HostCOMDevice("Debugger")); - } catch (...) { + hostcom.reset(new HostCOMDevice(this, "Debugger")); + } catch (...) { } + if ((bool)hostcom == false) { + warnx("Failed to initialize HostCOMDevice at %s", __method__); return false; } hostcom->SetRxCallback(ToDeviceCallback(&Debugger::RxCallback)); hostcom->SetAcceptCallback(ToDeviceCallback(&Debugger::AcceptCallback)); - hostcom->SetCallbackDevice(this); return true; } @@ -137,14 +139,28 @@ Debugger::Init() syncer = GetSyncer(); - if (gMainApp.Has(VMCap::M88K)) { - md_mpu.reset(new DebuggerMD_m88xx0(this)); - } else { - md_mpu.reset(new DebuggerMD_m680x0(this)); + try { + if (gMainApp.Has(VMCap::M88K)) { + md_mpu.reset(new DebuggerMD_m88xx0(this)); + } else { + md_mpu.reset(new DebuggerMD_m680x0(this)); + } + } catch (...) { } + if ((bool)md_mpu == false) { + warnx("Failed to initialize md_mpu at %s", __method__); + return false; } + if (gMainApp.Has(VMCap::LUNA)) { - md_xp.reset(new DebuggerMD_hd64180(this)); + try { + md_xp.reset(new DebuggerMD_hd64180(this)); + } catch (...) { } + if ((bool)md_xp == false) { + warnx("Failed to initialize md_xp at %s", __method__); + return false; + } } + // とりあえずメインプロセッサに固定 curmd = md_mpu.get(); @@ -203,7 +219,14 @@ Debugger::Init() } // を取り出す - if (!ParseAddr(addrstr.c_str(), &bp.addr)) { + if (ParseVerbHex(addrstr.c_str(), &bp.addr)) { + bp.type = BreakpointType::Address; + } else if (addrstr[0] == 'v' + && ParseVector( + ParseCPU(cpustr), &(addrstr.c_str()[1]), (uint32 *)&bp.vec1)) { + bp.type = BreakpointType::Exception; + bp.vec2 = bp.vec1; + } else { warnx("\"%s\": Invalid breakpoint address", str.c_str()); return false; } @@ -212,10 +235,21 @@ Debugger::Init() bp.skip = atoi(skipstr.c_str()); } // 登録 - bp.type = BreakpointType::Address; AddBreakpoint(bp, cpustr); } + // --bi-exg なら命令ブレークポイントを設定 + // (CPU のチェックはしていない) + if (gMainApp.debug_breakinst_exg) { + breakpoint_t bp; + bp.type = BreakpointType::Instruction; + bp.inst = 0xcf4f0000; + bp.mask = 0xffff0000; + AddBreakpoint(bp, ""); + // 今登録されている命令ブレークの必要命令長を再計算 + RecalcInstMask(); + } + // 入出力を FILE で扱う cons = funopen(this, readfunc, writefunc, NULL, NULL); if (cons == NULL) { @@ -230,6 +264,8 @@ Debugger::Init() void Debugger::ThreadRun() { + SetThreadAffinityHint(AffinityClass::Light); + // disp_regs の初期値設定。 // 再接続でも継続してていいような気がするのでループ外で初期化。 disp_regs.clear(); @@ -319,14 +355,16 @@ Debugger::Terminate() static int readfunc(void *cookie, char *buf, int bufsize) { - return ((Debugger *)cookie)->ReadFunc(buf, bufsize); + auto debugger = reinterpret_cast(cookie); + return debugger->ReadFunc(buf, bufsize); } // funopen の write コールバック static int writefunc(void *cookie, const char *buf, int len) { - return ((Debugger *)cookie)->WriteFunc(buf, len); + auto debugger = reinterpret_cast(cookie); + return debugger->WriteFunc(buf, len); } // funopen の read コールバックの本体 @@ -460,7 +498,7 @@ Debugger::Input(int c) LeavePrompt(false); UIMessage::Post(UIMessage::APPEXIT); } - } else if (c < ' ') { + } else if (c < ' ' || c == 0x07f) { // 他のコントロールコードはとりあえず無視 } else { // 通常文字なら、エコーバックして追加 @@ -874,8 +912,10 @@ Debugger::CheckBreakpointInst(breakpoint // bi_inst_bytes が読み込んだバイト数(bi_inst の左からの有効バイト数)。 // bi_need_bytes が現在のブレークポイントで読み込む必要のあるバイト数。 - saddr_t laddr(bp.md->GetPC(), bp.md->IsSuper()); - DebuggerMemoryStream mem(bp.md, laddr, MMULookupMode::True); + busaddr laddr = busaddr(bp.md->GetPC()) + | BusAddr::Fetch + | busaddr::SU(bp.md->IsSuper()); + DebuggerMemoryStream mem(bp.md, laddr); // 必要なバイト数に達するまで読み足す bi_inst = 0; @@ -929,7 +969,6 @@ Debugger::NotifyExceptionXP(int vector) { "c", &Debugger::cmd_c, }, { "ct", &Debugger::cmd_ct, }, { "d", &Debugger::cmd_d, }, - { "dt", &Debugger::cmd_dt, }, { "D", &Debugger::cmd_D, }, { "disp", &Debugger::cmd_disp, }, { "exhist", &Debugger::cmd_exhist, }, @@ -939,7 +978,6 @@ Debugger::NotifyExceptionXP(int vector) { "help", &Debugger::cmd_h, }, { "L", &Debugger::cmd_L, }, { "m", &Debugger::cmd_m, }, - { "mt", &Debugger::cmd_mt, }, { "M", &Debugger::cmd_M, }, { "mpu", &Debugger::cmd_mpu, }, { "n", &Debugger::cmd_n, }, @@ -1221,12 +1259,11 @@ Debugger::HelpDetails = { { "d", R"**( Command: D
] [] Command: d [[:]
] [] - Command: dt [[:]
] [] Shows disassemble. The first form ("D") interprets
as a physical address. - The second and third form ("d", "dt") interprets
as a logical - address if the address translation is enabled. Normally,
is + The second form ("d") interprets
as a logical address + if the address translation is enabled. Normally,
is interpreted in the current privilege and current address space. You can change it by modifier. On m68k, can be specified either by function code number directly @@ -1237,11 +1274,7 @@ Debugger::HelpDetails = { modifier ('s' or 'u', same as above) and following CMMU identifiers: 'd' .. Data CMMU 'i' or 'p' .. Instruction CMMU Or CMMU can also be identified by CMMU number (like '6' or '7'). - - "d" only looks up in ATC (on m68k) or in BATC/PATC (on m88k). - "dt" will simulate to search the page table in addition to that. )**" }, - { "dt", "=d" }, { "D", "=d" }, //----- @@ -1291,12 +1324,11 @@ Debugger::HelpDetails = { { "m", R"**( Command: M
] [] Command: m [[:]
] [] - Command: mt [[:]
] [] Shows memory dump. The first form ("M") interprets
as a physical address. - The second and third form ("m", "mt") interprets
as a logical - address if the address translation is enabled. Normally,
is + The second form ("m") interprets
as a logical address + if the address translation is enabled. Normally,
is interpreted in the current privilege and current address space. You can change it by modifier. On m68k, can be specified either by function code number directly @@ -1307,11 +1339,7 @@ Debugger::HelpDetails = { modifier ('s' or 'u', same as above) and following CMMU identifiers: 'd' .. Data CMMU 'i' or 'p' .. Instruction CMMU Or CMMU can also be identified by CMMU number (like '6' or '7'). - - "m" only looks up in ATC (on m68k) or in BATC/PATC (on m88k). - "mt" will simulate to search the page table in addition to that. )**" }, - { "mt", "=m" }, { "M", "=m" }, //----- @@ -1714,9 +1742,9 @@ Debugger::cmd_bv() int bi = AddBreakpoint(bp, cpustr); if (bi == -1) { fprintf(cons, "no free breakpoints\n"); - } else { - fprintf(cons, "breakpoint #%d added\n", bi); + return CmdAct::Stay; } + fprintf(cons, "breakpoint #%d added\n", bi); // この CPU 側に、すでに来ている例外をクリア。 // ブレークポイント設定の有無に関わらず例外が起きたら CPU 側から常に @@ -2008,8 +2036,8 @@ Debugger::cmd_hist_common(BranchHistory& int lines = std::min(used, maxlines) + 1; // MonitorUpdate() は TextScreen 高さに合わせて出力してくれる。 - auto& histmon = hist.monitor; - auto size = histmon.GetSize(); + auto *histmon = hist.monitor; + auto size = histmon->GetSize(); TextScreen screen; screen.Init(size.width, lines); @@ -2075,7 +2103,7 @@ Debugger::cmd_ct() // エラーならメッセージを表示して false を返す。 // sa は in/out パラメータ。 bool -Debugger::GetAddr(saddr_t *sa, bool default_data) +Debugger::GetAddr(busaddr *sa, bool default_data) { if (args.size() < 2) { // 引数なしなら、呼び出し側が sa にセットした前回値をそのまま使う。 @@ -2192,15 +2220,15 @@ Debugger::GetAddr(saddr_t *sa, bool defa if (mod_prog < 0) { mod_prog = !default_data; } - sa->SetSuper(mod_super); - sa->SetData(!mod_prog); + sa->ChangeSuper(mod_super); + sa->ChangeData(!mod_prog); // アドレス if (ParseAddr(str.c_str() + addrpos, &addr) == false) { return false; } // 命令境界に丸める - sa->SetAddr(addr & ~(curmd->inst_bytes - 1)); + sa->ChangeAddr(addr & ~(curmd->inst_bytes - 1)); return true; } @@ -2241,11 +2269,13 @@ Debugger::cmd_z() } else { // 可変長なら逆アセンブルしてみるしか。 - saddr_t laddr(curmd->GetPC(), curmd->IsSuper()); - DebuggerMemoryStream mem(curmd, laddr, MMULookupMode::True); + busaddr laddr = busaddr(curmd->GetPC()) + | BusAddr::Fetch + | busaddr::SU(curmd->IsSuper()); + DebuggerMemoryStream mem(curmd, laddr); // XXX 失敗したらどうすべ curmd->Disassemble(mem); - step_addr = (uint32)mem.laddr; + step_addr = mem.laddr.Addr(); } step_type = StepType::Addr; step_md = curmd; @@ -2268,45 +2298,42 @@ void Debugger::ResetStickyAddr() { pc = curmd->GetPC(); - m_last_addr.Set(pc, curmd->IsSuper(), true); - d_last_addr.Set(pc, curmd->IsSuper(), false); + m_last_addr = busaddr(pc) | BusAddr::Read | busaddr::SU(curmd->IsSuper()); + d_last_addr = busaddr(pc) | BusAddr::Fetch | busaddr::SU(curmd->IsSuper()); } -// 逆アセンブル: d [[SU:] []] (論理、テーブルサーチなし) +// 逆アセンブル: d [[SU:] []] (論理) Debugger::CmdAct Debugger::cmd_d() { - return cmd_d_common(MemoryMode::Logical, MMULookupMode::False); -} - -// 逆アセンブル: dt [[SU:]] []] (論理、テーブルサーチあり) -Debugger::CmdAct -Debugger::cmd_dt() -{ - return cmd_d_common(MemoryMode::Logical, MMULookupMode::True); + return cmd_d_common(BusAddr::Logical); } // 逆アセンブル: D [ []] (物理) Debugger::CmdAct Debugger::cmd_D() { - return cmd_d_common(MemoryMode::Physical, MMULookupMode::None); + return cmd_d_common(BusAddr::Physical); } // 逆アセンブル共通 Debugger::CmdAct -Debugger::cmd_d_common(MemoryMode access_mode, MMULookupMode lookup_mode) +Debugger::cmd_d_common(busaddr access_mode) { - saddr_t saddr; + busaddr saddr; int row; row = 10; - // 開始アドレス + // 開始アドレス。S/U は GetAddr() がセットする。 saddr = d_last_addr; if (GetAddr(&saddr, false) == false) { return CmdAct::Stay; } + + // 論理アドレス/物理アドレスはコマンドによって決まる。 + saddr |= access_mode; + // 2つ目の引数があれば行数 if (args.size() > 2) { row = strtol(args[2].c_str(), NULL, 10); @@ -2314,21 +2341,18 @@ Debugger::cmd_d_common(MemoryMode access // アドレス幅を制限 (XP用) (ここ?) uint64 mask; - if (access_mode == MemoryMode::Logical) { - mask = (1ULL << curmd->GetLASize()) - 1; - } else { + if (saddr.IsPhysical()) { mask = (1ULL << curmd->GetPASize()) - 1; + } else { + mask = (1ULL << curmd->GetLASize()) - 1; } - saddr = (uint32)saddr & (uint32)mask; + saddr &= (uint32)mask; Memdump disasm(curmd, curmd->arch); disasm.SetAddr(saddr); - disasm.SetAccessMode(access_mode); - disasm.SetLookupMode(lookup_mode); disasm.Print(cons, row); - // アドレスと Super/User 状態を次回継続用に保存 - // (Super/Data はコマンドで都度指定なので気にしなくていい) + // アドレスを次回継続用に保存 d_last_addr = disasm.GetAddr(); return CmdAct::Stay; @@ -2410,41 +2434,38 @@ Debugger::cmd_L() return CmdAct::Stay; } -// メモリダンプ: m [ []] (論理、テーブルサーチなし) +// メモリダンプ: m [ []] (論理) Debugger::CmdAct Debugger::cmd_m() { - return cmd_m_common(MemoryMode::Logical, MMULookupMode::False); -} - -// メモリダンプ: mt [ []] (論理、テーブルサーチあり) -Debugger::CmdAct -Debugger::cmd_mt() -{ - return cmd_m_common(MemoryMode::Logical, MMULookupMode::True); + return cmd_m_common(BusAddr::Logical); } // メモリダンプ: M [ []] (物理) Debugger::CmdAct Debugger::cmd_M() { - return cmd_m_common(MemoryMode::Physical, MMULookupMode::None); + return cmd_m_common(BusAddr::Physical); } // メモリダンプ共通 Debugger::CmdAct -Debugger::cmd_m_common(MemoryMode access_mode, MMULookupMode lookup_mode) +Debugger::cmd_m_common(busaddr access_mode) { - saddr_t saddr; + busaddr saddr; int row; row = 8; - // 開始アドレス + // 開始アドレス。S/U は GetAddr() がセットする。 saddr = m_last_addr; if (GetAddr(&saddr, true) == false) { return CmdAct::Stay; } + + // 論理アドレス/物理アドレスはコマンドによって決まる。 + saddr |= access_mode; + // 2つ目の引数があれば行数 if (args.size() > 2) { row = strtol(args[2].c_str(), NULL, 10); @@ -2452,22 +2473,19 @@ Debugger::cmd_m_common(MemoryMode access // アドレス幅を制限 (XP用) (ここ?) uint64 mask; - if (access_mode == MemoryMode::Logical) { - mask = (1ULL << curmd->GetLASize()) - 1; - } else { + if (saddr.IsPhysical()) { mask = (1ULL << curmd->GetPASize()) - 1; + } else { + mask = (1ULL << curmd->GetLASize()) - 1; } - saddr = (uint32)saddr & (uint32)mask; + saddr &= (uint32)mask; Memdump memdump(curmd); memdump.SetAddr(saddr); - memdump.SetAccessMode(access_mode); - memdump.SetLookupMode(lookup_mode); memdump.SetFormat(Memdump::Word); memdump.Print(cons, row); // アドレスを次回継続用に保存 - // (Super/Data はコマンドで都度指定なので気にしなくていい) m_last_addr = memdump.GetAddr(); return CmdAct::Stay; @@ -2491,9 +2509,10 @@ Debugger::cmd_minus() std::string addrbuf; std::string textbuf; - // 論理アクセス時、ATC ミスが分かったほうが便利だと思うので lookup なし - saddr_t laddr(pc, curmd->IsSuper()); - DebuggerMemoryStream mem(curmd, laddr, MMULookupMode::False); + busaddr laddr = busaddr(pc) + | BusAddr::Fetch + | busaddr::SU(curmd->IsSuper()); + DebuggerMemoryStream mem(curmd, laddr); // アドレス if (mem.FormatAddr(addrbuf) == false) { fprintf(cons, "%s\n", addrbuf.c_str()); @@ -2553,15 +2572,17 @@ Debugger::cmd_n_common(bool trace) void Debugger::SetNBreakpoint() { - saddr_t laddr(curmd->GetPC(), curmd->IsSuper()); - DebuggerMemoryStream mem(curmd, laddr, MMULookupMode::True); + busaddr laddr = busaddr(curmd->GetPC()) + | BusAddr::Fetch + | busaddr::SU(curmd->IsSuper()); + DebuggerMemoryStream mem(curmd, laddr); // 命令がサブルーチンやトラップなどステップインできる命令か。 if (curmd->IsOpStepIn(mem)) { // この次の命令にブレークをかける if (curmd->inst_bytes_fixed != 0) { // 固定長命令 - step_addr = (uint32)mem.laddr; + step_addr = mem.laddr.Addr(); } else { // 可変長なら逆アセンブルしてみるしか。 // 表示用文字列は作る必要ないけど、処理分けるのも手間だし @@ -2571,7 +2592,7 @@ Debugger::SetNBreakpoint() mem.ResetAddr(curmd->GetPC()); // XXX 失敗したらどうすべ curmd->Disassemble(mem); - step_addr = (uint32)mem.laddr; + step_addr = mem.laddr.Addr(); } } else { // そうでなければ1命令進める。 @@ -2600,12 +2621,12 @@ Debugger::CmdAct Debugger::cmd_show() { if (args.size() != 2) { - std::vector list; + std::vector list; // 登録されているモニタだけを列挙 // (登録されていてもサブウィンドウの ID を持っているものは除外) for (const auto mon : gMonitorManager->GetList()) { - int id = mon->GetId(); + uint id = mon->GetId(); if (id <= ID_MONITOR_END) { list.push_back(id); } @@ -2623,7 +2644,7 @@ Debugger::cmd_show() std::string name = args[1]; for (auto mon : gMonitorManager->GetList()) { - int id = mon->GetId(); + uint id = mon->GetId(); const auto& aliases = gMonitorManager->GetAliases(id); bool matched = false; @@ -2647,7 +2668,7 @@ Debugger::cmd_show() fprintf(cons, "unknown monitor name: \"%s\"\n", name.c_str()); } else if (candidates.size() == 1) { // 確定した - Monitor& mon = *(candidates[0]); + Monitor *mon = candidates[0]; ShowMonitor(mon); } else { // 候補が複数あった @@ -2665,12 +2686,12 @@ Debugger::cmd_show() // モニタを更新して表示。 void -Debugger::ShowMonitor(Monitor& monitor) +Debugger::ShowMonitor(Monitor *monitor) { // モニタを更新 TextScreen ts; - auto size = monitor.GetSize(); + auto size = monitor->GetSize(); ts.Init(size.width, size.height); MONITOR_UPDATE(monitor, ts); @@ -2711,7 +2732,10 @@ Debugger::ShowTextScreen(TextScreen& mon *d++ = '['; *d++ = 'm'; break; - case TA::On: + case TA::Reverse: + case TA::ReverseRed: + case TA::ReverseGreen: + case TA::ReverseOrange: *d++ = 0x1b; *d++ = '['; *d++ = '7'; @@ -2860,11 +2884,6 @@ Debugger::ParseAddr(const char *arg, uin uint64 r; r = curmd->GetRegAddr(arg + 1); if ((int64)r < 0) { -#if 0 // not yet - fprintf(cons, "valid register name are: %s%s\n", - "%d0-%d7,%a0-%a7,%sp,%usp,%isp,%pc", - ",%msp,%vbr,%srp,%crp"); -#endif fprintf(cons, "invalid register name\n"); return false; }