Annotation of nono/debugger/debugger_m680x0.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.8   root        7: //
                      8: // デバッガ (M680x0 依存部分)
                      9: //
                     10: 
1.1       root       11: #include "debugger_m680x0.h"
1.1.1.9   root       12: #include "debugger_memory.h"
                     13: #include "debugger.h"
1.1.1.11  root       14: #include "exttostr.h"
                     15: #include "m680x0disasm.h"
1.1.1.9   root       16: #include "m68030mmu.h"
                     17: #include "mainbus.h"
1.1.1.13! root       18: #include "vectortable.h"
1.1       root       19: 
1.1.1.2   root       20: // コンストラクタ
1.1.1.9   root       21: DebuggerMD_m680x0::DebuggerMD_m680x0(Debugger *parent_)
                     22:        : inherited(parent_, CPUArch::M680x0)
1.1.1.2   root       23: {
1.1.1.9   root       24:        // この時点で Get*Device() は使える
1.1.1.10  root       25:        cpu = GetMPU680x0Device(parent->mpu);
1.1.1.9   root       26:        bus = GetMainbusDevice();
1.1.1.2   root       27: 
1.1.1.3   root       28:        // 機種依存変数
1.1.1.4   root       29:        inst_bytes = 2;
1.1.1.9   root       30:        lasize = 32;
                     31:        pasize = 32;
                     32:        name = "mpu";
1.1.1.2   root       33: }
                     34: 
                     35: // デストラクタ
                     36: DebuggerMD_m680x0::~DebuggerMD_m680x0()
                     37: {
                     38: }
                     39: 
1.1       root       40: // アドレス変換
1.1.1.10  root       41: busaddr
                     42: DebuggerMD_m680x0::TranslateAddr(busaddr laddr) const
1.1       root       43: {
1.1.1.10  root       44:        return cpu->TranslatePeek(laddr);
1.1       root       45: }
                     46: 
1.1.1.11  root       47: // op が 680x0 の条件命令 Bcc, Scc, TRAPcc, DBcc なら true を返す。
                     48: /*static*/ bool
1.1       root       49: DebuggerMD_m680x0::IsOPcc(uint16 op)
                     50: {
                     51:        uint16 cc;
                     52: 
                     53:        if ((op & 0xf000) == 0x6000) {
                     54:                cc = (op >> 8) & 0xf;
                     55:                if (cc == 0 || cc == 1) {               // BRA, BSR
                     56:                        return false;
                     57:                } else {
                     58:                        return true;                            // Bcc
                     59:                }
                     60:        }
                     61: 
                     62:        if ((op & 0xf0c0) == 0x50c0) {          // Scc, TRAPcc, DBcc
                     63:                return true;
                     64:        }
                     65: 
                     66:        return false;
                     67: }
                     68: 
                     69: // op が DBcc 命令なら true を返す。
1.1.1.11  root       70: /*static*/ bool
1.1       root       71: DebuggerMD_m680x0::IsDBcc(uint16 op)
                     72: {
                     73:        if ((op & 0xf0f8) == 0x50c8) {          // DBcc
                     74:                return true;
                     75:        }
                     76:        return false;
                     77: }
                     78: 
1.1.1.11  root       79: // ir[] が FBcc, FScc, FDBcc, FTRAPcc 命令なら condition のあるワード位置を
                     80: // 返す。これらの条件命令でなければ (FNOP も含む)、-1 を返す。
                     81: /*static*/ int
                     82: DebuggerMD_m680x0::IsFXcc(const std::vector<uint16>& ir)
                     83: {
                     84:        if ((ir[0] & 0xfe00) != 0xf200) {
                     85:                return -1;
                     86:        }
                     87:        if (ir.size() < 2) {
                     88:                return -1;
                     89:        }
                     90: 
                     91:        // FNOP は除く。
                     92:        if (ir[0] == 0xf280 && ir[1] == 0) {
                     93:                return -1;
                     94:        }
                     95: 
                     96:        uint type = (ir[0] >> 6) & 7;
                     97:        if (type == 1) {                // FScc/FDBcc/FTRAPcc
                     98:                return 1;
                     99:        } else if (type == 2) { // FBcc.W
                    100:                return 0;
                    101:        } else if (type == 3) { // FBcc.L
                    102:                return 0;
                    103:        }
                    104:        return -1;
                    105: }
                    106: 
1.1       root      107: // op の cccc 条件が現在の CCR で成立するなら true を返す。
                    108: bool
1.1.1.11  root      109: DebuggerMD_m680x0::IsCond(uint16 op) const
1.1       root      110: {
1.1.1.9   root      111:        bool N = cpu->reg.ccr.IsN();
                    112:        bool Z = cpu->reg.ccr.IsZ();
                    113:        bool V = cpu->reg.ccr.IsV();
                    114:        bool C = cpu->reg.ccr.IsC();
1.1       root      115: 
                    116:        switch ((op >> 8) & 0x0f) {
                    117:         case 0:        // T
                    118:                return true;
                    119:         case 1:        // F
                    120:                return false;
                    121:         case 2:        // HI
                    122:                return (!C) && (!Z);
                    123:         case 3:        // LS
                    124:                return C || Z;
                    125:         case 4:        // CC
                    126:                return !C;
                    127:         case 5:        // CS
                    128:                return C;
                    129:         case 6:        // NE
                    130:                return !Z;
                    131:         case 7:        // EQ
                    132:                return Z;
                    133:         case 8:        // VC
                    134:                return !V;
                    135:         case 9:        // VS
                    136:                return V;
                    137:         case 10:       // PL
                    138:                return !N;
                    139:         case 11:       // MI
                    140:                return N;
                    141:         case 12:       // GE
                    142:                return (N && V) || ((!N) && (!V));
                    143:         case 13:       // LT
                    144:                return (N && (!V)) || ((!N) && V);
                    145:         case 14:       // GT
                    146:                return (N && V && (!Z)) || ((!N) && (!V) && (!Z));
                    147:         case 15:       // LE
                    148:                return Z || (N && (!V)) || ((!N) && V);
                    149:         default:
                    150:                __unreachable();
                    151:        }
                    152: }
                    153: 
                    154: // addr 位置の命令が条件命令なら、成立可否などの文字列を返す。
                    155: // Bcc, Scc, TRAPcc 命令なら、条件が成立するかどうか。
                    156: // DBcc 命令ならブランチするかどうか。
                    157: const char *
1.1.1.11  root      158: DebuggerMD_m680x0::CondStr(const std::vector<uint16>& ir) const
1.1       root      159: {
                    160:        uint16 op = ir[0];
                    161: 
                    162:        // DBcc 命令なら、ブランチするかどうか
                    163:        // IsOPcc() は DBcc も含んでいるため、IsDBcc() の判定のほうが先。
                    164:        // DBcc は内部でカウンタレジスタを減算してから比較するため、
                    165:        // 命令実行前のカウンタが 0 の時点でループ終了となることに注意。
                    166:        if (IsDBcc(op)) {
                    167:                // 成立したら何もしない
                    168:                if (IsCond(op)) {
                    169:                        return " (will fall)";
                    170:                }
                    171:                // カウンタが -1 なら何もしない
                    172:                uint rr = op & 7;
1.1.1.9   root      173:                if ((cpu->reg.R[rr] & 0xffff) == 0) {
1.1       root      174:                        return " (will expire)";
                    175:                }
                    176:                // それ以外はブランチ
                    177:                return " (will take)";
                    178:        }
                    179: 
                    180:        // Bcc, Scc, TRAPcc 命令なら条件が成立するかどうか
                    181:        if (IsOPcc(op)) {
                    182:                if (IsCond(op)) {
                    183:                        return " (will take)";
                    184:                } else {
                    185:                        return " (will not take)";
                    186:                }
                    187:        }
                    188: 
1.1.1.11  root      189:        // FXcc
                    190:        int n = IsFXcc(ir);
                    191:        if (n >= 0) {
                    192:                struct fpemu fe0;
                    193:                struct fpframe fpf0;
                    194:                memset(&fe0, 0, sizeof(fe0));
                    195:                fe0.fe_fpframe = &fpf0;
                    196:                fe0.fe_fpsr = cpu->reg.fpframe.fpf_fpsr;
                    197:                int result = test_cc(&fe0, ir[n]);
                    198:                if (result < 0) {
                    199:                        return " (will take)";
                    200:                } else if (result == 0) {
                    201:                        return " (will not take)";
                    202:                }
                    203:        }
                    204: 
1.1       root      205:        // (ここで知ってる)条件命令ではない
                    206:        return "";
                    207: }
                    208: 
                    209: void
                    210: DebuggerMD_m680x0::SetStepOut()
                    211: {
1.1.1.9   root      212:        so_a7 = cpu->reg.A[7];
                    213:        so_sr = cpu->GetSR() & 0x3000;
1.1       root      214: }
                    215: 
                    216: bool
                    217: DebuggerMD_m680x0::IsStepOut() const
                    218: {
1.1.1.9   root      219:        return (cpu->reg.A[7] > so_a7 || (cpu->GetSR() & 0x3000) != so_sr);
1.1       root      220: }
                    221: 
1.1.1.4   root      222: // この命令がステップイン出来るなら true を返す
                    223: bool
