Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  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. */
  76. uint32_t m68k_read_disassembler_8(unsigned int addr)
  77. {
  78.             return m68k_read_memory_8(addr);
  79. }
  80.  
  81. uint32_t m68k_read_disassembler_16(unsigned int addr)
  82. {
  83.             return m68k_read_memory_16(addr);
  84. }
  85.  
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.  */
  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.