Annotation of nono/vm/interrupt.cpp, revision 1.1.1.9

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
1.1.1.6   root        7: //
                      8: // 割り込みコントローラ
                      9: //
                     10: 
                     11: // IODevice
                     12: //    |
                     13: //    |  +-----------------+
                     14: //    +--| InterruptDevice | (割り込みコントローラの共通部)
                     15: //       +-----------------+
                     16: //          |  +-----------------+
                     17: //          +--| M680x0Interrupt | (m68k 割り込みコントローラの共通部)
                     18: //          |  +-----------------+
                     19: //          |     |
                     20: //          |     |  +-----------------+
                     21: //          |     +--| X68030Interrupt | (X68030 の割り込みコントローラ)
                     22: //          |     |  +-----------------+
                     23: //          |     |
                     24: //          |     |  +---------------+
                     25: //          |     +--| LunaInterrupt |   (LUNA-I の割り込みコントローラ)
1.1.1.9 ! root       26: //          |     |  +---------------+
        !            27: //          |     |
        !            28: //          |     |  +---------------+
        !            29: //          |     +--| NewsInterrupt |   (NEWS の割り込みコントローラ)
        !            30: //          |     |  +---------------+
        !            31: //          |     |
        !            32: //          |     |  +------------------+
        !            33: //          |     +--| Virt68kInterrupt | (virt68k の割り込みコントローラ)
        !            34: //          |        +------------------+
1.1.1.6   root       35: //          |
                     36: //          +-- PEDECDevice   (X68030 の Lv1 担当コントローラ)
1.1.1.7   root       37: //          +-- SysCtlrDevice (LUNA-88K の割り込みコントローラ)
1.1.1.9 ! root       38: //          +-- GFPICDevice   (virt68k の各レベル担当コントローラ)
1.1.1.6   root       39: 
1.1       root       40: #include "interrupt.h"
                     41: #include "dmac.h"
1.1.1.9 ! root       42: #include "goldfish_pic.h"
1.1       root       43: #include "lance.h"
                     44: #include "pedec.h"
                     45: #include "m68030.h"
                     46: #include "mfp.h"
                     47: #include "mpu680x0.h"
1.1.1.7   root       48: #include "newsctlr.h"
1.1.1.6   root       49: #include "nmi.h"
1.1.1.8   root       50: #include "rtl8019as.h"
1.1       root       51: #include "scc.h"
                     52: #include "sio.h"
                     53: #include "spc.h"
                     54: #include "sysclk.h"
                     55: 
                     56: //
1.1.1.9 ! root       57: // 割り込みコントローラ (共通部)
1.1       root       58: //
                     59: 
1.1.1.7   root       60: // コンストラクタ(オブジェクト名指定なし)
                     61: InterruptDevice::InterruptDevice()
                     62:        : InterruptDevice(OBJ_INTERRUPT)        // 移譲
1.1.1.4   root       63: {
                     64: }
                     65: 
1.1.1.7   root       66: // コンストラクタ(オブジェクト名指定あり)
                     67: InterruptDevice::InterruptDevice(int objid_)
                     68:        : inherited(objid_)
1.1       root       69: {
                     70: }
                     71: 
                     72: // デストラクタ
                     73: InterruptDevice::~InterruptDevice()
                     74: {
                     75: }
                     76: 
1.1.1.5   root       77: // リセット
                     78: void
1.1.1.6   root       79: InterruptDevice::ResetHard(bool poweron)
1.1.1.5   root       80: {
                     81:        memset(&counter, 0, sizeof(counter));
                     82: }
                     83: 
