|
|
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:
9: #include "bus.h"
10: #include "cvprompt.h"
11: #include "textscreen.h"
1.1.1.2 ! root 12: #include <array>
! 13:
! 14: using ConstStringPair = std::pair<const std::string, const std::string>;
! 15: using HelpMessages = std::vector<ConstStringPair>;
1.1 root 16:
17: // 諸情報付きのアドレス
18: struct saddr_t
19: {
20: uint32 addr = 0; // アドレス(32bit)
21:
22: // addr が論理アドレスなら true。
23: // MMU の有効/無効状態はここにセットするのではなく、メモリアクセスに
24: // 際してアドレス変換を行う側がその時点で改めてチェックするので、
25: // ここはどちらかというと物理アドレスなら false くらいの意味合い。
26: bool logical = false;
27:
28: // addr が論理アドレスの場合に、テーブルサーチも行うなら true。
29: // false なら TT、ATC のみ検索する。
30: bool search = false;
31:
32: // addr がスーパバイザアクセスなら true。
33: bool super = false;
34:
35: // addr がデータアクセスなら true。
36: bool data = false;
37:
38: bool IsLogical() const { return logical; }
39: bool IsSearch() const { return search; }
40: bool IsSuper() const { return super; }
41: bool IsData() const { return data; }
42: bool IsInst() const { return !data; }
43:
44: // (論理)アドレスと Super/User ビットを合わせた 33bit アドレスを返す
45: uint64 GetSaddr() const {
46: uint64 sa = addr;
47: if (IsSuper()) {
48: sa |= 0x100000000ULL;
49: }
50: return sa;
51: }
52: };
53:
54: enum MemdumpMode {
55: Physical = 0, // 物理アドレス
56: Logical_atc, // 論理アドレス (ただし TT、ATC のみ検索)
57: Logical_search, // 論理アドレス (TT、ATC、テーブルサーチすべて行う)
58: };
59:
60: class Console;
61: class DebuggerMD;
62: class Disasm;
63:
1.1.1.2 ! root 64: class Debugger final
1.1 root 65: {
66: friend class DebuggerMD_m680x0;
67: friend class DebuggerMD_m88xx0;
68: private:
69: // 型
1.1.1.2 ! root 70: enum CommandAction {
! 71: Stay, // デバッガプロンプトに留まる
! 72: Leave, // デバッガプロンプトを抜けて VM を実行する
! 73: Quit, // デバッガとの接続を終了する
! 74: };
! 75: using cmdfunc_t = void (Debugger::*)();
1.1 root 76: typedef struct {
77: const char *name;
78: cmdfunc_t func;
1.1.1.2 ! root 79: CommandAction action;
1.1 root 80: } cmddef_t;
81:
82: // ブレークポイント
83: typedef struct {
84: bool enable;
85: bool ismemory;
86: uint32 addr;
87: uint32 count;
88: } breakpoint_t;
89: static const int MAX_BREAKPOINTS = 8;
90:
91: public:
92: Debugger();
1.1.1.2 ! root 93: ~Debugger() { }
1.1 root 94:
95: void Init();
96: void ThreadRun();
97: bool Check();
98:
99: private:
1.1.1.2 ! root 100: bool Accept();
! 101: bool AcquirePrompt();
! 102: CommandAction MainLoop();
! 103: void ParseCmdbuf();
1.1 root 104: // コマンド名は大文字小文字を区別する関係でスネークスタイル。
105: void cmd_b();
106: void cmd_b_list();
107: void cmd_brhist();
108: void cmd_bx();
109: void cmd_c();
110: void cmd_d();
111: void cmd_dt();
112: void cmd_D();
113: void cmd_h();
114: void cmd_L();
115: void cmd_m();
116: void cmd_mt();
117: void cmd_M();
118: void cmd_minus();
119: void cmd_n();
120: void cmd_q();
121: void cmd_s();
122: void cmd_so();
123: void cmd_show();
124: void cmd_t();
125:
126: int AddBreakpoint(uint32 addr, bool ismemory);
127: bool GetAddr(uint32& addr, uint32& lastaddr);
128: void cmd_d_common(MemdumpMode mode);
129: void cmd_m_common(MemdumpMode mode);
130: bool ParseAddr(const char *arg, uint32_t *addrp);
131: bool SetNBreakpoint();
132:
1.1.1.2 ! root 133: static const HelpMessages HelpMsgMain;
! 134: void Help(const HelpMessages msgs);
! 135:
! 136: // モニターを更新して表示
! 137: void ShowMonitor(Object& obj);
! 138: // テキストスクリーンを表示
! 139: void ShowTextScreen(TextScreen& screen);
1.1 root 140:
141: // アドレスをダンプ表示用に整形して返す
142: bool FormatDumpAddr(saddr_t addr, std::string& addrstr);
143:
144: DebuggerMD *md = NULL; // 機種依存部分
145:
146: Console *cons = NULL; // 入出力
147: const char *prompt; // プロンプト文字列
148: std::string cmdbuf {}; // 現在のコマンドライン
149: std::string last_cmdbuf {}; // 直前のコマンドライン
1.1.1.2 ! root 150: std::vector<std::string> args {};
1.1 root 151:
152: uint32 pc = 0;
153: uint32 nextpc = 0;
154: std::vector<uint8> ir {}; // この後実行する命令のバイナリ列
1.1.1.2 ! root 155: std::array<breakpoint_t, MAX_BREAKPOINTS> bpoint {};
1.1 root 156: bool bc_enable = false;
157: uint32 bc_addr = 0;
158: uint32 d_last_addr = 0;
159: uint32 m_last_addr = 0;
160: bool n_enable = false;
161: bool n_breakenable = false;
162: uint32 n_breakaddr = 0;
163: uint32 n_count = 0;
164: bool s_enable = false;
165: uint32 s_count = 0;
166: bool so_enable = false;
167: bool t_enable = false;
168: uint32 t_count = 0;
169:
170: // 一度VMを実行して再びプロンプトに来たら true
171: bool is_continued = false;
172:
1.1.1.2 ! root 173: static std::vector<cmddef_t> cmdtable;
1.1 root 174: };
175:
176: // デバッガの CPU 依存部分
177: class DebuggerMD
178: {
179: public:
180: DebuggerMD(Debugger *arg) {
181: parent = arg;
182: }
183: virtual ~DebuggerMD() { }
184:
185: // CPU のリクエストフラグに flag を立てる
186: virtual void ReqSet(uint32 flag) = 0;
187: // CPU のリクエストフラグから flag を落とす
188: virtual void ReqClr(uint32 flag) = 0;
189:
190: // 特権モードなら true を返す
191: virtual bool IsSuper() const = 0;
192: // MMU が有効なら true を返す
193: virtual bool MMUEnabled() const = 0;
194:
195: // アドレス変換をする。
196: // MMUEnabled() が true であることは呼び出し側が確認すること。
197: // 変換できなければ (uint64)-1 を返す。
198: virtual uint64 TranslateAddr(saddr_t laddr) = 0;
199:
200: // 現在の命令先頭アドレスを返す
201: virtual uint32 GetPC() const = 0;
202:
203: // ステップアウトを設定する
204: virtual void SetStepOut() = 0;
205: // ステップアウトなら true を返す
206: virtual bool IsStepOut() const = 0;
207:
208: // name で示されるのレジスタの値を返す。
209: // メモリダンプで指定するケースを想定しているので、明らかにアドレスでは
210: // ないレジスタは含まなくてよい (m680x0 の SR など)。ただし Dn は含めて
211: // よい。また m680x0 の SRP/CRP は下位32ビットでよい。
212: // name が正しくない場合は (uint64)-1 を返す。
213: virtual uint64 GetRegAddr(const char *name) const = 0;
214:
215: // 現在のレジスタセットを内部にバックアップする
216: virtual void BackupRegs() = 0;
217:
1.1.1.2 ! root 218: // レジスタ表示系のコマンドを実行。処理すれば true を返す。
! 219: virtual bool ShowRegister(Console *cons,
! 220: const std::vector<std::string>& args) = 0;
! 221: // レジスタ表示系コマンドのヘルプメッセージを取得
! 222: virtual const HelpMessages& GetRegisterHelp() const = 0;
! 223:
! 224: // ブランチ履歴(オブジェクト)を取得
! 225: virtual Object& GetBrHist() const = 0;
1.1 root 226:
227: // 直近の命令でアクセスした laddr が一致したら true を返す
228: // 1 命令で複数にアクセスする場合を考慮して、md 側で判断する
229: virtual bool CheckLEA(uint32 laddr) = 0;
230:
231: // 逆アセンブル。
232: // laddr の位置の命令を一つ逆アセンブルする。
233: // 成功すれば true を返し、失敗すれば(?) false を返す。
234: // 成功した場合 mnemonic に逆アセンブルした文字列が、
235: // bin にこの命令のバイナリ列が格納されている。
236: // mnemonic は単純に命令部分のみ、16進ダンプや付随情報は含まない。
237: // bin はメモリイメージのバイト順で格納すること。
238: virtual bool Disassemble(saddr_t laddr,
239: std::string& mnemonic, std::vector<uint8>& bin) = 0;
240:
241: // 逆アセンブルをフォーマット。
242: // オフライン版は逆アセンブルウィンドウなど、
243: // オンライン版(Live) はデバッガプロンプトで表示するやつ。
244: virtual std::string FormatDisasm(const std::string& mnemonic,
245: const std::vector<uint8>& bin) = 0;
246: virtual std::string FormatDisasmLive(const std::string& mnemonic,
247: const std::vector<uint8>& bin) = 0;
248:
249: protected:
250: Debugger *parent; // 親クラス
251: };
252:
253: #define NORM "\x1b[0m"
254: #define BOLD "\x1b[1m"
255: #define BOLDIF(n) ((n) ? BOLD : "")
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.