|
|
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.1.13! root 18: #include "vectortable.h"
1.1 root 19:
1.1.1.2 root 20: // コンストラクタ
1.1.1.9 root 21: DebuggerMD_m680x0::DebuggerMD_m680x0(Debugger *parent_)
22: : inherited(parent_, CPUArch::M680x0)
1.1.1.2 root 23: {
1.1.1.9 root 24: // この時点で Get*Device() は使える
1.1.1.10 root 25: cpu = GetMPU680x0Device(parent->mpu);
1.1.1.9 root 26: bus = GetMainbusDevice();
1.1.1.2 root 27:
1.1.1.3 root 28: // 機種依存変数
1.1.1.4 root 29: inst_bytes = 2;
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.13! root 259: if (name[1] < '0' || name[1] > '7') {
! 260: return (uint64)-1;
! 261: }
1.1.1.9 root 262: addr = cpu->reg.A[name[1] - '0'];
1.1 root 263:
264: } else if ((*name | 0x20) == 'd') {
1.1.1.13! root 265: if (name[1] < '0' || name[1] > '7') {
! 266: return (uint64)-1;
! 267: }
1.1.1.9 root 268: addr = cpu->reg.D[name[1] - '0'];
1.1 root 269:
270: } else if (strcmp(name, "sp") == 0) {
1.1.1.9 root 271: addr = cpu->reg.A[7];
1.1 root 272:
273: } else if (strcmp(name, "usp") == 0) {
1.1.1.11 root 274: if (cpu->reg.s == false) {
275: addr = cpu->reg.A[7];
276: } else {
277: addr = cpu->reg.usp;
278: }
1.1 root 279:
280: } else if (strcmp(name, "isp") == 0) {
1.1.1.11 root 281: if (cpu->reg.s && cpu->reg.m == false) {
282: addr = cpu->reg.A[7];
283: } else {
284: addr = cpu->reg.isp;
285: }
1.1 root 286:
287: } else if (strcmp(name, "msp") == 0) {
1.1.1.11 root 288: if (cpu->reg.s && cpu->reg.m) {
289: addr = cpu->reg.A[7];
290: } else {
291: addr = cpu->reg.msp;
292: }
293:
294: } else if (strcmp(name, "ssp") == 0) {
295: if (cpu->reg.s) {
296: addr = cpu->reg.A[7];
297: } else {
298: if (cpu->reg.m) {
299: addr = cpu->reg.msp;
300: } else {
301: addr = cpu->reg.isp;
302: }
303: }
1.1 root 304:
305: } else if (strcmp(name, "pc") == 0) {
1.1.1.9 root 306: addr = cpu->reg.pc;
1.1 root 307:
308: } else if (strcmp(name, "vbr") == 0) {
1.1.1.9 root 309: addr = cpu->GetVBR();
1.1 root 310:
311: } else if (strcmp(name, "srp") == 0) {
1.1.1.11 root 312: if (cpu->GetMPUType() == m680x0MPUType::M68030) {
313: auto cpu68030 = dynamic_cast<MPU68030Device *>(cpu);
314: addr = cpu68030->GetSRPl();
315: } else {
316: auto cpu68040 = dynamic_cast<MPU68040Device *>(cpu);
317: addr = cpu68040->GetSRP();
318: }
1.1 root 319:
320: } else if (strcmp(name, "crp") == 0) {
1.1.1.11 root 321: auto cpu68030 = dynamic_cast<MPU68030Device *>(cpu);
322: if (cpu68030) {
323: addr = cpu68030->GetCRPl();
324: } else {
325: return (uint64)-1;
326: }
327:
328: } else if (strcmp(name, "urp") == 0) {
329: auto cpu68040 = dynamic_cast<MPU68040Device *>(cpu);
330: if (cpu68040) {
331: addr = cpu68040->GetURP();
332: } else {
333: return (uint64)-1;
334: }
1.1 root 335:
336: } else {
337: return (uint64)-1;
338: }
339: return addr;
340: }
341:
1.1.1.2 root 342: // レジスタ表示系コマンドのヘルプ
343: /*static*/ const HelpMessages
1.1.1.5 root 344: DebuggerMD_m680x0::HelpListReg = {
1.1.1.4 root 345: { "r", "Show general registers" },
346: { "ra", "Show ATC" },
347: { "rf", "Show FPU registers" },
348: { "rm", "Show MMU registers" },
349: { "ro", "Show other registers" },
1.1.1.2 root 350: };
351:
1.1.1.5 root 352: /*static*/ const HelpMessages
353: DebuggerMD_m680x0::HelpReg = {
354: //-----
355: { "r", R"**(
356: Command: r
357:
358: Shows main registers.
359: )**" },
360:
361: //-----
362: { "ra", R"**(
363: Command: ra
364:
365: Shows m68030 ATC(Address Translation Cache) information. Note that
366: nono's ATC implementation is very different from the real one (to
367: improve performance).
368: )**" },
369:
370: //-----
371: { "rf", R"**(
372: Command: rf
373:
374: Shows 68881/68882's FPU registers.
375: )**" },
376:
377: //-----
378: { "rm", R"**(
379: Command: rm
380:
381: Shows registers related to MMU and cache.
382: )**" },
383:
384: //-----
385: { "ro", R"**(
386: Command: ro
387:
388: Shows other registers.
389: )**" },
390: };
391:
392: const HelpMessages&
393: DebuggerMD_m680x0::GetHelpListReg() const
394: {
395: return HelpListReg;
396: }
397:
1.1.1.2 root 398: const HelpMessages&
1.1.1.5 root 399: DebuggerMD_m680x0::GetHelpReg() const
1.1.1.2 root 400: {
1.1.1.5 root 401: return HelpReg;
1.1.1.2 root 402: }
403:
404: // レジスタ表示系コマンド
405: bool
1.1.1.8 root 406: DebuggerMD_m680x0::ShowRegister(FILE *cons,
1.1.1.2 root 407: const std::vector<std::string>& args)
408: {
409: // 余分な引数は無視する?
410:
411: if (args[0] == "r") {
412: ShowRegMain(cons);
413: return true;
414: }
415: if (args[0] == "ra") {
1.1.1.8 root 416: ShowRegATC();
1.1.1.2 root 417: return true;
418: }
419: if (args[0] == "rf") {
420: ShowRegFPU(cons);
421: return true;
422: }
423: if (args[0] == "rm") {
1.1.1.11 root 424: if (cpu->GetMPUType() == m680x0MPUType::M68030) {
425: ShowRegMMU30(cons);
426: } else {
427: ShowRegMMU40(cons);
428: }
1.1.1.2 root 429: return true;
430: }
431: if (args[0] == "ro") {
1.1.1.8 root 432: ShowRegOther();
1.1.1.2 root 433: return true;
434: }
435:
436: // 該当なし
437: return false;
438: }
439:
440:
1.1 root 441: // レジスタ表示 (基本セット)
442: void
1.1.1.8 root 443: DebuggerMD_m680x0::ShowRegMain(FILE *cons)
1.1 root 444: {
445: /*
446: D0:00000070 D4:CCCCCCCC A0:00FFAA32 A4:CCCCCCCC SR=F810(S I=0 X----)
447: D1:0000FFFF D5:00000000 A1:00000A7A A5:00000A7A
448: D2:00FF0000 D6:00000000 A2:CCCCCCCC A6:CCCCCCCC
449: D3:CCCCCCCC D7:00000003 A3:CCCCCCCC A7:00001FD8
450: */
451: bool vr[16];
452:
1.1.1.9 root 453: for (int i = 0; i < countof(cpu->reg.R); i++) {
454: vr[i] = (cpu->reg.R[i] != prev.R[i]);
1.1 root 455: }
456:
457: // 1行目
1.1.1.8 root 458: fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s ",
1.1.1.9 root 459: BOLDIF(vr[ 0]), 0, cpu->reg.R[ 0], NORM,
460: BOLDIF(vr[ 4]), 4, cpu->reg.R[ 4], NORM,
461: BOLDIF(vr[ 8]), 0, cpu->reg.R[ 8], NORM,
462: BOLDIF(vr[12]), 4, cpu->reg.R[12], NORM);
1.1 root 463:
464: // 1行目 SR
1.1.1.9 root 465: uint16 sr = cpu->GetSR();
466: uint16 prevsr = prev.GetSR();
1.1 root 467: // SR は上位バイトと下位バイトが変化したくらいでいいか?
1.1.1.8 root 468: fprintf(cons, " SR:%s%02x%s%s%02x%s",
1.1 root 469: BOLDIF((sr & 0xff00) != (prevsr & 0xff00)),
470: sr >> 8,
471: NORM,
472: BOLDIF((sr & 0x00ff) != (prevsr & 0x00ff)),
473: sr & 0xff,
474: NORM);
1.1.1.8 root 475: fprintf(cons, "(%c I=%d %c%c%c%c%c)\n",
1.1 root 476: (sr & 0x2000) ? 'S' : '-',
477: (sr >> 8) & 7,
1.1.1.9 root 478: (sr & M68K::CCR_X) ? 'X' : '-',
479: (sr & M68K::CCR_N) ? 'N' : '-',
480: (sr & M68K::CCR_Z) ? 'Z' : '-',
481: (sr & M68K::CCR_V) ? 'V' : '-',
482: (sr & M68K::CCR_C) ? 'C' : '-');
1.1 root 483:
484: // 2行目
1.1.1.8 root 485: fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n",
1.1.1.9 root 486: BOLDIF(vr[ 1]), 1, cpu->reg.R[ 1], NORM,
487: BOLDIF(vr[ 5]), 5, cpu->reg.R[ 5], NORM,
488: BOLDIF(vr[ 9]), 1, cpu->reg.R[ 9], NORM,
489: BOLDIF(vr[13]), 5, cpu->reg.R[13], NORM);
1.1 root 490:
491: // 3行目
1.1.1.8 root 492: fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n",
1.1.1.9 root 493: BOLDIF(vr[ 2]), 2, cpu->reg.R[ 2], NORM,
494: BOLDIF(vr[ 6]), 6, cpu->reg.R[ 6], NORM,
495: BOLDIF(vr[10]), 2, cpu->reg.R[10], NORM,
496: BOLDIF(vr[14]), 6, cpu->reg.R[14], NORM);
1.1 root 497:
498: // 4行目
1.1.1.8 root 499: fprintf(cons, "%sD%d:%08x%s %sD%d:%08x%s %sA%d:%08x%s %sA%d:%08x%s\n",
1.1.1.9 root 500: BOLDIF(vr[ 3]), 3, cpu->reg.R[ 3], NORM,
501: BOLDIF(vr[ 7]), 7, cpu->reg.R[ 7], NORM,
502: BOLDIF(vr[11]), 3, cpu->reg.R[11], NORM,
503: BOLDIF(vr[15]), 7, cpu->reg.R[15], NORM);
1.1 root 504: }
505:
506: // FPU レジスタ表示
507: void
1.1.1.8 root 508: DebuggerMD_m680x0::ShowRegFPU(FILE *cons)
1.1 root 509: {
510: /*
1.1.1.11 root 511: FP0:0000_12345678_12345678 = -0.1234567890123456789)
512: FPCR: 1234 BS,SN,OE,OF,UF,DZ,X2,X1 RP=.X RM=Minus
513: FPSR: 12345678 N Z Inf NAN Q=$xx BS,SN,OE,OF,UF,DZ,X2,X1 AV AO AU AZ AX
514: FPIAR:12345678
1.1 root 515: */
516:
517: uint32 fpcr, fpsr, fpiar;
518: uint32 ppcr, ppsr, ppiar;
519: static const char * const rmstr[] = {
520: "Near",
521: "Zero",
522: "Minus",
523: "Plus",
524: };
525:
526: fpcr = cpu->reg.fpframe.fpf_fpcr;
527: fpsr = cpu->reg.fpframe.fpf_fpsr;
528: fpiar = cpu->reg.fpframe.fpf_fpiar;
529: ppcr = prev.fpframe.fpf_fpcr;
530: ppsr = prev.fpframe.fpf_fpsr;
531: ppiar = prev.fpframe.fpf_fpiar;
532:
1.1.1.11 root 533: for (uint n = 0; n < 8; n++) {
534: uint32 *c_ = cpu->reg.fpframe.fpf_regs + (n) * 3;
535: uint32 *p_ = prev.fpframe.fpf_regs + (n) * 3;
536: bool d = (c_[0] ^ p_[0]) | (c_[1] ^ p_[1]) | (c_[2] ^ p_[2]);
537: fprintf(cons, "%sFP%u:%04x_%08x_%08x%s = %s\n",
538: BOLDIF(d), n, c_[0] >> 16, c_[1], c_[2], NORM,
539: ExtToStr(c_).c_str());
540: }
1.1 root 541:
1.1.1.11 root 542: fprintf(cons, "%sFPCR: %04x%s%20s",
543: BOLDIF(fpcr != ppcr), fpcr, NORM, "");
544: fprintf(cons, "%s %s %s %s %s %s %s %s ",
1.1 root 545: (fpcr & 0x8000) ? "BS" : "--",
546: (fpcr & 0x4000) ? "SN" : "--",
1.1.1.11 root 547: (fpcr & 0x2000) ? "OE" : "--",
548: (fpcr & 0x1000) ? "OF" : "--",
1.1 root 549: (fpcr & 0x0800) ? "UF" : "--",
550: (fpcr & 0x0400) ? "DZ" : "--",
1.1.1.11 root 551: (fpcr & 0x0200) ? "X2" : "--",
552: (fpcr & 0x0100) ? "X1" : "--");
553: fprintf(cons, "RP=.%c RM=%s\n",
554: "XSD?"[(fpcr >> 6) & 3],
1.1 root 555: rmstr[(fpcr >> 4) & 3]);
556:
557: uint cc = fpsr >> 24;
1.1.1.11 root 558: fprintf(cons, "%sFPSR: %08x%s ", BOLDIF(fpsr != ppsr), fpsr, NORM);
559: fprintf(cons, "%c %c %s %s Q=$%02x ",
1.1 root 560: (cc & 0x08) ? 'N' : '-',
561: (cc & 0x04) ? 'Z' : '-',
562: (cc & 0x02) ? "Inf" : "---",
563: (cc & 0x01) ? "NAN" : "---",
564: (fpsr >> 16) & 0xff);
1.1.1.11 root 565: fprintf(cons, "%s %s %s %s %s %s %s %s ",
1.1 root 566: (fpsr & 0x8000) ? "BS" : "--",
567: (fpsr & 0x4000) ? "SN" : "--",
568: (fpsr & 0x2000) ? "OP" : "--",
569: (fpsr & 0x1000) ? "OV" : "--",
570: (fpsr & 0x0800) ? "UF" : "--",
571: (fpsr & 0x0400) ? "DZ" : "--",
572: (fpsr & 0x0200) ? "I2" : "--",
573: (fpsr & 0x0100) ? "I1" : "--");
1.1.1.11 root 574: fprintf(cons, "%s %s %s %s %s\n",
575: (fpsr & 0x80) ? "AV" : "--",
576: (fpsr & 0x40) ? "AO" : "--",
577: (fpsr & 0x20) ? "AU" : "--",
578: (fpsr & 0x10) ? "AZ" : "--",
579: (fpsr & 0x08) ? "AX" : "--");
1.1 root 580:
1.1.1.8 root 581: fprintf(cons, "%sFPIAR:%08x%s\n", BOLDIF(fpiar != ppiar), fpiar, NORM);
1.1 root 582: }
583:
1.1.1.11 root 584: // 68030 MMU レジスタ表示
1.1 root 585: void
1.1.1.11 root 586: DebuggerMD_m680x0::ShowRegMMU30(FILE *cons)
1.1 root 587: {
588: /*
589: SRP:00001111_22223333 TT0:00001111 TC:00001111 (---)
590: CRP:00001111_22223333 TT1:00001111 MMUSR: 0011 (
591: */
1.1.1.11 root 592: auto cpu68030 = dynamic_cast<MPU68030Device *>(cpu);
1.1 root 593: uint64 srp, osrp;
594: uint64 crp, ocrp;
595: uint32 tt0, ott0;
596: uint32 tt1, ott1;
597: uint32 tc, otc;
598: uint16 sr, osr;
599: bool p;
600: bool t;
601: bool c;
602:
1.1.1.11 root 603: srp = cpu68030->GetSRP();
604: crp = cpu68030->GetCRP();
605: tt0 = cpu68030->GetTT(0);
606: tt1 = cpu68030->GetTT(1);
607: tc = cpu68030->GetTC();
608: sr = cpu68030->GetMMUSR();
1.1 root 609:
610: osrp = prev.srp.q;
611: ocrp = prev.crp.q;
612: ott0 = prev.tt[0];
613: ott1 = prev.tt[1];
614: otc = prev.tc;
615: osr = prev.mmusr;
616:
617: // 1行目
618: p = (srp != osrp);
619: t = (tt0 != ott0);
620: c = (tc != otc);
1.1.1.8 root 621: fprintf(cons, "%sSRP:%08x_%08x%s %sTT0:%08x%s(%c%c%c)",
1.1 root 622: BOLDIF(p), (uint32)(srp >> 32), (uint32)srp, NORM,
623: BOLDIF(t), tt0, NORM,
624: (tt0 & m68030TT::E) ? 'E' : '-',
625: (tt0 & m68030TT::CI) ? 'C' : '-',
626: (tt0 & m68030TT::RWM) ? '-' : ((tt0 & m68030TT::RW) ? 'R' : 'W'));
1.1.1.8 root 627: fprintf(cons, " %sTC:%08x%s(%c%c%c)\n",
1.1 root 628: BOLDIF(c), tc, NORM,
629: (tc & m68030TC::TC_E) ? 'E' : '-',
630: (tc & m68030TC::TC_SRE) ? 'S' : '-',
631: (tc & m68030TC::TC_FCL) ? 'F' : '-');
632:
633: // 2行目
634: p = (crp != ocrp);
635: t = (tt1 != ott1);
636: c = (sr != osr);
1.1.1.8 root 637: fprintf(cons, "%sCRP:%08x_%08x%s %sTT1:%08x%s(%c%c%c)",
1.1 root 638: BOLDIF(p), uint32(crp >> 32), (uint32)crp, NORM,
639: BOLDIF(t), tt1, NORM,
640: (tt1 & m68030TT::E) ? 'E' : '-',
641: (tt1 & m68030TT::CI) ? 'C' : '-',
642: (tt1 & m68030TT::RWM) ? '-' : ((tt1 & m68030TT::RW) ? 'R' : 'W'));
1.1.1.8 root 643: fprintf(cons, " %sMMUSR: %04x%s(%c%c%c%c%c%c%c N=%d)\n",
1.1 root 644: BOLDIF(c), sr, NORM,
645: (sr & m68030MMUSR::B) ? 'B' : '-',
646: (sr & m68030MMUSR::L) ? 'L' : '-',
647: (sr & m68030MMUSR::S) ? 'S' : '-',
648: (sr & m68030MMUSR::W) ? 'W' : '-',
649: (sr & m68030MMUSR::I) ? 'I' : '-',
650: (sr & m68030MMUSR::M) ? 'M' : '-',
651: (sr & m68030MMUSR::T) ? 'T' : '-',
652: (sr & m68030MMUSR::N));
653: }
654:
1.1.1.11 root 655: // 68040 MMU レジスタ表示
656: void
657: DebuggerMD_m680x0::ShowRegMMU40(FILE *cons)
658: {
659: fprintf(cons, "Not implemented\n");
660: }
661:
1.1 root 662: // ATC を表示
663: void
1.1.1.8 root 664: DebuggerMD_m680x0::ShowRegATC()
1.1 root 665: {
1.1.1.8 root 666: parent->ShowMonitor(gMonitorManager->Get(ID_MONITOR_MPUATC));
1.1 root 667: }
668:
669: // その他のレジスタを表示
670: void
1.1.1.8 root 671: DebuggerMD_m680x0::ShowRegOther()
1.1 root 672: {
673: TextScreen s(80, 2);
674:
675: // 0 1 2 3 4 5 6
676: // 012345678901234567890123456789012345678901234567890123456789012345
677: // CACR:01234567 VBR:01234567 USP:01234567
678: // CAAR:01234567 SFC:0 DFC:0 MSP:01234567
679:
680: #define EM(name) ((cpu->reg.name != prev.name) ? TA::Em : TA::Normal)
681: s.Print(0, 0, EM(cacr), "CACR:%08x", cpu->reg.cacr);
682: s.Print(0, 1, EM(caar), "CAAR:%08x", cpu->reg.caar);
683:
684: s.Print(15, 0, EM(vbr), "VBR:%08x", cpu->reg.vbr);
1.1.1.10 root 685: s.Print(15, 1, EM(sfc), "SFC:%d", cpu->reg.GetSFC());
686: s.Print(22, 1, EM(dfc), "DFC:%d", cpu->reg.GetDFC());
1.1 root 687:
688: // スタック欄はモードによって表示を変える。
689: // ユーザ 割り込み マスタ
690: // 1行目 ISP USP USP
691: // 2行目 MSP MSP ISP
1.1.1.9 root 692: if (!cpu->IsSuper()) {
1.1 root 693: s.Print(29, 0, EM(isp), "ISP:%08x", cpu->reg.isp);
694: } else {
695: s.Print(29, 0, EM(usp), "USP:%08x", cpu->reg.usp);
696: }
1.1.1.9 root 697: if (!cpu->IsMaster()) {
1.1 root 698: s.Print(29, 1, EM(msp), "MSP:%08x", cpu->reg.msp);
699: } else {
700: s.Print(29, 1, EM(isp), "ISP:%08x", cpu->reg.isp);
701: }
702:
1.1.1.2 root 703: parent->ShowTextScreen(s);
1.1 root 704: }
705:
1.1.1.9 root 706: // オンライン用逆アセンブル
707: std::string
708: DebuggerMD_m680x0::Disassemble(DebuggerMemoryStream& mem)
1.1 root 709: {
1.1.1.9 root 710: m680x0disasm dis;
711: if (dis.Exec(&mem) == false) {
712: return "dis.Exec() failed";
713: }
714:
715: // dis.bin は uint8 列なのでこれを uint16 列に変換
716: std::vector<uint16> words;
717: for (int i = 0; i < dis.bin.size(); i += 2) {
718: words.push_back((dis.bin[i] << 8) | dis.bin[i + 1]);
1.1 root 719: }
720:
721: // 16進ダンプ
722: std::string dumpbuf;
1.1.1.9 root 723: for (auto w : words) {
724: dumpbuf += string_format("%04x ", w);
1.1 root 725: }
726:
727: // ダンプは5ワード分 (越えたら知らん)
1.1.1.9 root 728: std::string str = string_format("%-25s", dumpbuf.c_str());
729: // ニーモニック
730: str += dis.text;
731: // (あれば) 条件判断
732: str += CondStr(words);
1.1 root 733:
1.1.1.9 root 734: return str;
1.1 root 735: }
1.1.1.12 root 736:
737: // 命令ニーモニックに対するバイナリを文字列形式で返す。
738: // 対応しない場合は "" を返す。cmd_bi 用。
739: std::string
740: DebuggerMD_m680x0::ParseInst(const std::string& inst) const
741: {
1.1.1.13! root 742: if (inst == "frestore") return "f340:ffc0";
! 743: if (inst == "fsave") return "f300:ffc0";
! 744: if (inst == "nop") return "4e71";
! 745: if (inst == "ptestr") return "f0008200:ffc0e200";
! 746: if (inst == "ptestw") return "f0008000:ffc0e200";
1.1.1.12 root 747: if (inst == "rte") return "4e73";
748:
749: return "";
750: }
1.1.1.13! root 751:
! 752: // 例外フレーム処理用の便利クラス。
! 753: // 例外フレーム内は基本ワード単位なのに、仕様書のオフセットはバイト単位
! 754: // なのでこういうヘルパーがないと事故が多発する。
! 755: class StackData
! 756: {
! 757: public:
! 758: StackData(DebuggerMemoryStream& mem_)
! 759: : mem(mem_)
! 760: {
! 761: }
! 762:
! 763: // 合計が words [ワード] になるまで追加で読み込む。
! 764: void ReadWordUntil(size_t words);
! 765: // 合計が bytes (偶数) [バイト] になるまで追加で読み込む。
! 766: void ReadByteUntil(size_t bytes);
! 767:
! 768: // 改行込みで出力。
! 769: void Print(FILE *out, size_t byteoffset, uint bytes) const;
! 770: void Print(FILE *out, size_t byteoffset, uint bytes,
! 771: const char *, ...) const __printflike(5, 6);
! 772:
! 773: // 共通の表示用文字列を作成して返す。戻り値は改行なしの文字列。
! 774: std::string Format(size_t byteoffset, uint bytes) const;
! 775: std::string Format(size_t byteoffset, uint bytes,
! 776: const char *, ...) const __printflike(4, 5);
! 777:
! 778: // byteoffset の位置のデータを表示用文字列にする。
! 779: std::string FormatWord(size_t byteoffset) const;
! 780: std::string FormatLong(size_t byteoffset) const;
! 781:
! 782: // byteoffset の位置からのワードデータを返す。バスエラーなら -1。
! 783: uint32 Word(size_t byteoffset) const;
! 784: // byteoffset の位置からのロングワードを返す。バスエラーなら (uint64)-1。
! 785: uint64 Long(size_t byteoffset) const;
! 786:
! 787: // データサイズをバイト単位で返す。
! 788: size_t bytesize() const noexcept { return framebuf.size() * 2; }
! 789:
! 790: private:
! 791: std::string FormatV(size_t byteoffset, uint bytes,
! 792: const char *, va_list) const __printflike(4, 0);
! 793:
! 794: DebuggerMemoryStream mem;
! 795: std::vector<uint32> framebuf {};
! 796: };
! 797:
! 798: void
! 799: StackData::ReadWordUntil(size_t words)
! 800: {
! 801: while (framebuf.size() < words) {
! 802: framebuf.push_back(mem.Read(2));
! 803: }
! 804: }
! 805:
! 806: void
! 807: StackData::ReadByteUntil(size_t bytes)
! 808: {
! 809: assert((bytes % 1) == 0);
! 810: size_t words = bytes / 2;
! 811: while (framebuf.size() < words) {
! 812: framebuf.push_back(mem.Read(2));
! 813: }
! 814: }
! 815:
! 816: // 改行込みで表示する。bytes は 2, 4, 16 のみ。追加情報なし。
! 817: void
! 818: StackData::Print(FILE *out, size_t byteoffset, uint bytes) const
! 819: {
! 820: fprintf(out, "%s\n", Format(byteoffset, bytes).c_str());
! 821: }
! 822:
! 823: // 改行込みで表示する。bytes は 2, 4, 16 のみ。
! 824: void
! 825: StackData::Print(FILE *out, size_t byteoffset, uint bytes,
! 826: const char *fmt, ...) const
! 827: {
! 828: va_list ap;
! 829:
! 830: assert(bytes == 2 || bytes == 4 || bytes == 16);
! 831:
! 832: va_start(ap, fmt);
! 833: fprintf(out, "%s\n", FormatV(byteoffset, bytes, fmt, ap).c_str());
! 834: va_end(ap);
! 835: }
! 836:
! 837: // 共通の表示用文字列を作成して返す。戻り値は改行なしの文字列。
! 838: std::string
! 839: StackData::Format(size_t byteoffset, uint bytes) const
! 840: {
! 841: std::string s = string_format("+$%02x: ", (uint)byteoffset);
! 842: if (bytes == 2) {
! 843: s += FormatWord(byteoffset);
! 844: } else if (bytes == 4) {
! 845: s += FormatLong(byteoffset);
! 846: } else {
! 847: s += FormatLong(byteoffset);
! 848: s += ' ';
! 849: s += FormatLong(byteoffset + 4);
! 850: s += ' ';
! 851: s += FormatLong(byteoffset + 8);
! 852: s += ' ';
! 853: s += FormatLong(byteoffset + 12);
! 854: }
! 855:
! 856: return s;
! 857: }
! 858:
! 859: // 共通の表示用文字列を作成して返す。戻り値は改行なしの文字列。
! 860: std::string
! 861: StackData::Format(size_t byteoffset, uint bytes, const char *fmt, ...) const
! 862: {
! 863: std::string str;
! 864: va_list ap;
! 865:
! 866: va_start(ap, fmt);
! 867: str = FormatV(byteoffset, bytes, fmt, ap);
! 868: va_end(ap);
! 869:
! 870: return str;
! 871: }
! 872:
! 873: // 共通の表示用文字列を作成して返す。戻り値は改行なしの文字列。
! 874: std::string
! 875: StackData::FormatV(size_t byteoffset, uint bytes,
! 876: const char *fmt, va_list ap) const
! 877: {
! 878: std::string s = Format(byteoffset, bytes);
! 879:
! 880: char text[128];
! 881: vsnprintf(text, sizeof(text), fmt, ap);
! 882: if (text[0]) {
! 883: if (bytes == 2) {
! 884: s += " ";
! 885: }
! 886: s += string_format(" : %s", text);
! 887: }
! 888: return s;
! 889: }
! 890:
! 891: // byteoffset の位置からのワードデータを表示用文字列にする。
! 892: std::string
! 893: StackData::FormatWord(size_t byteoffset) const
! 894: {
! 895: uint32 data = Word(byteoffset);
! 896: if ((int32)data < 0) {
! 897: return "----";
! 898: } else {
! 899: char buf[16];
! 900: snprintf(buf, sizeof(buf), "%04x", data);
! 901: return buf;
! 902: }
! 903: }
! 904:
! 905: // byteoffset の位置からのロングワードデータを表示用文字列にする。
! 906: std::string
! 907: StackData::FormatLong(size_t byteoffset) const
! 908: {
! 909: uint64 data = Long(byteoffset);
! 910: if ((int64)data < 0) {
! 911: return "--------";
! 912: } else {
! 913: char buf[16];
! 914: snprintf(buf, sizeof(buf), "%08x", (uint32)data);
! 915: return buf;
! 916: }
! 917: }
! 918:
! 919: uint32
! 920: StackData::Word(size_t byteoffset) const
! 921: {
! 922: size_t wordoffset = byteoffset / 2;
! 923: assert(wordoffset < framebuf.size());
! 924: return framebuf[wordoffset];
! 925: }
! 926:
! 927: uint64
! 928: StackData::Long(size_t byteoffset) const
! 929: {
! 930: uint32 hi = Word(byteoffset);
! 931: uint32 lo = Word(byteoffset + 2);
! 932: if ((int32)hi < 0 || (int32)lo < 0) {
! 933: return (uint64)-1;
! 934: }
! 935: return (hi << 16) | lo;
! 936: }
! 937:
! 938: // 例外フレームを表示する。
! 939: void
! 940: DebuggerMD_m680x0::PrintExceptionFrame(FILE *out, busaddr addr)
! 941: {
! 942: DebuggerMemoryStream mem(this, addr);
! 943: StackData frame(mem);
! 944:
! 945: fprintf(out, "Exception stack at $%08x\n", addr.Addr());
! 946:
! 947: frame.ReadWordUntil(4);
! 948:
! 949: // ここからフレーム別。
! 950: uint32 format = frame.Word(6) >> 12;
! 951: switch (format) {
! 952: case 0x0: // 034 Four word stack
! 953: PrintExceptionFrame0(out, frame);
! 954: break;
! 955:
! 956: case 0x1: // 034 Throwaway four word stack
! 957: PrintExceptionFrameCommon(out, frame, true);
! 958: break;
! 959:
! 960: case 0x2: // 034 Six word stack
! 961: PrintExceptionFrame2(out, frame);
! 962: break;
! 963:
! 964: case 0x3: // --4 Floating-point post-instruction stack
! 965: PrintExceptionFrame3(out, frame);
! 966: break;
! 967:
! 968: case 0x4: // --L Eight-word stack
! 969: PrintExceptionFrame4(out, frame);
! 970: break;
! 971:
! 972: case 0x7: // --4 Access error stack
! 973: PrintExceptionFrame7(out, frame);
! 974: break;
! 975:
! 976: case 0xb: // -3- Long bus cycle stack
! 977: PrintExceptionFrameB(out, frame);
! 978: break;
! 979:
! 980: case 9: // -3- Coprocessor mid-instruction Stack
! 981: case 0xa: // -3- Short bus cycle stack (nono は生成しない)
! 982: default:
! 983: fprintf(out, "Format $%x not supported\n", format);
! 984: break;
! 985: }
! 986: }
! 987:
! 988: // 共通の4ワード目までを表示する。
! 989: bool
! 990: DebuggerMD_m680x0::PrintExceptionFrameCommon(FILE *out,
! 991: const StackData& frame, bool pc_is_next)
! 992: {
! 993: // $06: Format|Vector
! 994: uint32 format_vector = frame.Word(6);
! 995: uint32 format = format_vector >> 12;
! 996: std::string s6;
! 997: if ((int32)format_vector < 0) {
! 998: s6 += "Format+Vector";
! 999: } else {
! 1000: uint32 vector = (format_vector >> 2) & 0xff;
! 1001: s6 += string_format("Format=$%x Vector=$%02x", format, vector);
! 1002:
! 1003: // ベクタ番号からベクタ名を引いてみる。
! 1004: // Vector=$b は本来 Format=$0 で F ライン例外だが、
! 1005: // Format=$2 Vector=$b なら 68040 の未実装 FP 命令例外なので区別する。
! 1006: const char *exname = NULL;
! 1007: if (format == 2 && vector == 0x0b) {
! 1008: exname = "Unimplemented FP Instruction";
! 1009: } else {
! 1010: auto vectortable = GetVectorTable();
! 1011: exname = vectortable->GetExceptionName(vector);
! 1012: }
! 1013: if (exname) {
! 1014: s6 += " \"";
! 1015: s6 += exname;
! 1016: s6 += '\"';
! 1017: }
! 1018: }
! 1019:
! 1020: frame.Print(out, 0, 2, "SR");
! 1021: frame.Print(out, 2, 4, "%sPC", pc_is_next ? "Next ": "");
! 1022: frame.Print(out, 6, 2, "%s", s6.c_str());
! 1023:
! 1024: // ここがバスエラーならもう出来ることはない。
! 1025: if ((int32)format_vector < 0) {
! 1026: return false;
! 1027: }
! 1028: return true;
! 1029: }
! 1030:
! 1031: void
! 1032: DebuggerMD_m680x0::PrintExceptionFrame0(FILE *out, StackData& frame)
! 1033: {
! 1034: // Format$0 の PC は
! 1035: // 種類 PC
! 1036: // ----
! 1037: // ・割り込み 次の命令
! 1038: // ・TRAP#N 次の命令
! 1039: // ・フォーマットエラー 当該命令(RTE/FRESTORE)
! 1040: // ・不当命令 当該命令
! 1041: // ・A/F ライン命令 当該命令
! 1042: // ・特権違反 当該命令
! 1043:
! 1044: bool next;
! 1045: uint vector = (frame.Word(0x06) & 0xfff) >> 2;
! 1046: switch (vector) {
! 1047: case M68K::EXCEP_FORMAT:
! 1048: case M68K::EXCEP_ILLEGAL:
! 1049: case M68K::EXCEP_ALINE:
! 1050: case M68K::EXCEP_FLINE:
! 1051: case M68K::EXCEP_PRIV:
! 1052: next = false;
! 1053: break;
! 1054: default:
! 1055: next = true;
! 1056: break;
! 1057: }
! 1058: PrintExceptionFrameCommon(out, frame, next);
! 1059: }
! 1060:
! 1061: void
! 1062: DebuggerMD_m680x0::PrintExceptionFrame2(FILE *out, StackData& frame)
! 1063: {
! 1064: // Format$2 の PC と Address は
! 1065: // 種類 PC Address
! 1066: // ---- -- -------
! 1067: // ・CHK/CHK2/TRAP*/ 次の命令 例外を起こした命令
! 1068: // FTRAPcc/Trace/ZeroDiv
! 1069: // ・MMU 構成例外 次の命令 例外を起こした命令
! 1070: // ・040 未実装FP命令 次の命令 FPが計算したEA
! 1071: // ・040 アドレスエラー 当該命令 参照アドレス-1
! 1072:
! 1073: bool next;
! 1074: const char *addr;
! 1075: uint vector = (frame.Word(0x06) & 0xfff) >> 2;
! 1076: switch (vector) {
! 1077: case M68K::EXCEP_ZERODIV:
! 1078: case M68K::EXCEP_CHK:
! 1079: case M68K::EXCEP_TRAPV:
! 1080: case M68K::EXCEP_TRACE:
! 1081: case M68K::EXCEP_MMU_CONFIG:
! 1082: next = true;
! 1083: addr = "Caused instruction address";
! 1084: break;
! 1085:
! 1086: case M68K::EXCEP_FLINE: // これは 040 の EXCEP_FP_UNIMPL
! 1087: next = true;
! 1088: addr = "Calculated EA";
! 1089: break;
! 1090:
! 1091: case M68K::EXCEP_ADDRERR:
! 1092: next = false;
! 1093: addr = "Reference Address - 1";
! 1094: break;
! 1095:
! 1096: default:
! 1097: next = false;
! 1098: addr = "?";
! 1099: break;
! 1100: }
! 1101:
! 1102: frame.ReadWordUntil(6);
! 1103: if (PrintExceptionFrameCommon(out, frame, next) == false) {
! 1104: return;
! 1105: }
! 1106: frame.Print(out, 0x08, 4, "%s", addr);
! 1107: }
! 1108:
! 1109: void
! 1110: DebuggerMD_m680x0::PrintExceptionFrame3(FILE *out, StackData& frame)
! 1111: {
! 1112: frame.ReadWordUntil(6);
! 1113: if (PrintExceptionFrameCommon(out, frame, true) == false) {
! 1114: return;
! 1115: }
! 1116: frame.Print(out, 0x08, 4, "Effective Address");
! 1117: }
! 1118:
! 1119: void
! 1120: DebuggerMD_m680x0::PrintExceptionFrame4(FILE *out, StackData& frame)
! 1121: {
! 1122: frame.ReadWordUntil(8);
! 1123: if (PrintExceptionFrameCommon(out, frame, true) == false) {
! 1124: return;
! 1125: }
! 1126: frame.Print(out, 0x08, 4, "Effective Address");
! 1127: frame.Print(out, 0x0c, 4, "PC of Faulted Instruction");
! 1128: }
! 1129:
! 1130: void
! 1131: DebuggerMD_m680x0::PrintExceptionFrame7(FILE *out, StackData& frame)
! 1132: {
! 1133: static const char * const sizestr[] = {
! 1134: ".L",
! 1135: ".B",
! 1136: ".W",
! 1137: "Line",
! 1138: };
! 1139:
! 1140: frame.ReadWordUntil(30);
! 1141: if (PrintExceptionFrameCommon(out, frame, true) == false) {
! 1142: return;
! 1143: }
! 1144: frame.Print(out, 0x08, 4, "Effective Address");
! 1145:
! 1146: // SSW
! 1147: uint16 ssw = frame.Word(0x0c);
! 1148: frame.Print(out, 0x0c, 2,
! 1149: "SSW (%s %s %s %s %s %s %s RW=%c size=%s TT=%u TM=%u)",
! 1150: ((ssw & M68040::SSW_CP) ? "CP" : "--"),
! 1151: ((ssw & M68040::SSW_CU) ? "CU" : "--"),
! 1152: ((ssw & M68040::SSW_CT) ? "CT" : "--"),
! 1153: ((ssw & M68040::SSW_CM) ? "CM" : "--"),
! 1154: ((ssw & M68040::SSW_MA) ? "MA" : "--"),
! 1155: ((ssw & M68040::SSW_ATC) ? "ATC" : "---"),
! 1156: ((ssw & M68040::SSW_LK) ? "LK" : "--"),
! 1157: ((ssw & M68040::SSW_RW) ? 'R' : 'W'),
! 1158: sizestr[(ssw >> 5) & 3],
! 1159: ((ssw >> 3) & 3),
! 1160: (ssw & 7));
! 1161:
! 1162: // WB[321]S
! 1163: for (uint i = 0; i < 3; i++) {
! 1164: size_t off = 0x0e + i * 2;
! 1165: uint16 wbs = frame.Word(off);
! 1166: std::string stbuf;
! 1167: if ((wbs & 0x80)) {
! 1168: stbuf = "Valid";
! 1169: stbuf += string_format(" size=%s", sizestr[(wbs >> 5) & 3]);
! 1170: stbuf += string_format(" TT=%u", (wbs >> 3) & 3);
! 1171: stbuf += string_format(" TM=%u", wbs & 7);
! 1172: } else {
! 1173: stbuf = "no pending";
! 1174: }
! 1175: frame.Print(out, off, 2, "WB%u Status (%s)", 3 - i, stbuf.c_str());
! 1176: }
! 1177:
! 1178: frame.Print(out, 0x14, 4, "Fault Address");
! 1179: frame.Print(out, 0x18, 4, "WB3 Address");
! 1180: frame.Print(out, 0x1c, 4, "WB3 Data");
! 1181: frame.Print(out, 0x20, 4, "WB2 Address");
! 1182: frame.Print(out, 0x24, 4, "WB2 Data");
! 1183: frame.Print(out, 0x28, 4, "WB1 Address");
! 1184: frame.Print(out, 0x2c, 4, "WB1 Data / PushData 0");
! 1185: frame.Print(out, 0x30, 4, "Push Data 1");
! 1186: frame.Print(out, 0x34, 4, "Push Data 2");
! 1187: frame.Print(out, 0x38, 4, "Push Data 3");
! 1188: }
! 1189:
! 1190: void
! 1191: DebuggerMD_m680x0::PrintExceptionFrameB(FILE *out, StackData& frame)
! 1192: {
! 1193: frame.ReadWordUntil(46);
! 1194: if (PrintExceptionFrameCommon(out, frame, false) == false) {
! 1195: return;
! 1196: }
! 1197: frame.Print(out, 0x08, 2); // internal
! 1198:
! 1199: // SSW
! 1200: uint16 ssw = frame.Word(0x0a);
! 1201: frame.Print(out, 0x0a, 2,
! 1202: "SSW (%s %s %s %s %s %s RW=%c size=%c FC=%u)",
! 1203: ((ssw & M68030::SSW_FC) ? "FC" : "--"),
! 1204: ((ssw & M68030::SSW_FB) ? "FB" : "--"),
! 1205: ((ssw & M68030::SSW_RC) ? "RC" : "--"),
! 1206: ((ssw & M68030::SSW_RB) ? "RB" : "--"),
! 1207: ((ssw & M68030::SSW_DF) ? "DF" : "--"),
! 1208: ((ssw & M68030::SSW_RM) ? "RM" : "--"),
! 1209: ((ssw & M68030::SSW_RW) ? 'R' : 'W'),
! 1210: "LBW3"[(ssw >> 4) & 3],
! 1211: (ssw & 7));
! 1212:
! 1213: frame.Print(out, 0x0c, 2, "Instruction Pipe Stage C");
! 1214: frame.Print(out, 0x0e, 2, "Instruction Pipe Stage B");
! 1215: frame.Print(out, 0x10, 4, "Data Cycle Fault Address");
! 1216: frame.Print(out, 0x14, 4);
! 1217: frame.Print(out, 0x18, 4, "Data Output Buffer");
! 1218: frame.Print(out, 0x1c, 4);
! 1219: frame.Print(out, 0x20, 4);
! 1220: frame.Print(out, 0x24, 4, "Stage B Address");
! 1221: frame.Print(out, 0x28, 4);
! 1222: frame.Print(out, 0x2c, 4, "Data Input Buffer");
! 1223:
! 1224: // 残りは内部データなのでまとめる。
! 1225: frame.Print(out, 0x30, 4, "(internal registers)");
! 1226: // +$36 にちょっと構造があるけどとりあえず無視。
! 1227: for (uint i = 0x34; i < frame.bytesize(); i += 4) {
! 1228: if (i == 0x34 || i == 0x48) {
! 1229: fprintf(out, "+$%02x:", i);
! 1230: }
! 1231: fprintf(out, " %s", frame.FormatLong(i).c_str());
! 1232: if (i == 0x44) {
! 1233: fprintf(out, "\n");
! 1234: }
! 1235: }
! 1236: fprintf(out, "\n");
! 1237: }
! 1238:
! 1239: void
! 1240: DebuggerMD_m680x0::PrintFPStateFrame(FILE *out, busaddr addr)
! 1241: {
! 1242: DebuggerMemoryStream mem(this, addr);
! 1243: StackData frame(mem);
! 1244:
! 1245: fprintf(out, "Floating-point state frame at $%08x\n", addr.Addr());
! 1246:
! 1247: frame.ReadByteUntil(4);
! 1248:
! 1249: // 第1ワードはバージョンと後続の長さ。
! 1250: uint64 w00 = frame.Long(0x00);
! 1251: uint32 ver = (w00 >> 24) & 0xff;
! 1252: uint32 len = (w00 >> 16) & 0xff;
! 1253: // VER LEN Name
! 1254: // $00 ANY Null State Frame
! 1255: // ver $18 68881 IDLE
! 1256: // ver $38 68882 IDLE
! 1257: // ver $B4 68881 BUSY
! 1258: // ver $D4 68882 BUSY
! 1259: // $41 $00 68040 IDLE
! 1260: // $41 $30 68040 Unimplemented Instruction
! 1261: // $41 $60 68040 BUSY
! 1262: if (ver == 0x00) {
! 1263: frame.Print(out, 0x00, 4, "Null State Frame");
! 1264: } else {
! 1265: // NULL フレーム以外は残り len バイトある。
! 1266: frame.ReadByteUntil(len + 4);
! 1267:
! 1268: if (ver == 0x41) {
! 1269: switch (len) {
! 1270: case 0x00:
! 1271: frame.Print(out, 0x00, 4, "68040 Idle State Frame");
! 1272: break;
! 1273: case 0x30:
! 1274: frame.Print(out, 0x00, 4,
! 1275: "68040 Unimplemented Instruction State Frame");
! 1276: PrintFPFrame68040Unimpl(out, frame, 0);
! 1277: break;
! 1278: case 0x60:
! 1279: frame.Print(out, 0x00, 4, "68040 Busy State Frame");
! 1280: PrintFPFrame68040Busy(out, frame);
! 1281: break;
! 1282: default:
! 1283: frame.Print(out, 0x00, 4, "68040 Unknown State Frame?");
! 1284: break;
! 1285: }
! 1286: } else {
! 1287: switch (len) {
! 1288: case 0x18:
! 1289: frame.Print(out, 0x00, 4, "68881 Idle State Frame");
! 1290: PrintFPFrame6888xIdle(out, frame, len);
! 1291: break;
! 1292: case 0x38:
! 1293: frame.Print(out, 0x00, 4, "68882 Idle State Frame");
! 1294: PrintFPFrame6888xIdle(out, frame, len);
! 1295: break;
! 1296: case 0xb4:
! 1297: frame.Print(out, 0x00, 4, "68881 Busy State Frame");
! 1298: PrintFPFrame6888xBusy(out, frame, len);
! 1299: break;
! 1300: case 0xd4:
! 1301: frame.Print(out, 0x00, 4, "68882 Busy State Frame");
! 1302: PrintFPFrame6888xBusy(out, frame, len);
! 1303: break;
! 1304: default:
! 1305: frame.Print(out, 0x00, 4, "Unknown State Frame?");
! 1306: break;
! 1307: }
! 1308: }
! 1309: }
! 1310: }
! 1311:
! 1312: void
! 1313: DebuggerMD_m680x0::PrintFPFrame6888xIdle(FILE *out, StackData& frame,
! 1314: uint32 len)
! 1315: {
! 1316: bool is68882 = (len == 0x38);
! 1317:
! 1318: frame.Print(out, 0x04, 2, "Command/Condition Register");
! 1319: frame.Print(out, 0x06, 2);
! 1320: uint32 pos = 0x08;
! 1321: if (is68882) {
! 1322: for (; pos < 0x28; pos += 16) {
! 1323: frame.Print(out, pos, 16, "(internal register)");
! 1324: }
! 1325: }
! 1326: for (uint i = 0; i < 12; i += 4) {
! 1327: frame.Print(out, pos, 4, "Exceptional Operand");
! 1328: pos += 4;
! 1329: }
! 1330: frame.Print(out, pos, 4, "Operand Register");
! 1331: pos += 4;
! 1332: frame.Print(out, pos, 4, "BIU Flags");
! 1333: }
! 1334:
! 1335: void
! 1336: DebuggerMD_m680x0::PrintFPFrame6888xBusy(FILE *out, StackData& frame,
! 1337: uint32 len)
! 1338: {
! 1339: uint pos = 4;
! 1340: uint cnt = len / 16;
! 1341: for (uint i = 0; i < cnt; i++) {
! 1342: frame.Print(out, pos, 16, "(internal register)");
! 1343: pos += 16;
! 1344: }
! 1345: for (; pos < len + 4; pos += 4) {
! 1346: frame.Print(out, pos, 4, "(internal register)");
! 1347: }
! 1348: }
! 1349:
! 1350: // 68040 の未実装命令ステートフレーム。
! 1351: // 68040 のビジーフレームからも呼ばれる。base には Unimpl の原点を指定するが
! 1352: // +$00 からの4バイト分の表示は呼び出し側の担当。
! 1353: void
! 1354: DebuggerMD_m680x0::PrintFPFrame68040Unimpl(FILE *out, StackData& frame,
! 1355: uint base)
! 1356: {
! 1357: // +$04.L: CMDREG3B
! 1358: uint32 reg3b = frame.Word(base + 0x04);
! 1359: frame.Print(out, base + 0x04, 4, "CMDREG3B=$%03x", reg3b);
! 1360:
! 1361: // +$08.L: (reserved)
! 1362: uint16 exc = frame.Word(base + 0x08);
! 1363: frame.Print(out, base + 0x08, 4,
! 1364: "(NMNEXC %s %s %s %s %s) (NMCEXC %s %s %s %s %s)",
! 1365: ((exc & 0x0200) ? "UN" : "--"),
! 1366: ((exc & 0x0100) ? "SN" : "--"),
! 1367: ((exc & 0x0080) ? "OE" : "--"),
! 1368: ((exc & 0x0040) ? "OF" : "--"),
! 1369: ((exc & 0x0020) ? "UF" : "--"),
! 1370: ((exc & 0x0010) ? "UN" : "--"),
! 1371: ((exc & 0x0008) ? "SN" : "--"),
! 1372: ((exc & 0x0004) ? "OE" : "--"),
! 1373: ((exc & 0x0002) ? "OF" : "--"),
! 1374: ((exc & 0x0001) ? "UF" : "--"));
! 1375:
! 1376: // +$0c.L: STAG...
! 1377: uint32 w0c = frame.Word(base + 0x0c);
! 1378: uint32 stag = (w0c >> 13) & 7;
! 1379: frame.Print(out, base + 0x0c, 4,
! 1380: "STAG=%u%s (E=%u) M66=%u M1=%u M0=%u SBIT=%u",
! 1381: stag, MPU68040Device::GetFPUTagName(stag).c_str(),
! 1382: ((w0c & 0x1000) ? 1 : 0),
! 1383: ((w0c & 0x0400) ? 1 : 0),
! 1384: ((w0c & 0x0200) ? 1 : 0),
! 1385: ((w0c & 0x0100) ? 1 : 0),
! 1386: ((w0c & 0x0080) ? 1 : 0));
! 1387:
! 1388: // +$10.L: CMDREG1B
! 1389: uint32 reg1b = frame.Word(base + 0x10);
! 1390: uint32 opclass = reg1b >> 13;
! 1391: uint32 rx = (reg1b >> 10) & 7;
! 1392: uint32 ry = (reg1b >> 7) & 7;
! 1393: uint32 cmd = reg1b & 0x7f;
! 1394: std::string cmdname = MPU68040Device::GetReg1BName(opclass, rx, cmd);
! 1395: frame.Print(out, base + 0x10, 4,
! 1396: "CMDREG1B=$%04x: OPCLASS=%x Rs=%u Rd=%u CMD=$%02x(%s)",
! 1397: reg1b,
! 1398: opclass, rx, ry,
! 1399: cmd, cmdname.c_str());
! 1400:
! 1401: // +$14.L: DTAG...
! 1402: uint32 w14 = frame.Word(base + 0x14);
! 1403: uint32 dtag = (w14 >> 13) & 7;
! 1404: frame.Print(out, base + 0x14, 4,
! 1405: "DTAG=%u%s (FPTEMP15=%u) WBTEMP15=%u",
! 1406: dtag, MPU68040Device::GetFPUTagName(dtag).c_str(),
! 1407: ((w14 & 0x1000) ? 1 : 0),
! 1408: ((w14 & 0x0010) ? 1 : 0));
! 1409:
! 1410: // +$18.L: E1,E3,T
! 1411: uint32 w18 = frame.Word(base + 0x18);
! 1412: frame.Print(out, base + 0x18, 4,
! 1413: "E1=%u E3=%u (S=%u X=%u U=%u) T=%u",
! 1414: ((w18 & 0x0400) ? 1 : 0),
! 1415: ((w18 & 0x0200) ? 1 : 0),
! 1416: ((w18 & 0x0100) ? 1 : 0),
! 1417: ((w18 & 0x0080) ? 1 : 0),
! 1418: ((w18 & 0x0020) ? 1 : 0),
! 1419: ((w18 & 0x0010) ? 1 : 0));
! 1420:
! 1421: // +$1C.L: FPTS,FPTE
! 1422: uint32 w1c = frame.Word(base + 0x1c);
! 1423: frame.Print(out, base + 0x1c, 4, "FPTS=%u FPTE=$%04x",
! 1424: ((w1c & 0x8000) ? 1 : 0),
! 1425: (w1c & 0x7fff));
! 1426:
! 1427: // +$20.L: FPTM
! 1428: // +$24.L: FPTM
! 1429: frame.Print(out, base + 0x20, 4, "FPTM[63:32]");
! 1430: frame.Print(out, base + 0x24, 4, "FPTM[31:00]");
! 1431:
! 1432: // +$28.L: ETS,ETE
! 1433: uint32 w28 = frame.Word(base + 0x28);
! 1434: frame.Print(out, base + 0x28, 4, "ETS=%u ETE=$%04x",
! 1435: ((w28 & 0x8000) ? 1 : 0),
! 1436: (w28 & 0x7fff));
! 1437:
! 1438: // +$2C.L: ETM
! 1439: // +$30.L: ETM
! 1440: frame.Print(out, base + 0x2c, 4, "ETM[63:32]");
! 1441: frame.Print(out, base + 0x30, 4, "ETM[31:00]");
! 1442: }
! 1443:
! 1444: void
! 1445: DebuggerMD_m680x0::PrintFPFrame68040Busy(FILE *out, StackData& frame)
! 1446: {
! 1447: frame.Print(out, 0x04, 4, "(reserved)");
! 1448:
! 1449: // $08 CU_SAVEPC
! 1450: uint32 w08 = frame.Word(0x08);
! 1451: frame.Print(out, 0x08, 4, "CU_SAVEPC=$%02x", w08 >> 25);
! 1452:
! 1453: frame.Print(out, 0x0c, 4, "(reserved)");
! 1454: frame.Print(out, 0x10, 4, "(reserved)");
! 1455: frame.Print(out, 0x14, 4, "(reserved)");
! 1456:
! 1457: // $18 WBT
! 1458: uint32 w18 = frame.Word(0x18);
! 1459: frame.Print(out, 0x18, 4, "WBT S=%u E=$%04x",
! 1460: ((w18 & 0x8000) ? 1 : 0),
! 1461: (w18 & 0x7fff));
! 1462: frame.Print(out, 0x1c, 4, "WBTM[63:32]");
! 1463: frame.Print(out, 0x20, 4, "WBTM[31:00]");
! 1464:
! 1465: frame.Print(out, 0x24, 4, "(reserved)");
! 1466: frame.Print(out, 0x28, 4, "FPIARCU");
! 1467: frame.Print(out, 0x2c, 4, "(reserved)");
! 1468: frame.Print(out, 0x30, 4, "(reserved)");
! 1469:
! 1470: // これ以降は Unimpl と同じ。
! 1471: PrintFPFrame68040Unimpl(out, frame, 0x30);
! 1472: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.