Annotation of nono/debugger/branchhistory.cpp, revision 1.1.1.8

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
1.1.1.5   root        7: //
1.1       root        8: // ブランチ履歴
1.1.1.5   root        9: //
1.1       root       10: 
                     11: #include "branchhistory.h"
1.1.1.8 ! root       12: #include "m68030disasm.h"
1.1       root       13: #include "m88100.h"
1.1.1.7   root       14: #include "mpu64180.h"
1.1.1.5   root       15: #include "vectortable.h"
1.1       root       16: 
                     17: // コンストラクタ
1.1.1.7   root       18: BranchHistory::BranchHistory(int objid_)
                     19:        : inherited(objid_)
1.1       root       20: {
1.1.1.7   root       21:        int monitor_id;
                     22: 
                     23:        switch (GetId()) {
                     24:         case OBJ_MPU_BRHIST:
                     25:                is_exhist = false;
                     26:                monitor_id = ID_SUBWIN_BRHIST;
                     27:                break;
                     28:         case OBJ_MPU_EXHIST:
                     29:                is_exhist = true;
                     30:                monitor_id = ID_SUBWIN_EXHIST;
                     31:                break;
                     32:         case OBJ_XP_BRHIST:
                     33:                is_exhist = false;
                     34:                monitor_id = ID_SUBWIN_XPBRHIST;
                     35:                break;
                     36:         case OBJ_XP_EXHIST:
                     37:                is_exhist = true;
                     38:                monitor_id = ID_SUBWIN_XPEXHIST;
                     39:                break;
                     40:         default:
                     41:                PANIC("unknown id %s", GetIdStr());
                     42:        }
1.1.1.4   root       43: 
1.1.1.5   root       44:        // ログは不要
                     45:        ClearAlias();
                     46: 
1.1.1.7   root       47:        vectortable = GetVectorTable();
                     48: 
1.1.1.5   root       49:        monitor.func = ToMonitorCallback(&BranchHistory::MonitorUpdate);
1.1.1.6   root       50:        monitor.SetSize(55, 1 + 32); // ヘッダ1行とエントリ数
                     51:        monitor.SetMaxHeight(1 + 256);
1.1.1.7   root       52:        monitor.Regist(monitor_id);
                     53: 
                     54:        // hd64180 はこれを上書きする
                     55:        x_count = 45;
1.1       root       56: }
                     57: 
                     58: // デストラクタ
                     59: BranchHistory::~BranchHistory()
                     60: {
                     61: }
                     62: 
                     63: // 初期化
                     64: void
                     65: BranchHistory::Clear()
                     66: {
                     67:        top = 0;
                     68:        for (int i = 0; i < countof(entry); i++) {
                     69:                BranchEntry& e = entry[i];
                     70:                e.count = 0;
                     71:                e.from  = 0xffffffff;
                     72:                e.to    = 0xffffffff;
                     73:                e.inst  = 0;
                     74:        }
                     75: }
                     76: 
                     77: // 使用中のエントリ数を取得する
                     78: int
                     79: BranchHistory::GetUsed() const
                     80: {
                     81:        int i = 0;
                     82: 
                     83:        // top の位置から一巡するまで。有効エントリは count > 0。
                     84:        for (; i < 256; i++) {
                     85:                if (entry[(256 + top - i) % 256].count == 0) {
                     86:                        break;
                     87:                }
                     88:        }
                     89:        return i;
                     90: }
                     91: 
                     92: // モニタ更新
                     93: void
