--- nono/vm/pedec.cpp 2026/04/29 17:04:55 1.1.1.3 +++ nono/vm/pedec.cpp 2026/04/29 17:05:21 1.1.1.8 @@ -4,28 +4,63 @@ // 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("PEDEC") + : inherited(OBJ_PEDEC) { - devaddr = baseaddr; - devlen = 0x2000; } +// デストラクタ PEDECDevice::~PEDECDevice() { } +// 初期化 +bool +PEDECDevice::Init() +{ + if (inherited::Init() == false) { + return false; + } + + fdc = GetFDCDevice(); + interrupt = GetInterruptDevice(); + spc = GetSPCDevice(); + + return true; +} + +// リセット void -PEDECDevice::ResetHard() +PEDECDevice::ResetHard(bool poweron) { - int_asserted = 0; - int_enabled = IntmapSPC; + inherited::ResetHard(poweron); + + intmap_enabled = IntmapSPC; // XXX vector } @@ -50,22 +85,22 @@ PEDECDevice::Write(uint32 offset, uint32 { 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)); + intmap_enabled = IntmapSPC; + intmap_enabled |= (data & 0x08) ? IntmapHDD : 0; + intmap_enabled |= (data & 0x04) ? IntmapFDC : 0; + intmap_enabled |= (data & 0x02) ? IntmapFDD : 0; + intmap_enabled |= (data & 0x01) ? IntmapPRT : 0; + + putlog(1, "Set Interrupt Mask HDD=%d FDC=%d FDD=%d PRT=%d", + ((intmap_enabled & IntmapHDD) ? 1 : 0), + ((intmap_enabled & IntmapFDC) ? 1 : 0), + ((intmap_enabled & IntmapFDD) ? 1 : 0), + ((intmap_enabled & IntmapPRT) ? 1 : 0)); return 0; case 1: // $E9C003 割り込みベクタ vector = data & 0xfc; - putlog(1, "割り込みベクタ設定 $%02x", vector); + putlog(1, "Set Interrupt Vector $%02x", vector); return 0; default: @@ -89,74 +124,71 @@ PEDECDevice::Peek(uint32 offset) } } +void +PEDECDevice::MonitorUpdate(TextScreen& screen, uint intr_level, int y) +{ + struct { + const char *name; + uint32 map; + } table[] = { + { "SPC", IntmapSPC }, + { "FDC", IntmapFDC }, + { "FDD", IntmapFDD }, + { "HDD", IntmapHDD }, + { "PRT", IntmapPRT }, + }; + + for (int i = 0; i < countof(table); i++) { + uint32 map = table[i].map; + int clz = __builtin_clz(map); + screen.Puts(4, y, TA::OnOff(intmap & map), table[i].name); + if (intr_level >= 1 || (intmap_enabled & map) == 0) { + screen.Puts(11, y, "Mask"); + } + screen.Print(15, y, "%26s", format_number(counter[clz]).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 & IntmapFDC) ? 0x80 : 0; + data |= (intmap & IntmapFDD) ? 0x40 : 0; + data |= (intmap & IntmapPRT) ? 0x20 : 0; + data |= (intmap & IntmapHDD) ? 0x10 : 0; + data |= (intmap_enabled & IntmapHDD) ? 0x08 : 0; + data |= (intmap_enabled & IntmapFDC) ? 0x04 : 0; + data |= (intmap_enabled & IntmapFDD) ? 0x02 : 0; + data |= (intmap_enabled & 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_enabled & 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 & intmap_enabled); + interrupt->ChangeINT(this, stat); } // 割り込みアクノリッジ int PEDECDevice::InterruptAcknowledge(int lv) { - uint32 stat = (int_asserted & int_enabled); + uint32 stat = (intmap & intmap_enabled); // SPC と I/O コントローラ担当の4本どっちが優先かは分からないので // SPC を優先しておくのでいいだろう。 @@ -167,7 +199,25 @@ PEDECDevice::InterruptAcknowledge(int lv if ((stat & IntmapFDC)) { return vector + 0; + } else if ((stat & IntmapFDD)) { + return vector + 1; } else { - PANIC("Unknown interrupt acknowledge"); + VMPANIC("Unknown interrupt acknowledge"); + } +} + +// デバイスから Intmap 値を引く +uint32 +PEDECDevice::GetIntmap(const Device *source) const +{ + if (__predict_true(source == spc)) { + return IntmapSPC; + } + if (__predict_true(source == fdc)) { + return IntmapFDC; + } + if (dynamic_cast(source)) { + return IntmapFDD; } + VMPANIC("Unsupported interrupt device"); }