1 // DGen
2 // Tooling to help debug.
3 // (C) 2012 Edd Barrett <vext01@gmail.com>
4
5 #include <errno.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <stdint.h>
11 #include <assert.h>
12
13 #ifdef WITH_MUSA
14 extern "C" {
15 #include "musa/m68k.h"
16 }
17 #endif
18
19 #ifdef WITH_DZ80
20 #include "dz80/types.h"
21 #include "dz80/dissz80.h"
22 #endif
23
24 #include "pd.h"
25 #include "md.h"
26 #include "system.h"
27 #include "debug.h"
28 #include "linenoise/linenoise.h"
29
30 static const char *debug_context_names[] = {
31 "M68K", "Z80", "YM2612", "SN76489"
32 };
33
34 /**
35 * Aliases for the various cores.
36 * @{
37 */
38 /** Aliases for SN76489 core. */
39 const char *psg_aliases[] = { "sn", "sn76489", "psg", NULL };
40 /** Aliases for YM2612 core. */
41 const char *fm_aliases[] = { "fm", "ym", "ym2612", NULL };
42 /** Aliases for Z80 core. */
43 const char *z80_aliases[] = { "z80", "z", NULL};
44 /** Aliases for M68K core. */
45 const char *m68k_aliases[] = { "m68k", "m", "68000", "m68000", NULL};
46 /** @} */
47
48 #define CURRENT_DEBUG_CONTEXT_NAME debug_context_names[debug_context]
49
50 // ===[ C Functions ]=========================================================
51
52 /**
53 * Linenoise completion callback.
54 *
55 * @param buf String so far.
56 * @param lc List of linenoise completions.
57 */
58 #ifndef NO_COMPLETION
completion(const char * buf,linenoiseCompletions * lc)59 void completion(const char *buf, linenoiseCompletions *lc) {
60
61 const struct md::dgen_debugger_cmd *cmd = md::debug_cmd_list;
62
63 while (cmd->cmd != NULL) {
64 if (strlen(cmd->cmd) != 1) {
65 if (buf[0] == cmd->cmd[0]) {
66 linenoiseAddCompletion(lc, cmd->cmd);
67 }
68 }
69 cmd++;
70 }
71 }
72 #endif
73
74 #ifdef WITH_MUSA
75 /** @{ Callbacks for Musashi. */
m68k_read_disassembler_8(unsigned int addr)76 uint32_t m68k_read_disassembler_8(unsigned int addr)
77 {
78 return m68k_read_memory_8(addr);
79 }
80
m68k_read_disassembler_16(unsigned int addr)81 uint32_t m68k_read_disassembler_16(unsigned int addr)
82 {
83 return m68k_read_memory_16(addr);
84 }
85
m68k_read_disassembler_32(unsigned int addr)86 uint32_t m68k_read_disassembler_32(unsigned int addr)
87 {
88 return m68k_read_memory_32(addr);
89 }
90 /** @} */
91 #endif
92
93 /**
94 * A simple wrapper around strtoul() with error check.
95 *
96 * @param[in] str String to convert to number.
97 * @param[out] ret Number "str" represents.
98 * @return -1 on error.
99 */
debug_strtou32(const char * str,uint32_t * ret)100 static int debug_strtou32(const char *str, uint32_t *ret)
101 {
102 char *end = NULL;
103
104 errno = 0;
105 *ret = (uint32_t)strtoul(str, &end, 0);
106
107 if (errno) {
108 perror("strtoul");
109 return (-1);
110 }
111
112 if (end == str)
113 return (-1);
114
115 return (0);
116 }
117
118 /**
119 * Check if at least one M68K breakpoint is set.
120 *
121 * @return 1 if true, 0 otherwise.
122 */
debug_is_m68k_bp_set()123 bool md::debug_is_m68k_bp_set()
124 {
125 if (debug_bp_m68k[0].flags & BP_FLAG_USED)
126 return (1);
127
128 return (0);
129 }
130
131 /**
132 * Check if at least one Z80 breakpoint is set.
133 *
134 * @return 1 if true, 0 otherwise.
135 */
debug_is_z80_bp_set()136 bool md::debug_is_z80_bp_set()
137 {
138 if (debug_bp_z80[0].flags & BP_FLAG_USED)
139 return 1;
140 return 0;
141 }
142
143 /**
144 * Check if at least one M68K watchpoint is set.
145 *
146 * @return 1 if true, 0 otherwise.
147 */
debug_is_m68k_wp_set()148 bool md::debug_is_m68k_wp_set()
149 {
150 if (debug_wp_m68k[0].flags & BP_FLAG_USED)
151 return (1);
152
153 return (0);
154 }
155
156 /**
157 * Check if at least one Z80 watchpoint is set.
158 *
159 * @return 1 if true, 0 otherwise.
160 */
debug_is_z80_wp_set()161 bool md::debug_is_z80_wp_set()
162 {
163 if (debug_wp_z80[0].flags & BP_FLAG_USED)
164 return 1;
165 return 0;
166 }
167
168 /**
169 * Get the ID of the next free M68K watchpoint.
170 *
171 * @return ID or -1 if none free.
172 */
debug_next_free_wp_m68k()173 int md::debug_next_free_wp_m68k()
174 {
175 int i;
176
177 for (i = 0; i < MAX_WATCHPOINTS; i++) {
178 if (!(debug_wp_m68k[i].flags & WP_FLAG_USED))
179 return (i);
180 }
181
182 return (-1); // no free slots
183 }
184
185 /**
186 * Get the ID of the next free Z80 watchpoint.
187 *
188 * @return ID or -1 if none free.
189 */
debug_next_free_wp_z80()190 int md::debug_next_free_wp_z80()
191 {
192 unsigned int i;
193
194 for (i = 0; (i < MAX_WATCHPOINTS); ++i)
195 if (!(debug_wp_z80[i].flags & WP_FLAG_USED))
196 return i;
197 return -1;
198 }
199
200 /**
201 * Get the ID of the next free M68K breakpoint.
202 *
203 * @return ID or -1 if none free.
204 */
debug_next_free_bp_m68k()205 int md::debug_next_free_bp_m68k()
206 {
207 int i;
208
209 for (i = 0; i < MAX_BREAKPOINTS; i++) {
210 if (!(debug_bp_m68k[i].flags & BP_FLAG_USED))
211 return (i);
212 }
213
214 return (-1); // no free slots
215 }
216
217 #ifdef WITH_DZ80
218
disz80_read(void * ctx,WORD addr)219 static BYTE disz80_read(void *ctx, WORD addr)
220 {
221 class md *md = (class md *)ctx;
222
223 return md->z80_read(addr);
224 }
225
226 #endif
227
228 /**
229 * Get the ID of the next free Z80 breakpoint.
230 *
231 * @return ID or -1 if none free.
232 */
debug_next_free_bp_z80()233 int md::debug_next_free_bp_z80()
234 {
235 unsigned int i;
236
237 for (i = 0; (i < MAX_BREAKPOINTS); ++i)
238 if (!(debug_bp_z80[i].flags & BP_FLAG_USED))
239 return i;
240 return -1;
241 }
242
243 /**
244 * Initialise the debugger.
245 *
246 * All breakpoints are disabled by default.
247 */
debug_init()248 void md::debug_init()
249 {
250 // start with all breakpoints and watchpoints disabled
251 memset(debug_bp_m68k, 0, sizeof(debug_bp_m68k));
252 memset(debug_wp_m68k, 0, sizeof(debug_wp_m68k));
253 memset(debug_bp_z80, 0, sizeof(debug_bp_z80));
254 memset(debug_wp_z80, 0, sizeof(debug_wp_z80));
255
256 #ifndef NO_COMPLETION
257 linenoiseSetCompletionCallback(completion);
258 #endif
259
260 debug_step_m68k = 0;
261 debug_trace_m68k = 0;
262 debug_step_z80 = 0;
263 debug_trace_z80 = 0;
264 debug_context = DBG_CONTEXT_M68K;
265 debug_trap = false;
266 debug_m68k_instr_count = 0;
267 debug_z80_instr_count = 0;
268 debug_instr_count_enabled = false;
269
270 #ifdef WITH_DZ80
271 memset(&disz80, 0, sizeof(disz80));
272 dZ80_SetDefaultOptions(&disz80);
273 disz80.cpuType = DCPU_Z80;
274 disz80.flags = (DISFLAG_SINGLE | DISFLAG_CALLBACK);
275 disz80.mem0Start = (BYTE *)this;
276 disz80.memCB = disz80_read;
277 #endif
278 }
279
280 /**
281 * Find the index of a M68K breakpoint.
282 *
283 * @param addr Address to look for.
284 * @return -1 if no breakpoint is found, otherwise its index in
285 * debug_bp_m68k[].
286 */
debug_find_bp_m68k(uint32_t addr)287 int md::debug_find_bp_m68k(uint32_t addr)
288 {
289 int i;
290
291 for (i = 0; i < MAX_BREAKPOINTS; i++) {
292
293 if (!(debug_bp_m68k[i].flags & BP_FLAG_USED))
294 break;
295
296 if (debug_bp_m68k[i].addr == addr)
297 return (i);
298 }
299
300 return (-1); // not found
301 }
302
303 /**
304 * Find the index of a Z80 breakpoint.
305 *
306 * @param addr Address to look for.
307 * @return -1 if no breakpoint is found, otherwise its index in
308 * debug_bp_z80[].
309 */
debug_find_bp_z80(uint16_t addr)310 int md::debug_find_bp_z80(uint16_t addr)
311 {
312 unsigned int i;
313
314 for (i = 0; (i < MAX_BREAKPOINTS); ++i) {
315 if (!(debug_bp_z80[i].flags & BP_FLAG_USED))
316 break;
317 if (debug_bp_z80[i].addr == addr)
318 return i;
319 }
320 return -1;
321 }
322
323 /**
324 * Find the index of a M68K watchpoint by its start address.
325 *
326 * @param addr Address to look for.
327 * @return -1 if no watchpoint at the given address, otherwise its index in
328 * debug_wp_m68k[].
329 */
debug_find_wp_m68k(uint32_t addr)330 int md::debug_find_wp_m68k(uint32_t addr)
331 {
332 int i;
333
334 for (i = 0; i < MAX_WATCHPOINTS; i++) {
335
336 if (!(debug_wp_m68k[i].flags & WP_FLAG_USED))
337 break;
338
339 if (debug_wp_m68k[i].start_addr == addr)
340 return (i);
341 }
342
343 return (-1); // not found
344 }
345
346 /**
347 * Find the index of a Z80 watchpoint by its start address.
348 *
349 * @param addr Address to look for.
350 * @return -1 if no watchpoint at the given address, otherwise its index in
351 * debug_wp_z80[].
352 */
debug_find_wp_z80(uint16_t addr)353 int md::debug_find_wp_z80(uint16_t addr)
354 {
355 unsigned int i;
356
357 for (i = 0; (i < MAX_WATCHPOINTS); ++i) {
358 if (!(debug_wp_z80[i].flags & WP_FLAG_USED))
359 break;
360 if (debug_wp_z80[i].start_addr == addr)
361 return i;
362 }
363 return -1;
364 }
365
366 /**
367 * Pretty prints hex dump.
368 *
369 * @param[in] buf Buffer to pretty print.
370 * @param len Number of bytes to print.
371 * @param addr_label_start The address of the first byte.
372 */
debug_print_hex_buf(unsigned char * buf,size_t len,size_t addr_label_start)373 static void debug_print_hex_buf(
374 unsigned char *buf, size_t len, size_t addr_label_start)
375 {
376 uint32_t i, done = 0;
377 unsigned char byte;
378 char ascii[17], *ap, *hp;
379 char hdr[60] = " ";
380 char hex[] = "0123456789abcdef";
381
382 // header
383 for (i = 0; i < 16; i++) {
384 hp = strchr(hdr, '\0');
385 hp[0] = hex[(addr_label_start + i) % 16];
386 hp[1] = ' ';
387 hp[2] = ' ';
388 hp[3] = '\0';
389 }
390 printf("%s\n", hdr);
391
392 // process lines of 16 bytes
393 ap = ascii;
394 for (i = 0; i < len; i++, done++, ap++) {
395
396 if (i % 16 == 0) {
397 ascii[16] = '\0';
398
399 if (i > 0)
400 printf(" |%s|\n", ascii);
401
402 printf("0x%08x: ", (uint32_t) addr_label_start + i);
403 ap = ascii;
404 }
405
406 byte = buf[i];
407 // 0x20 to 0x7e is printable ascii
408 if ((byte >= 0x20) && (byte <= 0x7e))
409 *ap = byte;
410 else
411 *ap = '.';
412
413 printf("%02x ", byte);
414 }
415
416 // make it all line up
417 if (i % 16) {
418 ascii[(i % 16)] = '\0';
419 i = i % 16;
420 while (i <= 15) {
421 printf(" ");
422 i++;
423 }
424 }
425
426 // print rest of ascii
427 printf(" |%s|\n", ascii);
428 fflush(stdout);
429 }
430
431 /**
432 * Print a M68K watchpoint in a human-readable form.
433 *
434 * @param idx Index of watchpoint to print.
435 */
debug_print_m68k_wp(int idx)436 void md::debug_print_m68k_wp(int idx)
437 {
438 struct dgen_wp *w = &(debug_wp_m68k[idx]);
439
440 printf("#%0d:\t0x%08x-%08x (%u bytes)\n", idx,
441 w->start_addr, w->end_addr, w->end_addr - w->start_addr + 1);
442
443 debug_print_hex_buf(w->bytes, w->end_addr - w->start_addr + 1, w->start_addr);
444 fflush(stdout);
445 }
446
447 /**
448 * Print a Z80 watchpoint in a human-readable form.
449 *
450 * @param idx Index of watchpoint to print.
451 */
debug_print_z80_wp(int idx)452 void md::debug_print_z80_wp(int idx)
453 {
454 struct dgen_wp *w = &debug_wp_z80[idx];
455
456 printf("#%0d:\t0x%04x-%04x (%u bytes)\n", idx, w->start_addr,
457 w->end_addr, (w->end_addr - w->start_addr + 1));
458 debug_print_hex_buf(w->bytes, (w->end_addr - w->start_addr + 1),
459 w->start_addr);
460 fflush(stdout);
461 }
462
463 /**
464 * Check the given M68K watchpoint against cached memory to see if it should
465 * fire.
466 *
467 * @param[in] w Watch point to check.
468 * @return 1 if true, else 0.
469 */
debug_should_m68k_wp_fire(struct dgen_wp * w)470 int md::debug_should_m68k_wp_fire(struct dgen_wp *w)
471 {
472 unsigned int i;
473 unsigned char *p;
474
475 for (i = w->start_addr, p = w->bytes; i <= w->end_addr; i++, p++) {
476 if (misc_readbyte(i) != *p)
477 return (1); // hit
478 }
479
480 return (0);
481 }
482
483 /**
484 * Check the given Z80 watchpoint against cached memory to see if it should
485 * fire.
486 *
487 * @param[in] w Watch point to check.
488 * @return 1 if true, else 0.
489 */
debug_should_z80_wp_fire(struct dgen_wp * w)490 int md::debug_should_z80_wp_fire(struct dgen_wp *w)
491 {
492 unsigned int i = w->start_addr;
493 unsigned char *p = w->bytes;
494
495 while (i <= w->end_addr)
496 if (z80_read(i++) != *p++)
497 return 1;
498 return 0;
499 }
500
501 /**
502 * Get M68K PC.
503 *
504 * @return Current PC.
505 */
m68k_get_pc()506 uint32_t md::m68k_get_pc()
507 {
508 m68k_state_dump();
509 return le2h32(m68k_state.pc);
510 }
511
512 /**
513 * Get Z80 PC.
514 *
515 * @return Current PC.
516 */
z80_get_pc()517 uint16_t md::z80_get_pc()
518 {
519 z80_state_dump();
520 return le2h16(z80_state.pc);
521 }
522
523 /**
524 * Breakpoint handler fired before every M68K instruction.
525 */
debug_m68k_check_bps()526 bool md::debug_m68k_check_bps()
527 {
528 uint32_t pc = m68k_get_pc();
529 unsigned int i;
530 bool bp = false;
531
532 if (debug_step_m68k) {
533 if ((--debug_step_m68k) == 0) {
534 debug_enter();
535 bp = true;
536 }
537 goto trace;
538 }
539 for (i = 0; (i < MAX_BREAKPOINTS); i++) {
540 if (!(debug_bp_m68k[i].flags & BP_FLAG_USED))
541 break; // no bps after first disabled one
542 if (pc == debug_bp_m68k[i].addr) {
543 if (debug_bp_m68k[i].flags & BP_FLAG_FIRED) {
544 debug_bp_m68k[i].flags &= ~BP_FLAG_FIRED;
545 continue;
546 }
547 debug_bp_m68k[i].flags |= BP_FLAG_FIRED;
548 printf("m68k breakpoint hit @ 0x%08x\n", pc);
549 debug_enter();
550 bp = true;
551 break;
552 }
553 }
554 trace:
555 if (debug_trace_m68k) {
556 if (!bp)
557 debug_print_m68k_disassemble(pc, 1);
558 --debug_trace_m68k;
559 }
560 fflush(stdout);
561 return bp;
562 }
563
564 /**
565 * Watchpoint handler fired after every M68K instruction.
566 */
debug_m68k_check_wps()567 bool md::debug_m68k_check_wps()
568 {
569 unsigned int i;
570 bool wp = false;
571
572 for (i = 0; (i < MAX_WATCHPOINTS); i++) {
573 if (!(debug_wp_m68k[i].flags & BP_FLAG_USED))
574 break; // no wps after first disabled one
575 if (debug_should_m68k_wp_fire(&(debug_wp_m68k[i]))) {
576 printf("m68k watchpoint #%d fired\n", i);
577 debug_wp_m68k[i].flags |= WP_FLAG_FIRED;
578 debug_print_m68k_wp(i);
579 debug_enter();
580 debug_update_fired_m68k_wps();
581 wp = true;
582 break;
583 }
584 }
585 fflush(stdout);
586 return wp;
587 }
588
589 /**
590 * Breakpoint handler fired before every Z80 instruction.
591 */
debug_z80_check_bps()592 bool md::debug_z80_check_bps()
593 {
594 uint16_t pc = z80_get_pc();
595 unsigned int i;
596 bool bp = false;
597
598 if (debug_step_z80) {
599 if ((--debug_step_z80) == 0) {
600 debug_enter();
601 bp = true;
602 }
603 goto trace;
604 }
605 for (i = 0; (i < MAX_BREAKPOINTS); i++) {
606 if (!(debug_bp_z80[i].flags & BP_FLAG_USED))
607 break; // no bps after first disabled one
608 if (pc == debug_bp_z80[i].addr) {
609 if (debug_bp_z80[i].flags & BP_FLAG_FIRED) {
610 debug_bp_z80[i].flags &= ~BP_FLAG_FIRED;
611 continue;
612 }
613 debug_bp_z80[i].flags |= BP_FLAG_FIRED;
614 printf("z80 breakpoint hit @ 0x%04x\n", pc);
615 debug_enter();
616 bp = true;
617 break;
618 }
619 }
620 trace:
621 if (debug_trace_z80) {
622 if (!bp)
623 debug_print_z80_disassemble(pc, 1);
624 --debug_trace_z80;
625 }
626 fflush(stdout);
627 return bp;
628 }
629
630 /**
631 * Watchpoint handler fired after every Z80 instruction.
632 */
debug_z80_check_wps()633 bool md::debug_z80_check_wps()
634 {
635 unsigned int i;
636 bool wp = false;
637
638 for (i = 0; (i < MAX_WATCHPOINTS); i++) {
639 if (!(debug_wp_z80[i].flags & BP_FLAG_USED))
640 break;
641 if (debug_should_z80_wp_fire(&(debug_wp_z80[i]))) {
642 printf("z80 watchpoint #%d fired\n", i);
643 debug_wp_z80[i].flags |= WP_FLAG_FIRED;
644 debug_print_z80_wp(i);
645 debug_enter();
646 debug_update_fired_z80_wps();
647 wp = true;
648 break;
649 }
650 }
651 fflush(stdout);
652 return wp;
653 }
654
655 /**
656 * Remove a M68K breakpoint.
657 *
658 * @param index Index of breakpoint to remove.
659 */
debug_rm_bp_m68k(int index)660 void md::debug_rm_bp_m68k(int index)
661 {
662 if (!(debug_bp_m68k[index].flags & BP_FLAG_USED)) {
663 printf("breakpoint not set\n");
664 fflush(stdout);
665 return;
666 }
667
668 // shift everything down one
669 if (index == MAX_BREAKPOINTS - 1) {
670 debug_bp_m68k[index].addr = 0;
671 debug_bp_m68k[index].flags = 0;
672 } else {
673 memmove(&(debug_bp_m68k[index]),
674 &(debug_bp_m68k[index+1]),
675 sizeof(struct dgen_bp) * (MAX_BREAKPOINTS - index - 1));
676 // disable last slot
677 debug_bp_m68k[MAX_BREAKPOINTS - 1].addr = 0;
678 debug_bp_m68k[MAX_BREAKPOINTS - 1].flags = 0;
679 }
680 }
681
682 /**
683 * Remove a Z80 breakpoint.
684 *
685 * @param index Index of breakpoint to remove.
686 */
debug_rm_bp_z80(int index)687 void md::debug_rm_bp_z80(int index)
688 {
689 if (!(debug_bp_z80[index].flags & BP_FLAG_USED)) {
690 printf("breakpoint not set\n");
691 fflush(stdout);
692 return;
693 }
694 if (index == (MAX_BREAKPOINTS - 1)) {
695 debug_bp_z80[index].addr = 0;
696 debug_bp_z80[index].flags = 0;
697 }
698 else {
699 memmove(&debug_bp_z80[index],
700 &debug_bp_z80[index + 1],
701 (sizeof(struct dgen_bp) *
702 (MAX_BREAKPOINTS - index - 1)));
703 debug_bp_z80[MAX_BREAKPOINTS - 1].addr = 0;
704 debug_bp_z80[MAX_BREAKPOINTS - 1].flags = 0;
705 }
706 }
707
708 /**
709 * Remove a M68K watchpoint.
710 *
711 * @param index Index of watchpoint to remove.
712 */
debug_rm_wp_m68k(int index)713 void md::debug_rm_wp_m68k(int index)
714 {
715 if (!(debug_wp_m68k[index].flags & WP_FLAG_USED)) {
716 printf("watchpoint not set\n");
717 fflush(stdout);
718 return;
719 }
720
721 free(debug_wp_m68k[index].bytes);
722
723 // shift everything down one
724 if (index == MAX_WATCHPOINTS - 1) {
725 debug_wp_m68k[index].start_addr = 0;
726 debug_wp_m68k[index].flags = 0;
727 } else {
728 memmove(&(debug_wp_m68k[index]),
729 &(debug_wp_m68k[index+1]),
730 sizeof(struct dgen_bp) * (MAX_WATCHPOINTS - index - 1));
731 // disable last slot
732 debug_wp_m68k[MAX_WATCHPOINTS - 1].start_addr = 0;
733 debug_wp_m68k[MAX_WATCHPOINTS - 1].flags = 0;
734 }
735 }
736
737 /**
738 * Remove a Z80 watchpoint.
739 *
740 * @param index Index of watchpoint to remove.
741 */
debug_rm_wp_z80(int index)742 void md::debug_rm_wp_z80(int index)
743 {
744 if (!(debug_wp_z80[index].flags & WP_FLAG_USED)) {
745 printf("watchpoint not set\n");
746 fflush(stdout);
747 return;
748 }
749 free(debug_wp_z80[index].bytes);
750 if (index == (MAX_WATCHPOINTS - 1)) {
751 debug_wp_z80[index].start_addr = 0;
752 debug_wp_z80[index].flags = 0;
753 }
754 else {
755 memmove(&debug_wp_z80[index],
756 &debug_wp_z80[index + 1],
757 (sizeof(struct dgen_bp) *
758 (MAX_WATCHPOINTS - index - 1)));
759 debug_wp_z80[MAX_WATCHPOINTS - 1].start_addr = 0;
760 debug_wp_z80[MAX_WATCHPOINTS - 1].flags = 0;
761 }
762 }
763
764 /**
765 * Pretty print M68K breakpoints.
766 */
debug_list_bps_m68k()767 void md::debug_list_bps_m68k()
768 {
769 int i;
770
771 printf("m68k breakpoints:\n");
772 for (i = 0; i < MAX_BREAKPOINTS; i++) {
773 if (!(debug_bp_m68k[i].flags & BP_FLAG_USED))
774 break; // can be no more after first disabled bp
775
776 printf("#%0d:\t0x%08x\n", i, debug_bp_m68k[i].addr);
777 }
778
779 if (i == 0)
780 printf("\tno m68k breakpoints set\n");
781 fflush(stdout);
782 }
783
784 /**
785 * Pretty print Z80 breakpoints.
786 */
debug_list_bps_z80()787 void md::debug_list_bps_z80()
788 {
789 unsigned int i;
790
791 printf("z80 breakpoints:\n");
792 for (i = 0; (i < MAX_BREAKPOINTS); i++) {
793 if (!(debug_bp_z80[i].flags & BP_FLAG_USED))
794 break;
795 printf("#%0d:\t0x%04x\n", i, debug_bp_z80[i].addr);
796 }
797 if (i == 0)
798 printf("\tno z80 breakpoints set\n");
799 fflush(stdout);
800 }
801
802 /**
803 * Pretty print M68K watchpoints.
804 */
debug_list_wps_m68k()805 void md::debug_list_wps_m68k()
806 {
807 int i;
808
809 printf("m68k watchpoints:\n");
810 for (i = 0; i < MAX_WATCHPOINTS; i++) {
811 if (!(debug_wp_m68k[i].flags & WP_FLAG_USED))
812 break; // can be no more after first disabled
813 debug_print_m68k_wp(i);
814 }
815
816 if (i == 0)
817 printf("\tno m68k watchpoints set\n");
818 fflush(stdout);
819 }
820
821 /**
822 * Pretty print Z80 watchpoints.
823 */
debug_list_wps_z80()824 void md::debug_list_wps_z80()
825 {
826 unsigned int i;
827
828 printf("z80 watchpoints:\n");
829 for (i = 0; (i < MAX_WATCHPOINTS); i++) {
830 if (!(debug_wp_z80[i].flags & WP_FLAG_USED))
831 break;
832 debug_print_z80_wp(i);
833 }
834 if (i == 0)
835 printf("\tno z80 watchpoints set\n");
836 fflush(stdout);
837 }
838
839 /**
840 * Add a M68K breakpoint.
841 *
842 * @param addr Address to break on.
843 * @return Always 1.
844 */
debug_set_bp_m68k(uint32_t addr)845 int md::debug_set_bp_m68k(uint32_t addr)
846 {
847 int slot;
848
849 if ((debug_find_bp_m68k(addr)) != -1) {
850 printf("breakpoint already set at this address\n");
851 goto out;
852 }
853
854 slot = debug_next_free_bp_m68k();
855 if (slot == -1) {
856 printf("No space for another break point\n");
857 goto out;
858 }
859
860 debug_bp_m68k[slot].addr = addr;
861 debug_bp_m68k[slot].flags = BP_FLAG_USED;
862 printf("m68k breakpoint #%d set @ 0x%08x\n", slot, addr);
863 out:
864 fflush(stdout);
865 return (1);
866 }
867
868 /**
869 * Add a Z80 breakpoint.
870 *
871 * @param addr Address to break on.
872 * @return Always 1.
873 */
debug_set_bp_z80(uint16_t addr)874 int md::debug_set_bp_z80(uint16_t addr)
875 {
876 int slot;
877
878 if ((debug_find_bp_z80(addr)) != -1) {
879 printf("breakpoint already set at this address\n");
880 goto out;
881 }
882 slot = debug_next_free_bp_z80();
883 if (slot == -1) {
884 printf("No space for another break point\n");
885 goto out;
886 }
887 debug_bp_z80[slot].addr = addr;
888 debug_bp_z80[slot].flags = BP_FLAG_USED;
889 printf("z80 breakpoint #%d set @ 0x%04x\n", slot, addr);
890 out:
891 fflush(stdout);
892 return 1;
893 }
894
895 /**
896 * Convert a core name to a context ID.
897 *
898 * @param[in] arg NUL-terminated core name.
899 * @return Core context ID or -1 on error.
900 */
debug_parse_cpu(char * arg)901 static int debug_parse_cpu(char *arg)
902 {
903 uint32_t num;
904 const char **p;
905
906 /* by name */
907 for (p = z80_aliases; *p != NULL; p++) {
908 if (strcmp(arg, *p) == 0)
909 return (DBG_CONTEXT_Z80);
910 }
911
912 for (p = m68k_aliases; *p != NULL; p++) {
913 if (strcmp(arg, *p) == 0)
914 return (DBG_CONTEXT_M68K);
915 }
916
917 for (p = fm_aliases; *p != NULL; p++) {
918 if (strcmp(arg, *p) == 0)
919 return (DBG_CONTEXT_YM2612);
920 }
921
922 for (p = psg_aliases; *p != NULL; p++) {
923 if (strcmp(arg, *p) == 0)
924 return (DBG_CONTEXT_SN76489);
925 }
926
927 /* by index */
928 if ((debug_strtou32(arg, &num)) < 0)
929 return (-1);
930
931 if (num > DBG_CONTEXT_SN76489)
932 return (-1);
933
934 return ((int) num);
935 }
936
937 // ===[ C++ Methods ]=========================================================
938
939 /**
940 * Add a M68K watchpoint to a range of addresses.
941 *
942 * @param start_addr Start address of watchpoint range.
943 * @param end_addr End address of watchpoint range.
944 */
debug_set_wp_m68k(uint32_t start_addr,uint32_t end_addr)945 void md::debug_set_wp_m68k(uint32_t start_addr, uint32_t end_addr)
946 {
947 int slot;
948
949 slot = debug_next_free_wp_m68k();
950 if (slot == -1) {
951 printf("No space for another watch point\n");
952 goto out;
953 }
954
955 debug_wp_m68k[slot].start_addr = start_addr;
956 debug_wp_m68k[slot].end_addr = end_addr;
957 debug_wp_m68k[slot].flags = WP_FLAG_USED;
958 debug_wp_m68k[slot].bytes = (unsigned char *) malloc(end_addr - start_addr + 1);
959 if (debug_wp_m68k[slot].bytes == NULL) {
960 perror("malloc");
961 goto out;
962 }
963
964 debug_update_m68k_wp_cache(&(debug_wp_m68k[slot]));
965
966 printf("m68k watchpoint #%d set @ 0x%08x-0x%08x (%u bytes)\n",
967 slot, start_addr, end_addr, end_addr - start_addr + 1);
968 out:
969 fflush(stdout);
970 }
971
972 /**
973 * Update the data pointer of a single M68K watchpoint.
974 *
975 * @param w Watchpoint to update.
976 */
debug_update_m68k_wp_cache(struct dgen_wp * w)977 void md::debug_update_m68k_wp_cache(struct dgen_wp *w)
978 {
979 unsigned int addr;
980 unsigned char *p;
981
982 p = w->bytes;
983 for (addr = w->start_addr; addr <= w->end_addr; addr++) {
984 *(p++) = misc_readbyte(addr);
985 }
986 }
987
988 /**
989 * Resynchronise all M68K watchpoints based on actual data.
990 */
debug_update_fired_m68k_wps()991 void md::debug_update_fired_m68k_wps()
992 {
993 int i;
994
995 for (i = 0; i < MAX_WATCHPOINTS; i++) {
996
997 if (!(debug_wp_m68k[i].flags & WP_FLAG_USED))
998 return;
999
1000 if (!(debug_wp_m68k[i].flags & WP_FLAG_FIRED))
1001 continue;
1002
1003 debug_update_m68k_wp_cache(&(debug_wp_m68k[i]));
1004 debug_wp_m68k[i].flags &= ~WP_FLAG_FIRED;
1005 }
1006 }
1007
1008 /**
1009 * Add a Z80 watchpoint to a range of addresses.
1010 *
1011 * @param start_addr Start address of watchpoint range.
1012 * @param end_addr End address of watchpoint range.
1013 */
debug_set_wp_z80(uint16_t start_addr,uint16_t end_addr)1014 void md::debug_set_wp_z80(uint16_t start_addr, uint16_t end_addr)
1015 {
1016 int slot;
1017
1018 slot = debug_next_free_wp_z80();
1019 if (slot == -1) {
1020 printf("No space for another watch point\n");
1021 goto out;
1022 }
1023 debug_wp_z80[slot].start_addr = start_addr;
1024 debug_wp_z80[slot].end_addr = end_addr;
1025 debug_wp_z80[slot].flags = WP_FLAG_USED;
1026 debug_wp_z80[slot].bytes =
1027 (unsigned char *)malloc(end_addr - start_addr + 1);
1028 if (debug_wp_z80[slot].bytes == NULL) {
1029 perror("malloc");
1030 goto out;
1031 }
1032 debug_update_z80_wp_cache(&(debug_wp_z80[slot]));
1033 printf("z80 watchpoint #%d set @ 0x%04x-0x%04x (%u bytes)\n",
1034 slot, start_addr, end_addr, (end_addr - start_addr + 1));
1035 out:
1036 fflush(stdout);
1037 }
1038
1039 /**
1040 * Update the data pointer of a single Z80 watchpoint.
1041 *
1042 * @param w Watchpoint to update.
1043 */
debug_update_z80_wp_cache(struct dgen_wp * w)1044 void md::debug_update_z80_wp_cache(struct dgen_wp *w)
1045 {
1046 unsigned int addr;
1047 unsigned char *p = w->bytes;
1048
1049 for (addr = w->start_addr; (addr <= w->end_addr); addr++)
1050 *(p++) = z80_read(addr);
1051 }
1052
1053 /**
1054 * Resynchronise all Z80 watchpoints based on actual data.
1055 */
debug_update_fired_z80_wps()1056 void md::debug_update_fired_z80_wps()
1057 {
1058 int i;
1059
1060 for (i = 0; (i < MAX_WATCHPOINTS); i++) {
1061 if (!(debug_wp_z80[i].flags & WP_FLAG_USED))
1062 return;
1063 if (!(debug_wp_z80[i].flags & WP_FLAG_FIRED))
1064 continue;
1065 debug_update_z80_wp_cache(&(debug_wp_z80[i]));
1066 debug_wp_z80[i].flags &= ~WP_FLAG_FIRED;
1067 }
1068 }
1069
1070 /**
1071 * Watchpoints (watch) command handler.
1072 *
1073 * - If n_args == 0 then list watchpoints.
1074 * - If n_args == 1 then add a watchpoint with length 1 with start address
1075 * defined in args[0].
1076 * - If n_args == 2 then add a watch point with start address args[0] and
1077 * length args[1].
1078 *
1079 * @param n_args Number of arguments.
1080 * @param args Arguments, see above.
1081 * @return Always 1.
1082 */
debug_cmd_watch(int n_args,char ** args)1083 int md::debug_cmd_watch(int n_args, char **args)
1084 {
1085 uint32_t start, len = 1;
1086
1087 if (debug_context != DBG_CONTEXT_M68K){
1088 printf("watchpoints not supported on %s core\n",
1089 CURRENT_DEBUG_CONTEXT_NAME);
1090 goto out;
1091 }
1092
1093 switch (n_args) {
1094 case 2:
1095 if ((debug_strtou32(args[1], &len)) < 0) {
1096 printf("length malformed: %s\n", args[1]);
1097 goto out;
1098 }
1099 // fallthru
1100 case 1:
1101 if ((debug_strtou32(args[0], &start)) < 0) {
1102 printf("address malformed: %s\n", args[0]);
1103 goto out;
1104 }
1105 debug_set_wp_m68k(start, start+len-1); // one byte
1106 break;
1107 case 0:
1108 // listing wps
1109 debug_list_wps_m68k();
1110 break;
1111 };
1112 out:
1113 fflush(stdout);
1114 return (1);
1115 }
1116
1117 /**
1118 * Pretty print a block of memory as a hex dump.
1119 *
1120 * @param addr Start address.
1121 * @param len Length (in bytes) to dump.
1122 */
debug_dump_mem(uint32_t addr,uint32_t len)1123 void md::debug_dump_mem(uint32_t addr, uint32_t len)
1124 {
1125 uint32_t i;
1126 unsigned char *buf;
1127
1128 // we have to make a buffer to pass down
1129 buf = (unsigned char *) malloc(len);
1130 if (buf == NULL) {
1131 perror("malloc");
1132 return;
1133 }
1134
1135 for (i = 0; i < len; i++) {
1136 buf[i] = misc_readbyte(addr + i);
1137 }
1138
1139 debug_print_hex_buf(buf, len, addr);
1140 free(buf);
1141 }
1142
1143 /**
1144 * Memory dump (mem) command handler.
1145 *
1146 * - If n_args == 1 then args[0] is start address to dump from for
1147 * DEBUG_DFLT_MEMDUMP_LEN bytes.
1148 * - If n_args == 2 then args[0] is start address and args[1] is number of
1149 * bytes to dump.
1150 *
1151 * @param n_args Number of arguments.
1152 * @param args Arguments, see above.
1153 * @return Always 1.
1154 */
debug_cmd_mem(int n_args,char ** args)1155 int md::debug_cmd_mem(int n_args, char **args)
1156 {
1157 uint32_t addr, len = DEBUG_DFLT_MEMDUMP_LEN;
1158
1159 if (debug_context != DBG_CONTEXT_M68K) {
1160 printf("memory dumping not implemented on %s core\n",
1161 CURRENT_DEBUG_CONTEXT_NAME);
1162 goto out;
1163 }
1164
1165 switch (n_args) {
1166 case 2: /* specified length */
1167 if ((debug_strtou32(args[1], &len)) < 0) {
1168 printf("length malformed: %s\n", args[1]);
1169 goto out;
1170 }
1171 /* FALLTHRU */
1172 case 1: /* default length */
1173 if ((debug_strtou32(args[0], &addr)) < 0) {
1174 printf("addr malformed: %s\n", args[0]);
1175 goto out;
1176 }
1177
1178 debug_dump_mem(addr, len);
1179 break;
1180 };
1181 out:
1182 fflush(stdout);
1183 return (1);
1184 }
1185
1186 /**
1187 * Memory/registers write (setb/setw/setl/setr) commands handler.
1188 *
1189 * - args[1] is the numerical value to write to registers/memory.
1190 * - If type == ~0u, args[0] is a register name.
1191 * - If type == 1, args[0] is the address of a byte.
1192 * - If type == 2, args[0] is the address of a word.
1193 * - If type == 4, args[0] is the address of a long word.
1194 *
1195 * @param n_args Number of arguments (ignored, always 2).
1196 * @param args Arguments, see above.
1197 * @param type Data type to write, see above.
1198 * @return Always 1.
1199 */
debug_cmd_setbwlr(int n_args,char ** args,unsigned int type)1200 int md::debug_cmd_setbwlr(int n_args, char **args, unsigned int type)
1201 {
1202 uint32_t addr = 0;
1203 union {
1204 uint32_t *r32;
1205 uint16_t *r16;
1206 uint8_t *r8;
1207 void *ptr;
1208 } reg_ptr = { NULL };
1209 unsigned int reg = -1;
1210 uint32_t val;
1211
1212 (void)n_args;
1213 assert(n_args == 2);
1214 if ((debug_context != DBG_CONTEXT_M68K) &&
1215 (debug_context != DBG_CONTEXT_Z80)) {
1216 printf("memory setting not implemented on %s core\n",
1217 CURRENT_DEBUG_CONTEXT_NAME);
1218 goto out;
1219 }
1220 if (type == ~0u) {
1221 static const struct {
1222
1223 #define REG0(id, idx) { \
1224 # id # idx, \
1225 ((uintptr_t)&m68k_state.id[idx] - (uintptr_t)&m68k_state), \
1226 sizeof(m68k_state.id[idx]) \
1227 }
1228
1229 #define REG1(id) { # id, offsetof(m68k_state_t, id), sizeof(m68k_state.id) }
1230
1231 #define REG2(id, idx, name) { \
1232 name, \
1233 ((uintptr_t)&z80_state.alt[idx].id - (uintptr_t)&z80_state), \
1234 sizeof(z80_state.alt[idx].id) \
1235 }
1236
1237 #define REG3(id) { # id, offsetof(z80_state_t, id), sizeof(z80_state.id) }
1238
1239 const char *name;
1240 size_t offset;
1241 size_t size;
1242 } regid[2][32] = {
1243 {
1244 // M68K
1245 REG0(a, 0), REG0(a, 1), REG0(a, 2), REG0(a, 3),
1246 REG0(a, 4), REG0(a, 5), REG0(a, 6), REG0(a, 7),
1247 REG0(d, 0), REG0(d, 1), REG0(d, 2), REG0(d, 3),
1248 REG0(d, 4), REG0(d, 5), REG0(d, 6), REG0(d, 7),
1249 REG1(pc), REG1(sr)
1250 },
1251 {
1252 // Z80
1253 REG2(fa, 0, "af"), REG2(fa, 1, "af'"),
1254 REG2(cb, 0, "bc"), REG2(cb, 1, "bc'"),
1255 REG2(ed, 0, "de"), REG2(ed, 1, "de'"),
1256 REG2(lh, 0, "hl"), REG2(lh, 1, "hl'"),
1257 REG3(ix), REG3(iy), REG3(sp), REG3(pc),
1258 REG3(r), REG3(i), REG3(iff), REG3(im)
1259 }
1260 };
1261 unsigned int idx;
1262 uint8_t *state;
1263
1264 if (debug_context == DBG_CONTEXT_M68K) {
1265 idx = 0;
1266 state = (uint8_t *)&m68k_state;
1267 }
1268 else if (debug_context == DBG_CONTEXT_Z80) {
1269 idx = 1;
1270 state = (uint8_t *)&z80_state;
1271 }
1272 else
1273 goto out;
1274 for (addr = 0;
1275 (addr != (sizeof(regid[idx]) / sizeof(regid[idx][0])));
1276 ++addr) {
1277 if (regid[idx][addr].name == NULL)
1278 break;
1279 if (strcasecmp(regid[idx][addr].name, args[0]))
1280 continue;
1281 reg_ptr.ptr =
1282 (void *)(state + regid[idx][addr].offset);
1283 reg = regid[idx][addr].size;
1284 break;
1285 }
1286 if (reg == -1u) {
1287 printf("unknown register %s\n", args[0]);
1288 goto out;
1289 }
1290 }
1291 else if (debug_strtou32(args[0], &addr) < 0) {
1292 printf("addr malformed: %s\n", args[0]);
1293 goto out;
1294 }
1295 if (debug_strtou32(args[1], &val) < 0) {
1296 printf("value malformed: %s\n", args[1]);
1297 goto out;
1298 }
1299 switch (type) {
1300 case 1:
1301 /* byte */
1302 misc_writebyte(addr, val);
1303 break;
1304 case 2:
1305 /* word */
1306 misc_writeword(addr, val);
1307 break;
1308 case 4:
1309 /* long */
1310 misc_writeword(addr, ((val >> 16) & 0xffff));
1311 misc_writeword((addr + 2), (val & 0xffff));
1312 break;
1313 case ~0u:
1314 /* register */
1315 m68k_state_dump();
1316 z80_state_dump();
1317 if (reg == 2)
1318 *reg_ptr.r16 = le2h16(val);
1319 else if (reg == 4)
1320 *reg_ptr.r32 = le2h32(val);
1321 else if (reg == 1)
1322 *reg_ptr.r8 = val;
1323 m68k_state_restore();
1324 z80_state_restore();
1325 break;
1326 default:
1327 printf("unknown type size %u\n", type);
1328 }
1329 out:
1330 fflush(stdout);
1331 return 1;
1332 }
1333
1334 /**
1335 * Set byte (setb) command handler, see debug_cmd_setbwlr().
1336 *
1337 * @return Always 1.
1338 */
debug_cmd_setb(int n_args,char ** args)1339 int md::debug_cmd_setb(int n_args, char **args)
1340 {
1341 return debug_cmd_setbwlr(n_args, args, 1);
1342 }
1343
1344 /**
1345 * Set word (setw) command handler, see debug_cmd_setbwlr().
1346 *
1347 * @return Always 1.
1348 */
debug_cmd_setw(int n_args,char ** args)1349 int md::debug_cmd_setw(int n_args, char **args)
1350 {
1351 return debug_cmd_setbwlr(n_args, args, 2);
1352 }
1353
1354 /**
1355 * Set long word (setl) command handler, see debug_cmd_setbwlr().
1356 *
1357 * @return Always 1.
1358 */
debug_cmd_setl(int n_args,char ** args)1359 int md::debug_cmd_setl(int n_args, char **args)
1360 {
1361 return debug_cmd_setbwlr(n_args, args, 4);
1362 }
1363
1364 /**
1365 * Set register (setr) command handler, see debug_cmd_setbwlr().
1366 *
1367 * @return Always 1.
1368 */
debug_cmd_setr(int n_args,char ** args)1369 int md::debug_cmd_setr(int n_args, char **args)
1370 {
1371 return debug_cmd_setbwlr(n_args, args, ~0u);
1372 }
1373
1374 /**
1375 * Disassemble (dis) command handler.
1376 *
1377 * - If n_args == 0, do nothing.
1378 * - If n_args == 1 start disassembling from address args[0] for
1379 * DEBUG_DFLT_DASM_LEN instructions.
1380 * - If n_args == 2 start disassembling from address args[0] for args[1]
1381 * instructions.
1382 *
1383 * @param n_args Number of arguments.
1384 * @param[in] args Arguments list.
1385 * @return Always 1.
1386 */
debug_cmd_dis(int n_args,char ** args)1387 int md::debug_cmd_dis(int n_args, char **args)
1388 {
1389 uint32_t addr;
1390 uint32_t length = DEBUG_DFLT_DASM_LEN;
1391
1392 if (debug_context == DBG_CONTEXT_M68K)
1393 addr = m68k_get_pc();
1394 else if (debug_context == DBG_CONTEXT_Z80)
1395 addr = z80_get_pc();
1396 else {
1397 printf("disassembly is not implemented on %s core\n",
1398 CURRENT_DEBUG_CONTEXT_NAME);
1399 goto out;
1400 }
1401
1402 switch (n_args) {
1403 case 0:
1404 // nothing :)
1405 break;
1406 case 2:
1407 if ((debug_strtou32(args[1], &length)) < 0) {
1408 printf("length malformed: %s\n", args[1]);
1409 goto out;
1410 }
1411 // fallthru
1412 case 1:
1413 if ((debug_strtou32(args[0], &addr)) < 0) {
1414 printf("address malformed: %s\n", args[0]);
1415 goto out;
1416 }
1417 break;
1418 };
1419
1420 if (debug_context == DBG_CONTEXT_M68K)
1421 debug_print_m68k_disassemble(addr, length);
1422 else if (debug_context == DBG_CONTEXT_Z80)
1423 debug_print_z80_disassemble(addr, length);
1424 out:
1425 fflush(stdout);
1426 return (1);
1427 }
1428
1429 /**
1430 * Continue (cont) command handler. This command drops out of debug mode.
1431 *
1432 * @param n_args Number of arguments (ignored).
1433 * @param args Arguments (ignored).
1434 * @return Always 0 (debugger should exit).
1435 */
debug_cmd_cont(int n_args,char ** args)1436 int md::debug_cmd_cont(int n_args, char **args)
1437 {
1438 (void) n_args;
1439 (void) args;
1440
1441 debug_trap = false;
1442 return (0); // causes debugger to exit
1443 }
1444
1445 /**
1446 * Pretty print the M68K registers using m68k_state from class md.
1447 */
debug_show_m68k_regs()1448 void md::debug_show_m68k_regs()
1449 {
1450 int i;
1451 uint16_t sr;
1452
1453 m68k_state_dump();
1454 sr = le2h16(m68k_state.sr);
1455
1456 if (debug_instr_count_enabled)
1457 printf("m68k (%lu instructions):\n", debug_m68k_instr_count);
1458 else
1459 printf("m68k:\n");
1460
1461 printf("\tpc:\t0x%08x\n\tsr:\t0x%08x\n", le2h32(m68k_state.pc), sr);
1462
1463 // print SR register - user byte
1464 printf("\t user sr : <X=%u, N=%u, Z=%u, V=%u, C=%u>\n",
1465 (sr & M68K_SR_EXTEND) ? 1 : 0,
1466 (sr & M68K_SR_NEGATIVE) ? 1 : 0,
1467 (sr & M68K_SR_ZERO) ? 1 : 0,
1468 (sr & M68K_SR_OVERFLOW) ? 1 : 0,
1469 (sr & M68K_SR_CARRY) ? 1 : 0);
1470
1471 // print SR register - system byte
1472 printf("\t sys sr : <TE=%u%u, SUS=%u, MIS=%u, IPM=%u%u%u>\n",
1473 (sr & M68K_SR_TRACE_EN1) ? 1 : 0,
1474 (sr & M68K_SR_TRACE_EN2) ? 1 : 0,
1475 (sr & M68K_SR_SUP_STATE) ? 1 : 0,
1476 (sr & M68K_SR_MI_STATE) ? 1 : 0,
1477 (sr & M68K_SR_IP_MASK1) ? 1 : 0,
1478 (sr & M68K_SR_IP_MASK2) ? 1 : 0,
1479 (sr & M68K_SR_IP_MASK3) ? 1 : 0);
1480
1481 // d*
1482 for (i = 0; i < 8; i++)
1483 printf("\td%d:\t0x%08x\n", i, le2h32(m68k_state.d[i]));
1484 // a*
1485 for (i = 0; i < 8; i++)
1486 printf("\ta%d:\t0x%08x\n", i, le2h32(m68k_state.a[i]));
1487 fflush(stdout);
1488 }
1489
1490 #define PRINT_Z80_FLAGS(x) \
1491 printf("\t <S=%u, Z= %u, H=%u, P/V=%u, N=%u, C=%u>\n", \
1492 (x & Z80_SR_SIGN) ? 1 : 0, \
1493 (x & Z80_SR_ZERO) ? 1 : 0, \
1494 (x & Z80_SR_HALF_CARRY) ? 1 : 0, \
1495 (x & Z80_SR_PARITY_OVERFLOW) ? 1 : 0, \
1496 (x & Z80_SR_ADD_SUB) ? 1 : 0, \
1497 (x & Z80_SR_CARRY) ? 1 : 0);
1498 /**
1499 * Pretty print Z80 registers using z80_state from class md.
1500 */
debug_show_z80_regs()1501 void md::debug_show_z80_regs()
1502 {
1503 int i;
1504
1505 z80_state_dump();
1506 printf("z80:\n");
1507
1508 for (i = 0; i < 2; i++) {
1509 const char *alt = (i ? "'" : "");
1510
1511 printf("\t af%s:\t0x%04x\n",
1512 alt, le2h16(z80_state.alt[i].fa));
1513 PRINT_Z80_FLAGS(z80_state.alt[i].fa >> 1);
1514 printf("\t bc%s:\t0x%04x\n"
1515 "\t de%s:\t0x%04x\n"
1516 "\t hl%s:\t0x%04x\n",
1517 alt, le2h16(z80_state.alt[i].cb),
1518 alt, le2h16(z80_state.alt[i].ed),
1519 alt, le2h16(z80_state.alt[i].lh));
1520 }
1521
1522 printf("\t ix:\t0x%04x\n"
1523 "\t iy:\t0x%04x\n"
1524 "\t sp:\t0x%04x\n"
1525 "\t pc:\t0x%04x\n"
1526 "\t r:\t0x%02x\n"
1527 "\t i:\t0x%02x\n"
1528 "\tiff:\t0x%02x\n"
1529 "\t im:\t0x%02x\n",
1530 le2h16(z80_state.ix),
1531 le2h16(z80_state.iy),
1532 le2h16(z80_state.sp),
1533 le2h16(z80_state.pc),
1534 z80_state.r,
1535 z80_state.i,
1536 z80_state.iff,
1537 z80_state.im);
1538 fflush(stdout);
1539 }
1540
1541 /**
1542 * Help (help) command handler.
1543 *
1544 * @param n_args Number of arguments (ignored).
1545 * @param args List of arguments (ignored).
1546 * @return Always 1.
1547 */
debug_cmd_help(int n_args,char ** args)1548 int md::debug_cmd_help(int n_args, char **args)
1549 {
1550 (void) n_args;
1551 (void) args;
1552
1553 printf("commands:\n"
1554 "\tC/cpu <cpu>\t\tswitch to cpu context\n"
1555 "\t-b/-break <#num/addr>\tremove breakpoint for current cpu\n"
1556 "\tb/break <addr>\t\tset breakpoint for current cpu\n"
1557 "\tb/break\t\t\tshow breakpoints for current cpu\n"
1558 "\tc/cont\t\t\texit debugger and continue execution\n"
1559 "\td/dis <addr> <num>\tdisasm 'num' instrs starting at 'addr'\n"
1560 "\td/dis <addr>\t\tdisasm %u instrs starting at 'addr'\n"
1561 "\td/dis\t\t\tdisasm %u instrs starting at the current instr\n"
1562 "\tm/mem <addr> <len>\tdump 'len' bytes of memory at 'addr'\n"
1563 "\tm/mem <addr>\t\tdump %u bytes of memory at 'addr'\n"
1564 "\tset/setb <addr> <val>\twrite byte 'val' to memory at 'addr'\n"
1565 "\tsetw <addr> <val>\twrite word 'val' to memory at 'addr'\n"
1566 "\tsetl <addr> <val>\twrite long 'val' to memory at 'addr'\n"
1567 "\tsetr <reg> <val>\twrite 'val' to register 'reg'\n"
1568 "\th/help/?\t\tshow this message\n"
1569 "\tr/reg\t\t\tshow registers of current cpu\n"
1570 "\tcount\t\t\ttoggle instructions counters\n"
1571 "\ts/step\t\t\tstep one instruction\n"
1572 "\ts/step <num>\t\tstep 'num' instructions\n"
1573 "\tt/trace [bool|num]\ttoggle instructions tracing\n"
1574 "\t-w/-watch <#num/addr>\tremove watchpoint for current cpu\n"
1575 "\tw/watch <addr> <len>\tset multi-byte watchpoint for current cpu\n"
1576 "\tw/watch <addr>\t\tset 1-byte watchpoint for current cpu\n"
1577 "\tw/watch\t\t\tshow watchpoints for current cpu\n"
1578 "\ncpu names/numbers:\n"
1579 "\t'm68k', 'm', '68000', 'm68000' or '%d' refers to the main m68000 chip\n"
1580 "\t'z80', 'z' or '%d' refers to the secondary z80 chip\n"
1581 "\t'ym', 'fm', 'ym2612' or '%d' refers to the fm2616 sound chip\n"
1582 "\t'sn', 'sn76489', 'psg' or '%d' refers to the sn76489 sound chip\n",
1583 DEBUG_DFLT_DASM_LEN, DEBUG_DFLT_DASM_LEN, DEBUG_DFLT_MEMDUMP_LEN,
1584 DBG_CONTEXT_M68K, DBG_CONTEXT_Z80, DBG_CONTEXT_YM2612, DBG_CONTEXT_SN76489);
1585 fflush(stdout);
1586 return (1);
1587 }
1588
1589 /**
1590 * Dump registers (reg) command handler.
1591 * This command pretty prints registers for the current context.
1592 *
1593 * @param n_args Number of arguments (ignored).
1594 * @param[in] args List of arguments (ignored).
1595 * @return Always 1.
1596 */
debug_cmd_reg(int n_args,char ** args)1597 int md::debug_cmd_reg(int n_args, char **args)
1598 {
1599 (void) n_args;
1600 (void) args;
1601
1602 switch (debug_context) {
1603 case DBG_CONTEXT_M68K:
1604 debug_show_m68k_regs();
1605 break;
1606 case DBG_CONTEXT_Z80:
1607 debug_show_z80_regs();
1608 break;
1609 case DBG_CONTEXT_YM2612:
1610 debug_show_ym2612_regs();
1611 break;
1612 default:
1613 printf("register dump not implemented on %s core\n",
1614 CURRENT_DEBUG_CONTEXT_NAME);
1615 break;
1616 };
1617 fflush(stdout);
1618 return (1);
1619 }
1620
1621 /**
1622 * Instructions counters toggle (count) command handler.
1623 *
1624 * - If n_args == 0, toggle (enable/disable) instructions counters.
1625 * - If n_args == 1 and args[0] is a boolean string, toggle instructions
1626 * counters accordingly.
1627 *
1628 * @param n_args Number of arguments.
1629 * @param args Arguments.
1630 * @return Always 1.
1631 */
debug_cmd_count(int n_args,char ** args)1632 int md::debug_cmd_count(int n_args, char **args)
1633 {
1634 static const struct {
1635 const char *param;
1636 bool value;
1637 } opt[] = {
1638 { "true", true }, { "false", false },
1639 { "yes", true }, { "no", false },
1640 { "on", true }, { "off", false },
1641 { "enable", true }, { "disable", false }
1642 };
1643
1644 if (n_args == 1) {
1645 uint32_t i;
1646
1647 for (i = 0; (i != (sizeof(opt) / sizeof(opt[0]))); ++i)
1648 if (!strcasecmp(args[0], opt[i].param)) {
1649 debug_instr_count_enabled = opt[i].value;
1650 break;
1651 }
1652 if (i == (sizeof(opt) / sizeof(opt[0]))) {
1653 if (debug_strtou32(args[0], &i) == -1) {
1654 printf("invalid argument: %s\n", args[0]);
1655 goto out;
1656 }
1657 debug_instr_count_enabled = !!i;
1658 }
1659 }
1660 else
1661 debug_instr_count_enabled = !debug_instr_count_enabled;
1662 printf("instructions counters ");
1663 if (!debug_instr_count_enabled)
1664 printf("disabled.\n");
1665 else {
1666 debug_m68k_instr_count = 0;
1667 debug_z80_instr_count = 0;
1668 printf("enabled.\n");
1669 }
1670 out:
1671 fflush(stdout);
1672 return 1;
1673 }
1674
1675 /**
1676 * Breakpoint (break) command handler.
1677 *
1678 * - If n_args == 0, list breakpoints.
1679 * - If n_args == 1, set a breakpoint at address args[0].
1680 *
1681 * @param n_args Number of arguments.
1682 * @param[in] args List of arguments.
1683 * @return Always 1.
1684 */
debug_cmd_break(int n_args,char ** args)1685 int md::debug_cmd_break(int n_args, char **args)
1686 {
1687 uint32_t num;
1688
1689 if ((debug_context != DBG_CONTEXT_M68K) &&
1690 (debug_context != DBG_CONTEXT_Z80)) {
1691 printf("breakpoints are not supported on %s\n",
1692 CURRENT_DEBUG_CONTEXT_NAME);
1693 goto out;
1694 }
1695
1696 switch (n_args) {
1697 case 1:
1698 // setting a bp
1699 if ((debug_strtou32(args[0], &num)) < 0) {
1700 printf("address malformed: %s\n", args[0]);
1701 goto out;
1702 }
1703 if (debug_context == DBG_CONTEXT_M68K)
1704 debug_set_bp_m68k(num);
1705 else if (debug_context == DBG_CONTEXT_Z80)
1706 debug_set_bp_z80(num);
1707 break;
1708 case 0:
1709 // listing bps
1710 if (debug_context == DBG_CONTEXT_M68K)
1711 debug_list_bps_m68k();
1712 else if (debug_context == DBG_CONTEXT_Z80)
1713 debug_list_bps_z80();
1714 };
1715
1716 out:
1717 fflush(stdout);
1718 return (1);
1719 }
1720
1721 /**
1722 * Quit (quit) command handler.
1723 * This command makes DGen/SDL quit.
1724 *
1725 * @param n_args Number of arguments (ignored).
1726 * @param args List of arguments (ignored).
1727 * @return Always -1.
1728 */
debug_cmd_quit(int n_args,char ** args)1729 int md::debug_cmd_quit(int n_args, char **args)
1730 {
1731 (void) n_args;
1732 (void) args;
1733 debug_leave();
1734 return -1;
1735 }
1736
1737 /**
1738 * Core/CPU selection (cpu) command.
1739 * Switch to the core/CPU given in args[0].
1740 *
1741 * @param n_args Number of arguments (should always be 1).
1742 * @param args List of arguments.
1743 * @return Always 1.
1744 */
debug_cmd_cpu(int n_args,char ** args)1745 int md::debug_cmd_cpu(int n_args, char **args)
1746 {
1747 (void) n_args;
1748
1749 int ctx;
1750
1751 ctx = debug_parse_cpu(args[0]);
1752 if (ctx < 0) {
1753 printf("unknown cpu: %s\n", args[0]);
1754 goto out;
1755 }
1756
1757 debug_context = ctx;
1758 out:
1759 fflush(stdout);
1760 return (1);
1761 }
1762
1763 /**
1764 * Step (step) command handler for the current core.
1765 *
1766 * - If n_args == 0, step one instruction.
1767 * - If n_args == 1, step args[0] instructions.
1768 *
1769 * @param n_args Number of arguments.
1770 * @param args List of arguments.
1771 * @return 0 if execution should continue, 1 otherwise.
1772 */
debug_cmd_step(int n_args,char ** args)1773 int md::debug_cmd_step(int n_args, char **args)
1774 {
1775 uint32_t num = 1;
1776
1777 if ((n_args >= 1) && (debug_strtou32(args[0], &num) < 0)) {
1778 printf("malformed number: %s\n", args[0]);
1779 goto out;
1780 }
1781 if (debug_context == DBG_CONTEXT_M68K)
1782 debug_step_m68k = (num + 1); /* triggered when 0 */
1783 else if (debug_context == DBG_CONTEXT_Z80)
1784 debug_step_z80 = (num + 1);
1785 else {
1786 printf("stepping not supported on %s\n",
1787 CURRENT_DEBUG_CONTEXT_NAME);
1788 goto out;
1789 }
1790 fflush(stdout);
1791 debug_trap = false;
1792 return (0); // continue executing
1793 out:
1794 fflush(stdout);
1795 return (1);
1796 }
1797
1798 /**
1799 * Trace toggle (trace) command handler.
1800 *
1801 * - If n_args == 0, toggle (enable/disable) instructions tracing permanently.
1802 * - If n_args == 1 and args[0] is a number, enable instructions tracing for
1803 * this number of instructions.
1804 * - If n_args == 1 and args[0] is a boolean string, toggle instructions
1805 * tracing accordingly.
1806 *
1807 * @param n_args Number of arguments.
1808 * @param args Arguments.
1809 * @return Always 1.
1810 */
debug_cmd_trace(int n_args,char ** args)1811 int md::debug_cmd_trace(int n_args, char **args)
1812 {
1813 static const struct {
1814 const char *param;
1815 unsigned int value;
1816 } opt[] = {
1817 { "true", ~0u }, { "false", 0 },
1818 { "yes", ~0u }, { "no", 0 },
1819 { "on", ~0u }, { "off", 0 },
1820 { "enable", ~0u }, { "disable", 0 }
1821 };
1822 unsigned int *which;
1823
1824 if ((which = &debug_trace_m68k, debug_context != DBG_CONTEXT_M68K) &&
1825 (which = &debug_trace_z80, debug_context != DBG_CONTEXT_Z80)) {
1826 printf("instructions tracing not supported on %s\n",
1827 CURRENT_DEBUG_CONTEXT_NAME);
1828 goto out;
1829 }
1830 if (n_args == 1) {
1831 uint32_t i;
1832
1833 for (i = 0; (i != (sizeof(opt) / sizeof(opt[0]))); ++i)
1834 if (!strcasecmp(args[0], opt[i].param)) {
1835 *which = opt[i].value;
1836 break;
1837 }
1838 if (i == (sizeof(opt) / sizeof(opt[0]))) {
1839 if (debug_strtou32(args[0], &i) == -1) {
1840 printf("invalid argument: %s\n", args[0]);
1841 goto out;
1842 }
1843 *which = i;
1844 }
1845 }
1846 else
1847 *which = (!*which * ~0u);
1848 printf("instructions tracing ");
1849 switch (*which) {
1850 case 0:
1851 printf("disabled.\n");
1852 break;
1853 case ~0u:
1854 printf("enabled permanently.\n");
1855 break;
1856 default:
1857 printf("enabled for the next %u instruction(s).\n", *which);
1858 break;
1859 }
1860 out:
1861 fflush(stdout);
1862 return 1;
1863 }
1864
1865 /**
1866 * Watchpoint removal (-watch) command handler.
1867 *
1868 * If args[0] starts with a #, remove a watchpoint by ID. Otherwise, remove
1869 * it by address.
1870 *
1871 * @param n_args Number of arguments (always 1).
1872 * @param[in] args List of arguments.
1873 * @return Always 1.
1874 */
debug_cmd_minus_watch(int n_args,char ** args)1875 int md::debug_cmd_minus_watch(int n_args, char **args)
1876 {
1877 int index = -1;
1878 uint32_t num;
1879
1880 (void) n_args;
1881
1882 if ((debug_context != DBG_CONTEXT_M68K) &&
1883 (debug_context != DBG_CONTEXT_Z80)) {
1884 printf("watchpoints not supported on %s\n",
1885 CURRENT_DEBUG_CONTEXT_NAME);
1886 goto out;
1887 }
1888
1889 if (args[0][0] == '#') { // remove by index
1890
1891 if (strlen(args[0]) < 2) {
1892 printf("parse error\n");
1893 goto out;
1894 }
1895
1896 if ((debug_strtou32(args[0]+1, &num)) < 0) {
1897 printf("address malformed: %s\n", args[0]);
1898 goto out;
1899 }
1900 index = num;
1901
1902 if ((index < 0) || (index >= MAX_BREAKPOINTS)) {
1903 printf("breakpoint out of range\n");
1904 goto out;
1905 }
1906 } else { // remove by address
1907 if ((debug_strtou32(args[0], &num)) < 0) {
1908 printf("address malformed: %s\n", args[0]);
1909 goto out;
1910 }
1911 if (debug_context == DBG_CONTEXT_M68K)
1912 index = debug_find_wp_m68k(num);
1913 else if (debug_context == DBG_CONTEXT_Z80)
1914 index = debug_find_wp_z80(num);
1915 }
1916 if (debug_context == DBG_CONTEXT_M68K)
1917 debug_rm_wp_m68k(index);
1918 else if (debug_context == DBG_CONTEXT_Z80)
1919 debug_rm_wp_z80(index);
1920 out:
1921 fflush(stdout);
1922 return (1);
1923 }
1924
1925
1926 /**
1927 * Breakpoint removal (-break) command handler.
1928 *
1929 * If args[0] starts with a #, remove a breakpoint by ID. Otherwise, remove
1930 * it by address.
1931 *
1932 * @param n_args Number of arguments (always 1).
1933 * @param args List of arguments.
1934 * @return Always 1.
1935 */
debug_cmd_minus_break(int n_args,char ** args)1936 int md::debug_cmd_minus_break(int n_args, char **args)
1937 {
1938 int index = -1;
1939 uint32_t num;
1940
1941 (void) n_args;
1942
1943 if ((debug_context != DBG_CONTEXT_M68K) &&
1944 (debug_context != DBG_CONTEXT_Z80)) {
1945 printf("breakpoints not supported on %s\n",
1946 CURRENT_DEBUG_CONTEXT_NAME);
1947 goto out;
1948 }
1949
1950 if (args[0][0] == '#') { // remove by index
1951
1952 if (strlen(args[0]) < 2) {
1953 printf("parse error\n");
1954 goto out;
1955 }
1956
1957 if ((debug_strtou32(args[0]+1, &num)) < 0) {
1958 printf("address malformed: %s\n", args[0]);
1959 goto out;
1960 }
1961 index = num;
1962
1963 if ((index < 0) || (index >= MAX_BREAKPOINTS)) {
1964 printf("breakpoint out of range\n");
1965 goto out;
1966 }
1967
1968 } else { // remove by address
1969 if ((debug_strtou32(args[0], &num)) < 0) {
1970 printf("address malformed: %s\n", args[0]);
1971 goto out;
1972 }
1973 if (debug_context == DBG_CONTEXT_M68K)
1974 index = debug_find_bp_m68k(num);
1975 else if (debug_context == DBG_CONTEXT_Z80)
1976 index = debug_find_bp_z80(num);
1977 if (index < 0) {
1978 printf("no breakpoint here: %s\n", args[0]);
1979 goto out;
1980 }
1981 }
1982 // we now have an index into our bp array
1983 if (debug_context == DBG_CONTEXT_M68K)
1984 debug_rm_bp_m68k(index);
1985 else if (debug_context == DBG_CONTEXT_Z80)
1986 debug_rm_bp_z80(index);
1987 out:
1988 fflush(stdout);
1989 return (1);
1990 }
1991
1992 /**
1993 * Dispatch a command to the relevant handler method.
1994 *
1995 * @param n_toks Number of tokens (arguments).
1996 * @param toks List of tokens (arguments).
1997 * @return 1 if n_toks is 0, otherwise the command handler's return value.
1998 */
debug_despatch_cmd(int n_toks,char ** toks)1999 int md::debug_despatch_cmd(int n_toks, char **toks)
2000 {
2001
2002 struct md::dgen_debugger_cmd *d = (struct md::dgen_debugger_cmd *)
2003 md::debug_cmd_list, *found = NULL;
2004
2005 if (n_toks == 0)
2006 return 1;
2007 while (d->cmd != NULL) {
2008 if ((strcmp(toks[0], d->cmd) == 0) && (n_toks-1 == d->n_args)) {
2009 found = d;
2010 break;
2011 }
2012 d++;
2013 }
2014
2015 if (found == NULL) {
2016 printf("unknown command/wrong argument count (type '?' for help)\n");
2017 fflush(stdout);
2018 return (1);
2019 }
2020
2021 // all is well, call
2022 return ((this->*found->handler)(n_toks-1, &toks[1]));
2023 }
2024
2025 #define MAX_DISASM 128
2026 /**
2027 * Pretty print a M68K disassembly.
2028 *
2029 * @param from Address to start disassembling from.
2030 * @param len Number of instructions to disassemble.
2031 */
debug_print_m68k_disassemble(uint32_t from,int len)2032 void md::debug_print_m68k_disassemble(uint32_t from, int len)
2033 {
2034 #ifdef WITH_MUSA
2035 int i;
2036 char disasm[MAX_DISASM];
2037
2038 md_set_musa(1); // assign static in md:: so C can get at it (HACK)
2039 for (i = 0; i < len; i++) {
2040 unsigned int sz;
2041
2042 sz = m68k_disassemble(disasm, from, M68K_CPU_TYPE_68040);
2043 printf(" 0x%06x: %s\n", from, disasm);
2044 from += sz;
2045 }
2046 md_set_musa(0);
2047 #else
2048 (void)len;
2049 printf(" 0x%06x: %02x %02x [...]\n", from,
2050 misc_readbyte(from), misc_readbyte(from + 1));
2051 #endif
2052 fflush(stdout);
2053 }
2054
2055 /**
2056 * Pretty print a Z80 disassembly.
2057 *
2058 * @param from Address to start disassembling from.
2059 * @param num Number of instructions to disassemble.
2060 */
debug_print_z80_disassemble(uint16_t from,unsigned int num)2061 void md::debug_print_z80_disassemble(uint16_t from, unsigned int num)
2062 {
2063 #ifdef WITH_DZ80
2064 unsigned int i;
2065
2066 for (i = 0; (i < num); ++i) {
2067 int err;
2068
2069 disz80.start = from;
2070 disz80.end = from;
2071 err = dZ80_Disassemble(&disz80);
2072 if (err != DERR_NONE)
2073 printf(" 0x%04x: ??? error: %s\n",
2074 from, dZ80_GetErrorText(err));
2075 else
2076 printf(" 0x%04x: %8s %s\n",
2077 from, disz80.hexDisBuf, disz80.disBuf);
2078 from += disz80.bytesProcessed;
2079 }
2080 #else
2081 (void)num;
2082 printf(" 0x%04x: %02x [...]\n", from, z80_read(from));
2083 #endif
2084 fflush(stdout);
2085 }
2086
2087 /**
2088 * Leave debugger.
2089 */
debug_leave()2090 void md::debug_leave()
2091 {
2092 if (debug_trap == false)
2093 return;
2094 linenoise_nb_clean();
2095 debug_trap = false;
2096 }
2097
2098 /**
2099 * Enter debugger and show command prompt.
2100 */
debug_enter()2101 int md::debug_enter()
2102 {
2103 char *cmd, prompt[32];
2104 char *p, *next;
2105 char *toks[MAX_DEBUG_TOKS];
2106 int n_toks = 0;
2107 uint32_t m68k_pc = m68k_get_pc();
2108 uint16_t z80_pc = z80_get_pc();
2109 int ret;
2110
2111 if (debug_trap == false) {
2112 pd_message("Debug trap.");
2113 debug_trap = true;
2114
2115 if (debug_context == DBG_CONTEXT_M68K)
2116 debug_print_m68k_disassemble(m68k_pc, 1);
2117 else if (debug_context == DBG_CONTEXT_Z80)
2118 debug_print_z80_disassemble(z80_pc, 1);
2119 }
2120
2121 switch (debug_context) {
2122 case DBG_CONTEXT_M68K:
2123 snprintf(prompt, sizeof(prompt), "m68k:0x%08x> ", m68k_pc);
2124 break;
2125 case DBG_CONTEXT_Z80:
2126 snprintf(prompt, sizeof(prompt), "z80:0x%04x> ", z80_pc);
2127 break;
2128 case DBG_CONTEXT_YM2612:
2129 snprintf(prompt, sizeof(prompt), "ym2612> ");
2130 break;
2131 case DBG_CONTEXT_SN76489:
2132 snprintf(prompt, sizeof(prompt), "sn76489> ");
2133 break;
2134 default:
2135 printf("unknown cpu. should not happen\n");
2136 fflush(stdout);
2137 return 0;
2138 };
2139
2140 if ((cmd = linenoise_nb(prompt)) == NULL) {
2141 if (!linenoise_nb_eol())
2142 return 0;
2143 linenoise_nb_clean();
2144 return 0;
2145 }
2146
2147 linenoiseHistoryAdd((const char *)cmd);
2148
2149 // tokenise
2150 next = p = cmd;
2151 n_toks = 0;
2152 while ((n_toks < MAX_DEBUG_TOKS) &&
2153 ((p = strtok(next, " \t")) != NULL)) {
2154 toks[n_toks++] = p;
2155 next = NULL;
2156 }
2157
2158 ret = debug_despatch_cmd(n_toks, toks);
2159 free(cmd);
2160 return ret;
2161 }
2162
2163
2164 /**
2165 * List of commands.
2166 */
2167 const struct md::dgen_debugger_cmd md::debug_cmd_list[] = {
2168 // breakpoints
2169 {(char *) "break", 1, &md::debug_cmd_break},
2170 {(char *) "b", 1, &md::debug_cmd_break},
2171 {(char *) "break", 0, &md::debug_cmd_break},
2172 {(char *) "b", 0, &md::debug_cmd_break},
2173 {(char *) "-break", 1, &md::debug_cmd_minus_break},
2174 {(char *) "-b", 1, &md::debug_cmd_minus_break},
2175 // switch debug context
2176 {(char *) "C", 1, &md::debug_cmd_cpu},
2177 {(char *) "cpu", 1, &md::debug_cmd_cpu},
2178 // continue emulation
2179 {(char *) "cont", 0, &md::debug_cmd_cont},
2180 {(char *) "c", 0, &md::debug_cmd_cont},
2181 // disassemble
2182 {(char *) "dis", 0, &md::debug_cmd_dis},
2183 {(char *) "d", 0, &md::debug_cmd_dis},
2184 {(char *) "dis", 1, &md::debug_cmd_dis},
2185 {(char *) "d", 1, &md::debug_cmd_dis},
2186 {(char *) "dis", 2, &md::debug_cmd_dis},
2187 {(char *) "d", 2, &md::debug_cmd_dis},
2188 // help
2189 {(char *) "help", 0, &md::debug_cmd_help},
2190 {(char *) "h", 0, &md::debug_cmd_help},
2191 {(char *) "?", 0, &md::debug_cmd_help},
2192 // memory
2193 {(char *) "m", 1, &md::debug_cmd_mem},
2194 {(char *) "mem", 1, &md::debug_cmd_mem},
2195 {(char *) "m", 2, &md::debug_cmd_mem},
2196 {(char *) "mem", 2, &md::debug_cmd_mem},
2197 {(char *) "set", 2, &md::debug_cmd_setb},
2198 {(char *) "setb", 2, &md::debug_cmd_setb},
2199 {(char *) "setw", 2, &md::debug_cmd_setw},
2200 {(char *) "setl", 2, &md::debug_cmd_setl},
2201 {(char *) "setr", 2, &md::debug_cmd_setr},
2202 // quit
2203 {(char *) "quit", 0, &md::debug_cmd_quit},
2204 {(char *) "q", 0, &md::debug_cmd_quit},
2205 {(char *) "exit", 0, &md::debug_cmd_quit},
2206 {(char *) "e", 0, &md::debug_cmd_quit},
2207 // dump registers
2208 {(char *) "reg", 0, &md::debug_cmd_reg},
2209 {(char *) "r", 0, &md::debug_cmd_reg},
2210 {(char *) "count", 1, &md::debug_cmd_count},
2211 {(char *) "count", 0, &md::debug_cmd_count},
2212 // step
2213 {(char *) "step", 1, &md::debug_cmd_step},
2214 {(char *) "s", 1, &md::debug_cmd_step},
2215 {(char *) "step", 0, &md::debug_cmd_step},
2216 {(char *) "s", 0, &md::debug_cmd_step},
2217 {(char *) "trace", 1, &md::debug_cmd_trace},
2218 {(char *) "t", 1, &md::debug_cmd_trace},
2219 {(char *) "trace", 0, &md::debug_cmd_trace},
2220 {(char *) "t", 0, &md::debug_cmd_trace},
2221 // watch points
2222 {(char *) "watch", 2, &md::debug_cmd_watch},
2223 {(char *) "w", 2, &md::debug_cmd_watch},
2224 {(char *) "watch", 1, &md::debug_cmd_watch},
2225 {(char *) "w", 1, &md::debug_cmd_watch},
2226 {(char *) "watch", 0, &md::debug_cmd_watch},
2227 {(char *) "w", 0, &md::debug_cmd_watch},
2228 {(char *) "-watch", 1, &md::debug_cmd_minus_watch},
2229 {(char *) "-w", 1, &md::debug_cmd_minus_watch},
2230 // sentinal
2231 {NULL, 0, NULL}
2232 };
2233