Annotation of nono/m88xx0/m88100core.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2020 [email protected]
        !             4: //
        !             5: 
        !             6: #include "m88100.h"
        !             7: #include "m88100excep.h"
        !             8: #include "debugger.h"
        !             9: #include "cvprompt.h"
        !            10: #include "mpu.h"
        !            11: 
        !            12: #define OP_DEF(name)   void __CONCAT(m88kcpu::op_,name)()
        !            13: #define OP_FUNC(name)  __CONCAT(op_,name)()
        !            14: #include "m88100ops.cpp"
        !            15: 
        !            16: // リセット例外のようなもの?
        !            17: void
        !            18: m88kcpu::Reset(uint32 reset_vector)
        !            19: {
        !            20:        // TODO: 未完成
        !            21:        psr = 0x800003ff;
        !            22:        // SFD1 = 0;
        !            23:        psr &= ~PSR_SFD1;
        !            24: 
        !            25: #if TEST_INTERRUPT
        !            26: psr &= ~PSR_IND;
        !            27: psr &= ~PSR_SFRZ;
        !            28: #endif
        !            29: 
        !            30:        vbr = 0;
        !            31: 
        !            32:        // 実際には m88k MPU はリセット直後は 0 番地から実行を開始するので、
        !            33:        // 大抵の場合システムでリセット直後は 0 番地付近に ROM を見せるように
        !            34:        // してあるのだと思うが、ここではその代わりに ROM のアドレスを指定して、
        !            35:        // 直接そこから実行を開始することにする。
        !            36:        fip = reset_vector;
        !            37:        nip = 0;
        !            38:        xip = 0;
        !            39: 
        !            40:        fetch();
        !            41: }
        !            42: 
        !            43: // request サイクル分実行する。
        !            44: uint32
        !            45: m88kcpu::Run(uint64 request)
        !            46: {
        !            47:        uint64 goal_cycle = total_cycle + request;
        !            48:        bool is_release = false;
        !            49:        bool is_intr = false;
        !            50: 
        !            51:        while (!is_release) {
        !            52:                // shift pipeline
        !            53:                opX = opF;
        !            54:                xip = nip;
        !            55: 
        !            56:                // prefetch next inst
        !            57:                fetch();
        !            58: 
        !            59:                // この時点で実行しようとする命令が opX に入っている
        !            60: 
        !            61:                if (atomic_reqflag != 0) {
        !            62:                        // 何かが起きた
        !            63: 
        !            64:                        // 割り込みの認識
        !            65:                        // 割り込みの実行は命令実行完了後、次のプリフェッチの前
        !            66:                        if ((atomic_reqflag & CPU_REQ_INTR)) {
        !            67:                                atomic_reqflag &= ~CPU_REQ_INTR;
        !            68:                                is_intr = true;
        !            69: #if TEST_INTERRUPT
        !            70:                                        atomic_reqflag |= CPU_REQ_PROMPT;
        !            71: #endif
        !            72:                        }
        !            73: 
        !            74:                        if ((atomic_reqflag & CPU_REQ_TRACE)) {
        !            75:                                // デバッガプロンプトを出すかどうかを判断する
        !            76:                                //inst_count++;
        !            77:                                if (debugger_check()) {
        !            78:                                        atomic_reqflag |= CPU_REQ_PROMPT;
        !            79:                                }
        !            80:                        }
        !            81: 
        !            82:                        if ((atomic_reqflag & CPU_REQ_PROMPT)) {
        !            83:                                // デバッガプロンプトのための実行停止
        !            84: 
        !            85:                                // プロンプト獲得を通知
        !            86:                                gCVPrompt->NotifyAcquire();
        !            87: 
        !            88:                                // プロンプト解放を待機
        !            89:                                gCVPrompt->WaitRelease();
        !            90: 
        !            91:                                // プロンプトを抜けたのでここでフラグを落とす
        !            92:                                atomic_reqflag &= ~CPU_REQ_PROMPT;
        !            93:                        }
        !            94: 
        !            95:                        if ((atomic_reqflag & CPU_REQ_RELEASE)) {
        !            96:                                // 中断リクエスト受信
        !            97:                                // この命令を実行し終わったら抜ける
        !            98:                                atomic_reqflag &= ~CPU_REQ_RELEASE;
        !            99:                                is_release = true;
        !           100:                        }
        !           101:                }
        !           102: 
        !           103:                if (OpIsBusErr(opX)) {
        !           104:                        // プリフェッチしていた命令がバスエラー
        !           105:                        Exception(M88K_EXCEP_INST);
        !           106:                        continue;
        !           107:                }
        !           108: 
        !           109:                uint32 op12 = op32_to_12(opX);
        !           110: 
        !           111:                switch (op12) {
        !           112: #include "m88100switch.inc"
        !           113:                 default:
        !           114:                        __unreachable();
        !           115:                }
        !           116: 
        !           117:                if (is_intr) {
        !           118:                        is_intr = false;
        !           119:                        if (!(psr & PSR_IND)) {
        !           120:                                gMPU->putlog(4, "INTR take");
        !           121:                                ExceptionCore(M88K_EXCEP_INTERRUPT, ExceptionKind::INTR);
        !           122:                                continue;
        !           123:                        } else {
        !           124:                                gMPU->putlog(4, "INTR DISABLE");
        !           125:                        }
        !           126:                }
        !           127: 
        !           128:                total_cycle++;
        !           129:                if (total_cycle >= goal_cycle)
        !           130:                        break;
        !           131:        }
        !           132: 
        !           133:        return atomic_reqflag;
        !           134: }
        !           135: 
        !           136: // この命令後に実行を中断して VM に戻る
        !           137: void
        !           138: m88kcpu::Release()
        !           139: {
        !           140:        atomic_reqflag |= CPU_REQ_RELEASE;
        !           141: }
        !           142: 
        !           143: // 通常の例外。
        !           144: // エラー、割り込み、TRAP からは使いません。
        !           145: // vec はベクタ番号。
        !           146: void
        !           147: m88kcpu::Exception(int vec)
        !           148: {
        !           149:        ExceptionCore(vec, ExceptionKind::NORMAL);
        !           150: }
        !           151: 
        !           152: // 例外処理コア部分
        !           153: // vec はベクタ番号。
        !           154: void
        !           155: m88kcpu::ExceptionCore(int vec, ExceptionKind cause)
        !           156: {
        !           157:        if (psr & PSR_SFRZ) {
        !           158:                if (cause != ExceptionKind::TRAP) {
        !           159:                        gMPU->putlog(2, "SFRZ Error Exception");
        !           160:                        vec = M88K_EXCEP_ERROR;
        !           161:                        cause = ExceptionKind::ERROR;
        !           162:                }
        !           163:        } else {
        !           164:                gMPU->putlog(2, "Exception %x", vec);
        !           165:                sxip = xip;
        !           166:                snip = nip;
        !           167:                sfip = fip; 
        !           168: 
        !           169:                sxip |= SIP_V;
        !           170:                snip |= SIP_V;
        !           171:                // XXX:実機と異なり、fip は常にフェッチ前なので V=0
        !           172:                // ^^^^ コレ自体怪しい. INTERRUPT とか。
        !           173:                // でもたぶん例外ハンドラでここのビット見ないだろうなあ
        !           174: 
        !           175:                if (OpIsBusErr(opX)) {
        !           176:                        sxip |= SIP_E;  // E bit
        !           177:                }
        !           178:                if (OpIsBusErr(opF)) {
        !           179:                        snip |= SIP_E;  // E bit
        !           180:                }
        !           181: 
        !           182:                if (vec == M88K_EXCEP_UNIMPL_OP) {
        !           183:                        sxip &= ~SIP_V;
        !           184:                }
        !           185:        }
        !           186: 
        !           187:        epsr = psr;
        !           188:        psr |= PSR_SUPER | PSR_SFD1 | PSR_IND | PSR_SFRZ;
        !           189: 
        !           190:        fip = vbr + (vec << 3);
        !           191:        fetch();
        !           192:        if (OpIsBusErr(opF)) {
        !           193:                if (cause == ExceptionKind::ERROR) {
        !           194:                        // double bus fault
        !           195:                        // 実機は無限ループ状態
        !           196:                        PANIC("Infinite ERROR (double bus fault)");
        !           197:                } else {
        !           198:                        ExceptionCore(M88K_EXCEP_ERROR, ExceptionKind::ERROR);
        !           199:                }
        !           200:        }
        !           201: }
        !           202: 
        !           203: // データアクセス例外(Read)
        !           204: void
        !           205: m88kcpu::ReadDataException(uint32 addr, uint32 flag)
        !           206: {
        !           207:        // ミスアラインドはこの例外より前にチェックされていて、
        !           208:        // ここにはアラインドしかこない。
        !           209:        dma0 = addr & ~0x3;
        !           210:        dmt0 = ((psr & PSR_BO_LE) ? DM_BO : 0)
        !           211:             | (((psr & PSR_SUPER) && !(flag & DM_USR)) ? DM_DAS : 0)
        !           212:             | (flag & DM_DOUB1)        // ダブルワードの第1アクセスのときセット
        !           213:             | (flag & DM_LOCK)         // xmem でセット
        !           214:             | (FLD_D << 7)
        !           215:             | (flag & DM_SIGNED)
        !           216:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
        !           217:             | 0 // DM_WRITE = 0
        !           218:             | DM_VALID;
        !           219:        Exception(M88K_EXCEP_DATA);
        !           220: }
        !           221: 
        !           222: // データアクセス例外(Write)
        !           223: void
        !           224: m88kcpu::WriteDataException(uint32 addr, uint32 data, uint32 flag)
        !           225: {
        !           226:        // ミスアラインドはこの例外より前にチェックされていて、
        !           227:        // ここにはアラインドしかこない。
        !           228:        dma0 = addr & ~0x3;
        !           229:        dmt0 = ((psr & PSR_BO_LE) ? DM_BO : 0)
        !           230:             | (((psr & PSR_SUPER) && !(flag & DM_USR)) ? DM_DAS : 0)
        !           231:             | (flag & DM_DOUB1)        // ダブルワードの第1アクセスのときセット
        !           232:             | (flag & DM_LOCK)         // xmem でセット
        !           233:             | (FLD_D << 7)
        !           234:             | (flag & DM_SIGNED)
        !           235:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
        !           236:             | DM_WRITE
        !           237:             | DM_VALID;
        !           238: 
        !           239:        // dmd は Byte Enable 位置に配置される
        !           240:        if (flag & DM_SIZE_B) {
        !           241:                dmd0 = data << ((3 - (addr & 0x03)) * 8);
        !           242:        } else if (flag & DM_SIZE_H) {
        !           243:                dmd0 = data << ((2 - (addr & 0x03)) * 16);
        !           244:        } else {
        !           245:                dmd0 = data;
        !           246:        }
        !           247:        Exception(M88K_EXCEP_DATA);
        !           248: }
        !           249: 
        !           250: void
        !           251: m88kcpu::Interrupt()
        !           252: {
        !           253:        atomic_reqflag |= CPU_REQ_INTR;
        !           254:        gMPU->putlog(4, "INTERRUPT ACK (アドレスは不正確)");
        !           255: }
        !           256: 
        !           257: void
        !           258: m88kcpu::fpu_unimpl()
        !           259: {
        !           260:        printf("%s\n", __func__);
        !           261: }

unix.superglobalmegacorp.com

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