--- nono/vm/mpu88xx0.cpp 2026/04/29 17:05:43 1.1.1.18 +++ nono/vm/mpu88xx0.cpp 2026/04/29 17:05:50 1.1.1.19 @@ -11,6 +11,7 @@ #include "mpu88xx0.h" #include "config.h" #include "debugger.h" +#include "event.h" #include "m88100disasm.h" #include "scheduler.h" @@ -135,9 +136,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 は、電源オン時に最低これだけアサートしなければならないという値 @@ -147,19 +147,17 @@ MPU88xx0Device::ResetHard(bool poweron) // リセット例外が起動するまでに時間がかかるというところを都合よく真似て // おく。 - exec_event.func = ToEventCallback(&MPU88xx0Device::ResetCallback); - exec_event.time = (8 + 256) * clock_nsec; - exec_event.SetName(GetName() + " Reset"); + exec_event->func = ToEventCallback(&MPU88xx0Device::ResetCallback); + exec_event->time = (8 + 256) * clock_nsec; + 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; @@ -170,8 +168,9 @@ MPU88xx0Device::ResetCallback(Event& ev) // デバッガに通知 (例外ブレーク用) debugger->NotifyExceptionMain(0); - // 内部の割り込み状態をクリア - intr_pending = 0; + // 内部の例外状態をクリア + resetting = false; + excep_pending = 0; ChangeState(CPU_STATE_NORMAL); // 実際どこかは分からんけど PSR 設定の前にリセットしておきたい @@ -218,15 +217,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->func = exec_normal; + exec_event->time = cycle * clock_nsec; + exec_event->SetName(GetName() + " Execute"); scheduler->StartEvent(exec_event); } // トレース実行のコールバック void -MPU88xx0Device::ExecTrace(Event& ev) +MPU88xx0Device::ExecTrace(Event *ev) { debugger->ExecMain(); ExecNormal(ev); @@ -241,7 +240,7 @@ MPU88xx0Device::SetTrace(bool enable) } else { exec_normal = ToEventCallback(&MPU88xx0Device::ExecNormal); } - exec_event.func = exec_normal; + exec_event->func = exec_normal; } // アクセス中の論理アドレスを取得 @@ -267,14 +266,42 @@ void MPU88xx0Device::Interrupt(int level) { // level は 0 か 1。 - intr_pending = level; + intr_asserted = level; - if (intr_pending && IsIntrEnable() && (cpu_state == CPU_STATE_STOP)) { - // 割り込みを受け付けたら STOP 解除。 - ChangeState(CPU_STATE_NORMAL); + if (intr_asserted && IsIntrEnable()) { + OuterException(EXCPRI_INTERRUPT); + + 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; + } } } +void +MPU88xx0Device::SetPSR() +{ + 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 エミュレーションのコールバックを指定 void MPU88xx0Device::SetFLineCallback(bool (*callback)(MPU88xx0Device *, void *), @@ -406,23 +433,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);