1.1.1.9 ! root       84: // 子デバイスを登録する。
        !            85: void
        !            86: InterruptDevice::RegistINT(uint32 intmap_, const char *name_, Device *source_)
        !            87: {
        !            88:        for (const auto& m : intmap_list) {
        !            89:                assertmsg(m.intmap != intmap_,
        !            90:                        "intmap=%08x already registered", intmap_);
        !            91:                if (source_ != NULL) {
        !            92:                        assertmsg(m.source != source_,
        !            93:                                "source=%p already registered", source_);
        !            94:                }
        !            95:        }
        !            96:        intmap_list.emplace_back(intmap_, name_, source_);
        !            97: 
        !            98:        // 登録された intmap の和
        !            99:        intmap_avail |= intmap_;
        !           100: }
        !           101: 
        !           102: // デバイスから Intmap 値を引く
        !           103: uint32
        !           104: InterruptDevice::GetIntmap(const Device *source) const
        !           105: {
        !           106:        for (const auto& m : intmap_list) {
        !           107:                if (m.source == source) {
        !           108:                        return m.intmap;
        !           109:                }
        !           110:        }
        !           111: 
        !           112:        VMPANIC("Unknown interrupt source?");
        !           113: }
        !           114: 
        !           115: // Intmap 値から名前を引く
        !           116: const char *
        !           117: InterruptDevice::GetIntName(uint32 intmap_) const
        !           118: {
        !           119:        for (const auto& m : intmap_list) {
        !           120:                if (m.intmap == intmap_) {
        !           121:                        return m.name;
        !           122:                }
        !           123:        }
        !           124: 
        !           125:        return "???";
        !           126: }
        !           127: 
1.1.1.5   root      128: // 子デバイスが割り込み信号線をアサートした
                    129: void
                    130: InterruptDevice::AssertINT(Device *source)
                    131: {
                    132:        uint32 oldmap;
                    133:        uint32 srcmap;
                    134: 
1.1.1.9 ! root      135:        oldmap = intmap_status;
1.1.1.5   root      136:        srcmap = GetIntmap(source);
1.1.1.9 ! root      137:        intmap_status |= srcmap;
1.1.1.5   root      138: 
1.1.1.9 ! root      139:        if ((oldmap ^ intmap_status) != 0) {
1.1.1.5   root      140:                // 立ち上がりエッジでカウント
                    141:                counter[__builtin_clz(srcmap)]++;
                    142:                ChangeInterrupt();
                    143:        }
                    144: }
                    145: 
                    146: // 子デバイスが割り込み信号線をネゲートした
                    147: void
                    148: InterruptDevice::NegateINT(Device *source)
                    149: {
                    150:        uint32 oldmap;
                    151:        uint32 srcmap;
                    152: 
1.1.1.9 ! root      153:        oldmap = intmap_status;
1.1.1.5   root      154:        srcmap = GetIntmap(source);
1.1.1.9 ! root      155:        intmap_status &= ~srcmap;
1.1.1.5   root      156: 
1.1.1.9 ! root      157:        if ((oldmap ^ intmap_status) != 0) {
1.1.1.5   root      158:                ChangeInterrupt();
                    159:        }
                    160: }
1.1       root      161: 
1.1.1.8   root      162: // 割り込み信号線の状態を取得
                    163: bool
                    164: InterruptDevice::GetINT(const Device *source) const
                    165: {
                    166:        uint32 srcmap;
                    167: 
                    168:        srcmap = GetIntmap(source);
                    169: 
1.1.1.9 ! root      170:        return (intmap_status & srcmap);
1.1.1.8   root      171: }
                    172: 
                    173: 
1.1       root      174: //
                    175: // 仮想割り込みコントローラ (m680x0 共通部)
                    176: //
                    177: 
                    178: // コンストラクタ
                    179: M680x0Interrupt::M680x0Interrupt()
                    180: {
1.1.1.9 ! root      181:        intmap_status = IntmapSentinel;
        !           182:        // m680x0 仮想割り込みコントローラにはマスクがないので使わない。
        !           183:        // 念のためそれっぽい値を入れておく。
        !           184:        intmap_enable = 0xfffffff0;
1.1       root      185: }
                    186: 
                    187: // デストラクタ
                    188: M680x0Interrupt::~M680x0Interrupt()
                    189: {
                    190: }
                    191: 
1.1.1.7   root      192: // 初期化
                    193: bool
                    194: M680x0Interrupt::Init()
                    195: {
                    196:        if (inherited::Init() == false) {
                    197:                return false;
                    198:        }
                    199: 
1.1.1.9 ! root      200:        mpu680x0 = GetMPU680x0Device(mpu);
        !           201: 
1.1.1.7   root      202:        return true;
                    203: }
                    204: 
1.1       root      205: // リセット
                    206: void
1.1.1.6   root      207: M680x0Interrupt::ResetHard(bool poweron)
1.1       root      208: {
1.1.1.6   root      209:        inherited::ResetHard(poweron);
1.1       root      210: }
                    211: 
                    212: void
