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

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2022 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // デバッガ (HD64180 依存部分)
                      9: //
                     10: 
                     11: #include "debugger_hd64180.h"
                     12: #include "debugger_memory.h"
                     13: #include "xpbus.h"
                     14: 
                     15: // コンストラクタ
                     16: DebuggerMD_hd64180::DebuggerMD_hd64180(Debugger *parent_)
                     17:        : inherited(parent_, CPUArch::HD64180)
                     18: {
                     19:        // この時点で Get*Device() は使える
                     20:        cpu = GetMPU64180Device();
                     21:        bus = GetXPbusDevice();
                     22: 
                     23:        // 機種依存変数
                     24:        inst_bytes = 1;
                     25:        inst_bytes_fixed = 0;
                     26:        lasize = 16;
                     27:        pasize = 20;
                     28:        name = "xp";
                     29: }
                     30: 
                     31: // デストラクタ
                     32: DebuggerMD_hd64180::~DebuggerMD_hd64180()
                     33: {
                     34: }
                     35: 
                     36: // 動作状態を返す
                     37: CPUState
                     38: DebuggerMD_hd64180::GetCPUState() const
                     39: {
                     40:        // HD64180::OpMode を CPUState に変換
                     41:        auto opmode = cpu->GetOpMode();
                     42:        switch (opmode) {
                     43:         case HD64180::OpMode::Normal:
                     44:                return CPUState::Normal;
                     45: 
                     46:         case HD64180::OpMode::Reset:
                     47:         case HD64180::OpMode::Halt:
                     48:         case HD64180::OpMode::Sleep:
                     49:                return CPUState::Halt;
                     50: 
                     51:         default:
                     52:                PANIC("corrupted opmode=%d", (int)opmode);
                     53:        }
                     54: }
                     55: 
1.1.1.2 ! root       56: // アドレス変換
        !            57: busaddr
        !            58: DebuggerMD_hd64180::TranslateAddr(busaddr laddr) const
