From: Toni Wilen Date: Tue, 1 Aug 2017 19:06:47 +0000 (+0300) Subject: 68030 + MMU + caches + "cycle-exact" support. 68040 MMU cache inhibit (CI) and full... X-Git-Tag: 3600~140 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=f13e639340f9ff6365059675cd7a616151da79a8;p=francis%2Fwinuae.git 68030 + MMU + caches + "cycle-exact" support. 68040 MMU cache inhibit (CI) and full invalidation/flushing support. 68030 locked read-modify-write TTR support. --- diff --git a/cpummu.cpp b/cpummu.cpp index 1dcbf578..b0a28cb6 100644 --- a/cpummu.cpp +++ b/cpummu.cpp @@ -48,6 +48,7 @@ uae_u32 mmu_tagmask, mmu_pagemask, mmu_pagemaski; struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_SLOTS][ATC_WAYS]; bool mmu_pagesize_8k; int mmu_pageshift, mmu_pageshift1m; +uae_u8 mmu_cache_state; int mmu060_state; uae_u16 mmu_opcode; @@ -68,6 +69,7 @@ struct mmu_icache mmu_icache_data[MMU_ICACHE_SZ]; #endif #if MMU_IPAGECACHE uae_u32 atc_last_ins_laddr, atc_last_ins_paddr; +uae_u8 atc_last_ins_cache; #endif #if MMU_DPAGECACHE struct mmufastcache atc_data_cache_read[MMUFASTCACHE_ENTRIES]; @@ -527,7 +529,8 @@ static int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super) return TTR_NO_MATCH; } } - + if (ttr & MMU_TTR_CACHE_DISABLE) + mmu_cache_state = CACHE_DISABLE_MMU; return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH; } } @@ -726,6 +729,8 @@ fail: l->tag = tag; } status = MMU_MMUSR_B; + *status060 |= MMU_FSLW_LK | MMU_FSLW_TWE; + #if MMUDEBUG > 0 write_log(_T("MMU: bus error during table search.\n")); #endif @@ -747,6 +752,7 @@ static void mmu_add_cache(uaecptr addr, uaecptr phys, bool super, bool data, boo uae_u32 laddr = (addr & mmu_pagemaski) | (super ? 1 : 0); atc_last_ins_laddr = laddr; atc_last_ins_paddr = phys; + atc_last_ins_cache = mmu_cache_state; #else ; #endif @@ -814,6 +820,9 @@ atc_retry: // save way for next access (likely in same page) mmu_atc_ways[data] = way; + if (l->status & MMU_MMUSR_CM_DISABLE) + mmu_cache_state = CACHE_DISABLE_MMU; + mmu_add_cache(addr, l->phys, super, data, write); // return translated addr diff --git a/cpummu30.cpp b/cpummu30.cpp index 91043cbd..30a7c334 100644 --- a/cpummu30.cpp +++ b/cpummu30.cpp @@ -316,30 +316,30 @@ bool mmu_op30_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) #if MMU030_OP_DBG_MSG switch (preg) { case 0x10: - write_log(_T("PMOVE: %s TC %08X\n"), rw ? _T("read"): _T("write"), - rw ? tc_030 : x_get_long(extra)); + write_log(_T("PMOVE: %s TC %08X PC=%08x\n"), rw ? _T("read"): _T("write"), + rw ? tc_030 : x_get_long(extra), m68k_getpc()); break; case 0x12: - write_log(_T("PMOVE: %s SRP %08X%08X\n"), rw ? _T("read") : _T("write"), + write_log(_T("PMOVE: %s SRP %08X%08X PC=%08x\n"), rw ? _T("read") : _T("write"), rw?(uae_u32)(srp_030>>32)&0xFFFFFFFF:x_get_long(extra), - rw?(uae_u32)srp_030&0xFFFFFFFF:x_get_long(extra+4)); + rw?(uae_u32)srp_030&0xFFFFFFFF:x_get_long(extra+4), m68k_getpc()); break; case 0x13: - write_log(_T("PMOVE: %s CRP %08X%08X\n"), rw ? _T("read") : _T("write"), + write_log(_T("PMOVE: %s CRP %08X%08X PC=%08x\n"), rw ? _T("read") : _T("write"), rw?(uae_u32)(crp_030>>32)&0xFFFFFFFF:x_get_long(extra), - rw?(uae_u32)crp_030&0xFFFFFFFF:x_get_long(extra+4)); + rw?(uae_u32)crp_030&0xFFFFFFFF:x_get_long(extra+4), m68k_getpc()); break; case 0x18: - write_log(_T("PMOVE: %s MMUSR %04X\n"), rw ? _T("read") : _T("write"), - rw?mmusr_030:x_get_word(extra)); + write_log(_T("PMOVE: %s MMUSR %04X PC=%08x\n"), rw ? _T("read") : _T("write"), + rw?mmusr_030:x_get_word(extra), m68k_getpc()); break; case 0x02: - write_log(_T("PMOVE: %s TT0 %08X\n"), rw ? _T("read") : _T("write"), - rw?tt0_030:x_get_long(extra)); + write_log(_T("PMOVE: %s TT0 %08X PC=%08x\n"), rw ? _T("read") : _T("write"), + rw?tt0_030:x_get_long(extra), m68k_getpc()); break; case 0x03: - write_log(_T("PMOVE: %s TT1 %08X\n"), rw ? _T("read") : _T("write"), - rw?tt1_030:x_get_long(extra)); + write_log(_T("PMOVE: %s TT1 %08X PC=%08x\n"), rw ? _T("read") : _T("write"), + rw?tt1_030:x_get_long(extra), m68k_getpc()); break; default: break; @@ -440,8 +440,8 @@ bool mmu_op30_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) } #if MMU030_OP_DBG_MSG - write_log(_T("PTEST%c: addr = %08X, fc = %i, level = %i, "), - rw?'R':'W', extra, fc, level); + write_log(_T("PTEST%c: addr = %08X, fc = %i, level = %i, PC=%08x, "), + rw?'R':'W', extra, fc, level, m68k_getpc()); if (a) { write_log(_T("return descriptor to register A%i\n"), areg); } else { @@ -2144,9 +2144,38 @@ uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc) { } /* Not commonly used access function */ + +static void mmu030_put_generic_lrmw(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int flags) +{ + mmu030_cache_state = CACHE_ENABLE_ALL; + if (fc != 7 && (!tt_enabled || !mmu030_match_lrmw_ttr_access(addr,fc)) && mmu030.enabled) { + int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); + if (atc_line_num>=0) { + addr = mmu030_put_atc_generic(addr, atc_line_num, fc, flags); + } else { + mmu030_table_search(addr, fc, true, 0); + atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); + addr = mmu030_put_atc_generic(addr, atc_line_num, fc, flags); + } + } + + cacheablecheck(addr); + if (size == sz_byte) + x_phys_put_byte(addr, val); + else if (size == sz_word) + x_phys_put_word(addr, val); + else + x_phys_put_long(addr, val); +} + void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int flags) { mmu030_cache_state = CACHE_ENABLE_ALL; + + if (flags & MMU030_SSW_RM) { + return mmu030_put_generic_lrmw(addr, val, fc, size, flags); + } + if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true)) && mmu030.enabled) { int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); if (atc_line_num>=0) { @@ -2170,7 +2199,7 @@ void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int fla static uae_u32 mmu030_get_generic_lrmw(uaecptr addr, uae_u32 fc, int size, int flags) { mmu030_cache_state = CACHE_ENABLE_ALL; - if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) { + if (fc != 7 && (!tt_enabled || !mmu030_match_lrmw_ttr_access(addr,fc)) && mmu030.enabled) { int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); if (atc_line_num>=0) { addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, true); diff --git a/gencpu.cpp b/gencpu.cpp index 64fc53c8..20850cef 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -2782,7 +2782,7 @@ static void resetvars (void) // tracer getpc = "m68k_getpci ()"; if (using_mmu == 68030) { - // 68030 cache MMU + // 68030 cache MMU / CE cache MMU disp020 = "get_disp_ea_020_mmu030c"; prefetch_long = "get_ilong_mmu030c_state"; prefetch_word = "get_iword_mmu030c_state"; @@ -5511,7 +5511,7 @@ static void generate_includes (FILE * f, int id) fprintf (f, "#include \"cputbl.h\"\n"); if (id == 31 || id == 33) fprintf (f, "#include \"cpummu.h\"\n"); - else if (id == 32 || id == 34) + else if (id == 32 || id == 34 || id == 35) fprintf (f, "#include \"cpummu030.h\"\n"); fprintf (f, "#define CPUFUNC(x) x##_ff\n" @@ -5880,7 +5880,7 @@ static void generate_cpu (int id, int mode) postfix = id; if (id == 0 || id == 11 || id == 13 || id == 20 || id == 21 || id == 22 || id == 23 || id == 24 || - id == 31 || id == 32 || id == 33 || id == 34 || + id == 31 || id == 32 || id == 33 || id == 34 || id == 35 || id == 40 || id == 50) { if (generate_stbl) fprintf (stblfile, "#ifdef CPUEMU_%d%s\n", postfix, extraup); @@ -5996,6 +5996,15 @@ static void generate_cpu (int id, int mode) read_counts (); for (rp = 0; rp < nr_cpuop_funcs; rp++) opcode_next_clev[rp] = cpu_level; + } else if (id == 35) { // 35 = 68030 MMU + caches + CE + mmu_postfix = "030c"; + cpu_level = 3; + using_ce020 = 2; + using_prefetch_020 = 2; + using_mmu = 68030; + read_counts (); + for (rp = 0; rp < nr_cpuop_funcs; rp++) + opcode_next_clev[rp] = cpu_level; } else if (id < 6) { cpu_level = 5 - (id - 0); // "generic" cpu_generic = true; @@ -6060,7 +6069,7 @@ int main(int argc, char *argv[]) generate_includes (stblfile, 0); for (i = 0; i <= 55; i++) { - if ((i >= 6 && i < 11) || (i > 14 && i < 20) || (i > 25 && i < 31) || (i > 34 && i < 40)) + if ((i >= 6 && i < 11) || (i > 14 && i < 20) || (i > 25 && i < 31) || (i > 35 && i < 40)) continue; generate_stbl = 1; generate_cpu (i, 0); diff --git a/include/cpummu.h b/include/cpummu.h index a60baf75..2831feb9 100644 --- a/include/cpummu.h +++ b/include/cpummu.h @@ -63,6 +63,7 @@ extern uae_u16 mmu_opcode; extern bool mmu_restart; extern bool mmu_ttr_enabled, mmu_ttr_enabled_ins, mmu_ttr_enabled_data; extern bool rmw_cycle; +extern uae_u8 mmu_cache_state; extern void mmu_dump_tables(void); @@ -76,6 +77,8 @@ extern void mmu_dump_tables(void); #define MMU_TTR_UX_SHIFT 8 #define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5)) #define MMU_TTR_CACHE_SHIFT 5 +#define MMU_TTR_CACHE_DISABLE (1 << 6) +#define MMU_TTR_CACHE_MODE (1 << 5) #define MMU_TTR_BIT_WRITE_PROTECT (1 << 2) #define MMU_UDT_MASK 3 @@ -108,6 +111,8 @@ extern void mmu_dump_tables(void); #define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0) #define MMU_MMUSR_S (1 << 7) #define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5)) +#define MMU_MMUSR_CM_DISABLE (1 << 6) +#define MMU_MMUSR_CM_MODE (1 << 5) #define MMU_MMUSR_M (1 << 4) #define MMU_MMUSR_W (1 << 2) #define MMU_MMUSR_T (1 << 1) @@ -233,6 +238,7 @@ extern void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size); #if MMU_IPAGECACHE extern uae_u32 atc_last_ins_laddr, atc_last_ins_paddr; +extern uae_u8 atc_last_ins_cache; #endif #if MMU_DPAGECACHE @@ -252,8 +258,16 @@ extern int mmu_data_read_hit, mmu_data_read_miss; extern int mmu_data_write_hit, mmu_data_write_miss; #endif +STATIC_INLINE void cacheablecheck(uaecptr addr) +{ + if (mmu_cache_state == CACHE_ENABLE_ALL) { + // MMU didn't inhibit caches, use hardware cache state + mmu_cache_state = ce_cachable[addr >> 16]; + } +} static ALWAYS_INLINE uae_u32 mmu_get_ilong(uaecptr addr, int size) { + mmu_cache_state = CACHE_ENABLE_ALL; if ((!mmu_ttr_enabled_ins || mmu_match_ttr_ins(addr,regs.s!=0) == TTR_NO_MATCH) && regs.mmu_enabled) { #if MMU_IPAGECACHE if (((addr & mmu_pagemaski) | regs.s) == atc_last_ins_laddr) { @@ -261,6 +275,7 @@ static ALWAYS_INLINE uae_u32 mmu_get_ilong(uaecptr addr, int size) mmu_ins_hit++; #endif addr = atc_last_ins_paddr | (addr & mmu_pagemask); + mmu_cache_state = atc_last_ins_cache; } else { #if CACHE_HIT_COUNT mmu_ins_miss++; @@ -271,11 +286,13 @@ static ALWAYS_INLINE uae_u32 mmu_get_ilong(uaecptr addr, int size) } #endif } + cacheablecheck(addr); return x_phys_get_ilong(addr); } static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size) { + mmu_cache_state = CACHE_ENABLE_ALL; if ((!mmu_ttr_enabled_ins || mmu_match_ttr_ins(addr,regs.s!=0) == TTR_NO_MATCH) && regs.mmu_enabled) { #if MMU_IPAGECACHE if (((addr & mmu_pagemaski) | regs.s) == atc_last_ins_laddr) { @@ -283,6 +300,7 @@ static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size) mmu_ins_hit++; #endif addr = atc_last_ins_paddr | (addr & mmu_pagemask); + mmu_cache_state = atc_last_ins_cache; } else { #if CACHE_HIT_COUNT mmu_ins_miss++; @@ -293,6 +311,7 @@ static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size) } #endif } + cacheablecheck(addr); return x_phys_get_iword(addr); } diff --git a/include/newcpu.h b/include/newcpu.h index f3699f5b..eb1d0abf 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -663,6 +663,7 @@ extern const struct cputbl op_smalltbl_22_ff[]; // prefetch extern const struct cputbl op_smalltbl_23_ff[]; // CE extern const struct cputbl op_smalltbl_32_ff[]; // MMU extern const struct cputbl op_smalltbl_34_ff[]; // MMU + cache +extern const struct cputbl op_smalltbl_35_ff[]; // MMU + CE + cache /* 68020 */ extern const struct cputbl op_smalltbl_3_ff[]; extern const struct cputbl op_smalltbl_43_ff[]; diff --git a/newcpu.cpp b/newcpu.cpp index ce5f30ec..97b8232a 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -1296,7 +1296,7 @@ void flush_cpu_caches(bool force) bool doflush = currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact; if (currprefs.cpu_model == 68020) { - if (regs.cacr & 0x08) { // clear instr cache + if ((regs.cacr & 0x08) || force) { // clear instr cache for (int i = 0; i < CACHELINES020; i++) caches020[i].valid = 0; regs.cacr &= ~0x08; @@ -1306,7 +1306,7 @@ void flush_cpu_caches(bool force) regs.cacr &= ~0x04; } } else if (currprefs.cpu_model == 68030) { - if (regs.cacr & 0x08) { // clear instr cache + if ((regs.cacr & 0x08) || force) { // clear instr cache if (doflush) { for (int i = 0; i < CACHELINES030; i++) { icaches030[i].valid[0] = 0; @@ -1321,7 +1321,7 @@ void flush_cpu_caches(bool force) icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0; regs.cacr &= ~0x04; } - if (regs.cacr & 0x800) { // clear data cache + if ((regs.cacr & 0x800) || force) { // clear data cache if (doflush) { for (int i = 0; i < CACHELINES030; i++) { dcaches030[i].valid[0] = 0; @@ -1354,9 +1354,48 @@ void flush_cpu_caches(bool force) void flush_cpu_caches_040(uae_u16 opcode) { int cache = (opcode >> 6) & 3; - if (!(cache & 2)) - return; - flush_cpu_caches(true); + int scope = (opcode >> 3) & 3; + int areg = opcode & 7; + uaecptr addr = m68k_areg(regs, areg); + bool push = (opcode & 0x20) != 0; + + regs.prefetch020addr = 0xffffffff; + for (int k = 0; k < 2; k++) { + if (cache & (1 << k)) { + if (scope == 3) { + // all + flush_cpu_caches(true); + } else { + uae_u32 pagesize; + if (scope == 2) { + // page + pagesize = mmu_pagesize_8k ? 8192 : 4096; + } else { + // line + pagesize = 16; + } + addr &= ~(pagesize - 1); + for (int j = 0; j < pagesize; j += 16, addr += 16) { + int index = (addr >> 4) & (cachesets04060minus1); + uae_u32 tag = addr & ~((cachesets04060 << 4) - 1); + struct cache040 *c = k ? &icaches040[index] : &dcaches040[index]; + for (int i = 0; i < CACHELINES040; i++) { + if (c->valid[i] && c->tag[i] == tag) { + // data cache not yet in use + for (int ii = 0; ii < 4; ii++) { + if (c->dirty[i][ii]) { + c->dirty[i][ii] = false; + if (push) + put_long(addr + ii * 4, c->data[i][ii]); + } + } + c->valid[i] = false; + } + } + } + } + } + } } void set_cpu_caches (bool flush) @@ -1397,21 +1436,21 @@ static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode) return 4; } -// generic+direct, generic+direct+jit, generic+indirect, more compatible, cycle-exact, mmu, mmu+more compatible -static const struct cputbl *cputbls[6][7] = +// generic+direct, generic+direct+jit, generic+indirect, more compatible, cycle-exact, mmu, mmu+more compatible, mmu+mc+ce +static const struct cputbl *cputbls[6][8] = { // 68000 - { op_smalltbl_5_ff, op_smalltbl_45_ff, op_smalltbl_55_ff, op_smalltbl_12_ff, op_smalltbl_14_ff, NULL, NULL }, + { op_smalltbl_5_ff, op_smalltbl_45_ff, op_smalltbl_55_ff, op_smalltbl_12_ff, op_smalltbl_14_ff, NULL, NULL, NULL }, // 68010 - { op_smalltbl_4_ff, op_smalltbl_44_ff, op_smalltbl_54_ff, op_smalltbl_11_ff, op_smalltbl_13_ff, NULL, NULL }, + { op_smalltbl_4_ff, op_smalltbl_44_ff, op_smalltbl_54_ff, op_smalltbl_11_ff, op_smalltbl_13_ff, NULL, NULL, NULL }, // 68020 - { op_smalltbl_3_ff, op_smalltbl_43_ff, op_smalltbl_53_ff, op_smalltbl_20_ff, op_smalltbl_21_ff, NULL, NULL }, + { op_smalltbl_3_ff, op_smalltbl_43_ff, op_smalltbl_53_ff, op_smalltbl_20_ff, op_smalltbl_21_ff, NULL, NULL, NULL }, // 68030 - { op_smalltbl_2_ff, op_smalltbl_42_ff, op_smalltbl_52_ff, op_smalltbl_22_ff, op_smalltbl_23_ff, op_smalltbl_32_ff, op_smalltbl_34_ff }, + { op_smalltbl_2_ff, op_smalltbl_42_ff, op_smalltbl_52_ff, op_smalltbl_22_ff, op_smalltbl_23_ff, op_smalltbl_32_ff, op_smalltbl_34_ff, op_smalltbl_35_ff }, // 68040 - { op_smalltbl_1_ff, op_smalltbl_41_ff, op_smalltbl_51_ff, op_smalltbl_25_ff, op_smalltbl_25_ff, op_smalltbl_31_ff, op_smalltbl_31_ff }, + { op_smalltbl_1_ff, op_smalltbl_41_ff, op_smalltbl_51_ff, op_smalltbl_25_ff, op_smalltbl_25_ff, op_smalltbl_31_ff, op_smalltbl_31_ff, op_smalltbl_31_ff }, // 68060 - { op_smalltbl_0_ff, op_smalltbl_40_ff, op_smalltbl_50_ff, op_smalltbl_24_ff, op_smalltbl_24_ff, op_smalltbl_33_ff, op_smalltbl_33_ff } + { op_smalltbl_0_ff, op_smalltbl_40_ff, op_smalltbl_50_ff, op_smalltbl_24_ff, op_smalltbl_24_ff, op_smalltbl_33_ff, op_smalltbl_33_ff, op_smalltbl_33_ff } }; static void build_cpufunctbl (void) @@ -1423,7 +1462,9 @@ static void build_cpufunctbl (void) if (!currprefs.cachesize) { if (currprefs.mmu_model) { - if (currprefs.cpu_compatible) + if (currprefs.cpu_cycle_exact) + mode = 7; + else if (currprefs.cpu_compatible) mode = 6; else mode = 5; @@ -1679,7 +1720,10 @@ static void prefs_changed_cpu (void) } } currprefs.mmu_ec = changed_prefs.mmu_ec; - currprefs.cpu_compatible = changed_prefs.cpu_compatible; + if (currprefs.cpu_compatible != changed_prefs.cpu_compatible) { + currprefs.cpu_compatible = changed_prefs.cpu_compatible; + flush_cpu_caches(true); + } currprefs.address_space_24 = changed_prefs.address_space_24; currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact; currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact; @@ -3310,6 +3354,7 @@ static void m68k_reset2(bool hardreset) mmufixup[0].reg = -1; mmufixup[1].reg = -1; mmu030_cache_state = CACHE_ENABLE_ALL; + mmu_cache_state = CACHE_ENABLE_ALL; cachesets04060 = currprefs.cpu_model == 68060 ? CACHESETS060 : CACHESETS040; cachesets04060minus1 = cachesets04060 - 1; if (currprefs.mmu_model >= 68040) { @@ -4977,6 +5022,12 @@ static void opcodedebug (uae_u32 pc, uae_u16 opcode, bool full) } } +static void check_halt(void) +{ + if (regs.halted) + do_specialties (0); +} + void cpu_halt (int id) { // id < 0: m68k halted, PPC active. @@ -5003,6 +5054,7 @@ static void m68k_run_mmu060 (void) struct flag_struct f; int halt = 0; + check_halt(); while (!halt) { TRY (prb) { for (;;) { @@ -5061,6 +5113,7 @@ static void m68k_run_mmu040 (void) flag_struct f; int halt = 0; + check_halt(); while (!halt) { TRY (prb) { for (;;) { @@ -5118,6 +5171,7 @@ static void m68k_run_mmu030 (void) mmu030_opcode_stageb = -1; mmu030_fake_prefetch = -1; + check_halt(); while(!halt) { TRY (prb) { for (;;) { @@ -5161,8 +5215,10 @@ insretry: for (;;) { regs.opcode = regs.irc = mmu030_opcode; mmu030_idx = 0; - count_instr (regs.opcode); - do_cycles (cpu_cycles); + if (!currprefs.cpu_cycle_exact) { + count_instr (regs.opcode); + do_cycles (cpu_cycles); + } mmu030_retry = false; cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode); @@ -7317,7 +7373,7 @@ void m68k_dumpcache (void) uae_u8 *restore_cpu (uae_u8 *src) { - int i, flags, model; + int flags, model; uae_u32 l; currprefs.cpu_model = changed_prefs.cpu_model = model = restore_u32 (); @@ -7332,7 +7388,7 @@ uae_u8 *restore_cpu (uae_u8 *src) currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact; currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0; currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0; - for (i = 0; i < 15; i++) + for (int i = 0; i < 15; i++) regs.regs[i] = restore_u32 (); regs.pc = restore_u32 (); regs.irc = restore_u16 (); @@ -7404,9 +7460,10 @@ uae_u8 *restore_cpu (uae_u8 *src) } } } else { - for (int i = 0; i < CPU_PIPELINE_MAX; i++) + for (int i = 0; i < CPU_PIPELINE_MAX; i++) { regs.prefetch020[i] = restore_u16 (); regs.prefetch020_valid[i] = false; + } } } else if (model == 68030) { for (int i = 0; i < CACHELINES030; i++) { @@ -8650,6 +8707,7 @@ static void fill_icache030 (uae_u32 addr) regs.cacheholdingdata_valid = 0; regs.cacheholdingaddr020 = 0xffffffff; regs.cacheholdingdata020 = 0xffffffff; + end_020_cycle_prefetch(false); return; } ENDTRY @@ -9033,6 +9091,7 @@ uae_u32 get_word_030_prefetch (int o) v = regs.prefetch020[0]; regs.prefetch020[0] = regs.prefetch020[1]; regs.prefetch020[1] = regs.prefetch020[2]; + regs.prefetch020_valid[2] = false; if (!regs.prefetch020_valid[1]) { do_access_or_bus_error(0xffffffff, pc); } @@ -9081,60 +9140,79 @@ uae_u32 get_long_icache030(uaecptr addr) uae_u32 fill_icache040(uae_u32 addr) { int index, lws; - uae_u32 tag; + uae_u32 tag, addr2; struct cache040 *c; int line; + uae_u8 cm = CACHE_ENABLE_ALL; static int lastline; - if (!(regs.cacr & 0x8000)) { - uae_u32 addr2 = addr & ~15; - lws = (addr >> 2) & 3; - addr &= ~3; - if (regs.prefetch020addr == addr2) - return regs.prefetch040[lws]; - regs.prefetch020addr = addr2; + addr2 = addr & ~15; + lws = (addr >> 2) & 3; + + if (regs.prefetch020addr == addr2) + return regs.prefetch040[lws]; + + if (regs.cacr & 0x8000) { + + index = (addr >> 4) & (cachesets04060minus1); + tag = regs.s | (addr & ~((cachesets04060 << 4) - 1)); + c = &icaches040[index]; + for (int i = 0; i < CACHELINES040; i++) { + if (c->valid[lastline] && c->tag[lastline] == tag) { + // cache hit + if (!(cm & CACHE_ENABLE_INS)) { + c->valid[lastline] = false; + goto end; + } + icachelinecnt++; + x_do_cycles(1 * cpucycleunit); + return c->data[lastline][lws]; + } + lastline++; + lastline &= (CACHELINES040 - 1); + } + // cache miss + cm = mmu_cache_state; + regs.prefetch020addr = 0xffffffff; regs.prefetch040[0] = icache_fetch(addr2 + 0); regs.prefetch040[1] = icache_fetch(addr2 + 4); regs.prefetch040[2] = icache_fetch(addr2 + 8); regs.prefetch040[3] = icache_fetch(addr2 + 12); + regs.prefetch020addr = addr2; + if (!(cm & CACHE_ENABLE_INS)) + goto end; + + if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) { + line = (icachelinecnt >> 1) & (CACHELINES040 - 1); + } else { + for (line = 0; line < CACHELINES040; line++) { + if (c->valid[line] == false) + break; + } + } + c->tag[line] = tag; + c->valid[line] = true; + c->data[line][0] = regs.prefetch040[0]; + c->data[line][1] = regs.prefetch040[1]; + c->data[line][2] = regs.prefetch040[2]; + c->data[line][3] = regs.prefetch040[3]; if (!currprefs.cpu_memory_cycle_exact) x_do_cycles(4 * cpucycleunit); - return regs.prefetch040[lws]; - } + return c->data[line][lws]; - index = (addr >> 4) & (cachesets04060minus1); - tag = regs.s | (addr & ~((cachesets04060 << 4) - 1)); - lws = (addr >> 2) & 3; - addr &= ~15; - c = &icaches040[index]; - for (int i = 0; i < CACHELINES040; i++) { - if (c->valid[lastline] && c->tag[lastline] == tag) { - // cache hit - icachelinecnt++; - x_do_cycles(1 * cpucycleunit); - return c->data[lastline][lws]; - } - lastline++; - lastline &= (CACHELINES040 - 1); } - // cache miss - if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) { - line = (icachelinecnt >> 1) & (CACHELINES040 - 1); - } else { - for (line = 0; line < CACHELINES040; line++) { - if (c->valid[line] == false) - break; - } - } - c->tag[line] = tag; - c->valid[line] = true; - c->data[line][0] = icache_fetch(addr + 0); - c->data[line][1] = icache_fetch(addr + 4); - c->data[line][2] = icache_fetch(addr + 8); - c->data[line][3] = icache_fetch(addr + 12); + +end: + if (regs.prefetch020addr == addr2) + return regs.prefetch040[lws]; + regs.prefetch020addr = addr2; + regs.prefetch040[0] = icache_fetch(addr2 + 0); + regs.prefetch040[1] = icache_fetch(addr2 + 4); + regs.prefetch040[2] = icache_fetch(addr2 + 8); + regs.prefetch040[3] = icache_fetch(addr2 + 12); if (!currprefs.cpu_memory_cycle_exact) x_do_cycles(4 * cpucycleunit); - return c->data[line][lws]; + return regs.prefetch040[lws]; } #if 0 diff --git a/od-win32/sysconfig.h b/od-win32/sysconfig.h index 3d33d0e6..f3acc0ef 100644 --- a/od-win32/sysconfig.h +++ b/od-win32/sysconfig.h @@ -66,6 +66,7 @@ #define CPUEMU_32 /* Previous 68030 MMU */ #define CPUEMU_33 /* 68060 MMU */ #define CPUEMU_34 /* 68030 MMU + cache */ +#define CPUEMU_35 /* 68030 MMU + cache + CE */ #define CPUEMU_40 /* generic 680x0 with JIT direct memory access */ #define CPUEMU_50 /* generic 680x0 with indirect memory access */ #define ACTION_REPLAY /* Action Replay 1/2/3 support */