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

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "m88100.h"
                      8: #include "m88100excep.h"
                      9: #include "debugger.h"
                     10: #include "cvprompt.h"
                     11: #include "mpu.h"
                     12: 
                     13: #define OP_DEF(name)   void __CONCAT(m88kcpu::op_,name)()
                     14: #define OP_FUNC(name)  __CONCAT(op_,name)()
                     15: #include "m88100ops.cpp"
                     16: 
                     17: // リセット例外のようなもの?
                     18: void
1.1.1.5   root       19: m88kcpu::Reset()
1.1       root       20: {
1.1.1.4   root       21:        const uint32 Undefined = 0xcccccccc;
                     22: 
1.1.1.5   root       23:        // 内部の割り込み状態をクリア
                     24:        intr_pending = 0;
                     25: 
1.1.1.4   root       26:        // 履歴を初期化。リセット前の履歴いらんよな?
                     27:        exhist.Clear();
                     28:        brhist.Clear();
                     29: 
                     30:        // Table 6-8 (p6-47)
1.1       root       31:        psr = 0x800003ff;
1.1.1.4   root       32:        // XXX ただし SFU1 は未実装なので下げておく
1.1       root       33:        psr &= ~PSR_SFD1;
                     34: 
1.1.1.2   root       35: #if defined(TEST_INTERRUPT)
1.1.1.4   root       36:        psr &= ~PSR_IND;
                     37:        psr &= ~PSR_SFRZ;
1.1       root       38: #endif
                     39: 
1.1.1.4   root       40:        SetPSR();
1.1.1.2   root       41: 
1.1.1.4   root       42:        epsr = Undefined;
                     43:        // scoreboard: cleared
                     44:        ssbr = Undefined;
1.1.1.2   root       45: 
1.1       root       46:        // 実際には m88k MPU はリセット直後は 0 番地から実行を開始するので、
                     47:        // 大抵の場合システムでリセット直後は 0 番地付近に ROM を見せるように
                     48:        // してあるのだと思うが、ここではその代わりに ROM のアドレスを指定して、
                     49:        // 直接そこから実行を開始することにする。
                     50:        fip = reset_vector;
                     51:        nip = 0;
                     52:        xip = 0;
1.1.1.4   root       53:        sfip = Undefined;
                     54:        snip = Undefined;
                     55:        sxip = Undefined;
                     56: 
                     57:        vbr = 0;
                     58:        // DMTx は bit0(Valid) をクリア。他は不定。
                     59:        dmt0 &= ~DM_VALID;
                     60:        dmt1 &= ~DM_VALID;
                     61:        dmt2 &= ~DM_VALID;
                     62:        dma0 = Undefined;
                     63:        dma1 = Undefined;
                     64:        dma2 = Undefined;
                     65:        dmd0 = Undefined;
                     66:        dmd1 = Undefined;
                     67:        dmd2 = Undefined;
                     68:        for (int i = 1; i < 32; i++) {
                     69:                r[i] = Undefined;
                     70:        }
                     71: 
                     72:        fpecr = 0;
                     73:        for (int i = 1; i < 9; i++) {
                     74:                fcr[i] = Undefined;
                     75:        }
                     76:        fpcr = 0;
                     77:        fpsr = 0;
                     78: 
                     79:        cmmu[0].Reset();
                     80:        cmmu[1].Reset();
                     81: 
                     82:        // 履歴を初期化
                     83:        exhist.Clear();
                     84:        brhist.Clear();
                     85: 
                     86:        // 例外履歴に記録 (例外発生はブランチ履歴にも記録)
                     87:        // リセット例外発生時の from にはあまり意味がないので 0 にするか。
1.1.1.5   root       88:        exhist.AddEntry(0 | 1, 0, 0xfc000000 | 0);
                     89:        brhist.AddEntry(0 | 1, 0, 0xfc000000 | 0);
1.1.1.4   root       90:        // デバッガに通知 (例外ブレーク用)
                     91:        debugger_notify_exception(0);
1.1       root       92: 
                     93:        fetch();
                     94: }
                     95: 
1.1.1.5   root       96: // 仮想時間 delta [nsec] だけ CPU を実行する。実際には大抵行き過ぎる。
                     97: // 戻り値はフラグ。
                     98: //
                     99: // 戻る時に仮想時刻を確定させなくても構わない。スケジューラはこれを呼び出した
                    100: // 後に必然的に仮想時刻を取得することになるため、そこで確定させられる。
