Annotation of nono/debugger/memdump.cpp, revision 1.1.1.4

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.