]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Full 68040/060 data cache emulation, MMU emulation compatible. 68030/040/060 data...
authorToni Wilen <twilen@winuae.net>
Sat, 12 Aug 2017 18:29:30 +0000 (21:29 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 12 Aug 2017 18:29:30 +0000 (21:29 +0300)
16 files changed:
cfgfile.cpp
cpummu.cpp
cpummu30.cpp
debug.cpp
expansion.cpp
filesys.cpp
gfxboard.cpp
include/cpu_prefetch.h
include/cpummu.h
include/cpummu030.h
include/memory.h
include/newcpu.h
include/options.h
main.cpp
memory.cpp
newcpu.cpp

index f235a53210241a6c55af4624f9727f5870571925..2e8dcbf3edd79429eff0880bef3b2e6e7d91a3fc 100644 (file)
@@ -1953,6 +1953,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
 
        cfgfile_write_bool (f, _T("immediate_blits"), p->immediate_blits);
        cfgfile_dwrite_str (f, _T("waiting_blits"), waitblits[p->waiting_blits]);
+       cfgfile_dwrite (f, _T("blitter_throttle"), _T("%.8f"), p->blitter_speed_throttle);
        cfgfile_write_bool (f, _T("ntsc"), p->ntscmode);
        cfgfile_write_bool(f, _T("genlock"), p->genlock);
        cfgfile_dwrite_bool(f, _T("genlock_alpha"), p->genlock_alpha);
@@ -2228,6 +2229,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        }
        cfgfile_write_bool (f, _T("cpu_compatible"), p->cpu_compatible);
        cfgfile_write_bool (f, _T("cpu_24bit_addressing"), p->address_space_24);
+       cfgfile_write_bool (f, _T("cpu_data_cache"), p->cpu_data_cache);
        /* do not reorder end */
        cfgfile_dwrite_bool(f, _T("cpu_reset_pause"), p->reset_delay);
        cfgfile_dwrite_bool(f, _T("cpu_threaded"), p->cpu_thread);
@@ -4991,6 +4993,7 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
                || cfgfile_yesno(option, value, _T("genlock_alpha"), &p->genlock_alpha)
                || cfgfile_yesno(option, value, _T("genlock_aspect"), &p->genlock_aspect)
                || cfgfile_yesno(option, value, _T("cpu_compatible"), &p->cpu_compatible)
+               || cfgfile_yesno(option, value, _T("cpu_data_cache"), &p->cpu_data_cache)
                || cfgfile_yesno(option, value, _T("cpu_threaded"), &p->cpu_thread)
                || cfgfile_yesno(option, value, _T("cpu_24bit_addressing"), &p->address_space_24)
                || cfgfile_yesno(option, value, _T("cpu_reset_pause"), &p->reset_delay)
@@ -5404,6 +5407,9 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
                        p->m68k_speed = -1;
                return 1;
        }
+       if (cfgfile_doubleval(option, value, _T("blitter_throttle"), &p->blitter_speed_throttle)) {
+               return 1;
+       }
 
        if (cfgfile_intval (option, value, _T("dongle"), &p->dongle, 1)) {
                if (p->dongle == 0)
@@ -5484,7 +5490,7 @@ void cfgfile_compatibility_rtg(struct uae_prefs *p)
        int vga = -1;
        for (int i = 0; i < MAX_RTG_BOARDS; i++) {
                struct rtgboardconfig *rbc = &p->rtgboards[i];
-               if (rbc->rtgmem_type == GFXBOARD_A2410  || rbc->rtgmem_type == GFXBOARD_RESOLVER) {
+               if (rbc->rtgmem_type == GFXBOARD_A2410) {
                        if (a2410 >= 0) {
                                rbc->rtgmem_size = 0;
                                rbc->rtgmem_type = 0;
index b0a28cb6683456919f88d0f150f1ae09808a9362..2636fc93220420317719399d4229946bc0bc4459 100644 (file)
@@ -33,7 +33,7 @@
 #include "cpummu.h"
 #include "debug.h"
 
-#define MMUDUMP 0
+#define MMUDUMP 1
 
 #define DBG_MMU_VERBOSE        1
 #define DBG_MMU_SANITY 1
@@ -49,6 +49,7 @@ 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;
+uae_u8 cache_default_ins, cache_default_data;
 
 int mmu060_state;
 uae_u16 mmu_opcode;
@@ -91,7 +92,7 @@ static void mmu_dump_ttr(const TCHAR * label, uae_u32 ttr)
        from_addr = ttr & MMU_TTR_LOGICAL_BASE;
        to_addr = (ttr & MMU_TTR_LOGICAL_MASK) << 8;
 
-       write_log(_T("%s: [%08x] %08x - %08x enabled=%d supervisor=%d wp=%d cm=%02d\n"),
+       console_out_f(_T("%s: [%08x] %08x - %08x enabled=%d supervisor=%d wp=%d cm=%02d\n"),
                        label, ttr,
                        from_addr, to_addr,
                        ttr & MMU_TTR_BIT_ENABLED ? 1 : 0,
@@ -326,7 +327,7 @@ static void mmu_dump_atc(void)
 /* {{{ mmu_dump_tables */
 void mmu_dump_tables(void)
 {
-       write_log(_T("URP: %08x   SRP: %08x  MMUSR: %x  TC: %x\n"), regs.urp, regs.srp, regs.mmusr, regs.tcr);
+       console_out_f(_T("URP: %08x   SRP: %08x  MMUSR: %x  TC: %x\n"), regs.urp, regs.srp, regs.mmusr, regs.tcr);
        mmu_dump_ttr(_T("DTT0"), regs.dtt0);
        mmu_dump_ttr(_T("DTT1"), regs.dtt1);
        mmu_dump_ttr(_T("ITT0"), regs.itt0);
@@ -334,6 +335,8 @@ void mmu_dump_tables(void)
        mmu_dump_atc();
 #if MMUDUMP
        mmu_dump_table("SRP", regs.srp);
+       if (regs.urp != regs.srp)
+               mmu_dump_table("URP", regs.urp);
 #endif
 }
 /* }}} */
@@ -494,14 +497,11 @@ void mmu_bus_error(uaecptr addr, uae_u32 val, int fc, bool write, int size,uae_u
        regs.mmu_fault_addr = addr;
 
 #if 0
-       if (m68k_getpc () == 0x0004B0AC) {
-               write_log (_T("*"));
-#if 0
-               extern void activate_debugger(void);
-               activate_debugger ();
-#endif
-       }
+       activate_debugger ();
 #endif
+
+       cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
+
        THROW(2);
 }
 
@@ -529,8 +529,14 @@ static int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super)
                                        return TTR_NO_MATCH;
                                }
                        }
-                       if (ttr & MMU_TTR_CACHE_DISABLE)
+                       if (ttr & MMU_TTR_CACHE_DISABLE) {
                                mmu_cache_state = CACHE_DISABLE_MMU;
+                       } else {
+                               mmu_cache_state = CACHE_ENABLE_ALL;
+                               if (ttr && MMU_TTR_CACHE_MODE) {
+                                       mmu_cache_state |= CACHE_ENABLE_COPYBACK;
+                               }
+                       }
                        return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH;
                }
        }
@@ -599,6 +605,19 @@ int mmu_match_ttr_maybe_write(uaecptr addr, bool super, bool data, int size, boo
        return res;
 }
 
+// Descriptor read accesses can use data cache but never allocate new cache lines.
+static uae_u32 desc_get_long(uaecptr addr)
+{
+       mmu_cache_state = ce_cachable[addr >>16] | CACHE_DISABLE_ALLOCATE;
+       return x_phys_get_long(addr);
+}
+// Write accesses probably are always pushed to memomory
+static void desc_put_long(uaecptr addr, uae_u32 v)
+{
+       mmu_cache_state = CACHE_DISABLE_MMU;
+       x_phys_put_long(addr, v);
+}
+
 /*
  * Lookup the address by walking the page table and updating
  * the page descriptors accordingly. Returns the found descriptor
@@ -619,7 +638,7 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s
     
     SAVE_EXCEPTION;
     TRY(prb) {
-        desc = phys_get_long(desc_addr);
+        desc = desc_get_long(desc_addr);
         if ((desc & 2) == 0) {
 #if MMUDEBUG > 1
             write_log(_T("MMU: invalid root descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"),
@@ -630,13 +649,14 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s
         }
         
         wp |= desc;
-        if ((desc & MMU_DES_USED) == 0)
-            phys_put_long(desc_addr, desc | MMU_DES_USED);
+        if ((desc & MMU_DES_USED) == 0) {
+            desc_put_long(desc_addr, desc | MMU_DES_USED);
+               }
         
         /* fetch pointer table descriptor */
         i = (addr >> 16) & 0x1fc;
         desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i;
-        desc = phys_get_long(desc_addr);
+        desc = desc_get_long(desc_addr);
         if ((desc & 2) == 0) {
 #if MMUDEBUG > 1
             write_log(_T("MMU: invalid ptr descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"),
@@ -647,7 +667,7 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s
         }
         wp |= desc;
         if ((desc & MMU_DES_USED) == 0)
-            phys_put_long(desc_addr, desc | MMU_DES_USED);
+            desc_put_long(desc_addr, desc | MMU_DES_USED);
         
         /* fetch page table descriptor */
         if (mmu_pagesize_8k) {
@@ -658,11 +678,11 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s
             desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) + i;
         }
         
-        desc = phys_get_long(desc_addr);
+        desc = desc_get_long(desc_addr);
         if ((desc & 3) == 2) {
             /* indirect */
             desc_addr = desc & MMU_PAGE_INDIRECT_MASK;
-            desc = phys_get_long(desc_addr);
+            desc = desc_get_long(desc_addr);
         }
         if ((desc & 1) == 1) {
             wp |= desc;
@@ -670,17 +690,17 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s
                 if ((wp & MMU_DES_WP) || ((desc & MMU_DES_SUPER) && !super)) {
                     if ((desc & MMU_DES_USED) == 0) {
                         desc |= MMU_DES_USED;
-                        phys_put_long(desc_addr, desc);
+                        desc_put_long(desc_addr, desc);
                     }
                 } else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) !=
                            (MMU_DES_USED|MMU_DES_MODIFIED)) {
                     desc |= MMU_DES_USED|MMU_DES_MODIFIED;
-                    phys_put_long(desc_addr, desc);
+                    desc_put_long(desc_addr, desc);
                 }
             } else {
                 if ((desc & MMU_DES_USED) == 0) {
                     desc |= MMU_DES_USED;
-                    phys_put_long(desc_addr, desc);
+                    desc_put_long(desc_addr, desc);
                 }
             }
             desc |= wp & MMU_DES_WP;
@@ -764,11 +784,13 @@ static void mmu_add_cache(uaecptr addr, uaecptr phys, bool super, bool data, boo
                        if (idx2 < MMUFASTCACHE_ENTRIES - 1) {
                                atc_data_cache_write[idx2].log = idx1;
                                atc_data_cache_write[idx2].phys = phys;
+                               atc_data_cache_write[idx2].cache_state = mmu_cache_state;
                        }
                } else {
                        if (idx2 < MMUFASTCACHE_ENTRIES - 1) {
                                atc_data_cache_read[idx2].log = idx1;
                                atc_data_cache_read[idx2].phys = phys;
+                               atc_data_cache_read[idx2].cache_state = mmu_cache_state;
                        }
                }
 #endif
@@ -820,8 +842,14 @@ atc_retry:
                                // save way for next access (likely in same page)
                                mmu_atc_ways[data] = way;
 
-                               if (l->status & MMU_MMUSR_CM_DISABLE)
+                               if (l->status & MMU_MMUSR_CM_DISABLE) {
                                        mmu_cache_state = CACHE_DISABLE_MMU;
+                               } else {
+                                       mmu_cache_state = CACHE_ENABLE_ALL;
+                                       if (l->status & MMU_MMUSR_CM_MODE) {
+                                               mmu_cache_state |= CACHE_ENABLE_COPYBACK;
+                                       }
+                               }
 
                                mmu_add_cache(addr, l->phys, super, data, write);
 
@@ -942,10 +970,10 @@ static uae_u16 REGPARAM2 mmu_get_lrmw_word_unaligned(uaecptr addr)
 {
        uae_u16 res;
 
-       res = (uae_u16)mmu_get_user_byte(addr, regs.s != 0, true, sz_word) << 8;
+       res = (uae_u16)mmu_get_user_byte(addr, regs.s != 0, true, sz_word, true) << 8;
        SAVE_EXCEPTION;
        TRY(prb) {
-               res |= mmu_get_user_byte(addr + 1, regs.s != 0, true, sz_word);
+               res |= mmu_get_user_byte(addr + 1, regs.s != 0, true, sz_word, true);
                RESTORE_EXCEPTION;
        }
        CATCH(prb) {
@@ -961,10 +989,10 @@ static uae_u32 REGPARAM2 mmu_get_lrmw_long_unaligned(uaecptr addr)
        uae_u32 res;
 
        if (likely(!(addr & 1))) {
-               res = (uae_u32)mmu_get_user_word(addr, regs.s != 0, true, sz_long) << 16;
+               res = (uae_u32)mmu_get_user_word(addr, regs.s != 0, true, sz_long, true) << 16;
                SAVE_EXCEPTION;
                TRY(prb) {
-                       res |= mmu_get_user_word(addr + 2, regs.s != 0, true, sz_long);
+                       res |= mmu_get_user_word(addr + 2, regs.s != 0, true, sz_long, true);
                        RESTORE_EXCEPTION;
                }
                CATCH(prb) {
@@ -973,12 +1001,12 @@ static uae_u32 REGPARAM2 mmu_get_lrmw_long_unaligned(uaecptr addr)
                        THROW_AGAIN(prb);
                } ENDTRY
        } else {
-               res = (uae_u32)mmu_get_user_byte(addr, regs.s != 0, true, sz_long) << 8;
+               res = (uae_u32)mmu_get_user_byte(addr, regs.s != 0, true, sz_long, true) << 8;
                SAVE_EXCEPTION;
                TRY(prb) {
-                       res = (res | mmu_get_user_byte(addr + 1, regs.s != 0, true, sz_long)) << 8;
-                       res = (res | mmu_get_user_byte(addr + 2, regs.s != 0, true, sz_long)) << 8;
-                       res |= mmu_get_user_byte(addr + 3, regs.s != 0, true, sz_long);
+                       res = (res | mmu_get_user_byte(addr + 1, regs.s != 0, true, sz_long, true)) << 8;
+                       res = (res | mmu_get_user_byte(addr + 2, regs.s != 0, true, sz_long, true)) << 8;
+                       res |= mmu_get_user_byte(addr + 3, regs.s != 0, true, sz_long, true);
                        RESTORE_EXCEPTION;
                }
                CATCH(prb) {
@@ -990,6 +1018,48 @@ static uae_u32 REGPARAM2 mmu_get_lrmw_long_unaligned(uaecptr addr)
        return res;
 }
 
+
+static void REGPARAM2 mmu_put_lrmw_long_unaligned(uaecptr addr, uae_u32 val)
+{
+       SAVE_EXCEPTION;
+       TRY(prb) {
+               if (likely(!(addr & 1))) {
+                       mmu_put_user_word(addr, val >> 16, regs.s != 0, sz_long, true);
+                       mmu_put_user_word(addr + 2, val, regs.s != 0, sz_long, true);
+               } else {
+                       mmu_put_user_byte(addr, val >> 24, regs.s != 0, sz_long, true);
+                       mmu_put_user_byte(addr + 1, val >> 16, regs.s != 0, sz_long, true);
+                       mmu_put_user_byte(addr + 2, val >> 8, regs.s != 0, sz_long, true);
+                       mmu_put_user_byte(addr + 3, val, regs.s != 0, sz_long, true);
+               }
+               RESTORE_EXCEPTION;
+       }
+       CATCH(prb) {
+               RESTORE_EXCEPTION;
+               regs.wb3_data = val;
+               misalignednotfirstcheck(addr);
+               THROW_AGAIN(prb);
+       } ENDTRY
+}
+
+static void REGPARAM2 mmu_put_lrmw_word_unaligned(uaecptr addr, uae_u16 val)
+{
+       SAVE_EXCEPTION;
+       TRY(prb) {
+               mmu_put_user_byte(addr, val >> 8, regs.s != 0, sz_word, true);
+               mmu_put_user_byte(addr + 1, val, regs.s != 0, sz_word, true);
+               RESTORE_EXCEPTION;
+       }
+       CATCH(prb) {
+               RESTORE_EXCEPTION;
+               regs.wb3_data = val;
+               misalignednotfirstcheck(addr);
+               THROW_AGAIN(prb);
+       } ENDTRY
+}
+
+
+
 void REGPARAM2 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data)
 {
        SAVE_EXCEPTION;
@@ -1036,13 +1106,13 @@ uae_u32 REGPARAM2 sfc_get_long(uaecptr addr)
 
        ismoves = true;
        if (likely(!is_unaligned(addr, 4))) {
-               res = mmu_get_user_long(addr, super, false, sz_long);
+               res = mmu_get_user_long(addr, super, false, sz_long, false);
        } else {
                if (likely(!(addr & 1))) {
-                       res = (uae_u32)mmu_get_user_word(addr, super, false, sz_long) << 16;
+                       res = (uae_u32)mmu_get_user_word(addr, super, false, sz_long, false) << 16;
                        SAVE_EXCEPTION;
                        TRY(prb) {
-                               res |= mmu_get_user_word(addr + 2, super, false, sz_long);
+                               res |= mmu_get_user_word(addr + 2, super, false, sz_long, false);
                                RESTORE_EXCEPTION;
                        }
                        CATCH(prb) {
@@ -1051,12 +1121,12 @@ uae_u32 REGPARAM2 sfc_get_long(uaecptr addr)
                                THROW_AGAIN(prb);
                        } ENDTRY
                } else {
-                       res = (uae_u32)mmu_get_user_byte(addr, super, false, sz_long) << 8;
+                       res = (uae_u32)mmu_get_user_byte(addr, super, false, sz_long, false) << 8;
                        SAVE_EXCEPTION;
                        TRY(prb) {
-                               res = (res | mmu_get_user_byte(addr + 1, super, false, sz_long)) << 8;
-                               res = (res | mmu_get_user_byte(addr + 2, super, false, sz_long)) << 8;
-                               res |= mmu_get_user_byte(addr + 3, super, false, sz_long);
+                               res = (res | mmu_get_user_byte(addr + 1, super, false, sz_long, false)) << 8;
+                               res = (res | mmu_get_user_byte(addr + 2, super, false, sz_long, false)) << 8;
+                               res |= mmu_get_user_byte(addr + 3, super, false, sz_long, false);
                                RESTORE_EXCEPTION;
                        }
                        CATCH(prb) {
@@ -1078,12 +1148,12 @@ uae_u16 REGPARAM2 sfc_get_word(uaecptr addr)
 
        ismoves = true;
        if (likely(!is_unaligned(addr, 2))) {
-               res = mmu_get_user_word(addr, super, false, sz_word);
+               res = mmu_get_user_word(addr, super, false, sz_word, false);
        } else {
-               res = (uae_u16)mmu_get_user_byte(addr, super, false, sz_word) << 8;
+               res = (uae_u16)mmu_get_user_byte(addr, super, false, sz_word, false) << 8;
                SAVE_EXCEPTION;
                TRY(prb) {
-                       res |= mmu_get_user_byte(addr + 1, super, false, sz_word);
+                       res |= mmu_get_user_byte(addr + 1, super, false, sz_word, false);
                        RESTORE_EXCEPTION;
                }
                CATCH(prb) {
@@ -1102,7 +1172,7 @@ uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr)
        uae_u8 res;
        
        ismoves = true;
-       res = mmu_get_user_byte(addr, super, false, sz_byte);
+       res = mmu_get_user_byte(addr, super, false, sz_byte, false);
        ismoves = false;
        return res;
 }
@@ -1115,15 +1185,15 @@ void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val)
        SAVE_EXCEPTION;
        TRY(prb) {
                if (likely(!is_unaligned(addr, 4))) {
-                       mmu_put_user_long(addr, val, super, sz_long);
+                       mmu_put_user_long(addr, val, super, sz_long, false);
                } else if (likely(!(addr & 1))) {
-                       mmu_put_user_word(addr, val >> 16, super, sz_long);
-                       mmu_put_user_word(addr + 2, val, super, sz_long);
+                       mmu_put_user_word(addr, val >> 16, super, sz_long, false);
+                       mmu_put_user_word(addr + 2, val, super, sz_long, false);
                } else {
-                       mmu_put_user_byte(addr, val >> 24, super, sz_long);
-                       mmu_put_user_byte(addr + 1, val >> 16, super, sz_long);
-                       mmu_put_user_byte(addr + 2, val >> 8, super, sz_long);
-                       mmu_put_user_byte(addr + 3, val, super, sz_long);
+                       mmu_put_user_byte(addr, val >> 24, super, sz_long, false);
+                       mmu_put_user_byte(addr + 1, val >> 16, super, sz_long, false);
+                       mmu_put_user_byte(addr + 2, val >> 8, super, sz_long, false);
+                       mmu_put_user_byte(addr + 3, val, super, sz_long, false);
                }
                RESTORE_EXCEPTION;
        }
@@ -1144,10 +1214,10 @@ void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val)
        SAVE_EXCEPTION;
        TRY(prb) {
                if (likely(!is_unaligned(addr, 2))) {
-                       mmu_put_user_word(addr, val, super, sz_word);
+                       mmu_put_user_word(addr, val, super, sz_word, false);
                } else {
-                       mmu_put_user_byte(addr, val >> 8, super, sz_word);
-                       mmu_put_user_byte(addr + 1, val, super, sz_word);
+                       mmu_put_user_byte(addr, val >> 8, super, sz_word, false);
+                       mmu_put_user_byte(addr + 1, val, super, sz_word, false);
                }
                RESTORE_EXCEPTION;
        }
@@ -1167,7 +1237,7 @@ void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val)
        ismoves = true;
        SAVE_EXCEPTION;
        TRY(prb) {
-               mmu_put_user_byte(addr, val, super, sz_byte);
+               mmu_put_user_byte(addr, val, super, sz_byte, false);
                RESTORE_EXCEPTION;
        }
        CATCH(prb) {
@@ -1186,8 +1256,10 @@ void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size)
        if ((!mmu_ttr_enabled || mmu_match_ttr(addr,super,data) == TTR_NO_MATCH) && regs.mmu_enabled) {
                addr = mmu_translate(addr, 0, super, data, false, size);
        }
+       // MOVE16 read and cache miss: do not allocate new cache line
+       mmu_cache_state |= CACHE_DISABLE_ALLOCATE;
        for (int i = 0; i < 4; i++) {
-               v[i] = phys_get_long(addr + i * 4);
+               v[i] = x_phys_get_long(addr + i * 4);
        }
 }
 
@@ -1199,8 +1271,10 @@ void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size)
        if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,super,data,val[0],size) == TTR_NO_MATCH) && regs.mmu_enabled) {
                addr = mmu_translate(addr, val[0], super, data, true, size);
        }
