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