2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
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 */
29 int status; // 0 = none, 1 = enabled, other = disabled
31 } table[MAX_BREAK_POINTS], stored[MAX_BREAK_POINTS];
36 class DEBUGGER : public DEVICE
39 DEVICE *d_parent, *d_mem, *d_io;
42 void check_mem_break_points(break_point_t *bp, uint32_t addr, int length)
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;
54 if(exception_happened && stop_on_exception) {
57 if(!now_suspended && d_child != NULL) {
58 if(d_child->is_cpu()) {
59 d_child->check_break_points();
61 now_suspended = d_child->hit();
64 void check_io_break_points(break_point_t *bp, uint32_t addr)
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;
71 bp->restart = bp->table[i].check_point;
76 if(!now_suspended && d_child != NULL) {
77 if(d_child->is_cpu()) {
78 d_child->check_break_points();
80 now_suspended = d_child->hit();
84 DEBUGGER(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
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;
97 memset(history, 0, sizeof(history));
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;
107 cpu_trace_overwrap = false;
108 set_device_name(_T("Debugger"));
115 for(DEVICE* device = vm->first_device; device; device = device->next_device) {
116 if(device->get_debugger() == this) {
121 assert(d_parent != NULL);
127 void __FASTCALL write_data8(uint32_t addr, uint32_t data)
129 d_mem->write_data8(addr, data);
130 check_mem_break_points(&wbp, addr, 1);
132 uint32_t __FASTCALL read_data8(uint32_t addr)
134 uint32_t val = d_mem->read_data8(addr);
135 check_mem_break_points(&rbp, addr, 1);
138 void __FASTCALL write_data16(uint32_t addr, uint32_t data)
140 d_mem->write_data16(addr, data);
141 check_mem_break_points(&wbp, addr, 2);
143 uint32_t __FASTCALL read_data16(uint32_t addr)
145 uint32_t val = d_mem->read_data16(addr);
146 check_mem_break_points(&rbp, addr, 2);
149 void __FASTCALL write_data32(uint32_t addr, uint32_t data)
151 d_mem->write_data32(addr, data);
152 check_mem_break_points(&wbp, addr, 4);
154 uint32_t __FASTCALL read_data32(uint32_t addr)
156 uint32_t val = d_mem->read_data32(addr);
157 check_mem_break_points(&rbp, addr, 4);
160 void __FASTCALL write_data8w(uint32_t addr, uint32_t data, int* wait)
162 d_mem->write_data8w(addr, data, wait);
163 check_mem_break_points(&wbp, addr, 1);
165 uint32_t __FASTCALL read_data8w(uint32_t addr, int* wait)
167 uint32_t val = d_mem->read_data8w(addr, wait);
168 check_mem_break_points(&rbp, addr, 1);
171 void __FASTCALL write_data16w(uint32_t addr, uint32_t data, int* wait)
173 d_mem->write_data16w(addr, data, wait);
174 check_mem_break_points(&wbp, addr, 2);
176 uint32_t __FASTCALL read_data16w(uint32_t addr, int* wait)
178 uint32_t val = d_mem->read_data16w(addr, wait);
179 check_mem_break_points(&rbp, addr, 2);
182 void __FASTCALL write_data32w(uint32_t addr, uint32_t data, int* wait)
184 d_mem->write_data32w(addr, data, wait);
185 check_mem_break_points(&wbp, addr, 4);
187 uint32_t __FASTCALL read_data32w(uint32_t addr, int* wait)
189 uint32_t val = d_mem->read_data32w(addr, wait);
190 check_mem_break_points(&rbp, addr, 4);
193 uint32_t __FASTCALL fetch_op(uint32_t addr, int *wait)
195 uint32_t val = d_mem->fetch_op(addr, wait);
196 check_mem_break_points(&rbp, addr, 1);
199 void __FASTCALL write_io8(uint32_t addr, uint32_t data)
201 d_io->write_io8(addr, data);
202 check_io_break_points(&obp, addr);
204 uint32_t __FASTCALL read_io8(uint32_t addr)
206 uint32_t val = d_io->read_io8(addr);
207 check_io_break_points(&ibp, addr);
210 void __FASTCALL write_io16(uint32_t addr, uint32_t data)
212 d_io->write_io16(addr, data);
213 check_io_break_points(&obp, addr);
215 uint32_t __FASTCALL read_io16(uint32_t addr)
217 uint32_t val = d_io->read_io16(addr);
218 check_io_break_points(&ibp, addr);
221 void __FASTCALL write_io32(uint32_t addr, uint32_t data)
223 d_io->write_io32(addr, data);
224 check_io_break_points(&obp, addr);
226 uint32_t __FASTCALL read_io32(uint32_t addr)
228 uint32_t val = d_io->read_io32(addr);
229 check_io_break_points(&ibp, addr);
232 void __FASTCALL write_io8w(uint32_t addr, uint32_t data, int* wait)
234 d_io->write_io8w(addr, data, wait);
235 check_io_break_points(&obp, addr);
237 uint32_t __FASTCALL read_io8w(uint32_t addr, int* wait)
239 uint32_t val = d_io->read_io8w(addr, wait);
240 check_io_break_points(&ibp, addr);
243 void __FASTCALL write_io16w(uint32_t addr, uint32_t data, int* wait)
245 d_io->write_io16w(addr, data, wait);
246 check_io_break_points(&obp, addr);
248 uint32_t __FASTCALL read_io16w(uint32_t addr, int* wait)
250 uint32_t val = d_io->read_io16w(addr, wait);
251 check_io_break_points(&ibp, addr);
254 void __FASTCALL write_io32w(uint32_t addr, uint32_t data, int* wait)
256 d_io->write_io32w(addr, data, wait);
257 check_io_break_points(&obp, addr);
259 uint32_t __FASTCALL read_io32w(uint32_t addr, int* wait)
261 uint32_t val = d_io->read_io32w(addr, wait);
262 check_io_break_points(&ibp, addr);
265 void __FASTCALL write_via_debugger_data8(uint32_t addr, uint32_t data)
267 d_mem->write_via_debugger_data8(addr, data);
268 check_mem_break_points(&wbp, addr, 1);
270 uint32_t __FASTCALL read_via_debugger_data8(uint32_t addr)
272 uint32_t val = d_mem->read_via_debugger_data8(addr);
273 check_mem_break_points(&rbp, addr, 1);
276 void __FASTCALL write_via_debugger_data16(uint32_t addr, uint32_t data)
278 d_mem->write_via_debugger_data16(addr, data);
279 check_mem_break_points(&wbp, addr, 2);
281 uint32_t __FASTCALL read_via_debugger_data16(uint32_t addr)
283 uint32_t val = d_mem->read_via_debugger_data16(addr);
284 check_mem_break_points(&rbp, addr, 2);
287 void __FASTCALL write_via_debugger_data32(uint32_t addr, uint32_t data)
289 d_mem->write_via_debugger_data32(addr, data);
290 check_mem_break_points(&wbp, addr, 4);
292 uint32_t __FASTCALL read_via_debugger_data32(uint32_t addr)
294 uint32_t val = d_mem->read_via_debugger_data32(addr);
295 check_mem_break_points(&rbp, addr, 4);
298 void __FASTCALL write_via_debugger_data8w(uint32_t addr, uint32_t data, int* wait)
300 d_mem->write_via_debugger_data8w(addr, data, wait);
301 check_mem_break_points(&wbp, addr, 1);
303 uint32_t __FASTCALL read_via_debugger_data8w(uint32_t addr, int* wait)
305 uint32_t val = d_mem->read_via_debugger_data8w(addr, wait);
306 check_mem_break_points(&rbp, addr, 1);
309 void __FASTCALL write_via_debugger_data16w(uint32_t addr, uint32_t data, int* wait)
311 d_mem->write_via_debugger_data16w(addr, data, wait);
312 check_mem_break_points(&wbp, addr, 2);
314 uint32_t __FASTCALL read_via_debugger_data16w(uint32_t addr, int* wait)
316 uint32_t val = d_mem->read_via_debugger_data16w(addr, wait);
317 check_mem_break_points(&rbp, addr, 2);
320 void __FASTCALL write_via_debugger_data32w(uint32_t addr, uint32_t data, int* wait)
322 d_mem->write_via_debugger_data32w(addr, data, wait);
323 check_mem_break_points(&wbp, addr, 4);
325 uint32_t __FASTCALL read_via_debugger_data32w(uint32_t addr, int* wait)
327 uint32_t val = d_mem->read_via_debugger_data32w(addr, wait);
328 check_mem_break_points(&rbp, addr, 4);
331 void __FASTCALL write_via_debugger_io8(uint32_t addr, uint32_t data)
333 d_io->write_via_debugger_io8(addr, data);
334 check_io_break_points(&obp, addr);
336 uint32_t __FASTCALL read_via_debugger_io8(uint32_t addr)
338 uint32_t val = d_io->read_via_debugger_io8(addr);
339 check_io_break_points(&ibp, addr);
342 void __FASTCALL write_via_debugger_io16(uint32_t addr, uint32_t data)
344 d_io->write_via_debugger_io16(addr, data);
345 check_io_break_points(&obp, addr);
347 uint32_t __FASTCALL read_via_debugger_io16(uint32_t addr)
349 uint32_t val = d_io->read_via_debugger_io16(addr);
350 check_io_break_points(&ibp, addr);
353 void __FASTCALL write_via_debugger_io32(uint32_t addr, uint32_t data)
355 d_io->write_via_debugger_io32(addr, data);
356 check_io_break_points(&obp, addr);
358 uint32_t __FASTCALL read_via_debugger_io32(uint32_t addr)
360 uint32_t val = d_io->read_via_debugger_io32(addr);
361 check_io_break_points(&ibp, addr);
364 void __FASTCALL write_via_debugger_io8w(uint32_t addr, uint32_t data, int* wait)
366 d_io->write_via_debugger_io8w(addr, data, wait);
367 check_io_break_points(&obp, addr);
369 uint32_t __FASTCALL read_via_debugger_io8w(uint32_t addr, int* wait)
371 uint32_t val = d_io->read_via_debugger_io8w(addr, wait);
372 check_io_break_points(&ibp, addr);
375 void __FASTCALL write_via_debugger_io16w(uint32_t addr, uint32_t data, int* wait)
377 d_io->write_via_debugger_io16w(addr, data, wait);
378 check_io_break_points(&obp, addr);
380 uint32_t __FASTCALL read_via_debugger_io16w(uint32_t addr, int* wait)
382 uint32_t val = d_io->read_via_debugger_io16w(addr, wait);
383 check_io_break_points(&ibp, addr);
386 void __FASTCALL write_via_debugger_io32w(uint32_t addr, uint32_t data, int* wait)
388 d_io->write_via_debugger_io32w(addr, data, wait);
389 check_io_break_points(&obp, addr);
391 uint32_t __FASTCALL read_via_debugger_io32w(uint32_t addr, int* wait)
393 uint32_t val = d_io->read_via_debugger_io32w(addr, wait);
394 check_io_break_points(&ibp, addr);
403 void set_context_mem(DEVICE* device)
407 void set_context_io(DEVICE* device)
411 void set_context_child(DEBUGGER* device)
415 void check_break_points(uint32_t addr)
417 check_mem_break_points(&bp, addr, 1);
419 void check_break_points()
421 check_mem_break_points(&bp, d_parent->get_next_pc(), 1);
423 void store_break_points()
425 if(d_child != NULL) {
426 d_child->store_break_points();
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));
439 void restore_break_points()
441 if(d_child != NULL) {
442 d_child->restore_break_points();
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));
452 if(d_child != NULL && d_child->hit()) {
455 return (bp.hit || rbp.hit || wbp.hit || ibp.hit || obp.hit);
459 if(d_child != NULL && !d_child->restartable()) {
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;
471 if(d_child != NULL) {
472 d_child->clear_hit();
474 bp.hit = rbp.hit = wbp.hit = ibp.hit = obp.hit = false;
476 void add_symbol(uint32_t addr, const _TCHAR *name)
478 symbol_t *symbol = (symbol_t *)calloc(sizeof(symbol_t), 1);
480 symbol->name = (_TCHAR *)calloc(sizeof(_TCHAR), _tcslen(name) + 1);
481 my_tcscpy_s(symbol->name, _tcslen(name) + 1, name);
483 if(first_symbol == NULL) {
484 first_symbol = symbol;
486 last_symbol->next_symbol = symbol;
488 last_symbol = symbol;
490 void release_symbols()
492 for(symbol_t* symbol = first_symbol; symbol;) {
493 symbol_t *next_symbol = symbol->next_symbol;
494 if(symbol->name != NULL) {
498 symbol = next_symbol;
500 first_symbol = last_symbol = NULL;
502 void add_cpu_trace_exception(uint64_t exception_code)
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;
507 // Userdata should after executing instruction.
508 void add_cpu_trace_userdata(uint32_t data, uint32_t mask)
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);
513 void add_cpu_trace(uint32_t pc)
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;
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];
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?
540 bool cpu_trace_exp_map[MAX_CPU_TRACE];
542 bool cpu_trace_overwrap;