+       // MOVE16 write invalidates existing line and also does not allocate new cache lines.
+       mmu_cache_state = CACHE_DISABLE_MMU;
        for (int i = 0; i < 4; i++) {
-               phys_put_long(addr + i * 4, val[i]);
+               x_phys_put_long(addr + i * 4, val[i]);
        }
 }
 
@@ -1351,12 +1425,28 @@ void REGPARAM2 mmu_set_funcs(void)
        if (currprefs.cpu_memory_cycle_exact || currprefs.cpu_compatible) {
                x_phys_get_iword = get_word_icache040;
                x_phys_get_ilong = get_long_icache040;
-               x_phys_get_byte = get_byte_cache_040;
-               x_phys_get_word = get_word_cache_040;
-               x_phys_get_long = get_long_cache_040;
-               x_phys_put_byte = put_byte_cache_040;
-               x_phys_put_word = put_word_cache_040;
-               x_phys_put_long = put_long_cache_040;
+               if (currprefs.cpu_data_cache) {
+                       x_phys_get_byte = get_byte_cache_040;
+                       x_phys_get_word = get_word_cache_040;
+                       x_phys_get_long = get_long_cache_040;
+                       x_phys_put_byte = put_byte_cache_040;
+                       x_phys_put_word = put_word_cache_040;
+                       x_phys_put_long = put_long_cache_040;
+               } else if (currprefs.cpu_memory_cycle_exact) {
+                       x_phys_get_byte = mem_access_delay_byte_read_c040;
+                       x_phys_get_word = mem_access_delay_word_read_c040;
+                       x_phys_get_long = mem_access_delay_long_read_c040;
+                       x_phys_put_byte = mem_access_delay_byte_write_c040;
+                       x_phys_put_word = mem_access_delay_word_write_c040;
+                       x_phys_put_long = mem_access_delay_long_write_c040;
+               } else {
+                       x_phys_get_byte = phys_get_byte;
+                       x_phys_get_word = phys_get_word;
+                       x_phys_get_long = phys_get_long;
+                       x_phys_put_byte = phys_put_byte;
+                       x_phys_put_word = phys_put_word;
+                       x_phys_put_long = phys_put_long;
+               }
        } else {
                x_phys_get_iword = phys_get_word;
                x_phys_get_ilong = phys_get_long;
@@ -1390,13 +1480,22 @@ void REGPARAM2 mmu_set_tc(uae_u16 tc)
        mmu_pageshift = mmu_pagesize_8k ? 13 : 12;
        mmu_pageshift1m = mmu_pageshift - 1;
 
+       cache_default_ins = CACHE_ENABLE_ALL;
+       cache_default_data = CACHE_ENABLE_ALL;
+       if (currprefs.mmu_model == 68060) {
+               int dc = (tc >> 3) & 3;
+               cache_default_ins = 0;
+               if (!(dc & 2))
+                       cache_default_ins = CACHE_ENABLE_ALL;
+               dc = (tc >> 8) & 3;
+               cache_default_data = 0;
+               if (!(dc & 2))
+                       cache_default_data = (dc & 1) ? CACHE_ENABLE_COPYBACK | CACHE_ENABLE_ALL : CACHE_ENABLE_ALL;
+       }
+
        mmu_flush_atc_all(true);
 
        write_log(_T("%d MMU: enabled=%d page8k=%d PC=%08x\n"), currprefs.mmu_model, regs.mmu_enabled, mmu_pagesize_8k, m68k_getpc());
-#if MMUDUMP
-       if (regs.mmu_enabled)
-               mmu_dump_tables();
-#endif
 }
 
 void REGPARAM2 mmu_set_super(bool super)
@@ -1483,18 +1582,18 @@ void uae_mmu_put_lrmw (uaecptr addr, uae_u32 v, int size, int type)
 {
        locked_rmw_cycle = true;
        if (size == sz_byte) {
-               mmu_put_byte(addr, v, true, sz_byte);
+               mmu_put_user_byte(addr, v, regs.s, sz_byte, true);
        } else if (size == sz_word) {
                if (unlikely(is_unaligned(addr, 2))) {
-                       mmu_put_word_unaligned(addr, v, true);
+                       mmu_put_lrmw_word_unaligned(addr, v);
                } else {
-                       mmu_put_word(addr, v, true, sz_word);
+                       mmu_put_user_word(addr, v, regs.s != 0, sz_word, true);
                }
        } else {
                if (unlikely(is_unaligned(addr, 4)))
-                       mmu_put_long_unaligned(addr, v, true);
+                       mmu_put_lrmw_long_unaligned(addr, v);
                else
-                       mmu_put_long(addr, v, true, sz_long);
+                       mmu_put_user_long(addr, v, regs.s, sz_long, true);
        }
        locked_rmw_cycle = false;
 }
@@ -1503,18 +1602,18 @@ uae_u32 uae_mmu_get_lrmw (uaecptr addr, int size, int type)
        uae_u32 v;
        locked_rmw_cycle = true;
        if (size == sz_byte) {
-               v = mmu_get_user_byte(addr, regs.s != 0, true, sz_byte);
+               v = mmu_get_user_byte(addr, regs.s != 0, true, sz_byte, true);
        } else if (size == sz_word) {
                if (unlikely(is_unaligned(addr, 2))) {
                        v = mmu_get_lrmw_word_unaligned(addr);
                } else {
-                       v = mmu_get_user_word(addr, regs.s != 0, true, sz_word);
+                       v = mmu_get_user_word(addr, regs.s != 0, true, sz_word, true);
                }
        } else {
                if (unlikely(is_unaligned(addr, 4)))
                        v = mmu_get_lrmw_long_unaligned(addr);
                else
-                       v = mmu_get_user_long(addr, regs.s != 0, true, sz_long);
+                       v = mmu_get_user_long(addr, regs.s != 0, true, sz_long, true);
        }
        locked_rmw_cycle = false;
        return v;
index 30a7c334daca67f6d72149035c0f14d77138833c..de4278d10698723ec2fc9132310093abfac33eeb 100644 (file)
@@ -2444,27 +2444,27 @@ uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write)
 
 static uae_u32 get_dcache_byte(uaecptr addr)
 {
-       return read_dcache030(addr, 0, (regs.s ? 4 : 0) | 1);
+       return read_dcache030_bget(addr, (regs.s ? 4 : 0) | 1);
 }
 static uae_u32 get_dcache_word(uaecptr addr)
 {
-       return read_dcache030(addr, 1, (regs.s ? 4 : 0) | 1);
+       return read_dcache030_wget(addr, (regs.s ? 4 : 0) | 1);
 }
 static uae_u32 get_dcache_long(uaecptr addr)
 {
-       return read_dcache030(addr, 2, (regs.s ? 4 : 0) | 1);
+       return read_dcache030_lget(addr, (regs.s ? 4 : 0) | 1);
 }
 static void put_dcache_byte(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 0, (regs.s ? 4 : 0) | 1);
+       write_dcache030_bput(addr, v, (regs.s ? 4 : 0) | 1);
 }
 static void put_dcache_word(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 1, (regs.s ? 4 : 0) | 1);
+       write_dcache030_wput(addr, v, (regs.s ? 4 : 0) | 1);
 }
 static void put_dcache_long(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 2, (regs.s ? 4 : 0) | 1);
+       write_dcache030_lput(addr, v, (regs.s ? 4 : 0) | 1);
 }
 
 /* MMU Reset */
@@ -2515,7 +2515,6 @@ void mmu030_set_funcs(void)
        }
 }
 
-
 void m68k_do_rte_mmu030 (uaecptr a7)
 {
        // Restore access error exception state
index 50fb80ac6ab09e7a84907bd5696f29e4389834f0..ec2aa0de6662739915166c1108b468e8b4137e7a 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -117,6 +117,7 @@ static const TCHAR help[] = {
        _T("  c                     Dump state of the CIA, disk drives and custom registers.\n")
        _T("  r                     Dump state of the CPU.\n")
        _T("  r <reg> <value>       Modify CPU registers (Dx,Ax,USP,ISP,VBR,...).\n")
+       _T("  rc[d]                 Show CPU instruction or data cache contents.\n")
        _T("  m <address> [<lines>] Memory dump starting at <address>.\n")
        _T("  a <address>           Assembler.\n")
        _T("  d <address> [<lines>] Disassembly starting at <address>.\n")
@@ -297,7 +298,7 @@ uae_u32 get_byte_debug (uaecptr addr)
                                if (debug_mmu_mode & 1) {
                                        v = mmu_get_iword(addr, sz_byte);
                                } else {
-                                       v = mmu_get_user_byte (addr, regs.s != 0, false, sz_byte);
+                                       v = mmu_get_user_byte (addr, regs.s != 0, false, sz_byte, false);
                                }
                        }
                } CATCH(p) {
@@ -321,7 +322,7 @@ uae_u32 get_word_debug (uaecptr addr)
                                if (debug_mmu_mode & 1) {
                                        v = mmu_get_iword(addr, sz_word);
                                } else {
-                                       v = mmu_get_user_word (addr, regs.s != 0, false, sz_word);
+                                       v = mmu_get_user_word (addr, regs.s != 0, false, sz_word, false);
                                }
                        }
                } CATCH(p) {
@@ -345,7 +346,7 @@ uae_u32 get_long_debug (uaecptr addr)
                                if (debug_mmu_mode & 1) {
                                        v = mmu_get_ilong(addr, sz_long);
                                } else {
-                                       v = mmu_get_user_long (addr, regs.s != 0, false, sz_long);
+                                       v = mmu_get_user_long (addr, regs.s != 0, false, sz_long, false);
                                }
                        }
                } CATCH(p) {
@@ -3692,6 +3693,8 @@ typedef struct UaeMemoryMap {
 } UaeMemoryMap;
 #endif
 
+static const TCHAR *bankmodes[] = { _T("F32"), _T("C16"), _T("C32"), _T("CIA"), _T("F16"), _T("F16X") };
+
 static void memory_map_dump_3(UaeMemoryMap *map, int log)
 {
        bool imold;
@@ -3767,10 +3770,12 @@ static void memory_map_dump_3(UaeMemoryMap *map, int log)
                                        size_out /= 1024;
                                        size_ext = 'M';
                                }
-#if 1
-                               _stprintf (txt, _T("%08X %7d%c/%d = %7d%c %s"), (j << 16) | bankoffset, size_out, size_ext,
-                                       mirrored, mirrored ? size_out / mirrored : size_out, size_ext, name);
-#endif
+                               _stprintf (txt, _T("%08X %7d%c/%d = %7d%c %s%s %s %s"), (j << 16) | bankoffset, size_out, size_ext,
+                                       mirrored, mirrored ? size_out / mirrored : size_out, size_ext,
+                                       (a1->flags & ABFLAG_CACHE_ENABLE_INS) ? _T("I") : _T("-"),
+                                       (a1->flags & ABFLAG_CACHE_ENABLE_DATA) ? _T("D") : _T("-"),
+                                       bankmodes[ce_banktype[j]],
+                                       name);
                                tmp[0] = 0;
                                if ((a1->flags & ABFLAG_ROM) && mirrored) {
                                        TCHAR *p = txt + _tcslen (txt);
@@ -3809,7 +3814,6 @@ static void memory_map_dump_3(UaeMemoryMap *map, int log)
                                                map->num_regions += 1;
                                        }
                                }
-#if 1
                                _tcscat (txt, _T("\n"));
                                if (log > 0)
                                        write_log (_T("%s"), txt);
@@ -3821,7 +3825,6 @@ static void memory_map_dump_3(UaeMemoryMap *map, int log)
                                        else if (log == 0)
                                                console_out (tmp);
                                }
-#endif
                                if (!sb)
                                        break;
                                bankoffset = bankoffset2;
@@ -5162,12 +5165,14 @@ static bool debug_line (TCHAR *input)
                case 'e': dump_custom_regs (tolower(*inptr) == 'a'); break;
                case 'r':
                        {
-                               if (*inptr == 'c')
-                                       m68k_dumpcache ();
-                               else if (more_params(&inptr))
+                               if (*inptr == 'c') {
+                                       next_char(&inptr);
+                                       m68k_dumpcache (*inptr == 'd');
+                               } else if (more_params(&inptr)) {
                                        m68k_modify (&inptr);
-                               else
+                               } else {
                                        m68k_dumpstate (&nextpc);
+                               }
                        }
                        break;
                case 'D': deepcheatsearch (&inptr); break;
