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

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

unix.superglobalmegacorp.com

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