1.1.1.5   root      213: M680x0Interrupt::ChangeInterrupt()
1.1       root      214: {
                    215:        int newipl;
                    216: 
1.1.1.9 ! root      217:        // intmap_status は最下位ビットを常に立ててあるので 0 にならない
        !           218:        newipl = (uint)(31 - __builtin_clz(intmap_status)) / 4;
1.1       root      219: 
1.1.1.5   root      220:        // 割り込みレベルが変わったら、新しいレベルを通知
                    221:        if (newipl != ipl) {
1.1       root      222:                ipl = newipl;
1.1.1.7   root      223:                mpu->Interrupt(ipl);
1.1       root      224:        }
                    225: }
                    226: 
                    227: 
                    228: //
                    229: // X68030 仮想割り込みコントローラ
                    230: //
                    231: 
                    232: // コンストラクタ
                    233: X68030Interrupt::X68030Interrupt()
                    234: {
1.1.1.6   root      235:        monitor.func = ToMonitorCallback(&X68030Interrupt::MonitorUpdate);
1.1.1.4   root      236:        monitor.Regist(ID_MONITOR_INTERRUPT);
1.1       root      237: }
                    238: 
                    239: // デストラクタ
                    240: X68030Interrupt::~X68030Interrupt()
                    241: {
                    242: }
                    243: 
1.1.1.7   root      244: // 初期化
                    245: bool
                    246: X68030Interrupt::Init()
                    247: {
                    248:        if (inherited::Init() == false) {
                    249:                return false;
                    250:        }
                    251: 
                    252:        dmac = GetDMACDevice();
                    253:        mfp = GetMFPDevice();
                    254:        nmi = GetNMIDevice();
                    255:        pedec = GetPEDECDevice();
                    256:        scc = GetSCCDevice();
1.1.1.9 ! root      257:        for (int i = 0; i < 2; i++) {
        !           258:                net[i] = gMainApp.FindObject<RTL8019ASDevice>(OBJ_ETHERNET(i));
1.1       root      259:        }
1.1.1.9 ! root      260: 
        !           261:        // 検索順
        !           262:        RegistINT(IntmapMFP,    "MFP",          mfp);
        !           263:        RegistINT(IntmapDMAC,   "DMAC",         dmac);
        !           264:        RegistINT(IntmapPEDEC,  "PEDEC",        pedec);
        !           265:        RegistINT(IntmapSCC,    "SCC",          scc);
        !           266:        if (net[0]) {
        !           267:                RegistINT(IntmapNereid0,"Nereid0",      net[0]);
        !           268:        }
        !           269:        if (net[1]) {
        !           270:                RegistINT(IntmapNereid1,"Nereid1",      net[1]);
        !           271:        }
        !           272:        RegistINT(IntmapNMI,    "NMI",          nmi);
        !           273: 
        !           274:        // 表示順
        !           275:        // XXX const uint32 がそのまま push_back() 出来ないようだ
        !           276:        disp_list.clear();
        !           277:        disp_list.push_back((uint32)IntmapNMI);
        !           278:        disp_list.push_back((uint32)IntmapMFP);
        !           279:        disp_list.push_back((uint32)IntmapSCC);
        !           280:        if (net[0]) {
        !           281:                disp_list.push_back((uint32)IntmapNereid0);
1.1       root      282:        }
1.1.1.9 ! root      283:        if (net[1]) {
        !           284:                disp_list.push_back((uint32)IntmapNereid1);
1.1       root      285:        }
1.1.1.9 ! root      286:        disp_list.push_back((uint32)IntmapDMAC);
        !           287:        disp_list.push_back((uint32)IntmapPEDEC);
        !           288: 
        !           289:        // 行数が確定したのでサイズ設定
        !           290:        monitor.SetSize(41, 1 + disp_list.size() + 5/*PEDEC*/);
        !           291: 
        !           292:        return true;
1.1       root      293: }
                    294: 
                    295: // 割り込みアクノリッジに応答する