1.1.1.5   root      224: DebuggerMD_m680x0::IsOpStepIn(DebuggerMemoryStream& mem)
1.1.1.4   root      225: {
1.1.1.9   root      226:        uint32 op = mem.Read(inst_bytes);
1.1.1.5   root      227: 
1.1.1.4   root      228:        if ((op & 0xfff0) == 0x4e40             // TRAP
                    229:         || (op == 0x4e76)                              // TRAPV
                    230:         || (op & 0xffc0) == 0x4e80             // JSR
                    231:         || (op & 0xf0f8) == 0x50f8             // TRAPcc
                    232:         || (op & 0xff00) == 0x6100             // BSR
                    233:         || (op & 0xfff8) == 0xf278             // FTRAPcc
1.1.1.10  root      234:         || (op & 0xfe00) == 0xfe00             // DOS($FFxx), FPACK($FExx)
1.1.1.4   root      235:        ) {
                    236:                return true;
                    237:        }
                    238: 
                    239:        // IOCS コール(に逆アセンブラで見えるやつ)も一命令扱いにしておく。
                    240:        // XXX 本当は X68k の時だけだが今の所副作用なさげなので
                    241:        if ((op & 0xff00) == 0x7000) {  // MOVEQ to %d0
1.1.1.9   root      242:                uint32 op2 = mem.Read(inst_bytes);
1.1.1.4   root      243:                if (op2 == 0x4e4f) {            // TRAP #15
                    244:                        return true;
                    245:                }
                    246:        }
                    247: 
                    248:        return false;
                    249: }
                    250: 
1.1       root      251: // レジスタ名からそのレジスタ値を返す。
1.1.1.9   root      252: // メモリダンプのような用途なのでアドレスとして使うレジスタのみ。
1.1       root      253: uint64
                    254: DebuggerMD_m680x0::GetRegAddr(const char *name) const
                    255: {
                    256:        uint32 addr;
                    257: 
                    258:        if ((*name | 0x20) == 'a') {
1.1.1.13! root      259:                if (name[1] < '0' || name[1] > '7') {
        !           260:                        return (uint64)-1;
        !           261:                }
1.1.1.9   root      262:                addr = cpu->reg.A[name[1] - '0'];
1.1       root      263: 
                    264:        } else if ((*name | 0x20) == 'd') {
1.1.1.13! root      265:                if (name[1] < '0' || name[1] > '7') {
        !           266:                        return (uint64)-1;
        !           267:                }
1.1.1.9   root      268:                addr = cpu->reg.D[name[1] - '0'];
1.1       root      269: 
                    270:        } else if (strcmp(name, "sp") == 0) {
1.1.1.9   root      271:                addr = cpu->reg.A[7];
1.1       root      272: 
                    273:        } else if (strcmp(name, "usp") == 0) {
1.1.1.11  root      274:                if (cpu->reg.s == false) {
                    275:                        addr = cpu->reg.A[7];
                    276:                } else {
                    277:                        addr = cpu->reg.usp;
                    278:                }
1.1       root      279: 
                    280:        } else if (strcmp(name, "isp") == 0) {
1.1.1.11  root      281:                if (cpu->reg.s && cpu->reg.m == false) {
                    282:                        addr = cpu->reg.A[7];
                    283:                } else {
                    284:                        addr = cpu->reg.isp;
                    285:                }
1.1       root      286: 
                    287:        } else if (strcmp(name, "msp") == 0) {
1.1.1.11  root      288:                if (cpu->reg.s && cpu->reg.m) {
                    289:                        addr = cpu->reg.A[7];
                    290:                } else {
                    291:                        addr = cpu->reg.msp;
                    292:                }
                    293: 
                    294:        } else if (strcmp(name, "ssp") == 0) {
                    295:                if (cpu->reg.s) {
                    296:                        addr = cpu->reg.A[7];
                    297:                } else {
                    298:                        if (cpu->reg.m) {
                    299:                                addr = cpu->reg.msp;
                    300:                        } else {
                    301:                                addr = cpu->reg.isp;
                    302:                        }
                    303:                }
1.1       root      304: 
                    305:        } else if (strcmp(name, "pc") == 0) {
1.1.1.9   root      306:                addr = cpu->reg.pc;
1.1       root      307: 
                    308:        } else if (strcmp(name, "vbr") == 0) {
1.1.1.9   root      309:                addr = cpu->GetVBR();
1.1       root      310: 
                    311:        } else if (strcmp(name, "srp") == 0) {
1.1.1.11  root      312:                if (cpu->GetMPUType() == m680x0MPUType::M68030) {
                    313:                        auto cpu68030 = dynamic_cast<MPU68030Device *>(cpu);
                    314:                        addr = cpu68030->GetSRPl();
                    315:                } else {
                    316:                        auto cpu68040 = dynamic_cast<MPU68040Device *>(cpu);
                    317:                        addr = cpu68040->GetSRP();
                    318:                }
1.1       root      319: 
                    320:        } else if (strcmp(name, "crp") == 0) {
1.1.1.11  root      321:                auto cpu68030 = dynamic_cast<MPU68030Device *>(cpu);
                    322:                if (cpu68030) {
                    323:                        addr = cpu68030->GetCRPl();
                    324:                } else {
                    325:                        return (uint64)-1;
                    326:                }
                    327: 
                    328:        } else if (strcmp(name, "urp") == 0) {
                    329:                auto cpu68040 = dynamic_cast<MPU68040Device *>(cpu);
                    330:                if (cpu68040) {
                    331:                        addr = cpu68040->GetURP();
                    332:                } else {
                    333:                        return (uint64)-1;
                    334:                }
1.1       root      335: 
                    336:        } else {
                    337:                return (uint64)-1;
                    338:        }
                    339:        return addr;
                    340: }
                    341: 
1.1.1.2   root      342: // レジスタ表示系コマンドのヘルプ
                    343: /*static*/ const HelpMessages
1.1.1.5   root      344: DebuggerMD_m680x0::HelpListReg = {
1.1.1.4   root      345:        { "r",          "Show general registers" },
                    346:        { "ra",         "Show ATC" },
                    347:        { "rf",         "Show FPU registers" },
                    348:        { "rm",         "Show MMU registers" },
                    349:        { "ro",         "Show other registers" },
1.1.1.2   root      350: };
                    351: 
1.1.1.5   root      352: /*static*/ const HelpMessages
                    353: DebuggerMD_m680x0::HelpReg = {
                    354:        //-----
                    355:        { "r", R"**(
                    356:        Command: r
                    357: 
                    358:        Shows main registers.
                    359:        )**" },
                    360: 
                    361:        //-----
                    362:        { "ra", R"**(
                    363:        Command: ra
                    364: 
                    365:        Shows m68030 ATC(Address Translation Cache) information.  Note that
                    366:        nono's ATC implementation is very different from the real one (to
                    367:        improve performance).
                    368:        )**" },
                    369: 
                    370:        //-----
                    371:        { "rf", R"**(
                    372:        Command: rf
                    373: 
                    374:        Shows 68881/68882's FPU registers.
                    375:        )**" },
                    376: 
                    377:        //-----
                    378:        { "rm", R"**(
                    379:        Command: rm
                    380: 
                    381:        Shows registers related to MMU and cache.
                    382:        )**" },
                    383: 
                    384:        //-----
                    385:        { "ro", R"**(
                    386:        Command: ro
                    387: 
                    388:        Shows other registers.
                    389:        )**" },
                    390: };
                    391: 
                    392: const HelpMessages&
                    393: DebuggerMD_m680x0::GetHelpListReg() const
                    394: {
                    395:        return HelpListReg;
                    396: }
                    397: 
1.1.1.2   root      398: const HelpMessages&
1.1.1.5   root      399: DebuggerMD_m680x0::GetHelpReg() const
1.1.1.2   root      400: {
1.1.1.5   root      401:        return HelpReg;
1.1.1.2   root      402: }
                    403: 
                    404: // レジスタ表示系コマンド
                    405: bool
1.1.1.8   root      406: DebuggerMD_m680x0::ShowRegister(FILE *cons,
1.1.1.2   root      407:        const std::vector<std::string>& args)
                    408: {
                    409:        // 余分な引数は無視する?
                    410: 
                    411:        if (args[0] == "r") {
                    412:                ShowRegMain(cons);
                    413:                return true;
                    414:        }
                    415:        if (args[0] == "ra") {
1.1.1.8   root      416:                ShowRegATC();
1.1.1.2   root      417:                return true;
                    418:        }
                    419:        if (args[0] == "rf") {
                    420:                ShowRegFPU(cons);
                    421:                return true;
                    422:        }
                    423:        if (args[0] == "rm") {
1.1.1.11  root      424:                if (cpu->GetMPUType() == m680x0MPUType::M68030) {
                    425:                        ShowRegMMU30(cons);
                    426:                } else {
                    427:                        ShowRegMMU40(cons);
                    428:                }
1.1.1.2   root      429:                return true;
                    430:        }
                    431:        if (args[0] == "ro") {
1.1.1.8   root      432:                ShowRegOther();
1.1.1.2   root      433:                return true;
                    434:        }
                    435: 
                    436:        // 該当なし
                    437:        return false;
                    438: }
                    439: 
                    440: 
1.1       root      441: // レジスタ表示 (基本セット)
                    442: void
