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

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: 
        !            56: // アドレス変換 (lookup は不要)
        !            57: uint64
        !            58: DebuggerMD_hd64180::TranslateAddr(saddr_t laddr, bool lookup) const
        !            59: {
        !            60:        return cpu->TranslatePeek((uint32)laddr);
        !            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.