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

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

unix.superglobalmegacorp.com

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