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

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.9 ! root      215:                // XXX 命令の実行でリリースするのに、いったんループを回って
        !           216:                // からではタイミングが遅すぎる
        !           217:                if ((atomic_reqflag & CPU_REQ_RELEASE)) {
        !           218:                        // 中断リクエスト受信
        !           219:                        // この命令を実行し終わったら抜ける
        !           220:                        atomic_reqflag &= ~CPU_REQ_RELEASE;
        !           221:                        is_release = true;
        !           222:                }
        !           223: 
1.1.1.5   root      224:                if (used_cycle >= goal_cycle)
1.1       root      225:                        break;
                    226:        }
                    227: 
1.1.1.6   root      228:  exit:
1.1.1.5   root      229:        total_vtime += Cycle2Vtime(used_cycle);
                    230:        used_cycle = 0;
                    231: 
1.1.1.7   root      232:        // HALT 状態がないので NORMAL か STOP かだけでいい
                    233:        return (atomic_reqflag & CPU_REQ_STOP)
                    234:                ? Scheduler::SCHED_CPU_STOP
                    235:                : Scheduler::SCHED_CPU_NORMAL;
1.1.1.5   root      236: }
                    237: 
1.1       root      238: // この命令後に実行を中断して VM に戻る
                    239: void
                    240: m88kcpu::Release()
                    241: {
                    242:        atomic_reqflag |= CPU_REQ_RELEASE;
                    243: }
                    244: 
1.1.1.5   root      245: // リセット例外を発行する
                    246: void
                    247: m88kcpu::RequestReset()
                    248: {
                    249:        atomic_reqflag |= CPU_REQ_RESET;
                    250: }
                    251: 
