--- nono/debugger/memdump.cpp 2026/04/29 17:05:16 1.1.1.2 +++ nono/debugger/memdump.cpp 2026/04/29 17:05:32 1.1.1.5 @@ -11,26 +11,25 @@ #include "memdump.h" #include "debugger_memory.h" #include "debugger_private.h" -#include "device.h" #include "hd64180disasm.h" -#include "m68030disasm.h" +#include "m680x0disasm.h" #include "m88100disasm.h" +#include "mainbus.h" +#include "monitor.h" // // メモリダンプ (基本クラス) // // コンストラクタ -Memdump::Memdump(int objid_) +Memdump::Memdump(uint objid_) : inherited(objid_) { // ログは不要 ClearAlias(); // 初期値 - saddr.SetSuper(true); - saddr.SetData(true); - SetAccessMode(MemoryMode::Physical); + saddr = BusAddr::SRead | BusAddr::Physical; SetFormat(Word); } @@ -51,7 +50,7 @@ Memdump::Memdump(DebuggerMD *md_, CPUArc Format fmt_; switch (asm_arch) { case CPUArch::M680x0: - fmt_ = M68030Disasm; + fmt_ = M680x0Disasm; break; case CPUArch::M88xx0: fmt_ = M88100Disasm; @@ -78,51 +77,27 @@ Memdump::InitMD(DebuggerMD *md_) bus = md->GetBus(); } -// saddr を設定する。 +// busaddr を設定する。 void -Memdump::SetAddr(const saddr_t& saddr_) +Memdump::SetAddr(busaddr saddr_) { - SetAddr(saddr_.GetAddr()); - SetData(saddr_.IsData()); - SetSuper(saddr_.IsSuper()); + saddr = saddr_; + MaskAddr(); } // アドレスを設定する。 void Memdump::SetAddr(uint32 laddr_) { - // 今の表示形式での境界に揃える - laddr_ = laddr_ & ~(GetStride() - 1); - - saddr.SetAddr(laddr_); -} - -// User/Super を設定する。 -void -Memdump::SetSuper(bool super_) -{ - saddr.SetSuper(super_); -} - -// Data/Inst を設定する。 -void -Memdump::SetData(bool data_) -{ - saddr.SetData(data_); + saddr.ChangeAddr(laddr_); + MaskAddr(); } -// アクセスモードを設定する。 +// 今の表示形式での境界に揃える。 void -Memdump::SetAccessMode(MemoryMode access_mode_) +Memdump::MaskAddr() { - access_mode = access_mode_; -} - -// MMU ルックアップモードを設定する。 -void -Memdump::SetLookupMode(MMULookupMode lookup_mode_) -{ - lookup_mode = lookup_mode_; + saddr &= ~(GetStride() - 1); } // アドレスをバイト単位で加算(減算)する。 @@ -149,6 +124,8 @@ Memdump::SetFormat(Memdump::Format fmt_) fixed = 16; break; case M68030PageShort: + case M68040TableDesc: + case M68040PageDesc: case M88200Page: fixed = 4; break; @@ -156,7 +133,7 @@ Memdump::SetFormat(Memdump::Format fmt_) fixed = 8; break; - case M68030Disasm: + case M680x0Disasm: line.reset(new m680x0disasm()); inst_bytes = 2; break; @@ -172,7 +149,7 @@ Memdump::SetFormat(Memdump::Format fmt_) } // 表示形式を切り替えたことによってアドレスに端数が出るのを防ぐ - SetAddr(saddr.GetAddr()); + MaskAddr(); } // 物理メモリ paddr 以降の内容を越権的に読み出す。bytes は 1, 2, 4 を想定。 @@ -180,44 +157,39 @@ Memdump::SetFormat(Memdump::Format fmt_) uint64 Memdump::Peek(uint32 paddr, int bytes) const { - uint64 data = 0; + uint32 data = 0; while (--bytes >= 0) { - data = (data << 8) | bus->Peek8(paddr++); + busdata bd = bus->Peek1(paddr++); + if (__predict_false(bd.IsBusErr())) { + return bd; + } + data = (data << 8) | bd.Data(); } return data; } // 物理メモリ paddr 以降の内容を越権的に書き換える。 // bytes は 1, 2, 4 を想定しており、paddr はこれに整列しているはず。 -// バスエラーが起きたらその場で処理を中止して (uint64)-1 を返す。 -uint64 +// バスエラーが起きたらその場で処理を中止して false を返す。 +bool Memdump::Poke(uint32 paddr, uint32 data, int bytes) { - IODevice *dev = bus->FindDevice(paddr); - assert(dev); - while (--bytes >= 0) { uint32 d = data >> (bytes * 8); - uint64 berr = dev->Poke8(paddr++, d & 0xff); - if ((int64)berr < 0) { - return berr; + if (bus->Poke1(paddr++, d & 0xff) == false) { + return false; } } - return 0; + return true; } // この paddr が Poke() 可能なら true を返す。 bool Memdump::CanPoke(uint32 paddr) const { - IODevice *dev = bus->FindDevice(paddr); - assert(dev); - - // -1 でチェック - uint64 r = dev->Poke8(paddr, -1); - return (bool)(r == 0); + return bus->Poke1(paddr, -1); } // コンソールに出力。 @@ -225,7 +197,7 @@ Memdump::CanPoke(uint32 paddr) const void Memdump::Print(FILE *cons, int row) { - DebuggerMemoryStream mem(md, saddr, access_mode, lookup_mode); + DebuggerMemoryStream mem(md, saddr); for (int y = 0; y < row; y++) { std::string addrbuf; @@ -279,7 +251,7 @@ Memdump::Print(FILE *cons, int row) break; } - case M68030Disasm: + case M680x0Disasm: case M88100Disasm: case HD64180Disasm: line->Exec(&mem); @@ -305,7 +277,7 @@ Memdump::Read(DebuggerMemoryStream& mem, std::vector vec(bytes); for (int i = 0; i < bytes; i++) { - vec[i] = mem.Read8(); + vec[i] = mem.Read1(); } return vec; @@ -442,18 +414,34 @@ Memdump::dtname[4] = { "(Next Long) ", }; +/*static*/ const char * const +Memdump::udtname[4] = { + "(Invalid) ", + "(Invalid) ", + "(Resident)", + "(Resident)", +}; + +/*static*/ const char * const +Memdump::pdtname[4] = { + "(Invalid) ", + "(Resident)", + "(Indirect)", + "(Resident)", +}; + // // メモリダンプモニタ // // コンストラクタ -MemdumpMonitor::MemdumpMonitor(int objid_, int monid_) +MemdumpMonitor::MemdumpMonitor(uint objid_, int monid_) : inherited(objid_) { - monitor.func = ToMonitorCallback(&MemdumpMonitor::MonitorUpdate); - monitor.SetSize(84, 16); - monitor.Regist(monid_); + monitor = gMonitorManager->Regist(monid_, this); + monitor->func = ToMonitorCallback(&MemdumpMonitor::MonitorUpdate); + monitor->SetSize(84, 16); } // デストラクタ @@ -465,7 +453,7 @@ MemdumpMonitor::~MemdumpMonitor() void MemdumpMonitor::MonitorUpdate(Monitor *, TextScreen& screen) { - DebuggerMemoryStream mem(md, saddr, access_mode, lookup_mode); + DebuggerMemoryStream mem(md, saddr); screen.Clear(); @@ -474,6 +462,8 @@ MemdumpMonitor::MonitorUpdate(Monitor *, case Word: case Long: case M68030PageShort: + case M68040TableDesc: + case M68040PageDesc: case M88200Page: MonitorUpdateMemdump(screen, mem); break; @@ -482,7 +472,7 @@ MemdumpMonitor::MonitorUpdate(Monitor *, screen.Puts(0, 0, "68030PageLong not supported"); break; - case M68030Disasm: + case M680x0Disasm: case M88100Disasm: case HD64180Disasm: MonitorUpdateDisasm(screen, mem); @@ -534,6 +524,12 @@ MemdumpMonitor::MonitorUpdateMemdump(Tex case M68030PageShort: Update68030PageShort(screen, dx, y, vec); break; + case M68040TableDesc: + Update68040TableDesc(screen, dx, y, vec); + break; + case M68040PageDesc: + Update68040PageDesc(screen, dx, y, vec); + break; case M88200Page: Update88200Page(screen, dx, y, vec); break; @@ -581,6 +577,77 @@ MemdumpMonitor::Update68030PageShort(Tex screen.Print(x + 30, y, attr, "DT=%d%s", dt, dtname[dt]); } +// (x, y) に 68040 テーブルディスクリプタのダンプを出力する。 +void +MemdumpMonitor::Update68040TableDesc(TextScreen& screen, int x, int y, + const std::vector& vec) +{ + // 2 3 4 5 6 7 + // 9012345678901234567890123456789012345678901234567890123 + // 00000000 $00000000 U W UDT=0(Invalid) + + uint32 data = 0; + for (auto b : vec) { + if (b < 0) { + screen.Puts(x, y, "BusErr"); + return; + } + data = (data << 8) | (uint8)b; + } + + screen.Puts(x, y, strhex(data).c_str()); + + bool resident = (data & 2); + TA attr = resident ? TA::Normal : TA::Disable; + + // 1段(23bit)、2段4K(24bit)、2段8K(25bit) はとりあえず区別しない。 + screen.Putc(x + 10, y, attr, '$'); + screen.Puts(x + 11, y, attr, strhex(data & 0xffff'ff80).c_str()); + screen.Putc(x + 20, y, attr, (data & 0x0008) ? 'U' : '-'); + screen.Putc(x + 22, y, attr, (data & 0x0004) ? 'W' : '-'); + uint32 udt = data & 3; + screen.Print(x + 24, y, attr, "UDT=%u%s", udt, udtname[udt]); +} + +// (x, y) に 68040 ページディスクリプタのダンプを出力する。 +void +MemdumpMonitor::Update68040PageDesc(TextScreen& screen, int x, int y, + const std::vector& vec) +{ + // 2 3 4 5 6 7 + // 9012345678901234567890123456789012345678901234567890123456 + // 00000000 $00000000 UR G U1 U0 S CMx M U W PDT=0(Resident) + + uint32 data = 0; + for (auto b : vec) { + if (b < 0) { + screen.Puts(x, y, "BusErr"); + return; + } + data = (data << 8) | (uint8)b; + } + + screen.Puts(x, y, strhex(data).c_str()); + + uint32 pdt = data & 3; + bool resident = (pdt != 0); + TA attr = resident ? TA::Normal : TA::Disable; + + // 4K/8K ページサイズはとりあえず区別しない。 + screen.Putc(x + 10, y, attr, '$'); + screen.Puts(x + 11, y, attr, strhex(data & 0xffff'f000).c_str()); + screen.Puts(x + 20, y, attr, (data & 0x0800) ? "UR" : "--"); + screen.Putc(x + 23, y, attr, (data & 0x0400) ? 'G' : '-'); + screen.Puts(x + 25, y, attr, (data & 0x0200) ? "U1" : "--"); + screen.Puts(x + 28, y, attr, (data & 0x0100) ? "U0" : "--"); + screen.Putc(x + 31, y, attr, (data & 0x0080) ? 'S' : '-'); + screen.Print(x + 33, y, attr, "CM%u", (data & 0x0060) >> 5); + screen.Putc(x + 37, y, attr, (data & 0x0010) ? 'M' : '-'); + screen.Putc(x + 39, y, attr, (data & 0x0008) ? 'U' : '-'); + screen.Putc(x + 41, y, attr, (data & 0x0004) ? 'W' : '-'); + screen.Print(x + 43, y, attr, "PDT=%u%s", pdt, pdtname[pdt]); +} + // (x, y) に 88200 ページディスクリプタのダンプを出力する。 void MemdumpMonitor::Update88200Page(TextScreen& screen, int x, int y, @@ -627,17 +694,18 @@ MemdumpMonitor::MonitorUpdateDisasm(Text int row = screen.GetRow(); // 逆アセンブラ用の次行アドレスバッファを必要ならリサイズ - if (row != nextaddr.size()) { - nextaddr.resize(row); + if ((row + 1) != nextaddr.size()) { + nextaddr.resize(row + 1); } + nextaddr[0] = mem.laddr.Addr(); for (int y = 0; y < row; y++) { std::string addrbuf; bool accessible; TA attr; // PC のいる行をボールドに - if (__predict_false((uint32)mem.laddr == md->GetPC())) { + if (__predict_false(mem.laddr.Addr() == md->GetPC())) { attr = TA::Em; } else { attr = TA::Normal; @@ -657,7 +725,7 @@ MemdumpMonitor::MonitorUpdateDisasm(Text // 次行の開始アドレスを覚えておく。 // 逆アセンブラで n 行下へ移動する時のため。 - nextaddr[y] = mem.laddr.GetAddr(); + nextaddr[y + 1] = mem.laddr.Addr(); } } @@ -670,17 +738,8 @@ MemdumpMonitor::GetLineOffset(int n) con return n * fixed; } else { // 可変長フォーマット - - // 引数 n を nextaddr[] のインデックス i に変換。 - // 0行下は先頭行。 - // 1行下なら2行目なので nextaddr は [0]、 - // 2行下なら3行目なので nextaddr は [1]。 - if (n == 0) { - return 0; - } - int i = n - 1; - if (0 <= i && i < nextaddr.size()) { - return nextaddr[i] - (uint32)saddr; + if (0 <= n && n < nextaddr.size()) { + return nextaddr[n] - nextaddr[0]; } else { // なければ仕方ないので適当に返す return n * inst_bytes; @@ -699,7 +758,7 @@ MemdumpMonitor::GetPageOffset(int n) con // 逆アセンブルでは実際にこの動作をすると連続性が失われて読みにくいので // 1行だぶらせることにする。 - int row = monitor.GetSize().height; + int row = monitor->GetSize().height; if (inst_bytes) { // 逆アセンブルの場合 if (n < 0) {