1.1       root      101: uint32
1.1.1.5   root      102: m88kcpu::Run(uint32 delta)
1.1       root      103: {
                    104:        bool is_release = false;
                    105:        bool is_intr = false;
                    106: 
1.1.1.5   root      107:        assert(used_cycle == 0);
                    108: 
                    109:        goal_cycle = Vtime2Cycle(delta);
                    110:        if (__predict_false(goal_cycle == 0)) {
                    111:                goal_cycle = 1;
                    112:        }
                    113: 
1.1.1.2   root      114:        if ((atomic_reqflag & CPU_REQ_STOP)) {
1.1.1.5   root      115:                if ((atomic_reqflag & (CPU_REQ_INTR | CPU_REQ_PROMPT | CPU_REQ_RESET))) {
                    116:                        // 割り込み、デバッガ、リセットが来たら STOP 解除。
                    117:                        atomic_reqflag &= ~CPU_REQ_STOP;
                    118:                } else {
1.1.1.2   root      119:                        // STOP 継続として戻る。
1.1.1.5   root      120:                        used_cycle = goal_cycle;
1.1.1.6 ! root      121:                        goto exit;
1.1.1.2   root      122:                }
                    123:        }
                    124: 
1.1       root      125:        while (!is_release) {
                    126:                // shift pipeline
                    127:                opX = opF;
                    128:                xip = nip;
                    129: 
                    130:                // prefetch next inst
                    131:                fetch();
                    132: 
                    133:                // この時点で実行しようとする命令が opX に入っている
                    134: 
                    135:                if (atomic_reqflag != 0) {
                    136:                        // 何かが起きた
                    137: 
1.1.1.5   root      138:                        if ((atomic_reqflag & CPU_REQ_RESET)) {
                    139:                                // リセット例外。
                    140:                                atomic_reqflag &= ~CPU_REQ_RESET;
                    141:                                Reset();
                    142:                                // XIP がリセットベクタを指すためにはもう一回フェッチが必要
                    143:                                // なので、ここは continue が必要。
                    144:                                continue;
                    145:                        }
                    146: 
1.1       root      147:                        // 割り込みの認識
                    148:                        // 割り込みの実行は命令実行完了後、次のプリフェッチの前
                    149:                        if ((atomic_reqflag & CPU_REQ_INTR)) {
                    150:                                atomic_reqflag &= ~CPU_REQ_INTR;
1.1.1.5   root      151:                                if (intr_pending && IsIntrEnable()) {
                    152:                                        // この命令のあとに割り込み処理
                    153:                                        is_intr = true;
                    154:                                }
1.1.1.2   root      155: #if defined(TEST_INTERRUPT)
1.1.1.4   root      156:                                atomic_reqflag |= CPU_REQ_PROMPT;
1.1       root      157: #endif
                    158:                        }
                    159: 
                    160:                        if ((atomic_reqflag & CPU_REQ_TRACE)) {
                    161:                                // デバッガプロンプトを出すかどうかを判断する
                    162:                                //inst_count++;
                    163:                                if (debugger_check()) {
                    164:                                        atomic_reqflag |= CPU_REQ_PROMPT;
                    165:                                }
                    166:                        }
                    167: 
                    168:                        if ((atomic_reqflag & CPU_REQ_PROMPT)) {
                    169:                                // デバッガプロンプトのための実行停止
                    170: 
                    171:                                // プロンプト獲得を通知
                    172:                                gCVPrompt->NotifyAcquire();
                    173: 
                    174:                                // プロンプト解放を待機
                    175:                                gCVPrompt->WaitRelease();
                    176: 
                    177:                                // プロンプトを抜けたのでここでフラグを落とす
                    178:                                atomic_reqflag &= ~CPU_REQ_PROMPT;
1.1.1.4   root      179: 
                    180:                                // プロンプトから戻ってきたら一旦スケジューラまで戻る(?)。
                    181:                                // reset コマンドのようにデバッガからスケジューラに出した
                    182:                                // リクエストを(なるはやで?)回収するため。
                    183:                                atomic_reqflag |= CPU_REQ_RELEASE;
1.1       root      184:                        }
                    185: 
                    186:                        if ((atomic_reqflag & CPU_REQ_RELEASE)) {
                    187:                                // 中断リクエスト受信
                    188:                                // この命令を実行し終わったら抜ける
                    189:                                atomic_reqflag &= ~CPU_REQ_RELEASE;
                    190:                                is_release = true;
                    191:                        }
                    192:                }
                    193: 
                    194:                if (OpIsBusErr(opX)) {
                    195:                        // プリフェッチしていた命令がバスエラー
                    196:                        Exception(M88K_EXCEP_INST);
                    197:                        continue;
                    198:                }
                    199: 
                    200:                uint32 op12 = op32_to_12(opX);
                    201: 
                    202:                switch (op12) {
                    203: #include "m88100switch.inc"
                    204:                 default:
1.1.1.2   root      205:                        OP_FUNC(illegal);
                    206:                        break;
1.1       root      207:                }
                    208: 
1.1.1.5   root      209:                if (is_intr && IsIntrEnable()) {
                    210:                        // 割り込み処理要求が来ていて、直前の命令が割り込みを禁止していなければ割り込み
                    211:                        // XXX 実際は違う気がする
                    212:                        is_intr = false;
                    213:                        gMPU->putlog(4, "INTR take");
                    214:                        ExceptionCore(M88K_EXCEP_INTERRUPT, ExceptionKind::INTR);
                    215:                        continue;
1.1       root      216:                }
                    217: 
1.1.1.5   root      218:                used_cycle++;
1.1.1.2   root      219: 
                    220:                if ((atomic_reqflag & CPU_REQ_STOP)) {
                    221:                        // STOP 状態は、残りサイクルを消費したことにして戻る
                    222:                        gMPU->putlog(2, "STOP 状態検出");
1.1.1.6 ! root      223:                        if (used_cycle < goal_cycle) {
        !           224:                                used_cycle = goal_cycle;
        !           225:                        }
1.1.1.2   root      226:                }
                    227: 
1.1.1.5   root      228:                if (used_cycle >= goal_cycle)
1.1       root      229:                        break;
                    230:        }
                    231: 
1.1.1.6 ! root      232:  exit:
1.1.1.5   root      233:        total_vtime += Cycle2Vtime(used_cycle);
                    234:        used_cycle = 0;
                    235: 
1.1.1.6 ! root      236:        return atomic_reqflag;
1.1.1.5   root      237: }
                    238: 
