comparison debug.c @ 2053:3414a4423de1 segacd

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sat, 15 Jan 2022 13:15:21 -0800
parents 3a46ff899fa6
children a7b753e260a2 8ee7ecbf3f21
comparison
equal deleted inserted replaced
1692:5dacaef602a7 2053:3414a4423de1
7 #include <sys/select.h> 7 #include <sys/select.h>
8 #endif 8 #endif
9 #include "render.h" 9 #include "render.h"
10 #include "util.h" 10 #include "util.h"
11 #include "terminal.h" 11 #include "terminal.h"
12 #include "z80inst.h"
13
14 #ifdef NEW_CORE
15 #define Z80_OPTS opts
16 #else
17 #define Z80_OPTS options
18 #endif
12 19
13 static bp_def * breakpoints = NULL; 20 static bp_def * breakpoints = NULL;
14 static bp_def * zbreakpoints = NULL; 21 static bp_def * zbreakpoints = NULL;
15 static uint32_t bp_index = 0; 22 static uint32_t bp_index = 0;
16 static uint32_t zbp_index = 0; 23 static uint32_t zbp_index = 0;
86 return; 93 return;
87 } 94 }
88 } 95 }
89 } 96 }
90 97
98 static uint8_t m68k_read_byte(uint32_t address, m68k_context *context)
99 {
100 //TODO: share this implementation with GDB debugger
101 return read_byte(address, (void **)context->mem_pointers, &context->options->gen, context);
102 }
103
91 uint16_t m68k_read_word(uint32_t address, m68k_context *context) 104 uint16_t m68k_read_word(uint32_t address, m68k_context *context)
92 { 105 {
93 return read_word(address, (void **)context->mem_pointers, &context->options->gen, context); 106 return read_word(address, (void **)context->mem_pointers, &context->options->gen, context);
94 } 107 }
95 108
96 uint32_t m68k_read_long(uint32_t address, m68k_context *context) 109 uint32_t m68k_read_long(uint32_t address, m68k_context *context)
97 { 110 {
98 return m68k_read_word(address, context) << 16 | m68k_read_word(address + 2, context); 111 return m68k_read_word(address, context) << 16 | m68k_read_word(address + 2, context);
99 } 112 }
100 113
101 void debugger_print(m68k_context *context, char format_char, char *param) 114 void debugger_print(m68k_context *context, char format_char, char *param, uint32_t address)
102 { 115 {
103 uint32_t value; 116 uint32_t value;
104 char format[8]; 117 char format[8];
105 strcpy(format, "%s: %d\n"); 118 strcpy(format, "%s: %d\n");
106 switch (format_char) 119 switch (format_char)
132 value &= 0xFFFF; 145 value &= 0xFFFF;
133 } else if (param[3] == 'b') { 146 } else if (param[3] == 'b') {
134 value &= 0xFF; 147 value &= 0xFF;
135 } 148 }
136 } 149 }
137 } else if (param[0] == 'S' && param[1] == 'R') { 150 } else if (param[0] == 's' && param[1] == 'r') {
138 value = (context->status << 8); 151 value = (context->status << 8);
139 for (int flag = 0; flag < 5; flag++) { 152 for (int flag = 0; flag < 5; flag++) {
140 value |= context->flags[flag] << (4-flag); 153 value |= context->flags[flag] << (4-flag);
141 } 154 }
142 } else if(param[0] == 'c') { 155 } else if(param[0] == 'c') {
143 value = context->current_cycle; 156 value = context->current_cycle;
144 } else if(param[0] == 'f') { 157 } else if(param[0] == 'f') {
145 genesis_context *gen = context->system; 158 genesis_context *gen = context->system;
146 value = gen->vdp->frame; 159 value = gen->vdp->frame;
160 } else if (param[0] == 'p' && param[1] == 'c') {
161 value = address;
147 } else if ((param[0] == '0' && param[1] == 'x') || param[0] == '$') { 162 } else if ((param[0] == '0' && param[1] == 'x') || param[0] == '$') {
148 char *after; 163 char *after;
149 uint32_t p_addr = strtol(param+(param[0] == '0' ? 2 : 1), &after, 16); 164 uint32_t p_addr = strtol(param+(param[0] == '0' ? 2 : 1), &after, 16);
150 if (after[0] == '.' && after[1] == 'l') { 165 if (after[0] == '.' && after[1] == 'l') {
151 value = m68k_read_long(p_addr, context); 166 value = m68k_read_long(p_addr, context);
167 } else if (after[0] == '.' && after[1] == 'b') {
168 value = m68k_read_byte(p_addr, context);
152 } else { 169 } else {
153 value = m68k_read_word(p_addr, context); 170 value = m68k_read_word(p_addr, context);
154 } 171 }
155 } else if(param[0] == '(' && (param[1] == 'a' || param[1] == 'd') && param[2] >= '0' && param[2] <= '7' && param[3] == ')') { 172 } else if(param[0] == '(' && (param[1] == 'a' || param[1] == 'd') && param[2] >= '0' && param[2] <= '7' && param[3] == ')') {
156 uint8_t reg = param[2] - '0'; 173 uint8_t reg = param[2] - '0';
157 uint32_t p_addr = param[1] == 'a' ? context->aregs[reg] : context->dregs[reg]; 174 uint32_t p_addr = param[1] == 'a' ? context->aregs[reg] : context->dregs[reg];
158 if (param[4] == '.' && param[5] == 'l') { 175 if (param[4] == '.' && param[5] == 'l') {
159 value = m68k_read_long(p_addr, context); 176 value = m68k_read_long(p_addr, context);
177 } else if (param[4] == '.' && param[5] == 'b') {
178 value = m68k_read_byte(p_addr, context);
160 } else { 179 } else {
161 value = m68k_read_word(p_addr, context); 180 value = m68k_read_word(p_addr, context);
162 } 181 }
163 } else { 182 } else {
164 fprintf(stderr, "Unrecognized parameter to p: %s\n", param); 183 fprintf(stderr, "Unrecognized parameter to p: %s\n", param);
188 default: 207 default:
189 fprintf(stderr, "Unrecognized format character: %c\n", format_char); 208 fprintf(stderr, "Unrecognized format character: %c\n", format_char);
190 } 209 }
191 switch (param[0]) 210 switch (param[0])
192 { 211 {
212 #ifndef NEW_CORE
193 case 'a': 213 case 'a':
194 if (param[1] == 'f') { 214 if (param[1] == 'f') {
195 if(param[2] == '\'') { 215 if(param[2] == '\'') {
196 value = context->alt_regs[Z80_A] << 8; 216 value = context->alt_regs[Z80_A] << 8;
197 value |= context->alt_flags[ZF_S] << 7; 217 value |= context->alt_flags[ZF_S] << 7;
329 value = context->iff2; 349 value = context->iff2;
330 } else { 350 } else {
331 value = context->im; 351 value = context->im;
332 } 352 }
333 break; 353 break;
354 #endif
334 case 's': 355 case 's':
335 if (param[1] == 'p') { 356 if (param[1] == 'p') {
336 value = context->sp; 357 value = context->sp;
337 } 358 }
338 break; 359 break;
339 case '0': 360 case '0':
340 if (param[1] == 'x') { 361 if (param[1] == 'x') {
341 uint16_t p_addr = strtol(param+2, NULL, 16); 362 uint16_t p_addr = strtol(param+2, NULL, 16);
342 if (p_addr < 0x4000) { 363 value = read_byte(p_addr, (void **)context->mem_pointers, &context->options->gen, context);
343 value = system->zram[p_addr & 0x1FFF];
344 } else if(p_addr >= 0x8000) {
345 uint32_t v_addr = context->bank_reg << 15;
346 v_addr += p_addr & 0x7FFF;
347 if (v_addr < 0x400000) {
348 value = system->cart[v_addr/2];
349 } else if(v_addr > 0xE00000) {
350 value = system->work_ram[(v_addr & 0xFFFF)/2];
351 }
352 if (v_addr & 1) {
353 value &= 0xFF;
354 } else {
355 value >>= 8;
356 }
357 }
358 } 364 }
359 break; 365 break;
360 } 366 }
361 printf(format, param, value); 367 printf(format, param, value);
362 } 368 }
375 if (*this_bp) { 381 if (*this_bp) {
376 printf("Z80 Breakpoint %d hit\n", (*this_bp)->index); 382 printf("Z80 Breakpoint %d hit\n", (*this_bp)->index);
377 } else { 383 } else {
378 zremove_breakpoint(context, address); 384 zremove_breakpoint(context, address);
379 } 385 }
380 uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->options->gen); 386 uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
381 if (!pc) { 387 if (!pc) {
382 fatal_error("Failed to get native pointer on entering Z80 debugger at address %X\n", address); 388 fatal_error("Failed to get native pointer on entering Z80 debugger at address %X\n", address);
383 } 389 }
384 for (disp_def * cur = zdisplays; cur; cur = cur->next) { 390 for (disp_def * cur = zdisplays; cur; cur = cur->next) {
385 zdebugger_print(context, cur->format_char, cur->param); 391 zdebugger_print(context, cur->format_char, cur->param);
485 //TODO: Handle conditional branch instructions 491 //TODO: Handle conditional branch instructions
486 if (inst.op == Z80_JP) { 492 if (inst.op == Z80_JP) {
487 if (inst.addr_mode == Z80_IMMED) { 493 if (inst.addr_mode == Z80_IMMED) {
488 after = inst.immed; 494 after = inst.immed;
489 } else if (inst.ea_reg == Z80_HL) { 495 } else if (inst.ea_reg == Z80_HL) {
496 #ifndef NEW_CORE
490 after = context->regs[Z80_H] << 8 | context->regs[Z80_L]; 497 after = context->regs[Z80_H] << 8 | context->regs[Z80_L];
491 } else if (inst.ea_reg == Z80_IX) { 498 } else if (inst.ea_reg == Z80_IX) {
492 after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL]; 499 after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL];
493 } else if (inst.ea_reg == Z80_IY) { 500 } else if (inst.ea_reg == Z80_IY) {
494 after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL]; 501 after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL];
502 #endif
495 } 503 }
496 } else if(inst.op == Z80_JR) { 504 } else if(inst.op == Z80_JR) {
497 after += inst.immed; 505 after += inst.immed;
498 } else if(inst.op == Z80_RET) { 506 } else if(inst.op == Z80_RET) {
499 uint8_t *sp = get_native_pointer(context->sp, (void **)context->mem_pointers, &context->options->gen); 507 uint8_t *sp = get_native_pointer(context->sp, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
500 if (sp) { 508 if (sp) {
501 after = *sp; 509 after = *sp;
502 sp = get_native_pointer((context->sp + 1) & 0xFFFF, (void **)context->mem_pointers, &context->options->gen); 510 sp = get_native_pointer((context->sp + 1) & 0xFFFF, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
503 if (sp) { 511 if (sp) {
504 after |= *sp << 8; 512 after |= *sp << 8;
505 } 513 }
506 } 514 }
507 } 515 }
525 if (!param) { 533 if (!param) {
526 fputs("s command requires a file name\n", stderr); 534 fputs("s command requires a file name\n", stderr);
527 break; 535 break;
528 } 536 }
529 memmap_chunk const *ram_chunk = NULL; 537 memmap_chunk const *ram_chunk = NULL;
530 for (int i = 0; i < context->options->gen.memmap_chunks; i++) 538 for (int i = 0; i < context->Z80_OPTS->gen.memmap_chunks; i++)
531 { 539 {
532 memmap_chunk const *cur = context->options->gen.memmap + i; 540 memmap_chunk const *cur = context->Z80_OPTS->gen.memmap + i;
533 if (cur->flags & MMAP_WRITE) { 541 if (cur->flags & MMAP_WRITE) {
534 ram_chunk = cur; 542 ram_chunk = cur;
535 break; 543 break;
536 } 544 }
537 } 545 }
538 if (ram_chunk) { 546 if (ram_chunk) {
539 uint32_t size = ram_chunk->end - ram_chunk->start; 547 uint32_t size = ram_chunk->end - ram_chunk->start;
540 if (size > ram_chunk->mask) { 548 if (size > ram_chunk->mask) {
541 size = ram_chunk->mask+1; 549 size = ram_chunk->mask+1;
542 } 550 }
543 uint8_t *buf = get_native_pointer(ram_chunk->start, (void **)context->mem_pointers, &context->options->gen); 551 uint8_t *buf = get_native_pointer(ram_chunk->start, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
544 FILE * f = fopen(param, "wb"); 552 FILE * f = fopen(param, "wb");
545 if (f) { 553 if (f) {
546 if(fwrite(buf, 1, size, f) != size) { 554 if(fwrite(buf, 1, size, f) != size) {
547 fputs("Error writing file\n", stderr); 555 fputs("Error writing file\n", stderr);
548 } 556 }
554 } else { 562 } else {
555 fputs("Failed to find a RAM memory chunk\n", stderr); 563 fputs("Failed to find a RAM memory chunk\n", stderr);
556 } 564 }
557 break; 565 break;
558 } 566 }
567 case '?':
568 print_z80_help();
569 break;
559 default: 570 default:
560 if ( 571 if (
561 !context->options->gen.debug_cmd_handler 572 !context->Z80_OPTS->gen.debug_cmd_handler
562 || !context->options->gen.debug_cmd_handler(&system->header, input_buf) 573 || !context->Z80_OPTS->gen.debug_cmd_handler(&system->header, input_buf)
563 ) { 574 ) {
564 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf); 575 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf);
565 } 576 }
566 break; 577 break;
567 } 578 }
568 } 579 }
569 return context; 580 return context;
572 #endif 583 #endif
573 584
574 static uint32_t branch_t; 585 static uint32_t branch_t;
575 static uint32_t branch_f; 586 static uint32_t branch_f;
576 587
577 int run_debugger_command(m68k_context *context, char *input_buf, m68kinst inst, uint32_t after) 588 int run_debugger_command(m68k_context *context, uint32_t address, char *input_buf, m68kinst inst, uint32_t after)
578 { 589 {
579 char * param; 590 char * param;
580 char format_char; 591 char format_char;
581 genesis_context *system = context->system; 592 genesis_context *system = context->system;
582 uint32_t value; 593 uint32_t value;
690 param = find_param(input_buf); 701 param = find_param(input_buf);
691 if (!param) { 702 if (!param) {
692 fputs("display command requires a parameter\n", stderr); 703 fputs("display command requires a parameter\n", stderr);
693 break; 704 break;
694 } 705 }
695 debugger_print(context, format_char, param); 706 debugger_print(context, format_char, param, address);
696 add_display(&displays, &disp_index, format_char, param); 707 add_display(&displays, &disp_index, format_char, param);
697 } else { 708 } else {
698 param = find_param(input_buf); 709 param = find_param(input_buf);
699 if (!param) { 710 if (!param) {
700 fputs("d command requires a parameter\n", stderr); 711 fputs("d command requires a parameter\n", stderr);
721 format_char = input_buf[i+1]; 732 format_char = input_buf[i+1];
722 break; 733 break;
723 } 734 }
724 } 735 }
725 param = find_param(input_buf); 736 param = find_param(input_buf);
726 if (!param) { 737 if (param) {
727 fputs("p command requires a parameter\n", stderr); 738 debugger_print(context, format_char, param, address);
728 break; 739 } else {
729 } 740 m68k_disasm(&inst, input_buf);
730 debugger_print(context, format_char, param); 741 printf("%X: %s\n", address, input_buf);
742 }
743
731 break; 744 break;
732 case 'n': 745 case 'n':
733 if (inst.op == M68K_RTS) { 746 if (inst.op == M68K_RTS) {
734 after = m68k_read_long(context->aregs[7], context); 747 after = m68k_read_long(context->aregs[7], context);
735 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { 748 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
789 case 's': 802 case 's':
790 if (input_buf[1] == 'e') { 803 if (input_buf[1] == 'e') {
791 param = find_param(input_buf); 804 param = find_param(input_buf);
792 if (!param) { 805 if (!param) {
793 fputs("Missing destination parameter for set\n", stderr); 806 fputs("Missing destination parameter for set\n", stderr);
807 return 1;
794 } 808 }
795 char *val = find_param(param); 809 char *val = find_param(param);
796 if (!val) { 810 if (!val) {
797 fputs("Missing value parameter for set\n", stderr); 811 fputs("Missing value parameter for set\n", stderr);
812 return 1;
798 } 813 }
799 long int_val; 814 long int_val;
800 int reg_num; 815 int reg_num;
801 switch (val[0]) 816 switch (val[0])
802 { 817 {
833 break; 848 break;
834 default: 849 default:
835 fprintf(stderr, "Invalid destinatino %s\n", param); 850 fprintf(stderr, "Invalid destinatino %s\n", param);
836 } 851 }
837 break; 852 break;
853 } else if (input_buf[1] == 'r') {
854 system->header.soft_reset(&system->header);
855 return 0;
838 } else { 856 } else {
839 if (inst.op == M68K_RTS) { 857 if (inst.op == M68K_RTS) {
840 after = m68k_read_long(context->aregs[7], context); 858 after = m68k_read_long(context->aregs[7], context);
841 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { 859 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
842 after = m68k_read_long(context->aregs[7] + 2, context); 860 after = m68k_read_long(context->aregs[7] + 2, context);
927 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param); 945 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param);
928 } 946 }
929 break; 947 break;
930 } 948 }
931 #endif 949 #endif
950 case '?':
951 print_m68k_help();
952 break;
932 case 'q': 953 case 'q':
933 puts("Quitting"); 954 puts("Quitting");
934 exit(0); 955 exit(0);
935 break; 956 break;
936 default: 957 default:
937 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf); 958 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf);
938 break; 959 break;
939 } 960 }
940 return 1; 961 return 1;
941 } 962 }
942 963
964 void print_m68k_help()
965 {
966 printf("M68k Debugger Commands\n");
967 printf(" b ADDRESS - Set a breakpoint at ADDRESS\n");
968 printf(" d BREAKPOINT - Delete a 68K breakpoint\n");
969 printf(" co BREAKPOINT - Run a list of debugger commands each time\n");
970 printf(" BREAKPOINT is hit\n");
971 printf(" a ADDRESS - Advance to address\n");
972 printf(" n - Advance to next instruction\n");
973 printf(" o - Advance to next instruction ignoring branches to\n");
974 printf(" lower addresses (good for breaking out of loops)\n");
975 printf(" s - Advance to next instruction (follows bsr/jsr)\n");
976 printf(" se REG|ADDRESS VALUE - Set value\n");
977 printf(" sr - Soft reset\n");
978 printf(" c - Continue\n");
979 printf(" bt - Print a backtrace\n");
980 printf(" p[/(x|X|d|c)] VALUE - Print a register or memory location\n");
981 printf(" di[/(x|X|d|c)] VALUE - Print a register or memory location each time\n");
982 printf(" a breakpoint is hit\n");
983 printf(" vs - Print VDP sprite list\n");
984 printf(" vr - Print VDP register info\n");
985 printf(" yc [CHANNEL NUM] - Print YM-2612 channel info\n");
986 printf(" yt - Print YM-2612 timer info\n");
987 printf(" zb ADDRESS - Set a Z80 breakpoint\n");
988 printf(" zp[/(x|X|d|c)] VALUE - Display a Z80 value\n");
989 printf(" ? - Display help\n");
990 printf(" q - Quit BlastEm\n");
991 }
992
993 void print_z80_help()
994 {
995 printf("Z80 Debugger Commands\n");
996 printf(" b ADDRESS - Set a breakpoint at ADDRESS\n");
997 printf(" de BREAKPOINT - Delete a Z80 breakpoint\n");
998 printf(" a ADDRESS - Advance to address\n");
999 printf(" n - Advance to next instruction\n");
1000 printf(" c - Continue\n");
1001 printf(" p[/(x|X|d|c)] VALUE - Print a register or memory location\n");
1002 printf(" di[/(x|X|d|c)] VALUE - Print a register or memory location each time\n");
1003 printf(" a breakpoint is hit\n");
1004 printf(" q - Quit BlastEm\n");
1005 }
943 1006
944 void debugger(m68k_context * context, uint32_t address) 1007 void debugger(m68k_context * context, uint32_t address)
945 { 1008 {
946 static char last_cmd[1024]; 1009 static char last_cmd[1024];
947 char input_buf[1024]; 1010 char input_buf[1024];
987 while (debugging && *commands) 1050 while (debugging && *commands)
988 { 1051 {
989 char *cmd = commands; 1052 char *cmd = commands;
990 strip_nl(cmd); 1053 strip_nl(cmd);
991 commands += strlen(cmd) + 1; 1054 commands += strlen(cmd) + 1;
992 debugging = run_debugger_command(context, cmd, inst, after); 1055 debugging = run_debugger_command(context, address, cmd, inst, after);
993 } 1056 }
994 free(copy); 1057 free(copy);
995 } 1058 }
996 if (debugging) { 1059 if (debugging) {
997 printf("68K Breakpoint %d hit\n", (*this_bp)->index); 1060 printf("68K Breakpoint %d hit\n", (*this_bp)->index);
1000 } 1063 }
1001 } else { 1064 } else {
1002 remove_breakpoint(context, address); 1065 remove_breakpoint(context, address);
1003 } 1066 }
1004 for (disp_def * cur = displays; cur; cur = cur->next) { 1067 for (disp_def * cur = displays; cur; cur = cur->next) {
1005 debugger_print(context, cur->format_char, cur->param); 1068 debugger_print(context, cur->format_char, cur->param, address);
1006 } 1069 }
1007 m68k_disasm(&inst, input_buf); 1070 m68k_disasm(&inst, input_buf);
1008 printf("%X: %s\n", address, input_buf); 1071 printf("%X: %s\n", address, input_buf);
1009 #ifdef _WIN32 1072 #ifdef _WIN32
1010 #define prompt 1 1073 #define prompt 1
1040 if (input_buf[0]) { 1103 if (input_buf[0]) {
1041 strcpy(last_cmd, input_buf); 1104 strcpy(last_cmd, input_buf);
1042 } else { 1105 } else {
1043 strcpy(input_buf, last_cmd); 1106 strcpy(input_buf, last_cmd);
1044 } 1107 }
1045 debugging = run_debugger_command(context, input_buf, inst, after); 1108 debugging = run_debugger_command(context, address, input_buf, inst, after);
1046 } 1109 }
1047 return; 1110 return;
1048 } 1111 }