Mercurial > repos > blastem
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; |