Mercurial > repos > blastem
comparison debug.c @ 829:cc05444a4a4e
WIP debugger improvements. Partial support for display command in 68K debugger. Minor refactor to support commands on a breakpoint.
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 25 Sep 2015 18:12:55 -0700 |
parents | 792be135d3af |
children | 5a3ac6093ea2 |
comparison
equal
deleted
inserted
replaced
828:22c3c52b9871 | 829:cc05444a4a4e |
---|---|
84 if (*buf == '\n') { | 84 if (*buf == '\n') { |
85 *buf = 0; | 85 *buf = 0; |
86 return; | 86 return; |
87 } | 87 } |
88 } | 88 } |
89 } | |
90 | |
91 void debugger_print(m68k_context *context, char format_char, char *param) | |
92 { | |
93 uint32_t value; | |
94 char format[8]; | |
95 strcpy(format, "%s: %d\n"); | |
96 switch (format_char) | |
97 { | |
98 case 'x': | |
99 case 'X': | |
100 case 'd': | |
101 case 'c': | |
102 format[5] = format_char; | |
103 break; | |
104 case '\0': | |
105 break; | |
106 default: | |
107 fprintf(stderr, "Unrecognized format character: %c\n", format_char); | |
108 } | |
109 if (param[0] == 'd' && param[1] >= '0' && param[1] <= '7') { | |
110 value = context->dregs[param[1]-'0']; | |
111 } else if (param[0] == 'a' && param[1] >= '0' && param[1] <= '7') { | |
112 value = context->aregs[param[1]-'0']; | |
113 } else if (param[0] == 'S' && param[1] == 'R') { | |
114 value = (context->status << 8); | |
115 for (int flag = 0; flag < 5; flag++) { | |
116 value |= context->flags[flag] << (4-flag); | |
117 } | |
118 } else if(param[0] == 'c') { | |
119 value = context->current_cycle; | |
120 } else if ((param[0] == '0' && param[1] == 'x') || param[0] == '$') { | |
121 uint32_t p_addr = strtol(param+(param[0] == '0' ? 2 : 1), NULL, 16); | |
122 if ((p_addr & 0xFFFFFF) == 0xC00004) { | |
123 genesis_context * gen = context->system; | |
124 value = vdp_hv_counter_read(gen->vdp); | |
125 } else { | |
126 value = read_dma_value(p_addr/2); | |
127 } | |
128 } else { | |
129 fprintf(stderr, "Unrecognized parameter to p: %s\n", param); | |
130 return; | |
131 } | |
132 printf(format, param, value); | |
89 } | 133 } |
90 | 134 |
91 #ifndef NO_Z80 | 135 #ifndef NO_Z80 |
92 | 136 |
93 void zdebugger_print(z80_context * context, char format_char, char * param) | 137 void zdebugger_print(z80_context * context, char format_char, char * param) |
466 return context; | 510 return context; |
467 } | 511 } |
468 | 512 |
469 #endif | 513 #endif |
470 | 514 |
515 static uint32_t branch_t; | |
516 static uint32_t branch_f; | |
517 | |
518 int run_debugger_command(m68k_context *context, char *input_buf) | |
519 { | |
520 m68kinst inst; | |
521 char * param; | |
522 char format_char; | |
523 uint32_t value, after; | |
524 bp_def *new_bp, **this_bp; | |
525 switch(input_buf[0]) | |
526 { | |
527 case 'c': | |
528 printf("%X, %X\n", input_buf[1], input_buf[2]); | |
529 puts("Continuing"); | |
530 return 0; | |
531 case 'b': | |
532 if (input_buf[1] == 't') { | |
533 uint32_t stack = context->aregs[7]; | |
534 if (stack >= 0xE00000) { | |
535 stack &= 0xFFFF; | |
536 uint8_t non_adr_count = 0; | |
537 do { | |
538 uint32_t bt_address = ram[stack/2] << 16 | ram[stack/2+1]; | |
539 bt_address = get_instruction_start(context->native_code_map, bt_address - 2); | |
540 if (bt_address) { | |
541 stack += 4; | |
542 non_adr_count = 0; | |
543 uint16_t *bt_pc = NULL; | |
544 if (bt_address < 0x400000) { | |
545 bt_pc = cart + bt_address/2; | |
546 } else if(bt_address > 0xE00000) { | |
547 bt_pc = ram + (bt_address & 0xFFFF)/2; | |
548 } | |
549 m68k_decode(bt_pc, &inst, bt_address); | |
550 m68k_disasm(&inst, input_buf); | |
551 printf("%X: %s\n", bt_address, input_buf); | |
552 } else { | |
553 //non-return address value on stack can be word wide | |
554 stack += 2; | |
555 non_adr_count++; | |
556 } | |
557 stack &= 0xFFFF; | |
558 } while (stack && non_adr_count < 6); | |
559 } | |
560 } else { | |
561 param = find_param(input_buf); | |
562 if (!param) { | |
563 fputs("b command requires a parameter\n", stderr); | |
564 break; | |
565 } | |
566 value = strtol(param, NULL, 16); | |
567 insert_breakpoint(context, value, (uint8_t *)debugger); | |
568 new_bp = malloc(sizeof(bp_def)); | |
569 new_bp->next = breakpoints; | |
570 new_bp->address = value; | |
571 new_bp->index = bp_index++; | |
572 breakpoints = new_bp; | |
573 printf("68K Breakpoint %d set at %X\n", new_bp->index, value); | |
574 } | |
575 break; | |
576 case 'a': | |
577 param = find_param(input_buf); | |
578 if (!param) { | |
579 fputs("a command requires a parameter\n", stderr); | |
580 break; | |
581 } | |
582 value = strtol(param, NULL, 16); | |
583 insert_breakpoint(context, value, (uint8_t *)debugger); | |
584 return 0; | |
585 case 'd': | |
586 if (input_buf[1] == 'i') { | |
587 format_char = 0; | |
588 for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) { | |
589 if (input_buf[i] == '/') { | |
590 format_char = input_buf[i+1]; | |
591 break; | |
592 } | |
593 } | |
594 param = find_param(input_buf); | |
595 if (!param) { | |
596 fputs("display command requires a parameter\n", stderr); | |
597 break; | |
598 } | |
599 debugger_print(context, format_char, param); | |
600 add_display(&displays, &disp_index, format_char, param); | |
601 } else { | |
602 param = find_param(input_buf); | |
603 if (!param) { | |
604 fputs("d command requires a parameter\n", stderr); | |
605 break; | |
606 } | |
607 value = atoi(param); | |
608 this_bp = find_breakpoint_idx(&breakpoints, value); | |
609 if (!*this_bp) { | |
610 fprintf(stderr, "Breakpoint %d does not exist\n", value); | |
611 break; | |
612 } | |
613 new_bp = *this_bp; | |
614 *this_bp = (*this_bp)->next; | |
615 free(new_bp); | |
616 } | |
617 break; | |
618 case 'p': | |
619 format_char = 0; | |
620 for(int i = 2; input_buf[i] != 0 && input_buf[i] != ' '; i++) { | |
621 if (input_buf[i] == '/') { | |
622 format_char = input_buf[i+1]; | |
623 break; | |
624 } | |
625 } | |
626 param = find_param(input_buf); | |
627 if (!param) { | |
628 fputs("p command requires a parameter\n", stderr); | |
629 break; | |
630 } | |
631 debugger_print(context, format_char, param); | |
632 break; | |
633 case 'n': | |
634 if (inst.op == M68K_RTS) { | |
635 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); | |
636 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | |
637 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); | |
638 } else if(m68k_is_noncall_branch(&inst)) { | |
639 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { | |
640 branch_f = after; | |
641 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); | |
642 insert_breakpoint(context, branch_t, (uint8_t *)debugger); | |
643 } else if(inst.op == M68K_DBCC) { | |
644 if ( inst.extra.cond == COND_FALSE) { | |
645 if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) { | |
646 after = m68k_branch_target(&inst, context->dregs, context->aregs); | |
647 } | |
648 } else { | |
649 branch_t = after; | |
650 branch_f = m68k_branch_target(&inst, context->dregs, context->aregs); | |
651 insert_breakpoint(context, branch_f, (uint8_t *)debugger); | |
652 } | |
653 } else { | |
654 after = m68k_branch_target(&inst, context->dregs, context->aregs); | |
655 } | |
656 } | |
657 insert_breakpoint(context, after, (uint8_t *)debugger); | |
658 return 0; | |
659 case 'o': | |
660 if (inst.op == M68K_RTS) { | |
661 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); | |
662 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | |
663 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); | |
664 } else if(m68k_is_noncall_branch(&inst)) { | |
665 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { | |
666 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
667 if (branch_t < after) { | |
668 branch_t = 0; | |
669 } else { | |
670 branch_f = after; | |
671 insert_breakpoint(context, branch_t, (uint8_t *)debugger); | |
672 } | |
673 } else if(inst.op == M68K_DBCC) { | |
674 uint32_t target = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
675 if (target > after) { | |
676 if (inst.extra.cond == COND_FALSE) { | |
677 after = target; | |
678 } else { | |
679 branch_f = target; | |
680 branch_t = after; | |
681 insert_breakpoint(context, branch_f, (uint8_t *)debugger); | |
682 } | |
683 } | |
684 } else { | |
685 after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
686 } | |
687 } | |
688 insert_breakpoint(context, after, (uint8_t *)debugger); | |
689 return 0; | |
690 case 's': | |
691 if (inst.op == M68K_RTS) { | |
692 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); | |
693 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | |
694 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); | |
695 } else if(m68k_is_branch(&inst)) { | |
696 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { | |
697 branch_f = after; | |
698 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
699 insert_breakpoint(context, branch_t, (uint8_t *)debugger); | |
700 } else if(inst.op == M68K_DBCC && inst.extra.cond != COND_FALSE) { | |
701 branch_t = after; | |
702 branch_f = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
703 insert_breakpoint(context, branch_f, (uint8_t *)debugger); | |
704 } else { | |
705 after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
706 } | |
707 } | |
708 insert_breakpoint(context, after, (uint8_t *)debugger); | |
709 return 0; | |
710 case 'v': { | |
711 genesis_context * gen = context->system; | |
712 //VDP debug commands | |
713 switch(input_buf[1]) | |
714 { | |
715 case 's': | |
716 vdp_print_sprite_table(gen->vdp); | |
717 break; | |
718 case 'r': | |
719 vdp_print_reg_explain(gen->vdp); | |
720 break; | |
721 } | |
722 break; | |
723 } | |
724 case 'y': { | |
725 genesis_context * gen = context->system; | |
726 //YM-2612 debug commands | |
727 switch(input_buf[1]) | |
728 { | |
729 case 'c': | |
730 if (input_buf[2] == ' ') { | |
731 int channel = atoi(input_buf+3)-1; | |
732 ym_print_channel_info(gen->ym, channel); | |
733 } else { | |
734 for (int i = 0; i < 6; i++) { | |
735 ym_print_channel_info(gen->ym, i); | |
736 } | |
737 } | |
738 } | |
739 break; | |
740 } | |
741 #ifndef NO_Z80 | |
742 case 'z': { | |
743 genesis_context * gen = context->system; | |
744 //Z80 debug commands | |
745 switch(input_buf[1]) | |
746 { | |
747 case 'b': | |
748 param = find_param(input_buf); | |
749 if (!param) { | |
750 fputs("zb command requires a parameter\n", stderr); | |
751 break; | |
752 } | |
753 value = strtol(param, NULL, 16); | |
754 zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger); | |
755 new_bp = malloc(sizeof(bp_def)); | |
756 new_bp->next = zbreakpoints; | |
757 new_bp->address = value; | |
758 new_bp->index = zbp_index++; | |
759 zbreakpoints = new_bp; | |
760 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value); | |
761 break; | |
762 case 'p': | |
763 param = find_param(input_buf); | |
764 if (!param) { | |
765 fputs("zp command requires a parameter\n", stderr); | |
766 break; | |
767 } | |
768 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param); | |
769 } | |
770 break; | |
771 } | |
772 #endif | |
773 case 'q': | |
774 puts("Quitting"); | |
775 exit(0); | |
776 break; | |
777 default: | |
778 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf); | |
779 break; | |
780 } | |
781 return 1; | |
782 } | |
783 | |
784 | |
471 m68k_context * debugger(m68k_context * context, uint32_t address) | 785 m68k_context * debugger(m68k_context * context, uint32_t address) |
472 { | 786 { |
473 static char last_cmd[1024]; | 787 static char last_cmd[1024]; |
474 char input_buf[1024]; | 788 char input_buf[1024]; |
475 static uint32_t branch_t; | |
476 static uint32_t branch_f; | |
477 m68kinst inst; | 789 m68kinst inst; |
478 | 790 |
479 init_terminal(); | 791 init_terminal(); |
480 | 792 |
481 sync_components(context, 0); | 793 sync_components(context, 0); |
498 bp_def ** this_bp = find_breakpoint(&breakpoints, address); | 810 bp_def ** this_bp = find_breakpoint(&breakpoints, address); |
499 if (*this_bp) { | 811 if (*this_bp) { |
500 printf("68K Breakpoint %d hit\n", (*this_bp)->index); | 812 printf("68K Breakpoint %d hit\n", (*this_bp)->index); |
501 } else { | 813 } else { |
502 remove_breakpoint(context, address); | 814 remove_breakpoint(context, address); |
815 } | |
816 for (disp_def * cur = displays; cur; cur = cur->next) { | |
817 debugger_print(context, cur->format_char, cur->param); | |
503 } | 818 } |
504 uint16_t * pc; | 819 uint16_t * pc; |
505 if (address < 0x400000) { | 820 if (address < 0x400000) { |
506 pc = cart + address/2; | 821 pc = cart + address/2; |
507 } else if(address > 0xE00000) { | 822 } else if(address > 0xE00000) { |
548 if (input_buf[0]) { | 863 if (input_buf[0]) { |
549 strcpy(last_cmd, input_buf); | 864 strcpy(last_cmd, input_buf); |
550 } else { | 865 } else { |
551 strcpy(input_buf, last_cmd); | 866 strcpy(input_buf, last_cmd); |
552 } | 867 } |
553 char * param; | 868 debugging = run_debugger_command(context, input_buf); |
554 char format[8]; | |
555 uint32_t value; | |
556 bp_def * new_bp; | |
557 switch(input_buf[0]) | |
558 { | |
559 case 'c': | |
560 puts("Continuing"); | |
561 debugging = 0; | |
562 break; | |
563 case 'b': | |
564 if (input_buf[1] == 't') { | |
565 uint32_t stack = context->aregs[7]; | |
566 if (stack >= 0xE00000) { | |
567 stack &= 0xFFFF; | |
568 uint8_t non_adr_count = 0; | |
569 do { | |
570 uint32_t bt_address = ram[stack/2] << 16 | ram[stack/2+1]; | |
571 bt_address = get_instruction_start(context->native_code_map, bt_address - 2); | |
572 if (bt_address) { | |
573 stack += 4; | |
574 non_adr_count = 0; | |
575 uint16_t *bt_pc = NULL; | |
576 if (bt_address < 0x400000) { | |
577 bt_pc = cart + bt_address/2; | |
578 } else if(bt_address > 0xE00000) { | |
579 bt_pc = ram + (bt_address & 0xFFFF)/2; | |
580 } | |
581 m68k_decode(bt_pc, &inst, bt_address); | |
582 m68k_disasm(&inst, input_buf); | |
583 printf("%X: %s\n", bt_address, input_buf); | |
584 } else { | |
585 //non-return address value on stack can be word wide | |
586 stack += 2; | |
587 non_adr_count++; | |
588 } | |
589 stack &= 0xFFFF; | |
590 } while (stack && non_adr_count < 6); | |
591 } | |
592 } else { | |
593 param = find_param(input_buf); | |
594 if (!param) { | |
595 fputs("b command requires a parameter\n", stderr); | |
596 break; | |
597 } | |
598 value = strtol(param, NULL, 16); | |
599 insert_breakpoint(context, value, (uint8_t *)debugger); | |
600 new_bp = malloc(sizeof(bp_def)); | |
601 new_bp->next = breakpoints; | |
602 new_bp->address = value; | |
603 new_bp->index = bp_index++; | |
604 breakpoints = new_bp; | |
605 printf("68K Breakpoint %d set at %X\n", new_bp->index, value); | |
606 } | |
607 break; | |
608 case 'a': | |
609 param = find_param(input_buf); | |
610 if (!param) { | |
611 fputs("a command requires a parameter\n", stderr); | |
612 break; | |
613 } | |
614 value = strtol(param, NULL, 16); | |
615 insert_breakpoint(context, value, (uint8_t *)debugger); | |
616 debugging = 0; | |
617 break; | |
618 case 'd': | |
619 param = find_param(input_buf); | |
620 if (!param) { | |
621 fputs("d command requires a parameter\n", stderr); | |
622 break; | |
623 } | |
624 value = atoi(param); | |
625 this_bp = find_breakpoint_idx(&breakpoints, value); | |
626 if (!*this_bp) { | |
627 fprintf(stderr, "Breakpoint %d does not exist\n", value); | |
628 break; | |
629 } | |
630 new_bp = *this_bp; | |
631 *this_bp = (*this_bp)->next; | |
632 free(new_bp); | |
633 break; | |
634 case 'p': | |
635 strcpy(format, "%s: %d\n"); | |
636 if (input_buf[1] == '/') { | |
637 switch (input_buf[2]) | |
638 { | |
639 case 'x': | |
640 case 'X': | |
641 case 'd': | |
642 case 'c': | |
643 format[5] = input_buf[2]; | |
644 break; | |
645 default: | |
646 fprintf(stderr, "Unrecognized format character: %c\n", input_buf[2]); | |
647 } | |
648 } | |
649 param = find_param(input_buf); | |
650 if (!param) { | |
651 fputs("p command requires a parameter\n", stderr); | |
652 break; | |
653 } | |
654 if (param[0] == 'd' && param[1] >= '0' && param[1] <= '7') { | |
655 value = context->dregs[param[1]-'0']; | |
656 } else if (param[0] == 'a' && param[1] >= '0' && param[1] <= '7') { | |
657 value = context->aregs[param[1]-'0']; | |
658 } else if (param[0] == 'S' && param[1] == 'R') { | |
659 value = (context->status << 8); | |
660 for (int flag = 0; flag < 5; flag++) { | |
661 value |= context->flags[flag] << (4-flag); | |
662 } | |
663 } else if(param[0] == 'c') { | |
664 value = context->current_cycle; | |
665 } else if ((param[0] == '0' && param[1] == 'x') || param[0] == '$') { | |
666 uint32_t p_addr = strtol(param+(param[0] == '0' ? 2 : 1), NULL, 16); | |
667 if ((p_addr & 0xFFFFFF) == 0xC00004) { | |
668 genesis_context * gen = context->system; | |
669 value = vdp_hv_counter_read(gen->vdp); | |
670 } else { | |
671 value = read_dma_value(p_addr/2); | |
672 } | |
673 } else { | |
674 fprintf(stderr, "Unrecognized parameter to p: %s\n", param); | |
675 break; | |
676 } | |
677 printf(format, param, value); | |
678 break; | |
679 case 'n': | |
680 if (inst.op == M68K_RTS) { | |
681 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); | |
682 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | |
683 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); | |
684 } else if(m68k_is_noncall_branch(&inst)) { | |
685 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { | |
686 branch_f = after; | |
687 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs); | |
688 insert_breakpoint(context, branch_t, (uint8_t *)debugger); | |
689 } else if(inst.op == M68K_DBCC) { | |
690 if ( inst.extra.cond == COND_FALSE) { | |
691 if (context->dregs[inst.dst.params.regs.pri] & 0xFFFF) { | |
692 after = m68k_branch_target(&inst, context->dregs, context->aregs); | |
693 } | |
694 } else { | |
695 branch_t = after; | |
696 branch_f = m68k_branch_target(&inst, context->dregs, context->aregs); | |
697 insert_breakpoint(context, branch_f, (uint8_t *)debugger); | |
698 } | |
699 } else { | |
700 after = m68k_branch_target(&inst, context->dregs, context->aregs); | |
701 } | |
702 } | |
703 insert_breakpoint(context, after, (uint8_t *)debugger); | |
704 debugging = 0; | |
705 break; | |
706 case 'o': | |
707 if (inst.op == M68K_RTS) { | |
708 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); | |
709 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | |
710 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); | |
711 } else if(m68k_is_noncall_branch(&inst)) { | |
712 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { | |
713 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
714 if (branch_t < after) { | |
715 branch_t = 0; | |
716 } else { | |
717 branch_f = after; | |
718 insert_breakpoint(context, branch_t, (uint8_t *)debugger); | |
719 } | |
720 } else if(inst.op == M68K_DBCC) { | |
721 uint32_t target = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
722 if (target > after) { | |
723 if (inst.extra.cond == COND_FALSE) { | |
724 after = target; | |
725 } else { | |
726 branch_f = target; | |
727 branch_t = after; | |
728 insert_breakpoint(context, branch_f, (uint8_t *)debugger); | |
729 } | |
730 } | |
731 } else { | |
732 after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
733 } | |
734 } | |
735 insert_breakpoint(context, after, (uint8_t *)debugger); | |
736 debugging = 0; | |
737 break; | |
738 case 's': | |
739 if (inst.op == M68K_RTS) { | |
740 after = (read_dma_value(context->aregs[7]/2) << 16) | read_dma_value(context->aregs[7]/2 + 1); | |
741 } else if (inst.op == M68K_RTE || inst.op == M68K_RTR) { | |
742 after = (read_dma_value((context->aregs[7]+2)/2) << 16) | read_dma_value((context->aregs[7]+2)/2 + 1); | |
743 } else if(m68k_is_branch(&inst)) { | |
744 if (inst.op == M68K_BCC && inst.extra.cond != COND_TRUE) { | |
745 branch_f = after; | |
746 branch_t = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
747 insert_breakpoint(context, branch_t, (uint8_t *)debugger); | |
748 } else if(inst.op == M68K_DBCC && inst.extra.cond != COND_FALSE) { | |
749 branch_t = after; | |
750 branch_f = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
751 insert_breakpoint(context, branch_f, (uint8_t *)debugger); | |
752 } else { | |
753 after = m68k_branch_target(&inst, context->dregs, context->aregs) & 0xFFFFFF; | |
754 } | |
755 } | |
756 insert_breakpoint(context, after, (uint8_t *)debugger); | |
757 debugging = 0; | |
758 break; | |
759 case 'v': { | |
760 genesis_context * gen = context->system; | |
761 //VDP debug commands | |
762 switch(input_buf[1]) | |
763 { | |
764 case 's': | |
765 vdp_print_sprite_table(gen->vdp); | |
766 break; | |
767 case 'r': | |
768 vdp_print_reg_explain(gen->vdp); | |
769 break; | |
770 } | |
771 break; | |
772 } | |
773 case 'y': { | |
774 genesis_context * gen = context->system; | |
775 //YM-2612 debug commands | |
776 switch(input_buf[1]) | |
777 { | |
778 case 'c': | |
779 if (input_buf[2] == ' ') { | |
780 int channel = atoi(input_buf+3)-1; | |
781 ym_print_channel_info(gen->ym, channel); | |
782 } else { | |
783 for (int i = 0; i < 6; i++) { | |
784 ym_print_channel_info(gen->ym, i); | |
785 } | |
786 } | |
787 } | |
788 break; | |
789 } | |
790 #ifndef NO_Z80 | |
791 case 'z': { | |
792 genesis_context * gen = context->system; | |
793 //Z80 debug commands | |
794 switch(input_buf[1]) | |
795 { | |
796 case 'b': | |
797 param = find_param(input_buf); | |
798 if (!param) { | |
799 fputs("zb command requires a parameter\n", stderr); | |
800 break; | |
801 } | |
802 value = strtol(param, NULL, 16); | |
803 zinsert_breakpoint(gen->z80, value, (uint8_t *)zdebugger); | |
804 new_bp = malloc(sizeof(bp_def)); | |
805 new_bp->next = zbreakpoints; | |
806 new_bp->address = value; | |
807 new_bp->index = zbp_index++; | |
808 zbreakpoints = new_bp; | |
809 printf("Z80 Breakpoint %d set at %X\n", new_bp->index, value); | |
810 break; | |
811 case 'p': | |
812 param = find_param(input_buf); | |
813 if (!param) { | |
814 fputs("zp command requires a parameter\n", stderr); | |
815 break; | |
816 } | |
817 zdebugger_print(gen->z80, input_buf[2] == '/' ? input_buf[3] : 0, param); | |
818 } | |
819 break; | |
820 } | |
821 #endif | |
822 case 'q': | |
823 puts("Quitting"); | |
824 exit(0); | |
825 break; | |
826 default: | |
827 fprintf(stderr, "Unrecognized debugger command %s\n", input_buf); | |
828 break; | |
829 } | |
830 } | 869 } |
831 return context; | 870 return context; |
832 } | 871 } |