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