Annotation of nono/debugger/debugger_m88xx0.cpp, revision 1.1.1.4

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "console.h"
                      8: #include "debugger_private.h"
                      9: #include "debugger_m88xx0.h"
                     10: #include "m88100disasm.h"
1.1.1.2   root       11: #include "m88100acc.h"
1.1       root       12: #include "mystring.h"
                     13: 
                     14: // newval が oldval から変化していれば太字属性にするマクロ
                     15: #define TSBOLD(newval, oldval) (((newval) != (oldval)) ? TA::Em : TA::Off)
                     16: 
                     17: // cpu->name が変化していれば太字属性にするマクロ
                     18: #define TSBOLDC(name) TSBOLD(cpu->name, prev.name)
                     19: 
                     20: // name の mask で示される部分が変化していれば太字属性にする
                     21: #define TSBOLDM(name, mask) TSBOLD((cpu->name & (mask)), (prev.name & (mask)))
                     22: 
1.1.1.2   root       23: // コンストラクタ
                     24: DebuggerMD_m88xx0::DebuggerMD_m88xx0(Debugger *parent_, m88kcpu *cpu_)
                     25:        : inherited(parent_)
                     26: {
                     27:        cpu = cpu_;
                     28: 
1.1.1.3   root       29:        // 機種依存変数
                     30:        vector_max = 512;
1.1.1.4 ! root       31:        inst_bytes = 4;
        !            32:        inst_bytes_fixed = 4;
1.1.1.3   root       33: 
1.1.1.2   root       34:        // 奇数にしておくことで初回に必ずアドレス変換を起こさせる。
                     35:        last_lpage[0].addr = 0xffffffff;
                     36:        last_lpage[1].addr = 0xffffffff;
                     37: 
                     38:        cmp_rd = -1;
                     39: }
                     40: 
                     41: // デストラクタ
                     42: DebuggerMD_m88xx0::~DebuggerMD_m88xx0()
                     43: {
                     44: }
                     45: 
                     46: bool
                     47: DebuggerMD_m88xx0::MMUEnabled() const
                     48: {
                     49:        // XXX 命令/データの区別がまだないので、とりあえず命令のほうだけ見る
                     50:        uint32 xapr = cpu->cmmu[0].GetAPR(IsSuper() ? 1 : 0);
                     51:        return (xapr & m88200::APR_TE);
                     52: }
                     53: 
                     54: // アドレス変換
                     55: uint64
                     56: DebuggerMD_m88xx0::TranslateAddr(saddr_t laddr)
                     57: {
                     58:        uint64 paddr;
                     59:        int isdata;
                     60:        m88200 *cmmu;
                     61: 
                     62:        // XXX とりあえずね
                     63:        isdata = (laddr.data) ? 1 : 0;
                     64:        if (isdata == 0) {
                     65:                cmmu = &cpu->cmmu[0];
                     66:        } else {
                     67:                cmmu = &cpu->cmmu[1];
                     68:        }
                     69: 
                     70:        // ページ境界(と初回)でアドレス変換
                     71:        saddr_t lpage;
                     72:        lpage.addr  = laddr.addr & 0xfffff000;
                     73:        lpage.super = laddr.super;
                     74:        if (lpage.GetSaddr() != last_lpage[isdata].GetSaddr()) {
                     75:                last_lpage[isdata] = lpage;
                     76: 
                     77:                bool do_search = laddr.IsSearch();
                     78:                paddr = cmmu->TranslatePeek(laddr.addr, laddr.super, do_search);
                     79:                if ((int64)paddr < 0) {
                     80:                        last_lpage[isdata].addr = 0xffffffff;
                     81:                }
                     82:                last_ppage[isdata] = paddr & 0xfffff000;
                     83:        } else {
                     84:                paddr = last_ppage[isdata] | (laddr.addr & 0x00000fff);
                     85:        }
                     86:        return paddr;
                     87: }
                     88: 
1.1.1.4 ! root       89: // op が bb0 命令なら true を返す
        !            90: /*static*/ bool
        !            91: DebuggerMD_m88xx0::IsBB0(uint32 op)
        !            92: {
        !            93:        return ((op & 0xf8000000) == 0xd0000000);               // bb0
        !            94: }
        !            95: 
        !            96: // op が tb0 命令なら true を返す
        !            97: /*static*/ bool
        !            98: DebuggerMD_m88xx0::IsTB0(uint32 op)
        !            99: {
        !           100:        return ((op & 0xfc00fe00) == 0xf000d000);               // tb0
        !           101: }
        !           102: 
