comparison debug.c @ 2359:04d29635d238

Support for arrays in debugger language
author Michael Pavone <pavone@retrodev.com>
date Sat, 28 Oct 2023 14:39:19 -0700
parents 4b2ac43c106e
children 053ba4551c62
comparison
equal deleted inserted replaced
2358:4b2ac43c106e 2359:04d29635d238
165 return (token) { 165 return (token) {
166 .type = TOKEN_RPAREN 166 .type = TOKEN_RPAREN
167 }; 167 };
168 } 168 }
169 *end = start + 1; 169 *end = start + 1;
170 token_type type = TOKEN_NAME;
170 while (**end && !isspace(**end)) 171 while (**end && !isspace(**end))
171 { 172 {
172 uint8_t done = 0; 173 uint8_t done = 0;
173 switch (**end) 174 switch (**end)
174 { 175 {
176 case '[':
177 type = TOKEN_ARRAY;
175 case '+': 178 case '+':
176 case '-': 179 case '-':
177 case '*': 180 case '*':
178 case '/': 181 case '/':
179 case '&': 182 case '&':
183 case '=': 186 case '=':
184 case '!': 187 case '!':
185 case '>': 188 case '>':
186 case '<': 189 case '<':
187 case '.': 190 case '.':
188 case '[':
189 case ']': 191 case ']':
190 case '(': 192 case '(':
191 case ')': 193 case ')':
192 done = 1; 194 done = 1;
193 break; 195 break;
200 } 202 }
201 char *name = malloc(*end - start + 1); 203 char *name = malloc(*end - start + 1);
202 memcpy(name, start, *end - start); 204 memcpy(name, start, *end - start);
203 name[*end-start] = 0; 205 name[*end-start] = 0;
204 return (token) { 206 return (token) {
205 .type = TOKEN_NAME, 207 .type = type,
206 .v = { 208 .v = {
207 .str = name 209 .str = name
208 } 210 }
209 }; 211 };
210 } 212 }
247 ret->op = first; 249 ret->op = first;
248 ret->left = target; 250 ret->left = target;
249 *end = after_first; 251 *end = after_first;
250 return ret; 252 return ret;
251 } 253 }
252 if (first.type == TOKEN_LBRACKET) { 254 if (first.type == TOKEN_LBRACKET || first.type == TOKEN_ARRAY) {
253 expr *ret = calloc(1, sizeof(expr)); 255 expr *ret = calloc(1, sizeof(expr));
254 ret->type = EXPR_MEM; 256 ret->type = EXPR_MEM;
257 if (first.type == TOKEN_ARRAY) {
258 //current token is the array name
259 //consume the bracket token
260 parse_token(after_first, &after_first);
261 ret->right = calloc(1, sizeof(expr));
262 ret->right->type = EXPR_SCALAR;
263 ret->right->op = first;
264 }
265
255 ret->left = parse_expression(after_first, end); 266 ret->left = parse_expression(after_first, end);
256 if (!ret->left) { 267 if (!ret->left) {
257 fprintf(stderr, "Expression expected after `[`\n"); 268 fprintf(stderr, "Expression expected after `[`\n");
258 free(ret); 269 free(ret);
259 return NULL; 270 return NULL;
394 ret->type = EXPR_UNARY; 405 ret->type = EXPR_UNARY;
395 ret->op = first; 406 ret->op = first;
396 ret->left = target; 407 ret->left = target;
397 return ret; 408 return ret;
398 } 409 }
399 if (first.type == TOKEN_LBRACKET) { 410 if (first.type == TOKEN_LBRACKET || first.type == TOKEN_ARRAY) {
400 expr *ret = calloc(1, sizeof(expr)); 411 expr *ret = calloc(1, sizeof(expr));
401 ret->type = EXPR_MEM; 412 ret->type = EXPR_MEM;
413 if (first.type == TOKEN_ARRAY) {
414 //current token is the array name
415 //consume the bracket token
416 parse_token(after_first, &after_first);
417 ret->right = calloc(1, sizeof(expr));
418 ret->right->type = EXPR_SCALAR;
419 ret->right->op = first;
420 }
421
402 ret->left = parse_expression(after_first, end); 422 ret->left = parse_expression(after_first, end);
403 if (!ret->left) { 423 if (!ret->left) {
404 fprintf(stderr, "Expression expected after `[`\n"); 424 fprintf(stderr, "Expression expected after `[`\n");
405 free(ret); 425 free(ret);
406 return NULL; 426 return NULL;
510 ret->type = EXPR_UNARY; 530 ret->type = EXPR_UNARY;
511 ret->op = first; 531 ret->op = first;
512 ret->left = target; 532 ret->left = target;
513 return ret; 533 return ret;
514 } 534 }
515 if (first.type == TOKEN_LBRACKET) { 535 if (first.type == TOKEN_LBRACKET || first.type == TOKEN_ARRAY) {
516 expr *ret = calloc(1, sizeof(expr)); 536 expr *ret = calloc(1, sizeof(expr));
517 ret->type = EXPR_MEM; 537 ret->type = EXPR_MEM;
538 if (first.type == TOKEN_ARRAY) {
539 //current token is the array name
540 //consume the bracket token
541 parse_token(after_first, &after_first);
542 ret->right = calloc(1, sizeof(expr));
543 ret->right->type = EXPR_SCALAR;
544 ret->right->op = first;
545 }
546
518 ret->left = parse_expression(after_first, end); 547 ret->left = parse_expression(after_first, end);
519 if (!ret->left) { 548 if (!ret->left) {
520 fprintf(stderr, "Expression expected after `[`\n"); 549 fprintf(stderr, "Expression expected after `[`\n");
521 free(ret); 550 free(ret);
522 return NULL; 551 return NULL;
620 *end = after_first; 649 *end = after_first;
621 return ret; 650 return ret;
622 } 651 }
623 } 652 }
624 653
654 static debug_array* full_array_resolve(debug_root *root, const char *name)
655 {
656 debug_array *ret = root->array_resolve(root, name);
657 if (!ret) {
658 ret = tern_find_ptr(root->arrays, name);
659 }
660 return ret;
661 }
662
625 uint8_t eval_expr(debug_root *root, expr *e, uint32_t *out) 663 uint8_t eval_expr(debug_root *root, expr *e, uint32_t *out)
626 { 664 {
627 uint32_t right; 665 uint32_t right;
628 switch(e->type) 666 switch(e->type)
629 { 667 {
723 } 761 }
724 return 1; 762 return 1;
725 case EXPR_MEM: 763 case EXPR_MEM:
726 if (!eval_expr(root, e->left, out)) { 764 if (!eval_expr(root, e->left, out)) {
727 return 0; 765 return 0;
766 }
767 if (e->right) {
768 debug_array *array = full_array_resolve(root, e->right->op.v.str);
769 if (!array || *out >= array->size) {
770 return 0;
771 }
772 *out = array->get(root, array, *out);
773 return 1;
728 } 774 }
729 return root->read_mem(root, out, e->op.v.op[0]); 775 return root->read_mem(root, out, e->op.v.op[0]);
730 default: 776 default:
731 return 0; 777 return 0;
732 } 778 }
917 if (!strcmp(name, "f") || !strcmp(name, "frame")) { 963 if (!strcmp(name, "f") || !strcmp(name, "frame")) {
918 *out = gen->vdp->frame; 964 *out = gen->vdp->frame;
919 return 1; 965 return 1;
920 } 966 }
921 return 0; 967 return 0;
968 }
969
970 static uint32_t debug_vram_get(debug_root *root, debug_array *array, uint32_t index)
971 {
972 m68k_context *m68k = root->cpu_context;
973 genesis_context *gen = m68k->system;
974 return gen->vdp->vdpmem[index];
975 }
976
977 static void debug_vram_set(debug_root *root, debug_array *array, uint32_t index, uint32_t value)
978 {
979 m68k_context *m68k = root->cpu_context;
980 genesis_context *gen = m68k->system;
981 gen->vdp->vdpmem[index] = value;
982 }
983
984 static uint32_t debug_vsram_get(debug_root *root, debug_array *array, uint32_t index)
985 {
986 m68k_context *m68k = root->cpu_context;
987 genesis_context *gen = m68k->system;
988 return gen->vdp->vsram[index] & VSRAM_BITS;
989 }
990
991 static void debug_vsram_set(debug_root *root, debug_array *array, uint32_t index, uint32_t value)
992 {
993 m68k_context *m68k = root->cpu_context;
994 genesis_context *gen = m68k->system;
995 gen->vdp->vsram[index] = value;
996 }
997
998 static uint32_t debug_cram_get(debug_root *root, debug_array *array, uint32_t index)
999 {
1000 m68k_context *m68k = root->cpu_context;
1001 genesis_context *gen = m68k->system;
1002 return gen->vdp->cram[index] & CRAM_BITS;
1003 }
1004
1005 static void debug_cram_set(debug_root *root, debug_array *array, uint32_t index, uint32_t value)
1006 {
1007 m68k_context *m68k = root->cpu_context;
1008 genesis_context *gen = m68k->system;
1009 gen->vdp->cram[index] = value;
1010 }
1011
1012 static uint32_t debug_vreg_get(debug_root *root, debug_array *array, uint32_t index)
1013 {
1014 m68k_context *m68k = root->cpu_context;
1015 genesis_context *gen = m68k->system;
1016 return gen->vdp->regs[index];
1017 }
1018
1019 static void debug_vreg_set(debug_root *root, debug_array *array, uint32_t index, uint32_t value)
1020 {
1021 m68k_context *m68k = root->cpu_context;
1022 genesis_context *gen = m68k->system;
1023 vdp_reg_write(gen->vdp, index, value);
1024 }
1025
1026 static debug_array* resolve_vdp_array(debug_root *root, const char *name)
1027 {
1028 static debug_array vram = {
1029 .get = debug_vram_get, .set = debug_vram_set,
1030 .size = VRAM_SIZE, .storage = VRAM_SIZE
1031 };
1032 static debug_array vsram = {
1033 .get = debug_vsram_get, .set = debug_vsram_set,
1034 };
1035 static debug_array cram = {
1036 .get = debug_cram_get, .set = debug_cram_set,
1037 .storage = CRAM_SIZE, .size = CRAM_SIZE
1038 };
1039 static debug_array regs = {
1040 .get = debug_vreg_get, .set = debug_vreg_set,
1041 .storage = VDP_REGS, .size = VDP_REGS
1042 };
1043 if (!strcasecmp(name, "vram")) {
1044 return &vram;
1045 }
1046 if (!strcasecmp(name, "vsram")) {
1047 m68k_context *m68k = root->cpu_context;
1048 genesis_context *gen = m68k->system;
1049 vsram.storage = vsram.size = gen->vdp->vsram_size;
1050 return &vsram;
1051 }
1052 if (!strcasecmp(name, "cram")) {
1053 return &cram;
1054 }
1055 if (!strcasecmp(name, "reg")) {
1056 return &regs;
1057 }
1058 return NULL;
1059 }
1060
1061 static debug_array* resolve_genesis_array(debug_root *root, const char *name)
1062 {
1063 for (const char *cur = name; *cur; ++cur)
1064 {
1065 if (*cur == ':') {
1066 if (cur - name == 3 && !memcmp(name, "vdp", 3)) {
1067 return resolve_vdp_array(root, cur + 1);
1068 } /*else if (cur - name == 3 && !memcmp(name, "sub", 3)) {
1069 m68k_context *m68k = root->cpu_context;
1070 genesis_context *gen = m68k->system;
1071 if (gen->expansion) {
1072 segacd_context *cd = gen->expansion;
1073 root = find_m68k_root(cd->m68k);
1074 return root->resolve(root, cur + 1, out);
1075 } else {
1076 return NULL;
1077 }
1078 }*/ else {
1079 return NULL;
1080 }
1081 }
1082 }
1083 return NULL;
1084 }
1085
1086 static debug_array* resolve_null_array(debug_root *root, const char *name)
1087 {
1088 return NULL;
922 } 1089 }
923 1090
924 void ambiguous_iter(char *key, tern_val val, uint8_t valtype, void *data) 1091 void ambiguous_iter(char *key, tern_val val, uint8_t valtype, void *data)
925 { 1092 {
926 char *prefix = data; 1093 char *prefix = data;
1613 static uint8_t cmd_set(debug_root *root, parsed_command *cmd) 1780 static uint8_t cmd_set(debug_root *root, parsed_command *cmd)
1614 { 1781 {
1615 char *name = NULL; 1782 char *name = NULL;
1616 char size = 0; 1783 char size = 0;
1617 uint32_t address; 1784 uint32_t address;
1785 debug_array *array = NULL;
1618 switch (cmd->args[0].parsed->type) 1786 switch (cmd->args[0].parsed->type)
1619 { 1787 {
1620 case EXPR_SCALAR: 1788 case EXPR_SCALAR:
1621 if (cmd->args[0].parsed->op.type == TOKEN_NAME) { 1789 if (cmd->args[0].parsed->op.type == TOKEN_NAME) {
1622 name = cmd->args[0].parsed->op.v.str; 1790 name = cmd->args[0].parsed->op.v.str;
1638 size = cmd->args[0].parsed->op.v.op[0]; 1806 size = cmd->args[0].parsed->op.v.op[0];
1639 if (!eval_expr(root, cmd->args[0].parsed->left, &address)) { 1807 if (!eval_expr(root, cmd->args[0].parsed->left, &address)) {
1640 fprintf(stderr, "Failed to eval %s\n", cmd->args[0].raw); 1808 fprintf(stderr, "Failed to eval %s\n", cmd->args[0].raw);
1641 return 1; 1809 return 1;
1642 } 1810 }
1811 if (cmd->args[0].parsed->right) {
1812 array = full_array_resolve(root, cmd->args[0].parsed->right->op.v.str);
1813 if (!array) {
1814 fprintf(stderr, "Failed to resolve array %s\n", cmd->args[0].parsed->right->op.v.str);
1815 return 1;
1816 }
1817 if (!array->set) {
1818 fprintf(stderr, "Array %s is read-only\n", cmd->args[0].parsed->right->op.v.str);
1819 return 1;
1820 }
1821 if (address >= array->size) {
1822 fprintf(stderr, "Address %X is out of bounds for array %s\n", address, cmd->args[0].parsed->right->op.v.str);
1823 return 1;
1824 }
1825 }
1643 break; 1826 break;
1644 default: 1827 default:
1645 fprintf(stderr, "First argument to set must be a name or memory expression, got %s\n", expr_type_names[cmd->args[0].parsed->type]); 1828 fprintf(stderr, "First argument to set must be a name or memory expression, got %s\n", expr_type_names[cmd->args[0].parsed->type]);
1646 return 1; 1829 return 1;
1647 } 1830 }
1673 root->variables = tern_insert_int(root->variables, name, value); 1856 root->variables = tern_insert_int(root->variables, name, value);
1674 } else { 1857 } else {
1675 fprintf(stderr, "Failed to set %s\n", name); 1858 fprintf(stderr, "Failed to set %s\n", name);
1676 } 1859 }
1677 } 1860 }
1861 } else if (array) {
1862 array->set(root, array, address, value);
1678 } else if (!root->write_mem(root, address, value, size)) { 1863 } else if (!root->write_mem(root, address, value, size)) {
1679 fprintf(stderr, "Failed to write to address %X\n", address); 1864 fprintf(stderr, "Failed to write to address %X\n", address);
1680 } 1865 }
1681 return 1; 1866 return 1;
1682 } 1867 }
1694 return 1; 1879 return 1;
1695 } 1880 }
1696 value = cmd->args[1].value; 1881 value = cmd->args[1].value;
1697 } 1882 }
1698 root->variables = tern_insert_int(root->variables, cmd->args[0].parsed->op.v.str, value); 1883 root->variables = tern_insert_int(root->variables, cmd->args[0].parsed->op.v.str, value);
1884 return 1;
1885 }
1886
1887 static uint32_t user_array_get(debug_root *root, debug_array *array, uint32_t index)
1888 {
1889 return array->data[index];
1890 }
1891
1892 static void user_array_set(debug_root *root, debug_array *array, uint32_t index, uint32_t value)
1893 {
1894 array->data[index] = value;
1895 }
1896
1897 static void user_array_append(debug_root *root, debug_array *array, uint32_t value)
1898 {
1899 if (array->size == array->storage) {
1900 array->storage *= 2;
1901 array->data = realloc(array->data, sizeof(uint32_t) * array->storage);
1902 }
1903 array->data[array->size++] = value;
1904 }
1905
1906 static uint8_t cmd_array(debug_root *root, parsed_command *cmd)
1907 {
1908 if (cmd->args[0].parsed->type != EXPR_SCALAR || cmd->args[0].parsed->op.type != TOKEN_NAME) {
1909 fprintf(stderr, "First argument to array must be a name, got %s\n", expr_type_names[cmd->args[0].parsed->type]);
1910 return 1;
1911 }
1912 debug_array *array = tern_find_ptr(root->arrays, cmd->args[0].parsed->op.v.str);
1913 if (!array) {
1914 array = calloc(1, sizeof(debug_array));
1915 array->get = user_array_get;
1916 array->set = user_array_set;
1917 array->append = user_array_append;
1918 array->storage = cmd->num_args > 1 ? cmd->num_args - 1 : 4;
1919 array->data = calloc(array->storage, sizeof(uint32_t));
1920 root->arrays = tern_insert_ptr(root->arrays, cmd->args[0].parsed->op.v.str, array);
1921 }
1922 array->size = cmd->num_args - 1;
1923 for (uint32_t i = 1; i < cmd->num_args; i++)
1924 {
1925 if (!eval_expr(root, cmd->args[i].parsed, &cmd->args[i].value)) {
1926 fprintf(stderr, "Failed to eval %s\n", cmd->args[i].raw);
1927 return 1;
1928 }
1929 array->set(root, array, i - 1, cmd->args[i].value);
1930 }
1931 return 1;
1932 }
1933
1934 static uint8_t cmd_append(debug_root *root, parsed_command *cmd)
1935 {
1936 if (cmd->args[0].parsed->type != EXPR_SCALAR || cmd->args[0].parsed->op.type != TOKEN_NAME) {
1937 fprintf(stderr, "First argument to append must be a name, got %s\n", expr_type_names[cmd->args[0].parsed->type]);
1938 return 1;
1939 }
1940 debug_array *array = full_array_resolve(root, cmd->args[0].parsed->op.v.str);
1941 if (!array) {
1942 fprintf(stderr, "Failed to resolve array %s\n", cmd->args[0].parsed->op.v.str);
1943 return 1;
1944 }
1945 if (!array->append) {
1946 fprintf(stderr, "Array %s doesn't support appending\n", cmd->args[0].parsed->op.v.str);
1947 return 1;
1948 }
1949 if (!eval_expr(root, cmd->args[1].parsed, &cmd->args[1].value)) {
1950 fprintf(stderr, "Failed to eval %s\n", cmd->args[1].raw);
1951 return 1;
1952 }
1953 array->append(root, array, cmd->args[1].value);
1699 return 1; 1954 return 1;
1700 } 1955 }
1701 1956
1702 static uint8_t cmd_frames(debug_root *root, parsed_command *cmd) 1957 static uint8_t cmd_frames(debug_root *root, parsed_command *cmd)
1703 { 1958 {
2230 .max_args = 2, 2485 .max_args = 2,
2231 .skip_eval = 1 2486 .skip_eval = 1
2232 }, 2487 },
2233 { 2488 {
2234 .names = (const char *[]){ 2489 .names = (const char *[]){
2490 "array", NULL
2491 },
2492 .usage = "array NAME [VALUE...]",
2493 .desc = "Create a new array called NAME if it doesn't already exist. The array is initialized with the remaining parameters",
2494 .impl = cmd_array,
2495 .min_args = 1,
2496 .max_args = -1,
2497 .skip_eval = 1
2498 },
2499 {
2500 .names = (const char *[]){
2501 "append", NULL
2502 },
2503 .usage = "append NAME VALUE",
2504 .desc = "Increase the size of array NAME by 1 and set the last element to VALUE",
2505 .impl = cmd_append,
2506 .min_args = 2,
2507 .max_args = 2,
2508 .skip_eval = 1
2509 },
2510 {
2511 .names = (const char *[]){
2235 "frames", NULL 2512 "frames", NULL
2236 }, 2513 },
2237 .usage = "frames EXPRESSION", 2514 .usage = "frames EXPRESSION",
2238 .desc = "Resume execution for EXPRESSION video frames", 2515 .desc = "Resume execution for EXPRESSION video frames",
2239 .impl = cmd_frames, 2516 .impl = cmd_frames,
2865 case SYSTEM_GENESIS: 3142 case SYSTEM_GENESIS:
2866 case SYSTEM_SEGACD: 3143 case SYSTEM_SEGACD:
2867 //check if this is the main CPU 3144 //check if this is the main CPU
2868 if (context->system == current_system) { 3145 if (context->system == current_system) {
2869 root->resolve = resolve_genesis; 3146 root->resolve = resolve_genesis;
3147 root->array_resolve = resolve_genesis_array;
2870 add_commands(root, genesis_commands, NUM_GENESIS); 3148 add_commands(root, genesis_commands, NUM_GENESIS);
2871 if (current_system->type == SYSTEM_SEGACD) { 3149 if (current_system->type == SYSTEM_SEGACD) {
2872 add_segacd_maincpu_labels(root->disasm); 3150 add_segacd_maincpu_labels(root->disasm);
2873 add_commands(root, scd_main_commands, NUM_SCD_MAIN); 3151 add_commands(root, scd_main_commands, NUM_SCD_MAIN);
2874 } 3152 }
2877 add_segacd_subcpu_labels(root->disasm); 3155 add_segacd_subcpu_labels(root->disasm);
2878 add_commands(root, scd_sub_commands, NUM_SCD_SUB); 3156 add_commands(root, scd_sub_commands, NUM_SCD_SUB);
2879 } 3157 }
2880 default: 3158 default:
2881 root->resolve = resolve_m68k; 3159 root->resolve = resolve_m68k;
3160 root->array_resolve = resolve_null_array;
2882 } 3161 }
2883 tern_foreach(root->disasm->labels, symbol_map, root); 3162 tern_foreach(root->disasm->labels, symbol_map, root);
2884 } 3163 }
2885 return root; 3164 return root;
2886 } 3165 }
3395 add_commands(root, sms_commands, NUM_SMS); 3674 add_commands(root, sms_commands, NUM_SMS);
3396 break; 3675 break;
3397 default: 3676 default:
3398 root->resolve = resolve_z80; 3677 root->resolve = resolve_z80;
3399 } 3678 }
3679 root->array_resolve = resolve_null_array;
3400 root->read_mem = read_z80; 3680 root->read_mem = read_z80;
3401 root->write_mem = write_z80; 3681 root->write_mem = write_z80;
3402 root->set = set_z80; 3682 root->set = set_z80;
3403 root->disasm = create_z80_disasm(); 3683 root->disasm = create_z80_disasm();
3404 } 3684 }