From: Toni Wilen Date: Fri, 28 Jul 2017 14:56:25 +0000 (+0300) Subject: 68030 MMU mode cache enable/cache inhibit emulation improved. 68040/060 MMU mode... X-Git-Tag: 3600~141 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=05d1bec2bf61a00c84524a37b8f864431348228e;p=francis%2Fwinuae.git 68030 MMU mode cache enable/cache inhibit emulation improved. 68040/060 MMU mode instruction cache is now emulated if compatible mode. --- diff --git a/cpummu30.cpp b/cpummu30.cpp index 4e2fab6f..91043cbd 100644 --- a/cpummu30.cpp +++ b/cpummu30.cpp @@ -69,7 +69,7 @@ uae_u16 mmu030_state[3]; uae_u32 mmu030_data_buffer; uae_u32 mmu030_disp_store[2]; uae_u32 mmu030_fmovem_store[2]; -int mmu030_cache_inhibit; +uae_u8 mmu030_cache_state; struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS]; #if MMU_DPAGECACHE030 @@ -100,7 +100,7 @@ typedef struct { uaecptr addr; bool modified; bool write_protect; - bool cache_inhibit; + uae_u8 cache_inhibit; bool bus_error; } physical; @@ -149,7 +149,7 @@ static struct { uae_u16 status; #if MMU_IPAGECACHE030 - int mmu030_cache_inhibit; + uae_u8 mmu030_cache_state; #if MMU_DIRECT_ACCESS uae_u8 *mmu030_last_physical_address_real; #else @@ -699,12 +699,12 @@ static int mmu030_match_ttr(uaecptr addr, uae_u32 fc, bool write) tt0 = mmu030_do_match_ttr(tt0_030, mmu030.transparent.tt0, addr, fc, write); if (tt0&TT_OK_MATCH) { if (tt0_030&TT_CI) - mmu030_cache_inhibit = 1; + mmu030_cache_state = CACHE_DISABLE_MMU; } tt1 = mmu030_do_match_ttr(tt1_030, mmu030.transparent.tt1, addr, fc, write); if (tt1&TT_OK_MATCH) { if (tt0_030&TT_CI) - mmu030_cache_inhibit = 1; + mmu030_cache_state = CACHE_DISABLE_MMU; } return (tt0|tt1); @@ -1196,7 +1196,7 @@ uae_u32 mmu030_table_search(uaecptr addr, uae_u32 fc, bool write, int level) { bool super = (fc&4) ? true : false; bool super_violation = false; bool write_protected = false; - bool cache_inhibit = false; + uae_u8 cache_inhibit = CACHE_ENABLE_ALL; bool descr_modified = false; mmu030.status = 0; /* Reset status */ @@ -1483,7 +1483,7 @@ uae_u32 mmu030_table_search(uaecptr addr, uae_u32 fc, bool write, int level) { mmu030.status |= write_protected ? MMUSR_WRITE_PROTECTED : 0; /* check if caching is inhibited */ - cache_inhibit = descr[0]&DESCR_CI ? true : false; + cache_inhibit = (descr[0]&DESCR_CI) ? CACHE_DISABLE_MMU : CACHE_ENABLE_ALL; /* check for the modified bit and set it in the status register */ mmu030.status |= (descr[0]&DESCR_M) ? MMUSR_MODIFIED : 0; @@ -1779,7 +1779,7 @@ static uaecptr mmu030_put_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) { return 0; } - mmu030_cache_inhibit = mmu030.atc[l].physical.cache_inhibit; + mmu030_cache_state = mmu030.atc[l].physical.cache_inhibit; mmu030_add_data_write_cache(addr, physical_addr, fc); @@ -1801,7 +1801,7 @@ static uaecptr mmu030_get_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) { return 0; } - mmu030_cache_inhibit = mmu030.atc[l].physical.cache_inhibit; + mmu030_cache_state = mmu030.atc[l].physical.cache_inhibit; mmu030_add_data_read_cache(addr, physical_addr, fc); @@ -1824,7 +1824,7 @@ static uaecptr mmu030_get_i_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) { } #if MMU_IPAGECACHE030 - mmu030.mmu030_cache_inhibit = mmu030.atc[l].physical.cache_inhibit; + mmu030.mmu030_cache_state = mmu030.atc[l].physical.cache_inhibit; #if MMU_DIRECT_ACCESS mmu030.mmu030_last_physical_address_real = get_real_address(physical_addr); #else @@ -1833,7 +1833,7 @@ static uaecptr mmu030_get_i_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) { mmu030.mmu030_last_logical_address = (addr & mmu030.translation.page.imask) | fc; #endif - mmu030_cache_inhibit = mmu030.atc[l].physical.cache_inhibit; + mmu030_cache_state = mmu030.atc[l].physical.cache_inhibit; return physical_addr + page_index; } @@ -1927,13 +1927,15 @@ static int mmu030_logical_is_in_atc(uaecptr addr, uae_u32 fc, bool write) { STATIC_INLINE void cacheablecheck(uaecptr addr) { - if (!ce_cachable[addr >> 16] && !mmu030_cache_inhibit) - mmu030_cache_inhibit = -1; // CIN active + if (mmu030_cache_state == CACHE_ENABLE_ALL) { + // MMU didn't inhibit caches, use hardware cache state + mmu030_cache_state = ce_cachable[addr >> 16]; + } } void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc) { - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true)) && mmu030.enabled) { #if MMU_DPAGECACHE030 uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc; @@ -1958,7 +1960,7 @@ void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc) void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc) { - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true)) && mmu030.enabled) { #if MMU_DPAGECACHE030 uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc; @@ -1983,7 +1985,7 @@ void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc) void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc) { - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true)) && mmu030.enabled) { #if MMU_DPAGECACHE030 uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc; @@ -2009,7 +2011,7 @@ void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc) uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc) { - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) { #if MMU_DPAGECACHE030 uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc; @@ -2034,7 +2036,7 @@ uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc) uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc) { - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) { #if MMU_DPAGECACHE030 uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc; @@ -2059,7 +2061,7 @@ uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc) uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc) { - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) { #if MMU_DPAGECACHE030 uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc; @@ -2091,14 +2093,14 @@ uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc) uae_u8 *p = &mmu030.mmu030_last_physical_address_real[addr & mmu030.translation.page.mask]; return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); #else - mmu030_cache_inhibit = mmu030.mmu030_cache_inhibit; + mmu030_cache_state = mmu030.mmu030_cache_state; return x_phys_get_ilong(mmu030.mmu030_last_physical_address + (addr & mmu030.translation.page.mask)); #endif } mmu030.mmu030_last_logical_address = 0xffffffff; #endif - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) { int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); if (atc_line_num >= 0) { @@ -2108,6 +2110,7 @@ uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc) addr = mmu030_get_i_atc(addr, mmu030_logical_is_in_atc(addr, fc, false), fc, MMU030_SSW_SIZE_L); } } + cacheablecheck(addr); return x_phys_get_ilong(addr); } @@ -2119,14 +2122,14 @@ uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc) { uae_u8 *p = &mmu030.mmu030_last_physical_address_real[addr & mmu030.translation.page.mask]; return (p[0] << 8) | p[1]; #else - mmu030_cache_inhibit = mmu030.mmu030_cache_inhibit; + mmu030_cache_state = mmu030.mmu030_cache_state; return x_phys_get_iword(mmu030.mmu030_last_physical_address + (addr & mmu030.translation.page.mask)); #endif } mmu030.mmu030_last_logical_address = 0xffffffff; #endif - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) { int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); if (atc_line_num >= 0) { @@ -2136,13 +2139,14 @@ uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc) { addr = mmu030_get_i_atc(addr, mmu030_logical_is_in_atc(addr, fc, false), fc, MMU030_SSW_SIZE_W); } } + cacheablecheck(addr); return x_phys_get_iword(addr); } /* Not commonly used access function */ void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int flags) { - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; 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) { @@ -2165,7 +2169,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_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) { int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); if (atc_line_num>=0) { @@ -2187,7 +2191,7 @@ static uae_u32 mmu030_get_generic_lrmw(uaecptr addr, uae_u32 fc, int size, int f uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int flags) { - mmu030_cache_inhibit = 0; + mmu030_cache_state = CACHE_ENABLE_ALL; if (flags & MMU030_SSW_RM) { return mmu030_get_generic_lrmw(addr, fc, size, flags); @@ -2212,9 +2216,10 @@ uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int flags) return x_phys_get_long(addr); } -bool uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size) +uae_u8 uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size) { uae_u32 fc = regs.fc030; + mmu030_cache_state = CACHE_ENABLE_ALL; if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,write)) && mmu030.enabled) { uae_u32 flags = mmu030_size[size]; int atc_line_num = mmu030_logical_is_in_atc(addr, fc, write); @@ -2226,8 +2231,10 @@ bool uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size) addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, false); } } - cacheablecheck(addr); - return mmu030_cache_inhibit == 0; + // MMU inhibited + if (mmu030_cache_state != CACHE_ENABLE_ALL) + return mmu030_cache_state; + return ce_cachable[addr >> 16]; } /* Locked RMW is rarely used */ diff --git a/include/cpummu.h b/include/cpummu.h index a7cde2d0..a60baf75 100644 --- a/include/cpummu.h +++ b/include/cpummu.h @@ -271,7 +271,7 @@ static ALWAYS_INLINE uae_u32 mmu_get_ilong(uaecptr addr, int size) } #endif } - return phys_get_long(addr); + return x_phys_get_ilong(addr); } static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size) @@ -293,7 +293,7 @@ static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size) } #endif } - return phys_get_word(addr); + return x_phys_get_iword(addr); } diff --git a/include/cpummu030.h b/include/cpummu030.h index 9bd41f4c..3e3baa33 100644 --- a/include/cpummu030.h +++ b/include/cpummu030.h @@ -23,7 +23,7 @@ extern uae_u16 mmu030_state[3]; extern uae_u32 mmu030_data_buffer; extern uae_u32 mmu030_disp_store[2]; extern uae_u32 mmu030_fmovem_store[2]; -extern int mmu030_cache_inhibit; +extern uae_u8 mmu030_cache_state, mmu030_cache_state_default; #define MMU030_STATEFLAG1_FMOVEM 0x2000 #define MMU030_STATEFLAG1_MOVEM1 0x4000 @@ -204,7 +204,7 @@ static ALWAYS_INLINE void uae_mmu030_put_byte_fc(uaecptr addr, uae_u32 val) { mmu030_put_byte(addr, val, regs.fc030); } -bool uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size); +uae_u8 uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size); #define ACCESS_CHECK_PUT \ if (!mmu030_ad[mmu030_idx].done) { \ @@ -663,7 +663,6 @@ STATIC_INLINE uae_u32 get_iword_mmu030c_state (int o) ACCESS_EXIT_GET return v; } -uae_u32 get_long_030_prefetch(int o); STATIC_INLINE uae_u32 get_ilong_mmu030c_state (int o) { uae_u32 v; diff --git a/include/memory.h b/include/memory.h index 1666db6c..951b4ac2 100644 --- a/include/memory.h +++ b/include/memory.h @@ -166,6 +166,14 @@ struct autoconfig_info #define CE_MEMBANK_CHIP32 2 #define CE_MEMBANK_CIA 3 #define CE_MEMBANK_FAST16 4 +//#define CE_MEMBANK_FAST16_EXTRA_ACCURACY 5 +#define CACHE_ENABLE_DATA 0x01 +#define CACHE_ENABLE_DATA_BURST 0x02 +#define CACHE_ENABLE_INS 0x80 +#define CACHE_ENABLE_INS_BURST 0x40 +#define CACHE_ENABLE_BOTH (CACHE_ENABLE_DATA | CACHE_ENABLE_INS) +#define CACHE_ENABLE_ALL (CACHE_ENABLE_BOTH | CACHE_ENABLE_INS_BURST | CACHE_ENABLE_DATA_BURST) +#define CACHE_DISABLE_MMU 0x10 extern uae_u8 ce_banktype[65536], ce_cachable[65536]; #define MEMORY_LGET(name) \ diff --git a/include/newcpu.h b/include/newcpu.h index 374a7c2a..f3699f5b 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -125,6 +125,7 @@ struct cache030 }; #define CACHESETS040 64 +#define CACHESETS060 128 #define CACHELINES040 4 struct cache040 { @@ -223,6 +224,8 @@ struct regstruct int pipeline_stop; uae_u8 fc030; + uae_u32 prefetch040[CPU_PIPELINE_MAX]; + int ce020endcycle; int ce020startcycle; int ce020prefetchendcycle; diff --git a/memory.cpp b/memory.cpp index 81eb6588..b75e5813 100644 --- a/memory.cpp +++ b/memory.cpp @@ -1822,7 +1822,7 @@ static void add_shmmaps (uae_u32 start, addrbank *what) y = xmalloc (shmpiece, 1); *y = *x; base = ((uae_u8 *) NATMEM_OFFSET) + start; - y->native_address = (uae_u8*)uae_shmat (what, y->id, base, 0); + y->native_address = (uae_u8*)uae_shmat (what, y->id, base, 0, NULL); if (y->native_address == (void *) -1) { write_log (_T("NATMEM: Failure to map existing at %08x (%p)\n"), start, base); dumplist (); @@ -1902,7 +1902,7 @@ bool mapped_malloc (addrbank *ab) return ab->baseaddr != NULL; } if (!(ab->flags & ABFLAG_NOALLOC)) { - answer = uae_shmat (ab, id, 0, 0); + answer = uae_shmat (ab, id, NULL, 0, &md); uae_shmctl (id, UAE_IPC_RMID, NULL); } else { write_log(_T("MMAN: mapped_malloc using existing baseaddr %p\n"), ab->baseaddr); @@ -2216,18 +2216,25 @@ static void fill_ce_banks (void) } else { memset (ce_banktype, CE_MEMBANK_FAST32, sizeof ce_banktype); } - // data cachable regions (2 = burst supported) - memset(ce_cachable, 0, sizeof ce_cachable); - memset(ce_cachable + (0x00c00000 >> 16), 1, currprefs.bogomem_size >> 16); + + memset(ce_cachable, CACHE_ENABLE_INS, sizeof ce_cachable); + memset(ce_cachable + (0x00f80000 >> 16), CACHE_ENABLE_BOTH, 524288 >> 16); + memset(ce_cachable + (0x00c00000 >> 16), CACHE_ENABLE_BOTH, currprefs.bogomem_size >> 16); for (int i = 0; i < MAX_RAM_BOARDS; i++) { if (fastmem_bank[i].start != 0xffffffff) - memset(ce_cachable + (fastmem_bank[i].start >> 16), 1 | 2, currprefs.fastmem[i].size >> 16); + memset(ce_cachable + (fastmem_bank[i].start >> 16), CACHE_ENABLE_BOTH, currprefs.fastmem[i].size >> 16); if (z3fastmem_bank[i].start != 0xffffffff) - memset(ce_cachable + (z3fastmem_bank[i].start >> 16), 1 | 2, currprefs.z3fastmem[i].size >> 16); + memset(ce_cachable + (z3fastmem_bank[i].start >> 16), CACHE_ENABLE_ALL, currprefs.z3fastmem[i].size >> 16); + } + memset(ce_cachable + (a3000hmem_bank.start >> 16), CACHE_ENABLE_ALL, currprefs.mbresmem_high_size >> 16); + memset(ce_cachable + (a3000lmem_bank.start >> 16), CACHE_ENABLE_ALL, currprefs.mbresmem_low_size >> 16); + memset(ce_cachable + (mem25bit_bank.start >> 16), CACHE_ENABLE_ALL, currprefs.mem25bit_size >> 16); + + if (uae_boot_rom_type > 0) { + for (int i = 0; i < sizeof(ce_cachable); i++) { + ce_cachable[i] &= ~(CACHE_ENABLE_DATA | CACHE_ENABLE_DATA_BURST); + } } - memset(ce_cachable + (a3000hmem_bank.start >> 16), 1 | 2, currprefs.mbresmem_high_size >> 16); - memset(ce_cachable + (a3000lmem_bank.start >> 16), 1 | 2, currprefs.mbresmem_low_size >> 16); - memset(ce_cachable + (mem25bit_bank.start >> 16), 1 | 2, currprefs.mem25bit_size >> 16); addrbank *ab = &get_mem_bank(0); if (ab && (ab->flags & ABFLAG_CHIPRAM)) { diff --git a/newcpu.cpp b/newcpu.cpp index 9de571a8..ce5f30ec 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -78,7 +78,7 @@ int m68k_pc_indirect; bool m68k_interrupt_delay; static bool m68k_reset_delay; -static bool dcache_complete_inhibit; +static int cachesets04060, cachesets04060minus1; static int cpu_prefs_changed_flag; @@ -116,8 +116,8 @@ static struct cache020 caches020[CACHELINES020]; static struct cache030 icaches030[CACHELINES030]; static struct cache030 dcaches030[CACHELINES030]; static int icachelinecnt, dcachelinecnt; -static struct cache040 icaches040[CACHESETS040]; -static struct cache040 dcaches040[CACHESETS040]; +static struct cache040 icaches040[CACHESETS060]; +static struct cache040 dcaches040[CACHESETS060]; static int fallback_cpu_model, fallback_mmu_model, fallback_fpu_model; static bool fallback_cpu_compatible, fallback_cpu_address_space_24; @@ -761,16 +761,16 @@ static void do_cycles_ce020_post (unsigned long cycles, uae_u32 v) do_cycles_ce020 (cycles); } -static bool dcache030_check_dummy(uaecptr addr, bool write, uae_u32 size) +static uae_u8 dcache030_check_nommu(uaecptr addr, bool write, uae_u32 size) { - return true; + return ce_cachable[addr >> 16]; } static uae_u32 (*icache_fetch)(uaecptr); static uae_u32 (*dcache030_lget)(uaecptr); static uae_u32 (*dcache030_wget)(uaecptr); static uae_u32 (*dcache030_bget)(uaecptr); -static bool (*dcache030_check)(uaecptr, bool, uae_u32); +static uae_u8 (*dcache030_check)(uaecptr, bool, uae_u32); static void (*dcache030_lput)(uaecptr, uae_u32); static void (*dcache030_wput)(uaecptr, uae_u32); static void (*dcache030_bput)(uaecptr, uae_u32); @@ -1225,7 +1225,7 @@ static void set_x_funcs (void) dcache030_lget = get_long; dcache030_wget = get_word; dcache030_bget = get_byte; - dcache030_check = dcache030_check_dummy; + dcache030_check = dcache030_check_nommu; if (currprefs.cpu_cycle_exact) { icache_fetch = mem_access_delay_longi_read_ce020; } @@ -1341,7 +1341,7 @@ void flush_cpu_caches(bool force) icachelinecnt = 0; dcachelinecnt = 0; if (doflush) { - for (int i = 0; i < CACHESETS040; i++) { + for (int i = 0; i < CACHESETS060; i++) { icaches040[i].valid[0] = 0; icaches040[i].valid[1] = 0; icaches040[i].valid[2] = 0; @@ -1397,7 +1397,7 @@ static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode) return 4; } -// generic+direct, generic+direct+jit, generic+indirect, more compatible, cycle-exact, mmu, mm+more compatible +// generic+direct, generic+direct+jit, generic+indirect, more compatible, cycle-exact, mmu, mmu+more compatible static const struct cputbl *cputbls[6][7] = { // 68000 @@ -1409,9 +1409,9 @@ static const struct cputbl *cputbls[6][7] = // 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 }, // 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, NULL }, + { 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 }, // 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, NULL } + { 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 } }; static void build_cpufunctbl (void) @@ -3309,9 +3309,9 @@ static void m68k_reset2(bool hardreset) mmufixup[0].reg = -1; mmufixup[1].reg = -1; - mmu030_cache_inhibit = 0; - dcache_complete_inhibit = uae_boot_rom_type > 0; - //dcache_complete_inhibit = true; + mmu030_cache_state = CACHE_ENABLE_ALL; + cachesets04060 = currprefs.cpu_model == 68060 ? CACHESETS060 : CACHESETS040; + cachesets04060minus1 = cachesets04060 - 1; if (currprefs.mmu_model >= 68040) { mmu_reset (); mmu_set_tc (regs.tcr); @@ -7395,12 +7395,18 @@ uae_u8 *restore_cpu (uae_u8 *src) regs.cacheholdingaddr020 = restore_u32 (); regs.cacheholdingdata020 = restore_u32 (); if (flags & 0x20000000) { - // 2.7.0 new - for (int i = 0; i < CPU_PIPELINE_MAX; i++) - regs.prefetch020[i] = restore_u32 (); + if (flags & 0x4000000) { + // 3.6 new (back to 16 bits) + for (int i = 0; i < CPU_PIPELINE_MAX; i++) { + uae_u32 v = restore_u32(); + regs.prefetch020[i] = v >> 16; + regs.prefetch020_valid[i] = (v & 1) != 0; + } + } } else { 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++) { @@ -7420,11 +7426,21 @@ uae_u8 *restore_cpu (uae_u8 *src) regs.prefetch020addr = restore_u32 (); regs.cacheholdingaddr020 = restore_u32 (); regs.cacheholdingdata020 = restore_u32 (); - for (int i = 0; i < CPU_PIPELINE_MAX; i++) - regs.prefetch020[i] = restore_u32 (); + if (flags & 0x4000000) { + for (int i = 0; i < CPU_PIPELINE_MAX; i++) { + uae_u32 v = restore_u32(); + regs.prefetch020[i] = v >> 16; + regs.prefetch020_valid[i] = (v & 1) != 0; + } + } else { + for (int i = 0; i < CPU_PIPELINE_MAX; i++) { + regs.prefetch020[i] = restore_u32 (); + regs.prefetch020_valid[i] = false; + } + } } else if (model == 68040) { if (flags & 0x8000000) { - for (int i = 0; i < CACHESETS040; i++) { + for (int i = 0; i < ((model == 68060 && (flags & 0x4000000)) ? CACHESETS060 : CACHESETS040); i++) { for (int j = 0; j < CACHELINES040; j++) { icaches040[i].data[j][0] = restore_u32(); icaches040[i].data[j][1] = restore_u32(); @@ -7438,7 +7454,7 @@ uae_u8 *restore_cpu (uae_u8 *src) regs.cacheholdingaddr020 = restore_u32(); regs.cacheholdingdata020 = restore_u32(); for (int i = 0; i < CPU_PIPELINE_MAX; i++) - regs.prefetch020[i] = restore_u32(); + regs.prefetch040[i] = restore_u32(); } } if (model >= 68020) { @@ -7682,7 +7698,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr) dstbak = dst = xmalloc (uae_u8, 1000 + 20000); model = currprefs.cpu_model; save_u32 (model); /* MODEL */ - save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 |(currprefs.address_space_24 ? 1 : 0)); /* FLAGS */ + save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 | 0x4000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */ for (i = 0;i < 15; i++) save_u32 (regs.regs[i]); /* D0-D7 A0-A6 */ save_u32 (m68k_getpc ()); /* PC */ @@ -7751,7 +7767,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr) save_u32 (regs.cacheholdingaddr020); save_u32 (regs.cacheholdingdata020); for (int i = 0; i < CPU_PIPELINE_MAX; i++) - save_u32 (regs.prefetch020[i]); + save_u32 ((regs.prefetch020[i] << 16) | (regs.prefetch020_valid[i] ? 1 : 0)); } else if (model == 68030) { for (int i = 0; i < CACHELINES030; i++) { for (int j = 0; j < 4; j++) { @@ -7773,7 +7789,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr) for (int i = 0; i < CPU_PIPELINE_MAX; i++) save_u32 (regs.prefetch020[i]); } else if (model >= 68040) { - for (int i = 0; i < CACHESETS040; i++) { + for (int i = 0; i < (model == 68060 ? CACHESETS060 : CACHESETS040); i++) { for (int j = 0; j < CACHELINES040; j++) { save_u32(icaches040[i].data[j][0]); save_u32(icaches040[i].data[j][1]); @@ -7787,7 +7803,7 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr) save_u32(regs.cacheholdingaddr020); save_u32(regs.cacheholdingdata020); for (int i = 0; i < CPU_PIPELINE_MAX; i++) - save_u32(regs.prefetch020[i]); + save_u32(regs.prefetch040[i]); } if (currprefs.cpu_model >= 68020) { save_u32 (0); //save_u32 (regs.ce020memcycles); @@ -8637,12 +8653,12 @@ static void fill_icache030 (uae_u32 addr) return; } ENDTRY - if (!mmu030_cache_inhibit) { + if (mmu030_cache_state & CACHE_ENABLE_INS) { if ((regs.cacr & 0x03) == 0x01) { // instruction cache not frozen and enabled update_icache030 (c, data, tag, lws); } - if ((regs.cacr & 0x11) == 0x11 && (c->valid[0] + c->valid[1] + c->valid[2] + c->valid[3] == 1) && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) { + if ((mmu030_cache_state & CACHE_ENABLE_INS_BURST) && (regs.cacr & 0x11) == 0x11 && (c->valid[0] + c->valid[1] + c->valid[2] + c->valid[3] == 1)) { // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram int i; for (i = 0; i < 4; i++) { @@ -8651,9 +8667,9 @@ static void fill_icache030 (uae_u32 addr) } uaecptr baddr = addr & ~15; if (currprefs.mmu_model) { - if (currprefs.cpu_cycle_exact) - do_cycles_ce020(3 * (CPU020_MEM_CYCLE - 1)); TRY (prb) { + if (currprefs.cpu_cycle_exact) + do_cycles_ce020(3 * (CPU020_MEM_CYCLE - 1)); for (int j = 0; j < 3; j++) { i++; i &= 3; @@ -8679,12 +8695,6 @@ static void fill_icache030 (uae_u32 addr) regs.cacheholdingdata020 = data; } -STATIC_INLINE bool candcache030 (uaecptr addr) -{ - // mmu mode cacheability is checked in mmu030_get/mmu030_put routines - return currprefs.mmu_model || ce_cachable[addr >> 16] != 0; -} - #if VALIDATE_68030_DATACACHE static void validate_dcache030(void) { @@ -8744,7 +8754,7 @@ static void write_dcache030x(uaecptr addr, uae_u32 val, uae_u32 size, uae_u32 fc // All writes ignore external CIIN signal. if (width == 32 && offset == 0 && wa) { - if (mmu030_cache_inhibit <= 0) { + if (!(mmu030_cache_state & CACHE_DISABLE_MMU)) { update_dcache030(c1, val, tag1, fc, lws1); #if VALIDATE_68030_DATACACHE validate_dcache030(); @@ -8857,7 +8867,7 @@ uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc) { uae_u32 addr_o = addr; regs.fc030 = fc; - if ((regs.cacr & 0x100) && !dcache_complete_inhibit) { // data cache enabled? + if (regs.cacr & 0x100) { // data cache enabled? static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff }; struct cache030 *c1, *c2; int lws1, lws2; @@ -8871,16 +8881,14 @@ uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc) c1 = getdcache030 (dcaches030, addr, &tag1, &lws1); addr &= ~3; if (!c1->valid[lws1] || c1->tag != tag1 || c1->fc != fc) { - // Cache miss and caching inhibited -> normal read - if (mmu030_cache_inhibit || !candcache030(addr)) - goto end; // MMU validate address, returns zero if valid but uncacheable // throws bus error if invalid - if (!dcache030_check(addr_o, false, size)) + uae_u8 cs = dcache030_check(addr_o, false, size); + if (!(cs & CACHE_ENABLE_DATA)) goto end; v1 = dcache030_lget(addr); update_dcache030 (c1, v1, tag1, fc, lws1); - if (!mmu030_cache_inhibit && (regs.cacr & 0x1100) == 0x1100) + if ((cs & CACHE_ENABLE_DATA_BURST) && (regs.cacr & 0x1100) == 0x1100) dcache030_maybe_burst(addr, c1, lws1); #if VALIDATE_68030_DATACACHE validate_dcache030(); @@ -8907,13 +8915,12 @@ uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc) addr += 4; c2 = getdcache030 (dcaches030, addr, &tag2, &lws2); if (!c2->valid[lws2] || c2->tag != tag2 || c2->fc != fc) { - if (mmu030_cache_inhibit || !candcache030(addr)) - goto end; - if (!dcache030_check(addr, false, 2)) + uae_u8 cs = dcache030_check(addr, false, 2); + if (!(cs & CACHE_ENABLE_DATA)) goto end; v2 = dcache030_lget(addr); update_dcache030 (c2, v2, tag2, fc, lws2); - if (!mmu030_cache_inhibit && (regs.cacr & 0x1100) == 0x1100) + if ((cs & CACHE_ENABLE_DATA_BURST) && (regs.cacr & 0x1100) == 0x1100) dcache030_maybe_burst(addr, c2, lws2); #if VALIDATE_68030_DATACACHE validate_dcache030(); @@ -8956,12 +8963,12 @@ void write_dcache030_mmu(uaecptr addr, uae_u32 val, uae_u32 size) uae_u32 read_dcache030_lrmw_mmu(uaecptr addr, uae_u32 size) { - mmu030_cache_inhibit = 1; + mmu030_cache_state = CACHE_DISABLE_MMU; return read_dcache030(addr, size, (regs.s ? 4 : 0) | 1); } void write_dcache030_lrmw_mmu(uaecptr addr, uae_u32 val, uae_u32 size) { - mmu030_cache_inhibit = 1; + mmu030_cache_state = CACHE_DISABLE_MMU; write_dcache030(addr, val, size, (regs.s ? 4 : 0) | 1); } @@ -9073,51 +9080,47 @@ uae_u32 get_long_icache030(uaecptr addr) uae_u32 fill_icache040(uae_u32 addr) { - int index, i, lws; + int index, lws; uae_u32 tag; struct cache040 *c; int line; + static int lastline; if (!(regs.cacr & 0x8000)) { uae_u32 addr2 = addr & ~15; lws = (addr >> 2) & 3; addr &= ~3; if (regs.prefetch020addr == addr2) - return regs.prefetch020[lws]; + return regs.prefetch040[lws]; regs.prefetch020addr = addr2; - if (currprefs.cpu_memory_cycle_exact) { - regs.prefetch020[0] = mem_access_delay_longi_read_ce020(addr2 + 0); - regs.prefetch020[1] = mem_access_delay_longi_read_ce020(addr2 + 4); - regs.prefetch020[2] = mem_access_delay_longi_read_ce020(addr2 + 8); - regs.prefetch020[3] = mem_access_delay_longi_read_ce020(addr2 + 12); - } else { - regs.prefetch020[0] = get_longi(addr2 + 0); - regs.prefetch020[1] = get_longi(addr2 + 4); - regs.prefetch020[2] = get_longi(addr2 + 8); - regs.prefetch020[3] = get_longi(addr2 + 12); + 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 regs.prefetch020[lws]; + return regs.prefetch040[lws]; } - index = (addr >> 4) & (CACHESETS040 - 1); - tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1)); + index = (addr >> 4) & (cachesets04060minus1); + tag = regs.s | (addr & ~((cachesets04060 << 4) - 1)); lws = (addr >> 2) & 3; addr &= ~15; c = &icaches040[index]; - for (i = 0; i < CACHELINES040; i++) { - if (c->valid[i] && c->tag[i] == tag) { + 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[i][lws]; + 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 { + } else { for (line = 0; line < CACHELINES040; line++) { if (c->valid[line] == false) break; @@ -9125,18 +9128,12 @@ uae_u32 fill_icache040(uae_u32 addr) } c->tag[line] = tag; c->valid[line] = true; - if (currprefs.cpu_memory_cycle_exact) { - c->data[line][0] = mem_access_delay_longi_read_ce020(addr + 0); - c->data[line][1] = mem_access_delay_longi_read_ce020(addr + 4); - c->data[line][2] = mem_access_delay_longi_read_ce020(addr + 8); - c->data[line][3] = mem_access_delay_longi_read_ce020(addr + 12); - } else { - c->data[line][0] = get_longi(addr + 0); - c->data[line][1] = get_longi(addr + 4); - c->data[line][2] = get_longi(addr + 8); - c->data[line][3] = get_longi(addr + 12); + 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); + if (!currprefs.cpu_memory_cycle_exact) x_do_cycles(4 * cpucycleunit); - } return c->data[line][lws]; }