Annotation of nono/debugger/debugger_private.h, revision 1.1.1.4

1.1       root        1: //
                      2: // nono
1.1.1.2   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #pragma once
                      8: 
1.1.1.3   root        9: #include "branchhistory.h"
1.1       root       10: #include "bus.h"
                     11: #include "cvprompt.h"
                     12: #include "textscreen.h"
1.1.1.2   root       13: #include <array>
                     14: 
                     15: using ConstStringPair = std::pair<const std::string, const std::string>;
                     16: using HelpMessages = std::vector<ConstStringPair>;
1.1       root       17: 
                     18: // 諸情報付きのアドレス
                     19: struct saddr_t
                     20: {
1.1.1.4 ! root       21:        // アドレス(32bit)
        !            22:        uint32 addr {};
1.1       root       23: 
                     24:        // addr が論理アドレスなら true。
                     25:        // MMU の有効/無効状態はここにセットするのではなく、メモリアクセスに
                     26:        // 際してアドレス変換を行う側がその時点で改めてチェックするので、
                     27:        // ここはどちらかというと物理アドレスなら false くらいの意味合い。
1.1.1.4 ! root       28:        bool logical {};
1.1       root       29: 
                     30:        // addr が論理アドレスの場合に、テーブルサーチも行うなら true。
                     31:        // false なら TT、ATC のみ検索する。
1.1.1.4 ! root       32:        bool search {};
1.1       root       33: 
                     34:        // addr がスーパバイザアクセスなら true。
1.1.1.4 ! root       35:        bool super {};
1.1       root       36: 
                     37:        // addr がデータアクセスなら true。
1.1.1.4 ! root       38:        bool data {};
1.1       root       39: 
                     40:        bool IsLogical() const  { return logical; }
                     41:        bool IsSearch() const   { return search; }
                     42:        bool IsSuper() const    { return super; }
                     43:        bool IsData() const             { return data; }
                     44:        bool IsInst() const             { return !data; }
                     45: 
                     46:        // (論理)アドレスと Super/User ビットを合わせた 33bit アドレスを返す
                     47:        uint64 GetSaddr() const {
                     48:                uint64 sa = addr;
                     49:                if (IsSuper()) {
                     50:                        sa |= 0x100000000ULL;
                     51:                }
                     52:                return sa;
                     53:        }
                     54: };
                     55: 
                     56: enum MemdumpMode {
                     57:        Physical = 0,           // 物理アドレス
                     58:        Logical_atc,            // 論理アドレス (ただし TT、ATC のみ検索)
                     59:        Logical_search,         // 論理アドレス (TT、ATC、テーブルサーチすべて行う)
                     60: };
                     61: 
                     62: class Console;
                     63: class DebuggerMD;
                     64: class Disasm;
                     65: 