@@ -5439,11 +5444,16 @@ static bool debug_line (TCHAR *input)
                                if (*inptr == 'm' && inptr[1] == 'u') {
                                        if (currprefs.mmu_model) {
                                                inptr += 2;
-                                               if (more_params (&inptr))
-                                                       debug_mmu_mode = readint (&inptr);
-                                               else
-                                                       debug_mmu_mode = 0;
-                                               console_out_f (_T("MMU translation function code = %d\n"), debug_mmu_mode);
+                                               if (inptr[0] == 'd') {
+                                                       if (currprefs.mmu_model >= 68040)
+                                                               mmu_dump_tables();
+                                               } else {
+                                                       if (more_params (&inptr))
+                                                               debug_mmu_mode = readint (&inptr);
+                                                       else
+                                                               debug_mmu_mode = 0;
+                                                       console_out_f (_T("MMU translation function code = %d\n"), debug_mmu_mode);
+                                               }
                                        }
                                        break;
                                }
index bf71bc7ef44b3b2bcc07f2d6498b80d669574e6d..d107f4314c2cb8300d3ae70333e07a4c5428dc1c 100644 (file)
@@ -994,28 +994,28 @@ addrbank fastmem_bank[MAX_RAM_BOARDS] =
                fastmem0_lput, fastmem0_wput, fastmem0_bput,
                fastmem0_xlate, fastmem0_check, NULL, _T("*"), _T("Fast memory"),
                fastmem0_lget, fastmem0_wget,
-               ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+               ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
        },
        {
                fastmem1_lget, fastmem1_wget, fastmem1_bget,
                fastmem1_lput, fastmem1_wput, fastmem1_bput,
                fastmem1_xlate, fastmem1_check, NULL, _T("*"), _T("Fast memory 2"),
                fastmem1_lget, fastmem1_wget,
-               ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+               ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
        },
        {
                fastmem2_lget, fastmem2_wget, fastmem2_bget,
                fastmem2_lput, fastmem2_wput, fastmem2_bput,
                fastmem2_xlate, fastmem2_check, NULL, _T("*"), _T("Fast memory 3"),
                fastmem2_lget, fastmem2_wget,
-               ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+               ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
        },
        {
                fastmem3_lget, fastmem3_wget, fastmem3_bget,
                fastmem3_lput, fastmem3_wput, fastmem3_bput,
                fastmem3_xlate, fastmem3_check, NULL, _T("*"), _T("Fast memory 4"),
                fastmem3_lget, fastmem3_wget,
-               ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+               ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
        }
 };
 
@@ -1467,28 +1467,28 @@ addrbank z3fastmem_bank[MAX_RAM_BOARDS] =
                z3fastmem0_lput, z3fastmem0_wput, z3fastmem0_bput,
                z3fastmem0_xlate, z3fastmem0_check, NULL, _T("*"), _T("Zorro III Fast RAM"),
                z3fastmem0_lget, z3fastmem0_wget,
-               ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+               ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
        },
        {
                z3fastmem1_lget, z3fastmem1_wget, z3fastmem1_bget,
                z3fastmem1_lput, z3fastmem1_wput, z3fastmem1_bput,
                z3fastmem1_xlate, z3fastmem1_check, NULL, _T("*"), _T("Zorro III Fast RAM #2"),
                z3fastmem1_lget, z3fastmem1_wget,
-               ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+               ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
        },
        {
                z3fastmem2_lget, z3fastmem2_wget, z3fastmem2_bget,
                z3fastmem2_lput, z3fastmem2_wput, z3fastmem2_bput,
                z3fastmem2_xlate, z3fastmem2_check, NULL, _T("*"), _T("Zorro III Fast RAM #3"),
                z3fastmem2_lget, z3fastmem2_wget,
-               ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+               ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
        },
        {
                z3fastmem3_lget, z3fastmem3_wget, z3fastmem3_bget,
                z3fastmem3_lput, z3fastmem3_wput, z3fastmem3_bput,
                z3fastmem3_xlate, z3fastmem3_check, NULL, _T("*"), _T("Zorro III Fast RAM #4"),
                z3fastmem3_lget, z3fastmem3_wget,
-               ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+               ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
        }
 };
 
@@ -1499,7 +1499,7 @@ addrbank z3chipmem_bank = {
        z3chipmem_lput, z3chipmem_wput, z3chipmem_bput,
        z3chipmem_xlate, z3chipmem_check, NULL, _T("*"), _T("MegaChipRAM"),
        z3chipmem_lget, z3chipmem_wget,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
 };
 
 /* ********************************************************** */
@@ -5336,7 +5336,7 @@ static const struct cpuboardsubtype gvpboard_sub[] = {
 };
 static const struct cpuboardsubtype blizzardboard_sub[] = {
        {
-               _T("Blizzard 1230 II"),
+               _T("Blizzard 1230 I/II"),
                _T("Blizzard1230II"),
                ROMTYPE_CB_B1230MK2, 0,
                cpuboard_ncr9x_add_scsi_unit, EXPANSIONTYPE_SCSI,
index 00d5398a4ee69b3d5f5786b856f864876d49a519..5c6a7f6c4229ae5f72aedf61f77b167b965874d0 100644 (file)
@@ -5255,7 +5255,6 @@ static void       action_read(TrapContext *ctx, Unit *unit, dpacket *packet)
                                k->file_pos += actual;
                        }
                        xfree (buf);
-                       flush_dcache (addr, size);
                        size = 0;
                }
        }
@@ -5307,7 +5306,6 @@ static void       action_read(TrapContext *ctx, Unit *unit, dpacket *packet)
                        PUT_PCK_RES1 (packet, actual);
                        k->file_pos += actual;
                }
-               flush_dcache (addr, size);
        }
 
        TRACE((_T("=%d\n"), actual));
index e238177b0ef9648ac0ba5d5a32aa079066717062..9e2271559e34a59c18fe36c8132ad5a042e854bb 100644 (file)
@@ -169,6 +169,14 @@ static const struct gfxboard boards[] =
                0x00000000, 0x00200000, 0x00200000, 0x10000, 0, 0, 2, false,
                0, 0xc1, &a2410_func
        },
+#if 0
+       {
+               _T("Resolver"), _T("DMI"), _T("Resolver"),
+               2129, 1, 0,
+               0x00000000, 0x00200000, 0x00200000, 0x10000, 0, 0, 2, false,
+               0, 0xc1, &a2410_func
+       },
+#endif
        {
                _T("x86 bridgeboard VGA"), _T("x86"), _T("VGA"),
                0, 0, 0,
@@ -278,7 +286,7 @@ static const addrbank tmpl_gfxboard_bank_memory = {
        gfxboard_lput_mem, gfxboard_wput_mem, gfxboard_bput_mem,
        gfxboard_xlate, gfxboard_check, NULL, NULL, NULL,
        gfxboard_lget_mem, gfxboard_wget_mem,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
 };
 
 static const addrbank tmpl_gfxboard_bank_memory_nojit = {
@@ -286,7 +294,7 @@ static const addrbank tmpl_gfxboard_bank_memory_nojit = {
        gfxboard_lput_mem_nojit, gfxboard_wput_mem_nojit, gfxboard_bput_mem_nojit,
        gfxboard_xlate, gfxboard_check, NULL, NULL, NULL,
        gfxboard_lget_mem_nojit, gfxboard_wget_mem_nojit,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, S_READ, S_WRITE
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, S_READ, S_WRITE
 };
 
 static const addrbank tmpl_gfxboard_bank_wbsmemory = {
@@ -294,7 +302,7 @@ static const addrbank tmpl_gfxboard_bank_wbsmemory = {
        gfxboard_lput_wbsmem, gfxboard_wput_wbsmem, gfxboard_bput_wbsmem,
        gfxboard_xlate, gfxboard_check, NULL, NULL, NULL,
        gfxboard_lget_wbsmem, gfxboard_wget_wbsmem,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, S_READ, S_WRITE
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, S_READ, S_WRITE
 };
 
 static const addrbank tmpl_gfxboard_bank_lbsmemory = {
@@ -302,7 +310,7 @@ static const addrbank tmpl_gfxboard_bank_lbsmemory = {
        gfxboard_lput_lbsmem, gfxboard_wput_lbsmem, gfxboard_bput_lbsmem,
        gfxboard_xlate, gfxboard_check, NULL, NULL, NULL,
        gfxboard_lget_lbsmem, gfxboard_wget_lbsmem,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, S_READ, S_WRITE
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, S_READ, S_WRITE
 };
 
 static const addrbank tmpl_gfxboard_bank_nbsmemory = {
@@ -310,7 +318,7 @@ static const addrbank tmpl_gfxboard_bank_nbsmemory = {
        gfxboard_lput_nbsmem, gfxboard_wput_nbsmem, gfxboard_bput_bsmem,
        gfxboard_xlate, gfxboard_check, NULL, NULL, _T("Picasso IV banked VRAM"),
        gfxboard_lget_nbsmem, gfxboard_wget_nbsmem,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, S_READ, S_WRITE
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, S_READ, S_WRITE
 };
 
 static const addrbank tmpl_gfxboard_bank_registers = {
index da2bf1f481c09f35ac43cb56b92bd4fb0f8dd183..1cd69b24c45d057b007c79274da5bb740966047a 100644 (file)
@@ -177,27 +177,27 @@ extern uae_u32 get_word_030_prefetch(int);
 
 STATIC_INLINE void put_long_030(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 2, (regs.s ? 4 : 0) | 1);
+       write_data_030_lput(addr, v);
 }
 STATIC_INLINE void put_word_030(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 1, (regs.s ? 4 : 0) | 1);
+       write_data_030_wput(addr, v);
 }
 STATIC_INLINE void put_byte_030(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 0, (regs.s ? 4 : 0) | 1);
+       write_data_030_bput(addr, v);
 }
 STATIC_INLINE uae_u32 get_long_030(uaecptr addr)
 {
-       return read_dcache030(addr, 2, (regs.s ? 4 : 0) | 1);
+       return read_data_030_lget(addr);
 }
 STATIC_INLINE uae_u32 get_word_030(uaecptr addr)
 {
-       return read_dcache030(addr, 1, (regs.s ? 4 : 0) | 1);
+       return read_data_030_wget(addr);
 }
 STATIC_INLINE uae_u32 get_byte_030(uaecptr addr)
 {
-       return read_dcache030(addr, 0, (regs.s ? 4 : 0) | 1);
+       return read_data_030_bget(addr);
 }
 
 STATIC_INLINE uae_u32 get_long_030_prefetch(int o)
@@ -243,27 +243,27 @@ extern uae_u32 get_word_ce030_prefetch_opcode(int);
 
 STATIC_INLINE void put_long_ce030 (uaecptr addr, uae_u32 v)
 {
-       write_dcache030 (addr, v, 2, (regs.s ? 4 : 0) | 1);
+       write_dcache030_lput(addr, v, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE void put_word_ce030 (uaecptr addr, uae_u32 v)
 {
-       write_dcache030 (addr, v, 1, (regs.s ? 4 : 0) | 1);
+       write_dcache030_wput(addr, v, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE void put_byte_ce030 (uaecptr addr, uae_u32 v)
 {
-       write_dcache030 (addr, v, 0, (regs.s ? 4 : 0) | 1);
+       write_dcache030_bput(addr, v, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE uae_u32 get_long_ce030 (uaecptr addr)
 {
-       return read_dcache030 (addr, 2, (regs.s ? 4 : 0) | 1);
+       return read_dcache030_lget(addr, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE uae_u32 get_word_ce030 (uaecptr addr)
 {
-       return read_dcache030 (addr, 1, (regs.s ? 4 : 0) | 1);
+       return read_dcache030_wget(addr, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE uae_u32 get_byte_ce030 (uaecptr addr)
 {
-       return read_dcache030 (addr, 0, (regs.s ? 4 : 0) | 1);
+       return read_dcache030_bget(addr, (regs.s ? 4 : 0) | 1);
 }
 
 STATIC_INLINE uae_u32 get_long_ce030_prefetch (int o)
index 2831feb9fa9cab1c51824df785d9e010e62e35d8..f7f306e7e7b44b1ff8845324922f76b4d8fbb879 100644 (file)
@@ -64,6 +64,7 @@ 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 uae_u8 cache_default_ins, cache_default_data;
 
 extern void mmu_dump_tables(void);
 
@@ -247,6 +248,7 @@ struct mmufastcache
 {
        uae_u32 log;
        uae_u32 phys;
+       uae_u8 cache_state;
 };
 extern struct mmufastcache atc_data_cache_read[MMUFASTCACHE_ENTRIES];
 extern struct mmufastcache atc_data_cache_write[MMUFASTCACHE_ENTRIES];
@@ -258,16 +260,9 @@ 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;
+       mmu_cache_state = cache_default_ins;
        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) {
@@ -286,13 +281,12 @@ 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;
+       mmu_cache_state = cache_default_ins;
        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) {
@@ -311,19 +305,20 @@ static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size)
                }
 #endif
        }
-       cacheablecheck(addr);
        return x_phys_get_iword(addr);
 }
 
 
 static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, bool data, int size)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr(addr,regs.s!=0,data) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_read[idx2].log == idx1) {
                        addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_read_hit++;
 #endif
@@ -337,17 +332,19 @@ static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, bool data, int size)
                }
 #endif
        }
-       return phys_get_long(addr);
+       return x_phys_get_long(addr);
 }
 
 static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, bool data, int size)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr(addr,regs.s!=0,data) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_read[idx2].log == idx1) {
                        addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_read_hit++;
 #endif
@@ -361,17 +358,19 @@ static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, bool data, int size)
                }
 #endif
        }
-       return phys_get_word(addr);
+       return x_phys_get_word(addr);
 }
 
 static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, bool data, int size)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr(addr,regs.s!=0,data) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_read[idx2].log == idx1) {
                        addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_read_hit++;
 #endif
@@ -385,17 +384,19 @@ static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, bool data, int size)
                }
 #endif
 }
-       return phys_get_byte(addr);
+       return x_phys_get_byte(addr);
 }
 
 static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int size)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,regs.s!=0,data,val,size) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_write[idx2].log == idx1) {
                        addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_write_hit++;
 #endif
@@ -409,17 +410,19 @@ static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int
                }
 #endif
        }
-       phys_put_long(addr, val);
+       x_phys_put_long(addr, val);
 }
 
 static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, bool data, int size)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,regs.s!=0,data,val,size) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_write[idx2].log == idx1) {
                        addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_write_hit++;
 #endif
@@ -433,17 +436,19 @@ static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, bool data, int
                }
 #endif
        }
-       phys_put_word(addr, val);
+       x_phys_put_word(addr, val);
 }
 
 static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, bool data, int size)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,regs.s!=0,data,val,size) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_write[idx2].log == idx1) {
                        addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_write_hit++;
 #endif
@@ -457,17 +462,19 @@ static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, bool data, int
                }
 #endif
        }
-       phys_put_byte(addr, val);
+       x_phys_put_byte(addr, val);
 }
 
-static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool write, int size)
+static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool write, int size, bool ci)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr_maybe_write(addr,super,true,size,write) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0);
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_read[idx2].log == idx1) {
                        addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_read_hit++;
 #endif
@@ -481,17 +488,21 @@ static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool wr
                }
 #endif
        }
-       return phys_get_long(addr);
+       if (ci)
+               mmu_cache_state = CACHE_DISABLE_MMU;
+       return x_phys_get_long(addr);
 }
 
-static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool write, int size)
+static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool write, int size, bool ci)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr_maybe_write(addr,super,true,size,write) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0);
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_read[idx2].log == idx1) {
                        addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_read_hit++;
 #endif
@@ -505,17 +516,21 @@ static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool wr
                }
 #endif
        }
-       return phys_get_word(addr);
+       if (ci)
+               mmu_cache_state = CACHE_DISABLE_MMU;
+       return x_phys_get_word(addr);
 }
 
-static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool write, int size)
+static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool write, int size, bool ci)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr_maybe_write(addr,super,true,size,write) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0);
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_read[idx2].log == idx1) {
                        addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_read_hit++;
 #endif
@@ -529,17 +544,21 @@ static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool wri
                }
 #endif
        }
-       return phys_get_byte(addr);
+       if (ci)
+               mmu_cache_state = CACHE_DISABLE_MMU;
+       return x_phys_get_byte(addr);
 }
 
-static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool super, int size)
+static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool super, int size, bool ci)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,super,true,val,size) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0);
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_write[idx2].log == idx1) {
                        addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_write_hit++;
 #endif
@@ -553,17 +572,21 @@ static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool supe
                }
 #endif
        }
-       phys_put_long(addr, val);
+       if (ci)
+               mmu_cache_state = CACHE_DISABLE_MMU;
+       x_phys_put_long(addr, val);
 }
 
-static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool super, int size)
+static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool super, int size, bool ci)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,super,true,val,size) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0);
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_write[idx2].log == idx1) {
                        addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_write_hit++;
 #endif
@@ -577,17 +600,21 @@ static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool supe
                }
 #endif
        }
-       phys_put_word(addr, val);
+       if (ci)
+               mmu_cache_state = CACHE_DISABLE_MMU;
+       x_phys_put_word(addr, val);
 }
 
-static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super, int size)
+static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super, int size, bool ci)
 {
+       mmu_cache_state = cache_default_data;
        if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,super,true,val,size) == TTR_NO_MATCH) && regs.mmu_enabled) {
 #if MMU_DPAGECACHE
                uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0);
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1);
                if (atc_data_cache_write[idx2].log == idx1) {
                        addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask);
+                       mmu_cache_state = atc_data_cache_read[idx2].cache_state;
 #if CACHE_HIT_COUNT
                        mmu_data_write_hit++;
 #endif