1.1.1.2   root      103: // op が bb0/tb0 命令なら true を返す
                    104: /*static*/ bool
                    105: DebuggerMD_m88xx0::IsBBTB0(uint32 op)
                    106: {
1.1.1.4 ! root      107:        return IsBB0(op) || IsTB0(op);
1.1.1.2   root      108: }
                    109: 
                    110: // op が bb1 命令なら true を返す
                    111: /*static*/ bool
                    112: DebuggerMD_m88xx0::IsBB1(uint32 op)
                    113: {
                    114:        return ((op & 0xf8000000) == 0xd8000000);               // bb1
                    115: }
                    116: 
                    117: // op が tb1 命令なら true を返す
                    118: /*static*/ bool
                    119: DebuggerMD_m88xx0::IsTB1(uint32 op)
                    120: {
                    121:        return ((op & 0xfc00fe00) == 0xf000d800);               // tb1
                    122: }
                    123: 
                    124: // op が bb1/tb1 命令なら true を返す
                    125: /*static*/ bool
                    126: DebuggerMD_m88xx0::IsBBTB1(uint32 op)
                    127: {
                    128:        return IsBB1(op) || IsTB1(op);
                    129: }
                    130: 
1.1       root      131: void
                    132: DebuggerMD_m88xx0::BackupRegs()
                    133: {
                    134:        prev = (m88100reg)*cpu;
                    135: }
                    136: 
1.1.1.2   root      137: void
                    138: DebuggerMD_m88xx0::SetStepOut()
                    139: {
                    140:        so_r1 = cpu->r[1];
                    141: }
                    142: 
                    143: bool
                    144: DebuggerMD_m88xx0::IsStepOut() const
                    145: {
                    146:        return (cpu->xip == so_r1);
                    147: }
                    148: 
