Annotation of nono/m88xx0/m88100core.cpp, revision 1.1.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.