Annotation of nono/vm/mpu88xx0.cpp, revision 1.1.1.13

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: 
1.1.1.11  root        7: //
                      8: // MPU (M88xx0)
                      9: //
1.1       root       10: 
                     11: #include "mpu88xx0.h"
                     12: #include "config.h"
1.1.1.11  root       13: #include "debugger.h"
1.1.1.12  root       14: #include "m88100disasm.h"
1.1.1.11  root       15: #include "scheduler.h"
1.1.1.13! root       16: #include "syncer.h"
1.1.1.2   root       17: 
1.1       root       18: // コンストラクタ
1.1.1.7   root       19: MPU88xx0Device::MPU88xx0Device()
1.1.1.13! root       20:        : inherited()
1.1       root       21: {
1.1.1.13! root       22:        SetName("MPU(88100)");
1.1.1.4   root       23: 
1.1.1.13! root       24:        // LUNA-88K では CMMU の ID は次のように割り振ってあるようだ。
1.1.1.2   root       25:        // OpenBSD の sys/arch/luna68k/include/board.h より。
                     26:        //
                     27:        //       Inst Data
                     28:        // CPU#0 ID=7 ID=6
                     29:        // CPU#1 ID=5 ID=4
                     30:        // CPU#2 ID=3 ID=2
                     31:        // CPU#3 ID=1 ID=0
                     32:        //
1.1.1.13! root       33:        // 厳密にはこれは LUNA-88K のハードウェアがどういうコンフィグレーションで
1.1.1.2   root       34:        // m88200 を使うかなので、ここではなくて vm_luna あたりのほうがいいかも
                     35:        // しれんけど、あまり遠いのも面倒なので、とりあえずこの辺に。
                     36:        // あとマルチプロセッサになったらまたその時考える。
1.1.1.13! root       37:        cmmu[0].reset(new m88200(this, 7));
        !            38:        cmmu[1].reset(new m88200(this, 6));
1.1.1.2   root       39: 
1.1.1.8   root       40:        // レジスタモニター
1.1.1.11  root       41:        monitor.func = ToMonitorCallback(&MPU88xx0Device::MonitorUpdate);
1.1.1.10  root       42:        monitor.SetSize(79, 28);
1.1.1.8   root       43:        monitor.Regist(ID_MONITOR_MPUREG);
1.1       root       44: }
                     45: 
                     46: // デストラクタ
                     47: MPU88xx0Device::~MPU88xx0Device()
                     48: {
                     49: }
                     50: 
1.1.1.13! root       51: // 初期化
1.1.1.5   root       52: bool
                     53: MPU88xx0Device::Init()
                     54: {
                     55:        if (inherited::Init() == false) {
                     56:                return false;
                     57:        }
                     58: 
1.1.1.13! root       59:        debugger = GetDebugger();
        !            60: 
1.1.1.12  root       61:        const ConfigItem& item_stop = gConfig->Find("mpu-pseudo-stop");
1.1.1.13! root       62:        pseudo_stop_enable = (bool)item_stop.AsInt();
1.1.1.12  root       63: 
                     64:        const ConfigItem& item_altname = gConfig->Find(".m88k-altname");
                     65:        m88100disasm::use_altname = item_altname.AsInt();
1.1.1.8   root       66: 
1.1.1.5   root       67:        return true;
                     68: }
                     69: 
1.1.1.11  root       70: // リセット
                     71: void
                     72: MPU88xx0Device::ResetHard(bool poweron)
