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