--- nono/vm/mpu88xx0.cpp 2026/04/29 17:05:29 1.1.1.15 +++ nono/vm/mpu88xx0.cpp 2026/04/29 17:06:00 1.1.1.20 @@ -11,9 +11,9 @@ #include "mpu88xx0.h" #include "config.h" #include "debugger.h" +#include "event.h" #include "m88100disasm.h" #include "scheduler.h" -#include "syncer.h" // コンストラクタ MPU88xx0Device::MPU88xx0Device() @@ -53,9 +53,9 @@ MPU88xx0Device::MPU88xx0Device() excep_counter.resize(512); // レジスタモニター - monitor.func = ToMonitorCallback(&MPU88xx0Device::MonitorUpdate); - monitor.SetSize(79, 25); - monitor.Regist(ID_MONITOR_MPUREG); + monitor = gMonitorManager->Regist(ID_MONITOR_MPUREG, this); + monitor->SetCallback(&MPU88xx0Device::MonitorScreen); + monitor->SetSize(79, 25); } // デストラクタ @@ -71,13 +71,9 @@ MPU88xx0Device::Init() return false; } - debugger = GetDebugger(); + pseudo_stop_enable = gConfig->Find("mpu-pseudo-stop").AsBool(); - const ConfigItem& item_stop = gConfig->Find("mpu-pseudo-stop"); - pseudo_stop_enable = (bool)item_stop.AsInt(); - - const ConfigItem& item_altname = gConfig->Find(".m88k-altname"); - m88100disasm::use_altname = item_altname.AsInt(); + m88100disasm::use_altname = gConfig->Find(".m88k-altname").AsBool(); // MPU のバージョン。 const ConfigItem& item_88100ver = gConfig->Find("m88100-version"); @@ -138,9 +134,8 @@ MPU88xx0Device::ResetHard(bool poweron) reg.xip = 0; } - // intr_pending は m88100core.cpp の ExecNormal() 中のコメント参照。 resetting = true; - intr_pending = 1; + Exception(EXCPRI_RESET); // リセット例外を 8+256 クロック後に起こす。 // 8+256 は、電源オン時に最低これだけアサートしなければならないという値 @@ -150,31 +145,29 @@ MPU88xx0Device::ResetHard(bool poweron) // リセット例外が起動するまでに時間がかかるというところを都合よく真似て // おく。 - exec_event.func = ToEventCallback(&MPU88xx0Device::ResetCallback); - exec_event.time = (8 + 256) * clock_nsec; - exec_event.SetName(GetName() + " Reset"); + exec_event->SetCallback(&MPU88xx0Device::ResetCallback); + exec_event->time = (8 + 256) * clock_tsec; + exec_event->SetName(GetName() + " Reset"); scheduler->RestartEvent(exec_event); } // リセット例外コールバック。 // MPU リセットから規定時間後に呼ばれる。 void -MPU88xx0Device::ResetCallback(Event& ev) +MPU88xx0Device::ResetCallback(Event *ev) { - resetting = false; - // リセット例外を実行 uint64 cycle_start = used_cycle; // 例外履歴に記録 (例外発生はブランチ履歴にも記録) // リセット例外も発生時の XIP を記録する。(LUNA-88K の PROM 1.20) + last_vector = 0; exhist.AddEntry(reg.xip | 1, 0, 0xfc000000 | 0); brhist.AddEntry(reg.xip | 1, 0, 0xfc000000 | 0); - // デバッガに通知 (例外ブレーク用) - debugger->NotifyExceptionMain(0); - // 内部の割り込み状態をクリア - intr_pending = 0; + // 内部の例外状態をクリア + resetting = false; + excep_pending = 0; ChangeState(CPU_STATE_NORMAL); // 実際どこかは分からんけど PSR 設定の前にリセットしておきたい @@ -221,15 +214,15 @@ MPU88xx0Device::ResetCallback(Event& ev) // 以降は通常走行 int cycle = used_cycle - cycle_start; - exec_event.func = exec_normal; - exec_event.time = cycle * clock_nsec; - exec_event.SetName(GetName() + " Execute"); + exec_event->SetCallback(exec_normal); + exec_event->time = cycle * clock_tsec; + exec_event->SetName(GetName() + " Execute"); scheduler->StartEvent(exec_event); } // トレース実行のコールバック void -MPU88xx0Device::ExecTrace(Event& ev) +MPU88xx0Device::ExecTrace(Event *ev) { debugger->ExecMain(); ExecNormal(ev); @@ -244,54 +237,48 @@ MPU88xx0Device::SetTrace(bool enable) } else { exec_normal = ToEventCallback(&MPU88xx0Device::ExecNormal); } - exec_event.func = exec_normal; + exec_event->SetCallback(exec_normal); } +// Interrupt void -MPU88xx0Device::ChangeState(uint32 new_state) +MPU88xx0Device::Interrupt(int level) { - // new_state (CPU_STATE_*) と - // RequestCPUMode() の引数 Syncer::SCHED_CPU_* は - // 実は同じ値なのでそのまま渡してよいことにする。 - static_assert(CPU_STATE_NORMAL == Syncer::SCHED_CPU_NORMAL, ""); - static_assert(CPU_STATE_STOP == Syncer::SCHED_CPU_STOP, ""); - - if (cpu_state != new_state) { - cpu_state = new_state; - // スケジューラに通知 - syncer->RequestCPUMode(new_state); - } -} + // level は 0 か 1。 + intr_asserted = level; -// アクセス中の論理アドレスを取得 -uint32 -MPU88xx0Device::GetLaddr() const -{ - m88200 *m = m88200::GetBusMaster(); - assert(m); - return m->GetLaddr(); -} + if (intr_asserted && IsIntrEnable()) { + OuterException(EXCPRI_INTERRUPT); -// アクセス中の物理アドレスを取得 -uint32 -MPU88xx0Device::GetPaddr() const -{ - m88200 *m = m88200::GetBusMaster(); - assert(m); - return m->GetPaddr(); + if (cpu_state == CPU_STATE_STOP) { + // 割り込みを受け付けたら STOP 解除。 + ChangeState(CPU_STATE_NORMAL); + } + } else { + excep_pending &= ~EXCPRI_INTERRUPT; + // INTERRUPT を下げたことで全員いなくなれば OUTER を下げる。 + if ((excep_pending & EXCPRI_OUTER_MASK) == 0) { + excep_pending &= ~EXCPRI_OUTER; + } + } } -// Interrupt void -MPU88xx0Device::Interrupt(int level) +MPU88xx0Device::SetPSR() { - // level は 0 か 1。 - intr_pending = level; - - if (intr_pending && IsIntrEnable() && (cpu_state == CPU_STATE_STOP)) { - // 割り込みを受け付けたら STOP 解除。 - ChangeState(CPU_STATE_NORMAL); + if (intr_asserted && IsIntrEnable()) { + OuterException(EXCPRI_INTERRUPT); + } else { + excep_pending &= ~EXCPRI_INTERRUPT; + // INTERRUPT を下げたことで全員いなくなれば OUTER を下げる。 + if ((excep_pending & EXCPRI_OUTER_MASK) == 0) { + excep_pending &= ~EXCPRI_OUTER; + } } + + // CMMU に S/U 信号を出す + cmmu[0]->SetSuper(IsSuper()); + cmmu[1]->SetSuper(IsSuper()); } // DOS call エミュレーションのコールバックを指定 @@ -307,7 +294,7 @@ MPU88xx0Device::SetFLineCallback(bool (* // モニター更新 void -MPU88xx0Device::MonitorUpdate(Monitor *, TextScreen& screen) +MPU88xx0Device::MonitorScreen(Monitor *, TextScreen& screen) { m88100reg tmp; int x; @@ -425,23 +412,49 @@ MPU88xx0Device::MonitorUpdate(Monitor *, screen.Puts(x + 41, y, ")"); y++; + char tsiz[4] = { 's', 'd', '2', '3' }; screen.Print(0, y++, - "fppt(fcr5): %08x(OpCode=%%%c%c%c%c%c T1=%u T2=%u TD=%u Dest=r%u)", + "fppt(fcr5): %08x(OpCode=%%%c%c%c%c%c T1=%c T2=%c TD=%c Dest=r%u)", tmp.fppt, ((tmp.fppt >> 15) & 1) + '0', ((tmp.fppt >> 14) & 1) + '0', ((tmp.fppt >> 13) & 1) + '0', ((tmp.fppt >> 12) & 1) + '0', ((tmp.fppt >> 11) & 1) + '0', - ((tmp.fppt >> 9) & 3), - ((tmp.fppt >> 7) & 3), - ((tmp.fppt >> 5) & 3), + tsiz[(tmp.fppt >> 9) & 3], + tsiz[(tmp.fppt >> 7) & 3], + tsiz[(tmp.fppt >> 5) & 3], (tmp.fppt & M88100::FPPT_DEST)); - screen.Print(0, y++, "fphs1(fcr1)/fpls1(fcr2): %08x'%08x", - tmp.fphs1, tmp.fpls1); - screen.Print(0, y++, "fphs2(fcr3)/fpls2(fcr4): %08x'%08x", - tmp.fphs2, tmp.fpls2); + for (uint i = 0; i < 2; i++) { + uint32 hs; + uint32 ls; + bool isfloat; + if (i == 0) { + hs = tmp.fphs1; + ls = tmp.fpls1; + isfloat = (tmp.fppt & 0x600) == 0; + } else { + hs = tmp.fphs2; + ls = tmp.fpls2; + isfloat = (tmp.fppt & 0x180) == 0; + } + uint n = i * 2; + screen.Print(0, y, "fphs%u(fcr%u)/fpls%u(fcr%u): %08x'%08x =", + (i + 1), (n + 1), (i + 1), (n + 2), hs, ls); + int32 e = ((int32)(hs << 1)) >> 21; + screen.Print(45, y, "%c0.%05x'", + ((hs & 0x80000000) ? '-' : '+'), + (hs & 0x000f'ffff)); + if (isfloat) { + screen.Print(45 + 9, y, "%1x", (ls >> 28) & 0xf); + screen.Print(45 + 10, y, TA::Disable, "%07x", (ls & 0x0fff'ffff)); + screen.Print(45 + 18, y, "e%+d", e); + } else { + screen.Print(45 + 9, y, "%08x e%+d", ls, e); + } + y++; + } screen.Print(0, y, "fprh(fcr6) /fprl(fcr7): %08x'%08x(", tmp.fprh, tmp.fprl);