1.1.1.8   root      443: DebuggerMD_m680x0::ShowRegMain(FILE *cons)
1.1       root      444: {
                    445: /*
                    446: D0:00000070 D4:CCCCCCCC  A0:00FFAA32 A4:CCCCCCCC  SR=F810(S I=0 X----)
                    447: D1:0000FFFF D5:00000000  A1:00000A7A A5:00000A7A
                    448: D2:00FF0000 D6:00000000  A2:CCCCCCCC A6:CCCCCCCC
                    449: D3:CCCCCCCC D7:00000003  A3:CCCCCCCC A7:00001FD8
                    450: */
                    451:        bool vr[16];
                    452: 
1.1.1.9   root      453:        for (int i = 0; i < countof(cpu->reg.R); i++) {
                    454:                vr[i] = (cpu->reg.R[i] != prev.R[i]);
1.1       root      455:        }
                    456: 
                    457:        // 1行目
1.1.1.8   root      458:        fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s  %sA%d:%08x%s %sA%d:%08x%s ",
1.1.1.9   root      459:                BOLDIF(vr[ 0]),  0, cpu->reg.R[ 0], NORM,
                    460:                BOLDIF(vr[ 4]),  4, cpu->reg.R[ 4], NORM,
                    461:                BOLDIF(vr[ 8]),  0, cpu->reg.R[ 8], NORM,
                    462:                BOLDIF(vr[12]),  4, cpu->reg.R[12], NORM);
1.1       root      463: 
                    464:        // 1行目 SR
1.1.1.9   root      465:        uint16 sr = cpu->GetSR();
                    466:        uint16 prevsr = prev.GetSR();
1.1       root      467:        // SR は上位バイトと下位バイトが変化したくらいでいいか?
1.1.1.8   root      468:        fprintf(cons, " SR:%s%02x%s%s%02x%s",
1.1       root      469:                BOLDIF((sr & 0xff00) != (prevsr & 0xff00)),
                    470:                sr >> 8,
                    471:                NORM,
                    472:                BOLDIF((sr & 0x00ff) != (prevsr & 0x00ff)),
                    473:                sr & 0xff,
                    474:                NORM);
1.1.1.8   root      475:        fprintf(cons, "(%c I=%d %c%c%c%c%c)\n",
1.1       root      476:                (sr & 0x2000) ? 'S' : '-',
                    477:                (sr >> 8) & 7,
1.1.1.9   root      478:                (sr & M68K::CCR_X) ? 'X' : '-',
                    479:                (sr & M68K::CCR_N) ? 'N' : '-',
                    480:                (sr & M68K::CCR_Z) ? 'Z' : '-',
                    481:                (sr & M68K::CCR_V) ? 'V' : '-',
                    482:                (sr & M68K::CCR_C) ? 'C' : '-');
1.1       root      483: 
                    484:        // 2行目
1.1.1.8   root      485:        fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s  %sA%d:%08x%s %sA%d:%08x%s\n",
1.1.1.9   root      486:                BOLDIF(vr[ 1]),  1, cpu->reg.R[ 1], NORM,
                    487:                BOLDIF(vr[ 5]),  5, cpu->reg.R[ 5], NORM,
                    488:                BOLDIF(vr[ 9]),  1, cpu->reg.R[ 9], NORM,
                    489:                BOLDIF(vr[13]),  5, cpu->reg.R[13], NORM);
1.1       root      490: 
                    491:        // 3行目
1.1.1.8   root      492:        fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s  %sA%d:%08x%s %sA%d:%08x%s\n",
1.1.1.9   root      493:                BOLDIF(vr[ 2]),  2, cpu->reg.R[ 2], NORM,
                    494:                BOLDIF(vr[ 6]),  6, cpu->reg.R[ 6], NORM,
                    495:                BOLDIF(vr[10]),  2, cpu->reg.R[10], NORM,
                    496:                BOLDIF(vr[14]),  6, cpu->reg.R[14], NORM);
1.1       root      497: 
                    498:        // 4行目
1.1.1.8   root      499:        fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s  %sA%d:%08x%s %sA%d:%08x%s\n",
1.1.1.9   root      500:                BOLDIF(vr[ 3]),  3, cpu->reg.R[ 3], NORM,
                    501:                BOLDIF(vr[ 7]),  7, cpu->reg.R[ 7], NORM,
                    502:                BOLDIF(vr[11]),  3, cpu->reg.R[11], NORM,
                    503:                BOLDIF(vr[15]),  7, cpu->reg.R[15], NORM);
1.1       root      504: }
                    505: 
                    506: // FPU レジスタ表示
                    507: void
1.1.1.8   root      508: DebuggerMD_m680x0::ShowRegFPU(FILE *cons)
1.1       root      509: {
                    510: /*
1.1.1.11  root      511: FP0:0000_12345678_12345678 = -0.1234567890123456789)
                    512: FPCR:     1234                   BS,SN,OE,OF,UF,DZ,X2,X1  RP=.X RM=Minus
                    513: FPSR: 12345678 N Z Inf NAN Q=$xx BS,SN,OE,OF,UF,DZ,X2,X1  AV AO AU AZ AX
                    514: FPIAR:12345678
1.1       root      515: */
                    516: 
                    517:        uint32 fpcr, fpsr, fpiar;
                    518:        uint32 ppcr, ppsr, ppiar;
                    519:        static const char * const rmstr[] = {
                    520:                "Near",
                    521:                "Zero",
                    522:                "Minus",
                    523:                "Plus",
                    524:        };
                    525: 
                    526:        fpcr  = cpu->reg.fpframe.fpf_fpcr;
                    527:        fpsr  = cpu->reg.fpframe.fpf_fpsr;
                    528:        fpiar = cpu->reg.fpframe.fpf_fpiar;
                    529:        ppcr  = prev.fpframe.fpf_fpcr;
                    530:        ppsr  = prev.fpframe.fpf_fpsr;
                    531:        ppiar = prev.fpframe.fpf_fpiar;
                    532: 
1.1.1.11  root      533:        for (uint n = 0; n < 8; n++) {
                    534:                uint32 *c_ = cpu->reg.fpframe.fpf_regs + (n) * 3;
                    535:                uint32 *p_ = prev.fpframe.fpf_regs + (n) * 3;
                    536:                bool d = (c_[0] ^ p_[0]) | (c_[1] ^ p_[1]) | (c_[2] ^ p_[2]);
                    537:                fprintf(cons, "%sFP%u:%04x_%08x_%08x%s = %s\n",
                    538:                        BOLDIF(d), n, c_[0] >> 16, c_[1], c_[2], NORM,
                    539:                        ExtToStr(c_).c_str());
                    540:        }
1.1       root      541: 
1.1.1.11  root      542:        fprintf(cons, "%sFPCR:     %04x%s%20s",
                    543:                BOLDIF(fpcr != ppcr), fpcr, NORM, "");
                    544:        fprintf(cons, "%s %s %s %s %s %s %s %s  ",
1.1       root      545:                (fpcr & 0x8000) ? "BS" : "--",
                    546:                (fpcr & 0x4000) ? "SN" : "--",
1.1.1.11  root      547:                (fpcr & 0x2000) ? "OE" : "--",
                    548:                (fpcr & 0x1000) ? "OF" : "--",
1.1       root      549:                (fpcr & 0x0800) ? "UF" : "--",
                    550:                (fpcr & 0x0400) ? "DZ" : "--",
1.1.1.11  root      551:                (fpcr & 0x0200) ? "X2" : "--",
                    552:                (fpcr & 0x0100) ? "X1" : "--");
                    553:        fprintf(cons, "RP=.%c RM=%s\n",
                    554:                "XSD?"[(fpcr >> 6) & 3],
1.1       root      555:                rmstr[(fpcr >> 4) & 3]);
                    556: 
                    557:        uint cc = fpsr >> 24;
1.1.1.11  root      558:        fprintf(cons, "%sFPSR: %08x%s ", BOLDIF(fpsr != ppsr), fpsr, NORM);
                    559:        fprintf(cons, "%c %c %s %s Q=$%02x  ",
1.1       root      560:                (cc & 0x08) ? 'N' : '-',
                    561:                (cc & 0x04) ? 'Z' : '-',
                    562:                (cc & 0x02) ? "Inf" : "---",
                    563:                (cc & 0x01) ? "NAN" : "---",
                    564:                (fpsr >> 16) & 0xff);
1.1.1.11  root      565:        fprintf(cons, "%s %s %s %s %s %s %s %s  ",
1.1       root      566:                (fpsr & 0x8000) ? "BS" : "--",
                    567:                (fpsr & 0x4000) ? "SN" : "--",
                    568:                (fpsr & 0x2000) ? "OP" : "--",
                    569:                (fpsr & 0x1000) ? "OV" : "--",
                    570:                (fpsr & 0x0800) ? "UF" : "--",
                    571:                (fpsr & 0x0400) ? "DZ" : "--",
                    572:                (fpsr & 0x0200) ? "I2" : "--",
                    573:                (fpsr & 0x0100) ? "I1" : "--");
1.1.1.11  root      574:        fprintf(cons, "%s %s %s %s %s\n",
                    575:                (fpsr & 0x80) ? "AV" : "--",
                    576:                (fpsr & 0x40) ? "AO" : "--",
                    577:                (fpsr & 0x20) ? "AU" : "--",
                    578:                (fpsr & 0x10) ? "AZ" : "--",
                    579:                (fpsr & 0x08) ? "AX" : "--");
1.1       root      580: 
1.1.1.8   root      581:        fprintf(cons, "%sFPIAR:%08x%s\n", BOLDIF(fpiar != ppiar), fpiar, NORM);
1.1       root      582: }
                    583: 
