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

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

unix.superglobalmegacorp.com

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