|
|
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.