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