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