--- nono/debugger/debugger_private.h 2026/04/29 17:04:40 1.1.1.4 +++ nono/debugger/debugger_private.h 2026/04/29 17:05:28 1.1.1.13 @@ -4,252 +4,33 @@ // Licensed under nono-license.txt // +// +// デバッガ (内部用) +// + #pragma once -#include "branchhistory.h" +#include "debugger_defs.h" #include "bus.h" -#include "cvprompt.h" -#include "textscreen.h" -#include -using ConstStringPair = std::pair; -using HelpMessages = std::vector; +class IODevice; -// 諸情報付きのアドレス -struct saddr_t +enum class CPUState { - // アドレス(32bit) - uint32 addr {}; - - // addr が論理アドレスなら true。 - // MMU の有効/無効状態はここにセットするのではなく、メモリアクセスに - // 際してアドレス変換を行う側がその時点で改めてチェックするので、 - // ここはどちらかというと物理アドレスなら false くらいの意味合い。 - bool logical {}; - - // addr が論理アドレスの場合に、テーブルサーチも行うなら true。 - // false なら TT、ATC のみ検索する。 - bool search {}; - - // addr がスーパバイザアクセスなら true。 - bool super {}; - - // addr がデータアクセスなら true。 - bool data {}; - - bool IsLogical() const { return logical; } - bool IsSearch() const { return search; } - bool IsSuper() const { return super; } - bool IsData() const { return data; } - bool IsInst() const { return !data; } - - // (論理)アドレスと Super/User ビットを合わせた 33bit アドレスを返す - uint64 GetSaddr() const { - uint64 sa = addr; - if (IsSuper()) { - sa |= 0x100000000ULL; - } - return sa; - } -}; - -enum MemdumpMode { - Physical = 0, // 物理アドレス - Logical_atc, // 論理アドレス (ただし TT、ATC のみ検索) - Logical_search, // 論理アドレス (TT、ATC、テーブルサーチすべて行う) -}; - -class Console; -class DebuggerMD; -class Disasm; - -class Debugger final -{ - friend class DebuggerMD_m680x0; - friend class DebuggerMD_m88xx0; - private: - // 型 - enum CommandAction { - Stay, // デバッガプロンプトに留まる - Leave, // デバッガプロンプトを抜けて VM を実行する - Quit, // デバッガとの接続を終了する - }; - using cmdfunc_t = void (Debugger::*)(); - typedef struct { - const char *name; - cmdfunc_t func; - CommandAction action; - } cmddef_t; - - // ブレークポイント種別 - enum BreakpointType { - Unused = 0, - Address, // このアドレスに来る直前 - Memory, // このアドレスをアクセスした直後 - Exception, // この例外を検出した直後 - Instruction, // この命令を実行する直前 - }; - - // ブレークポイント - typedef struct { - BreakpointType type {}; // 種別 - // 種別ごとのパラメータ - union { - uint32 addr {}; // ターゲットアドレス (Address/Memory) - struct { - int vec1; // ベクタ番号 (開始) - int vec2; // ベクタ番号 (終了) - }; - struct { - uint32 inst; // 命令ワード - uint32 mask; // マスク - }; - }; - - uint32 matched {}; // 成立回数 (積算) - - // skip はユーザ指定値。ただし - // -1 なら常にスキップ、つまりブレークせずカウントのみ行う、 - // 0 ならスキップなし、つまり成立ごとにブレーク(これがデフォルト)、 - // n(>0) なら n 回の成立をスキップし、(n+1) 回目でブレークの意。 - int32 skip {}; // スキップ回数 (ユーザ指定値) - int32 skipremain {}; // 残りスキップ回数 (0 で成立) - } breakpoint_t; - static const int MAX_BREAKPOINTS = 8; - - public: - Debugger(); - ~Debugger() { } - - void Init(); - void ThreadRun(); - bool Check(); - void NotifyException(int vector); - - // ブレークポイントモニタを更新 - void MonitorBreakpoint(TextScreen& monitor); - - private: - bool Accept(); - bool AcquirePrompt(); - CommandAction MainLoop(); - bool CheckAllBreakpoints(); - bool CheckBreakpointInst(breakpoint_t&); - void ParseCmdbuf(); - // コマンド名は大文字小文字を区別する関係でスネークスタイル。 - void cmd_b(); - void cmd_bi(); - void cmd_bm(); - void cmd_bv(); - void cmd_b_list(); - void cmd_b_set(BreakpointType); - void cmd_brhist(); - void cmd_bx(); - void cmd_c(); - void cmd_d(); - void cmd_dt(); - void cmd_D(); - void cmd_disp(); - void cmd_exhist(); - void cmd_h(); - void cmd_hb(); - void cmd_hr(); - void cmd_L(); - void cmd_m(); - void cmd_mt(); - void cmd_M(); - void cmd_minus(); - void cmd_n(); - void cmd_nt(); - void cmd_q(); - void cmd_reset(); - void cmd_s(); - void cmd_st(); - void cmd_so(); - void cmd_sot(); - void cmd_show(); - void cmd_t(); - - int AddBreakpoint(const breakpoint_t&); - void RecalcInstMask(); - bool GetAddr(saddr_t *addr); - void cmd_d_common(MemdumpMode mode); - void cmd_hist_common(BranchHistory& hist, uint64 flag); - void cmd_m_common(MemdumpMode mode); - void cmd_n_common(bool); - void cmd_s_common(bool); - void cmd_so_common(bool); - bool ParseVerbHex(const char *arg, uint32 *valp); - bool ParseAddr(const char *arg, uint32_t *addrp); - void SetNBreakpoint(); - - static const HelpMessages HelpMsgMain; - static const HelpMessages HelpMsgBreakpoints; - static const HelpMessages HelpDetails; - void Help(const HelpMessages& msgs); - - // 個別ヘルプメッセージを出力用に置換 - std::string HelpConvert(const std::string& msg); - - // モニターを更新して表示 - void ShowMonitor(IMonitor& monitor); - // テキストスクリーンを表示 - void ShowTextScreen(TextScreen& screen); - - // アドレスをダンプ表示用に整形して返す - bool FormatDumpAddr(saddr_t addr, std::string& addrstr); - - DebuggerMD *md {}; // 機種依存部分 - - Console *cons {}; // 入出力 - const char *prompt {}; // プロンプト文字列 - std::string cmdbuf {}; // 現在のコマンドライン - std::string last_cmdbuf {}; // 直前のコマンドライン - std::vector args {}; - - uint32 pc {}; - std::vector ir {}; // この後実行する命令のバイナリ列 - std::array bpoint {}; - bool bc_enable {}; - uint32 bc_addr {}; - uint32 bi_inst {}; - int bi_inst_bytes {}; - int bi_need_bytes {}; - int bv_vector = -1; - uint32 d_last_addr {}; - uint32 m_last_addr {}; - bool n_enable {}; - uint32 n_breakaddr {}; - uint32 n_count {}; - bool s_enable {}; - uint32 s_count {}; - bool so_enable {}; - bool t_enable {}; - uint32 t_count {}; - - // 一度VMを実行して再びプロンプトに来たら true - bool is_continued {}; - - // プロンプトで表示するレジスタ群 - std::vector disp_regs {}; - - static std::vector cmdtable; + Normal = 0, + Stop, // STOP 命令など割り込み待ち状態 + Halt, // ホールト、リセットなど非動作状態 }; // デバッガの CPU 依存部分 class DebuggerMD { public: - DebuggerMD(Debugger *parent_) { - parent = parent_; - } - virtual ~DebuggerMD() { } - - // CPU のリクエストフラグに flag を立てる - virtual void ReqSet(uint32 flag) = 0; - // CPU のリクエストフラグから flag を落とす - virtual void ReqClr(uint32 flag) = 0; + DebuggerMD(Debugger *parent_, CPUArch arch_); + virtual ~DebuggerMD(); + // CPU の実行状態を返す。 + virtual CPUState GetCPUState() const = 0; // 特権モードなら true を返す virtual bool IsSuper() const = 0; // MMU が有効なら true を返す @@ -257,24 +38,20 @@ class DebuggerMD // アドレス変換をする。 // MMUEnabled() が true であることは呼び出し側が確認すること。 - // 変換できなければ (uint64)-1 を返す。 - virtual uint64 TranslateAddr(saddr_t laddr) = 0; + // 変換出来なければ BusAddr::BusErr を返す。 + // テーブルサーチを行ったら BusAddr::TableSearched を立てる。 + virtual busaddr TranslateAddr(busaddr laddr) const = 0; // 現在の命令先頭アドレスを返す virtual uint32 GetPC() const = 0; - // MMU 状態を考慮して、プログラム空間の指定のアドレスから1命令語を - // 読み出して、下(右)詰めにして返す。 - // 命令語が可変長な CPU では最短命令長 (この命令の全ワードではない)。 - uint64 PeekFetch(saddr_t laddr); - // ステップアウトを設定する virtual void SetStepOut() = 0; // ステップアウトなら true を返す virtual bool IsStepOut() const = 0; // この命令がステップイン出来るなら true を返す (cmd_n 用) - virtual bool IsOpStepIn(uint32 op) = 0; + virtual bool IsOpStepIn(DebuggerMemoryStream& mem) = 0; // name で示されるのレジスタの値を返す。 // メモリダンプで指定するケースを想定しているので、明らかにアドレスでは @@ -287,49 +64,49 @@ class DebuggerMD virtual void BackupRegs() = 0; // レジスタ表示系のコマンドを実行。処理すれば true を返す。 - virtual bool ShowRegister(Console *cons, - const std::vector& args) = 0; + virtual bool ShowRegister(FILE *, const std::vector& args) = 0; + // レジスタ表示系コマンドのヘルプ一覧を取得 + virtual const HelpMessages& GetHelpListReg() const = 0; // レジスタ表示系コマンドのヘルプメッセージを取得 - virtual const HelpMessages& GetRegisterHelp() const = 0; - - // ブランチ履歴・例外履歴(オブジェクト)を取得 - virtual BranchHistory& GetBrHist() const = 0; - virtual BranchHistory& GetExHist() const = 0; + virtual const HelpMessages& GetHelpReg() const = 0; // 直近の命令でアクセスした laddr が一致したら true を返す // 1 命令で複数にアクセスする場合を考慮して、md 側で判断する virtual bool CheckLEA(uint32 laddr) = 0; - // 逆アセンブル。 - // laddr の位置の命令を一つ逆アセンブルする。 - // 成功すれば true を返し、失敗すれば(?) false を返す。 - // 成功した場合 mnemonic に逆アセンブルした文字列が、 - // bin にこの命令のバイナリ列が格納されている。 - // mnemonic は単純に命令部分のみ、16進ダンプや付随情報は含まない。 - // bin はメモリイメージのバイト順で格納すること。 - virtual bool Disassemble(saddr_t laddr, - std::string& mnemonic, std::vector& bin) = 0; - - // 逆アセンブルをフォーマット。 - // オフライン版は逆アセンブルウィンドウなど、 - // オンライン版(Live) はデバッガプロンプトで表示するやつ。 - virtual std::string FormatDisasm(const std::string& mnemonic, - const std::vector& bin) = 0; - virtual std::string FormatDisasmLive(const std::string& mnemonic, - const std::vector& bin) = 0; + // mem.laddr の位置の命令を一つ逆アセンブルする。 + virtual std::string Disassemble(DebuggerMemoryStream& mem) = 0; - // 例外のベクタ番号から名前を取得。 - virtual const char *GetExceptionName(int vector) const = 0; + // 機種名を取得する + const std::string& GetName() const { return name; } + + // この CPU のバスを返す + IODevice *GetBus() const { return bus; } + // このバスの論理アドレス幅 (ビット数) を返す + int GetLASize() const { return lasize; } + // このバスの物理アドレス幅 (ビット数) を返す + int GetPASize() const { return pasize; } + + // 機種 + CPUArch arch {}; - // ベクタ番号の最大値 (+1) - int vector_max {}; // 最短の1命令のバイト数 uint inst_bytes {}; // 命令が固定長ならそのバイト数、可変長なら 0 uint inst_bytes_fixed {}; + // 例外ブレーク。 + // 機種固有ではないが main と xp でそれぞれに必要なので、ここに持っておく。 + int bv_vector {}; + protected: Debugger *parent {}; // 親クラス + + std::string name {}; // 機種名 + + IODevice *bus {}; // 対応する外部バス + int lasize {}; // バスの論理アドレス幅 + int pasize {}; // バスの物理アドレス幅 }; #define NORM "\x1b[0m"