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

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

unix.superglobalmegacorp.com

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