1.1       root      239: // この命令後に実行を中断して VM に戻る
                    240: void
                    241: m88kcpu::Release()
                    242: {
                    243:        atomic_reqflag |= CPU_REQ_RELEASE;
                    244: }
                    245: 
1.1.1.5   root      246: // リセット例外を発行する
                    247: void
                    248: m88kcpu::RequestReset()
                    249: {
                    250:        atomic_reqflag |= CPU_REQ_RESET;
                    251: }
                    252: 
1.1       root      253: // 通常の例外。
1.1.1.2   root      254: // DataAccessException, エラー、割り込み、TRAP からは使わない。
1.1       root      255: // vec はベクタ番号。
                    256: void
                    257: m88kcpu::Exception(int vec)
                    258: {
                    259:        ExceptionCore(vec, ExceptionKind::NORMAL);
                    260: }
                    261: 
                    262: // 例外処理コア部分
                    263: // vec はベクタ番号。
                    264: void
                    265: m88kcpu::ExceptionCore(int vec, ExceptionKind cause)
                    266: {
1.1.1.4   root      267:        uint syscall = 0;
                    268: 
1.1.1.3   root      269:        // 例外履歴に記録 (例外発生はブランチ履歴にも記録)
1.1.1.4   root      270:        // OpenBSD システムコールなら番号もついでに記録。
                    271:        // システムコール番号は tb0 発行時点で r13 にセットされている。
                    272:        // ただし 0 番は syscall(2) (間接システムコール) で、実際の番号は r2。
                    273:        // 198番 __syscall(2) だと r2:r3 (なので実質 r3)。
                    274:        if (vec == 450) {
                    275:                syscall = r[13];
                    276:                if (syscall == 0) {
                    277:                        syscall = r[2];
                    278:                } else if (syscall == 198) {
                    279:                        syscall = r[3];
                    280:                }
                    281:                syscall &= 0xfff;
                    282:        }
1.1.1.5   root      283:        uint32 from = xip | (IsSuper() ? 1 : 0);
                    284:        uint32 inst = 0xfc000000 | (syscall << 12) | vec;
                    285:        exhist.AddEntry(from, 0, inst);
                    286:        brhist.AddEntry(from, 0, inst);
1.1.1.3   root      287:        // デバッガに通知 (例外ブレーク用)
1.1.1.4   root      288:        debugger_notify_exception(vec);
                    289: 
                    290:        // 命令中で起きる例外はとりあえず全部2クロック追加? (Table.7-5)
                    291:        if (cause != ExceptionKind::INTR) {
1.1.1.5   root      292:                AddCycle(2);
1.1.1.4   root      293:        }
1.1.1.3   root      294: 
1.1       root      295:        if (psr & PSR_SFRZ) {
                    296:                if (cause != ExceptionKind::TRAP) {
                    297:                        gMPU->putlog(2, "SFRZ Error Exception");
                    298:                        vec = M88K_EXCEP_ERROR;
                    299:                        cause = ExceptionKind::ERROR;
                    300:                }
                    301:        } else {
                    302:                gMPU->putlog(2, "Exception %x", vec);
1.1.1.2   root      303:                if (vec != 1) {
                    304:                        gMPU->putlog(1, "Exception %x x=%x n=%x f=%x", vec, xip, nip, fip);
                    305:                }
1.1       root      306:                sxip = xip;
                    307:                snip = nip;
                    308:                sfip = fip; 
                    309: 
                    310:                sxip |= SIP_V;
                    311:                snip |= SIP_V;
1.1.1.4   root      312:                sfip |= SIP_V;
1.1       root      313: 
                    314:                if (OpIsBusErr(opX)) {
                    315:                        sxip |= SIP_E;  // E bit
                    316:                }
                    317:                if (OpIsBusErr(opF)) {
                    318:                        snip |= SIP_E;  // E bit
                    319:                }
                    320: 
                    321:                if (vec == M88K_EXCEP_UNIMPL_OP) {
                    322:                        sxip &= ~SIP_V;
                    323:                }
                    324:        }
                    325: 
1.1.1.2   root      326:        if (cause != ExceptionKind::DATA) {
                    327:                // データアクセス例外以外は、
                    328:                // データパイプラインはフラッシュ状態とする。
                    329:                // ほんとうは違う。かも。
                    330:                dmt0 = 0;
                    331:        } else {
                    332:                // xip: ld/st/xmem
                    333:                // nip: next
                    334:                // fip: fetch
                    335: 
                    336:                // rom1.2 は DAE が起きると、
                    337: 
                    338:                // ROM挙動               CPU の RTE 挙動
                    339:                // sfip = sxip
                    340:                // sxip -> ~V (INVALID)  CPU はそもそも sxip を評価しない
                    341:                // snip = 0 (INVALID)    CPU はこれを nop 相当に処理する
                    342:                // rte
                    343: 
                    344:                // してくる。そのまま読むと命令を再実行しようとしているように
                    345:                // 読めるが、再実行すると無限ループになってしまう。
                    346:                // DAE の時点で xip が進んでいることを期待して利用している?
                    347: 
                    348:                // openbsd は
                    349:                // xmem の write バスエラーを検知すると命令を再実行するために
                    350:                // fip = nip, nip = xip して rte する。ということは xip = xmem に
                    351:                // なっていることを期待している。
                    352: 
                    353:                // というわけで
                    354:                // ld で DataAccessException のときは、実CPUはすでに次の命令を
                    355:                // 実行している?
                    356:                // もう少し考えると、スコアボードでレジスタの干渉がなければ、
                    357:                // 実行している?
                    358: 
                    359:                // 仕方がないのでハックでごまかす。
                    360:                // rte のほうも参照のこと。
                    361: 
                    362:                if (IsSuper() && xip >= 0x41000000 && xip < 0x42000000) {
                    363:                        // 遅延例外機構がないので、ROM 合わせのハック。
                    364:                        sxip = snip;
                    365:                }
                    366:        }
                    367: 
1.1       root      368:        epsr = psr;
1.1.1.2   root      369:        SetPSR(psr | PSR_SUPER | PSR_SFD1 | PSR_IND | PSR_SFRZ);
1.1       root      370: 
                    371:        fip = vbr + (vec << 3);
                    372:        fetch();
1.1.1.3   root      373:        // ここでベクタに飛ぶのだが、ベクタ内の2命令でおそらく必ずもう一度
                    374:        // 分岐してそっちでも履歴が残るので、ここでブランチ履歴を残すのは
                    375:        // ちょっと冗長という気もする。
                    376: 
1.1       root      377:        if (OpIsBusErr(opF)) {
                    378:                if (cause == ExceptionKind::ERROR) {
                    379:                        // double bus fault
                    380:                        // 実機は無限ループ状態
                    381:                        PANIC("Infinite ERROR (double bus fault)");
                    382:                } else {
                    383:                        ExceptionCore(M88K_EXCEP_ERROR, ExceptionKind::ERROR);
                    384:                }
                    385:        }
                    386: }
                    387: 