@@ -601,7 +628,9 @@ static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super
                }
 #endif
        }
-       phys_put_byte(addr, val);
+       if (ci)
+               mmu_cache_state = CACHE_DISABLE_MMU;
+       x_phys_put_byte(addr, val);
 }
 
 
index 3e3baa33acbcc94626269cb7788e4ed4ba8397c0..f12b4b1d05eeb433805e4ebf3d6623b5a8c9e983 100644 (file)
@@ -513,7 +513,7 @@ static ALWAYS_INLINE uae_u32 sfc030c_get_long(uaecptr addr)
 #if MMUDEBUG > 2
        write_log(_T("sfc030_get_long: FC = %i\n"),fc);
 #endif
-       return read_dcache030(addr, 2, regs.sfc);
+       return read_dcache030_lget(addr, regs.sfc);
 }
 
 static ALWAYS_INLINE uae_u16 sfc030c_get_word(uaecptr addr)
@@ -521,7 +521,7 @@ static ALWAYS_INLINE uae_u16 sfc030c_get_word(uaecptr addr)
 #if MMUDEBUG > 2
        write_log(_T("sfc030_get_word: FC = %i\n"),fc);
 #endif
-       return read_dcache030(addr, 1, regs.sfc);
+       return read_dcache030_wget(addr, regs.sfc);
 }
 
 static ALWAYS_INLINE uae_u8 sfc030c_get_byte(uaecptr addr)
@@ -529,7 +529,7 @@ static ALWAYS_INLINE uae_u8 sfc030c_get_byte(uaecptr addr)
 #if MMUDEBUG > 2
        write_log(_T("sfc030_get_byte: FC = %i\n"),fc);
 #endif
-       return read_dcache030(addr, 0, regs.sfc);
+       return read_dcache030_bget(addr, regs.sfc);
 }
 
 static ALWAYS_INLINE void dfc030c_put_long(uaecptr addr, uae_u32 val)
@@ -537,7 +537,7 @@ static ALWAYS_INLINE void dfc030c_put_long(uaecptr addr, uae_u32 val)
 #if MMUDEBUG > 2
        write_log(_T("dfc030_put_long: %08X = %08X FC = %i\n"), addr, val, fc);
 #endif
-       write_dcache030(addr, val, 2, regs.dfc);
+       write_dcache030_lput(addr, val, regs.dfc);
 }
 
 static ALWAYS_INLINE void dfc030c_put_word(uaecptr addr, uae_u16 val)
@@ -545,7 +545,7 @@ static ALWAYS_INLINE void dfc030c_put_word(uaecptr addr, uae_u16 val)
 #if MMUDEBUG > 2
        write_log(_T("dfc030_put_word: %08X = %04X FC = %i\n"), addr, val, fc);
 #endif
-       write_dcache030(addr, val, 1, regs.dfc);
+       write_dcache030_wput(addr, val, regs.dfc);
 }
 
 static ALWAYS_INLINE void dfc030c_put_byte(uaecptr addr, uae_u8 val)
@@ -553,7 +553,7 @@ static ALWAYS_INLINE void dfc030c_put_byte(uaecptr addr, uae_u8 val)
 #if MMUDEBUG > 2
        write_log(_T("dfc030_put_byte: %08X = %02X FC = %i\n"), addr, val, fc);
 #endif
-       write_dcache030(addr, val, 0, regs.dfc);
+       write_dcache030_bput(addr, val, regs.dfc);
 }
 
 uae_u32 REGPARAM3 get_disp_ea_020_mmu030c (uae_u32 base, int idx) REGPARAM;
@@ -561,7 +561,7 @@ uae_u32 REGPARAM3 get_disp_ea_020_mmu030c (uae_u32 base, int idx) REGPARAM;
 STATIC_INLINE void put_byte_mmu030c_state (uaecptr addr, uae_u32 v)
 {
        ACCESS_CHECK_PUT
-       write_dcache030_mmu(addr, v, 0);
+       write_data_030_bput(addr, v);
        ACCESS_EXIT_PUT
 }
 STATIC_INLINE void put_lrmw_byte_mmu030c_state (uaecptr addr, uae_u32 v)
@@ -573,7 +573,7 @@ STATIC_INLINE void put_lrmw_byte_mmu030c_state (uaecptr addr, uae_u32 v)
 STATIC_INLINE void put_word_mmu030c_state (uaecptr addr, uae_u32 v)
 {
        ACCESS_CHECK_PUT
-       write_dcache030_mmu(addr, v, 1);
+       write_data_030_wput(addr, v);
        ACCESS_EXIT_PUT
 }
 STATIC_INLINE void put_lrmw_word_mmu030c_state (uaecptr addr, uae_u32 v)
@@ -585,7 +585,7 @@ STATIC_INLINE void put_lrmw_word_mmu030c_state (uaecptr addr, uae_u32 v)
 STATIC_INLINE void put_long_mmu030c_state (uaecptr addr, uae_u32 v)
 {
        ACCESS_CHECK_PUT
-       write_dcache030_mmu(addr, v, 2);
+       write_data_030_lput(addr, v);
        ACCESS_EXIT_PUT
 }
 STATIC_INLINE void put_lrmw_long_mmu030c_state (uaecptr addr, uae_u32 v)
@@ -599,7 +599,7 @@ STATIC_INLINE uae_u32 get_byte_mmu030c_state (uaecptr addr)
 {
        uae_u32 v;
        ACCESS_CHECK_GET
-    v = read_dcache030_mmu(addr, 0);
+    v = read_data_030_bget(addr);
        ACCESS_EXIT_GET
        return v;
 }
@@ -616,7 +616,7 @@ STATIC_INLINE uae_u32 get_word_mmu030c_state (uaecptr addr)
 {
        uae_u32 v;
        ACCESS_CHECK_GET
-    v = read_dcache030_mmu(addr, 1);
+    v = read_data_030_wget(addr);
        ACCESS_EXIT_GET
        return v;
 }
@@ -632,7 +632,7 @@ STATIC_INLINE uae_u32 get_long_mmu030c_state (uaecptr addr)
 {
        uae_u32 v;
        ACCESS_CHECK_GET
-    v = read_dcache030_mmu(addr, 2);
+    v = read_data_030_lget(addr);
        ACCESS_EXIT_GET
        return v;
 }
@@ -700,19 +700,19 @@ STATIC_INLINE uae_u32 next_ilong_mmu030c_state (void)
 
 STATIC_INLINE uae_u32 get_word_mmu030c (uaecptr addr)
 {
-       return read_dcache030_mmu(addr, 1);
+       return read_data_030_wget(addr);
 }
 STATIC_INLINE uae_u32 get_long_mmu030c (uaecptr addr)
 {
-       return read_dcache030_mmu(addr, 2);
+       return read_data_030_lget(addr);
 }
 STATIC_INLINE void put_word_mmu030c (uaecptr addr, uae_u32 v)
 {
-    write_dcache030_mmu(addr, v, 1);
+    write_data_030_wput(addr, v);
 }
 STATIC_INLINE void put_long_mmu030c (uaecptr addr, uae_u32 v)
 {
-    write_dcache030_mmu(addr, v, 2);
+    write_data_030_lput(addr, v);
 }
 
 extern void m68k_do_rts_mmu030c(void);
index 951b4ac2b86d8e47745bd11aa284ddab8b281d7f..7141e8ab717a93ec5610cfb340056aab679ab9ed 100644 (file)
@@ -75,13 +75,33 @@ extern uaecptr uaeboard_base;
 
 extern uae_u8* baseaddr[];
 
+#define CACHE_ENABLE_DATA 0x01
+#define CACHE_ENABLE_DATA_BURST 0x02
+#define CACHE_ENABLE_COPYBACK 0x020
+#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_ALLOCATE 0x08
+#define CACHE_DISABLE_MMU 0x10
+extern uae_u8 ce_banktype[65536], ce_cachable[65536];
+
+#define ABFLAG_CACHE_SHIFT 16
 enum
 {
        ABFLAG_UNK = 0, ABFLAG_RAM = 1, ABFLAG_ROM = 2, ABFLAG_ROMIN = 4, ABFLAG_IO = 8,
        ABFLAG_NONE = 16, ABFLAG_SAFE = 32, ABFLAG_INDIRECT = 64, ABFLAG_NOALLOC = 128,
        ABFLAG_RTG = 256, ABFLAG_THREADSAFE = 512, ABFLAG_DIRECTMAP = 1024, ABFLAG_ALLOCINDIRECT = 2048,
        ABFLAG_CHIPRAM = 4096, ABFLAG_CIA = 8192, ABFLAG_PPCIOSPACE = 16384,
+       ABFLAG_CACHE_ENABLE_DATA = CACHE_ENABLE_DATA << ABFLAG_CACHE_SHIFT,
+       ABFLAG_CACHE_ENABLE_DATA_BURST = CACHE_ENABLE_DATA_BURST << ABFLAG_CACHE_SHIFT,
+       ABFLAG_CACHE_ENABLE_INS = CACHE_ENABLE_INS << ABFLAG_CACHE_SHIFT,
+       ABFLAG_CACHE_ENABLE_INS_BURST = CACHE_ENABLE_INS_BURST << ABFLAG_CACHE_SHIFT,
 };
+
+#define ABFLAG_CACHE_ENABLE_BOTH (ABFLAG_CACHE_ENABLE_DATA | ABFLAG_CACHE_ENABLE_INS)
+#define ABFLAG_CACHE_ENABLE_ALL (ABFLAG_CACHE_ENABLE_BOTH | ABFLAG_CACHE_ENABLE_INS_BURST | ABFLAG_CACHE_ENABLE_DATA_BURST)
+
 typedef struct {
        /* These ones should be self-explanatory... */
        mem_get_func lget, wget, bget;
@@ -167,14 +187,6 @@ struct autoconfig_info
 #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) \
 static uae_u32 REGPARAM3 name ## _lget (uaecptr) REGPARAM; \
index eb1d0abff1ab6733fdd4d02fedb1421e3bb856bf..9d54117362234d54d1765ba41026fce717edaf12 100644 (file)
@@ -131,6 +131,7 @@ struct cache040
 {
        uae_u32 data[CACHELINES040][4];
        bool dirty[CACHELINES040][4];
+       bool gdirty[CACHELINES040];
        bool valid[CACHELINES040];
        uae_u32 tag[CACHELINES040];
 };
@@ -330,6 +331,14 @@ uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr);
 uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr);
 uae_u32 mem_access_delay_wordi_read_ce020 (uaecptr addr);
 
+void mem_access_delay_long_write_c040 (uaecptr addr, uae_u32 v);
+void mem_access_delay_word_write_c040 (uaecptr addr, uae_u32 v);
+void mem_access_delay_byte_write_c040 (uaecptr addr, uae_u32 v);
+uae_u32 mem_access_delay_byte_read_c040 (uaecptr addr);
+uae_u32 mem_access_delay_word_read_c040 (uaecptr addr);
+uae_u32 mem_access_delay_long_read_c040 (uaecptr addr);
+uae_u32 mem_access_delay_longi_read_c040 (uaecptr addr);
+
 extern uae_u32(REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
 
 /* direct (regs.pc_p) access */
@@ -522,11 +531,26 @@ STATIC_INLINE void m68k_setpc_normal(uaecptr pc)
        }
 }
 
-extern void write_dcache030(uaecptr, uae_u32, uae_u32, uae_u32);
-extern uae_u32 read_dcache030(uaecptr, uae_u32, uae_u32);
-
-extern void write_dcache030_mmu(uaecptr, uae_u32, uae_u32);
-extern uae_u32 read_dcache030_mmu(uaecptr, uae_u32);
+extern uae_u32(*read_data_030_bget)(uaecptr);
+extern uae_u32(*read_data_030_wget)(uaecptr);
+extern uae_u32(*read_data_030_lget)(uaecptr);
+extern void(*write_data_030_bput)(uaecptr,uae_u32);
+extern void(*write_data_030_wput)(uaecptr,uae_u32);
+extern void(*write_data_030_lput)(uaecptr,uae_u32);
+
+extern void write_dcache030_bput(uaecptr, uae_u32, uae_u32);
+extern void write_dcache030_wput(uaecptr, uae_u32, uae_u32);
+extern void write_dcache030_lput(uaecptr, uae_u32, uae_u32);
+extern uae_u32 read_dcache030_bget(uaecptr, uae_u32);
+extern uae_u32 read_dcache030_wget(uaecptr, uae_u32);
+extern uae_u32 read_dcache030_lget(uaecptr, uae_u32);
+
+extern void write_dcache030_mmu_bput(uaecptr, uae_u32);
+extern void write_dcache030_mmu_wput(uaecptr, uae_u32);
+extern void write_dcache030_mmu_lput(uaecptr, uae_u32);
+extern uae_u32 read_dcache030_mmu_bget(uaecptr);
+extern uae_u32 read_dcache030_mmu_wget(uaecptr);
+extern uae_u32 read_dcache030_mmu_lget(uaecptr);
 extern void write_dcache030_lrmw_mmu(uaecptr, uae_u32, uae_u32);
 extern uae_u32 read_dcache030_lrmw_mmu(uaecptr, uae_u32);
 
@@ -595,7 +619,7 @@ extern void init_m68k (void);
 extern void m68k_go (int);
 extern void m68k_dumpstate (uaecptr *);
 extern void m68k_dumpstate (uaecptr, uaecptr *);
-extern void m68k_dumpcache (void);
+extern void m68k_dumpcache (bool);
 extern int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor);
 extern int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor);
 extern void divbyzero_special (bool issigned, uae_s32 dst);
@@ -694,7 +718,6 @@ extern void compemu_reset(void);
 #define flush_icache_hard(int) do {} while (0)
 #endif
 bool check_prefs_changed_comp (bool);
-extern void flush_dcache (uaecptr, int);
 
 extern int movec_illg (int regno);
 extern uae_u32 val_move2c (int regno);
