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

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

unix.superglobalmegacorp.com

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