1.1.1.4   root       94: BranchHistory::MonitorUpdate(Monitor *, TextScreen& screen)
1.1       root       95: {
                     96:        uint8 t;
                     97:        int y;
                     98:        int ydelta;
                     99:        int row;
                    100: 
                    101:        // userdata は表示開始位置と各種フラグ。
                    102:        // 下位 32bit が表示開始位置で、0 なら先頭のエントリから、1 なら先頭の
1.1.1.4   root      103:        // 一つ次のエントリから、…を表す (表示行数は screen の高さ分)。
1.1       root      104:        // BottomToTop が %1 なら並び順を下から上に変える (コンソール用)。
1.1.1.4   root      105:        bool bottom_to_top = (screen.userdata & BottomToTop);
                    106:        int pos = (int)screen.userdata;
1.1       root      107: 
                    108:        // 0         1         2         3         4         5         6
                    109:        // 0123456789012345678901234567890123456789012345678901234567890123456789
                    110:        // No. FromAddr  Instruction          ToAddr    Iteration
                    111:        // 001 U:01234567(01234567:bcnd.n) -> $01234567 x123456789
                    112:        // 001 U:01234567(0123:trap )      -> $01234567 x123456789
                    113:        // 002 S:01234567<  2> Bus Error
                    114:        // 002 S:01234567< 69> MFP Timer-C
                    115:        //                     01234567890123456789012
                    116: 
1.1.1.4   root      117:        screen.Clear();
                    118:        row = screen.GetRow();
1.1       root      119: 
                    120:        // 最初の1行は常にヘッダ
1.1.1.7   root      121:        std::string header = FormatHeader();
                    122:        screen.Puts(0, 0, header.c_str());
1.1       root      123: 
                    124:        // pos は最新を 0 とした通し番号。(スクロールしてたら開始が 0 とは限らない)
                    125:        // t が entry[] 上の現在位置。
                    126:        // y は表示座標。(上から表示か下から表示かが変わる)
                    127:        t = top - pos;
                    128:        int pos_end = pos + row - 1;
                    129:        if (bottom_to_top == false) {
                    130:                y = 1;
                    131:                ydelta = 1;
                    132:        } else {
                    133:                y = row - 1;
                    134:                ydelta = -1;
                    135:        }
                    136:        for (; pos < pos_end; pos++, y += ydelta) {
                    137:                BranchEntry& e = entry[t--];
                    138:                if (e.count == 0) {
                    139:                        continue;
                    140:                }
                    141:                std::string str = FormatEntry(e);
1.1.1.4   root      142:                screen.Print(0, y, "%3d %s", pos, str.c_str());
1.1       root      143:                if (e.count > 1) {
1.1.1.7   root      144:                        screen.Print(x_count, y, "x%9u", e.count);
1.1       root      145:                }
                    146:        }
                    147: }
                    148: 
1.1.1.7   root      149: // ヘッダ文字列を返す。(m68k, m88k 共通)
                    150: std::string
                    151: BranchHistory::FormatHeader() const
                    152: {
                    153:        if (is_exhist) {
                    154:                //      012345678901234567890123456789012345678901234567890123456789
                    155:                return "No. FromAddr   Vec. Exception                Iteration";
                    156:        } else {
                    157:                //      012345678901234567890123456789012345678901234567890123456789
                    158:                return "No. FromAddr  Instruction          ToAddr    Iteration";
                    159:        }
                    160: }
1.1       root      161: 
                    162: 
                    163: //
                    164: // m680x0 ブランチ履歴 (どこに置くのがよいか)
                    165: //
                    166: 
1.1.1.8 ! root      167: // m680x0 ブランチ履歴では、通常ブランチ、例外発生 (IOCS コールと
        !           168: // それ以外)、例外ベクタによるジャンプの4つを区別する。
1.1       root      169: //
1.1.1.8 ! root      170: // 1. 通常の分岐:
        !           171: //     from は上位31ビットが分岐元 PC、最下位ビットが S/U。
        !           172: //     to   は32ビット全体が分岐先 PC。
        !           173: //     inst は上位2ビットが %00 (Normal)、下位16ビットに分岐元命令の1ワード目。
        !           174: //
        !           175: //      31  30         15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
        !           176: //     +---+---+--  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        !           177: //     | 0 | 0 |  ..  |               instruction word                |
        !           178: //     +---+---+--  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        !           179: //
        !           180: // 2. 例外発生 (IOCS コール以外の場合):
        !           181: //     from は上位31ビットが例外発生時の PC、最下位ビットが S/U。
        !           182: //     to   は不問だが 0 にすること。
        !           183: //     inst は上位2ビットが %11 (Exception)、Number はベクタ番号 (0-255)。
        !           184: //     例外が TRAP#15 で IOCS コールっぽくない場合もこちら。
        !           185: //
        !           186: //      31  30         15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
        !           187: //     +---+---+--  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        !           188: //     | 1 | 1 |  ..  |           0           |        Vector         |
        !           189: //     +---+---+--  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        !           190: //
        !           191: // 3. 例外発生 (IOCS コールの場合):
        !           192: //     from, to は同じ。
        !           193: //     inst は上位2ビットが %10 (IOCSCall)、Number は IOCS コール番号 (0-255)。
        !           194: //
        !           195: //      31  30         15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
        !           196: //     +---+---+--  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        !           197: //     | 1 | 0 |  ..  |           0           |   IOCS Call Number    |
        !           198: //     +---+---+--  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
