comparison blastem.c @ 366:836585d389b8

Partial implementation of Z80 debugger
author Mike Pavone <pavone@retrodev.com>
date Fri, 31 May 2013 19:43:13 -0700
parents 62177cc39049
children c9d2a2371f5e
comparison
equal deleted inserted replaced
365:3ba3b6656fff 366:836585d389b8
971 uint32_t address; 971 uint32_t address;
972 uint32_t index; 972 uint32_t index;
973 } bp_def; 973 } bp_def;
974 974
975 bp_def * breakpoints = NULL; 975 bp_def * breakpoints = NULL;
976 bp_def * zbreakpoints = NULL;
976 uint32_t bp_index = 0; 977 uint32_t bp_index = 0;
978 uint32_t zbp_index = 0;
977 979
978 bp_def ** find_breakpoint(bp_def ** cur, uint32_t address) 980 bp_def ** find_breakpoint(bp_def ** cur, uint32_t address)
979 { 981 {
980 while (*cur) { 982 while (*cur) {
981 if ((*cur)->address == address) { 983 if ((*cur)->address == address) {
1017 return; 1019 return;
1018 } 1020 }
1019 } 1021 }
1020 } 1022 }
1021 1023
1022 m68k_context * debugger(m68k_context * context, uint32_t address) 1024 z80_context * zdebugger(z80_context * context, uint16_t address)
1023 { 1025 {
1024 static char last_cmd[1024]; 1026 static char last_cmd[1024];
1025 char input_buf[1024]; 1027 char input_buf[1024];
1026 static uint32_t branch_t; 1028 static uint16_t branch_t;
1027 static uint32_t branch_f; 1029 static uint16_t branch_f;
1028 m68kinst inst; 1030 z80inst inst;
1029 //probably not necessary, but let's play it safe
1030 address &= 0xFFFFFF;
1031 if (address == branch_t) {
1032 bp_def ** f_bp = find_breakpoint(&breakpoints, branch_f);
1033 if (!*f_bp) {
1034 remove_breakpoint(context, branch_f);
1035 }
1036 branch_t = branch_f = 0;
1037 } else if(address == branch_f) {
1038 bp_def ** t_bp = find_breakpoint(&breakpoints, branch_t);
1039 if (!*t_bp) {
1040 remove_breakpoint(context, branch_t);
1041 }
1042 branch_t = branch_f = 0;
1043 }
1044 //Check if this is a user set breakpoint, or just a temporary one 1031 //Check if this is a user set breakpoint, or just a temporary one
1045 bp_def ** this_bp = find_breakpoint(&breakpoints, address); 1032 bp_def ** this_bp = find_breakpoint(&zbreakpoints, address);
1046 if (*this_bp) { 1033 if (*this_bp) {
1047 printf("Breakpoint %d hit\n", (*this_bp)->index); 1034 printf("Z80 Breakpoint %d hit\n", (*this_bp)->index);
1048 } else { 1035 } else {
1049 remove_breakpoint(context, address); 1036 zremove_breakpoint(context, address);
1050 } 1037 }
1051 uint16_t * pc; 1038 uint8_t * pc;
1052 if (address < 0x400000) { 1039 if (address < 0x4000) {
1053 pc = cart + address/2; 1040 pc = z80_ram + (address & 0x1FFF);
1054 } else if(address > 0xE00000) { 1041 } else if (address >= 0x8000) {
1055 pc = ram + (address & 0xFFFF)/2; 1042 if (context->bank_reg < (0x400000 >> 15)) {
1043 fprintf(stderr, "Entered Z80 debugger in banked memory address %X, which is not yet supported\n", address);
1044 exit(1);
1045 } else {
1046 fprintf(stderr, "Entered Z80 debugger in banked memory address %X, but the bank is not pointed to a cartridge address\n", address);
1047 exit(1);
1048 }
1056 } else { 1049 } else {
1057 fprintf(stderr, "Entered debugger at address %X\n", address); 1050 fprintf(stderr, "Entered Z80 debugger at address %X\n", address);
1058 exit(1); 1051 exit(1);
1059 } 1052 }
1060 uint16_t * after_pc = m68k_decode(pc, &inst, address); 1053 uint8_t * after_pc = z80_decode(pc, &inst);
1061 m68k_disasm(&inst, input_buf); 1054 z80_disasm(&inst, input_buf, address);
1062 printf("%X: %s\n", address, input_buf); 1055 printf("%X:\t%s\n", address, input_buf);
1063 uint32_t after = address + (after_pc-pc)*2; 1056 uint16_t after = address + (after_pc-pc);
1064 int debugging = 1; 1057 int debugging = 1;
1065 while (debugging) { 1058 while(debugging) {
1066 fputs(">", stdout); 1059 fputs(">", stdout);
1067 if (!fgets(input_buf, sizeof(input_buf), stdin)) { 1060 if (!fgets(input_buf, sizeof(input_buf), stdin)) {
1068 fputs("fgets failed", stderr); 1061 fputs("fgets failed", stderr);
1069 break; 1062 break;
1070 } 1063 }
1079 char format[8]; 1072 char format[8];
1080 uint32_t value; 1073 uint32_t value;
1081 bp_def * new_bp; 1074 bp_def * new_bp;
1082 switch(input_buf[0]) 1075 switch(input_buf[0])
1083 { 1076 {
1084 case 'c': 1077 case 'a':
1085 puts("Continuing"); 1078 param = find_param(input_buf);
1086 debugging = 0; 1079 if (!param) {
1080 fputs("a command requires a parameter\n", stderr);
1081 break;
1082 }
1083 value = strtol(param, NULL, 16);
1084 zinsert_breakpoint(context, value, (uint8_t *)zdebugger);
1087 break; 1085 break;
1088 case 'b': 1086 case 'b':
1089 param = find_param(input_buf); 1087 param = find_param(input_buf);
1090 if (!param) { 1088 if (!param) {
1091 fputs("b command requires a parameter\n", stderr); 1089 fputs("b command requires a parameter\n", stderr);
1092 break; 1090 break;
1093 } 1091 }
1094 value = strtol(param, NULL, 16); 1092 value = strtol(param, NULL, 16);
1095 insert_breakpoint(context, value, (uint8_t *)debugger); 1093 zinsert_breakpoint(context, value, (uint8_t *)zdebugger);
1096 new_bp = malloc(sizeof(bp_def)); 1094 new_bp = malloc(sizeof(bp_def));
1097 new_bp->next = breakpoints; 1095 new_bp->next = zbreakpoints;
1098 new_bp->address = value; 1096 new_bp->address = value;
1099 new_bp->index = bp_index++; 1097 new_bp->index = zbp_index++;
1100 breakpoints = new_bp; 1098 zbreakpoints = new_bp;
1101 printf("Breakpoint %d set at %X\n", new_bp->index, value); 1099 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
1102 break; 1100 break;
1103 case 'a': 1101 case 'c':
1104 param = find_param(input_buf); 1102 puts("Continuing");
1105 if (!param) {
1106 fputs("a command requires a parameter\n", stderr);
1107 break;
1108 }
1109 value = strtol(param, NULL, 16);
1110 insert_breakpoint(context, value, (uint8_t *)debugger);
1111 debugging = 0; 1103 debugging = 0;
1112 break; 1104 break;
1113 case 'd': 1105 case 'n':
1114 param = find_param(input_buf); 1106 //TODO: Handle branch instructions
1115 if (!param) { 1107 zinsert_breakpoint(context, after, (uint8_t *)zdebugger);
1116 fputs("b command requires a parameter\n", stderr);
1117 break;
1118 }
1119 value = atoi(param);
1120 this_bp = find_breakpoint_idx(&breakpoints, value);
1121 if (!*this_bp) {
1122 fprintf(stderr, "Breakpoint %d does not exist\n", value);
1123 break;
1124 }
1125 new_bp = *this_bp;
1126 *this_bp = (*this_bp)->next;
1127 free(new_bp);
1128 break; 1108 break;
1129 case 'p': 1109 case 'p':
1130 strcpy(format, "%s: %d\n"); 1110 strcpy(format, "%s: %d\n");
1131 if (input_buf[1] == '/') { 1111 if (input_buf[1] == '/') {
1132 switch (input_buf[2]) 1112 switch (input_buf[2])
1144 param = find_param(input_buf); 1124 param = find_param(input_buf);
1145 if (!param) { 1125 if (!param) {
1146 fputs("p command requires a parameter\n", stderr); 1126 fputs("p command requires a parameter\n", stderr);
1147 break; 1127 break;
1148 } 1128 }
1129 switch (param[0])
1130 {
1131 case 'a':
1132 if (param[1] == 'f') {
1133 if(param[2] == '\'') {
1134 value = context->alt_regs[Z80_A] << 8;
1135 value |= context->alt_flags[ZF_S] << 7;
1136 value |= context->alt_flags[ZF_Z] << 6;
1137 value |= context->alt_flags[ZF_H] << 4;
1138 value |= context->alt_flags[ZF_PV] << 2;
1139 value |= context->alt_flags[ZF_N] << 1;
1140 value |= context->alt_flags[ZF_C];
1141 } else {
1142 value = context->regs[Z80_A] << 8;
1143 value |= context->flags[ZF_S] << 7;
1144 value |= context->flags[ZF_Z] << 6;
1145 value |= context->flags[ZF_H] << 4;
1146 value |= context->flags[ZF_PV] << 2;
1147 value |= context->flags[ZF_N] << 1;
1148 value |= context->flags[ZF_C];
1149 }
1150 } else if(param[1] == '\'') {
1151 value = context->alt_regs[Z80_A];
1152 } else {
1153 value = context->regs[Z80_A];
1154 }
1155 break;
1156 case 'b':
1157 if (param[1] == 'c') {
1158 if(param[2] == '\'') {
1159 value = context->alt_regs[Z80_B] << 8;
1160 value |= context->alt_regs[Z80_C];
1161 } else {
1162 value = context->regs[Z80_B] << 8;
1163 value |= context->regs[Z80_C];
1164 }
1165 } else if(param[1] == '\'') {
1166 value = context->alt_regs[Z80_B];
1167 } else {
1168 value = context->regs[Z80_B];
1169 }
1170 break;
1171 case 'c':
1172 if(param[1] == '\'') {
1173 value = context->alt_regs[Z80_C];
1174 } else {
1175 value = context->regs[Z80_C];
1176 }
1177 break;
1178 case 'd':
1179 if (param[1] == 'e') {
1180 if(param[2] == '\'') {
1181 value = context->alt_regs[Z80_D] << 8;
1182 value |= context->alt_regs[Z80_E];
1183 } else {
1184 value = context->regs[Z80_D] << 8;
1185 value |= context->regs[Z80_E];
1186 }
1187 } else if(param[1] == '\'') {
1188 value = context->alt_regs[Z80_D];
1189 } else {
1190 value = context->regs[Z80_D];
1191 }
1192 break;
1193 case 'e':
1194 if(param[1] == '\'') {
1195 value = context->alt_regs[Z80_E];
1196 } else {
1197 value = context->regs[Z80_E];
1198 }
1199 break;
1200 case 'f':
1201 if(param[2] == '\'') {
1202 value = context->alt_flags[ZF_S] << 7;
1203 value |= context->alt_flags[ZF_Z] << 6;
1204 value |= context->alt_flags[ZF_H] << 4;
1205 value |= context->alt_flags[ZF_PV] << 2;
1206 value |= context->alt_flags[ZF_N] << 1;
1207 value |= context->alt_flags[ZF_C];
1208 } else {
1209 value = context->flags[ZF_S] << 7;
1210 value |= context->flags[ZF_Z] << 6;
1211 value |= context->flags[ZF_H] << 4;
1212 value |= context->flags[ZF_PV] << 2;
1213 value |= context->flags[ZF_N] << 1;
1214 value |= context->flags[ZF_C];
1215 }
1216 break;
1217 case 'h':
1218 if (param[1] == 'l') {
1219 if(param[2] == '\'') {
1220 value = context->alt_regs[Z80_H] << 8;
1221 value |= context->alt_regs[Z80_L];
1222 } else {
1223 value = context->regs[Z80_H] << 8;
1224 value |= context->regs[Z80_L];
1225 }
1226 } else if(param[1] == '\'') {
1227 value = context->alt_regs[Z80_H];
1228 } else {
1229 value = context->regs[Z80_H];
1230 }
1231 break;
1232 case 'l':
1233 if(param[1] == '\'') {
1234 value = context->alt_regs[Z80_L];
1235 } else {
1236 value = context->regs[Z80_L];
1237 }
1238 break;
1239 case 'i':
1240 if(param[1] == 'x') {
1241 if (param[2] == 'h') {
1242 value = context->regs[Z80_IXH];
1243 } else if(param[2] == 'l') {
1244 value = context->regs[Z80_IXL];
1245 } else {
1246 value = context->regs[Z80_IXH] << 8;
1247 value |= context->regs[Z80_IXL];
1248 }
1249 } else if(param[1] == 'y') {
1250 if (param[2] == 'h') {
1251 value = context->regs[Z80_IYH];
1252 } else if(param[2] == 'l') {
1253 value = context->regs[Z80_IYL];
1254 } else {
1255 value = context->regs[Z80_IYH] << 8;
1256 value |= context->regs[Z80_IYL];
1257 }
1258 } else {
1259 value = context->im;
1260 }
1261 break;
1262 case '0':
1263 if (param[1] == 'x') {
1264 uint16_t p_addr = strtol(param+2, NULL, 16);
1265 if (p_addr < 0x4000) {
1266 value = z80_ram[p_addr & 0x1FFF];
1267 }
1268 }
1269 break;
1270 }
1271 printf(format, param, value);
1272 break;
1273 case 'q':
1274 puts("Quitting");
1275 exit(0);
1276 break;
1277 default:
1278 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf);
1279 break;
1280 }
1281 }
1282 return context;
1283 }
1284
1285 m68k_context * debugger(m68k_context * context, uint32_t address)
1286 {
1287 static char last_cmd[1024];
1288 char input_buf[1024];
1289 static uint32_t branch_t;
1290 static uint32_t branch_f;
1291 m68kinst inst;
1292 //probably not necessary, but let's play it safe
1293 address &= 0xFFFFFF;
1294 if (address == branch_t) {
1295 bp_def ** f_bp = find_breakpoint(&breakpoints, branch_f);
1296 if (!*f_bp) {
1297 remove_breakpoint(context, branch_f);
1298 }
1299 branch_t = branch_f = 0;
1300 } else if(address == branch_f) {
1301 bp_def ** t_bp = find_breakpoint(&breakpoints, branch_t);
1302 if (!*t_bp) {
1303 remove_breakpoint(context, branch_t);
1304 }
1305 branch_t = branch_f = 0;
1306 }
1307 //Check if this is a user set breakpoint, or just a temporary one
1308 bp_def ** this_bp = find_breakpoint(&breakpoints, address);
1309 if (*this_bp) {
1310 printf("68K Breakpoint %d hit\n", (*this_bp)->index);
1311 } else {
1312 remove_breakpoint(context, address);
1313 }
1314 uint16_t * pc;
1315 if (address < 0x400000) {
1316 pc = cart + address/2;
1317 } else if(address > 0xE00000) {
1318 pc = ram + (address & 0xFFFF)/2;
1319 } else {
1320 fprintf(stderr, "Entered 68K debugger at address %X\n", address);
1321 exit(1);
1322 }
1323 uint16_t * after_pc = m68k_decode(pc, &inst, address);
1324 m68k_disasm(&inst, input_buf);
1325 printf("%X: %s\n", address, input_buf);
1326 uint32_t after = address + (after_pc-pc)*2;
1327 int debugging = 1;
1328 while (debugging) {
1329 fputs(">", stdout);
1330 if (!fgets(input_buf, sizeof(input_buf), stdin)) {
1331 fputs("fgets failed", stderr);
1332 break;
1333 }
1334 strip_nl(input_buf);
1335 //hitting enter repeats last command
1336 if (input_buf[0]) {
1337 strcpy(last_cmd, input_buf);
1338 } else {
1339 strcpy(input_buf, last_cmd);
1340 }
1341 char * param;
1342 char format[8];
1343 uint32_t value;
1344 bp_def * new_bp;
1345 switch(input_buf[0])
1346 {
1347 case 'c':
1348 puts("Continuing");
1349 debugging = 0;
1350 break;
1351 case 'b':
1352 param = find_param(input_buf);
1353 if (!param) {
1354 fputs("b command requires a parameter\n", stderr);
1355 break;
1356 }
1357 value = strtol(param, NULL, 16);
1358 insert_breakpoint(context, value, (uint8_t *)debugger);
1359 new_bp = malloc(sizeof(bp_def));
1360 new_bp->next = breakpoints;
1361 new_bp->address = value;
1362 new_bp->index = bp_index++;
1363 breakpoints = new_bp;
1364 printf("68K Breakpoint %d set at %X\n", new_bp->index, value);
1365 break;
1366 case 'a':
1367 param = find_param(input_buf);
1368 if (!param) {
1369 fputs("a command requires a parameter\n", stderr);
1370 break;
1371 }
1372 value = strtol(param, NULL, 16);
1373 insert_breakpoint(context, value, (uint8_t *)debugger);
1374 debugging = 0;
1375 break;
1376 case 'd':
1377 param = find_param(input_buf);
1378 if (!param) {
1379 fputs("b command requires a parameter\n", stderr);
1380 break;
1381 }
1382 value = atoi(param);
1383 this_bp = find_breakpoint_idx(&breakpoints, value);
1384 if (!*this_bp) {
1385 fprintf(stderr, "Breakpoint %d does not exist\n", value);
1386 break;
1387 }
1388 new_bp = *this_bp;
1389 *this_bp = (*this_bp)->next;
1390 free(new_bp);
1391 break;
1392 case 'p':
1393 strcpy(format, "%s: %d\n");
1394 if (input_buf[1] == '/') {
1395 switch (input_buf[2])
1396 {
1397 case 'x':
1398 case 'X':
1399 case 'd':
1400 case 'c':
1401 format[5] = input_buf[2];
1402 break;
1403 default:
1404 fprintf(stderr, "Unrecognized format character: %c\n", input_buf[2]);
1405 }
1406 }
1407 param = find_param(input_buf);
1408 if (!param) {
1409 fputs("p command requires a parameter\n", stderr);
1410 break;
1411 }
1149 if (param[0] == 'd' && param[1] >= '0' && param[1] <= '7') { 1412 if (param[0] == 'd' && param[1] >= '0' && param[1] <= '7') {
1150 value = context->dregs[param[1]-'0']; 1413 value = context->dregs[param[1]-'0'];
1151 } else if (param[0] == 'a' && param[1] >= '0' && param[1] <= '7') { 1414 } else if (param[0] == 'a' && param[1] >= '0' && param[1] <= '7') {
1152 value = context->aregs[param[1]-'0']; 1415 value = context->aregs[param[1]-'0'];
1153 } else if (param[0] == 'S' && param[1] == 'R') { 1416 } else if (param[0] == 'S' && param[1] == 'R') {
1190 case 's': 1453 case 's':
1191 vdp_print_sprite_table(gen->vdp); 1454 vdp_print_sprite_table(gen->vdp);
1192 break; 1455 break;
1193 case 'r': 1456 case 'r':
1194 vdp_print_reg_explain(gen->vdp); 1457 vdp_print_reg_explain(gen->vdp);
1458 break;
1459 }
1460 break;
1461 }
1462 case 'z': {
1463 genesis_context * gen = context->system;
1464 //Z80 debug commands
1465 switch(input_buf[1])
1466 {
1467 case 'b':
1468 param = find_param(input_buf);
1469 if (!param) {
1470 fputs("zb command requires a parameter\n", stderr);
1471 break;
1472 }
1473 value = strtol(param, NULL, 16);
1474 zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger);
1475 new_bp = malloc(sizeof(bp_def));
1476 new_bp->next = zbreakpoints;
1477 new_bp->address = value;
1478 new_bp->index = zbp_index++;
1479 zbreakpoints = new_bp;
1480 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value);
1195 break; 1481 break;
1196 } 1482 }
1197 break; 1483 break;
1198 } 1484 }
1199 case 'q': 1485 case 'q':