comparison blastem.c @ 372:5dcf7551bb36

Bunch of Z80 debugger improvements
author Mike Pavone <pavone@retrodev.com>
date Sun, 02 Jun 2013 20:14:27 -0700
parents c9d2a2371f5e
children d42a8a3e4894
comparison
equal deleted inserted replaced
371:0f8a759f1ff4 372:5dcf7551bb36
997 cur = &((*cur)->next); 997 cur = &((*cur)->next);
998 } 998 }
999 return cur; 999 return cur;
1000 } 1000 }
1001 1001
1002 typedef struct disp_def {
1003 struct disp_def * next;
1004 char * param;
1005 uint32_t index;
1006 char format_char;
1007 } disp_def;
1008
1009 disp_def * displays = NULL;
1010 disp_def * zdisplays = NULL;
1011 uint32_t disp_index = 0;
1012 uint32_t zdisp_index = 0;
1013
1014 void add_display(disp_def ** head, uint32_t *index, char format_char, char * param)
1015 {
1016 disp_def * ndisp = malloc(sizeof(*ndisp));
1017 ndisp->format_char = format_char;
1018 ndisp->param = strdup(param);
1019 ndisp->next = *head;
1020 ndisp->index = *index++;
1021 *head = ndisp;
1022 }
1023
1024 void remove_display(disp_def ** head, uint32_t index)
1025 {
1026 while (*head) {
1027 if ((*head)->index == index) {
1028 disp_def * del_disp = *head;
1029 *head = del_disp->next;
1030 free(del_disp->param);
1031 free(del_disp);
1032 } else {
1033 head = &(*head)->next;
1034 }
1035 }
1036 }
1037
1002 char * find_param(char * buf) 1038 char * find_param(char * buf)
1003 { 1039 {
1004 for (; *buf; buf++) { 1040 for (; *buf; buf++) {
1005 if (*buf == ' ') { 1041 if (*buf == ' ') {
1006 if (*(buf+1)) { 1042 if (*(buf+1)) {
1017 if (*buf == '\n') { 1053 if (*buf == '\n') {
1018 *buf = 0; 1054 *buf = 0;
1019 return; 1055 return;
1020 } 1056 }
1021 } 1057 }
1058 }
1059
1060 void zdebugger_print(z80_context * context, char format_char, char * param)
1061 {
1062 uint32_t value;
1063 char format[8];
1064 strcpy(format, "%s: %d\n");
1065 switch (format_char)
1066 {
1067 case 'x':
1068 case 'X':
1069 case 'd':
1070 case 'c':
1071 format[5] = format_char;
1072 break;
1073 case '\0':
1074 break;
1075 default:
1076 fprintf(stderr, "Unrecognized format character: %c\n", format_char);
1077 }
1078 switch (param[0])
1079 {
1080 case 'a':
1081 if (param[1] == 'f') {
1082 if(param[2] == '\'') {
1083 value = context->alt_regs[Z80_A] << 8;
1084 value |= context->alt_flags[ZF_S] << 7;
1085 value |= context->alt_flags[ZF_Z] << 6;
1086 value |= context->alt_flags[ZF_H] << 4;
1087 value |= context->alt_flags[ZF_PV] << 2;
1088 value |= context->alt_flags[ZF_N] << 1;
1089 value |= context->alt_flags[ZF_C];
1090 } else {
1091 value = context->regs[Z80_A] << 8;
1092 value |= context->flags[ZF_S] << 7;
1093 value |= context->flags[ZF_Z] << 6;
1094 value |= context->flags[ZF_H] << 4;
1095 value |= context->flags[ZF_PV] << 2;
1096 value |= context->flags[ZF_N] << 1;
1097 value |= context->flags[ZF_C];
1098 }
1099 } else if(param[1] == '\'') {
1100 value = context->alt_regs[Z80_A];
1101 } else {
1102 value = context->regs[Z80_A];
1103 }
1104 break;
1105 case 'b':
1106 if (param[1] == 'c') {
1107 if(param[2] == '\'') {
1108 value = context->alt_regs[Z80_B] << 8;
1109 value |= context->alt_regs[Z80_C];
1110 } else {
1111 value = context->regs[Z80_B] << 8;
1112 value |= context->regs[Z80_C];
1113 }
1114 } else if(param[1] == '\'') {
1115 value = context->alt_regs[Z80_B];
1116 } else {
1117 value = context->regs[Z80_B];
1118 }
1119 break;
1120 case 'c':
1121 if(param[1] == '\'') {
1122 value = context->alt_regs[Z80_C];
1123 } else if(param[1] == 'y') {
1124 value = context->current_cycle;
1125 } else {
1126 value = context->regs[Z80_C];
1127 }
1128 break;
1129 case 'd':
1130 if (param[1] == 'e') {
1131 if(param[2] == '\'') {
1132 value = context->alt_regs[Z80_D] << 8;
1133 value |= context->alt_regs[Z80_E];
1134 } else {
1135 value = context->regs[Z80_D] << 8;
1136 value |= context->regs[Z80_E];
1137 }
1138 } else if(param[1] == '\'') {
1139 value = context->alt_regs[Z80_D];
1140 } else {
1141 value = context->regs[Z80_D];
1142 }
1143 break;
1144 case 'e':
1145 if(param[1] == '\'') {
1146 value = context->alt_regs[Z80_E];
1147 } else {
1148 value = context->regs[Z80_E];
1149 }
1150 break;
1151 case 'f':
1152 if(param[2] == '\'') {
1153 value = context->alt_flags[ZF_S] << 7;
1154 value |= context->alt_flags[ZF_Z] << 6;
1155 value |= context->alt_flags[ZF_H] << 4;
1156 value |= context->alt_flags[ZF_PV] << 2;
1157 value |= context->alt_flags[ZF_N] << 1;
1158 value |= context->alt_flags[ZF_C];
1159 } else {
1160 value = context->flags[ZF_S] << 7;
1161 value |= context->flags[ZF_Z] << 6;
1162 value |= context->flags[ZF_H] << 4;
1163 value |= context->flags[ZF_PV] << 2;
1164 value |= context->flags[ZF_N] << 1;
1165 value |= context->flags[ZF_C];
1166 }
1167 break;
1168 case 'h':
1169 if (param[1] == 'l') {
1170 if(param[2] == '\'') {
1171 value = context->alt_regs[Z80_H] << 8;
1172 value |= context->alt_regs[Z80_L];
1173 } else {
1174 value = context->regs[Z80_H] << 8;
1175 value |= context->regs[Z80_L];
1176 }
1177 } else if(param[1] == '\'') {
1178 value = context->alt_regs[Z80_H];
1179 } else {
1180 value = context->regs[Z80_H];
1181 }
1182 break;
1183 case 'l':
1184 if(param[1] == '\'') {
1185 value = context->alt_regs[Z80_L];
1186 } else {
1187 value = context->regs[Z80_L];
1188 }
1189 break;
1190 case 'i':
1191 if(param[1] == 'x') {
1192 if (param[2] == 'h') {
1193 value = context->regs[Z80_IXH];
1194 } else if(param[2] == 'l') {
1195 value = context->regs[Z80_IXL];
1196 } else {
1197 value = context->regs[Z80_IXH] << 8;
1198 value |= context->regs[Z80_IXL];
1199 }
1200 } else if(param[1] == 'y') {
1201 if (param[2] == 'h') {
1202 value = context->regs[Z80_IYH];
1203 } else if(param[2] == 'l') {
1204 value = context->regs[Z80_IYL];
1205 } else {
1206 value = context->regs[Z80_IYH] << 8;
1207 value |= context->regs[Z80_IYL];
1208 }
1209 } else if(param[1] == 'n') {
1210 value = context->int_cycle;
1211 } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '1') {
1212 value = context->iff1;
1213 } else if(param[1] == 'f' && param[2] == 'f' && param[3] == '2') {
1214 value = context->iff2;
1215 } else {
1216 value = context->im;
1217 }
1218 break;
1219 case 's':
1220 if (param[1] == 'p') {
1221 value = context->sp;
1222 }
1223 break;
1224 case '0':
1225 if (param[1] == 'x') {
1226 uint16_t p_addr = strtol(param+2, NULL, 16);
1227 if (p_addr < 0x4000) {
1228 value = z80_ram[p_addr & 0x1FFF];
1229 }
1230 }
1231 break;
1232 }
1233 printf(format, param, value);
1022 } 1234 }
1023 1235
1024 z80_context * zdebugger(z80_context * context, uint16_t address) 1236 z80_context * zdebugger(z80_context * context, uint16_t address)
1025 { 1237 {
1026 static char last_cmd[1024]; 1238 static char last_cmd[1024];
1048 } 1260 }
1049 } else { 1261 } else {
1050 fprintf(stderr, "Entered Z80 debugger at address %X\n", address); 1262 fprintf(stderr, "Entered Z80 debugger at address %X\n", address);
1051 exit(1); 1263 exit(1);
1052 } 1264 }
1265 for (disp_def * cur = zdisplays; cur; cur = cur->next) {
1266 zdebugger_print(context, cur->format_char, cur->param);
1267 }
1053 uint8_t * after_pc = z80_decode(pc, &inst); 1268 uint8_t * after_pc = z80_decode(pc, &inst);
1054 z80_disasm(&inst, input_buf, address); 1269 z80_disasm(&inst, input_buf, address);
1055 printf("%X:\t%s\n", address, input_buf); 1270 printf("%X:\t%s\n", address, input_buf);
1056 uint16_t after = address + (after_pc-pc); 1271 uint16_t after = address + (after_pc-pc);
1057 int debugging = 1; 1272 int debugging = 1;
1100 break; 1315 break;
1101 case 'c': 1316 case 'c':
1102 puts("Continuing"); 1317 puts("Continuing");
1103 debugging = 0; 1318 debugging = 0;
1104 break; 1319 break;
1320 case 'd':
1321 if (input_buf[1] == 'i') {
1322 char format_char = 0;
1323 for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) {
1324 if (input_buf[i] == '/') {
1325 format_char = input_buf[i+1];
1326 break;
1327 }
1328 }
1329 param = find_param(input_buf);
1330 if (!param) {
1331 fputs("display command requires a parameter\n", stderr);
1332 break;
1333 }
1334 zdebugger_print(context, format_char, param);
1335 add_display(&zdisplays, &zdisp_index, format_char, param);
1336 } else if (input_buf[1] == 'e' || input_buf[1] == ' ') {
1337 param = find_param(input_buf);
1338 if (!param) {
1339 fputs("delete command requires a parameter\n", stderr);
1340 break;
1341 }
1342 if (param[0] >= '0' && param[0] <= '9') {
1343 value = atoi(param);
1344 this_bp = find_breakpoint_idx(&zbreakpoints, value);
1345 if (!*this_bp) {
1346 fprintf(stderr, "Breakpoint %d does not exist\n", value);
1347 break;
1348 }
1349 new_bp = *this_bp;
1350 zremove_breakpoint(context, new_bp->address);
1351 *this_bp = new_bp->next;
1352 free(new_bp);
1353 } else if (param[0] == 'd') {
1354 param = find_param(param);
1355 if (!param) {
1356 fputs("delete display command requires a parameter\n", stderr);
1357 break;
1358 }
1359 remove_display(&zdisplays, atoi(param));
1360 }
1361 }
1362 break;
1105 case 'n': 1363 case 'n':
1106 //TODO: Handle branch instructions 1364 //TODO: Handle branch instructions
1107 zinsert_breakpoint(context, after, (uint8_t *)zdebugger); 1365 zinsert_breakpoint(context, after, (uint8_t *)zdebugger);
1108 debugging = 0; 1366 debugging = 0;
1109 break; 1367 break;
1110 case 'p': 1368 case 'p':
1111 strcpy(format, "%s: %d\n");
1112 if (input_buf[1] == '/') {
1113 switch (input_buf[2])
1114 {
1115 case 'x':
1116 case 'X':
1117 case 'd':
1118 case 'c':
1119 format[5] = input_buf[2];
1120 break;
1121 default:
1122 fprintf(stderr, "Unrecognized format character: %c\n", input_buf[2]);
1123 }
1124 }
1125 param = find_param(input_buf); 1369 param = find_param(input_buf);
1126 if (!param) { 1370 if (!param) {
1127 fputs("p command requires a parameter\n", stderr); 1371 fputs("p command requires a parameter\n", stderr);
1128 break; 1372 break;
1129 } 1373 }
1130 switch (param[0]) 1374 zdebugger_print(context, input_buf[1] == '/' ? input_buf[2] : 0, param);
1131 {
1132 case 'a':
1133 if (param[1] == 'f') {
1134 if(param[2] == '\'') {
1135 value = context->alt_regs[Z80_A] << 8;
1136 value |= context->alt_flags[ZF_S] << 7;
1137 value |= context->alt_flags[ZF_Z] << 6;
1138 value |= context->alt_flags[ZF_H] << 4;
1139 value |= context->alt_flags[ZF_PV] << 2;
1140 value |= context->alt_flags[ZF_N] << 1;
1141 value |= context->alt_flags[ZF_C];
1142 } else {
1143 value = context->regs[Z80_A] << 8;
1144 value |= context->flags[ZF_S] << 7;
1145 value |= context->flags[ZF_Z] << 6;
1146 value |= context->flags[ZF_H] << 4;
1147 value |= context->flags[ZF_PV] << 2;
1148 value |= context->flags[ZF_N] << 1;
1149 value |= context->flags[ZF_C];
1150 }
1151 } else if(param[1] == '\'') {
1152 value = context->alt_regs[Z80_A];
1153 } else {
1154 value = context->regs[Z80_A];
1155 }
1156 break;
1157 case 'b':
1158 if (param[1] == 'c') {
1159 if(param[2] == '\'') {
1160 value = context->alt_regs[Z80_B] << 8;
1161 value |= context->alt_regs[Z80_C];
1162 } else {
1163 value = context->regs[Z80_B] << 8;
1164 value |= context->regs[Z80_C];
1165 }
1166 } else if(param[1] == '\'') {
1167 value = context->alt_regs[Z80_B];
1168 } else {
1169 value = context->regs[Z80_B];
1170 }
1171 break;
1172 case 'c':
1173 if(param[1] == '\'') {
1174 value = context->alt_regs[Z80_C];
1175 } else {
1176 value = context->regs[Z80_C];
1177 }
1178 break;
1179 case 'd':
1180 if (param[1] == 'e') {
1181 if(param[2] == '\'') {
1182 value = context->alt_regs[Z80_D] << 8;
1183 value |= context->alt_regs[Z80_E];
1184 } else {
1185 value = context->regs[Z80_D] << 8;
1186 value |= context->regs[Z80_E];
1187 }
1188 } else if(param[1] == '\'') {
1189 value = context->alt_regs[Z80_D];
1190 } else {
1191 value = context->regs[Z80_D];
1192 }
1193 break;
1194 case 'e':
1195 if(param[1] == '\'') {
1196 value = context->alt_regs[Z80_E];
1197 } else {
1198 value = context->regs[Z80_E];
1199 }
1200 break;
1201 case 'f':
1202 if(param[2] == '\'') {
1203 value = context->alt_flags[ZF_S] << 7;
1204 value |= context->alt_flags[ZF_Z] << 6;
1205 value |= context->alt_flags[ZF_H] << 4;
1206 value |= context->alt_flags[ZF_PV] << 2;
1207 value |= context->alt_flags[ZF_N] << 1;
1208 value |= context->alt_flags[ZF_C];
1209 } else {
1210 value = context->flags[ZF_S] << 7;
1211 value |= context->flags[ZF_Z] << 6;
1212 value |= context->flags[ZF_H] << 4;
1213 value |= context->flags[ZF_PV] << 2;
1214 value |= context->flags[ZF_N] << 1;
1215 value |= context->flags[ZF_C];
1216 }
1217 break;
1218 case 'h':
1219 if (param[1] == 'l') {
1220 if(param[2] == '\'') {
1221 value = context->alt_regs[Z80_H] << 8;
1222 value |= context->alt_regs[Z80_L];
1223 } else {
1224 value = context->regs[Z80_H] << 8;
1225 value |= context->regs[Z80_L];
1226 }
1227 } else if(param[1] == '\'') {
1228 value = context->alt_regs[Z80_H];
1229 } else {
1230 value = context->regs[Z80_H];
1231 }
1232 break;
1233 case 'l':
1234 if(param[1] == '\'') {
1235 value = context->alt_regs[Z80_L];
1236 } else {
1237 value = context->regs[Z80_L];
1238 }
1239 break;
1240 case 'i':
1241 if(param[1] == 'x') {
1242 if (param[2] == 'h') {
1243 value = context->regs[Z80_IXH];
1244 } else if(param[2] == 'l') {
1245 value = context->regs[Z80_IXL];
1246 } else {
1247 value = context->regs[Z80_IXH] << 8;
1248 value |= context->regs[Z80_IXL];
1249 }
1250 } else if(param[1] == 'y') {
1251 if (param[2] == 'h') {
1252 value = context->regs[Z80_IYH];
1253 } else if(param[2] == 'l') {
1254 value = context->regs[Z80_IYL];
1255 } else {
1256 value = context->regs[Z80_IYH] << 8;
1257 value |= context->regs[Z80_IYL];
1258 }
1259 } else {
1260 value = context->im;
1261 }
1262 break;
1263 case '0':
1264 if (param[1] == 'x') {
1265 uint16_t p_addr = strtol(param+2, NULL, 16);
1266 if (p_addr < 0x4000) {
1267 value = z80_ram[p_addr & 0x1FFF];
1268 }
1269 }
1270 break;
1271 }
1272 printf(format, param, value);
1273 break; 1375 break;
1274 case 'q': 1376 case 'q':
1275 puts("Quitting"); 1377 puts("Quitting");
1276 exit(0); 1378 exit(0);
1277 break; 1379 break;