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