--- nono/debugger/debugger_m680x0.cpp 2026/04/29 17:04:30 1.1.1.1 +++ nono/debugger/debugger_m680x0.cpp 2026/04/29 17:05:09 1.1.1.8 @@ -1,39 +1,46 @@ // // nono -// Copyright (C) 2020 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + +// +// デバッガ (M680x0 依存部分) // -#include "console.h" #include "debugger_private.h" #include "debugger_m680x0.h" #include "m68030disasm.h" #include "mpu.h" -#include "mystring.h" + +// コンストラクタ +DebuggerMD_m680x0::DebuggerMD_m680x0(Debugger *parent_, m68kcpu *cpu_) + : inherited(parent_, Arch::M680x0) +{ + cpu = cpu_; + + // 機種依存変数 + inst_bytes = 2; + inst_bytes_fixed = 0; +} + +// デストラクタ +DebuggerMD_m680x0::~DebuggerMD_m680x0() +{ +} // アドレス変換 uint64 -DebuggerMD_m680x0::TranslateAddr(saddr_t laddr) +DebuggerMD_m680x0::TranslateAddr(saddr_t laddr, bool lookup) const { - uint64 paddr; + uint fc; - // ページ境界(と初回)でアドレス変換 - saddr_t lpage; - lpage.addr = laddr.addr & cpu->mmu_tc.lmask; - lpage.super = laddr.super; - if (lpage.GetSaddr() != last_lpage.GetSaddr()) { - last_lpage = lpage; - uint32 fc2 = (lpage.super ? FC_SUPER : 0) | FC_PROG; // DATAは? - - bool do_search = laddr.IsSearch(); - paddr = m68030_mmu_translate_peek(cpu, laddr.addr, fc2, do_search); - if ((int64)paddr < 0) { - last_lpage.addr = 0xffffffff; - } - last_ppage = paddr & cpu->mmu_tc.lmask; - } else { - paddr = last_ppage | (laddr.addr & cpu->mmu_tc.pgmask); + fc = laddr.IsData() ? FC_DATA : FC_PROG; + if (laddr.IsSuper()) { + fc |= FC_SUPER; } - return paddr; + + return m68030_mmu_translate_peek(cpu, (uint32)laddr, fc, lookup); } // op が 68030 の条件命令 Bcc, Scc, TRAPcc, DBcc なら true を返す。 @@ -167,6 +174,34 @@ DebuggerMD_m680x0::IsStepOut() const return (RegA(7) > so_a7 || (RegSR & 0x3000) != so_sr); } +// この命令がステップイン出来るなら true を返す +bool +DebuggerMD_m680x0::IsOpStepIn(DebuggerMemoryStream& mem) +{ + uint32 op = mem.FetchInst(); + + if ((op & 0xfff0) == 0x4e40 // TRAP + || (op == 0x4e76) // TRAPV + || (op & 0xffc0) == 0x4e80 // JSR + || (op & 0xf0f8) == 0x50f8 // TRAPcc + || (op & 0xff00) == 0x6100 // BSR + || (op & 0xfff8) == 0xf278 // FTRAPcc + ) { + return true; + } + + // IOCS コール(に逆アセンブラで見えるやつ)も一命令扱いにしておく。 + // XXX 本当は X68k の時だけだが今の所副作用なさげなので + if ((op & 0xff00) == 0x7000) { // MOVEQ to %d0 + uint32 op2 = mem.FetchInst(); + if (op2 == 0x4e4f) { // TRAP #15 + return true; + } + } + + return false; +} + // レジスタ名からそのレジスタ値を返す。 // メモリダンプのような用途なのでアドレスとして使えるアドレスのみ。 uint64 @@ -212,9 +247,104 @@ DebuggerMD_m680x0::GetRegAddr(const char return addr; } +// レジスタ表示系コマンドのヘルプ +/*static*/ const HelpMessages +DebuggerMD_m680x0::HelpListReg = { + { "r", "Show general registers" }, + { "ra", "Show ATC" }, + { "rf", "Show FPU registers" }, + { "rm", "Show MMU registers" }, + { "ro", "Show other registers" }, +}; + +/*static*/ const HelpMessages +DebuggerMD_m680x0::HelpReg = { + //----- + { "r", R"**( + Command: r + + Shows main registers. + )**" }, + + //----- + { "ra", R"**( + Command: ra + + Shows m68030 ATC(Address Translation Cache) information. Note that + nono's ATC implementation is very different from the real one (to + improve performance). + )**" }, + + //----- + { "rf", R"**( + Command: rf + + Shows 68881/68882's FPU registers. + )**" }, + + //----- + { "rm", R"**( + Command: rm + + Shows registers related to MMU and cache. + )**" }, + + //----- + { "ro", R"**( + Command: ro + + Shows other registers. + )**" }, +}; + +const HelpMessages& +DebuggerMD_m680x0::GetHelpListReg() const +{ + return HelpListReg; +} + +const HelpMessages& +DebuggerMD_m680x0::GetHelpReg() const +{ + return HelpReg; +} + +// レジスタ表示系コマンド +bool +DebuggerMD_m680x0::ShowRegister(FILE *cons, + const std::vector& args) +{ + // 余分な引数は無視する? + + if (args[0] == "r") { + ShowRegMain(cons); + return true; + } + if (args[0] == "ra") { + ShowRegATC(); + return true; + } + if (args[0] == "rf") { + ShowRegFPU(cons); + return true; + } + if (args[0] == "rm") { + ShowRegMMU(cons); + return true; + } + if (args[0] == "ro") { + ShowRegOther(); + return true; + } + + // 該当なし + return false; +} + + // レジスタ表示 (基本セット) void -DebuggerMD_m680x0::ShowRegMain(Console *cons) +DebuggerMD_m680x0::ShowRegMain(FILE *cons) { /* D0:00000070 D4:CCCCCCCC A0:00FFAA32 A4:CCCCCCCC SR=F810(S I=0 X----) @@ -229,7 +359,7 @@ D3:CCCCCCCC D7:00000003 A3:CCCCCCCC A7: } // 1行目 - cons->Print("%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s ", + fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s ", BOLDIF(vr[ 0]), 0, RegR( 0), NORM, BOLDIF(vr[ 4]), 4, RegR( 4), NORM, BOLDIF(vr[ 8]), 0, RegR( 8), NORM, @@ -244,14 +374,14 @@ D3:CCCCCCCC D7:00000003 A3:CCCCCCCC A7: | (prev.ccr.IsV() ? M68K_CCR_V : 0) | (prev.ccr.IsC() ? M68K_CCR_C : 0); // SR は上位バイトと下位バイトが変化したくらいでいいか? - cons->Print(" SR:%s%02x%s%s%02x%s", + fprintf(cons, " SR:%s%02x%s%s%02x%s", BOLDIF((sr & 0xff00) != (prevsr & 0xff00)), sr >> 8, NORM, BOLDIF((sr & 0x00ff) != (prevsr & 0x00ff)), sr & 0xff, NORM); - cons->Print("(%c I=%d %c%c%c%c%c)\n", + fprintf(cons, "(%c I=%d %c%c%c%c%c)\n", (sr & 0x2000) ? 'S' : '-', (sr >> 8) & 7, (sr & M68K_CCR_X) ? 'X' : '-', @@ -261,21 +391,21 @@ D3:CCCCCCCC D7:00000003 A3:CCCCCCCC A7: (sr & M68K_CCR_C) ? 'C' : '-'); // 2行目 - cons->Print("%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n", + fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n", BOLDIF(vr[ 1]), 1, RegR( 1), NORM, BOLDIF(vr[ 5]), 5, RegR( 5), NORM, BOLDIF(vr[ 9]), 1, RegR( 9), NORM, BOLDIF(vr[13]), 5, RegR(13), NORM); // 3行目 - cons->Print("%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n", + fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n", BOLDIF(vr[ 2]), 2, RegR( 2), NORM, BOLDIF(vr[ 6]), 6, RegR( 6), NORM, BOLDIF(vr[10]), 2, RegR(10), NORM, BOLDIF(vr[14]), 6, RegR(14), NORM); // 4行目 - cons->Print("%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n", + fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n", BOLDIF(vr[ 3]), 3, RegR( 3), NORM, BOLDIF(vr[ 7]), 7, RegR( 7), NORM, BOLDIF(vr[11]), 3, RegR(11), NORM, @@ -284,7 +414,7 @@ D3:CCCCCCCC D7:00000003 A3:CCCCCCCC A7: // FPU レジスタ表示 void -DebuggerMD_m680x0::ShowRegFPU(Console *cons) +DebuggerMD_m680x0::ShowRegFPU(FILE *cons) { /* FP0:0000_12345678_12345678 (-0.1234567890123456789) FPCR:1234 @@ -301,7 +431,7 @@ FP7: uint32 *c_ = cpu->reg.fpframe.fpf_regs + (n) * 3; \ uint32 *p_ = prev.fpframe.fpf_regs + (n) * 3; \ bool d = (c_[0] ^ p_[0]) | (c_[1] ^ p_[1]) | (c_[2] ^ p_[2]); \ - cons->Print("%sFP%d:%04xxxxx_%08x_%08x (%-20s)%s ", \ + fprintf(cons, "%sFP%d:%04xxxxx_%08x_%08x (%-20s)%s ", \ BOLDIF(d), (n), c_[0] >> 16, c_[1], c_[2], "notyet", NORM); \ } while (0) @@ -328,10 +458,10 @@ FP7: ppiar = prev.fpframe.fpf_fpiar; PUT_FP(0); - cons->Print("%sFPCR:%04x%s\n", BOLDIF(fpcr != ppcr), fpcr, NORM); + fprintf(cons, "%sFPCR:%04x%s\n", BOLDIF(fpcr != ppcr), fpcr, NORM); PUT_FP(1); - cons->Print(" %s %s %s %s %s %s %s %s\n", + fprintf(cons, " %s %s %s %s %s %s %s %s\n", (fpcr & 0x8000) ? "BS" : "--", (fpcr & 0x4000) ? "SN" : "--", (fpcr & 0x2000) ? "OP" : "--", @@ -342,16 +472,16 @@ FP7: (fpcr & 0x0100) ? "I1" : "--"); PUT_FP(2); - cons->Print(" RP=%s RM=%s\n", + fprintf(cons, " RP=%s RM=%s\n", rpstr[(fpcr >> 6) & 3], rmstr[(fpcr >> 4) & 3]); PUT_FP(3); - cons->Print("%sFPSR:%08x%s\n", BOLDIF(fpsr != ppsr), fpsr, NORM); + fprintf(cons, "%sFPSR:%08x%s\n", BOLDIF(fpsr != ppsr), fpsr, NORM); PUT_FP(4); uint cc = fpsr >> 24; - cons->Print(" %c %c %s %s Q=$%02x\n", + fprintf(cons, " %c %c %s %s Q=$%02x\n", (cc & 0x08) ? 'N' : '-', (cc & 0x04) ? 'Z' : '-', (cc & 0x02) ? "Inf" : "---", @@ -359,7 +489,7 @@ FP7: (fpsr >> 16) & 0xff); PUT_FP(5); - cons->Print(" %s %s %s %s %s %s %s %s\n", + fprintf(cons, " %s %s %s %s %s %s %s %s\n", (fpsr & 0x8000) ? "BS" : "--", (fpsr & 0x4000) ? "SN" : "--", (fpsr & 0x2000) ? "OP" : "--", @@ -370,7 +500,7 @@ FP7: (fpsr & 0x0100) ? "I1" : "--"); PUT_FP(6); - cons->Print(" %s %s %s %s %s\n", + fprintf(cons, " %s %s %s %s %s\n", (fpsr & 0x80) ? "IOP" : "---", (fpsr & 0x40) ? "OVFL" : "----", (fpsr & 0x20) ? "UNFL" : "----", @@ -378,12 +508,12 @@ FP7: (fpsr & 0x08) ? "INEX" : "----"); PUT_FP(7); - cons->Print("%sFPIAR:%08x%s\n", BOLDIF(fpiar != ppiar), fpiar, NORM); + fprintf(cons, "%sFPIAR:%08x%s\n", BOLDIF(fpiar != ppiar), fpiar, NORM); } // MMU レジスタ表示 void -DebuggerMD_m680x0::ShowRegMMU(Console *cons) +DebuggerMD_m680x0::ShowRegMMU(FILE *cons) { /* SRP:00001111_22223333 TT0:00001111 TC:00001111 (---) @@ -417,13 +547,13 @@ CRP:00001111_22223333 TT1:00001111 MMUSR p = (srp != osrp); t = (tt0 != ott0); c = (tc != otc); - cons->Print("%sSRP:%08x_%08x%s %sTT0:%08x%s(%c%c%c)", + fprintf(cons, "%sSRP:%08x_%08x%s %sTT0:%08x%s(%c%c%c)", BOLDIF(p), (uint32)(srp >> 32), (uint32)srp, NORM, BOLDIF(t), tt0, NORM, (tt0 & m68030TT::E) ? 'E' : '-', (tt0 & m68030TT::CI) ? 'C' : '-', (tt0 & m68030TT::RWM) ? '-' : ((tt0 & m68030TT::RW) ? 'R' : 'W')); - cons->Print(" %sTC:%08x%s(%c%c%c)\n", + fprintf(cons, " %sTC:%08x%s(%c%c%c)\n", BOLDIF(c), tc, NORM, (tc & m68030TC::TC_E) ? 'E' : '-', (tc & m68030TC::TC_SRE) ? 'S' : '-', @@ -433,13 +563,13 @@ CRP:00001111_22223333 TT1:00001111 MMUSR p = (crp != ocrp); t = (tt1 != ott1); c = (sr != osr); - cons->Print("%sCRP:%08x_%08x%s %sTT1:%08x%s(%c%c%c)", + fprintf(cons, "%sCRP:%08x_%08x%s %sTT1:%08x%s(%c%c%c)", BOLDIF(p), uint32(crp >> 32), (uint32)crp, NORM, BOLDIF(t), tt1, NORM, (tt1 & m68030TT::E) ? 'E' : '-', (tt1 & m68030TT::CI) ? 'C' : '-', (tt1 & m68030TT::RWM) ? '-' : ((tt1 & m68030TT::RW) ? 'R' : 'W')); - cons->Print(" %sMMUSR: %04x%s(%c%c%c%c%c%c%c N=%d)\n", + fprintf(cons, " %sMMUSR: %04x%s(%c%c%c%c%c%c%c N=%d)\n", BOLDIF(c), sr, NORM, (sr & m68030MMUSR::B) ? 'B' : '-', (sr & m68030MMUSR::L) ? 'L' : '-', @@ -453,15 +583,14 @@ CRP:00001111_22223333 TT1:00001111 MMUSR // ATC を表示 void -DebuggerMD_m680x0::ShowRegATC(Console *cons) +DebuggerMD_m680x0::ShowRegATC() { - gMPUATC->MonitorUpdate(); - parent->ShowMonitor(gMPUATC->monitor); + parent->ShowMonitor(gMonitorManager->Get(ID_MONITOR_MPUATC)); } // その他のレジスタを表示 void -DebuggerMD_m680x0::ShowRegOther(Console *cons) +DebuggerMD_m680x0::ShowRegOther() { TextScreen s(80, 2); @@ -493,16 +622,16 @@ DebuggerMD_m680x0::ShowRegOther(Console s.Print(29, 1, EM(isp), "ISP:%08x", cpu->reg.isp); } - parent->ShowMonitor(s); + parent->ShowTextScreen(s); } // 逆アセンブル bool -DebuggerMD_m680x0::Disassemble(saddr_t laddr, +DebuggerMD_m680x0::Disassemble(DebuggerMemoryStream& mem, std::string& mnemonic, std::vector& bin) { - m680x0disasm dis(this); - if (dis.Exec(laddr) == false) { + m680x0disasm dis(mem); + if (dis.Exec() == false) { return false; } mnemonic = dis.text;