|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
1.1.1.2 root 6:
7: //
8: // メモリダンプ/逆アセンブル
1.1 root 9: //
10:
11: #include "memdump.h"
1.1.1.2 root 12: #include "debugger_memory.h"
13: #include "debugger_private.h"
14: #include "hd64180disasm.h"
1.1.1.5 root 15: #include "m680x0disasm.h"
1.1.1.2 root 16: #include "m88100disasm.h"
1.1.1.3 root 17: #include "mainbus.h"
1.1.1.5 root 18: #include "monitor.h"
1.1 root 19:
20: //
1.1.1.2 root 21: // メモリダンプ (基本クラス)
1.1 root 22: //
1.1.1.2 root 23:
24: // コンストラクタ
1.1.1.4 root 25: Memdump::Memdump(uint objid_)
1.1.1.2 root 26: : inherited(objid_)
27: {
28: // ログは不要
29: ClearAlias();
30:
31: // 初期値
1.1.1.4 root 32: saddr = BusAddr::SRead | BusAddr::Physical;
1.1.1.2 root 33: SetFormat(Word);
34: }
35:
36: // コンストラクタ (メモリダンプ用にデバッガから呼ばれるほう)
37: Memdump::Memdump(DebuggerMD *md_)
38: : Memdump(OBJ_NONE) // 移譲
39: {
40: InitMD(md_);
41: }
42:
43: // コンストラクタ (逆アセンブル用にデバッガから呼ばれるほう)
44: Memdump::Memdump(DebuggerMD *md_, CPUArch asm_arch)
45: : Memdump(OBJ_NONE) // 移譲
1.1 root 46: {
1.1.1.2 root 47: InitMD(md_);
1.1 root 48:
1.1.1.2 root 49: // asm_arch を Format に変換してセット
50: Format fmt_;
51: switch (asm_arch) {
52: case CPUArch::M680x0:
1.1.1.5 root 53: fmt_ = M680x0Disasm;
1.1.1.2 root 54: break;
55: case CPUArch::M88xx0:
56: fmt_ = M88100Disasm;
57: break;
58: case CPUArch::HD64180:
59: fmt_ = HD64180Disasm;
60: break;
61: default:
62: PANIC("corrupted asm_arch=%d", (int)asm_arch);
63: }
64: SetFormat(fmt_);
65: }
66:
67: // デストラクタ
68: Memdump::~Memdump()
69: {
70: }
1.1 root 71:
1.1.1.2 root 72: // md を初期化(代入)する。
73: void
74: Memdump::InitMD(DebuggerMD *md_)
75: {
76: md = md_;
77: bus = md->GetBus();
1.1 root 78: }
79:
1.1.1.3 root 80: // busaddr を設定する。
1.1.1.2 root 81: void
1.1.1.3 root 82: Memdump::SetAddr(busaddr saddr_)
1.1.1.2 root 83: {
1.1.1.3 root 84: saddr = saddr_;
85: MaskAddr();
1.1.1.2 root 86: }
87:
88: // アドレスを設定する。
89: void
90: Memdump::SetAddr(uint32 laddr_)
91: {
1.1.1.4 root 92: saddr.ChangeAddr(laddr_);
1.1.1.3 root 93: MaskAddr();
1.1.1.2 root 94: }
95:
1.1.1.3 root 96: // 今の表示形式での境界に揃える。
1.1.1.2 root 97: void
1.1.1.3 root 98: Memdump::MaskAddr()
1.1.1.2 root 99: {
1.1.1.3 root 100: saddr &= ~(GetStride() - 1);
1.1.1.2 root 101: }
102:
103: // アドレスをバイト単位で加算(減算)する。
104: void
105: Memdump::Offset(int bytes)
106: {
107: saddr += (uint32)bytes;
108: }
109:
110: // 表示フォーマットを設定する。
111: void
112: Memdump::SetFormat(Memdump::Format fmt_)
113: {
114: fmt = fmt_;
115:
116: line.reset();
117: fixed = 0;
118: inst_bytes = 0;
119:
120: switch (fmt) {
121: case Byte:
122: case Word:
123: case Long:
124: fixed = 16;
125: break;
126: case M68030PageShort:
1.1.1.5 root 127: case M68040TableDesc:
128: case M68040PageDesc:
1.1.1.2 root 129: case M88200Page:
130: fixed = 4;
131: break;
132: case M68030PageLong:
133: fixed = 8;
134: break;
135:
1.1.1.5 root 136: case M680x0Disasm:
1.1.1.2 root 137: line.reset(new m680x0disasm());
138: inst_bytes = 2;
139: break;
140: case M88100Disasm:
141: line.reset(new m88100disasm());
142: inst_bytes = 4;
143: fixed = 4; // 固定長フォーマットでもある
144: break;
145: case HD64180Disasm:
146: line.reset(new hd64180disasm());
147: inst_bytes = 1;
148: break;
149: }
150:
151: // 表示形式を切り替えたことによってアドレスに端数が出るのを防ぐ
1.1.1.3 root 152: MaskAddr();
1.1.1.2 root 153: }
154:
155: // 物理メモリ paddr 以降の内容を越権的に読み出す。bytes は 1, 2, 4 を想定。
156: // バスエラーなら負数を返す。
157: uint64
158: Memdump::Peek(uint32 paddr, int bytes) const
159: {
1.1.1.3 root 160: uint32 data = 0;
1.1.1.2 root 161:
162: while (--bytes >= 0) {
1.1.1.4 root 163: busdata bd = bus->Peek1(paddr++);
1.1.1.3 root 164: if (__predict_false(bd.IsBusErr())) {
165: return bd;
166: }
167: data = (data << 8) | bd.Data();
1.1.1.2 root 168: }
169: return data;
170: }
171:
172: // 物理メモリ paddr 以降の内容を越権的に書き換える。
173: // bytes は 1, 2, 4 を想定しており、paddr はこれに整列しているはず。
1.1.1.3 root 174: // バスエラーが起きたらその場で処理を中止して false を返す。
175: bool
1.1.1.2 root 176: Memdump::Poke(uint32 paddr, uint32 data, int bytes)
177: {
178: while (--bytes >= 0) {
179: uint32 d = data >> (bytes * 8);
1.1.1.4 root 180: if (bus->Poke1(paddr++, d & 0xff) == false) {
1.1.1.3 root 181: return false;
1.1.1.2 root 182: }
183: }
184:
1.1.1.3 root 185: return true;
1.1.1.2 root 186: }
187:
188: // この paddr が Poke() 可能なら true を返す。
189: bool
190: Memdump::CanPoke(uint32 paddr) const
191: {
1.1.1.4 root 192: return bus->Poke1(paddr, -1);
1.1.1.2 root 193: }
194:
195: // コンソールに出力。
196: // 出力後 saddr は更新されている。
197: void
198: Memdump::Print(FILE *cons, int row)
199: {
1.1.1.3 root 200: DebuggerMemoryStream mem(md, saddr);
1.1.1.2 root 201:
202: for (int y = 0; y < row; y++) {
203: std::string addrbuf;
204: bool accessible;
205:
206: accessible = mem.FormatAddr(addrbuf);
207: if (accessible == false) {
208: fprintf(cons, "%s\n", addrbuf.c_str());
209: mem.Offset(GetStride());
210: continue;
211: }
212: // addrbuf は "VA:" もしくは "VA:PA:" の形式で返ってくる。
213: // 本来は、どちらの形式であってもダンプは同じ桁から始めたいが、
214: // バイト表示では 80桁に収まらない。
215: // VA!=PA の場合はどうやっても 80桁に収まらないので諦めてそのまま
216: // 出力するが、VA==PA の時は PA 用の空き地を削れば 80桁に収められる
217: // ので、その努力はしてみる。
218: if (fmt == Byte) {
219: fprintf(cons, "%s ", addrbuf.c_str());
220: } else {
221: fprintf(cons, "%-18s ", addrbuf.c_str());
222: }
223:
224: switch (fmt) {
225: case Byte:
226: case Word:
227: case Long:
228: {
229: std::vector<int> vec = Read(mem, fixed);
230: std::string dumpbuf = DumpHex(vec);
231: std::string charbuf = DumpChar(vec);
232: // 左詰めでいいか
233: fprintf(cons, "%s %s\n", dumpbuf.c_str(), charbuf.c_str());
234: break;
235: }
236:
237: case M68030PageShort:
238: {
239: std::vector<int> vec = Read(mem, fixed);
240: std::string dumpbuf = Dump68030PageShort(vec);
241: // 文字ダンプどうすべ
242: fprintf(cons, "%s\n", dumpbuf.c_str());
243: break;
244: }
245: case M88200Page:
246: {
247: std::vector<int> vec = Read(mem, fixed);
248: std::string dumpbuf = Dump88200Page(vec);
249: // 文字ダンプどうすべ
250: fprintf(cons, "%s\n", dumpbuf.c_str());
251: break;
252: }
253:
1.1.1.5 root 254: case M680x0Disasm:
1.1.1.2 root 255: case M88100Disasm:
256: case HD64180Disasm:
257: line->Exec(&mem);
258: fprintf(cons, "%s%s\n", line->dump.c_str(), line->text.c_str());
259: break;
260:
261: default:
262: fprintf(cons, "fmt=%d not supported\n", (int)fmt);
263: mem.Offset(GetStride());
264: break;
265: }
266: }
267:
268: // アドレスを更新
269: saddr = mem.laddr;
270: }
271:
272: // メモリストリームから bytes バイト分読み込んでベクタにして返す。
273: // 各要素はバイトデータで、バスエラーは -1 になる。
274: std::vector<int>
275: Memdump::Read(DebuggerMemoryStream& mem, int bytes)
276: {
277: std::vector<int> vec(bytes);
278:
279: for (int i = 0; i < bytes; i++) {
1.1.1.4 root 280: vec[i] = mem.Read1();
1.1.1.2 root 281: }
282:
283: return vec;
284: }
285:
286: // vec[] の文字ダンプ文字列を返す。
1.1 root 287: std::string
1.1.1.2 root 288: Memdump::DumpChar(const std::vector<int>& vec)
1.1 root 289: {
1.1.1.2 root 290: std::string charbuf;
1.1 root 291:
1.1.1.2 root 292: for (auto c : vec) {
293: if (c < 0) {
294: charbuf += ' ';
295: } else {
296: charbuf += (0x20 <= c && c <= 0x7e) ? c : '.';
1.1 root 297: }
298: }
299:
1.1.1.2 root 300: return charbuf;
301: }
302:
303: // vec[] の HEX ダンプ文字列を返す。
304: // CLI, GUI 共通。
305: std::string
306: Memdump::DumpHex(const std::vector<int>& vec)
307: {
308: std::string dumpbuf;
309: int span;
310:
311: switch (fmt) {
312: case Byte: span = 1; break;
313: case Word: span = 2; break;
314: case Long: span = 4; break;
315: default:
316: PANIC("corrupted fmt=%d", (int)fmt);
1.1 root 317: }
318:
1.1.1.2 root 319: int s = span;
320: for (auto c : vec) {
321: if (c < 0) {
322: dumpbuf += "--";
323: } else {
324: dumpbuf += strhex(c, 2);
325: }
326:
327: if (--s == 0) {
328: dumpbuf += ' ';
329: s = span;
330: }
331: }
332:
333: return dumpbuf;
334: }
335:
336: // 68030 のショートフォーマットディスクリプタのダンプ文字列を返す。
337: std::string
338: Memdump::Dump68030PageShort(const std::vector<int>& vec)
339: {
340: std::string dumpbuf;
341:
342: // 2 3 4 5 6 7
343: // 9012345678901234567890123456789012345678901234567890123
344: // 00000000 DT=0(Invalid)
345: // ffffff00 DT=1(Page) $00000000 CI M U WP
346: // fffffff0 DT=2(Next Short) $00000000 U WP
347:
348: uint32 data = 0;
349: for (auto b : vec) {
350: if (b < 0) {
351: return "BusErr";
352: }
353: data = (data << 8) | (uint8)b;
1.1 root 354: }
355:
1.1.1.2 root 356: uint32 dt = (data & 0x03);
357: dumpbuf = string_format("%08x DT=%d%s", data, dt, dtname[dt]);
358:
359: if (dt != 0) {
360: if (dt == 1) {
361: dumpbuf += string_format(" $%08x %s %c",
362: (data & 0xffff'ff00),
363: (data & 0x40) ? "CI" : "- ",
364: (data & 0x10) ? 'M' : '-');
365: } else {
366: dumpbuf += string_format(" $%08x ", data & 0xffff'fff0);
367: }
368: dumpbuf += string_format(" %c %s",
369: (data & 0x08) ? 'U' : '-',
370: (data & 0x04) ? "WP" : "- ");
371: }
372:
373: return dumpbuf;
1.1 root 374: }
375:
1.1.1.2 root 376: // 88200 のセグメントディスクリプタとページディスクリプタ
377: std::string
378: Memdump::Dump88200Page(const std::vector<int>& vec)
379: {
380: std::string dumpbuf;
381:
382: // 2 3 4 5 6 7
383: // 9012345678901234567890123456789012345678901234567890123
384: // 00000000 $00000'000 WT SP G CI M U WP V
385:
386: uint32 data = 0;
387: for (auto b : vec) {
388: if (b < 0) {
389: return "BusErr";
390: }
391: data = (data << 8) | (uint8)b;
392: }
393:
394: dumpbuf = string_format("%08x $%05x'000 %s %s %c %s %c %c %s %c",
395: data,
396: (data >> 12),
397: (data & 0x200) ? "WT" : "- ",
398: (data & 0x100) ? "SP" : "- ",
399: (data & 0x080) ? 'G' : '-',
400: (data & 0x040) ? "CI" : "- ",
401: (data & 0x010) ? 'M' : '-',
402: (data & 0x008) ? 'U' : '-',
403: (data & 0x004) ? "WP" : "- ",
404: (data & 0x001) ? 'V' : '-');
405:
406: return dumpbuf;
407: }
408:
409: /*static*/ const char * const
410: Memdump::dtname[4] = {
411: "(Invalid) ",
412: "(Page) ",
413: "(Next Short)",
414: "(Next Long) ",
415: };
416:
1.1.1.5 root 417: /*static*/ const char * const
418: Memdump::udtname[4] = {
419: "(Invalid) ",
420: "(Invalid) ",
421: "(Resident)",
422: "(Resident)",
423: };
424:
425: /*static*/ const char * const
426: Memdump::pdtname[4] = {
427: "(Invalid) ",
428: "(Resident)",
429: "(Indirect)",
430: "(Resident)",
431: };
432:
1.1 root 433:
434: //
1.1.1.2 root 435: // メモリダンプモニタ
1.1 root 436: //
437:
438: // コンストラクタ
1.1.1.4 root 439: MemdumpMonitor::MemdumpMonitor(uint objid_, int monid_)
1.1.1.2 root 440: : inherited(objid_)
1.1 root 441: {
1.1.1.5 root 442: monitor = gMonitorManager->Regist(monid_, this);
1.1.1.7 ! root 443: monitor->SetCallback(&MemdumpMonitor::MonitorScreen);
1.1.1.6 root 444: monitor->SetSize(84, 32);
1.1.1.2 root 445: }
1.1 root 446:
1.1.1.2 root 447: // デストラクタ
448: MemdumpMonitor::~MemdumpMonitor()
449: {
450: }
1.1 root 451:
1.1.1.2 root 452: // モニタ更新
453: void
1.1.1.7 ! root 454: MemdumpMonitor::MonitorScreen(Monitor *, TextScreen& screen)
1.1.1.2 root 455: {
1.1.1.3 root 456: DebuggerMemoryStream mem(md, saddr);
1.1.1.2 root 457:
458: screen.Clear();
459:
460: switch (fmt) {
461: case Byte:
462: case Word:
463: case Long:
464: case M68030PageShort:
1.1.1.5 root 465: case M68040TableDesc:
466: case M68040PageDesc:
1.1.1.2 root 467: case M88200Page:
1.1.1.7 ! root 468: MonitorScreenMemdump(screen, mem);
1.1.1.2 root 469: break;
470:
471: case M68030PageLong:
472: screen.Puts(0, 0, "68030PageLong not supported");
473: break;
474:
1.1.1.5 root 475: case M680x0Disasm:
1.1.1.2 root 476: case M88100Disasm:
477: case HD64180Disasm:
1.1.1.7 ! root 478: MonitorScreenDisasm(screen, mem);
1.1.1.2 root 479: break;
480: }
1.1 root 481: }
482:
1.1.1.2 root 483: // モニタ更新 (メモリダンプ、ディスクリプタの場合)
484: void
1.1.1.7 ! root 485: MemdumpMonitor::MonitorScreenMemdump(TextScreen& screen,
1.1.1.2 root 486: DebuggerMemoryStream& mem)
1.1 root 487: {
1.1.1.2 root 488: // モニタでは 80桁を超えて必要サイズ確保してあるので
489: // "VA:" も "VA:PA:" も同じ幅を占有し、
490: // ダンプフィールドは常に 19桁目から開始する。(see Print())
491: int dx = 19;
492:
493: // 文字列ダンプは桁数によらず右詰め
494: int cx = screen.GetCol() - GetStride();
495:
496: int row = screen.GetRow();
497: for (int y = 0; y < row; y++) {
498: std::string addrbuf;
499: bool accessible;
500:
501: // アドレス欄
502: accessible = mem.FormatAddr(addrbuf);
503: screen.Puts(0, y, addrbuf.c_str());
504: if (accessible == false) {
505: mem.Offset(GetStride());
506: continue;
507: }
508:
509: // 文字ダンプ
510: std::vector<int> vec = Read(mem, GetStride());
511: std::string charbuf = DumpChar(vec);
512: screen.Puts(cx, y, charbuf.c_str());
513:
514: // ダンプ本体
515: switch (fmt) {
516: case Byte:
517: case Word:
518: case Long:
519: {
520: std::string dumpbuf = DumpHex(vec);
521: screen.Puts(dx, y, dumpbuf.c_str());
522: break;
523: }
524: case M68030PageShort:
525: Update68030PageShort(screen, dx, y, vec);
526: break;
1.1.1.5 root 527: case M68040TableDesc:
528: Update68040TableDesc(screen, dx, y, vec);
529: break;
530: case M68040PageDesc:
531: Update68040PageDesc(screen, dx, y, vec);
532: break;
1.1.1.2 root 533: case M88200Page:
534: Update88200Page(screen, dx, y, vec);
535: break;
536: default:
537: PANIC("corrupted fmt=%d", (int)fmt);
538: }
539: }
540: }
541:
542: // (x, y) に 68030 ページディスクリプタのダンプを出力する。
543: void
544: MemdumpMonitor::Update68030PageShort(TextScreen& screen, int x, int y,
545: const std::vector<int>& vec)
546: {
547: // 2 3 4 5 6 7
548: // 9012345678901234567890123456789012345678901234567890123
549: // 00000000 $00000000 CI M U WP DT=1(Page)
550: // 00000000 $00000000 U WP DT=2(Next Short)
551:
552: uint32 data = 0;
553: for (auto b : vec) {
554: if (b < 0) {
555: screen.Puts(x, y, "BusErr");
556: return;
557: }
558: data = (data << 8) | (uint8)b;
559: }
560:
561: screen.Puts(x, y, strhex(data).c_str());
562:
563: uint32 dt = (data & 0x03);
564: TA attr = (dt != 0) ? TA::Normal : TA::Disable;
565:
566: if (dt == 1) {
567: screen.Putc(x + 10, y, attr, '$');
568: screen.Puts(x + 11, y, attr, strhex(data & 0xffff'ff00).c_str());
569: screen.Puts(x + 20, y, attr, (data & 0x40) ? "CI" : "-");
570: screen.Putc(x + 23, y, attr, (data & 0x10) ? 'M' : '-');
571: } else {
572: screen.Putc(x + 10, y, attr, '$');
573: screen.Puts(x + 11, y, attr, strhex(data & 0xffff'fff0).c_str());
574: }
575: screen.Putc(x + 25, y, attr, (data & 0x08) ? 'U' : '-');
576: screen.Puts(x + 27, y, attr, (data & 0x04) ? "WP" : "-");
577: screen.Print(x + 30, y, attr, "DT=%d%s", dt, dtname[dt]);
578: }
579:
1.1.1.5 root 580: // (x, y) に 68040 テーブルディスクリプタのダンプを出力する。
581: void
582: MemdumpMonitor::Update68040TableDesc(TextScreen& screen, int x, int y,
583: const std::vector<int>& vec)
584: {
585: // 2 3 4 5 6 7
586: // 9012345678901234567890123456789012345678901234567890123
587: // 00000000 $00000000 U W UDT=0(Invalid)
588:
589: uint32 data = 0;
590: for (auto b : vec) {
591: if (b < 0) {
592: screen.Puts(x, y, "BusErr");
593: return;
594: }
595: data = (data << 8) | (uint8)b;
596: }
597:
598: screen.Puts(x, y, strhex(data).c_str());
599:
600: bool resident = (data & 2);
601: TA attr = resident ? TA::Normal : TA::Disable;
602:
603: // 1段(23bit)、2段4K(24bit)、2段8K(25bit) はとりあえず区別しない。
604: screen.Putc(x + 10, y, attr, '$');
605: screen.Puts(x + 11, y, attr, strhex(data & 0xffff'ff80).c_str());
606: screen.Putc(x + 20, y, attr, (data & 0x0008) ? 'U' : '-');
607: screen.Putc(x + 22, y, attr, (data & 0x0004) ? 'W' : '-');
608: uint32 udt = data & 3;
609: screen.Print(x + 24, y, attr, "UDT=%u%s", udt, udtname[udt]);
610: }
611:
612: // (x, y) に 68040 ページディスクリプタのダンプを出力する。
613: void
614: MemdumpMonitor::Update68040PageDesc(TextScreen& screen, int x, int y,
615: const std::vector<int>& vec)
616: {
617: // 2 3 4 5 6 7
618: // 9012345678901234567890123456789012345678901234567890123456
619: // 00000000 $00000000 UR G U1 U0 S CMx M U W PDT=0(Resident)
620:
621: uint32 data = 0;
622: for (auto b : vec) {
623: if (b < 0) {
624: screen.Puts(x, y, "BusErr");
625: return;
626: }
627: data = (data << 8) | (uint8)b;
628: }
629:
630: screen.Puts(x, y, strhex(data).c_str());
631:
632: uint32 pdt = data & 3;
633: bool resident = (pdt != 0);
634: TA attr = resident ? TA::Normal : TA::Disable;
635:
636: // 4K/8K ページサイズはとりあえず区別しない。
637: screen.Putc(x + 10, y, attr, '$');
638: screen.Puts(x + 11, y, attr, strhex(data & 0xffff'f000).c_str());
639: screen.Puts(x + 20, y, attr, (data & 0x0800) ? "UR" : "--");
640: screen.Putc(x + 23, y, attr, (data & 0x0400) ? 'G' : '-');
641: screen.Puts(x + 25, y, attr, (data & 0x0200) ? "U1" : "--");
642: screen.Puts(x + 28, y, attr, (data & 0x0100) ? "U0" : "--");
643: screen.Putc(x + 31, y, attr, (data & 0x0080) ? 'S' : '-');
644: screen.Print(x + 33, y, attr, "CM%u", (data & 0x0060) >> 5);
645: screen.Putc(x + 37, y, attr, (data & 0x0010) ? 'M' : '-');
646: screen.Putc(x + 39, y, attr, (data & 0x0008) ? 'U' : '-');
647: screen.Putc(x + 41, y, attr, (data & 0x0004) ? 'W' : '-');
648: screen.Print(x + 43, y, attr, "PDT=%u%s", pdt, pdtname[pdt]);
649: }
650:
1.1.1.2 root 651: // (x, y) に 88200 ページディスクリプタのダンプを出力する。
652: void
653: MemdumpMonitor::Update88200Page(TextScreen& screen, int x, int y,
654: const std::vector<int>& vec)
655: {
656: // 2 3 4 5 6 7
657: // 9012345678901234567890123456789012345678901234567890123
658: // 00000000 $00000'000 WT SP G CI M U WP V
659:
660: uint32 data = 0;
661: for (auto b : vec) {
662: if (b < 0) {
663: screen.Puts(x, y, "BusErr");
664: return;
665: }
666: data = (data << 8) | (uint8)b;
667: }
668:
669: screen.Puts(x, y, strhex(data).c_str());
670:
671: TA attr = (data & 0x001) ? TA::Normal : TA::Disable;
672: screen.Print(x + 10, y, attr, "$%05x'000 %s %s %c %s %c %c %s %c",
673: (data >> 12),
674: (data & 0x200) ? "WT" : "- ",
675: (data & 0x100) ? "SP" : "- ",
676: (data & 0x080) ? 'G' : '-',
677: (data & 0x040) ? "CI" : "- ",
678: (data & 0x010) ? 'M' : '-',
679: (data & 0x008) ? 'U' : '-',
680: (data & 0x004) ? "WP" : "- ",
681: (data & 0x001) ? 'V' : '-');
682: }
683:
684: // モニタ更新 (逆アセンブルの場合)
685: void
1.1.1.7 ! root 686: MemdumpMonitor::MonitorScreenDisasm(TextScreen& screen,
1.1.1.2 root 687: DebuggerMemoryStream& mem)
688: {
689: // モニタでは 80桁を超えて必要サイズ確保してあるので
690: // "VA:" も "VA:PA:" も同じ幅を占有し、
691: // ダンプフィールドは常に 19桁目から開始する。(see Print())
692: int dx = 19;
693:
694: int row = screen.GetRow();
695:
696: // 逆アセンブラ用の次行アドレスバッファを必要ならリサイズ
1.1.1.3 root 697: if ((row + 1) != nextaddr.size()) {
698: nextaddr.resize(row + 1);
1.1.1.2 root 699: }
700:
1.1.1.3 root 701: nextaddr[0] = mem.laddr.Addr();
1.1.1.2 root 702: for (int y = 0; y < row; y++) {
703: std::string addrbuf;
704: bool accessible;
705: TA attr;
706:
707: // PC のいる行をボールドに
1.1.1.4 root 708: if (__predict_false(mem.laddr.Addr() == md->GetPC())) {
1.1.1.2 root 709: attr = TA::Em;
710: } else {
711: attr = TA::Normal;
712: }
713:
714: // アドレス欄
715: accessible = mem.FormatAddr(addrbuf);
716: screen.Puts(0, y, attr, addrbuf.c_str());
717: if (accessible == false) {
718: mem.Offset(GetStride());
719: continue;
720: }
721:
722: line->Exec(&mem);
723: screen.Print(dx, y, attr, "%s%s",
724: line->dump.c_str(), line->text.c_str());
725:
726: // 次行の開始アドレスを覚えておく。
727: // 逆アセンブラで n 行下へ移動する時のため。
1.1.1.3 root 728: nextaddr[y + 1] = mem.laddr.Addr();
1.1.1.2 root 729: }
730: }
731:
732: // n 行下の行までのバイトオフセットを返す。
733: int
734: MemdumpMonitor::GetLineOffset(int n) const
735: {
736: if (fixed) {
737: // 固定長フォーマットなら fixed 倍するだけで求まる。
738: return n * fixed;
739: } else {
740: // 可変長フォーマット
1.1.1.3 root 741: if (0 <= n && n < nextaddr.size()) {
742: return nextaddr[n] - nextaddr[0];
1.1.1.2 root 743: } else {
744: // なければ仕方ないので適当に返す
745: return n * inst_bytes;
746: }
747: }
748: }
749:
750: // 前ページ位置(-1)、次ページ位置(1) までのバイトオフセットを返す。
751: int
752: MemdumpMonitor::GetPageOffset(int n) const
753: {
754: // 前ページ/次ページ開始位置は、メモリダンプと逆アセンブルで動作を変える。
755: // メモリダンプならきっちり次のページを表示してほしい。例えば 1画面が
756: // 16行(256バイト) で、現在 $100 にいて次ページに飛ぶ時は $200 になって
757: // ほしい。
758: // 逆アセンブルでは実際にこの動作をすると連続性が失われて読みにくいので
759: // 1行だぶらせることにする。
760:
1.1.1.6 root 761: int row = monitor->GetRow();
1.1.1.2 root 762: if (inst_bytes) {
763: // 逆アセンブルの場合
764: if (n < 0) {
765: // 戻る時は、(最短)命令長分ずつ戻るしかない。
766: return -inst_bytes * (row - 1);
767: } else {
768: return GetLineOffset(row - 1);
769: }
770: } else {
771: // メモリダンプ系の場合は単純に row 分前か後ろというだけ
772: return GetLineOffset(row * n);
773: }
1.1 root 774: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.