index 03bd015532aaa9ac2d3c72cf1ecd45c8d173ac3c..fcfd41495108d0fb53e7e3d3e9cb4a32011da5a7 100644 (file)
@@ -516,6 +516,7 @@ struct uae_prefs {
 
        bool immediate_blits;
        int waiting_blits;
+       double blitter_speed_throttle;
        unsigned int chipset_mask;
        bool keyboard_connected;
        bool ntscmode;
@@ -659,6 +660,7 @@ struct uae_prefs {
        bool int_no_unimplemented;
        bool fpu_no_unimplemented;
        bool address_space_24;
+       bool cpu_data_cache;
        bool picasso96_nocustom;
        int picasso96_modeflags;
        int cpu_model_fallback;
index 7144f00a895e95e2f5b73601b5a0bdc5e0bccc6f..5e3325c0f4ce8700ff6ddac5e8dda7e1e0dd1201 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -324,6 +324,15 @@ void fixup_cpu (struct uae_prefs *p)
                error_log(_T("Cycle-exact mode requires at least Disabled but emulated sound setting."));
        }
 
+       if (p->cpu_data_cache && (!p->cpu_compatible || p->cachesize || p->cpu_model < 68030)) {
+               p->cpu_data_cache = false;
+               error_log(_T("Data cache emulation requires More compatible, is not JIT compatible, 68030+ only."));
+       }
+       if (p->cpu_data_cache && (currprefs.uaeboard != 3 && uae_boot_rom_type > 0)) {
+               p->cpu_data_cache = false;
+               error_log(_T("Data cache emulation requires Indirect UAE Boot ROM."));
+       }
+
 #if 0
        if (p->cachesize && p->cpuboard_type && !cpuboard_jitdirectompatible(p) && !p->comptrustbyte) {
                error_log(_T("JIT direct is not compatible with emulated Blizzard accelerator boards."));
index b75e5813d35fdef4ed2cd3050cf52182d91a6bda..f750ee796a94b432949426343b5080c8686e9ff5 100644 (file)
@@ -1099,7 +1099,7 @@ addrbank chipmem_bank = {
        chipmem_lput, chipmem_wput, chipmem_bput,
        chipmem_xlate, chipmem_check, NULL, _T("chip"), _T("Chip memory"),
        chipmem_lget, chipmem_wget,
-       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CHIPRAM, 0, 0
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CHIPRAM | ABFLAG_CACHE_ENABLE_BOTH, 0, 0
 };
 
 addrbank chipmem_dummy_bank = {
@@ -1117,7 +1117,7 @@ addrbank chipmem_bank_ce2 = {
        chipmem_lput_ce2, chipmem_wput_ce2, chipmem_bput_ce2,
        chipmem_xlate, chipmem_check, NULL, NULL, _T("Chip memory (68020 'ce')"),
        chipmem_lget_ce2, chipmem_wget_ce2,
-       ABFLAG_RAM | ABFLAG_CHIPRAM, S_READ, S_WRITE
+       ABFLAG_RAM | ABFLAG_CHIPRAM | ABFLAG_CACHE_ENABLE_BOTH, S_READ, S_WRITE
 };
 #endif
 
@@ -1126,7 +1126,7 @@ addrbank bogomem_bank = {
        bogomem_lput, bogomem_wput, bogomem_bput,
        bogomem_xlate, bogomem_check, NULL, _T("bogo"), _T("Slow memory"),
        bogomem_lget, bogomem_wget,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_BOTH, 0, 0
 };
 
 addrbank cardmem_bank = {
@@ -1142,7 +1142,7 @@ addrbank mem25bit_bank = {
        mem25bit_lput, mem25bit_wput, mem25bit_bput,
        mem25bit_xlate, mem25bit_check, NULL, _T("25bitmem"), _T("25bit memory"),
        mem25bit_lget, mem25bit_wget,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
 };
 
 addrbank a3000lmem_bank = {
@@ -1150,7 +1150,7 @@ addrbank a3000lmem_bank = {
        a3000lmem_lput, a3000lmem_wput, a3000lmem_bput,
        a3000lmem_xlate, a3000lmem_check, NULL, _T("ramsey_low"), _T("RAMSEY memory (low)"),
        a3000lmem_lget, a3000lmem_wget,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
 };
 
 addrbank a3000hmem_bank = {
@@ -1158,7 +1158,7 @@ addrbank a3000hmem_bank = {
        a3000hmem_lput, a3000hmem_wput, a3000hmem_bput,
        a3000hmem_xlate, a3000hmem_check, NULL, _T("ramsey_high"), _T("RAMSEY memory (high)"),
        a3000hmem_lget, a3000hmem_wget,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
 };
 
 addrbank kickmem_bank = {
@@ -1166,7 +1166,7 @@ addrbank kickmem_bank = {
        kickmem_lput, kickmem_wput, kickmem_bput,
        kickmem_xlate, kickmem_check, NULL, _T("kick"), _T("Kickstart ROM"),
        kickmem_lget, kickmem_wget,
-       ABFLAG_ROM | ABFLAG_THREADSAFE, 0, S_WRITE
+       ABFLAG_ROM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, S_WRITE
 };
 
 addrbank kickram_bank = {
@@ -1174,7 +1174,7 @@ addrbank kickram_bank = {
        kickmem2_lput, kickmem2_wput, kickmem2_bput,
        kickmem_xlate, kickmem_check, NULL, NULL, _T("Kickstart Shadow RAM"),
        kickmem_lget, kickmem_wget,
-       ABFLAG_UNK | ABFLAG_SAFE, 0, S_WRITE
+       ABFLAG_UNK | ABFLAG_SAFE | ABFLAG_CACHE_ENABLE_ALL, 0, S_WRITE
 };
 
 addrbank extendedkickmem_bank = {
@@ -1182,14 +1182,14 @@ addrbank extendedkickmem_bank = {
        extendedkickmem_lput, extendedkickmem_wput, extendedkickmem_bput,
        extendedkickmem_xlate, extendedkickmem_check, NULL, NULL, _T("Extended Kickstart ROM"),
        extendedkickmem_lget, extendedkickmem_wget,
-       ABFLAG_ROM | ABFLAG_THREADSAFE, 0, S_WRITE
+       ABFLAG_ROM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, S_WRITE
 };
 addrbank extendedkickmem2_bank = {
        extendedkickmem2_lget, extendedkickmem2_wget, extendedkickmem2_bget,
        extendedkickmem2_lput, extendedkickmem2_wput, extendedkickmem2_bput,
        extendedkickmem2_xlate, extendedkickmem2_check, NULL, _T("rom_a8"), _T("Extended 2nd Kickstart ROM"),
        extendedkickmem2_lget, extendedkickmem2_wget,
-       ABFLAG_ROM | ABFLAG_THREADSAFE, 0, S_WRITE
+       ABFLAG_ROM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, S_WRITE
 };
 addrbank fakeuaebootrom_bank = {
        fakeuaebootrom_lget, fakeuaebootrom_wget, mem25bit_bget,
@@ -1207,14 +1207,14 @@ addrbank custmem1_bank = {
        custmem1_lput, custmem1_wput, custmem1_bput,
        custmem1_xlate, custmem1_check, NULL, _T("custmem1"), _T("Non-autoconfig RAM #1"),
        custmem1_lget, custmem1_wget,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
 };
 addrbank custmem2_bank = {
        custmem2_lget, custmem2_wget, custmem2_bget,
        custmem2_lput, custmem2_wput, custmem2_bput,
        custmem2_xlate, custmem2_check, NULL, _T("custmem2"), _T("Non-autoconfig RAM #2"),
        custmem2_lget, custmem2_wget,
-       ABFLAG_RAM | ABFLAG_THREADSAFE, 0, 0
+       ABFLAG_RAM | ABFLAG_THREADSAFE | ABFLAG_CACHE_ENABLE_ALL, 0, 0
 };
 
 #define fkickmem_size ROM_SIZE_512
@@ -2217,25 +2217,6 @@ static void fill_ce_banks (void)
                memset (ce_banktype, CE_MEMBANK_FAST32, sizeof ce_banktype);
        }
 
-       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), CACHE_ENABLE_BOTH, currprefs.fastmem[i].size >> 16);
-               if (z3fastmem_bank[i].start != 0xffffffff)
-                       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);
-               }
-       }
-
        addrbank *ab = &get_mem_bank(0);
        if (ab && (ab->flags & ABFLAG_CHIPRAM)) {
                for (i = 0; i < (0x200000 >> 16); i++) {
@@ -2256,7 +2237,6 @@ static void fill_ce_banks (void)
                b = &get_mem_bank (i << 16);
                if (b && !(b->flags & ABFLAG_CIA)) {
                        ce_banktype[i] = CE_MEMBANK_FAST32;
-                       ce_cachable[i] = 1;
                }
        }
        // CD32 ROM is 16-bit
@@ -2482,6 +2462,8 @@ void memory_reset (void)
        if (mem_hardreset > 2)
                memory_init ();
 
+       memset(ce_cachable, CACHE_ENABLE_INS, sizeof ce_cachable);
+
        be_cnt = be_recursive = 0;
        currprefs.chipmem_size = changed_prefs.chipmem_size;
        currprefs.bogomem_size = changed_prefs.bogomem_size;
@@ -2943,6 +2925,7 @@ static void map_banks2 (addrbank *bank, int start, int size, int realsize, int q
 #endif
                        }
                        put_mem_bank (bnr << 16, bank, realstart << 16);
+                       ce_cachable[bnr] = bank->flags >> ABFLAG_CACHE_SHIFT;
 #ifdef WITH_THREADED_CPU
                        if (currprefs.cpu_thread) {
                                if (orig_bank)
@@ -2974,6 +2957,7 @@ static void map_banks2 (addrbank *bank, int start, int size, int realsize, int q
 #endif
                        }
                        put_mem_bank ((bnr + hioffs) << 16, bank, realstart << 16);
+                       ce_cachable[bnr + hioffs] = bank->flags >> ABFLAG_CACHE_SHIFT;
 #ifdef WITH_THREADED_CPU
                        if (currprefs.cpu_thread) {
                                if (orig_bank)
index ab0180872474377343ef37c064661afa5595d78d..a521837d2135545a1494fbcdb49e088b44daf324 100644 (file)
 #define DEBUG_CD32CDTVIO 0
 #define EXCEPTION3_DEBUGGER 0
 #define CPUTRACE_DEBUG 0
+
 #define VALIDATE_68030_DATACACHE 0
+#define VALIDATE_68040_DATACACHE 0
+#define DISABLE_68040_COPYBACK 0
 
 #define MORE_ACCURATE_68020_PIPELINE 1
 
@@ -78,7 +81,8 @@ int m68k_pc_indirect;
 bool m68k_interrupt_delay;
 static bool m68k_reset_delay;
 
-static int cachesets04060, cachesets04060minus1;
+static int cacheisets04060, cacheisets04060mask, cacheitag04060mask;
+static int cachedsets04060, cachedsets04060mask, cachedtag04060mask;
 
 static int cpu_prefs_changed_flag;
 
@@ -115,9 +119,11 @@ static uae_u16 fake_mmusr_030;
 static struct cache020 caches020[CACHELINES020];
 static struct cache030 icaches030[CACHELINES030];
 static struct cache030 dcaches030[CACHELINES030];
-static int icachelinecnt, dcachelinecnt;
+static int icachelinecnt, icachehalfline;
+static int dcachelinecnt;
 static struct cache040 icaches040[CACHESETS060];
 static struct cache040 dcaches040[CACHESETS060];
+static int cache_lastline; 
 
 static int fallback_cpu_model, fallback_mmu_model, fallback_fpu_model;
 static bool fallback_cpu_compatible, fallback_cpu_address_space_24;
@@ -761,19 +767,26 @@ static void do_cycles_ce020_post (unsigned long cycles, uae_u32 v)
        do_cycles_ce020 (cycles);
 }
 
-static uae_u8 dcache030_check_nommu(uaecptr addr, bool write, uae_u32 size)
+static uae_u8 dcache_check_nommu(uaecptr addr, bool write, uae_u32 size)
 {
        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 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);
+static uae_u32 (*dcache_lget)(uaecptr);
+static uae_u32 (*dcache_wget)(uaecptr);
+static uae_u32 (*dcache_bget)(uaecptr);
+static uae_u8 (*dcache_check)(uaecptr, bool, uae_u32);
+static void (*dcache_lput)(uaecptr, uae_u32);
+static void (*dcache_wput)(uaecptr, uae_u32);
+static void (*dcache_bput)(uaecptr, uae_u32);
+
+uae_u32(*read_data_030_bget)(uaecptr);
+uae_u32(*read_data_030_wget)(uaecptr);
+uae_u32(*read_data_030_lget)(uaecptr);
+void(*write_data_030_bput)(uaecptr,uae_u32);
+void(*write_data_030_wput)(uaecptr,uae_u32);
+ void(*write_data_030_lput)(uaecptr,uae_u32);
 
 static void set_x_ifetches(void)
 {
@@ -1016,12 +1029,21 @@ static void set_x_funcs (void)
                                x_get_ibyte = NULL;
                                x_next_iword = next_iword_cache040;
                                x_next_ilong = next_ilong_cache040;
-                               x_put_long = put_long_cache_040;
-                               x_put_word = put_word_cache_040;
-                               x_put_byte = put_byte_cache_040;
-                               x_get_long = get_long_cache_040;
-                               x_get_word = get_word_cache_040;
-                               x_get_byte = get_byte_cache_040;
+                               if (currprefs.cpu_data_cache) {
+                                       x_put_long = put_long_cache_040;
+                                       x_put_word = put_word_cache_040;
+                                       x_put_byte = put_byte_cache_040;
+                                       x_get_long = get_long_cache_040;
+                                       x_get_word = get_word_cache_040;
+                                       x_get_byte = get_byte_cache_040;
+                               } else {
+                                       x_phys_get_byte = mem_access_delay_byte_read_c040;
+                                       x_phys_get_word = mem_access_delay_word_read_c040;
+                                       x_phys_get_long = mem_access_delay_long_read_c040;
+                                       x_phys_put_byte = mem_access_delay_byte_write_c040;
+                                       x_phys_put_word = mem_access_delay_word_write_c040;
+                                       x_phys_put_long = mem_access_delay_long_write_c040;
+                               }
                                x_do_cycles = do_cycles;
                                x_do_cycles_pre = do_cycles;
                                x_do_cycles_post = do_cycles_post;
@@ -1080,12 +1102,21 @@ static void set_x_funcs (void)
                                x_get_ibyte = NULL;
                                x_next_iword = next_iword_cache040;
                                x_next_ilong = next_ilong_cache040;
-                               x_put_long = put_long_cache_040;
-                               x_put_word = put_word_cache_040;
-                               x_put_byte = put_byte_cache_040;
-                               x_get_long = get_long_cache_040;
-                               x_get_word = get_word_cache_040;
-                               x_get_byte = get_byte_cache_040;
+                               if (currprefs.cpu_data_cache) {
+                                       x_put_long = put_long_cache_040;
+                                       x_put_word = put_word_cache_040;
+                                       x_put_byte = put_byte_cache_040;
+                                       x_get_long = get_long_cache_040;
+                                       x_get_word = get_word_cache_040;
+                                       x_get_byte = get_byte_cache_040;
+                               } else {
+                                       x_put_long = put_long;
+                                       x_put_word = put_word;
+                                       x_put_byte = put_byte;
+                                       x_get_long = get_long;
+                                       x_get_word = get_word;
+                                       x_get_byte = get_byte;
+                               }
                                x_do_cycles = do_cycles;
                                x_do_cycles_pre = do_cycles;
                                x_do_cycles_post = do_cycles_post;
@@ -1152,12 +1183,21 @@ static void set_x_funcs (void)
                x_get_ibyte = NULL;
                x_next_iword = next_iword_cache040;
                x_next_ilong = next_ilong_cache040;
-               x_put_long = put_long_cache_040;
-               x_put_word = put_word_cache_040;
-               x_put_byte = put_byte_cache_040;
-               x_get_long = get_long_cache_040;
-               x_get_word = get_word_cache_040;
-               x_get_byte = get_byte_cache_040;
+               if (currprefs.cpu_data_cache) {
+                       x_put_long = put_long_cache_040;
+                       x_put_word = put_word_cache_040;
+                       x_put_byte = put_byte_cache_040;
+                       x_get_long = get_long_cache_040;
+                       x_get_word = get_word_cache_040;
+                       x_get_byte = get_byte_cache_040;
+               } else {
+                       x_phys_get_byte = mem_access_delay_byte_read_c040;
+                       x_phys_get_word = mem_access_delay_word_read_c040;
+                       x_phys_get_long = mem_access_delay_long_read_c040;
+                       x_phys_put_byte = mem_access_delay_byte_write_c040;
+                       x_phys_put_word = mem_access_delay_word_write_c040;
+                       x_phys_put_long = mem_access_delay_long_write_c040;
+               }
                x_do_cycles = do_cycles_ce020;
                x_do_cycles_pre = do_cycles_ce020;
                x_do_cycles_post = do_cycles_ce020_post;
@@ -1218,45 +1258,96 @@ static void set_x_funcs (void)
        mmu_set_funcs();
        mmu030_set_funcs();
 
+       dcache_lput = put_long;
+       dcache_wput = put_word;
+       dcache_bput = put_byte;
+       dcache_lget = get_long;
+       dcache_wget = get_word;
+       dcache_bget = get_byte;
+       dcache_check = dcache_check_nommu;
+
        icache_fetch = get_longi;
-       dcache030_lput = put_long;
-       dcache030_wput = put_word;
-       dcache030_bput = put_byte;
-       dcache030_lget = get_long;
-       dcache030_wget = get_word;
-       dcache030_bget = get_byte;
-       dcache030_check = dcache030_check_nommu;
        if (currprefs.cpu_cycle_exact) {
                icache_fetch = mem_access_delay_longi_read_ce020;
        }
+       if (currprefs.cpu_model >= 68040 && currprefs.cpu_memory_cycle_exact) {
+               icache_fetch = mem_access_delay_longi_read_c040;
+               dcache_bget = mem_access_delay_byte_read_c040;
+               dcache_wget = mem_access_delay_word_read_c040;
+               dcache_lget = mem_access_delay_long_read_c040;
+               dcache_bput = mem_access_delay_byte_write_c040;
+               dcache_wput = mem_access_delay_word_write_c040;
+               dcache_lput = mem_access_delay_long_write_c040;
+       }
+
        if (currprefs.cpu_model == 68030) {
+
+               if (currprefs.cpu_data_cache) {
+                       read_data_030_bget = read_dcache030_mmu_bget;
+                       read_data_030_wget = read_dcache030_mmu_wget;
+                       read_data_030_lget = read_dcache030_mmu_lget;
+                       write_data_030_bput = write_dcache030_mmu_bput;
+                       write_data_030_wput = write_dcache030_mmu_wput;
+                       write_data_030_lput = write_dcache030_mmu_lput;
+               } else {
+                       read_data_030_bget = dcache_bget;
+                       read_data_030_wget = dcache_wget;
+                       read_data_030_lget = dcache_lget;
+                       write_data_030_bput = dcache_bput;
+                       write_data_030_wput = dcache_wput;
+                       write_data_030_lput = dcache_lput;
+               }
                if (currprefs.mmu_model) {
                        if (currprefs.cpu_compatible) {
                                icache_fetch = uae_mmu030_get_ilong_fc;
-                               dcache030_lput = uae_mmu030_put_long_fc;
-                               dcache030_wput = uae_mmu030_put_word_fc;
-                               dcache030_bput = uae_mmu030_put_byte_fc;
-                               dcache030_lget = uae_mmu030_get_long_fc;
-                               dcache030_wget = uae_mmu030_get_word_fc;
-                               dcache030_bget = uae_mmu030_get_byte_fc;
-                               dcache030_check = uae_mmu030_check_fc;
+                               dcache_lput = uae_mmu030_put_long_fc;
+                               dcache_wput = uae_mmu030_put_word_fc;
+                               dcache_bput = uae_mmu030_put_byte_fc;
+                               dcache_lget = uae_mmu030_get_long_fc;
+                               dcache_wget = uae_mmu030_get_word_fc;
+                               dcache_bget = uae_mmu030_get_byte_fc;
+                               dcache_check = uae_mmu030_check_fc;
                        } else {
                                icache_fetch = uae_mmu030_get_ilong;
-                               dcache030_lput = uae_mmu030_put_long;
-                               dcache030_wput = uae_mmu030_put_word;
-                               dcache030_bput = uae_mmu030_put_byte;
-                               dcache030_lget = uae_mmu030_get_long;
-                               dcache030_wget = uae_mmu030_get_word;
-                               dcache030_bget = uae_mmu030_get_byte;
+                               dcache_lput = uae_mmu030_put_long;
+                               dcache_wput = uae_mmu030_put_word;
+                               dcache_bput = uae_mmu030_put_byte;
+                               dcache_lget = uae_mmu030_get_long;
+                               dcache_wget = uae_mmu030_get_word;
+                               dcache_bget = uae_mmu030_get_byte;
+                       }
+                       if (currprefs.cpu_data_cache) {
+                               read_data_030_bget = read_dcache030_mmu_bget;
+                               read_data_030_wget = read_dcache030_mmu_wget;
+                               read_data_030_lget = read_dcache030_mmu_lget;
+                               write_data_030_bput = write_dcache030_mmu_bput;
+                               write_data_030_wput = write_dcache030_mmu_wput;
+                               write_data_030_lput = write_dcache030_mmu_lput;
+                       } else {
+                               if (currprefs.cpu_compatible) {
+                                       read_data_030_bget = uae_mmu030_get_byte_fc;
+                                       read_data_030_wget = uae_mmu030_get_word_fc;
+                                       read_data_030_lget = uae_mmu030_get_long_fc;
+                                       write_data_030_bput = uae_mmu030_put_byte_fc;
+                                       write_data_030_wput = uae_mmu030_put_word_fc;
+                                       write_data_030_lput = uae_mmu030_put_long_fc;
+                               } else {
+                                       read_data_030_bget = uae_mmu030_get_byte;
+                                       read_data_030_wget = uae_mmu030_get_word;
+                                       read_data_030_lget = uae_mmu030_get_long;
+                                       write_data_030_bput = uae_mmu030_put_byte;
+                                       write_data_030_wput = uae_mmu030_put_word;
+                                       write_data_030_lput = uae_mmu030_put_long;
+                               }
                        }
                } else if (currprefs.cpu_memory_cycle_exact) {
                        icache_fetch = mem_access_delay_longi_read_ce020;
-                       dcache030_lput = mem_access_delay_long_write_ce020;
-                       dcache030_wput = mem_access_delay_word_write_ce020;
-                       dcache030_bput = mem_access_delay_byte_write_ce020;
-                       dcache030_lget = mem_access_delay_long_read_ce020;
-                       dcache030_wget = mem_access_delay_word_read_ce020;
-                       dcache030_bget = mem_access_delay_byte_read_ce020;
+                       dcache_lput = mem_access_delay_long_write_ce020;
+                       dcache_wput = mem_access_delay_word_write_ce020;
+                       dcache_bput = mem_access_delay_byte_write_ce020;
+                       dcache_lget = mem_access_delay_long_read_ce020;
+                       dcache_wget = mem_access_delay_word_read_ce020;
+                       dcache_bget = mem_access_delay_byte_read_ce020;
                }
        }
 }
@@ -1291,6 +1382,25 @@ bool set_cpu_tracer (bool state)
        return is_cpu_tracer ();
 }
 
+static void invalidate_cpu_data_caches(void)
+{
+       if (currprefs.cpu_model == 68030) {
+               for (int i = 0; i < CACHELINES030; i++) {
+                       dcaches030[i].valid[0] = 0;
+                       dcaches030[i].valid[1] = 0;
+                       dcaches030[i].valid[2] = 0;
+                       dcaches030[i].valid[3] = 0;
+               }
+       } else if (currprefs.cpu_model >= 68040) {
+               dcachelinecnt = 0;
+               for (int i = 0; i < CACHESETS060; i++) {
+                       for (int j = 0; j < CACHELINES040; j++) {
+                               dcaches040[i].valid[j] = false;
+                       }
+               }
+       }
+}
+
 void flush_cpu_caches(bool force)
 {
        bool doflush = currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact;
@@ -1339,32 +1449,107 @@ void flush_cpu_caches(bool force)
        } else if (currprefs.cpu_model >= 68040) {
                mmu_flush_cache();
                icachelinecnt = 0;
-               dcachelinecnt = 0;
-               if (doflush) {
+               icachehalfline = 0;
+               if (doflush || force) {
                        for (int i = 0; i < CACHESETS060; i++) {
-                               icaches040[i].valid[0] = 0;
-                               icaches040[i].valid[1] = 0;
-                               icaches040[i].valid[2] = 0;
-                               icaches040[i].valid[3] = 0;
+                               for (int j = 0; j < CACHELINES040; j++) {
+                                       icaches040[i].valid[j] = false;
+                               }
                        }
                }
        }
 }
 
+#if VALIDATE_68040_DATACACHE > 1
+static void validate_dcache040(void)
+{
+       for (int i = 0; i < cachedsets04060; i++) {
+               struct cache040 *c = &dcaches040[i];
+               for (int j = 0; j < CACHELINES040; j++) {
+                       if (c->valid[j]) {
+                               uae_u32 addr = (c->tag[j] & cachedtag04060mask) | (i << 4);
+                               if (addr < 0x200000 || (addr >= 0xd80000 && addr < 0xe00000) || (addr >= 0xe80000 && addr < 0xf00000) || (addr >= 0xa00000 && addr < 0xc00000)) {
+                                       write_log(_T("Chip RAM or IO address cached! %08x\n"), addr);
+                               }
+                               for (int k = 0; k < 4; k++) {
+                                       if (!c->dirty[j][k]) {
+                                               uae_u32 v = get_long(addr + k * 4);
+                                               if (v != c->data[j][k]) {
+                                                       write_log(_T("Address %08x data cache mismatch %08x != %08x\n"), addr, v, c->data[j][k]);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+#endif
+
+static void dcache040_push_line(int index, int line, bool writethrough, bool invalidate)
+{
+       struct cache040 *c = &dcaches040[index];
+#if VALIDATE_68040_DATACACHE
+       if (!c->valid[line]) {
+               write_log("dcache040_push_line pushing invalid line!\n");
+       }
+#endif
+       if (c->gdirty[line]) {
+               uae_u32 addr = (c->tag[line] & cachedtag04060mask) | (index << 4);
+               for (int i = 0; i < 4; i++) {
+                       if (c->dirty[line][i] || (!writethrough && currprefs.cpu_model == 68060)) {
+                               dcache_lput(addr + i * 4, c->data[line][i]);
+                               c->dirty[line][i] = false;
+                       }
+               }
+               c->gdirty[line] = false;
+       }
+       if (invalidate)
+               c->valid[line] = false;
+
+#if VALIDATE_68040_DATACACHE > 1
+       validate_dcache040();
+#endif
+}
+
 void flush_cpu_caches_040(uae_u16 opcode)
 {
+       // 0 (1) = data, 1 (2) = instruction
        int cache = (opcode >> 6) & 3;
        int scope = (opcode >> 3) & 3;
        int areg = opcode & 7;
        uaecptr addr = m68k_areg(regs, areg);
        bool push = (opcode & 0x20) != 0;
+       bool pushinv = (regs.cacr & 0x01000000) == 0; // 68060 DPI
 
-       regs.prefetch020addr = 0xffffffff;
+#if VALIDATE_68040_DATACACHE
+       write_log(_T("push %d %d %d %08x %d %d\n"), cache, scope, areg, addr, push, pushinv);
+#endif
+
+       if (cache & 2)
+               regs.prefetch020addr = 0xffffffff;
        for (int k = 0; k < 2; k++) {
                if (cache & (1 << k)) {
                        if (scope == 3) {
                                // all
-                               flush_cpu_caches(true);
+                               if (!k) {
+                                       // data
+                                       for (int i = 0; i < cachedsets04060; i++) {
+                                               struct cache040 *c = &dcaches040[i];
+                                               for (int j = 0; j < CACHELINES040; j++) {
+                                                       if (c->valid[j]) {
+                                                               if (push) {
+                                                                       dcache040_push_line(i, j, false, pushinv);
+                                                               } else {
+                                                                       c->valid[j] = false;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       dcachelinecnt = 0;
+                               } else {
+                                       // instruction
+                                       flush_cpu_caches(true);
+                               }
                        } else {
                                uae_u32 pagesize;
                                if (scope == 2) {
@@ -1376,32 +1561,51 @@ void flush_cpu_caches_040(uae_u16 opcode)
                                }
                                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];
+                                       int index;
+                                       uae_u32 tag;
+                                       uae_u32 tagmask;
+                                       struct cache040 *c;
+                                       if (k) {
+                                               tagmask = cacheitag04060mask;
+                                               index = (addr >> 4) & cacheisets04060mask;
+                                               c = &icaches040[index];
+                                       } else {
+                                               tagmask = cachedtag04060mask;
+                                               index = (addr >> 4) & cachedsets04060mask;
+                                               c = &dcaches040[index];
+                                       }
+                                       tag = addr & tagmask;
                                        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]);
-                                                               }
+                                                       if (push) {
+                                                               dcache040_push_line(index, i, false, pushinv);
+                                                       } else {
+                                                               c->valid[i] = false;
                                                        }
-                                                       c->valid[i] = false;
                                                }
                                        }
                                }
                        }
                }
        }
+       mmu_flush_cache();
 }
 
 void set_cpu_caches (bool flush)
 {
        regs.prefetch020addr = 0xffffffff;
        regs.cacheholdingaddr020 = 0xffffffff;
+       cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
+
+       // 68060 FIC 1/2 instruction cache
+       cacheisets04060 = currprefs.cpu_model == 68060 && !(regs.cacr & 0x00002000) ? CACHESETS060 : CACHESETS040;
+       cacheisets04060mask = cacheisets04060 - 1;
+       cacheitag04060mask = ~((cacheisets04060 << 4) - 1);
+       // 68060 FOC 1/2 data cache
+       cachedsets04060 = currprefs.cpu_model == 68060 && !(regs.cacr & 0x08000000) ? CACHESETS060 : CACHESETS040;
+       cachedsets04060mask = cachedsets04060 - 1;
+       cachedtag04060mask = ~((cachedsets04060 << 4) - 1);
+       cache_lastline = 0;
 
 #ifdef JIT
        if (currprefs.cachesize) {
@@ -1701,7 +1905,6 @@ static void prefs_changed_cpu (void)
                        mmu_set_tc(tcr);
                        mmu_set_super(regs.s != 0);
                        mmu_tt_modified();
-                       mmu_dump_tables();
                } else if (currprefs.mmu_model == 68030) {
                        mmu030_reset(-1);
                        mmu030_flush_atc_all();
@@ -1723,6 +1926,11 @@ static void prefs_changed_cpu (void)
        if (currprefs.cpu_compatible != changed_prefs.cpu_compatible) {
                currprefs.cpu_compatible = changed_prefs.cpu_compatible;
                flush_cpu_caches(true);
+               invalidate_cpu_data_caches();
+       }
+       if (currprefs.cpu_data_cache != changed_prefs.cpu_data_cache) {
+               currprefs.cpu_data_cache = changed_prefs.cpu_data_cache;
+               invalidate_cpu_data_caches();
        }
        currprefs.address_space_24 = changed_prefs.address_space_24;
        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
@@ -1744,6 +1952,7 @@ static int check_prefs_changed_cpu2(void)
                || currprefs.fpu_model != changed_prefs.fpu_model
                || currprefs.mmu_model != changed_prefs.mmu_model
                || currprefs.mmu_ec != changed_prefs.mmu_ec
+               || currprefs.cpu_data_cache != changed_prefs.cpu_data_cache
                || currprefs.int_no_unimplemented != changed_prefs.int_no_unimplemented
                || currprefs.fpu_no_unimplemented != changed_prefs.fpu_no_unimplemented
                || currprefs.cpu_compatible != changed_prefs.cpu_compatible
@@ -2858,6 +3067,10 @@ static void Exception_mmu (int nr, uaecptr oldpc)
 
        interrupt = nr >= 24 && nr < 24 + 8;
 
+       // exception vector fetch and exception stack frame
+       // operations don't allocate new cachelines
+       cache_default_data |= CACHE_DISABLE_ALLOCATE;
+       
        exception_debug (nr);
        MakeSR ();
 
@@ -2905,6 +3118,9 @@ static void Exception_mmu (int nr, uaecptr oldpc)
                        exception3_read(regs.ir, newpc);
                return;
        }
+
+       cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
+
        m68k_setpci (newpc);
        fill_prefetch ();
        exception_check_trace (nr);
@@ -2953,6 +3169,8 @@ static void Exception_normal (int nr)
        int interrupt;
        int vector_nr = nr;
 
+       cache_default_data |= CACHE_DISABLE_ALLOCATE;
+
        interrupt = nr >= 24 && nr < 24 + 8;
 
        if (interrupt && currprefs.cpu_model <= 68010)
@@ -3167,6 +3385,7 @@ kludge_me_do:
                return;
        }
        m68k_setpc (newpc);
+       cache_default_data &= ~CACHE_DISABLE_ALLOCATE;
 #ifdef JIT
        set_special (SPCFLAG_END_COMPILE);
 #endif
@@ -3355,8 +3574,9 @@ static void m68k_reset2(bool hardreset)
        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.cpu_model >= 68040) {
+               set_cpu_caches(false);
+       }
        if (currprefs.mmu_model >= 68040) {
                mmu_reset ();
                mmu_set_tc (regs.tcr);
@@ -7347,7 +7567,7 @@ void m68k_dumpstate (uaecptr *nextpc)
 {
        m68k_dumpstate (m68k_getpc (), nextpc);
 }
-void m68k_dumpcache (void)
+void m68k_dumpcache (bool dc)
 {
        if (!currprefs.cpu_compatible)
                return;
@@ -7366,24 +7586,37 @@ void m68k_dumpcache (void)
                        console_out_f (_T("\n"));
                }
        } else if (currprefs.cpu_model == 68030) {
-               for (int j = 0; j < 2; j++) {
-                       console_out_f (_T("%s\n"), j == 0 ? _T("Instruction") : _T("Data"));
-                       for (int i = 0; i < CACHELINES030; i++) {
-                               struct cache030 *c = j ? &dcaches030[i] : &icaches030[i];
-                               int fc;
-                               uaecptr addr;
-                               if (j == 0) {
-                                       fc = (c->tag & 1) ? 6 : 2;
-                               } else {
-                                       fc = c->fc;
-                               }
-                               addr = c->tag & ~1;
-                               addr |= i << 4;
-                               console_out_f (_T("%08X %d: "), addr, fc);
-                               for (int j = 0; j < 4; j++) {
-                                       console_out_f (_T("%08X%c "), c->data[j], c->valid[j] ? '*' : ' ');
+               for (int i = 0; i < CACHELINES030; i++) {
+                       struct cache030 *c = dc ? &dcaches030[i] : &icaches030[i];
+                       int fc;
+                       uaecptr addr;
+                       if (!dc) {
+                               fc = (c->tag & 1) ? 6 : 2;
+                       } else {
+                               fc = c->fc;
+                       }
+                       addr = c->tag & ~1;
+                       addr |= i << 4;
+                       console_out_f (_T("%08X %d: "), addr, fc);
+                       for (int j = 0; j < 4; j++) {
+                               console_out_f (_T("%08X%c "), c->data[j], c->valid[j] ? '*' : ' ');
+                       }
+                       console_out_f (_T("\n"));
+               }
+       } else if (currprefs.cpu_model >= 68040) {
+               uae_u32 tagmask = dc ? cachedtag04060mask : cacheitag04060mask;
+               for (int i = 0; i < cachedsets04060; i++) {
+                       struct cache040 *c = dc ? &dcaches040[i] : &icaches040[i];
+                       for (int j = 0; j < CACHELINES040; j++) {
+                               if (c->valid[j]) {
+                                       uae_u32 addr = (c->tag[j] & tagmask) | (i << 4);
+                                       write_log(_T("%02d:%d %08x = %08x%c %08x%c %08x%c %08x%c\n"),
+                                               i, j, addr,
+                                               c->data[j][0], c->dirty[j][0] ? '*' : ' ',
+                                               c->data[j][1], c->dirty[j][1] ? '*' : ' ',
+                                               c->data[j][2], c->dirty[j][2] ? '*' : ' ',
+                                               c->data[j][3], c->dirty[j][3] ? '*' : ' ');
                                }
-                               console_out_f (_T("\n"));
                        }
                }
        }
@@ -7524,12 +7757,13 @@ uae_u8 *restore_cpu (uae_u8 *src)
                        if (flags & 0x8000000) {
                                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();
-                                               icaches040[i].data[j][2] = restore_u32();
-                                               icaches040[i].data[j][3] = restore_u32();
-                                               icaches040[i].tag[j] = restore_u32();
-                                               icaches040[i].valid[j] = restore_u16() & 1;
+                                               struct cache040 *c = &icaches040[i];
+                                               c->data[j][0] = restore_u32();
+                                               c->data[j][1] = restore_u32();
+                                               c->data[j][2] = restore_u32();
+                                               c->data[j][3] = restore_u32();
+                                               c->tag[j] = restore_u32();
+                                               c->valid[j] = restore_u16() & 1;
                                        }
                                }
                                regs.prefetch020addr = restore_u32();
@@ -7537,6 +7771,25 @@ uae_u8 *restore_cpu (uae_u8 *src)
                                regs.cacheholdingdata020 = restore_u32();
                                for (int i = 0; i < CPU_PIPELINE_MAX; i++)
                                        regs.prefetch040[i] = restore_u32();
+                               if (flags & 0x4000000) {
+                                       for (int i = 0; i < (model == 68060 ? CACHESETS060 : CACHESETS040); i++) {
+                                               for (int j = 0; j < CACHELINES040; j++) {
+                                                       struct cache040 *c = &dcaches040[i];
+                                                       c->data[j][0] = restore_u32();
+                                                       c->data[j][1] = restore_u32();
+                                                       c->data[j][2] = restore_u32();
+                                                       c->data[j][3] = restore_u32();
+                                                       c->tag[j] = restore_u32();
+                                                       uae_u16 v = restore_u16();
+                                                       c->valid[j] = (v & 1) != 0;
+                                                       c->dirty[j][0] = (v & 0x10) != 0;
+                                                       c->dirty[j][1] = (v & 0x20) != 0;
+                                                       c->dirty[j][2] = (v & 0x40) != 0;
+                                                       c->dirty[j][3] = (v & 0x80) != 0;
+                                                       c->gdirty[j] = c->dirty[j][0] || c->dirty[j][1] || c->dirty[j][2] || c->dirty[j][3];
+                                               }
+                                       }
+                               }
                        }
                }
                if (model >= 68020) {
@@ -7873,19 +8126,37 @@ uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
        } else if (model >= 68040) {
                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]);
-                               save_u32(icaches040[i].data[j][2]);
-                               save_u32(icaches040[i].data[j][3]);
-                               save_u32(icaches040[i].tag[j]);
-                               save_u16(icaches040[i].valid[j] ? 1 : 0);
+                               struct cache040 *c = &icaches040[i];
+                               save_u32(c->data[j][0]);
+                               save_u32(c->data[j][1]);
+                               save_u32(c->data[j][2]);
+                               save_u32(c->data[j][3]);
+                               save_u32(c->tag[j]);
+                               save_u16(c->valid[j] ? 1 : 0);
                        }
                }
                save_u32(regs.prefetch020addr);
                save_u32(regs.cacheholdingaddr020);
                save_u32(regs.cacheholdingdata020);
-               for (int i = 0; i < CPU_PIPELINE_MAX; i++)
+               for (int i = 0; i < CPU_PIPELINE_MAX; i++) {
                        save_u32(regs.prefetch040[i]);
+               }
+               for (int i = 0; i < (model == 68060 ? CACHESETS060 : CACHESETS040); i++) {
+                       for (int j = 0; j < CACHELINES040; j++) {
+                               struct cache040 *c = &dcaches040[i];
+                               save_u32(c->data[j][0]);
+                               save_u32(c->data[j][1]);
+                               save_u32(c->data[j][2]);
+                               save_u32(c->data[j][3]);
+                               save_u32(c->tag[j]);
+                               uae_u16 v = c->valid[j] ? 1 : 0;
+                               v |= c->dirty[j][0] ? 0x10 : 0;
+                               v |= c->dirty[j][1] ? 0x20 : 0;
+                               v |= c->dirty[j][2] ? 0x40 : 0;
+                               v |= c->dirty[j][3] ? 0x80 : 0;
+                               save_u16(v);
+                       }
+               }
        }
        if (currprefs.cpu_model >= 68020) {
                save_u32 (0); //save_u32 (regs.ce020memcycles);
@@ -8878,16 +9149,23 @@ static void write_dcache030x(uaecptr addr, uae_u32 val, uae_u32 size, uae_u32 fc
        }
 }
 
-void write_dcache030(uaecptr addr, uae_u32 v, uae_u32 size, uae_u32 fc)
+void write_dcache030_bput(uaecptr addr, uae_u32 v,uae_u32 fc)
 {
        regs.fc030 = fc;
-       if (size == 2)
-               dcache030_lput(addr, v);
-       else if (size == 1)
-               dcache030_wput(addr, v);
-       else
-               dcache030_bput(addr, v);
-       write_dcache030x(addr, v, size, fc);
+       dcache_bput(addr, v);
+       write_dcache030x(addr, v, 0, fc);
+}
+void write_dcache030_wput(uaecptr addr, uae_u32 v,uae_u32 fc)
+{
+       regs.fc030 = fc;
+       dcache_wput(addr, v);
+       write_dcache030x(addr, v, 1, fc);
+}
+void write_dcache030_lput(uaecptr addr, uae_u32 v,uae_u32 fc)
+{
+       regs.fc030 = fc;
+       dcache_lput(addr, v);
+       write_dcache030x(addr, v, 2, fc);
 }
 
 static void dcache030_maybe_burst(uaecptr addr, struct cache030 *c, int lws)
@@ -8907,7 +9185,7 @@ static void dcache030_maybe_burst(uaecptr addr, struct cache030 *c, int lws)
                                for (int j = 0; j < 3; j++) {
                                        i++;
                                        i &= 3;
-                                       c->data[i] = dcache030_lget (baddr + i * 4);
+                                       c->data[i] = dcache_lget (baddr + i * 4);
                                        c->valid[i] = true;
                                }
                        } CATCH (prb) {
@@ -8917,7 +9195,7 @@ static void dcache030_maybe_burst(uaecptr addr, struct cache030 *c, int lws)
                        for (int j = 0; j < 3; j++) {
                                i++;
                                i &= 3;
-                               c->data[i] = dcache030_lget (baddr + i * 4);
+                               c->data[i] = dcache_lget (baddr + i * 4);
                                c->valid[i] = true;
                        }
                        if (currprefs.cpu_cycle_exact)
@@ -8929,23 +9207,6 @@ static void dcache030_maybe_burst(uaecptr addr, struct cache030 *c, int lws)
        }
 }
 
-#if 0
-static void uae_cache_check(uaecptr addr, uae_u32 *v, struct cache030 *c, int lws, int size)
-{
-       if (uae_boot_rom_type <= 0)
-               return;
-       // this check and fix is needed for UAE filesystem handler because it runs in host side and in
-       // separate thread. No way to access via cache without locking that would cause major slowdown
-       // and unneeded complexity
-       uae_u32 tv = get_long(addr);
-       if (tv != *v) {
-               write_log(_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
-                       size, addr, tv, v, c->tag, lws, M68K_GETPC);
-               *v = tv;
-       }
-}
-#endif
-
 uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc)
 {
        uae_u32 addr_o = addr;
@@ -8966,10 +9227,10 @@ uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc)
                if (!c1->valid[lws1] || c1->tag != tag1 || c1->fc != fc) {
                        // MMU validate address, returns zero if valid but uncacheable
                        // throws bus error if invalid
-                       uae_u8 cs = dcache030_check(addr_o, false, size);
+                       uae_u8 cs = dcache_check(addr_o, false, size);
                        if (!(cs & CACHE_ENABLE_DATA))
                                goto end;
-                       v1 = dcache030_lget(addr);
+                       v1 = dcache_lget(addr);
                        update_dcache030 (c1, v1, tag1, fc, lws1);
                        if ((cs & CACHE_ENABLE_DATA_BURST) && (regs.cacr & 0x1100) == 0x1100)
                                dcache030_maybe_burst(addr, c1, lws1);
@@ -8979,9 +9240,6 @@ uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc)
                } else {
                        // Cache hit, inhibited caching do not prevent read hits.
                        v1 = c1->data[lws1];
-#if 0
-                       uae_cache_check(addr, &v1, c1, lws1, size);
-#endif
                }
 
                // only one long fetch needed?