1.1       root       59: {
1.1.1.2 ! root       60:        return cpu->TranslatePeek(laddr.Addr());
1.1       root       61: }
                     62: 
                     63: // ステップアウトを設定する
                     64: void
                     65: DebuggerMD_hd64180::SetStepOut()
                     66: {
                     67:        so_sp = cpu->reg.sp;
                     68: }
                     69: 
                     70: bool
                     71: DebuggerMD_hd64180::IsStepOut() const
                     72: {
                     73:        return (cpu->reg.sp > so_sp);
                     74: }
                     75: 
                     76: // この命令がステップイン出来るなら true を返す
                     77: bool
                     78: DebuggerMD_hd64180::IsOpStepIn(DebuggerMemoryStream& mem)
                     79: {
                     80:        uint8 op = mem.Read(inst_bytes);
                     81: 
                     82:        if ( op == 0xcd                         // CALL
                     83:         || (op & 0xc7) == 0xc4         // CALL cc
                     84:        ) {
                     85:                return true;
                     86:        }
                     87: 
                     88:        // LD*R, CP*R, IN*R, OT*R, OT*MR もステップイン扱いにしてみる。
                     89:        if (op == 0xed) {
                     90:                uint8 op2 = mem.Read(inst_bytes);
                     91:                if ((op2 & 0xd0) == 0x90) {
                     92:                        return true;
                     93:                }
                     94:        }
                     95: 
                     96:        return false;
                     97: }
                     98: 
                     99: // name で示されるレジスタの値を返す。
                    100: // メモリダンプのような用途なので主にアドレスとして使うレジスタのみ。
                    101: uint64
                    102: DebuggerMD_hd64180::GetRegAddr(const char *name) const
                    103: {
                    104:        uint32 addr;
                    105: 
                    106:        if (strcmp(name, "pc") == 0) {
                    107:                addr = cpu->GetPPC();
                    108: 
                    109:        } else if (strcmp(name, "sp") == 0) {
                    110:                addr = cpu->reg.sp;
                    111: 
                    112:        } else if (strcmp(name, "bc") == 0) {
                    113:                addr = cpu->reg.GetBC();
                    114: 
                    115:        } else if (strcmp(name, "de") == 0) {
                    116:                addr = cpu->reg.GetDE();
                    117: 
                    118:        } else if (strcmp(name, "hl") == 0) {
                    119:                addr = cpu->reg.GetHL();
                    120: 
                    121:        } else if (strcmp(name, "ix") == 0) {
                    122:                addr = cpu->reg.ix;
                    123: 
                    124:        } else if (strcmp(name, "iy") == 0) {
                    125:                addr = cpu->reg.iy;
                    126: 
                    127:        } else {
                    128:                return (uint64)-1;
                    129:        }
                    130:        return addr;
                    131: }
                    132: 
                    133: void
                    134: DebuggerMD_hd64180::BackupRegs()
                    135: {
                    136:        prev = cpu->reg;
                    137:        prev_i = cpu->GetI();
                    138: }
                    139: 
                    140: // レジスタ表示系コマンド
                    141: bool
                    142: DebuggerMD_hd64180::ShowRegister(FILE *cons,
                    143:        const std::vector<std::string>& args)
                    144: {
                    145:        // 余分な引数は無視する?
                    146: 
                    147:        if (args[0] == "r") {
                    148:                ShowRegMain(cons);
                    149:                return true;
                    150:        }
                    151:        if (args[0] == "ro") {
                    152:                ShowRegOther(cons);
                    153:                return true;
                    154:        }
                    155: 
                    156:        // 該当なし
                    157:        return false;
                    158: }
                    159: 
                    160: bool
                    161: DebuggerMD_hd64180::ShowRegMain(FILE *cons)
                    162: {
                    163:        // AF:00 00 (------)  PC:0000   AF':00 00 (-------)
                    164:        // BC:00 00           SP:0000   BC':00 00
                    165:        // DE:00 00  IX:0000   I:00     DE':00 00  IX':0000
                    166:        // HL:00 00  IY:0000   R:00     HL':00 00  IY':0000
                    167: 
                    168:        uint8 reg_i = cpu->GetI();
                    169:        uint8 reg_r = cpu->GetR();
                    170: 
                    171:        bool va = (cpu->reg.a != prev.a);
                    172:        bool vf = (cpu->reg.f.Get() != prev.f.Get());
                    173:        bool vb = (cpu->reg.b != prev.b);
                    174:        bool vc = (cpu->reg.c != prev.c);
                    175:        bool vd = (cpu->reg.d != prev.d);
                    176:        bool ve = (cpu->reg.e != prev.e);
                    177:        bool vh = (cpu->reg.h != prev.h);
                    178:        bool vl = (cpu->reg.l != prev.l);
                    179:        bool vix = (cpu->reg.ix != prev.ix);
                    180:        bool viy = (cpu->reg.iy != prev.iy);
                    181:        bool vsp = (cpu->reg.sp != prev.sp);
                    182: 
                    183:        bool vxa = (cpu->reg.ex.a != prev.ex.a);
                    184:        bool vxf = (cpu->reg.ex.f.Get() != prev.ex.f.Get());
                    185:        bool vxb = (cpu->reg.ex.b != prev.ex.b);
                    186:        bool vxc = (cpu->reg.ex.c != prev.ex.c);
                    187:        bool vxd = (cpu->reg.ex.d != prev.ex.d);
                    188:        bool vxe = (cpu->reg.ex.e != prev.ex.e);
                    189:        bool vxh = (cpu->reg.ex.h != prev.ex.h);
                    190:        bool vxl = (cpu->reg.ex.l != prev.ex.l);
                    191: 
                    192:        bool vi = (reg_i != prev_i);
                    193: 
                    194:        std::string fstr1 = FlagStr(cpu->reg.f);
                    195:        std::string fstr2 = FlagStr(cpu->reg.ex.f);
                    196: 
                    197:        fprintf(cons, "AF:%s%02x%s %s%02x%s (%s)  PC:%04x   "
                    198:                        "AF':%s%02x%s %s%02x%s (%s)\n",
                    199:                BOLDIF(va), cpu->reg.a, NORM,
                    200:                BOLDIF(vf), cpu->reg.f.Get(), NORM,
                    201:                fstr1.c_str(),
                    202:                cpu->reg.pc,
                    203:                BOLDIF(vxa), cpu->reg.ex.a, NORM,
                    204:                BOLDIF(vxf), cpu->reg.ex.f.Get(), NORM,
                    205:                fstr2.c_str());
                    206:        fprintf(cons, "BC:%s%02x%s %s%02x%s           SP:%s%04x%s   "
                    207:                        "BC':%s%02x%s %s%02x%s\n",
                    208:                BOLDIF(vb),  cpu->reg.b,        NORM,
                    209:                BOLDIF(vc),  cpu->reg.c,        NORM,
                    210:                BOLDIF(vsp), cpu->reg.sp,       NORM,
                    211:                BOLDIF(vxb), cpu->reg.ex.b,     NORM,
                    212:                BOLDIF(vxc), cpu->reg.ex.c,     NORM);
                    213:        fprintf(cons, "DE:%s%02x%s %s%02x%s  IX:%s%04x%s   I:%s%02x%s     "
                    214:                        "DE':%s%02x%s %s%02x%s\n",
                    215:                BOLDIF(vd),    cpu->reg.d,              NORM,
                    216:                BOLDIF(ve),    cpu->reg.e,              NORM,
                    217:                BOLDIF(vix),   cpu->reg.ix,             NORM,
                    218:                BOLDIF(vi),    reg_i,                   NORM,
                    219:                BOLDIF(vxe),   cpu->reg.ex.d,   NORM,
                    220:                BOLDIF(vxd),   cpu->reg.ex.e,   NORM);
                    221:        fprintf(cons, "HL:%s%02x%s %s%02x%s  IY:%s%04x%s   R:%02x     "
                    222:                        "HL':%s%02x%s %s%02x%s\n",
                    223:                BOLDIF(vh),    cpu->reg.h,              NORM,
                    224:                BOLDIF(vl),    cpu->reg.l,              NORM,
                    225:                BOLDIF(viy),   cpu->reg.iy,             NORM,
                    226:                reg_r,
                    227:                BOLDIF(vxh),   cpu->reg.ex.h,   NORM,
                    228:                BOLDIF(vxl),   cpu->reg.ex.l,   NORM);
                    229: 
                    230:        return true;
                    231: }
                    232: 
                    233: std::string
                    234: DebuggerMD_hd64180::FlagStr(const hd64180flag& f)
                    235: {
                    236:        std::string buf;
                    237: 
                    238:        buf += f.IsS() ? 'S' : '-';
                    239:        buf += f.IsZ() ? 'Z' : '-';
                    240:        buf += f.IsH() ? 'H' : '-';
                    241:        buf += f.IsV() ? 'V' : (f.IsP() ? 'P' : '-');
                    242:        buf += f.IsN() ? 'N' : '-';
                    243:        buf += f.IsC() ? 'C' : '-';
                    244: 
                    245:        return buf;
                    246: }
                    247: 
                    248: bool
                    249: DebuggerMD_hd64180::ShowRegOther(FILE *cons)
                    250: {
                    251:        fprintf(cons, "IEF1: %s\n", cpu->GetIEF1() ? "Enable" : "Disable");
                    252:        fprintf(cons, "IEF2: %s\n", cpu->GetIEF2() ? "Enable" : "Disable");
                    253:        return true;
                    254: }
                    255: 
                    256: // レジスタ表示系コマンドのヘルプ
                    257: /*static*/ const HelpMessages
                    258: DebuggerMD_hd64180::HelpListReg = {
                    259:        { "r",          "Show general registers" },
                    260:        { "ro",         "Show some internal statuses" },
                    261: };
                    262: 
                    263: /*static*/ const HelpMessages
                    264: DebuggerMD_hd64180::HelpReg = {
                    265:        //-----
                    266:        { "r", R"**(
                    267:        Command: r
                    268: 
                    269:        Shows general registers.
                    270:        )**" },
                    271: 
                    272:        //-----
                    273:        { "ro", R"**(
                    274:        Command: ro
                    275: 
                    276:        Show some internal statuses.
                    277:        )**" },
                    278: };
                    279: 
                    280: const HelpMessages&
                    281: DebuggerMD_hd64180::GetHelpListReg() const
                    282: {
                    283:        return HelpListReg;
                    284: }
                    285: 
                    286: const HelpMessages&
                    287: DebuggerMD_hd64180::GetHelpReg() const
                    288: {
                    289:        return HelpReg;
                    290: }
                    291: 
                    292: std::string
                    293: DebuggerMD_hd64180::Disassemble(DebuggerMemoryStream& mem)
                    294: {
                    295:        hd64180disasm dis;
                    296:        if (dis.Exec(&mem) == false) {
                    297:                return "dis.Exec() failed";
                    298:        }
                    299: 
                    300:        // dis.bin は uint8 列なのでそのままダンプ。
                    301:        std::string str;
                    302:        for (auto v : dis.bin) {
                    303:                str += string_format("%02x ", v);
                    304:        }
                    305:        // ダンプは最長5バイト分
                    306:        str += std::string((5 - dis.bin.size()) * 3, ' ');
                    307: 
                    308:        // ニーモニック
                    309:        str += dis.text;
                    310:        // (あれば) 条件判断
                    311:        str += CondStr(dis.bin);
                    312: 
                    313:        return str;
                    314: }
                    315: 
                    316: // ops が条件命令なら、成立可否などの文字列を返す。
                    317: const char *
                    318: DebuggerMD_hd64180::CondStr(const std::vector<uint8>& ops) const
                    319: {
                    320:        if (ops[0] == 0x10) {   // DJNZ
                    321:                if (cpu->reg.b == 0) {
                    322:                        return " (will expire)";
                    323:                } else {
                    324:                        return " (will take)";
                    325:                }
                    326:        }
                    327: 
                    328:        if ((ops[0] & 0xc7) == 0xc0             // RET f
                    329:         || (ops[0] & 0xc7) == 0xc2             // JP f
                    330:         || (ops[0] & 0xc7) == 0xc4)    // CALL f
                    331:        {
                    332:                if (cpu->reg.f.IsCond((ops[0] >> 3) & 7)) {
                    333:                        return " (will take)";
                    334:                } else {
                    335:                        return " (will not take)";
                    336:                }
                    337:        }
                    338: 
                    339:        // JR は f と同じ形式だが1ビット少ないだけ
                    340:        if ((ops[0] & 0xe7) == 0x20) {
                    341:                if (cpu->reg.f.IsCond((ops[0] >> 3) & 3)) {
                    342:                        return " (will take)";
                    343:                } else {
                    344:                        return " (will not take)";
                    345:                }
                    346:        }
                    347: 
                    348:        // 条件命令ではない
                    349:        return "";
                    350: }

unix.superglobalmegacorp.com

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