1.1       root      252: // 通常の例外。
1.1.1.2   root      253: // DataAccessException, エラー、割り込み、TRAP からは使わない。
1.1       root      254: // vec はベクタ番号。
                    255: void
                    256: m88kcpu::Exception(int vec)
                    257: {
                    258:        ExceptionCore(vec, ExceptionKind::NORMAL);
                    259: }
                    260: 
                    261: // 例外処理コア部分
                    262: // vec はベクタ番号。
                    263: void
                    264: m88kcpu::ExceptionCore(int vec, ExceptionKind cause)
                    265: {
1.1.1.4   root      266:        uint syscall = 0;
                    267: 
1.1.1.3   root      268:        // 例外履歴に記録 (例外発生はブランチ履歴にも記録)
1.1.1.4   root      269:        // OpenBSD システムコールなら番号もついでに記録。
                    270:        // システムコール番号は tb0 発行時点で r13 にセットされている。
                    271:        // ただし 0 番は syscall(2) (間接システムコール) で、実際の番号は r2。
                    272:        // 198番 __syscall(2) だと r2:r3 (なので実質 r3)。
                    273:        if (vec == 450) {
                    274:                syscall = r[13];
                    275:                if (syscall == 0) {
                    276:                        syscall = r[2];
                    277:                } else if (syscall == 198) {
                    278:                        syscall = r[3];
                    279:                }
                    280:                syscall &= 0xfff;
                    281:        }
1.1.1.5   root      282:        uint32 from = xip | (IsSuper() ? 1 : 0);
                    283:        uint32 inst = 0xfc000000 | (syscall << 12) | vec;
                    284:        exhist.AddEntry(from, 0, inst);
                    285:        brhist.AddEntry(from, 0, inst);
1.1.1.3   root      286:        // デバッガに通知 (例外ブレーク用)
1.1.1.4   root      287:        debugger_notify_exception(vec);
                    288: 
                    289:        // 命令中で起きる例外はとりあえず全部2クロック追加? (Table.7-5)
                    290:        if (cause != ExceptionKind::INTR) {
1.1.1.5   root      291:                AddCycle(2);
1.1.1.4   root      292:        }
1.1.1.3   root      293: 
1.1       root      294:        if (psr & PSR_SFRZ) {
                    295:                if (cause != ExceptionKind::TRAP) {
1.1.1.7   root      296:                        cpulog(2, "SFRZ Error Exception");
1.1       root      297:                        vec = M88K_EXCEP_ERROR;
                    298:                        cause = ExceptionKind::ERROR;
                    299:                }
                    300:        } else {
1.1.1.7   root      301:                cpulog(2, "Exception %x", vec);
1.1.1.2   root      302:                if (vec != 1) {
1.1.1.7   root      303:                        cpulog(1, "Exception %x x=%x n=%x f=%x", vec, xip, nip, fip);
1.1.1.2   root      304:                }
1.1       root      305:                sxip = xip;
                    306:                snip = nip;
1.1.1.7   root      307:                sfip = fip;
1.1       root      308: 
                    309:                sxip |= SIP_V;
                    310:                snip |= SIP_V;
1.1.1.4   root      311:                sfip |= SIP_V;
1.1       root      312: 
                    313:                if (OpIsBusErr(opX)) {
                    314:                        sxip |= SIP_E;  // E bit
                    315:                }
                    316:                if (OpIsBusErr(opF)) {
                    317:                        snip |= SIP_E;  // E bit
                    318:                }
                    319: 
                    320:                if (vec == M88K_EXCEP_UNIMPL_OP) {
                    321:                        sxip &= ~SIP_V;
                    322:                }
                    323:        }
                    324: 
1.1.1.2   root      325:        if (cause != ExceptionKind::DATA) {
                    326:                // データアクセス例外以外は、
                    327:                // データパイプラインはフラッシュ状態とする。
                    328:                // ほんとうは違う。かも。
                    329:                dmt0 = 0;
                    330:        } else {
                    331:                // xip: ld/st/xmem
                    332:                // nip: next
                    333:                // fip: fetch
                    334: 
                    335:                // rom1.2 は DAE が起きると、
                    336: 
                    337:                // ROM挙動               CPU の RTE 挙動
                    338:                // sfip = sxip
                    339:                // sxip -> ~V (INVALID)  CPU はそもそも sxip を評価しない
                    340:                // snip = 0 (INVALID)    CPU はこれを nop 相当に処理する
                    341:                // rte
                    342: 
                    343:                // してくる。そのまま読むと命令を再実行しようとしているように
                    344:                // 読めるが、再実行すると無限ループになってしまう。
                    345:                // DAE の時点で xip が進んでいることを期待して利用している?
                    346: 
                    347:                // openbsd は
                    348:                // xmem の write バスエラーを検知すると命令を再実行するために
                    349:                // fip = nip, nip = xip して rte する。ということは xip = xmem に
                    350:                // なっていることを期待している。
                    351: 
                    352:                // というわけで
                    353:                // ld で DataAccessException のときは、実CPUはすでに次の命令を
                    354:                // 実行している?
                    355:                // もう少し考えると、スコアボードでレジスタの干渉がなければ、
                    356:                // 実行している?
                    357: 
                    358:                // 仕方がないのでハックでごまかす。
                    359:                // rte のほうも参照のこと。
                    360: 
                    361:                if (IsSuper() && xip >= 0x41000000 && xip < 0x42000000) {
                    362:                        // 遅延例外機構がないので、ROM 合わせのハック。
                    363:                        sxip = snip;
                    364:                }
                    365:        }
                    366: 
1.1       root      367:        epsr = psr;
1.1.1.2   root      368:        SetPSR(psr | PSR_SUPER | PSR_SFD1 | PSR_IND | PSR_SFRZ);
1.1       root      369: 
                    370:        fip = vbr + (vec << 3);
                    371:        fetch();
1.1.1.3   root      372:        // ここでベクタに飛ぶのだが、ベクタ内の2命令でおそらく必ずもう一度
                    373:        // 分岐してそっちでも履歴が残るので、ここでブランチ履歴を残すのは
                    374:        // ちょっと冗長という気もする。
                    375: 
1.1       root      376:        if (OpIsBusErr(opF)) {
                    377:                if (cause == ExceptionKind::ERROR) {
                    378:                        // double bus fault
                    379:                        // 実機は無限ループ状態
                    380:                        PANIC("Infinite ERROR (double bus fault)");
                    381:                } else {
                    382:                        ExceptionCore(M88K_EXCEP_ERROR, ExceptionKind::ERROR);
                    383:                }
                    384:        }
                    385: }
                    386: 
1.1.1.5   root      387: inline
                    388: uint32
                    389: m88kcpu::Calcdmt(uint32 flag)
                    390: {
                    391:        return
                    392:                   ((psr & PSR_BO_LE) ? DM_BO : 0)
                    393:             | ((IsSuper() && !(flag & DM_USR)) ? DM_DAS : 0)
                    394:             | DM_VALID;
                    395: }
                    396: 