@@ -8998,10 +9256,10 @@ 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) {
-                       uae_u8 cs = dcache030_check(addr, false, 2);
+                       uae_u8 cs = dcache_check(addr, false, 2);
                        if (!(cs & CACHE_ENABLE_DATA))
                                goto end;
-                       v2 = dcache030_lget(addr);
+                       v2 = dcache_lget(addr);
                        update_dcache030 (c2, v2, tag2, fc, lws2);
                        if ((cs & CACHE_ENABLE_DATA_BURST) && (regs.cacr & 0x1100) == 0x1100)
                                dcache030_maybe_burst(addr, c2, lws2);
@@ -9010,9 +9268,6 @@ uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc)
 #endif
                } else {
                        v2 = c2->data[lws2];
-#if 0
-                       uae_cache_check(addr, &v2, c2, lws2, size);
-#endif
                }
 
                uae_u64 v64 = ((uae_u64)v1 << 32) | v2;
@@ -9028,31 +9283,68 @@ uae_u32 read_dcache030 (uaecptr addr, uae_u32 size, uae_u32 fc)
 end:
        // read from memory, data cache is disabled or inhibited.
        if (size == 2)
-               return dcache030_lget (addr_o);
+               return dcache_lget (addr_o);
        else if (size == 1)
-               return dcache030_wget (addr_o);
+               return dcache_wget (addr_o);
        else
