Patches no longer seem to be needed
[debian-dgen.git] / debug.cpp
bloba575fa0aa2567a05bc51479e92ac0f34026b5f7f
1 // DGen
2 // Tooling to help debug.
3 // (C) 2012 Edd Barrett <vext01@gmail.com>
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>
13 #ifdef WITH_MUSA
14 extern "C" {
15 #include "musa/m68k.h"
17 #endif
19 #ifdef WITH_DZ80
20 #include "dz80/types.h"
21 #include "dz80/dissz80.h"
22 #endif
24 #include "pd.h"
25 #include "md.h"
26 #include "system.h"
27 #include "debug.h"
28 #include "linenoise/linenoise.h"
30 static const char *debug_context_names[] = {
31 "M68K", "Z80", "YM2612", "SN76489"
34 /**
35 * Aliases for the various cores.
36 * @{
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 /** @} */
48 #define CURRENT_DEBUG_CONTEXT_NAME debug_context_names[debug_context]
50 // ===[ C Functions ]=========================================================
52 /**
53 * Linenoise completion callback.
55 * @param buf String so far.
56 * @param lc List of linenoise completions.
58 #ifndef NO_COMPLETION
59 void completion(const char *buf, linenoiseCompletions *lc) {
61 const struct md::dgen_debugger_cmd *cmd = md::debug_cmd_list;
63 while (cmd->cmd != NULL) {
64 if (strlen(cmd->cmd) != 1) {
65 if (buf[0] == cmd->cmd[0]) {
66 linenoiseAddCompletion(lc, cmd->cmd);
69 cmd++;
72 #endif
74 #ifdef WITH_MUSA
75 /** @{ Callbacks for Musashi. */
76 uint32_t m68k_read_disassembler_8(unsigned int addr)
78 return m68k_read_memory_8(addr);
81 uint32_t m68k_read_disassembler_16(unsigned int addr)
83 return m68k_read_memory_16(addr);
86 uint32_t m68k_read_disassembler_32(unsigned int addr)
88 return m68k_read_memory_32(addr);
90 /** @} */
91 #endif
93 /**
94 * A simple wrapper around strtoul() with error check.
96 * @param[in] str String to convert to number.
97 * @param[out] ret Number "str" represents.
98 * @return -1 on error.
100 static int debug_strtou32(const char *str, uint32_t *ret)
102 char *end = NULL;
104 errno = 0;
105 *ret = (uint32_t)strtoul(str, &end, 0);
107 if (errno) {
108 perror("strtoul");
109 return (-1);
112 if (end == str)
113 return (-1);
115 return (0);
119 * Check if at least one M68K breakpoint is set.
121 * @return 1 if true, 0 otherwise.
123 bool md::debug_is_m68k_bp_set()
125 if (debug_bp_m68k[0].flags & BP_FLAG_USED)
126 return (1);
128 return (0);
132 * Check if at least one Z80 breakpoint is set.
134 * @return 1 if true, 0 otherwise.
136 bool md::debug_is_z80_bp_set()
138 if (debug_bp_z80[0].flags & BP_FLAG_USED)
139 return 1;
140 return 0;
144 * Check if at least one M68K watchpoint is set.
146 * @return 1 if true, 0 otherwise.
148 bool md::debug_is_m68k_wp_set()
150 if (debug_wp_m68k[0].flags & BP_FLAG_USED)
151 return (1);
153 return (0);
157 * Check if at least one Z80 watchpoint is set.
159 * @return 1 if true, 0 otherwise.
161 bool md::debug_is_z80_wp_set()
163 if (debug_wp_z80[0].flags & BP_FLAG_USED)
164 return 1;
165 return 0;
169 * Get the ID of the next free M68K watchpoint.
171 * @return ID or -1 if none free.
173 int md::debug_next_free_wp_m68k()
175 int i;
177 for (i = 0; i < MAX_WATCHPOINTS; i++) {
178 if (!(debug_wp_m68k[i].flags & WP_FLAG_USED))
179 return (i);
182 return (-1); // no free slots
186 * Get the ID of the next free Z80 watchpoint.
188 * @return ID or -1 if none free.
190 int md::debug_next_free_wp_z80()
192 unsigned int i;
194 for (i = 0; (i < MAX_WATCHPOINTS); ++i)
195 if (!(debug_wp_z80[i].flags & WP_FLAG_USED))
196 return i;
197 return -1;
201 * Get the ID of the next free M68K breakpoint.
203 * @return ID or -1 if none free.
205 int md::debug_next_free_bp_m68k()
207 int i;
209 for (i = 0; i < MAX_BREAKPOINTS; i++) {
210 if (!(debug_bp_m68k[i].flags & BP_FLAG_USED))
211 return (i);
214 return (-1); // no free slots
217 #ifdef WITH_DZ80
219 static BYTE disz80_read(void *ctx, WORD addr)
221 class md *md = (class md *)ctx;
223 return md->z80_read(addr);
226 #endif
229 * Get the ID of the next free Z80 breakpoint.
231 * @return ID or -1 if none free.
233 int md::debug_next_free_bp_z80()
235 unsigned int i;
237 for (i = 0; (i < MAX_BREAKPOINTS); ++i)
238 if (!(debug_bp_z80[i].flags & BP_FLAG_USED))
239 return i;
240 return -1;
244 * Initialise the debugger.
246 * All breakpoints are disabled by default.
248 void md::debug_init()
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));
256 #ifndef NO_COMPLETION
257 linenoiseSetCompletionCallback(completion);
258 #endif
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;
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
281 * Find the index of a M68K breakpoint.
283 * @param addr Address to look for.
284 * @return -1 if no breakpoint is found, otherwise its index in
285 * debug_bp_m68k[].
287 int md::debug_find_bp_m68k(uint32_t addr)
289 int i;
291 for (i = 0; i < MAX_BREAKPOINTS; i++) {
293 if (!(debug_bp_m68k[i].flags & BP_FLAG_USED))
294 break;
296 if (debug_bp_m68k[i].addr == addr)
297 return (i);
300 return (-1); // not found
304 * Find the index of a Z80 breakpoint.
306 * @param addr Address to look for.
307 * @return -1 if no breakpoint is found, otherwise its index in
308 * debug_bp_z80[].
310 int md::debug_find_bp_z80(uint16_t addr)
312 unsigned int i;
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;
320 return -1;
324 * Find the index of a M68K watchpoint by its start address.
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[].
330 int md::debug_find_wp_m68k(uint32_t addr)
332 int i;
334 for (i = 0; i < MAX_WATCHPOINTS; i++) {
336 if (!(debug_wp_m68k[i].flags & WP_FLAG_USED))
337 break;
339 if (debug_wp_m68k[i].start_addr == addr)
340 return (i);
343 return (-1); // not found
347 * Find the index of a Z80 watchpoint by its start address.
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[].
353 int md::debug_find_wp_z80(uint16_t addr)
355 unsigned int i;
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;
363 return -1;
367 * Pretty prints hex dump.
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.
373 static void debug_print_hex_buf(
374 unsigned char *buf, size_t len, size_t addr_label_start)
376 uint32_t i, done = 0;
377 unsigned char byte;
378 char ascii[17], *ap, *hp;
379 char hdr[60] = " ";
380 char hex[] = "0123456789abcdef";
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';
390 printf("%s\n", hdr);
392 // process lines of 16 bytes
393 ap = ascii;
394 for (i = 0; i < len; i++, done++, ap++) {
396 if (i % 16 == 0) {
397 ascii[16] = '\0';
399 if (i > 0)
400 printf(" |%s|\n", ascii);
402 printf("0x%08x: ", (uint32_t) addr_label_start + i);
403 ap = ascii;
406 byte = buf[i];
407 // 0x20 to 0x7e is printable ascii
408 if ((byte >= 0x20) && (byte <= 0x7e))
409 *ap = byte;
410 else
411 *ap = '.';
413 printf("%02x ", byte);
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++;
426 // print rest of ascii
427 printf(" |%s|\n", ascii);
428 fflush(stdout);
432 * Print a M68K watchpoint in a human-readable form.
434 * @param idx Index of watchpoint to print.
436 void md::debug_print_m68k_wp(int idx)
438 struct dgen_wp *w = &(debug_wp_m68k[idx]);
440 printf("#%0d:\t0x%08x-%08x (%u bytes)\n", idx,
441 w->start_addr, w->end_addr, w->end_addr - w->start_addr + 1);
443 debug_print_hex_buf(w->bytes, w->end_addr - w->start_addr + 1, w->start_addr);
444 fflush(stdout);
448 * Print a Z80 watchpoint in a human-readable form.
450 * @param idx Index of watchpoint to print.
452 void md::debug_print_z80_wp(int idx)
454 struct dgen_wp *w = &debug_wp_z80[idx];
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);
464 * Check the given M68K watchpoint against cached memory to see if it should
465 * fire.
467 * @param[in] w Watch point to check.
468 * @return 1 if true, else 0.
470 int md::debug_should_m68k_wp_fire(struct dgen_wp *w)
472 unsigned int i;
473 unsigned char *p;
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
480 return (0);
484 * Check the given Z80 watchpoint against cached memory to see if it should
485 * fire.
487 * @param[in] w Watch point to check.
488 * @return 1 if true, else 0.
490 int md::debug_should_z80_wp_fire(struct dgen_wp *w)
492 unsigned int i = w->start_addr;
493 unsigned char *p = w->bytes;
495 while (i <= w->end_addr)
496 if (z80_read(i++) != *p++)
497 return 1;
498 return 0;
502 * Get M68K PC.
504 * @return Current PC.
506 uint32_t md::m68k_get_pc()
508 m68k_state_dump();
509 return le2h32(m68k_state.pc);
513 * Get Z80 PC.
515 * @return Current PC.
517 uint16_t md::z80_get_pc()
519 z80_state_dump();
520 return le2h16(z80_state.pc);
524 * Breakpoint handler fired before every M68K instruction.
526 bool md::debug_m68k_check_bps()
528 uint32_t pc = m68k_get_pc();
529 unsigned int i;
530 bool bp = false;
532 if (debug_step_m68k) {
533 if ((--debug_step_m68k) == 0) {
534 debug_enter();
535 bp = true;
537 goto trace;
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;
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;
554 trace:
555 if (debug_trace_m68k) {
556 if (!bp)
557 debug_print_m68k_disassemble(pc, 1);
558 --debug_trace_m68k;
560 fflush(stdout);
561 return bp;
565 * Watchpoint handler fired after every M68K instruction.
567 bool md::debug_m68k_check_wps()
569 unsigned int i;
570 bool wp = false;
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;
585 fflush(stdout);
586 return wp;
590 * Breakpoint handler fired before every Z80 instruction.
592 bool md::debug_z80_check_bps()
594 uint16_t pc = z80_get_pc();
595 unsigned int i;
596 bool bp = false;
598 if (debug_step_z80) {
599 if ((--debug_step_z80) == 0) {
600 debug_enter();
601 bp = true;
603 goto trace;
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;
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;
620 trace:
621 if (debug_trace_z80) {
622 if (!bp)
623 debug_print_z80_disassemble(pc, 1);
624 --debug_trace_z80;
626 fflush(stdout);
627 return bp;
631 * Watchpoint handler fired after every Z80 instruction.
633 bool md::debug_z80_check_wps()
635 unsigned int i;
636 bool wp = false;
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;
651 fflush(stdout);
652 return wp;
656 * Remove a M68K breakpoint.
658 * @param index Index of breakpoint to remove.
660 void md::debug_rm_bp_m68k(int index)
662 if (!(debug_bp_m68k[index].flags & BP_FLAG_USED)) {
663 printf("breakpoint not set\n");
664 fflush(stdout);
665 return;
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;
683 * Remove a Z80 breakpoint.
685 * @param index Index of breakpoint to remove.
687 void md::debug_rm_bp_z80(int index)
689 if (!(debug_bp_z80[index].flags & BP_FLAG_USED)) {
690 printf("breakpoint not set\n");
691 fflush(stdout);
692 return;
694 if (index == (MAX_BREAKPOINTS - 1)) {
695 debug_bp_z80[index].addr = 0;
696 debug_bp_z80[index].flags = 0;
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;
709 * Remove a M68K watchpoint.
711 * @param index Index of watchpoint to remove.
713 void md::debug_rm_wp_m68k(int index)
715 if (!(debug_wp_m68k[index].flags & WP_FLAG_USED)) {
716 printf("watchpoint not set\n");
717 fflush(stdout);
718 return;
721 free(debug_wp_m68k[index].bytes);
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;
738 * Remove a Z80 watchpoint.
740 * @param index Index of watchpoint to remove.
742 void md::debug_rm_wp_z80(int index)
744 if (!(debug_wp_z80[index].flags & WP_FLAG_USED)) {
745 printf("watchpoint not set\n");
746 fflush(stdout);
747 return;
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;
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;
765 * Pretty print M68K breakpoints.
767 void md::debug_list_bps_m68k()
769 int i;
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
776 printf("#%0d:\t0x%08x\n", i, debug_bp_m68k[i].addr);
779 if (i == 0)
780 printf("\tno m68k breakpoints set\n");
781 fflush(stdout);
785 * Pretty print Z80 breakpoints.
787 void md::debug_list_bps_z80()
789 unsigned int i;
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);
797 if (i == 0)
798 printf("\tno z80 breakpoints set\n");
799 fflush(stdout);
803 * Pretty print M68K watchpoints.
805 void md::debug_list_wps_m68k()
807 int i;
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);
816 if (i == 0)
817 printf("\tno m68k watchpoints set\n");
818 fflush(stdout);
822 * Pretty print Z80 watchpoints.
824 void md::debug_list_wps_z80()
826 unsigned int i;
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);
834 if (i == 0)
835 printf("\tno z80 watchpoints set\n");
836 fflush(stdout);
840 * Add a M68K breakpoint.
842 * @param addr Address to break on.
843 * @return Always 1.
845 int md::debug_set_bp_m68k(uint32_t addr)
847 int slot;
849 if ((debug_find_bp_m68k(addr)) != -1) {
850 printf("breakpoint already set at this address\n");
851 goto out;
854 slot = debug_next_free_bp_m68k();
855 if (slot == -1) {
856 printf("No space for another break point\n");
857 goto out;
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);
869 * Add a Z80 breakpoint.
871 * @param addr Address to break on.
872 * @return Always 1.
874 int md::debug_set_bp_z80(uint16_t addr)
876 int slot;
878 if ((debug_find_bp_z80(addr)) != -1) {
879 printf("breakpoint already set at this address\n");
880 goto out;
882 slot = debug_next_free_bp_z80();
883 if (slot == -1) {
884 printf("No space for another break point\n");
885 goto out;
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;
896 * Convert a core name to a context ID.
898 * @param[in] arg NUL-terminated core name.
899 * @return Core context ID or -1 on error.
901 static int debug_parse_cpu(char *arg)
903 uint32_t num;
904 const char **p;
906 /* by name */
907 for (p = z80_aliases; *p != NULL; p++) {
908 if (strcmp(arg, *p) == 0)
909 return (DBG_CONTEXT_Z80);
912 for (p = m68k_aliases; *p != NULL; p++) {
913 if (strcmp(arg, *p) == 0)
914 return (DBG_CONTEXT_M68K);
917 for (p = fm_aliases; *p != NULL; p++) {
918 if (strcmp(arg, *p) == 0)
919 return (DBG_CONTEXT_YM2612);
922 for (p = psg_aliases; *p != NULL; p++) {
923 if (strcmp(arg, *p) == 0)
924 return (DBG_CONTEXT_SN76489);
927 /* by index */
928 if ((debug_strtou32(arg, &num)) < 0)
929 return (-1);
931 if (num > DBG_CONTEXT_SN76489)
932 return (-1);
934 return ((int) num);
937 // ===[ C++ Methods ]=========================================================
940 * Add a M68K watchpoint to a range of addresses.
942 * @param start_addr Start address of watchpoint range.
943 * @param end_addr End address of watchpoint range.
945 void md::debug_set_wp_m68k(uint32_t start_addr, uint32_t end_addr)
947 int slot;
949 slot = debug_next_free_wp_m68k();
950 if (slot == -1) {
951 printf("No space for another watch point\n");
952 goto out;
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;
964 debug_update_m68k_wp_cache(&(debug_wp_m68k[slot]));
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);
973 * Update the data pointer of a single M68K watchpoint.
975 * @param w Watchpoint to update.
977 void md::debug_update_m68k_wp_cache(struct dgen_wp *w)
979 unsigned int addr;
980 unsigned char *p;
982 p = w->bytes;
983 for (addr = w->start_addr; addr <= w->end_addr; addr++) {
984 *(p++) = misc_readbyte(addr);
989 * Resynchronise all M68K watchpoints based on actual data.
991 void md::debug_update_fired_m68k_wps()
993 int i;
995 for (i = 0; i < MAX_WATCHPOINTS; i++) {
997 if (!(debug_wp_m68k[i].flags & WP_FLAG_USED))
998 return;
1000 if (!(debug_wp_m68k[i].flags & WP_FLAG_FIRED))
1001 continue;
1003 debug_update_m68k_wp_cache(&(debug_wp_m68k[i]));
1004 debug_wp_m68k[i].flags &= ~WP_FLAG_FIRED;
1009 * Add a Z80 watchpoint to a range of addresses.
1011 * @param start_addr Start address of watchpoint range.
1012 * @param end_addr End address of watchpoint range.
1014 void md::debug_set_wp_z80(uint16_t start_addr, uint16_t end_addr)
1016 int slot;
1018 slot = debug_next_free_wp_z80();
1019 if (slot == -1) {
1020 printf("No space for another watch point\n");
1021 goto out;
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;
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);
1040 * Update the data pointer of a single Z80 watchpoint.
1042 * @param w Watchpoint to update.
1044 void md::debug_update_z80_wp_cache(struct dgen_wp *w)
1046 unsigned int addr;
1047 unsigned char *p = w->bytes;
1049 for (addr = w->start_addr; (addr <= w->end_addr); addr++)
1050 *(p++) = z80_read(addr);
1054 * Resynchronise all Z80 watchpoints based on actual data.
1056 void md::debug_update_fired_z80_wps()
1058 int i;
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;
1071 * Watchpoints (watch) command handler.
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].
1079 * @param n_args Number of arguments.
1080 * @param args Arguments, see above.
1081 * @return Always 1.
1083 int md::debug_cmd_watch(int n_args, char **args)
1085 uint32_t start, len = 1;
1087 if (debug_context != DBG_CONTEXT_M68K){
1088 printf("watchpoints not supported on %s core\n",
1089 CURRENT_DEBUG_CONTEXT_NAME);
1090 goto out;
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;
1099 // fallthru
1100 case 1:
1101 if ((debug_strtou32(args[0], &start)) < 0) {
1102 printf("address malformed: %s\n", args[0]);
1103 goto out;
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;
1112 out:
1113 fflush(stdout);
1114 return (1);
1118 * Pretty print a block of memory as a hex dump.
1120 * @param addr Start address.
1121 * @param len Length (in bytes) to dump.
1123 void md::debug_dump_mem(uint32_t addr, uint32_t len)
1125 uint32_t i;
1126 unsigned char *buf;
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;
1135 for (i = 0; i < len; i++) {
1136 buf[i] = misc_readbyte(addr + i);
1139 debug_print_hex_buf(buf, len, addr);
1140 free(buf);
1144 * Memory dump (mem) command handler.
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.
1151 * @param n_args Number of arguments.
1152 * @param args Arguments, see above.
1153 * @return Always 1.
1155 int md::debug_cmd_mem(int n_args, char **args)
1157 uint32_t addr, len = DEBUG_DFLT_MEMDUMP_LEN;
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;
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;
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;
1178 debug_dump_mem(addr, len);
1179 break;
1181 out:
1182 fflush(stdout);
1183 return (1);
1187 * Memory/registers write (setb/setw/setl/setr) commands handler.
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.
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.
1200 int md::debug_cmd_setbwlr(int n_args, char **args, unsigned int type)
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;
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;
1220 if (type == ~0u) {
1221 static const struct {
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]) \
1229 #define REG1(id) { # id, offsetof(m68k_state_t, id), sizeof(m68k_state.id) }
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) \
1237 #define REG3(id) { # id, offsetof(z80_state_t, id), sizeof(z80_state.id) }
1239 const char *name;
1240 size_t offset;
1241 size_t size;
1242 } regid[2][32] = {
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)
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)
1261 unsigned int idx;
1262 uint8_t *state;
1264 if (debug_context == DBG_CONTEXT_M68K) {
1265 idx = 0;
1266 state = (uint8_t *)&m68k_state;
1268 else if (debug_context == DBG_CONTEXT_Z80) {
1269 idx = 1;
1270 state = (uint8_t *)&z80_state;
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;
1286 if (reg == -1u) {
1287 printf("unknown register %s\n", args[0]);
1288 goto out;
1291 else if (debug_strtou32(args[0], &addr) < 0) {
1292 printf("addr malformed: %s\n", args[0]);
1293 goto out;
1295 if (debug_strtou32(args[1], &val) < 0) {
1296 printf("value malformed: %s\n", args[1]);
1297 goto out;
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);
1329 out:
1330 fflush(stdout);
1331 return 1;
1335 * Set byte (setb) command handler, see debug_cmd_setbwlr().
1337 * @return Always 1.
1339 int md::debug_cmd_setb(int n_args, char **args)
1341 return debug_cmd_setbwlr(n_args, args, 1);
1345 * Set word (setw) command handler, see debug_cmd_setbwlr().
1347 * @return Always 1.
1349 int md::debug_cmd_setw(int n_args, char **args)
1351 return debug_cmd_setbwlr(n_args, args, 2);
1355 * Set long word (setl) command handler, see debug_cmd_setbwlr().
1357 * @return Always 1.
1359 int md::debug_cmd_setl(int n_args, char **args)
1361 return debug_cmd_setbwlr(n_args, args, 4);
1365 * Set register (setr) command handler, see debug_cmd_setbwlr().
1367 * @return Always 1.
1369 int md::debug_cmd_setr(int n_args, char **args)
1371 return debug_cmd_setbwlr(n_args, args, ~0u);
1375 * Disassemble (dis) command handler.
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.
1383 * @param n_args Number of arguments.
1384 * @param[in] args Arguments list.
1385 * @return Always 1.
1387 int md::debug_cmd_dis(int n_args, char **args)
1389 uint32_t addr;
1390 uint32_t length = DEBUG_DFLT_DASM_LEN;
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;
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;
1411 // fallthru
1412 case 1:
1413 if ((debug_strtou32(args[0], &addr)) < 0) {
1414 printf("address malformed: %s\n", args[0]);
1415 goto out;
1417 break;
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);
1430 * Continue (cont) command handler. This command drops out of debug mode.
1432 * @param n_args Number of arguments (ignored).
1433 * @param args Arguments (ignored).
1434 * @return Always 0 (debugger should exit).
1436 int md::debug_cmd_cont(int n_args, char **args)
1438 (void) n_args;
1439 (void) args;
1441 debug_trap = false;
1442 return (0); // causes debugger to exit
1446 * Pretty print the M68K registers using m68k_state from class md.
1448 void md::debug_show_m68k_regs()
1450 int i;
1451 uint16_t sr;
1453 m68k_state_dump();
1454 sr = le2h16(m68k_state.sr);
1456 if (debug_instr_count_enabled)
1457 printf("m68k (%lu instructions):\n", debug_m68k_instr_count);
1458 else
1459 printf("m68k:\n");
1461 printf("\tpc:\t0x%08x\n\tsr:\t0x%08x\n", le2h32(m68k_state.pc), sr);
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);
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);
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);
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);
1499 * Pretty print Z80 registers using z80_state from class md.
1501 void md::debug_show_z80_regs()
1503 int i;
1505 z80_state_dump();
1506 printf("z80:\n");
1508 for (i = 0; i < 2; i++) {
1509 const char *alt = (i ? "'" : "");
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));
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);
1542 * Help (help) command handler.
1544 * @param n_args Number of arguments (ignored).
1545 * @param args List of arguments (ignored).
1546 * @return Always 1.
1548 int md::debug_cmd_help(int n_args, char **args)
1550 (void) n_args;
1551 (void) args;
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);
1590 * Dump registers (reg) command handler.
1591 * This command pretty prints registers for the current context.
1593 * @param n_args Number of arguments (ignored).
1594 * @param[in] args List of arguments (ignored).
1595 * @return Always 1.
1597 int md::debug_cmd_reg(int n_args, char **args)
1599 (void) n_args;
1600 (void) args;
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;
1617 fflush(stdout);
1618 return (1);
1622 * Instructions counters toggle (count) command handler.
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.
1628 * @param n_args Number of arguments.
1629 * @param args Arguments.
1630 * @return Always 1.
1632 int md::debug_cmd_count(int n_args, char **args)
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 }
1644 if (n_args == 1) {
1645 uint32_t i;
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;
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;
1657 debug_instr_count_enabled = !!i;
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");
1670 out:
1671 fflush(stdout);
1672 return 1;
1676 * Breakpoint (break) command handler.
1678 * - If n_args == 0, list breakpoints.
1679 * - If n_args == 1, set a breakpoint at address args[0].
1681 * @param n_args Number of arguments.
1682 * @param[in] args List of arguments.
1683 * @return Always 1.
1685 int md::debug_cmd_break(int n_args, char **args)
1687 uint32_t num;
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;
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;
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();
1716 out:
1717 fflush(stdout);
1718 return (1);
1722 * Quit (quit) command handler.
1723 * This command makes DGen/SDL quit.
1725 * @param n_args Number of arguments (ignored).
1726 * @param args List of arguments (ignored).
1727 * @return Always -1.
1729 int md::debug_cmd_quit(int n_args, char **args)
1731 (void) n_args;
1732 (void) args;
1733 debug_leave();
1734 return -1;
1738 * Core/CPU selection (cpu) command.
1739 * Switch to the core/CPU given in args[0].
1741 * @param n_args Number of arguments (should always be 1).
1742 * @param args List of arguments.
1743 * @return Always 1.
1745 int md::debug_cmd_cpu(int n_args, char **args)
1747 (void) n_args;
1749 int ctx;
1751 ctx = debug_parse_cpu(args[0]);
1752 if (ctx < 0) {
1753 printf("unknown cpu: %s\n", args[0]);
1754 goto out;
1757 debug_context = ctx;
1758 out:
1759 fflush(stdout);
1760 return (1);
1764 * Step (step) command handler for the current core.
1766 * - If n_args == 0, step one instruction.
1767 * - If n_args == 1, step args[0] instructions.
1769 * @param n_args Number of arguments.
1770 * @param args List of arguments.
1771 * @return 0 if execution should continue, 1 otherwise.
1773 int md::debug_cmd_step(int n_args, char **args)
1775 uint32_t num = 1;
1777 if ((n_args >= 1) && (debug_strtou32(args[0], &num) < 0)) {
1778 printf("malformed number: %s\n", args[0]);
1779 goto out;
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;
1790 fflush(stdout);
1791 debug_trap = false;
1792 return (0); // continue executing
1793 out:
1794 fflush(stdout);
1795 return (1);
1799 * Trace toggle (trace) command handler.
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.
1807 * @param n_args Number of arguments.
1808 * @param args Arguments.
1809 * @return Always 1.
1811 int md::debug_cmd_trace(int n_args, char **args)
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 }
1822 unsigned int *which;
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;
1830 if (n_args == 1) {
1831 uint32_t i;
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;
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;
1843 *which = i;
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;
1860 out:
1861 fflush(stdout);
1862 return 1;
1866 * Watchpoint removal (-watch) command handler.
1868 * If args[0] starts with a #, remove a watchpoint by ID. Otherwise, remove
1869 * it by address.
1871 * @param n_args Number of arguments (always 1).
1872 * @param[in] args List of arguments.
1873 * @return Always 1.
1875 int md::debug_cmd_minus_watch(int n_args, char **args)
1877 int index = -1;
1878 uint32_t num;
1880 (void) n_args;
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;
1889 if (args[0][0] == '#') { // remove by index
1891 if (strlen(args[0]) < 2) {
1892 printf("parse error\n");
1893 goto out;
1896 if ((debug_strtou32(args[0]+1, &num)) < 0) {
1897 printf("address malformed: %s\n", args[0]);
1898 goto out;
1900 index = num;
1902 if ((index < 0) || (index >= MAX_BREAKPOINTS)) {
1903 printf("breakpoint out of range\n");
1904 goto out;
1906 } else { // remove by address
1907 if ((debug_strtou32(args[0], &num)) < 0) {
1908 printf("address malformed: %s\n", args[0]);
1909 goto out;
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);
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);
1927 * Breakpoint removal (-break) command handler.
1929 * If args[0] starts with a #, remove a breakpoint by ID. Otherwise, remove
1930 * it by address.
1932 * @param n_args Number of arguments (always 1).
1933 * @param args List of arguments.
1934 * @return Always 1.
1936 int md::debug_cmd_minus_break(int n_args, char **args)
1938 int index = -1;
1939 uint32_t num;
1941 (void) n_args;
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;
1950 if (args[0][0] == '#') { // remove by index
1952 if (strlen(args[0]) < 2) {
1953 printf("parse error\n");
1954 goto out;
1957 if ((debug_strtou32(args[0]+1, &num)) < 0) {
1958 printf("address malformed: %s\n", args[0]);
1959 goto out;
1961 index = num;
1963 if ((index < 0) || (index >= MAX_BREAKPOINTS)) {
1964 printf("breakpoint out of range\n");
1965 goto out;
1968 } else { // remove by address
1969 if ((debug_strtou32(args[0], &num)) < 0) {
1970 printf("address malformed: %s\n", args[0]);
1971 goto out;
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;
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);
1993 * Dispatch a command to the relevant handler method.
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.
1999 int md::debug_despatch_cmd(int n_toks, char **toks)
2002 struct md::dgen_debugger_cmd *d = (struct md::dgen_debugger_cmd *)
2003 md::debug_cmd_list, *found = NULL;
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;
2012 d++;
2015 if (found == NULL) {
2016 printf("unknown command/wrong argument count (type '?' for help)\n");
2017 fflush(stdout);
2018 return (1);
2021 // all is well, call
2022 return ((this->*found->handler)(n_toks-1, &toks[1]));
2025 #define MAX_DISASM 128
2027 * Pretty print a M68K disassembly.
2029 * @param from Address to start disassembling from.
2030 * @param len Number of instructions to disassemble.
2032 void md::debug_print_m68k_disassemble(uint32_t from, int len)
2034 #ifdef WITH_MUSA
2035 int i;
2036 char disasm[MAX_DISASM];
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;
2042 sz = m68k_disassemble(disasm, from, M68K_CPU_TYPE_68040);
2043 printf(" 0x%06x: %s\n", from, disasm);
2044 from += sz;
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);
2056 * Pretty print a Z80 disassembly.
2058 * @param from Address to start disassembling from.
2059 * @param num Number of instructions to disassemble.
2061 void md::debug_print_z80_disassemble(uint16_t from, unsigned int num)
2063 #ifdef WITH_DZ80
2064 unsigned int i;
2066 for (i = 0; (i < num); ++i) {
2067 int err;
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;
2080 #else
2081 (void)num;
2082 printf(" 0x%04x: %02x [...]\n", from, z80_read(from));
2083 #endif
2084 fflush(stdout);
2088 * Leave debugger.
2090 void md::debug_leave()
2092 if (debug_trap == false)
2093 return;
2094 linenoise_nb_clean();
2095 debug_trap = false;
2099 * Enter debugger and show command prompt.
2101 int md::debug_enter()
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;
2111 if (debug_trap == false) {
2112 pd_message("Debug trap.");
2113 debug_trap = true;
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);
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;
2140 if ((cmd = linenoise_nb(prompt)) == NULL) {
2141 if (!linenoise_nb_eol())
2142 return 0;
2143 linenoise_nb_clean();
2144 return 0;
2147 linenoiseHistoryAdd((const char *)cmd);
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;
2158 ret = debug_despatch_cmd(n_toks, toks);
2159 free(cmd);
2160 return ret;
2165 * List of commands.
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}