--- nono/debugger/debugger_m88xx0.cpp 2026/04/29 17:04:33 1.1.1.2 +++ nono/debugger/debugger_m88xx0.cpp 2026/04/29 17:05:09 1.1.1.9 @@ -4,12 +4,14 @@ // Licensed under nono-license.txt // -#include "console.h" +// +// デバッガ (M88xx0 依存部分) +// + #include "debugger_private.h" #include "debugger_m88xx0.h" #include "m88100disasm.h" #include "m88100acc.h" -#include "mystring.h" // newval が oldval から変化していれば太字属性にするマクロ #define TSBOLD(newval, oldval) (((newval) != (oldval)) ? TA::Em : TA::Off) @@ -22,13 +24,13 @@ // コンストラクタ DebuggerMD_m88xx0::DebuggerMD_m88xx0(Debugger *parent_, m88kcpu *cpu_) - : inherited(parent_) + : inherited(parent_, Arch::M88xx0) { cpu = cpu_; - // 奇数にしておくことで初回に必ずアドレス変換を起こさせる。 - last_lpage[0].addr = 0xffffffff; - last_lpage[1].addr = 0xffffffff; + // 機種依存変数 + inst_bytes = 4; + inst_bytes_fixed = 4; cmp_rd = -1; } @@ -48,45 +50,39 @@ DebuggerMD_m88xx0::MMUEnabled() const // アドレス変換 uint64 -DebuggerMD_m88xx0::TranslateAddr(saddr_t laddr) +DebuggerMD_m88xx0::TranslateAddr(saddr_t laddr, bool lookup) const { - uint64 paddr; - int isdata; m88200 *cmmu; // XXX とりあえずね - isdata = (laddr.data) ? 1 : 0; - if (isdata == 0) { + if (laddr.IsData() == false) { cmmu = &cpu->cmmu[0]; } else { cmmu = &cpu->cmmu[1]; } - // ページ境界(と初回)でアドレス変換 - saddr_t lpage; - lpage.addr = laddr.addr & 0xfffff000; - lpage.super = laddr.super; - if (lpage.GetSaddr() != last_lpage[isdata].GetSaddr()) { - last_lpage[isdata] = lpage; - - bool do_search = laddr.IsSearch(); - paddr = cmmu->TranslatePeek(laddr.addr, laddr.super, do_search); - if ((int64)paddr < 0) { - last_lpage[isdata].addr = 0xffffffff; - } - last_ppage[isdata] = paddr & 0xfffff000; - } else { - paddr = last_ppage[isdata] | (laddr.addr & 0x00000fff); - } - return paddr; + return cmmu->TranslatePeek((uint32)laddr, laddr.IsSuper(), lookup); +} + +// op が bb0 命令なら true を返す +/*static*/ bool +DebuggerMD_m88xx0::IsBB0(uint32 op) +{ + return ((op & 0xf8000000) == 0xd0000000); // bb0 +} + +// op が tb0 命令なら true を返す +/*static*/ bool +DebuggerMD_m88xx0::IsTB0(uint32 op) +{ + return ((op & 0xfc00fe00) == 0xf000d000); // tb0 } // op が bb0/tb0 命令なら true を返す /*static*/ bool DebuggerMD_m88xx0::IsBBTB0(uint32 op) { - return ((op & 0xf8000000) == 0xd0000000 || // bb0 - (op & 0xfc00fe00) == 0xf000d000 ); // tb0 + return IsBB0(op) || IsTB0(op); } // op が bb1 命令なら true を返す @@ -128,6 +124,26 @@ DebuggerMD_m88xx0::IsStepOut() const return (cpu->xip == so_r1); } +// この命令がステップイン出来るなら true を返す +bool +DebuggerMD_m88xx0::IsOpStepIn(DebuggerMemoryStream& mem) +{ + uint32 op = mem.FetchInst(); + + if ((op & 0xf800'0000) == 0xc800'0000 // bsr + || IsTB0(op) // tb0 + || (IsTB1(op) && ((op >> 16) & 0x1f) != 0) // tb1 (except r0) + || (op & 0xfc00'fe00) == 0xf000'e800 // tcnd + || (op & 0xfc00'fb00) == 0xf400'c800 // jsr + || (op & 0xfc00'0000) == 0xf800'0000 // tbnd imm + || (op & 0xfc00'ffe0) == 0xf400'f800 // tbnd rs2 + ) { + return true; + } + + return false; +} + // レジスタ名からそのレジスタ値を返す。 // メモリダンプのような用途なのでアドレスとして使えるアドレスのみ。 uint64 @@ -185,25 +201,95 @@ DebuggerMD_m88xx0::GetRegAddr(const char // レジスタ表示系コマンドのヘルプ /*static*/ const HelpMessages -DebuggerMD_m88xx0::HelpMsgRegister = { - { "r", "通常レジスタを表示" }, - { "rc", "制御レジスタを表示" }, - { "rf", "FPU レジスタを表示" }, - { "ro", "その他のレジスタを表示" }, - { "ra", "ATC を表示" }, - { "rd []", "データキャッシュを表示" }, - { "rm", "CMMU レジスタを表示" }, +DebuggerMD_m88xx0::HelpListReg = { + { "r", "Show general registers" }, + { "rc", "Show (integer) control registers" }, + { "rf", "Show floating point control registers" }, + { "ro", "Show other (shadow) registers" }, + { "ra", "Show ATC on CMMU" }, + { "rd", "Show data cache on CMMU" }, + { "rm", "Show CMMU registers" }, +}; + +/*static*/ const HelpMessages +DebuggerMD_m88xx0::HelpReg = { + //----- + { "r", R"**( + Command: r + + Shows general registers. + )**" }, + + //----- + { "rc", R"**( + Command: rc + + Shows the (integer) control registers. + )**" }, + + //----- + { "rf", R"**( + Command: rf + + Shows the floating point control registers. + )**" }, + + //----- + { "ro", R"**( + Command: ro + + Shows the other registers. + )**" }, + + //----- + { "ra", R"**( + Command: ra := 7, 6 + + Shows BATC/PATC on CMMU. + CMMU7 is instruction CMMU of CPU#0. + CMMU6 is data CMMU of CPU#0. + )**" }, + { "ra6", "=ra" }, + { "ra7", "=ra" }, + + //----- + { "rd", R"**( + Command: rd := 7, 6 + + Shows data cache on CMMU. + CMMU7 is instruction CMMU of CPU#0. + CMMU6 is data CMMU of CPU#0. + )**" }, + { "rd6", "=rd" }, + { "rd7", "=rd" }, + + //----- + { "rm", R"**( + Command: rm := 7, 6 + + Shows CMMU registers. + CMMU7 is instruction CMMU of CPU#0. + CMMU6 is data CMMU of CPU#0. + )**" }, + { "rm6", "=rm" }, + { "rm7", "=rm" }, }; const HelpMessages& -DebuggerMD_m88xx0::GetRegisterHelp() const +DebuggerMD_m88xx0::GetHelpListReg() const { - return HelpMsgRegister; + return HelpListReg; +} + +const HelpMessages& +DebuggerMD_m88xx0::GetHelpReg() const +{ + return HelpReg; } // レジスタ表示系コマンド bool -DebuggerMD_m88xx0::ShowRegister(Console *cons, +DebuggerMD_m88xx0::ShowRegister(FILE *cons, const std::vector& args) { int cmmu_id; @@ -211,42 +297,51 @@ DebuggerMD_m88xx0::ShowRegister(Console // 余分な引数は無視する? if (args[0] == "r") { - ShowRegMain(cons); + ShowRegMain(); return true; } if (args[0] == "rc") { - ShowRegCtrl(cons); + ShowRegCtrl(); return true; } if (args[0] == "rf") { - ShowRegFPU(cons); + ShowRegFPU(); return true; } if (args[0] == "ro") { - ShowRegOther(cons); + ShowRegOther(); return true; } if (MatchCMMUCmd(args[0], "ra", &cmmu_id)) { - parent->ShowMonitor(*gMPU88200ATC[7 - cmmu_id]); - return true; + Monitor *mon = gMonitorManager->Find(ID_MONITOR_ATC(cmmu_id)); + if (mon) { + parent->ShowMonitor(*mon); + return true; + } + goto notfound; } if (MatchCMMUCmd(args[0], "rd", &cmmu_id)) { - ShowRegCache(cons, args, cmmu_id); - return true; + return ShowRegCache(cons, args, cmmu_id); } if (MatchCMMUCmd(args[0], "rm", &cmmu_id)) { - ShowRegMMU(cons, cmmu_id); - return true; + Monitor *mon = gMonitorManager->Find(ID_MONITOR_CMMU(cmmu_id)); + if (mon) { + parent->ShowMonitor(*mon); + return true; + } + goto notfound; } // 該当なし + notfound: return false; } // CMMU ID 入りコマンド名を照合する。 // cmdname が basename + の時、*idp に id を格納して true を返す。 -// 一致しないか id が不正なら false を返す。 +// 一致しないか id が(数値でないなど)不正なら false を返す。 +// 実際にその id の CMMU が存在するかはここではチェックしない。 bool DebuggerMD_m88xx0::MatchCMMUCmd(const std::string& cmdname, const char *basename, int *idp) @@ -272,7 +367,7 @@ DebuggerMD_m88xx0::MatchCMMUCmd(const st } void -DebuggerMD_m88xx0::ShowRegMain(Console *cons) +DebuggerMD_m88xx0::ShowRegMain() { TextScreen s(80, 8); @@ -313,7 +408,7 @@ r2 :0070e1a0 r10:00000000 r18:00000000 } void -DebuggerMD_m88xx0::ShowRegCtrl(Console *cons) +DebuggerMD_m88xx0::ShowRegCtrl() { TextScreen s(80, 6); int x; @@ -322,12 +417,12 @@ DebuggerMD_m88xx0::ShowRegCtrl(Console * /* 0 1 2 3 4 5 6 7 0123456789012345678901234567890123456789012345678901234567890123456789012345678 -pid (cr0):12345678(Arch=$00 Ver=$00 M/C=Checker) ssbr(cr3):00000000 -psr (cr1):12345678(S,LE,SER,Cy SFD1,MXM,IND,SFRZ) vbr (cr7):00000000 -epsr(cr2):12345678(S,LE,SER,Cy SFD1,MXM,IND,SFRZ) sr0(cr17):00000000 -xip:00000000 opX:00000000(--) sxip(cr4):00000000:VE sr1(cr18):00000000 -nip:00000000 opF:00000000(--) snip(cr5):00000000:-- sr2(cr19):00000000 -fip:00000000 sfip(cr6):00000000:VE sr3(cr20):00000000 +pid (cr0):12345678(Arch=$00 Ver=$00 M/C=Checker) sr0(cr17):00000000 +psr (cr1):12345678(S,LE,SER,Cy SFD1,MXM,IND,SFRZ) sr1(cr18):00000000 +epsr(cr2):12345678(S,LE,SER,Cy SFD1,MXM,IND,SFRZ) sr2(cr19):00000000 +xip:00000000 opX:00000000(--) sxip(cr4):00000000:VE sr3(cr20):00000000 +nip:00000000 opF:00000000(--) snip(cr5):00000000:-- ssbr(cr3):00000000 +fip:00000000 sfip(cr6):00000000:VE vbr (cr7):00000000 */ #define PRINT_B(x, y, reg, mask, fmt, arg) do { \ @@ -362,7 +457,7 @@ fip:00000000 sfip(cr6 // epsr(cr2) y++; - s.Print(x, y, TSBOLDC(psr), "epsr(cr2):%08x", cpu->epsr); + s.Print(x, y, TSBOLDC(epsr), "epsr(cr2):%08x", cpu->epsr); s.Print(x + 18, y, "(s,le,ser,cy sfd1,mxm,ind,sfrz)"); PRINT_B(x + 19, y, epsr, m88100reg::PSR_SUPER, "%c", _new ? 'S' : '-'); PRINT_B(x + 21, y, epsr, m88100reg::PSR_BO_LE, "%s", _new ? "LE" : "BE"); @@ -398,17 +493,16 @@ fip:00000000 sfip(cr6 x = 55; y = 0; - // ssbr(cr3) - s.Print(x, y++, TSBOLDC(ssbr), "ssbr(cr3):%08x", cpu->ssbr); - // vbr(cr7) - s.Print(x, y++, TSBOLDC(vbr), "vbr (cr7):%08x", cpu->vbr); - // SR* for (int i = 0; i < 4; i++) { int rn = 17 + i; - s.Print(x, y + i, TSBOLDC(cr[rn]), "sr%d(cr%d):%08x", + s.Print(x, y++, TSBOLDC(cr[rn]), "sr%d(cr%d):%08x", i, rn, cpu->cr[rn]); } + // ssbr(cr3) + s.Print(x, y++, TSBOLDC(ssbr), "ssbr(cr3):%08x", cpu->ssbr); + // vbr(cr7) + s.Print(x, y++, TSBOLDC(vbr), "vbr (cr7):%08x", cpu->vbr); parent->ShowTextScreen(s); } @@ -416,65 +510,65 @@ fip:00000000 sfip(cr6 // CMMU のデータキャッシュを表示 // rd なら概要表示。 // rd なら個別セットの詳細表示。 -void -DebuggerMD_m88xx0::ShowRegCache(Console *cons, +// id を受け付ければ true を、そうでなければ false を返す。 +bool +DebuggerMD_m88xx0::ShowRegCache(FILE *cons, const std::vector& args, int id) { + m88200 *cmmu; + + // XXX id はまだ決め打ち + if (id == 7) { + cmmu = &cpu->cmmu[0]; + } else if (id == 6) { + cmmu = &cpu->cmmu[1]; + } else { + return false; + } + if (args.size() < 2) { - ShowRegCacheOverview(cons, id); + ShowRegCacheOverview(cmmu); } else { int set; char *end; errno = 0; set = strtol(args[1].c_str(), &end, 16); if (end == &args[1][0] || *end != '\0' || errno == ERANGE) { - cons->Print(" must be a number\n"); - return; + fprintf(cons, " must be a number\n"); + goto done; } if (set < 0 || set > 256) { - cons->Print(" must be in 00..ff\n"); - return; + fprintf(cons, " must be in 00..ff\n"); + goto done; } - ShowRegCacheSet(cons, id, set); + ShowRegCacheSet(cmmu, set); } + done: + return true; } // CMMU データキャッシュの概要表示 void -DebuggerMD_m88xx0::ShowRegCacheOverview(Console *cons, int id) +DebuggerMD_m88xx0::ShowRegCacheOverview(m88200 *cmmu) { TextScreen s(70, 17); - m88200 *cmmu; - // まだ今の所決め打ち - if (id == 7) { - cmmu = &cpu->cmmu[0]; - } else { - cmmu = &cpu->cmmu[1]; - } cmmu->MonitorCacheOverview(s, 0, false); parent->ShowTextScreen(s); } // CMMU データキャッシュの指定セットの詳細表示 void -DebuggerMD_m88xx0::ShowRegCacheSet(Console *cons, int id, int setidx) +DebuggerMD_m88xx0::ShowRegCacheSet(m88200 *cmmu, int setidx) { TextScreen s(70, 5); - m88200 *cmmu; - // まだ今の所決め打ち - if (id == 7) { - cmmu = &cpu->cmmu[0]; - } else { - cmmu = &cpu->cmmu[1]; - } cmmu->MonitorCacheSet(s, 0, setidx); parent->ShowTextScreen(s); } void -DebuggerMD_m88xx0::ShowRegFPU(Console *cons) +DebuggerMD_m88xx0::ShowRegFPU() { static const char * const fcrname[] = { "fpecr", @@ -503,21 +597,7 @@ DebuggerMD_m88xx0::ShowRegFPU(Console *c } void -DebuggerMD_m88xx0::ShowRegMMU(Console *cons, int id) -{ - m88200 *cmmu; - - // まだ今の所決め打ち - if (id == 7) { - cmmu = &cpu->cmmu[0]; - } else { - cmmu = &cpu->cmmu[1]; - } - parent->ShowMonitor(*cmmu); -} - -void -DebuggerMD_m88xx0::ShowRegOther(Console *cons) +DebuggerMD_m88xx0::ShowRegOther() { TextScreen s(80, 3); /* @@ -559,15 +639,26 @@ dmt0(cr14):0000(B, ,D,L,Rxx,S,LLLL,W,V) // 逆アセンブル bool -DebuggerMD_m88xx0::Disassemble(saddr_t laddr, +DebuggerMD_m88xx0::Disassemble(DebuggerMemoryStream& mem, std::string& mnemonic, std::vector& bin) { - m88100disasm dis(this); - if (dis.Exec(laddr) == false) { + m88100disasm dis(mem); + if (dis.Exec() == false) { return false; } - mnemonic = dis.text; bin = dis.bin; + mnemonic = dis.text; + if (!dis.alttext.empty()) { + // 別名追加 + int len = mnemonic.length() % 8; + if (len < 8) { + mnemonic += std::string(8 - len, ' '); + } else { + mnemonic += ' '; + } + mnemonic += dis.alttext; + } + return true; }