--- nono/vm/interrupt.h 2026/04/29 17:05:20 1.1.1.6 +++ nono/vm/interrupt.h 2026/04/29 17:05:28 1.1.1.8 @@ -13,23 +13,22 @@ #include "device.h" #include "monitor.h" #include +#include // XP からの割り込み用。 // これだけ1デバイスで2本あるので、仕方なく識別子を用意。 -#define DEVICE_XPINT_HIGH ((Device *)(intptr_t)1) -#define DEVICE_XPINT_LOW ((Device *)(intptr_t)2) +#define DEVICE_XPINT_HIGH (reinterpret_cast((intptr_t)1)) +#define DEVICE_XPINT_LOW (reinterpret_cast((intptr_t)2)) class DMACDevice; -class LanceDevice; +class GFPICDevice; class MFPDevice; -class NewsCtlrDevice; +class MPU680x0Device; class NMIDevice; class PEDECDevice; class RTL8019ASDevice; class SCCDevice; -class SIODevice; class SPCDevice; -class SysClkDevice; // 割り込みを受け付けるデバイス。 // これ自体は IODevice である必要はないが、PEDEC や SysCtlr がこれを @@ -37,15 +36,26 @@ class SysClkDevice; class InterruptDevice : public IODevice { using inherited = IODevice; + + // intmap と名前の紐付け + struct mapname { + uint32 intmap {}; + const char *name {}; + Device *source {}; + + mapname(uint32 intmap_, const char *name_, Device *source_) { + intmap = intmap_; + name = name_; + source = source_; + } + }; + public: InterruptDevice(); - InterruptDevice(int objid_); - virtual ~InterruptDevice() override; + InterruptDevice(uint objid_); + ~InterruptDevice() override; - // 継承クラスの ResetHard() は保持している割り込み情報を全てキャンセルする。 - // 各子デバイスはその ResetHard() で NegateINT() を明示的に呼び出して - // 割り込みをキャンセルする必要はなく、もし自身で独自に割り込み信号線の - // 状態に関する変数を持っていればそれをクリアするだけでよい。 + // リセットで割り込みを下げるのは各割り込み送出デバイスの責任。 void ResetHard(bool poweron) override; // AssertINT()、NegateINT()、ChangeINT() の呼び出し側は、 @@ -68,7 +78,7 @@ class InterruptDevice : public IODevice } // MPU からの割り込みアクノリッジに応答する - virtual int InterruptAcknowledge(int lv) = 0; + virtual busdata InterruptAcknowledge(int lv) = 0; // 割り込み信号線の状態を取得する bool GetINT(const Device *source) const; @@ -102,37 +112,62 @@ class InterruptDevice : public IODevice // して保持しつつ、アサートされている信号線のうち最もレベルの高いものは // 以下だけで求めることが出来る。 // - // ipl = (31 - __builtin_clz(intmap)) / 4; + // ipl = (31 - __builtin_clz(intmap_status)) / 4; // // LUNA-88K の外部割り込みコントローラであるシステムコントローラも // 概ねこれに近いので、sysctlr もこの構造を使う。 // // PEDEC は 7レベル分けする必要ないので、適当に割り当ててある。 + // + // Goldfish PIC は 7レベル分け不要なのと 32ビット必要そうなので、 + // 番兵を使わず 32ビット全域を使う。 + // また元の仕様が LSB 側から数えるスタイルなのでここでもそれに従う。 static const uint32 IntmapSentinel = 0x00000001; + // 割り込みソースを登録する。 + void RegistINT(uint32 intmap_, const char *name_, Device *source_); + // デバイスから Intmap 値を引く。 - virtual uint32 GetIntmap(const Device *source) const = 0; + uint32 GetIntmap(const Device *source) const; + + // Intmap 値から名前を引く。 + const char *GetIntName(uint32 intmap_) const; + + // 割り込みソース一覧 (概ね使用頻度の高い順) + std::vector intmap_list {}; + + // モニタでの表示順 (概ね優先度の高い順) + std::vector disp_list {}; + + // 割り込みソースが存在するところは %1 + uint32 intmap_avail {}; + + // 割り込み状態 (各 %1 ならアサート) + uint32 intmap_status {}; - // 割り込みマップ - uint32 intmap {}; + // (必要なら) 割り込みマスク (各 %1 なら有効) + // 割り込みマスク機能を持ってない人は使わなくてもよい。 + uint32 intmap_enable {}; // 割り込み回数 (アサートのエッジでカウントアップする) // [0] が Intmap の bit31 割り込みのカウント。 // [27] が Intmap の bit 4 割り込みのカウント。 - uint64 counter[28] {}; + uint64 counter[32] {}; }; // m680x0 仮想割り込みコントローラ (共通部) class M680x0Interrupt : public InterruptDevice { using inherited = InterruptDevice; + public: - static const int AutoVector = -1; // オートベクタ + // 割り込みアクノリッジの特殊値。 + static const uint32 AutoVector = -1; // オートベクタ要求 public: M680x0Interrupt(); - virtual ~M680x0Interrupt() override; + ~M680x0Interrupt() override; bool Init() override; void ResetHard(bool poweron) override; @@ -142,6 +177,8 @@ class M680x0Interrupt : public Interrupt // 現在の割り込みレベル int ipl {}; + + MPU680x0Device *mpu680x0 {}; }; // X68k 仮想割り込みコントローラ @@ -174,14 +211,12 @@ class X68030Interrupt : public M680x0Int public: X68030Interrupt(); - virtual ~X68030Interrupt() override; + ~X68030Interrupt() override; bool Init() override; - int InterruptAcknowledge(int lv) override; + busdata InterruptAcknowledge(int lv) override; private: - uint32 GetIntmap(const Device *soruce) const override; - DECLARE_MONITOR_CALLBACK(MonitorUpdate); DMACDevice *dmac {}; @@ -220,22 +255,14 @@ class LunaInterrupt : public M680x0Inter public: LunaInterrupt(); - virtual ~LunaInterrupt() override; + ~LunaInterrupt() override; bool Init() override; - int InterruptAcknowledge(int lv) override; + busdata InterruptAcknowledge(int lv) override; private: - uint32 GetIntmap(const Device *source) const override; - DECLARE_MONITOR_CALLBACK(MonitorUpdate); - LanceDevice *lance {}; - NMIDevice *nmi {}; - SIODevice *sio {}; - SPCDevice *spc {}; - SysClkDevice *sysclk {}; - Monitor monitor { this }; }; @@ -263,25 +290,62 @@ class NewsInterrupt : public M680x0Inter public: NewsInterrupt(); - virtual ~NewsInterrupt() override; + ~NewsInterrupt() override; bool Init() override; - int InterruptAcknowledge(int lv) override; + busdata InterruptAcknowledge(int lv) override; // 割り込みステータスを返す (NewsCtlr から呼ばれる) uint8 PeekStatus() const; private: - uint32 GetIntmap(const Device *source) const override; - DECLARE_MONITOR_CALLBACK(MonitorUpdate); - LanceDevice *lance {}; - NewsCtlrDevice *newsctlr {}; SCCDevice *scc {}; Monitor monitor { this }; }; + +// virt-m68k 仮想割り込みコントローラ +// +// Level +// 7 +// 6 GFPIC6 +// 5 GFPIC5 +// 4 GFPIC4 +// 3 GFPIC3 +// 2 GFPIC2 +// 1 GFPIC1 +// +class Virt68kInterrupt : public M680x0Interrupt +{ + using inherited = M680x0Interrupt; + + // 割り込みマップ 76543210 + static const uint32 IntmapGFPIC6 = 0x08000000; + static const uint32 IntmapGFPIC5 = 0x00800000; + static const uint32 IntmapGFPIC4 = 0x00080000; + static const uint32 IntmapGFPIC3 = 0x00008000; + static const uint32 IntmapGFPIC2 = 0x00000800; + static const uint32 IntmapGFPIC1 = 0x00000080; + + public: + Virt68kInterrupt(); + ~Virt68kInterrupt() override; + + bool Init() override; + busdata InterruptAcknowledge(int lv) override; + + // モニタを1行増やす。割り込みソース登録ごとに GFPIC から呼ばれる。 + void IncMonitorHeight(); + + private: + DECLARE_MONITOR_CALLBACK(MonitorUpdate); + + std::array gfpic {}; + + Monitor monitor { this }; +}; // LUNA-88K は sysctlr.cpp 参照。