|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.9 ! root 7: //
! 8: // デバッガ (M88xx0 依存部分)
! 9: //
! 10:
1.1 root 11: #include "debugger_private.h"
12: #include "debugger_m88xx0.h"
13: #include "m88100disasm.h"
1.1.1.2 root 14: #include "m88100acc.h"
1.1 root 15:
16: // newval が oldval から変化していれば太字属性にするマクロ
17: #define TSBOLD(newval, oldval) (((newval) != (oldval)) ? TA::Em : TA::Off)
18:
19: // cpu->name が変化していれば太字属性にするマクロ
20: #define TSBOLDC(name) TSBOLD(cpu->name, prev.name)
21:
22: // name の mask で示される部分が変化していれば太字属性にする
23: #define TSBOLDM(name, mask) TSBOLD((cpu->name & (mask)), (prev.name & (mask)))
24:
1.1.1.2 root 25: // コンストラクタ
26: DebuggerMD_m88xx0::DebuggerMD_m88xx0(Debugger *parent_, m88kcpu *cpu_)
1.1.1.9 ! root 27: : inherited(parent_, Arch::M88xx0)
1.1.1.2 root 28: {
29: cpu = cpu_;
30:
1.1.1.3 root 31: // 機種依存変数
1.1.1.4 root 32: inst_bytes = 4;
33: inst_bytes_fixed = 4;
1.1.1.3 root 34:
1.1.1.2 root 35: cmp_rd = -1;
36: }
37:
38: // デストラクタ
39: DebuggerMD_m88xx0::~DebuggerMD_m88xx0()
40: {
41: }
42:
43: bool
44: DebuggerMD_m88xx0::MMUEnabled() const
45: {
46: // XXX 命令/データの区別がまだないので、とりあえず命令のほうだけ見る
47: uint32 xapr = cpu->cmmu[0].GetAPR(IsSuper() ? 1 : 0);
48: return (xapr & m88200::APR_TE);
49: }
50:
51: // アドレス変換
52: uint64
1.1.1.5 root 53: DebuggerMD_m88xx0::TranslateAddr(saddr_t laddr, bool lookup) const
1.1.1.2 root 54: {
55: m88200 *cmmu;
56:
57: // XXX とりあえずね
1.1.1.5 root 58: if (laddr.IsData() == false) {
1.1.1.2 root 59: cmmu = &cpu->cmmu[0];
60: } else {
61: cmmu = &cpu->cmmu[1];
62: }
63:
1.1.1.5 root 64: return cmmu->TranslatePeek((uint32)laddr, laddr.IsSuper(), lookup);
1.1.1.2 root 65: }
66:
1.1.1.4 root 67: // op が bb0 命令なら true を返す
68: /*static*/ bool
69: DebuggerMD_m88xx0::IsBB0(uint32 op)
70: {
71: return ((op & 0xf8000000) == 0xd0000000); // bb0
72: }
73:
74: // op が tb0 命令なら true を返す
75: /*static*/ bool
76: DebuggerMD_m88xx0::IsTB0(uint32 op)
77: {
78: return ((op & 0xfc00fe00) == 0xf000d000); // tb0
79: }
80:
1.1.1.2 root 81: // op が bb0/tb0 命令なら true を返す
82: /*static*/ bool
83: DebuggerMD_m88xx0::IsBBTB0(uint32 op)
84: {
1.1.1.4 root 85: return IsBB0(op) || IsTB0(op);
1.1.1.2 root 86: }
87:
88: // op が bb1 命令なら true を返す
89: /*static*/ bool
90: DebuggerMD_m88xx0::IsBB1(uint32 op)
91: {
92: return ((op & 0xf8000000) == 0xd8000000); // bb1
93: }
94:
95: // op が tb1 命令なら true を返す
96: /*static*/ bool
97: DebuggerMD_m88xx0::IsTB1(uint32 op)
98: {
99: return ((op & 0xfc00fe00) == 0xf000d800); // tb1
100: }
101:
102: // op が bb1/tb1 命令なら true を返す
103: /*static*/ bool
104: DebuggerMD_m88xx0::IsBBTB1(uint32 op)
105: {
106: return IsBB1(op) || IsTB1(op);
107: }
108:
1.1 root 109: void
110: DebuggerMD_m88xx0::BackupRegs()
111: {
112: prev = (m88100reg)*cpu;
113: }
114:
1.1.1.2 root 115: void
116: DebuggerMD_m88xx0::SetStepOut()
117: {
118: so_r1 = cpu->r[1];
119: }
120:
121: bool
122: DebuggerMD_m88xx0::IsStepOut() const
123: {
124: return (cpu->xip == so_r1);
125: }
126:
1.1.1.4 root 127: // この命令がステップイン出来るなら true を返す
128: bool
1.1.1.5 root 129: DebuggerMD_m88xx0::IsOpStepIn(DebuggerMemoryStream& mem)
1.1.1.4 root 130: {
1.1.1.5 root 131: uint32 op = mem.FetchInst();
132:
1.1.1.4 root 133: if ((op & 0xf800'0000) == 0xc800'0000 // bsr
134: || IsTB0(op) // tb0
135: || (IsTB1(op) && ((op >> 16) & 0x1f) != 0) // tb1 (except r0)
136: || (op & 0xfc00'fe00) == 0xf000'e800 // tcnd
137: || (op & 0xfc00'fb00) == 0xf400'c800 // jsr
138: || (op & 0xfc00'0000) == 0xf800'0000 // tbnd imm
139: || (op & 0xfc00'ffe0) == 0xf400'f800 // tbnd rs2
140: ) {
141: return true;
142: }
143:
144: return false;
145: }
146:
1.1 root 147: // レジスタ名からそのレジスタ値を返す。
148: // メモリダンプのような用途なのでアドレスとして使えるアドレスのみ。
149: uint64
150: DebuggerMD_m88xx0::GetRegAddr(const char *name) const
151: {
152: char buf[8];
153:
154: if (strcmp(name, "xip") == 0) return cpu->xip;
155: if (strcmp(name, "nip") == 0) return cpu->nip;
156: if (strcmp(name, "fip") == 0) return cpu->fip;
157:
158: // 制御レジスタ
159: //if (strcmp(name, "pid") == 0) return cpu->pid;
160: //if (strcmp(name, "psr") == 0) return cpu->psr;
161: //if (strcmp(name, "epsr") == 0) return cpu->epsr;
162: //if (strcmp(name, "ssbr") == 0) return cpu->ssbr;
1.1.1.2 root 163: if (strcmp(name, "sxip") == 0) return cpu->sxip & m88100reg::SIP_MASK;
164: if (strcmp(name, "snip") == 0) return cpu->snip & m88100reg::SIP_MASK;
165: if (strcmp(name, "sfip") == 0) return cpu->sfip & m88100reg::SIP_MASK;
1.1 root 166: if (strcmp(name, "vbr") == 0) return cpu->vbr;
167: //if (strcmp(name, "dmt0") == 0) return cpu->dmt0;
168: if (strcmp(name, "dmd0") == 0) return cpu->dmd0;
169: if (strcmp(name, "dma0") == 0) return cpu->dma0;
170: //if (strcmp(name, "dmt1") == 0) return cpu->dmt1;
171: if (strcmp(name, "dmd1") == 0) return cpu->dmd1;
172: if (strcmp(name, "dma1") == 0) return cpu->dma1;
173: //if (strcmp(name, "dmt2") == 0) return cpu->dmt2;
174: if (strcmp(name, "dmd2") == 0) return cpu->dmd2;
175: if (strcmp(name, "dma2") == 0) return cpu->dma2;
176: if (strcmp(name, "sr0") == 0) return cpu->sr[0];
177: if (strcmp(name, "sr1") == 0) return cpu->sr[1];
178: if (strcmp(name, "sr2") == 0) return cpu->sr[2];
179: if (strcmp(name, "sr3") == 0) return cpu->sr[3];
180:
181: for (int i = 0; i < countof(cpu->cr); i++) {
182: snprintf(buf, sizeof(buf), "cr%d", i);
183: if (strcmp(name, buf) == 0) {
184: return cpu->cr[i];
185: }
186: }
187:
188: // FPU レジスタ
189: // XXX not implement
190:
191: // 通常レジスタ
192: for (int i = 0; i < countof(cpu->r); i++) {
193: snprintf(buf, sizeof(buf), "r%d", i);
194: if (strcmp(name, buf) == 0) {
195: return cpu->r[i];
196: }
197: }
198:
199: return (uint64)-1;
200: }
201:
1.1.1.2 root 202: // レジスタ表示系コマンドのヘルプ
203: /*static*/ const HelpMessages
1.1.1.5 root 204: DebuggerMD_m88xx0::HelpListReg = {
1.1.1.4 root 205: { "r", "Show general registers" },
206: { "rc", "Show (integer) control registers" },
207: { "rf", "Show floating point control registers" },
208: { "ro", "Show other (shadow) registers" },
209: { "ra<id>", "Show ATC on CMMU<id>" },
210: { "rd<id>", "Show data cache on CMMU<id>" },
211: { "rm<id>", "Show CMMU<id> registers" },
1.1.1.2 root 212: };
213:
1.1.1.5 root 214: /*static*/ const HelpMessages
215: DebuggerMD_m88xx0::HelpReg = {
216: //-----
217: { "r", R"**(
218: Command: r
219:
220: Shows general registers.
221: )**" },
222:
223: //-----
224: { "rc", R"**(
225: Command: rc
226:
227: Shows the (integer) control registers.
228: )**" },
229:
230: //-----
231: { "rf", R"**(
232: Command: rf
233:
234: Shows the floating point control registers.
235: )**" },
236:
237: //-----
238: { "ro", R"**(
239: Command: ro
240:
241: Shows the other registers.
242: )**" },
243:
244: //-----
245: { "ra", R"**(
246: Command: ra<id> <id> := 7, 6
247:
248: Shows BATC/PATC on CMMU<id>.
249: CMMU7 is instruction CMMU of CPU#0.
250: CMMU6 is data CMMU of CPU#0.
251: )**" },
252: { "ra6", "=ra" },
253: { "ra7", "=ra" },
254:
255: //-----
256: { "rd", R"**(
257: Command: rd<id> <id> := 7, 6
258:
259: Shows data cache on CMMU<id>.
260: CMMU7 is instruction CMMU of CPU#0.
261: CMMU6 is data CMMU of CPU#0.
262: )**" },
263: { "rd6", "=rd" },
264: { "rd7", "=rd" },
265:
266: //-----
267: { "rm", R"**(
268: Command: rm<id> <id> := 7, 6
269:
270: Shows CMMU<id> registers.
271: CMMU7 is instruction CMMU of CPU#0.
272: CMMU6 is data CMMU of CPU#0.
273: )**" },
274: { "rm6", "=rm" },
275: { "rm7", "=rm" },
276: };
277:
278: const HelpMessages&
279: DebuggerMD_m88xx0::GetHelpListReg() const
280: {
281: return HelpListReg;
282: }
283:
1.1.1.2 root 284: const HelpMessages&
1.1.1.5 root 285: DebuggerMD_m88xx0::GetHelpReg() const
1.1.1.2 root 286: {
1.1.1.5 root 287: return HelpReg;
1.1.1.2 root 288: }
289:
290: // レジスタ表示系コマンド
291: bool
1.1.1.9 ! root 292: DebuggerMD_m88xx0::ShowRegister(FILE *cons,
1.1.1.2 root 293: const std::vector<std::string>& args)
294: {
295: int cmmu_id;
296:
297: // 余分な引数は無視する?
298:
299: if (args[0] == "r") {
1.1.1.9 ! root 300: ShowRegMain();
1.1.1.2 root 301: return true;
302: }
303: if (args[0] == "rc") {
1.1.1.9 ! root 304: ShowRegCtrl();
1.1.1.2 root 305: return true;
306: }
307: if (args[0] == "rf") {
1.1.1.9 ! root 308: ShowRegFPU();
1.1.1.2 root 309: return true;
310: }
311: if (args[0] == "ro") {
1.1.1.9 ! root 312: ShowRegOther();
1.1.1.2 root 313: return true;
314: }
315:
316: if (MatchCMMUCmd(args[0], "ra", &cmmu_id)) {
1.1.1.9 ! root 317: Monitor *mon = gMonitorManager->Find(ID_MONITOR_ATC(cmmu_id));
1.1.1.7 root 318: if (mon) {
319: parent->ShowMonitor(*mon);
320: return true;
321: }
322: goto notfound;
1.1.1.2 root 323: }
324: if (MatchCMMUCmd(args[0], "rd", &cmmu_id)) {
1.1.1.7 root 325: return ShowRegCache(cons, args, cmmu_id);
1.1.1.2 root 326: }
327: if (MatchCMMUCmd(args[0], "rm", &cmmu_id)) {
1.1.1.9 ! root 328: Monitor *mon = gMonitorManager->Find(ID_MONITOR_CMMU(cmmu_id));
1.1.1.7 root 329: if (mon) {
330: parent->ShowMonitor(*mon);
331: return true;
332: }
333: goto notfound;
1.1.1.2 root 334: }
335:
336: // 該当なし
1.1.1.7 root 337: notfound:
1.1.1.2 root 338: return false;
339: }
340:
341: // CMMU ID 入りコマンド名を照合する。
342: // cmdname が basename + <id> の時、*idp に id を格納して true を返す。
1.1.1.7 root 343: // 一致しないか id が(数値でないなど)不正なら false を返す。
344: // 実際にその id の CMMU が存在するかはここではチェックしない。
1.1.1.2 root 345: bool
346: DebuggerMD_m88xx0::MatchCMMUCmd(const std::string& cmdname,
347: const char *basename, int *idp)
348: {
349: int baselen = strlen(basename);
350:
351: if (strncmp(cmdname.c_str(), basename, baselen) != 0) {
352: return false;
353: }
354:
355: // 先頭が一致したら id を調べる
356: int id;
357: const char *start = cmdname.c_str() + baselen;
358: char *end;
359: errno = 0;
360: id = strtoul(start, &end, 10);
361: if (*start == '\0' || *end != '\0' || errno == ERANGE) {
362: return false;
363: }
364:
365: *idp = id;
366: return true;
367: }
368:
1.1 root 369: void
1.1.1.9 ! root 370: DebuggerMD_m88xx0::ShowRegMain()
1.1 root 371: {
372: TextScreen s(80, 8);
373:
1.1.1.2 root 374: /*
375: r0 :00000000 r8 :00000000 r16:00000000 r24:00000000 b:bs=1 a:lo=1 8:ls=0
376: r1 :00700000 r9 :00000000 r17:00000000 r25:00000000
377: r2 :0070e1a0 r10:00000000 r18:00000000 r26:00000000
378: */
379:
1.1 root 380: for (int i = 0; i < countof(cpu->r); i++) {
381: s.Print((i / 8) * 14, i % 8, TSBOLDC(r[i]), "r%-2d:%08x", i, cpu->r[i]);
382: }
383:
1.1.1.2 root 384: // cmp 以降最初の分岐命令で結果レジスタの条件ビットマップを表示する。
385: // 分岐命令は bb1 #3 みたいな形式なのでそれだけでは条件演算子が分からない
386: // のと、bb1 #n 自体は cmp 以外に対しても使えるので、cmp 命令以降最初の
387: // 分岐命令でのみ表示してみる。
388: if (cmp_rd >= 0 && (IsBBTB0(cpu->opX) || IsBBTB1(cpu->opX))) {
389: static const char * const cmpstr[] = {
390: NULL, NULL, "eq", "ne", "gt", "le", "lt", "ge",
391: "hi", "ls", "lo", "hs",
392: };
393: int x = 0;
394: int y = 0;
395: uint32 res = cpu->r[cmp_rd];
396: for (int b = 11; b >= 2; b--) {
397: s.Print(57 + x * 7, y, "%x:%s=%d", b, cmpstr[b],
398: (res & (1 << b)) ? 1 : 0);
399: x++;
400: if (x > 2) {
401: x = 0;
402: y++;
403: }
404: }
405: }
406:
407: parent->ShowTextScreen(s);
1.1 root 408: }
409:
410: void
1.1.1.9 ! root 411: DebuggerMD_m88xx0::ShowRegCtrl()
1.1 root 412: {
413: TextScreen s(80, 6);
414: int x;
415: int y;
416:
417: /*
418: 0 1 2 3 4 5 6 7
419: 0123456789012345678901234567890123456789012345678901234567890123456789012345678
1.1.1.4 root 420: pid (cr0):12345678(Arch=$00 Ver=$00 M/C=Checker) sr0(cr17):00000000
421: psr (cr1):12345678(S,LE,SER,Cy SFD1,MXM,IND,SFRZ) sr1(cr18):00000000
422: epsr(cr2):12345678(S,LE,SER,Cy SFD1,MXM,IND,SFRZ) sr2(cr19):00000000
423: xip:00000000 opX:00000000(--) sxip(cr4):00000000:VE sr3(cr20):00000000
424: nip:00000000 opF:00000000(--) snip(cr5):00000000:-- ssbr(cr3):00000000
425: fip:00000000 sfip(cr6):00000000:VE vbr (cr7):00000000
1.1 root 426: */
427:
428: #define PRINT_B(x, y, reg, mask, fmt, arg) do { \
429: uint32 _new = cpu->reg & (mask); \
430: uint32 _old = prev.reg & (mask); \
431: s.Print((x), (y), TSBOLD(_new, _old), fmt, (arg)); \
432: } while (0)
433:
434: // pid(cr0)
435: x = 0;
436: y = 0;
1.1.1.2 root 437: s.Print(x, y, TSBOLDC(pid), "pid (cr0):%08x(", cpu->pid);
438: PRINT_B(x + 19, y, pid, m88100reg::PID_REV_MASK, "Arch=$%02x",
439: (_new >> 8) & 0xff);
440: PRINT_B(x + 28, y, pid, m88100reg::PID_VER_MASK, "Ver=$%02x",
441: (_new >> 1) & 0x7f);
442: PRINT_B(x + 36, y, pid, m88100reg::PID_MASTER, "M/C=%s)",
443: (_new & m88100reg::PID_MASTER) ? "Master" : "Checker");
1.1 root 444:
445: // psr(cr1)
446: y++;
447: s.Print(x, y, TSBOLDC(psr), "psr (cr1):%08x", cpu->psr);
448: s.Print(x + 18, y, "(s,le,ser,cy sfd1,mxm,ind,sfrz)");
449: PRINT_B(x + 19, y, psr, m88100reg::PSR_SUPER, "%c", _new ? 'S' : '-');
450: PRINT_B(x + 21, y, psr, m88100reg::PSR_BO_LE, "%s", _new ? "LE" : "BE");
451: PRINT_B(x + 24, y, psr, m88100reg::PSR_SER, "%s", _new ? "CON" : "SER");
452: PRINT_B(x + 28, y, psr, m88100reg::PSR_C, "%s", _new ? "Cy" : "--");
453: PRINT_B(x + 31, y, psr, m88100reg::PSR_SFD1, "%s", _new ? "SFD1" : "----");
454: PRINT_B(x + 36, y, psr, m88100reg::PSR_MXM, "%s", _new ? "MXM" : "---");
455: PRINT_B(x + 40, y, psr, m88100reg::PSR_IND, "%s", _new ? "IND" : "---");
456: PRINT_B(x + 44, y, psr, m88100reg::PSR_SFRZ, "%s", _new ? "SFRZ" : "----");
457:
458: // epsr(cr2)
459: y++;
1.1.1.4 root 460: s.Print(x, y, TSBOLDC(epsr), "epsr(cr2):%08x", cpu->epsr);
1.1 root 461: s.Print(x + 18, y, "(s,le,ser,cy sfd1,mxm,ind,sfrz)");
462: PRINT_B(x + 19, y, epsr, m88100reg::PSR_SUPER, "%c", _new ? 'S' : '-');
463: PRINT_B(x + 21, y, epsr, m88100reg::PSR_BO_LE, "%s", _new ? "LE" : "BE");
464: PRINT_B(x + 24, y, epsr, m88100reg::PSR_SER, "%s", _new ? "CON" : "SER");
465: PRINT_B(x + 28, y, epsr, m88100reg::PSR_C, "%s", _new ? "Cy" : "--");
466: PRINT_B(x + 31, y, epsr, m88100reg::PSR_SFD1, "%s", _new ? "SFD1":"----");
467: PRINT_B(x + 36, y, epsr, m88100reg::PSR_MXM, "%s", _new ? "MXM" : "---");
468: PRINT_B(x + 40, y, epsr, m88100reg::PSR_IND, "%s", _new ? "IND" : "---");
469: PRINT_B(x + 44, y, epsr, m88100reg::PSR_SFRZ, "%s", _new ? "SFRZ":"----");
470:
471: // *IP
472: x = 0;
473: y = 3;
474: s.Print(x, y, "xip:%08x opX:%08x(%c%c)",
475: cpu->xip, (uint32)cpu->opX,
476: cpu->OpIsBusErr(cpu->opX) ? 'B' : '-',
477: cpu->OpIsDelay(cpu->opX) ? 'D' : '-');
478: s.Print(x, y + 1, "nip:%08x opF:%08x(%c%c)",
479: cpu->nip, (uint32)cpu->opF,
480: cpu->OpIsBusErr(cpu->opF) ? 'B' : '-',
481: cpu->OpIsDelay(cpu->opX) ? 'D' : '-');
482: s.Print(x, y + 2, "fip:%08x", cpu->fip);
483:
484: // S*IP
485: x = 32;
486: for (int i = 0; i < 3; i++) {
487: s.Print(x, y + i, TSBOLDC(cr[4 + i]), "%s(cr%d):%08x:%c%c",
488: m88100reg::sipname[i], 4 + i,
489: (cpu->cr[4 + i] & m88100reg::SIP_MASK),
490: (cpu->cr[4 + i] & m88100reg::SIP_V) ? 'V' : '-',
491: (cpu->cr[4 + i] & m88100reg::SIP_E) ? 'E' : '-');
492: }
493:
494: x = 55;
495: y = 0;
496: // SR*
497: for (int i = 0; i < 4; i++) {
498: int rn = 17 + i;
1.1.1.4 root 499: s.Print(x, y++, TSBOLDC(cr[rn]), "sr%d(cr%d):%08x",
1.1 root 500: i, rn, cpu->cr[rn]);
501: }
1.1.1.4 root 502: // ssbr(cr3)
503: s.Print(x, y++, TSBOLDC(ssbr), "ssbr(cr3):%08x", cpu->ssbr);
504: // vbr(cr7)
505: s.Print(x, y++, TSBOLDC(vbr), "vbr (cr7):%08x", cpu->vbr);
1.1 root 506:
1.1.1.2 root 507: parent->ShowTextScreen(s);
508: }
509:
510: // CMMU のデータキャッシュを表示
511: // rd<N> なら概要表示。
512: // rd<N> <set> なら個別セットの詳細表示。
1.1.1.7 root 513: // id を受け付ければ true を、そうでなければ false を返す。
514: bool
1.1.1.9 ! root 515: DebuggerMD_m88xx0::ShowRegCache(FILE *cons,
1.1.1.2 root 516: const std::vector<std::string>& args, int id)
517: {
1.1.1.7 root 518: m88200 *cmmu;
519:
520: // XXX id はまだ決め打ち
521: if (id == 7) {
522: cmmu = &cpu->cmmu[0];
523: } else if (id == 6) {
524: cmmu = &cpu->cmmu[1];
525: } else {
526: return false;
527: }
528:
1.1.1.2 root 529: if (args.size() < 2) {
1.1.1.9 ! root 530: ShowRegCacheOverview(cmmu);
1.1.1.2 root 531: } else {
532: int set;
533: char *end;
534: errno = 0;
535: set = strtol(args[1].c_str(), &end, 16);
536: if (end == &args[1][0] || *end != '\0' || errno == ERANGE) {
1.1.1.9 ! root 537: fprintf(cons, "<set> must be a number\n");
1.1.1.7 root 538: goto done;
1.1.1.2 root 539: }
540: if (set < 0 || set > 256) {
1.1.1.9 ! root 541: fprintf(cons, "<set> must be in 00..ff\n");
1.1.1.7 root 542: goto done;
1.1.1.2 root 543: }
1.1.1.9 ! root 544: ShowRegCacheSet(cmmu, set);
1.1.1.2 root 545: }
1.1.1.7 root 546: done:
547: return true;
1.1.1.2 root 548: }
549:
550: // CMMU データキャッシュの概要表示
551: void
1.1.1.9 ! root 552: DebuggerMD_m88xx0::ShowRegCacheOverview(m88200 *cmmu)
1.1.1.2 root 553: {
554: TextScreen s(70, 17);
555:
556: cmmu->MonitorCacheOverview(s, 0, false);
557: parent->ShowTextScreen(s);
558: }
559:
560: // CMMU データキャッシュの指定セットの詳細表示
561: void
1.1.1.9 ! root 562: DebuggerMD_m88xx0::ShowRegCacheSet(m88200 *cmmu, int setidx)
1.1.1.2 root 563: {
564: TextScreen s(70, 5);
565:
566: cmmu->MonitorCacheSet(s, 0, setidx);
567: parent->ShowTextScreen(s);
1.1 root 568: }
569:
570: void
1.1.1.9 ! root 571: DebuggerMD_m88xx0::ShowRegFPU()
1.1 root 572: {
573: static const char * const fcrname[] = {
574: "fpecr",
575: "fphs1",
576: "fpls1",
577: "fphs2",
578: "fpls2",
579: "fppt",
580: "fprh",
581: "fprl",
582: "fpit",
583: "fpsr", // [9] 62
584: "fpcr", // [10] 63
585: };
586: TextScreen s(80, 4);
587:
588: for (int i = 0; i < 9; i++) {
589: s.Print((i / 4) * 22, i % 4, TSBOLDC(fcr[i]),
590: "%-5s(fcr%d):%08x", fcrname[i], i, cpu->fcr[i]);
591: }
592:
593: s.Print(44, 2, TSBOLDC(fpsr), "fpsr(fcr62):%08x", cpu->fpsr);
594: s.Print(44, 3, TSBOLDC(fpcr), "fpcr(fcr63):%08x", cpu->fpcr);
595:
1.1.1.2 root 596: parent->ShowTextScreen(s);
1.1 root 597: }
598:
599: void
1.1.1.9 ! root 600: DebuggerMD_m88xx0::ShowRegOther()
1.1 root 601: {
602: TextScreen s(80, 3);
603: /*
604: 0 1 2 3 4 5 6 7
605: 0123456789012345678901234567890123456789012345678901234567890123456789012345678
1.1.1.2 root 606: dmt0(cr8) :0000(B,S,D,L,Rxx,S,---B,W,V) dmd0(cr9) :00000000 dma0(cr10):00000000
607: dmt0(cr11):0000(B,U,D,L,Rxx,S,HH--,W,V) dmd0(cr9) :00000000 dma0(cr10):00000000
608: dmt0(cr14):0000(B, ,D,L,Rxx,S,LLLL,W,V) dmd0(cr9) :00000000 dma0(cr10):00000000
1.1 root 609: */
610: for (int i = 0; i <= 2; i++) {
611: int dt = 8 + i * 3;
612: int dd = 9 + i * 3;
613: int da = 10 + i * 3;
614:
615: s.Print(0, i, TSBOLDC(cr[dt]), "dmt%d(cr%-2d):%04x",
616: i, dt, (cpu->cr[dt] & 0xffff));
1.1.1.2 root 617: s.Print(15, i, "(b,s,d,l,rx, s,en ,w,v)");
1.1 root 618: PRINT_B(16, i, cr[dt], m88100reg::DM_BO, "%c", _new ? 'B' : '-');
1.1.1.2 root 619: PRINT_B(18, i, cr[dt], m88100reg::DM_DAS, "%c", _new ? 'S' : 'U');
620: PRINT_B(20, i, cr[dt], m88100reg::DM_DOUB1, "%c", _new ? 'D' : '-');
621: PRINT_B(22, i, cr[dt], m88100reg::DM_LOCK, "%c", _new ? 'L' : '-');
622: // カンマを前詰め。かつ DREG がボールドでもカンマはボールドにしない
623: PRINT_B(24, i, cr[dt], m88100reg::DM_DREG_MASK, "r%d", _new >> 7);
624: s.Puts(",");
625: PRINT_B(28, i, cr[dt], m88100reg::DM_SIGNED, "%c", _new ? 'S' : '-');
626: PRINT_B(30, i, cr[dt], m88100reg::DM_EN_MASK,"%s",
627: m88100reg::dmt_en_str[(_new >> 2) & 0xf]);
628: PRINT_B(35, i, cr[dt], m88100reg::DM_WRITE, "%c", _new ? 'W' : '-');
629: PRINT_B(37, i, cr[dt], m88100reg::DM_VALID, "%c", _new ? 'V' : '-');
1.1 root 630:
1.1.1.2 root 631: s.Print(40, i, TSBOLDC(cr[dd]), "dmd%d(cr%-2d):%08x",
1.1 root 632: i, dd, cpu->cr[dd]);
1.1.1.2 root 633: s.Print(60, i, TSBOLDC(cr[dd]), "dma%d(cr%2d):%08x",
1.1 root 634: i, da, cpu->cr[da]);
635: }
636:
1.1.1.2 root 637: parent->ShowTextScreen(s);
1.1 root 638: }
639:
640: // 逆アセンブル
641: bool
1.1.1.5 root 642: DebuggerMD_m88xx0::Disassemble(DebuggerMemoryStream& mem,
1.1 root 643: std::string& mnemonic, std::vector<uint8>& bin)
644: {
1.1.1.5 root 645: m88100disasm dis(mem);
646: if (dis.Exec() == false) {
1.1 root 647: return false;
648: }
649: bin = dis.bin;
1.1.1.8 root 650: mnemonic = dis.text;
651: if (!dis.alttext.empty()) {
652: // 別名追加
653: int len = mnemonic.length() % 8;
654: if (len < 8) {
655: mnemonic += std::string(8 - len, ' ');
656: } else {
657: mnemonic += ' ';
658: }
659: mnemonic += dis.alttext;
660: }
661:
1.1 root 662: return true;
663: }
664:
665: // 逆アセンブルをフォーマット (オフライン版)
666: std::string
667: DebuggerMD_m88xx0::FormatDisasm(const std::string& mnemonic,
668: const std::vector<uint8>& bin)
669: {
670: // 命令はすべて32ビット固定長
671: uint32 op = (bin[0] << 24) | (bin[1] << 16) | (bin[2] << 8) | bin[3];
672: return string_format("%08x %s", op, mnemonic.c_str());
673: }
674:
675: // 逆アセンブルをフォーマット (オンライン版)
676: std::string
677: DebuggerMD_m88xx0::FormatDisasmLive(const std::string& mnemonic,
678: const std::vector<uint8>& bin)
679: {
680: // 命令はすべて32ビット固定長
681: uint32 op = (bin[0] << 24) | (bin[1] << 16) | (bin[2] << 8) | bin[3];
682:
683: // 遅延スロットは分かりやすく表示したい
684: std::string delay;
685: if (cpu->OpIsDelay(cpu->opX)) {
686: delay = "(delayed) ";
687: }
688:
1.1.1.2 root 689: const char *cond = CondStr(op);
690: return string_format("%08x %s%s%s",
691: op, delay.c_str(), mnemonic.c_str(), cond);
692: }
693:
694: #define TAKE_IF(expr) do { \
695: if ((expr)) \
696: return " (will take)"; \
697: else \
698: return " (will not take)"; \
699: } while (0)
700:
701: // 条件命令なら、成立可否などの文字列を返す。
702: const char *
703: DebuggerMD_m88xx0::CondStr(uint32 op)
704: {
705: uint32 s = m88100opf_S1(op);
706:
707: if (IsBBTB0(op)) {
708: // 11010N BBBBB SSSSS dddddd dd dddddddd bb0
709: // 111100 BBBBB SSSSS 110100 0V VVVVVVVV tb0
710: // rS の bit B が %0 ならブランチ/トラップ
711: cmp_rd = -1;
712: uint32 b = m88100opf_B5(op);
713: TAKE_IF((cpu->r[s] & (1 << b)) == 0);
714: }
715: if (IsBB1(op)) {
716: // 11011N BBBBB SSSSS dddddd dd dddddddd bb1
717: // rS の bit B が %1 ならブランチ
718: cmp_rd = -1;
719: // 対 r0 なら絶対成立しないので nop
720: if (s == 0) {
721: return " (nop)";
722: }
723: uint32 b = m88100opf_B5(op);
724: TAKE_IF((cpu->r[s] & (1 << b)) != 0);
725: }
726: if (IsTB1(op)) {
727: // 111100 BBBBB SSSSS 110110 0V VVVVVVVV tb1
728: // rS の bit B が %1 ならトラップ
729: cmp_rd = -1;
730: // 対 r0 なら sync として使っており逆アセンブラ側で表示を加工してある
731: // のでこちら側では対処不要。
732: if (s == 0) {
733: return "";
734: }
735: uint32 b = m88100opf_B5(op);
736: TAKE_IF((cpu->r[s] & (1 << b)) != 0);
737: }
738: if ((op & 0xf8000000) == 0xe8000000 || // bcnd
739: (op & 0xfc00fe00) == 0xf000e800) // tcnd
740: {
741: // 11101N MMMMM SSSSS dddddd dd dddddddd bcnd
742: // rS が M5 で示される条件にマッチすればブランチ/トラップ
743: cmp_rd = -1;
744: uint32 m5 = m88100opf_M5(op);
745: TAKE_IF(
746: (m5 == 0x2 && cpu->r[s] == 0) || // eq0
747: (m5 == 0xd && cpu->r[s] != 0) || // ne0
748: (m5 == 0x1 && (int32)cpu->r[s] > 0) || // gt0
749: (m5 == 0xc && (int32)cpu->r[s] < 0) || // lt0
750: (m5 == 0x3 && (int32)cpu->r[s] >= 0) || // ge0
751: (m5 == 0xe && (int32)cpu->r[s] <= 0) // le0
752: );
753: }
754:
755: if ((op & 0xfc00fce0) == 0xf4007c00 || // cmp rD,rS1,rS2
756: (op & 0xfc000000) == 0x7c000000 ) // cmp rD,rS1,imm16
757: {
758: // 次の条件分岐命令で結果レジスタを表示するため、rD だけ覚えておく
759: cmp_rd = m88100opf_D(op);
760: }
761:
762: return "";
1.1 root 763: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.