OSDN Git Service

[VM][PC9801][MEMBUS] Split update_bios() to functions.
[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        16
20 #define MAX_COMMAND_LENGTH      1024
21 #define MAX_COMMAND_HISTORY     32
22 //#define MAX_CPU_TRACE         0x01000000 /* 16Msteps */
23 #define MAX_CPU_TRACE           0x00100000 /* 1Msteps */
24
25
26 typedef struct {
27         struct {
28                 uint32_t addr, mask;
29                 int status;     // 0 = none, 1 = enabled, other = disabled
30                 bool check_point;
31         } table[MAX_BREAK_POINTS], stored[MAX_BREAK_POINTS];
32         bool hit, restart;
33         uint32_t hit_addr;
34 } break_point_t;
35
36 class DEBUGGER : public DEVICE
37 {
38 private:
39         DEVICE *d_parent, *d_mem, *d_io;
40         DEBUGGER *d_child;
41         
42         void check_mem_break_points(break_point_t *bp, uint32_t addr, int length)
43         {
44                 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
45                         if(bp->table[i].status == 1) {
46                                 if(addr >= bp->table[i].addr && addr < bp->table[i].addr + length) {
47                                         bp->hit = now_suspended = true;
48                                         bp->hit_addr = bp->table[i].addr;
49                                         bp->restart = bp->table[i].check_point;
50                                         break;
51                                 }
52                         }
53                 }
54                 if(exception_happened && stop_on_exception) {
55                         now_suspended = true;
56                 }
57                 if(!now_suspended && d_child != NULL) {
58                         if(d_child->is_cpu()) {
59                                 d_child->check_break_points();
60                         }
61                         now_suspended = d_child->hit();
62                 }
63         }
64         void check_io_break_points(break_point_t *bp, uint32_t addr)
65         {
66                 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
67                         if(bp->table[i].status == 1) {
68                                 if((addr & bp->table[i].mask) == (bp->table[i].addr & bp->table[i].mask)) {
69                                         bp->hit = now_suspended = true;
70                                         bp->hit_addr = addr;
71                                         bp->restart = bp->table[i].check_point;
72                                         break;
73                                 }
74                         }
75                 }
76                 if(!now_suspended && d_child != NULL) {
77                         if(d_child->is_cpu()) {
78                                 d_child->check_break_points();
79                         }
80                         now_suspended = d_child->hit();
81                 }
82         }
83 public:
84         DEBUGGER(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
85         {
86                 memset(&bp, 0, sizeof(bp));
87                 memset(&rbp, 0, sizeof(rbp));
88                 memset(&wbp, 0, sizeof(wbp));
89                 memset(&ibp, 0, sizeof(ibp));
90                 memset(&obp, 0, sizeof(obp));
91                 first_symbol = last_symbol = NULL;
92                 my_tcscpy_s(file_path, _MAX_PATH, _T("debug.bin"));
93                 now_debugging = now_going = now_suspended = now_waiting = false;
94                 now_device_debugging = false;
95                 d_parent = NULL;
96                 d_child = NULL;
97                 memset(history, 0, sizeof(history));
98                 history_ptr = 0;
99                 memset(cpu_trace, 0xff, sizeof(cpu_trace));
100                 memset(cpu_trace_exp, 0x00, sizeof(cpu_trace_exp));
101                 memset(cpu_trace_exp_map, 0x00, sizeof(cpu_trace_exp_map));
102                 memset(cpu_trace_userdata, 0x00, sizeof(cpu_trace_userdata));
103                 exception_happened = false;
104                 stop_on_exception = true;
105                 prev_cpu_trace = 0xffffffff;
106                 cpu_trace_ptr = 0;
107                 cpu_trace_overwrap = false;
108                 set_device_name(_T("Debugger"));
109         }
110         ~DEBUGGER() {}
111         
112         // common functions
113         void initialize()
114         {
115                 for(DEVICE* device = vm->first_device; device; device = device->next_device) {
116                         if(device->get_debugger() == this) {
117                                 d_parent = device;
118                                 break;
119                         }
120                 }
121                 assert(d_parent != NULL);
122         }
123         void release()
124         {
125                 release_symbols();
126         }
127         void __FASTCALL write_data8(uint32_t addr, uint32_t data)
128         {
129                 d_mem->write_data8(addr, data);
130                 check_mem_break_points(&wbp, addr, 1);
131         }
132         uint32_t __FASTCALL read_data8(uint32_t addr)
133         {
134                 uint32_t val = d_mem->read_data8(addr);
135                 check_mem_break_points(&rbp, addr, 1);
136                 return val;
137         }
138         void __FASTCALL write_data16(uint32_t addr, uint32_t data)
139         {
140                 d_mem->write_data16(addr, data);
141                 check_mem_break_points(&wbp, addr, 2);
142         }
143         uint32_t __FASTCALL read_data16(uint32_t addr)
144         {
145                 uint32_t val = d_mem->read_data16(addr);
146                 check_mem_break_points(&rbp, addr, 2);
147                 return val;
148         }
149         void __FASTCALL write_data32(uint32_t addr, uint32_t data)
150         {
151                 d_mem->write_data32(addr, data);
152                 check_mem_break_points(&wbp, addr, 4);
153         }
154         uint32_t __FASTCALL read_data32(uint32_t addr)
155         {
156                 uint32_t val = d_mem->read_data32(addr);
157                 check_mem_break_points(&rbp, addr, 4);
158                 return val;
159         }
160         void __FASTCALL write_data8w(uint32_t addr, uint32_t data, int* wait)
161         {
162                 d_mem->write_data8w(addr, data, wait);
163                 check_mem_break_points(&wbp, addr, 1);
164         }
165         uint32_t __FASTCALL read_data8w(uint32_t addr, int* wait)
166         {
167                 uint32_t val = d_mem->read_data8w(addr, wait);
168                 check_mem_break_points(&rbp, addr, 1);
169                 return val;
170         }
171         void __FASTCALL write_data16w(uint32_t addr, uint32_t data, int* wait)
172         {
173                 d_mem->write_data16w(addr, data, wait);
174                 check_mem_break_points(&wbp, addr, 2);
175         }
176         uint32_t __FASTCALL read_data16w(uint32_t addr, int* wait)
177         {
178                 uint32_t val = d_mem->read_data16w(addr, wait);
179                 check_mem_break_points(&rbp, addr, 2);
180                 return val;
181         }
182         void __FASTCALL write_data32w(uint32_t addr, uint32_t data, int* wait)
183         {
184                 d_mem->write_data32w(addr, data, wait);
185                 check_mem_break_points(&wbp, addr, 4);
186         }
187         uint32_t __FASTCALL read_data32w(uint32_t addr, int* wait)
188         {
189                 uint32_t val = d_mem->read_data32w(addr, wait);
190                 check_mem_break_points(&rbp, addr, 4);
191                 return val;
192         }
193         uint32_t __FASTCALL fetch_op(uint32_t addr, int *wait)
194         {
195                 uint32_t val = d_mem->fetch_op(addr, wait);
196                 check_mem_break_points(&rbp, addr, 1);
197                 return val;
198         }
199         void __FASTCALL write_io8(uint32_t addr, uint32_t data)
200         {
201                 d_io->write_io8(addr, data);
202                 check_io_break_points(&obp, addr);
203         }
204         uint32_t __FASTCALL read_io8(uint32_t addr)
205         {
206                 uint32_t val = d_io->read_io8(addr);
207                 check_io_break_points(&ibp, addr);
208                 return val;
209         }
210         void __FASTCALL write_io16(uint32_t addr, uint32_t data)
211         {
212                 d_io->write_io16(addr, data);
213                 check_io_break_points(&obp, addr);
214         }
215         uint32_t __FASTCALL read_io16(uint32_t addr)
216         {
217                 uint32_t val = d_io->read_io16(addr);
218                 check_io_break_points(&ibp, addr);
219                 return val;
220         }
221         void __FASTCALL write_io32(uint32_t addr, uint32_t data)
222         {
223                 d_io->write_io32(addr, data);
224                 check_io_break_points(&obp, addr);
225         }
226         uint32_t __FASTCALL read_io32(uint32_t addr)
227         {
228                 uint32_t val = d_io->read_io32(addr);
229                 check_io_break_points(&ibp, addr);
230                 return val;
231         }
232         void __FASTCALL write_io8w(uint32_t addr, uint32_t data, int* wait)
233         {
234                 d_io->write_io8w(addr, data, wait);
235                 check_io_break_points(&obp, addr);
236         }
237         uint32_t __FASTCALL read_io8w(uint32_t addr, int* wait)
238         {
239                 uint32_t val = d_io->read_io8w(addr, wait);
240                 check_io_break_points(&ibp, addr);
241                 return val;
242         }
243         void __FASTCALL write_io16w(uint32_t addr, uint32_t data, int* wait)
244         {
245                 d_io->write_io16w(addr, data, wait);
246                 check_io_break_points(&obp, addr);
247         }
248         uint32_t __FASTCALL read_io16w(uint32_t addr, int* wait)
249         {
250                 uint32_t val = d_io->read_io16w(addr, wait);
251                 check_io_break_points(&ibp, addr);
252                 return val;
253         }
254         void __FASTCALL write_io32w(uint32_t addr, uint32_t data, int* wait)
255         {
256                 d_io->write_io32w(addr, data, wait);
257                 check_io_break_points(&obp, addr);
258         }
259         uint32_t __FASTCALL read_io32w(uint32_t addr, int* wait)
260         {
261                 uint32_t val = d_io->read_io32w(addr, wait);
262                 check_io_break_points(&ibp, addr);
263                 return val;
264         }
265         void __FASTCALL write_via_debugger_data8(uint32_t addr, uint32_t data)
266         {
267                 d_mem->write_via_debugger_data8(addr, data);
268                 check_mem_break_points(&wbp, addr, 1);
269         }
270         uint32_t __FASTCALL read_via_debugger_data8(uint32_t addr)
271         {
272                 uint32_t val = d_mem->read_via_debugger_data8(addr);
273                 check_mem_break_points(&rbp, addr, 1);
274                 return val;
275         }
276         void __FASTCALL write_via_debugger_data16(uint32_t addr, uint32_t data)
277         {
278                 d_mem->write_via_debugger_data16(addr, data);
279                 check_mem_break_points(&wbp, addr, 2);
280         }
281         uint32_t __FASTCALL read_via_debugger_data16(uint32_t addr)
282         {
283                 uint32_t val = d_mem->read_via_debugger_data16(addr);
284                 check_mem_break_points(&rbp, addr, 2);
285                 return val;
286         }
287         void __FASTCALL write_via_debugger_data32(uint32_t addr, uint32_t data)
288         {
289                 d_mem->write_via_debugger_data32(addr, data);
290                 check_mem_break_points(&wbp, addr, 4);
291         }
292         uint32_t __FASTCALL read_via_debugger_data32(uint32_t addr)
293         {
294                 uint32_t val = d_mem->read_via_debugger_data32(addr);
295                 check_mem_break_points(&rbp, addr, 4);
296                 return val;
297         }
298         void __FASTCALL write_via_debugger_data8w(uint32_t addr, uint32_t data, int* wait)
299         {
300                 d_mem->write_via_debugger_data8w(addr, data, wait);
301                 check_mem_break_points(&wbp, addr, 1);
302         }
303         uint32_t __FASTCALL read_via_debugger_data8w(uint32_t addr, int* wait)
304         {
305                 uint32_t val = d_mem->read_via_debugger_data8w(addr, wait);
306                 check_mem_break_points(&rbp, addr, 1);
307                 return val;
308         }
309         void __FASTCALL write_via_debugger_data16w(uint32_t addr, uint32_t data, int* wait)
310         {
311                 d_mem->write_via_debugger_data16w(addr, data, wait);
312                 check_mem_break_points(&wbp, addr, 2);
313         }
314         uint32_t __FASTCALL read_via_debugger_data16w(uint32_t addr, int* wait)
315         {
316                 uint32_t val = d_mem->read_via_debugger_data16w(addr, wait);
317                 check_mem_break_points(&rbp, addr, 2);
318                 return val;
319         }
320         void __FASTCALL write_via_debugger_data32w(uint32_t addr, uint32_t data, int* wait)
321         {
322                 d_mem->write_via_debugger_data32w(addr, data, wait);
323                 check_mem_break_points(&wbp, addr, 4);
324         }
325         uint32_t __FASTCALL read_via_debugger_data32w(uint32_t addr, int* wait)
326         {
327                 uint32_t val = d_mem->read_via_debugger_data32w(addr, wait);
328                 check_mem_break_points(&rbp, addr, 4);
329                 return val;
330         }
331         void __FASTCALL write_via_debugger_io8(uint32_t addr, uint32_t data)
332         {
333                 d_io->write_via_debugger_io8(addr, data);
334                 check_io_break_points(&obp, addr);
335         }
336         uint32_t __FASTCALL read_via_debugger_io8(uint32_t addr)
337         {
338                 uint32_t val = d_io->read_via_debugger_io8(addr);
339                 check_io_break_points(&ibp, addr);
340                 return val;
341         }
342         void __FASTCALL write_via_debugger_io16(uint32_t addr, uint32_t data)
343         {
344                 d_io->write_via_debugger_io16(addr, data);
345                 check_io_break_points(&obp, addr);
346         }
347         uint32_t __FASTCALL read_via_debugger_io16(uint32_t addr)
348         {
349                 uint32_t val = d_io->read_via_debugger_io16(addr);
350                 check_io_break_points(&ibp, addr);
351                 return val;
352         }
353         void __FASTCALL write_via_debugger_io32(uint32_t addr, uint32_t data)
354         {
355                 d_io->write_via_debugger_io32(addr, data);
356                 check_io_break_points(&obp, addr);
357         }
358         uint32_t __FASTCALL read_via_debugger_io32(uint32_t addr)
359         {
360                 uint32_t val = d_io->read_via_debugger_io32(addr);
361                 check_io_break_points(&ibp, addr);
362                 return val;
363         }
364         void __FASTCALL write_via_debugger_io8w(uint32_t addr, uint32_t data, int* wait)
365         {
366                 d_io->write_via_debugger_io8w(addr, data, wait);
367                 check_io_break_points(&obp, addr);
368         }
369         uint32_t __FASTCALL read_via_debugger_io8w(uint32_t addr, int* wait)
370         {
371                 uint32_t val = d_io->read_via_debugger_io8w(addr, wait);
372                 check_io_break_points(&ibp, addr);
373                 return val;
374         }
375         void __FASTCALL write_via_debugger_io16w(uint32_t addr, uint32_t data, int* wait)
376         {
377                 d_io->write_via_debugger_io16w(addr, data, wait);
378                 check_io_break_points(&obp, addr);
379         }
380         uint32_t __FASTCALL read_via_debugger_io16w(uint32_t addr, int* wait)
381         {
382                 uint32_t val = d_io->read_via_debugger_io16w(addr, wait);
383                 check_io_break_points(&ibp, addr);
384                 return val;
385         }
386         void __FASTCALL write_via_debugger_io32w(uint32_t addr, uint32_t data, int* wait)
387         {
388                 d_io->write_via_debugger_io32w(addr, data, wait);
389                 check_io_break_points(&obp, addr);
390         }
391         uint32_t __FASTCALL read_via_debugger_io32w(uint32_t addr, int* wait)
392         {
393                 uint32_t val = d_io->read_via_debugger_io32w(addr, wait);
394                 check_io_break_points(&ibp, addr);
395                 return val;
396         }
397         bool is_debugger()
398         {
399                 return true;
400         }
401
402         // unique functions
403         void set_context_mem(DEVICE* device)
404         {
405                 d_mem = device;
406         }
407         void set_context_io(DEVICE* device)
408         {
409                 d_io = device;
410         }
411         void set_context_child(DEBUGGER* device)
412         {
413                 d_child = device;
414         }
415         void check_break_points(uint32_t addr)
416         {
417                 check_mem_break_points(&bp, addr, 1);
418         }
419         void check_break_points()
420         {
421                 check_mem_break_points(&bp, d_parent->get_next_pc(), 1);
422         }
423         void store_break_points()
424         {
425                 if(d_child != NULL) {
426                         d_child->store_break_points();
427                 }
428                 memcpy( bp.stored,  bp.table, sizeof( bp.table));
429                 memcpy(rbp.stored, rbp.table, sizeof(rbp.table));
430                 memcpy(wbp.stored, wbp.table, sizeof(wbp.table));
431                 memcpy(ibp.stored, ibp.table, sizeof(ibp.table));
432                 memcpy(obp.stored, obp.table, sizeof(obp.table));
433                 memset( bp.table, 0, sizeof( bp.table));
434                 memset(rbp.table, 0, sizeof(rbp.table));
435                 memset(wbp.table, 0, sizeof(wbp.table));
436                 memset(ibp.table, 0, sizeof(ibp.table));
437                 memset(obp.table, 0, sizeof(obp.table));
438         }
439         void restore_break_points()
440         {
441                 if(d_child != NULL) {
442                         d_child->restore_break_points();
443                 }
444                 memcpy( bp.table,  bp.stored, sizeof( bp.table));
445                 memcpy(rbp.table, rbp.stored, sizeof(rbp.table));
446                 memcpy(wbp.table, wbp.stored, sizeof(wbp.table));
447                 memcpy(ibp.table, ibp.stored, sizeof(ibp.table));
448                 memcpy(obp.table, obp.stored, sizeof(obp.table));
449         }
450         bool hit()
451         {
452                 if(d_child != NULL && d_child->hit()) {
453                         return true;
454                 }
455                 return (bp.hit || rbp.hit || wbp.hit || ibp.hit || obp.hit);
456         }
457         bool restartable()
458         {
459                 if(d_child != NULL && !d_child->restartable()) {
460                         return false;
461                 }
462                 if( bp.hit && ! bp.restart) return false;
463                 if(rbp.hit && !rbp.restart) return false;
464                 if(wbp.hit && !wbp.restart) return false;
465                 if(ibp.hit && !ibp.restart) return false;
466                 if(obp.hit && !obp.restart) return false;
467                 return true;
468         }
469         void clear_hit()
470         {
471                 if(d_child != NULL) {
472                         d_child->clear_hit();
473                 }
474                 bp.hit = rbp.hit = wbp.hit = ibp.hit = obp.hit = false;
475         }
476         void add_symbol(uint32_t addr, const _TCHAR *name)
477         {
478                 symbol_t *symbol = (symbol_t *)calloc(sizeof(symbol_t), 1);
479                 symbol->addr = addr;
480                 symbol->name = (_TCHAR *)calloc(sizeof(_TCHAR), _tcslen(name) + 1);
481                 my_tcscpy_s(symbol->name, _tcslen(name) + 1, name);
482                 
483                 if(first_symbol == NULL) {
484                         first_symbol = symbol;
485                 } else {
486                         last_symbol->next_symbol = symbol;
487                 }
488                 last_symbol = symbol;
489         }
490         void release_symbols()
491         {
492                 for(symbol_t* symbol = first_symbol; symbol;) {
493                         symbol_t *next_symbol = symbol->next_symbol;
494                         if(symbol->name != NULL) {
495                                 free(symbol->name);
496                         }
497                         free(symbol);
498                         symbol = next_symbol;
499                 }
500                 first_symbol = last_symbol = NULL;
501         }
502         void add_cpu_trace_exception(uint64_t exception_code)
503         {
504                 cpu_trace_exp[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] = exception_code; 
505                 cpu_trace_exp_map[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] = true; 
506         }
507         // Userdata should after executing instruction.
508         void add_cpu_trace_userdata(uint32_t data, uint32_t mask)
509         {
510                 cpu_trace_userdata[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] &= ~mask;
511                 cpu_trace_userdata[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] |= (data & mask);
512         }
513         void add_cpu_trace(uint32_t pc)
514         {
515                 if(prev_cpu_trace != pc) {
516                         cpu_trace_exp_map[cpu_trace_ptr] = false; 
517                         cpu_trace_userdata[cpu_trace_ptr] = 0; 
518                         cpu_trace_exp[cpu_trace_ptr] = 0; 
519                         cpu_trace[cpu_trace_ptr++] = prev_cpu_trace = pc;
520                         if(cpu_trace_ptr >= MAX_CPU_TRACE) {
521                                 cpu_trace_overwrap = true;
522                                 cpu_trace_ptr = 0;
523                         }
524                 }
525         }
526         break_point_t bp, rbp, wbp, ibp, obp;
527         symbol_t *first_symbol, *last_symbol;
528         _TCHAR file_path[_MAX_PATH];
529         bool now_debugging, now_going, now_suspended, now_waiting, exception_happened;
530         uint64_t exception_code;
531         uint32_t exception_pc;
532         bool stop_on_exception;
533         bool now_device_debugging; // for non-cpu devices
534         _TCHAR history[MAX_COMMAND_HISTORY][MAX_COMMAND_LENGTH + 1];
535         int history_ptr;
536         uint32_t cpu_trace[MAX_CPU_TRACE], prev_cpu_trace;
537         uint64_t cpu_trace_exp[MAX_CPU_TRACE];
538         uint32_t cpu_trace_userdata[MAX_CPU_TRACE]; // ToDo: Is need larger userdata?
539         
540         bool cpu_trace_exp_map[MAX_CPU_TRACE];
541         int cpu_trace_ptr;
542         bool cpu_trace_overwrap;
543 };
544
545 //#endif
546 #endif
547