Mercurial > repos > blastem
comparison m68k_core.c @ 2072:cc13c100b027
Merge Sega CD branch now that it sort of works
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 30 Jan 2022 22:29:29 -0800 |
parents | d59ace2d7a6a |
children | 8554751f17b5 |
comparison
equal
deleted
inserted
replaced
2052:3748a2a8a4b7 | 2072:cc13c100b027 |
---|---|
92 } | 92 } |
93 | 93 |
94 void m68k_save_result(m68kinst * inst, m68k_options * opts) | 94 void m68k_save_result(m68kinst * inst, m68k_options * opts) |
95 { | 95 { |
96 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_UNUSED) { | 96 if (inst->dst.addr_mode != MODE_REG && inst->dst.addr_mode != MODE_AREG && inst->dst.addr_mode != MODE_UNUSED) { |
97 if (inst->dst.addr_mode == MODE_AREG_PREDEC && | 97 if (inst->dst.addr_mode == MODE_AREG_PREDEC && |
98 ((inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) || (inst->op == M68K_NBCD)) | 98 ((inst->src.addr_mode == MODE_AREG_PREDEC && inst->op != M68K_MOVE) || (inst->op == M68K_NBCD)) |
99 ) { | 99 ) { |
100 areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2); | 100 areg_to_native(opts, inst->dst.params.regs.pri, opts->gen.scratch2); |
101 } | 101 } |
102 m68k_write_size(opts, inst->extra.size, 1); | 102 m68k_write_size(opts, inst->extra.size, 1); |
487 } else { | 487 } else { |
488 translate_movem_memtoreg_reglist(opts, inst); | 488 translate_movem_memtoreg_reglist(opts, inst); |
489 } | 489 } |
490 opts->extra_code = opts->gen.code; | 490 opts->extra_code = opts->gen.code; |
491 opts->gen.code = tmp; | 491 opts->gen.code = tmp; |
492 | 492 |
493 rts(&opts->extra_code); | 493 rts(&opts->extra_code); |
494 return impl; | 494 return impl; |
495 } | 495 } |
496 | 496 |
497 static void translate_m68k_movem(m68k_options * opts, m68kinst * inst) | 497 static void translate_m68k_movem(m68k_options * opts, m68kinst * inst) |
498 { | 498 { |
499 code_info *code = &opts->gen.code; | 499 code_info *code = &opts->gen.code; |
500 uint8_t early_cycles; | 500 uint8_t early_cycles; |
501 uint16_t num_regs = inst->src.addr_mode == MODE_REG ? inst->src.params.immed : inst->dst.params.immed; | 501 uint16_t num_regs = inst->src.addr_mode == MODE_REG ? inst->src.params.immed : inst->dst.params.immed; |
502 { | 502 { |
503 //TODO: Move this popcount alg to a utility function | 503 //TODO: Move this popcount alg to a utility function |
504 uint16_t a = (num_regs & 0b1010101010101010) >> 1; | 504 uint16_t a = (num_regs & 0b1010101010101010) >> 1; |
505 uint16_t b = num_regs & 0b0101010101010101; | 505 uint16_t b = num_regs & 0b0101010101010101; |
506 num_regs = a + b; | 506 num_regs = a + b; |
507 a = (num_regs & 0b1100110011001100) >> 2; | 507 a = (num_regs & 0b1100110011001100) >> 2; |
547 break; | 547 break; |
548 default: | 548 default: |
549 m68k_disasm(inst, disasm_buf); | 549 m68k_disasm(inst, disasm_buf); |
550 fatal_error("%X: %s\naddress mode %d not implemented (movem dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); | 550 fatal_error("%X: %s\naddress mode %d not implemented (movem dst)\n", inst->address, disasm_buf, inst->dst.addr_mode); |
551 } | 551 } |
552 | 552 |
553 cycles(&opts->gen, early_cycles); | 553 cycles(&opts->gen, early_cycles); |
554 if (num_regs <= 9) { | 554 if (num_regs <= 9) { |
555 translate_movem_regtomem_reglist(opts, inst); | 555 translate_movem_regtomem_reglist(opts, inst); |
556 } else { | 556 } else { |
557 call(code, get_movem_impl(opts, inst)); | 557 call(code, get_movem_impl(opts, inst)); |
594 default: | 594 default: |
595 m68k_disasm(inst, disasm_buf); | 595 m68k_disasm(inst, disasm_buf); |
596 fatal_error("%X: %s\naddress mode %d not implemented (movem src)\n", inst->address, disasm_buf, inst->src.addr_mode); | 596 fatal_error("%X: %s\naddress mode %d not implemented (movem src)\n", inst->address, disasm_buf, inst->src.addr_mode); |
597 } | 597 } |
598 cycles(&opts->gen, early_cycles); | 598 cycles(&opts->gen, early_cycles); |
599 | 599 |
600 if (num_regs <= 9) { | 600 if (num_regs <= 9) { |
601 translate_movem_memtoreg_reglist(opts, inst); | 601 translate_movem_memtoreg_reglist(opts, inst); |
602 } else { | 602 } else { |
603 call(code, get_movem_impl(opts, inst)); | 603 call(code, get_movem_impl(opts, inst)); |
604 } | 604 } |
623 } | 623 } |
624 | 624 |
625 static void translate_m68k_rte(m68k_options *opts, m68kinst *inst) | 625 static void translate_m68k_rte(m68k_options *opts, m68kinst *inst) |
626 { | 626 { |
627 m68k_trap_if_not_supervisor(opts, inst); | 627 m68k_trap_if_not_supervisor(opts, inst); |
628 | 628 |
629 code_info *code = &opts->gen.code; | 629 code_info *code = &opts->gen.code; |
630 //Read saved SR | 630 //Read saved SR |
631 areg_to_native(opts, 7, opts->gen.scratch1); | 631 areg_to_native(opts, 7, opts->gen.scratch1); |
632 call(code, opts->read_16); | 632 call(code, opts->read_16); |
633 addi_areg(opts, 2, 7); | 633 addi_areg(opts, 2, 7); |
644 } | 644 } |
645 | 645 |
646 code_ptr get_native_address(m68k_options *opts, uint32_t address) | 646 code_ptr get_native_address(m68k_options *opts, uint32_t address) |
647 { | 647 { |
648 native_map_slot * native_code_map = opts->gen.native_code_map; | 648 native_map_slot * native_code_map = opts->gen.native_code_map; |
649 | 649 |
650 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL); | 650 memmap_chunk const *mem_chunk = find_map_chunk(address, &opts->gen, 0, NULL); |
651 if (mem_chunk) { | 651 if (mem_chunk) { |
652 //calculate the lowest alias for this address | 652 //calculate the lowest alias for this address |
653 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); | 653 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); |
654 } else { | 654 } else { |
678 //calculate the lowest alias for this address | 678 //calculate the lowest alias for this address |
679 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); | 679 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); |
680 } else { | 680 } else { |
681 address &= opts->gen.address_mask; | 681 address &= opts->gen.address_mask; |
682 } | 682 } |
683 | 683 |
684 uint32_t chunk = address / NATIVE_CHUNK_SIZE; | 684 uint32_t chunk = address / NATIVE_CHUNK_SIZE; |
685 if (!native_code_map[chunk].base) { | 685 if (!native_code_map[chunk].base) { |
686 return 0; | 686 return 0; |
687 } | 687 } |
688 uint32_t offset = address % NATIVE_CHUNK_SIZE; | 688 uint32_t offset = address % NATIVE_CHUNK_SIZE; |
726 //calculate the lowest alias for this address | 726 //calculate the lowest alias for this address |
727 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); | 727 address = mem_chunk->start + ((address - mem_chunk->start) & mem_chunk->mask); |
728 } else { | 728 } else { |
729 address &= opts->gen.address_mask; | 729 address &= opts->gen.address_mask; |
730 } | 730 } |
731 | 731 |
732 uint32_t chunk = address / NATIVE_CHUNK_SIZE; | 732 uint32_t chunk = address / NATIVE_CHUNK_SIZE; |
733 if (!native_code_map[chunk].base) { | 733 if (!native_code_map[chunk].base) { |
734 native_code_map[chunk].base = native_addr; | 734 native_code_map[chunk].base = native_addr; |
735 native_code_map[chunk].offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE); | 735 native_code_map[chunk].offsets = malloc(sizeof(int32_t) * NATIVE_CHUNK_SIZE); |
736 memset(native_code_map[chunk].offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE); | 736 memset(native_code_map[chunk].offsets, 0xFF, sizeof(int32_t) * NATIVE_CHUNK_SIZE); |
828 } else { | 828 } else { |
829 //spurious breakoint? | 829 //spurious breakoint? |
830 warning("Spurious breakpoing at %X\n", address); | 830 warning("Spurious breakpoing at %X\n", address); |
831 remove_breakpoint(context, address); | 831 remove_breakpoint(context, address); |
832 } | 832 } |
833 | 833 |
834 return context; | 834 return context; |
835 } | 835 } |
836 | 836 |
837 typedef enum { | 837 typedef enum { |
838 RAW_FUNC = 1, | 838 RAW_FUNC = 1, |
956 translate_m68k_odd(opts, inst); | 956 translate_m68k_odd(opts, inst); |
957 return; | 957 return; |
958 } | 958 } |
959 code_ptr start = opts->gen.code.cur; | 959 code_ptr start = opts->gen.code.cur; |
960 check_cycles_int(&opts->gen, inst->address); | 960 check_cycles_int(&opts->gen, inst->address); |
961 | 961 |
962 m68k_debug_handler bp; | 962 m68k_debug_handler bp; |
963 if ((bp = find_breakpoint(context, inst->address))) { | 963 if ((bp = find_breakpoint(context, inst->address))) { |
964 m68k_breakpoint_patch(context, inst->address, bp, start); | 964 m68k_breakpoint_patch(context, inst->address, bp, start); |
965 } | 965 } |
966 | 966 |
967 //log_address(&opts->gen, inst->address, "M68K: %X @ %d\n"); | 967 //log_address(&opts->gen, inst->address, opts->gen.clock_divider == 4 ? "Sub M68k: %X @ %d\n" : "Main M68K: %X @ %d\n"); |
968 if ( | 968 if ( |
969 (inst->src.addr_mode > MODE_AREG && inst->src.addr_mode < MODE_IMMEDIATE) | 969 (inst->src.addr_mode > MODE_AREG && inst->src.addr_mode < MODE_IMMEDIATE) |
970 || (inst->dst.addr_mode > MODE_AREG && inst->dst.addr_mode < MODE_IMMEDIATE) | 970 || (inst->dst.addr_mode > MODE_AREG && inst->dst.addr_mode < MODE_IMMEDIATE) |
971 || (inst->op == M68K_BCC && (inst->src.params.immed & 1)) | 971 || (inst->op == M68K_BCC && (inst->src.params.immed & 1)) |
972 ) { | 972 ) { |
973 //Not accurate for all cases, but probably good enough for now | 973 //Not accurate for all cases, but probably good enough for now |
974 m68k_set_last_prefetch(opts, inst->address + inst->bytes); | 974 m68k_set_last_prefetch(opts, inst->address + inst->bytes); |
1194 } | 1194 } |
1195 context->status = 0x27; | 1195 context->status = 0x27; |
1196 context->aregs[7] = reset_vec[0] << 16 | reset_vec[1]; | 1196 context->aregs[7] = reset_vec[0] << 16 | reset_vec[1]; |
1197 uint32_t address = reset_vec[2] << 16 | reset_vec[3]; | 1197 uint32_t address = reset_vec[2] << 16 | reset_vec[3]; |
1198 //interrupt mask may have changed so force a sync | 1198 //interrupt mask may have changed so force a sync |
1199 sync_components(context, address); | 1199 context->options->sync_components(context, address); |
1200 start_68k_context(context, address); | 1200 start_68k_context(context, address); |
1201 } | 1201 } |
1202 | 1202 |
1203 void m68k_options_free(m68k_options *opts) | 1203 void m68k_options_free(m68k_options *opts) |
1204 { | 1204 { |