1.1.1.9 ! root      296: busdata
1.1       root      297: X68030Interrupt::InterruptAcknowledge(int lv)
                    298: {
                    299:        switch (lv) {
1.1.1.6   root      300:         case 7:
                    301:                return AutoVector;
                    302: 
1.1       root      303:         case 6:
1.1.1.7   root      304:                return mfp->InterruptAcknowledge();
1.1       root      305: 
                    306:         case 5:
1.1.1.7   root      307:                return scc->InterruptAcknowledge();
1.1       root      308: 
1.1.1.8   root      309:         case 4:
1.1.1.9 ! root      310:                if ((intmap_status & IntmapNereid0)) {
        !           311:                        return net[0]->InterruptAcknowledge();
        !           312:                }
        !           313:                if ((intmap_status & IntmapNereid1)) {
        !           314:                        return net[1]->InterruptAcknowledge();
1.1.1.8   root      315:                }
                    316:                break;
                    317: 
1.1       root      318:         case 3:
1.1.1.7   root      319:                return dmac->InterruptAcknowledge();
1.1       root      320: 
                    321:         case 1:
1.1.1.7   root      322:                return pedec->InterruptAcknowledge(lv);
1.1       root      323: 
                    324:         default:
                    325:                break;
                    326:        }
1.1.1.9 ! root      327: 
        !           328:        return busdata::BusErr;
1.1       root      329: }
                    330: 
                    331: void
1.1.1.4   root      332: X68030Interrupt::MonitorUpdate(Monitor *, TextScreen& screen)
1.1       root      333: {
                    334:        int y;
                    335: 
                    336:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
1.1.1.7   root      337:        uint intr_mask = mpu680x0->reg.intr_mask;
1.1       root      338: 
1.1.1.4   root      339:        screen.Clear();
1.1       root      340: 
1.1.1.7   root      341:        // 0         1         2         3         4
                    342:        // 01234567890123456789012345678901234567890
1.1.1.8   root      343:        // Lv Device  IM=7                     Count
                    344:        // 1  Nereid0     01234567890123456789012345
                    345:        //     SPC    Mask
1.1.1.7   root      346: 
1.1       root      347:        y = 0;
1.1.1.8   root      348:        screen.Print(0, y, "Lv Device  IM=%d", intr_mask);
                    349:        screen.Puts(36, y, "Count");
1.1.1.7   root      350:        y++;
1.1.1.9 ! root      351:        for (uint32 map : disp_list) {
1.1       root      352:                int clz = __builtin_clz(map);
                    353:                int lv = (31 - clz) / 4;
1.1.1.4   root      354:                screen.Print(0, y, "%d", lv);
1.1.1.9 ! root      355:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
1.1.1.6   root      356:                if (lv <= intr_mask) {
1.1.1.8   root      357:                        screen.Puts(11, y, "Mask");
1.1       root      358:                }
1.1.1.8   root      359:                screen.Print(15, y, "%26s", format_number(counter[clz]).c_str());
1.1       root      360:                y++;
                    361:        }
1.1.1.2   root      362: 
1.1.1.5   root      363:        // PEDEC 分も一緒に表示したい
1.1.1.7   root      364:        pedec->MonitorUpdate(screen, intr_mask, y);
1.1       root      365: }
                    366: 
1.1.1.6   root      367: 
1.1       root      368: //
                    369: // LUNA-I 仮想割り込みコントローラ
                    370: //
                    371: 
                    372: // コンストラクタ
                    373: LunaInterrupt::LunaInterrupt()
                    374: {
1.1.1.6   root      375:        monitor.func = ToMonitorCallback(&LunaInterrupt::MonitorUpdate);
1.1.1.4   root      376:        monitor.Regist(ID_MONITOR_INTERRUPT);
1.1       root      377: }
                    378: 
                    379: // デストラクタ
                    380: LunaInterrupt::~LunaInterrupt()
                    381: {
                    382: }
                    383: 
