comparison debug.c @ 2358:4b2ac43c106e

Give debugger expression engine access to VDP and Sub CPU values. Add basic variable support
author Michael Pavone <pavone@retrodev.com>
date Sat, 28 Oct 2023 00:52:10 -0700
parents 344c6a3fe8a8
children 04d29635d238
comparison
equal deleted inserted replaced
2357:344c6a3fe8a8 2358:4b2ac43c106e
631 if (e->op.type == TOKEN_NAME) { 631 if (e->op.type == TOKEN_NAME) {
632 if (root->resolve(root, e->op.v.str, out)) { 632 if (root->resolve(root, e->op.v.str, out)) {
633 return 1; 633 return 1;
634 } 634 }
635 tern_val v; 635 tern_val v;
636 if (tern_find(root->variables, e->op.v.str, &v)) {
637 *out = v.intval;
638 return 1;
639 }
636 if (tern_find(root->symbols, e->op.v.str, &v)) { 640 if (tern_find(root->symbols, e->op.v.str, &v)) {
637 *out = v.intval; 641 *out = v.intval;
638 return 1; 642 return 1;
639 } 643 }
640 return 0; 644 return 0;
823 } 827 }
824 } else if(!strcasecmp(name, "cycle")) { 828 } else if(!strcasecmp(name, "cycle")) {
825 *out = context->current_cycle; 829 *out = context->current_cycle;
826 } else if (!strcasecmp(name, "pc")) { 830 } else if (!strcasecmp(name, "pc")) {
827 *out = root->address; 831 *out = root->address;
832 } else if (!strcasecmp(name, "sp")) {
833 *out = context->aregs[7];
828 } else if (!strcasecmp(name, "usp")) { 834 } else if (!strcasecmp(name, "usp")) {
829 *out = context->status & 0x20 ? context->aregs[8] : context->aregs[7]; 835 *out = context->status & 0x20 ? context->aregs[8] : context->aregs[7];
830 } else if (!strcasecmp(name, "ssp")) { 836 } else if (!strcasecmp(name, "ssp")) {
831 *out = context->status & 0x20 ? context->aregs[7] : context->aregs[8]; 837 *out = context->status & 0x20 ? context->aregs[7] : context->aregs[8];
832 } else { 838 } else {
845 } else if (!strcasecmp(name, "sr")) { 851 } else if (!strcasecmp(name, "sr")) {
846 context->status = value >> 8; 852 context->status = value >> 8;
847 for (int flag = 0; flag < 5; flag++) { 853 for (int flag = 0; flag < 5; flag++) {
848 context->flags[flag] = (value & (1 << (4 - flag))) != 0; 854 context->flags[flag] = (value & (1 << (4 - flag))) != 0;
849 } 855 }
856 } else if (!strcasecmp(name, "sp")) {
857 context->aregs[7] = value;
850 } else if (!strcasecmp(name, "usp")) { 858 } else if (!strcasecmp(name, "usp")) {
851 context->aregs[context->status & 0x20 ? 8 : 7] = value; 859 context->aregs[context->status & 0x20 ? 8 : 7] = value;
852 } else if (!strcasecmp(name, "ssp")) { 860 } else if (!strcasecmp(name, "ssp")) {
853 context->aregs[context->status & 0x20 ? 7 : 8] = value; 861 context->aregs[context->status & 0x20 ? 7 : 8] = value;
854 } else { 862 } else {
855 return 0; 863 return 0;
856 } 864 }
857 return 1; 865 return 1;
858 } 866 }
859 867
868 static uint8_t resolve_vdp(debug_root *root, const char *name, uint32_t *out)
869 {
870 m68k_context *m68k = root->cpu_context;
871 genesis_context *gen = m68k->system;
872 vdp_context *vdp = gen->vdp;
873 if (!strcasecmp(name, "vcounter")) {
874 *out = vdp->vcounter;
875 } else if (!strcasecmp(name, "hcounter")) {
876 *out = vdp->hslot;
877 } else if (!strcasecmp(name, "address")) {
878 *out = vdp->address;
879 }else if (!strcasecmp(name, "cd")) {
880 *out = vdp->cd;
881 } else if (!strcasecmp(name, "status")) {
882 *out = vdp_status(vdp);
883 } else {
884 return 0;
885 }
886 return 1;
887 }
888
860 static uint8_t resolve_genesis(debug_root *root, const char *name, uint32_t *out) 889 static uint8_t resolve_genesis(debug_root *root, const char *name, uint32_t *out)
861 { 890 {
891
892 for (const char *cur = name; *cur; ++cur)
893 {
894 if (*cur == ':') {
895 if (cur - name == 3 && !memcmp(name, "vdp", 3)) {
896 return resolve_vdp(root, cur + 1, out);
897 } else if (cur - name == 3 && !memcmp(name, "sub", 3)) {
898 m68k_context *m68k = root->cpu_context;
899 genesis_context *gen = m68k->system;
900 if (gen->expansion) {
901 segacd_context *cd = gen->expansion;
902 root = find_m68k_root(cd->m68k);
903 return root->resolve(root, cur + 1, out);
904 } else {
905 return 0;
906 }
907 } else {
908 return 0;
909 }
910 }
911 }
862 if (resolve_m68k(root, name, out)) { 912 if (resolve_m68k(root, name, out)) {
863 return 1; 913 return 1;
864 } 914 }
865 m68k_context *m68k = root->cpu_context; 915 m68k_context *m68k = root->cpu_context;
866 genesis_context *gen = m68k->system; 916 genesis_context *gen = m68k->system;
1616 value |= old; 1666 value |= old;
1617 } 1667 }
1618 } 1668 }
1619 if (name) { 1669 if (name) {
1620 if (!root->set(root, name, value)) { 1670 if (!root->set(root, name, value)) {
1621 fprintf(stderr, "Failed to set %s\n", name); 1671 tern_val v;
1672 if (tern_find(root->variables, name, &v)) {
1673 root->variables = tern_insert_int(root->variables, name, value);
1674 } else {
1675 fprintf(stderr, "Failed to set %s\n", name);
1676 }
1622 } 1677 }
1623 } else if (!root->write_mem(root, address, value, size)) { 1678 } else if (!root->write_mem(root, address, value, size)) {
1624 fprintf(stderr, "Failed to write to address %X\n", address); 1679 fprintf(stderr, "Failed to write to address %X\n", address);
1625 } 1680 }
1681 return 1;
1682 }
1683
1684 static uint8_t cmd_variable(debug_root *root, parsed_command *cmd)
1685 {
1686 if (cmd->args[0].parsed->type != EXPR_SCALAR || cmd->args[0].parsed->op.type != TOKEN_NAME) {
1687 fprintf(stderr, "First argument to variable must be a name, got %s\n", expr_type_names[cmd->args[0].parsed->type]);
1688 return 1;
1689 }
1690 uint32_t value = 0;
1691 if (cmd->num_args > 1) {
1692 if (!eval_expr(root, cmd->args[1].parsed, &cmd->args[1].value)) {
1693 fprintf(stderr, "Failed to eval %s\n", cmd->args[1].raw);
1694 return 1;
1695 }
1696 value = cmd->args[1].value;
1697 }
1698 root->variables = tern_insert_int(root->variables, cmd->args[0].parsed->op.v.str, value);
1626 return 1; 1699 return 1;
1627 } 1700 }
1628 1701
1629 static uint8_t cmd_frames(debug_root *root, parsed_command *cmd) 1702 static uint8_t cmd_frames(debug_root *root, parsed_command *cmd)
1630 { 1703 {
2141 }, 2214 },
2142 .usage = "set MEM|NAME VALUE", 2215 .usage = "set MEM|NAME VALUE",
2143 .desc = "Set a register, symbol or memory location to the result of evaluating VALUE", 2216 .desc = "Set a register, symbol or memory location to the result of evaluating VALUE",
2144 .impl = cmd_set, 2217 .impl = cmd_set,
2145 .min_args = 2, 2218 .min_args = 2,
2219 .max_args = 2,
2220 .skip_eval = 1
2221 },
2222 {
2223 .names = (const char *[]){
2224 "variable", NULL
2225 },
2226 .usage = "variable NAME [VALUE]",
2227 .desc = "Create a new variable called NAME and set it to VALUE or 0 if no value provided",
2228 .impl = cmd_variable,
2229 .min_args = 1,
2146 .max_args = 2, 2230 .max_args = 2,
2147 .skip_eval = 1 2231 .skip_eval = 1
2148 }, 2232 },
2149 { 2233 {
2150 .names = (const char *[]){ 2234 .names = (const char *[]){