X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=m68kcpu.c;h=b91be0a0b37ebf196d1c2726584f45b5206b9d5c;hb=22b742ee9ecd914e3d02f0f1fd0abbdfb7db16b8;hp=dd79593b4e762f786f6928a436346c7f76257d97;hpb=b4f8819a4c05358bb4da950b1995941024691898;p=pistorm diff --git a/m68kcpu.c b/m68kcpu.c index dd79593..b91be0a 100644 --- a/m68kcpu.c +++ b/m68kcpu.c @@ -40,7 +40,7 @@ extern void m68040_fpu_op0(void); extern void m68040_fpu_op1(void); -extern void m68881_mmu_ops(); +extern void m68851_mmu_ops(); extern unsigned char m68ki_cycles[][0x10000]; extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ extern void m68ki_build_opcode_table(void); @@ -145,8 +145,8 @@ const uint8 m68ki_exception_cycle_table[5][256] = 34, /* 7: TRAPV */ 34, /* 8: Privilege Violation */ 34, /* 9: Trace */ - 34, /* 10: 1010 */ - 34, /* 11: 1111 */ + 4, /* 10: 1010 */ + 4, /* 11: 1111 */ 4, /* 12: RESERVED */ 4, /* 13: Coprocessor Protocol Violation (unemulated) */ 4, /* 14: Format Error */ @@ -635,11 +635,11 @@ unsigned int m68k_get_reg(void* context, m68k_register_t regnum) case M68K_REG_A6: return cpu->dar[14]; case M68K_REG_A7: return cpu->dar[15]; case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc); - case M68K_REG_SR: return cpu->t1_flag | - cpu->t0_flag | + case M68K_REG_SR: return cpu->t1_flag | + cpu->t0_flag | (cpu->s_flag << 11) | (cpu->m_flag << 11) | - cpu->int_mask | + cpu->int_mask | ((cpu->x_flag & XFLAG_SET) >> 4) | ((cpu->n_flag & NFLAG_SET) >> 4) | ((!cpu->not_z_flag) << 2) | @@ -663,8 +663,12 @@ unsigned int m68k_get_reg(void* context, m68k_register_t regnum) { case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000; case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010; - case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020; + case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020; case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020; + case CPU_TYPE_EC030: return (unsigned int)M68K_CPU_TYPE_68EC030; + case CPU_TYPE_030: return (unsigned int)M68K_CPU_TYPE_68030; + case CPU_TYPE_EC040: return (unsigned int)M68K_CPU_TYPE_68EC040; + case CPU_TYPE_LC040: return (unsigned int)M68K_CPU_TYPE_68LC040; case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040; } return M68K_CPU_TYPE_INVALID; @@ -794,7 +798,8 @@ void m68k_set_cpu_type(unsigned int cpu_type) CYC_MOVEM_L = 3; CYC_SHIFT = 1; CYC_RESET = 132; - HAS_PMMU = 0; + HAS_PMMU = 0; + HAS_FPU = 0; return; case M68K_CPU_TYPE_SCC68070: m68k_set_cpu_type(M68K_CPU_TYPE_68010); @@ -816,7 +821,8 @@ void m68k_set_cpu_type(unsigned int cpu_type) CYC_MOVEM_L = 3; CYC_SHIFT = 1; CYC_RESET = 130; - HAS_PMMU = 0; + HAS_PMMU = 0; + HAS_FPU = 0; return; case M68K_CPU_TYPE_68EC020: CPU_TYPE = CPU_TYPE_EC020; @@ -833,7 +839,8 @@ void m68k_set_cpu_type(unsigned int cpu_type) CYC_MOVEM_L = 2; CYC_SHIFT = 0; CYC_RESET = 518; - HAS_PMMU = 0; + HAS_PMMU = 0; + HAS_FPU = 0; return; case M68K_CPU_TYPE_68020: CPU_TYPE = CPU_TYPE_020; @@ -850,7 +857,8 @@ void m68k_set_cpu_type(unsigned int cpu_type) CYC_MOVEM_L = 2; CYC_SHIFT = 0; CYC_RESET = 518; - HAS_PMMU = 0; + HAS_PMMU = 0; + HAS_FPU = 0; return; case M68K_CPU_TYPE_68030: CPU_TYPE = CPU_TYPE_030; @@ -867,7 +875,8 @@ void m68k_set_cpu_type(unsigned int cpu_type) CYC_MOVEM_L = 2; CYC_SHIFT = 0; CYC_RESET = 518; - HAS_PMMU = 1; + HAS_PMMU = 1; + HAS_FPU = 1; return; case M68K_CPU_TYPE_68EC030: CPU_TYPE = CPU_TYPE_EC030; @@ -884,7 +893,8 @@ void m68k_set_cpu_type(unsigned int cpu_type) CYC_MOVEM_L = 2; CYC_SHIFT = 0; CYC_RESET = 518; - HAS_PMMU = 0; /* EC030 lacks the PMMU and is effectively a die-shrink 68020 */ + HAS_PMMU = 0; /* EC030 lacks the PMMU and is effectively a die-shrink 68020 */ + HAS_FPU = 1; return; case M68K_CPU_TYPE_68040: // TODO: these values are not correct CPU_TYPE = CPU_TYPE_040; @@ -901,7 +911,8 @@ void m68k_set_cpu_type(unsigned int cpu_type) CYC_MOVEM_L = 2; CYC_SHIFT = 0; CYC_RESET = 518; - HAS_PMMU = 1; + HAS_PMMU = 1; + HAS_FPU = 1; return; case M68K_CPU_TYPE_68EC040: // Just a 68040 without pmmu apparently... CPU_TYPE = CPU_TYPE_EC040; @@ -918,10 +929,12 @@ void m68k_set_cpu_type(unsigned int cpu_type) CYC_MOVEM_L = 2; CYC_SHIFT = 0; CYC_RESET = 518; - HAS_PMMU = 0; + HAS_PMMU = 0; + HAS_FPU = 0; return; case M68K_CPU_TYPE_68LC040: CPU_TYPE = CPU_TYPE_LC040; + CPU_ADDRESS_MASK = 0xffffffff; m68ki_cpu.sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ m68ki_cpu.cyc_instruction = m68ki_cycles[4]; m68ki_cpu.cyc_exception = m68ki_exception_cycle_table[4]; @@ -934,7 +947,8 @@ void m68k_set_cpu_type(unsigned int cpu_type) m68ki_cpu.cyc_movem_l = 2; m68ki_cpu.cyc_shift = 0; m68ki_cpu.cyc_reset = 518; - HAS_PMMU = 1; + HAS_PMMU = 1; + HAS_FPU = 0; return; } } @@ -976,9 +990,6 @@ int m68k_execute(int num_cycles) /* Main loop. Keep going until we run out of clock cycles */ do { -#ifdef M68K_BUSERR_THING - int i; -#endif /* Set tracing accodring to T1. (T0 is done inside instruction) */ m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */ @@ -992,8 +1003,9 @@ int m68k_execute(int num_cycles) REG_PPC = REG_PC; /* Record previous D/A register state (in case of bus error) */ +//#define M68K_BUSERR_THING #ifdef M68K_BUSERR_THING - for (i = 15; i >= 0; i--){ + for (int i = 15; i >= 0; i--){ REG_DA_SAVE[i] = REG_DA[i]; } #endif @@ -1086,7 +1098,7 @@ void m68k_init(void) /* The first call to this function initializes the opcode handler jump table */ if(!emulation_initialized) - { + { m68ki_build_opcode_table(); emulation_initialized = 1; } @@ -1112,8 +1124,13 @@ void m68k_pulse_bus_error(void) /* Pulse the RESET line on the CPU */ void m68k_pulse_reset(void) { - /* Disable the PMMU on reset */ + /* Disable the PMMU/HMMU on reset, if any */ m68ki_cpu.pmmu_enabled = 0; +// m68ki_cpu.hmmu_enabled = 0; + + m68ki_cpu.mmu_tc = 0; + m68ki_cpu.mmu_tt0 = 0; + m68ki_cpu.mmu_tt1 = 0; /* Clear all stop levels and eat up all remaining cycles */ CPU_STOPPED = 0; @@ -1149,6 +1166,15 @@ void m68k_pulse_reset(void) CPU_RUN_MODE = RUN_MODE_NORMAL; RESET_CYCLES = CYC_EXCEPTION[EXCEPTION_RESET]; + + /* flush the MMU's cache */ + pmmu_atc_flush(); + + if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) + { + // clear instruction cache + m68ki_ic_clear(); + } } /* Pulse the HALT line on the CPU */ @@ -1179,20 +1205,20 @@ void m68k_set_context(void* src) /* Read data immediately following the PC */ inline unsigned int m68k_read_immediate_16(unsigned int address) { #if M68K_EMULATE_PREFETCH == OPT_ON - for (int i = 0; i < read_ranges; i++) { - if(address >= read_addr[i] && address < read_upper[i]) { - return be16toh(((unsigned short *)(read_data[i] + (address - read_addr[i])))[0]); + for (int i = 0; i < m68ki_cpu.read_ranges; i++) { + if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) { + return be16toh(((unsigned short *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]); } } #endif - + return m68k_read_memory_16(address); } inline unsigned int m68k_read_immediate_32(unsigned int address) { #if M68K_EMULATE_PREFETCH == OPT_ON - for (int i = 0; i < read_ranges; i++) { - if(address >= read_addr[i] && address < read_upper[i]) { - return be32toh(((unsigned int *)(read_data[i] + (address - read_addr[i])))[0]); + for (int i = 0; i < m68ki_cpu.read_ranges; i++) { + if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) { + return be32toh(((unsigned int *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]); } } #endif @@ -1202,27 +1228,27 @@ inline unsigned int m68k_read_immediate_32(unsigned int address) { /* Read data relative to the PC */ inline unsigned int m68k_read_pcrelative_8(unsigned int address) { - for (int i = 0; i < read_ranges; i++) { - if(address >= read_addr[i] && address < read_upper[i]) { - return read_data[i][address - read_addr[i]]; + for (int i = 0; i < m68ki_cpu.read_ranges; i++) { + if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) { + return m68ki_cpu.read_data[i][address - m68ki_cpu.read_addr[i]]; } } - + return m68k_read_memory_8(address); } inline unsigned int m68k_read_pcrelative_16(unsigned int address) { - for (int i = 0; i < read_ranges; i++) { - if(address >= read_addr[i] && address < read_upper[i]) { - return be16toh(((unsigned short *)(read_data[i] + (address - read_addr[i])))[0]); + for (int i = 0; i < m68ki_cpu.read_ranges; i++) { + if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) { + return be16toh(((unsigned short *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]); } } return m68k_read_memory_16(address); } inline unsigned int m68k_read_pcrelative_32(unsigned int address) { - for (int i = 0; i < read_ranges; i++) { - if(address >= read_addr[i] && address < read_upper[i]) { - return be32toh(((unsigned int *)(read_data[i] + (address - read_addr[i])))[0]); + for (int i = 0; i < m68ki_cpu.read_ranges; i++) { + if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) { + return be32toh(((unsigned int *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]); } } @@ -1230,45 +1256,96 @@ inline unsigned int m68k_read_pcrelative_32(unsigned int address) { } #endif + +uint m68ki_read_imm6_addr_slowpath(uint32_t pc, address_translation_cache *cache) +{ + uint32_t address = ADDRESS_68K(pc); + uint32_t pc_address_diff = pc - address; + for (int i = 0; i < m68ki_cpu.read_ranges; i++) { + if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) { + cache->lower = m68ki_cpu.read_addr[i] + pc_address_diff; + cache->upper = m68ki_cpu.read_upper[i] + pc_address_diff; + cache->offset = m68ki_cpu.read_data[i] - cache->lower; + REG_PC += 2; + return be16toh(((unsigned short *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]); + } + } + + m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + m68ki_cpu.mmu_tmp_fc = FLAG_S | FUNCTION_CODE_USER_PROGRAM; + m68ki_cpu.mmu_tmp_rw = 1; + m68ki_cpu.mmu_tmp_sz = M68K_SZ_WORD; + m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ + +#if M68K_EMULATE_PREFETCH +{ + uint result; + if(REG_PC != CPU_PREF_ADDR) + { + CPU_PREF_DATA = m68ki_ic_readimm16(REG_PC); + CPU_PREF_ADDR = m68ki_cpu.mmu_tmp_buserror_occurred ? ((uint32)~0) : REG_PC; + } + result = MASK_OUT_ABOVE_16(CPU_PREF_DATA); + REG_PC += 2; + if (!m68ki_cpu.mmu_tmp_buserror_occurred) { + // prefetch only if no bus error occurred in opcode fetch + CPU_PREF_DATA = m68ki_ic_readimm16(REG_PC); + CPU_PREF_ADDR = m68ki_cpu.mmu_tmp_buserror_occurred ? ((uint32)~0) : REG_PC; + // ignore bus error on prefetch + m68ki_cpu.mmu_tmp_buserror_occurred = 0; + } + return result; +} +#else + REG_PC += 2; + + return m68k_read_immediate_16(address); +#endif /* M68K_EMULATE_PREFETCH */ +} + + + void m68k_add_ram_range(uint32_t addr, uint32_t upper, unsigned char *ptr) { + m68ki_cpu.code_translation_cache.lower = 0; + m68ki_cpu.code_translation_cache.upper = 0; if ((addr == 0 && upper == 0) || upper < addr) return; - for (int i = 0; i < write_ranges; i++) { - if (write_addr[i] == addr) { + for (int i = 0; i < m68ki_cpu.write_ranges; i++) { + if (m68ki_cpu.write_addr[i] == addr) { uint8_t changed = 0; - if (write_upper[i] != upper) { - write_upper[i] = upper; + if (m68ki_cpu.write_upper[i] != upper) { + m68ki_cpu.write_upper[i] = upper; changed = 1; } - if (write_data[i] != ptr) { - write_data[i] = ptr; + if (m68ki_cpu.write_data[i] != ptr) { + m68ki_cpu.write_data[i] = ptr; changed = 1; } if (changed) { - printf("[MUSASHI] Adjusted mapped write range %d: %.8X-%.8X (%p)\n", write_ranges, addr, upper, ptr); + printf("[MUSASHI] Adjusted mapped write range %d: %.8X-%.8X (%p)\n", m68ki_cpu.write_ranges, addr, upper, ptr); } return; } } - if (read_ranges + 1 < 8) { - read_addr[read_ranges] = addr; - read_upper[read_ranges] = upper; - read_data[read_ranges] = ptr; - read_ranges++; - printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr); + if (m68ki_cpu.read_ranges + 1 < 8) { + m68ki_cpu.read_addr[m68ki_cpu.read_ranges] = addr; + m68ki_cpu.read_upper[m68ki_cpu.read_ranges] = upper; + m68ki_cpu.read_data[m68ki_cpu.read_ranges] = ptr; + m68ki_cpu.read_ranges++; + printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", m68ki_cpu.read_ranges, addr, upper, ptr); } else { printf("Can't Musashi map more than eight RAM/ROM read ranges.\n"); } - if (write_ranges + 1 < 8) { - write_addr[write_ranges] = addr; - write_upper[write_ranges] = upper; - write_data[write_ranges] = ptr; - write_ranges++; - printf("[MUSASHI] Mapped write range %d: %.8X-%.8X (%p)\n", write_ranges, addr, upper, ptr); + if (m68ki_cpu.write_ranges + 1 < 8) { + m68ki_cpu.write_addr[m68ki_cpu.write_ranges] = addr; + m68ki_cpu.write_upper[m68ki_cpu.write_ranges] = upper; + m68ki_cpu.write_data[m68ki_cpu.write_ranges] = ptr; + m68ki_cpu.write_ranges++; + printf("[MUSASHI] Mapped write range %d: %.8X-%.8X (%p)\n", m68ki_cpu.write_ranges, addr, upper, ptr); } else { printf("Can't Musashi map more than eight RAM write ranges.\n"); @@ -1277,39 +1354,58 @@ void m68k_add_ram_range(uint32_t addr, uint32_t upper, unsigned char *ptr) void m68k_add_rom_range(uint32_t addr, uint32_t upper, unsigned char *ptr) { + m68ki_cpu.code_translation_cache.lower = 0; + m68ki_cpu.code_translation_cache.upper = 0; if ((addr == 0 && upper == 0) || upper < addr) return; - for (int i = 0; i < read_ranges; i++) { - if (read_addr[i] == addr) { + for (int i = 0; i < m68ki_cpu.read_ranges; i++) { + if (m68ki_cpu.read_addr[i] == addr) { uint8_t changed = 0; - if (read_upper[i] != upper) { - read_upper[i] = upper; + if (m68ki_cpu.read_upper[i] != upper) { + m68ki_cpu.read_upper[i] = upper; changed = 1; } - if (read_data[i] != ptr) { - read_data[i] = ptr; + if (m68ki_cpu.read_data[i] != ptr) { + m68ki_cpu.read_data[i] = ptr; changed = 1; } if (changed) { - printf("[MUSASHI] Adjusted mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr); + printf("[MUSASHI] Adjusted mapped read range %d: %.8X-%.8X (%p)\n", m68ki_cpu.read_ranges, addr, upper, ptr); } return; } } - if (read_ranges + 1 < 8) { - read_addr[read_ranges] = addr; - read_upper[read_ranges] = upper; - read_data[read_ranges] = ptr; - read_ranges++; - printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr); + if (m68ki_cpu.read_ranges + 1 < 8) { + m68ki_cpu.read_addr[m68ki_cpu.read_ranges] = addr; + m68ki_cpu.read_upper[m68ki_cpu.read_ranges] = upper; + m68ki_cpu.read_data[m68ki_cpu.read_ranges] = ptr; + m68ki_cpu.read_ranges++; + printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", m68ki_cpu.read_ranges, addr, upper, ptr); } else { printf("Can't Musashi map more than eight RAM/ROM read ranges.\n"); } } +void m68k_clear_ranges() +{ + printf("[MUSASHI] Clearing all reads/write memory ranges.\n"); + for (int i = 0; i < 8; i++) { + m68ki_cpu.read_upper[i] = 0; + m68ki_cpu.read_addr[i] = 0; + m68ki_cpu.read_data[i] = NULL; + m68ki_cpu.write_upper[i] = 0; + m68ki_cpu.write_addr[i] = 0; + m68ki_cpu.write_data[i] = NULL; + } + m68ki_cpu.write_ranges = 0; + m68ki_cpu.read_ranges = 0; + m68ki_cpu.code_translation_cache.lower = 0; + m68ki_cpu.code_translation_cache.upper = 0; +} + /* ======================================================================== */ /* ============================== MAME STUFF ============================== */ /* ======================================================================== */