comparison m68k_core.c @ 1329:85a90964b557

Fix interaction between 68K debugger and instruction retranslation due to self modifying code or bank switching
author Michael Pavone <pavone@retrodev.com>
date Mon, 24 Apr 2017 20:49:31 -0700
parents c9dc2603b087
children f1607874dbee
comparison
equal deleted inserted replaced
1328:70faad89d491 1329:85a90964b557
778 } 778 }
779 fprintf(stderr, "M68K: Failed to calculate value of IR. Last prefetch address: %X\n", context->last_prefetch_address); 779 fprintf(stderr, "M68K: Failed to calculate value of IR. Last prefetch address: %X\n", context->last_prefetch_address);
780 return 0xFFFF; 780 return 0xFFFF;
781 } 781 }
782 782
783 static m68k_debug_handler find_breakpoint(m68k_context *context, uint32_t address)
784 {
785 for (uint32_t i = 0; i < context->num_breakpoints; i++)
786 {
787 if (context->breakpoints[i].address == address) {
788 return context->breakpoints[i].handler;
789 }
790 }
791 return NULL;
792 }
793
794 void insert_breakpoint(m68k_context * context, uint32_t address, m68k_debug_handler bp_handler)
795 {
796 if (!find_breakpoint(context, address)) {
797 if (context->bp_storage == context->num_breakpoints) {
798 context->bp_storage *= 2;
799 if (context->bp_storage < 4) {
800 context->bp_storage = 4;
801 }
802 context->breakpoints = realloc(context->breakpoints, context->bp_storage * sizeof(m68k_breakpoint));
803 }
804 context->breakpoints[context->num_breakpoints++] = (m68k_breakpoint){
805 .handler = bp_handler,
806 .address = address
807 };
808 m68k_breakpoint_patch(context, address, bp_handler, NULL);
809 }
810 }
811
812 m68k_context *m68k_bp_dispatcher(m68k_context *context, uint32_t address)
813 {
814 m68k_debug_handler handler = find_breakpoint(context, address);
815 if (handler) {
816 handler(context, address);
817 } else {
818 //spurious breakoint?
819 warning("Spurious breakpoing at %X\n", address);
820 remove_breakpoint(context, address);
821 }
822
823 return context;
824 }
825
783 typedef enum { 826 typedef enum {
784 RAW_FUNC = 1, 827 RAW_FUNC = 1,
785 BINARY_ARITH, 828 BINARY_ARITH,
786 UNARY_ARITH, 829 UNARY_ARITH,
787 OP_FUNC 830 OP_FUNC
893 RAW_IMPL(M68K_NOP, translate_m68k_nop), 936 RAW_IMPL(M68K_NOP, translate_m68k_nop),
894 RAW_IMPL(M68K_RESET, translate_m68k_reset), 937 RAW_IMPL(M68K_RESET, translate_m68k_reset),
895 RAW_IMPL(M68K_TAS, translate_m68k_tas), 938 RAW_IMPL(M68K_TAS, translate_m68k_tas),
896 }; 939 };
897 940
898 static void translate_m68k(m68k_options * opts, m68kinst * inst) 941 static void translate_m68k(m68k_context *context, m68kinst * inst)
899 { 942 {
943 m68k_options * opts = context->options;
900 if (inst->address & 1) { 944 if (inst->address & 1) {
901 translate_m68k_odd(opts, inst); 945 translate_m68k_odd(opts, inst);
902 return; 946 return;
903 } 947 }
948 code_ptr start = opts->gen.code.cur;
904 check_cycles_int(&opts->gen, inst->address); 949 check_cycles_int(&opts->gen, inst->address);
950
951 m68k_debug_handler bp;
952 if ((bp = find_breakpoint(context, inst->address))) {
953 m68k_breakpoint_patch(context, inst->address, bp, start);
954 }
955
905 //log_address(&opts->gen, inst->address, "M68K: %X @ %d\n"); 956 //log_address(&opts->gen, inst->address, "M68K: %X @ %d\n");
906 if ( 957 if (
907 (inst->src.addr_mode > MODE_AREG && inst->src.addr_mode < MODE_IMMEDIATE) 958 (inst->src.addr_mode > MODE_AREG && inst->src.addr_mode < MODE_IMMEDIATE)
908 || (inst->dst.addr_mode > MODE_AREG && inst->dst.addr_mode < MODE_IMMEDIATE) 959 || (inst->dst.addr_mode > MODE_AREG && inst->dst.addr_mode < MODE_IMMEDIATE)
909 || (inst->op == M68K_BCC && (inst->src.params.immed & 1)) 960 || (inst->op == M68K_BCC && (inst->src.params.immed & 1))
979 //printf("%X: %s\n", instbuf.address, disbuf); 1030 //printf("%X: %s\n", instbuf.address, disbuf);
980 1031
981 //make sure the beginning of the code for an instruction is contiguous 1032 //make sure the beginning of the code for an instruction is contiguous
982 check_code_prologue(code); 1033 check_code_prologue(code);
983 code_ptr start = code->cur; 1034 code_ptr start = code->cur;
984 translate_m68k(opts, &instbuf); 1035 translate_m68k(context, &instbuf);
985 code_ptr after = code->cur; 1036 code_ptr after = code->cur;
986 map_native_address(context, instbuf.address, start, m68k_size, after-start); 1037 map_native_address(context, instbuf.address, start, m68k_size, after-start);
987 } while(!m68k_is_terminal(&instbuf) && !(address & 1)); 1038 } while(!m68k_is_terminal(&instbuf) && !(address & 1));
988 process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context); 1039 process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context);
989 if (opts->gen.deferred) { 1040 if (opts->gen.deferred) {
1007 deferred_addr * orig_deferred = opts->gen.deferred; 1058 deferred_addr * orig_deferred = opts->gen.deferred;
1008 1059
1009 //make sure we have enough code space for the max size instruction 1060 //make sure we have enough code space for the max size instruction
1010 check_alloc_code(code, MAX_NATIVE_SIZE); 1061 check_alloc_code(code, MAX_NATIVE_SIZE);
1011 code_ptr native_start = code->cur; 1062 code_ptr native_start = code->cur;
1012 translate_m68k(opts, &instbuf); 1063 translate_m68k(context, &instbuf);
1013 code_ptr native_end = code->cur; 1064 code_ptr native_end = code->cur;
1014 /*uint8_t is_terminal = m68k_is_terminal(&instbuf); 1065 /*uint8_t is_terminal = m68k_is_terminal(&instbuf);
1015 if ((native_end - native_start) <= orig_size) { 1066 if ((native_end - native_start) <= orig_size) {
1016 code_ptr native_next; 1067 code_ptr native_next;
1017 if (!is_terminal) { 1068 if (!is_terminal) {
1023 code_info tmp; 1074 code_info tmp;
1024 tmp.cur = code->cur; 1075 tmp.cur = code->cur;
1025 tmp.last = code->last; 1076 tmp.last = code->last;
1026 code->cur = orig_code.cur; 1077 code->cur = orig_code.cur;
1027 code->last = orig_code.last; 1078 code->last = orig_code.last;
1028 translate_m68k(opts, &instbuf); 1079 translate_m68k(context, &instbuf);
1029 native_end = orig_code.cur = code->cur; 1080 native_end = orig_code.cur = code->cur;
1030 code->cur = tmp.cur; 1081 code->cur = tmp.cur;
1031 code->last = tmp.last; 1082 code->last = tmp.last;
1032 if (!is_terminal) { 1083 if (!is_terminal) {
1033 nop_fill_or_jmp_next(&orig_code, orig_start + orig_size, native_next); 1084 nop_fill_or_jmp_next(&orig_code, orig_start + orig_size, native_next);
1054 m68k_handle_deferred(context); 1105 m68k_handle_deferred(context);
1055 return native_start; 1106 return native_start;
1056 } else { 1107 } else {
1057 code_info tmp = *code; 1108 code_info tmp = *code;
1058 *code = orig_code; 1109 *code = orig_code;
1059 translate_m68k(opts, &instbuf); 1110 translate_m68k(context, &instbuf);
1060 orig_code = *code; 1111 orig_code = *code;
1061 *code = tmp; 1112 *code = tmp;
1062 if (!m68k_is_terminal(&instbuf)) { 1113 if (!m68k_is_terminal(&instbuf)) {
1063 jmp(&orig_code, get_native_address_trans(context, orig + (after-inst)*2)); 1114 jmp(&orig_code, get_native_address_trans(context, orig + (after-inst)*2));
1064 } 1115 }
1077 return ret; 1128 return ret;
1078 } 1129 }
1079 1130
1080 void remove_breakpoint(m68k_context * context, uint32_t address) 1131 void remove_breakpoint(m68k_context * context, uint32_t address)
1081 { 1132 {
1133 for (uint32_t i = 0; i < context->num_breakpoints; i++)
1134 {
1135 if (context->breakpoints[i].address == address) {
1136 if (i != (context->num_breakpoints-1)) {
1137 context->breakpoints[i] = context->breakpoints[context->num_breakpoints-1];
1138 }
1139 context->num_breakpoints--;
1140 break;
1141 }
1142 }
1082 code_ptr native = get_native_address(context->options, address); 1143 code_ptr native = get_native_address(context->options, address);
1144 if (!native) {
1145 return;
1146 }
1083 code_info tmp = context->options->gen.code; 1147 code_info tmp = context->options->gen.code;
1084 context->options->gen.code.cur = native; 1148 context->options->gen.code.cur = native;
1085 context->options->gen.code.last = native + MAX_NATIVE_SIZE; 1149 context->options->gen.code.last = native + MAX_NATIVE_SIZE;
1086 check_cycles_int(&context->options->gen, address); 1150 check_cycles_int(&context->options->gen, address);
1087 context->options->gen.code = tmp; 1151 context->options->gen.code = tmp;