1.1.1.7   root       73: {
1.1.1.11  root       74:        if (poweron) {
1.1.1.13! root       75:                // レジスタのうち不定と明記されてるものは、未初期化のまま触ったことが
        !            76:                // 分かりやすいような適当なパターンで埋めておく。ただし最上位も c に
        !            77:                // すると BT45x のレジスタ付近を指してしまうので、それは避けておく。
        !            78:                const uint32 Undefined = 0x0ccccccc;
        !            79:                for (int i = 1; i < 32; i++) {
        !            80:                        reg.r[i] = Undefined;
        !            81:                }
        !            82:                for (int i = 0; i < countof(reg.fcr); i++) {
        !            83:                        reg.fcr[i] = Undefined & reg.fcr_mask[i];
        !            84:                }
        !            85: 
        !            86:                reg.epsr = Undefined;
        !            87:                reg.ssbr = Undefined;
        !            88:                reg.sfip = Undefined;
        !            89:                reg.snip = Undefined;
        !            90:                reg.sxip = Undefined;
        !            91:                // DMTx は bit0(Valid) をクリア。DMAx/DMDx は不定。
        !            92:                reg.dma0 = Undefined;
        !            93:                reg.dma1 = Undefined;
        !            94:                reg.dma2 = Undefined;
        !            95:                reg.dmd0 = Undefined;
        !            96:                reg.dmd1 = Undefined;
        !            97:                reg.dmd2 = Undefined;
        !            98: 
        !            99:                // アクセスが一度もない時にどのアドレスとも一致しないようにしておく。
        !           100:                lastaddr = (uint64)-1;
        !           101: 
        !           102:                // サイクルを初期化。
        !           103:                used_cycle = 0;
        !           104: 
        !           105:                // 履歴は電源オン時だけ初期化。
        !           106:                // (LUNA-88K は ROM が正常パスで CPU リセットを行ったりするので)
        !           107:                exhist.Clear();
        !           108:                brhist.Clear();
        !           109: 
        !           110:                // この後起きるリセット例外で xip を初期化する前に参照することに
        !           111:                // なるので、これだけここでも初期化しておく。
        !           112:                reg.xip = 0;
1.1.1.11  root      113:        }
1.1.1.12  root      114:        resetting = true;
1.1.1.11  root      115: 
                    116:        // リセット例外を 8+256 クロック後に起こす。
                    117:        // 8+256 は、電源オン時に最低これだけアサートしなければならないという値
                    118:        // のはずで、実際これだけかかるとかいう値ではない。が、こちら側の都合で
                    119:        // この後実行される RAM の ResetHard() がブートページを用意した後で
                    120:        // cpu->Reset() で xip をフェッチするという順序にしないといけないため、
                    121:        // リセット例外が起動するまでに時間がかかるというところを都合よく真似て
                    122:        // おく。
                    123: 
                    124:        exec_event.func = ToEventCallback(&MPU88xx0Device::ResetCallback);
                    125:        exec_event.time = (8 + 256) * clock_nsec;
1.1.1.13! root      126:        exec_event.SetName(GetName() + " Reset");
        !           127:        scheduler->RestartEvent(exec_event);
1.1.1.7   root      128: }
                    129: 
1.1.1.11  root      130: // リセット例外コールバック。
                    131: // MPU リセットから規定時間後に呼ばれる。