1.1.1.5   root      388: inline
                    389: uint32
                    390: m88kcpu::Calcdmt(uint32 flag)
                    391: {
                    392:        return
                    393:                   ((psr & PSR_BO_LE) ? DM_BO : 0)
                    394:             | ((IsSuper() && !(flag & DM_USR)) ? DM_DAS : 0)
                    395:             | DM_VALID;
                    396: }
                    397: 
1.1       root      398: // データアクセス例外(Read)
1.1.1.5   root      399: // ld.b, ld.h, ld.hu, ld 用
1.1       root      400: void
1.1.1.5   root      401: m88kcpu::ReadDataException32(uint32 addr, uint32 flag)
1.1       root      402: {
                    403:        // ミスアラインドはこの例外より前にチェックされていて、
                    404:        // ここにはアラインドしかこない。
                    405:        dma0 = addr & ~0x3;
1.1.1.5   root      406:        dmt0 = Calcdmt(flag)
1.1       root      407:             | (FLD_D << 7)
                    408:             | (flag & DM_SIGNED)
                    409:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
1.1.1.5   root      410:        ;
                    411:        dmt1 &= ~DM_VALID;
                    412:        dmt2 &= ~DM_VALID;
1.1.1.2   root      413:        gMPU->putlog(1, "ReadDAE xip=%x addr=%x", xip, addr);
                    414:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
1.1       root      415: }
                    416: 
