Annotation of nono/hd64180/hd647180io.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2022 nono project
        !             4: // Licensed under nono-license.txt
        !             5: //
        !             6: 
        !             7: //
        !             8: // HD647180 I/O アクセス
        !             9: //
        !            10: 
        !            11: #include "mpu64180.h"
        !            12: #include "hd647180.h"
        !            13: #include "pio.h"
        !            14: #include "scheduler.h"
        !            15: #include "xpbus.h"
        !            16: 
        !            17: //#define ENABLE_SERIAL_LOG
        !            18: //#define ENABLE_SSG_LOG
        !            19: 
        !            20: uint32
        !            21: MPU64180Device::ReadIO(uint32 addr)
        !            22: {
        !            23:        CYCLE(iowait);
        !            24: 
        !            25:        // 内蔵 I/O
        !            26:        if (io_address <= addr && addr < io_address + 0x80) {
        !            27:                return ReadInternalIO(addr - io_address);
        !            28:        }
        !            29: 
        !            30:        return ReadExternalIO(addr);
        !            31: }
        !            32: 
        !            33: uint32
        !            34: MPU64180Device::ReadInternalIO(uint32 offset)
        !            35: {
        !            36:        uint32 data = -1;
        !            37: 
        !            38:        switch (offset) {
        !            39:         case 0x00:                                     // IO_CNTLA0
        !            40:         case 0x01:                                     // IO_CNTLA1
        !            41:                data = 0x10;
        !            42: #if defined(ENABLE_SERIAL_LOG)
        !            43:                putlog(0, "%s -> $%02x (NOT IMPLEMENTED)",
        !            44:                        IOName(offset).c_str(), data);
        !            45: #endif
        !            46:                return data;
        !            47:         case 0x02:                                     // IO_CNTLB0
        !            48:         case 0x03:                                     // IO_CNTLB1
        !            49:                break;
        !            50:         case 0x04:                                     // IO_STAT0
        !            51:         case 0x05:                                     // IO_STAT1
        !            52:                data = 0x02;
        !            53: #if defined(ENABLE_SERIAL_LOG)
        !            54:                putlog(0, "%s -> $%02x (NOT IMPLEMENTED)",
        !            55:                        IOName(offset).c_str(), data);
        !            56: #endif
        !            57:                return data;
        !            58:         case 0x06:                                     // IO_TDR0
        !            59:         case 0x07:                                     // IO_TDR1
        !            60:         case 0x08:                                     // IO_TSR0
        !            61:         case 0x09:                                     // IO_TSR1
        !            62:         case 0x0a:                                     // IO_CNTR
        !            63:         case 0x0b:                                     // IO_TRDR
        !            64:                break;
        !            65: 
        !            66:         case 0x0c:                                     // IO_TMDR0L
        !            67:                data = ReadTMDRL(0);
        !            68:                break;
        !            69:         case 0x0d:                                     // IO_TMDR0H
        !            70:                data = ReadTMDRH(0);
        !            71:                break;
        !            72:         case 0x0e:                                     // IO_RLDR0L
        !            73:                data = PeekRLDRL(0);
        !            74:                break;
        !            75:         case 0x0f:                                     // IO_RLDR0H
        !            76:                data = PeekRLDRH(0);
        !            77:                break;
        !            78:         case 0x10:                                     // IO_TCR
        !            79:                data = ReadTCR();
        !            80:                break;
        !            81:         case 0x14:                                     // IO_TMDR1L
        !            82:                data = ReadTMDRL(1);
        !            83:                break;
        !            84:         case 0x15:                                     // IO_TMDR1H
        !            85:                data = ReadTMDRH(1);
        !            86:                break;
        !            87:         case 0x16:                                     // IO_RLDR1L
        !            88:                data = PeekRLDRH(0);
        !            89:                break;
        !            90:         case 0x17:                                     // IO_RLDR1H
        !            91:                data = PeekRLDRH(1);
        !            92:                break;
        !            93:         case 0x18:                                     // IO_FRC
        !            94:                data = PeekFRC();
        !            95:                break;
        !            96: 
        !            97:         case 0x20:                                     // IO_SAR0L
        !            98:         case 0x21:                                     // IO_SAR0H
        !            99:         case 0x22:                                     // IO_SAR0B
        !           100:         case 0x23:                                     // IO_DAR0L
        !           101:         case 0x24:                                     // IO_DAR0H
        !           102:         case 0x25:                                     // IO_DAR0B
        !           103:         case 0x26:                                     // IO_BCR0L
        !           104:         case 0x27:                                     // IO_BCR0H
        !           105:         case 0x28:                                     // IO_MAR1L
        !           106:         case 0x29:                                     // IO_MAR1H
        !           107:         case 0x2a:                                     // IO_MAR1B
        !           108:         case 0x2b:                                     // IO_IAR1L
        !           109:         case 0x2c:                                     // IO_IAR1H
        !           110:         case 0x2e:                                     // IO_BCR1L
        !           111:         case 0x2f:                                     // IO_BCR1H
        !           112:         case 0x30:                                     // IO_DSTAT
        !           113:         case 0x31:                                     // IO_DMODE
        !           114:                break;
        !           115:         case 0x32:                                     // IO_DCNTL
        !           116:                data = PeekDCNTL();
        !           117:                break;
        !           118: 
        !           119:         case 0x33:                                     // IO_IL
        !           120:                data = PeekIL();
        !           121:                break;
        !           122:         case 0x34:                                     // IO_ITC
        !           123:                data = PeekITC();
        !           124:                break;
        !           125:         case 0x36:                                     // IO_RCR
        !           126:                data = PeekRCR();
        !           127:                break;
        !           128: 
        !           129:         case 0x38:                                     // IO_CBR
        !           130:                data = PeekCBR();
        !           131:                break;
        !           132: 
        !           133:         case 0x39:                                     // IO_BBR
        !           134:                data = PeekBBR();
        !           135:                break;
        !           136: 
        !           137:         case 0x3a:                                     // IO_CBAR
        !           138:                data = PeekCBAR();
        !           139:                break;
        !           140: 
        !           141:         case 0x3e:                                     // IO_OMCR
        !           142:                break;
        !           143:         case 0x3f:                                     // IO_ICR
        !           144:                data = PeekICR();
        !           145:                break;
        !           146: 
        !           147:         case 0x40:                                     // IO_T2FRCL
        !           148:         case 0x41:                                     // IO_T2FRCH
        !           149:         case 0x42:                                     // IO_T2OCR1L
        !           150:         case 0x43:                                     // IO_T2OCR1H
        !           151:         case 0x44:                                     // IO_T2OCR2L
        !           152:         case 0x45:                                     // IO_T2OCR2H
        !           153:         case 0x46:                                     // IO_T2ICRL
        !           154:         case 0x47:                                     // IO_T2ICRH
        !           155:         case 0x48:                                     // IO_T2CSR1
        !           156:         case 0x49:                                     // IO_T2CSR2
        !           157:                break;
        !           158: 
        !           159:         case 0x50:                                     // IO_CCSR
        !           160:                break;
        !           161:         case 0x51:                                     // IO_RMCR
        !           162:                data = PeekRMCR();
        !           163:                break;
        !           164: 
        !           165:         case 0x53:                                     // IO_DERA
        !           166:                break;
        !           167:         case 0x60:                                     // IO_IODRA
        !           168:                data = 0xff;
        !           169: #if defined(ENABLE_SERIAL_LOG)
        !           170:                putlog(0, "%s -> $%02x (NOT IMPLEMENTED)",
        !           171:                        IOName(offset).c_str(), data);
        !           172: #endif
        !           173:                return data;
        !           174:         case 0x61:                                     // IO_IODRB
        !           175:         case 0x62:                                     // IO_IODRC
        !           176:         case 0x63:                                     // IO_IODRD
        !           177:         case 0x64:                                     // IO_IODRE
        !           178:         case 0x65:                                     // IO_IODRF
        !           179:         case 0x66:                                     // IO_IDRG
        !           180:         case 0x70:                                     // IO_DDRA
        !           181:         case 0x71:                                     // IO_DDRB
        !           182:         case 0x72:                                     // IO_DDRC
        !           183:         case 0x73:                                     // IO_DDRD
        !           184:         case 0x74:                                     // IO_DDRE
        !           185:         case 0x75:                                     // IO_DDRF
        !           186:                break;
        !           187: 
        !           188:         default:
        !           189:                break;
        !           190:        }
        !           191: 
        !           192:        // 表示して値を返す部分はだいたいほぼ共通なので。
        !           193:        if ((int32)data < 0) {
        !           194:                // data が (32bitで) 負なら未実装ポート。
        !           195:                data = 0xff;
        !           196:                putlog(0, "ReadInternalIO %s -> $%02x (NOT IMPLEMENTED)",
        !           197:                        IOName(offset).c_str(), data);
        !           198:        } else {
        !           199:                putlog(2, "%s -> $%02x", IOName(offset).c_str(), data);
        !           200:        }
        !           201:        return data;
        !           202: }
        !           203: 
        !           204: uint32
        !           205: MPU64180Device::ReadExternalIO(uint32 addr)
        !           206: {
        !           207:        uint32 data = -1;
        !           208: 
        !           209:        // LUNA の外部 I/O はアドレスの上位バイト不問
        !           210:        switch (addr & 0xff) {
        !           211:         case 0x82:                                     // SSG
        !           212:         case 0x83:                                     // SSG
        !           213: #if !defined(ENABLE_SSG_LOG)
        !           214:                data = 0xff;
        !           215: #endif
        !           216:                break;
        !           217: 
        !           218:         case 0x90:                                     // INT0 ネゲート
        !           219:                // 読み込みでも (というかアクセスがあっただけで) ネゲート。
        !           220:                putlog(1, "%s Negate INT0", IOName(addr).c_str());
        !           221:                NegateINT0();
        !           222:                // 実際何が読めるかは不明だが。
        !           223:                return 0xff;
        !           224: 
        !           225:         case 0xa0:                                     // レベル5 割り込み要求
        !           226:         case 0xb0:                                     // レベル1 割り込み要求
        !           227:                // 読み込みでも割り込み上げそうだがとりあえず未実装へ回しておく。
        !           228:                break;
        !           229: 
        !           230:         default:
        !           231:                break;
        !           232:        }
        !           233: 
        !           234:        // 表示して値を返す部分はだいたいほぼ共通なので。
        !           235:        if ((int32)data < 0) {
        !           236:                // data が (32bitで) 負なら未実装ポート。
        !           237:                data = 0xff;
        !           238:                putlog(0, "ReadExternalIO %s -> $%02x (NOT IMPLEMENTED)",
        !           239:                        IOName(addr).c_str(), data);
        !           240:        } else {
        !           241:                putlog(2, "%s -> $%02x", IOName(addr).c_str(), data);
        !           242:        }
        !           243:        return data;
        !           244: }
        !           245: 
        !           246: uint32
        !           247: MPU64180Device::ReadTMDRL(int ch)
        !           248: {
        !           249:        auto& t = timer[ch];
        !           250: 
        !           251:        // TDR 読み出しで割り込みフラグクリアの実績を解除
        !           252:        t.tif &= ~0x02;
        !           253:        ChangeTimerInterrupt();
        !           254: 
        !           255:        // L の読み出しで count を tmp にラッチ
        !           256:        t.tmpcount = t.count;
        !           257: 
        !           258:        // でラッチした L を読み出す
        !           259:        return t.tmpcount & 0xff;
        !           260: }
        !           261: 
        !           262: uint32
        !           263: MPU64180Device::ReadTMDRH(int ch)
        !           264: {
        !           265:        auto& t = timer[ch];
        !           266: 
        !           267:        // TDR 読み出しで割り込みフラグクリアの実績を解除
        !           268:        t.tif &= ~0x02;
        !           269:        ChangeTimerInterrupt();
        !           270: 
        !           271:        // L 読み出し時にラッチしたやつを読み出す。
        !           272:        return t.tmpcount >> 8;
        !           273: }
        !           274: 
        !           275: uint32
        !           276: MPU64180Device::ReadTCR()
        !           277: {
        !           278:        // TCR 読み出しで割り込みフラグクリアの実績を解除
        !           279:        timer[0].tif &= ~0x01;
        !           280:        timer[1].tif &= ~0x01;
        !           281:        ChangeTimerInterrupt();
        !           282: 
        !           283:        return PeekTCR();
        !           284: }
        !           285: 
        !           286: uint32
        !           287: MPU64180Device::WriteIO(uint32 addr, uint32 data)
        !           288: {
        !           289:        CYCLE(iowait);
        !           290: 
        !           291:        // 内蔵 I/O
        !           292:        if (io_address <= addr && addr < io_address + 0x80) {
        !           293:                return WriteInternalIO(addr - io_address, data);
        !           294:        }
        !           295: 
        !           296:        return WriteExternalIO(addr, data);
        !           297: }
        !           298: 
        !           299: uint32
        !           300: MPU64180Device::WriteInternalIO(uint32 offset, uint32 data)
        !           301: {
        !           302:        switch (offset) {
        !           303:         case 0x00:                                     // IO_CNTLA0
        !           304:         case 0x01:                                     // IO_CNTLA1
        !           305: #if defined(USE_XPSERIAL)
        !           306:                putlog(0, "%s <- $%02x (NOT IMPLEMENTED)",
        !           307:                        IOName(offset).c_str(), data);
        !           308: #endif
        !           309:                return 0;
        !           310:         case 0x02:                                     // IO_CNTLB0
        !           311:         case 0x03:                                     // IO_CNTLB1
        !           312:         case 0x04:                                     // IO_STAT0
        !           313:         case 0x05:                                     // IO_STAT1
        !           314:         case 0x06:                                     // IO_TDR0
        !           315:         case 0x07:                                     // IO_TDR1
        !           316:         case 0x08:                                     // IO_TSR0
        !           317:         case 0x09:                                     // IO_TSR1
        !           318:         case 0x0a:                                     // IO_CNTR
        !           319:         case 0x0b:                                     // IO_TRDR
        !           320:                break;
        !           321: 
        !           322:         case 0x0c:                                     // IO_TMDR0L
        !           323:                return WriteTMDRL(0, data);
        !           324:         case 0x0d:                                     // IO_TMDR0H
        !           325:                return WriteTMDRH(0, data);
        !           326:         case 0x0e:                                     // IO_RLDR0L
        !           327:                return WriteRLDRL(0, data);
        !           328:         case 0x0f:                                     // IO_RLDR0H
        !           329:                return WriteRLDRH(0, data);
        !           330:         case 0x10:                                     // IO_TCR
        !           331:                return WriteTCR(data);
        !           332:         case 0x14:                                     // IO_TMDR1L
        !           333:                return WriteTMDRL(1, data);
        !           334:         case 0x15:                                     // IO_TMDR1H
        !           335:                return WriteTMDRH(1, data);
        !           336:         case 0x16:                                     // IO_RLDR1L
        !           337:                return WriteRLDRL(1, data);
        !           338:         case 0x17:                                     // IO_RLDR1H
        !           339:                return WriteRLDRH(1, data);
        !           340:         case 0x18:                                     // IO_FRC
        !           341:                // 書き込みは出来るけど、してはいけないっぽい。
        !           342:                // たぶん現在値が変わるだけだと思うけど未対応。
        !           343:                break;
        !           344: 
        !           345:         case 0x20:                                     // IO_SAR0L
        !           346:         case 0x21:                                     // IO_SAR0H
        !           347:         case 0x22:                                     // IO_SAR0B
        !           348:         case 0x23:                                     // IO_DAR0L
        !           349:         case 0x24:                                     // IO_DAR0H
        !           350:         case 0x25:                                     // IO_DAR0B
        !           351:         case 0x26:                                     // IO_BCR0L
        !           352:         case 0x27:                                     // IO_BCR0H
        !           353:         case 0x28:                                     // IO_MAR1L
        !           354:         case 0x29:                                     // IO_MAR1H
        !           355:         case 0x2a:                                     // IO_MAR1B
        !           356:         case 0x2b:                                     // IO_IAR1L
        !           357:         case 0x2c:                                     // IO_IAR1H
        !           358:         case 0x2e:                                     // IO_BCR1L
        !           359:         case 0x2f:                                     // IO_BCR1H
        !           360:         case 0x30:                                     // IO_DSTAT
        !           361:         case 0x31:                                     // IO_DMODE
        !           362:                break;
        !           363:         case 0x32:                                     // IO_DCNTL
        !           364:                return WriteDCNTL(data);
        !           365:                break;
        !           366: 
        !           367:         case 0x33:                                     // IO_IL
        !           368:                return WriteIL(data);
        !           369:         case 0x34:                                     // IO_ITC
        !           370:                return WriteITC(data);
        !           371:         case 0x36:                                     // IO_RCR
        !           372:                return WriteRCR(data);
        !           373: 
        !           374:         case 0x38:                                     // IO_CBR
        !           375:                return WriteCBR(data);
        !           376:         case 0x39:                                     // IO_BBR
        !           377:                return WriteBBR(data);
        !           378:         case 0x3a:                                     // IO_CBAR
        !           379:                return WriteCBAR(data);
        !           380: 
        !           381:         case 0x3e:                                     // IO_OMCR
        !           382:                break;
        !           383:         case 0x3f:                                     // IO_ICR
        !           384:                return WriteICR(data);
        !           385: 
        !           386:         case 0x40:                                     // IO_T2FRCL
        !           387:         case 0x41:                                     // IO_T2FRCH
        !           388:         case 0x42:                                     // IO_T2OCR1L
        !           389:         case 0x43:                                     // IO_T2OCR1H
        !           390:         case 0x44:                                     // IO_T2OCR2L
        !           391:         case 0x45:                                     // IO_T2OCR2H
        !           392:         case 0x46:                                     // IO_T2ICRL
        !           393:         case 0x47:                                     // IO_T2ICRH
        !           394:         case 0x48:                                     // IO_T2CSR1
        !           395:         case 0x49:                                     // IO_T2CSR2
        !           396:                break;
        !           397: 
        !           398:         case 0x50:                                     // IO_CCSR
        !           399:                break;
        !           400:         case 0x51:                                     // IO_RMCR
        !           401:                return WriteRMCR(data);
        !           402: 
        !           403:         case 0x53:                                     // IO_DERA
        !           404:         case 0x60:                                     // IO_IODRA
        !           405:         case 0x61:                                     // IO_IODRB
        !           406:         case 0x62:                                     // IO_IODRC
        !           407:         case 0x63:                                     // IO_IODRD
        !           408:         case 0x64:                                     // IO_IODRE
        !           409:         case 0x65:                                     // IO_IODRF
        !           410:         case 0x66:                                     // IO_IDRG
        !           411:         case 0x70:                                     // IO_DDRA
        !           412:         case 0x71:                                     // IO_DDRB
        !           413:         case 0x72:                                     // IO_DDRC
        !           414:         case 0x73:                                     // IO_DDRD
        !           415:         case 0x74:                                     // IO_DDRE
        !           416:         case 0x75:                                     // IO_DDRF
        !           417:                break;
        !           418: 
        !           419:         default:
        !           420:                break;
        !           421:        }
        !           422: 
        !           423:        putlog(0, "WriteInternalIO %s <- $%02x (NOT IMPLEMENTED)",
        !           424:                IOName(offset).c_str(), data);
        !           425:        return 0;
        !           426: }
        !           427: 
        !           428: uint32
        !           429: MPU64180Device::WriteExternalIO(uint32 addr, uint32 data)
        !           430: {
        !           431:        // LUNA の外部 I/O はアドレスの上位バイト不問
        !           432:        switch (addr & 0xff) {
        !           433:         case 0x82:                                     // SSG
        !           434:         case 0x83:                                     // SSG
        !           435: #if !defined(ENABLE_SSG_LOG)
        !           436:                return 0;
        !           437: #endif
        !           438:                break;
        !           439: 
        !           440:         case 0x90:                                     // INT0 ネゲート
        !           441:                putlog(1, "%s Negate INT0", IOName(addr).c_str());
        !           442:                NegateINT0();
        !           443:                return 0;
        !           444: 
        !           445:         case 0xa0:                                     // レベル5 割り込み要求
        !           446:                putlog(1, "%s Interrupt High", IOName(addr).c_str());
        !           447:                pio0->InterruptXPHigh();
        !           448:                return 0;
        !           449: 
        !           450:         case 0xb0:                                     // レベル1 割り込み要求
        !           451:                putlog(1, "%s Interrupt Low", IOName(addr).c_str());
        !           452:                pio0->InterruptXPLow();
        !           453:                return 0;
        !           454: 
        !           455:         default:
        !           456:                break;
        !           457:        }
        !           458: 
        !           459:        putlog(0, "WriteExternalIO %s <- $%02x (NOT IMPLEMENTED)",
        !           460:                IOName(addr).c_str(), data);
        !           461:        return 0;
        !           462: }
        !           463: 
        !           464: uint32
        !           465: MPU64180Device::WriteTMDRL(int ch, uint32 data)
        !           466: {
        !           467:        auto& t = timer[ch];
        !           468:        if (t.running) {
        !           469:                // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる?
        !           470:                putlog(0, "Writing %s <- $%02x while timer is running! (ignored)",
        !           471:                        IOName(HD647180::IO_TMDRL(ch)).c_str(), data);
        !           472:        } else {
        !           473:                t.count = (t.count & 0xff00) | data;
        !           474:                putlog(1, "%s <- $%02x (TMDR%d = $%04x)",
        !           475:                        IOName(HD647180::IO_TMDRL(ch)).c_str(), data, ch, t.count);
        !           476:        }
        !           477:        return 0;
        !           478: }
        !           479: 
        !           480: uint32
        !           481: MPU64180Device::WriteTMDRH(int ch, uint32 data)
        !           482: {
        !           483:        auto& t = timer[ch];
        !           484:        if (t.running) {
        !           485:                // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる?
        !           486:                putlog(0, "Writing %s <- $%02x while timer is running! (ignored)",
        !           487:                        IOName(HD647180::IO_TMDRH(ch)).c_str(), data);
        !           488:        } else {
        !           489:                t.count = (data << 8) | (t.count & 0x00ff);
        !           490:                putlog(1, "%s <- $%02x (TMDR%d = $%04x)",
        !           491:                        IOName(HD647180::IO_TMDRH(ch)).c_str(), data, ch, t.count);
        !           492:        }
        !           493:        return 0;
        !           494: }
        !           495: 
        !           496: uint32
        !           497: MPU64180Device::WriteRLDRL(int ch, uint32 data)
        !           498: {
        !           499:        // 動作中にも変更可能
        !           500:        auto& t = timer[ch];
        !           501:        t.reload = (t.reload & 0xff00) | data;
        !           502:        putlog(1, "%s <- $%02x (RLDR%d = $%04x)",
        !           503:                IOName(HD647180::IO_RLDRL(ch)).c_str(), data, ch, t.reload);
        !           504:        return 0;
        !           505: }
        !           506: 
        !           507: uint32
        !           508: MPU64180Device::WriteRLDRH(int ch, uint32 data)
        !           509: {
        !           510:        // 動作中にも変更可能
        !           511:        auto& t = timer[ch];
        !           512:        t.reload = (data << 8) | (t.reload & 0x00ff);
        !           513:        putlog(1, "%s <- $%02x (RLDR%d = $%04x)",
        !           514:                IOName(HD647180::IO_RLDRH(ch)).c_str(), data, ch, t.reload);
        !           515:        return 0;
        !           516: }
        !           517: 
        !           518: uint32
        !           519: MPU64180Device::WriteTCR(uint32 data)
        !           520: {
        !           521:        std::array<bool, 2> new_tde;
        !           522:        std::string msg;
        !           523: 
        !           524:        timer[1].intr_enable = (data & 0x20);
        !           525:        timer[0].intr_enable = (data & 0x10);
        !           526:        // intr_enable を変更したので ChangeTimerInterrupt() を呼ぶのは
        !           527:        // 最後に行っている。
        !           528: 
        !           529:        timer_toc = (data >> 2) & 3;
        !           530: 
        !           531:        new_tde[1] = (data & 0x02);
        !           532:        new_tde[0] = (data & 0x01);
        !           533:        msg = string_format("TIE1=%d TIE0=%d TOC=$%d",
        !           534:                (timer[1].intr_enable ? 1 : 0),
        !           535:                (timer[0].intr_enable ? 1 : 0),
        !           536:                timer_toc);
        !           537: 
        !           538:        for (int ch = 0; ch < timer.size(); ch++) {
        !           539:                auto& t = timer[ch];
        !           540:                if (t.running == false && new_tde[ch] == true) {
        !           541:                        // カウントダウン開始
        !           542:                        t.count = t.reload;
        !           543:                        t.running = true;
        !           544:                        MakeActiveTimer();
        !           545:                        msg += string_format(" Timer%d=Start", ch);
        !           546:                        EnableTimer();
        !           547:                } else if (t.running == true && new_tde[ch] == false) {
        !           548:                        // カウントダウン停止
        !           549: 
        !           550:                        // ここではタイマーの状態を停止にするだけでよい。
        !           551:                        // タイマーイベントの中で running が落ちてたら停止してくれる。
        !           552:                        t.running = false;
        !           553:                        MakeActiveTimer();
        !           554:                        msg += string_format(" Timer%d=Stop", ch);
        !           555:                } else {
        !           556:                        // 変化なし
        !           557:                }
        !           558:        }
        !           559: 
        !           560:        putlog(1, "%s <- $%02x: %s",
        !           561:                IOName(HD647180::IO_TCR).c_str(), data, msg.c_str());
        !           562: 
        !           563:        // ログの順序的に書き込みログの後で変更する
        !           564:        ChangeTimerInterrupt();
        !           565: 
        !           566:        return 0;
        !           567: }
        !           568: 
        !           569: uint32
        !           570: MPU64180Device::WriteDCNTL(uint32 data)
        !           571: {
        !           572:        // メモリウェイト 0,1,2,3
        !           573:        memwait = (data >> 6) & 3;
        !           574: 
        !           575:        // I/O ウェイトは 0,2,3,4
        !           576:        iowait = (data >> 4) & 3;
        !           577:        if (iowait != 0)
        !           578:                iowait++;
        !           579: 
        !           580:        // 下位4ビット分は未実装
        !           581:        dcntl = data & 0x0f;
        !           582:        return 0;
        !           583: }
        !           584: 
        !           585: uint32
        !           586: MPU64180Device::WriteIL(uint32 data)
        !           587: {
        !           588:        // 書き込み時にマスクする
        !           589:        intvec_low = data & 0xe0;
        !           590:        return 0;
        !           591: }
        !           592: 
        !           593: uint32
        !           594: MPU64180Device::WriteITC(uint32 data)
        !           595: {
        !           596:        itc_trap = (data & 0x80);
        !           597:        // UFO は ReadOnly
        !           598:        itc_ite2 = (data & 0x04);
        !           599:        itc_ite1 = (data & 0x02);
        !           600:        itc_ite0 = (data & 0x01);
        !           601: 
        !           602:        // XXX 割り込み変わったら何かする?
        !           603: 
        !           604:        return 0;
        !           605: }
        !           606: 
        !           607: uint32
        !           608: MPU64180Device::WriteRCR(uint32 data)
        !           609: {
        !           610:        // 未実装
        !           611:        rcr = data | 0x3c;
        !           612: 
        !           613:        if ((rcr & 0x80)) {
        !           614:                // Refresh Enable は未実装。無効にするなら表示不要。
        !           615:                putlog(0, "%s <- $%02x: Refresh Enable (NOT IMPLEMENTED)",
        !           616:                        IOName(HD647180::IO_RCR).c_str(), data);
        !           617:        } else {
        !           618:                // ログレベル 1 なら全部表示
        !           619:                putlog(1, "%s <- $%02x (NOT IMPLEMENTED)",
        !           620:                        IOName(HD647180::IO_RCR).c_str(), data);
        !           621:        }
        !           622:        return 0;
        !           623: }
        !           624: 
        !           625: uint32
        !           626: MPU64180Device::WriteCBR(uint32 data)
        !           627: {
        !           628:        int lv;
        !           629:        uint32 new_base = data << 12;
        !           630:        if (commbase != new_base) {
        !           631:                lv = 1;
        !           632:                commbase = new_base;
        !           633:        } else {
        !           634:                lv = 2;
        !           635:        }
        !           636:        putlog(lv, "%s <- $%02x: Common Base Addr=$%05x",
        !           637:                IOName(HD647180::IO_CBR).c_str(), data, commbase);
        !           638:        return 0;
        !           639: }
        !           640: 
        !           641: uint32
        !           642: MPU64180Device::WriteBBR(uint32 data)
        !           643: {
        !           644:        int lv;
        !           645:        uint32 new_base = data << 12;
        !           646:        if (bankbase != new_base) {
        !           647:                lv = 1;
        !           648:                bankbase = new_base;
        !           649:        } else {
        !           650:                lv = 2;
        !           651:        }
        !           652:        putlog(lv, "%s <- $%02x: Bank Base Addr=$%05x",
        !           653:                IOName(HD647180::IO_BBR).c_str(), data, bankbase);
        !           654:        return 0;
        !           655: }
        !           656: 
        !           657: uint32
        !           658: MPU64180Device::WriteCBAR(uint32 data)
        !           659: {
        !           660:        int lv;
        !           661:        uint32 new_comm = (data & 0xf0) << 8;
        !           662:        uint32 new_bank = (data & 0x0f) << 12;
        !           663:        if (commarea != new_comm || bankarea != new_bank) {
        !           664:                lv = 1;
        !           665:                commarea = new_comm;
        !           666:                bankarea = new_bank;
        !           667:        } else {
        !           668:                lv = 2;
        !           669:        }
        !           670:        putlog(lv, "%s <- $%02x: CommArea=$%04x BankArea=$%04x",
        !           671:                IOName(HD647180::IO_CBAR).c_str(), data, commarea, bankarea);
        !           672:        return 0;
        !           673: }
        !           674: 
        !           675: uint32
        !           676: MPU64180Device::WriteICR(uint32 data)
        !           677: {
        !           678:        io_address = data & 0x80;
        !           679:        putlog(1, "%s <- $%02x: I/O Address=$%02x",
        !           680:                IOName(HD647180::IO_ICR).c_str(), data, io_address);
        !           681: 
        !           682:        // IOSTP は未実装
        !           683:        if ((data & 0x20) != 0) {
        !           684:                putlog(0, "%s IOSTP (NOT IMPLEMENTED)");
        !           685:        }
        !           686:        return 0;
        !           687: }
        !           688: 
        !           689: uint32
        !           690: MPU64180Device::WriteRMCR(uint32 data)
        !           691: {
        !           692:        xpbus->SetRMCR(data);
        !           693:        putlog(1, "%s <- $%02x: RAM address=$%05x",
        !           694:                IOName(HD647180::IO_RMCR).c_str(), data, xpbus->GetXPRAMAddr());
        !           695:        return 0;
        !           696: }
        !           697: 
        !           698: uint32
        !           699: MPU64180Device::PeekIO(uint32 addr)
        !           700: {
        !           701:        // 内蔵 I/O
        !           702:        if (io_address <= addr && addr < io_address + 0x80) {
        !           703:                return PeekInternalIO(addr - io_address);
        !           704:        }
        !           705: 
        !           706:        return PeekExternalIO(addr);
        !           707: }
        !           708: 
        !           709: uint32
        !           710: MPU64180Device::PeekInternalIO(uint32 offset)
        !           711: {
        !           712:        switch (offset) {
        !           713:         case 0x00:                                     // IO_CNTLA0
        !           714:         case 0x01:                                     // IO_CNTLA1
        !           715:         case 0x02:                                     // IO_CNTLB0
        !           716:         case 0x03:                                     // IO_CNTLB1
        !           717:         case 0x04:                                     // IO_STAT0
        !           718:         case 0x05:                                     // IO_STAT1
        !           719:         case 0x06:                                     // IO_TDR0
        !           720:         case 0x07:                                     // IO_TDR1
        !           721:         case 0x08:                                     // IO_TSR0
        !           722:         case 0x09:                                     // IO_TSR1
        !           723:         case 0x0a:                                     // IO_CNTR
        !           724:         case 0x0b:                                     // IO_TRDR
        !           725:                break;
        !           726: 
        !           727:         case 0x0c:                                     // IO_TMDR0L
        !           728:                return PeekTMDRL(0);
        !           729:         case 0x0d:                                     // IO_TMDR0H
        !           730:                return PeekTMDRH(0);
        !           731:         case 0x0e:                                     // IO_RLDR0L
        !           732:                return PeekRLDRL(0);
        !           733:         case 0x0f:                                     // IO_RLDR0H
        !           734:                return PeekRLDRH(0);
        !           735:         case 0x10:                                     // IO_TCR
        !           736:                return PeekTCR();
        !           737:         case 0x14:                                     // IO_TMDR1L
        !           738:                return PeekTMDRL(1);
        !           739:         case 0x15:                                     // IO_TMDR1H
        !           740:                return PeekTMDRH(1);
        !           741:         case 0x16:                                     // IO_RLDR1L
        !           742:                return PeekRLDRL(1);
        !           743:         case 0x17:                                     // IO_RLDR1H
        !           744:                return PeekRLDRH(1);
        !           745:         case 0x18:                                     // IO_FRC
        !           746:                return PeekFRC();
        !           747: 
        !           748:         case 0x20:                                     // IO_SAR0L
        !           749:         case 0x21:                                     // IO_SAR0H
        !           750:         case 0x22:                                     // IO_SAR0B
        !           751:         case 0x23:                                     // IO_DAR0L
        !           752:         case 0x24:                                     // IO_DAR0H
        !           753:         case 0x25:                                     // IO_DAR0B
        !           754:         case 0x26:                                     // IO_BCR0L
        !           755:         case 0x27:                                     // IO_BCR0H
        !           756:         case 0x28:                                     // IO_MAR1L
        !           757:         case 0x29:                                     // IO_MAR1H
        !           758:         case 0x2a:                                     // IO_MAR1B
        !           759:         case 0x2b:                                     // IO_IAR1L
        !           760:         case 0x2c:                                     // IO_IAR1H
        !           761:         case 0x2e:                                     // IO_BCR1L
        !           762:         case 0x2f:                                     // IO_BCR1H
        !           763:         case 0x30:                                     // IO_DSTAT
        !           764:         case 0x31:                                     // IO_DMODE
        !           765:                break;
        !           766:         case 0x32:                                     // IO_DCNTL
        !           767:                return PeekDCNTL();
        !           768: 
        !           769:         case 0x33:                                     // IO_IL
        !           770:                return PeekIL();
        !           771:         case 0x34:                                     // IO_ITC
        !           772:                return PeekITC();
        !           773:         case 0x36:                                     // IO_RCR
        !           774:                return PeekRCR();
        !           775: 
        !           776:         case 0x38:                                     // IO_CBR
        !           777:                return PeekCBR();
        !           778:         case 0x39:                                     // IO_BBR
        !           779:                return PeekBBR();
        !           780:         case 0x3a:                                     // IO_CBAR
        !           781:                return PeekCBAR();
        !           782: 
        !           783:         case 0x3e:                                     // IO_OMCR
        !           784:                break;
        !           785:         case 0x3f:                                     // IO_ICR
        !           786:                return PeekICR();
        !           787: 
        !           788:         case 0x40:                                     // IO_T2FRCL
        !           789:         case 0x41:                                     // IO_T2FRCH
        !           790:         case 0x42:                                     // IO_T2OCR1L
        !           791:         case 0x43:                                     // IO_T2OCR1H
        !           792:         case 0x44:                                     // IO_T2OCR2L
        !           793:         case 0x45:                                     // IO_T2OCR2H
        !           794:         case 0x46:                                     // IO_T2ICRL
        !           795:         case 0x47:                                     // IO_T2ICRH
        !           796:         case 0x48:                                     // IO_T2CSR1
        !           797:         case 0x49:                                     // IO_T2CSR2
        !           798:                break;
        !           799: 
        !           800:         case 0x50:                                     // IO_CCSR
        !           801:                break;
        !           802:         case 0x51:                                     // IO_RMCR
        !           803:                return xpbus->GetRMCR();
        !           804: 
        !           805:         case 0x53:                                     // IO_DERA
        !           806:         case 0x60:                                     // IO_IODRA
        !           807:         case 0x61:                                     // IO_IODRB
        !           808:         case 0x62:                                     // IO_IODRC
        !           809:         case 0x63:                                     // IO_IODRD
        !           810:         case 0x64:                                     // IO_IODRE
        !           811:         case 0x65:                                     // IO_IODRF
        !           812:         case 0x66:                                     // IO_IDRG
        !           813:         case 0x70:                                     // IO_DDRA
        !           814:         case 0x71:                                     // IO_DDRB
        !           815:         case 0x72:                                     // IO_DDRC
        !           816:         case 0x73:                                     // IO_DDRD
        !           817:         case 0x74:                                     // IO_DDRE
        !           818:         case 0x75:                                     // IO_DDRF
        !           819:                break;
        !           820: 
        !           821:         default:
        !           822:                break;
        !           823:        }
        !           824:        return 0xff;
        !           825: }
        !           826: 
        !           827: uint32
        !           828: MPU64180Device::PeekExternalIO(uint32 addr)
        !           829: {
        !           830:        // LUNA の外部 I/O はアドレスの上位バイト不問
        !           831:        switch (addr & 0xff) {
        !           832:         case 0x82:                                     // SSG
        !           833:         case 0x83:                                     // SSG
        !           834:                break;
        !           835: 
        !           836:         case 0x90:                                     // INT0 ネゲート
        !           837:                break;
        !           838: 
        !           839:         case 0xa0:                                     // レベル5 割り込み要求
        !           840:         case 0xb0:                                     // レベル1 割り込み要求
        !           841:                break;
        !           842: 
        !           843:         default:
        !           844:                break;
        !           845:        }
        !           846:        return 0xff;
        !           847: }
        !           848: 
        !           849: uint32
        !           850: MPU64180Device::PeekTMDRL(int ch) const
        !           851: {
        !           852:        return timer[ch].count & 0xff;
        !           853: }
        !           854: 
        !           855: uint32
        !           856: MPU64180Device::PeekTMDRH(int ch) const
        !           857: {
        !           858:        return timer[ch].count >> 8;
        !           859: }
        !           860: 
        !           861: uint32
        !           862: MPU64180Device::PeekRLDRL(int ch) const
        !           863: {
        !           864:        return timer[ch].reload & 0xff;
        !           865: }
        !           866: 
        !           867: uint32
        !           868: MPU64180Device::PeekRLDRH(int ch) const
        !           869: {
        !           870:        return timer[ch].reload >> 8;
        !           871: }
        !           872: 
        !           873: uint32
        !           874: MPU64180Device::PeekTCR() const
        !           875: {
        !           876:        uint32 data = (timer_toc << 2);
        !           877: 
        !           878:        if (timer[1].tif != 0)
        !           879:                data |= 0x80;
        !           880:        if (timer[0].tif != 0)
        !           881:                data |= 0x40;
        !           882:        if (timer[1].intr_enable)
        !           883:                data |= 0x20;
        !           884:        if (timer[0].intr_enable)
        !           885:                data |= 0x10;
        !           886:        if (timer[1].running)
        !           887:                data |= 0x02;
        !           888:        if (timer[0].running)
        !           889:                data |= 0x01;
        !           890: 
        !           891:        return data;
        !           892: }
        !           893: 
        !           894: uint32
        !           895: MPU64180Device::PeekFRC() const
        !           896: {
        !           897:        if (opmode == OpMode::Reset) {
        !           898:                return 0xff;
        !           899:        } else {
        !           900:                // Free Running Counter はリセット時に 0FFH で、
        !           901:                // そこから 10φ ごとに1ずつ減っていく。
        !           902:                // そのため、リセット時の時刻を覚えておき、経過時間から計算する。
        !           903:                uint64 time = scheduler->GetVirtTime() - timer_epoch;
        !           904:                return 0xff - (uint8)(time / (clock_nsec * 10));
        !           905:        }
        !           906: }
        !           907: 
        !           908: uint32
        !           909: MPU64180Device::PeekDCNTL() const
        !           910: {
        !           911:        uint32 data;
        !           912: 
        !           913:        data = (memwait << 6);
        !           914:        if (iowait != 0) {
        !           915:                data |= (iowait - 1) << 4;
        !           916:        }
        !           917:        data |= dcntl;
        !           918: 
        !           919:        return data;
        !           920: }
        !           921: 
        !           922: uint32
        !           923: MPU64180Device::PeekIL() const
        !           924: {
        !           925:        return intvec_low;
        !           926: }
        !           927: 
        !           928: uint32
        !           929: MPU64180Device::PeekITC() const
        !           930: {
        !           931:        uint32 data = 0x38;
        !           932:        if (itc_trap)
        !           933:                data |= 0x80;
        !           934:        if (itc_ufo)
        !           935:                data |= 0x40;
        !           936:        if (itc_ite2)
        !           937:                data |= 0x04;
        !           938:        if (itc_ite1)
        !           939:                data |= 0x02;
        !           940:        if (itc_ite0)
        !           941:                data |= 0x01;
        !           942:        return data;
        !           943: }
        !           944: 
        !           945: uint32
        !           946: MPU64180Device::PeekRCR() const
        !           947: {
        !           948:        return rcr;
        !           949: }
        !           950: 
        !           951: uint32
        !           952: MPU64180Device::PeekCBR() const
        !           953: {
        !           954:        return (commbase >> 12) & 0xff;
        !           955: }
        !           956: 
        !           957: uint32
        !           958: MPU64180Device::PeekBBR() const
        !           959: {
        !           960:        return (bankbase >> 12) & 0xff;
        !           961: }
        !           962: 
        !           963: uint32
        !           964: MPU64180Device::PeekCBAR() const
        !           965: {
        !           966:        uint32 data;
        !           967: 
        !           968:        data  = (commarea >>  8) & 0xf0;
        !           969:        data |= (bankarea >> 12) & 0x0f;
        !           970: 
        !           971:        return data;
        !           972: }
        !           973: 
        !           974: uint32
        !           975: MPU64180Device::PeekICR() const
        !           976: {
        !           977:        // IOSTP は未実装
        !           978:        return io_address | 0x5f;
        !           979: }
        !           980: 
        !           981: uint32
        !           982: MPU64180Device::PeekRMCR() const
        !           983: {
        !           984:        return xpbus->GetRMCR();
        !           985: }
        !           986: 
        !           987: // アドレス (とあれば名前) を返す。
        !           988: /*static*/ std::string
        !           989: MPU64180Device::IOName(uint32 addr)
        !           990: {
        !           991:        std::string buf;
        !           992: 
        !           993:        if (addr < 0x100) {
        !           994:                buf = string_format("%02XH", addr);
        !           995:        } else {
        !           996:                buf = string_format("%04XH", addr);
        !           997:        }
        !           998: 
        !           999:        if (addr < ionames.size() && ionames[addr] != NULL) {
        !          1000:                buf += '(';
        !          1001:                buf += ionames[addr];
        !          1002:                buf += ')';
        !          1003:        }
        !          1004:        return buf;
        !          1005: }
        !          1006: 
        !          1007: /*static*/ std::vector<const char *>
        !          1008: MPU64180Device::ionames = {
        !          1009:        "CNTLA0",       // 00
        !          1010:        "CNTLA1",       // 01
        !          1011:        "CNTLB0",       // 02
        !          1012:        "CNTLB1",       // 03
        !          1013:        "STAT0",        // 04
        !          1014:        "STAT1",        // 05
        !          1015:        "TDR0",         // 06
        !          1016:        "TDR1",         // 07
        !          1017:        "TSR0",         // 08
        !          1018:        "TSR1",         // 09
        !          1019:        "CNTR",         // 0a
        !          1020:        "TRDR",         // 0b
        !          1021:        "TMDR0L",       // 0c
        !          1022:        "TMDR0H",       // 0d
        !          1023:        "RLDR0L",       // 0e
        !          1024:        "RLDR0H",       // 0f
        !          1025: 
        !          1026:        "TCR",          // 10
        !          1027:        NULL,           // 11
        !          1028:        NULL,           // 12
        !          1029:        NULL,           // 13
        !          1030:        "TMDR1L",       // 14
        !          1031:        "TMDR1H",       // 15
        !          1032:        "RLDR1L",       // 16
        !          1033:        "RLDR1H",       // 17
        !          1034:        "FRFC",         // 18
        !          1035:        NULL,           // 19
        !          1036:        NULL,           // 1a
        !          1037:        NULL,           // 1b
        !          1038:        NULL,           // 1c
        !          1039:        NULL,           // 1d
        !          1040:        NULL,           // 1e
        !          1041:        NULL,           // 1f
        !          1042: 
        !          1043:        "SAR0L",        // 20
        !          1044:        "SAR0H",        // 21
        !          1045:        "SAR0B",        // 22
        !          1046:        "DAR0L",        // 23
        !          1047:        "DAR0H",        // 24
        !          1048:        "DAR0B",        // 25
        !          1049:        "BCR0L",        // 26
        !          1050:        "BCR0H",        // 27
        !          1051:        "MAR1L",        // 28
        !          1052:        "MAR1H",        // 29
        !          1053:        "MAR1B",        // 2a
        !          1054:        "IAR1L",        // 2b
        !          1055:        "IAR1H",        // 2c
        !          1056:        NULL,           // 2d
        !          1057:        "BCR1L",        // 2e
        !          1058:        "BCR1H",        // 2f
        !          1059: 
        !          1060:        "DSTAT",        // 30
        !          1061:        "DMODE",        // 31
        !          1062:        "DCNTL",        // 32
        !          1063:        "IL",           // 33
        !          1064:        "ITC",          // 34
        !          1065:        NULL,           // 35
        !          1066:        "RCR",          // 36
        !          1067:        NULL,           // 37
        !          1068:        "CBR",          // 38
        !          1069:        "BBR",          // 39
        !          1070:        "CBAR",         // 3a
        !          1071:        NULL,           // 3b
        !          1072:        NULL,           // 3c
        !          1073:        NULL,           // 3d
        !          1074:        "OMCR",         // 3e
        !          1075:        "ICR",          // 3f
        !          1076: 
        !          1077:        "T2FRCL",       // 40
        !          1078:        "T2FRCH",       // 41
        !          1079:        "T2OCR1L",      // 42
        !          1080:        "T2OCR1H",      // 43
        !          1081:        "T2OCR2L",      // 44
        !          1082:        "T2OCR2H",      // 45
        !          1083:        "T2ICRL",       // 46
        !          1084:        "T2ICRH",       // 47
        !          1085:        "T2CSR1",       // 48
        !          1086:        "T2CSR2",       // 49
        !          1087:        NULL,           // 4a
        !          1088:        NULL,           // 4b
        !          1089:        NULL,           // 4c
        !          1090:        NULL,           // 4d
        !          1091:        NULL,           // 4e
        !          1092:        NULL,           // 4f
        !          1093: 
        !          1094:        "CCSR",         // 50
        !          1095:        "RMCR",         // 51
        !          1096:        NULL,           // 52
        !          1097:        "DERA",         // 53
        !          1098:        NULL,           // 54
        !          1099:        NULL,           // 55
        !          1100:        NULL,           // 56
        !          1101:        NULL,           // 57
        !          1102:        NULL,           // 58
        !          1103:        NULL,           // 59
        !          1104:        NULL,           // 5a
        !          1105:        NULL,           // 5b
        !          1106:        NULL,           // 5c
        !          1107:        NULL,           // 5d
        !          1108:        NULL,           // 5e
        !          1109:        NULL,           // 5f
        !          1110: 
        !          1111:        "IODRA",        // 60
        !          1112:        "IODRB",        // 61
        !          1113:        "IODRC",        // 62
        !          1114:        "IODRD",        // 63
        !          1115:        "IODRE",        // 64
        !          1116:        "IODRF",        // 65
        !          1117:        "IDRG",         // 66
        !          1118:        NULL,           // 67
        !          1119:        NULL,           // 68
        !          1120:        NULL,           // 69
        !          1121:        NULL,           // 6a
        !          1122:        NULL,           // 6b
        !          1123:        NULL,           // 6c
        !          1124:        NULL,           // 6d
        !          1125:        NULL,           // 6e
        !          1126:        NULL,           // 6f
        !          1127: 
        !          1128:        "DDRA",         // 70
        !          1129:        "DDRB",         // 71
        !          1130:        "DDRC",         // 72
        !          1131:        "DDRD",         // 73
        !          1132:        "DDRE",         // 74
        !          1133:        "DDRF",         // 75
        !          1134: };

unix.superglobalmegacorp.com

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