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