1.1       root      199: //
1.1.1.8 ! root      200: // 4. 例外ベクタによる分岐 (例外処理の最後に起きる):
1.1.1.3   root      201: //     from はベクタアドレス、
                    202: //     to   は分岐先 (0 も起こりえる)、
1.1.1.8 ! root      203: //     inst は上位2ビットが %01 (VectorJump)。
        !           204: //
        !           205: //      31  30         15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
        !           206: //     +---+---+--  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        !           207: //     | 0 | 1 |  ..  |                       0                       |
        !           208: //     +---+---+--  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
        !           209: //
1.1       root      210: 
                    211: // コンストラクタ
1.1.1.7   root      212: BranchHistory_m680x0::BranchHistory_m680x0(int objid_)
                    213:        : inherited(objid_)
1.1       root      214: {
                    215: }
                    216: 
                    217: // デストラクタ
                    218: BranchHistory_m680x0::~BranchHistory_m680x0()
                    219: {
                    220: }
                    221: 
                    222: // 1エントリ分の表示内容作成
                    223: std::string
                    224: BranchHistory_m680x0::FormatEntry(const BranchEntry& e)
                    225: {
                    226:        // m68k では from の最下位1ビットを S/U として使う
                    227:        std::string desc = string_format("%c:%08x",
                    228:                (e.from & 1) ? 'S' : 'U', (e.from & ~1));
                    229: 
1.1.1.8 ! root      230:        switch (e.inst >> 30) {
        !           231:         case 0:        // 通常分岐
        !           232:         {
1.1       root      233:                const char *mnemonic;
1.1.1.8 ! root      234:                uint32 inst = e.inst & 0xffff;
1.1       root      235:                if (inst == 0x4e73) {
                    236:                        mnemonic = ":rte";
                    237:                } else if (inst == 0x4e75) {
                    238:                        mnemonic = ":rts";
                    239:                } else if (inst == 0x4e77) {
                    240:                        mnemonic = ":rtr";
                    241:                } else if ((inst & 0xffc0) == 0x4e80) {
                    242:                        mnemonic = ":jsr";
                    243:                } else if ((inst & 0xffc0) == 0x4ec0) {
                    244:                        mnemonic = ":jmp";
                    245:                } else if ((inst & 0xfff8) == 0x51c8) {
                    246:                        mnemonic = ":dbra";
                    247:                } else if ((inst & 0xf0f8) == 0x50c8) {
                    248:                        mnemonic = ":dbcc";
                    249:                } else if ((inst & 0xff00) == 0x6000) {
                    250:                        mnemonic = ":bra";
                    251:                } else if ((inst & 0xff00) == 0x6100) {
                    252:                        mnemonic = ":bsr";
                    253:                } else if ((inst & 0xf000) == 0x6000) {
                    254:                        mnemonic = ":bcc";
                    255:                } else if ((inst & 0xfff8) == 0xf248) {
                    256:                        mnemonic = ":fdbcc";
                    257:                } else if ((inst & 0xff80) == 0xf280) {
                    258:                        mnemonic = ":fbcc";
                    259:                } else {
                    260:                        mnemonic = "";
                    261:                }
                    262:                desc += string_format("(%04x%-6s)      -> $%08x", inst, mnemonic, e.to);
1.1.1.8 ! root      263:                break;
        !           264:         }
        !           265: 
        !           266:         case 1:        // 例外ベクタフェッチによるジャンプ
        !           267:                // 例外ベクタフェッチしてジャンプ
        !           268:                desc += string_format("(vector fetch)    -> $%08x", e.to);
        !           269:                break;
        !           270: 
        !           271:         case 2:        // 例外発生 (IOCS コール)
        !           272:         {
        !           273:                uint num = e.inst & 0xff;
        !           274:                const char *name = m680x0disasm::GetIOCSName(num);
        !           275:                if (name != NULL) {
        !           276:                        desc += string_format("<%3d> IOCS %s", M68K::EXCEP_TRAP15, name);
        !           277:                } else {
        !           278:                        desc += string_format("<%3d> IOCS $%02x", M68K::EXCEP_TRAP15, num);
        !           279:                }
        !           280:                break;
        !           281:         }
        !           282: 
        !           283:         case 3:        // 例外発生 (IOCS コール以外)
        !           284:         {
        !           285:                uint32 vector = e.inst & 0xff;
        !           286:                const char *name = vectortable->GetExceptionName(vector);
        !           287:                desc += string_format("<%3d> %s", vector, name ?: "");
        !           288:                break;
        !           289:         }
        !           290: 
        !           291:         default:
        !           292:                __unreachable();
1.1       root      293:        }
                    294:        return desc;
                    295: }
                    296: 
                    297: 
                    298: //
                    299: // m88xx0 ブランチ履歴 (どこに置くのがよいか)
                    300: //
                    301: 
                    302: // m88xx0 ブランチ履歴では、通常ブランチ、例外発生の2つを区別する。
                    303: // m68k は例外ベクタに書いてあるアドレスに飛ぶのでもう1種類分けてあったが、
                    304: // m88k は例外ベクタを直接実行するのでそれは不要。
                    305: //
                    306: // 通常の分岐:
