comparison debug.c @ 2720:7dcc84cb14ee

Get uPD78K/II partially hooked up in debugger
author Michael Pavone <pavone@retrodev.com>
date Wed, 16 Jul 2025 19:26:38 -0700
parents 829205a9647a
children aa1d7118307c
comparison
equal deleted inserted replaced
2719:f817aedf5e53 2720:7dcc84cb14ee
2 #include "genesis.h" 2 #include "genesis.h"
3 #include "68kinst.h" 3 #include "68kinst.h"
4 #include "segacd.h" 4 #include "segacd.h"
5 #include "blastem.h" 5 #include "blastem.h"
6 #include "bindings.h" 6 #include "bindings.h"
7 #include "upd78k2_dis.h"
7 #include <ctype.h> 8 #include <ctype.h>
8 #include <math.h> 9 #include <math.h>
9 #include <stdlib.h> 10 #include <stdlib.h>
10 #include <string.h> 11 #include <string.h>
11 #ifndef _WIN32 12 #ifndef _WIN32
1558 return 0; 1559 return 0;
1559 } 1560 }
1560 *out = m68k_read_long(*out, context); 1561 *out = m68k_read_long(*out, context);
1561 } else { 1562 } else {
1562 if (*out & 1) { 1563 if (*out & 1) {
1563 fprintf(stderr, "Wword access to odd addresses ($%X) is not allowed\n", *out); 1564 fprintf(stderr, "Word access to odd addresses ($%X) is not allowed\n", *out);
1564 return 0; 1565 return 0;
1565 } 1566 }
1566 *out = m68k_read_word(*out, context); 1567 *out = m68k_read_word(*out, context);
1567 } 1568 }
1568 return 1; 1569 return 1;
2299 static void read_wait_progress(void) 2300 static void read_wait_progress(void)
2300 { 2301 {
2301 process_events(); 2302 process_events();
2302 #ifndef IS_LIB 2303 #ifndef IS_LIB
2303 render_update_display(); 2304 render_update_display();
2304 vdp_context *vdp = current_system->get_vdp(current_system); 2305 if (current_system->get_vdp) {
2305 if (vdp) { 2306 vdp_context *vdp = current_system->get_vdp(current_system);
2306 vdp_update_per_frame_debug(vdp); 2307 if (vdp) {
2308 vdp_update_per_frame_debug(vdp);
2309 }
2307 } 2310 }
2308 #endif 2311 #endif
2309 } 2312 }
2310 2313
2311 static uint8_t read_parse_command(debug_root *root, parsed_command *out, int indent_level) 2314 static uint8_t read_parse_command(debug_root *root, parsed_command *out, int indent_level)
5031 tern_foreach(root->disasm->labels, symbol_map, root); 5034 tern_foreach(root->disasm->labels, symbol_map, root);
5032 } 5035 }
5033 return root; 5036 return root;
5034 } 5037 }
5035 5038
5039 static uint8_t read_upd_byte(upd78k2_context *upd, uint32_t address)
5040 {
5041 if (address > 0xFE00 && address < 0xFF00) {
5042 return upd->iram[address & 0xFF];
5043 }
5044 return read_byte(address, (void **)upd->mem_pointers, &upd->opts->gen, upd);
5045 }
5046
5047 static uint8_t read_upd(debug_root *root, uint32_t *out, char size)
5048 {
5049 upd78k2_context *upd = root->cpu_context;
5050 uint32_t address = *out;
5051 *out = read_upd_byte(upd, address);
5052 if (size != 'b') {
5053 *out |= read_upd_byte(upd, address + 1) << 8;
5054 if (size == 'l') {
5055 *out |= read_upd_byte(upd, address + 2) << 16;
5056 *out |= read_upd_byte(upd, address + 3) << 24;
5057 }
5058 }
5059 return 1;
5060 }
5061
5062 static void write_upd_byte(upd78k2_context *upd, uint32_t address, uint8_t value)
5063 {
5064 if (address > 0xFE00 && address < 0xFF00) {
5065 upd->iram[address & 0xFF] = value;
5066 } else {
5067 write_byte(address, value, (void **)upd->mem_pointers, &upd->opts->gen, upd);
5068 }
5069 }
5070
5071 static uint8_t write_upd(debug_root *root, uint32_t address, uint32_t value, char size)
5072 {
5073 upd78k2_context *upd = root->cpu_context;
5074 write_upd_byte(upd, address, value);
5075 if (size != 'b') {
5076 write_upd_byte(upd, address + 1, value >> 8);
5077 if (size == 'l') {
5078 write_upd_byte(upd, address + 2, value >> 16);
5079 write_upd_byte(upd, address + 3, value >> 24);
5080 }
5081 }
5082 return 1;
5083 }
5084
5085 static uint32_t upd_chunk_end(debug_root *root, uint32_t start_address)
5086 {
5087 upd78k2_context *upd = root->cpu_context;
5088 memmap_chunk const *chunk = find_map_chunk(start_address, &upd->opts->gen, 0, NULL);
5089 if (!chunk) {
5090 return start_address;
5091 }
5092 if (chunk->mask == upd->opts->gen.address_mask) {
5093 return chunk->end;
5094 }
5095 return (start_address & ~chunk->mask) + chunk->mask + 1;
5096 }
5097
5098 static debug_val upd_reg_get(debug_var *var)
5099 {
5100 upd78k2_context *upd = var->ptr;
5101 return debug_int(upd->main[var->val.v.u32]);
5102 }
5103
5104 static void upd_reg_set(debug_var *var, debug_val val)
5105 {
5106 upd78k2_context *upd = var->ptr;
5107 uint32_t ival;
5108 if (!debug_cast_int(val, &ival)) {
5109 static const char regs[] = "xacbedlh";
5110 fprintf(stderr, "uPD78K/II register %c can only be set to an integer\n", regs[var->val.v.u32]);
5111 return;
5112 }
5113 upd->main[var->val.v.u32] = ival;
5114 }
5115
5116 static debug_val upd_regpair_get(debug_var *var)
5117 {
5118 upd78k2_context *upd = var->ptr;
5119 uint16_t val = upd->main[var->val.v.u32 * 2];
5120 val |= upd->main[var->val.v.u32 * 2 + 1] << 8;
5121 return debug_int(val);
5122 }
5123
5124 static void upd_regpair_set(debug_var *var, debug_val val)
5125 {
5126 upd78k2_context *upd = var->ptr;
5127 uint32_t ival;
5128 if (!debug_cast_int(val, &ival)) {
5129 static const char regs[] = "xacbedlh";
5130 fprintf(stderr, "uPD78K/II register %c can only be set to an integer\n", regs[var->val.v.u32]);
5131 return;
5132 }
5133 upd->main[var->val.v.u32 * 2] = ival;
5134 upd->main[var->val.v.u32 * 2 + 1] = ival >> 8;
5135 }
5136
5137 debug_root *find_upd_root(upd78k2_context *upd)
5138 {
5139 debug_root *root = find_root(upd);
5140 if (root && !root->commands) {
5141 add_commands(root, common_commands, NUM_COMMON);
5142 root->read_mem = read_upd;
5143 root->write_mem = write_upd;
5144 root->chunk_end = upd_chunk_end;
5145 root->disasm = create_upd78k2_disasm();
5146 static const char *regs[] = {"x","a","c","b","e","d","l","h"};
5147 static const char *regpairs[] = {"ax", "bc", "de", "hl"};
5148 debug_var *var;
5149 for (int i = 0; i < sizeof(regs)/sizeof(*regs); i++)
5150 {
5151 var = calloc(1, sizeof(debug_var));
5152 var->get = upd_reg_get;
5153 var->set = upd_reg_set;
5154 var->ptr = root->cpu_context;
5155 var->val.v.u32 = i;
5156 root->variables = tern_insert_ptr(root->variables, regs[i], var);
5157 }
5158 for (int i = 0; i < sizeof(regpairs)/sizeof(*regpairs); i++)
5159 {
5160 var = calloc(1, sizeof(debug_var));
5161 var->get = upd_regpair_get;
5162 var->set = upd_regpair_set;
5163 var->ptr = root->cpu_context;
5164 var->val.v.u32 = i;
5165 root->variables = tern_insert_ptr(root->variables, regpairs[i], var);
5166 }
5167 }
5168 return root;
5169 }
5170
5036 #ifndef NO_Z80 5171 #ifndef NO_Z80
5037 #ifdef NEW_CORE 5172 #ifdef NEW_CORE
5038 #define Z80_OPTS opts 5173 #define Z80_OPTS opts
5039 #else 5174 #else
5040 #define Z80_OPTS options 5175 #define Z80_OPTS options
5662 m68k_disasm_labels(&inst, input_buf, root->disasm); 5797 m68k_disasm_labels(&inst, input_buf, root->disasm);
5663 printf("%X: %s\n", address, input_buf); 5798 printf("%X: %s\n", address, input_buf);
5664 debugger_repl(root); 5799 debugger_repl(root);
5665 return; 5800 return;
5666 } 5801 }
5802
5803 static uint8_t upd_debug_fetch(uint16_t address, void *data)
5804 {
5805 upd78k2_context *upd = data;
5806 return read_byte(address, (void **)upd->mem_pointers, &upd->opts->gen, upd);
5807 }
5808
5809 void upd_debugger(upd78k2_context *upd)
5810 {
5811 static char last_cmd[1024];
5812 char input_buf[1024];
5813
5814 init_terminal();
5815
5816 debug_root *root = find_upd_root(upd);
5817 if (!root) {
5818 return;
5819 }
5820 /*
5821 if (upd->pc == root->branch_t) {
5822 bp_def ** f_bp = find_breakpoint(&root->breakpoints, root->branch_f, BP_TYPE_CPU);
5823 if (!*f_bp) {
5824 remove_breakpoint(context, root->branch_f);
5825 }
5826 root->branch_t = root->branch_f = 0;
5827 } else if(upd->pc == root->branch_f) {
5828 bp_def ** t_bp = find_breakpoint(&root->breakpoints, root->branch_t, BP_TYPE_CPU);
5829 if (!*t_bp) {
5830 remove_breakpoint(context, root->branch_t);
5831 }
5832 root->branch_t = root->branch_f = 0;
5833 }
5834 */
5835
5836 root->address = upd->pc;
5837 int debugging = 1;
5838 //Check if this is a user set breakpoint, or just a temporary one
5839 bp_def ** this_bp = find_breakpoint(&root->breakpoints, upd->pc, BP_TYPE_CPU);
5840 if (*this_bp) {
5841 if ((*this_bp)->condition) {
5842 debug_val condres;
5843 if (eval_expr(root, (*this_bp)->condition, &condres)) {
5844 if (!condres.v.u32) {
5845 return;
5846 }
5847 } else {
5848 fprintf(stderr, "Failed to eval condition for uPD78K/II breakpoint %u\n", (*this_bp)->index);
5849 free_expr((*this_bp)->condition);
5850 (*this_bp)->condition = NULL;
5851 }
5852 }
5853 for (uint32_t i = 0; debugging && i < (*this_bp)->num_commands; i++)
5854 {
5855 debugging = run_command(root, (*this_bp)->commands + i);
5856 }
5857 if (debugging) {
5858 printf("uPD78K/II Breakpoint %d hit\n", (*this_bp)->index);
5859 } else {
5860 fflush(stdout);
5861 return;
5862 }
5863 } else {
5864 //remove_breakpoint(context, address);
5865 }
5866 upd_address_ref ref;
5867 uint16_t after = upd78k2_disasm(input_buf, &ref, upd->pc, upd_debug_fetch, upd, root->disasm);
5868 root->after = after;
5869 root->inst = &ref;
5870 for (disp_def * cur = root->displays; cur; cur = cur->next) {
5871 char format_str[8];
5872 make_format_str(format_str, cur->format);
5873 for (int i = 0; i < cur->num_args; i++)
5874 {
5875 eval_expr(root, cur->args[i].parsed, &cur->args[i].value);
5876 do_print(root, format_str, cur->args[i].raw, cur->args[i].value);
5877 }
5878 }
5879 printf("%X: %s\n", root->address, input_buf);
5880 debugger_repl(root);
5881 return;
5882 }