|
|
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 : "")
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.