|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.