-               return dcache030_bget (addr_o);
+               return dcache_bget (addr_o);
+}
+uae_u32 read_dcache030_bget(uaecptr addr, uae_u32 fc)
+{
+       return read_dcache030(addr, 0, fc);
+}
+uae_u32 read_dcache030_wget(uaecptr addr, uae_u32 fc)
+{
+       return read_dcache030(addr, 1, fc);
+}
+uae_u32 read_dcache030_lget(uaecptr addr, uae_u32 fc)
+{
+       return read_dcache030(addr, 2, fc);
 }
 
-uae_u32 read_dcache030_mmu(uaecptr addr, uae_u32 size)
+uae_u32 read_dcache030_mmu_bget(uaecptr addr)
+{
+       return read_dcache030_bget(addr, (regs.s ? 4 : 0) | 1);
+}
+uae_u32 read_dcache030_mmu_wget(uaecptr addr)
+{
+       return read_dcache030_wget(addr, (regs.s ? 4 : 0) | 1);
+}
+uae_u32 read_dcache030_mmu_lget(uaecptr addr)
+{
+       return read_dcache030_lget(addr, (regs.s ? 4 : 0) | 1);
+}
+void write_dcache030_mmu_bput(uaecptr addr, uae_u32 val)
+{
+       write_dcache030_bput(addr, val, (regs.s ? 4 : 0) | 1);
+}
+void write_dcache030_mmu_wput(uaecptr addr, uae_u32 val)
 {
-       return read_dcache030(addr, size, (regs.s ? 4 : 0) | 1);
+       write_dcache030_wput(addr, val, (regs.s ? 4 : 0) | 1);
 }
-void write_dcache030_mmu(uaecptr addr, uae_u32 val, uae_u32 size)
+void write_dcache030_mmu_lput(uaecptr addr, uae_u32 val)
 {
-       write_dcache030(addr, val, size, (regs.s ? 4 : 0) | 1);
+       write_dcache030_lput(addr, val, (regs.s ? 4 : 0) | 1);
 }
 
 uae_u32 read_dcache030_lrmw_mmu(uaecptr addr, uae_u32 size)
 {
        mmu030_cache_state = CACHE_DISABLE_MMU;
-       return read_dcache030(addr, size, (regs.s ? 4 : 0) | 1);
+       if (size == 0)
+               return read_dcache030_bget(addr, (regs.s ? 4 : 0) | 1);
+       if (size == 1)
+               return read_dcache030_wget(addr, (regs.s ? 4 : 0) | 1);
+       return read_dcache030_lget(addr, (regs.s ? 4 : 0) | 1);
 }
 void write_dcache030_lrmw_mmu(uaecptr addr, uae_u32 val, uae_u32 size)
 {
        mmu030_cache_state = CACHE_DISABLE_MMU;
-       write_dcache030(addr, val, size, (regs.s ? 4 : 0) | 1);
+       if (size == 0)
+               write_dcache030_bput(addr, val, (regs.s ? 4 : 0) | 1);
+       else if (size == 1)
+               write_dcache030_wput(addr, val, (regs.s ? 4 : 0) | 1);
+       else
+               write_dcache030_lput(addr, val, (regs.s ? 4 : 0) | 1);
 }
 
 static void do_access_or_bus_error(uaecptr pc, uaecptr pcnow)
@@ -9168,47 +9460,52 @@ uae_u32 fill_icache040(uae_u32 addr)
        uae_u32 tag, addr2;
        struct cache040 *c;
        int line;
-       uae_u8 cm = CACHE_ENABLE_ALL;
-       static int lastline; 
 
        addr2 = addr & ~15;
        lws = (addr >> 2) & 3;
 
-       if (regs.prefetch020addr == addr2)
+       if (regs.prefetch020addr == addr2) {
                return regs.prefetch040[lws];
+       }
 
        if (regs.cacr & 0x8000) {
 
-               index = (addr >> 4) & (cachesets04060minus1);
-               tag = regs.s | (addr & ~((cachesets04060 << 4) - 1));
+               if (!(ce_cachable[addr >> 16] & CACHE_ENABLE_INS))
+                       mmu_cache_state = CACHE_DISABLE_MMU;
+
+               index = (addr >> 4) & cacheisets04060mask;
+               tag = addr & cacheitag04060mask;
                c = &icaches040[index];
                for (int i = 0; i < CACHELINES040; i++) {
-                       if (c->valid[lastline] && c->tag[lastline] == tag) {
+                       if (c->valid[cache_lastline] && c->tag[cache_lastline] == tag) {
                                // cache hit
-                               if (!(cm & CACHE_ENABLE_INS)) {
-                                       c->valid[lastline] = false;
+                               if (!(mmu_cache_state & CACHE_ENABLE_INS) || (mmu_cache_state & CACHE_DISABLE_MMU)) {
+                                       c->valid[cache_lastline] = false;
                                        goto end;
                                }
-                               icachelinecnt++;
-                               x_do_cycles(1 * cpucycleunit);
-                               return c->data[lastline][lws];
+                               if ((lws & 1) != icachehalfline) {
+                                       icachehalfline ^= 1;
+                                       icachelinecnt++;
+                               }
+                               return c->data[cache_lastline][lws];
                        }
-                       lastline++;
-                       lastline &= (CACHELINES040 - 1);
+                       cache_lastline++;
+                       cache_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))
+               if (!(mmu_cache_state & CACHE_ENABLE_INS) || (mmu_cache_state & CACHE_DISABLE_MMU))
+                       goto end;
+               if (regs.cacr & 0x00004000) // 68060 NAI
                        goto end;
-
                if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
-                       line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
+                       line = icachelinecnt & (CACHELINES040 - 1);
+                       icachehalfline = (lws & 1) ? 0 : 1;
                } else {
                        for (line = 0; line < CACHELINES040; line++) {
                                if (c->valid[line] == false)
@@ -9221,8 +9518,10 @@ uae_u32 fill_icache040(uae_u32 addr)
                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);
+               if ((lws & 1) != icachehalfline) {
+                       icachehalfline ^= 1;
+                       icachelinecnt++;
+               }
                return c->data[line][lws];
 
        }
@@ -9235,124 +9534,406 @@ end:
        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.prefetch040[lws];
 }
 
-#if 0
-static bool is_dcache040(uae_u32 addr)
+STATIC_INLINE void do_cycles_c040_mem (int clocks, uae_u32 val)
 {
-       int index, i, lws;
-       uae_u32 tag;
-       struct cache040 *c;
+       x_do_cycles_post (clocks * cpucycleunit, val);
+}
 
-       addr &= ~15;
-       index = (addr >> 4) & (CACHESETS040 - 1);
-       tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
-       lws = (addr >> 2) & 3;
-       c = &dcaches040[index];
-       for (i = 0; i < CACHELINES040; i++) {
-               if (c->valid[i] && c->tag[i] == tag) {
-                       return true;
+uae_u32 mem_access_delay_longi_read_c040 (uaecptr addr)
+{
+       uae_u32 v;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+               v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
+               v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
+               break;
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) != 0) {
+                       v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
+                       v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
+               } else {
+                       v = wait_cpu_cycle_read_ce020 (addr, -1);
+               }
+               break;
+       case CE_MEMBANK_FAST16:
+               v = get_longi (addr);
+               do_cycles_c040_mem(1, v);
+               break;
+       case CE_MEMBANK_FAST32:
+               v = get_longi (addr);
+               break;
+       default:
+               v = get_longi (addr);
+               break;
+       }
+       return v;
+}
+uae_u32 mem_access_delay_long_read_c040 (uaecptr addr)
+{
+       uae_u32 v;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+               v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
+               v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
+               break;
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) != 0) {
+                       v  = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
+                       v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) <<  0;
+               } else {
+                       v = wait_cpu_cycle_read_ce020 (addr, -1);
                }
+               break;
+       case CE_MEMBANK_FAST16:
+               v = get_long (addr);
+               do_cycles_c040_mem(1, v);
+               break;
+       case CE_MEMBANK_FAST32:
+               v = get_long (addr);
+               break;
+       default:
+               v = get_long (addr);
+               break;
        }
-       return false;
+       return v;
 }
 
-uae_u32 read_dcache040(uae_u32 addr)
+uae_u32 mem_access_delay_word_read_c040 (uaecptr addr)
 {
-       int index, i, lws;
-       uae_u32 tag;
-       struct cache040 *c;
-       int line;
+       uae_u32 v;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) == 3) {
+                       v  = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
+                       v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
+               } else {
+                       v = wait_cpu_cycle_read_ce020 (addr, 1);
+               }
+               break;
+       case CE_MEMBANK_FAST16:
+               v = get_word (addr);
+               do_cycles_c040_mem (2, v);
+               break;
+       case CE_MEMBANK_FAST32:
+               v = get_word (addr);
+                break;
+       default:
+                v = get_word (addr);
+               break;
+       }
+       return v;
+}
 
-       addr &= ~15;
-       index = (addr >> 4) & (CACHESETS040 - 1);
-       tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
-       lws = (addr >> 2) & 3;
-       c = &dcaches040[index];
-       for (i = 0; i < CACHELINES040; i++) {
-               if (c->valid[i] && c->tag[i] == tag) {
-                       // cache hit
-                       dcachelinecnt++;
-                       return c->data[i][lws];
+uae_u32 mem_access_delay_byte_read_c040 (uaecptr addr)
+{
+       uae_u32 v;
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
+               v = wait_cpu_cycle_read_ce020 (addr, 0);
+               break;
+       case CE_MEMBANK_FAST16:
+               v = get_byte (addr);
+               do_cycles_c040_mem (1, v);
+               break;
+       case CE_MEMBANK_FAST32:
+               v = get_byte (addr);
+               break;
+       default:
+               v = get_byte (addr);
+               break;
+       }
+       return v;
+}
+
+void mem_access_delay_byte_write_c040 (uaecptr addr, uae_u32 v)
+{
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
+               wait_cpu_cycle_write_ce020 (addr, 0, v);
+               break;
+       case CE_MEMBANK_FAST16:
+               put_byte (addr, v);
+               do_cycles_c040_mem (1, v);
+               break;
+       case CE_MEMBANK_FAST32:
+               put_byte (addr, v);
+               break;
+       default:
+               put_byte (addr, v);
+       break;
+       }
+}
+
+void mem_access_delay_word_write_c040 (uaecptr addr, uae_u32 v)
+{
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) == 3) {
+                       wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
+                       wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
+               } else {
+                       wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
+               }
+               break;
+       case CE_MEMBANK_FAST16:
+               put_word (addr, v);
+               if ((addr & 3) == 3)
+                       do_cycles_c040_mem(2, v);
+               else
+                       do_cycles_c040_mem(1, v);
+               break;
+       case CE_MEMBANK_FAST32:
+               put_word (addr, v);
+               break;
+       default:
+               put_word (addr, v);
+       break;
+       }
+}
+
+void mem_access_delay_long_write_c040 (uaecptr addr, uae_u32 v)
+{
+       switch (ce_banktype[addr >> 16])
+       {
+       case CE_MEMBANK_CHIP16:
+               wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
+               wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
+               break;
+       case CE_MEMBANK_CHIP32:
+               if ((addr & 3) == 3) {
+                       wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
+                       wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >>  0) & 0xffff);
+               } else {
+                       wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
                }
