--- nono/vm/sysctlr.h 2026/04/29 17:04:39 1.1.1.2 +++ nono/vm/sysctlr.h 2026/04/29 17:04:45 1.1.1.3 @@ -9,14 +9,29 @@ #pragma once #include "device.h" +#include "interrupt.h" class SysCtlrDevice - : public IODevice + : public InterruptDevice { - using inherited = IODevice; + using inherited = InterruptDevice; + + // 割り込みマップ 76543210 + static const uint32 IntmapNMI = 0x80000000; + static const uint32 IntmapSysClk = 0x08000000; + static const uint32 IntmapSIO = 0x00800000; + static const uint32 IntmapLance = 0x00080000; + static const uint32 IntmapSPC = 0x00008000; + static const uint32 IntmapSoft3 = 0x00000080; + static const uint32 IntmapSoft2 = 0x00000040; + static const uint32 IntmapSoft1 = 0x00000020; + static const uint32 IntmapSoft0 = 0x00000010; + public: SysCtlrDevice(); - ~SysCtlrDevice() override; + virtual ~SysCtlrDevice() override; + + void ResetHard() override; void MonitorUpdate(TextScreen&) override; @@ -24,12 +39,42 @@ class SysCtlrDevice uint64 Write32(uint32 addr, uint32 data) override; uint64 Peek8(uint32 addr) override; - uint8 GetIntMask(int id) const { return intmask[id]; } - void TellIntLevel(int id, int level) { intlevel[id] |= level; } + // InterruptDevice インタフェース + void AssertINT(Device *soruce) override; + void NegateINT(Device *source) override; + int InterruptAcknowledge(int lv) override; + private: - uint8 intmask[4] {}; - // 発生した割り込みのレベルビットマップ - uint8 intlevel[4] {}; + // デバイスから Intmap 値を引く + uint32 GetIntmap(Device *source) const; + + // 割り込み状態を更新 + void ChangeInterrupt(); + + // マスク設定レジスタの書き込み値から内部用マスクを作成 + static uint32 MakeIntMask(uint32 data, int n); + + // 割り込みマップ (M680x0Interrupt::intmap と同じ構造) + uint32 intmap {}; + + // 割り込み回数 (アサートのエッジでカウントアップする) + // [0] が Intmap の bit31 割り込みのカウント。 + // [27] が Intmap の bit 4 割り込みのカウント。 + uint32 counter[28] {}; + + // CPU ごとのパラメータ + struct { + // 割り込みマスク (設定値) + // 書き込み時の値をそのまま保持しておくので bit31-26 のみ有効。他は %0。 + uint32 maskval; + + // 内部用 intmap に対する割り込みマスク + uint32 intmask; + + // 現在の最高位の割り込みレベル + int ipl; + } cpu[4] {}; }; -extern std::unique_ptr gSysCtlr; +// グローバルインスタンスはここではなく gInterrupt を使用する +// (LUNA88K ではこれがメインの割り込みコントローラなので)