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

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