Mercurial > repos > blastem
comparison debug.c @ 2188:e17d99c96c89
Make blocks an explicitly supported concept in the debugger rather than a one-off for the commands command
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 20 Aug 2022 11:40:41 -0700 |
parents | d0129f19ca52 |
children | 6b33ce6bc740 |
comparison
equal
deleted
inserted
replaced
2187:d0129f19ca52 | 2188:e17d99c96c89 |
---|---|
901 command_arg *args = NULL; | 901 command_arg *args = NULL; |
902 if (*cur && *cur != '\n') { | 902 if (*cur && *cur != '\n') { |
903 ++cur; | 903 ++cur; |
904 } | 904 } |
905 text = cur; | 905 text = cur; |
906 if (def->raw_impl) { | 906 if (def->raw_args) { |
907 while (*cur && *cur != '\n') | 907 while (*cur && *cur != '\n') |
908 { | 908 { |
909 ++cur; | 909 ++cur; |
910 } | 910 } |
911 char *raw_param = NULL; | 911 char *raw_param = NULL; |
975 cleanup_name: | 975 cleanup_name: |
976 free(name); | 976 free(name); |
977 return ret; | 977 return ret; |
978 } | 978 } |
979 | 979 |
980 static void free_parsed_command(parsed_command *cmd); | |
981 static void free_command_block(command_block *block) | |
982 { | |
983 for (int i = 0; i < block->num_commands; i++) | |
984 { | |
985 free_parsed_command(block->commands + i); | |
986 } | |
987 free(block->commands); | |
988 } | |
989 | |
980 static void free_parsed_command(parsed_command *cmd) | 990 static void free_parsed_command(parsed_command *cmd) |
981 { | 991 { |
982 free(cmd->format); | 992 free(cmd->format); |
983 free(cmd->raw); | 993 free(cmd->raw); |
984 for (int i = 0; i < cmd->num_args; i++) | 994 for (int i = 0; i < cmd->num_args; i++) |
985 { | 995 { |
986 free(cmd->args[i].raw); | 996 free(cmd->args[i].raw); |
987 free_expr(cmd->args[i].parsed); | 997 free_expr(cmd->args[i].parsed); |
988 } | 998 } |
999 free_command_block(&cmd->block); | |
1000 free_command_block(&cmd->else_block); | |
989 free(cmd->args); | 1001 free(cmd->args); |
990 } | 1002 } |
991 | 1003 |
992 static uint8_t cmd_quit(debug_root *root, char *format, int num_args, command_arg *args) | 1004 enum { |
1005 READ_FAILED = 0, | |
1006 NORMAL, | |
1007 EMPTY, | |
1008 ELSE, | |
1009 END | |
1010 }; | |
1011 | |
1012 static uint8_t read_parse_command(debug_root *root, parsed_command *out, int indent_level) | |
1013 { | |
1014 ++indent_level; | |
1015 for (int i = 0; i < indent_level; i++) | |
1016 { | |
1017 putchar('>'); | |
1018 } | |
1019 putchar(' '); | |
1020 fflush(stdout); | |
1021 #ifdef _WIN32 | |
1022 #define wait 0 | |
1023 #else | |
1024 int wait = 1; | |
1025 fd_set read_fds; | |
1026 FD_ZERO(&read_fds); | |
1027 struct timeval timeout; | |
1028 #endif | |
1029 do { | |
1030 process_events(); | |
1031 #ifndef _WIN32 | |
1032 timeout.tv_sec = 0; | |
1033 timeout.tv_usec = 16667; | |
1034 FD_SET(fileno(stdin), &read_fds); | |
1035 if(select(fileno(stdin) + 1, &read_fds, NULL, NULL, &timeout) >= 1) { | |
1036 wait = 0; | |
1037 } | |
1038 #endif | |
1039 } while (wait); | |
1040 | |
1041 char input_buf[1024]; | |
1042 if (!fgets(input_buf, sizeof(input_buf), stdin)) { | |
1043 fputs("fgets failed", stderr); | |
1044 return READ_FAILED; | |
1045 } | |
1046 char *stripped = strip_ws(input_buf); | |
1047 if (!stripped[0]) { | |
1048 return EMPTY; | |
1049 } | |
1050 if (indent_level > 1) { | |
1051 if (!strcmp(stripped, "else")) { | |
1052 return ELSE; | |
1053 } | |
1054 if (!strcmp(stripped, "end")) { | |
1055 return END; | |
1056 } | |
1057 } | |
1058 if (parse_command(root, input_buf, out)) { | |
1059 if (!out->def->has_block) { | |
1060 return NORMAL; | |
1061 } | |
1062 int command_storage = 4; | |
1063 command_block *block = &out->block; | |
1064 block->commands = calloc(command_storage, sizeof(parsed_command)); | |
1065 block->num_commands = 0; | |
1066 for (;;) | |
1067 { | |
1068 if (block->num_commands == command_storage) { | |
1069 command_storage *= 2; | |
1070 block->commands = realloc(block->commands, command_storage * sizeof(parsed_command)); | |
1071 } | |
1072 switch (read_parse_command(root, block->commands + block->num_commands, indent_level)) | |
1073 { | |
1074 case READ_FAILED: | |
1075 return READ_FAILED; | |
1076 case NORMAL: | |
1077 block->num_commands++; | |
1078 break; | |
1079 case END: | |
1080 return NORMAL; | |
1081 case ELSE: | |
1082 if (block == &out->else_block) { | |
1083 fprintf(stderr, "Too many else blocks for command %s\n", out->def->names[0]); | |
1084 return READ_FAILED; | |
1085 } | |
1086 if (!out->def->accepts_else) { | |
1087 fprintf(stderr, "Command %s does not take an else block\n", out->def->names[0]); | |
1088 return READ_FAILED; | |
1089 } | |
1090 block = &out->else_block; | |
1091 block->commands = calloc(command_storage, sizeof(parsed_command)); | |
1092 block->num_commands = 0; | |
1093 break; | |
1094 } | |
1095 } | |
1096 } | |
1097 return READ_FAILED; | |
1098 } | |
1099 | |
1100 static uint8_t run_command(debug_root *root, parsed_command *cmd) | |
1101 { | |
1102 if (!cmd->def->raw_args && !cmd->def->skip_eval) { | |
1103 for (int i = 0; i < cmd->num_args; i++) | |
1104 { | |
1105 if (!eval_expr(root, cmd->args[i].parsed, &cmd->args[i].value)) { | |
1106 fprintf(stderr, "Failed to eval %s\n", cmd->args[i].raw); | |
1107 return 1; | |
1108 } | |
1109 } | |
1110 } | |
1111 return cmd->def->impl(root, cmd); | |
1112 } | |
1113 | |
1114 static void debugger_repl(debug_root *root) | |
1115 { | |
1116 | |
1117 int debugging = 1; | |
1118 parsed_command cmds[2] = {0}; | |
1119 int cur = 0; | |
1120 uint8_t has_last = 0; | |
1121 while(debugging) { | |
1122 switch (read_parse_command(root, cmds + cur, 0)) | |
1123 { | |
1124 case NORMAL: | |
1125 debugging = run_command(root, cmds + cur); | |
1126 if (debugging && has_last) { | |
1127 cur = !cur; | |
1128 free_parsed_command(cmds + cur); | |
1129 memset(cmds + cur, 0, sizeof(cmds[cur])); | |
1130 } | |
1131 break; | |
1132 case EMPTY: | |
1133 debugging = run_command(root, cmds + !cur); | |
1134 break; | |
1135 } | |
1136 } | |
1137 free_parsed_command(cmds); | |
1138 free_parsed_command(cmds + 1); | |
1139 } | |
1140 | |
1141 static uint8_t cmd_quit(debug_root *root, parsed_command *cmd) | |
993 { | 1142 { |
994 exit(0); | 1143 exit(0); |
995 } | 1144 } |
996 | 1145 |
997 typedef struct { | 1146 typedef struct { |
1082 fputs(extra_desc, stdout); | 1231 fputs(extra_desc, stdout); |
1083 } | 1232 } |
1084 putchar('\n'); | 1233 putchar('\n'); |
1085 } | 1234 } |
1086 | 1235 |
1087 static uint8_t cmd_help(debug_root *root, char *format, char *param) | 1236 static uint8_t cmd_help(debug_root *root, parsed_command *cmd) |
1088 { | 1237 { |
1089 help_state state = {0,0}; | 1238 help_state state = {0,0}; |
1090 tern_foreach(root->commands, help_first_pass, &state); | 1239 tern_foreach(root->commands, help_first_pass, &state); |
1091 tern_foreach(root->commands, help_reset_visited, &state); | 1240 tern_foreach(root->commands, help_reset_visited, &state); |
1092 tern_foreach(root->commands, help_second_pass, &state); | 1241 tern_foreach(root->commands, help_second_pass, &state); |
1093 tern_foreach(root->commands, help_reset_visited, &state); | 1242 tern_foreach(root->commands, help_reset_visited, &state); |
1094 return 1; | 1243 return 1; |
1095 } | 1244 } |
1096 | 1245 |
1097 static uint8_t cmd_continue(debug_root *root, char *format, int num_args, command_arg *args) | 1246 static uint8_t cmd_continue(debug_root *root, parsed_command *cmd) |
1098 { | 1247 { |
1099 return 0; | 1248 return 0; |
1100 } | 1249 } |
1101 | 1250 |
1102 static uint8_t cmd_print(debug_root *root, char *format, int num_args, command_arg *args) | 1251 static void make_format_str(char *format_str, char *format) |
1103 { | 1252 { |
1104 char format_str[8]; | |
1105 strcpy(format_str, "%s: %d\n"); | 1253 strcpy(format_str, "%s: %d\n"); |
1106 if (format) { | 1254 if (format) { |
1107 switch (format[0]) | 1255 switch (format[0]) |
1108 { | 1256 { |
1109 case 'x': | 1257 case 'x': |
1115 break; | 1263 break; |
1116 default: | 1264 default: |
1117 fprintf(stderr, "Unrecognized format character: %c\n", format[0]); | 1265 fprintf(stderr, "Unrecognized format character: %c\n", format[0]); |
1118 } | 1266 } |
1119 } | 1267 } |
1120 for (int i = 0; i < num_args; i++) | 1268 } |
1121 { | 1269 |
1122 if (format && format[0] == 's') { | 1270 static void do_print(debug_root *root, char *format_str, char *raw, uint32_t value) |
1123 char tmp[128]; | 1271 { |
1124 int j; | 1272 if (format_str[5] == 's') { |
1125 uint32_t addr = args[i].value; | 1273 char tmp[128]; |
1126 for (j = 0; j < sizeof(tmp)-1; j++, addr++) | 1274 int j; |
1127 { | 1275 uint32_t addr = value; |
1128 uint32_t tmp_addr = addr; | 1276 for (j = 0; j < sizeof(tmp)-1; j++, addr++) |
1129 root->read_mem(root, &tmp_addr, 'b'); | 1277 { |
1130 char c = tmp_addr; | 1278 uint32_t tmp_addr = addr; |
1131 if (c < 0x20 || c > 0x7F) { | 1279 root->read_mem(root, &tmp_addr, 'b'); |
1132 break; | 1280 char c = tmp_addr; |
1133 } | 1281 if (c < 0x20 || c > 0x7F) { |
1134 tmp[j] = c; | 1282 break; |
1135 } | 1283 } |
1136 tmp[j] = 0; | 1284 tmp[j] = c; |
1137 printf(format_str, args[i].raw, tmp); | 1285 } |
1138 } else { | 1286 tmp[j] = 0; |
1139 printf(format_str, args[i].raw, args[i].value); | 1287 printf(format_str, raw, tmp); |
1140 } | 1288 } else { |
1289 printf(format_str, raw, value); | |
1290 } | |
1291 } | |
1292 | |
1293 static uint8_t cmd_print(debug_root *root, parsed_command *cmd) | |
1294 { | |
1295 char format_str[8]; | |
1296 make_format_str(format_str, cmd->format); | |
1297 for (int i = 0; i < cmd->num_args; i++) | |
1298 { | |
1299 do_print(root, format_str, cmd->args[i].raw, cmd->args[i].value); | |
1141 } | 1300 } |
1142 return 1; | 1301 return 1; |
1143 } | 1302 } |
1144 | 1303 |
1145 static uint8_t cmd_printf(debug_root *root, char *format, char *param) | 1304 static uint8_t cmd_printf(debug_root *root, parsed_command *cmd) |
1146 { | 1305 { |
1306 char *param = cmd->raw; | |
1147 if (!param) { | 1307 if (!param) { |
1148 fputs("printf requires at least one parameter\n", stderr); | 1308 fputs("printf requires at least one parameter\n", stderr); |
1149 return 1; | 1309 return 1; |
1150 } | 1310 } |
1151 while (isblank(*param)) | 1311 while (isblank(*param)) |
1243 } | 1403 } |
1244 } | 1404 } |
1245 return 1; | 1405 return 1; |
1246 } | 1406 } |
1247 | 1407 |
1248 static uint8_t cmd_display(debug_root *root, char *format, int num_args, command_arg *args) | 1408 static uint8_t cmd_display(debug_root *root, parsed_command *cmd) |
1249 { | 1409 { |
1250 cmd_print(root, format, num_args, args); | 1410 cmd_print(root, cmd); |
1251 disp_def *ndisp = calloc(1, sizeof(*ndisp)); | 1411 disp_def *ndisp = calloc(1, sizeof(*ndisp)); |
1252 ndisp->next = root->displays; | 1412 ndisp->next = root->displays; |
1253 ndisp->index = root->disp_index++; | 1413 ndisp->index = root->disp_index++; |
1254 ndisp->format = format ? strdup(format) : NULL; | 1414 ndisp->format = cmd->format ? strdup(cmd->format) : NULL; |
1255 ndisp->num_args = num_args; | 1415 ndisp->num_args = cmd->num_args; |
1256 ndisp->args = calloc(num_args, sizeof(command_arg)); | 1416 ndisp->args = cmd->args; |
1257 memcpy(ndisp->args, args, num_args * sizeof(command_arg)); | 1417 cmd->args = NULL; |
1258 memset(args, 0, num_args * sizeof(command_arg)); | 1418 cmd->num_args = 0; |
1259 root->displays = ndisp; | 1419 root->displays = ndisp; |
1260 printf("Added display %d\n", ndisp->index); | 1420 printf("Added display %d\n", ndisp->index); |
1261 return 1; | 1421 return 1; |
1262 } | 1422 } |
1263 | 1423 |
1264 static uint8_t cmd_delete_display(debug_root *root, char *format, int num_args, command_arg *args) | 1424 static uint8_t cmd_delete_display(debug_root *root, parsed_command *cmd) |
1265 { | 1425 { |
1266 disp_def **cur = &root->displays; | 1426 disp_def **cur = &root->displays; |
1267 while (*cur) | 1427 while (*cur) |
1268 { | 1428 { |
1269 if ((*cur)->index == args[0].value) { | 1429 if ((*cur)->index == cmd->args[0].value) { |
1270 disp_def *del_disp = *cur; | 1430 disp_def *del_disp = *cur; |
1271 *cur = del_disp->next; | 1431 *cur = del_disp->next; |
1272 free(del_disp->format); | 1432 free(del_disp->format); |
1273 for (int i = 0; i < del_disp->num_args; i++) | 1433 for (int i = 0; i < del_disp->num_args; i++) |
1274 { | 1434 { |
1283 } | 1443 } |
1284 } | 1444 } |
1285 return 1; | 1445 return 1; |
1286 } | 1446 } |
1287 | 1447 |
1288 static uint8_t cmd_softreset(debug_root *root, char *format, int num_args, command_arg *args) | 1448 static uint8_t cmd_softreset(debug_root *root, parsed_command *cmd) |
1289 { | 1449 { |
1290 if (current_system->soft_reset) { | 1450 if (current_system->soft_reset) { |
1291 current_system->soft_reset(current_system); | 1451 current_system->soft_reset(current_system); |
1292 return 0; | 1452 return 0; |
1293 } else { | 1453 } else { |
1294 fputs("Current system does not support soft reset", stderr); | 1454 fputs("Current system does not support soft reset", stderr); |
1295 return 1; | 1455 return 1; |
1296 } | 1456 } |
1297 } | 1457 } |
1298 | 1458 |
1299 static uint8_t cmd_command(debug_root *root, char *format, int num_args, command_arg *args) | 1459 static uint8_t cmd_command(debug_root *root, parsed_command *cmd) |
1300 { | 1460 { |
1301 bp_def **target = find_breakpoint_idx(&root->breakpoints, args[0].value); | 1461 bp_def **target = find_breakpoint_idx(&root->breakpoints, cmd->args[0].value); |
1302 if (!target) { | 1462 if (!target) { |
1303 fprintf(stderr, "Breakpoint %d does not exist!\n", args[0].value); | 1463 fprintf(stderr, "Breakpoint %d does not exist!\n", cmd->args[0].value); |
1304 return 1; | 1464 return 1; |
1305 } | 1465 } |
1306 printf("Enter commands for breakpoing %d, type end when done\n", args[0].value); | |
1307 char cmd_buf[1024]; | |
1308 char *commands = NULL; | |
1309 uint32_t cmd_storage = 4; | |
1310 for (uint32_t i = 0; i < (*target)->num_commands; i++) | 1466 for (uint32_t i = 0; i < (*target)->num_commands; i++) |
1311 { | 1467 { |
1312 free_parsed_command((*target)->commands + i); | 1468 free_parsed_command((*target)->commands + i); |
1313 } | 1469 } |
1314 free((*target)->commands); | 1470 free((*target)->commands); |
1315 (*target)->commands = calloc(cmd_storage, sizeof(parsed_command)); | 1471 (*target)->commands = cmd->block.commands; |
1316 for (;;) | 1472 (*target)->num_commands = cmd->block.num_commands; |
1317 { | 1473 cmd->block.commands = NULL; |
1318 fputs(">>", stdout); | 1474 cmd->block.num_commands = 0; |
1319 fflush(stdout); | 1475 return 1; |
1320 fgets(cmd_buf, sizeof(cmd_buf), stdin); | |
1321 if (!strcmp(cmd_buf, "end\n")) { | |
1322 return 1; | |
1323 } else { | |
1324 if ((*target)->num_commands == cmd_storage) { | |
1325 cmd_storage *= 2; | |
1326 (*target)->commands = realloc((*target)->commands, cmd_storage * sizeof(parsed_command)); | |
1327 } | |
1328 if (parse_command(root, cmd_buf, (*target)->commands + (*target)->num_commands)) { | |
1329 ++(*target)->num_commands; | |
1330 } | |
1331 } | |
1332 } | |
1333 } | 1476 } |
1334 | 1477 |
1335 const char *expr_type_names[] = { | 1478 const char *expr_type_names[] = { |
1336 "EXPR_NONE", | 1479 "EXPR_NONE", |
1337 "EXPR_SCALAR", | 1480 "EXPR_SCALAR", |
1339 "EXPR_BINARY", | 1482 "EXPR_BINARY", |
1340 "EXPR_SIZE", | 1483 "EXPR_SIZE", |
1341 "EXPR_MEM" | 1484 "EXPR_MEM" |
1342 }; | 1485 }; |
1343 | 1486 |
1344 static uint8_t run_command(debug_root *root, parsed_command *cmd) | 1487 static uint8_t cmd_set(debug_root *root, parsed_command *cmd) |
1345 { | |
1346 if (cmd->def->raw_impl) { | |
1347 return cmd->def->raw_impl(root, cmd->format, cmd->raw); | |
1348 } else { | |
1349 for (int i = 0; i < cmd->num_args; i++) | |
1350 { | |
1351 if (!eval_expr(root, cmd->args[i].parsed, &cmd->args[i].value)) { | |
1352 fprintf(stderr, "Failed to eval %s\n", cmd->args[i].raw); | |
1353 return 1; | |
1354 } | |
1355 } | |
1356 return cmd->def->impl(root, cmd->format, cmd->num_args, cmd->args); | |
1357 } | |
1358 } | |
1359 | |
1360 static uint8_t cmd_set(debug_root *root, char *format, int num_args, command_arg *args) | |
1361 { | 1488 { |
1362 char *name = NULL; | 1489 char *name = NULL; |
1363 char size = 0; | 1490 char size = 0; |
1364 uint32_t address; | 1491 uint32_t address; |
1365 switch (args[0].parsed->type) | 1492 switch (cmd->args[0].parsed->type) |
1366 { | 1493 { |
1367 case EXPR_SCALAR: | 1494 case EXPR_SCALAR: |
1368 if (args[0].parsed->op.type == TOKEN_NAME) { | 1495 if (cmd->args[0].parsed->op.type == TOKEN_NAME) { |
1369 name = args[0].parsed->op.v.str; | 1496 name = cmd->args[0].parsed->op.v.str; |
1370 } else { | 1497 } else { |
1371 fputs("First argument to set must be a name or memory expression, not a number", stderr); | 1498 fputs("First argument to set must be a name or memory expression, not a number", stderr); |
1372 return 1; | 1499 return 1; |
1373 } | 1500 } |
1374 break; | 1501 break; |
1375 case EXPR_SIZE: | 1502 case EXPR_SIZE: |
1376 size = args[0].parsed->op.v.op[0]; | 1503 size = cmd->args[0].parsed->op.v.op[0]; |
1377 if (args[0].parsed->left->op.type == TOKEN_NAME) { | 1504 if (cmd->args[0].parsed->left->op.type == TOKEN_NAME) { |
1378 name = args[0].parsed->left->op.v.str; | 1505 name = cmd->args[0].parsed->left->op.v.str; |
1379 } else { | 1506 } else { |
1380 fputs("First argument to set must be a name or memory expression, not a number", stderr); | 1507 fputs("First argument to set must be a name or memory expression, not a number", stderr); |
1381 return 1; | 1508 return 1; |
1382 } | 1509 } |
1383 break; | 1510 break; |
1384 case EXPR_MEM: | 1511 case EXPR_MEM: |
1385 size = args[0].parsed->op.v.op[0]; | 1512 size = cmd->args[0].parsed->op.v.op[0]; |
1386 if (!eval_expr(root, args[0].parsed->left, &address)) { | 1513 if (!eval_expr(root, cmd->args[0].parsed->left, &address)) { |
1387 fprintf(stderr, "Failed to eval %s\n", args[0].raw); | 1514 fprintf(stderr, "Failed to eval %s\n", cmd->args[0].raw); |
1388 return 1; | 1515 return 1; |
1389 } | 1516 } |
1390 break; | 1517 break; |
1391 default: | 1518 default: |
1392 fprintf(stderr, "First argument to set must be a name or memory expression, got %s\n", expr_type_names[args[0].parsed->type]); | 1519 fprintf(stderr, "First argument to set must be a name or memory expression, got %s\n", expr_type_names[cmd->args[0].parsed->type]); |
1393 return 1; | 1520 return 1; |
1394 } | 1521 } |
1395 if (!eval_expr(root, args[1].parsed, &args[1].value)) { | 1522 if (!eval_expr(root, cmd->args[1].parsed, &cmd->args[1].value)) { |
1396 fprintf(stderr, "Failed to eval %s\n", args[1].raw); | 1523 fprintf(stderr, "Failed to eval %s\n", cmd->args[1].raw); |
1397 return 1; | 1524 return 1; |
1398 } | 1525 } |
1399 uint32_t value = args[1].value; | 1526 uint32_t value = cmd->args[1].value; |
1400 if (name && size && size != 'l') { | 1527 if (name && size && size != 'l') { |
1401 uint32_t old; | 1528 uint32_t old; |
1402 if (!root->resolve(root, name, &old)) { | 1529 if (!root->resolve(root, name, &old)) { |
1403 fprintf(stderr, "Failed to eval %s\n", name); | 1530 fprintf(stderr, "Failed to eval %s\n", name); |
1404 return 1; | 1531 return 1; |
1421 fprintf(stderr, "Failed to write to address %X\n", address); | 1548 fprintf(stderr, "Failed to write to address %X\n", address); |
1422 } | 1549 } |
1423 return 1; | 1550 return 1; |
1424 } | 1551 } |
1425 | 1552 |
1426 static uint8_t cmd_frames(debug_root *root, char *format, int num_args, command_arg *args) | 1553 static uint8_t cmd_frames(debug_root *root, parsed_command *cmd) |
1427 { | 1554 { |
1428 current_system->enter_debugger_frames = args[0].value; | 1555 current_system->enter_debugger_frames = cmd->args[0].value; |
1429 return 0; | 1556 return 0; |
1430 } | 1557 } |
1431 | 1558 |
1432 static uint8_t cmd_bindup(debug_root *root, char *format, char *param) | 1559 static uint8_t cmd_bindup(debug_root *root, parsed_command *cmd) |
1433 { | 1560 { |
1434 if (!bind_up(param)) { | 1561 if (!bind_up(cmd->raw)) { |
1435 fprintf(stderr, "%s is not a valid binding name\n", param); | 1562 fprintf(stderr, "%s is not a valid binding name\n", cmd->raw); |
1436 } | 1563 } |
1437 return 1; | 1564 return 1; |
1438 } | 1565 } |
1439 | 1566 |
1440 static uint8_t cmd_binddown(debug_root *root, char *format, char *param) | 1567 static uint8_t cmd_binddown(debug_root *root, parsed_command *cmd) |
1441 { | 1568 { |
1442 if (!bind_down(param)) { | 1569 if (!bind_down(cmd->raw)) { |
1443 fprintf(stderr, "%s is not a valid binding name\n", param); | 1570 fprintf(stderr, "%s is not a valid binding name\n", cmd->raw); |
1444 } | 1571 } |
1445 return 1; | 1572 return 1; |
1446 } | 1573 } |
1447 | 1574 |
1448 static uint8_t cmd_condition(debug_root *root, char *format, int num_args, command_arg *args) | 1575 static uint8_t cmd_condition(debug_root *root, parsed_command *cmd) |
1449 { | 1576 { |
1450 if (!eval_expr(root, args[0].parsed, &args[0].value)) { | 1577 if (!eval_expr(root, cmd->args[0].parsed, &cmd->args[0].value)) { |
1451 fprintf(stderr, "Failed to evaluate breakpoint number: %s\n", args[0].raw); | 1578 fprintf(stderr, "Failed to evaluate breakpoint number: %s\n", cmd->args[0].raw); |
1452 return 1; | 1579 return 1; |
1453 } | 1580 } |
1454 bp_def **target = find_breakpoint_idx(&root->breakpoints, args[0].value); | 1581 bp_def **target = find_breakpoint_idx(&root->breakpoints, cmd->args[0].value); |
1455 if (!*target) { | 1582 if (!*target) { |
1456 fprintf(stderr, "Failed to find breakpoint %u\n", args[0].value); | 1583 fprintf(stderr, "Failed to find breakpoint %u\n", cmd->args[0].value); |
1457 return 1; | 1584 return 1; |
1458 } | 1585 } |
1459 free_expr((*target)->condition); | 1586 free_expr((*target)->condition); |
1460 if (num_args > 1 && args[1].parsed) { | 1587 if (cmd->num_args > 1 && cmd->args[1].parsed) { |
1461 (*target)->condition = args[1].parsed; | 1588 (*target)->condition = cmd->args[1].parsed; |
1462 args[1].parsed = NULL; | 1589 cmd->args[1].parsed = NULL; |
1463 } else { | 1590 } else { |
1464 (*target)->condition = NULL; | 1591 (*target)->condition = NULL; |
1465 } | 1592 } |
1466 return 1; | 1593 return 1; |
1467 } | 1594 } |
1468 | 1595 |
1469 static uint8_t cmd_delete_m68k(debug_root *root, char *format, int num_args, command_arg *args) | 1596 static uint8_t cmd_delete_m68k(debug_root *root, parsed_command *cmd) |
1470 { | 1597 { |
1471 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, args[0].value); | 1598 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, cmd->args[0].value); |
1472 if (!*this_bp) { | 1599 if (!*this_bp) { |
1473 fprintf(stderr, "Breakpoint %d does not exist\n", args[0].value); | 1600 fprintf(stderr, "Breakpoint %d does not exist\n", cmd->args[0].value); |
1474 return 1; | 1601 return 1; |
1475 } | 1602 } |
1476 bp_def *tmp = *this_bp; | 1603 bp_def *tmp = *this_bp; |
1477 remove_breakpoint(root->cpu_context, tmp->address); | 1604 remove_breakpoint(root->cpu_context, tmp->address); |
1478 *this_bp = (*this_bp)->next; | 1605 *this_bp = (*this_bp)->next; |
1485 } | 1612 } |
1486 free(tmp); | 1613 free(tmp); |
1487 return 1; | 1614 return 1; |
1488 } | 1615 } |
1489 | 1616 |
1490 static uint8_t cmd_breakpoint_m68k(debug_root *root, char *format, int num_args, command_arg *args) | 1617 static uint8_t cmd_breakpoint_m68k(debug_root *root, parsed_command *cmd) |
1491 { | 1618 { |
1492 insert_breakpoint(root->cpu_context, args[0].value, debugger); | 1619 insert_breakpoint(root->cpu_context, cmd->args[0].value, debugger); |
1493 bp_def *new_bp = calloc(1, sizeof(bp_def)); | 1620 bp_def *new_bp = calloc(1, sizeof(bp_def)); |
1494 new_bp->next = root->breakpoints; | 1621 new_bp->next = root->breakpoints; |
1495 new_bp->address = args[0].value; | 1622 new_bp->address = cmd->args[0].value; |
1496 new_bp->index = root->bp_index++; | 1623 new_bp->index = root->bp_index++; |
1497 root->breakpoints = new_bp; | 1624 root->breakpoints = new_bp; |
1498 printf("68K Breakpoint %d set at %X\n", new_bp->index, args[0].value); | 1625 printf("68K Breakpoint %d set at %X\n", new_bp->index, cmd->args[0].value); |
1499 return 1; | 1626 return 1; |
1500 } | 1627 } |
1501 | 1628 |
1502 static uint8_t cmd_advance_m68k(debug_root *root, char *format, int num_args, command_arg *args) | 1629 static uint8_t cmd_advance_m68k(debug_root *root, parsed_command *cmd) |
1503 { | 1630 { |
1504 insert_breakpoint(root->cpu_context, args[0].value, debugger); | 1631 insert_breakpoint(root->cpu_context, cmd->args[0].value, debugger); |
1505 return 0; | 1632 return 0; |
1506 } | 1633 } |
1507 | 1634 |
1508 static uint8_t cmd_step_m68k(debug_root *root, char *format, int num_args, command_arg *args) | 1635 static uint8_t cmd_step_m68k(debug_root *root, parsed_command *cmd) |
1509 { | 1636 { |
1510 m68kinst *inst = root->inst; | 1637 m68kinst *inst = root->inst; |
1511 m68k_context *context = root->cpu_context; | 1638 m68k_context *context = root->cpu_context; |
1512 uint32_t after = root->after; | 1639 uint32_t after = root->after; |
1513 if (inst->op == M68K_RTS) { | 1640 if (inst->op == M68K_RTS) { |
1535 } | 1662 } |
1536 insert_breakpoint(root->cpu_context, after, debugger); | 1663 insert_breakpoint(root->cpu_context, after, debugger); |
1537 return 0; | 1664 return 0; |
1538 } | 1665 } |
1539 | 1666 |
1540 static uint8_t cmd_over_m68k(debug_root *root, char *format, int num_args, command_arg *args) | 1667 static uint8_t cmd_over_m68k(debug_root *root, parsed_command *cmd) |
1541 { | 1668 { |
1542 m68kinst *inst = root->inst; | 1669 m68kinst *inst = root->inst; |
1543 m68k_context *context = root->cpu_context; | 1670 m68k_context *context = root->cpu_context; |
1544 uint32_t after = root->after; | 1671 uint32_t after = root->after; |
1545 if (inst->op == M68K_RTS) { | 1672 if (inst->op == M68K_RTS) { |
1572 } | 1699 } |
1573 insert_breakpoint(root->cpu_context, after, debugger); | 1700 insert_breakpoint(root->cpu_context, after, debugger); |
1574 return 0; | 1701 return 0; |
1575 } | 1702 } |
1576 | 1703 |
1577 static uint8_t cmd_next_m68k(debug_root *root, char *format, int num_args, command_arg *args) | 1704 static uint8_t cmd_next_m68k(debug_root *root, parsed_command *cmd) |
1578 { | 1705 { |
1579 m68kinst *inst = root->inst; | 1706 m68kinst *inst = root->inst; |
1580 m68k_context *context = root->cpu_context; | 1707 m68k_context *context = root->cpu_context; |
1581 uint32_t after = root->after; | 1708 uint32_t after = root->after; |
1582 if (inst->op == M68K_RTS) { | 1709 if (inst->op == M68K_RTS) { |
1604 } | 1731 } |
1605 insert_breakpoint(root->cpu_context, after, debugger); | 1732 insert_breakpoint(root->cpu_context, after, debugger); |
1606 return 0; | 1733 return 0; |
1607 } | 1734 } |
1608 | 1735 |
1609 static uint8_t cmd_backtrace_m68k(debug_root *root, char *format, int num_args, command_arg *args) | 1736 static uint8_t cmd_backtrace_m68k(debug_root *root, parsed_command *cmd) |
1610 { | 1737 { |
1611 m68k_context *context = root->cpu_context; | 1738 m68k_context *context = root->cpu_context; |
1612 uint32_t stack = context->aregs[7]; | 1739 uint32_t stack = context->aregs[7]; |
1613 uint8_t non_adr_count = 0; | 1740 uint8_t non_adr_count = 0; |
1614 do { | 1741 do { |
1630 //TODO: Make sure we don't wander into an invalid memory region | 1757 //TODO: Make sure we don't wander into an invalid memory region |
1631 } while (stack && non_adr_count < 6); | 1758 } while (stack && non_adr_count < 6); |
1632 return 1; | 1759 return 1; |
1633 } | 1760 } |
1634 | 1761 |
1635 static uint8_t cmd_vdp_sprites(debug_root *root, char *format, int num_args, command_arg *args) | 1762 static uint8_t cmd_vdp_sprites(debug_root *root, parsed_command *cmd) |
1636 { | 1763 { |
1637 m68k_context *context = root->cpu_context; | 1764 m68k_context *context = root->cpu_context; |
1638 genesis_context * gen = context->system; | 1765 genesis_context * gen = context->system; |
1639 vdp_print_sprite_table(gen->vdp); | 1766 vdp_print_sprite_table(gen->vdp); |
1640 return 1; | 1767 return 1; |
1641 } | 1768 } |
1642 | 1769 |
1643 static uint8_t cmd_vdp_regs(debug_root *root, char *format, int num_args, command_arg *args) | 1770 static uint8_t cmd_vdp_regs(debug_root *root, parsed_command *cmd) |
1644 { | 1771 { |
1645 m68k_context *context = root->cpu_context; | 1772 m68k_context *context = root->cpu_context; |
1646 genesis_context * gen = context->system; | 1773 genesis_context * gen = context->system; |
1647 vdp_print_reg_explain(gen->vdp); | 1774 vdp_print_reg_explain(gen->vdp); |
1648 return 1; | 1775 return 1; |
1649 } | 1776 } |
1650 | 1777 |
1651 static uint8_t cmd_ym_channel(debug_root *root, char *format, int num_args, command_arg *args) | 1778 static uint8_t cmd_ym_channel(debug_root *root, parsed_command *cmd) |
1652 { | 1779 { |
1653 m68k_context *context = root->cpu_context; | 1780 m68k_context *context = root->cpu_context; |
1654 genesis_context * gen = context->system; | 1781 genesis_context * gen = context->system; |
1655 if (num_args) { | 1782 if (cmd->num_args) { |
1656 ym_print_channel_info(gen->ym, args[0].value - 1); | 1783 ym_print_channel_info(gen->ym, cmd->args[0].value - 1); |
1657 } else { | 1784 } else { |
1658 for (int i = 0; i < 6; i++) { | 1785 for (int i = 0; i < 6; i++) { |
1659 ym_print_channel_info(gen->ym, i); | 1786 ym_print_channel_info(gen->ym, i); |
1660 } | 1787 } |
1661 } | 1788 } |
1662 return 1; | 1789 return 1; |
1663 } | 1790 } |
1664 | 1791 |
1665 static uint8_t cmd_ym_timer(debug_root *root, char *format, int num_args, command_arg *args) | 1792 static uint8_t cmd_ym_timer(debug_root *root, parsed_command *cmd) |
1666 { | 1793 { |
1667 m68k_context *context = root->cpu_context; | 1794 m68k_context *context = root->cpu_context; |
1668 genesis_context * gen = context->system; | 1795 genesis_context * gen = context->system; |
1669 ym_print_timer_info(gen->ym); | 1796 ym_print_timer_info(gen->ym); |
1670 return 1; | 1797 return 1; |
1671 } | 1798 } |
1672 | 1799 |
1673 static uint8_t cmd_sub(debug_root *root, char *format, char *param) | 1800 static uint8_t cmd_sub(debug_root *root, parsed_command *cmd) |
1674 { | 1801 { |
1802 char *param = cmd->raw; | |
1675 while (param && *param && isblank(*param)) | 1803 while (param && *param && isblank(*param)) |
1676 { | 1804 { |
1677 ++param; | 1805 ++param; |
1678 } | 1806 } |
1679 m68k_context *m68k = root->cpu_context; | 1807 m68k_context *m68k = root->cpu_context; |
1696 cd->enter_debugger = 1; | 1824 cd->enter_debugger = 1; |
1697 return 0; | 1825 return 0; |
1698 } | 1826 } |
1699 } | 1827 } |
1700 | 1828 |
1701 static uint8_t cmd_main(debug_root *root, char *format, char *param) | 1829 static uint8_t cmd_main(debug_root *root, parsed_command *cmd) |
1702 { | 1830 { |
1831 char *param = cmd->raw; | |
1703 while (param && *param && isblank(*param)) | 1832 while (param && *param && isblank(*param)) |
1704 { | 1833 { |
1705 ++param; | 1834 ++param; |
1706 } | 1835 } |
1707 m68k_context *m68k = root->cpu_context; | 1836 m68k_context *m68k = root->cpu_context; |
1724 cd->genesis->header.enter_debugger = 1; | 1853 cd->genesis->header.enter_debugger = 1; |
1725 return 0; | 1854 return 0; |
1726 } | 1855 } |
1727 } | 1856 } |
1728 | 1857 |
1729 static uint8_t cmd_gen_z80(debug_root *root, char *format, char *param) | 1858 static uint8_t cmd_gen_z80(debug_root *root, parsed_command *cmd) |
1730 { | 1859 { |
1860 char *param = cmd->raw; | |
1731 while (param && *param && isblank(*param)) | 1861 while (param && *param && isblank(*param)) |
1732 { | 1862 { |
1733 ++param; | 1863 ++param; |
1734 } | 1864 } |
1735 m68k_context *m68k = root->cpu_context; | 1865 m68k_context *m68k = root->cpu_context; |
1769 .names = (const char *[]){ | 1899 .names = (const char *[]){ |
1770 "help", "?", NULL | 1900 "help", "?", NULL |
1771 }, | 1901 }, |
1772 .usage = "help", | 1902 .usage = "help", |
1773 .desc = "Print a list of available commands for the current debug context", | 1903 .desc = "Print a list of available commands for the current debug context", |
1774 .raw_impl = cmd_help, | 1904 .impl = cmd_help, |
1775 .min_args = 0, | 1905 .min_args = 0, |
1776 .max_args = 1 | 1906 .max_args = 1, |
1907 .raw_args = 1 | |
1777 }, | 1908 }, |
1778 { | 1909 { |
1779 .names = (const char *[]){ | 1910 .names = (const char *[]){ |
1780 "continue", "c", NULL | 1911 "continue", "c", NULL |
1781 }, | 1912 }, |
1799 .names = (const char *[]){ | 1930 .names = (const char *[]){ |
1800 "printf", NULL | 1931 "printf", NULL |
1801 }, | 1932 }, |
1802 .usage = "printf FORMAT EXPRESSION...", | 1933 .usage = "printf FORMAT EXPRESSION...", |
1803 .desc = "Print a string with C-style formatting specifiers replaced with the value of the remaining arguments", | 1934 .desc = "Print a string with C-style formatting specifiers replaced with the value of the remaining arguments", |
1804 .raw_impl = cmd_printf, | 1935 .impl = cmd_printf, |
1805 .min_args = 1, | 1936 .min_args = 1, |
1806 .max_args = -1 | 1937 .max_args = -1, |
1938 .raw_args = 1 | |
1807 }, | 1939 }, |
1808 { | 1940 { |
1809 .names = (const char *[]){ | 1941 .names = (const char *[]){ |
1810 "softreset", "sr", NULL | 1942 "softreset", "sr", NULL |
1811 }, | 1943 }, |
1841 }, | 1973 }, |
1842 .usage = "command BREAKPOINT", | 1974 .usage = "command BREAKPOINT", |
1843 .desc = "Set a list of debugger commands to be executed when the given breakpoint is hit", | 1975 .desc = "Set a list of debugger commands to be executed when the given breakpoint is hit", |
1844 .impl = cmd_command, | 1976 .impl = cmd_command, |
1845 .min_args = 1, | 1977 .min_args = 1, |
1846 .max_args = 1 | 1978 .max_args = 1, |
1979 .has_block = 1 | |
1847 }, | 1980 }, |
1848 { | 1981 { |
1849 .names = (const char *[]){ | 1982 .names = (const char *[]){ |
1850 "set", NULL | 1983 "set", NULL |
1851 }, | 1984 }, |
1870 .names = (const char *[]){ | 2003 .names = (const char *[]){ |
1871 "bindup", NULL | 2004 "bindup", NULL |
1872 }, | 2005 }, |
1873 .usage = "bindup NAME", | 2006 .usage = "bindup NAME", |
1874 .desc = "Simulate a keyup for binding NAME", | 2007 .desc = "Simulate a keyup for binding NAME", |
1875 .raw_impl = cmd_bindup, | 2008 .impl = cmd_bindup, |
1876 .min_args = 1, | 2009 .min_args = 1, |
1877 .max_args = 1 | 2010 .max_args = 1, |
2011 .raw_args = 1 | |
1878 }, | 2012 }, |
1879 { | 2013 { |
1880 .names = (const char *[]){ | 2014 .names = (const char *[]){ |
1881 "binddown", NULL | 2015 "binddown", NULL |
1882 }, | 2016 }, |
1883 .usage = "bindown NAME", | 2017 .usage = "bindown NAME", |
1884 .desc = "Simulate a keydown for binding NAME", | 2018 .desc = "Simulate a keydown for binding NAME", |
1885 .raw_impl = cmd_binddown, | 2019 .impl = cmd_binddown, |
1886 .min_args = 1, | 2020 .min_args = 1, |
1887 .max_args = 1 | 2021 .max_args = 1, |
2022 .raw_args = 1 | |
1888 }, | 2023 }, |
1889 { | 2024 { |
1890 .names = (const char *[]){ | 2025 .names = (const char *[]){ |
1891 "condition", NULL | 2026 "condition", NULL |
1892 }, | 2027 }, |
1893 .usage = "condition BREAKPOINT [EXPRESSION]", | 2028 .usage = "condition BREAKPOINT [EXPRESSION]", |
1894 .desc = "Makes breakpoint BREAKPOINT conditional on the value of EXPRESSION or removes a condition if EXPRESSION is omitted", | 2029 .desc = "Makes breakpoint BREAKPOINT conditional on the value of EXPRESSION or removes a condition if EXPRESSION is omitted", |
1895 .impl = cmd_condition, | 2030 .impl = cmd_condition, |
1896 .min_args = 1, | 2031 .min_args = 1, |
1897 .max_args = 2 | 2032 .max_args = 2, |
2033 .skip_eval = 1 | |
1898 } | 2034 } |
1899 }; | 2035 }; |
1900 #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands)) | 2036 #define NUM_COMMON (sizeof(common_commands)/sizeof(*common_commands)) |
1901 | 2037 |
1902 command_def m68k_commands[] = { | 2038 command_def m68k_commands[] = { |
2000 .names = (const char *[]){ | 2136 .names = (const char *[]){ |
2001 "z80", NULL | 2137 "z80", NULL |
2002 }, | 2138 }, |
2003 .usage = "z80 [COMMAND]", | 2139 .usage = "z80 [COMMAND]", |
2004 .desc = "Run a Z80 debugger command or switch to Z80 context when no command is given", | 2140 .desc = "Run a Z80 debugger command or switch to Z80 context when no command is given", |
2005 .raw_impl = cmd_gen_z80, | 2141 .impl = cmd_gen_z80, |
2006 .min_args = 0, | 2142 .min_args = 0, |
2007 .max_args = -1 | 2143 .max_args = -1, |
2144 .raw_args = 1 | |
2008 }, | 2145 }, |
2009 #endif | 2146 #endif |
2010 { | 2147 { |
2011 .names = (const char *[]){ | 2148 .names = (const char *[]){ |
2012 "ymchannel", "yc", NULL | 2149 "ymchannel", "yc", NULL |
2036 .names = (const char *[]){ | 2173 .names = (const char *[]){ |
2037 "subcpu", NULL | 2174 "subcpu", NULL |
2038 }, | 2175 }, |
2039 .usage = "subcpu [COMMAND]", | 2176 .usage = "subcpu [COMMAND]", |
2040 .desc = "Run a Sub-CPU debugger command or switch to Sub-CPU context when no command is given", | 2177 .desc = "Run a Sub-CPU debugger command or switch to Sub-CPU context when no command is given", |
2041 .raw_impl = cmd_sub, | 2178 .impl = cmd_sub, |
2042 .min_args = 0, | 2179 .min_args = 0, |
2043 .max_args = -1 | 2180 .max_args = -1, |
2181 .raw_args = 1 | |
2044 } | 2182 } |
2045 }; | 2183 }; |
2046 | 2184 |
2047 #define NUM_SCD_MAIN (sizeof(scd_main_commands)/sizeof(*scd_main_commands)) | 2185 #define NUM_SCD_MAIN (sizeof(scd_main_commands)/sizeof(*scd_main_commands)) |
2048 | 2186 |
2051 .names = (const char *[]){ | 2189 .names = (const char *[]){ |
2052 "maincpu", NULL | 2190 "maincpu", NULL |
2053 }, | 2191 }, |
2054 .usage = "maincpu [COMMAND]", | 2192 .usage = "maincpu [COMMAND]", |
2055 .desc = "Run a Main-CPU debugger command or switch to Main-CPU context when no command is given", | 2193 .desc = "Run a Main-CPU debugger command or switch to Main-CPU context when no command is given", |
2056 .raw_impl = cmd_main, | 2194 .impl = cmd_main, |
2057 .min_args = 0, | 2195 .min_args = 0, |
2058 .max_args = -1 | 2196 .max_args = -1, |
2197 .raw_args = 1 | |
2059 } | 2198 } |
2060 }; | 2199 }; |
2061 | 2200 |
2062 #define NUM_SCD_SUB (sizeof(scd_main_commands)/sizeof(*scd_main_commands)) | 2201 #define NUM_SCD_SUB (sizeof(scd_main_commands)/sizeof(*scd_main_commands)) |
2063 | 2202 |
2064 #ifndef NO_Z80 | 2203 #ifndef NO_Z80 |
2065 | 2204 |
2066 static uint8_t cmd_delete_z80(debug_root *root, char *format, int num_args, command_arg *args) | 2205 static uint8_t cmd_delete_z80(debug_root *root, parsed_command *cmd) |
2067 { | 2206 { |
2068 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, args[0].value); | 2207 bp_def **this_bp = find_breakpoint_idx(&root->breakpoints, cmd->args[0].value); |
2069 if (!*this_bp) { | 2208 if (!*this_bp) { |
2070 fprintf(stderr, "Breakpoint %d does not exist\n", args[0].value); | 2209 fprintf(stderr, "Breakpoint %d does not exist\n", cmd->args[0].value); |
2071 return 1; | 2210 return 1; |
2072 } | 2211 } |
2073 bp_def *tmp = *this_bp; | 2212 bp_def *tmp = *this_bp; |
2074 zremove_breakpoint(root->cpu_context, tmp->address); | 2213 zremove_breakpoint(root->cpu_context, tmp->address); |
2075 *this_bp = (*this_bp)->next; | 2214 *this_bp = (*this_bp)->next; |
2082 } | 2221 } |
2083 free(tmp); | 2222 free(tmp); |
2084 return 1; | 2223 return 1; |
2085 } | 2224 } |
2086 | 2225 |
2087 static uint8_t cmd_breakpoint_z80(debug_root *root, char *format, int num_args, command_arg *args) | 2226 static uint8_t cmd_breakpoint_z80(debug_root *root, parsed_command *cmd) |
2088 { | 2227 { |
2089 zinsert_breakpoint(root->cpu_context, args[0].value, (uint8_t *)zdebugger); | 2228 zinsert_breakpoint(root->cpu_context, cmd->args[0].value, (uint8_t *)zdebugger); |
2090 bp_def *new_bp = calloc(1, sizeof(bp_def)); | 2229 bp_def *new_bp = calloc(1, sizeof(bp_def)); |
2091 new_bp->next = root->breakpoints; | 2230 new_bp->next = root->breakpoints; |
2092 new_bp->address = args[0].value; | 2231 new_bp->address = cmd->args[0].value; |
2093 new_bp->index = root->bp_index++; | 2232 new_bp->index = root->bp_index++; |
2094 root->breakpoints = new_bp; | 2233 root->breakpoints = new_bp; |
2095 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, args[0].value); | 2234 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, cmd->args[0].value); |
2096 return 1; | 2235 return 1; |
2097 } | 2236 } |
2098 | 2237 |
2099 static uint8_t cmd_advance_z80(debug_root *root, char *format, int num_args, command_arg *args) | 2238 static uint8_t cmd_advance_z80(debug_root *root, parsed_command *cmd) |
2100 { | 2239 { |
2101 zinsert_breakpoint(root->cpu_context, args[0].value, (uint8_t *)zdebugger); | 2240 zinsert_breakpoint(root->cpu_context, cmd->args[0].value, (uint8_t *)zdebugger); |
2102 return 0; | 2241 return 0; |
2103 } | 2242 } |
2104 | 2243 |
2105 static uint8_t cmd_step_z80(debug_root *root, char *format, int num_args, command_arg *args) | 2244 static uint8_t cmd_step_z80(debug_root *root, parsed_command *cmd) |
2106 { | 2245 { |
2107 z80inst *inst = root->inst; | 2246 z80inst *inst = root->inst; |
2108 z80_context *context = root->cpu_context; | 2247 z80_context *context = root->cpu_context; |
2109 uint32_t after = root->after; | 2248 uint32_t after = root->after; |
2110 //TODO: handle conditional branches | 2249 //TODO: handle conditional branches |
2134 } | 2273 } |
2135 zinsert_breakpoint(context, after, (uint8_t *)zdebugger); | 2274 zinsert_breakpoint(context, after, (uint8_t *)zdebugger); |
2136 return 0; | 2275 return 0; |
2137 } | 2276 } |
2138 | 2277 |
2139 static uint8_t cmd_over_z80(debug_root *root, char *format, int num_args, command_arg *args) | 2278 static uint8_t cmd_over_z80(debug_root *root, parsed_command *cmd) |
2140 { | 2279 { |
2141 fputs("not implemented yet\n", stderr); | 2280 fputs("not implemented yet\n", stderr); |
2142 return 1; | 2281 return 1; |
2143 } | 2282 } |
2144 | 2283 |
2145 static uint8_t cmd_next_z80(debug_root *root, char *format, int num_args, command_arg *args) | 2284 static uint8_t cmd_next_z80(debug_root *root, parsed_command *cmd) |
2146 { | 2285 { |
2147 z80inst *inst = root->inst; | 2286 z80inst *inst = root->inst; |
2148 z80_context *context = root->cpu_context; | 2287 z80_context *context = root->cpu_context; |
2149 uint32_t after = root->after; | 2288 uint32_t after = root->after; |
2150 //TODO: handle conditional branches | 2289 //TODO: handle conditional branches |
2174 } | 2313 } |
2175 zinsert_breakpoint(context, after, (uint8_t *)zdebugger); | 2314 zinsert_breakpoint(context, after, (uint8_t *)zdebugger); |
2176 return 0; | 2315 return 0; |
2177 } | 2316 } |
2178 | 2317 |
2179 static uint8_t cmd_backtrace_z80(debug_root *root, char *format, int num_args, command_arg *args) | 2318 static uint8_t cmd_backtrace_z80(debug_root *root, parsed_command *cmd) |
2180 { | 2319 { |
2181 z80_context *context = root->cpu_context; | 2320 z80_context *context = root->cpu_context; |
2182 uint32_t stack = context->sp; | 2321 uint32_t stack = context->sp; |
2183 uint8_t non_adr_count = 0; | 2322 uint8_t non_adr_count = 0; |
2184 do { | 2323 do { |
2204 //TODO: Make sure we don't wander into an invalid memory region | 2343 //TODO: Make sure we don't wander into an invalid memory region |
2205 } while (stack && non_adr_count < 6); | 2344 } while (stack && non_adr_count < 6); |
2206 return 1; | 2345 return 1; |
2207 } | 2346 } |
2208 | 2347 |
2209 static uint8_t cmd_gen_m68k(debug_root *root, char *format, char *param) | 2348 static uint8_t cmd_gen_m68k(debug_root *root, parsed_command *cmd) |
2210 { | 2349 { |
2350 char *param = cmd->raw; | |
2211 while (param && *param && isblank(*param)) | 2351 while (param && *param && isblank(*param)) |
2212 { | 2352 { |
2213 ++param; | 2353 ++param; |
2214 } | 2354 } |
2215 genesis_context *gen = (genesis_context *)current_system; | 2355 genesis_context *gen = (genesis_context *)current_system; |
2313 .names = (const char *[]){ | 2453 .names = (const char *[]){ |
2314 "m68k", NULL | 2454 "m68k", NULL |
2315 }, | 2455 }, |
2316 .usage = "m68k [COMMAND]", | 2456 .usage = "m68k [COMMAND]", |
2317 .desc = "Run a M68K debugger command or switch to M68K context when no command is given", | 2457 .desc = "Run a M68K debugger command or switch to M68K context when no command is given", |
2318 .raw_impl = cmd_gen_m68k, | 2458 .impl = cmd_gen_m68k, |
2319 .min_args = 0, | 2459 .min_args = 0, |
2320 .max_args = -1 | 2460 .max_args = -1, |
2461 .raw_args = 1 | |
2321 } | 2462 } |
2322 }; | 2463 }; |
2323 | 2464 |
2324 #define NUM_GEN_Z80 (sizeof(gen_z80_commands)/sizeof(*gen_z80_commands)) | 2465 #define NUM_GEN_Z80 (sizeof(gen_z80_commands)/sizeof(*gen_z80_commands)) |
2325 | 2466 |
2869 init_terminal(); | 3010 init_terminal(); |
2870 debug_root *root = find_z80_root(context); | 3011 debug_root *root = find_z80_root(context); |
2871 if (!root) { | 3012 if (!root) { |
2872 return context; | 3013 return context; |
2873 } | 3014 } |
3015 root->address = address; | |
2874 //Check if this is a user set breakpoint, or just a temporary one | 3016 //Check if this is a user set breakpoint, or just a temporary one |
2875 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); | 3017 bp_def ** this_bp = find_breakpoint(&root->breakpoints, address); |
2876 if (*this_bp) { | 3018 if (*this_bp) { |
2877 if ((*this_bp)->condition) { | 3019 if ((*this_bp)->condition) { |
2878 uint32_t condres; | 3020 uint32_t condres; |
2892 } | 3034 } |
2893 uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->Z80_OPTS->gen); | 3035 uint8_t * pc = get_native_pointer(address, (void **)context->mem_pointers, &context->Z80_OPTS->gen); |
2894 if (!pc) { | 3036 if (!pc) { |
2895 fatal_error("Failed to get native pointer on entering Z80 debugger at address %X\n", address); | 3037 fatal_error("Failed to get native pointer on entering Z80 debugger at address %X\n", address); |
2896 } | 3038 } |
3039 uint8_t * after_pc = z80_decode(pc, &inst); | |
3040 uint16_t after = address + (after_pc-pc); | |
3041 root->after = after; | |
3042 root->inst = &inst; | |
2897 for (disp_def * cur = root->displays; cur; cur = cur->next) { | 3043 for (disp_def * cur = root->displays; cur; cur = cur->next) { |
3044 char format_str[8]; | |
3045 make_format_str(format_str, cur->format); | |
2898 for (int i = 0; i < cur->num_args; i++) | 3046 for (int i = 0; i < cur->num_args; i++) |
2899 { | 3047 { |
2900 eval_expr(root, cur->args[i].parsed, &cur->args[i].value); | 3048 eval_expr(root, cur->args[i].parsed, &cur->args[i].value); |
2901 } | 3049 do_print(root, format_str, cur->args[i].raw, cur->args[i].value); |
2902 cmd_print(root, cur->format, cur->num_args, cur->args); | 3050 } |
2903 } | 3051 } |
2904 uint8_t * after_pc = z80_decode(pc, &inst); | 3052 |
2905 z80_disasm(&inst, input_buf, address); | 3053 z80_disasm(&inst, input_buf, address); |
2906 printf("%X:\t%s\n", address, input_buf); | 3054 printf("%X:\t%s\n", address, input_buf); |
2907 uint16_t after = address + (after_pc-pc); | 3055 debugger_repl(root); |
2908 root->address = address; | |
2909 root->after = after; | |
2910 root->inst = &inst; | |
2911 int debugging = 1; | |
2912 while(debugging) { | |
2913 fputs(">", stdout); | |
2914 if (!fgets(input_buf, sizeof(input_buf), stdin)) { | |
2915 fputs("fgets failed", stderr); | |
2916 break; | |
2917 } | |
2918 strip_nl(input_buf); | |
2919 //hitting enter repeats last command | |
2920 if (input_buf[0]) { | |
2921 strcpy(last_cmd, input_buf); | |
2922 } else { | |
2923 strcpy(input_buf, last_cmd); | |
2924 } | |
2925 parsed_command cmd; | |
2926 if (parse_command(root, input_buf, &cmd)) { | |
2927 debugging = run_command(root, &cmd); | |
2928 free_parsed_command(&cmd); | |
2929 } | |
2930 } | |
2931 return context; | 3056 return context; |
2932 } | 3057 } |
2933 | 3058 |
2934 #endif | 3059 #endif |
2935 | 3060 |
2997 } | 3122 } |
2998 uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address); | 3123 uint32_t after = m68k_decode(m68k_instruction_fetch, context, &inst, address); |
2999 root->after = after; | 3124 root->after = after; |
3000 root->inst = &inst; | 3125 root->inst = &inst; |
3001 for (disp_def * cur = root->displays; cur; cur = cur->next) { | 3126 for (disp_def * cur = root->displays; cur; cur = cur->next) { |
3127 char format_str[8]; | |
3128 make_format_str(format_str, cur->format); | |
3002 for (int i = 0; i < cur->num_args; i++) | 3129 for (int i = 0; i < cur->num_args; i++) |
3003 { | 3130 { |
3004 eval_expr(root, cur->args[i].parsed, &cur->args[i].value); | 3131 eval_expr(root, cur->args[i].parsed, &cur->args[i].value); |
3005 } | 3132 do_print(root, format_str, cur->args[i].raw, cur->args[i].value); |
3006 cmd_print(root, cur->format, cur->num_args, cur->args); | 3133 } |
3007 } | 3134 } |
3008 m68k_disasm(&inst, input_buf); | 3135 m68k_disasm(&inst, input_buf); |
3009 printf("%X: %s\n", address, input_buf); | 3136 printf("%X: %s\n", address, input_buf); |
3010 #ifdef _WIN32 | 3137 debugger_repl(root); |
3011 #define prompt 1 | |
3012 #else | |
3013 int prompt = 1; | |
3014 fd_set read_fds; | |
3015 FD_ZERO(&read_fds); | |
3016 struct timeval timeout; | |
3017 #endif | |
3018 while (debugging) { | |
3019 if (prompt) { | |
3020 fputs(">", stdout); | |
3021 fflush(stdout); | |
3022 } | |
3023 process_events(); | |
3024 #ifndef _WIN32 | |
3025 timeout.tv_sec = 0; | |
3026 timeout.tv_usec = 16667; | |
3027 FD_SET(fileno(stdin), &read_fds); | |
3028 if(select(fileno(stdin) + 1, &read_fds, NULL, NULL, &timeout) < 1) { | |
3029 prompt = 0; | |
3030 continue; | |
3031 } else { | |
3032 prompt = 1; | |
3033 } | |
3034 #endif | |
3035 if (!fgets(input_buf, sizeof(input_buf), stdin)) { | |
3036 fputs("fgets failed", stderr); | |
3037 break; | |
3038 } | |
3039 strip_nl(input_buf); | |
3040 //hitting enter repeats last command | |
3041 if (input_buf[0]) { | |
3042 strcpy(last_cmd, input_buf); | |
3043 } else { | |
3044 strcpy(input_buf, last_cmd); | |
3045 } | |
3046 parsed_command cmd; | |
3047 if (parse_command(root, input_buf, &cmd)) { | |
3048 debugging = run_command(root, &cmd); | |
3049 free_parsed_command(&cmd); | |
3050 } | |
3051 } | |
3052 return; | 3138 return; |
3053 } | 3139 } |