1.1       root      397: // データアクセス例外(Read)
1.1.1.5   root      398: // ld.b, ld.h, ld.hu, ld 用
1.1       root      399: void
1.1.1.5   root      400: m88kcpu::ReadDataException32(uint32 addr, uint32 flag)
1.1       root      401: {
                    402:        // ミスアラインドはこの例外より前にチェックされていて、
                    403:        // ここにはアラインドしかこない。
                    404:        dma0 = addr & ~0x3;
1.1.1.5   root      405:        dmt0 = Calcdmt(flag)
1.1       root      406:             | (FLD_D << 7)
                    407:             | (flag & DM_SIGNED)
                    408:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
1.1.1.5   root      409:        ;
                    410:        dmt1 &= ~DM_VALID;
                    411:        dmt2 &= ~DM_VALID;
1.1.1.7   root      412:        cpulog(1, "ReadDAE xip=%x addr=%x", xip, addr);
1.1.1.2   root      413:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
1.1       root      414: }
                    415: 
1.1.1.5   root      416: // データアクセス例外(Read)
                    417: // ld.d 用
                    418: void
                    419: m88kcpu::ReadDataException64(uint32 addr, uint32 flag)
                    420: {
                    421:        // ミスアラインドはこの例外より前にチェックされていて、
                    422:        // ここにはアラインドしかこない。
                    423:        dma0 = addr;
                    424:        dmt0 = Calcdmt(flag)
                    425:             | DM_DOUB1                 // ダブルワードの第1アクセスのときセット
                    426:             | (FLD_D << 7)
                    427:             | DM_EN_MASK               // 32ビット有効
                    428:        ;
                    429: 
                    430:        dma1 = dma0 + 4;
                    431:        dmt1 = Calcdmt(flag)
                    432:             | (FLD_D2 << 7)
                    433:             | DM_EN_MASK                       // 32ビット有効
                    434:        ;
                    435: 
                    436:        dmt2 &= ~DM_VALID;
                    437: 
                    438:        if ((flag & DM_DOUB1) == 0) {
                    439:                // .d の2ワード目がバスエラー。第1ワードのアクセスは成功した。
                    440:                dmt0 &= ~DM_VALID;
                    441:        }
                    442: 
1.1.1.7   root      443:        cpulog(1, "ReadDAE64 xip=%x addr=%x", xip, addr);
1.1.1.5   root      444:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
                    445: }
                    446: 
1.1       root      447: // データアクセス例外(Write)
1.1.1.5   root      448: // st.b, st.h, st.hu, st 用
1.1       root      449: void
1.1.1.5   root      450: m88kcpu::WriteDataException32(uint32 addr, uint32 flag)
1.1       root      451: {
                    452:        // ミスアラインドはこの例外より前にチェックされていて、
                    453:        // ここにはアラインドしかこない。
                    454:        dma0 = addr & ~0x3;
1.1.1.5   root      455:        dmt0 = Calcdmt(flag)
1.1       root      456:             | (FLD_D << 7)
                    457:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
                    458:             | DM_WRITE
1.1.1.5   root      459:        ;
                    460:        dmd0 = rD;
1.1       root      461: 
1.1.1.5   root      462:        dmt1 &= ~DM_VALID;
                    463:        dmt2 &= ~DM_VALID;
1.1.1.7   root      464:        cpulog(1, "WriteDAE xip=%x addr=%x", xip, addr);
1.1.1.2   root      465:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
                    466: }
                    467: 
1.1.1.5   root      468: // データアクセス例外(Write)
                    469: // st.d 用
                    470: void
                    471: m88kcpu::WriteDataException64(uint32 addr, uint32 flag)
                    472: {
                    473:        // ミスアラインドはこの例外より前にチェックされていて、
                    474:        // ここにはアラインドしかこない。
                    475:        dma0 = addr & ~0x3;
                    476:        dmt0 = Calcdmt(flag)
                    477:             | DM_DOUB1         // ダブルワードの第1アクセスのときセット
                    478:             | (FLD_D << 7)
                    479:             | DM_EN_MASK
                    480:             | DM_WRITE
                    481:        ;
                    482:        dmd0 = rD;
                    483: 
                    484:        dma1 = dma0 + 4;
                    485:        dmt1 = Calcdmt(flag)
                    486:             | (FLD_D2 << 7)
                    487:             | DM_EN_MASK
                    488:             | DM_WRITE
                    489:        ;
                    490:        dmd1 = rD2;
                    491: 
                    492:        dmt2 &= ~DM_VALID;
                    493: 
                    494:        if ((flag & DM_DOUB1) == 0) {
                    495:                // .d の2ワード目がバスエラー。第1ワードのアクセスは成功した。
                    496:                dmt0 &= ~DM_VALID;
                    497:        }
                    498: 
1.1.1.7   root      499:        cpulog(1, "WriteDAE64 xip=%x addr=%x", xip, addr);
1.1.1.5   root      500:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
                    501: }
                    502: 