1.1.1.7   root      384: // 初期化
                    385: bool
                    386: LunaInterrupt::Init()
                    387: {
                    388:        if (inherited::Init() == false) {
                    389:                return false;
                    390:        }
                    391: 
1.1.1.9 ! root      392:        // 検索順
        !           393:        RegistINT(IntmapSysClk, "Clock",        GetSysClkDevice());
        !           394:        RegistINT(IntmapSPC,    "SPC",          GetSPCDevice());
        !           395:        RegistINT(IntmapSIO,    "SIO",          GetSIODevice());
        !           396:        RegistINT(IntmapLance,  "Lance",        GetLanceDevice());
        !           397:        RegistINT(IntmapXPHigh, "XP(Hi)",       DEVICE_XPINT_HIGH);
        !           398:        RegistINT(IntmapXPLow,  "XP(Lo)",       DEVICE_XPINT_LOW);
        !           399:        RegistINT(IntmapNMI,    "NMI",          GetNMIDevice());
        !           400: 
        !           401:        // 表示順
        !           402:        disp_list = {
        !           403:                IntmapNMI,
        !           404:                IntmapSIO,
        !           405:                IntmapSysClk,
        !           406:                IntmapXPHigh,
        !           407:                IntmapLance,
        !           408:                IntmapSPC,
        !           409:                IntmapXPLow,
        !           410:        };
1.1.1.7   root      411: 
1.1.1.9 ! root      412:        // 行数が確定したのでサイズ設定
        !           413:        monitor.SetSize(40, 1 + disp_list.size());
1.1.1.7   root      414: 
1.1.1.9 ! root      415:        return true;
1.1       root      416: }
                    417: 
                    418: // 割り込みアクノリッジに応答する
1.1.1.9 ! root      419: busdata
1.1       root      420: LunaInterrupt::InterruptAcknowledge(int lv)
                    421: {
                    422:        // LUNA は全てオートベクタ
                    423:        return AutoVector;
                    424: }
                    425: 
                    426: void
1.1.1.4   root      427: LunaInterrupt::MonitorUpdate(Monitor *, TextScreen& screen)
1.1       root      428: {
                    429:        int y;
1.1.1.7   root      430: 
                    431:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
                    432:        uint intr_mask = mpu680x0->reg.intr_mask;
                    433: 
                    434:        screen.Clear();
                    435: 
                    436:        // 0         1         2         3         4
                    437:        // 01234567890123456789012345678901234567890
                    438:        // Lv Device IM=7                     Count
                    439:        // 1  XP(Hi) Mask01234567890123456789012345
                    440: 
                    441:        y = 0;
                    442:        screen.Print(0, y, "Lv Device IM=%d", intr_mask);
                    443:        screen.Puts(35, y, "Count");
                    444:        y++;
1.1.1.9 ! root      445:        for (uint32 map : disp_list) {
1.1.1.7   root      446:                int clz = __builtin_clz(map);
                    447:                int lv = (31 - clz) / 4;
                    448:                screen.Print(0, y, "%d", lv);
1.1.1.9 ! root      449:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
1.1.1.7   root      450:                if (lv <= intr_mask) {
                    451:                        screen.Puts(10, y, "Mask");
                    452:                }
                    453:                screen.Print(14, y, "%26s", format_number(counter[clz]).c_str());
                    454:                y++;
                    455:        }
                    456: }
                    457: 
                    458: 
                    459: //
                    460: // NEWS 仮想割り込みコントローラ
                    461: //
                    462: 
                    463: // コンストラクタ
                    464: NewsInterrupt::NewsInterrupt()
                    465: {
                    466:        monitor.func = ToMonitorCallback(&NewsInterrupt::MonitorUpdate);
                    467:        monitor.Regist(ID_MONITOR_INTERRUPT);
                    468: }
                    469: 
                    470: // デストラクタ
                    471: NewsInterrupt::~NewsInterrupt()
                    472: {
                    473: }
                    474: 
                    475: // 初期化
                    476: bool
                    477: NewsInterrupt::Init()
                    478: {
                    479:        if (inherited::Init() == false) {
                    480:                return false;
                    481:        }
                    482: 
1.1.1.9 ! root      483:        // 割り込みアクノリッジで使う
1.1.1.7   root      484:        scc = GetSCCDevice();
                    485: 
1.1.1.9 ! root      486:        // 検索順
        !           487:        RegistINT(IntmapTimer,  "Timer",        GetNewsCtlrDevice());
        !           488:        RegistINT(IntmapLance,  "Lance",        GetLanceDevice());
        !           489:        RegistINT(IntmapSCC,    "SCC",          scc);
        !           490: 
        !           491:        // 表示順
        !           492:        disp_list = {
        !           493:                IntmapTimer,
        !           494:                IntmapSCC,
        !           495:                IntmapLance,
        !           496:        };
1.1.1.7   root      497: 
1.1.1.9 ! root      498:        // 行数が確定したのでサイズ設定
        !           499:        monitor.SetSize(40, 1 + disp_list.size());
        !           500: 
        !           501:        return true;
1.1.1.7   root      502: }
                    503: 
                    504: // 割り込みアクノリッジに応答する
