comparison m68k_core.c @ 2499:d74d3998482c

Make some progress on compiling full emulator with new 68K core
author Michael Pavone <pavone@retrodev.com>
date Tue, 30 Apr 2024 00:02:14 -0700
parents 767ec72acca7
children 9df8dec435b7
comparison
equal deleted inserted replaced
2498:dffda054d218 2499:d74d3998482c
665 return native_code_map[chunk].base + native_code_map[chunk].offsets[offset]; 665 return native_code_map[chunk].base + native_code_map[chunk].offsets[offset];
666 } 666 }
667 667
668 code_ptr get_native_from_context(m68k_context * context, uint32_t address) 668 code_ptr get_native_from_context(m68k_context * context, uint32_t address)
669 { 669 {
670 return get_native_address(context->options, address); 670 return get_native_address(context->opts, address);
671 } 671 }
672 672
673 uint32_t get_instruction_start(m68k_options *opts, uint32_t address) 673 uint32_t get_instruction_start(m68k_options *opts, uint32_t address)
674 { 674 {
675 native_map_slot * native_code_map = opts->gen.native_code_map; 675 native_map_slot * native_code_map = opts->gen.native_code_map;
698 return address; 698 return address;
699 } 699 }
700 700
701 static void map_native_address(m68k_context * context, uint32_t address, code_ptr native_addr, uint8_t size, uint8_t native_size) 701 static void map_native_address(m68k_context * context, uint32_t address, code_ptr native_addr, uint8_t size, uint8_t native_size)
702 { 702 {
703 m68k_options * opts = context->options; 703 m68k_options * opts = context->opts;
704 native_map_slot * native_code_map = opts->gen.native_code_map; 704 native_map_slot * native_code_map = opts->gen.native_code_map;
705 uint32_t meta_off; 705 uint32_t meta_off;
706 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off); 706 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, MMAP_CODE, &meta_off);
707 if (mem_chunk) { 707 if (mem_chunk) {
708 if (mem_chunk->flags & MMAP_CODE) { 708 if (mem_chunk->flags & MMAP_CODE) {
772 || (inst->op == M68K_BCC && inst->extra.cond == COND_TRUE); 772 || (inst->op == M68K_BCC && inst->extra.cond == COND_TRUE);
773 } 773 }
774 774
775 static void m68k_handle_deferred(m68k_context * context) 775 static void m68k_handle_deferred(m68k_context * context)
776 { 776 {
777 m68k_options * opts = context->options; 777 m68k_options * opts = context->opts;
778 process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context); 778 process_deferred(&opts->gen.deferred, context, (native_addr_func)get_native_from_context);
779 if (opts->gen.deferred) { 779 if (opts->gen.deferred) {
780 translate_m68k_stream(opts->gen.deferred->address, context); 780 translate_m68k_stream(opts->gen.deferred->address, context);
781 } 781 }
782 } 782 }
783 783
784 uint16_t m68k_get_ir(m68k_context *context) 784 uint16_t m68k_get_ir(m68k_context *context)
785 { 785 {
786 uint32_t inst_addr = get_instruction_start(context->options, context->last_prefetch_address-2); 786 uint32_t inst_addr = get_instruction_start(context->opts, context->last_prefetch_address-2);
787 uint16_t *native_addr = get_native_pointer(inst_addr, (void **)context->mem_pointers, &context->options->gen); 787 uint16_t *native_addr = get_native_pointer(inst_addr, (void **)context->mem_pointers, &context->opts->gen);
788 if (native_addr) { 788 if (native_addr) {
789 return *native_addr; 789 return *native_addr;
790 } 790 }
791 fprintf(stderr, "M68K: Failed to calculate value of IR. Last prefetch address: %X\n", context->last_prefetch_address); 791 fprintf(stderr, "M68K: Failed to calculate value of IR. Last prefetch address: %X\n", context->last_prefetch_address);
792 return 0xFFFF; 792 return 0xFFFF;
852 m68k_watchpoint *watch = m68k_find_watchpoint(address, context); 852 m68k_watchpoint *watch = m68k_find_watchpoint(address, context);
853 if (!watch) { 853 if (!watch) {
854 return vcontext; 854 return vcontext;
855 } 855 }
856 if (watch->check_change) { 856 if (watch->check_change) {
857 uint16_t old = read_word(address, (void **)context->mem_pointers, &context->options->gen, context); 857 uint16_t old = read_word(address, (void **)context->mem_pointers, &context->opts->gen, context);
858 if (old == value) { 858 if (old == value) {
859 return vcontext; 859 return vcontext;
860 } 860 }
861 context->wp_old_value = old; 861 context->wp_old_value = old;
862 } else { 862 } else {
863 context->wp_old_value = value; 863 context->wp_old_value = value;
864 } 864 }
865 context->wp_hit_address = address; 865 context->wp_hit_address = address;
866 context->wp_hit_value = value; 866 context->wp_hit_value = value;
867 context->wp_hit = 1; 867 context->wp_hit = 1;
868 context->target_cycle = context->sync_cycle = context->current_cycle; 868 context->target_cycle = context->sync_cycle = context->cycles;
869 system_header *system = context->system; 869 system_header *system = context->system;
870 return vcontext; 870 return vcontext;
871 } 871 }
872 872
873 static void *m68k_watchpoint_check8(uint32_t address, void *vcontext, uint8_t value) 873 static void *m68k_watchpoint_check8(uint32_t address, void *vcontext, uint8_t value)
876 m68k_watchpoint *watch = m68k_find_watchpoint(address, context); 876 m68k_watchpoint *watch = m68k_find_watchpoint(address, context);
877 if (!watch) { 877 if (!watch) {
878 return vcontext; 878 return vcontext;
879 } 879 }
880 if (watch->check_change) { 880 if (watch->check_change) {
881 uint8_t old = read_byte(address, (void **)context->mem_pointers, &context->options->gen, context); 881 uint8_t old = read_byte(address, (void **)context->mem_pointers, &context->opts->gen, context);
882 if (old == value) { 882 if (old == value) {
883 return vcontext; 883 return vcontext;
884 } 884 }
885 context->wp_old_value = old; 885 context->wp_old_value = old;
886 } else { 886 } else {
887 context->wp_old_value = value; 887 context->wp_old_value = value;
888 } 888 }
889 context->wp_hit_address = address; 889 context->wp_hit_address = address;
890 context->wp_hit_value = value; 890 context->wp_hit_value = value;
891 context->wp_hit = 1; 891 context->wp_hit = 1;
892 context->target_cycle = context->sync_cycle = context->current_cycle; 892 context->target_cycle = context->sync_cycle = context->cycles;
893 system_header *system = context->system; 893 system_header *system = context->system;
894 return vcontext; 894 return vcontext;
895 } 895 }
896 896
897 static void m68k_enable_watchpoints(m68k_context *context) 897 static void m68k_enable_watchpoints(m68k_context *context)
898 { 898 {
899 if (context->options->gen.check_watchpoints_16) { 899 if (context->opts->gen.check_watchpoints_16) {
900 //already enabled 900 //already enabled
901 return; 901 return;
902 } 902 }
903 context->options->gen.check_watchpoints_16 = m68k_watchpoint_check16; 903 context->opts->gen.check_watchpoints_16 = m68k_watchpoint_check16;
904 context->options->gen.check_watchpoints_8 = m68k_watchpoint_check8; 904 context->opts->gen.check_watchpoints_8 = m68k_watchpoint_check8;
905 //re-generate write handlers with watchpoints enabled 905 //re-generate write handlers with watchpoints enabled
906 code_ptr new_write16 = gen_mem_fun(&context->options->gen, context->options->gen.memmap, context->options->gen.memmap_chunks, WRITE_16, NULL); 906 code_ptr new_write16 = gen_mem_fun(&context->opts->gen, context->opts->gen.memmap, context->opts->gen.memmap_chunks, WRITE_16, NULL);
907 code_ptr new_write8 = gen_mem_fun(&context->options->gen, context->options->gen.memmap, context->options->gen.memmap_chunks, WRITE_8, NULL); 907 code_ptr new_write8 = gen_mem_fun(&context->opts->gen, context->opts->gen.memmap, context->opts->gen.memmap_chunks, WRITE_8, NULL);
908 908
909 //patch old write handlers to point to the new ones 909 //patch old write handlers to point to the new ones
910 code_info code = { 910 code_info code = {
911 .cur = context->options->write_16, 911 .cur = context->opts->write_16,
912 .last = context->options->write_16 + 256 912 .last = context->opts->write_16 + 256
913 }; 913 };
914 jmp(&code, new_write16); 914 jmp(&code, new_write16);
915 code.cur = context->options->write_8; 915 code.cur = context->opts->write_8;
916 code.last = code.cur + 256; 916 code.last = code.cur + 256;
917 jmp(&code, new_write8); 917 jmp(&code, new_write8);
918 context->options->write_16 = new_write16; 918 context->opts->write_16 = new_write16;
919 context->options->write_8 = new_write8; 919 context->opts->write_8 = new_write8;
920 } 920 }
921 921
922 void m68k_add_watchpoint(m68k_context *context, uint32_t address, uint32_t size) 922 void m68k_add_watchpoint(m68k_context *context, uint32_t address, uint32_t size)
923 { 923 {
924 uint32_t end = address + size - 1; 924 uint32_t end = address + size - 1;
931 m68k_enable_watchpoints(context); 931 m68k_enable_watchpoints(context);
932 if (context->wp_storage == context->num_watchpoints) { 932 if (context->wp_storage == context->num_watchpoints) {
933 context->wp_storage = context->wp_storage ? context->wp_storage * 2 : 4; 933 context->wp_storage = context->wp_storage ? context->wp_storage * 2 : 4;
934 context->watchpoints = realloc(context->watchpoints, context->wp_storage * sizeof(m68k_watchpoint)); 934 context->watchpoints = realloc(context->watchpoints, context->wp_storage * sizeof(m68k_watchpoint));
935 } 935 }
936 const memmap_chunk *chunk = find_map_chunk(address, &context->options->gen, 0, NULL); 936 const memmap_chunk *chunk = find_map_chunk(address, &context->opts->gen, 0, NULL);
937 context->watchpoints[context->num_watchpoints++] = (m68k_watchpoint){ 937 context->watchpoints[context->num_watchpoints++] = (m68k_watchpoint){
938 .start = address, 938 .start = address,
939 .end = end, 939 .end = end,
940 .check_change = chunk && (chunk->flags & MMAP_READ) 940 .check_change = chunk && (chunk->flags & MMAP_READ)
941 }; 941 };
1075 RAW_IMPL(M68K_TAS, translate_m68k_tas), 1075 RAW_IMPL(M68K_TAS, translate_m68k_tas),
1076 }; 1076 };
1077 1077
1078 static void translate_m68k(m68k_context *context, m68kinst * inst) 1078 static void translate_m68k(m68k_context *context, m68kinst * inst)
1079 { 1079 {
1080 m68k_options * opts = context->options; 1080 m68k_options * opts = context->opts;
1081 if (inst->address & 1) { 1081 if (inst->address & 1) {
1082 translate_m68k_odd(opts, inst); 1082 translate_m68k_odd(opts, inst);
1083 return; 1083 return;
1084 } 1084 }
1085 code_ptr start = opts->gen.code.cur; 1085 code_ptr start = opts->gen.code.cur;
1133 } 1133 }
1134 1134
1135 uint16_t m68k_instruction_fetch(uint32_t address, void *vcontext) 1135 uint16_t m68k_instruction_fetch(uint32_t address, void *vcontext)
1136 { 1136 {
1137 m68k_context *context = vcontext; 1137 m68k_context *context = vcontext;
1138 return read_word(address, (void **)context->mem_pointers, &context->options->gen, context); 1138 return read_word(address, (void **)context->mem_pointers, &context->opts->gen, context);
1139 } 1139 }
1140 1140
1141 void translate_m68k_stream(uint32_t address, m68k_context * context) 1141 void translate_m68k_stream(uint32_t address, m68k_context * context)
1142 { 1142 {
1143 m68kinst instbuf; 1143 m68kinst instbuf;
1144 m68k_options * opts = context->options; 1144 m68k_options * opts = context->opts;
1145 code_info *code = &opts->gen.code; 1145 code_info *code = &opts->gen.code;
1146 if(get_native_address(opts, address)) { 1146 if(get_native_address(opts, address)) {
1147 return; 1147 return;
1148 } 1148 }
1149 memmap_chunk const *starting_chunk = NULL; 1149 memmap_chunk const *starting_chunk = NULL;
1212 } while(opts->gen.deferred); 1212 } while(opts->gen.deferred);
1213 } 1213 }
1214 1214
1215 void * m68k_retranslate_inst(uint32_t address, m68k_context * context) 1215 void * m68k_retranslate_inst(uint32_t address, m68k_context * context)
1216 { 1216 {
1217 m68k_options * opts = context->options; 1217 m68k_options * opts = context->opts;
1218 code_info *code = &opts->gen.code; 1218 code_info *code = &opts->gen.code;
1219 uint8_t orig_size = get_native_inst_size(opts, address); 1219 uint8_t orig_size = get_native_inst_size(opts, address);
1220 code_ptr orig_start = get_native_address(context->options, address); 1220 code_ptr orig_start = get_native_address(context->opts, address);
1221 uint32_t orig = address; 1221 uint32_t orig = address;
1222 code_info orig_code = {orig_start, orig_start + orig_size + 5, 0}; 1222 code_info orig_code = {orig_start, orig_start + orig_size + 5, 0};
1223 m68kinst instbuf; 1223 m68kinst instbuf;
1224 uint32_t after_address = m68k_decode(m68k_instruction_fetch, context, &instbuf, orig); 1224 uint32_t after_address = m68k_decode(m68k_instruction_fetch, context, &instbuf, orig);
1225 if (orig_size != MAX_NATIVE_SIZE) { 1225 if (orig_size != MAX_NATIVE_SIZE) {
1288 } 1288 }
1289 } 1289 }
1290 1290
1291 code_ptr get_native_address_trans(m68k_context * context, uint32_t address) 1291 code_ptr get_native_address_trans(m68k_context * context, uint32_t address)
1292 { 1292 {
1293 code_ptr ret = get_native_address(context->options, address); 1293 code_ptr ret = get_native_address(context->opts, address);
1294 if (!ret) { 1294 if (!ret) {
1295 translate_m68k_stream(address, context); 1295 translate_m68k_stream(address, context);
1296 ret = get_native_address(context->options, address); 1296 ret = get_native_address(context->opts, address);
1297 } 1297 }
1298 return ret; 1298 return ret;
1299 } 1299 }
1300 1300
1301 void remove_breakpoint(m68k_context * context, uint32_t address) 1301 void remove_breakpoint(m68k_context * context, uint32_t address)
1308 } 1308 }
1309 context->num_breakpoints--; 1309 context->num_breakpoints--;
1310 break; 1310 break;
1311 } 1311 }
1312 } 1312 }
1313 code_ptr native = get_native_address(context->options, address); 1313 code_ptr native = get_native_address(context->opts, address);
1314 if (!native) { 1314 if (!native) {
1315 return; 1315 return;
1316 } 1316 }
1317 code_info tmp = context->options->gen.code; 1317 code_info tmp = context->opts->gen.code;
1318 context->options->gen.code.cur = native; 1318 context->opts->gen.code.cur = native;
1319 context->options->gen.code.last = native + MAX_NATIVE_SIZE; 1319 context->opts->gen.code.last = native + MAX_NATIVE_SIZE;
1320 check_cycles_int(&context->options->gen, address); 1320 check_cycles_int(&context->opts->gen, address);
1321 context->options->gen.code = tmp; 1321 context->opts->gen.code = tmp;
1322 } 1322 }
1323 1323
1324 void start_68k_context(m68k_context * context, uint32_t address) 1324 void start_68k_context(m68k_context * context, uint32_t address)
1325 { 1325 {
1326 code_ptr addr = get_native_address_trans(context, address); 1326 code_ptr addr = get_native_address_trans(context, address);
1327 m68k_options * options = context->options; 1327 m68k_options * options = context->opts;
1328 options->start_context(addr, context); 1328 options->start_context(addr, context);
1329 } 1329 }
1330 1330
1331 void resume_68k(m68k_context *context) 1331 void resume_68k(m68k_context *context)
1332 { 1332 {
1333 code_ptr addr = context->resume_pc; 1333 code_ptr addr = context->resume_pc;
1334 if (!context->stack_storage_count) { 1334 if (!context->stack_storage_count) {
1335 context->resume_pc = NULL; 1335 context->resume_pc = NULL;
1336 } 1336 }
1337 m68k_options * options = context->options; 1337 m68k_options * options = context->opts;
1338 context->should_return = 0; 1338 context->should_return = 0;
1339 options->start_context(addr, context); 1339 options->start_context(addr, context);
1340 } 1340 }
1341 1341
1342 void m68k_reset(m68k_context * context) 1342 void m68k_reset(m68k_context * context)
1343 { 1343 {
1344 //TODO: Actually execute the M68K reset vector rather than simulating some of its behavior 1344 //TODO: Actually execute the M68K reset vector rather than simulating some of its behavior
1345 uint16_t *reset_vec = get_native_pointer(0, (void **)context->mem_pointers, &context->options->gen); 1345 uint16_t *reset_vec = get_native_pointer(0, (void **)context->mem_pointers, &context->opts->gen);
1346 if (!(context->status & 0x20)) { 1346 if (!(context->status & 0x20)) {
1347 //switching from user to system mode so swap stack pointers 1347 //switching from user to system mode so swap stack pointers
1348 context->aregs[8] = context->aregs[7]; 1348 context->aregs[8] = context->aregs[7];
1349 } 1349 }
1350 context->resume_pc = NULL; 1350 context->resume_pc = NULL;
1351 context->stack_storage_count = 0; 1351 context->stack_storage_count = 0;
1352 context->status = 0x27; 1352 context->status = 0x27;
1353 context->aregs[7] = ((uint32_t)reset_vec[0]) << 16 | reset_vec[1]; 1353 context->aregs[7] = ((uint32_t)reset_vec[0]) << 16 | reset_vec[1];
1354 uint32_t address = ((uint32_t)reset_vec[2]) << 16 | reset_vec[3]; 1354 uint32_t address = ((uint32_t)reset_vec[2]) << 16 | reset_vec[3];
1355 //interrupt mask may have changed so force a sync 1355 //interrupt mask may have changed so force a sync
1356 context->options->sync_components(context, address); 1356 context->opts->sync_components(context, address);
1357 start_68k_context(context, address); 1357 start_68k_context(context, address);
1358 } 1358 }
1359 1359
1360 void m68k_options_free(m68k_options *opts) 1360 void m68k_options_free(m68k_options *opts)
1361 { 1361 {
1379 1379
1380 1380
1381 m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler) 1381 m68k_context * init_68k_context(m68k_options * opts, m68k_reset_handler reset_handler)
1382 { 1382 {
1383 m68k_context * context = calloc(1, sizeof(m68k_context) + ram_size(&opts->gen) / (1 << opts->gen.ram_flags_shift) / 8); 1383 m68k_context * context = calloc(1, sizeof(m68k_context) + ram_size(&opts->gen) / (1 << opts->gen.ram_flags_shift) / 8);
1384 context->options = opts; 1384 context->opts = opts;
1385 context->int_cycle = CYCLE_NEVER; 1385 context->int_cycle = CYCLE_NEVER;
1386 context->status = 0x27; 1386 context->status = 0x27;
1387 context->reset_handler = (code_ptr)reset_handler; 1387 context->reset_handler = (code_ptr)reset_handler;
1388 return context; 1388 return context;
1389 } 1389 }
1403 for (int flag = 4; flag >= 0; flag--) { 1403 for (int flag = 4; flag >= 0; flag--) {
1404 sr <<= 1; 1404 sr <<= 1;
1405 sr |= context->flags[flag] != 0; 1405 sr |= context->flags[flag] != 0;
1406 } 1406 }
1407 save_int16(buf, sr); 1407 save_int16(buf, sr);
1408 save_int32(buf, context->current_cycle); 1408 save_int32(buf, context->cycles);
1409 save_int32(buf, context->int_cycle); 1409 save_int32(buf, context->int_cycle);
1410 save_int8(buf, context->int_num); 1410 save_int8(buf, context->int_num);
1411 save_int8(buf, context->int_pending); 1411 save_int8(buf, context->int_pending);
1412 save_int8(buf, context->trace_pending); 1412 save_int8(buf, context->trace_pending);
1413 } 1413 }
1430 for (int flag = 0; flag < 5; flag++) 1430 for (int flag = 0; flag < 5; flag++)
1431 { 1431 {
1432 context->flags[flag] = sr & 1; 1432 context->flags[flag] = sr & 1;
1433 sr >>= 1; 1433 sr >>= 1;
1434 } 1434 }
1435 context->current_cycle = load_int32(buf); 1435 context->cycles = load_int32(buf);
1436 context->int_cycle = load_int32(buf); 1436 context->int_cycle = load_int32(buf);
1437 context->int_num = load_int8(buf); 1437 context->int_num = load_int8(buf);
1438 context->int_pending = load_int8(buf); 1438 context->int_pending = load_int8(buf);
1439 context->trace_pending = load_int8(buf); 1439 context->trace_pending = load_int8(buf);
1440 context->stack_storage_count = 0; 1440 context->stack_storage_count = 0;