--- nono/vm/interrupt.cpp 2026/04/29 17:04:45 1.1 +++ nono/vm/interrupt.cpp 2026/04/29 17:05:06 1.1.1.5 @@ -38,11 +38,16 @@ std::unique_ptr gInterr // 仮想割り込みコントローラ (共通部) // -// コンストラクタ +// コンストラクタ(オブジェクト名指定あり) +InterruptDevice::InterruptDevice(const std::string& objname_) + : inherited(objname_) +{ +} + +// コンストラクタ(オブジェクト名指定なし) InterruptDevice::InterruptDevice() + : InterruptDevice("Interrupt") { - logname = "interrupt"; - devname = "Interrupt"; } // デストラクタ @@ -50,6 +55,47 @@ InterruptDevice::~InterruptDevice() { } +// リセット +void +InterruptDevice::ResetHard() +{ + intmap = IntmapSentinel; + memset(&counter, 0, sizeof(counter)); +} + +// 子デバイスが割り込み信号線をアサートした +void +InterruptDevice::AssertINT(Device *source) +{ + uint32 oldmap; + uint32 srcmap; + + oldmap = intmap; + srcmap = GetIntmap(source); + intmap |= srcmap; + + if ((oldmap ^ intmap) != 0) { + // 立ち上がりエッジでカウント + counter[__builtin_clz(srcmap)]++; + ChangeInterrupt(); + } +} + +// 子デバイスが割り込み信号線をネゲートした +void +InterruptDevice::NegateINT(Device *source) +{ + uint32 oldmap; + uint32 srcmap; + + oldmap = intmap; + srcmap = GetIntmap(source); + intmap &= ~srcmap; + + if ((oldmap ^ intmap) != 0) { + ChangeInterrupt(); + } +} // // 仮想割り込みコントローラ (m680x0 共通部) @@ -76,51 +122,20 @@ M680x0Interrupt::~M680x0Interrupt() void M680x0Interrupt::ResetHard() { + inherited::ResetHard(); ipl = 0; - intmap = 0x00000001; - memset(&counter, 0, sizeof(counter)); -} - -// 子デバイスが割り込み信号線をアサートした (m680x0 共通) -void -M680x0Interrupt::AssertINT(Device *source) -{ - uint32 oldmap; - uint32 srcmap; - int newipl; - - oldmap = intmap; - srcmap = GetIntmap(source); - intmap |= srcmap; - - if ((oldmap ^ intmap) != 0) { - // 立ち上がりエッジでカウント - counter[__builtin_clz(srcmap)]++; - } - - newipl = (uint)(31 - __builtin_clz(intmap)) / 4; - - // アサートによって割り込みレベルが上がったら、新しいレベルを通知 - // (現在通知中より低い割り込みは受け付けただけでここで保留) - if (newipl > ipl) { - ipl = newipl; - gMPU->Interrupt(ipl); - } } -// 小デバイスが割り込み信号線をネゲートした (m680x0 共通) void -M680x0Interrupt::NegateINT(Device *source) +M680x0Interrupt::ChangeInterrupt() { int newipl; - intmap &= ~GetIntmap(source); - // intmap の最下位ビットは常に立ててあり intmap は 0 にならない + // intmap の最下位ビットは常に立ててあるので 0 にならない newipl = (uint)(31 - __builtin_clz(intmap)) / 4; - // ネゲートによって割り込みレベルが下がったら、新しいレベルを通知 - // (以前に保留されていた低いレベルがあればここで見えるようになる) - if (newipl < ipl) { + // 割り込みレベルが変わったら、新しいレベルを通知 + if (newipl != ipl) { ipl = newipl; gMPU->Interrupt(ipl); } @@ -134,7 +149,9 @@ M680x0Interrupt::NegateINT(Device *sourc // コンストラクタ X68030Interrupt::X68030Interrupt() { - monitor_size = nnSize(24, 6); + monitor.func = (MonitorCallback_t)&X68030Interrupt::MonitorUpdate; + monitor.SetSize(25, 11); + monitor.Regist(ID_MONITOR_INTERRUPT); } // デストラクタ @@ -189,7 +206,7 @@ X68030Interrupt::InterruptAcknowledge(in } void -X68030Interrupt::MonitorUpdate(TextScreen& monitor) +X68030Interrupt::MonitorUpdate(Monitor *, TextScreen& screen) { int y; struct { @@ -206,23 +223,25 @@ X68030Interrupt::MonitorUpdate(TextScree // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい uint intr_level = gMPU680x0->GetCPU()->reg.intr_level; - monitor.Clear(); + screen.Clear(); y = 0; - monitor.Print(0, y++, "Lv Device Count IM=%d", intr_level); + screen.Print(0, y++, "Lv Device Count IM=%d", intr_level); for (int i = 0; i < countof(table); i++) { uint32 map = table[i].map; int clz = __builtin_clz(map); int lv = (31 - clz) / 4; - monitor.Print(0, y, "%d", lv); - monitor.Print(2, y, TA::OnOff(intmap & map), "%s", table[i].name); - monitor.Print(8, y, "%10u", counter[clz]); + screen.Print(0, y, "%d", lv); + screen.Print(2, y, TA::OnOff(intmap & map), "%s", table[i].name); + screen.Print(8, y, "%11" PRIu64, counter[clz]); if (lv <= intr_level) { - monitor.Puts(20, y, "Mask"); + screen.Puts(21, y, "Mask"); } y++; } - // XXX PEDEC 分もここに表示したい + + // PEDEC 分も一緒に表示したい + gPEDEC->MonitorUpdate(screen, intr_level, y); } // @@ -232,7 +251,9 @@ X68030Interrupt::MonitorUpdate(TextScree // コンストラクタ LunaInterrupt::LunaInterrupt() { - monitor_size = nnSize(24, 5); + monitor.func = (MonitorCallback_t)&LunaInterrupt::MonitorUpdate; + monitor.SetSize(25, 5); + monitor.Regist(ID_MONITOR_INTERRUPT); } // デストラクタ @@ -269,7 +290,7 @@ LunaInterrupt::InterruptAcknowledge(int } void -LunaInterrupt::MonitorUpdate(TextScreen& monitor) +LunaInterrupt::MonitorUpdate(Monitor *, TextScreen& screen) { int y; struct { @@ -285,19 +306,19 @@ LunaInterrupt::MonitorUpdate(TextScreen& // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい uint intr_level = gMPU680x0->GetCPU()->reg.intr_level; - monitor.Clear(); + screen.Clear(); y = 0; - monitor.Print(0, y++, "Lv Device Count IM=%d", intr_level); + screen.Print(0, y++, "Lv Device Count IM=%d", intr_level); for (int i = 0; i < countof(table); i++) { uint32 map = table[i].map; int clz = __builtin_clz(map); int lv = (31 - clz) / 4; - monitor.Print(0, y, "%d", lv); - monitor.Print(2, y, TA::OnOff(intmap & map), "%s", table[i].name); - monitor.Print(8, y, "%10u", counter[clz]); + screen.Print(0, y, "%d", lv); + screen.Print(2, y, TA::OnOff(intmap & map), "%s", table[i].name); + screen.Print(8, y, "%11" PRIu64, counter[clz]); if (lv <= intr_level) { - monitor.Puts(20, y, "Mask"); + screen.Puts(21, y, "Mask"); } y++; }