1.1.1.5   root      417: // データアクセス例外(Read)
                    418: // ld.d 用
                    419: void
                    420: m88kcpu::ReadDataException64(uint32 addr, uint32 flag)
                    421: {
                    422:        // ミスアラインドはこの例外より前にチェックされていて、
                    423:        // ここにはアラインドしかこない。
                    424:        dma0 = addr;
                    425:        dmt0 = Calcdmt(flag)
                    426:             | DM_DOUB1                 // ダブルワードの第1アクセスのときセット
                    427:             | (FLD_D << 7)
                    428:             | DM_EN_MASK               // 32ビット有効
                    429:        ;
                    430: 
                    431:        dma1 = dma0 + 4;
                    432:        dmt1 = Calcdmt(flag)
                    433:             | (FLD_D2 << 7)
                    434:             | DM_EN_MASK                       // 32ビット有効
                    435:        ;
                    436: 
                    437:        dmt2 &= ~DM_VALID;
                    438: 
                    439:        if ((flag & DM_DOUB1) == 0) {
                    440:                // .d の2ワード目がバスエラー。第1ワードのアクセスは成功した。
                    441:                dmt0 &= ~DM_VALID;
                    442:        }
                    443: 
                    444:        gMPU->putlog(1, "ReadDAE64 xip=%x addr=%x", xip, addr);
                    445:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
                    446: }
                    447: 
1.1       root      448: // データアクセス例外(Write)
1.1.1.5   root      449: // st.b, st.h, st.hu, st 用
1.1       root      450: void
1.1.1.5   root      451: m88kcpu::WriteDataException32(uint32 addr, uint32 flag)
1.1       root      452: {
                    453:        // ミスアラインドはこの例外より前にチェックされていて、
                    454:        // ここにはアラインドしかこない。
                    455:        dma0 = addr & ~0x3;
1.1.1.5   root      456:        dmt0 = Calcdmt(flag)
1.1       root      457:             | (FLD_D << 7)
                    458:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
                    459:             | DM_WRITE
1.1.1.5   root      460:        ;
                    461:        dmd0 = rD;
1.1       root      462: 
1.1.1.5   root      463:        dmt1 &= ~DM_VALID;
                    464:        dmt2 &= ~DM_VALID;
1.1.1.2   root      465:        gMPU->putlog(1, "WriteDAE xip=%x addr=%x", xip, addr);
                    466:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
                    467: }
                    468: 
