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

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

unix.superglobalmegacorp.com

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