1.1       root      132: void
1.1.1.11  root      133: MPU88xx0Device::ResetCallback(Event& ev)
1.1       root      134: {
1.1.1.12  root      135:        resetting = false;
                    136: 
1.1.1.11  root      137:        // リセット例外を実行
1.1.1.13! root      138:        uint64 cycle_start = used_cycle;
        !           139: 
        !           140:        // 例外履歴に記録 (例外発生はブランチ履歴にも記録)
        !           141:        // リセット例外も発生時の XIP を記録する。(LUNA-88K の PROM 1.20)
        !           142:        exhist.AddEntry(reg.xip | 1, 0, 0xfc000000 | 0);
        !           143:        brhist.AddEntry(reg.xip | 1, 0, 0xfc000000 | 0);
        !           144:        // デバッガに通知 (例外ブレーク用)
        !           145:        debugger->NotifyExceptionMain(0);
        !           146: 
        !           147:        // 内部の割り込み状態をクリア
        !           148:        intr_pending = 0;
        !           149:        ChangeState(CPU_STATE_NORMAL);
        !           150: 
        !           151:        // 実際どこかは分からんけど PSR 設定の前にリセットしておきたい
        !           152:        cmmu[0]->Reset();
        !           153:        cmmu[1]->Reset();
        !           154: 
        !           155:        // Table 6-8 (p6-47)
        !           156:        reg.psr = 0x800003ff;
        !           157:        // XXX ただし SFU1 は未実装なので下げておく
        !           158:        reg.psr &= ~PSR_SFD1;
        !           159: 
        !           160: #if defined(TEST_INTERRUPT)
        !           161:        reg.psr &= ~PSR_IND;
        !           162:        reg.psr &= ~PSR_SFRZ;
        !           163: #endif
        !           164: 
        !           165:        SetPSR();
        !           166: 
        !           167:        reg.fip = 0;
        !           168: 
        !           169:        // レジスタのうち明記されてるものをクリア。
        !           170:        // 不定と明記されてるものはリセットでは触らないでおく。
        !           171:        // scoreboard: cleared
        !           172:        reg.nip = 0;
        !           173:        reg.xip = 0;
        !           174:        reg.vbr = 0;
        !           175:        reg.fpecr = 0;
        !           176:        reg.fpcr = 0;
        !           177:        reg.fpsr = 0;
        !           178:        // DMTx は bit0(Valid) をクリア。他は不定
        !           179:        reg.dmt0 &= ~DM_VALID;
        !           180:        reg.dmt1 &= ~DM_VALID;
        !           181:        reg.dmt2 &= ~DM_VALID;
        !           182: 
        !           183:        fetch();
        !           184: 
        !           185:        // リセット例外はここまで。
        !           186:        // ここからは最初の命令のプリフェッチ
        !           187:        Prefetch();
1.1.1.11  root      188: 
                    189:        // コールバックを ResetCallback から Exec* に差し替える前のここで
                    190:        // トレース状態を初期化する。
1.1.1.13! root      191:        SetTrace(debugger->IsTrace());
1.1.1.11  root      192: 
                    193:        // 以降は通常走行
1.1.1.13! root      194:        int cycle = used_cycle - cycle_start;
1.1.1.11  root      195:        exec_event.func = exec_normal;
                    196:        exec_event.time = cycle * clock_nsec;
1.1.1.13! root      197:        exec_event.SetName(GetName() + " Execute");
        !           198:        scheduler->StartEvent(exec_event);
1.1.1.11  root      199: }
                    200: 
                    201: // トレース実行のコールバック
                    202: void
                    203: MPU88xx0Device::ExecTrace(Event& ev)
                    204: {
1.1.1.13! root      205:        debugger->ExecMain();
1.1.1.11  root      206:        ExecNormal(ev);
                    207: }
                    208: 
                    209: // トレース状態を設定する
                    210: void
                    211: MPU88xx0Device::SetTrace(bool enable)
                    212: {
                    213:        if (enable) {
                    214:                exec_normal = ToEventCallback(&MPU88xx0Device::ExecTrace);
                    215:        } else {
                    216:                exec_normal = ToEventCallback(&MPU88xx0Device::ExecNormal);
                    217:        }
                    218:        exec_event.func = exec_normal;
                    219: }
                    220: 
                    221: void
1.1.1.13! root      222: MPU88xx0Device::ChangeState(uint32 new_state)
1.1.1.11  root      223: {
1.1.1.13! root      224:        // new_state (CPU_STATE_*) と
        !           225:        // RequestCPUMode() の引数 Syncer::SCHED_CPU_* は
1.1.1.11  root      226:        // 実は同じ値なのでそのまま渡してよいことにする。
1.1.1.13! root      227:        static_assert(CPU_STATE_NORMAL == Syncer::SCHED_CPU_NORMAL, "");
        !           228:        static_assert(CPU_STATE_STOP   == Syncer::SCHED_CPU_STOP,   "");
1.1.1.11  root      229: 
1.1.1.13! root      230:        if (cpu_state != new_state) {
        !           231:                cpu_state = new_state;
        !           232:                // スケジューラに通知
        !           233:                syncer->RequestCPUMode(new_state);
1.1.1.11  root      234:        }
1.1       root      235: }
                    236: 
1.1.1.6   root      237: // アクセス中の論理アドレスを取得
                    238: uint32
                    239: MPU88xx0Device::GetLaddr() const
                    240: {
1.1.1.13! root      241:        m88200 *m = m88200::GetBusMaster();
        !           242:        assert(m);
        !           243:        return m->GetLaddr();
1.1.1.6   root      244: }
                    245: 
                    246: // アクセス中の物理アドレスを取得
                    247: uint32
                    248: MPU88xx0Device::GetPaddr() const
                    249: {
1.1.1.13! root      250:        m88200 *m = m88200::GetBusMaster();
        !           251:        assert(m);
        !           252:        return m->GetPaddr();
1.1.1.4   root      253: }
                    254: 
1.1.1.2   root      255: // Interrupt
                    256: void