1.1.1.3   root      307: //     from は上位30ビットが分岐元 XIP、最下位ビットが S/U、
                    308: //     to   は32ビット全体が分岐先アドレス、
                    309: //     inst は命令ワード。
1.1       root      310: //
                    311: // 例外発生:
1.1.1.3   root      312: //     from は上位30ビットが例外発生時の XIP、最下位ビットが S/U、
                    313: //     to   は 0。
                    314: //     inst は $fc000VVV で VVV (9ビット)がベクタ番号。
                    315: //     命令ワードとは衝突しない (instruction.txt 参照)。
1.1       root      316: 
                    317: // コンストラクタ
1.1.1.7   root      318: BranchHistory_m88xx0::BranchHistory_m88xx0(int objid_)
                    319:        : inherited(objid_)
1.1       root      320: {
                    321: }
                    322: 
                    323: // デストラクタ
                    324: BranchHistory_m88xx0::~BranchHistory_m88xx0()
                    325: {
                    326: }
                    327: 
                    328: // 1エントリ分の表示内容作成
                    329: std::string
                    330: BranchHistory_m88xx0::FormatEntry(const BranchEntry& e)
                    331: {
                    332:        // m88k では from の最下位1ビットを S/U として使う
                    333:        std::string desc = string_format("%c:%08x",
                    334:                (e.from & 1) ? 'S' : 'U', (e.from & ~1));
                    335: 
                    336:        if (e.inst >= 0xfc000000 && e.to == 0) {
                    337:                // 例外発生記録
                    338:                // 発生アドレスとベクタを表示
                    339:                uint32 vector = e.inst & 0x1ff;
1.1.1.7   root      340:                const char *name = vectortable->GetExceptionName(vector);
1.1       root      341:                desc += string_format("<%3d> %s", vector, name ?: "");
1.1.1.7   root      342:                if (vector == 128 || vector == 450) {
                    343:                        // 450 なら OpenBSD のシステムコール番号を追加。
                    344:                        // 非公式 NetBSD/luna88k は(今の所?) 128 を使ってるようだ。
1.1       root      345:                        desc += string_format("(%d)", (e.inst >> 12) & 0xfff);
                    346:                }
                    347:        } else if (e.inst >= 0xc0000000) {
                    348:                // ブランチ
                    349:                const char *mnemonic = "";
                    350:                uint32 up4 = (e.inst >> 26) & 0xf;
                    351:                switch (up4) {
                    352:                 case 0:        mnemonic = ":br";               break;
                    353:                 case 1:        mnemonic = ":br.n";             break;
                    354:                 case 2:        mnemonic = ":bsr";              break;
                    355:                 case 3:        mnemonic = ":bsr.n";    break;
                    356:                 case 4:        mnemonic = ":bb0";              break;
                    357:                 case 5:        mnemonic = ":bb0.n";    break;
1.1.1.2   root      358:                 case 6:        mnemonic = ":bb1";              break;
1.1       root      359:                 case 7:        mnemonic = ":bb1.n";    break;
                    360: 
                    361:                 case 0xa:      mnemonic = ":bcnd";             break;
                    362:                 case 0xb:      mnemonic = ":bcnd.n";   break;
                    363:                 case 0xc: {
                    364:                        uint32 lo6 = (e.inst >> 10) & 0x3f;
                    365:                        if (lo6 == 0x34) {
                    366:                                mnemonic = ":tb0";
                    367:                        } else if (lo6 == 0x36) {
                    368:                                mnemonic = ":tb1";
                    369:                        } else if (lo6 == 0x3a) {
                    370:                                mnemonic = ":tcnd";
                    371:                        }
                    372:                        break;
                    373:                 }
                    374:                 case 0xd: {
                    375:                        uint32 lo6 = (e.inst >> 10) & 0x3f;
                    376:                        if (lo6 == 0x30) {
                    377:                                if ((e.inst & 0x1f) == 1) {
                    378:                                        mnemonic = ":jmp r1";
                    379:                                } else {
                    380:                                        mnemonic = ":jmp";
                    381:                                }
                    382:                        } else if (lo6 == 0x31) {
                    383:                                mnemonic = ":jmp.n";
                    384:                        } else if (lo6 == 0x32) {
                    385:                                mnemonic = ":jsr";
                    386:                        } else if (lo6 == 0x33) {
                    387:                                mnemonic = ":jsr.n";
                    388:                        } else if (lo6 == 0x3f) {
                    389:                                mnemonic = ":rte";
                    390:                        }
                    391:                        break;
                    392:                 }
                    393:                 case 0xe:      mnemonic = ":tbnd";     break;
                    394:                 default:
                    395:                        break;
                    396:                }
                    397:                desc += string_format("(%08x%-7s) -> $%08x", e.inst, mnemonic, e.to);
                    398:        }
                    399:        return desc;
                    400: }
