Mercurial > repos > blastem
comparison debug.c @ 1931:374a5ae694e8 mame_interp
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 18 Apr 2020 11:42:53 -0700 |
parents | 0a26f3657295 23394a890508 |
children | a7b753e260a2 |
comparison
equal
deleted
inserted
replaced
1843:13abdc98379e | 1931:374a5ae694e8 |
---|---|
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" | 12 #include "z80inst.h" |
13 | 13 |
14 #ifndef USE_NATIVE | 14 #ifdef NEW_CORE |
15 #define Z80_OPTS opts | 15 #define Z80_OPTS opts |
16 #else | 16 #else |
17 #define Z80_OPTS options | 17 #define Z80_OPTS options |
18 #endif | 18 #endif |
19 | 19 |
103 uint32_t m68k_read_long(uint32_t address, m68k_context *context) | 103 uint32_t m68k_read_long(uint32_t address, m68k_context *context) |
104 { | 104 { |
105 return m68k_read_word(address, context) << 16 | m68k_read_word(address + 2, context); | 105 return m68k_read_word(address, context) << 16 | m68k_read_word(address + 2, context); |
106 } | 106 } |
107 | 107 |
108 void debugger_print(m68k_context *context, char format_char, char *param) | 108 void debugger_print(m68k_context *context, char format_char, char *param, uint32_t address) |
109 { | 109 { |
110 uint32_t value; | 110 uint32_t value; |
111 char format[8]; | 111 char format[8]; |
112 strcpy(format, "%s: %d\n"); | 112 strcpy(format, "%s: %d\n"); |
113 switch (format_char) | 113 switch (format_char) |
139 value &= 0xFFFF; | 139 value &= 0xFFFF; |
140 } else if (param[3] == 'b') { | 140 } else if (param[3] == 'b') { |
141 value &= 0xFF; | 141 value &= 0xFF; |
142 } | 142 } |
143 } | 143 } |
144 } else if (param[0] == 'S' && param[1] == 'R') { | 144 } else if (param[0] == 's' && param[1] == 'r') { |
145 value = (context->status << 8); | 145 value = (context->status << 8); |
146 for (int flag = 0; flag < 5; flag++) { | 146 for (int flag = 0; flag < 5; flag++) { |
147 value |= context->flags[flag] << (4-flag); | 147 value |= context->flags[flag] << (4-flag); |
148 } | 148 } |
149 } else if(param[0] == 'c') { | 149 } else if(param[0] == 'c') { |
150 value = context->current_cycle; | 150 value = context->current_cycle; |
151 } else if(param[0] == 'f') { | 151 } else if(param[0] == 'f') { |
152 genesis_context *gen = context->system; | 152 genesis_context *gen = context->system; |
153 value = gen->vdp->frame; | 153 value = gen->vdp->frame; |
154 } else if (param[0] == 'p' && param[1] == 'c') { | |
155 value = address; | |
154 } else if ((param[0] == '0' && param[1] == 'x') || param[0] == '$') { | 156 } else if ((param[0] == '0' && param[1] == 'x') || param[0] == '$') { |
155 char *after; | 157 char *after; |
156 uint32_t p_addr = strtol(param+(param[0] == '0' ? 2 : 1), &after, 16); | 158 uint32_t p_addr = strtol(param+(param[0] == '0' ? 2 : 1), &after, 16); |
157 if (after[0] == '.' && after[1] == 'l') { | 159 if (after[0] == '.' && after[1] == 'l') { |
158 value = m68k_read_long(p_addr, context); | 160 value = m68k_read_long(p_addr, context); |
195 default: | 197 default: |
196 fprintf(stderr, "Unrecognized format character: %c\n", format_char); | 198 fprintf(stderr, "Unrecognized format character: %c\n", format_char); |
197 } | 199 } |
198 switch (param[0]) | 200 switch (param[0]) |
199 { | 201 { |
200 #ifdef USE_NATIVE | 202 #ifndef NEW_CORE |
201 case 'a': | 203 case 'a': |
202 if (param[1] == 'f') { | 204 if (param[1] == 'f') { |
203 if(param[2] == '\'') { | 205 if(param[2] == '\'') { |
204 value = context->alt_regs[Z80_A] << 8; | 206 value = context->alt_regs[Z80_A] << 8; |
205 value |= context->alt_flags[ZF_S] << 7; | 207 value |= context->alt_flags[ZF_S] << 7; |
346 } | 348 } |
347 break; | 349 break; |
348 case '0': | 350 case '0': |
349 if (param[1] == 'x') { | 351 if (param[1] == 'x') { |
350 uint16_t p_addr = strtol(param+2, NULL, 16); | 352 uint16_t p_addr = strtol(param+2, NULL, 16); |
351 if (p_addr < 0x4000) { | 353 value = read_byte(p_addr, (void **)context->mem_pointers, &context->options->gen, context); |
352 value = system->zram[p_addr & 0x1FFF]; | |
353 } else if(p_addr >= 0x8000) { | |
354 uint32_t v_addr = system->z80_bank_reg << 15; | |
355 v_addr += p_addr & 0x7FFF; | |
356 if (v_addr < 0x400000) { | |
357 value = system->cart[v_addr/2]; | |
358 } else if(v_addr > 0xE00000) { | |
359 value = system->work_ram[(v_addr & 0xFFFF)/2]; | |
360 } | |
361 if (v_addr & 1) { | |
362 value &= 0xFF; | |
363 } else { | |
364 value >>= 8; | |
365 } | |
366 } | |
367 } | 354 } |
368 break; | 355 break; |
369 } | 356 } |
370 printf(format, param, value); | 357 printf(format, param, value); |
371 } | 358 } |
494 //TODO: Handle conditional branch instructions | 481 //TODO: Handle conditional branch instructions |
495 if (inst.op == Z80_JP) { | 482 if (inst.op == Z80_JP) { |
496 if (inst.addr_mode == Z80_IMMED) { | 483 if (inst.addr_mode == Z80_IMMED) { |
497 after = inst.immed; | 484 after = inst.immed; |
498 } else if (inst.ea_reg == Z80_HL) { | 485 } else if (inst.ea_reg == Z80_HL) { |
499 #ifdef USE_NATIVE | 486 #ifndef NEW_CORE |
500 after = context->regs[Z80_H] << 8 | context->regs[Z80_L]; | 487 after = context->regs[Z80_H] << 8 | context->regs[Z80_L]; |
501 } else if (inst.ea_reg == Z80_IX) { | 488 } else if (inst.ea_reg == Z80_IX) { |
502 after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL]; | 489 after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL]; |
503 } else if (inst.ea_reg == Z80_IY) { | 490 } else if (inst.ea_reg == Z80_IY) { |
504 after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL]; | 491 after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL]; |
565 } else { | 552 } else { |
566 fputs("Failed to find a RAM memory chunk\n", stderr); | 553 fputs("Failed to find a RAM memory chunk\n", stderr); |
567 } | 554 } |
568 break; | 555 break; |
569 } | 556 } |
557 case '?': | |
558 print_z80_help(); | |
559 break; | |
570 default: | 560 default: |
571 if ( | 561 if ( |
572 !context->Z80_OPTS->gen.debug_cmd_handler | 562 !context->Z80_OPTS->gen.debug_cmd_handler |
573 || !context->Z80_OPTS->gen.debug_cmd_handler(&system->header, input_buf) | 563 || !context->Z80_OPTS->gen.debug_cmd_handler(&system->header, input_buf) |
574 ) { | 564 ) { |
575 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf); | 565 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf); |
576 } | 566 } |
577 break; | 567 break; |
578 } | 568 } |
579 } | 569 } |
580 return context; | 570 return context; |
583 #endif | 573 #endif |
584 | 574 |
585 static uint32_t branch_t; | 575 static uint32_t branch_t; |
586 static uint32_t branch_f; | 576 static uint32_t branch_f; |
587 | 577 |
588 int run_debugger_command(m68k_context *context, char *input_buf, m68kinst inst, uint32_t after) | 578 int run_debugger_command(m68k_context *context, uint32_t address, char *input_buf, m68kinst inst, uint32_t after) |
589 { | 579 { |
590 char * param; | 580 char * param; |
591 char format_char; | 581 char format_char; |
592 genesis_context *system = context->system; | 582 genesis_context *system = context->system; |
593 uint32_t value; | 583 uint32_t value; |
701 param = find_param(input_buf); | 691 param = find_param(input_buf); |
702 if (!param) { | 692 if (!param) { |
703 fputs("display command requires a parameter\n", stderr); | 693 fputs("display command requires a parameter\n", stderr); |
704 break; | 694 break; |
705 } | 695 } |
706 debugger_print(context, format_char, param); | 696 debugger_print(context, format_char, param, address); |
707 add_display(&displays, &disp_index, format_char, param); | 697 add_display(&displays, &disp_index, format_char, param); |
708 } else { | 698 } else { |
709 param = find_param(input_buf); | 699 param = find_param(input_buf); |
710 if (!param) { | 700 if (!param) { |
711 fputs("d command requires a parameter\n", stderr); | 701 fputs("d command requires a parameter\n", stderr); |
732 format_char = input_buf[i+1]; | 722 format_char = input_buf[i+1]; |
733 break; | 723 break; |
734 } | 724 } |
735 } | 725 } |
736 param = find_param(input_buf); | 726 param = find_param(input_buf); |
737 if (!param) { | 727 if (param) { |
738 fputs("p command requires a parameter\n", stderr); | 728 debugger_print(context, format_char, param, address); |
739 break; | 729 } else { |
740 } | 730 m68k_disasm(&inst, input_buf); |
741 debugger_print(context, format_char, param); | 731 printf("%X: %s\n", address, input_buf); |
732 } | |
733 | |
742 break; | 734 break; |
743 case 'n': | 735 case 'n': |
744 if (inst.op == M68K_RTS) { | 736 if (inst.op == M68K_RTS) { |
745 after = m68k_read_long(context->aregs[7], context); | 737 after = m68k_read_long(context->aregs[7], context); |
746 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | 738 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { |
800 case 's': | 792 case 's': |
801 if (input_buf[1] == 'e') { | 793 if (input_buf[1] == 'e') { |
802 param = find_param(input_buf); | 794 param = find_param(input_buf); |
803 if (!param) { | 795 if (!param) { |
804 fputs("Missing destination parameter for set\n", stderr); | 796 fputs("Missing destination parameter for set\n", stderr); |
797 return 1; | |
805 } | 798 } |
806 char *val = find_param(param); | 799 char *val = find_param(param); |
807 if (!val) { | 800 if (!val) { |
808 fputs("Missing value parameter for set\n", stderr); | 801 fputs("Missing value parameter for set\n", stderr); |
802 return 1; | |
809 } | 803 } |
810 long int_val; | 804 long int_val; |
811 int reg_num; | 805 int reg_num; |
812 switch (val[0]) | 806 switch (val[0]) |
813 { | 807 { |
844 break; | 838 break; |
845 default: | 839 default: |
846 fprintf(stderr, "Invalid destinatino %s\n", param); | 840 fprintf(stderr, "Invalid destinatino %s\n", param); |
847 } | 841 } |
848 break; | 842 break; |
843 } else if (input_buf[1] == 'r') { | |
844 system->header.soft_reset(&system->header); | |
845 return 0; | |
849 } else { | 846 } else { |
850 if (inst.op == M68K_RTS) { | 847 if (inst.op == M68K_RTS) { |
851 after = m68k_read_long(context->aregs[7], context); | 848 after = m68k_read_long(context->aregs[7], context); |
852 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | 849 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { |
853 after = m68k_read_long(context->aregs[7] + 2, context); | 850 after = m68k_read_long(context->aregs[7] + 2, context); |
938 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param); | 935 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param); |
939 } | 936 } |
940 break; | 937 break; |
941 } | 938 } |
942 #endif | 939 #endif |
940 case '?': | |
941 print_m68k_help(); | |
942 break; | |
943 case 'q': | 943 case 'q': |
944 puts("Quitting"); | 944 puts("Quitting"); |
945 exit(0); | 945 exit(0); |
946 break; | 946 break; |
947 default: | 947 default: |
948 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf); | 948 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf); |
949 break; | 949 break; |
950 } | 950 } |
951 return 1; | 951 return 1; |
952 } | 952 } |
953 | 953 |
954 void print_m68k_help() | |
955 { | |
956 printf("M68k Debugger Commands\n"); | |
957 printf(" b ADDRESS - Set a breakpoint at ADDRESS\n"); | |
958 printf(" d BREAKPOINT - Delete a 68K breakpoint\n"); | |
959 printf(" co BREAKPOINT - Run a list of debugger commands each time\n"); | |
960 printf(" BREAKPOINT is hit\n"); | |
961 printf(" a ADDRESS - Advance to address\n"); | |
962 printf(" n - Advance to next instruction\n"); | |
963 printf(" o - Advance to next instruction ignoring branches to\n"); | |
964 printf(" lower addresses (good for breaking out of loops)\n"); | |
965 printf(" s - Advance to next instruction (follows bsr/jsr)\n"); | |
966 printf(" se REG|ADDRESS VALUE - Set value\n"); | |
967 printf(" sr - Soft reset\n"); | |
968 printf(" c - Continue\n"); | |
969 printf(" bt - Print a backtrace\n"); | |
970 printf(" p[/(x|X|d|c)] VALUE - Print a register or memory location\n"); | |
971 printf(" di[/(x|X|d|c)] VALUE - Print a register or memory location each time\n"); | |
972 printf(" a breakpoint is hit\n"); | |
973 printf(" vs - Print VDP sprite list\n"); | |
974 printf(" vr - Print VDP register info\n"); | |
975 printf(" yc [CHANNEL NUM] - Print YM-2612 channel info\n"); | |
976 printf(" yt - Print YM-2612 timer info\n"); | |
977 printf(" zb ADDRESS - Set a Z80 breakpoint\n"); | |
978 printf(" zp[/(x|X|d|c)] VALUE - Display a Z80 value\n"); | |
979 printf(" ? - Display help\n"); | |
980 printf(" q - Quit BlastEm\n"); | |
981 } | |
982 | |
983 void print_z80_help() | |
984 { | |
985 printf("Z80 Debugger Commands\n"); | |
986 printf(" b ADDRESS - Set a breakpoint at ADDRESS\n"); | |
987 printf(" de BREAKPOINT - Delete a Z80 breakpoint\n"); | |
988 printf(" a ADDRESS - Advance to address\n"); | |
989 printf(" n - Advance to next instruction\n"); | |
990 printf(" c - Continue\n"); | |
991 printf(" p[/(x|X|d|c)] VALUE - Print a register or memory location\n"); | |
992 printf(" di[/(x|X|d|c)] VALUE - Print a register or memory location each time\n"); | |
993 printf(" a breakpoint is hit\n"); | |
994 printf(" q - Quit BlastEm\n"); | |
995 } | |
954 | 996 |
955 void debugger(m68k_context * context, uint32_t address) | 997 void debugger(m68k_context * context, uint32_t address) |
956 { | 998 { |
957 static char last_cmd[1024]; | 999 static char last_cmd[1024]; |
958 char input_buf[1024]; | 1000 char input_buf[1024]; |
998 while (debugging && *commands) | 1040 while (debugging && *commands) |
999 { | 1041 { |
1000 char *cmd = commands; | 1042 char *cmd = commands; |
1001 strip_nl(cmd); | 1043 strip_nl(cmd); |
1002 commands += strlen(cmd) + 1; | 1044 commands += strlen(cmd) + 1; |
1003 debugging = run_debugger_command(context, cmd, inst, after); | 1045 debugging = run_debugger_command(context, address, cmd, inst, after); |
1004 } | 1046 } |
1005 free(copy); | 1047 free(copy); |
1006 } | 1048 } |
1007 if (debugging) { | 1049 if (debugging) { |
1008 printf("68K Breakpoint %d hit\n", (*this_bp)->index); | 1050 printf("68K Breakpoint %d hit\n", (*this_bp)->index); |
1011 } | 1053 } |
1012 } else { | 1054 } else { |
1013 remove_breakpoint(context, address); | 1055 remove_breakpoint(context, address); |
1014 } | 1056 } |
1015 for (disp_def * cur = displays; cur; cur = cur->next) { | 1057 for (disp_def * cur = displays; cur; cur = cur->next) { |
1016 debugger_print(context, cur->format_char, cur->param); | 1058 debugger_print(context, cur->format_char, cur->param, address); |
1017 } | 1059 } |
1018 m68k_disasm(&inst, input_buf); | 1060 m68k_disasm(&inst, input_buf); |
1019 printf("%X: %s\n", address, input_buf); | 1061 printf("%X: %s\n", address, input_buf); |
1020 #ifdef _WIN32 | 1062 #ifdef _WIN32 |
1021 #define prompt 1 | 1063 #define prompt 1 |
1051 if (input_buf[0]) { | 1093 if (input_buf[0]) { |
1052 strcpy(last_cmd, input_buf); | 1094 strcpy(last_cmd, input_buf); |
1053 } else { | 1095 } else { |
1054 strcpy(input_buf, last_cmd); | 1096 strcpy(input_buf, last_cmd); |
1055 } | 1097 } |
1056 debugging = run_debugger_command(context, input_buf, inst, after); | 1098 debugging = run_debugger_command(context, address, input_buf, inst, after); |
1057 } | 1099 } |
1058 return; | 1100 return; |
1059 } | 1101 } |