1.1.1.2   root      503: // データアクセス例外(xmem)
1.1.1.5   root      504: // xmem には .d は無い
1.1.1.2   root      505: void
1.1.1.5   root      506: m88kcpu::XmemDataException(uint32 addr, uint32 flag)
1.1.1.2   root      507: {
                    508:        dma0 = addr & ~0x3;
1.1.1.5   root      509:        dmt0 = Calcdmt(flag)
                    510:             | DM_LOCK          // xmem でセット
1.1.1.2   root      511:             | (FLD_D << 7)
                    512:             | (flag & DM_SIGNED)
                    513:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
1.1.1.5   root      514:        ;
1.1.1.2   root      515: 
1.1.1.5   root      516:        dma1 = dma0;
                    517:        dmt1 = Calcdmt(flag)
                    518:             | DM_LOCK          // xmem でセット
1.1.1.2   root      519:             | (FLD_D << 7)
                    520:             | (flag & DM_SIGNED)
                    521:             | ((flag & DM_EN_MASK) >> (addr & 0x03))
                    522:             | DM_WRITE
1.1.1.5   root      523:        ;
                    524:        dmd1 = rD;
1.1.1.2   root      525: 
1.1.1.5   root      526:        dmt2 &= ~DM_VALID;
1.1.1.2   root      527: 
                    528:        // ミスアラインドはこの例外より前にチェックされていて、
                    529:        // ここにはアラインドしかこない。
                    530:        if (cmmu[1].fault_code != m88200::FAULT_CODE_BUSERR
                    531:         || cmmu[1].acc_read) {
                    532:                // アドレス変換フォルトまたは read 時点
                    533:                // nop
1.1       root      534:        } else {
1.1.1.2   root      535:                // xmem の write 時点
1.1.1.5   root      536:                dmt0 &= ~DM_VALID;
1.1       root      537:        }
1.1.1.2   root      538: 
1.1.1.7   root      539:        cpulog(1, "xmemDAE xip=%x addr=%x", xip, addr);
1.1.1.2   root      540:        ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
1.1       root      541: }
                    542: 
1.1.1.5   root      543: // FP 例外
                    544: // fpex: FP例外コード M88K_FPEXCEP
                    545: void
                    546: m88kcpu::FPException(int fpex)
                    547: {
                    548:        // FDVZ 以上の例外が PRECISE。
                    549:        // 未満の FUNF, FOVF, FINX は IMPRECISE。
                    550:        int vec = (fpex >= M88K_FPEXCEP_FDVZ) ? M88K_EXCEP_SFU1_PRECISE : M88K_EXCEP_SFU1_IMPRECISE;
                    551:        fpecr = fpex;
                    552: 
                    553:        Exception(vec);
                    554: }
                    555: 
1.1       root      556: void
1.1.1.5   root      557: m88kcpu::Interrupt(int level)
1.1       root      558: {
1.1.1.5   root      559:        // level は 0 か 1。
                    560:        intr_pending = level;
1.1       root      561:        atomic_reqflag |= CPU_REQ_INTR;
                    562: }
                    563: 
                    564: void
                    565: m88kcpu::fpu_unimpl()
                    566: {
                    567:        printf("%s\n", __func__);
1.1.1.5   root      568:        FPException(M88K_FPEXCEP_FUNIMP);
1.1       root      569: }
1.1.1.2   root      570: 
                    571: OP_DEF(illegal)
                    572: {
                    573:        // 本来は不当命令例外?
1.1.1.7   root      574:        cpulog(0, "Illegal instruction %08x", (uint32)opX);
1.1.1.2   root      575: }

unix.superglobalmegacorp.com

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