1.1.1.2   root       66: class Debugger final
1.1       root       67: {
                     68:        friend class DebuggerMD_m680x0;
                     69:        friend class DebuggerMD_m88xx0;
                     70:  private:
                     71:        // 型
1.1.1.2   root       72:        enum CommandAction {
                     73:                Stay,           // デバッガプロンプトに留まる
                     74:                Leave,          // デバッガプロンプトを抜けて VM を実行する
                     75:                Quit,           // デバッガとの接続を終了する
                     76:        };
                     77:        using cmdfunc_t = void (Debugger::*)();
1.1       root       78:        typedef struct {
                     79:                const char *name;
                     80:                cmdfunc_t func;
1.1.1.2   root       81:                CommandAction action;
1.1       root       82:        } cmddef_t;
                     83: 
1.1.1.3   root       84:        // ブレークポイント種別
                     85:        enum BreakpointType {
                     86:                Unused = 0,
                     87:                Address,                // このアドレスに来る直前
                     88:                Memory,                 // このアドレスをアクセスした直後
                     89:                Exception,              // この例外を検出した直後
                     90:                Instruction,    // この命令を実行する直前
                     91:        };
                     92: 
1.1       root       93:        // ブレークポイント
                     94:        typedef struct {
1.1.1.3   root       95:                BreakpointType type {}; // 種別
                     96:                // 種別ごとのパラメータ
                     97:                union {
                     98:                        uint32 addr {};         // ターゲットアドレス (Address/Memory)
                     99:                        struct {
                    100:                                int vec1;               // ベクタ番号 (開始)
                    101:                                int vec2;               // ベクタ番号 (終了)
                    102:                        };
                    103:                        struct {
                    104:                                uint32 inst;    // 命令ワード
                    105:                                uint32 mask;    // マスク
                    106:                        };
                    107:                };
                    108: 
                    109:                uint32 matched {};              // 成立回数 (積算)
                    110: 
                    111:                // skip はユーザ指定値。ただし
                    112:                // -1 なら常にスキップ、つまりブレークせずカウントのみ行う、
                    113:                // 0 ならスキップなし、つまり成立ごとにブレーク(これがデフォルト)、
                    114:                // n(>0) なら n 回の成立をスキップし、(n+1) 回目でブレークの意。
                    115:                int32 skip {};                  // スキップ回数 (ユーザ指定値)
                    116:                int32 skipremain {};    // 残りスキップ回数 (0 で成立)
1.1       root      117:        } breakpoint_t;
                    118:        static const int MAX_BREAKPOINTS = 8;
                    119: 
                    120:  public:
                    121:        Debugger();
1.1.1.2   root      122:        ~Debugger() { }
1.1       root      123: 
                    124:        void Init();
                    125:        void ThreadRun();
                    126:        bool Check();
1.1.1.3   root      127:        void NotifyException(int vector);
                    128: 
                    129:        // ブレークポイントモニタを更新
                    130:        void MonitorBreakpoint(TextScreen& monitor);
1.1       root      131: 
                    132:  private:
1.1.1.2   root      133:        bool Accept();
                    134:        bool AcquirePrompt();
                    135:        CommandAction MainLoop();
1.1.1.3   root      136:        bool CheckAllBreakpoints();
                    137:        bool CheckBreakpointInst(breakpoint_t&);
1.1.1.2   root      138:        void ParseCmdbuf();
1.1       root      139:        // コマンド名は大文字小文字を区別する関係でスネークスタイル。
                    140:        void cmd_b();
1.1.1.3   root      141:        void cmd_bi();
                    142:        void cmd_bm();
                    143:        void cmd_bv();
1.1       root      144:        void cmd_b_list();
1.1.1.3   root      145:        void cmd_b_set(BreakpointType);
1.1       root      146:        void cmd_brhist();
                    147:        void cmd_bx();
                    148:        void cmd_c();
                    149:        void cmd_d();
                    150:        void cmd_dt();
                    151:        void cmd_D();
1.1.1.4 ! root      152:        void cmd_disp();
1.1.1.3   root      153:        void cmd_exhist();
1.1       root      154:        void cmd_h();
1.1.1.4 ! root      155:        void cmd_hb();
        !           156:        void cmd_hr();
1.1       root      157:        void cmd_L();
                    158:        void cmd_m();
                    159:        void cmd_mt();
                    160:        void cmd_M();
                    161:        void cmd_minus();
                    162:        void cmd_n();
1.1.1.4 ! root      163:        void cmd_nt();
1.1       root      164:        void cmd_q();
1.1.1.4 ! root      165:        void cmd_reset();
1.1       root      166:        void cmd_s();
1.1.1.4 ! root      167:        void cmd_st();
1.1       root      168:        void cmd_so();
1.1.1.4 ! root      169:        void cmd_sot();
1.1       root      170:        void cmd_show();
                    171:        void cmd_t();
                    172: 
1.1.1.3   root      173:        int AddBreakpoint(const breakpoint_t&);
                    174:        void RecalcInstMask();
1.1.1.4 ! root      175:        bool GetAddr(saddr_t *addr);
1.1       root      176:        void cmd_d_common(MemdumpMode mode);
1.1.1.3   root      177:        void cmd_hist_common(BranchHistory& hist, uint64 flag);
1.1       root      178:        void cmd_m_common(MemdumpMode mode);
1.1.1.4 ! root      179:        void cmd_n_common(bool);
        !           180:        void cmd_s_common(bool);
        !           181:        void cmd_so_common(bool);
1.1.1.3   root      182:        bool ParseVerbHex(const char *arg, uint32 *valp);
1.1       root      183:        bool ParseAddr(const char *arg, uint32_t *addrp);
1.1.1.4 ! root      184:        void SetNBreakpoint();
1.1       root      185: 
1.1.1.2   root      186:        static const HelpMessages HelpMsgMain;
1.1.1.4 ! root      187:        static const HelpMessages HelpMsgBreakpoints;
        !           188:        static const HelpMessages HelpDetails;
        !           189:        void Help(const HelpMessages& msgs);
        !           190: 
        !           191:        // 個別ヘルプメッセージを出力用に置換
        !           192:        std::string HelpConvert(const std::string& msg);
1.1.1.2   root      193: 
                    194:        // モニターを更新して表示
1.1.1.3   root      195:        void ShowMonitor(IMonitor& monitor);
1.1.1.2   root      196:        // テキストスクリーンを表示
                    197:        void ShowTextScreen(TextScreen& screen);
1.1       root      198: 
                    199:        // アドレスをダンプ表示用に整形して返す
                    200:        bool FormatDumpAddr(saddr_t addr, std::string& addrstr);
                    201: 
1.1.1.4 ! root      202:        DebuggerMD *md {};                      // 機種依存部分
1.1       root      203: 
1.1.1.4 ! root      204:        Console *cons {};                       // 入出力
        !           205:        const char *prompt {};          // プロンプト文字列
1.1       root      206:        std::string cmdbuf {};          // 現在のコマンドライン
                    207:        std::string last_cmdbuf {};     // 直前のコマンドライン
1.1.1.2   root      208:        std::vector<std::string> args {};
1.1       root      209: 
1.1.1.4 ! root      210:        uint32 pc {};
1.1       root      211:        std::vector<uint8> ir {};       // この後実行する命令のバイナリ列
1.1.1.2   root      212:        std::array<breakpoint_t, MAX_BREAKPOINTS> bpoint {};
1.1.1.4 ! root      213:        bool bc_enable {};
        !           214:        uint32 bc_addr {};
        !           215:        uint32 bi_inst {};
        !           216:        int bi_inst_bytes {};
        !           217:        int bi_need_bytes {};
1.1.1.3   root      218:        int bv_vector = -1;
1.1.1.4 ! root      219:        uint32 d_last_addr {};
        !           220:        uint32 m_last_addr {};
        !           221:        bool n_enable {};
        !           222:        uint32 n_breakaddr {};
        !           223:        uint32 n_count {};
        !           224:        bool s_enable {};
        !           225:        uint32 s_count {};
        !           226:        bool so_enable {};
        !           227:        bool t_enable {};
        !           228:        uint32 t_count {};
1.1       root      229: 
                    230:        // 一度VMを実行して再びプロンプトに来たら true
1.1.1.4 ! root      231:        bool is_continued {};
        !           232: 
        !           233:        // プロンプトで表示するレジスタ群
        !           234:        std::vector<std::string> disp_regs {};
1.1       root      235: 
1.1.1.2   root      236:        static std::vector<cmddef_t> cmdtable;
1.1       root      237: };
                    238: 
                    239: // デバッガの CPU 依存部分
                    240: class DebuggerMD
                    241: {
                    242:  public:
1.1.1.4 ! root      243:        DebuggerMD(Debugger *parent_) {
        !           244:                parent = parent_;
1.1       root      245:        }
                    246:        virtual ~DebuggerMD() { }
                    247: 
                    248:        // CPU のリクエストフラグに flag を立てる
                    249:        virtual void ReqSet(uint32 flag) = 0;
                    250:        // CPU のリクエストフラグから flag を落とす
                    251:        virtual void ReqClr(uint32 flag) = 0;
                    252: 
                    253:        // 特権モードなら true を返す
                    254:        virtual bool IsSuper() const = 0;
                    255:        // MMU が有効なら true を返す
                    256:        virtual bool MMUEnabled() const = 0;
                    257: 
                    258:        // アドレス変換をする。
                    259:        // MMUEnabled() が true であることは呼び出し側が確認すること。
                    260:        // 変換できなければ (uint64)-1 を返す。
                    261:        virtual uint64 TranslateAddr(saddr_t laddr) = 0;
                    262: 
                    263:        // 現在の命令先頭アドレスを返す
                    264:        virtual uint32 GetPC() const = 0;
                    265: 
1.1.1.4 ! root      266:        // MMU 状態を考慮して、プログラム空間の指定のアドレスから1命令語を
        !           267:        // 読み出して、下(右)詰めにして返す。
        !           268:        // 命令語が可変長な CPU では最短命令長 (この命令の全ワードではない)。
        !           269:        uint64 PeekFetch(saddr_t laddr);
        !           270: 
1.1       root      271:        // ステップアウトを設定する
                    272:        virtual void SetStepOut() = 0;
                    273:        // ステップアウトなら true を返す
                    274:        virtual bool IsStepOut() const = 0;
                    275: 
1.1.1.4 ! root      276:        // この命令がステップイン出来るなら true を返す (cmd_n 用)
        !           277:        virtual bool IsOpStepIn(uint32 op) = 0;
        !           278: 
1.1       root      279:        // name で示されるのレジスタの値を返す。
                    280:        // メモリダンプで指定するケースを想定しているので、明らかにアドレスでは
                    281:        // ないレジスタは含まなくてよい (m680x0 の SR など)。ただし Dn は含めて
                    282:        // よい。また m680x0 の SRP/CRP は下位32ビットでよい。
                    283:        // name が正しくない場合は (uint64)-1 を返す。
                    284:        virtual uint64 GetRegAddr(const char *name) const = 0;
                    285: 
                    286:        // 現在のレジスタセットを内部にバックアップする
                    287:        virtual void BackupRegs() = 0;
                    288: 
1.1.1.2   root      289:        // レジスタ表示系のコマンドを実行。処理すれば true を返す。
                    290:        virtual bool ShowRegister(Console *cons,
                    291:                const std::vector<std::string>& args) = 0;
                    292:        // レジスタ表示系コマンドのヘルプメッセージを取得
                    293:        virtual const HelpMessages& GetRegisterHelp() const = 0;
                    294: 
1.1.1.3   root      295:        // ブランチ履歴・例外履歴(オブジェクト)を取得
                    296:        virtual BranchHistory& GetBrHist() const = 0;
                    297:        virtual BranchHistory& GetExHist() const = 0;
1.1       root      298: 
                    299:        // 直近の命令でアクセスした laddr が一致したら true を返す
                    300:        // 1 命令で複数にアクセスする場合を考慮して、md 側で判断する
                    301:        virtual bool CheckLEA(uint32 laddr) = 0;
                    302: 
                    303:        // 逆アセンブル。
                    304:        // laddr の位置の命令を一つ逆アセンブルする。
                    305:        // 成功すれば true を返し、失敗すれば(?) false を返す。
                    306:        // 成功した場合 mnemonic に逆アセンブルした文字列が、
                    307:        // bin にこの命令のバイナリ列が格納されている。
                    308:        // mnemonic は単純に命令部分のみ、16進ダンプや付随情報は含まない。
                    309:        // bin はメモリイメージのバイト順で格納すること。
                    310:        virtual bool Disassemble(saddr_t laddr,
                    311:                std::string& mnemonic, std::vector<uint8>& bin) = 0;
                    312: 
                    313:        // 逆アセンブルをフォーマット。
                    314:        // オフライン版は逆アセンブルウィンドウなど、
                    315:        // オンライン版(Live) はデバッガプロンプトで表示するやつ。
                    316:        virtual std::string FormatDisasm(const std::string& mnemonic,
                    317:                const std::vector<uint8>& bin) = 0;
                    318:        virtual std::string FormatDisasmLive(const std::string& mnemonic,
                    319:                const std::vector<uint8>& bin) = 0;
                    320: 
1.1.1.4 ! root      321:        // 例外のベクタ番号から名前を取得。
        !           322:        virtual const char *GetExceptionName(int vector) const = 0;
        !           323: 
1.1.1.3   root      324:        // ベクタ番号の最大値 (+1)
1.1.1.4 ! root      325:        int vector_max {};
        !           326:        // 最短の1命令のバイト数
        !           327:        uint inst_bytes {};
        !           328:        // 命令が固定長ならそのバイト数、可変長なら 0
        !           329:        uint inst_bytes_fixed {};
1.1.1.3   root      330: 
1.1       root      331:  protected:
1.1.1.4 ! root      332:        Debugger *parent {};    // 親クラス
1.1       root      333: };
                    334: 
                    335: #define NORM           "\x1b[0m"
                    336: #define BOLD           "\x1b[1m"
                    337: #define BOLDIF(n)      ((n) ? BOLD : "")

unix.superglobalmegacorp.com

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