OSDN Git Service

[VM][General] Merge Upstream 20180530.
[csp-qt/common_source_project-fm7.git] / source / src / vm / debugger.h
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2014.09.02-
6
7         [ debugger ]
8 */
9
10 #ifndef _DEBUGGER_H_
11 #define _DEBUGGER_H_
12
13 //#include "vm.h"
14 //#include "../emu.h"
15 #include "device.h"
16
17 //#ifdef USE_DEBUGGER
18
19 #define MAX_BREAK_POINTS        8
20 #define MAX_COMMAND_LENGTH      64
21 #define MAX_COMMAND_HISTORY     32
22 #define MAX_CPU_TRACE           1024
23
24 typedef struct {
25         struct {
26                 uint32_t addr, mask;
27                 int status;     // 0 = none, 1 = enabled, other = disabled
28                 bool check_point;
29         } table[MAX_BREAK_POINTS], stored[MAX_BREAK_POINTS];
30         bool hit, restart;
31         uint32_t hit_addr;
32 } break_point_t;
33
34 class DEBUGGER : public DEVICE
35 {
36 private:
37         DEVICE *d_mem, *d_io;
38         
39         void check_mem_break_points(break_point_t *bp, uint32_t addr, int length)
40         {
41                 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
42                         if(bp->table[i].status == 1) {
43                                 if(addr >= bp->table[i].addr && addr < bp->table[i].addr + length) {
44                                         bp->hit = now_suspended = true;
45                                         bp->hit_addr = bp->table[i].addr;
46                                         bp->restart = bp->table[i].check_point;
47                                         break;
48                                 }
49                         }
50                 }
51         }
52         void check_io_break_points(break_point_t *bp, uint32_t addr)
53         {
54                 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
55                         if(bp->table[i].status == 1) {
56                                 if((addr & bp->table[i].mask) == (bp->table[i].addr & bp->table[i].mask)) {
57                                         bp->hit = now_suspended = true;
58                                         bp->hit_addr = addr;
59                                         bp->restart = bp->table[i].check_point;
60                                         break;
61                                 }
62                         }
63                 }
64         }
65 public:
66         DEBUGGER(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
67         {
68                 memset(&bp, 0, sizeof(bp));
69                 memset(&rbp, 0, sizeof(rbp));
70                 memset(&wbp, 0, sizeof(wbp));
71                 memset(&ibp, 0, sizeof(ibp));
72                 memset(&obp, 0, sizeof(obp));
73                 first_symbol = last_symbol = NULL;
74                 my_tcscpy_s(file_path, _MAX_PATH, _T("debug.bin"));
75                 now_debugging = now_going = now_suspended = now_waiting = false;
76                 memset(history, 0, sizeof(history));
77                 history_ptr = 0;
78                 memset(cpu_trace, 0xff, sizeof(cpu_trace));
79                 prev_cpu_trace = 0xffffffff;
80                 cpu_trace_ptr = 0;
81                 set_device_name(_T("Debugger"));
82         }
83         ~DEBUGGER() {}
84         
85         // common functions
86         void release()
87         {
88                 release_symbols();
89         }
90         void write_data8(uint32_t addr, uint32_t data)
91         {
92                 check_mem_break_points(&wbp, addr, 1);
93                 d_mem->write_data8(addr, data);
94         }
95         uint32_t read_data8(uint32_t addr)
96         {
97                 check_mem_break_points(&rbp, addr, 1);
98                 return d_mem->read_data8(addr);
99         }
100         void write_data16(uint32_t addr, uint32_t data)
101         {
102                 check_mem_break_points(&wbp, addr, 2);
103                 d_mem->write_data16(addr, data);
104         }
105         uint32_t read_data16(uint32_t addr)
106         {
107                 check_mem_break_points(&rbp, addr, 2);
108                 return d_mem->read_data16(addr);
109         }
110         void write_data32(uint32_t addr, uint32_t data)
111         {
112                 check_mem_break_points(&wbp, addr, 4);
113                 d_mem->write_data32(addr, data);
114         }
115         uint32_t read_data32(uint32_t addr)
116         {
117                 check_mem_break_points(&rbp, addr, 4);
118                 return d_mem->read_data32(addr);
119         }
120         void write_data8w(uint32_t addr, uint32_t data, int* wait)
121         {
122                 check_mem_break_points(&wbp, addr, 1);
123                 d_mem->write_data8w(addr, data, wait);
124         }
125         uint32_t read_data8w(uint32_t addr, int* wait)
126         {
127                 check_mem_break_points(&rbp, addr, 1);
128                 return d_mem->read_data8w(addr, wait);
129         }
130         void write_data16w(uint32_t addr, uint32_t data, int* wait)
131         {
132                 check_mem_break_points(&wbp, addr, 2);
133                 d_mem->write_data16w(addr, data, wait);
134         }
135         uint32_t read_data16w(uint32_t addr, int* wait)
136         {
137                 check_mem_break_points(&rbp, addr, 2);
138                 return d_mem->read_data16w(addr, wait);
139         }
140         void write_data32w(uint32_t addr, uint32_t data, int* wait)
141         {
142                 check_mem_break_points(&wbp, addr, 4);
143                 d_mem->write_data32w(addr, data, wait);
144         }
145         uint32_t read_data32w(uint32_t addr, int* wait)
146         {
147                 check_mem_break_points(&rbp, addr, 4);
148                 return d_mem->read_data32w(addr, wait);
149         }
150         uint32_t fetch_op(uint32_t addr, int *wait)
151         {
152                 check_mem_break_points(&rbp, addr, 1);
153                 return d_mem->fetch_op(addr, wait);
154         }
155         void write_io8(uint32_t addr, uint32_t data)
156         {
157                 check_io_break_points(&obp, addr);
158                 d_io->write_io8(addr, data);
159         }
160         uint32_t read_io8(uint32_t addr)
161         {
162                 check_io_break_points(&ibp, addr);
163                 return d_io->read_io8(addr);
164         }
165         void write_io16(uint32_t addr, uint32_t data)
166         {
167                 check_io_break_points(&obp, addr);
168                 d_io->write_io16(addr, data);
169         }
170         uint32_t read_io16(uint32_t addr)
171         {
172                 check_io_break_points(&ibp, addr);
173                 return d_io->read_io16(addr);
174         }
175         void write_io32(uint32_t addr, uint32_t data)
176         {
177                 check_io_break_points(&obp, addr);
178                 d_io->write_io32(addr, data);
179         }
180         uint32_t read_io32(uint32_t addr)
181         {
182                 check_io_break_points(&ibp, addr);
183                 return d_io->read_io32(addr);
184         }
185         void write_io8w(uint32_t addr, uint32_t data, int* wait)
186         {
187                 check_io_break_points(&obp, addr);
188                 d_io->write_io8w(addr, data, wait);
189         }
190         uint32_t read_io8w(uint32_t addr, int* wait)
191         {
192                 check_io_break_points(&ibp, addr);
193                 return d_io->read_io8w(addr, wait);
194         }
195         void write_io16w(uint32_t addr, uint32_t data, int* wait)
196         {
197                 check_io_break_points(&obp, addr);
198                 d_io->write_io16w(addr, data, wait);
199         }
200         uint32_t read_io16w(uint32_t addr, int* wait)
201         {
202                 check_io_break_points(&ibp, addr);
203                 return d_io->read_io16w(addr, wait);
204         }
205         void write_io32w(uint32_t addr, uint32_t data, int* wait)
206         {
207                 check_io_break_points(&obp, addr);
208                 d_io->write_io32w(addr, data, wait);
209         }
210         uint32_t read_io32w(uint32_t addr, int* wait)
211         {
212                 check_io_break_points(&ibp, addr);
213                 return d_io->read_io32w(addr, wait);
214         }
215
216         // unique functions
217         void set_context_mem(DEVICE* device)
218         {
219                 d_mem = device;
220         }
221         void set_context_io(DEVICE* device)
222         {
223                 d_io = device;
224         }
225         void check_break_points(uint32_t addr)
226         {
227                 check_mem_break_points(&bp, addr, 1);
228         }
229         void store_break_points()
230         {
231                 memcpy( bp.stored,  bp.table, sizeof( bp.table));
232                 memcpy(rbp.stored, rbp.table, sizeof(rbp.table));
233                 memcpy(wbp.stored, wbp.table, sizeof(wbp.table));
234                 memcpy(ibp.stored, ibp.table, sizeof(ibp.table));
235                 memcpy(obp.stored, obp.table, sizeof(obp.table));
236                 memset( bp.table, 0, sizeof( bp.table));
237                 memset(rbp.table, 0, sizeof(rbp.table));
238                 memset(wbp.table, 0, sizeof(wbp.table));
239                 memset(ibp.table, 0, sizeof(ibp.table));
240                 memset(obp.table, 0, sizeof(obp.table));
241         }
242         void restore_break_points()
243         {
244                 memcpy( bp.table,  bp.stored, sizeof( bp.table));
245                 memcpy(rbp.table, rbp.stored, sizeof(rbp.table));
246                 memcpy(wbp.table, wbp.stored, sizeof(wbp.table));
247                 memcpy(ibp.table, ibp.stored, sizeof(ibp.table));
248                 memcpy(obp.table, obp.stored, sizeof(obp.table));
249         }
250         bool hit()
251         {
252                 return (bp.hit || rbp.hit || wbp.hit || ibp.hit || obp.hit);
253         }
254         void add_symbol(uint32_t addr, const _TCHAR *name)
255         {
256                 symbol_t *symbol = (symbol_t *)calloc(sizeof(symbol_t), 1);
257                 symbol->addr = addr;
258                 symbol->name = (_TCHAR *)calloc(sizeof(_TCHAR), _tcslen(name) + 1);
259                 my_tcscpy_s(symbol->name, _tcslen(name) + 1, name);
260                 
261                 if(first_symbol == NULL) {
262                         first_symbol = symbol;
263                 } else {
264                         last_symbol->next_symbol = symbol;
265                 }
266                 last_symbol = symbol;
267         }
268         void release_symbols()
269         {
270                 for(symbol_t* symbol = first_symbol; symbol;) {
271                         symbol_t *next_symbol = symbol->next_symbol;
272                         if(symbol->name != NULL) {
273                                 free(symbol->name);
274                         }
275                         free(symbol);
276                         symbol = next_symbol;
277                 }
278                 first_symbol = last_symbol = NULL;
279         }
280         void add_cpu_trace(uint32_t pc)
281         {
282                 if(prev_cpu_trace != pc) {
283                         cpu_trace[cpu_trace_ptr++] = prev_cpu_trace = pc;
284                         cpu_trace_ptr &= (MAX_CPU_TRACE - 1);
285                 }
286         }
287         break_point_t bp, rbp, wbp, ibp, obp;
288         symbol_t *first_symbol, *last_symbol;
289         _TCHAR file_path[_MAX_PATH];
290         bool now_debugging, now_going, now_suspended, now_waiting;
291         _TCHAR history[MAX_COMMAND_HISTORY][MAX_COMMAND_LENGTH + 1];
292         int history_ptr;
293         uint32_t cpu_trace[MAX_CPU_TRACE], prev_cpu_trace;
294         int cpu_trace_ptr;
295 };
296
297 //#endif
298 #endif
299