1.1.1.5   root      469: // データアクセス例外(Write)
                    470: // st.d 用
                    471: void
                    472: m88kcpu::WriteDataException64(uint32 addr, uint32 flag)
                    473: {
                    474:        // ミスアラインドはこの例外より前にチェックされていて、
                    475:        // ここにはアラインドしかこない。
                    476:        dma0 = addr & ~0x3;
                    477:        dmt0 = Calcdmt(flag)
                    478:             | DM_DOUB1         // ダブルワードの第1アクセスのときセット
                    479:             | (FLD_D << 7)
                    480:             | DM_EN_MASK
                    481:             | DM_WRITE
                    482:        ;
                    483:        dmd0 = rD;
                    484: 
                    485:        dma1 = dma0 + 4;
                    486:        dmt1 = Calcdmt(flag)
                    487:             | (FLD_D2 << 7)
                    488:             | DM_EN_MASK
                    489:             | DM_WRITE
                    490:        ;
                    491:        dmd1 = rD2;
                    492: 
                    493:        dmt2 &= ~DM_VALID;
                    494: 
                    495:        if ((flag & DM_DOUB1) == 0) {
                    496:                // .d の2ワード目がバスエラー。第1ワードのアクセスは成功した。
                    497:                dmt0 &= ~DM_VALID;
                    498:        }
                    499: 
                    500:        gMPU->putlog(1, "WriteDAE64 xip=%x addr=%x", xip, addr);
                    501:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
                    502: }
                    503: 
1.1.1.2   root      504: // データアクセス例外(xmem)
1.1.1.5   root      505: // xmem には .d は無い
1.1.1.2   root      506: void
1.1.1.5   root      507: m88kcpu::XmemDataException(uint32 addr, uint32 flag)
1.1.1.2   root      508: {
                    509:        dma0 = addr & ~0x3;
1.1.1.5   root      510:        dmt0 = Calcdmt(flag)
                    511:             | DM_LOCK          // xmem でセット
1.1.1.2   root      512:             | (FLD_D << 7)
                    513:             | (flag & DM_SIGNED)
                    514:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
1.1.1.5   root      515:        ;
1.1.1.2   root      516: 
1.1.1.5   root      517:        dma1 = dma0;
                    518:        dmt1 = Calcdmt(flag)
                    519:             | DM_LOCK          // xmem でセット
1.1.1.2   root      520:             | (FLD_D << 7)
                    521:             | (flag & DM_SIGNED)
                    522:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
                    523:             | DM_WRITE
1.1.1.5   root      524:        ;
                    525:        dmd1 = rD;
1.1.1.2   root      526: 
1.1.1.5   root      527:        dmt2 &= ~DM_VALID;
1.1.1.2   root      528: 
                    529:        // ミスアラインドはこの例外より前にチェックされていて、
                    530:        // ここにはアラインドしかこない。
                    531:        if (cmmu[1].fault_code != m88200::FAULT_CODE_BUSERR
                    532:         || cmmu[1].acc_read) {
                    533:                // アドレス変換フォルトまたは read 時点
                    534:                // nop
1.1       root      535:        } else {
1.1.1.2   root      536:                // xmem の write 時点
1.1.1.5   root      537:                dmt0 &= ~DM_VALID;
1.1       root      538:        }
1.1.1.2   root      539: 
                    540:        gMPU->putlog(1, "xmemDAE xip=%x addr=%x", xip, addr);
                    541:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
1.1       root      542: }
                    543: 
1.1.1.5   root      544: // FP 例外
                    545: // fpex: FP例外コード M88K_FPEXCEP
                    546: void
                    547: m88kcpu::FPException(int fpex)
                    548: {
                    549:        // FDVZ 以上の例外が PRECISE。
                    550:        // 未満の FUNF, FOVF, FINX は IMPRECISE。
                    551:        int vec = (fpex >= M88K_FPEXCEP_FDVZ) ? M88K_EXCEP_SFU1_PRECISE : M88K_EXCEP_SFU1_IMPRECISE;
                    552:        fpecr = fpex;
                    553: 
                    554:        Exception(vec);
                    555: }
                    556: 
1.1       root      557: void
1.1.1.5   root      558: m88kcpu::Interrupt(int level)
1.1       root      559: {
1.1.1.5   root      560:        // level は 0 か 1。
                    561:        intr_pending = level;
1.1       root      562:        atomic_reqflag |= CPU_REQ_INTR;
                    563: }
                    564: 
                    565: void
                    566: m88kcpu::fpu_unimpl()
                    567: {
                    568:        printf("%s\n", __func__);
1.1.1.5   root      569:        FPException(M88K_FPEXCEP_FUNIMP);
1.1       root      570: }
1.1.1.2   root      571: 
                    572: OP_DEF(illegal)
                    573: {
                    574:        // 本来は不当命令例外?
                    575:        gMPU->putlog(0, "Illegal instruction %08x", (uint32)opX);
                    576: }

unix.superglobalmegacorp.com

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