1.1.1.4 ! root      149: // この命令がステップイン出来るなら true を返す
        !           150: bool
        !           151: DebuggerMD_m88xx0::IsOpStepIn(uint32 op)
        !           152: {
        !           153:        if ((op & 0xf800'0000) == 0xc800'0000           // bsr
        !           154:         || IsTB0(op)                                                           // tb0
        !           155:         || (IsTB1(op) && ((op >> 16) & 0x1f) != 0)     // tb1 (except r0)
        !           156:         || (op & 0xfc00'fe00) == 0xf000'e800           // tcnd
        !           157:         || (op & 0xfc00'fb00) == 0xf400'c800           // jsr
        !           158:         || (op & 0xfc00'0000) == 0xf800'0000           // tbnd imm
        !           159:         || (op & 0xfc00'ffe0) == 0xf400'f800           // tbnd rs2
        !           160:        ) {
        !           161:                return true;
        !           162:        }
        !           163: 
        !           164:        return false;
        !           165: }
        !           166: 
1.1       root      167: // レジスタ名からそのレジスタ値を返す。
                    168: // メモリダンプのような用途なのでアドレスとして使えるアドレスのみ。
                    169: uint64
                    170: DebuggerMD_m88xx0::GetRegAddr(const char *name) const
                    171: {
                    172:        char buf[8];
                    173: 
                    174:        if (strcmp(name, "xip") == 0) return cpu->xip;
                    175:        if (strcmp(name, "nip") == 0) return cpu->nip;
                    176:        if (strcmp(name, "fip") == 0) return cpu->fip;
                    177: 
                    178:        // 制御レジスタ
                    179:        //if (strcmp(name, "pid") == 0) return cpu->pid;
                    180:        //if (strcmp(name, "psr") == 0) return cpu->psr;
                    181:        //if (strcmp(name, "epsr") == 0)        return cpu->epsr;
                    182:        //if (strcmp(name, "ssbr") == 0)        return cpu->ssbr;
1.1.1.2   root      183:        if (strcmp(name, "sxip") == 0)  return cpu->sxip & m88100reg::SIP_MASK;
                    184:        if (strcmp(name, "snip") == 0)  return cpu->snip & m88100reg::SIP_MASK;
                    185:        if (strcmp(name, "sfip") == 0)  return cpu->sfip & m88100reg::SIP_MASK;
1.1       root      186:        if (strcmp(name, "vbr") == 0)   return cpu->vbr;
                    187:        //if (strcmp(name, "dmt0") == 0)        return cpu->dmt0;
                    188:        if (strcmp(name, "dmd0") == 0)  return cpu->dmd0;
                    189:        if (strcmp(name, "dma0") == 0)  return cpu->dma0;
                    190:        //if (strcmp(name, "dmt1") == 0)        return cpu->dmt1;
                    191:        if (strcmp(name, "dmd1") == 0)  return cpu->dmd1;
                    192:        if (strcmp(name, "dma1") == 0)  return cpu->dma1;
                    193:        //if (strcmp(name, "dmt2") == 0)        return cpu->dmt2;
                    194:        if (strcmp(name, "dmd2") == 0)  return cpu->dmd2;
                    195:        if (strcmp(name, "dma2") == 0)  return cpu->dma2;
                    196:        if (strcmp(name, "sr0") == 0)   return cpu->sr[0];
                    197:        if (strcmp(name, "sr1") == 0)   return cpu->sr[1];
                    198:        if (strcmp(name, "sr2") == 0)   return cpu->sr[2];
                    199:        if (strcmp(name, "sr3") == 0)   return cpu->sr[3];
                    200: 
                    201:        for (int i = 0; i < countof(cpu->cr); i++) {
                    202:                snprintf(buf, sizeof(buf), "cr%d", i);
                    203:                if (strcmp(name, buf) == 0) {
                    204:                        return cpu->cr[i];
                    205:                }
                    206:        }
                    207: 
                    208:        // FPU レジスタ
                    209:        // XXX not implement
                    210: 
                    211:        // 通常レジスタ
                    212:        for (int i = 0; i < countof(cpu->r); i++) {
                    213:                snprintf(buf, sizeof(buf), "r%d", i);
                    214:                if (strcmp(name, buf) == 0) {
                    215:                        return cpu->r[i];
                    216:                }
                    217:        }
                    218: 
                    219:        return (uint64)-1;
                    220: }
                    221: 
1.1.1.2   root      222: // レジスタ表示系コマンドのヘルプ
                    223: /*static*/ const HelpMessages
                    224: DebuggerMD_m88xx0::HelpMsgRegister = {
1.1.1.4 ! root      225:        { "r",          "Show general registers" },
        !           226:        { "rc",         "Show (integer) control registers" },
        !           227:        { "rf",         "Show floating point control registers" },
        !           228:        { "ro",         "Show other (shadow) registers" },
        !           229:        { "ra<id>",     "Show ATC on CMMU<id>" },
        !           230:        { "rd<id>",     "Show data cache on CMMU<id>" },
        !           231:        { "rm<id>",     "Show CMMU<id> registers" },
1.1.1.2   root      232: };
                    233: 
                    234: const HelpMessages&
                    235: DebuggerMD_m88xx0::GetRegisterHelp() const
                    236: {
                    237:        return HelpMsgRegister;
                    238: }
                    239: 
                    240: // レジスタ表示系コマンド
                    241: bool
                    242: DebuggerMD_m88xx0::ShowRegister(Console *cons,
                    243:        const std::vector<std::string>& args)
                    244: {
                    245:        int cmmu_id;
                    246: 
                    247:        // 余分な引数は無視する?
                    248: 
                    249:        if (args[0] == "r") {
                    250:                ShowRegMain(cons);
                    251:                return true;
                    252:        }
                    253:        if (args[0] == "rc") {
                    254:                ShowRegCtrl(cons);
                    255:                return true;
                    256:        }
                    257:        if (args[0] == "rf") {
                    258:                ShowRegFPU(cons);
                    259:                return true;
                    260:        }
                    261:        if (args[0] == "ro") {
                    262:                ShowRegOther(cons);
                    263:                return true;
                    264:        }
                    265: 
                    266:        if (MatchCMMUCmd(args[0], "ra", &cmmu_id)) {
                    267:                parent->ShowMonitor(*gMPU88200ATC[7 - cmmu_id]);
                    268:                return true;
                    269:        }
                    270:        if (MatchCMMUCmd(args[0], "rd", &cmmu_id)) {
                    271:                ShowRegCache(cons, args, cmmu_id);
                    272:                return true;
                    273:        }
                    274:        if (MatchCMMUCmd(args[0], "rm", &cmmu_id)) {
                    275:                ShowRegMMU(cons, cmmu_id);
                    276:                return true;
                    277:        }
                    278: 
                    279:        // 該当なし
                    280:        return false;
                    281: }
                    282: 
                    283: // CMMU ID 入りコマンド名を照合する。
                    284: // cmdname が basename + <id> の時、*idp に id を格納して true を返す。
                    285: // 一致しないか id が不正なら false を返す。
                    286: bool
                    287: DebuggerMD_m88xx0::MatchCMMUCmd(const std::string& cmdname,
                    288:        const char *basename, int *idp)
                    289: {
                    290:        int baselen = strlen(basename);
                    291: 
                    292:        if (strncmp(cmdname.c_str(), basename, baselen) != 0) {
                    293:                return false;
                    294:        }
                    295: 
                    296:        // 先頭が一致したら id を調べる
                    297:        int id;
                    298:        const char *start = cmdname.c_str() + baselen;
                    299:        char *end;
                    300:        errno = 0;
                    301:        id = strtoul(start, &end, 10);
                    302:        if (*start == '\0' || *end != '\0' || errno == ERANGE) {
                    303:                return false;
                    304:        }
                    305: 
                    306:        *idp = id;
                    307:        return true;
                    308: }
                    309: 
1.1       root      310: void
                    311: DebuggerMD_m88xx0::ShowRegMain(Console *cons)
                    312: {
                    313:        TextScreen s(80, 8);
                    314: 
1.1.1.2   root      315: /*
                    316: r0 :00000000  r8 :00000000  r16:00000000  r24:00000000   b:bs=1 a:lo=1 8:ls=0
                    317: r1 :00700000  r9 :00000000  r17:00000000  r25:00000000
                    318: r2 :0070e1a0  r10:00000000  r18:00000000  r26:00000000
                    319: */
                    320: 
1.1       root      321:        for (int i = 0; i < countof(cpu->r); i++) {
                    322:                s.Print((i / 8) * 14, i % 8, TSBOLDC(r[i]), "r%-2d:%08x", i, cpu->r[i]);
                    323:        }
                    324: 
1.1.1.2   root      325:        // cmp 以降最初の分岐命令で結果レジスタの条件ビットマップを表示する。
                    326:        // 分岐命令は bb1 #3 みたいな形式なのでそれだけでは条件演算子が分からない
                    327:        // のと、bb1 #n 自体は cmp 以外に対しても使えるので、cmp 命令以降最初の
                    328:        // 分岐命令でのみ表示してみる。
                    329:        if (cmp_rd >= 0 && (IsBBTB0(cpu->opX) || IsBBTB1(cpu->opX))) {
                    330:                static const char * const cmpstr[] = {
                    331:                        NULL, NULL, "eq", "ne", "gt", "le", "lt", "ge",
                    332:                        "hi", "ls", "lo", "hs",
                    333:                };
                    334:                int x = 0;
                    335:                int y = 0;
                    336:                uint32 res = cpu->r[cmp_rd];
                    337:                for (int b = 11; b >= 2; b--) {
                    338:                        s.Print(57 + x * 7, y, "%x:%s=%d", b, cmpstr[b],
                    339:                                (res & (1 << b)) ? 1 : 0);
                    340:                        x++;
                    341:                        if (x > 2) {
                    342:                                x = 0;
                    343:                                y++;
                    344:                        }
                    345:                }
                    346:        }
                    347: 
                    348:        parent->ShowTextScreen(s);
1.1       root      349: }
                    350: 
                    351: void
                    352: DebuggerMD_m88xx0::ShowRegCtrl(Console *cons)
                    353: {
                    354:        TextScreen s(80, 6);
                    355:        int x;
                    356:        int y;
                    357: 
                    358: /*
                    359: 0         1         2         3         4         5         6         7
                    360: 0123456789012345678901234567890123456789012345678901234567890123456789012345678
1.1.1.4 ! root      361: pid (cr0):12345678(Arch=$00 Ver=$00 M/C=Checker)       sr0(cr17):00000000
        !           362: psr (cr1):12345678(S,LE,SER,Cy SFD1,MXM,IND,SFRZ)      sr1(cr18):00000000
        !           363: epsr(cr2):12345678(S,LE,SER,Cy SFD1,MXM,IND,SFRZ)      sr2(cr19):00000000
        !           364: xip:00000000  opX:00000000(--)  sxip(cr4):00000000:VE  sr3(cr20):00000000
        !           365: nip:00000000  opF:00000000(--)  snip(cr5):00000000:--  ssbr(cr3):00000000
        !           366: fip:00000000                    sfip(cr6):00000000:VE  vbr (cr7):00000000
1.1       root      367: */
                    368: 
                    369: #define PRINT_B(x, y, reg, mask, fmt, arg)     do { \
                    370:        uint32 _new = cpu->reg & (mask);        \
                    371:        uint32 _old = prev.reg & (mask);        \
                    372:        s.Print((x), (y), TSBOLD(_new, _old), fmt, (arg));      \
                    373: } while (0)
                    374: 
                    375:        // pid(cr0)
                    376:        x = 0;
                    377:        y = 0;
1.1.1.2   root      378:        s.Print(x,      y, TSBOLDC(pid), "pid (cr0):%08x(", cpu->pid);
                    379:        PRINT_B(x + 19, y, pid, m88100reg::PID_REV_MASK, "Arch=$%02x",
                    380:                (_new >> 8) & 0xff);
                    381:        PRINT_B(x + 28, y, pid, m88100reg::PID_VER_MASK, "Ver=$%02x",
                    382:                (_new >> 1) & 0x7f);
                    383:        PRINT_B(x + 36, y, pid, m88100reg::PID_MASTER, "M/C=%s)",
                    384:                (_new & m88100reg::PID_MASTER) ? "Master" : "Checker");
1.1       root      385: 
                    386:        // psr(cr1)
                    387:        y++;
                    388:        s.Print(x,      y, TSBOLDC(psr), "psr (cr1):%08x", cpu->psr);
                    389:        s.Print(x + 18, y, "(s,le,ser,cy sfd1,mxm,ind,sfrz)");
                    390:        PRINT_B(x + 19, y, psr, m88100reg::PSR_SUPER, "%c", _new ? 'S' : '-');
                    391:        PRINT_B(x + 21, y, psr, m88100reg::PSR_BO_LE, "%s", _new ? "LE" : "BE");
                    392:        PRINT_B(x + 24, y, psr, m88100reg::PSR_SER,   "%s", _new ? "CON" : "SER");
                    393:        PRINT_B(x + 28, y, psr, m88100reg::PSR_C,     "%s", _new ? "Cy" : "--");
                    394:        PRINT_B(x + 31, y, psr, m88100reg::PSR_SFD1,  "%s", _new ? "SFD1" : "----");
                    395:        PRINT_B(x + 36, y, psr, m88100reg::PSR_MXM,   "%s", _new ? "MXM" : "---");
                    396:        PRINT_B(x + 40, y, psr, m88100reg::PSR_IND,   "%s", _new ? "IND" : "---");
                    397:        PRINT_B(x + 44, y, psr, m88100reg::PSR_SFRZ,  "%s", _new ? "SFRZ" : "----");
                    398: 
                    399:        // epsr(cr2)
                    400:        y++;
1.1.1.4 ! root      401:        s.Print(x,      y, TSBOLDC(epsr), "epsr(cr2):%08x", cpu->epsr);
1.1       root      402:        s.Print(x + 18, y, "(s,le,ser,cy sfd1,mxm,ind,sfrz)");
                    403:        PRINT_B(x + 19, y, epsr, m88100reg::PSR_SUPER, "%c", _new ? 'S' : '-');
                    404:        PRINT_B(x + 21, y, epsr, m88100reg::PSR_BO_LE, "%s", _new ? "LE" : "BE");
                    405:        PRINT_B(x + 24, y, epsr, m88100reg::PSR_SER,   "%s", _new ? "CON" : "SER");
                    406:        PRINT_B(x + 28, y, epsr, m88100reg::PSR_C,     "%s", _new ? "Cy" : "--");
                    407:        PRINT_B(x + 31, y, epsr, m88100reg::PSR_SFD1,  "%s", _new ? "SFD1":"----");
                    408:        PRINT_B(x + 36, y, epsr, m88100reg::PSR_MXM,   "%s", _new ? "MXM" : "---");
                    409:        PRINT_B(x + 40, y, epsr, m88100reg::PSR_IND,   "%s", _new ? "IND" : "---");
                    410:        PRINT_B(x + 44, y, epsr, m88100reg::PSR_SFRZ,  "%s", _new ? "SFRZ":"----");
                    411: 
                    412:        // *IP
                    413:        x = 0;
                    414:        y = 3;
                    415:        s.Print(x,      y, "xip:%08x  opX:%08x(%c%c)",
                    416:                cpu->xip, (uint32)cpu->opX,
                    417:                cpu->OpIsBusErr(cpu->opX) ? 'B' : '-',
                    418:                cpu->OpIsDelay(cpu->opX)  ? 'D' : '-');
                    419:        s.Print(x,  y + 1, "nip:%08x  opF:%08x(%c%c)",
                    420:                cpu->nip, (uint32)cpu->opF,
                    421:                cpu->OpIsBusErr(cpu->opF) ? 'B' : '-',
                    422:                cpu->OpIsDelay(cpu->opX)  ? 'D' : '-');
                    423:        s.Print(x,  y + 2, "fip:%08x", cpu->fip);
                    424: 
                    425:        // S*IP
                    426:        x = 32;
                    427:        for (int i = 0; i < 3; i++) {
                    428:                s.Print(x, y + i, TSBOLDC(cr[4 + i]), "%s(cr%d):%08x:%c%c",
                    429:                        m88100reg::sipname[i], 4 + i,
                    430:                        (cpu->cr[4 + i] & m88100reg::SIP_MASK),
                    431:                        (cpu->cr[4 + i] & m88100reg::SIP_V) ? 'V' : '-',
                    432:                        (cpu->cr[4 + i] & m88100reg::SIP_E) ? 'E' : '-');
                    433:        }
                    434: 
                    435:        x = 55;
                    436:        y = 0;
                    437:        // SR*
                    438:        for (int i = 0; i < 4; i++) {
                    439:                int rn = 17 + i;
1.1.1.4 ! root      440:                s.Print(x, y++, TSBOLDC(cr[rn]), "sr%d(cr%d):%08x",
1.1       root      441:                        i, rn, cpu->cr[rn]);
                    442:        }
1.1.1.4 ! root      443:        // ssbr(cr3)
        !           444:        s.Print(x, y++, TSBOLDC(ssbr), "ssbr(cr3):%08x", cpu->ssbr);
        !           445:        // vbr(cr7)
        !           446:        s.Print(x, y++, TSBOLDC(vbr),  "vbr (cr7):%08x", cpu->vbr);
1.1       root      447: 
1.1.1.2   root      448:        parent->ShowTextScreen(s);
                    449: }
                    450: 
                    451: // CMMU のデータキャッシュを表示
                    452: // rd<N>       なら概要表示。
                    453: // rd<N> <set> なら個別セットの詳細表示。
                    454: void
                    455: DebuggerMD_m88xx0::ShowRegCache(Console *cons,
                    456:        const std::vector<std::string>& args, int id)
                    457: {
                    458:        if (args.size() < 2) {
                    459:                ShowRegCacheOverview(cons, id);
                    460:        } else {
                    461:                int set;
                    462:                char *end;
                    463:                errno = 0;
                    464:                set = strtol(args[1].c_str(), &end, 16);
                    465:                if (end == &args[1][0] || *end != '\0' || errno == ERANGE) {
                    466:                        cons->Print("<set> must be a number\n");
                    467:                        return;
                    468:                }
                    469:                if (set < 0 || set > 256) {
                    470:                        cons->Print("<set> must be in 00..ff\n");
                    471:                        return;
                    472:                }
                    473:                ShowRegCacheSet(cons, id, set);
                    474:        }
                    475: }
                    476: 
                    477: // CMMU データキャッシュの概要表示
                    478: void
                    479: DebuggerMD_m88xx0::ShowRegCacheOverview(Console *cons, int id)
                    480: {
                    481:        TextScreen s(70, 17);
                    482:        m88200 *cmmu;
                    483: 
                    484:        // まだ今の所決め打ち
                    485:        if (id == 7) {
                    486:                cmmu = &cpu->cmmu[0];
                    487:        } else {
                    488:                cmmu = &cpu->cmmu[1];
                    489:        }
                    490:        cmmu->MonitorCacheOverview(s, 0, false);
                    491:        parent->ShowTextScreen(s);
                    492: }
                    493: 
                    494: // CMMU データキャッシュの指定セットの詳細表示
                    495: void
                    496: DebuggerMD_m88xx0::ShowRegCacheSet(Console *cons, int id, int setidx)
                    497: {
                    498:        TextScreen s(70, 5);
                    499:        m88200 *cmmu;
                    500: 
                    501:        // まだ今の所決め打ち
                    502:        if (id == 7) {
                    503:                cmmu = &cpu->cmmu[0];
                    504:        } else {
                    505:                cmmu = &cpu->cmmu[1];
                    506:        }
                    507:        cmmu->MonitorCacheSet(s, 0, setidx);
                    508:        parent->ShowTextScreen(s);
1.1       root      509: }
                    510: 
                    511: void
                    512: DebuggerMD_m88xx0::ShowRegFPU(Console *cons)
                    513: {
                    514:        static const char * const fcrname[] = {
                    515:                "fpecr",
                    516:                "fphs1",
                    517:                "fpls1",
                    518:                "fphs2",
                    519:                "fpls2",
                    520:                "fppt",
                    521:                "fprh",
                    522:                "fprl",
                    523:                "fpit",
                    524:                "fpsr", // [9]  62
                    525:                "fpcr", // [10] 63
                    526:        };
                    527:        TextScreen s(80, 4);
                    528: 
                    529:        for (int i = 0; i < 9; i++) {
                    530:                s.Print((i / 4) * 22, i % 4, TSBOLDC(fcr[i]),
                    531:                        "%-5s(fcr%d):%08x", fcrname[i], i, cpu->fcr[i]);
                    532:        }
                    533: 
                    534:        s.Print(44, 2, TSBOLDC(fpsr), "fpsr(fcr62):%08x", cpu->fpsr);
                    535:        s.Print(44, 3, TSBOLDC(fpcr), "fpcr(fcr63):%08x", cpu->fpcr);
                    536: 
1.1.1.2   root      537:        parent->ShowTextScreen(s);
1.1       root      538: }
                    539: 
                    540: void
1.1.1.2   root      541: DebuggerMD_m88xx0::ShowRegMMU(Console *cons, int id)
                    542: {
                    543:        m88200 *cmmu;
                    544: 
                    545:        // まだ今の所決め打ち
                    546:        if (id == 7) {
                    547:                cmmu = &cpu->cmmu[0];
                    548:        } else {
                    549:                cmmu = &cpu->cmmu[1];
                    550:        }
                    551:        parent->ShowMonitor(*cmmu);
                    552: }
                    553: 
                    554: void
                    555: DebuggerMD_m88xx0::ShowRegOther(Console *cons)
1.1       root      556: {
                    557:        TextScreen s(80, 3);
                    558: /*
                    559: 0         1         2         3         4         5         6         7
                    560: 0123456789012345678901234567890123456789012345678901234567890123456789012345678
1.1.1.2   root      561: dmt0(cr8) :0000(B,S,D,L,Rxx,S,---B,W,V) dmd0(cr9) :00000000 dma0(cr10):00000000
                    562: dmt0(cr11):0000(B,U,D,L,Rxx,S,HH--,W,V) dmd0(cr9) :00000000 dma0(cr10):00000000
                    563: dmt0(cr14):0000(B, ,D,L,Rxx,S,LLLL,W,V) dmd0(cr9) :00000000 dma0(cr10):00000000
1.1       root      564: */
                    565:        for (int i = 0; i <= 2; i++) {
                    566:                int dt =  8 + i * 3;
                    567:                int dd =  9 + i * 3;
                    568:                int da = 10 + i * 3;
                    569: 
                    570:                s.Print(0, i, TSBOLDC(cr[dt]), "dmt%d(cr%-2d):%04x",
                    571:                        i, dt, (cpu->cr[dt] & 0xffff));
1.1.1.2   root      572:                s.Print(15, i, "(b,s,d,l,rx, s,en  ,w,v)");
1.1       root      573:                PRINT_B(16, i, cr[dt], m88100reg::DM_BO,     "%c", _new ? 'B' : '-');
1.1.1.2   root      574:                PRINT_B(18, i, cr[dt], m88100reg::DM_DAS,    "%c", _new ? 'S' : 'U');
                    575:                PRINT_B(20, i, cr[dt], m88100reg::DM_DOUB1,  "%c", _new ? 'D' : '-');
                    576:                PRINT_B(22, i, cr[dt], m88100reg::DM_LOCK,   "%c", _new ? 'L' : '-');
                    577:                // カンマを前詰め。かつ DREG がボールドでもカンマはボールドにしない
                    578:                PRINT_B(24, i, cr[dt], m88100reg::DM_DREG_MASK, "r%d", _new >> 7);
                    579:                s.Puts(",");
                    580:                PRINT_B(28, i, cr[dt], m88100reg::DM_SIGNED, "%c", _new ? 'S' : '-');
                    581:                PRINT_B(30, i, cr[dt], m88100reg::DM_EN_MASK,"%s",
                    582:                        m88100reg::dmt_en_str[(_new >> 2) & 0xf]);
                    583:                PRINT_B(35, i, cr[dt], m88100reg::DM_WRITE,  "%c", _new ? 'W' : '-');
                    584:                PRINT_B(37, i, cr[dt], m88100reg::DM_VALID,  "%c", _new ? 'V' : '-');
1.1       root      585: 
1.1.1.2   root      586:                s.Print(40, i, TSBOLDC(cr[dd]), "dmd%d(cr%-2d):%08x",
1.1       root      587:                        i, dd, cpu->cr[dd]);
1.1.1.2   root      588:                s.Print(60, i, TSBOLDC(cr[dd]), "dma%d(cr%2d):%08x",
1.1       root      589:                        i, da, cpu->cr[da]);
                    590:        }
                    591: 
1.1.1.2   root      592:        parent->ShowTextScreen(s);
1.1       root      593: }
                    594: 
                    595: // 逆アセンブル
                    596: bool
                    597: DebuggerMD_m88xx0::Disassemble(saddr_t laddr,
                    598:        std::string& mnemonic, std::vector<uint8>& bin)
                    599: {
                    600:        m88100disasm dis(this);
                    601:        if (dis.Exec(laddr) == false) {
                    602:                return false;
                    603:        }
                    604:        mnemonic = dis.text;
                    605:        bin = dis.bin;
                    606:        return true;
                    607: }
                    608: 
                    609: // 逆アセンブルをフォーマット (オフライン版)
                    610: std::string
                    611: DebuggerMD_m88xx0::FormatDisasm(const std::string& mnemonic,
                    612:        const std::vector<uint8>& bin)
                    613: {
                    614:        // 命令はすべて32ビット固定長
                    615:        uint32 op = (bin[0] << 24) | (bin[1] << 16) | (bin[2] << 8) | bin[3];
                    616:        return string_format("%08x %s", op, mnemonic.c_str());
                    617: }
                    618: 
                    619: // 逆アセンブルをフォーマット (オンライン版)
                    620: std::string
                    621: DebuggerMD_m88xx0::FormatDisasmLive(const std::string& mnemonic,
                    622:        const std::vector<uint8>& bin)
                    623: {
                    624:        // 命令はすべて32ビット固定長
                    625:        uint32 op = (bin[0] << 24) | (bin[1] << 16) | (bin[2] << 8) | bin[3];
                    626: 
                    627:        // 遅延スロットは分かりやすく表示したい
                    628:        std::string delay;
                    629:        if (cpu->OpIsDelay(cpu->opX)) {
                    630:                delay = "(delayed) ";
                    631:        }
                    632: 
1.1.1.2   root      633:        const char *cond = CondStr(op);
                    634:        return string_format("%08x %s%s%s",
                    635:                op, delay.c_str(), mnemonic.c_str(), cond);
                    636: }
                    637: 
1.1.1.4 ! root      638: // 例外のベクタ番号から名前を取得。
        !           639: const char *
        !           640: DebuggerMD_m88xx0::GetExceptionName(int vector) const
        !           641: {
        !           642:        return m88kcpu::GetExceptionName(vector);
        !           643: }
        !           644: 
1.1.1.2   root      645: #define TAKE_IF(expr) do { \
                    646:        if ((expr)) \
                    647:                return " (will take)";  \
                    648:        else \
                    649:                return " (will not take)";      \
                    650: } while (0)
                    651: 
                    652: // 条件命令なら、成立可否などの文字列を返す。
                    653: const char *
                    654: DebuggerMD_m88xx0::CondStr(uint32 op)
                    655: {
                    656:        uint32 s = m88100opf_S1(op);
                    657: 
                    658:        if (IsBBTB0(op)) {
                    659:                // 11010N BBBBB SSSSS dddddd dd dddddddd        bb0
                    660:                // 111100 BBBBB SSSSS 110100 0V VVVVVVVV        tb0
                    661:                // rS の bit B が %0 ならブランチ/トラップ
                    662:                cmp_rd = -1;
                    663:                uint32 b = m88100opf_B5(op);
                    664:                TAKE_IF((cpu->r[s] & (1 << b)) == 0);
                    665:        }
                    666:        if (IsBB1(op)) {
                    667:                // 11011N BBBBB SSSSS dddddd dd dddddddd        bb1
                    668:                // rS の bit B が %1 ならブランチ
                    669:                cmp_rd = -1;
                    670:                // 対 r0 なら絶対成立しないので nop
                    671:                if (s == 0) {
                    672:                        return " (nop)";
                    673:                }
                    674:                uint32 b = m88100opf_B5(op);
                    675:                TAKE_IF((cpu->r[s] & (1 << b)) != 0);
                    676:        }
                    677:        if (IsTB1(op)) {
                    678:                // 111100 BBBBB SSSSS 110110 0V VVVVVVVV        tb1
                    679:                // rS の bit B が %1 ならトラップ
                    680:                cmp_rd = -1;
                    681:                // 対 r0 なら sync として使っており逆アセンブラ側で表示を加工してある
                    682:                // のでこちら側では対処不要。
                    683:                if (s == 0) {
                    684:                        return "";
                    685:                }
                    686:                uint32 b = m88100opf_B5(op);
                    687:                TAKE_IF((cpu->r[s] & (1 << b)) != 0);
                    688:        }
                    689:        if ((op & 0xf8000000) == 0xe8000000 ||  // bcnd
                    690:            (op & 0xfc00fe00) == 0xf000e800)    // tcnd
                    691:        {
                    692:                // 11101N MMMMM SSSSS dddddd dd dddddddd        bcnd
                    693:                // rS が M5 で示される条件にマッチすればブランチ/トラップ
                    694:                cmp_rd = -1;
                    695:                uint32 m5 = m88100opf_M5(op);
                    696:                TAKE_IF(
                    697:                    (m5 == 0x2 && cpu->r[s] == 0) ||            // eq0
                    698:                    (m5 == 0xd && cpu->r[s] != 0) ||            // ne0
                    699:                    (m5 == 0x1 && (int32)cpu->r[s] > 0)  ||     // gt0
                    700:                    (m5 == 0xc && (int32)cpu->r[s] < 0)  ||     // lt0
                    701:                    (m5 == 0x3 && (int32)cpu->r[s] >= 0) ||     // ge0
                    702:                    (m5 == 0xe && (int32)cpu->r[s] <= 0)        // le0
                    703:                );
                    704:        }
                    705: 
                    706:        if ((op & 0xfc00fce0) == 0xf4007c00 ||  // cmp rD,rS1,rS2
                    707:            (op & 0xfc000000) == 0x7c000000   ) // cmp rD,rS1,imm16
                    708:        {
                    709:                // 次の条件分岐命令で結果レジスタを表示するため、rD だけ覚えておく
                    710:                cmp_rd = m88100opf_D(op);
                    711:        }
                    712: 
                    713:        return "";
1.1       root      714: }

unix.superglobalmegacorp.com

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