1.1.1.7   root      401: 
                    402: 
                    403: //
                    404: // XP ブランチ履歴
                    405: //
                    406: 
                    407: // XP ブランチ履歴では、通常ブランチ、例外発生、例外ベクタによるジャンプの
                    408: // 3つを区別する。
                    409: //
                    410: // 通常の分岐
                    411: //     from は下位 16 ビットが分岐元 PC
                    412: //     to   は下位 16 ビットが分岐先 PC
                    413: //     inst の最上位ビットが %0 で区別する。
                    414: //     inst の下位 16 ビットに命令を上詰めで。例えば
                    415: //     CALL (1バイト命令 CD nn nn) なら $0000'cd00、
                    416: //     RETI (2バイト命令 ED 4D) なら $0000'ed4d。
                    417: //
                    418: // 例外発生
                    419: //     from は下位 16 ビットが例外発生時の PC
                    420: //     to   は $ffffffff ならこのエントリはベクタ方式の例外発生時側を示す、
                    421: //             そうでなければダイレクト方式で下位 16 ビットが分岐先 PC
                    422: //     inst の最上位ビットが %1 で inst が $ffffffff でなければ
                    423: //     下位に優先度(0-15)。
                    424: //
                    425: // 例外ベクタジャンプの場合
                    426: //     from はベクタアドレス
                    427: //     to   は分岐先 PC、
                    428: //     inst が $ffffffff で区別する。
                    429: 
                    430: // コンストラクタ
                    431: BranchHistory_hd64180::BranchHistory_hd64180(int objid_)
                    432:        : inherited(objid_)
                    433: {
                    434:        monitor.SetSize(48, 1 + 32); // ヘッダ1行とエントリ数
                    435:        x_count = 38;
                    436: }
                    437: 
                    438: // デストラクタ
                    439: BranchHistory_hd64180::~BranchHistory_hd64180()
                    440: {
                    441: }
                    442: 
                    443: // ヘッダ文字列を返す。
                    444: std::string
                    445: BranchHistory_hd64180::FormatHeader() const
                    446: {
                    447:        if (is_exhist) {
                    448:                //      01234567890123456789012345678901234567890123456789
                    449:                return "No. From  Exception                   Iteration";
                    450:        } else {
                    451:                //      01234567890123456789012345678901234567890123456789
                    452:                return "No. From Instruction           ToAddr Iteration";
                    453:        }
                    454: }
                    455: 
                    456: // 1エントリ分の表示内容作成
                    457: std::string
                    458: BranchHistory_hd64180::FormatEntry(const BranchEntry& e)
                    459: {
                    460:        // 0         1         2         3         4         5
                    461:        // 012345678901234567890123456789012345678901234567890
                    462:        // No. From Instruction           ToAddr Iteration
                    463:        // 001 0123(0000:CALL NZ)      -> $0234 x123456899
                    464:        // No. From Exception
                    465:        // 002 0123<00> Timer Overflow
                    466:        // 003 0038(vector fetch)      -> $0000
                    467: 
                    468:        std::string desc = strhex(e.from, 4);
                    469: 
                    470:        if (e.inst == 0xffffffff) {
                    471:                // 例外ベクタフェッチしてジャンプ
                    472:                desc += string_format("(vector fetch)      -> $%04x", e.to);
                    473:        } else if ((int32)e.inst < 0) {
                    474:                // 例外発生
                    475:                uint32 vector = e.inst & 0xff;
                    476:                desc += string_format("<%2d>%-15s",
                    477:                        vector, MPU64180Device::InterruptName[vector]);
                    478:                // 例外履歴には宛先は出さないほうに統一。
                    479:                // ブランチ履歴でも、ベクタ方式なら宛先不要。
                    480:                if (is_exhist == false && e.to != -1) {
                    481:                        desc += string_format(" -> $%04x", e.to);
                    482:                }
                    483:        } else {
                    484:                // ブランチ
                    485:                std::string mnemonic;
                    486:                uint32 inst = e.inst & 0xffff;
                    487:                if (inst == 0x1000) {
                    488:                        mnemonic = ":DJNZ";
                    489:                } else if (inst == 0x1800) {
                    490:                        mnemonic = ":JR";
                    491:                } else if (inst == 0xc300) {
                    492:                        mnemonic = ":JP";
                    493:                } else if (inst == 0xc900) {
                    494:                        mnemonic = ":RET";
                    495:                } else if (inst == 0xcd00) {
                    496:                        mnemonic = ":CALL";
                    497:                } else if (inst == 0xe900) {
                    498:                        mnemonic = ":JP (HL)";
                    499:                } else if (inst == 0xed45) {
                    500:                        mnemonic = ":RETN";
                    501:                } else if (inst == 0xed4d) {
                    502:                        mnemonic = ":RETI";
                    503:                } else if (inst == 0xdde9) {
                    504:                        mnemonic = ":JP (IX)";
                    505:                } else if (inst == 0xfde9) {
                    506:                        mnemonic = ":JP (IY)";
                    507:                } else if ((inst & 0xe700) == 0x2000) {
                    508:                        mnemonic = ":JR " + fstr((inst >> 11) & 3);
                    509:                } else if ((inst & 0xc700) == 0xc000) {
                    510:                        mnemonic = ":RET " + fstr((inst >> 11) & 7);
                    511:                } else if ((inst & 0xc700) == 0xc200) {
                    512:                        mnemonic = ":JP " + fstr((inst >> 11) & 7);
                    513:                } else if ((inst & 0xc700) == 0xc400) {
                    514:                        mnemonic = ":CALL " + fstr((inst >> 11) & 7);
                    515:                } else if ((inst & 0xc700) == 0xc700) {
                    516:                        mnemonic = string_format(":RST %02xH", (inst >> 8) & 0x38);
                    517:                }
                    518:                desc += string_format("(%04x%-8s)      -> $%04x",
                    519:                        inst, mnemonic.c_str(), e.to);
                    520:        }
                    521:        return desc;
                    522: }
                    523: 
                    524: /*static*/ std::string
                    525: BranchHistory_hd64180::fstr(int f)
                    526: {
                    527:        static const char fff[] =
                    528:                "NZ\0\0"
                    529:                "Z\0\0\0"
                    530:                "NC\0\0"
                    531:                "C\0\0\0"
                    532:                "PO\0\0"
                    533:                "PE\0\0"
                    534:                "P\0\0\0"
                    535:                "M";
                    536: 
                    537:        return &fff[f * 4];
                    538: }

unix.superglobalmegacorp.com

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