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