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);