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

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

unix.superglobalmegacorp.com

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