1.1.1.11  root      584: // 68030 MMU レジスタ表示
1.1       root      585: void
1.1.1.11  root      586: DebuggerMD_m680x0::ShowRegMMU30(FILE *cons)
1.1       root      587: {
                    588: /*
                    589: SRP:00001111_22223333 TT0:00001111 TC:00001111 (---)
                    590: CRP:00001111_22223333 TT1:00001111 MMUSR: 0011 (
                    591: */
1.1.1.11  root      592:        auto cpu68030 = dynamic_cast<MPU68030Device *>(cpu);
1.1       root      593:        uint64 srp, osrp;
                    594:        uint64 crp, ocrp;
                    595:        uint32 tt0, ott0;
                    596:        uint32 tt1, ott1;
                    597:        uint32 tc,  otc;
                    598:        uint16 sr,  osr;
                    599:        bool p;
                    600:        bool t;
                    601:        bool c;
                    602: 
1.1.1.11  root      603:        srp = cpu68030->GetSRP();
                    604:        crp = cpu68030->GetCRP();
                    605:        tt0 = cpu68030->GetTT(0);
                    606:        tt1 = cpu68030->GetTT(1);
                    607:        tc  = cpu68030->GetTC();
                    608:        sr  = cpu68030->GetMMUSR();
1.1       root      609: 
                    610:        osrp = prev.srp.q;
                    611:        ocrp = prev.crp.q;
                    612:        ott0 = prev.tt[0];
                    613:        ott1 = prev.tt[1];
                    614:        otc  = prev.tc;
                    615:        osr  = prev.mmusr;
                    616: 
                    617:        // 1行目
                    618:        p = (srp != osrp);
                    619:        t = (tt0 != ott0);
                    620:        c = (tc  != otc);
1.1.1.8   root      621:        fprintf(cons, "%sSRP:%08x_%08x%s  %sTT0:%08x%s(%c%c%c)",
1.1       root      622:                BOLDIF(p), (uint32)(srp >> 32), (uint32)srp, NORM,
                    623:                BOLDIF(t), tt0, NORM,
                    624:                (tt0 & m68030TT::E)   ? 'E' : '-',
                    625:                (tt0 & m68030TT::CI)  ? 'C' : '-',
                    626:                (tt0 & m68030TT::RWM) ? '-' : ((tt0 & m68030TT::RW)  ? 'R' : 'W'));
1.1.1.8   root      627:        fprintf(cons, "  %sTC:%08x%s(%c%c%c)\n",
1.1       root      628:                BOLDIF(c), tc, NORM,
                    629:                (tc & m68030TC::TC_E)   ? 'E' : '-',
                    630:                (tc & m68030TC::TC_SRE) ? 'S' : '-',
                    631:                (tc & m68030TC::TC_FCL) ? 'F' : '-');
                    632: 
                    633:        // 2行目
                    634:        p = (crp != ocrp);
                    635:        t = (tt1 != ott1);
                    636:        c = (sr  != osr);
1.1.1.8   root      637:        fprintf(cons, "%sCRP:%08x_%08x%s  %sTT1:%08x%s(%c%c%c)",
1.1       root      638:                BOLDIF(p), uint32(crp >> 32), (uint32)crp, NORM,
                    639:                BOLDIF(t), tt1, NORM,
                    640:                (tt1 & m68030TT::E)   ? 'E' : '-',
                    641:                (tt1 & m68030TT::CI)  ? 'C' : '-',
                    642:                (tt1 & m68030TT::RWM) ? '-' : ((tt1 & m68030TT::RW)  ? 'R' : 'W'));
1.1.1.8   root      643:        fprintf(cons, "  %sMMUSR: %04x%s(%c%c%c%c%c%c%c N=%d)\n",
1.1       root      644:                BOLDIF(c), sr,  NORM,
                    645:                (sr & m68030MMUSR::B) ? 'B' : '-',
                    646:                (sr & m68030MMUSR::L) ? 'L' : '-',
                    647:                (sr & m68030MMUSR::S) ? 'S' : '-',
                    648:                (sr & m68030MMUSR::W) ? 'W' : '-',
                    649:                (sr & m68030MMUSR::I) ? 'I' : '-',
                    650:                (sr & m68030MMUSR::M) ? 'M' : '-',
                    651:                (sr & m68030MMUSR::T) ? 'T' : '-',
                    652:                (sr & m68030MMUSR::N));
                    653: }
                    654: 
1.1.1.11  root      655: // 68040 MMU レジスタ表示
                    656: void
                    657: DebuggerMD_m680x0::ShowRegMMU40(FILE *cons)
                    658: {
                    659:        fprintf(cons, "Not implemented\n");
                    660: }
                    661: 
1.1       root      662: // ATC を表示
                    663: void
1.1.1.8   root      664: DebuggerMD_m680x0::ShowRegATC()
1.1       root      665: {
1.1.1.8   root      666:        parent->ShowMonitor(gMonitorManager->Get(ID_MONITOR_MPUATC));
1.1       root      667: }
                    668: 
                    669: // その他のレジスタを表示
                    670: void
1.1.1.8   root      671: DebuggerMD_m680x0::ShowRegOther()
1.1       root      672: {
                    673:        TextScreen s(80, 2);
                    674: 
                    675:        // 0         1         2         3         4         5         6
                    676:        // 012345678901234567890123456789012345678901234567890123456789012345
                    677:        // CACR:01234567  VBR:01234567  USP:01234567
                    678:        // CAAR:01234567  SFC:0  DFC:0  MSP:01234567
                    679: 
                    680: #define EM(name) ((cpu->reg.name != prev.name) ? TA::Em : TA::Normal)
                    681:        s.Print(0, 0, EM(cacr), "CACR:%08x", cpu->reg.cacr);
                    682:        s.Print(0, 1, EM(caar), "CAAR:%08x", cpu->reg.caar);
                    683: 
                    684:        s.Print(15, 0, EM(vbr), "VBR:%08x", cpu->reg.vbr);
1.1.1.10  root      685:        s.Print(15, 1, EM(sfc), "SFC:%d", cpu->reg.GetSFC());
                    686:        s.Print(22, 1, EM(dfc), "DFC:%d", cpu->reg.GetDFC());
1.1       root      687: 
                    688:        // スタック欄はモードによって表示を変える。
                    689:        //              ユーザ       割り込み    マスタ
                    690:        // 1行目      ISP             USP                     USP
                    691:        // 2行目      MSP             MSP                     ISP
1.1.1.9   root      692:        if (!cpu->IsSuper()) {
1.1       root      693:                s.Print(29, 0, EM(isp), "ISP:%08x", cpu->reg.isp);
                    694:        } else {
                    695:                s.Print(29, 0, EM(usp), "USP:%08x", cpu->reg.usp);
                    696:        }
1.1.1.9   root      697:        if (!cpu->IsMaster()) {
1.1       root      698:                s.Print(29, 1, EM(msp), "MSP:%08x", cpu->reg.msp);
                    699:        } else {
                    700:                s.Print(29, 1, EM(isp), "ISP:%08x", cpu->reg.isp);
                    701:        }
                    702: 
1.1.1.2   root      703:        parent->ShowTextScreen(s);
1.1       root      704: }
                    705: 
1.1.1.9   root      706: // オンライン用逆アセンブル
                    707: std::string
                    708: DebuggerMD_m680x0::Disassemble(DebuggerMemoryStream& mem)
1.1       root      709: {
1.1.1.9   root      710:        m680x0disasm dis;
                    711:        if (dis.Exec(&mem) == false) {
                    712:                return "dis.Exec() failed";
                    713:        }
                    714: 
                    715:        // dis.bin は uint8 列なのでこれを uint16 列に変換
                    716:        std::vector<uint16> words;
                    717:        for (int i = 0; i < dis.bin.size(); i += 2) {
                    718:                words.push_back((dis.bin[i] << 8) | dis.bin[i + 1]);
1.1       root      719:        }
                    720: 
                    721:        // 16進ダンプ
                    722:        std::string dumpbuf;
1.1.1.9   root      723:        for (auto w : words) {
                    724:                dumpbuf += string_format("%04x ", w);
1.1       root      725:        }
                    726: 
                    727:        // ダンプは5ワード分 (越えたら知らん)
1.1.1.9   root      728:        std::string str = string_format("%-25s", dumpbuf.c_str());
                    729:        // ニーモニック
                    730:        str += dis.text;
                    731:        // (あれば) 条件判断
                    732:        str += CondStr(words);
1.1       root      733: 
1.1.1.9   root      734:        return str;
1.1       root      735: }
1.1.1.12  root      736: 
                    737: // 命令ニーモニックに対するバイナリを文字列形式で返す。
                    738: // 対応しない場合は "" を返す。cmd_bi 用。
                    739: std::string
                    740: DebuggerMD_m680x0::ParseInst(const std::string& inst) const
                    741: {
1.1.1.13! root      742:        if (inst == "frestore") return "f340:ffc0";
        !           743:        if (inst == "fsave")    return "f300:ffc0";
        !           744:        if (inst == "nop")              return "4e71";
        !           745:        if (inst == "ptestr")   return "f0008200:ffc0e200";
        !           746:        if (inst == "ptestw")   return "f0008000:ffc0e200";
1.1.1.12  root      747:        if (inst == "rte")              return "4e73";
                    748: 
                    749:        return "";
                    750: }