+               break;
+       case CE_MEMBANK_FAST16:
+               put_long (addr, v);
+               do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               break;
+       case CE_MEMBANK_FAST32:
+               put_long (addr, v);
+               break;
+       default:
+               put_long (addr, v);
+               break;
        }
-       // cache miss
-       if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
-               line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
-               for (i = 0; i < 4; i++) {
-                       if (c->dirty[line][i]) {
-                               c->dirty[line][i] = false;
-                               mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
-                       }
+}
+
+static uae_u32 dcache040_get_data(uaecptr addr, struct cache040 *c, int line, int size)
+{
+       static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
+       int offset = (addr & 15) * 8;
+       int offset32 = offset & 31;
+       int slot = offset / 32;
+       int width = 8 << size;
+       uae_u32 vv;
+
+       if (offset32 + width <= 32) {
+               uae_u32 v = c->data[line][slot];
+               v >>= 32 - (offset32 + width);
+               v &= mask[size];
+               vv = v;
+       } else {
+#if VALIDATE_68040_DATACACHE
+               if (slot >= 3) {
+                       write_log(_T("invalid dcache040_get_data!\n"));
+                       return 0;
                }
+#endif
+               uae_u64 v = c->data[line][slot];
+               v <<= 32;
+               v |= c->data[line][slot + 1];
+               v >>= 64 - (offset32 + width);
+               vv = v & mask[size];
        }
-       else {
+       return vv;
+}
+
+static void dcache040_update(uaecptr addr, struct cache040 *c, int line, uae_u32 val, int size)
+{
+       static const uae_u64 mask64[3] = { 0xff, 0xffff, 0xffffffff };
+       static const uae_u32 mask32[3] = { 0xff, 0xffff, 0xffffffff };
+       int offset = (addr & 15) * 8;
+       int offset32 = offset & 31;
+       int slot = offset / 32;
+       int width = 8 << size;
+
+#if VALIDATE_68040_DATACACHE > 1
+       validate_dcache040();
+#endif
+
+       if (offset32 + width <= 32) {
+               int shift = 32 - (offset32 + width);
+               uae_u32 v = c->data[line][slot];
+               v &= ~(mask32[size] << shift);
+               v |= val << shift;
+               c->data[line][slot] = v;
+               c->dirty[line][slot] = true;
+       } else {
+#if VALIDATE_68040_DATACACHE
+               if (slot >= 3) {
+                       write_log(_T("invalid dcache040_update!\n"));
+                       return;
+               }
+#endif
+               int shift = 64 - (offset32 + width);
+               uae_u64 v = c->data[line][slot];
+               v <<= 32;
+               v |= c->data[line][slot + 1];
+               v &= ~(mask64[size] << shift);
+               v |= ((uae_u64)val) << shift;
+               c->data[line][slot] = v >> 32;
+               c->dirty[line][slot] = true;
+               c->data[line][slot + 1] = (uae_u32)v;
+               c->dirty[line][slot + 1] = true;
+       }
+       c->gdirty[line] = true;
+}
+
+static int dcache040_fill_line(int index, uae_u32 tag, uaecptr addr)
+{
+       // cache miss
+       struct cache040 *c = &dcaches040[index];
+       int line;
+       if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
+               // all lines allocated, choose one, push and invalidate.
+               line = dcachelinecnt & (CACHELINES040 - 1);
+               dcachelinecnt++;
+               dcache040_push_line(index, line, false, true);
+       } else {
+               // at least one invalid
                for (line = 0; line < CACHELINES040; line++) {
                        if (c->valid[line] == false)
                                break;
                }
        }
        c->tag[line] = tag;
+       c->dirty[line][0] = false;
+       c->dirty[line][1] = false;
+       c->dirty[line][2] = false;
+       c->dirty[line][3] = false;
+       c->gdirty[line] = false;
+       c->data[line][0] = dcache_lget(addr + 0);
+       c->data[line][1] = dcache_lget(addr + 4);
+       c->data[line][2] = dcache_lget(addr + 8);
+       c->data[line][3] = dcache_lget(addr + 12);
        c->valid[line] = true;
-       c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
-       c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
-       c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
-       c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
-       regs.cacheholdingaddr020 = addr;
+       return line;
 }
 
-void write_dcache040(uae_u32 addr, uae_u32 val)
+static uae_u32 read_dcache040(uae_u32 addr, int size, uae_u32 (*fetch)(uaecptr))
 {
-       int index, i, lws;
+       int index;
        uae_u32 tag;
        struct cache040 *c;
        int line;
+       uae_u32 addr_o = addr;
+
+       if (!(regs.cacr & 0x80000000))
+               goto nocache;
+
+#if VALIDATE_68040_DATACACHE > 1
+       validate_dcache040();
+#endif
+
+       // Simple because 68040+ caches physical addresses (68030 caches logical addresses)
+       if (!(ce_cachable[addr >> 16] & CACHE_ENABLE_DATA))
+               mmu_cache_state = CACHE_DISABLE_MMU;
 
        addr &= ~15;
-       index = (addr >> 4) & (CACHESETS040 - 1);
-       tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
-       lws = (addr >> 2) & 3;
+       index = (addr >> 4) & cachedsets04060mask;
+       tag = addr & cachedtag04060mask;
        c = &dcaches040[index];
-       for (i = 0; i < CACHELINES040; i++) {
-               if (c->valid[i] && c->tag[i] == tag) {
+       for (line = 0; line < CACHELINES040; line++) {
+               if (c->valid[line] && c->tag[line] == tag) {
                        // cache hit
                        dcachelinecnt++;
-                       c->data[i][lws] = val;
-                       mem_access_delay_long_write_ce020(addr + i * 4, c->data[i][lws]);
-                       //c->dirty[i][lws] = true;
+                       // Cache hit but MMU disabled: do not cache, push and invalidate possible existing line
+                       if (mmu_cache_state & CACHE_DISABLE_MMU) {
+                               dcache040_push_line(index, line, false, true);
+                               goto nocache;
+                       }
+                       return dcache040_get_data(addr_o, c, line, size);
                }
        }
-#if 0
-       // cache miss
-       if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
-               line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
-               for (i = 0; i < 4; i++) {
-                       if (c->dirty[line][i]) {
-                               c->dirty[line][i] = false;
-                               mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
+       // Cache miss
+       // 040+ always caches whole line
+       if ((mmu_cache_state & CACHE_DISABLE_MMU) || !(mmu_cache_state & CACHE_ENABLE_DATA) || (mmu_cache_state & CACHE_DISABLE_ALLOCATE) || (regs.cacr & 0x400000000)) {
+nocache:
+               return fetch(addr_o);
+       }
+       // Allocate new cache line, return requested data.
+       line = dcache040_fill_line(index, tag, addr);
+       return dcache040_get_data(addr_o, c, line, size);
+}
+
+static void write_dcache040(uae_u32 addr, uae_u32 val, int size, void (*store)(uaecptr, uae_u32))
+{
+       static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
+       int index;
+       uae_u32 tag;
+       struct cache040 *c;
+       int line;
+       uae_u32 addr_o = addr;
+
+       val &= mask[size];
+
+       if (!(regs.cacr & 0x80000000))
+               goto nocache;
+
+       if (!(ce_cachable[addr >> 16] & CACHE_ENABLE_DATA))
+               mmu_cache_state = CACHE_DISABLE_MMU;
+
+       addr &= ~15;
+       index = (addr >> 4) & cachedsets04060mask;
+       tag = addr & cachedtag04060mask;
+       c = &dcaches040[index];
+       for (line = 0; line < CACHELINES040; line++) {
+               if (c->valid[line] && c->tag[line] == tag) {
+                       // cache hit
+                       dcachelinecnt++;
+                       // Cache hit but MMU disabled: do not cache, push and invalidate possible existing line
+                       if (mmu_cache_state & CACHE_DISABLE_MMU) {
+                               dcache040_push_line(index, line, false, true);
+                               goto nocache;
+                       }
+                       dcache040_update(addr_o, c, line, val, size);
+                       // If not copyback mode: push modifications immediately (write-through)
+                       if (!(mmu_cache_state & CACHE_ENABLE_COPYBACK) || DISABLE_68040_COPYBACK) {
+                               dcache040_push_line(index, line, true, false);
                        }
+                       return;
                }
        }
-       else {
-               for (line = 0; line < CACHELINES040; line++) {
-                       if (c->valid[line] == false)
-                               break;
-               }
+       // Cache miss
+       // 040+ always caches whole line
+       // Writes misses in write-through mode don't allocate new cache lines
+       if (!(mmu_cache_state & CACHE_ENABLE_DATA) || (mmu_cache_state & CACHE_DISABLE_MMU) || (mmu_cache_state & CACHE_DISABLE_ALLOCATE) || !(mmu_cache_state & CACHE_ENABLE_COPYBACK) || (regs.cacr & 0x400000000)) {
+nocache:
+               store(addr_o, val);
+               return;
+       }
+       // Allocate new cache line and update it with new data.
+       line = dcache040_fill_line(index, tag, addr);
+       dcache040_update(addr_o, c, line, val, size);
+       if (DISABLE_68040_COPYBACK) {
+               dcache040_push_line(index, line, true, false);
        }
-       c->tag[line] = tag;
-       c->valid[line] = true;
-       c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
-       c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
-       c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
-       c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
-       c->data[line][lws] = val;
-       c->dirty[line][lws] = true;
-#endif
 }
-#endif
 
 // really unoptimized
 uae_u32 get_word_icache040(uaecptr addr)
@@ -9378,147 +9959,67 @@ uae_u32 get_iword_cache_040(int o)
        return get_word_icache040(m68k_getpci() + o);
 }
 
-STATIC_INLINE bool nocache040(uaecptr addr)
-{
-       if (!currprefs.cpu_memory_cycle_exact)
-               return false;
-       if (!(regs.cacr & 0x80000000))
-               return true;
-       if (addr >= 0xd80000 && addr < 0xc00000)
-               return true;
-       if (addr >= 0xe80000 && addr < 0xf00000)
-               return true;
-       return false;
-}
-
 void put_long_cache_040(uaecptr addr, uae_u32 v)
 {
-#if 1
-       if (nocache040(addr))
-               mem_access_delay_long_write_ce020(addr, v);
-       else
-               put_long(addr, v);
-#else
-       if ((addr & 2) == 0) {
-               if (is_dcache040(addr))
-                       write_dcache040(addr, v);
-               else if (currprefs.cpu_memory_cycle_exact)
-                       mem_access_delay_long_write_ce020(addr, v);
-               else
-                       put_long(addr, v);
-       } else {
-               uae_u32 vp;
-               if (is_dcache040(addr)) {
-                       vp = read_dcache040(addr);
-                       vp &= 0xffff0000;
-                       vp |= v >> 16;
-                       write_dcache040(addr, vp);
-               } else if (currprefs.cpu_memory_cycle_exact) {
-                       mem_access_delay_word_write_ce020(addr + 0, v >> 16);
-               } else {
-                       put_word(addr + 0, v >> 16);
-               }
-               if (is_dcache040(addr + 4)) {
-                       vp = read_dcache040(addr + 4);
-                       vp &= 0x0000ffff;
-                       vp |= v << 16;
-                       write_dcache040(addr + 4, vp);
-               } else if (currprefs.cpu_memory_cycle_exact) {
-                       mem_access_delay_word_write_ce020(addr + 2, v);
-               } else {
-                       put_word(addr + 2, v);
-               }
+       int offset = addr & 15;
+       // access must not cross cachelines
+       if (offset < 13) {
+               write_dcache040(addr, v, 2, dcache_lput);
+       } else if (offset == 13 || offset == 15) {
+               write_dcache040(addr + 0, v >> 24, 0, dcache_bput);
+               write_dcache040(addr + 1, v >>  8, 1, dcache_wput);
+               write_dcache040(addr + 3, v >>  0, 0, dcache_bput);
+       } else if (offset == 14) {
+               write_dcache040(addr + 0, v >> 16, 1, dcache_wput);
+               write_dcache040(addr + 2, v >>  0, 1, dcache_wput);
        }
-#endif
 }
 void put_word_cache_040(uaecptr addr, uae_u32 v)
 {
-#if 1
-       if (nocache040(addr))
-               mem_access_delay_word_write_ce020(addr, v);
-       else
-               put_word(addr, v);
-#else
-       if (is_dcache040(addr)) {
-               uae_u32 vp;
-               vp = read_dcache040(addr);
-               if (addr & 2) {
-                       vp &= 0xffff0000;
-                       vp |= v & 0xffff;
-               } else {
-                       vp &= 0x0000ffff;
-                       vp |= v << 16;
-               }
-               write_dcache040(addr, vp);
-       } else if (currprefs.cpu_memory_cycle_exact) {
-               mem_access_delay_word_write_ce020(addr, v);
+       int offset = addr & 15;
+       if (offset < 15) {
+               write_dcache040(addr, v, 1, dcache_wput);
        } else {
-               put_word(addr, v);
+               write_dcache040(addr + 0, v >> 8, 0, dcache_bput);
+               write_dcache040(addr + 1, v >> 0, 0, dcache_bput);
        }
-#endif
 }
 void put_byte_cache_040(uaecptr addr, uae_u32 v)
 {
-#if 1
-       if (nocache040(addr))
-               mem_access_delay_byte_write_ce020(addr, v);
-       else
-               put_byte(addr, v);
-#else
-       if (is_dcache040(addr)) {
-               uae_u32 vp;
-               uae_u32 mask = 0xff000000 >> (addr & 3);
-               vp = read_dcache040(addr);
-               vp &= ~mask;
-               vp |= (v << (3 - (addr & 3))) & mask;
-               write_dcache040(addr, vp);
-       } else if (currprefs.cpu_memory_cycle_exact) {
-               mem_access_delay_byte_write_ce020(addr, v);
-       } else {
-               put_byte(addr, v);
-       }
-#endif
+       return write_dcache040(addr, v, 0, dcache_bput);
 }
 
 uae_u32 get_long_cache_040(uaecptr addr)
 {
-#if 1
-       if (nocache040(addr))
-               return mem_access_delay_long_read_ce020(addr);
-       else
-               return get_long(addr);
-#else
-       uae_u32 v1, v2;
-       v1 = read_dcache040(addr);
-       if ((addr & 2) == 0)
-               return v1;
-       v2 = read_dcache040(addr + 4);
-       return (v2 >> 16) | (v1 << 16);
-#endif
+       uae_u32 v;
+       int offset = addr & 15;
+       if (offset < 13) {
+               v = read_dcache040(addr, 2, dcache_lget);
+       } else if (offset == 13 || offset == 15) {
+               v =  read_dcache040(addr + 0, 0, dcache_bget) << 24;
+               v |= read_dcache040(addr + 1, 1, dcache_wget) <<  8;
+               v |= read_dcache040(addr + 3, 0, dcache_bget) <<  0;
+       } else if (offset == 14) {
+               v =  read_dcache040(addr + 0, 1, dcache_wget) << 16;
+               v |= read_dcache040(addr + 2, 1, dcache_wget) <<  0;
+       }
+       return v;
 }
 uae_u32 get_word_cache_040(uaecptr addr)
 {
-#if 1
-       if (nocache040(addr))
-               return mem_access_delay_word_read_ce020(addr);
-       else
-               return get_word(addr);
-#else
-       uae_u32 v = read_dcache040(addr);
-       return v >> ((addr & 2) ? 0 : 16);
-#endif
+       uae_u32 v;
+       int offset = addr & 15;
+       if (offset < 15) {
+               v = read_dcache040(addr, 1, dcache_wget);
+       } else {
+               v =  read_dcache040(addr + 0, 0, dcache_bget) << 8;
+               v |= read_dcache040(addr + 1, 0, dcache_bget) << 0;
+       }
+       return v;
 }
 uae_u32 get_byte_cache_040(uaecptr addr)
 {
-#if 1
-       if (nocache040(addr))
-               return mem_access_delay_byte_read_ce020(addr);
-       else
-               return get_byte(addr);
-#else
-       uae_u32 v = read_dcache040(addr);
-       return v >> (8 * (3 - (addr & 3)));
-#endif
+       return read_dcache040(addr, 0, dcache_bget);
 }
 uae_u32 next_iword_cache040(void)
 {
@@ -9533,20 +10034,6 @@ uae_u32 next_ilong_cache040(void)
        return r;
 }
 
-void flush_dcache (uaecptr addr, int size)
-{
-       if (!currprefs.cpu_memory_cycle_exact && !currprefs.cpu_compatible)
-               return;
-       if (currprefs.cpu_model >= 68030) {
-               for (int i = 0; i < CACHELINES030; i++) {
-                       dcaches030[i].valid[0] = 0;
-                       dcaches030[i].valid[1] = 0;
-                       dcaches030[i].valid[2] = 0;
-                       dcaches030[i].valid[3] = 0;
-               }
-       }
-}
-
 void check_t0_trace(void)
 {
        if (regs.t0 && currprefs.cpu_model >= 68020) {