Mercurial > repos > blastem
comparison debug.c @ 2175:8c28c5466d70
Minor cleanup of debugger changes
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 06 Aug 2022 22:10:42 -0700 |
parents | eff7bedfc838 |
children | 44596610b2a0 |
comparison
equal
deleted
inserted
replaced
2174:eff7bedfc838 | 2175:8c28c5466d70 |
---|---|
624 *end = after_first; | 624 *end = after_first; |
625 return ret; | 625 return ret; |
626 } | 626 } |
627 } | 627 } |
628 | 628 |
629 typedef struct debug_context debug_context; | 629 uint8_t eval_expr(debug_root *root, expr *e, uint32_t *out) |
630 typedef uint8_t (*resolver)(debug_context *context, const char *name, uint32_t *out); | |
631 typedef uint8_t (*reader)(debug_context *context, uint32_t *out, char size); | |
632 | |
633 struct debug_context { | |
634 resolver resolve; | |
635 reader read_mem; | |
636 void *system; | |
637 uint32_t address; | |
638 }; | |
639 | |
640 uint8_t eval_expr(debug_context *context, expr *e, uint32_t *out) | |
641 { | 630 { |
642 uint32_t right; | 631 uint32_t right; |
643 switch(e->type) | 632 switch(e->type) |
644 { | 633 { |
645 case EXPR_SCALAR: | 634 case EXPR_SCALAR: |
646 if (e->op.type == TOKEN_NAME) { | 635 if (e->op.type == TOKEN_NAME) { |
647 return context->resolve(context, e->op.v.str, out); | 636 return root->resolve(root, e->op.v.str, out); |
648 } else { | 637 } else { |
649 *out = e->op.v.num; | 638 *out = e->op.v.num; |
650 return 1; | 639 return 1; |
651 } | 640 } |
652 case EXPR_UNARY: | 641 case EXPR_UNARY: |
653 if (!eval_expr(context, e->left, out)) { | 642 if (!eval_expr(root, e->left, out)) { |
654 return 0; | 643 return 0; |
655 } | 644 } |
656 switch (e->op.v.op[0]) | 645 switch (e->op.v.op[0]) |
657 { | 646 { |
658 case '!': | 647 case '!': |
667 default: | 656 default: |
668 return 0; | 657 return 0; |
669 } | 658 } |
670 return 1; | 659 return 1; |
671 case EXPR_BINARY: | 660 case EXPR_BINARY: |
672 if (!eval_expr(context, e->left, out) || !eval_expr(context, e->right, &right)) { | 661 if (!eval_expr(root, e->left, out) || !eval_expr(root, e->right, &right)) { |
673 return 0; | 662 return 0; |
674 } | 663 } |
675 switch (e->op.v.op[0]) | 664 switch (e->op.v.op[0]) |
676 { | 665 { |
677 case '+': | 666 case '+': |
704 default: | 693 default: |
705 return 0; | 694 return 0; |
706 } | 695 } |
707 return 1; | 696 return 1; |
708 case EXPR_SIZE: | 697 case EXPR_SIZE: |
709 if (!eval_expr(context, e->left, out)) { | 698 if (!eval_expr(root, e->left, out)) { |
710 return 0; | 699 return 0; |
711 } | 700 } |
712 switch (e->op.v.op[0]) | 701 switch (e->op.v.op[0]) |
713 { | 702 { |
714 case 'b': | 703 case 'b': |
718 *out &= 0xFFFF; | 707 *out &= 0xFFFF; |
719 break; | 708 break; |
720 } | 709 } |
721 return 1; | 710 return 1; |
722 case EXPR_MEM: | 711 case EXPR_MEM: |
723 if (!eval_expr(context, e->left, out)) { | 712 if (!eval_expr(root, e->left, out)) { |
724 return 0; | 713 return 0; |
725 } | 714 } |
726 return context->read_mem(context, out, e->op.v.op[0]); | 715 return root->read_mem(root, out, e->op.v.op[0]); |
727 default: | 716 default: |
728 return 0; | 717 return 0; |
729 } | 718 } |
730 } | 719 } |
731 | 720 |
789 static uint32_t m68k_read_long(uint32_t address, m68k_context *context) | 778 static uint32_t m68k_read_long(uint32_t address, m68k_context *context) |
790 { | 779 { |
791 return m68k_read_word(address, context) << 16 | m68k_read_word(address + 2, context); | 780 return m68k_read_word(address, context) << 16 | m68k_read_word(address + 2, context); |
792 } | 781 } |
793 | 782 |
794 static uint8_t read_m68k(m68k_context *context, uint32_t *out, char size) | 783 static uint8_t read_m68k(debug_root *root, uint32_t *out, char size) |
795 { | 784 { |
785 m68k_context *context = root->cpu_context; | |
796 if (size == 'b') { | 786 if (size == 'b') { |
797 *out = m68k_read_byte(*out, context); | 787 *out = m68k_read_byte(*out, context); |
798 } else if (size == 'l') { | 788 } else if (size == 'l') { |
799 *out = m68k_read_long(*out, context); | 789 *out = m68k_read_long(*out, context); |
800 } else { | 790 } else { |
801 *out = m68k_read_word(*out, context); | 791 *out = m68k_read_word(*out, context); |
802 } | 792 } |
803 return 1; | 793 return 1; |
804 } | 794 } |
805 | 795 |
806 static uint8_t read_genesis(debug_context *context, uint32_t *out, char size) | 796 static uint8_t resolve_m68k(debug_root *root, const char *name, uint32_t *out) |
807 { | 797 { |
808 genesis_context *gen = context->system; | 798 m68k_context *context = root->cpu_context; |
809 return read_m68k(gen->m68k, out, size); | |
810 } | |
811 | |
812 static uint8_t resolve_m68k(debug_context *debug, m68k_context *context, const char *name, uint32_t *out) | |
813 { | |
814 if ((name[0] == 'd' || name[0] == 'D') && name[1] >= '0' && name[1] <= '7' && !name[2]) { | 799 if ((name[0] == 'd' || name[0] == 'D') && name[1] >= '0' && name[1] <= '7' && !name[2]) { |
815 *out = context->dregs[name[1]-'0']; | 800 *out = context->dregs[name[1]-'0']; |
816 } else if ((name[0] == 'a' || name[0] == 'A') && name[1] >= '0' && name[1] <= '7' && !name[2]) { | 801 } else if ((name[0] == 'a' || name[0] == 'A') && name[1] >= '0' && name[1] <= '7' && !name[2]) { |
817 *out = context->aregs[name[1]-'0']; | 802 *out = context->aregs[name[1]-'0']; |
818 } else if (!strcasecmp(name, "sr")) { | 803 } else if (!strcasecmp(name, "sr")) { |
821 *out |= context->flags[flag] << (4-flag); | 806 *out |= context->flags[flag] << (4-flag); |
822 } | 807 } |
823 } else if(!strcasecmp(name, "cycle")) { | 808 } else if(!strcasecmp(name, "cycle")) { |
824 *out = context->current_cycle; | 809 *out = context->current_cycle; |
825 } else if (!strcasecmp(name, "pc")) { | 810 } else if (!strcasecmp(name, "pc")) { |
826 *out = debug->address; | 811 *out = root->address; |
827 } else if (!strcasecmp(name, "usp")) { | 812 } else if (!strcasecmp(name, "usp")) { |
828 *out = context->status & 0x20 ? context->aregs[8] : context->aregs[7]; | 813 *out = context->status & 0x20 ? context->aregs[8] : context->aregs[7]; |
829 } else if (!strcasecmp(name, "ssp")) { | 814 } else if (!strcasecmp(name, "ssp")) { |
830 *out = context->status & 0x20 ? context->aregs[7] : context->aregs[8]; | 815 *out = context->status & 0x20 ? context->aregs[7] : context->aregs[8]; |
831 } else { | 816 } else { |
832 return 0; | 817 return 0; |
833 } | 818 } |
834 return 1; | 819 return 1; |
835 } | 820 } |
836 | 821 |
837 static uint8_t resolve_genesis(debug_context *context, const char *name, uint32_t *out) | 822 static uint8_t resolve_genesis(debug_root *root, const char *name, uint32_t *out) |
838 { | 823 { |
839 genesis_context *gen = context->system; | 824 if (resolve_m68k(root, name, out)) { |
840 if (resolve_m68k(context, gen->m68k, name, out)) { | |
841 return 1; | 825 return 1; |
842 } | 826 } |
827 m68k_context *m68k = root->cpu_context; | |
828 genesis_context *gen = m68k->system; | |
843 if (!strcmp(name, "f") || !strcmp(name, "frame")) { | 829 if (!strcmp(name, "f") || !strcmp(name, "frame")) { |
844 *out = gen->vdp->frame; | 830 *out = gen->vdp->frame; |
845 return 1; | 831 return 1; |
846 } | 832 } |
847 return 0; | 833 return 0; |
848 } | 834 } |
849 | 835 |
850 void debugger_print(m68k_context *context, char format_char, char *param, uint32_t address) | 836 void debugger_print(debug_root *root, char format_char, char *param) |
851 { | 837 { |
852 uint32_t value; | 838 uint32_t value; |
853 char format[8]; | 839 char format[8]; |
854 strcpy(format, "%s: %d\n"); | 840 strcpy(format, "%s: %d\n"); |
855 switch (format_char) | 841 switch (format_char) |
864 case '\0': | 850 case '\0': |
865 break; | 851 break; |
866 default: | 852 default: |
867 fprintf(stderr, "Unrecognized format character: %c\n", format_char); | 853 fprintf(stderr, "Unrecognized format character: %c\n", format_char); |
868 } | 854 } |
869 debug_context c = { | |
870 .resolve = resolve_genesis, | |
871 .read_mem = read_genesis, | |
872 .system = context->system, | |
873 .address = address | |
874 }; | |
875 char *after; | 855 char *after; |
876 uint8_t at_least_one = 0; | 856 uint8_t at_least_one = 0; |
877 while (*param && *param != '\n') | 857 while (*param && *param != '\n') |
878 { | 858 { |
879 at_least_one = 1; | 859 at_least_one = 1; |
880 expr *e = parse_expression(param, &after); | 860 expr *e = parse_expression(param, &after); |
881 if (e) { | 861 if (e) { |
882 if (!eval_expr(&c, e, &value)) { | 862 if (!eval_expr(root, e, &value)) { |
883 fprintf(stderr, "Failed to eval %s\n", param); | 863 fprintf(stderr, "Failed to eval %s\n", param); |
884 } | 864 } |
885 free_expr(e); | 865 free_expr(e); |
886 } else { | 866 } else { |
887 fprintf(stderr, "Failed to parse %s\n", param); | 867 fprintf(stderr, "Failed to parse %s\n", param); |
893 if (format_char == 's') { | 873 if (format_char == 's') { |
894 char tmp[128]; | 874 char tmp[128]; |
895 int i; | 875 int i; |
896 for (i = 0; i < sizeof(tmp)-1; i++, value++) | 876 for (i = 0; i < sizeof(tmp)-1; i++, value++) |
897 { | 877 { |
898 char c = m68k_read_byte(value, context); | 878 uint32_t addr = value; |
879 root->read_mem(root, &addr, 'b'); | |
880 char c = addr; | |
899 if (c < 0x20 || c > 0x7F) { | 881 if (c < 0x20 || c > 0x7F) { |
900 break; | 882 break; |
901 } | 883 } |
902 tmp[i] = c; | 884 tmp[i] = c; |
903 } | 885 } |
1438 bp_def *new_bp, **this_bp; | 1420 bp_def *new_bp, **this_bp; |
1439 debug_root *root = find_root(context); | 1421 debug_root *root = find_root(context); |
1440 if (!root) { | 1422 if (!root) { |
1441 return 0; | 1423 return 0; |
1442 } | 1424 } |
1425 root->address = address; | |
1443 switch(input_buf[0]) | 1426 switch(input_buf[0]) |
1444 { | 1427 { |
1445 case 'c': | 1428 case 'c': |
1446 if (input_buf[1] == 0 || input_buf[1] == 'o' && input_buf[2] == 'n') | 1429 if (input_buf[1] == 0 || input_buf[1] == 'o' && input_buf[2] == 'n') |
1447 { | 1430 { |
1540 param = find_param(input_buf); | 1523 param = find_param(input_buf); |
1541 if (!param) { | 1524 if (!param) { |
1542 fputs("display command requires a parameter\n", stderr); | 1525 fputs("display command requires a parameter\n", stderr); |
1543 break; | 1526 break; |
1544 } | 1527 } |
1545 debugger_print(context, format_char, param, address); | 1528 debugger_print(root, format_char, param); |
1546 add_display(&root->displays, &root->disp_index, format_char, param); | 1529 add_display(&root->displays, &root->disp_index, format_char, param); |
1547 } else { | 1530 } else { |
1548 param = find_param(input_buf); | 1531 param = find_param(input_buf); |
1549 if (!param) { | 1532 if (!param) { |
1550 fputs("d command requires a parameter\n", stderr); | 1533 fputs("d command requires a parameter\n", stderr); |
1572 break; | 1555 break; |
1573 } | 1556 } |
1574 } | 1557 } |
1575 param = find_param(input_buf); | 1558 param = find_param(input_buf); |
1576 if (param) { | 1559 if (param) { |
1577 debugger_print(context, format_char, param, address); | 1560 debugger_print(root, format_char, param); |
1578 } else { | 1561 } else { |
1579 m68k_disasm(&inst, input_buf); | 1562 m68k_disasm(&inst, input_buf); |
1580 printf("%X: %s\n", address, input_buf); | 1563 printf("%X: %s\n", address, input_buf); |
1581 } | 1564 } |
1582 | 1565 |
1844 } | 1827 } |
1845 } else { | 1828 } else { |
1846 remove_breakpoint(context, address); | 1829 remove_breakpoint(context, address); |
1847 } | 1830 } |
1848 for (disp_def * cur = root->displays; cur; cur = cur->next) { | 1831 for (disp_def * cur = root->displays; cur; cur = cur->next) { |
1849 debugger_print(context, cur->format_char, cur->param, address); | 1832 debugger_print(root, cur->format_char, cur->param); |
1850 } | 1833 } |
1851 m68k_disasm(&inst, input_buf); | 1834 m68k_disasm(&inst, input_buf); |
1852 printf("%X: %s\n", address, input_buf); | 1835 printf("%X: %s\n", address, input_buf); |
1853 #ifdef _WIN32 | 1836 #ifdef _WIN32 |
1854 #define prompt 1 | 1837 #define prompt 1 |