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