Mercurial > repos > blastem
comparison debug.c @ 2182:2d7f8195be3b
Add support for conditional breakpoints
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 13 Aug 2022 22:51:31 -0700 |
parents | 0c723b8b637c |
children | eb2e0e61b1b4 |
comparison
equal
deleted
inserted
replaced
2181:0c723b8b637c | 2182:2d7f8195be3b |
---|---|
1325 fprintf(stderr, "%s is not a valid binding name\n", param); | 1325 fprintf(stderr, "%s is not a valid binding name\n", param); |
1326 } | 1326 } |
1327 return 1; | 1327 return 1; |
1328 } | 1328 } |
1329 | 1329 |
1330 static uint8_t cmd_condition(debug_root *root, char *format, int num_args, command_arg *args) | |
1331 { | |
1332 if (!eval_expr(root, args[0].parsed, &args[0].value)) { | |
1333 fprintf(stderr, "Failed to evaluate breakpoint number: %s\n", args[0].raw); | |
1334 return 1; | |
1335 } | |
1336 bp_def **target = find_breakpoint_idx(&root->breakpoints, args[0].value); | |
1337 if (!*target) { | |
1338 fprintf(stderr, "Failed to find breakpoint %u\n", args[0].value); | |
1339 return 1; | |
1340 } | |
1341 free_expr((*target)->condition); | |
1342 if (num_args > 1 && args[1].parsed) { | |
1343 (*target)->condition = args[1].parsed; | |
1344 args[1].parsed = NULL; | |
1345 } else { | |
1346 (*target)->condition = NULL; | |
1347 } | |
1348 return 1; | |
1349 } | |
1350 | |
1330 static uint8_t cmd_delete_m68k(debug_root *root, char *format, int num_args, command_arg *args) | 1351 static uint8_t cmd_delete_m68k(debug_root *root, char *format, int num_args, command_arg *args) |
1331 { | 1352 { |
1332 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, args[0].value); | 1353 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, args[0].value); |
1333 if (!*this_bp) { | 1354 if (!*this_bp) { |
1334 fprintf(stderr, "Breakpoint %d does not exist\n", args[0].value); | 1355 fprintf(stderr, "Breakpoint %d does not exist\n", args[0].value); |
1734 .usage = "bindown NAME", | 1755 .usage = "bindown NAME", |
1735 .desc = "Simulate a keydown for binding NAME", | 1756 .desc = "Simulate a keydown for binding NAME", |
1736 .raw_impl = cmd_binddown, | 1757 .raw_impl = cmd_binddown, |
1737 .min_args = 1, | 1758 .min_args = 1, |
1738 .max_args = 1 | 1759 .max_args = 1 |
1760 }, | |
1761 { | |
1762 .names = (const char *[]){ | |
1763 "condition", NULL | |
1764 }, | |
1765 .usage = "condition BREAKPOINT [EXPRESSION]", | |
1766 .desc = "Makes breakpoint BREAKPOINT conditional on the value of EXPRESSION or removes a condition if EXPRESSION is omitted", | |
1767 .impl = cmd_condition, | |
1768 .min_args = 1, | |
1769 .max_args = 2 | |
1739 } | 1770 } |
1740 }; | 1771 }; |
1741 #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands)) | 1772 #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands)) |
1742 | 1773 |
1743 command_def m68k_commands[] = { | 1774 command_def m68k_commands[] = { |
2668 return context; | 2699 return context; |
2669 } | 2700 } |
2670 //Check if this is a user set breakpoint, or just a temporary one | 2701 //Check if this is a user set breakpoint, or just a temporary one |
2671 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); | 2702 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); |
2672 if (*this_bp) { | 2703 if (*this_bp) { |
2704 if ((*this_bp)->condition) { | |
2705 uint32_t condres; | |
2706 if (eval_expr(root, (*this_bp)->condition, &condres)) { | |
2707 if (!condres) { | |
2708 return context; | |
2709 } | |
2710 } else { | |
2711 fprintf(stderr, "Failed to eval condition for Z80 breakpoint %u\n", (*this_bp)->index); | |
2712 free_expr((*this_bp)->condition); | |
2713 (*this_bp)->condition = NULL; | |
2714 } | |
2715 } | |
2673 printf("Z80 Breakpoint %d hit\n", (*this_bp)->index); | 2716 printf("Z80 Breakpoint %d hit\n", (*this_bp)->index); |
2674 } else { | 2717 } else { |
2675 zremove_breakpoint(context, address); | 2718 zremove_breakpoint(context, address); |
2676 } | 2719 } |
2677 uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->Z80_OPTS->gen); | 2720 uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->Z80_OPTS->gen); |
2744 remove_breakpoint(context, root->branch_t); | 2787 remove_breakpoint(context, root->branch_t); |
2745 } | 2788 } |
2746 root->branch_t = root->branch_f = 0; | 2789 root->branch_t = root->branch_f = 0; |
2747 } | 2790 } |
2748 | 2791 |
2749 uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address); | |
2750 root->address = address; | 2792 root->address = address; |
2751 root->after = after; | |
2752 root->inst = &inst; | |
2753 int debugging = 1; | 2793 int debugging = 1; |
2754 //Check if this is a user set breakpoint, or just a temporary one | 2794 //Check if this is a user set breakpoint, or just a temporary one |
2755 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); | 2795 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); |
2756 if (*this_bp) { | 2796 if (*this_bp) { |
2797 if ((*this_bp)->condition) { | |
2798 uint32_t condres; | |
2799 if (eval_expr(root, (*this_bp)->condition, &condres)) { | |
2800 if (!condres) { | |
2801 return; | |
2802 } | |
2803 } else { | |
2804 fprintf(stderr, "Failed to eval condition for M68K breakpoint %u\n", (*this_bp)->index); | |
2805 free_expr((*this_bp)->condition); | |
2806 (*this_bp)->condition = NULL; | |
2807 } | |
2808 } | |
2757 for (uint32_t i = 0; debugging && i < (*this_bp)->num_commands; i++) | 2809 for (uint32_t i = 0; debugging && i < (*this_bp)->num_commands; i++) |
2758 { | 2810 { |
2759 debugging = run_command(root, (*this_bp)->commands + i); | 2811 debugging = run_command(root, (*this_bp)->commands + i); |
2760 } | 2812 } |
2761 if (debugging) { | 2813 if (debugging) { |
2764 return; | 2816 return; |
2765 } | 2817 } |
2766 } else { | 2818 } else { |
2767 remove_breakpoint(context, address); | 2819 remove_breakpoint(context, address); |
2768 } | 2820 } |
2821 uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address); | |
2822 root->after = after; | |
2823 root->inst = &inst; | |
2769 for (disp_def * cur = root->displays; cur; cur = cur->next) { | 2824 for (disp_def * cur = root->displays; cur; cur = cur->next) { |
2770 cmd_print(root, cur->format, cur->num_args, cur->args); | 2825 cmd_print(root, cur->format, cur->num_args, cur->args); |
2771 } | 2826 } |
2772 m68k_disasm(&inst, input_buf); | 2827 m68k_disasm(&inst, input_buf); |
2773 printf("%X: %s\n", address, input_buf); | 2828 printf("%X: %s\n", address, input_buf); |