|
|
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.8 root 7: //
8: // デバッガ (M680x0 依存部分)
9: //
10:
1.1 root 11: #include "debugger_m680x0.h"
1.1.1.9 root 12: #include "debugger_memory.h"
13: #include "debugger.h"
1.1.1.11! root 14: #include "exttostr.h"
! 15: #include "m680x0disasm.h"
1.1.1.9 root 16: #include "m68030mmu.h"
17: #include "mainbus.h"
1.1 root 18:
1.1.1.2 root 19: // コンストラクタ
1.1.1.9 root 20: DebuggerMD_m680x0::DebuggerMD_m680x0(Debugger *parent_)
21: : inherited(parent_, CPUArch::M680x0)
1.1.1.2 root 22: {
1.1.1.9 root 23: // この時点で Get*Device() は使える
1.1.1.10 root 24: cpu = GetMPU680x0Device(parent->mpu);
1.1.1.9 root 25: bus = GetMainbusDevice();
1.1.1.2 root 26:
1.1.1.3 root 27: // 機種依存変数
1.1.1.4 root 28: inst_bytes = 2;
29: inst_bytes_fixed = 0;
1.1.1.9 root 30: lasize = 32;
31: pasize = 32;
32: name = "mpu";
1.1.1.2 root 33: }
34:
35: // デストラクタ
36: DebuggerMD_m680x0::~DebuggerMD_m680x0()
37: {
38: }
39:
1.1 root 40: // アドレス変換
1.1.1.10 root 41: busaddr
42: DebuggerMD_m680x0::TranslateAddr(busaddr laddr) const
1.1 root 43: {
1.1.1.10 root 44: return cpu->TranslatePeek(laddr);
1.1 root 45: }
46:
1.1.1.11! root 47: // op が 680x0 の条件命令 Bcc, Scc, TRAPcc, DBcc なら true を返す。
! 48: /*static*/ bool
1.1 root 49: DebuggerMD_m680x0::IsOPcc(uint16 op)
50: {
51: uint16 cc;
52:
53: if ((op & 0xf000) == 0x6000) {
54: cc = (op >> 8) & 0xf;
55: if (cc == 0 || cc == 1) { // BRA, BSR
56: return false;
57: } else {
58: return true; // Bcc
59: }
60: }
61:
62: if ((op & 0xf0c0) == 0x50c0) { // Scc, TRAPcc, DBcc
63: return true;
64: }
65:
66: return false;
67: }
68:
69: // op が DBcc 命令なら true を返す。
1.1.1.11! root 70: /*static*/ bool
1.1 root 71: DebuggerMD_m680x0::IsDBcc(uint16 op)
72: {
73: if ((op & 0xf0f8) == 0x50c8) { // DBcc
74: return true;
75: }
76: return false;
77: }
78:
1.1.1.11! root 79: // ir[] が FBcc, FScc, FDBcc, FTRAPcc 命令なら condition のあるワード位置を
! 80: // 返す。これらの条件命令でなければ (FNOP も含む)、-1 を返す。
! 81: /*static*/ int
! 82: DebuggerMD_m680x0::IsFXcc(const std::vector<uint16>& ir)
! 83: {
! 84: if ((ir[0] & 0xfe00) != 0xf200) {
! 85: return -1;
! 86: }
! 87: if (ir.size() < 2) {
! 88: return -1;
! 89: }
! 90:
! 91: // FNOP は除く。
! 92: if (ir[0] == 0xf280 && ir[1] == 0) {
! 93: return -1;
! 94: }
! 95:
! 96: uint type = (ir[0] >> 6) & 7;
! 97: if (type == 1) { // FScc/FDBcc/FTRAPcc
! 98: return 1;
! 99: } else if (type == 2) { // FBcc.W
! 100: return 0;
! 101: } else if (type == 3) { // FBcc.L
! 102: return 0;
! 103: }
! 104: return -1;
! 105: }
! 106:
1.1 root 107: // op の cccc 条件が現在の CCR で成立するなら true を返す。
108: bool
1.1.1.11! root 109: DebuggerMD_m680x0::IsCond(uint16 op) const
1.1 root 110: {
1.1.1.9 root 111: bool N = cpu->reg.ccr.IsN();
112: bool Z = cpu->reg.ccr.IsZ();
113: bool V = cpu->reg.ccr.IsV();
114: bool C = cpu->reg.ccr.IsC();
1.1 root 115:
116: switch ((op >> 8) & 0x0f) {
117: case 0: // T
118: return true;
119: case 1: // F
120: return false;
121: case 2: // HI
122: return (!C) && (!Z);
123: case 3: // LS
124: return C || Z;
125: case 4: // CC
126: return !C;
127: case 5: // CS
128: return C;
129: case 6: // NE
130: return !Z;
131: case 7: // EQ
132: return Z;
133: case 8: // VC
134: return !V;
135: case 9: // VS
136: return V;
137: case 10: // PL
138: return !N;
139: case 11: // MI
140: return N;
141: case 12: // GE
142: return (N && V) || ((!N) && (!V));
143: case 13: // LT
144: return (N && (!V)) || ((!N) && V);
145: case 14: // GT
146: return (N && V && (!Z)) || ((!N) && (!V) && (!Z));
147: case 15: // LE
148: return Z || (N && (!V)) || ((!N) && V);
149: default:
150: __unreachable();
151: }
152: }
153:
154: // addr 位置の命令が条件命令なら、成立可否などの文字列を返す。
155: // Bcc, Scc, TRAPcc 命令なら、条件が成立するかどうか。
156: // DBcc 命令ならブランチするかどうか。
157: const char *
1.1.1.11! root 158: DebuggerMD_m680x0::CondStr(const std::vector<uint16>& ir) const
1.1 root 159: {
160: uint16 op = ir[0];
161:
162: // DBcc 命令なら、ブランチするかどうか
163: // IsOPcc() は DBcc も含んでいるため、IsDBcc() の判定のほうが先。
164: // DBcc は内部でカウンタレジスタを減算してから比較するため、
165: // 命令実行前のカウンタが 0 の時点でループ終了となることに注意。
166: if (IsDBcc(op)) {
167: // 成立したら何もしない
168: if (IsCond(op)) {
169: return " (will fall)";
170: }
171: // カウンタが -1 なら何もしない
172: uint rr = op & 7;
1.1.1.9 root 173: if ((cpu->reg.R[rr] & 0xffff) == 0) {
1.1 root 174: return " (will expire)";
175: }
176: // それ以外はブランチ
177: return " (will take)";
178: }
179:
180: // Bcc, Scc, TRAPcc 命令なら条件が成立するかどうか
181: if (IsOPcc(op)) {
182: if (IsCond(op)) {
183: return " (will take)";
184: } else {
185: return " (will not take)";
186: }
187: }
188:
1.1.1.11! root 189: // FXcc
! 190: int n = IsFXcc(ir);
! 191: if (n >= 0) {
! 192: struct fpemu fe0;
! 193: struct fpframe fpf0;
! 194: memset(&fe0, 0, sizeof(fe0));
! 195: fe0.fe_fpframe = &fpf0;
! 196: fe0.fe_fpsr = cpu->reg.fpframe.fpf_fpsr;
! 197: int result = test_cc(&fe0, ir[n]);
! 198: if (result < 0) {
! 199: return " (will take)";
! 200: } else if (result == 0) {
! 201: return " (will not take)";
! 202: }
! 203: }
! 204:
1.1 root 205: // (ここで知ってる)条件命令ではない
206: return "";
207: }
208:
209: void
210: DebuggerMD_m680x0::SetStepOut()
211: {
1.1.1.9 root 212: so_a7 = cpu->reg.A[7];
213: so_sr = cpu->GetSR() & 0x3000;
1.1 root 214: }
215:
216: bool
217: DebuggerMD_m680x0::IsStepOut() const
218: {
1.1.1.9 root 219: return (cpu->reg.A[7] > so_a7 || (cpu->GetSR() & 0x3000) != so_sr);
1.1 root 220: }
221:
1.1.1.4 root 222: // この命令がステップイン出来るなら true を返す
223: bool
1.1.1.5 root 224: DebuggerMD_m680x0::IsOpStepIn(DebuggerMemoryStream& mem)
1.1.1.4 root 225: {
1.1.1.9 root 226: uint32 op = mem.Read(inst_bytes);
1.1.1.5 root 227:
1.1.1.4 root 228: if ((op & 0xfff0) == 0x4e40 // TRAP
229: || (op == 0x4e76) // TRAPV
230: || (op & 0xffc0) == 0x4e80 // JSR
231: || (op & 0xf0f8) == 0x50f8 // TRAPcc
232: || (op & 0xff00) == 0x6100 // BSR
233: || (op & 0xfff8) == 0xf278 // FTRAPcc
1.1.1.10 root 234: || (op & 0xfe00) == 0xfe00 // DOS($FFxx), FPACK($FExx)
1.1.1.4 root 235: ) {
236: return true;
237: }
238:
239: // IOCS コール(に逆アセンブラで見えるやつ)も一命令扱いにしておく。
240: // XXX 本当は X68k の時だけだが今の所副作用なさげなので
241: if ((op & 0xff00) == 0x7000) { // MOVEQ to %d0
1.1.1.9 root 242: uint32 op2 = mem.Read(inst_bytes);
1.1.1.4 root 243: if (op2 == 0x4e4f) { // TRAP #15
244: return true;
245: }
246: }
247:
248: return false;
249: }
250:
1.1 root 251: // レジスタ名からそのレジスタ値を返す。
1.1.1.9 root 252: // メモリダンプのような用途なのでアドレスとして使うレジスタのみ。
1.1 root 253: uint64
254: DebuggerMD_m680x0::GetRegAddr(const char *name) const
255: {
256: uint32 addr;
257:
258: if ((*name | 0x20) == 'a') {
1.1.1.9 root 259: addr = cpu->reg.A[name[1] - '0'];
1.1 root 260:
261: } else if ((*name | 0x20) == 'd') {
1.1.1.9 root 262: addr = cpu->reg.D[name[1] - '0'];
1.1 root 263:
264: } else if (strcmp(name, "sp") == 0) {
1.1.1.9 root 265: addr = cpu->reg.A[7];
1.1 root 266:
267: } else if (strcmp(name, "usp") == 0) {
1.1.1.11! root 268: if (cpu->reg.s == false) {
! 269: addr = cpu->reg.A[7];
! 270: } else {
! 271: addr = cpu->reg.usp;
! 272: }
1.1 root 273:
274: } else if (strcmp(name, "isp") == 0) {
1.1.1.11! root 275: if (cpu->reg.s && cpu->reg.m == false) {
! 276: addr = cpu->reg.A[7];
! 277: } else {
! 278: addr = cpu->reg.isp;
! 279: }
1.1 root 280:
281: } else if (strcmp(name, "msp") == 0) {
1.1.1.11! root 282: if (cpu->reg.s && cpu->reg.m) {
! 283: addr = cpu->reg.A[7];
! 284: } else {
! 285: addr = cpu->reg.msp;
! 286: }
! 287:
! 288: } else if (strcmp(name, "ssp") == 0) {
! 289: if (cpu->reg.s) {
! 290: addr = cpu->reg.A[7];
! 291: } else {
! 292: if (cpu->reg.m) {
! 293: addr = cpu->reg.msp;
! 294: } else {
! 295: addr = cpu->reg.isp;
! 296: }
! 297: }
1.1 root 298:
299: } else if (strcmp(name, "pc") == 0) {
1.1.1.9 root 300: addr = cpu->reg.pc;
1.1 root 301:
302: } else if (strcmp(name, "vbr") == 0) {
1.1.1.9 root 303: addr = cpu->GetVBR();
1.1 root 304:
305: } else if (strcmp(name, "srp") == 0) {
1.1.1.11! root 306: if (cpu->GetMPUType() == m680x0MPUType::M68030) {
! 307: auto cpu68030 = dynamic_cast<MPU68030Device *>(cpu);
! 308: addr = cpu68030->GetSRPl();
! 309: } else {
! 310: auto cpu68040 = dynamic_cast<MPU68040Device *>(cpu);
! 311: addr = cpu68040->GetSRP();
! 312: }
1.1 root 313:
314: } else if (strcmp(name, "crp") == 0) {
1.1.1.11! root 315: auto cpu68030 = dynamic_cast<MPU68030Device *>(cpu);
! 316: if (cpu68030) {
! 317: addr = cpu68030->GetCRPl();
! 318: } else {
! 319: return (uint64)-1;
! 320: }
! 321:
! 322: } else if (strcmp(name, "urp") == 0) {
! 323: auto cpu68040 = dynamic_cast<MPU68040Device *>(cpu);
! 324: if (cpu68040) {
! 325: addr = cpu68040->GetURP();
! 326: } else {
! 327: return (uint64)-1;
! 328: }
1.1 root 329:
330: } else {
331: return (uint64)-1;
332: }
333: return addr;
334: }
335:
1.1.1.2 root 336: // レジスタ表示系コマンドのヘルプ
337: /*static*/ const HelpMessages
1.1.1.5 root 338: DebuggerMD_m680x0::HelpListReg = {
1.1.1.4 root 339: { "r", "Show general registers" },
340: { "ra", "Show ATC" },
341: { "rf", "Show FPU registers" },
342: { "rm", "Show MMU registers" },
343: { "ro", "Show other registers" },
1.1.1.2 root 344: };
345:
1.1.1.5 root 346: /*static*/ const HelpMessages
347: DebuggerMD_m680x0::HelpReg = {
348: //-----
349: { "r", R"**(
350: Command: r
351:
352: Shows main registers.
353: )**" },
354:
355: //-----
356: { "ra", R"**(
357: Command: ra
358:
359: Shows m68030 ATC(Address Translation Cache) information. Note that
360: nono's ATC implementation is very different from the real one (to
361: improve performance).
362: )**" },
363:
364: //-----
365: { "rf", R"**(
366: Command: rf
367:
368: Shows 68881/68882's FPU registers.
369: )**" },
370:
371: //-----
372: { "rm", R"**(
373: Command: rm
374:
375: Shows registers related to MMU and cache.
376: )**" },
377:
378: //-----
379: { "ro", R"**(
380: Command: ro
381:
382: Shows other registers.
383: )**" },
384: };
385:
386: const HelpMessages&
387: DebuggerMD_m680x0::GetHelpListReg() const
388: {
389: return HelpListReg;
390: }
391:
1.1.1.2 root 392: const HelpMessages&
1.1.1.5 root 393: DebuggerMD_m680x0::GetHelpReg() const
1.1.1.2 root 394: {
1.1.1.5 root 395: return HelpReg;
1.1.1.2 root 396: }
397:
398: // レジスタ表示系コマンド
399: bool
1.1.1.8 root 400: DebuggerMD_m680x0::ShowRegister(FILE *cons,
1.1.1.2 root 401: const std::vector<std::string>& args)
402: {
403: // 余分な引数は無視する?
404:
405: if (args[0] == "r") {
406: ShowRegMain(cons);
407: return true;
408: }
409: if (args[0] == "ra") {
1.1.1.8 root 410: ShowRegATC();
1.1.1.2 root 411: return true;
412: }
413: if (args[0] == "rf") {
414: ShowRegFPU(cons);
415: return true;
416: }
417: if (args[0] == "rm") {
1.1.1.11! root 418: if (cpu->GetMPUType() == m680x0MPUType::M68030) {
! 419: ShowRegMMU30(cons);
! 420: } else {
! 421: ShowRegMMU40(cons);
! 422: }
1.1.1.2 root 423: return true;
424: }
425: if (args[0] == "ro") {
1.1.1.8 root 426: ShowRegOther();
1.1.1.2 root 427: return true;
428: }
429:
430: // 該当なし
431: return false;
432: }
433:
434:
1.1 root 435: // レジスタ表示 (基本セット)
436: void
1.1.1.8 root 437: DebuggerMD_m680x0::ShowRegMain(FILE *cons)
1.1 root 438: {
439: /*
440: D0:00000070 D4:CCCCCCCC A0:00FFAA32 A4:CCCCCCCC SR=F810(S I=0 X----)
441: D1:0000FFFF D5:00000000 A1:00000A7A A5:00000A7A
442: D2:00FF0000 D6:00000000 A2:CCCCCCCC A6:CCCCCCCC
443: D3:CCCCCCCC D7:00000003 A3:CCCCCCCC A7:00001FD8
444: */
445: bool vr[16];
446:
1.1.1.9 root 447: for (int i = 0; i < countof(cpu->reg.R); i++) {
448: vr[i] = (cpu->reg.R[i] != prev.R[i]);
1.1 root 449: }
450:
451: // 1行目
1.1.1.8 root 452: fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s ",
1.1.1.9 root 453: BOLDIF(vr[ 0]), 0, cpu->reg.R[ 0], NORM,
454: BOLDIF(vr[ 4]), 4, cpu->reg.R[ 4], NORM,
455: BOLDIF(vr[ 8]), 0, cpu->reg.R[ 8], NORM,
456: BOLDIF(vr[12]), 4, cpu->reg.R[12], NORM);
1.1 root 457:
458: // 1行目 SR
1.1.1.9 root 459: uint16 sr = cpu->GetSR();
460: uint16 prevsr = prev.GetSR();
1.1 root 461: // SR は上位バイトと下位バイトが変化したくらいでいいか?
1.1.1.8 root 462: fprintf(cons, " SR:%s%02x%s%s%02x%s",
1.1 root 463: BOLDIF((sr & 0xff00) != (prevsr & 0xff00)),
464: sr >> 8,
465: NORM,
466: BOLDIF((sr & 0x00ff) != (prevsr & 0x00ff)),
467: sr & 0xff,
468: NORM);
1.1.1.8 root 469: fprintf(cons, "(%c I=%d %c%c%c%c%c)\n",
1.1 root 470: (sr & 0x2000) ? 'S' : '-',
471: (sr >> 8) & 7,
1.1.1.9 root 472: (sr & M68K::CCR_X) ? 'X' : '-',
473: (sr & M68K::CCR_N) ? 'N' : '-',
474: (sr & M68K::CCR_Z) ? 'Z' : '-',
475: (sr & M68K::CCR_V) ? 'V' : '-',
476: (sr & M68K::CCR_C) ? 'C' : '-');
1.1 root 477:
478: // 2行目
1.1.1.8 root 479: fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n",
1.1.1.9 root 480: BOLDIF(vr[ 1]), 1, cpu->reg.R[ 1], NORM,
481: BOLDIF(vr[ 5]), 5, cpu->reg.R[ 5], NORM,
482: BOLDIF(vr[ 9]), 1, cpu->reg.R[ 9], NORM,
483: BOLDIF(vr[13]), 5, cpu->reg.R[13], NORM);
1.1 root 484:
485: // 3行目
1.1.1.8 root 486: fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n",
1.1.1.9 root 487: BOLDIF(vr[ 2]), 2, cpu->reg.R[ 2], NORM,
488: BOLDIF(vr[ 6]), 6, cpu->reg.R[ 6], NORM,
489: BOLDIF(vr[10]), 2, cpu->reg.R[10], NORM,
490: BOLDIF(vr[14]), 6, cpu->reg.R[14], NORM);
1.1 root 491:
492: // 4行目
1.1.1.8 root 493: fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n",
1.1.1.9 root 494: BOLDIF(vr[ 3]), 3, cpu->reg.R[ 3], NORM,
495: BOLDIF(vr[ 7]), 7, cpu->reg.R[ 7], NORM,
496: BOLDIF(vr[11]), 3, cpu->reg.R[11], NORM,
497: BOLDIF(vr[15]), 7, cpu->reg.R[15], NORM);
1.1 root 498: }
499:
500: // FPU レジスタ表示
501: void
1.1.1.8 root 502: DebuggerMD_m680x0::ShowRegFPU(FILE *cons)
1.1 root 503: {
504: /*
1.1.1.11! root 505: FP0:0000_12345678_12345678 = -0.1234567890123456789)
! 506: FPCR: 1234 BS,SN,OE,OF,UF,DZ,X2,X1 RP=.X RM=Minus
! 507: FPSR: 12345678 N Z Inf NAN Q=$xx BS,SN,OE,OF,UF,DZ,X2,X1 AV AO AU AZ AX
! 508: FPIAR:12345678
1.1 root 509: */
510:
511: uint32 fpcr, fpsr, fpiar;
512: uint32 ppcr, ppsr, ppiar;
513: static const char * const rmstr[] = {
514: "Near",
515: "Zero",
516: "Minus",
517: "Plus",
518: };
519:
520: fpcr = cpu->reg.fpframe.fpf_fpcr;
521: fpsr = cpu->reg.fpframe.fpf_fpsr;
522: fpiar = cpu->reg.fpframe.fpf_fpiar;
523: ppcr = prev.fpframe.fpf_fpcr;
524: ppsr = prev.fpframe.fpf_fpsr;
525: ppiar = prev.fpframe.fpf_fpiar;
526:
1.1.1.11! root 527: for (uint n = 0; n < 8; n++) {
! 528: uint32 *c_ = cpu->reg.fpframe.fpf_regs + (n) * 3;
! 529: uint32 *p_ = prev.fpframe.fpf_regs + (n) * 3;
! 530: bool d = (c_[0] ^ p_[0]) | (c_[1] ^ p_[1]) | (c_[2] ^ p_[2]);
! 531: fprintf(cons, "%sFP%u:%04x_%08x_%08x%s = %s\n",
! 532: BOLDIF(d), n, c_[0] >> 16, c_[1], c_[2], NORM,
! 533: ExtToStr(c_).c_str());
! 534: }
1.1 root 535:
1.1.1.11! root 536: fprintf(cons, "%sFPCR: %04x%s%20s",
! 537: BOLDIF(fpcr != ppcr), fpcr, NORM, "");
! 538: fprintf(cons, "%s %s %s %s %s %s %s %s ",
1.1 root 539: (fpcr & 0x8000) ? "BS" : "--",
540: (fpcr & 0x4000) ? "SN" : "--",
1.1.1.11! root 541: (fpcr & 0x2000) ? "OE" : "--",
! 542: (fpcr & 0x1000) ? "OF" : "--",
1.1 root 543: (fpcr & 0x0800) ? "UF" : "--",
544: (fpcr & 0x0400) ? "DZ" : "--",
1.1.1.11! root 545: (fpcr & 0x0200) ? "X2" : "--",
! 546: (fpcr & 0x0100) ? "X1" : "--");
! 547: fprintf(cons, "RP=.%c RM=%s\n",
! 548: "XSD?"[(fpcr >> 6) & 3],
1.1 root 549: rmstr[(fpcr >> 4) & 3]);
550:
551: uint cc = fpsr >> 24;
1.1.1.11! root 552: fprintf(cons, "%sFPSR: %08x%s ", BOLDIF(fpsr != ppsr), fpsr, NORM);
! 553: fprintf(cons, "%c %c %s %s Q=$%02x ",
1.1 root 554: (cc & 0x08) ? 'N' : '-',
555: (cc & 0x04) ? 'Z' : '-',
556: (cc & 0x02) ? "Inf" : "---",
557: (cc & 0x01) ? "NAN" : "---",
558: (fpsr >> 16) & 0xff);
1.1.1.11! root 559: fprintf(cons, "%s %s %s %s %s %s %s %s ",
1.1 root 560: (fpsr & 0x8000) ? "BS" : "--",
561: (fpsr & 0x4000) ? "SN" : "--",
562: (fpsr & 0x2000) ? "OP" : "--",
563: (fpsr & 0x1000) ? "OV" : "--",
564: (fpsr & 0x0800) ? "UF" : "--",
565: (fpsr & 0x0400) ? "DZ" : "--",
566: (fpsr & 0x0200) ? "I2" : "--",
567: (fpsr & 0x0100) ? "I1" : "--");
1.1.1.11! root 568: fprintf(cons, "%s %s %s %s %s\n",
! 569: (fpsr & 0x80) ? "AV" : "--",
! 570: (fpsr & 0x40) ? "AO" : "--",
! 571: (fpsr & 0x20) ? "AU" : "--",
! 572: (fpsr & 0x10) ? "AZ" : "--",
! 573: (fpsr & 0x08) ? "AX" : "--");
1.1 root 574:
1.1.1.8 root 575: fprintf(cons, "%sFPIAR:%08x%s\n", BOLDIF(fpiar != ppiar), fpiar, NORM);
1.1 root 576: }
577:
1.1.1.11! root 578: // 68030 MMU レジスタ表示
1.1 root 579: void
1.1.1.11! root 580: DebuggerMD_m680x0::ShowRegMMU30(FILE *cons)
1.1 root 581: {
582: /*
583: SRP:00001111_22223333 TT0:00001111 TC:00001111 (---)
584: CRP:00001111_22223333 TT1:00001111 MMUSR: 0011 (
585: */
1.1.1.11! root 586: auto cpu68030 = dynamic_cast<MPU68030Device *>(cpu);
1.1 root 587: uint64 srp, osrp;
588: uint64 crp, ocrp;
589: uint32 tt0, ott0;
590: uint32 tt1, ott1;
591: uint32 tc, otc;
592: uint16 sr, osr;
593: bool p;
594: bool t;
595: bool c;
596:
1.1.1.11! root 597: srp = cpu68030->GetSRP();
! 598: crp = cpu68030->GetCRP();
! 599: tt0 = cpu68030->GetTT(0);
! 600: tt1 = cpu68030->GetTT(1);
! 601: tc = cpu68030->GetTC();
! 602: sr = cpu68030->GetMMUSR();
1.1 root 603:
604: osrp = prev.srp.q;
605: ocrp = prev.crp.q;
606: ott0 = prev.tt[0];
607: ott1 = prev.tt[1];
608: otc = prev.tc;
609: osr = prev.mmusr;
610:
611: // 1行目
612: p = (srp != osrp);
613: t = (tt0 != ott0);
614: c = (tc != otc);
1.1.1.8 root 615: fprintf(cons, "%sSRP:%08x_%08x%s %sTT0:%08x%s(%c%c%c)",
1.1 root 616: BOLDIF(p), (uint32)(srp >> 32), (uint32)srp, NORM,
617: BOLDIF(t), tt0, NORM,
618: (tt0 & m68030TT::E) ? 'E' : '-',
619: (tt0 & m68030TT::CI) ? 'C' : '-',
620: (tt0 & m68030TT::RWM) ? '-' : ((tt0 & m68030TT::RW) ? 'R' : 'W'));
1.1.1.8 root 621: fprintf(cons, " %sTC:%08x%s(%c%c%c)\n",
1.1 root 622: BOLDIF(c), tc, NORM,
623: (tc & m68030TC::TC_E) ? 'E' : '-',
624: (tc & m68030TC::TC_SRE) ? 'S' : '-',
625: (tc & m68030TC::TC_FCL) ? 'F' : '-');
626:
627: // 2行目
628: p = (crp != ocrp);
629: t = (tt1 != ott1);
630: c = (sr != osr);
1.1.1.8 root 631: fprintf(cons, "%sCRP:%08x_%08x%s %sTT1:%08x%s(%c%c%c)",
1.1 root 632: BOLDIF(p), uint32(crp >> 32), (uint32)crp, NORM,
633: BOLDIF(t), tt1, NORM,
634: (tt1 & m68030TT::E) ? 'E' : '-',
635: (tt1 & m68030TT::CI) ? 'C' : '-',
636: (tt1 & m68030TT::RWM) ? '-' : ((tt1 & m68030TT::RW) ? 'R' : 'W'));
1.1.1.8 root 637: fprintf(cons, " %sMMUSR: %04x%s(%c%c%c%c%c%c%c N=%d)\n",
1.1 root 638: BOLDIF(c), sr, NORM,
639: (sr & m68030MMUSR::B) ? 'B' : '-',
640: (sr & m68030MMUSR::L) ? 'L' : '-',
641: (sr & m68030MMUSR::S) ? 'S' : '-',
642: (sr & m68030MMUSR::W) ? 'W' : '-',
643: (sr & m68030MMUSR::I) ? 'I' : '-',
644: (sr & m68030MMUSR::M) ? 'M' : '-',
645: (sr & m68030MMUSR::T) ? 'T' : '-',
646: (sr & m68030MMUSR::N));
647: }
648:
1.1.1.11! root 649: // 68040 MMU レジスタ表示
! 650: void
! 651: DebuggerMD_m680x0::ShowRegMMU40(FILE *cons)
! 652: {
! 653: fprintf(cons, "Not implemented\n");
! 654: }
! 655:
1.1 root 656: // ATC を表示
657: void
1.1.1.8 root 658: DebuggerMD_m680x0::ShowRegATC()
1.1 root 659: {
1.1.1.8 root 660: parent->ShowMonitor(gMonitorManager->Get(ID_MONITOR_MPUATC));
1.1 root 661: }
662:
663: // その他のレジスタを表示
664: void
1.1.1.8 root 665: DebuggerMD_m680x0::ShowRegOther()
1.1 root 666: {
667: TextScreen s(80, 2);
668:
669: // 0 1 2 3 4 5 6
670: // 012345678901234567890123456789012345678901234567890123456789012345
671: // CACR:01234567 VBR:01234567 USP:01234567
672: // CAAR:01234567 SFC:0 DFC:0 MSP:01234567
673:
674: #define EM(name) ((cpu->reg.name != prev.name) ? TA::Em : TA::Normal)
675: s.Print(0, 0, EM(cacr), "CACR:%08x", cpu->reg.cacr);
676: s.Print(0, 1, EM(caar), "CAAR:%08x", cpu->reg.caar);
677:
678: s.Print(15, 0, EM(vbr), "VBR:%08x", cpu->reg.vbr);
1.1.1.10 root 679: s.Print(15, 1, EM(sfc), "SFC:%d", cpu->reg.GetSFC());
680: s.Print(22, 1, EM(dfc), "DFC:%d", cpu->reg.GetDFC());
1.1 root 681:
682: // スタック欄はモードによって表示を変える。
683: // ユーザ 割り込み マスタ
684: // 1行目 ISP USP USP
685: // 2行目 MSP MSP ISP
1.1.1.9 root 686: if (!cpu->IsSuper()) {
1.1 root 687: s.Print(29, 0, EM(isp), "ISP:%08x", cpu->reg.isp);
688: } else {
689: s.Print(29, 0, EM(usp), "USP:%08x", cpu->reg.usp);
690: }
1.1.1.9 root 691: if (!cpu->IsMaster()) {
1.1 root 692: s.Print(29, 1, EM(msp), "MSP:%08x", cpu->reg.msp);
693: } else {
694: s.Print(29, 1, EM(isp), "ISP:%08x", cpu->reg.isp);
695: }
696:
1.1.1.2 root 697: parent->ShowTextScreen(s);
1.1 root 698: }
699:
1.1.1.9 root 700: // オンライン用逆アセンブル
701: std::string
702: DebuggerMD_m680x0::Disassemble(DebuggerMemoryStream& mem)
1.1 root 703: {
1.1.1.9 root 704: m680x0disasm dis;
705: if (dis.Exec(&mem) == false) {
706: return "dis.Exec() failed";
707: }
708:
709: // dis.bin は uint8 列なのでこれを uint16 列に変換
710: std::vector<uint16> words;
711: for (int i = 0; i < dis.bin.size(); i += 2) {
712: words.push_back((dis.bin[i] << 8) | dis.bin[i + 1]);
1.1 root 713: }
714:
715: // 16進ダンプ
716: std::string dumpbuf;
1.1.1.9 root 717: for (auto w : words) {
718: dumpbuf += string_format("%04x ", w);
1.1 root 719: }
720:
721: // ダンプは5ワード分 (越えたら知らん)
1.1.1.9 root 722: std::string str = string_format("%-25s", dumpbuf.c_str());
723: // ニーモニック
724: str += dis.text;
725: // (あれば) 条件判断
726: str += CondStr(words);
1.1 root 727:
1.1.1.9 root 728: return str;
1.1 root 729: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.