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

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: }

unix.superglobalmegacorp.com

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