1.1.1.9 ! root      505: busdata
1.1.1.7   root      506: NewsInterrupt::InterruptAcknowledge(int lv)
                    507: {
                    508:        // NEWS では 5 の SCC だけベクタで、他はオートベクタ?
                    509:        switch (lv) {
                    510:         case 5:
                    511:                return scc->InterruptAcknowledge();
                    512: 
                    513:         default:
                    514:                return AutoVector;
                    515:        }
                    516: }
                    517: 
                    518: // ステータスバイトを読み出す。NewsCtlr から呼ばれる。
                    519: uint8
                    520: NewsInterrupt::PeekStatus() const
                    521: {
                    522:        uint8 data = 0;
                    523: 
1.1.1.9 ! root      524:        if ((intmap_status & IntmapSIC)) {
1.1.1.7   root      525:                data |= 0x80;
                    526:        }
1.1.1.9 ! root      527:        if ((intmap_status & IntmapLance)) {
1.1.1.7   root      528:                data |= 0x04;
                    529:        }
                    530: 
                    531:        return data;
                    532: }
                    533: 
                    534: void
                    535: NewsInterrupt::MonitorUpdate(Monitor *, TextScreen& screen)
                    536: {
                    537:        int y;
1.1       root      538: 
                    539:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
1.1.1.7   root      540:        uint intr_mask = mpu680x0->reg.intr_mask;
1.1       root      541: 
1.1.1.4   root      542:        screen.Clear();
1.1       root      543: 
1.1.1.7   root      544:        // 0         1         2         3         4
                    545:        // 01234567890123456789012345678901234567890
                    546:        // Lv Device IM=7                     Count
                    547:        // 1  XP(Hi) Mask01234567890123456789012345
                    548: 
1.1       root      549:        y = 0;
1.1.1.7   root      550:        screen.Print(0, y, "Lv Device IM=%d", intr_mask);
                    551:        screen.Puts(35, y, "Count");
                    552:        y++;
1.1.1.9 ! root      553:        for (uint32 map : disp_list) {
1.1       root      554:                int clz = __builtin_clz(map);
                    555:                int lv = (31 - clz) / 4;
1.1.1.4   root      556:                screen.Print(0, y, "%d", lv);
1.1.1.9 ! root      557:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
1.1.1.6   root      558:                if (lv <= intr_mask) {
1.1.1.7   root      559:                        screen.Puts(10, y, "Mask");
1.1       root      560:                }
1.1.1.7   root      561:                screen.Print(14, y, "%26s", format_number(counter[clz]).c_str());
1.1       root      562:                y++;
                    563:        }
                    564: }
