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

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: //          |     |  +------------------+
1.1.1.10! root       33: //          |     +--| Virt68kInterrupt | (virt-m68k の割り込みコントローラ)
1.1.1.9   root       34: //          |        +------------------+
1.1.1.6   root       35: //          |
                     36: //          +-- PEDECDevice   (X68030 の Lv1 担当コントローラ)
1.1.1.7   root       37: //          +-- SysCtlrDevice (LUNA-88K の割り込みコントローラ)
1.1.1.10! root       38: //          +-- GFPICDevice   (virt-m68k の各レベル担当コントローラ)
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: // コンストラクタ(オブジェクト名指定あり)
1.1.1.10! root       67: InterruptDevice::InterruptDevice(uint objid_)
1.1.1.7   root       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: {
1.1.1.10! root      215:        uint newipl;
1.1       root      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: 
1.1.1.10! root      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.10! root      348:        screen.Print(0, y, "Lv Device  IM=%u", intr_mask);
1.1.1.8   root      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.10! root      354:                screen.Print(0, y, "%u", 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;
1.1.1.10! root      442:        screen.Print(0, y, "Lv Device IM=%u", intr_mask);
1.1.1.7   root      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;
1.1.1.10! root      448:                screen.Print(0, y, "%u", 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.10! root      550:        screen.Print(0, y, "Lv Device IM=%u", intr_mask);
1.1.1.7   root      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.10! root      556:                screen.Print(0, y, "%u", 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: //
1.1.1.10! root      568: // virt-m68k 仮想割り込みコントローラ
1.1.1.9   root      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;
1.1.1.10! root      662:        screen.Print(0, y, "Lv Device IM=%u IRQ         20         10         1",
1.1.1.9   root      663:                intr_mask);
                    664:        screen.Puts(72, y, "Count");
                    665:        y++;
                    666:        for (uint32 map : disp_list) {
1.1.1.10! root      667:                uint clz = __builtin_clz(map);
        !           668:                uint lv = (uint)(31 - clz) / 4;
        !           669:                screen.Print(0, y, "%u", lv);
1.1.1.9   root      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.