1.1.1.13! root      751: 
        !           752: // 例外フレーム処理用の便利クラス。
        !           753: // 例外フレーム内は基本ワード単位なのに、仕様書のオフセットはバイト単位
        !           754: // なのでこういうヘルパーがないと事故が多発する。
        !           755: class StackData
        !           756: {
        !           757:  public:
        !           758:        StackData(DebuggerMemoryStream& mem_)
        !           759:                : mem(mem_)
        !           760:        {
        !           761:        }
        !           762: 
        !           763:        // 合計が words [ワード] になるまで追加で読み込む。
        !           764:        void ReadWordUntil(size_t words);
        !           765:        // 合計が bytes (偶数) [バイト] になるまで追加で読み込む。
        !           766:        void ReadByteUntil(size_t bytes);
        !           767: 
        !           768:        // 改行込みで出力。
        !           769:        void Print(FILE *out, size_t byteoffset, uint bytes) const;
        !           770:        void Print(FILE *out, size_t byteoffset, uint bytes,
        !           771:                const char *, ...) const __printflike(5, 6);
        !           772: 
        !           773:        // 共通の表示用文字列を作成して返す。戻り値は改行なしの文字列。
        !           774:        std::string Format(size_t byteoffset, uint bytes) const;
        !           775:        std::string Format(size_t byteoffset, uint bytes,
        !           776:                const char *, ...) const __printflike(4, 5);
        !           777: 
        !           778:        // byteoffset の位置のデータを表示用文字列にする。
        !           779:        std::string FormatWord(size_t byteoffset) const;
        !           780:        std::string FormatLong(size_t byteoffset) const;
        !           781: 
        !           782:        // byteoffset の位置からのワードデータを返す。バスエラーなら -1。
        !           783:        uint32 Word(size_t byteoffset) const;
        !           784:        // byteoffset の位置からのロングワードを返す。バスエラーなら (uint64)-1。
        !           785:        uint64 Long(size_t byteoffset) const;
        !           786: 
        !           787:        // データサイズをバイト単位で返す。
        !           788:        size_t bytesize() const noexcept { return framebuf.size() * 2; }
        !           789: 
        !           790:  private:
        !           791:        std::string FormatV(size_t byteoffset, uint bytes,
        !           792:                const char *, va_list) const __printflike(4, 0);
        !           793: 
        !           794:        DebuggerMemoryStream mem;
        !           795:        std::vector<uint32> framebuf {};
        !           796: };
        !           797: 
        !           798: void
        !           799: StackData::ReadWordUntil(size_t words)
        !           800: {
        !           801:        while (framebuf.size() < words) {
        !           802:                framebuf.push_back(mem.Read(2));
        !           803:        }
        !           804: }
        !           805: 
        !           806: void
        !           807: StackData::ReadByteUntil(size_t bytes)
        !           808: {
        !           809:        assert((bytes % 1) == 0);
        !           810:        size_t words = bytes / 2;
        !           811:        while (framebuf.size() < words) {
        !           812:                framebuf.push_back(mem.Read(2));
        !           813:        }
        !           814: }
        !           815: 
        !           816: // 改行込みで表示する。bytes は 2, 4, 16 のみ。追加情報なし。
        !           817: void
        !           818: StackData::Print(FILE *out, size_t byteoffset, uint bytes) const
        !           819: {
        !           820:        fprintf(out, "%s\n", Format(byteoffset, bytes).c_str());
        !           821: }
        !           822: 
        !           823: // 改行込みで表示する。bytes は 2, 4, 16 のみ。
        !           824: void
        !           825: StackData::Print(FILE *out, size_t byteoffset, uint bytes,
        !           826:        const char *fmt, ...) const
        !           827: {
        !           828:        va_list ap;
        !           829: 
        !           830:        assert(bytes == 2 || bytes == 4 || bytes == 16);
        !           831: 
        !           832:        va_start(ap, fmt);
        !           833:        fprintf(out, "%s\n", FormatV(byteoffset, bytes, fmt, ap).c_str());
        !           834:        va_end(ap);
        !           835: }
        !           836: 
        !           837: // 共通の表示用文字列を作成して返す。戻り値は改行なしの文字列。
        !           838: std::string
        !           839: StackData::Format(size_t byteoffset, uint bytes) const
        !           840: {
        !           841:        std::string s = string_format("+$%02x: ", (uint)byteoffset);
        !           842:        if (bytes == 2) {
        !           843:                s += FormatWord(byteoffset);
        !           844:        } else if (bytes == 4) {
        !           845:                s += FormatLong(byteoffset);
        !           846:        } else {
        !           847:                s += FormatLong(byteoffset);
        !           848:                s += ' ';
        !           849:                s += FormatLong(byteoffset + 4);
        !           850:                s += ' ';
        !           851:                s += FormatLong(byteoffset + 8);
        !           852:                s += ' ';
        !           853:                s += FormatLong(byteoffset + 12);
        !           854:        }
        !           855: 
        !           856:        return s;
        !           857: }
        !           858: 
        !           859: // 共通の表示用文字列を作成して返す。戻り値は改行なしの文字列。
        !           860: std::string
        !           861: StackData::Format(size_t byteoffset, uint bytes, const char *fmt, ...) const
        !           862: {
        !           863:        std::string str;
        !           864:        va_list ap;
        !           865: 
        !           866:        va_start(ap, fmt);
        !           867:        str = FormatV(byteoffset, bytes, fmt, ap);
        !           868:        va_end(ap);
        !           869: 
        !           870:        return str;
        !           871: }
        !           872: 
        !           873: // 共通の表示用文字列を作成して返す。戻り値は改行なしの文字列。
        !           874: std::string
        !           875: StackData::FormatV(size_t byteoffset, uint bytes,
        !           876:        const char *fmt, va_list ap) const
        !           877: {
        !           878:        std::string s = Format(byteoffset, bytes);
        !           879: 
        !           880:        char text[128];
        !           881:        vsnprintf(text, sizeof(text), fmt, ap);
        !           882:        if (text[0]) {
        !           883:                if (bytes == 2) {
        !           884:                        s += "    ";
        !           885:                }
        !           886:                s += string_format(" : %s", text);
        !           887:        }
        !           888:        return s;
        !           889: }
        !           890: 
        !           891: // byteoffset の位置からのワードデータを表示用文字列にする。
        !           892: std::string
        !           893: StackData::FormatWord(size_t byteoffset) const
        !           894: {
        !           895:        uint32 data = Word(byteoffset);
        !           896:        if ((int32)data < 0) {
        !           897:                return "----";
        !           898:        } else {
        !           899:                char buf[16];
        !           900:                snprintf(buf, sizeof(buf), "%04x", data);
        !           901:                return buf;
        !           902:        }
        !           903: }
        !           904: 
        !           905: // byteoffset の位置からのロングワードデータを表示用文字列にする。
        !           906: std::string
        !           907: StackData::FormatLong(size_t byteoffset) const
        !           908: {
        !           909:        uint64 data = Long(byteoffset);
        !           910:        if ((int64)data < 0) {
        !           911:                return "--------";
        !           912:        } else {
        !           913:                char buf[16];
        !           914:                snprintf(buf, sizeof(buf), "%08x", (uint32)data);
        !           915:                return buf;
        !           916:        }
        !           917: }
        !           918: 
        !           919: uint32
        !           920: StackData::Word(size_t byteoffset) const
        !           921: {
        !           922:        size_t wordoffset = byteoffset / 2;
        !           923:        assert(wordoffset < framebuf.size());
        !           924:        return framebuf[wordoffset];
        !           925: }
        !           926: 
        !           927: uint64
        !           928: StackData::Long(size_t byteoffset) const
        !           929: {
        !           930:        uint32 hi = Word(byteoffset);
        !           931:        uint32 lo = Word(byteoffset + 2);
        !           932:        if ((int32)hi < 0 || (int32)lo < 0) {
        !           933:                return (uint64)-1;
        !           934:        }
        !           935:        return (hi << 16) | lo;
        !           936: }
        !           937: 
        !           938: // 例外フレームを表示する。
        !           939: void
        !           940: DebuggerMD_m680x0::PrintExceptionFrame(FILE *out, busaddr addr)
        !           941: {
        !           942:        DebuggerMemoryStream mem(this, addr);
        !           943:        StackData frame(mem);
        !           944: 
        !           945:        fprintf(out, "Exception stack at $%08x\n", addr.Addr());
        !           946: 
        !           947:        frame.ReadWordUntil(4);
        !           948: 
        !           949:        // ここからフレーム別。
        !           950:        uint32 format = frame.Word(6) >> 12;
        !           951:        switch (format) {
        !           952:         case 0x0:      // 034 Four word stack
        !           953:                PrintExceptionFrame0(out, frame);
        !           954:                break;
        !           955: 
        !           956:         case 0x1:      // 034 Throwaway four word stack
        !           957:                PrintExceptionFrameCommon(out, frame, true);
        !           958:                break;
        !           959: 
        !           960:         case 0x2:      // 034 Six word stack
        !           961:                PrintExceptionFrame2(out, frame);
        !           962:                break;
        !           963: 
        !           964:         case 0x3:      // --4 Floating-point post-instruction stack
        !           965:                PrintExceptionFrame3(out, frame);
        !           966:                break;
        !           967: 
        !           968:         case 0x4:      // --L Eight-word stack
        !           969:                PrintExceptionFrame4(out, frame);
        !           970:                break;
        !           971: 
        !           972:         case 0x7:      // --4 Access error stack
        !           973:                PrintExceptionFrame7(out, frame);
        !           974:                break;
        !           975: 
        !           976:         case 0xb:      // -3- Long bus cycle stack
        !           977:                PrintExceptionFrameB(out, frame);
        !           978:                break;
        !           979: 
        !           980:         case 9:        // -3- Coprocessor mid-instruction Stack
        !           981:         case 0xa:      // -3- Short bus cycle stack (nono は生成しない)
        !           982:         default:
        !           983:                fprintf(out, "Format $%x not supported\n", format);
        !           984:                break;
        !           985:        }
        !           986: }
        !           987: 
        !           988: // 共通の4ワード目までを表示する。
        !           989: bool
        !           990: DebuggerMD_m680x0::PrintExceptionFrameCommon(FILE *out,
        !           991:        const StackData& frame, bool pc_is_next)
        !           992: {
        !           993:        // $06: Format|Vector
        !           994:        uint32 format_vector = frame.Word(6);
        !           995:        uint32 format = format_vector >> 12;
        !           996:        std::string s6;
        !           997:        if ((int32)format_vector < 0) {
        !           998:                s6 += "Format+Vector";
        !           999:        } else {
        !          1000:                uint32 vector = (format_vector >> 2) & 0xff;
        !          1001:                s6 += string_format("Format=$%x Vector=$%02x", format, vector);
        !          1002: 
        !          1003:                // ベクタ番号からベクタ名を引いてみる。
        !          1004:                // Vector=$b は本来 Format=$0 で F ライン例外だが、
        !          1005:                // Format=$2 Vector=$b なら 68040 の未実装 FP 命令例外なので区別する。
        !          1006:                const char *exname = NULL;
        !          1007:                if (format == 2 && vector == 0x0b) {
        !          1008:                        exname = "Unimplemented FP Instruction";
        !          1009:                } else {
        !          1010:                        auto vectortable = GetVectorTable();
        !          1011:                        exname = vectortable->GetExceptionName(vector);
        !          1012:                }
        !          1013:                if (exname) {
        !          1014:                        s6 += " \"";
        !          1015:                        s6 += exname;
        !          1016:                        s6 += '\"';
        !          1017:                }
        !          1018:        }
        !          1019: 
        !          1020:        frame.Print(out, 0, 2, "SR");
        !          1021:        frame.Print(out, 2, 4, "%sPC", pc_is_next ? "Next ": "");
        !          1022:        frame.Print(out, 6, 2, "%s", s6.c_str());
        !          1023: 
        !          1024:        // ここがバスエラーならもう出来ることはない。
        !          1025:        if ((int32)format_vector < 0) {
        !          1026:                return false;
        !          1027:        }
        !          1028:        return true;
        !          1029: }
        !          1030: 
        !          1031: void
        !          1032: DebuggerMD_m680x0::PrintExceptionFrame0(FILE *out, StackData& frame)
        !          1033: {
        !          1034:        // Format$0 の PC は
        !          1035:        // 種類                                                       PC
        !          1036:        // ----
        !          1037:        // ・割り込み                                      次の命令
        !          1038:        // ・TRAP#N                                            次の命令
        !          1039:        // ・フォーマットエラー                       当該命令(RTE/FRESTORE)
        !          1040:        // ・不当命令                                      当該命令
        !          1041:        // ・A/F ライン命令                               当該命令
        !          1042:        // ・特権違反                                      当該命令
        !          1043: 
        !          1044:        bool next;
        !          1045:        uint vector = (frame.Word(0x06) & 0xfff) >> 2;
        !          1046:        switch (vector) {
        !          1047:         case M68K::EXCEP_FORMAT:
        !          1048:         case M68K::EXCEP_ILLEGAL:
        !          1049:         case M68K::EXCEP_ALINE:
        !          1050:         case M68K::EXCEP_FLINE:
        !          1051:         case M68K::EXCEP_PRIV:
        !          1052:                next = false;
        !          1053:                break;
        !          1054:         default:
        !          1055:                next = true;
        !          1056:                break;
        !          1057:        }
        !          1058:        PrintExceptionFrameCommon(out, frame, next);
        !          1059: }
        !          1060: 
        !          1061: void
        !          1062: DebuggerMD_m680x0::PrintExceptionFrame2(FILE *out, StackData& frame)
        !          1063: {
        !          1064:        // Format$2 の PC と Address は
        !          1065:        // 種類                                                       PC                      Address
        !          1066:        // ----                                                 --                      -------
        !          1067:        // ・CHK/CHK2/TRAP*/                   次の命令    例外を起こした命令
        !          1068:        //   FTRAPcc/Trace/ZeroDiv
        !          1069:        // ・MMU 構成例外                          次の命令    例外を起こした命令
        !          1070:        // ・040 未実装FP命令                     次の命令    FPが計算したEA
        !          1071:        // ・040 アドレスエラー                 当該命令    参照アドレス-1
        !          1072: 
        !          1073:        bool next;
        !          1074:        const char *addr;
        !          1075:        uint vector = (frame.Word(0x06) & 0xfff) >> 2;
        !          1076:        switch (vector) {
        !          1077:         case M68K::EXCEP_ZERODIV:
        !          1078:         case M68K::EXCEP_CHK:
        !          1079:         case M68K::EXCEP_TRAPV:
        !          1080:         case M68K::EXCEP_TRACE:
        !          1081:         case M68K::EXCEP_MMU_CONFIG:
        !          1082:                next = true;
        !          1083:                addr = "Caused instruction address";
        !          1084:                break;
        !          1085: 
        !          1086:         case M68K::EXCEP_FLINE:        // これは 040 の EXCEP_FP_UNIMPL
        !          1087:                next = true;
        !          1088:                addr = "Calculated EA";
        !          1089:                break;
        !          1090: 
        !          1091:         case M68K::EXCEP_ADDRERR:
        !          1092:                next = false;
        !          1093:                addr = "Reference Address - 1";
        !          1094:                break;
        !          1095: 
        !          1096:         default:
        !          1097:                next = false;
        !          1098:                addr = "?";
        !          1099:                break;
        !          1100:        }
        !          1101: 
        !          1102:        frame.ReadWordUntil(6);
        !          1103:        if (PrintExceptionFrameCommon(out, frame, next) == false) {
        !          1104:                return;
        !          1105:        }
        !          1106:        frame.Print(out, 0x08, 4, "%s", addr);
        !          1107: }
        !          1108: 
        !          1109: void
        !          1110: DebuggerMD_m680x0::PrintExceptionFrame3(FILE *out, StackData& frame)
        !          1111: {
        !          1112:        frame.ReadWordUntil(6);
        !          1113:        if (PrintExceptionFrameCommon(out, frame, true) == false) {
        !          1114:                return;
        !          1115:        }
        !          1116:        frame.Print(out, 0x08, 4, "Effective Address");
        !          1117: }
        !          1118: 
        !          1119: void
        !          1120: DebuggerMD_m680x0::PrintExceptionFrame4(FILE *out, StackData& frame)
        !          1121: {
        !          1122:        frame.ReadWordUntil(8);
        !          1123:        if (PrintExceptionFrameCommon(out, frame, true) == false) {
        !          1124:                return;
        !          1125:        }
        !          1126:        frame.Print(out, 0x08, 4, "Effective Address");
        !          1127:        frame.Print(out, 0x0c, 4, "PC of Faulted Instruction");
        !          1128: }
        !          1129: 
        !          1130: void
        !          1131: DebuggerMD_m680x0::PrintExceptionFrame7(FILE *out, StackData& frame)
        !          1132: {
        !          1133:        static const char * const sizestr[] = {
        !          1134:                ".L",
        !          1135:                ".B",
        !          1136:                ".W",
        !          1137:                "Line",
        !          1138:        };
        !          1139: 
        !          1140:        frame.ReadWordUntil(30);
        !          1141:        if (PrintExceptionFrameCommon(out, frame, true) == false) {
        !          1142:                return;
        !          1143:        }
        !          1144:        frame.Print(out, 0x08, 4, "Effective Address");
        !          1145: 
        !          1146:        // SSW
        !          1147:        uint16 ssw = frame.Word(0x0c);
        !          1148:        frame.Print(out, 0x0c, 2,
        !          1149:                "SSW (%s %s %s %s %s %s %s RW=%c size=%s TT=%u TM=%u)",
        !          1150:                ((ssw & M68040::SSW_CP)  ? "CP" : "--"),
        !          1151:                ((ssw & M68040::SSW_CU)  ? "CU" : "--"),
        !          1152:                ((ssw & M68040::SSW_CT)  ? "CT" : "--"),
        !          1153:                ((ssw & M68040::SSW_CM)  ? "CM" : "--"),
        !          1154:                ((ssw & M68040::SSW_MA)  ? "MA" : "--"),
        !          1155:                ((ssw & M68040::SSW_ATC) ? "ATC" : "---"),
        !          1156:                ((ssw & M68040::SSW_LK)  ? "LK" : "--"),
        !          1157:                ((ssw & M68040::SSW_RW)  ? 'R' : 'W'),
        !          1158:                sizestr[(ssw >> 5) & 3],
        !          1159:                ((ssw >> 3) & 3),
        !          1160:                (ssw & 7));
        !          1161: 
        !          1162:        // WB[321]S
        !          1163:        for (uint i = 0; i < 3; i++) {
        !          1164:                size_t off = 0x0e + i * 2;
        !          1165:                uint16 wbs = frame.Word(off);
        !          1166:                std::string stbuf;
        !          1167:                if ((wbs & 0x80)) {
        !          1168:                        stbuf = "Valid";
        !          1169:                        stbuf += string_format(" size=%s", sizestr[(wbs >> 5) & 3]);
        !          1170:                        stbuf += string_format(" TT=%u", (wbs >> 3) & 3);
        !          1171:                        stbuf += string_format(" TM=%u", wbs & 7);
        !          1172:                } else {
        !          1173:                        stbuf = "no pending";
        !          1174:                }
        !          1175:                frame.Print(out, off, 2, "WB%u Status (%s)", 3 - i, stbuf.c_str());
        !          1176:        }
        !          1177: 
        !          1178:        frame.Print(out, 0x14, 4, "Fault Address");
        !          1179:        frame.Print(out, 0x18, 4, "WB3 Address");
        !          1180:        frame.Print(out, 0x1c, 4, "WB3 Data");
        !          1181:        frame.Print(out, 0x20, 4, "WB2 Address");
        !          1182:        frame.Print(out, 0x24, 4, "WB2 Data");
        !          1183:        frame.Print(out, 0x28, 4, "WB1 Address");
        !          1184:        frame.Print(out, 0x2c, 4, "WB1 Data / PushData 0");
        !          1185:        frame.Print(out, 0x30, 4, "Push Data 1");
        !          1186:        frame.Print(out, 0x34, 4, "Push Data 2");
        !          1187:        frame.Print(out, 0x38, 4, "Push Data 3");
        !          1188: }
        !          1189: 
        !          1190: void
        !          1191: DebuggerMD_m680x0::PrintExceptionFrameB(FILE *out, StackData& frame)
        !          1192: {
        !          1193:        frame.ReadWordUntil(46);
        !          1194:        if (PrintExceptionFrameCommon(out, frame, false) == false) {
        !          1195:                return;
        !          1196:        }
        !          1197:        frame.Print(out, 0x08, 2);      // internal
        !          1198: 
        !          1199:        // SSW
        !          1200:        uint16 ssw = frame.Word(0x0a);
        !          1201:        frame.Print(out, 0x0a, 2,
        !          1202:                "SSW (%s %s %s %s %s %s RW=%c size=%c FC=%u)",
        !          1203:                ((ssw & M68030::SSW_FC) ? "FC" : "--"),
        !          1204:                ((ssw & M68030::SSW_FB) ? "FB" : "--"),
        !          1205:                ((ssw & M68030::SSW_RC) ? "RC" : "--"),
        !          1206:                ((ssw & M68030::SSW_RB) ? "RB" : "--"),
        !          1207:                ((ssw & M68030::SSW_DF) ? "DF" : "--"),
        !          1208:                ((ssw & M68030::SSW_RM) ? "RM" : "--"),
        !          1209:                ((ssw & M68030::SSW_RW) ? 'R'  : 'W'),
        !          1210:                "LBW3"[(ssw >> 4) & 3],
        !          1211:                (ssw & 7));
        !          1212: 
        !          1213:        frame.Print(out, 0x0c, 2, "Instruction Pipe Stage C");
        !          1214:        frame.Print(out, 0x0e, 2, "Instruction Pipe Stage B");
        !          1215:        frame.Print(out, 0x10, 4, "Data Cycle Fault Address");
        !          1216:        frame.Print(out, 0x14, 4);
        !          1217:        frame.Print(out, 0x18, 4, "Data Output Buffer");
        !          1218:        frame.Print(out, 0x1c, 4);
        !          1219:        frame.Print(out, 0x20, 4);
        !          1220:        frame.Print(out, 0x24, 4, "Stage B Address");
        !          1221:        frame.Print(out, 0x28, 4);
        !          1222:        frame.Print(out, 0x2c, 4, "Data Input Buffer");
        !          1223: 
        !          1224:        // 残りは内部データなのでまとめる。
        !          1225:        frame.Print(out, 0x30, 4, "(internal registers)");
        !          1226:        // +$36 にちょっと構造があるけどとりあえず無視。
        !          1227:        for (uint i = 0x34; i < frame.bytesize(); i += 4) {
        !          1228:                if (i == 0x34 || i == 0x48) {
        !          1229:                        fprintf(out, "+$%02x:", i);
        !          1230:                }
        !          1231:                fprintf(out, " %s", frame.FormatLong(i).c_str());
        !          1232:                if (i == 0x44) {
        !          1233:                        fprintf(out, "\n");
        !          1234:                }
        !          1235:        }
        !          1236:        fprintf(out, "\n");
        !          1237: }
        !          1238: 
        !          1239: void
        !          1240: DebuggerMD_m680x0::PrintFPStateFrame(FILE *out, busaddr addr)
        !          1241: {
        !          1242:        DebuggerMemoryStream mem(this, addr);
        !          1243:        StackData frame(mem);
        !          1244: 
        !          1245:        fprintf(out, "Floating-point state frame at $%08x\n", addr.Addr());
        !          1246: 
        !          1247:        frame.ReadByteUntil(4);
        !          1248: 
        !          1249:        // 第1ワードはバージョンと後続の長さ。
        !          1250:        uint64 w00 = frame.Long(0x00);
        !          1251:        uint32 ver = (w00 >> 24) & 0xff;
        !          1252:        uint32 len = (w00 >> 16) & 0xff;
        !          1253:        // VER LEN      Name
        !          1254:        // $00 ANY      Null State Frame
        !          1255:        // ver $18      68881 IDLE
        !          1256:        // ver $38      68882 IDLE
        !          1257:        // ver $B4      68881 BUSY
        !          1258:        // ver $D4      68882 BUSY
        !          1259:        // $41 $00      68040 IDLE
        !          1260:        // $41 $30      68040 Unimplemented Instruction
        !          1261:        // $41 $60      68040 BUSY
        !          1262:        if (ver == 0x00) {
        !          1263:                frame.Print(out, 0x00, 4, "Null State Frame");
        !          1264:        } else {
        !          1265:                // NULL フレーム以外は残り len バイトある。
        !          1266:                frame.ReadByteUntil(len + 4);
        !          1267: 
        !          1268:                if (ver == 0x41) {
        !          1269:                        switch (len) {
        !          1270:                         case 0x00:
        !          1271:                                frame.Print(out, 0x00, 4, "68040 Idle State Frame");
        !          1272:                                break;
        !          1273:                         case 0x30:
        !          1274:                                frame.Print(out, 0x00, 4,
        !          1275:                                        "68040 Unimplemented Instruction State Frame");
        !          1276:                                PrintFPFrame68040Unimpl(out, frame, 0);
        !          1277:                                break;
        !          1278:                         case 0x60:
        !          1279:                                frame.Print(out, 0x00, 4, "68040 Busy State Frame");
        !          1280:                                PrintFPFrame68040Busy(out, frame);
        !          1281:                                break;
        !          1282:                         default:
        !          1283:                                frame.Print(out, 0x00, 4, "68040 Unknown State Frame?");
        !          1284:                                break;
        !          1285:                        }
        !          1286:                } else {
        !          1287:                        switch (len) {
        !          1288:                         case 0x18:
        !          1289:                                frame.Print(out, 0x00, 4, "68881 Idle State Frame");
        !          1290:                                PrintFPFrame6888xIdle(out, frame, len);
        !          1291:                                break;
        !          1292:                         case 0x38:
        !          1293:                                frame.Print(out, 0x00, 4, "68882 Idle State Frame");
        !          1294:                                PrintFPFrame6888xIdle(out, frame, len);
        !          1295:                                break;
        !          1296:                         case 0xb4:
        !          1297:                                frame.Print(out, 0x00, 4, "68881 Busy State Frame");
        !          1298:                                PrintFPFrame6888xBusy(out, frame, len);
        !          1299:                                break;
        !          1300:                         case 0xd4:
        !          1301:                                frame.Print(out, 0x00, 4, "68882 Busy State Frame");
        !          1302:                                PrintFPFrame6888xBusy(out, frame, len);
        !          1303:                                break;
        !          1304:                         default:
        !          1305:                                frame.Print(out, 0x00, 4, "Unknown State Frame?");
        !          1306:                                break;
        !          1307:                        }
        !          1308:                }
        !          1309:        }
        !          1310: }
        !          1311: 
        !          1312: void
        !          1313: DebuggerMD_m680x0::PrintFPFrame6888xIdle(FILE *out, StackData& frame,
        !          1314:        uint32 len)
        !          1315: {
        !          1316:        bool is68882 = (len == 0x38);
        !          1317: 
        !          1318:        frame.Print(out, 0x04, 2, "Command/Condition Register");
        !          1319:        frame.Print(out, 0x06, 2);
        !          1320:        uint32 pos = 0x08;
        !          1321:        if (is68882) {
        !          1322:                for (; pos < 0x28; pos += 16) {
        !          1323:                        frame.Print(out, pos, 16, "(internal register)");
        !          1324:                }
        !          1325:        }
        !          1326:        for (uint i = 0; i < 12; i += 4) {
        !          1327:                frame.Print(out, pos, 4, "Exceptional Operand");
        !          1328:                pos += 4;
        !          1329:        }
        !          1330:        frame.Print(out, pos, 4, "Operand Register");
        !          1331:        pos += 4;
        !          1332:        frame.Print(out, pos, 4, "BIU Flags");
        !          1333: }
        !          1334: 
        !          1335: void
        !          1336: DebuggerMD_m680x0::PrintFPFrame6888xBusy(FILE *out, StackData& frame,
        !          1337:        uint32 len)
        !          1338: {
        !          1339:        uint pos = 4;
        !          1340:        uint cnt = len / 16;
        !          1341:        for (uint i = 0; i < cnt; i++) {
        !          1342:                frame.Print(out, pos, 16, "(internal register)");
        !          1343:                pos += 16;
        !          1344:        }
        !          1345:        for (; pos < len + 4; pos += 4) {
        !          1346:                frame.Print(out, pos, 4, "(internal register)");
        !          1347:        }
        !          1348: }
        !          1349: 
        !          1350: // 68040 の未実装命令ステートフレーム。
        !          1351: // 68040 のビジーフレームからも呼ばれる。base には Unimpl の原点を指定するが
        !          1352: // +$00 からの4バイト分の表示は呼び出し側の担当。
        !          1353: void
        !          1354: DebuggerMD_m680x0::PrintFPFrame68040Unimpl(FILE *out, StackData& frame,
        !          1355:        uint base)
        !          1356: {
        !          1357:        // +$04.L: CMDREG3B
        !          1358:        uint32 reg3b = frame.Word(base + 0x04);
        !          1359:        frame.Print(out, base + 0x04, 4, "CMDREG3B=$%03x", reg3b);
        !          1360: 
        !          1361:        // +$08.L: (reserved)
        !          1362:        uint16 exc = frame.Word(base + 0x08);
        !          1363:        frame.Print(out, base + 0x08, 4,
        !          1364:                "(NMNEXC %s %s %s %s %s) (NMCEXC %s %s %s %s %s)",
        !          1365:                ((exc & 0x0200) ? "UN" : "--"),
        !          1366:                ((exc & 0x0100) ? "SN" : "--"),
        !          1367:                ((exc & 0x0080) ? "OE" : "--"),
        !          1368:                ((exc & 0x0040) ? "OF" : "--"),
        !          1369:                ((exc & 0x0020) ? "UF" : "--"),
        !          1370:                ((exc & 0x0010) ? "UN" : "--"),
        !          1371:                ((exc & 0x0008) ? "SN" : "--"),
        !          1372:                ((exc & 0x0004) ? "OE" : "--"),
        !          1373:                ((exc & 0x0002) ? "OF" : "--"),
        !          1374:                ((exc & 0x0001) ? "UF" : "--"));
        !          1375: 
        !          1376:        // +$0c.L: STAG...
        !          1377:        uint32 w0c = frame.Word(base + 0x0c);
        !          1378:        uint32 stag = (w0c >> 13) & 7;
        !          1379:        frame.Print(out, base + 0x0c, 4,
        !          1380:                "STAG=%u%s (E=%u) M66=%u M1=%u M0=%u SBIT=%u",
        !          1381:                stag, MPU68040Device::GetFPUTagName(stag).c_str(),
        !          1382:                ((w0c & 0x1000) ? 1 : 0),
        !          1383:                ((w0c & 0x0400) ? 1 : 0),
        !          1384:                ((w0c & 0x0200) ? 1 : 0),
        !          1385:                ((w0c & 0x0100) ? 1 : 0),
        !          1386:                ((w0c & 0x0080) ? 1 : 0));
        !          1387: 
        !          1388:        // +$10.L: CMDREG1B
        !          1389:        uint32 reg1b = frame.Word(base + 0x10);
        !          1390:        uint32 opclass = reg1b >> 13;
        !          1391:        uint32 rx = (reg1b >> 10) & 7;
        !          1392:        uint32 ry = (reg1b >>  7) & 7;
        !          1393:        uint32 cmd = reg1b & 0x7f;
        !          1394:        std::string cmdname = MPU68040Device::GetReg1BName(opclass, rx, cmd);
        !          1395:        frame.Print(out, base + 0x10, 4,
        !          1396:                "CMDREG1B=$%04x: OPCLASS=%x Rs=%u Rd=%u CMD=$%02x(%s)",
        !          1397:                reg1b,
        !          1398:                opclass, rx, ry,
        !          1399:                cmd, cmdname.c_str());
        !          1400: 
        !          1401:        // +$14.L: DTAG...
        !          1402:        uint32 w14 = frame.Word(base + 0x14);
        !          1403:        uint32 dtag = (w14 >> 13) & 7;
        !          1404:        frame.Print(out, base + 0x14, 4,
        !          1405:                "DTAG=%u%s (FPTEMP15=%u) WBTEMP15=%u",
        !          1406:                dtag, MPU68040Device::GetFPUTagName(dtag).c_str(),
        !          1407:                ((w14 & 0x1000) ? 1 : 0),
        !          1408:                ((w14 & 0x0010) ? 1 : 0));
        !          1409: 
        !          1410:        // +$18.L: E1,E3,T
        !          1411:        uint32 w18 = frame.Word(base + 0x18);
        !          1412:        frame.Print(out, base + 0x18, 4,
        !          1413:                "E1=%u E3=%u (S=%u X=%u U=%u) T=%u",
        !          1414:                ((w18 & 0x0400) ? 1 : 0),
        !          1415:                ((w18 & 0x0200) ? 1 : 0),
        !          1416:                ((w18 & 0x0100) ? 1 : 0),
        !          1417:                ((w18 & 0x0080) ? 1 : 0),
        !          1418:                ((w18 & 0x0020) ? 1 : 0),
        !          1419:                ((w18 & 0x0010) ? 1 : 0));
        !          1420: 
        !          1421:        // +$1C.L: FPTS,FPTE
        !          1422:        uint32 w1c = frame.Word(base + 0x1c);
        !          1423:        frame.Print(out, base + 0x1c, 4, "FPTS=%u FPTE=$%04x",
        !          1424:                ((w1c & 0x8000) ? 1 : 0),
        !          1425:                 (w1c & 0x7fff));
        !          1426: 
        !          1427:        // +$20.L: FPTM
        !          1428:        // +$24.L: FPTM
        !          1429:        frame.Print(out, base + 0x20, 4, "FPTM[63:32]");
        !          1430:        frame.Print(out, base + 0x24, 4, "FPTM[31:00]");
        !          1431: 
        !          1432:        // +$28.L: ETS,ETE
        !          1433:        uint32 w28 = frame.Word(base + 0x28);
        !          1434:        frame.Print(out, base + 0x28, 4, "ETS=%u ETE=$%04x",
        !          1435:                ((w28 & 0x8000) ? 1 : 0),
        !          1436:                 (w28 & 0x7fff));
        !          1437: 
        !          1438:        // +$2C.L: ETM
        !          1439:        // +$30.L: ETM
        !          1440:        frame.Print(out, base + 0x2c, 4, "ETM[63:32]");
        !          1441:        frame.Print(out, base + 0x30, 4, "ETM[31:00]");
        !          1442: }
        !          1443: 
        !          1444: void
        !          1445: DebuggerMD_m680x0::PrintFPFrame68040Busy(FILE *out, StackData& frame)
        !          1446: {
        !          1447:        frame.Print(out, 0x04, 4, "(reserved)");
        !          1448: 
        !          1449:        // $08 CU_SAVEPC
        !          1450:        uint32 w08 = frame.Word(0x08);
        !          1451:        frame.Print(out, 0x08, 4, "CU_SAVEPC=$%02x", w08 >> 25);
        !          1452: 
        !          1453:        frame.Print(out, 0x0c, 4, "(reserved)");
        !          1454:        frame.Print(out, 0x10, 4, "(reserved)");
        !          1455:        frame.Print(out, 0x14, 4, "(reserved)");
        !          1456: 
        !          1457:        // $18 WBT
        !          1458:        uint32 w18 = frame.Word(0x18);
        !          1459:        frame.Print(out, 0x18, 4, "WBT S=%u E=$%04x",
        !          1460:                ((w18 & 0x8000) ? 1 : 0),
        !          1461:                 (w18 & 0x7fff));
        !          1462:        frame.Print(out, 0x1c, 4, "WBTM[63:32]");
        !          1463:        frame.Print(out, 0x20, 4, "WBTM[31:00]");
        !          1464: 
        !          1465:        frame.Print(out, 0x24, 4, "(reserved)");
        !          1466:        frame.Print(out, 0x28, 4, "FPIARCU");
        !          1467:        frame.Print(out, 0x2c, 4, "(reserved)");
        !          1468:        frame.Print(out, 0x30, 4, "(reserved)");
        !          1469: 
        !          1470:        // これ以降は Unimpl と同じ。
        !          1471:        PrintFPFrame68040Unimpl(out, frame, 0x30);
        !          1472: }

unix.superglobalmegacorp.com

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