--- nono/vm/pedec.cpp 2026/04/29 17:04:45 1.1 +++ nono/vm/pedec.cpp 2026/04/29 17:05:25 1.1.1.9 @@ -4,80 +4,147 @@ // Licensed under nono-license.txt // +// +// PEDEC +// + +// IODevice +// | +// +-- InterruptDevice (割り込みコントローラの共通部) +// | +// +-- M680x0Interrupt (m68k 割り込みコントローラの共通部) +// | | +// | +-- X68030Interrupt (X68030 の割り込みコントローラ) +// | +-- LunaInterrupt (LUNA-I の割り込みコントローラ) +// | +// | +-------------+ +// +--| PEDECDevice | (X68030 の Lv1 担当コントローラ) +// | +-------------+ +// | +// +-- SysCtlrDevice (LUNA-88K の割り込みコントローラ) + #include "pedec.h" #include "fdc.h" +#include "fdd.h" #include "spc.h" -std::unique_ptr gPEDEC; - +// コンストラクタ PEDECDevice::PEDECDevice() + : inherited(OBJ_PEDEC) { - logname = "pedec"; - devname = "PEDEC"; - devaddr = baseaddr; - devlen = 0x2000; } +// デストラクタ PEDECDevice::~PEDECDevice() { } +// 初期化 +bool +PEDECDevice::Init() +{ + if (inherited::Init() == false) { + return false; + } + + interrupt = GetInterruptDevice(); + + // 検索順 + RegistINT(IntmapSPC, "SPC", GetSPCDevice()); + RegistINT(IntmapFDC, "FDC", GetFDCDevice()); + RegistINT(IntmapHDD, "HDD", NULL); + RegistINT(IntmapPRT, "PRT", NULL); + // FDD は4本を共有しているのでいろいろ特別扱い。 + RegistINT(IntmapFDD0, "FDD0", gMainApp.FindObject(OBJ_FDD(0))); + RegistINT(IntmapFDD1, "FDD1", gMainApp.FindObject(OBJ_FDD(1))); + RegistINT(IntmapFDD2, "FDD2", gMainApp.FindObject(OBJ_FDD(2))); + RegistINT(IntmapFDD3, "FDD3", gMainApp.FindObject(OBJ_FDD(3))); + // 名前表示用 + RegistINT(IntmapFDD, "FDD", NULL); + + // 表示順 + disp_list = { + IntmapSPC, + IntmapFDC, + IntmapFDD, + IntmapHDD, + IntmapPRT, + }; + + return true; +} + +// リセット void -PEDECDevice::ResetHard() +PEDECDevice::ResetHard(bool poweron) { - int_asserted = 0; - int_enabled = IntmapSPC; + inherited::ResetHard(poweron); + + intmap_enable = IntmapSPC; + ChangeInterrupt(); + // XXX vector } -uint64 -PEDECDevice::Read(uint32 addr) +busdata +PEDECDevice::Read(uint32 offset) { - switch (addr) { + busdata data; + + switch (offset) { case 0: // $E9C001 割り込みステータス - return GetStat(); + data = GetStat(); + break; case 1: // $E9C003 割り込みベクタ // 書き込み専用 - return 0xff; + data = 0xff; + break; default: - return 0xff; + data = 0xff; + break; } + + // XXX wait? + return data; } -uint64 -PEDECDevice::Write(uint32 addr, uint32 data) +busdata +PEDECDevice::Write(uint32 offset, uint32 data) { - switch (addr) { + switch (offset) { case 0: // $E9C001 割り込みマスク - int_enabled = IntmapSPC; - int_enabled |= (data & 0x08) ? IntmapHDD : 0; - int_enabled |= (data & 0x04) ? IntmapFDC : 0; - int_enabled |= (data & 0x02) ? IntmapFDD : 0; - int_enabled |= (data & 0x01) ? IntmapPRT : 0; - - putlog(1, "割り込みマスク設定 HDD=%d FDC=%d FDD=%d PRT=%d", - ((int_enabled & IntmapHDD) ? 1 : 0), - ((int_enabled & IntmapFDC) ? 1 : 0), - ((int_enabled & IntmapFDD) ? 1 : 0), - ((int_enabled & IntmapPRT) ? 1 : 0)); - return 0; + intmap_enable = IntmapSPC; + intmap_enable |= (data & 0x08) ? IntmapHDD : 0; + intmap_enable |= (data & 0x04) ? IntmapFDC : 0; + intmap_enable |= (data & 0x02) ? IntmapFDD : 0; + intmap_enable |= (data & 0x01) ? IntmapPRT : 0; + + putlog(1, "Set Interrupt Mask HDD=%d FDC=%d FDD=%d PRT=%d", + ((intmap_enable & IntmapHDD) ? 1 : 0), + ((intmap_enable & IntmapFDC) ? 1 : 0), + ((intmap_enable & IntmapFDD) ? 1 : 0), + ((intmap_enable & IntmapPRT) ? 1 : 0)); + break; case 1: // $E9C003 割り込みベクタ vector = data & 0xfc; - putlog(1, "割り込みベクタ設定 $%02x", vector); - return 0; + putlog(1, "Set Interrupt Vector $%02x", vector); + break; default: - return 0; + break; } + + // XXX wait? + return 0; } -uint64 -PEDECDevice::Peek(uint32 addr) +busdata +PEDECDevice::Peek(uint32 offset) { - switch (addr) { + switch (offset) { case 0: return GetStat(); @@ -90,74 +157,64 @@ PEDECDevice::Peek(uint32 addr) } } +void +PEDECDevice::MonitorUpdate(TextScreen& screen, uint intr_level, int y) +{ + for (uint32 map : disp_list) { + int clz = __builtin_clz(map); + screen.Puts(4, y, TA::OnOff(intmap_status & map), GetIntName(map)); + if (intr_level >= 1 || (intmap_enable & map) == 0) { + screen.Puts(11, y, "Mask"); + } + uint64 cnt = counter[clz]; + if (__predict_false(map == IntmapFDD)) { + // FDD は4つの和 + cnt += counter[clz + 1] + counter[clz + 2] + counter[clz + 3]; + } + screen.Print(15, y, "%26s", format_number(cnt).c_str()); + y++; + } +} + // 割り込みステータスレジスタの値を取得。 // (Peek からも呼ばれるので副作用を持たせてはいけない) uint32 PEDECDevice::GetStat() const { uint32 data = 0; - data |= (int_asserted & IntmapFDC) ? 0x80 : 0; - data |= (int_asserted & IntmapFDD) ? 0x40 : 0; - data |= (int_asserted & IntmapPRT) ? 0x20 : 0; - data |= (int_asserted & IntmapHDD) ? 0x10 : 0; - data |= (int_enabled & IntmapHDD) ? 0x08 : 0; - data |= (int_enabled & IntmapFDC) ? 0x04 : 0; - data |= (int_enabled & IntmapFDD) ? 0x02 : 0; - data |= (int_enabled & IntmapPRT) ? 0x01 : 0; + data |= (intmap_status & IntmapFDC) ? 0x80 : 0; + data |= (intmap_status & IntmapFDD) ? 0x40 : 0; + data |= (intmap_status & IntmapPRT) ? 0x20 : 0; + data |= (intmap_status & IntmapHDD) ? 0x10 : 0; + data |= (intmap_enable & IntmapHDD) ? 0x08 : 0; + data |= (intmap_enable & IntmapFDC) ? 0x04 : 0; + data |= (intmap_enable & IntmapFDD) ? 0x02 : 0; + data |= (intmap_enable & IntmapPRT) ? 0x01 : 0; return data; } -// 子デバイスが割り込み信号線をアサートした +// 割り込み信号線の状態を変える void -PEDECDevice::AssertINT(Device *source) +PEDECDevice::ChangeInterrupt() { - if (__predict_true(source == gSPC.get())) { - int_asserted |= IntmapSPC; - - } else if (__predict_true(source == gFDC.get())) { - int_asserted |= IntmapFDC; +#if 0 // こんなログ出したいかも // ログ表示のためだけ - if ((int_enabled & IntmapFDC)) { + if ((intmap_enable & IntmapFDC)) { putlog(1, "FDC からの割り込み要求"); } else { putlog(2, "FDC からの割り込み要求(マスク)"); } +#endif - } else { - PANIC("Unknown interrupt source"); - } - - ChangeInterrupt(); -} - -// 子デバイスが割り込み信号線をネゲートした -void -PEDECDevice::NegateINT(Device *source) -{ - if (__predict_true(source == gSPC.get())) { - int_asserted &= ~IntmapSPC; - } else if (__predict_true(source == gFDC.get())) { - int_asserted &= ~IntmapFDC; - } else { - PANIC("Unknown interrupt source"); - } - - ChangeInterrupt(); -} - -// 割り込み信号線の状態を変える -void -PEDECDevice::ChangeInterrupt() -{ - uint32 stat = (int_asserted & int_enabled); - gInterrupt->ChangeINT(this, stat); + uint32 stat = (intmap_status & intmap_enable); + interrupt->ChangeINT(this, stat); } // 割り込みアクノリッジ -int +busdata PEDECDevice::InterruptAcknowledge(int lv) { - uint32 stat = (int_asserted & int_enabled); + uint32 stat = (intmap_status & intmap_enable); // SPC と I/O コントローラ担当の4本どっちが優先かは分からないので // SPC を優先しておくのでいいだろう。 @@ -168,7 +225,9 @@ PEDECDevice::InterruptAcknowledge(int lv if ((stat & IntmapFDC)) { return vector + 0; + } else if ((stat & IntmapFDD)) { + return vector + 1; } else { - PANIC("Unknown interrupt acknowledge"); + return busdata::BusErr; } }