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