comparison debug.c @ 2178:f6d5bde4d07f

Finish debugger refactor started with expression parser changes
author Michael Pavone <pavone@retrodev.com>
date Sat, 13 Aug 2022 19:16:30 -0700
parents 44596610b2a0
children 9a8dd4ba2753
comparison
equal deleted inserted replaced
2177:44596610b2a0 2178:f6d5bde4d07f
18 #define Z80_OPTS opts 18 #define Z80_OPTS opts
19 #else 19 #else
20 #define Z80_OPTS options 20 #define Z80_OPTS options
21 #endif 21 #endif
22 22
23
24
25 static debug_root roots[5]; 23 static debug_root roots[5];
26 static uint32_t num_roots; 24 static uint32_t num_roots;
27 #define MAX_DEBUG_ROOTS (sizeof(roots)/sizeof(*roots)) 25 #define MAX_DEBUG_ROOTS (sizeof(roots)/sizeof(*roots))
28 26
29 debug_root *find_root(void *cpu) 27 debug_root *find_root(void *cpu)
62 } 60 }
63 cur = &((*cur)->next); 61 cur = &((*cur)->next);
64 } 62 }
65 return cur; 63 return cur;
66 } 64 }
67
68 typedef enum {
69 TOKEN_NONE,
70 TOKEN_NUM,
71 TOKEN_NAME,
72 TOKEN_OPER,
73 TOKEN_SIZE,
74 TOKEN_LBRACKET,
75 TOKEN_RBRACKET,
76 TOKEN_LPAREN,
77 TOKEN_RPAREN
78 } token_type;
79 65
80 static const char *token_type_names[] = { 66 static const char *token_type_names[] = {
81 "TOKEN_NONE", 67 "TOKEN_NONE",
82 "TOKEN_NUM", 68 "TOKEN_NUM",
83 "TOKEN_NAME", 69 "TOKEN_NAME",
87 "TOKEN_RBRACKET", 73 "TOKEN_RBRACKET",
88 "TOKEN_LPAREN", 74 "TOKEN_LPAREN",
89 "TOKEN_RPAREN" 75 "TOKEN_RPAREN"
90 }; 76 };
91 77
92 typedef struct {
93 token_type type;
94 union {
95 char *str;
96 char op[3];
97 uint32_t num;
98 } v;
99 } token;
100
101 static token parse_token(char *start, char **end) 78 static token parse_token(char *start, char **end)
102 { 79 {
103 while(*start && isblank(*start) && *start != '\n') 80 while(*start && isblank(*start) && *start != '\n' && *start != '\r')
104 { 81 {
105 ++start; 82 ++start;
106 } 83 }
107 if (!*start || *start == '\n') { 84 if (!*start || *start == '\n' || *start == '\r') {
108 return (token){ 85 return (token){
109 .type = TOKEN_NONE 86 .type = TOKEN_NONE
110 }; 87 };
111 *end = start; 88 *end = start;
112 } 89 }
182 return (token) { 159 return (token) {
183 .type = TOKEN_RPAREN 160 .type = TOKEN_RPAREN
184 }; 161 };
185 } 162 }
186 *end = start + 1; 163 *end = start + 1;
187 while (**end && !isblank(**end)) 164 while (**end && !isspace(**end))
188 { 165 {
189 uint8_t done = 0; 166 uint8_t done = 0;
190 switch (**end) 167 switch (**end)
191 { 168 {
192 case '+': 169 case '+':
217 .v = { 194 .v = {
218 .str = name 195 .str = name
219 } 196 }
220 }; 197 };
221 } 198 }
222
223 typedef enum {
224 EXPR_NONE,
225 EXPR_SCALAR,
226 EXPR_UNARY,
227 EXPR_BINARY,
228 EXPR_SIZE,
229 EXPR_MEM
230 } expr_type;
231
232 typedef struct expr expr;
233
234 struct expr {
235 expr_type type;
236 expr *left;
237 expr *right;
238 token op;
239 };
240 199
241 static void free_expr(expr *e) 200 static void free_expr(expr *e)
242 { 201 {
243 if (!e) { 202 if (!e) {
244 return; 203 return;
617 value->left = calloc(1, sizeof(expr)); 576 value->left = calloc(1, sizeof(expr));
618 value->left->type = EXPR_SCALAR; 577 value->left->type = EXPR_SCALAR;
619 value->left->op = first; 578 value->left->op = first;
620 return maybe_binary(value, after_second, end); 579 return maybe_binary(value, after_second, end);
621 } else { 580 } else {
581 if (second.type == TOKEN_NAME) {
582 free(second.v.str);
583 }
622 expr *ret = calloc(1, sizeof(expr)); 584 expr *ret = calloc(1, sizeof(expr));
623 ret->type = EXPR_SCALAR; 585 ret->type = EXPR_SCALAR;
624 ret->op = first; 586 ret->op = first;
625 *end = after_first; 587 *end = after_first;
626 return ret; 588 return ret;
717 default: 679 default:
718 return 0; 680 return 0;
719 } 681 }
720 } 682 }
721 683
722 void add_display(disp_def ** head, uint32_t *index, char format_char, char * param)
723 {
724 disp_def * ndisp = malloc(sizeof(*ndisp));
725 ndisp->format_char = format_char;
726 ndisp->param = strdup(param);
727 ndisp->next = *head;
728 ndisp->index = *index++;
729 *head = ndisp;
730 }
731
732 void remove_display(disp_def ** head, uint32_t index)
733 {
734 while (*head) {
735 if ((*head)->index == index) {
736 disp_def * del_disp = *head;
737 *head = del_disp->next;
738 free(del_disp->param);
739 free(del_disp);
740 } else {
741 head = &(*head)->next;
742 }
743 }
744 }
745
746 char * find_param(char * buf) 684 char * find_param(char * buf)
747 { 685 {
748 for (; *buf; buf++) { 686 for (; *buf; buf++) {
749 if (*buf == ' ') { 687 if (*buf == ' ') {
750 if (*(buf+1)) { 688 if (*(buf+1)) {
785 { 723 {
786 m68k_context *context = root->cpu_context; 724 m68k_context *context = root->cpu_context;
787 if (size == 'b') { 725 if (size == 'b') {
788 *out = m68k_read_byte(*out, context); 726 *out = m68k_read_byte(*out, context);
789 } else if (size == 'l') { 727 } else if (size == 'l') {
728 if (*out & 1) {
729 fprintf(stderr, "Longword access to odd addresses (%X) is not allowed\n", *out);
730 return 0;
731 }
790 *out = m68k_read_long(*out, context); 732 *out = m68k_read_long(*out, context);
791 } else { 733 } else {
734 if (*out & 1) {
735 fprintf(stderr, "Wword access to odd addresses (%X) is not allowed\n", *out);
736 return 0;
737 }
792 *out = m68k_read_word(*out, context); 738 *out = m68k_read_word(*out, context);
739 }
740 return 1;
741 }
742
743 static uint8_t write_m68k(debug_root *root, uint32_t address, uint32_t value, char size)
744 {
745 m68k_context *context = root->cpu_context;
746 if (size == 'b') {
747 write_byte(address, value, (void **)context->mem_pointers, &context->options->gen, context);
748 } else if (size == 'l') {
749 if (address & 1) {
750 fprintf(stderr, "Longword access to odd addresses (%X) is not allowed\n", address);
751 return 0;
752 }
753 write_word(address, value >> 16, (void **)context->mem_pointers, &context->options->gen, context);
754 write_word(address + 2, value, (void **)context->mem_pointers, &context->options->gen, context);
755 } else {
756 if (address & 1) {
757 fprintf(stderr, "Wword access to odd addresses (%X) is not allowed\n", address);
758 return 0;
759 }
760 write_word(address, value, (void **)context->mem_pointers, &context->options->gen, context);
793 } 761 }
794 return 1; 762 return 1;
795 } 763 }
796 764
797 static uint8_t resolve_m68k(debug_root *root, const char *name, uint32_t *out) 765 static uint8_t resolve_m68k(debug_root *root, const char *name, uint32_t *out)
818 return 0; 786 return 0;
819 } 787 }
820 return 1; 788 return 1;
821 } 789 }
822 790
791 static uint8_t set_m68k(debug_root *root, const char *name, uint32_t value)
792 {
793 m68k_context *context = root->cpu_context;
794 if ((name[0] == 'd' || name[0] == 'D') && name[1] >= '0' && name[1] <= '7' && !name[2]) {
795 context->dregs[name[1]-'0'] = value;
796 } else if ((name[0] == 'a' || name[0] == 'A') && name[1] >= '0' && name[1] <= '7' && !name[2]) {
797 context->aregs[name[1]-'0'] = value;
798 } else if (!strcasecmp(name, "sr")) {
799 context->status = value >> 8;
800 for (int flag = 0; flag < 5; flag++) {
801 context->flags[flag] = (value & (1 << (4 - flag))) != 0;
802 }
803 } else if (!strcasecmp(name, "usp")) {
804 context->aregs[context->status & 0x20 ? 8 : 7] = value;
805 } else if (!strcasecmp(name, "ssp")) {
806 context->aregs[context->status & 0x20 ? 7 : 8] = value;
807 } else {
808 return 0;
809 }
810 return 1;
811 }
812
823 static uint8_t resolve_genesis(debug_root *root, const char *name, uint32_t *out) 813 static uint8_t resolve_genesis(debug_root *root, const char *name, uint32_t *out)
824 { 814 {
825 if (resolve_m68k(root, name, out)) { 815 if (resolve_m68k(root, name, out)) {
826 return 1; 816 return 1;
827 } 817 }
832 return 1; 822 return 1;
833 } 823 }
834 return 0; 824 return 0;
835 } 825 }
836 826
837 void debugger_print(debug_root *root, char format_char, char *param) 827 void ambiguous_iter(char *key, tern_val val, uint8_t valtype, void *data)
838 { 828 {
839 uint32_t value; 829 char *prefix = data;
840 char format[8]; 830 char * full = alloc_concat(prefix, key);
841 strcpy(format, "%s: %d\n"); 831 fprintf(stderr, "\t%s\n", full);
842 switch (format_char) 832 free(full);
843 { 833 }
844 case 'x': 834
845 case 'X': 835 uint8_t parse_command(debug_root *root, char *text, parsed_command *out)
846 case 'd': 836 {
847 case 'c': 837 char *cur = text;
848 case 's': 838 while (*cur && *cur != '/' && !isspace(*cur))
849 format[5] = format_char; 839 {
850 break; 840 ++cur;
851 case '\0': 841 }
852 break; 842 char *name = malloc(cur - text + 1);
853 default: 843 memcpy(name, text, cur - text);
854 fprintf(stderr, "Unrecognized format character: %c\n", format_char); 844 name[cur-text] = 0;
855 } 845 uint8_t ret = 0;
856 char *after; 846 tern_node *prefix_res = tern_find_prefix(root->commands, name);
857 uint8_t at_least_one = 0; 847 command_def *def = tern_find_ptr(prefix_res, "");
858 while (*param && *param != '\n') 848 if (!def) {
859 { 849 tern_node *node = prefix_res;
860 at_least_one = 1; 850 while (node)
861 expr *e = parse_expression(param, &after); 851 {
862 if (e) { 852 if (node->left || node->right) {
863 if (!eval_expr(root, e, &value)) { 853 break;
864 fprintf(stderr, "Failed to eval %s\n", param); 854 }
865 } 855 if (node->el) {
866 free_expr(e); 856 node = node->straight.next;
867 } else { 857 } else {
868 fprintf(stderr, "Failed to parse %s\n", param); 858 def = node->straight.value.ptrval;
869 } 859 break;
870 char *tmp_param = malloc(after-param+1); 860 }
871 memcpy(tmp_param, param, after-param); 861 }
872 tmp_param[after-param] = 0; 862 if (!def && prefix_res) {
873 param = after; 863 fprintf(stderr, "%s is ambiguous. Matching commands:\n", name);
874 if (format_char == 's') { 864 tern_foreach(prefix_res, ambiguous_iter, name);
865 goto cleanup_name;
866 }
867 }
868 if (!def) {
869 fprintf(stderr, "%s is not a recognized command\n", name);
870 goto cleanup_name;
871 }
872 char *format = NULL;
873 if (*cur == '/') {
874 ++cur;
875 text = cur;
876 while (*cur && !isspace(*cur))
877 {
878 ++cur;
879 }
880 format = malloc(cur - text + 1);
881 memcpy(format, text, cur - text);
882 format[cur - text] = 0;
883 }
884 int num_args = 0;
885 command_arg *args = NULL;
886 if (*cur && *cur != '\n') {
887 ++cur;
888 }
889 text = cur;
890 if (def->raw_impl) {
891 while (*cur && *cur != '\n')
892 {
893 ++cur;
894 }
895 char *raw_param = NULL;
896 if (cur != text) {
897 raw_param = malloc(cur - text + 1);
898 memcpy(raw_param, text, cur - text);
899 raw_param[cur - text] = 0;
900 }
901 out->raw = raw_param;
902 out->args = NULL;
903 out->num_args = 0;
904 } else {
905 int arg_storage = 0;
906 if (def->max_args > 0) {
907 arg_storage = def->max_args;
908 } else if (def->max_args) {
909 arg_storage = def->min_args > 0 ? 2 * def->min_args : 2;
910 }
911 if (arg_storage) {
912 args = calloc(arg_storage, sizeof(command_arg));
913 }
914 while (*text && *text != '\n')
915 {
916 char *after;
917 expr *e = parse_expression(text, &after);
918 if (e) {
919 if (num_args == arg_storage) {
920 if (def->max_args >= 0) {
921 free_expr(e);
922 fprintf(stderr, "Command %s takes a max of %d arguments, but at least %d provided\n", name, def->max_args, def->max_args+1);
923 goto cleanup_args;
924 } else {
925 arg_storage *= 2;
926 args = realloc(args, arg_storage * sizeof(command_arg));
927 }
928 }
929 args[num_args].parsed = e;
930 args[num_args].raw = malloc(after - text + 1);
931 memcpy(args[num_args].raw, text, after - text);
932 args[num_args++].raw[after - text] = 0;
933 text = after;
934 } else {
935 goto cleanup_args;
936 }
937 }
938 if (num_args < def->min_args) {
939 fprintf(stderr, "Command %s requires at least %d arguments, but only %d provided\n", name, def->min_args, num_args);
940 goto cleanup_args;
941 }
942 out->raw = NULL;
943 out->args = args;
944 out->num_args = num_args;
945 }
946 out->def = def;
947 out->format = format;
948
949 ret = 1;
950 cleanup_args:
951 if (!ret) {
952 for (int i = 0; i < num_args; i++)
953 {
954 free_expr(args[i].parsed);
955 free(args[i].raw);
956 }
957 free(args);
958 }
959 cleanup_name:
960 free(name);
961 return ret;
962 }
963
964 static void free_parsed_command(parsed_command *cmd)
965 {
966 free(cmd->format);
967 free(cmd->raw);
968 for (int i = 0; i < cmd->num_args; i++)
969 {
970 free(cmd->args[i].raw);
971 free_expr(cmd->args[i].parsed);
972 }
973 free(cmd->args);
974 }
975
976 static uint8_t cmd_quit(debug_root *root, char *format, int num_args, command_arg *args)
977 {
978 exit(0);
979 }
980
981 typedef struct {
982 size_t num_commands;
983 size_t longest_command;
984 } help_state;
985
986 static void help_first_pass(char *key, tern_val val, uint8_t valtype, void *data)
987 {
988 command_def *def = val.ptrval;
989 if (def->visited) {
990 return;
991 }
992 def->visited = 1;
993 help_state *state = data;
994 state->num_commands++;
995 size_t len = strlen(def->usage);
996 if (len > state->longest_command) {
997 state->longest_command = len;
998 }
999 }
1000
1001 static void help_reset_visited(char *key, tern_val val, uint8_t valtype, void *data)
1002 {
1003 command_def *def = val.ptrval;
1004 def->visited = 0;
1005 }
1006
1007 static void help_second_pass(char *key, tern_val val, uint8_t valtype, void *data)
1008 {
1009 command_def *def = val.ptrval;
1010 if (def->visited) {
1011 return;
1012 }
1013 def->visited = 1;
1014 help_state *state = data;
1015 size_t len = strlen(def->usage);
1016 printf(" %s", def->usage);
1017 while (len < state->longest_command) {
1018 putchar(' ');
1019 len++;
1020 }
1021 int remaining = 80 - state->longest_command - 5;
1022 const char *extra_desc = NULL;
1023 if (strlen(def->desc) <= remaining) {
1024 printf(" - %s\n", def->desc);
1025 } else {
1026 char split[76];
1027 int split_point = remaining;
1028 while (split_point > 0 && !isspace(def->desc[split_point]))
1029 {
1030 --split_point;
1031 }
1032 if (!split_point) {
1033 split_point = remaining;
1034 }
1035 memcpy(split, def->desc, split_point);
1036 extra_desc = def->desc + split_point + 1;
1037 split[split_point] = 0;
1038 printf(" - %s\n", split);
1039 }
1040 if (def->names[1]) {
1041 fputs(" Aliases: ", stdout);
1042 len = strlen(" Aliases: ");
1043 const char **name = def->names + 1;
1044 uint8_t first = 1;
1045 while (*name)
1046 {
1047 if (first) {
1048 first = 0;
1049 } else {
1050 putchar(',');
1051 putchar(' ');
1052 len += 2;
1053 }
1054 fputs(*name, stdout);
1055 len += strlen(*name);
1056 ++name;
1057 }
1058 } else {
1059 len = 0;
1060 }
1061 if (extra_desc) {
1062 while (len < state->longest_command + 5) {
1063 putchar(' ');
1064 len++;
1065 }
1066 fputs(extra_desc, stdout);
1067 }
1068 putchar('\n');
1069 }
1070
1071 static uint8_t cmd_help(debug_root *root, char *format, char *param)
1072 {
1073 help_state state = {0,0};
1074 tern_foreach(root->commands, help_first_pass, &state);
1075 tern_foreach(root->commands, help_reset_visited, &state);
1076 tern_foreach(root->commands, help_second_pass, &state);
1077 tern_foreach(root->commands, help_reset_visited, &state);
1078 return 1;
1079 }
1080
1081 static uint8_t cmd_continue(debug_root *root, char *format, int num_args, command_arg *args)
1082 {
1083 return 0;
1084 }
1085
1086 static uint8_t cmd_print(debug_root *root, char *format, int num_args, command_arg *args)
1087 {
1088 char format_str[8];
1089 strcpy(format_str, "%s: %d\n");
1090 if (format) {
1091 switch (format[0])
1092 {
1093 case 'x':
1094 case 'X':
1095 case 'd':
1096 case 'c':
1097 case 's':
1098 format_str[5] = format[0];
1099 break;
1100 default:
1101 fprintf(stderr, "Unrecognized format character: %c\n", format[0]);
1102 }
1103 }
1104 for (int i = 0; i < num_args; i++)
1105 {
1106 if (format && format[0] == 's') {
875 char tmp[128]; 1107 char tmp[128];
876 int i; 1108 int j;
877 for (i = 0; i < sizeof(tmp)-1; i++, value++) 1109 uint32_t addr = args[i].value;
1110 for (j = 0; j < sizeof(tmp)-1; j++, addr++)
878 { 1111 {
879 uint32_t addr = value; 1112 uint32_t tmp_addr = addr;
880 root->read_mem(root, &addr, 'b'); 1113 root->read_mem(root, &tmp_addr, 'b');
881 char c = addr; 1114 char c = addr;
882 if (c < 0x20 || c > 0x7F) { 1115 if (c < 0x20 || c > 0x7F) {
883 break; 1116 break;
884 } 1117 }
885 tmp[i] = c; 1118 tmp[j] = c;
886 } 1119 }
887 tmp[i] = 0; 1120 tmp[j] = 0;
888 printf(format, tmp_param, tmp); 1121 printf(format_str, args[i].raw, tmp);
889 } else { 1122 } else {
890 printf(format, tmp_param, value); 1123 printf(format_str, args[i].raw, args[i].value);
891 } 1124 }
892 free(tmp_param); 1125 }
893 while (*param && isblank(*param) && *param != '\n') 1126 return 1;
1127 }
1128
1129 static uint8_t cmd_display(debug_root *root, char *format, int num_args, command_arg *args)
1130 {
1131 cmd_print(root, format, num_args, args);
1132 disp_def *ndisp = calloc(1, sizeof(*ndisp));
1133 ndisp->next = root->displays;
1134 ndisp->index = root->disp_index++;
1135 ndisp->format = format ? strdup(format) : NULL;
1136 ndisp->num_args = num_args;
1137 ndisp->args = calloc(num_args, sizeof(command_arg));
1138 memcpy(ndisp->args, args, num_args * sizeof(command_arg));
1139 memset(args, 0, num_args * sizeof(command_arg));
1140 root->displays = ndisp;
1141 printf("Added display %d\n", ndisp->index);
1142 return 1;
1143 }
1144
1145 static uint8_t cmd_delete_display(debug_root *root, char *format, int num_args, command_arg *args)
1146 {
1147 disp_def **cur = &root->displays;
1148 while (*cur)
1149 {
1150 if ((*cur)->index == args[0].value) {
1151 disp_def *del_disp = *cur;
1152 *cur = del_disp->next;
1153 free(del_disp->format);
1154 for (int i = 0; i < del_disp->num_args; i++)
1155 {
1156 free(del_disp->args[i].raw);
1157 free_expr(del_disp->args[i].parsed);
1158 }
1159 free(del_disp->args);
1160 free(del_disp);
1161 break;
1162 } else {
1163 cur = &(*cur)->next;
1164 }
1165 }
1166 return 1;
1167 }
1168
1169 static uint8_t cmd_softreset(debug_root *root, char *format, int num_args, command_arg *args)
1170 {
1171 if (current_system->soft_reset) {
1172 current_system->soft_reset(current_system);
1173 return 0;
1174 } else {
1175 fputs("Current system does not support soft reset", stderr);
1176 return 1;
1177 }
1178 }
1179
1180 static uint8_t cmd_command(debug_root *root, char *format, int num_args, command_arg *args)
1181 {
1182 bp_def **target = find_breakpoint_idx(&root->breakpoints, args[0].value);
1183 if (!target) {
1184 fprintf(stderr, "Breakpoint %d does not exist!\n", args[0].value);
1185 return 1;
1186 }
1187 printf("Enter commands for breakpoing %d, type end when done\n", args[0].value);
1188 char cmd_buf[1024];
1189 char *commands = NULL;
1190 uint32_t cmd_storage = 4;
1191 for (uint32_t i = 0; i < (*target)->num_commands; i++)
1192 {
1193 free_parsed_command((*target)->commands + i);
1194 }
1195 free((*target)->commands);
1196 (*target)->commands = calloc(cmd_storage, sizeof(parsed_command));
1197 for (;;)
1198 {
1199 fputs(">>", stdout);
1200 fflush(stdout);
1201 fgets(cmd_buf, sizeof(cmd_buf), stdin);
1202 if (!strcmp(cmd_buf, "end\n")) {
1203 return 1;
1204 } else {
1205 if ((*target)->num_commands == cmd_storage) {
1206 cmd_storage *= 2;
1207 (*target)->commands = realloc((*target)->commands, cmd_storage * sizeof(parsed_command));
1208 }
1209 if (parse_command(root, cmd_buf, (*target)->commands + (*target)->num_commands)) {
1210 ++(*target)->num_commands;
1211 }
1212 }
1213 }
1214 }
1215
1216 const char *expr_type_names[] = {
1217 "EXPR_NONE",
1218 "EXPR_SCALAR",
1219 "EXPR_UNARY",
1220 "EXPR_BINARY",
1221 "EXPR_SIZE",
1222 "EXPR_MEM"
1223 };
1224
1225 static uint8_t run_command(debug_root *root, parsed_command *cmd)
1226 {
1227 if (cmd->def->raw_impl) {
1228 return cmd->def->raw_impl(root, cmd->format, cmd->raw);
1229 } else {
1230 for (int i = 0; i < cmd->num_args; i++)
894 { 1231 {
895 ++param; 1232 if (!eval_expr(root, cmd->args[i].parsed, &cmd->args[i].value)) {
896 } 1233 fprintf(stderr, "Failed to eval %s\n", cmd->args[i].raw);
897 } 1234 return 1;
898 if (!at_least_one) { 1235 }
899 fprintf(stderr, "Missing argument to print/%c\n", format_char); 1236 }
900 } 1237 return cmd->def->impl(root, cmd->format, cmd->num_args, cmd->args);
901 } 1238 }
902 1239 }
903 #ifndef NO_Z80 1240
904 1241 static uint8_t cmd_set(debug_root *root, char *format, int num_args, command_arg *args)
905 void zdebugger_print(z80_context * context, char format_char, char * param) 1242 {
906 { 1243 char *name = NULL;
907 uint32_t value; 1244 char size = 0;
908 char format[8]; 1245 uint32_t address;
909 strcpy(format, "%s: %d\n"); 1246 switch (args[0].parsed->type)
910 genesis_context *system = context->system; 1247 {
911 switch (format_char) 1248 case EXPR_SCALAR:
912 { 1249 if (args[0].parsed->op.type == TOKEN_NAME) {
913 case 'x': 1250 name = args[0].parsed->op.v.str;
914 case 'X': 1251 } else {
915 case 'd': 1252 fputs("First argument to set must be a name or memory expression, not a number", stderr);
916 case 'c': 1253 return 1;
917 format[5] = format_char; 1254 }
918 break; 1255 break;
919 case '\0': 1256 case EXPR_SIZE:
1257 size = args[0].parsed->op.v.op[0];
1258 if (args[0].parsed->left->op.type == TOKEN_NAME) {
1259 name = args[0].parsed->left->op.v.str;
1260 } else {
1261 fputs("First argument to set must be a name or memory expression, not a number", stderr);
1262 return 1;
1263 }
1264 break;
1265 case EXPR_MEM:
1266 size = args[0].parsed->op.v.op[0];
1267 if (!eval_expr(root, args[0].parsed->left, &address)) {
1268 fprintf(stderr, "Failed to eval %s\n", args[0].raw);
1269 return 1;
1270 }
920 break; 1271 break;
921 default: 1272 default:
922 fprintf(stderr, "Unrecognized format character: %c\n", format_char); 1273 fprintf(stderr, "First argument to set must be a name or memory expression, got %s\n", expr_type_names[args[0].parsed->type]);
923 } 1274 return 1;
924 switch (param[0]) 1275 }
925 { 1276 if (!eval_expr(root, args[1].parsed, &args[1].value)) {
1277 fprintf(stderr, "Failed to eval %s\n", args[1].raw);
1278 return 1;
1279 }
1280 uint32_t value = args[1].value;
1281 if (name && size && size != 'l') {
1282 uint32_t old;
1283 if (!root->resolve(root, name, &old)) {
1284 fprintf(stderr, "Failed to eval %s\n", name);
1285 return 1;
1286 }
1287 if (size == 'b') {
1288 old &= 0xFFFFFF00;
1289 value &= 0xFF;
1290 value |= old;
1291 } else {
1292 old &= 0xFFFF0000;
1293 value &= 0xFFFF;
1294 value |= old;
1295 }
1296 }
1297 if (name) {
1298 if (!root->set(root, name, value)) {
1299 fprintf(stderr, "Failed to set %s\n", name);
1300 }
1301 } else if (!root->write_mem(root, address, value, size)) {
1302 fprintf(stderr, "Failed to write to address %X\n", address);
1303 }
1304 return 1;
1305 }
1306
1307 static uint8_t cmd_delete_m68k(debug_root *root, char *format, int num_args, command_arg *args)
1308 {
1309 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, args[0].value);
1310 if (!*this_bp) {
1311 fprintf(stderr, "Breakpoint %d does not exist\n", args[0].value);
1312 return 1;
1313 }
1314 bp_def *tmp = *this_bp;
1315 remove_breakpoint(root->cpu_context, tmp->address);
1316 *this_bp = (*this_bp)->next;
1317 if (tmp->commands) {
1318 for (uint32_t i = 0; i < tmp->num_commands; i++)
1319 {
1320 free_parsed_command(tmp->commands + i);
1321 }
1322 free(tmp->commands);
1323 }
1324 free(tmp);
1325 return 1;
1326 }
1327
1328 static uint8_t cmd_breakpoint_m68k(debug_root *root, char *format, int num_args, command_arg *args)
1329 {
1330 insert_breakpoint(root->cpu_context, args[0].value, debugger);
1331 bp_def *new_bp = calloc(1, sizeof(bp_def));
1332 new_bp->next = root->breakpoints;
1333 new_bp->address = args[0].value;
1334 new_bp->index = root->bp_index++;
1335 root->breakpoints = new_bp;
1336 printf("68K Breakpoint %d set at %X\n", new_bp->index, args[0].value);
1337 return 1;
1338 }
1339
1340 static uint8_t cmd_advance_m68k(debug_root *root, char *format, int num_args, command_arg *args)
1341 {
1342 insert_breakpoint(root->cpu_context, args[0].value, debugger);
1343 return 0;
1344 }
1345
1346 static uint8_t cmd_step_m68k(debug_root *root, char *format, int num_args, command_arg *args)
1347 {
1348 m68kinst *inst = root->inst;
1349 m68k_context *context = root->cpu_context;
1350 uint32_t after = root->after;
1351 if (inst->op == M68K_RTS) {
1352 after = m68k_read_long(context->aregs[7], context);
1353 } else if (inst->op == M68K_RTE || inst->op == M68K_RTR) {
1354 after = m68k_read_long(context->aregs[7] + 2, context);
1355 } else if(m68k_is_branch(inst)) {
1356 if (inst->op == M68K_BCC && inst->extra.cond != COND_TRUE) {
1357 root->branch_f = after;
1358 root->branch_t = m68k_branch_target(inst, context->dregs, context->aregs) & 0xFFFFFF;
1359 insert_breakpoint(context, root->branch_t, debugger);
1360 } else if(inst->op == M68K_DBCC) {
1361 if (inst->extra.cond == COND_FALSE) {
1362 if (context->dregs[inst->dst.params.regs.pri] & 0xFFFF) {
1363 after = m68k_branch_target(inst, context->dregs, context->aregs);
1364 }
1365 } else {
1366 root->branch_t = after;
1367 root->branch_f = m68k_branch_target(inst, context->dregs, context->aregs);
1368 insert_breakpoint(context, root->branch_f, debugger);
1369 }
1370 } else {
1371 after = m68k_branch_target(inst, context->dregs, context->aregs) & 0xFFFFFF;
1372 }
1373 }
1374 insert_breakpoint(root->cpu_context, after, debugger);
1375 return 0;
1376 }
1377
1378 static uint8_t cmd_over_m68k(debug_root *root, char *format, int num_args, command_arg *args)
1379 {
1380 m68kinst *inst = root->inst;
1381 m68k_context *context = root->cpu_context;
1382 uint32_t after = root->after;
1383 if (inst->op == M68K_RTS) {
1384 after = m68k_read_long(context->aregs[7], context);
1385 } else if (inst->op == M68K_RTE || inst->op == M68K_RTR) {
1386 after = m68k_read_long(context->aregs[7] + 2, context);
1387 } else if(m68k_is_noncall_branch(inst)) {
1388 if (inst->op == M68K_BCC && inst->extra.cond != COND_TRUE) {
1389 root->branch_t = m68k_branch_target(inst, context->dregs, context->aregs) & 0xFFFFFF;
1390 if (root->branch_t < after) {
1391 root->branch_t = 0;
1392 } else {
1393 root->branch_f = after;
1394 insert_breakpoint(context, root->branch_t, debugger);
1395 }
1396 } else if(inst->op == M68K_DBCC) {
1397 uint32_t target = m68k_branch_target(inst, context->dregs, context->aregs) & 0xFFFFFF;
1398 if (target > after) {
1399 if (inst->extra.cond == COND_FALSE) {
1400 after = target;
1401 } else {
1402 root->branch_f = target;
1403 root->branch_t = after;
1404 insert_breakpoint(context, root->branch_f, debugger);
1405 }
1406 }
1407 } else {
1408 after = m68k_branch_target(inst, context->dregs, context->aregs) & 0xFFFFFF;
1409 }
1410 }
1411 insert_breakpoint(root->cpu_context, after, debugger);
1412 return 0;
1413 }
1414
1415 static uint8_t cmd_next_m68k(debug_root *root, char *format, int num_args, command_arg *args)
1416 {
1417 m68kinst *inst = root->inst;
1418 m68k_context *context = root->cpu_context;
1419 uint32_t after = root->after;
1420 if (inst->op == M68K_RTS) {
1421 after = m68k_read_long(context->aregs[7], context);
1422 } else if (inst->op == M68K_RTE || inst->op == M68K_RTR) {
1423 after = m68k_read_long(context->aregs[7] + 2, context);
1424 } else if(m68k_is_noncall_branch(inst)) {
1425 if (inst->op == M68K_BCC && inst->extra.cond != COND_TRUE) {
1426 root->branch_f = after;
1427 root->branch_t = m68k_branch_target(inst, context->dregs, context->aregs);
1428 insert_breakpoint(context, root->branch_t, debugger);
1429 } else if(inst->op == M68K_DBCC) {
1430 if ( inst->extra.cond == COND_FALSE) {
1431 if (context->dregs[inst->dst.params.regs.pri] & 0xFFFF) {
1432 after = m68k_branch_target(inst, context->dregs, context->aregs);
1433 }
1434 } else {
1435 root->branch_t = after;
1436 root->branch_f = m68k_branch_target(inst, context->dregs, context->aregs);
1437 insert_breakpoint(context, root->branch_f, debugger);
1438 }
1439 } else {
1440 after = m68k_branch_target(inst, context->dregs, context->aregs) & 0xFFFFFF;
1441 }
1442 }
1443 insert_breakpoint(root->cpu_context, after, debugger);
1444 return 0;
1445 }
1446
1447 static uint8_t cmd_backtrace_m68k(debug_root *root, char *format, int num_args, command_arg *args)
1448 {
1449 m68k_context *context = root->cpu_context;
1450 uint32_t stack = context->aregs[7];
1451 uint8_t non_adr_count = 0;
1452 do {
1453 uint32_t bt_address = m68k_instruction_fetch(stack, context);
1454 bt_address = get_instruction_start(context->options, bt_address - 2);
1455 if (bt_address) {
1456 stack += 4;
1457 non_adr_count = 0;
1458 m68kinst inst;
1459 char buf[128];
1460 m68k_decode(m68k_instruction_fetch, context, &inst, bt_address);
1461 m68k_disasm(&inst, buf);
1462 printf("%X: %s\n", bt_address, buf);
1463 } else {
1464 //non-return address value on stack can be word wide
1465 stack += 2;
1466 non_adr_count++;
1467 }
1468 //TODO: Make sure we don't wander into an invalid memory region
1469 } while (stack && non_adr_count < 6);
1470 return 1;
1471 }
1472
1473 static uint8_t cmd_vdp_sprites(debug_root *root, char *format, int num_args, command_arg *args)
1474 {
1475 m68k_context *context = root->cpu_context;
1476 genesis_context * gen = context->system;
1477 vdp_print_sprite_table(gen->vdp);
1478 return 1;
1479 }
1480
1481 static uint8_t cmd_vdp_regs(debug_root *root, char *format, int num_args, command_arg *args)
1482 {
1483 m68k_context *context = root->cpu_context;
1484 genesis_context * gen = context->system;
1485 vdp_print_reg_explain(gen->vdp);
1486 return 1;
1487 }
1488
1489 static uint8_t cmd_ym_channel(debug_root *root, char *format, int num_args, command_arg *args)
1490 {
1491 m68k_context *context = root->cpu_context;
1492 genesis_context * gen = context->system;
1493 if (num_args) {
1494 ym_print_channel_info(gen->ym, args[0].value - 1);
1495 } else {
1496 for (int i = 0; i < 6; i++) {
1497 ym_print_channel_info(gen->ym, i);
1498 }
1499 }
1500 return 1;
1501 }
1502
1503 static uint8_t cmd_ym_timer(debug_root *root, char *format, int num_args, command_arg *args)
1504 {
1505 m68k_context *context = root->cpu_context;
1506 genesis_context * gen = context->system;
1507 ym_print_timer_info(gen->ym);
1508 return 1;
1509 }
1510
1511 static uint8_t cmd_sub(debug_root *root, char *format, char *param)
1512 {
1513 while (param && *param && isblank(*param))
1514 {
1515 ++param;
1516 }
1517 m68k_context *m68k = root->cpu_context;
1518 genesis_context *gen = m68k->system;
1519 segacd_context *cd = gen->expansion;
1520 if (param && *param && !isspace(*param)) {
1521 parsed_command cmd;
1522 debug_root *sub_root = find_m68k_root(cd->m68k);
1523 if (!sub_root) {
1524 fputs("Failed to get debug root for Sub CPU\n", stderr);
1525 return 1;
1526 }
1527 if (!parse_command(sub_root, param, &cmd)) {
1528 return 1;
1529 }
1530 uint8_t ret = run_command(sub_root, &cmd);
1531 free_parsed_command(&cmd);
1532 return ret;
1533 } else {
1534 cd->enter_debugger = 1;
1535 return 0;
1536 }
1537 }
1538
1539 static uint8_t cmd_main(debug_root *root, char *format, char *param)
1540 {
1541 while (param && *param && isblank(*param))
1542 {
1543 ++param;
1544 }
1545 m68k_context *m68k = root->cpu_context;
1546 segacd_context *cd = m68k->system;
1547
1548 if (param && *param && !isspace(*param)) {
1549 parsed_command cmd;
1550 debug_root *main_root = find_m68k_root(cd->genesis->m68k);
1551 if (!main_root) {
1552 fputs("Failed to get debug root for Main CPU\n", stderr);
1553 return 1;
1554 }
1555 if (!parse_command(main_root, param, &cmd)) {
1556 return 1;
1557 }
1558 uint8_t ret = run_command(main_root, &cmd);
1559 free_parsed_command(&cmd);
1560 return ret;
1561 } else {
1562 cd->genesis->header.enter_debugger = 1;
1563 return 0;
1564 }
1565 }
1566
1567 static uint8_t cmd_gen_z80(debug_root *root, char *format, char *param)
1568 {
1569 while (param && *param && isblank(*param))
1570 {
1571 ++param;
1572 }
1573 m68k_context *m68k = root->cpu_context;
1574 genesis_context *gen = m68k->system;
1575
1576 if (param && *param && !isspace(*param)) {
1577 parsed_command cmd;
1578 debug_root *z80_root = find_z80_root(gen->z80);
1579 if (!z80_root) {
1580 fputs("Failed to get debug root for Z80\n", stderr);
1581 return 1;
1582 }
1583 if (!parse_command(z80_root, param, &cmd)) {
1584 return 1;
1585 }
1586 uint8_t ret = run_command(z80_root, &cmd);
1587 free_parsed_command(&cmd);
1588 return ret;
1589 } else {
1590 fputs("not implemented yet", stderr);
1591 return 0;
1592 }
1593 }
1594
1595 command_def common_commands[] = {
1596 {
1597 .names = (const char *[]){
1598 "quit", NULL
1599 },
1600 .usage = "quit",
1601 .desc = "Quit BlastEm",
1602 .impl = cmd_quit,
1603 .min_args = 0,
1604 .max_args = 0,
1605 },
1606 {
1607 .names = (const char *[]){
1608 "help", "?", NULL
1609 },
1610 .usage = "help",
1611 .desc = "Print a list of available commands for the current debug context",
1612 .raw_impl = cmd_help,
1613 .min_args = 0,
1614 .max_args = 1
1615 },
1616 {
1617 .names = (const char *[]){
1618 "continue", "c", NULL
1619 },
1620 .usage = "continue",
1621 .desc = "Resume execution",
1622 .impl = cmd_continue,
1623 .min_args = 0,
1624 .max_args = 0
1625 },
1626 {
1627 .names = (const char *[]){
1628 "print", NULL
1629 },
1630 .usage = "print[/FORMAT] EXPRESSION...",
1631 .desc = "Print one or more expressions using the optional format character",
1632 .impl = cmd_print,
1633 .min_args = 1,
1634 .max_args = -1
1635 },
1636 {
1637 .names = (const char *[]){
1638 "softreset", "sr", NULL
1639 },
1640 .usage = "softreset",
1641 .desc = "Perform a soft-reset for the current system",
1642 .impl = cmd_softreset,
1643 .min_args = 0,
1644 .max_args = 0,
1645 },
1646 {
1647 .names = (const char *[]){
1648 "display", NULL
1649 },
1650 .usage = "display[/FORMAT] EXPRESSION...",
1651 .desc = "Print one or more expressions every time the debugger is entered",
1652 .impl = cmd_display,
1653 .min_args = 1,
1654 .max_args = -1
1655 },
1656 {
1657 .names = (const char *[]){
1658 "deletedisplay", "dd", NULL
1659 },
1660 .usage = "deletedisplay DISPLAYNUM",
1661 .desc = "Remove expressions added with the `display` command",
1662 .impl = cmd_delete_display,
1663 .min_args = 1,
1664 .max_args = 1
1665 },
1666 {
1667 .names = (const char *[]){
1668 "commands", NULL
1669 },
1670 .usage = "command BREAKPOINT",
1671 .desc = "Set a list of debugger commands to be executed when the given breakpoint is hit",
1672 .impl = cmd_command,
1673 .min_args = 1,
1674 .max_args = 1
1675 },
1676 {
1677 .names = (const char *[]){
1678 "set", NULL
1679 },
1680 .usage = "set MEM|NAME VALUE",
1681 .desc = "Set a register, symbol or memory location to the result of evaluating VALUE",
1682 .impl = cmd_set,
1683 .min_args = 2,
1684 .max_args = 2,
1685 .skip_eval = 1
1686 }
1687 };
1688 #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands))
1689
1690 command_def m68k_commands[] = {
1691 {
1692 .names = (const char *[]){
1693 "breakpoint", "b", NULL
1694 },
1695 .usage = "breakpoint ADDRESSS",
1696 .desc = "Set a breakpoint at ADDRESS",
1697 .impl = cmd_breakpoint_m68k,
1698 .min_args = 1,
1699 .max_args = 1
1700 },
1701 {
1702 .names = (const char *[]){
1703 "advance", NULL
1704 },
1705 .usage = "advance ADDRESS",
1706 .desc = "Advance to ADDRESS",
1707 .impl = cmd_advance_m68k,
1708 .min_args = 1,
1709 .max_args = 1
1710 },
1711 {
1712 .names = (const char *[]){
1713 "step", "s", NULL
1714 },
1715 .usage = "step",
1716 .desc = "Advance to the next instruction, stepping into subroutines",
1717 .impl = cmd_step_m68k,
1718 .min_args = 0,
1719 .max_args = 0
1720 },
1721 {
1722 .names = (const char *[]){
1723 "over", NULL
1724 },
1725 .usage = "over",
1726 .desc = "Advance to the next instruction, ignoring branches to lower addresses",
1727 .impl = cmd_over_m68k,
1728 .min_args = 0,
1729 .max_args = 0
1730 },
1731 {
1732 .names = (const char *[]){
1733 "next", NULL
1734 },
1735 .usage = "next",
1736 .desc = "Advance to the next instruction",
1737 .impl = cmd_next_m68k,
1738 .min_args = 0,
1739 .max_args = 0
1740 },
1741 {
1742 .names = (const char *[]){
1743 "backtrace", "bt", NULL
1744 },
1745 .usage = "backtrace",
1746 .desc = "Print a backtrace",
1747 .impl = cmd_backtrace_m68k,
1748 .min_args = 0,
1749 .max_args = 0
1750 },
1751 {
1752 .names = (const char *[]){
1753 "delete", "d", NULL
1754 },
1755 .usage = "delete BREAKPOINT",
1756 .desc = "Remove breakpoint identified by BREAKPOINT",
1757 .impl = cmd_delete_m68k,
1758 .min_args = 1,
1759 .max_args = 1
1760 }
1761 };
1762
1763 #define NUM_68K (sizeof(m68k_commands)/sizeof(*m68k_commands))
1764
1765 command_def genesis_commands[] = {
1766 {
1767 .names = (const char *[]){
1768 "vdpsprites", "vs", NULL
1769 },
1770 .usage = "vdpsprites",
1771 .desc = "Print the VDP sprite table",
1772 .impl = cmd_vdp_sprites,
1773 .min_args = 0,
1774 .max_args = 0
1775 },
1776 {
1777 .names = (const char *[]){
1778 "vdpsregs", "vr", NULL
1779 },
1780 .usage = "vdpregs",
1781 .desc = "Print VDP register values with a short description",
1782 .impl = cmd_vdp_regs,
1783 .min_args = 0,
1784 .max_args = 0
1785 },
1786 #ifndef NO_Z80
1787 {
1788 .names = (const char *[]){
1789 "z80", NULL
1790 },
1791 .usage = "z80 [COMMAND]",
1792 .desc = "Run a Z80 debugger command or switch to Z80 context when no command is given",
1793 .raw_impl = cmd_gen_z80,
1794 .min_args = 0,
1795 .max_args = -1
1796 },
1797 #endif
1798 {
1799 .names = (const char *[]){
1800 "ymchannel", "yc", NULL
1801 },
1802 .usage = "ymchannel [CHANNEL]",
1803 .desc = "Print YM-2612 channel and operator params. Limited to CHANNEL if specified",
1804 .impl = cmd_ym_channel,
1805 .min_args = 0,
1806 .max_args = 1
1807 },
1808 {
1809 .names = (const char *[]){
1810 "ymtimer", "yt", NULL
1811 },
1812 .usage = "ymtimer",
1813 .desc = "Print YM-2612 timer info",
1814 .impl = cmd_ym_timer,
1815 .min_args = 0,
1816 .max_args = 0
1817 }
1818 };
1819
1820 #define NUM_GENESIS (sizeof(genesis_commands)/sizeof(*genesis_commands))
1821
1822 command_def scd_main_commands[] = {
1823 {
1824 .names = (const char *[]){
1825 "subcpu", NULL
1826 },
1827 .usage = "subcpu [COMMAND]",
1828 .desc = "Run a Sub-CPU debugger command or switch to Sub-CPU context when no command is given",
1829 .raw_impl = cmd_sub,
1830 .min_args = 0,
1831 .max_args = -1
1832 }
1833 };
1834
1835 #define NUM_SCD_MAIN (sizeof(scd_main_commands)/sizeof(*scd_main_commands))
1836
1837 command_def scd_sub_commands[] = {
1838 {
1839 .names = (const char *[]){
1840 "maincpu", NULL
1841 },
1842 .usage = "maincpu [COMMAND]",
1843 .desc = "Run a Main-CPU debugger command or switch to Main-CPU context when no command is given",
1844 .raw_impl = cmd_main,
1845 .min_args = 0,
1846 .max_args = -1
1847 }
1848 };
1849
1850 #define NUM_SCD_SUB (sizeof(scd_main_commands)/sizeof(*scd_main_commands))
1851
1852 #ifndef NO_Z80
1853
1854 static uint8_t cmd_delete_z80(debug_root *root, char *format, int num_args, command_arg *args)
1855 {
1856 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, args[0].value);
1857 if (!*this_bp) {
1858 fprintf(stderr, "Breakpoint %d does not exist\n", args[0].value);
1859 return 1;
1860 }
1861 bp_def *tmp = *this_bp;
1862 zremove_breakpoint(root->cpu_context, tmp->address);
1863 *this_bp = (*this_bp)->next;
1864 if (tmp->commands) {
1865 for (uint32_t i = 0; i < tmp->num_commands; i++)
1866 {
1867 free_parsed_command(tmp->commands + i);
1868 }
1869 free(tmp->commands);
1870 }
1871 free(tmp);
1872 return 1;
1873 }
1874
1875 static uint8_t cmd_breakpoint_z80(debug_root *root, char *format, int num_args, command_arg *args)
1876 {
1877 zinsert_breakpoint(root->cpu_context, args[0].value, (uint8_t *)zdebugger);
1878 bp_def *new_bp = calloc(1, sizeof(bp_def));
1879 new_bp->next = root->breakpoints;
1880 new_bp->address = args[0].value;
1881 new_bp->index = root->bp_index++;
1882 root->breakpoints = new_bp;
1883 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, args[0].value);
1884 return 1;
1885 }
1886
1887 static uint8_t cmd_advance_z80(debug_root *root, char *format, int num_args, command_arg *args)
1888 {
1889 zinsert_breakpoint(root->cpu_context, args[0].value, (uint8_t *)zdebugger);
1890 return 0;
1891 }
1892
1893 static uint8_t cmd_step_z80(debug_root *root, char *format, int num_args, command_arg *args)
1894 {
1895 z80inst *inst = root->inst;
1896 z80_context *context = root->cpu_context;
1897 uint32_t after = root->after;
1898 //TODO: handle conditional branches
1899 if (inst->op == Z80_JP || inst->op == Z80_CALL || inst->op == Z80_RST) {
1900 if (inst->addr_mode == Z80_IMMED) {
1901 after = inst->immed;
1902 } else if (inst->ea_reg == Z80_HL) {
926 #ifndef NEW_CORE 1903 #ifndef NEW_CORE
1904 after = context->regs[Z80_H] << 8 | context->regs[Z80_L];
1905 } else if (inst->ea_reg == Z80_IX) {
1906 after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL];
1907 } else if (inst->ea_reg == Z80_IY) {
1908 after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL];
1909 #endif
1910 }
1911 } else if(inst->op == Z80_JR) {
1912 after += inst->immed;
1913 } else if(inst->op == Z80_RET) {
1914 uint8_t *sp = get_native_pointer(context->sp, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
1915 if (sp) {
1916 after = *sp;
1917 sp = get_native_pointer((context->sp + 1) & 0xFFFF, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
1918 if (sp) {
1919 after |= *sp << 8;
1920 }
1921 }
1922 }
1923 zinsert_breakpoint(context, after, (uint8_t *)zdebugger);
1924 return 0;
1925 }
1926
1927 static uint8_t cmd_over_z80(debug_root *root, char *format, int num_args, command_arg *args)
1928 {
1929 fputs("not implemented yet\n", stderr);
1930 return 1;
1931 }
1932
1933 static uint8_t cmd_next_z80(debug_root *root, char *format, int num_args, command_arg *args)
1934 {
1935 z80inst *inst = root->inst;
1936 z80_context *context = root->cpu_context;
1937 uint32_t after = root->after;
1938 //TODO: handle conditional branches
1939 if (inst->op == Z80_JP) {
1940 if (inst->addr_mode == Z80_IMMED) {
1941 after = inst->immed;
1942 } else if (inst->ea_reg == Z80_HL) {
1943 #ifndef NEW_CORE
1944 after = context->regs[Z80_H] << 8 | context->regs[Z80_L];
1945 } else if (inst->ea_reg == Z80_IX) {
1946 after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL];
1947 } else if (inst->ea_reg == Z80_IY) {
1948 after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL];
1949 #endif
1950 }
1951 } else if(inst->op == Z80_JR) {
1952 after += inst->immed;
1953 } else if(inst->op == Z80_RET) {
1954 uint8_t *sp = get_native_pointer(context->sp, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
1955 if (sp) {
1956 after = *sp;
1957 sp = get_native_pointer((context->sp + 1) & 0xFFFF, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
1958 if (sp) {
1959 after |= *sp << 8;
1960 }
1961 }
1962 }
1963 zinsert_breakpoint(context, after, (uint8_t *)zdebugger);
1964 return 0;
1965 }
1966
1967 static uint8_t cmd_backtrace_z80(debug_root *root, char *format, int num_args, command_arg *args)
1968 {
1969 z80_context *context = root->cpu_context;
1970 uint32_t stack = context->sp;
1971 uint8_t non_adr_count = 0;
1972 do {
1973 uint32_t bt_address = stack;
1974 if (!root->read_mem(root, &bt_address, 'w')) {
1975 break;
1976 }
1977 bt_address = z80_get_instruction_start(context, bt_address - 1);
1978 if (bt_address != 0xFEEDFEED) {
1979 stack += 4;
1980 non_adr_count = 0;
1981 z80inst inst;
1982 char buf[128];
1983 uint8_t *pc = get_native_pointer(bt_address, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
1984 z80_decode(pc, &inst);
1985 z80_disasm(&inst, buf, bt_address);
1986 printf("%X: %s\n", bt_address, buf);
1987 } else {
1988 //non-return address value on stack can be byte wide
1989 stack++;
1990 non_adr_count++;
1991 }
1992 //TODO: Make sure we don't wander into an invalid memory region
1993 } while (stack && non_adr_count < 6);
1994 return 1;
1995 }
1996
1997 command_def z80_commands[] = {
1998 {
1999 .names = (const char *[]){
2000 "breakpoint", "b", NULL
2001 },
2002 .usage = "breakpoint ADDRESSS",
2003 .desc = "Set a breakpoint at ADDRESS",
2004 .impl = cmd_breakpoint_z80,
2005 .min_args = 1,
2006 .max_args = 1
2007 },
2008 {
2009 .names = (const char *[]){
2010 "advance", NULL
2011 },
2012 .usage = "advance ADDRESS",
2013 .desc = "Advance to ADDRESS",
2014 .impl = cmd_advance_z80,
2015 .min_args = 1,
2016 .max_args = 1
2017 },
2018 {
2019 .names = (const char *[]){
2020 "step", "s", NULL
2021 },
2022 .usage = "step",
2023 .desc = "Advance to the next instruction, stepping into subroutines",
2024 .impl = cmd_step_z80,
2025 .min_args = 0,
2026 .max_args = 0
2027 },
2028 {
2029 .names = (const char *[]){
2030 "over", NULL
2031 },
2032 .usage = "over",
2033 .desc = "Advance to the next instruction, ignoring branches to lower addresses",
2034 .impl = cmd_over_z80,
2035 .min_args = 0,
2036 .max_args = 0
2037 },
2038 {
2039 .names = (const char *[]){
2040 "next", NULL
2041 },
2042 .usage = "next",
2043 .desc = "Advance to the next instruction",
2044 .impl = cmd_next_z80,
2045 .min_args = 0,
2046 .max_args = 0
2047 },
2048 {
2049 .names = (const char *[]){
2050 "backtrace", "bt", NULL
2051 },
2052 .usage = "backtrace",
2053 .desc = "Print a backtrace",
2054 .impl = cmd_backtrace_z80,
2055 .min_args = 0,
2056 .max_args = 0
2057 },
2058 {
2059 .names = (const char *[]){
2060 "delete", "d", NULL
2061 },
2062 .usage = "delete BREAKPOINT",
2063 .desc = "Remove breakpoint identified by BREAKPOINT",
2064 .impl = cmd_delete_z80,
2065 .min_args = 1,
2066 .max_args = 1
2067 }
2068 };
2069
2070 #define NUM_Z80 (sizeof(z80_commands)/sizeof(*z80_commands))
2071
2072 #endif
2073
2074 void add_commands(debug_root *root, command_def *defs, uint32_t num_commands)
2075 {
2076 for (uint32_t i = 0; i < num_commands; i++)
2077 {
2078 for (int j = 0; defs[i].names[j]; j++)
2079 {
2080 root->commands = tern_insert_ptr(root->commands, defs[i].names[j], defs + i);
2081 }
2082 }
2083 }
2084
2085 debug_root *find_m68k_root(m68k_context *context)
2086 {
2087 debug_root *root = find_root(context);
2088 if (root && !root->commands) {
2089 add_commands(root, common_commands, NUM_COMMON);
2090 add_commands(root, m68k_commands, NUM_68K);
2091 root->read_mem = read_m68k;
2092 root->write_mem = write_m68k;
2093 root->set = set_m68k;
2094 switch (current_system->type)
2095 {
2096 case SYSTEM_GENESIS:
2097 case SYSTEM_SEGACD:
2098 //check if this is the main CPU
2099 if (context->system == current_system) {
2100 root->resolve = resolve_genesis;
2101 add_commands(root, genesis_commands, NUM_GENESIS);
2102 if (current_system->type == SYSTEM_SEGACD) {
2103 add_commands(root, scd_main_commands, NUM_SCD_MAIN);
2104 }
2105 break;
2106 } else {
2107 add_commands(root, scd_sub_commands, NUM_SCD_SUB);
2108 }
2109 default:
2110 root->resolve = resolve_m68k;
2111 }
2112 }
2113 return root;
2114 }
2115
2116 #ifndef NO_Z80
2117
2118 static uint8_t read_z80(debug_root *root, uint32_t *out, char size)
2119 {
2120 z80_context *context = root->cpu_context;
2121 uint32_t address = *out;
2122 *out = read_byte(address, (void **)context->mem_pointers, &context->options->gen, context);
2123 if (size == 'w') {
2124 *out |= read_byte(address + 1, (void **)context->mem_pointers, &context->options->gen, context) << 8;
2125 }
2126 return 1;
2127 }
2128
2129 static uint8_t write_z80(debug_root *root, uint32_t address, uint32_t value, char size)
2130 {
2131 z80_context *context = root->cpu_context;
2132 write_byte(address, value, (void **)context->mem_pointers, &context->options->gen, context);
2133 if (size == 'w') {
2134 write_byte(address + 1, value >> 8, (void **)context->mem_pointers, &context->options->gen, context);
2135 }
2136 return 1;
2137 }
2138
2139 static uint8_t resolve_z80(debug_root *root, const char *name, uint32_t *out)
2140 {
2141 z80_context *context = root->cpu_context;
2142 switch (tolower(name[0]))
2143 {
927 case 'a': 2144 case 'a':
928 if (param[1] == 'f') { 2145 if (!name[1]) {
929 if(param[2] == '\'') { 2146 *out = context->regs[Z80_A];
930 value = context->alt_regs[Z80_A] << 8; 2147 } else if (name[1] == '\'' && !name[2]) {
931 value |= context->alt_flags[ZF_S] << 7; 2148 *out = context->alt_regs[Z80_A];
932 value |= context->alt_flags[ZF_Z] << 6; 2149 } else if (tolower(name[1]) == 'f') {
933 value |= context->alt_flags[ZF_H] << 4; 2150 if (!name[2]) {
934 value |= context->alt_flags[ZF_PV] << 2; 2151 *out = context->regs[Z80_A] << 8;
935 value |= context->alt_flags[ZF_N] << 1; 2152 *out |= context->flags[ZF_S] << 7;
936 value |= context->alt_flags[ZF_C]; 2153 *out |= context->flags[ZF_Z] << 6;
2154 *out |= context->flags[ZF_H] << 4;
2155 *out |= context->flags[ZF_PV] << 2;
2156 *out |= context->flags[ZF_N] << 1;
2157 *out |= context->flags[ZF_C];
2158 } else if (name[2] == '\'' && !name[3]) {
2159 *out = context->alt_regs[Z80_A] << 8;
2160 *out |= context->alt_flags[ZF_S] << 7;
2161 *out |= context->alt_flags[ZF_Z] << 6;
2162 *out |= context->alt_flags[ZF_H] << 4;
2163 *out |= context->alt_flags[ZF_PV] << 2;
2164 *out |= context->alt_flags[ZF_N] << 1;
2165 *out |= context->alt_flags[ZF_C];
937 } else { 2166 } else {
938 value = context->regs[Z80_A] << 8; 2167 return 0;
939 value |= context->flags[ZF_S] << 7; 2168 }
940 value |= context->flags[ZF_Z] << 6;
941 value |= context->flags[ZF_H] << 4;
942 value |= context->flags[ZF_PV] << 2;
943 value |= context->flags[ZF_N] << 1;
944 value |= context->flags[ZF_C];
945 }
946 } else if(param[1] == '\'') {
947 value = context->alt_regs[Z80_A];
948 } else { 2169 } else {
949 value = context->regs[Z80_A]; 2170 return 0;
950 } 2171 }
951 break; 2172 break;
952 case 'b': 2173 case 'b':
953 if (param[1] == 'c') { 2174 if (!name[1]) {
954 if(param[2] == '\'') { 2175 *out = context->regs[Z80_B];
955 value = context->alt_regs[Z80_B] << 8; 2176 } else if (name[1] == '\'' && !name[2]) {
956 value |= context->alt_regs[Z80_C]; 2177 *out = context->alt_regs[Z80_B];
2178 } else if (tolower(name[1]) == 'c') {
2179 if (!name[2]) {
2180 *out = context->regs[Z80_B] << 8 | context->regs[Z80_C];
2181 } else if (name[2] == '\'' && !name[3]) {
2182 *out = context->alt_regs[Z80_B] << 8 | context->alt_regs[Z80_C];
957 } else { 2183 } else {
958 value = context->regs[Z80_B] << 8; 2184 return 0;
959 value |= context->regs[Z80_C]; 2185 }
960 }
961 } else if(param[1] == '\'') {
962 value = context->alt_regs[Z80_B];
963 } else if(param[1] == 'a') {
964 value = context->bank_reg << 15;
965 } else {
966 value = context->regs[Z80_B];
967 } 2186 }
968 break; 2187 break;
969 case 'c': 2188 case 'c':
970 if(param[1] == '\'') { 2189 if (!name[1]) {
971 value = context->alt_regs[Z80_C]; 2190 *out = context->regs[Z80_C];
972 } else if(param[1] == 'y') { 2191 } else if (name[1] == '\'' && !name[2]) {
973 value = context->current_cycle; 2192 *out = context->alt_regs[Z80_C];
974 } else { 2193 } else {
975 value = context->regs[Z80_C]; 2194 return 0;
976 } 2195 }
977 break; 2196 break;
978 case 'd': 2197 case 'd':
979 if (param[1] == 'e') { 2198 if (!name[1]) {
980 if(param[2] == '\'') { 2199 *out = context->regs[Z80_D];
981 value = context->alt_regs[Z80_D] << 8; 2200 } else if (name[1] == '\'' && !name[2]) {
982 value |= context->alt_regs[Z80_E]; 2201 *out = context->alt_regs[Z80_D];
2202 } else if (tolower(name[1]) == 'e') {
2203 if (!name[2]) {
2204 *out = context->regs[Z80_D] << 8 | context->regs[Z80_E];
2205 } else if (name[2] == '\'' && !name[3]) {
2206 *out = context->alt_regs[Z80_D] << 8 | context->alt_regs[Z80_E];
983 } else { 2207 } else {
984 value = context->regs[Z80_D] << 8; 2208 return 0;
985 value |= context->regs[Z80_E]; 2209 }
986 }
987 } else if(param[1] == '\'') {
988 value = context->alt_regs[Z80_D];
989 } else {
990 value = context->regs[Z80_D];
991 } 2210 }
992 break; 2211 break;
993 case 'e': 2212 case 'e':
994 if(param[1] == '\'') { 2213 if (!name[1]) {
995 value = context->alt_regs[Z80_E]; 2214 *out = context->regs[Z80_E];
2215 } else if (name[1] == '\'' && !name[2]) {
2216 *out = context->alt_regs[Z80_E];
996 } else { 2217 } else {
997 value = context->regs[Z80_E]; 2218 return 0;
998 } 2219 }
999 break; 2220 break;
1000 case 'f': 2221 case 'f':
1001 if(param[2] == '\'') { 2222 if (!name[1]) {
1002 value = context->alt_flags[ZF_S] << 7; 2223 *out = context->flags[ZF_S] << 7;
1003 value |= context->alt_flags[ZF_Z] << 6; 2224 *out |= context->flags[ZF_Z] << 6;
1004 value |= context->alt_flags[ZF_H] << 4; 2225 *out |= context->flags[ZF_H] << 4;
1005 value |= context->alt_flags[ZF_PV] << 2; 2226 *out |= context->flags[ZF_PV] << 2;
1006 value |= context->alt_flags[ZF_N] << 1; 2227 *out |= context->flags[ZF_N] << 1;
1007 value |= context->alt_flags[ZF_C]; 2228 *out |= context->flags[ZF_C];
2229 } else if (name[1] == '\'' && !name[2]) {
2230 *out = context->alt_flags[ZF_S] << 7;
2231 *out |= context->alt_flags[ZF_Z] << 6;
2232 *out |= context->alt_flags[ZF_H] << 4;
2233 *out |= context->alt_flags[ZF_PV] << 2;
2234 *out |= context->alt_flags[ZF_N] << 1;
2235 *out |= context->alt_flags[ZF_C];
1008 } else { 2236 } else {
1009 value = context->flags[ZF_S] << 7; 2237 return 0;
1010 value |= context->flags[ZF_Z] << 6;
1011 value |= context->flags[ZF_H] << 4;
1012 value |= context->flags[ZF_PV] << 2;
1013 value |= context->flags[ZF_N] << 1;
1014 value |= context->flags[ZF_C];
1015 } 2238 }
1016 break; 2239 break;
1017 case 'h': 2240 case 'h':
1018 if (param[1] == 'l') { 2241 if (!name[1]) {
1019 if(param[2] == '\'') { 2242 *out = context->regs[Z80_H];
1020 value = context->alt_regs[Z80_H] << 8; 2243 } else if (name[1] == '\'' && !name[2]) {
1021 value |= context->alt_regs[Z80_L]; 2244 *out = context->alt_regs[Z80_H];
2245 } else if (tolower(name[1]) == 'e') {
2246 if (!name[2]) {
2247 *out = context->regs[Z80_H] << 8 | context->regs[Z80_L];
2248 } else if (name[2] == '\'' && !name[3]) {
2249 *out = context->alt_regs[Z80_H] << 8 | context->alt_regs[Z80_L];
1022 } else { 2250 } else {
1023 value = context->regs[Z80_H] << 8; 2251 return 0;
1024 value |= context->regs[Z80_L]; 2252 }
1025 } 2253 }
1026 } else if(param[1] == '\'') { 2254 break;
1027 value = context->alt_regs[Z80_H]; 2255 case 'i':
1028 } else { 2256 switch (tolower(name[1]))
1029 value = context->regs[Z80_H]; 2257 {
2258 case 0:
2259 *out = context->regs[Z80_I];
2260 break;
2261 case 'f':
2262 if (name[2] != 'f' || name[3] < '1' || name[4]) {
2263 return 0;
2264 }
2265 if (name[3] == '1') {
2266 *out = context->iff1;
2267 } else if (name[3] == '2') {
2268 *out = context->iff2;
2269 } else {
2270 return 0;
2271 }
2272 break;
2273 case 'm':
2274 if (name[2]) {
2275 return 0;
2276 }
2277 *out = context->im;
2278 break;
2279 case 'n':
2280 if (strcasecmp(name +2, "t_cycle")) {
2281 return 0;
2282 }
2283 *out = context->int_cycle;
2284 break;
2285 case 'r':
2286 if (name[2]) {
2287 return 0;
2288 }
2289 *out = context->regs[Z80_I] << 8 | context->regs[Z80_R];
2290 break;
2291 case 'x':
2292 switch (tolower(name[2]))
2293 {
2294 case 0:
2295 *out = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL];
2296 break;
2297 case 'h':
2298 if (name[3]) {
2299 return 0;
2300 }
2301 *out = context->regs[Z80_IXH];
2302 case 'l':
2303 if (name[3]) {
2304 return 0;
2305 }
2306 *out = context->regs[Z80_IXL];
2307 default:
2308 return 0;
2309 }
2310 break;
2311 case 'y':
2312 switch (tolower(name[2]))
2313 {
2314 case 0:
2315 *out = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL];
2316 break;
2317 case 'h':
2318 if (name[3]) {
2319 return 0;
2320 }
2321 *out = context->regs[Z80_IYH];
2322 case 'l':
2323 if (name[3]) {
2324 return 0;
2325 }
2326 *out = context->regs[Z80_IYL];
2327 default:
2328 return 0;
2329 }
2330 break;
2331 default:
2332 return 0;
1030 } 2333 }
1031 break; 2334 break;
1032 case 'l': 2335 case 'l':
1033 if(param[1] == '\'') { 2336 if (!name[1]) {
1034 value = context->alt_regs[Z80_L]; 2337 *out = context->regs[Z80_L];
2338 } else if (name[1] == '\'' && !name[2]) {
2339 *out = context->alt_regs[Z80_L];
1035 } else { 2340 } else {
1036 value = context->regs[Z80_L]; 2341 return 0;
2342 }
2343 break;
2344 case 'p':
2345 if (tolower(name[1]) != 'c' || name[2]) {
2346 return 0;
2347 }
2348 *out = root->address;
2349 break;
2350 case 'r':
2351 if (name[1]) {
2352 return 0;
2353 }
2354 *out = context->regs[Z80_R];
2355 case 's':
2356 if (tolower(name[1]) != 'p' || name[2]) {
2357 return 0;
2358 }
2359 *out = context->sp;
2360 break;
2361 default:
2362 return 0;
2363 }
2364 return 1;
2365 }
2366
2367 static uint8_t set_z80(debug_root *root, const char *name, uint32_t value)
2368 {
2369 z80_context *context = root->cpu_context;
2370 switch (tolower(name[0]))
2371 {
2372 case 'a':
2373 if (!name[1]) {
2374 context->regs[Z80_A] = value;
2375 } else if (name[1] == '\'' && !name[2]) {
2376 context->alt_regs[Z80_A] = value;
2377 } else if (tolower(name[1]) == 'f') {
2378 if (!name[2]) {
2379 context->regs[Z80_A] = value >> 8;
2380 context->flags[ZF_S] = value >> 7 & 1;
2381 context->flags[ZF_Z] = value >> 6 & 1;
2382 context->flags[ZF_H] = value >> 4 & 1;
2383 context->flags[ZF_PV] = value >> 2 & 1;
2384 context->flags[ZF_N] = value >> 1 & 1;
2385 context->flags[ZF_C] = value & 1;
2386 } else if (name[2] == '\'' && !name[3]) {
2387 context->alt_regs[Z80_A] = value >> 8;
2388 context->alt_flags[ZF_S] = value >> 7 & 1;
2389 context->alt_flags[ZF_Z] = value >> 6 & 1;
2390 context->alt_flags[ZF_H] = value >> 4 & 1;
2391 context->alt_flags[ZF_PV] = value >> 2 & 1;
2392 context->alt_flags[ZF_N] = value >> 1 & 1;
2393 context->alt_flags[ZF_C] = value & 1;
2394 } else {
2395 return 0;
2396 }
2397 } else {
2398 return 0;
2399 }
2400 break;
2401 case 'b':
2402 if (!name[1]) {
2403 context->regs[Z80_B] = value;
2404 } else if (name[1] == '\'' && !name[2]) {
2405 context->alt_regs[Z80_B] = value;
2406 } else if (tolower(name[1]) == 'c') {
2407 if (!name[2]) {
2408 context->regs[Z80_B] = value >> 8;
2409 context->regs[Z80_C] = value;
2410 } else if (name[2] == '\'' && !name[3]) {
2411 context->alt_regs[Z80_B] = value >> 8;
2412 context->alt_regs[Z80_C] = value;
2413 } else {
2414 return 0;
2415 }
2416 }
2417 break;
2418 case 'c':
2419 if (!name[1]) {
2420 context->regs[Z80_C] = value;
2421 } else if (name[1] == '\'' && !name[2]) {
2422 context->alt_regs[Z80_C] = value;
2423 } else {
2424 return 0;
2425 }
2426 break;
2427 case 'd':
2428 if (!name[1]) {
2429 context->regs[Z80_D] = value;
2430 } else if (name[1] == '\'' && !name[2]) {
2431 context->alt_regs[Z80_D] = value;
2432 } else if (tolower(name[1]) == 'e') {
2433 if (!name[2]) {
2434 context->regs[Z80_D] = value >> 8;
2435 context->regs[Z80_E] = value;
2436 } else if (name[2] == '\'' && !name[3]) {
2437 context->alt_regs[Z80_D] = value >> 8;
2438 context->alt_regs[Z80_E] = value;
2439 } else {
2440 return 0;
2441 }
2442 }
2443 break;
2444 case 'e':
2445 if (!name[1]) {
2446 context->regs[Z80_E] = value;
2447 } else if (name[1] == '\'' && !name[2]) {
2448 context->alt_regs[Z80_E] = value;
2449 } else {
2450 return 0;
2451 }
2452 break;
2453 case 'f':
2454 if (!name[1]) {
2455 context->flags[ZF_S] = value >> 7 & 1;
2456 context->flags[ZF_Z] = value >> 6 & 1;
2457 context->flags[ZF_H] = value >> 4 & 1;
2458 context->flags[ZF_PV] = value >> 2 & 1;
2459 context->flags[ZF_N] = value >> 1 & 1;
2460 context->flags[ZF_C] = value & 1;
2461 } else if (name[1] == '\'' && !name[2]) {
2462 context->alt_flags[ZF_S] = value >> 7 & 1;
2463 context->alt_flags[ZF_Z] = value >> 6 & 1;
2464 context->alt_flags[ZF_H] = value >> 4 & 1;
2465 context->alt_flags[ZF_PV] = value >> 2 & 1;
2466 context->alt_flags[ZF_N] = value >> 1 & 1;
2467 context->alt_flags[ZF_C] = value & 1;
2468 } else {
2469 return 0;
2470 }
2471 break;
2472 case 'h':
2473 if (!name[1]) {
2474 context->regs[Z80_H] = value;
2475 } else if (name[1] == '\'' && !name[2]) {
2476 context->alt_regs[Z80_H] = value;
2477 } else if (tolower(name[1]) == 'e') {
2478 if (!name[2]) {
2479 context->regs[Z80_H] = value >> 8;
2480 context->regs[Z80_L] = value;
2481 } else if (name[2] == '\'' && !name[3]) {
2482 context->alt_regs[Z80_H] = value >> 8;
2483 context->alt_regs[Z80_L] = value;
2484 } else {
2485 return 0;
2486 }
1037 } 2487 }
1038 break; 2488 break;
1039 case 'i': 2489 case 'i':
1040 if(param[1] == 'x') { 2490 switch (tolower(name[1]))
1041 if (param[2] == 'h') { 2491 {
1042 value = context->regs[Z80_IXH]; 2492 case 0:
1043 } else if(param[2] == 'l') { 2493 context->regs[Z80_I] = value;
1044 value = context->regs[Z80_IXL]; 2494 break;
2495 case 'f':
2496 if (name[2] != 'f' || name[3] < '1' || name[4]) {
2497 return 0;
2498 }
2499 if (name[3] == '1') {
2500 context->iff1 = value != 0;
2501 } else if (name[3] == '2') {
2502 context->iff2 = value != 0;
1045 } else { 2503 } else {
1046 value = context->regs[Z80_IXH] << 8; 2504 return 0;
1047 value |= context->regs[Z80_IXL]; 2505 }
1048 } 2506 break;
1049 } else if(param[1] == 'y') { 2507 case 'm':
1050 if (param[2] == 'h') { 2508 if (name[2]) {
1051 value = context->regs[Z80_IYH]; 2509 return 0;
1052 } else if(param[2] == 'l') { 2510 }
1053 value = context->regs[Z80_IYL]; 2511 context->im = value & 3;
1054 } else { 2512 break;
1055 value = context->regs[Z80_IYH] << 8; 2513 case 'r':
1056 value |= context->regs[Z80_IYL]; 2514 if (name[2]) {
1057 } 2515 return 0;
1058 } else if(param[1] == 'n') { 2516 }
1059 value = context->int_cycle; 2517 context->regs[Z80_I] = value >> 8;
1060 } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '1') { 2518 context->regs[Z80_R] = value;
1061 value = context->iff1; 2519 break;
1062 } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '2') { 2520 case 'x':
1063 value = context->iff2; 2521 switch (tolower(name[2]))
2522 {
2523 case 0:
2524 context->regs[Z80_IXH] = value >> 8;
2525 context->regs[Z80_IXL] = value;
2526 break;
2527 case 'h':
2528 if (name[3]) {
2529 return 0;
2530 }
2531 context->regs[Z80_IXH] = value;
2532 case 'l':
2533 if (name[3]) {
2534 return 0;
2535 }
2536 context->regs[Z80_IXL] = value;
2537 default:
2538 return 0;
2539 }
2540 break;
2541 case 'y':
2542 switch (tolower(name[2]))
2543 {
2544 case 0:
2545 context->regs[Z80_IYH] = value >> 8;
2546 context->regs[Z80_IYL] = value;
2547 break;
2548 case 'h':
2549 if (name[3]) {
2550 return 0;
2551 }
2552 context->regs[Z80_IYH] = value;
2553 case 'l':
2554 if (name[3]) {
2555 return 0;
2556 }
2557 context->regs[Z80_IYL] = value;
2558 default:
2559 return 0;
2560 }
2561 break;
2562 default:
2563 return 0;
2564 }
2565 break;
2566 case 'l':
2567 if (!name[1]) {
2568 context->regs[Z80_L] = value;
2569 } else if (name[1] == '\'' && !name[2]) {
2570 context->alt_regs[Z80_L] = value;
1064 } else { 2571 } else {
1065 value = context->im; 2572 return 0;
1066 } 2573 }
1067 break; 2574 break;
1068 #endif 2575 case 'r':
2576 if (name[1]) {
2577 return 0;
2578 }
2579 context->regs[Z80_R] = value;
1069 case 's': 2580 case 's':
1070 if (param[1] == 'p') { 2581 if (tolower(name[1]) != 'p' || name[2]) {
1071 value = context->sp; 2582 return 0;
1072 } 2583 }
2584 context->sp = value;
1073 break; 2585 break;
1074 case '0': 2586 default:
1075 if (param[1] == 'x') { 2587 return 0;
1076 uint16_t p_addr = strtol(param+2, NULL, 16); 2588 }
1077 value = read_byte(p_addr, (void **)context->mem_pointers, &context->options->gen, context); 2589 return 1;
1078 } 2590 }
1079 break; 2591
1080 } 2592 debug_root *find_z80_root(z80_context *context)
1081 printf(format, param, value); 2593 {
2594 debug_root *root = find_root(context);
2595 if (root && !root->commands) {
2596 add_commands(root, common_commands, NUM_COMMON);
2597 add_commands(root, z80_commands, NUM_Z80);
2598 root->read_mem = read_z80;
2599 root->write_mem = write_z80;
2600 root->set = set_z80;
2601 root->resolve = resolve_z80;
2602 }
2603 return root;
1082 } 2604 }
1083 2605
1084 z80_context * zdebugger(z80_context * context, uint16_t address) 2606 z80_context * zdebugger(z80_context * context, uint16_t address)
1085 { 2607 {
1086 static char last_cmd[1024]; 2608 static char last_cmd[1024];
1087 char input_buf[1024]; 2609 char input_buf[1024];
1088 z80inst inst; 2610 z80inst inst;
1089 genesis_context *system = context->system; 2611 genesis_context *system = context->system;
1090 init_terminal(); 2612 init_terminal();
1091 //Check if this is a user set breakpoint, or just a temporary one
1092 debug_root *root = find_root(context); 2613 debug_root *root = find_root(context);
1093 if (!root) { 2614 if (!root) {
1094 return context; 2615 return context;
1095 } 2616 }
2617 //Check if this is a user set breakpoint, or just a temporary one
1096 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); 2618 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address);
1097 if (*this_bp) { 2619 if (*this_bp) {
1098 printf("Z80 Breakpoint %d hit\n", (*this_bp)->index); 2620 printf("Z80 Breakpoint %d hit\n", (*this_bp)->index);
1099 } else { 2621 } else {
1100 zremove_breakpoint(context, address); 2622 zremove_breakpoint(context, address);
1102 uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->Z80_OPTS->gen); 2624 uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
1103 if (!pc) { 2625 if (!pc) {
1104 fatal_error("Failed to get native pointer on entering Z80 debugger at address %X\n", address); 2626 fatal_error("Failed to get native pointer on entering Z80 debugger at address %X\n", address);
1105 } 2627 }
1106 for (disp_def * cur = root->displays; cur; cur = cur->next) { 2628 for (disp_def * cur = root->displays; cur; cur = cur->next) {
1107 zdebugger_print(context, cur->format_char, cur->param); 2629 cmd_print(root, cur->format, cur->num_args, cur->args);
1108 } 2630 }
1109 uint8_t * after_pc = z80_decode(pc, &inst); 2631 uint8_t * after_pc = z80_decode(pc, &inst);
1110 z80_disasm(&inst, input_buf, address); 2632 z80_disasm(&inst, input_buf, address);
1111 printf("%X:\t%s\n", address, input_buf); 2633 printf("%X:\t%s\n", address, input_buf);
1112 uint16_t after = address + (after_pc-pc); 2634 uint16_t after = address + (after_pc-pc);
2635 root->address = address;
2636 root->after = after;
2637 root->inst = &inst;
1113 int debugging = 1; 2638 int debugging = 1;
1114 while(debugging) { 2639 while(debugging) {
1115 fputs(">", stdout); 2640 fputs(">", stdout);
1116 if (!fgets(input_buf, sizeof(input_buf), stdin)) { 2641 if (!fgets(input_buf, sizeof(input_buf), stdin)) {
1117 fputs("fgets failed", stderr); 2642 fputs("fgets failed", stderr);
1122 if (input_buf[0]) { 2647 if (input_buf[0]) {
1123 strcpy(last_cmd, input_buf); 2648 strcpy(last_cmd, input_buf);
1124 } else { 2649 } else {
1125 strcpy(input_buf, last_cmd); 2650 strcpy(input_buf, last_cmd);
1126 } 2651 }
1127 char * param; 2652 parsed_command cmd;
1128 char format[8]; 2653 if (parse_command(root, input_buf, &cmd)) {
1129 uint32_t value; 2654 debugging = run_command(root, &cmd);
1130 bp_def * new_bp; 2655 free_parsed_command(&cmd);
1131 switch(input_buf[0]) 2656 }
1132 { 2657 }
1133 case 'a': 2658 return context;
1134 param = find_param(input_buf); 2659 }
1135 if (!param) { 2660
1136 fputs("a command requires a parameter\n", stderr);
1137 break;
1138 }
1139 value = strtol(param, NULL, 16);
1140 zinsert_breakpoint(context, value, (uint8_t *)zdebugger);
1141 debugging = 0;
1142 break;
1143 case 'b':
1144 param = find_param(input_buf);
1145 if (!param) {
1146 fputs("b command requires a parameter\n", stderr);
1147 break;
1148 }
1149 value = strtol(param, NULL, 16);
1150 zinsert_breakpoint(context, value, (uint8_t *)zdebugger);
1151 new_bp = malloc(sizeof(bp_def));
1152 new_bp->next = root->breakpoints;
1153 new_bp->address = value;
1154 new_bp->index = root->bp_index++;
1155 new_bp->commands = NULL;
1156 root->breakpoints = new_bp;
1157 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
1158 break;
1159 case 'c':
1160 puts("Continuing");
1161 debugging = 0;
1162 break;
1163 case 'd':
1164 if (input_buf[1] == 'i') {
1165 char format_char = 0;
1166 for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) {
1167 if (input_buf[i] == '/') {
1168 format_char = input_buf[i+1];
1169 break;
1170 }
1171 }
1172 param = find_param(input_buf);
1173 if (!param) {
1174 fputs("display command requires a parameter\n", stderr);
1175 break;
1176 }
1177 zdebugger_print(context, format_char, param);
1178 add_display(&root->displays, &root->disp_index, format_char, param);
1179 } else if (input_buf[1] == 'e' || input_buf[1] == ' ') {
1180 param = find_param(input_buf);
1181 if (!param) {
1182 fputs("delete command requires a parameter\n", stderr);
1183 break;
1184 }
1185 if (param[0] >= '0' && param[0] <= '9') {
1186 value = atoi(param);
1187 this_bp = find_breakpoint_idx(&root->breakpoints, value);
1188 if (!*this_bp) {
1189 fprintf(stderr, "Breakpoint %d does not exist\n", value);
1190 break;
1191 }
1192 new_bp = *this_bp;
1193 zremove_breakpoint(context, new_bp->address);
1194 *this_bp = new_bp->next;
1195 free(new_bp);
1196 } else if (param[0] == 'd') {
1197 param = find_param(param);
1198 if (!param) {
1199 fputs("delete display command requires a parameter\n", stderr);
1200 break;
1201 }
1202 remove_display(&root->displays, atoi(param));
1203 }
1204 }
1205 break;
1206 case 'n':
1207 //TODO: Handle conditional branch instructions
1208 if (inst.op == Z80_JP) {
1209 if (inst.addr_mode == Z80_IMMED) {
1210 after = inst.immed;
1211 } else if (inst.ea_reg == Z80_HL) {
1212 #ifndef NEW_CORE
1213 after = context->regs[Z80_H] << 8 | context->regs[Z80_L];
1214 } else if (inst.ea_reg == Z80_IX) {
1215 after = context->regs[Z80_IXH] << 8 | context->regs[Z80_IXL];
1216 } else if (inst.ea_reg == Z80_IY) {
1217 after = context->regs[Z80_IYH] << 8 | context->regs[Z80_IYL];
1218 #endif 2661 #endif
1219 }
1220 } else if(inst.op == Z80_JR) {
1221 after += inst.immed;
1222 } else if(inst.op == Z80_RET) {
1223 uint8_t *sp = get_native_pointer(context->sp, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
1224 if (sp) {
1225 after = *sp;
1226 sp = get_native_pointer((context->sp + 1) & 0xFFFF, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
1227 if (sp) {
1228 after |= *sp << 8;
1229 }
1230 }
1231 }
1232 zinsert_breakpoint(context, after, (uint8_t *)zdebugger);
1233 debugging = 0;
1234 break;
1235 case 'p':
1236 param = find_param(input_buf);
1237 if (!param) {
1238 fputs("p command requires a parameter\n", stderr);
1239 break;
1240 }
1241 zdebugger_print(context, input_buf[1] == '/' ? input_buf[2] : 0, param);
1242 break;
1243 case 'q':
1244 puts("Quitting");
1245 exit(0);
1246 break;
1247 case 's': {
1248 param = find_param(input_buf);
1249 if (!param) {
1250 fputs("s command requires a file name\n", stderr);
1251 break;
1252 }
1253 memmap_chunk const *ram_chunk = NULL;
1254 for (int i = 0; i < context->Z80_OPTS->gen.memmap_chunks; i++)
1255 {
1256 memmap_chunk const *cur = context->Z80_OPTS->gen.memmap + i;
1257 if (cur->flags & MMAP_WRITE) {
1258 ram_chunk = cur;
1259 break;
1260 }
1261 }
1262 if (ram_chunk) {
1263 uint32_t size = ram_chunk->end - ram_chunk->start;
1264 if (size > ram_chunk->mask) {
1265 size = ram_chunk->mask+1;
1266 }
1267 uint8_t *buf = get_native_pointer(ram_chunk->start, (void **)context->mem_pointers, &context->Z80_OPTS->gen);
1268 FILE * f = fopen(param, "wb");
1269 if (f) {
1270 if(fwrite(buf, 1, size, f) != size) {
1271 fputs("Error writing file\n", stderr);
1272 }
1273 fclose(f);
1274 printf("Wrote %d bytes to %s\n", size, param);
1275 } else {
1276 fprintf(stderr, "Could not open %s for writing\n", param);
1277 }
1278 } else {
1279 fputs("Failed to find a RAM memory chunk\n", stderr);
1280 }
1281 break;
1282 }
1283 case '?':
1284 print_z80_help();
1285 break;
1286 default:
1287 if (
1288 !context->Z80_OPTS->gen.debug_cmd_handler
1289 || !context->Z80_OPTS->gen.debug_cmd_handler(&system->header, input_buf)
1290 ) {
1291 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf);
1292 }
1293 break;
1294 }
1295 }
1296 return context;
1297 }
1298
1299 #endif
1300
1301 int run_debugger_command(m68k_context *context, uint32_t address, char *input_buf, m68kinst inst, uint32_t after);
1302 int run_genesis_debugger_command(m68k_context *context, uint32_t address, char *input_buf)
1303 {
1304 genesis_context * gen = context->system;
1305 char *param;
1306 uint32_t value;
1307 bp_def *new_bp;
1308 switch (input_buf[0])
1309 {
1310 case 'v':
1311 //VDP debug commands
1312 switch(input_buf[1])
1313 {
1314 case 's':
1315 vdp_print_sprite_table(gen->vdp);
1316 break;
1317 case 'r':
1318 vdp_print_reg_explain(gen->vdp);
1319 break;
1320 }
1321 break;
1322 case 'y':
1323 //YM-2612 debug commands
1324 switch(input_buf[1])
1325 {
1326 case 'c':
1327 if (input_buf[2] == ' ') {
1328 int channel = atoi(input_buf+3)-1;
1329 ym_print_channel_info(gen->ym, channel);
1330 } else {
1331 for (int i = 0; i < 6; i++) {
1332 ym_print_channel_info(gen->ym, i);
1333 }
1334 }
1335 break;
1336 case 't':
1337 ym_print_timer_info(gen->ym);
1338 break;
1339 }
1340 break;
1341 case 'u':
1342 if (gen->expansion) {
1343 segacd_context *cd = gen->expansion;
1344 if (input_buf[1]) {
1345 //TODO: filter out commands that are unsafe to run when we don't have the current Sub CPU address
1346 run_debugger_command(cd->m68k, 0, input_buf + 1, (m68kinst){}, 0);
1347 } else {
1348 cd->enter_debugger = 1;
1349 return 0;
1350 }
1351 } else {
1352 fputs("u command only valid when Sega/Mega CD is active\n", stderr);
1353 }
1354 break;
1355 #ifndef NO_Z80
1356 case 'z':
1357 //Z80 debug commands
1358 switch(input_buf[1])
1359 {
1360 case 'b': {
1361 param = find_param(input_buf);
1362 if (!param) {
1363 fputs("zb command requires a parameter\n", stderr);
1364 break;
1365 }
1366 value = strtol(param, NULL, 16);
1367 debug_root *zroot = find_root(gen->z80);
1368 zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger);
1369 new_bp = malloc(sizeof(bp_def));
1370 new_bp->next = zroot->breakpoints;
1371 new_bp->address = value;
1372 new_bp->index = zroot->bp_index++;
1373 zroot->breakpoints = new_bp;
1374 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
1375 break;
1376 }
1377 case 'p':
1378 param = find_param(input_buf);
1379 if (!param) {
1380 fputs("zp command requires a parameter\n", stderr);
1381 break;
1382 }
1383 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param);
1384 }
1385 break;
1386 #endif
1387 default:
1388 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf);
1389 break;
1390 }
1391 return 1;
1392 }
1393
1394 int run_subcpu_debugger_command(m68k_context *context, uint32_t address, char *input_buf)
1395 {
1396 segacd_context *cd = context->system;
1397 switch (input_buf[0])
1398 {
1399 case 'm':
1400 if (input_buf[1]) {
1401 //TODO: filter out commands that are unsafe to run when we don't have the current Main CPU address
1402 return run_debugger_command(cd->genesis->m68k, 0, input_buf + 1, (m68kinst){}, 0);
1403 } else {
1404 cd->genesis->header.enter_debugger = 1;
1405 return 0;
1406 }
1407 break;
1408 default:
1409 fprintf(stderr, "Unrecognized debugger command %s\nUse '?' for help.\n", input_buf);
1410 break;
1411 }
1412 return 1;
1413 }
1414
1415 int run_debugger_command(m68k_context *context, uint32_t address, char *input_buf, m68kinst inst, uint32_t after)
1416 {
1417 char * param;
1418 char format_char;
1419 genesis_context *system = context->system;
1420 uint32_t value;
1421 bp_def *new_bp, **this_bp;
1422 debug_root *root = find_root(context);
1423 if (!root) {
1424 return 0;
1425 }
1426 root->address = address;
1427 switch(input_buf[0])
1428 {
1429 case 'c':
1430 if (input_buf[1] == 0 || input_buf[1] == 'o' && input_buf[2] == 'n')
1431 {
1432 puts("Continuing");
1433 return 0;
1434 } else if (input_buf[1] == 'o' && input_buf[2] == 'm') {
1435 param = find_param(input_buf);
1436 if (!param) {
1437 fputs("com command requires a parameter\n", stderr);
1438 break;
1439 }
1440 bp_def **target = find_breakpoint_idx(&root->breakpoints, atoi(param));
1441 if (!target) {
1442 fprintf(stderr, "Breakpoint %s does not exist!\n", param);
1443 break;
1444 }
1445 printf("Enter commands for breakpoing %d, type end when done\n", atoi(param));
1446 char cmd_buf[1024];
1447 char *commands = NULL;
1448 for (;;)
1449 {
1450 fputs(">>", stdout);
1451 fflush(stdout);
1452 fgets(cmd_buf, sizeof(cmd_buf), stdin);
1453 if (strcmp(cmd_buf, "end\n")) {
1454 if (commands) {
1455 char *tmp = commands;
1456 commands = alloc_concat(commands, cmd_buf);
1457 free(tmp);
1458 } else {
1459 commands = strdup(cmd_buf);
1460 }
1461 } else {
1462 break;
1463 }
1464 }
1465 (*target)->commands = commands;
1466 } else {
1467 }
1468 break;
1469 case 'b':
1470 if (input_buf[1] == 't') {
1471 uint32_t stack = context->aregs[7];
1472 uint8_t non_adr_count = 0;
1473 do {
1474 uint32_t bt_address = m68k_instruction_fetch(stack, context);
1475 bt_address = get_instruction_start(context->options, bt_address - 2);
1476 if (bt_address) {
1477 stack += 4;
1478 non_adr_count = 0;
1479 m68k_decode(m68k_instruction_fetch, context, &inst, bt_address);
1480 m68k_disasm(&inst, input_buf);
1481 printf("%X: %s\n", bt_address, input_buf);
1482 } else {
1483 //non-return address value on stack can be word wide
1484 stack += 2;
1485 non_adr_count++;
1486 }
1487 //TODO: Make sure we don't wander into an invalid memory region
1488 } while (stack && non_adr_count < 6);
1489 } else {
1490 param = find_param(input_buf);
1491 if (!param) {
1492 fputs("b command requires a parameter\n", stderr);
1493 break;
1494 }
1495 value = strtol(param, NULL, 16);
1496 insert_breakpoint(context, value, debugger);
1497 new_bp = malloc(sizeof(bp_def));
1498 new_bp->next = root->breakpoints;
1499 new_bp->address = value;
1500 new_bp->index = root->bp_index++;
1501 new_bp->commands = NULL;
1502 root->breakpoints = new_bp;
1503 printf("68K Breakpoint %d set at %X\n", new_bp->index, value);
1504 }
1505 break;
1506 case 'a':
1507 param = find_param(input_buf);
1508 if (!param) {
1509 fputs("a command requires a parameter\n", stderr);
1510 break;
1511 }
1512 value = strtol(param, NULL, 16);
1513 insert_breakpoint(context, value, debugger);
1514 return 0;
1515 case 'd':
1516 if (input_buf[1] == 'i') {
1517 format_char = 0;
1518 for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) {
1519 if (input_buf[i] == '/') {
1520 format_char = input_buf[i+1];
1521 break;
1522 }
1523 }
1524 param = find_param(input_buf);
1525 if (!param) {
1526 fputs("display command requires a parameter\n", stderr);
1527 break;
1528 }
1529 debugger_print(root, format_char, param);
1530 add_display(&root->displays, &root->disp_index, format_char, param);
1531 } else {
1532 param = find_param(input_buf);
1533 if (!param) {
1534 fputs("d command requires a parameter\n", stderr);
1535 break;
1536 }
1537 value = atoi(param);
1538 this_bp = find_breakpoint_idx(&root->breakpoints, value);
1539 if (!*this_bp) {
1540 fprintf(stderr, "Breakpoint %d does not exist\n", value);
1541 break;
1542 }
1543 new_bp = *this_bp;
1544 *this_bp = (*this_bp)->next;
1545 if (new_bp->commands) {
1546 free(new_bp->commands);
1547 }
1548 free(new_bp);
1549 }
1550 break;
1551 case 'p':
1552 format_char = 0;
1553 for(int i = 1; input_buf[i] != 0 && input_buf[i] != ' '; i++) {
1554 if (input_buf[i] == '/') {
1555 format_char = input_buf[i+1];
1556 break;
1557 }
1558 }
1559 param = find_param(input_buf);
1560 if (param) {
1561 debugger_print(root, format_char, param);
1562 } else {
1563 m68k_disasm(&inst, input_buf);
1564 printf("%X: %s\n", address, input_buf);
1565 }
1566
1567 break;
1568 case 'n':
1569 if (inst.op == M68K_RTS) {
1570 after = m68k_read_long(context->aregs[7], context);
1571 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
1572 after = m68k_read_long(context->aregs[7] + 2, context);
1573 } else if(m68k_is_noncall_branch(&inst)) {
1574 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
1575 root->branch_f = after;
1576 root->branch_t = m68k_branch_target(&inst, context->dregs, context->aregs);
1577 insert_breakpoint(context, root->branch_t, debugger);
1578 } else if(inst.op == M68K_DBCC) {
1579 if ( inst.extra.cond == COND_FALSE) {
1580 if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) {
1581 after = m68k_branch_target(&inst, context->dregs, context->aregs);
1582 }
1583 } else {
1584 root->branch_t = after;
1585 root->branch_f = m68k_branch_target(&inst, context->dregs, context->aregs);
1586 insert_breakpoint(context, root->branch_f, debugger);
1587 }
1588 } else {
1589 after = m68k_branch_target(&inst, context->dregs, context->aregs);
1590 }
1591 }
1592 insert_breakpoint(context, after, debugger);
1593 return 0;
1594 case 'o':
1595 if (inst.op == M68K_RTS) {
1596 after = m68k_read_long(context->aregs[7], context);
1597 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
1598 after = m68k_read_long(context->aregs[7] + 2, context);
1599 } else if(m68k_is_noncall_branch(&inst)) {
1600 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
1601 root->branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
1602 if (root->branch_t < after) {
1603 root->branch_t = 0;
1604 } else {
1605 root->branch_f = after;
1606 insert_breakpoint(context, root->branch_t, debugger);
1607 }
1608 } else if(inst.op == M68K_DBCC) {
1609 uint32_t target = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
1610 if (target > after) {
1611 if (inst.extra.cond == COND_FALSE) {
1612 after = target;
1613 } else {
1614 root->branch_f = target;
1615 root->branch_t = after;
1616 insert_breakpoint(context, root->branch_f, debugger);
1617 }
1618 }
1619 } else {
1620 after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
1621 }
1622 }
1623 insert_breakpoint(context, after, debugger);
1624 return 0;
1625 case 's':
1626 if (input_buf[1] == 'e') {
1627 param = find_param(input_buf);
1628 if (!param) {
1629 fputs("Missing destination parameter for set\n", stderr);
1630 return 1;
1631 }
1632 char *val = find_param(param);
1633 if (!val) {
1634 fputs("Missing value parameter for set\n", stderr);
1635 return 1;
1636 }
1637 long int_val;
1638 int reg_num;
1639 switch (val[0])
1640 {
1641 case 'd':
1642 case 'a':
1643 reg_num = val[1] - '0';
1644 if (reg_num < 0 || reg_num > 8) {
1645 fprintf(stderr, "Invalid register %s\n", val);
1646 return 1;
1647 }
1648 int_val = (val[0] == 'd' ? context->dregs : context->aregs)[reg_num];
1649 break;
1650 case '$':
1651 int_val = strtol(val+1, NULL, 16);
1652 break;
1653 case '0':
1654 if (val[1] == 'x') {
1655 int_val = strtol(val+2, NULL, 16);
1656 break;
1657 }
1658 default:
1659 int_val = strtol(val, NULL, 10);
1660 }
1661 switch(param[0])
1662 {
1663 case 'd':
1664 case 'a':
1665 reg_num = param[1] - '0';
1666 if (reg_num < 0 || reg_num > 8) {
1667 fprintf(stderr, "Invalid register %s\n", param);
1668 return 1;
1669 }
1670 (param[0] == 'd' ? context->dregs : context->aregs)[reg_num] = int_val;
1671 break;
1672 default:
1673 fprintf(stderr, "Invalid destinatino %s\n", param);
1674 }
1675 break;
1676 } else if (input_buf[1] == 'r') {
1677 system->header.soft_reset(&system->header);
1678 return 0;
1679 } else {
1680 if (inst.op == M68K_RTS) {
1681 after = m68k_read_long(context->aregs[7], context);
1682 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) {
1683 after = m68k_read_long(context->aregs[7] + 2, context);
1684 } else if(m68k_is_branch(&inst)) {
1685 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) {
1686 root->branch_f = after;
1687 root->branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
1688 insert_breakpoint(context, root->branch_t, debugger);
1689 } else if(inst.op == M68K_DBCC) {
1690 if (inst.extra.cond == COND_FALSE) {
1691 if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) {
1692 after = m68k_branch_target(&inst, context->dregs, context->aregs);
1693 }
1694 } else {
1695 root->branch_t = after;
1696 root->branch_f = m68k_branch_target(&inst, context->dregs, context->aregs);
1697 insert_breakpoint(context, root->branch_f, debugger);
1698 }
1699 } else {
1700 after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF;
1701 }
1702 }
1703 insert_breakpoint(context, after, debugger);
1704 return 0;
1705 }
1706 case '?':
1707 print_m68k_help();
1708 break;
1709 case 'q':
1710 puts("Quitting");
1711 exit(0);
1712 break;
1713 default: {
1714 if (context->system == current_system) {
1715 //primary 68K for current system
1716 return run_genesis_debugger_command(context, address, input_buf);
1717 } else {
1718 //presumably Sega CD sub CPU
1719 //TODO: consider making this more generic
1720 return run_subcpu_debugger_command(context, address, input_buf);
1721 }
1722 break;
1723 }
1724 }
1725 return 1;
1726 }
1727
1728 void print_m68k_help()
1729 {
1730 printf("M68k Debugger Commands\n");
1731 printf(" b ADDRESS - Set a breakpoint at ADDRESS\n");
1732 printf(" d BREAKPOINT - Delete a 68K breakpoint\n");
1733 printf(" co BREAKPOINT - Run a list of debugger commands each time\n");
1734 printf(" BREAKPOINT is hit\n");
1735 printf(" a ADDRESS - Advance to address\n");
1736 printf(" n - Advance to next instruction\n");
1737 printf(" o - Advance to next instruction ignoring branches to\n");
1738 printf(" lower addresses (good for breaking out of loops)\n");
1739 printf(" s - Advance to next instruction (follows bsr/jsr)\n");
1740 printf(" se REG|ADDRESS VALUE - Set value\n");
1741 printf(" sr - Soft reset\n");
1742 printf(" c - Continue\n");
1743 printf(" bt - Print a backtrace\n");
1744 printf(" p[/(x|X|d|c)] VALUE - Print a register or memory location\n");
1745 printf(" di[/(x|X|d|c)] VALUE - Print a register or memory location each time\n");
1746 printf(" a breakpoint is hit\n");
1747 printf(" vs - Print VDP sprite list\n");
1748 printf(" vr - Print VDP register info\n");
1749 printf(" yc [CHANNEL NUM] - Print YM-2612 channel info\n");
1750 printf(" yt - Print YM-2612 timer info\n");
1751 printf(" zb ADDRESS - Set a Z80 breakpoint\n");
1752 printf(" zp[/(x|X|d|c)] VALUE - Display a Z80 value\n");
1753 printf(" ? - Display help\n");
1754 printf(" q - Quit BlastEm\n");
1755 }
1756
1757 void print_z80_help()
1758 {
1759 printf("Z80 Debugger Commands\n");
1760 printf(" b ADDRESS - Set a breakpoint at ADDRESS\n");
1761 printf(" de BREAKPOINT - Delete a Z80 breakpoint\n");
1762 printf(" a ADDRESS - Advance to address\n");
1763 printf(" n - Advance to next instruction\n");
1764 printf(" c - Continue\n");
1765 printf(" p[/(x|X|d|c)] VALUE - Print a register or memory location\n");
1766 printf(" di[/(x|X|d|c)] VALUE - Print a register or memory location each time\n");
1767 printf(" a breakpoint is hit\n");
1768 printf(" q - Quit BlastEm\n");
1769 }
1770 2662
1771 void debugger(m68k_context * context, uint32_t address) 2663 void debugger(m68k_context * context, uint32_t address)
1772 { 2664 {
1773 static char last_cmd[1024]; 2665 static char last_cmd[1024];
1774 char input_buf[1024]; 2666 char input_buf[1024];
1779 context->options->sync_components(context, 0); 2671 context->options->sync_components(context, 0);
1780 if (context->system == current_system) { 2672 if (context->system == current_system) {
1781 genesis_context *gen = context->system; 2673 genesis_context *gen = context->system;
1782 vdp_force_update_framebuffer(gen->vdp); 2674 vdp_force_update_framebuffer(gen->vdp);
1783 } 2675 }
1784 debug_root *root = find_root(context); 2676 debug_root *root = find_m68k_root(context);
1785 if (!root) { 2677 if (!root) {
1786 return; 2678 return;
1787 } 2679 }
1788 //probably not necessary, but let's play it safe 2680 //probably not necessary, but let's play it safe
1789 address &= 0xFFFFFF; 2681 address &= 0xFFFFFF;
1800 } 2692 }
1801 root->branch_t = root->branch_f = 0; 2693 root->branch_t = root->branch_f = 0;
1802 } 2694 }
1803 2695
1804 uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address); 2696 uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address);
2697 root->address = address;
2698 root->after = after;
2699 root->inst = &inst;
1805 int debugging = 1; 2700 int debugging = 1;
1806 //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
1807 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); 2702 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address);
1808 if (*this_bp) { 2703 if (*this_bp) {
1809 2704 for (uint32_t i = 0; debugging && i < (*this_bp)->num_commands; i++)
1810 if ((*this_bp)->commands)
1811 { 2705 {
1812 char *commands = strdup((*this_bp)->commands); 2706 debugging = run_command(root, (*this_bp)->commands + i);
1813 char *copy = commands;
1814
1815 while (debugging && *commands)
1816 {
1817 char *cmd = commands;
1818 strip_nl(cmd);
1819 commands += strlen(cmd) + 1;
1820 debugging = run_debugger_command(context, address, cmd, inst, after);
1821 }
1822 free(copy);
1823 } 2707 }
1824 if (debugging) { 2708 if (debugging) {
1825 printf("68K Breakpoint %d hit\n", (*this_bp)->index); 2709 printf("68K Breakpoint %d hit\n", (*this_bp)->index);
1826 } else { 2710 } else {
1827 return; 2711 return;
1828 } 2712 }
1829 } else { 2713 } else {
1830 remove_breakpoint(context, address); 2714 remove_breakpoint(context, address);
1831 } 2715 }
1832 for (disp_def * cur = root->displays; cur; cur = cur->next) { 2716 for (disp_def * cur = root->displays; cur; cur = cur->next) {
1833 debugger_print(root, cur->format_char, cur->param); 2717 cmd_print(root, cur->format, cur->num_args, cur->args);
1834 } 2718 }
1835 m68k_disasm(&inst, input_buf); 2719 m68k_disasm(&inst, input_buf);
1836 printf("%X: %s\n", address, input_buf); 2720 printf("%X: %s\n", address, input_buf);
1837 #ifdef _WIN32 2721 #ifdef _WIN32
1838 #define prompt 1 2722 #define prompt 1
1868 if (input_buf[0]) { 2752 if (input_buf[0]) {
1869 strcpy(last_cmd, input_buf); 2753 strcpy(last_cmd, input_buf);
1870 } else { 2754 } else {
1871 strcpy(input_buf, last_cmd); 2755 strcpy(input_buf, last_cmd);
1872 } 2756 }
1873 debugging = run_debugger_command(context, address, input_buf, inst, after); 2757 parsed_command cmd;
2758 if (parse_command(root, input_buf, &cmd)) {
2759 debugging = run_command(root, &cmd);
2760 free_parsed_command(&cmd);
2761 }
1874 } 2762 }
1875 return; 2763 return;
1876 } 2764 }