1.1.1.9 ! root      565: 
        !           566: 
        !           567: //
        !           568: // virt68k 仮想割り込みコントローラ
        !           569: //
        !           570: 
        !           571: // コンストラクタ
        !           572: Virt68kInterrupt::Virt68kInterrupt()
        !           573: {
        !           574:        monitor.func = ToMonitorCallback(&Virt68kInterrupt::MonitorUpdate);
        !           575:        monitor.Regist(ID_MONITOR_INTERRUPT);
        !           576: }
        !           577: 
        !           578: // デストラクタ
        !           579: Virt68kInterrupt::~Virt68kInterrupt()
        !           580: {
        !           581: }
        !           582: 
        !           583: // 初期化
        !           584: bool
        !           585: Virt68kInterrupt::Init()
        !           586: {
        !           587:        if (inherited::Init() == false) {
        !           588:                return false;
        !           589:        }
        !           590: 
        !           591:        // [0] は無視。
        !           592:        gfpic[6] = GetGFPICDevice(6);
        !           593:        gfpic[5] = GetGFPICDevice(5);
        !           594:        gfpic[4] = GetGFPICDevice(4);
        !           595:        gfpic[3] = GetGFPICDevice(3);
        !           596:        gfpic[2] = GetGFPICDevice(2);
        !           597:        gfpic[1] = GetGFPICDevice(1);
        !           598: 
        !           599:        // 検索順
        !           600:        RegistINT(IntmapGFPIC6, "GFPIC6",       gfpic[6]);
        !           601:        RegistINT(IntmapGFPIC5, "GFPIC5",       gfpic[5]);
        !           602:        RegistINT(IntmapGFPIC4, "GFPIC4",       gfpic[4]);
        !           603:        RegistINT(IntmapGFPIC3, "GFPIC3",       gfpic[3]);
        !           604:        RegistINT(IntmapGFPIC2, "GFPIC2",       gfpic[2]);
        !           605:        RegistINT(IntmapGFPIC1, "GFPIC1",       gfpic[1]);
        !           606: 
        !           607:        // 表示順
        !           608:        disp_list = {
        !           609:                IntmapGFPIC6,
        !           610:                IntmapGFPIC5,
        !           611:                IntmapGFPIC4,
        !           612:                IntmapGFPIC3,
        !           613:                IntmapGFPIC2,
        !           614:                IntmapGFPIC1,
        !           615:        };
        !           616: 
        !           617:        // ここまでの行数でサイズ設定。
        !           618:        // この後各割り込みソースの Init() から GFPIC への RegistIRQ() する
        !           619:        // たびに増やされていく。
        !           620:        monitor.SetSize(77, 2 + disp_list.size() + 1);
        !           621: 
        !           622:        return true;
        !           623: }
        !           624: 
        !           625: void
        !           626: Virt68kInterrupt::IncMonitorHeight()
        !           627: {
        !           628:        auto size = monitor.GetSize();
        !           629:        monitor.SetSize(size.width, size.height + 1);
        !           630: }
        !           631: 
        !           632: // 割り込みアクノリッジに応答する
        !           633: busdata
        !           634: Virt68kInterrupt::InterruptAcknowledge(int lv)
        !           635: {
        !           636:        // ?
        !           637:        return AutoVector;
        !           638: }
        !           639: 
        !           640: void
        !           641: Virt68kInterrupt::MonitorUpdate(Monitor *, TextScreen& screen)
        !           642: {
        !           643:        int y;
        !           644: 
        !           645:        // CPU の割り込み可否は本当は関係ないけど、便宜的に一緒に表示したい
        !           646:        uint intr_mask = mpu680x0->reg.intr_mask;
        !           647:        // 各 PIC の状況も一緒に表示したい。picmap の添字はレベル(1-6)
        !           648:        std::array<uint32, 7> picmap;
        !           649:        for (int lv = 1; lv < picmap.size(); lv++) {
        !           650:                picmap[lv] = gfpic[lv]->intmap_status;
        !           651:        }
        !           652: 
        !           653:        screen.Clear();
        !           654: 
        !           655: // 0         1         2         3         4         5         6         7
        !           656: // 01234567890123456789012345678901234567890123456789012345678901234567890123456
        !           657: // Lv Device IM=7 IRQ         20         10         1                      Count
        !           658: // 1  GFPIC1 Mask 21098765 43210987 65432109 87654321 01234567890123456789012345
        !           659: //                E:Enable  D:Disable  .:NotConnected
        !           660: 
        !           661:        y = 0;
        !           662:        screen.Print(0, y, "Lv Device IM=%d IRQ         20         10         1",
        !           663:                intr_mask);
        !           664:        screen.Puts(72, y, "Count");
        !           665:        y++;
        !           666:        for (uint32 map : disp_list) {
        !           667:                int clz = __builtin_clz(map);
        !           668:                int lv = (31 - clz) / 4;
        !           669:                screen.Print(0, y, "%d", lv);
        !           670:                screen.Puts(3, y, TA::OnOff(intmap_status & map), GetIntName(map));
        !           671:                if (lv <= intr_mask) {
        !           672:                        screen.Puts(10, y, "Mask");
        !           673:                }
        !           674: 
        !           675:                // 各入力ピンの状態も表示しないと何も分からない。
        !           676:                gfpic[lv]->MonitorUpdateSummary(screen, 15, y);
        !           677: 
        !           678:                screen.Print(51, y, "%26s", format_number(counter[clz]).c_str());
        !           679:                y++;
        !           680:        }
        !           681:        screen.Puts(15, y, "E:Enable  D:Disable  .:NotConnected");
        !           682:        y++;
        !           683:        y++;
        !           684: 
        !           685:        for (uint32 map : disp_list) {
        !           686:                int clz = __builtin_clz(map);
        !           687:                int lv = (31 - clz) / 4;
        !           688:                y = gfpic[lv]->MonitorUpdateDetail(screen, y, lv);
        !           689:        }
        !           690: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.