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

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

unix.superglobalmegacorp.com

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