1.1.1.5   root      257: MPU88xx0Device::Interrupt(int level)
1.1.1.2   root      258: {
1.1.1.13! root      259:        // level は 0 か 1。
        !           260:        intr_pending = level;
        !           261: 
        !           262:        if (intr_pending && IsIntrEnable() && (cpu_state == CPU_STATE_STOP)) {
        !           263:                // 割り込みを受け付けたら STOP 解除。
        !           264:                ChangeState(CPU_STATE_NORMAL);
        !           265:        }
1.1.1.2   root      266: }
                    267: 
1.1.1.9   root      268: // DOS call エミュレーションのコールバックを指定
                    269: void
1.1.1.13! root      270: MPU88xx0Device::SetFLineCallback(bool (*callback)(MPU88xx0Device *, void *),
        !           271:        void *arg)
1.1.1.9   root      272: {
1.1.1.13! root      273:        fline_callback = callback;
        !           274:        fline_arg = arg;
1.1.1.9   root      275: }
                    276: 
                    277: // MPU からのアクセスをエミュレート
                    278: uint64
                    279: MPU88xx0Device::Read8(uint32 addr)
                    280: {
1.1.1.13! root      281:        return cmmu[1]->load_8(addr);
1.1.1.9   root      282: }
                    283: 
                    284: uint64
                    285: MPU88xx0Device::Read16(uint32 addr)
                    286: {
                    287:        if ((addr & 1) == 0) {
1.1.1.13! root      288:                return cmmu[1]->load_16(addr);
1.1.1.9   root      289:        } else {
                    290:                uint64 h, l;
                    291:                h = Read8(addr);
                    292:                if ((int64)h < 0) {
                    293:                        return h;
                    294:                }
                    295:                l = Read8(addr + 1);
                    296:                if ((int64)l < 0) {
                    297:                        return l;
                    298:                }
                    299:                return (h << 8) | l;
                    300:        }
                    301: }
                    302: 
                    303: uint64
                    304: MPU88xx0Device::Read32(uint32 addr)
                    305: {
                    306:        if ((addr & 3) == 0) {
1.1.1.13! root      307:                return cmmu[1]->load_32(addr);
1.1.1.9   root      308:        } else if ((addr & 1) == 0) {
                    309:                uint64 h, l;
                    310:                h = Read16(addr);
                    311:                if ((int64)h < 0) {
                    312:                        return h;
                    313:                }
                    314:                l = Read16(addr + 2);
                    315:                if ((int64)l < 0) {
                    316:                        return l;
                    317:                }
                    318:                return (h << 16) | l;
                    319:        } else {
                    320:                uint64 h, m, l;
                    321:                h = Read8(addr);
                    322:                if ((int64)h < 0) {
                    323:                        return h;
                    324:                }
                    325:                m = Read16(addr + 1);
                    326:                if ((int64)m < 0) {
                    327:                        return m;
                    328:                }
                    329:                l = Read8(addr + 3);
                    330:                if ((int64)l < 0) {
                    331:                        return l;
                    332:                }
                    333:                return (h << 24) | (m << 8) | l;
                    334:        }
                    335: }
                    336: 
                    337: uint64
                    338: MPU88xx0Device::Write8(uint32 addr, uint32 data)
                    339: {
1.1.1.13! root      340:        return cmmu[1]->store_8(addr, data & 0xff);
1.1.1.9   root      341: }
                    342: 
                    343: uint64
                    344: MPU88xx0Device::Write16(uint32 addr, uint32 data)
                    345: {
                    346:        if ((addr & 1) == 0) {
1.1.1.13! root      347:                return cmmu[1]->store_16(addr, data & 0xffff);
1.1.1.9   root      348:        } else {
                    349:                uint64 r;
                    350:                r = Write8(addr, data >> 8);
                    351:                if ((int64)r < 0) {
                    352:                        return r;
                    353:                }
                    354:                return Write8(addr + 1, data);
                    355:        }
                    356: }
                    357: 
                    358: uint64
                    359: MPU88xx0Device::Write32(uint32 addr, uint32 data)
                    360: {
                    361:        if ((addr & 3) == 0) {
1.1.1.13! root      362:                return cmmu[1]->store_32(addr, data);
1.1.1.9   root      363:        } else if ((addr & 1) == 0) {
                    364:                uint64 r;
                    365:                r = Write16(addr, data >> 16);
                    366:                if ((int64)r < 0) {
                    367:                        return r;
                    368:                }
                    369:                return Write16(addr + 2, data);
                    370:        } else {
                    371:                uint64 r;
                    372:                r = Write8(addr, data >> 24);
                    373:                if ((int64)r < 0) {
                    374:                        return r;
                    375:                }
                    376:                r = Write16(addr + 1, data >> 8);
                    377:                if ((int64)r < 0) {
                    378:                        return r;
                    379:                }
                    380:                return Write8(addr + 3, data);
                    381:        }
                    382: }
                    383: 
