|
|
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: lasize = 16;
26: pasize = 20;
27: name = "xp";
28: }
29:
30: // デストラクタ
31: DebuggerMD_hd64180::~DebuggerMD_hd64180()
32: {
33: }
34:
35: // 動作状態を返す
36: CPUState
37: DebuggerMD_hd64180::GetCPUState() const
38: {
39: // HD64180::OpMode を CPUState に変換
40: auto opmode = cpu->GetOpMode();
41: switch (opmode) {
42: case HD64180::OpMode::Normal:
43: return CPUState::Normal;
44:
45: case HD64180::OpMode::Reset:
46: case HD64180::OpMode::Halt:
47: case HD64180::OpMode::Sleep:
48: return CPUState::Halt;
49:
50: default:
51: PANIC("corrupted opmode=%d", (int)opmode);
52: }
53: }
54:
1.1.1.2 root 55: // アドレス変換
56: busaddr
57: DebuggerMD_hd64180::TranslateAddr(busaddr laddr) const
1.1 root 58: {
1.1.1.3 root 59: uint32 paddr = cpu->TranslatePeek(laddr.Addr());
60: return busaddr(paddr);
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: {
1.1.1.4 root 163: // AF:00 00 (------) PC:0000 AF':00 00
1.1 root 164: // BC:00 00 SP:0000 BC':00 00
1.1.1.4 root 165: // DE:00 00 IX:0000 I:00 DE':00 00
166: // HL:00 00 IY:0000 R:00 HL':00 00
1.1 root 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: fprintf(cons, "AF:%s%02x%s %s%02x%s (%s) PC:%04x "
1.1.1.4 root 196: "AF':%s%02x%s %s%02x%s\n",
1.1 root 197: BOLDIF(va), cpu->reg.a, NORM,
198: BOLDIF(vf), cpu->reg.f.Get(), NORM,
199: fstr1.c_str(),
200: cpu->reg.pc,
201: BOLDIF(vxa), cpu->reg.ex.a, NORM,
1.1.1.4 root 202: BOLDIF(vxf), cpu->reg.ex.f.Get(), NORM);
1.1 root 203: fprintf(cons, "BC:%s%02x%s %s%02x%s SP:%s%04x%s "
204: "BC':%s%02x%s %s%02x%s\n",
205: BOLDIF(vb), cpu->reg.b, NORM,
206: BOLDIF(vc), cpu->reg.c, NORM,
207: BOLDIF(vsp), cpu->reg.sp, NORM,
208: BOLDIF(vxb), cpu->reg.ex.b, NORM,
209: BOLDIF(vxc), cpu->reg.ex.c, NORM);
210: fprintf(cons, "DE:%s%02x%s %s%02x%s IX:%s%04x%s I:%s%02x%s "
211: "DE':%s%02x%s %s%02x%s\n",
212: BOLDIF(vd), cpu->reg.d, NORM,
213: BOLDIF(ve), cpu->reg.e, NORM,
214: BOLDIF(vix), cpu->reg.ix, NORM,
215: BOLDIF(vi), reg_i, NORM,
216: BOLDIF(vxe), cpu->reg.ex.d, NORM,
217: BOLDIF(vxd), cpu->reg.ex.e, NORM);
218: fprintf(cons, "HL:%s%02x%s %s%02x%s IY:%s%04x%s R:%02x "
219: "HL':%s%02x%s %s%02x%s\n",
220: BOLDIF(vh), cpu->reg.h, NORM,
221: BOLDIF(vl), cpu->reg.l, NORM,
222: BOLDIF(viy), cpu->reg.iy, NORM,
223: reg_r,
224: BOLDIF(vxh), cpu->reg.ex.h, NORM,
225: BOLDIF(vxl), cpu->reg.ex.l, NORM);
226:
227: return true;
228: }
229:
230: std::string
231: DebuggerMD_hd64180::FlagStr(const hd64180flag& f)
232: {
233: std::string buf;
234:
235: buf += f.IsS() ? 'S' : '-';
236: buf += f.IsZ() ? 'Z' : '-';
237: buf += f.IsH() ? 'H' : '-';
238: buf += f.IsV() ? 'V' : (f.IsP() ? 'P' : '-');
239: buf += f.IsN() ? 'N' : '-';
240: buf += f.IsC() ? 'C' : '-';
241:
242: return buf;
243: }
244:
245: bool
246: DebuggerMD_hd64180::ShowRegOther(FILE *cons)
247: {
248: fprintf(cons, "IEF1: %s\n", cpu->GetIEF1() ? "Enable" : "Disable");
249: fprintf(cons, "IEF2: %s\n", cpu->GetIEF2() ? "Enable" : "Disable");
250: return true;
251: }
252:
253: // レジスタ表示系コマンドのヘルプ
254: /*static*/ const HelpMessages
255: DebuggerMD_hd64180::HelpListReg = {
256: { "r", "Show general registers" },
257: { "ro", "Show some internal statuses" },
258: };
259:
260: /*static*/ const HelpMessages
261: DebuggerMD_hd64180::HelpReg = {
262: //-----
263: { "r", R"**(
264: Command: r
265:
266: Shows general registers.
267: )**" },
268:
269: //-----
270: { "ro", R"**(
271: Command: ro
272:
273: Show some internal statuses.
274: )**" },
275: };
276:
277: const HelpMessages&
278: DebuggerMD_hd64180::GetHelpListReg() const
279: {
280: return HelpListReg;
281: }
282:
283: const HelpMessages&
284: DebuggerMD_hd64180::GetHelpReg() const
285: {
286: return HelpReg;
287: }
288:
289: std::string
290: DebuggerMD_hd64180::Disassemble(DebuggerMemoryStream& mem)
291: {
292: hd64180disasm dis;
293: if (dis.Exec(&mem) == false) {
1.1.1.5 root 294: return "dis.Exec() failed.";
1.1 root 295: }
296:
297: // dis.bin は uint8 列なのでそのままダンプ。
298: std::string str;
299: for (auto v : dis.bin) {
300: str += string_format("%02x ", v);
301: }
302: // ダンプは最長5バイト分
303: str += std::string((5 - dis.bin.size()) * 3, ' ');
304:
305: // ニーモニック
306: str += dis.text;
307: // (あれば) 条件判断
308: str += CondStr(dis.bin);
309:
310: return str;
311: }
312:
313: // ops が条件命令なら、成立可否などの文字列を返す。
314: const char *
315: DebuggerMD_hd64180::CondStr(const std::vector<uint8>& ops) const
316: {
317: if (ops[0] == 0x10) { // DJNZ
318: if (cpu->reg.b == 0) {
319: return " (will expire)";
320: } else {
321: return " (will take)";
322: }
323: }
324:
325: if ((ops[0] & 0xc7) == 0xc0 // RET f
326: || (ops[0] & 0xc7) == 0xc2 // JP f
327: || (ops[0] & 0xc7) == 0xc4) // CALL f
328: {
329: if (cpu->reg.f.IsCond((ops[0] >> 3) & 7)) {
330: return " (will take)";
331: } else {
332: return " (will not take)";
333: }
334: }
335:
336: // JR は f と同じ形式だが1ビット少ないだけ
337: if ((ops[0] & 0xe7) == 0x20) {
338: if (cpu->reg.f.IsCond((ops[0] >> 3) & 3)) {
339: return " (will take)";
340: } else {
341: return " (will not take)";
342: }
343: }
344:
345: // 条件命令ではない
346: return "";
347: }
1.1.1.5 root 348:
349: // 命令ニーモニックに対するバイナリを文字列形式で返す。
350: // 対応しない場合は "" を返す。cmd_bi 用。
351: std::string
352: DebuggerMD_hd64180::ParseInst(const std::string& inst) const
353: {
354: return "";
355: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.