comparison m68k_core.c @ 2054:8ee7ecbf3f21 segacd

Implement enough of Sega CD gate array and Sub CPU to pass Sik's Mode 1 test ROM
author Michael Pavone <pavone@retrodev.com>
date Tue, 18 Jan 2022 00:03:50 -0800
parents c157a535ceeb
children d59ace2d7a6a
comparison
equal deleted inserted replaced
2053:3414a4423de1 2054:8ee7ecbf3f21
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, "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 {