1.1.1.13! root      384: #define FA(val, bit)   TA::OnOff((val) & M88100::bit)
1.1.1.10  root      385: 
1.1       root      386: // モニター更新
1.1.1.3   root      387: void
1.1.1.8   root      388: MPU88xx0Device::MonitorUpdate(Monitor *, TextScreen& screen)
1.1       root      389: {
1.1.1.13! root      390:        m88100reg tmp;
1.1       root      391:        int x;
                    392:        int y;
                    393: 
1.1.1.8   root      394:        screen.Clear();
1.1       root      395: 
                    396:        // ローカルにコピー
1.1.1.13! root      397:        tmp = reg;
1.1       root      398: 
                    399:        //
                    400:        for (int i = 0; i < countof(reg.r); i++) {
1.1.1.13! root      401:                screen.Print((i / 8) * 14, i % 8, "r%-2d:%08x", i, tmp.r[i]);
1.1       root      402:        }
                    403: 
                    404:        // 制御レジスタ
                    405:        x = 0;
                    406:        y = 9;
1.1.1.8   root      407:        screen.Print(x, y++,  "pid (cr0):%08x(Arch=$%02x Ver=$%02x MC=%s)",
1.1.1.13! root      408:                tmp.pid,
        !           409:                (tmp.pid >> 8) & 0xff,
        !           410:                (tmp.pid >> 1) & 0x7f,
        !           411:                (tmp.pid & 1) ? "Master" : "Checker");
        !           412:        screen.Print(x, y, "psr (cr1):%08x(", tmp.psr);
        !           413:        screen.Puts(x + 19, y, FA(tmp.psr,  PSR_SUPER), "S");
1.1.1.8   root      414:        screen.Puts(x + 21, y,
1.1.1.13! root      415:                ((tmp.psr & M88100::PSR_BO_LE) ? "BO=LE" : "BO=BE"));
        !           416:        screen.Puts(x + 27, y, FA(tmp.psr,  PSR_SER),  "SER");
        !           417:        screen.Puts(x + 31, y, FA(tmp.psr,  PSR_C),    "Cy");
        !           418:        screen.Puts(x + 34, y, FA(tmp.psr,  PSR_SFD1), "SFD1");
        !           419:        screen.Puts(x + 39, y, FA(tmp.psr,  PSR_MXM),  "MXM");
        !           420:        screen.Puts(x + 43, y, FA(tmp.psr,  PSR_IND),  "IND");
        !           421:        screen.Puts(x + 47, y, FA(tmp.psr,  PSR_SFRZ), "SFRZ");
1.1.1.8   root      422:        screen.Puts(x + 51, y, ")");
1.1.1.2   root      423:        y++;
1.1.1.13! root      424:        screen.Print(x, y, "epsr(cr2):%08x(", tmp.epsr);
        !           425:        screen.Puts(x + 19, y, FA(tmp.epsr, PSR_SUPER), "S");
1.1.1.8   root      426:        screen.Puts(x + 21, y,
1.1.1.13! root      427:                ((tmp.epsr& M88100::PSR_BO_LE) ? "BO=LE" : "BO=BE"));
        !           428:        screen.Puts(x + 27, y, FA(tmp.epsr, PSR_SER),  "SER");
        !           429:        screen.Puts(x + 31, y, FA(tmp.epsr, PSR_C),    "Cy");
        !           430:        screen.Puts(x + 34, y, FA(tmp.epsr, PSR_SFD1), "SFD1");
        !           431:        screen.Puts(x + 39, y, FA(tmp.epsr, PSR_MXM),  "MXM");
        !           432:        screen.Puts(x + 43, y, FA(tmp.epsr, PSR_IND),  "IND");
        !           433:        screen.Puts(x + 47, y, FA(tmp.epsr, PSR_SFRZ), "SFRZ");
1.1.1.8   root      434:        screen.Puts(x + 51, y, ")");
1.1       root      435: 
1.1.1.2   root      436:        // 制御レジスタ(左中; *IP)
1.1       root      437:        x = 0;
                    438:        y = 12;
1.1.1.13! root      439:        screen.Print(x, y + 0, "xip:%08x  opX:%08x(%c)",
        !           440:                tmp.xip, (uint32)tmp.opX,
        !           441:                OpIsBusErr(tmp.opX) ? 'B' : '-');
        !           442:        screen.Print(x, y + 1, "nip:%08x  opF:%08x(%c)",
        !           443:                tmp.nip, (uint32)tmp.opF,
        !           444:                OpIsBusErr(tmp.opF) ? 'B' : '-');
        !           445:        screen.Print(x, y + 2, "fip:%08x", tmp.fip);
1.1       root      446: 
                    447:        // 制御レジスタ (S*IP)
                    448:        x = 32;
                    449:        for (int i = 0; i < 3; i++) {
1.1.1.8   root      450:                screen.Print(x, y + i, "%s(cr%d):%08x:%c%c",
1.1       root      451:                        m88100reg::sipname[i], 4 + i,
1.1.1.13! root      452:                        (tmp.cr[4 + i] & M88100::SIP_MASK),
        !           453:                        (tmp.cr[4 + i] & M88100::SIP_V) ? 'V' : '-',
        !           454:                        (tmp.cr[4 + i] & M88100::SIP_E) ? 'E' : '-');
1.1       root      455:        }
                    456: 
1.1.1.2   root      457:        // 制御レジスタ(右中)
1.1       root      458:        x = 55;
                    459:        y = 9;
                    460:        for (int i = 0; i < 4; i++) {
                    461:                int rn = 17 + i;
1.1.1.13! root      462:                screen.Print(x, y++, "sr%d(cr%d):%08x", i, rn, tmp.cr[rn]);
1.1       root      463:        }
1.1.1.13! root      464:        screen.Print(x, y++, "ssbr(cr3):%08x", tmp.ssbr);
        !           465:        screen.Print(x, y++, "vbr (cr7):%08x", tmp.vbr);
1.1       root      466: 
1.1.1.10  root      467:        // MMU レジスタ(次段)
1.1.1.2   root      468:        y = 15;
                    469:        for (int i = 0; i <= 2; i++) {
                    470:                int dt =  8 + i * 3;
                    471:                int dd =  9 + i * 3;
                    472:                int da = 10 + i * 3;
                    473: 
1.1.1.8   root      474:                screen.Print(0, y, "dmt%d(cr%-2d):%04x",
1.1.1.13! root      475:                        i, dt, (tmp.cr[dt] & 0xffff));
1.1.1.8   root      476:                screen.Puts(15, y, "(b,s,d,l,rx, s,en  ,w,v)");
1.1.1.13! root      477:                screen.Puts(16, y, (tmp.cr[dt] & M88100::DM_BO)     ? "B" : "-");
        !           478:                screen.Puts(18, y, (tmp.cr[dt] & M88100::DM_DAS)    ? "S" : "U");
        !           479:                screen.Puts(20, y, (tmp.cr[dt] & M88100::DM_DOUB1)  ? "D" : "-");
        !           480:                screen.Puts(22, y, (tmp.cr[dt] & M88100::DM_LOCK)   ? "L" : "-");
1.1.1.2   root      481:                // カンマが自然に見えるようにここだけカンマも含めて前詰めで出力
1.1.1.8   root      482:                screen.Print(25, y, "%d,",
1.1.1.13! root      483:                        (tmp.cr[dt] & M88100::DM_DREG_MASK) >> 7);
        !           484:                screen.Puts(28, y, (tmp.cr[dt] & M88100::DM_SIGNED) ? "S" : "-");
        !           485:                uint32 en = (tmp.cr[dt] & M88100::DM_EN_MASK) >> 2;
1.1.1.8   root      486:                screen.Puts(30, y, m88100reg::dmt_en_str[en]);
1.1.1.13! root      487:                screen.Puts(35, y, (tmp.cr[dt] & M88100::DM_WRITE)  ? "W" : "-");
        !           488:                screen.Puts(37, y, (tmp.cr[dt] & M88100::DM_VALID)  ? "V" : "-");
1.1.1.2   root      489: 
1.1.1.13! root      490:                screen.Print(40, y, "dmd%d(cr%-2d):%08x", i, dd, tmp.cr[dd]);
        !           491:                screen.Print(60, y, "dma%d(cr%2d):%08x",  i, da, tmp.cr[da]);
1.1.1.2   root      492:                y++;
                    493:        }
1.1.1.10  root      494:        y++;
                    495: 
                    496:        // FPU レジスタ (下段)
1.1.1.13! root      497:        screen.Print(0, y, "fpecr(fcr0):%08x(", tmp.fpecr);
1.1.1.10  root      498:        x = 21;
1.1.1.13! root      499:        screen.Puts(x +  0, y, FA(tmp.fpecr, FPECR_FIOV),       "FIOV");
        !           500:        screen.Puts(x +  5, y, FA(tmp.fpecr, FPECR_FUNIMP),     "FUNIMP");
        !           501:        screen.Puts(x + 12, y, FA(tmp.fpecr, FPECR_FPRV),       "FPRV");
        !           502:        screen.Puts(x + 17, y, FA(tmp.fpecr, FPECR_FROP),       "FROP");
        !           503:        screen.Puts(x + 22, y, FA(tmp.fpecr, FPECR_FDVZ),       "FDVZ");
        !           504:        screen.Puts(x + 27, y, FA(tmp.fpecr, FPECR_FUNF),       "FUNF");
        !           505:        screen.Puts(x + 32, y, FA(tmp.fpecr, FPECR_FOVF),       "FOVF");
        !           506:        screen.Puts(x + 37, y, FA(tmp.fpecr, FPECR_FINX),       "FINX");
1.1.1.10  root      507:        screen.Puts(x + 41, y, ")");
                    508:        y++;
                    509: 
                    510:        screen.Print(0, y++,
                    511:                "fppt(fcr5): %08x(OpCode=%%%c%c%c%c%c T1=%d T2=%d TD=%d Dest=r%d)",
1.1.1.13! root      512:                tmp.fppt,
        !           513:                ((tmp.fppt >> 15) & 1) + '0',
        !           514:                ((tmp.fppt >> 14) & 1) + '0',
        !           515:                ((tmp.fppt >> 13) & 1) + '0',
        !           516:                ((tmp.fppt >> 12) & 1) + '0',
        !           517:                ((tmp.fppt >> 11) & 1) + '0',
        !           518:                ((tmp.fppt >>  9) & 3),
        !           519:                ((tmp.fppt >>  7) & 3),
        !           520:                ((tmp.fppt >>  5) & 3),
        !           521:                (tmp.fppt & M88100::FPPT_DEST));
1.1.1.10  root      522: 
                    523:        screen.Print(0, y++, "fphs1(fcr1)/fpls1(fcr2): %08x'%08x",
1.1.1.13! root      524:                tmp.fphs1, tmp.fpls1);
1.1.1.10  root      525:        screen.Print(0, y++, "fphs2(fcr3)/fpls2(fcr4): %08x'%08x",
1.1.1.13! root      526:                tmp.fphs2, tmp.fpls2);
1.1.1.10  root      527: 
                    528:        screen.Print(0, y, "fprh(fcr6) /fprl(fcr7):  %08x'%08x(",
1.1.1.13! root      529:                tmp.fprh, tmp.fprl);
1.1.1.10  root      530:        x = 43;
1.1.1.13! root      531:        screen.Puts(x + 0, y, FA(tmp.fprh, FPRH_ADDONE), "ADDONE");
        !           532:        screen.Print(x + 7, y, "RM=%s)", rmstr[(tmp.fprh >> 29) & 3]);
1.1.1.10  root      533:        y++;
                    534: 
                    535:        x = 21;
                    536:        screen.Print(0, y, "fpit(fcr8): %08x(OpCode=%%%c%c%c%c%c TD=%d",
1.1.1.13! root      537:                tmp.fpit,
        !           538:                ((tmp.fpit >> 15) & 1) + '0',
        !           539:                ((tmp.fpit >> 14) & 1) + '0',
        !           540:                ((tmp.fpit >> 13) & 1) + '0',
        !           541:                ((tmp.fpit >> 12) & 1) + '0',
        !           542:                ((tmp.fpit >> 11) & 1) + '0',
        !           543:                ((tmp.fpit >> 10) & 1));
        !           544:        screen.Puts(x + 19, y, FA(tmp.fpit, FPIT_EFINV), "EINV");
        !           545:        screen.Puts(x + 24, y, FA(tmp.fpit, FPIT_EFDVZ), "EDVZ");
        !           546:        screen.Puts(x + 29, y, FA(tmp.fpit, FPIT_EFUNF), "EUNF");
        !           547:        screen.Puts(x + 34, y, FA(tmp.fpit, FPIT_EFOVF), "EOVF");
        !           548:        screen.Puts(x + 39, y, FA(tmp.fpit, FPIT_EFINX), "EINX");
        !           549:        screen.Print(x + 44, y, "Dest=r%d)", tmp.fpit & M88100::FPIT_DEST);
1.1.1.10  root      550:        y++;
                    551: 
1.1.1.13! root      552:        uint32 sign = (tmp.fprh & M88100::FPRH_SIGN);
        !           553:        uint32 exp  = (int32)tmp.fpit >> 20;
        !           554:        uint32 mant_h = (tmp.fprh & 0x000fffff);
        !           555:        uint32 mant_l = tmp.fprl;
1.1.1.10  root      556:        screen.Print(12, y, "result: %c%1x.%05x'%08x'grs e%+d",
                    557:                (sign ? '-' : '+'),
1.1.1.13! root      558:                ((tmp.fprh >> 20) & 1),
1.1.1.10  root      559:                mant_h,
                    560:                mant_l,
                    561:                exp - 0x3ff);
1.1.1.13! root      562:        screen.Puts(38, y, FA(tmp.fprh, FPRH_GUARD),  "G");
        !           563:        screen.Puts(39, y, FA(tmp.fprh, FPRH_ROUND),  "R");
        !           564:        screen.Puts(40, y, FA(tmp.fprh, FPRH_STICKY), "S");
1.1.1.10  root      565:        screen.Print(48, y, "($%03x)", exp & 0x7ff);
                    566:        // Inf と NAN はこの形式だけからでは分かりづらいので別途追加で表示。
                    567:        // exp は符号拡張しているので指数部 $7ff は exp == -1。
                    568:        if (exp == 0xffffffff) {
                    569:                x = 55;
                    570:                if ((mant_h | mant_l) == 0) {
                    571:                        if (sign == 0) {
                    572:                                screen.Puts(x, y, "= +Inf");
                    573:                        } else {
                    574:                                screen.Puts(x, y, "= -Inf");
                    575:                        }
                    576:                } else {
                    577:                        if (sign == 0) {
                    578:                                screen.Puts(x, y, "= +NAN");
                    579:                        } else {
                    580:                                screen.Puts(x, y, "= -NAN");
                    581:                        }
                    582:                }
                    583:        }
                    584:        y++;
                    585: 
1.1.1.13! root      586:        screen.Print(0, y, "fpsr(fcr62):%08x(", tmp.fpsr);
1.1.1.10  root      587:        x = 21;
1.1.1.13! root      588:        screen.Puts(x +  0, y, FA(tmp.fpsr, FPSR_AFINV), "AFINV");
        !           589:        screen.Puts(x +  6, y, FA(tmp.fpsr, FPSR_AFDVZ), "AFDVZ");
        !           590:        screen.Puts(x + 12, y, FA(tmp.fpsr, FPSR_AFUNF), "AFUNF");
        !           591:        screen.Puts(x + 18, y, FA(tmp.fpsr, FPSR_AFOVF), "AFOVF");
        !           592:        screen.Puts(x + 24, y, FA(tmp.fpsr, FPSR_AFINX), "AFINX");
1.1.1.10  root      593:        screen.Puts(x + 29, y, ")");
                    594:        y++;
                    595: 
1.1.1.13! root      596:        screen.Print(0, y, "fpcr(fcr63):%08x(", tmp.fpcr);
        !           597:        screen.Puts(x +  0, y, FA(tmp.fpcr, FPCR_EFINV), "EFINV");
        !           598:        screen.Puts(x +  6, y, FA(tmp.fpcr, FPCR_EFDVZ), "EFDVZ");
        !           599:        screen.Puts(x + 12, y, FA(tmp.fpcr, FPCR_EFUNF), "EFUNF");
        !           600:        screen.Puts(x + 18, y, FA(tmp.fpcr, FPCR_EFOVF), "EFOVF");
        !           601:        screen.Puts(x + 24, y, FA(tmp.fpcr, FPCR_EFINX), "EFINX");
        !           602:        screen.Print(x + 30, y, "RM=%s)", rmstr[(tmp.fpcr >> 14) & 3]);
1.1       root      603: }

unix.superglobalmegacorp.com

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