]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68030 MMU + full prefetch pipeline, instruction and data cache emulation.
authorToni Wilen <twilen@winuae.net>
Thu, 27 Jul 2017 18:00:31 +0000 (21:00 +0300)
committerToni Wilen <twilen@winuae.net>
Thu, 27 Jul 2017 18:00:31 +0000 (21:00 +0300)
cpummu30.cpp
gencpu.cpp
include/cpu_prefetch.h
include/cpummu030.h
include/newcpu.h
newcpu.cpp
od-win32/sysconfig.h

index e953e0cb544b927866d75cadabaa33d290d7aeba..4e2fab6f64e27290fdf744babf047fcaf3d0be0b 100644 (file)
@@ -34,6 +34,7 @@
 #include "options.h"
 #include "memory.h"
 #include "newcpu.h"
+#include "debug.h"
 #include "cpummu030.h"
 
 #define MMU030_OP_DBG_MSG 0
@@ -68,6 +69,7 @@ uae_u16 mmu030_state[3];
 uae_u32 mmu030_data_buffer;
 uae_u32 mmu030_disp_store[2];
 uae_u32 mmu030_fmovem_store[2];
+int mmu030_cache_inhibit;
 struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS];
 
 #if MMU_DPAGECACHE030
@@ -84,6 +86,8 @@ static struct mmufastcache030 atc_data_cache_write[MMUFASTCACHE_ENTRIES030];
 /* for debugging messages */
 char table_letter[4] = {'A','B','C','D'};
 
+static const uae_u32 mmu030_size[3] = { MMU030_SSW_SIZE_B, MMU030_SSW_SIZE_W, MMU030_SSW_SIZE_L };
+
 uae_u64 srp_030, crp_030;
 uae_u32 tt0_030, tt1_030, tc_030;
 uae_u16 mmusr_030;
@@ -145,6 +149,7 @@ static struct {
     uae_u16 status;
 
 #if MMU_IPAGECACHE030
+       int mmu030_cache_inhibit;
 #if MMU_DIRECT_ACCESS
        uae_u8 *mmu030_last_physical_address_real;
 #else
@@ -311,29 +316,29 @@ bool mmu_op30_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
 #if MMU030_OP_DBG_MSG
     switch (preg) {
         case 0x10:
-            write_log(_T("PMOVE: %s TC %08X\n"), rw?"read":"write",
-                      rw?tc_030:x_get_long(extra));
+            write_log(_T("PMOVE: %s TC %08X\n"), rw ? _T("read"):  _T("write"),
+                      rw ? tc_030 : x_get_long(extra));
             break;
         case 0x12:
-            write_log(_T("PMOVE: %s SRP %08X%08X\n"), rw?"read":"write",
+            write_log(_T("PMOVE: %s SRP %08X%08X\n"), rw ? _T("read") : _T("write"),
                       rw?(uae_u32)(srp_030>>32)&0xFFFFFFFF:x_get_long(extra),
                       rw?(uae_u32)srp_030&0xFFFFFFFF:x_get_long(extra+4));
             break;
         case 0x13:
-            write_log(_T("PMOVE: %s CRP %08X%08X\n"), rw?"read":"write",
+            write_log(_T("PMOVE: %s CRP %08X%08X\n"), rw ? _T("read") : _T("write"),
                       rw?(uae_u32)(crp_030>>32)&0xFFFFFFFF:x_get_long(extra),
                       rw?(uae_u32)crp_030&0xFFFFFFFF:x_get_long(extra+4));
             break;
         case 0x18:
-            write_log(_T("PMOVE: %s MMUSR %04X\n"), rw?"read":"write",
+            write_log(_T("PMOVE: %s MMUSR %04X\n"), rw ? _T("read") : _T("write"),
                       rw?mmusr_030:x_get_word(extra));
             break;
         case 0x02:
-            write_log(_T("PMOVE: %s TT0 %08X\n"), rw?"read":"write",
+            write_log(_T("PMOVE: %s TT0 %08X\n"), rw ? _T("read") : _T("write"),
                       rw?tt0_030:x_get_long(extra));
             break;
         case 0x03:
-            write_log(_T("PMOVE: %s TT1 %08X\n"), rw?"read":"write",
+            write_log(_T("PMOVE: %s TT1 %08X\n"), rw ? _T("read") : _T("write"),
                       rw?tt1_030:x_get_long(extra));
             break;
         default:
@@ -647,13 +652,12 @@ TT_info mmu030_decode_tt(uae_u32 TT) {
 static int mmu030_do_match_ttr(uae_u32 tt, TT_info comp, uaecptr addr, uae_u32 fc, bool write)
 {
        if (tt & TT_ENABLE)     {       /* transparent translation enabled */
-        
+
         /* Compare actual function code with function code base using mask */
         if ((comp.fc_base&comp.fc_mask)==(fc&comp.fc_mask)) {
-            
+
             /* Compare actual address with address base using mask */
             if ((comp.addr_base&comp.addr_mask)==(addr&comp.addr_mask)) {
-                
                 if (tt&TT_RWM) {  /* r/w field disabled */
                     return TT_OK_MATCH;
                 } else {
@@ -672,13 +676,12 @@ static int mmu030_do_match_ttr(uae_u32 tt, TT_info comp, uaecptr addr, uae_u32 f
 static int mmu030_do_match_lrmw_ttr(uae_u32 tt, TT_info comp, uaecptr addr, uae_u32 fc)
 {
        if ((tt & TT_ENABLE) && (tt & TT_RWM))  {       /* transparent translation enabled */
-        
+
         /* Compare actual function code with function code base using mask */
         if ((comp.fc_base&comp.fc_mask)==(fc&comp.fc_mask)) {
-            
+
             /* Compare actual address with address base using mask */
             if ((comp.addr_base&comp.addr_mask)==(addr&comp.addr_mask)) {
-                
                                return TT_OK_MATCH;
             }
                }
@@ -693,17 +696,15 @@ static int mmu030_match_ttr(uaecptr addr, uae_u32 fc, bool write)
 {
     int tt0, tt1;
 
-    bool cache_inhibit = false; /* TODO: pass to memory access function */
-    
     tt0 = mmu030_do_match_ttr(tt0_030, mmu030.transparent.tt0, addr, fc, write);
     if (tt0&TT_OK_MATCH) {
-        cache_inhibit = (tt0_030&TT_CI) ? true : false;
-    }
+               if (tt0_030&TT_CI)
+               mmu030_cache_inhibit = 1;
+       }
     tt1 = mmu030_do_match_ttr(tt1_030, mmu030.transparent.tt1, addr, fc, write);
     if (tt1&TT_OK_MATCH) {
-        if (!cache_inhibit) {
-            cache_inhibit = (tt1_030&TT_CI) ? true : false;
-        }
+               if (tt0_030&TT_CI)
+               mmu030_cache_inhibit = 1;
     }
     
     return (tt0|tt1);
@@ -785,6 +786,8 @@ static int mmu030_match_lrmw_ttr_access(uaecptr addr, uae_u32 fc)
 
 static void mmu030_do_fake_prefetch(void)
 {
+       if (currprefs.cpu_compatible)
+               return;
        // fetch next opcode before MMU state switches.
        // There are programs that do following:
        // - enable MMU
@@ -1700,9 +1703,29 @@ uae_u32 mmu030_ptest_table_search(uaecptr logical_addr, uae_u32 fc, bool write,
 #define ATC030_PHYS_CI  0x04000000
 #define ATC030_PHYS_BE  0x08000000
 
-void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc) {
+void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc)
+{
+       if (flags < 0) {
+               read = (regs.mmu_ssw & MMU030_SSW_RW) ? 1 : 0;
+               fc = regs.mmu_ssw & 7;
+               flags = regs.mmu_ssw & ~(MMU030_SSW_FC | MMU030_SSW_RC | MMU030_SSW_FB | MMU030_SSW_RB | MMU030_SSW_RW | 7);
+       }
        regs.mmu_fault_addr = addr;
-       regs.mmu_ssw = (fc & 1) ? MMU030_SSW_DF | (MMU030_SSW_DF << 1) : (MMU030_SSW_FB | MMU030_SSW_RB);
+       if (fc & 1) {
+               regs.mmu_ssw = MMU030_SSW_DF | (MMU030_SSW_DF << 1);
+       } else {
+               if (currprefs.cpu_compatible) {
+                       if (regs.prefetch020_valid[1] != 1 && regs.prefetch020_valid[2] == 1) {
+                               regs.mmu_ssw = MMU030_SSW_FC | MMU030_SSW_RC;
+                       } else if (regs.prefetch020_valid[2] != 1) {
+                               regs.mmu_ssw = MMU030_SSW_FB | MMU030_SSW_RB;
+                       } else {
+                               write_log(_T("mmu030_page_fault without invalid prefetch!\n"));
+                       }
+               } else {
+                       regs.mmu_ssw = MMU030_SSW_FB | MMU030_SSW_RB;
+               }
+       }
        regs.mmu_ssw |= read ? MMU030_SSW_RW : 0;
        regs.mmu_ssw |= flags;
        regs.mmu_ssw |= fc;
@@ -1713,9 +1736,6 @@ void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc) {
                addr, regs.mmu_ssw, read, (flags & MMU030_SSW_SIZE_B) ? 1 : (flags & MMU030_SSW_SIZE_W) ? 2 : 4, fc,
                regs.instruction_pc, (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val, mmu030_opcode & 0xffff);
 #endif
-       
-//     extern void activate_debugger(void);
-//     activate_debugger ();
 
        THROW(2);
 }
@@ -1754,12 +1774,14 @@ static uaecptr mmu030_put_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) {
               l, physical_addr, page_index);
 #endif
     
-    if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) {
+       if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) {
         mmu030_page_fault(addr, false, MMU030_SSW_SIZE_B, fc);
         return 0;
     }
 
-       mmu030_add_data_write_cache(addr, physical_addr, fc);
+       mmu030_cache_inhibit = mmu030.atc[l].physical.cache_inhibit;
+
+       mmu030_add_data_write_cache(addr, physical_addr, fc);
 
        return physical_addr + page_index;
 }
@@ -1774,11 +1796,13 @@ static uaecptr mmu030_get_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) {
               physical_addr, page_index);
 #endif
    
-    if (mmu030.atc[l].physical.bus_error) {
+       if (mmu030.atc[l].physical.bus_error) {
         mmu030_page_fault(addr, true, size, fc);
         return 0;
     }
 
+       mmu030_cache_inhibit = mmu030.atc[l].physical.cache_inhibit;
+       
        mmu030_add_data_read_cache(addr, physical_addr, fc);
 
        return physical_addr + page_index;
@@ -1800,6 +1824,7 @@ static uaecptr mmu030_get_i_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) {
        }
 
 #if MMU_IPAGECACHE030
+       mmu030.mmu030_cache_inhibit = mmu030.atc[l].physical.cache_inhibit;
 #if MMU_DIRECT_ACCESS
        mmu030.mmu030_last_physical_address_real = get_real_address(physical_addr);
 #else
@@ -1808,6 +1833,8 @@ static uaecptr mmu030_get_i_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) {
        mmu030.mmu030_last_logical_address = (addr & mmu030.translation.page.imask) | fc;
 #endif
 
+       mmu030_cache_inhibit = mmu030.atc[l].physical.cache_inhibit;
+
        return physical_addr + page_index;
 }
 
@@ -1818,8 +1845,8 @@ static uaecptr mmu030_put_atc_generic(uaecptr addr, int l, uae_u32 fc, int flags
     uae_u32 physical_addr = mmu030.atc[l].physical.addr & addr_mask;
 
 #if MMU030_ATC_DBG_MSG
-    write_log(_T("ATC match(%i): page addr = %08X, index = %08X (bput %02X)\n"),
-              l, physical_addr, page_index, val);
+    write_log(_T("ATC match(%i): page addr = %08X, index = %08X\n"),
+              l, physical_addr, page_index);
 #endif
     
     if (mmu030.atc[l].physical.write_protect || mmu030.atc[l].physical.bus_error) {
@@ -1898,9 +1925,16 @@ static int mmu030_logical_is_in_atc(uaecptr addr, uae_u32 fc, bool write) {
  * create a new ATC entry and then look up the physical address. 
  */
 
+STATIC_INLINE void cacheablecheck(uaecptr addr)
+{
+       if (!ce_cachable[addr >> 16] && !mmu030_cache_inhibit)
+               mmu030_cache_inhibit = -1; // CIN active
+}
+
 void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc)
 {
-    if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true)) && mmu030.enabled) {
 #if MMU_DPAGECACHE030
                uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES030 - 1);
@@ -1918,12 +1952,14 @@ void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc)
                        }
                }
        }
+       cacheablecheck(addr);
        x_phys_put_long(addr,val);
 }
 
 void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc)
 {
-    if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true)) && mmu030.enabled) {
 #if MMU_DPAGECACHE030
                uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES030 - 1);
@@ -1941,12 +1977,14 @@ void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc)
                        }
                }
        }
+       cacheablecheck(addr);
        x_phys_put_word(addr,val);
 }
 
 void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc)
 {
-    if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true)) && mmu030.enabled) {
 #if MMU_DPAGECACHE030
                uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES030 - 1);
@@ -1964,13 +2002,15 @@ void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc)
                        }
                }
        }
+       cacheablecheck(addr);
        x_phys_put_byte(addr,val);
 }
 
 
 uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc)
 {
-   if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) {
 #if MMU_DPAGECACHE030
                uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES030 - 1);
@@ -1988,12 +2028,14 @@ uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc)
                        }
                }
        }
+       cacheablecheck(addr);
        return x_phys_get_long(addr);
 }
 
 uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc)
 {
-   if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) {
 #if MMU_DPAGECACHE030
                uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES030 - 1);
@@ -2011,12 +2053,14 @@ uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc)
                        }
                }
        }
+       cacheablecheck(addr);
        return x_phys_get_word(addr);
 }
 
 uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc)
 {
-   if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) {
 #if MMU_DPAGECACHE030
                uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size3m) | fc;
                uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES030 - 1);
@@ -2034,6 +2078,7 @@ uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc)
                        }
                }
        }
+       cacheablecheck(addr);
        return x_phys_get_byte(addr);
 }
 
@@ -2046,13 +2091,15 @@ uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc)
                uae_u8 *p = &mmu030.mmu030_last_physical_address_real[addr & mmu030.translation.page.mask];
                return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]);
 #else
+               mmu030_cache_inhibit = mmu030.mmu030_cache_inhibit;
                return x_phys_get_ilong(mmu030.mmu030_last_physical_address + (addr & mmu030.translation.page.mask));
 #endif
        }
        mmu030.mmu030_last_logical_address = 0xffffffff;
 #endif
 
-       if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) {
                int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false);
                if (atc_line_num >= 0) {
                        addr = mmu030_get_i_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_L);
@@ -2072,13 +2119,15 @@ uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc) {
                uae_u8 *p = &mmu030.mmu030_last_physical_address_real[addr & mmu030.translation.page.mask];
                return (p[0] << 8) | p[1];
 #else
+               mmu030_cache_inhibit = mmu030.mmu030_cache_inhibit;
                return x_phys_get_iword(mmu030.mmu030_last_physical_address + (addr & mmu030.translation.page.mask));
 #endif
        }
        mmu030.mmu030_last_logical_address = 0xffffffff;
 #endif
 
-       if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) {
                int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false);
                if (atc_line_num >= 0) {
                        addr = mmu030_get_i_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_W);
@@ -2093,7 +2142,8 @@ uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc) {
 /* Not commonly used access function */
 void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int flags)
 {
-       if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,true)) && mmu030.enabled) {
                int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true);
                if (atc_line_num>=0) {
                        addr = mmu030_put_atc_generic(addr, atc_line_num, fc, flags);
@@ -2104,6 +2154,7 @@ void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int fla
                }
        }
 
+       cacheablecheck(addr);
        if (size == sz_byte)
                x_phys_put_byte(addr, val);
        else if (size == sz_word)
@@ -2114,7 +2165,8 @@ void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int fla
 
 static uae_u32 mmu030_get_generic_lrmw(uaecptr addr, uae_u32 fc, int size, int flags)
 {
-       if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false))) && (mmu030.enabled)) {
+       mmu030_cache_inhibit = 0;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) {
                int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true);
                if (atc_line_num>=0) {
                        addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, true);
@@ -2125,6 +2177,7 @@ static uae_u32 mmu030_get_generic_lrmw(uaecptr addr, uae_u32 fc, int size, int f
                }
        }
 
+       cacheablecheck(addr);
        if (size == sz_byte)
                return x_phys_get_byte(addr);
        else if (size == sz_word)
@@ -2134,11 +2187,13 @@ static uae_u32 mmu030_get_generic_lrmw(uaecptr addr, uae_u32 fc, int size, int f
 
 uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int flags)
 {
+       mmu030_cache_inhibit = 0;
+
        if (flags & MMU030_SSW_RM) {
                return mmu030_get_generic_lrmw(addr, fc, size, flags);
        }
 
-       if (((fc != 7) || (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false))) && (mmu030.enabled)) {
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,false)) && mmu030.enabled) {
                int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false);
                if (atc_line_num>=0) {
                        addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, false);
@@ -2149,6 +2204,7 @@ uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int flags)
                }
        }
 
+       cacheablecheck(addr);
        if (size == sz_byte)
                return x_phys_get_byte(addr);
        else if (size == sz_word)
@@ -2156,6 +2212,23 @@ uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int flags)
        return x_phys_get_long(addr);
 }
 
+bool uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size)
+{
+       uae_u32 fc = regs.fc030;
+       if (fc != 7 && (!tt_enabled || !mmu030_match_ttr_access(addr,fc,write)) && mmu030.enabled) {
+               uae_u32 flags = mmu030_size[size];
+               int atc_line_num = mmu030_logical_is_in_atc(addr, fc, write);
+               if (atc_line_num>=0) {
+                       addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, write);
+               } else {
+                       mmu030_table_search(addr, fc, write, 0);
+                       atc_line_num = mmu030_logical_is_in_atc(addr, fc, write);
+                       addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, false);
+               }
+       }
+       cacheablecheck(addr);
+       return mmu030_cache_inhibit == 0;
+}
 
 /* Locked RMW is rarely used */
 uae_u32 uae_mmu030_get_lrmw(uaecptr addr, int size)
@@ -2335,27 +2408,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);
+       return read_dcache030(addr, 0, (regs.s ? 4 : 0) | 1);
 }
 static uae_u32 get_dcache_word(uaecptr addr)
 {
-       return read_dcache030(addr, 1);
+       return read_dcache030(addr, 1, (regs.s ? 4 : 0) | 1);
 }
 static uae_u32 get_dcache_long(uaecptr addr)
 {
-       return read_dcache030(addr, 2);
+       return read_dcache030(addr, 2, (regs.s ? 4 : 0) | 1);
 }
 static void put_dcache_byte(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 0);
+       write_dcache030(addr, v, 0, (regs.s ? 4 : 0) | 1);
 }
 static void put_dcache_word(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 1);
+       write_dcache030(addr, v, 1, (regs.s ? 4 : 0) | 1);
 }
 static void put_dcache_long(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 2);
+       write_dcache030(addr, v, 2, (regs.s ? 4 : 0) | 1);
 }
 
 /* MMU Reset */
@@ -2385,15 +2458,15 @@ void mmu030_set_funcs(void)
 {
        if (currprefs.mmu_model != 68030)
                return;
-       if (currprefs.cpu_memory_cycle_exact || currprefs.cpu_compatible) {
-               x_phys_get_iword = get_word_icache030;
-               x_phys_get_ilong = get_long_icache030;
-               x_phys_get_byte = get_dcache_byte;
-               x_phys_get_word = get_dcache_word;
-               x_phys_get_long = get_dcache_long;
-               x_phys_put_byte = put_dcache_byte;
-               x_phys_put_word = put_dcache_word;
-               x_phys_put_long = put_dcache_long;
+       if (currprefs.cpu_memory_cycle_exact) {
+               x_phys_get_iword = mem_access_delay_wordi_read_ce020;
+               x_phys_get_ilong = mem_access_delay_longi_read_ce020;
+               x_phys_get_byte = mem_access_delay_byte_read_ce020;
+               x_phys_get_word = mem_access_delay_word_read_ce020;
+               x_phys_get_long = mem_access_delay_long_read_ce020;
+               x_phys_put_byte = mem_access_delay_byte_write_ce020;
+               x_phys_put_word = mem_access_delay_word_write_ce020;
+               x_phys_put_long = mem_access_delay_long_write_ce020;
        } else {
                x_phys_get_iword = phys_get_word;
                x_phys_get_ilong = phys_get_long;
@@ -2422,8 +2495,11 @@ void m68k_do_rte_mmu030 (uaecptr a7)
        else
                get_word_mmu030(a7 + 32 - 2);
 
+       // Internal register, misc flags
+       uae_u32 ps = get_long_mmu030c(a7 + 0x28);
        // Internal register, our opcode storage area
-       mmu030_opcode = get_long_mmu030 (a7 + 0x14);
+       uae_u32 oc = get_long_mmu030c (a7 + 0x14);
+       mmu030_opcode = (ps & 0x80000000) ? -1 : (oc & 0xffff);
        // Misc state data
        mmu030_state[0] = get_word_mmu030 (a7 + 0x30);
        mmu030_state[1] = get_word_mmu030 (a7 + 0x32);
@@ -2572,3 +2648,207 @@ uae_u32 REGPARAM2 get_disp_ea_020_mmu030 (uae_u32 base, int idx)
 
        return v;
 }
+
+// cache
+
+void m68k_do_rts_mmu030c (void)
+{
+       m68k_setpc (get_long_mmu030c_state (m68k_areg (regs, 7)));
+       m68k_areg (regs, 7) += 4;
+}
+
+void m68k_do_bsr_mmu030c (uaecptr oldpc, uae_s32 offset)
+{
+       put_long_mmu030c_state (m68k_areg (regs, 7) - 4, oldpc);
+       m68k_areg (regs, 7) -= 4;
+       m68k_incpci (offset);
+}
+
+
+uae_u32 REGPARAM2 get_disp_ea_020_mmu030c (uae_u32 base, int idx)
+{
+       uae_u16 dp;
+       int reg;
+       uae_u32 v;
+       int oldidx;
+       int pcadd = 0;
+
+       // we need to do this hack here because in worst case we don't have enough
+       // stack frame space to store two very large 020 addressing mode access state
+       // + whatever the instruction itself does.
+
+       if (mmu030_state[1] & (1 << idx)) {
+               m68k_incpci (((mmu030_state[2] >> (idx * 4)) & 15) * 2);
+               return mmu030_disp_store[idx];
+       }
+
+       oldidx = mmu030_idx;
+       dp = next_iword_mmu030c_state ();
+       pcadd += 1;
+       
+       reg = (dp >> 12) & 15;
+       uae_s32 regd = regs.regs[reg];
+       if ((dp & 0x800) == 0)
+               regd = (uae_s32)(uae_s16)regd;
+       regd <<= (dp >> 9) & 3;
+       if (dp & 0x100) {
+               uae_s32 outer = 0;
+               if (dp & 0x80)
+                       base = 0;
+               if (dp & 0x40)
+                       regd = 0;
+
+               if ((dp & 0x30) == 0x20) {
+                       base += (uae_s32)(uae_s16) next_iword_mmu030c_state ();
+                       pcadd += 1;
+               }
+               if ((dp & 0x30) == 0x30) {
+                       base += next_ilong_mmu030c_state ();
+                       pcadd += 2;
+               }
+
+               if ((dp & 0x3) == 0x2) {
+                       outer = (uae_s32)(uae_s16) next_iword_mmu030c_state ();
+                       pcadd += 1;
+               }
+               if ((dp & 0x3) == 0x3) {
+                       outer = next_ilong_mmu030c_state ();
+                       pcadd += 2;
+               }
+
+               if ((dp & 0x4) == 0) {
+                       base += regd;
+               }
+               if (dp & 0x3) {
+                       base = get_long_mmu030c_state (base);
+               }
+               if (dp & 0x4) {
+                       base += regd;
+               }
+               v = base + outer;
+       } else {
+               v = base + (uae_s32)((uae_s8)dp) + regd;
+       }
+
+       mmu030_state[1] |= 1 << idx;
+       mmu030_state[2] |= pcadd << (idx * 4);
+       mmu030_disp_store[idx] = v;
+       mmu030_idx = oldidx;
+       mmu030_ad[mmu030_idx].done = false;
+
+       return v;
+}
+
+void m68k_do_rte_mmu030c (uaecptr a7)
+{
+       // Restore access error exception state
+
+       uae_u16 format = get_word_mmu030c (a7 + 6);
+       uae_u16 frame = format >> 12;
+       uae_u16 ssw = get_word_mmu030c (a7 + 10);
+       uae_u16 sr = get_word_mmu030c (a7);
+       uae_u32 pc = get_long_mmu030c (a7 + 2);
+
+       // Fetch last word, real CPU does it to allow OS bus handler to map
+       // the page if frame crosses pages and following page is not resident.
+       if (frame == 0xb)
+               get_word_mmu030c(a7 + 92 - 2);
+       else
+               get_word_mmu030c(a7 + 32 - 2);
+
+       // Internal register, misc flags
+       uae_u32 ps = get_long_mmu030c(a7 + 0x28);
+       // Internal register, our opcode storage area
+       uae_u32 oc = get_long_mmu030c (a7 + 0x14);
+       mmu030_opcode = (ps & 0x80000000) ? -1 : (oc & 0xffff);
+       // Misc state data
+       mmu030_state[0] = get_word_mmu030c (a7 + 0x30);
+       mmu030_state[1] = get_word_mmu030c (a7 + 0x32);
+       mmu030_state[2] = get_word_mmu030c (a7 + 0x34);
+       mmu030_disp_store[0] = get_long_mmu030c (a7 + 0x1c);
+       mmu030_disp_store[1] = get_long_mmu030c (a7 + 0x1c + 4);
+       if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) {
+               mmu030_fmovem_store[0] = get_long_mmu030c (a7 + 0x5c - (7 + 1) * 4);
+               mmu030_fmovem_store[1] = get_long_mmu030c (a7 + 0x5c - (8 + 1) * 4);
+       }
+       // Rerun "mmu030_opcode" using restored state.
+       mmu030_retry = true;
+
+       if (frame == 0xb) {
+               uae_u16 idxsize = get_word_mmu030c(a7 + 0x36);
+               for (int i = 0; i < idxsize + 1; i++) {
+                       mmu030_ad[i].done = i < idxsize;
+                       mmu030_ad[i].val = get_long_mmu030c(a7 + 0x5c - (i + 1) * 4);
+               }
+               mmu030_ad[idxsize + 1].done = false;
+               // did we have data fault but DF bit cleared?
+               if (ssw & (MMU030_SSW_DF << 1) && !(ssw & MMU030_SSW_DF)) {
+                       // DF not set: mark access as done
+                       if (ssw & MMU030_SSW_RM) {
+                               // Read-Modify-Write: whole instruction is considered done
+                               write_log (_T("Read-Modify-Write and DF bit cleared! PC=%08x\n"), regs.instruction_pc);
+                               mmu030_retry = false;
+                       } else if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
+                               // if movem, skip next move
+                               mmu030_data_buffer = get_long_mmu030c(a7 + 0x2c);
+                               mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
+                       } else {
+                               mmu030_ad[idxsize].done = true;
+                               if (ssw & MMU030_SSW_RW) {
+                                       // Read and no DF: use value in data input buffer
+                                       mmu030_data_buffer = get_long_mmu030c(a7 + 0x2c);
+                                       mmu030_ad[idxsize].val = mmu030_data_buffer;
+                               }
+                       }
+               }
+
+               regs.prefetch020_valid[0] = (ps & 1) ? 1 : 0;
+               regs.prefetch020_valid[1] = (ps & 2) ? 1 : 0;
+               regs.prefetch020_valid[2] = (ps & 4) ? 1 : 0;
+               regs.pipeline_r8[0] = (ps >> 8) & 7;
+               regs.pipeline_r8[1] = (ps >> 11) & 7;
+               regs.pipeline_pos = (ps >> 16) & 15;
+               regs.pipeline_stop = ((ps >> 20) & 15) == 15 ? -1 : (ps >> 20) & 15;
+
+               uae_u32 stagesbc = get_long_mmu030c(a7 + 0x0c);
+               regs.prefetch020[2] = stagesbc;
+               regs.prefetch020[1] = stagesbc >> 16;
+               regs.prefetch020[0] = oc >> 16;
+
+               if ((ssw & MMU030_SSW_FB) && !(ssw & MMU030_SSW_RB)) {
+                       regs.prefetch020_valid[2] = 1;
+                       write_log (_T("Software fixed stage B! opcode = %04x\n"), regs.prefetch020[2]);
+               }
+               if ((ssw & MMU030_SSW_FC) && !(ssw & MMU030_SSW_RC)) {
+                       regs.prefetch020_valid[1] = 1;
+                       write_log (_T("Software fixed stage C! opcode = %04x\n"), regs.prefetch020[1]);
+               }
+
+               m68k_areg (regs, 7) += 92;
+
+               regs.sr = sr;
+               MakeFromSR_T0();
+               if (pc & 1) {
+                       exception3i (0x4E73, pc);
+                       return;
+               }
+               m68k_setpci (pc);
+
+               if (!(ssw & (MMU030_SSW_DF << 1))) {
+                       if (!regs.prefetch020_valid[0] && regs.prefetch020_valid[2]) {
+                               // Prefetch was software fixed, continue pipeline refill
+                               fill_prefetch_030_ntx_continue();
+                       } else if (regs.prefetch020_valid[0] && regs.prefetch020_valid[1]) {
+                               // Finished?
+                               fill_prefetch_030_ntx_continue();
+                       } else if (mmu030_opcode == -1) {
+                               // Previous branch instruction finished successfully but its pipeline refill
+                               // step caused the exception, retry the refill, do not retry branch instruction.
+                               fill_prefetch_030_ntx();
+                       }
+               }
+
+       } else {
+               m68k_areg (regs, 7) += 32;
+       }
+}
index 19f8e31596e31d0e01cd2e183998606d037573e8..64fc53c81130aed9314662f20d7c0454012cb54e 100644 (file)
@@ -184,11 +184,6 @@ static void fpulimit (void)
        n_braces = 0;
 }
 
-static void cpulimit (void)
-{
-       printf ("#ifndef CPUEMU_68000_ONLY\n");
-}
-
 static int s_count_read, s_count_write, s_count_cycles, s_count_ncycles;
 
 static void push_ins_cnt(void)
@@ -1654,21 +1649,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
 
        if (getv == 1) {
                start_brace ();
-               if (using_ce020 || using_prefetch_020) {
-                       switch (size) {
-                       case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); count_read++; break;
-                       case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcw, name); count_read++; break;
-                       case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, srcl, name); count_read += 2; break;
-                       default: term ();
-                       }
-               } else if (using_ce || using_prefetch) {
-                       switch (size) {
-                       case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); count_read++; break;
-                       case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcw, name); count_read++; break;
-                       case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa) << 16; %s |= %s (%sa + 2);\n", name, srcw, name, name, srcw, name); count_read += 2; break;
-                       default: term ();
-                       }
-               } else if (using_mmu) {
+               if (using_mmu) {
                        if (flags & GF_FC) {
                                switch (size) {
                                case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = sfc%s_get_byte (%sa);\n", name, mmu_postfix, name); break;
@@ -1684,6 +1665,20 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                                default: term ();
                                }
                        }
+               } else if (using_ce020 || using_prefetch_020) {
+                       switch (size) {
+                       case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); count_read++; break;
+                       case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcw, name); count_read++; break;
+                       case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa);\n", name, srcl, name); count_read += 2; break;
+                       default: term ();
+                       }
+               } else if (using_ce || using_prefetch) {
+                       switch (size) {
+                       case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); count_read++; break;
+                       case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = %s (%sa);\n", name, srcw, name); count_read++; break;
+                       case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = %s (%sa) << 16; %s |= %s (%sa + 2);\n", name, srcw, name, name, srcw, name); count_read += 2; break;
+                       default: term ();
+                       }
                } else {
                        switch (size) {
                        case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = %s (%sa);\n", name, srcb, name); count_read++; break;
@@ -1861,7 +1856,37 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
        case PC8r:
                if (!(flags & GF_NOFAULTPC))
                        gen_set_fault_pc ();
-               if (using_ce020 || using_prefetch_020) {
+               if (using_mmu) {
+                       switch (size) {
+                       case sz_byte:
+                               insn_n_cycles += 4;
+                               if (flags & GF_FC)
+                                       printf ("\tdfc%s_put_byte (%sa, %s);\n", mmu_postfix, to, from);
+                               else
+                                       printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstblrmw : (candormw ? dstbrmw : dstb), to, from);
+                               break;
+                       case sz_word:
+                               insn_n_cycles += 4;
+                               if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
+                                       term ();
+                               if (flags & GF_FC)
+                                       printf ("\tdfc%s_put_word (%sa, %s);\n", mmu_postfix, to, from);
+                               else
+                                       printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstwlrmw : (candormw ? dstwrmw : dstw), to, from);
+                               break;
+                       case sz_long:
+                               insn_n_cycles += 8;
+                               if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
+                                       term ();
+                               if (flags & GF_FC)
+                                       printf ("\tdfc%s_put_long (%sa, %s);\n", mmu_postfix, to, from);
+                               else
+                                       printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstllrmw : (candormw ? dstlrmw : dstl), to, from);
+                               break;
+                       default:
+                               term ();
+                       }
+               } else if (using_ce020 || using_prefetch_020) {
                        switch (size) {
                        case sz_byte:
                                printf ("\t%s (%sa, %s);\n", dstb, to, from);
@@ -1913,36 +1938,6 @@ static void genastore_2 (const char *from, amodes mode, const char *reg, wordsiz
                        default:
                                term ();
                        }
-               } else if (using_mmu) {
-                       switch (size) {
-                       case sz_byte:
-                               insn_n_cycles += 4;
-                               if (flags & GF_FC)
-                                       printf ("\tdfc%s_put_byte (%sa, %s);\n", mmu_postfix, to, from);
-                               else
-                                       printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstblrmw : (candormw ? dstbrmw : dstb), to, from);
-                               break;
-                       case sz_word:
-                               insn_n_cycles += 4;
-                               if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
-                                       term ();
-                               if (flags & GF_FC)
-                                       printf ("\tdfc%s_put_word (%sa, %s);\n", mmu_postfix, to, from);
-                               else
-                                       printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstwlrmw : (candormw ? dstwrmw : dstw), to, from);
-                               break;
-                       case sz_long:
-                               insn_n_cycles += 8;
-                               if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
-                                       term ();
-                               if (flags & GF_FC)
-                                       printf ("\tdfc%s_put_long (%sa, %s);\n", mmu_postfix, to, from);
-                               else
-                                       printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstllrmw : (candormw ? dstlrmw : dstl), to, from);
-                               break;
-                       default:
-                               term ();
-                       }
                } else if (using_prefetch) {
                        switch (size) {
                        case sz_byte:
@@ -2786,7 +2781,35 @@ static void resetvars (void)
        if (using_indirect > 0) {
                // tracer
                getpc = "m68k_getpci ()";
-               if (!using_ce020 && !using_prefetch_020 && !using_ce) {
+               if (using_mmu == 68030) {
+                       // 68030 cache MMU
+                       disp020 = "get_disp_ea_020_mmu030c";
+                       prefetch_long = "get_ilong_mmu030c_state";
+                       prefetch_word = "get_iword_mmu030c_state";
+                       prefetch_opcode = "get_iword_mmu030c_opcode_state";
+                       nextw = "next_iword_mmu030c_state";
+                       nextl = "next_ilong_mmu030c_state";
+                       srcli = "get_ilong_mmu030c_state";
+                       srcwi = "get_iword_mmu030c_state";
+                       srcbi = "get_ibyte_mmu030c_state";
+                       srcl = "get_long_mmu030c_state";
+                       dstl = "put_long_mmu030c_state";
+                       srcw = "get_word_mmu030c_state";
+                       dstw = "put_word_mmu030c_state";
+                       srcb = "get_byte_mmu030c_state";
+                       dstb = "put_byte_mmu030c_state";
+                       srcblrmw = "get_lrmw_byte_mmu030c_state";
+                       srcwlrmw = "get_lrmw_word_mmu030c_state";
+                       srcllrmw = "get_lrmw_long_mmu030c_state";
+                       dstblrmw = "put_lrmw_byte_mmu030c_state";
+                       dstwlrmw = "put_lrmw_word_mmu030c_state";
+                       dstllrmw = "put_lrmw_long_mmu030c_state";
+                       srcld = "get_long_mmu030c";
+                       srcwd = "get_word_mmu030c";
+                       dstld = "put_long_mmu030c";
+                       dstwd = "put_word_mmu030c";
+                       getpc = "m68k_getpci ()";
+               } else if (!using_ce020 && !using_prefetch_020 && !using_ce) {
                        // generic + indirect
                        disp020 = "x_get_disp_ea_020";
                        prefetch_long = "get_iilong_jit";
@@ -3890,8 +3913,13 @@ static void gen_opcode (unsigned int opcode)
                        if (cpu_level == 2 || cpu_level == 3) { // 68020/68030 only
                                printf ("\t\telse if (frame == 0x9) { m68k_areg (regs, 7) += offset + 12; break; }\n");
                                if (using_mmu == 68030) {
-                                       printf ("\t\telse if (frame == 0xa) { m68k_do_rte_mmu030 (a); break; }\n");
-                                   printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030 (a); break; }\n");
+                                       if (using_prefetch_020) {
+                                               printf ("\t\telse if (frame == 0xa) { m68k_do_rte_mmu030c (a); break; }\n");
+                                           printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030c (a); goto %s; }\n", endlabelstr);
+                                       } else {
+                                               printf ("\t\telse if (frame == 0xa) { m68k_do_rte_mmu030 (a); break; }\n");
+                                           printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030 (a); break; }\n");
+                                       }
                                } else {
                                        printf ("\t\telse if (frame == 0xa) { m68k_areg (regs, 7) += offset + 24; break; }\n");
                                    printf ("\t\telse if (frame == 0xb) { m68k_areg (regs, 7) += offset + 84; break; }\n");
@@ -5483,7 +5511,7 @@ static void generate_includes (FILE * f, int id)
        fprintf (f, "#include \"cputbl.h\"\n");
        if (id == 31 || id == 33)
                fprintf (f, "#include \"cpummu.h\"\n");
-       else if (id == 32)
+       else if (id == 32 || id == 34)
                fprintf (f, "#include \"cpummu030.h\"\n");
 
        fprintf (f, "#define CPUFUNC(x) x##_ff\n"
@@ -5850,7 +5878,10 @@ static void generate_cpu (int id, int mode)
        }
 
        postfix = id;
-       if (id == 0 || id == 11 || id == 13 || id == 20 || id == 21 || id == 22 || id == 23 || id == 24 || id == 31 || id == 32 || id == 33 || id == 40 || id == 50) {
+       if (id == 0 || id == 11 || id == 13 ||
+               id == 20 || id == 21 || id == 22 || id == 23 || id == 24 ||
+               id == 31 || id == 32 || id == 33 || id == 34 ||
+               id == 40 || id == 50) {
                if (generate_stbl)
                        fprintf (stblfile, "#ifdef CPUEMU_%d%s\n", postfix, extraup);
                postfix2 = postfix;
@@ -5957,6 +5988,14 @@ static void generate_cpu (int id, int mode)
                read_counts ();
                for (rp = 0; rp < nr_cpuop_funcs; rp++)
                        opcode_next_clev[rp] = cpu_level;
+       } else if (id == 34) { // 34 = 68030 MMU + caches
+               mmu_postfix = "030c";
+               cpu_level = 3;
+               using_prefetch_020 = 2;
+               using_mmu = 68030;
+               read_counts ();
+               for (rp = 0; rp < nr_cpuop_funcs; rp++)
+                       opcode_next_clev[rp] = cpu_level;
        } else if (id < 6) {
                cpu_level = 5 - (id - 0); // "generic"
                cpu_generic = true;
@@ -6021,7 +6060,7 @@ int main(int argc, char *argv[])
        generate_includes (stblfile, 0);
 
        for (i = 0; i <= 55; i++) {
-               if ((i >= 6 && i < 11) || (i > 14 && i < 20) || (i > 25 && i < 31) || (i > 33 && i < 40))
+               if ((i >= 6 && i < 11) || (i > 14 && i < 20) || (i > 25 && i < 31) || (i > 34 && i < 40))
                        continue;
                generate_stbl = 1;
                generate_cpu (i, 0);
index 4db7b148c4f505c74550bde30e24f4cf082f0c96..da2bf1f481c09f35ac43cb56b92bd4fb0f8dd183 100644 (file)
@@ -101,14 +101,6 @@ STATIC_INLINE void do_head_cycles_ce020 (int h)
 }
 #endif
 
-void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v);
-void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v);
-void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v);
-uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr);
-uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr);
-uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr);
-uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr);
-
 STATIC_INLINE uae_u32 get_long_ce020 (uaecptr addr)
 {
        return mem_access_delay_long_read_ce020 (addr);
@@ -185,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);
+       write_dcache030(addr, v, 2, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE void put_word_030(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 1);
+       write_dcache030(addr, v, 1, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE void put_byte_030(uaecptr addr, uae_u32 v)
 {
-       write_dcache030(addr, v, 0);
+       write_dcache030(addr, v, 0, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE uae_u32 get_long_030(uaecptr addr)
 {
-       return read_dcache030(addr, 2);
+       return read_dcache030(addr, 2, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE uae_u32 get_word_030(uaecptr addr)
 {
-       return read_dcache030(addr, 1);
+       return read_dcache030(addr, 1, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE uae_u32 get_byte_030(uaecptr addr)
 {
-       return read_dcache030(addr, 0);
+       return read_dcache030(addr, 0, (regs.s ? 4 : 0) | 1);
 }
 
 STATIC_INLINE uae_u32 get_long_030_prefetch(int o)
@@ -251,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);
+       write_dcache030 (addr, v, 2, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE void put_word_ce030 (uaecptr addr, uae_u32 v)
 {
-       write_dcache030 (addr, v, 1);
+       write_dcache030 (addr, v, 1, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE void put_byte_ce030 (uaecptr addr, uae_u32 v)
 {
-       write_dcache030 (addr, v, 0);
+       write_dcache030 (addr, v, 0, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE uae_u32 get_long_ce030 (uaecptr addr)
 {
-       return read_dcache030 (addr, 2);
+       return read_dcache030 (addr, 2, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE uae_u32 get_word_ce030 (uaecptr addr)
 {
-       return read_dcache030 (addr, 1);
+       return read_dcache030 (addr, 1, (regs.s ? 4 : 0) | 1);
 }
 STATIC_INLINE uae_u32 get_byte_ce030 (uaecptr addr)
 {
-       return read_dcache030 (addr, 0);
+       return read_dcache030 (addr, 0, (regs.s ? 4 : 0) | 1);
 }
 
 STATIC_INLINE uae_u32 get_long_ce030_prefetch (int o)
index 7cb4d04f50185d1359bc14e32812912838f502c6..9bd41f4c19ba1e2cdda51b890492b981ffd75163 100644 (file)
@@ -23,6 +23,7 @@ extern uae_u16 mmu030_state[3];
 extern uae_u32 mmu030_data_buffer;
 extern uae_u32 mmu030_disp_store[2];
 extern uae_u32 mmu030_fmovem_store[2];
+extern int mmu030_cache_inhibit;
 
 #define MMU030_STATEFLAG1_FMOVEM 0x2000
 #define MMU030_STATEFLAG1_MOVEM1 0x4000
@@ -37,7 +38,6 @@ struct mmu030_access
 };
 extern struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS];
 
-uae_u32 REGPARAM3 get_disp_ea_020_mmu030 (uae_u32 base, int idx) REGPARAM;
 void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc);
 
 bool mmu_op30_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra);
@@ -117,7 +117,7 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_long(uaecptr addr)
                return mmu030_get_long_unaligned(addr, fc, 0);
        return mmu030_get_long(addr, fc);
 }
-static ALWAYS_INLINE uae_u16 uae_mmu030_get_word(uaecptr addr)
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_word(uaecptr addr)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
 
@@ -125,7 +125,7 @@ static ALWAYS_INLINE uae_u16 uae_mmu030_get_word(uaecptr addr)
                return mmu030_get_word_unaligned(addr, fc, 0);
        return mmu030_get_word(addr, fc);
 }
-static ALWAYS_INLINE uae_u8 uae_mmu030_get_byte(uaecptr addr)
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_byte(uaecptr addr)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
 
@@ -140,7 +140,7 @@ static ALWAYS_INLINE void uae_mmu030_put_long(uaecptr addr, uae_u32 val)
        else
                mmu030_put_long(addr, val, fc);
 }
-static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u16 val)
+static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u32 val)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
 
@@ -149,13 +149,100 @@ static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u16 val)
        else
                mmu030_put_word(addr, val, fc);
 }
-static ALWAYS_INLINE void uae_mmu030_put_byte(uaecptr addr, uae_u8 val)
+static ALWAYS_INLINE void uae_mmu030_put_byte(uaecptr addr, uae_u32 val)
 {
     uae_u32 fc = (regs.s ? 4 : 0) | 1;
 
        mmu030_put_byte(addr, val, fc);
 }
 
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong_fc(uaecptr addr)
+{
+       if (unlikely(is_unaligned(addr, 4)))
+               return mmu030_get_ilong_unaligned(addr, regs.fc030, 0);
+       return mmu030_get_ilong(addr, regs.fc030);
+}
+static ALWAYS_INLINE uae_u16 uae_mmu030_get_iword_fc(uaecptr addr)
+{
+       return mmu030_get_iword(addr, regs.fc030);
+}
+static ALWAYS_INLINE uae_u16 uae_mmu030_get_ibyte_fc(uaecptr addr)
+{
+       return mmu030_get_byte(addr, regs.fc030);
+}
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_long_fc(uaecptr addr)
+{
+       if (unlikely(is_unaligned(addr, 4)))
+               return mmu030_get_long_unaligned(addr, regs.fc030, 0);
+       return mmu030_get_long(addr, regs.fc030);
+}
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_word_fc(uaecptr addr)
+{
+       if (unlikely(is_unaligned(addr, 2)))
+               return mmu030_get_word_unaligned(addr, regs.fc030, 0);
+       return mmu030_get_word(addr, regs.fc030);
+}
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_byte_fc(uaecptr addr)
+{
+       return mmu030_get_byte(addr, regs.fc030);
+}
+static ALWAYS_INLINE void uae_mmu030_put_long_fc(uaecptr addr, uae_u32 val)
+{
+       if (unlikely(is_unaligned(addr, 4)))
+               mmu030_put_long_unaligned(addr, val, regs.fc030, 0);
+       else
+               mmu030_put_long(addr, val, regs.fc030);
+}
+static ALWAYS_INLINE void uae_mmu030_put_word_fc(uaecptr addr, uae_u32 val)
+{
+       if (unlikely(is_unaligned(addr, 2)))
+               mmu030_put_word_unaligned(addr, val,  regs.fc030, 0);
+       else
+               mmu030_put_word(addr, val, regs.fc030);
+}
+static ALWAYS_INLINE void uae_mmu030_put_byte_fc(uaecptr addr, uae_u32 val)
+{
+       mmu030_put_byte(addr, val, regs.fc030);
+}
+bool uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size);
+
+#define ACCESS_CHECK_PUT \
+       if (!mmu030_ad[mmu030_idx].done) { \
+               mmu030_ad[mmu030_idx].val = v; \
+       } else if (mmu030_ad[mmu030_idx].done) { \
+               mmu030_idx++; \
+               return; \
+       }
+
+#define ACCESS_CHECK_GET \
+       if (mmu030_ad[mmu030_idx].done) { \
+               v = mmu030_ad[mmu030_idx].val; \
+               mmu030_idx++; \
+               return v; \
+       }
+
+#define ACCESS_CHECK_GET_PC(pc) \
+       if (mmu030_ad[mmu030_idx].done) { \
+               v = mmu030_ad[mmu030_idx].val; \
+               mmu030_idx++; \
+               m68k_incpci (pc); \
+               return v; \
+       }
+
+#define ACCESS_EXIT_PUT \
+       mmu030_ad[mmu030_idx].done = true; \
+       mmu030_idx++; \
+       mmu030_ad[mmu030_idx].done = false;
+
+#define ACCESS_EXIT_GET \
+       mmu030_ad[mmu030_idx].val = v; \
+       mmu030_ad[mmu030_idx].done = true; \
+       mmu030_idx++; \
+       mmu030_ad[mmu030_idx].done = false;
+
+// non-cache
+
+
 static ALWAYS_INLINE uae_u32 sfc030_get_long(uaecptr addr)
 {
     uae_u32 fc = regs.sfc;
@@ -220,39 +307,7 @@ static ALWAYS_INLINE void dfc030_put_byte(uaecptr addr, uae_u8 val)
        mmu030_put_byte(addr, val, fc);
 }
 
-#define ACCESS_CHECK_PUT \
-       if (!mmu030_ad[mmu030_idx].done) { \
-               mmu030_ad[mmu030_idx].val = v; \
-       } else if (mmu030_ad[mmu030_idx].done) { \
-               mmu030_idx++; \
-               return; \
-       }
-
-#define ACCESS_CHECK_GET \
-       if (mmu030_ad[mmu030_idx].done) { \
-               v = mmu030_ad[mmu030_idx].val; \
-               mmu030_idx++; \
-               return v; \
-       }
-
-#define ACCESS_CHECK_GET_PC(pc) \
-       if (mmu030_ad[mmu030_idx].done) { \
-               v = mmu030_ad[mmu030_idx].val; \
-               mmu030_idx++; \
-               m68k_incpci (pc); \
-               return v; \
-       }
-
-#define ACCESS_EXIT_PUT \
-       mmu030_ad[mmu030_idx].done = true; \
-       mmu030_idx++; \
-       mmu030_ad[mmu030_idx].done = false;
-
-#define ACCESS_EXIT_GET \
-       mmu030_ad[mmu030_idx].val = v; \
-       mmu030_ad[mmu030_idx].done = true; \
-       mmu030_idx++; \
-       mmu030_ad[mmu030_idx].done = false;
+uae_u32 REGPARAM3 get_disp_ea_020_mmu030 (uae_u32 base, int idx) REGPARAM;
 
 STATIC_INLINE void put_byte_mmu030_state (uaecptr addr, uae_u32 v)
 {
@@ -405,7 +460,6 @@ STATIC_INLINE void put_byte_mmu030 (uaecptr addr, uae_u32 v)
 {
     uae_mmu030_put_byte (addr, v);
 }
-
 STATIC_INLINE void put_word_mmu030 (uaecptr addr, uae_u32 v)
 {
     uae_mmu030_put_word (addr, v);
@@ -452,4 +506,218 @@ extern void m68k_do_rte_mmu030 (uaecptr a7);
 extern void flush_mmu030 (uaecptr, int);
 extern void m68k_do_bsr_mmu030 (uaecptr oldpc, uae_s32 offset);
 
+// cache
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+       ACCESS_EXIT_PUT
+}
+STATIC_INLINE void put_lrmw_byte_mmu030c_state (uaecptr addr, uae_u32 v)
+{
+       ACCESS_CHECK_PUT
+       write_dcache030_lrmw_mmu(addr, v, 0);
+       ACCESS_EXIT_PUT
+}
+STATIC_INLINE void put_word_mmu030c_state (uaecptr addr, uae_u32 v)
+{
+       ACCESS_CHECK_PUT
+       write_dcache030_mmu(addr, v, 1);
+       ACCESS_EXIT_PUT
+}
+STATIC_INLINE void put_lrmw_word_mmu030c_state (uaecptr addr, uae_u32 v)
+{
+       ACCESS_CHECK_PUT
+       write_dcache030_lrmw_mmu(addr, v, 1);
+       ACCESS_EXIT_PUT
+}
+STATIC_INLINE void put_long_mmu030c_state (uaecptr addr, uae_u32 v)
+{
+       ACCESS_CHECK_PUT
+       write_dcache030_mmu(addr, v, 2);
+       ACCESS_EXIT_PUT
+}
+STATIC_INLINE void put_lrmw_long_mmu030c_state (uaecptr addr, uae_u32 v)
+{
+       ACCESS_CHECK_PUT
+       write_dcache030_lrmw_mmu(addr, v, 2);
+       ACCESS_EXIT_PUT
+}
+
+STATIC_INLINE uae_u32 get_byte_mmu030c_state (uaecptr addr)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET
+    v = read_dcache030_mmu(addr, 0);
+       ACCESS_EXIT_GET
+       return v;
+}
+STATIC_INLINE uae_u32 get_lrmw_byte_mmu030c_state (uaecptr addr)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET
+    v = read_dcache030_lrmw_mmu(addr, 0);
+       ACCESS_EXIT_GET
+       return v;
+}
+
+STATIC_INLINE uae_u32 get_word_mmu030c_state (uaecptr addr)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET
+    v = read_dcache030_mmu(addr, 1);
+       ACCESS_EXIT_GET
+       return v;
+}
+STATIC_INLINE uae_u32 get_lrmw_word_mmu030c_state (uaecptr addr)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET
+    v = read_dcache030_lrmw_mmu(addr, 1);
+       ACCESS_EXIT_GET
+       return v;
+}
+STATIC_INLINE uae_u32 get_long_mmu030c_state (uaecptr addr)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET
+    v = read_dcache030_mmu(addr, 2);
+       ACCESS_EXIT_GET
+       return v;
+}
+STATIC_INLINE uae_u32 get_lrmw_long_mmu030c_state (uaecptr addr)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET
+    v = read_dcache030_lrmw_mmu(addr, 2);
+       ACCESS_EXIT_GET
+       return v;
+}
+
+STATIC_INLINE uae_u32 get_ibyte_mmu030c_state (int o)
+{
+       uae_u32 v;
+    uae_u32 addr = m68k_getpci () + o;
+       ACCESS_CHECK_GET
+       v = get_word_icache030(addr);
+       ACCESS_EXIT_GET
+       return v;
+}
+uae_u32 get_word_030_prefetch(int o);
+STATIC_INLINE uae_u32 get_iword_mmu030c_state (int o)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET;
+       v = get_word_030_prefetch(o);
+       ACCESS_EXIT_GET
+       return v;
+}
+uae_u32 get_long_030_prefetch(int o);
+STATIC_INLINE uae_u32 get_ilong_mmu030c_state (int o)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET;
+       v = get_word_030_prefetch(o + 0) << 16;
+       v |= get_word_030_prefetch(o + 2);
+       ACCESS_EXIT_GET
+       return v;
+}
+STATIC_INLINE uae_u32 get_iword_mmu030c_opcode_state(int o)
+{
+       return get_iword_mmu030c_state(o);
+}
+
+
+STATIC_INLINE uae_u32 next_iword_mmu030c_state (void)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET_PC(2);
+       v = get_word_030_prefetch(0);
+       m68k_incpci(2);
+       ACCESS_EXIT_GET
+       return v;
+}
+STATIC_INLINE uae_u32 next_ilong_mmu030c_state (void)
+{
+       uae_u32 v;
+       ACCESS_CHECK_GET_PC(4);
+       v = get_word_030_prefetch(0) << 16;
+       v |= get_word_030_prefetch(2);
+    m68k_incpci (4);
+       ACCESS_EXIT_GET
+       return v;
+}
+
+STATIC_INLINE uae_u32 get_word_mmu030c (uaecptr addr)
+{
+       return read_dcache030_mmu(addr, 1);
+}
+STATIC_INLINE uae_u32 get_long_mmu030c (uaecptr addr)
+{
+       return read_dcache030_mmu(addr, 2);
+}
+STATIC_INLINE void put_word_mmu030c (uaecptr addr, uae_u32 v)
+{
+    write_dcache030_mmu(addr, v, 1);
+}
+STATIC_INLINE void put_long_mmu030c (uaecptr addr, uae_u32 v)
+{
+    write_dcache030_mmu(addr, v, 2);
+}
+
+extern void m68k_do_rts_mmu030c(void);
+extern void m68k_do_rte_mmu030c(uaecptr a7);
+extern void m68k_do_bsr_mmu030c(uaecptr oldpc, uae_s32 offset);
+
 #endif /* UAE_CPUMMU030_H */
index c3db99ab6f0ce9cf16accd9ef8474cec331a08b5..374a7c2a55015239ac65a7abc53d62874d41204a 100644 (file)
@@ -121,6 +121,7 @@ struct cache030
        uae_u32 data[4];
        bool valid[4];
        uae_u32 tag;
+       uae_u8 fc;
 };
 
 #define CACHESETS040 64
@@ -211,13 +212,16 @@ struct regstruct
        uae_u32 pcr;
        uae_u32 address_space_mask;
 
-       uae_u32 prefetch020[CPU_PIPELINE_MAX];
+       uae_u16 prefetch020[CPU_PIPELINE_MAX];
+       uae_u8 prefetch020_valid[CPU_PIPELINE_MAX];
        uae_u32 prefetch020addr;
        uae_u32 cacheholdingdata020;
        uae_u32 cacheholdingaddr020;
+       uae_u8 cacheholdingdata_valid;
        int pipeline_pos;
        int pipeline_r8[2];
        int pipeline_stop;
+       uae_u8 fc030;
 
        int ce020endcycle;
        int ce020startcycle;
@@ -249,7 +253,8 @@ struct cputracestruct
 
        uae_u32 msp, vbr;
        uae_u32 cacr, caar;
-       uae_u32 prefetch020[CPU_PIPELINE_MAX];
+       uae_u16 prefetch020[CPU_PIPELINE_MAX];
+       uae_u8 prefetch030_valid[CPU_PIPELINE_MAX];
        uae_u32 prefetch020addr;
        uae_u32 cacheholdingdata020;
        uae_u32 cacheholdingaddr020;
@@ -313,6 +318,15 @@ extern void(*x_cp_put_long)(uaecptr addr, uae_u32 v);
 extern uae_u32(*x_cp_next_iword)(void);
 extern uae_u32(*x_cp_next_ilong)(void);
 
+void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v);
+void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v);
+void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v);
+uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr);
+uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr);
+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);
+
 extern uae_u32(REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
 
 /* direct (regs.pc_p) access */
@@ -505,9 +519,15 @@ 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 void write_dcache030_lrmw_mmu(uaecptr, uae_u32, uae_u32);
+extern uae_u32 read_dcache030_lrmw_mmu(uaecptr, uae_u32);
+
 extern void check_t0_trace(void);
-extern void write_dcache030(uaecptr, uae_u32, int);
-extern uae_u32 read_dcache030(uaecptr, int);
 extern uae_u32 get_word_icache030(uaecptr addr);
 extern uae_u32 get_long_icache030(uaecptr addr);
 
@@ -614,6 +634,7 @@ extern void cpu_fallback(int mode);
 extern void fill_prefetch (void);
 extern void fill_prefetch_020_ntx(void);
 extern void fill_prefetch_030_ntx(void);
+extern void fill_prefetch_030_ntx_continue(void);
 extern void fill_prefetch_020(void);
 extern void fill_prefetch_030(void);
 
@@ -638,6 +659,7 @@ extern const struct cputbl op_smalltbl_52_ff[];
 extern const struct cputbl op_smalltbl_22_ff[]; // prefetch
 extern const struct cputbl op_smalltbl_23_ff[]; // CE
 extern const struct cputbl op_smalltbl_32_ff[]; // MMU
+extern const struct cputbl op_smalltbl_34_ff[]; // MMU + cache
 /* 68020 */
 extern const struct cputbl op_smalltbl_3_ff[];
 extern const struct cputbl op_smalltbl_43_ff[];
index 9cd433482d462ed217031725b318bff5ba33282b..9de571a831b4e69dd730a261d8b8198428b07ca6 100644 (file)
@@ -77,6 +77,9 @@ static int baseclock;
 int m68k_pc_indirect;
 bool m68k_interrupt_delay;
 static bool m68k_reset_delay;
+
+static bool dcache_complete_inhibit;
+
 static int cpu_prefs_changed_flag;
 
 int cpucycleunit;
@@ -246,15 +249,27 @@ static void set_x_cp_funcs(void)
        x_cp_get_disp_ea_020 = x_get_disp_ea_020;
 
        if (currprefs.mmu_model == 68030) {
-               x_cp_put_long = put_long_mmu030_state;
-               x_cp_put_word = put_word_mmu030_state;
-               x_cp_put_byte = put_byte_mmu030_state;
-               x_cp_get_long = get_long_mmu030_state;
-               x_cp_get_word = get_word_mmu030_state;
-               x_cp_get_byte = get_byte_mmu030_state;
-               x_cp_next_iword = next_iword_mmu030_state;
-               x_cp_next_ilong = next_ilong_mmu030_state;
-               x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
+               if (currprefs.cpu_compatible) {
+                       x_cp_put_long = put_long_mmu030c_state;
+                       x_cp_put_word = put_word_mmu030c_state;
+                       x_cp_put_byte = put_byte_mmu030c_state;
+                       x_cp_get_long = get_long_mmu030c_state;
+                       x_cp_get_word = get_word_mmu030c_state;
+                       x_cp_get_byte = get_byte_mmu030c_state;
+                       x_cp_next_iword = next_iword_mmu030c_state;
+                       x_cp_next_ilong = next_ilong_mmu030c_state;
+                       x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030c;
+               } else {
+                       x_cp_put_long = put_long_mmu030_state;
+                       x_cp_put_word = put_word_mmu030_state;
+                       x_cp_put_byte = put_byte_mmu030_state;
+                       x_cp_get_long = get_long_mmu030_state;
+                       x_cp_get_word = get_word_mmu030_state;
+                       x_cp_get_byte = get_byte_mmu030_state;
+                       x_cp_next_iword = next_iword_mmu030_state;
+                       x_cp_next_ilong = next_ilong_mmu030_state;
+                       x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
+               }
        }
 }
 
@@ -746,6 +761,20 @@ static void do_cycles_ce020_post (unsigned long cycles, uae_u32 v)
        do_cycles_ce020 (cycles);
 }
 
+static bool dcache030_check_dummy(uaecptr addr, bool write, uae_u32 size)
+{
+       return true;
+}
+
+static uae_u32 (*icache_fetch)(uaecptr);
+static uae_u32 (*dcache030_lget)(uaecptr);
+static uae_u32 (*dcache030_wget)(uaecptr);
+static uae_u32 (*dcache030_bget)(uaecptr);
+static bool (*dcache030_check)(uaecptr, bool, uae_u32);
+static void (*dcache030_lput)(uaecptr, uae_u32);
+static void (*dcache030_wput)(uaecptr, uae_u32);
+static void (*dcache030_bput)(uaecptr, uae_u32);
+
 static void set_x_ifetches(void)
 {
        if (m68k_pc_indirect) {
@@ -810,18 +839,53 @@ static void set_x_funcs (void)
 
                } else {
 
-                       x_prefetch = get_iword_mmu030;
-                       x_get_ilong = get_ilong_mmu030;
-                       x_get_iword = get_iword_mmu030;
-                       x_get_ibyte = get_ibyte_mmu030;
-                       x_next_iword = next_iword_mmu030;
-                       x_next_ilong = next_ilong_mmu030;
-                       x_put_long = put_long_mmu030;
-                       x_put_word = put_word_mmu030;
-                       x_put_byte = put_byte_mmu030;
-                       x_get_long = get_long_mmu030;
-                       x_get_word = get_word_mmu030;
-                       x_get_byte = get_byte_mmu030;
+                       if (currprefs.cpu_memory_cycle_exact) {
+                               x_prefetch = get_iword_mmu030c_state;
+                               x_get_ilong = get_ilong_mmu030c_state;
+                               x_get_iword = get_iword_mmu030c_state;
+                               x_get_ibyte = NULL;
+                               x_next_iword = next_iword_mmu030c_state;
+                               x_next_ilong = next_ilong_mmu030c_state;
+                               x_put_long = put_long_ce030;
+                               x_put_word = put_word_ce030;
+                               x_put_byte = put_byte_ce030;
+                               x_get_long = get_long_ce030;
+                               x_get_word = get_word_ce030;
+                               x_get_byte = get_byte_ce030;
+                               x_do_cycles = do_cycles;
+                               x_do_cycles_pre = do_cycles;
+                               x_do_cycles_post = do_cycles_post;
+                       } else if (currprefs.cpu_compatible) {
+                               x_prefetch = get_iword_mmu030c_state;
+                               x_get_ilong = get_ilong_mmu030c_state;
+                               x_get_iword = get_iword_mmu030c_state;
+                               x_get_ibyte = NULL;
+                               x_next_iword = next_iword_mmu030c_state;
+                               x_next_ilong = next_ilong_mmu030c_state;
+                               x_put_long = put_long_ce030;
+                               x_put_word = put_word_ce030;
+                               x_put_byte = put_byte_ce030;
+                               x_get_long = get_long_ce030;
+                               x_get_word = get_word_ce030;
+                               x_get_byte = get_byte_ce030;
+                               x_do_cycles = do_cycles;
+                               x_do_cycles_pre = do_cycles;
+                               x_do_cycles_post = do_cycles_post;
+                       } else {
+                               x_prefetch = get_iword_mmu030;
+                               x_get_ilong = get_ilong_mmu030;
+                               x_get_iword = get_iword_mmu030;
+                               x_get_ibyte = get_ibyte_mmu030;
+                               x_next_iword = next_iword_mmu030;
+                               x_next_ilong = next_ilong_mmu030;
+                               x_put_long = put_long_mmu030;
+                               x_put_word = put_word_mmu030;
+                               x_put_byte = put_byte_mmu030;
+                               x_get_long = get_long_mmu030;
+                               x_get_word = get_word_mmu030;
+                               x_get_byte = get_byte_mmu030;
+                       }
+
                }
                x_do_cycles = do_cycles;
                x_do_cycles_pre = do_cycles;
@@ -987,12 +1051,12 @@ static void set_x_funcs (void)
                                x_get_ibyte = NULL;
                                x_next_iword = next_iword_030_prefetch;
                                x_next_ilong = next_ilong_030_prefetch;
-                               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_put_long = put_long_030;
+                               x_put_word = put_word_030;
+                               x_put_byte = put_byte_030;
+                               x_get_long = get_long_030;
+                               x_get_word = get_word_030;
+                               x_get_byte = get_byte_030;
                                x_do_cycles = do_cycles;
                                x_do_cycles_pre = do_cycles;
                                x_do_cycles_post = do_cycles_post;
@@ -1154,6 +1218,47 @@ static void set_x_funcs (void)
        mmu_set_funcs();
        mmu030_set_funcs();
 
+       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_dummy;
+       if (currprefs.cpu_cycle_exact) {
+               icache_fetch = mem_access_delay_longi_read_ce020;
+       }
+       if (currprefs.cpu_model == 68030) {
+               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;
+                       } 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;
+                       }
+               } 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;
+               }
+       }
 }
 
 bool can_cpu_tracer (void)
@@ -1292,21 +1397,21 @@ static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
        return 4;
 }
 
-// generic+direct, generic+direct+jit, generic+indirect, more compatible, cycle-exact, mmu
-static const struct cputbl *cputbls[6][6] =
+// generic+direct, generic+direct+jit, generic+indirect, more compatible, cycle-exact, mmu, mm+more compatible
+static const struct cputbl *cputbls[6][7] =
 {
        // 68000
-       { op_smalltbl_5_ff, op_smalltbl_45_ff, op_smalltbl_55_ff, op_smalltbl_12_ff, op_smalltbl_14_ff, NULL },
+       { op_smalltbl_5_ff, op_smalltbl_45_ff, op_smalltbl_55_ff, op_smalltbl_12_ff, op_smalltbl_14_ff, NULL, NULL },
        // 68010
-       { op_smalltbl_4_ff, op_smalltbl_44_ff, op_smalltbl_54_ff, op_smalltbl_11_ff, op_smalltbl_13_ff, NULL },
+       { op_smalltbl_4_ff, op_smalltbl_44_ff, op_smalltbl_54_ff, op_smalltbl_11_ff, op_smalltbl_13_ff, NULL, NULL },
        // 68020
-       { op_smalltbl_3_ff, op_smalltbl_43_ff, op_smalltbl_53_ff, op_smalltbl_20_ff, op_smalltbl_21_ff, NULL },
+       { op_smalltbl_3_ff, op_smalltbl_43_ff, op_smalltbl_53_ff, op_smalltbl_20_ff, op_smalltbl_21_ff, NULL, NULL },
        // 68030
-       { op_smalltbl_2_ff, op_smalltbl_42_ff, op_smalltbl_52_ff, op_smalltbl_22_ff, op_smalltbl_23_ff, op_smalltbl_32_ff },
+       { op_smalltbl_2_ff, op_smalltbl_42_ff, op_smalltbl_52_ff, op_smalltbl_22_ff, op_smalltbl_23_ff, op_smalltbl_32_ff, op_smalltbl_34_ff },
        // 68040
-       { op_smalltbl_1_ff, op_smalltbl_41_ff, op_smalltbl_51_ff, op_smalltbl_25_ff, op_smalltbl_25_ff, op_smalltbl_31_ff },
+       { op_smalltbl_1_ff, op_smalltbl_41_ff, op_smalltbl_51_ff, op_smalltbl_25_ff, op_smalltbl_25_ff, op_smalltbl_31_ff, NULL },
        // 68060
-       { op_smalltbl_0_ff, op_smalltbl_40_ff, op_smalltbl_50_ff, op_smalltbl_24_ff, op_smalltbl_24_ff, op_smalltbl_33_ff }
+       { op_smalltbl_0_ff, op_smalltbl_40_ff, op_smalltbl_50_ff, op_smalltbl_24_ff, op_smalltbl_24_ff, op_smalltbl_33_ff, NULL }
 };
 
 static void build_cpufunctbl (void)
@@ -1317,14 +1422,18 @@ static void build_cpufunctbl (void)
        int lvl, mode;
 
        if (!currprefs.cachesize) {
-               if (currprefs.mmu_model)
-                       mode = 5;
-               else if (currprefs.cpu_cycle_exact)
+               if (currprefs.mmu_model) {
+                       if (currprefs.cpu_compatible)
+                               mode = 6;
+                       else
+                               mode = 5;
+               } else if (currprefs.cpu_cycle_exact) {
                        mode = 4;
-               else if (currprefs.cpu_compatible)
+               } else if (currprefs.cpu_compatible) {
                        mode = 3;
-               else
+               } else {
                        mode = 0;
+               }
                m68k_pc_indirect = mode != 0 ? 1 : 0;
        } else {
                mode = 1;
@@ -1569,6 +1678,7 @@ static void prefs_changed_cpu (void)
                        fake_crp_030 = crp_030;
                }
        }
+       currprefs.mmu_ec = changed_prefs.mmu_ec;
        currprefs.cpu_compatible = changed_prefs.cpu_compatible;
        currprefs.address_space_24 = changed_prefs.address_space_24;
        currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
@@ -1589,6 +1699,7 @@ static int check_prefs_changed_cpu2(void)
                || currprefs.cpu_model != changed_prefs.cpu_model
                || currprefs.fpu_model != changed_prefs.fpu_model
                || currprefs.mmu_model != changed_prefs.mmu_model
+               || currprefs.mmu_ec != changed_prefs.mmu_ec
                || 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
@@ -2552,10 +2663,17 @@ static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32
                        m68k_areg (regs, 7) -= 4;
                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
                        // 2xinternal
-                       m68k_areg (regs, 7) -= 2;
-                       x_put_word (m68k_areg (regs, 7), 0);
-                       m68k_areg (regs, 7) -= 2;
-                       x_put_word (m68k_areg (regs, 7), 0);
+                       {
+                               uae_u32 ps = (regs.prefetch020_valid[0] ? 1 : 0) | (regs.prefetch020_valid[1] ? 2 : 0) | (regs.prefetch020_valid[2] ? 4 : 0);
+                               ps |= ((regs.pipeline_r8[0] & 7) << 8);
+                               ps |= ((regs.pipeline_r8[1] & 7) << 11);
+                               ps |= ((regs.pipeline_pos & 15) << 16);
+                               ps |= ((regs.pipeline_stop & 15) << 20);
+                               if (mmu030_opcode == -1)
+                                       ps |= 1 << 31;
+                               m68k_areg (regs, 7) -= 4;
+                               x_put_long (m68k_areg (regs, 7), ps);
+                       }
                        // stage b address
                        m68k_areg (regs, 7) -= 4;
                        x_put_long (m68k_areg (regs, 7), mm030_stageb_address);
@@ -2570,13 +2688,13 @@ static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32
                         // Data output buffer = value that was going to be written
                        x_put_long (m68k_areg (regs, 7), (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val);
                        m68k_areg (regs, 7) -= 4;
-                       x_put_long (m68k_areg (regs, 7), mmu030_opcode);  // Internal register (opcode storage)
+                       x_put_long (m68k_areg (regs, 7), (mmu030_opcode & 0xffff) | (regs.prefetch020[0] << 16));  // Internal register (opcode storage)
                        m68k_areg (regs, 7) -= 4;
                        x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address
                        m68k_areg (regs, 7) -= 2;
-                       x_put_word (m68k_areg (regs, 7), 0);  // Instr. pipe stage B
+                       x_put_word (m68k_areg (regs, 7), regs.prefetch020[2]);  // Instr. pipe stage B
                        m68k_areg (regs, 7) -= 2;
-                       x_put_word (m68k_areg (regs, 7), 0);  // Instr. pipe stage C
+                       x_put_word (m68k_areg (regs, 7), regs.prefetch020[1]);  // Instr. pipe stage C
                        m68k_areg (regs, 7) -= 2;
                        x_put_word (m68k_areg (regs, 7), ssw);
                        m68k_areg (regs, 7) -= 2;
@@ -2652,13 +2770,12 @@ static void Exception_mmu030 (int nr, uaecptr oldpc)
     }
 #endif
 
+    newpc = x_get_long (regs.vbr + 4 * nr);
+
 #if 0
-       write_log (_T("Exception %d -> %08x\n", nr, newpc));
+       write_log (_T("Exception %d -> %08x\n"), nr, newpc);
 #endif
 
-
-    newpc = x_get_long (regs.vbr + 4 * nr);
-
        if (regs.m && interrupt) { /* M + Interrupt */
         Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
                MakeSR ();
@@ -3192,6 +3309,9 @@ static void m68k_reset2(bool hardreset)
 
        mmufixup[0].reg = -1;
        mmufixup[1].reg = -1;
+       mmu030_cache_inhibit = 0;
+       dcache_complete_inhibit = uae_boot_rom_type > 0;
+       //dcache_complete_inhibit = true;
        if (currprefs.mmu_model >= 68040) {
                mmu_reset ();
                mmu_set_tc (regs.tcr);
@@ -5025,7 +5145,10 @@ insretry:
                                        }
                                        mmu030_fake_prefetch = -1;
                                } else if (mmu030_opcode_stageb < 0) {
-                                       regs.opcode = x_prefetch (0);
+                                       if (currprefs.cpu_compatible)
+                                               regs.opcode = regs.irc;
+                                       else
+                                               regs.opcode = x_prefetch (0);
                                } else {
                                        regs.opcode = mmu030_opcode_stageb;
                                        mmu030_opcode_stageb = -1;
@@ -5036,7 +5159,7 @@ insretry:
 
                                cnt = 50;
                                for (;;) {
-                                       regs.opcode = mmu030_opcode;
+                                       regs.opcode = regs.irc = mmu030_opcode;
                                        mmu030_idx = 0;
                                        count_instr (regs.opcode);
                                        do_cycles (cpu_cycles);
@@ -5064,20 +5187,27 @@ insretry:
                        }
                } CATCH (prb) {
 
-                       regflags.cznv = f.cznv;
-                       regflags.x = f.x;
-
-                       m68k_setpci (regs.instruction_pc);
-
-                       if (mmufixup[0].reg >= 0) {
-                               m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
+                       if (mmu030_opcode == -1 && currprefs.cpu_compatible) {
+                               // full prefetch fill access fault
+                               // TODO: this should create shorter A-frame
                                mmufixup[0].reg = -1;
-                       }
-                       if (mmufixup[1].reg >= 0) {
-                               m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
                                mmufixup[1].reg = -1;
+                       } else {
+                               regflags.cznv = f.cznv;
+                               regflags.x = f.x;
+
+                               if (mmufixup[0].reg >= 0) {
+                                       m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
+                                       mmufixup[0].reg = -1;
+                               }
+                               if (mmufixup[1].reg >= 0) {
+                                       m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
+                                       mmufixup[1].reg = -1;
+                               }
                        }
 
+                       m68k_setpci (regs.instruction_pc);
+
                        TRY (prb2) {
                                Exception (prb);
                        } CATCH (prb2) {
@@ -5191,7 +5321,7 @@ static void m68k_run_2ce (void)
                                        r->cacheholdingdata020 = cputrace.cacheholdingdata020;
                                        r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
                                        r->prefetch020addr = cputrace.prefetch020addr;
-                                       memcpy (&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
+                                       memcpy (&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u16));
                                        memcpy (&caches020, &cputrace.caches020, sizeof caches020);
 
                                        m68k_setpc (cputrace.pc);
@@ -5259,7 +5389,7 @@ static void m68k_run_2ce (void)
                                        cputrace.cacheholdingdata020 = r->cacheholdingdata020;
                                        cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
                                        cputrace.prefetch020addr = r->prefetch020addr;
-                                       memcpy (&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
+                                       memcpy (&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u16));
                                        memcpy (&cputrace.caches020, &caches020, sizeof caches020);
 
                                        cputrace.memoryoffset = 0;
@@ -5328,7 +5458,7 @@ static void m68k_run_2p (void)
                                        r->cacheholdingdata020 = cputrace.cacheholdingdata020;
                                        r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
                                        r->prefetch020addr = cputrace.prefetch020addr;
-                                       memcpy (&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
+                                       memcpy (&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u16));
                                        memcpy (&caches020, &cputrace.caches020, sizeof caches020);
 
                                        m68k_setpc (cputrace.pc);
@@ -5379,7 +5509,7 @@ static void m68k_run_2p (void)
                                        cputrace.cacheholdingdata020 = r->cacheholdingdata020;
                                        cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
                                        cputrace.prefetch020addr = r->prefetch020addr;
-                                       memcpy (&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
+                                       memcpy (&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u16));
                                        memcpy (&cputrace.caches020, &caches020, sizeof caches020);
 
                                        cputrace.memoryoffset = 0;
@@ -6740,7 +6870,7 @@ void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cn
                } else if (lookup->mnemo == i_MOVES) {
                        TCHAR *p;
                        pc += 2;
-                       if (!(extra & 0x1000)) {
+                       if (!(extra & 0x0800)) {
                                pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
                                p = instrname + _tcslen(instrname);
                                _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
@@ -7106,16 +7236,24 @@ void m68k_dumpstate (uaecptr pc, uaecptr *nextpc)
                console_out_f (_T("SRP: %llX CRP: %llX\n"), srp_030, crp_030);
                console_out_f (_T("TT0: %08X TT1: %08X TC: %08X\n"), tt0_030, tt1_030, tc_030);
        }
-       if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) {
-               struct instr *dp;
-               struct mnemolookup *lookup1, *lookup2;
-               dp = table68k + regs.irc;
-               for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++)
-                       ;
-               dp = table68k + regs.ir;
-               for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++)
-                       ;
-               console_out_f (_T("Prefetch %04x (%s) %04x (%s) Chip latch %08X\n"), regs.irc, lookup1->name, regs.ir, lookup2->name, regs.chipset_latch_rw);
+       if (currprefs.cpu_compatible) {
+               if (currprefs.cpu_model == 68000) {
+                       struct instr *dp;
+                       struct mnemolookup *lookup1, *lookup2;
+                       dp = table68k + regs.irc;
+                       for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++)
+                               ;
+                       dp = table68k + regs.ir;
+                       for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++)
+                               ;
+                       console_out_f (_T("Prefetch %04x (%s) %04x (%s) Chip latch %08X\n"), regs.irc, lookup1->name, regs.ir, lookup2->name, regs.chipset_latch_rw);
+               } else if (currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) {
+                       console_out_f (_T("Prefetch %08x %08x (%d) %04x (%d) %04x (%d) %04x (%d)\n"),
+                               regs.cacheholdingaddr020, regs.cacheholdingdata020, regs.cacheholdingdata_valid,
+                               regs.prefetch020[0], regs.prefetch020_valid[0],
+                               regs.prefetch020[1], regs.prefetch020_valid[1],
+                               regs.prefetch020[2], regs.prefetch020_valid[2]);
+               }
        }
 
        if (pc != 0xffffffff) {
@@ -7137,24 +7275,35 @@ void m68k_dumpcache (void)
                        for (int j = 0; j < 4; j++) {
                                int s = i + j;
                                uaecptr addr;
+                               int fc;
                                struct cache020 *c = &caches020[s];
+                               fc = c->tag & 1;
                                addr = c->tag & ~1;
                                addr |= s << 2;
-                               console_out_f (_T("%08X:%08X%c "), addr, c->data, c->valid ? '*' : ' ');
+                               console_out_f (_T("%08X%c:%08X%c"), addr, fc ? 'S' : 'U', c->data, c->valid ? '*' : ' ');
                        }
                        console_out_f (_T("\n"));
                }
        } else if (currprefs.cpu_model == 68030) {
-               for (int i = 0; i < CACHELINES030; i++) {
-                       struct cache030 *c = &icaches030[i];
-                       uaecptr addr;
-                       addr = c->tag & ~1;
-                       addr |= i << 4;
-                       console_out_f (_T("%08X: "), addr);
-                       for (int j = 0; j < 4; j++) {
-                               console_out_f (_T("%08X%c "), c->data[j], c->valid[j] ? '*' : ' ');
+               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] ? '*' : ' ');
+                               }
+                               console_out_f (_T("\n"));
                        }
-                       console_out_f (_T("\n"));
                }
        }
 }
@@ -7943,13 +8092,14 @@ static void end_020_cycle_prefetch(bool opcode)
 }
 
 // this one is really simple and easy
-static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr), bool opcode)
+static void fill_icache020 (uae_u32 addr, bool opcode)
 {
        int index;
        uae_u32 tag;
        uae_u32 data;
        struct cache020 *c;
 
+       regs.fc030 = (regs.s ? 4 : 0) | 2;
        addr &= ~3;
        if (regs.cacheholdingaddr020 == addr)
                return;
@@ -7960,8 +8110,10 @@ static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr), bool opcode
                // cache hit
                regs.cacheholdingaddr020 = addr;
                regs.cacheholdingdata020 = c->data;
+               regs.cacheholdingdata_valid = true;
                return;
        }
+
        // cache miss
 #if 0
        // Prefetch apparently can be queued by bus controller
@@ -7976,7 +8128,7 @@ static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr), bool opcode
 #endif
 
        start_020_cycle_prefetch(opcode);
-       data = fetch (addr);
+       data = icache_fetch(addr);
        end_020_cycle_prefetch(opcode);
 
        if (!(regs.cacr & 2)) {
@@ -7986,6 +8138,7 @@ static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr), bool opcode
        }
        regs.cacheholdingaddr020 = addr;
        regs.cacheholdingdata020 = data;
+       regs.cacheholdingdata_valid = true;
 }
 
 #if MORE_ACCURATE_68020_PIPELINE
@@ -7993,8 +8146,13 @@ static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr), bool opcode
 #if PIPELINE_DEBUG
 static uae_u16 pipeline_opcode;
 #endif
-static void pipeline_020(uae_u16 w, uaecptr pc)
+static void pipeline_020(uaecptr pc)
 {
+       uae_u16 w = regs.prefetch020[1];
+       if (regs.prefetch020_valid[1] == 0) {
+               regs.pipeline_stop = -1;
+               return;
+       }
        if (regs.pipeline_pos < 0)
                return;
        if (regs.pipeline_pos > 0) {
@@ -8080,26 +8238,23 @@ static uae_u32 get_word_ce020_prefetch_2 (int o, bool opcode)
        uae_u32 pc = m68k_getpc () + o;
        uae_u32 v;
 
-       if (pc & 2) {
-               v = regs.prefetch020[0] & 0xffff;
+       v = regs.prefetch020[0];
+       regs.prefetch020[0] = regs.prefetch020[1];
+       regs.prefetch020[1] = regs.prefetch020[2];
 #if MORE_ACCURATE_68020_PIPELINE
-               pipeline_020(regs.prefetch020[1], pc );
+       pipeline_020(pc);
 #endif
-               regs.prefetch020[0] = regs.prefetch020[1];
+       if (pc & 2) {
                // branch instruction detected in pipeline: stop fetches until branch executed.
                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
-                       fill_icache020 (pc + 2 + 4, mem_access_delay_longi_read_ce020, opcode);
-                       regs.prefetch020[1] = regs.cacheholdingdata020;
+                       fill_icache020 (pc + 2 + 4, opcode);
                }
-               regs.db = regs.prefetch020[0] >> 16;
+               regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
        } else {
-               v = regs.prefetch020[0] >> 16;
-#if MORE_ACCURATE_68020_PIPELINE
-               pipeline_020(regs.prefetch020[1] >> 16, pc);
-#endif
-               regs.db = regs.prefetch020[1] >> 16;
+               regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
        }
        do_cycles_ce020_internal (2);
+       regs.db = regs.prefetch020[0];
        return v;
 }
 
@@ -8118,24 +8273,22 @@ uae_u32 get_word_020_prefetch (int o)
        uae_u32 pc = m68k_getpc () + o;
        uae_u32 v;
 
-       if (pc & 2) {
-               v = regs.prefetch020[0] & 0xffff;
+       v = regs.prefetch020[0];
+       regs.prefetch020[0] = regs.prefetch020[1];
+       regs.prefetch020[1] = regs.prefetch020[2];
 #if MORE_ACCURATE_68020_PIPELINE
-               pipeline_020(regs.prefetch020[1], pc);
+       pipeline_020(pc);
 #endif
-               regs.prefetch020[0] = regs.prefetch020[1];
+       if (pc & 2) {
+               // branch instruction detected in pipeline: stop fetches until branch executed.
                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
-                       fill_icache020 (pc + 2 + 4, currprefs.cpu_memory_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi, false);
-                       regs.prefetch020[1] = regs.cacheholdingdata020;
+                       fill_icache020 (pc + 2 + 4, false);
                }
-               regs.db = regs.prefetch020[0] >> 16;
+               regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
        } else {
-               v = regs.prefetch020[0] >> 16;
-#if MORE_ACCURATE_68020_PIPELINE
-               pipeline_020(regs.prefetch020[1] >> 16, pc);
-#endif
-               regs.db = regs.prefetch020[0];
+               regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
        }
+       regs.db = regs.prefetch020[0];
        return v;
 }
 
@@ -8223,6 +8376,37 @@ uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr)
        return v;
 }
 
+uae_u32 mem_access_delay_wordi_read_ce020 (uaecptr addr)
+{
+       uae_u32 v;
+       start_020_cycle();
+       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:
+       case CE_MEMBANK_FAST32:
+               v = get_wordi (addr);
+               if ((addr & 3) == 3)
+                       do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
+               else
+                       do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
+                break;
+       default:
+                v = get_wordi (addr);
+               break;
+       }
+       end_020_cycle();
+       return v;
+}
+
 uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr)
 {
        uae_u32 v;
@@ -8364,7 +8548,8 @@ void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v)
 
 
 // 68030 caches aren't so simple as 68020 cache..
-STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
+
+STATIC_INLINE struct cache030 *geticache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
 {
        int index, lws;
        uae_u32 tag;
@@ -8380,7 +8565,7 @@ STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, u
        return c;
 }
 
-STATIC_INLINE void update_cache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws)
+STATIC_INLINE void update_icache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws)
 {
        if (c->tag != tag)
                c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
@@ -8389,6 +8574,32 @@ STATIC_INLINE void update_cache030 (struct cache030 *c, uae_u32 val, uae_u32 tag
        c->data[lws] = val;
 }
 
+STATIC_INLINE struct cache030 *getdcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
+{
+       int index, lws;
+       uae_u32 tag;
+       struct cache030 *c;
+
+       addr &= ~3;
+       index = (addr >> 4) & (CACHELINES030 - 1);
+       tag = addr & ~((CACHELINES030 << 4) - 1);
+       lws = (addr >> 2) & 3;
+       c = &cp[index];
+       *tagp = tag;
+       *lwsp = lws;
+       return c;
+}
+
+STATIC_INLINE void update_dcache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, uae_u8 fc, int lws)
+{
+       if (c->tag != tag)
+               c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
+       c->tag = tag;
+       c->fc = fc;
+       c->valid[lws] = true;
+       c->data[lws] = val;
+}
+
 static void fill_icache030 (uae_u32 addr)
 {
        int lws;
@@ -8396,10 +8607,11 @@ static void fill_icache030 (uae_u32 addr)
        uae_u32 data;
        struct cache030 *c;
 
+       regs.fc030 = (regs.s ? 4 : 0) | 2;
        addr &= ~3;
-       if (regs.cacheholdingaddr020 == addr)
+       if (regs.cacheholdingaddr020 == addr || regs.cacheholdingdata_valid == 0)
                return;
-       c = getcache030 (icaches030, addr, &tag, &lws);
+       c = geticache030 (icaches030, addr, &tag, &lws);
        if (c->valid[lws] && c->tag == tag) {
                // cache hit
                regs.cacheholdingaddr020 = addr;
@@ -8407,33 +8619,71 @@ static void fill_icache030 (uae_u32 addr)
                return;
        }
 
-       // cache miss
-       if (currprefs.cpu_cycle_exact) {
-               regs.ce020memcycle_data = false;
-               start_020_cycle_prefetch(false);
-               data = mem_access_delay_longi_read_ce020 (addr);
-               end_020_cycle_prefetch(false);
-       } else if (currprefs.cpu_memory_cycle_exact) {
-               data = mem_access_delay_longi_read_ce020 (addr);
-       } else {
-               data = get_longi (addr);
-       }
-       if ((regs.cacr & 3) == 1) { // not frozen and enabled
-               update_cache030 (c, data, tag, lws);
-       }
-       if ((regs.cacr & 0x11) == 0x11 && lws == 0 && !c->valid[1] && !c->valid[2] && !c->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
-               // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
-               c->data[1] = get_longi (addr + 4);
-               c->data[2] = get_longi (addr + 8);
-               c->data[3] = get_longi (addr + 12);
-               if (currprefs.cpu_cycle_exact)
-                       do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[3]);
-               c->valid[1] = c->valid[2] = c->valid[3] = true;
+       TRY (prb2) {
+               // cache miss
+               if (currprefs.cpu_cycle_exact) {
+                       regs.ce020memcycle_data = false;
+                       start_020_cycle_prefetch(false);
+                       data = icache_fetch(addr);
+                       end_020_cycle_prefetch(false);
+               } else {
+                       data = icache_fetch(addr);
+               }
+       } CATCH (prb2) {
+               // Bus error/MMU access fault: Delayed exception.
+               regs.cacheholdingdata_valid = 0;
+               regs.cacheholdingaddr020 = 0xffffffff;
+               regs.cacheholdingdata020 = 0xffffffff;
+               return;
+       } ENDTRY
+
+       if (!mmu030_cache_inhibit) {
+               if ((regs.cacr & 0x03) == 0x01) {
+                       // instruction cache not frozen and enabled
+                       update_icache030 (c, data, tag, lws);
+               }
+               if ((regs.cacr & 0x11) == 0x11 && (c->valid[0] + c->valid[1] + c->valid[2] + c->valid[3] == 1) && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
+                       // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
+                       int i;
+                       for (i = 0; i < 4; i++) {
+                               if (c->valid[i])
+                                       break;
+                       }
+                       uaecptr baddr = addr & ~15;
+                       if (currprefs.mmu_model) {
+                               if (currprefs.cpu_cycle_exact)
+                                       do_cycles_ce020(3 * (CPU020_MEM_CYCLE - 1));
+                               TRY (prb) {
+                                       for (int j = 0; j < 3; j++) {
+                                               i++;
+                                               i &= 3;
+                                               c->data[i] = icache_fetch(baddr + i * 4);
+                                               c->valid[i] = true;
+                                       }
+                               } CATCH (prb) {
+                                       ; // abort burst fetch if bus error, do not report it.
+                               } ENDTRY
+                       } else {
+                               for (int j = 0; j < 3; j++) {
+                                       i++;
+                                       i &= 3;
+                                       c->data[i] = icache_fetch(baddr + i * 4);
+                                       c->valid[i] = true;
+                               }
+                               if (currprefs.cpu_cycle_exact)
+                                       do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[3]);
+                       }
+               }
        }
        regs.cacheholdingaddr020 = addr;
        regs.cacheholdingdata020 = data;
 }
 
+STATIC_INLINE bool candcache030 (uaecptr addr)
+{
+       // mmu mode cacheability is checked in mmu030_get/mmu030_put routines
+       return currprefs.mmu_model || ce_cachable[addr >> 16] != 0;
+}
 
 #if VALIDATE_68030_DATACACHE
 static void validate_dcache030(void)
@@ -8447,7 +8697,6 @@ static void validate_dcache030(void)
                                uae_u32 v = get_long(addr);
                                if (v != c->data[j]) {
                                        write_log(_T("Address %08x data cache mismatch %08x != %08x\n"), addr, v, c->data[j]);
-                                       activate_debugger();
                                }
                        }
                        addr += 4;
@@ -8473,220 +8722,258 @@ static void validate_dcache030_read(uae_u32 addr, uae_u32 ov, int size)
 }
 #endif
 
-STATIC_INLINE bool cancache030 (uaecptr addr)
-{
-       return ce_cachable[addr >> 16] != 0;
-}
-
 // and finally the worst part, 68030 data cache..
-static void write_dcache030x(uaecptr addr, uae_u32 val, int size)
-{
-       struct cache030 *c1, *c2;
-       int lws1, lws2;
-       uae_u32 tag1, tag2;
-       int aligned = addr & 3;
-       int wa = regs.cacr & 0x2000;
-       int hit;
-
-       if (!(regs.cacr & 0x100)) // data cache disabled?
-               return;
-       if (!cancache030(addr))
-               return;
-
-       c1 = getcache030(dcaches030, addr, &tag1, &lws1);
-
-       // easy one
-       if (size == 2 && aligned == 0 && wa) {
-               update_cache030(c1, val, tag1, lws1);
-               return;
-       }
-
-       hit = (c1->tag == tag1 && c1->valid[lws1]);
-       if (hit || wa) {
-               if (size == 2) {
-                       if (hit) {
-                               c1->data[lws1] &= ~(0xffffffff >> (aligned * 8));
-                               c1->data[lws1] |= val >> (aligned * 8);
-                       } else
-                               c1->valid[lws1] = false;
-               } else if (size == 1) {
-                       if (hit) {
-                               c1->data[lws1] &= ~(0xffff0000 >> (aligned * 8));
-                               c1->data[lws1] |= (val << 16) >> (aligned * 8);
-                       } else
+static void write_dcache030x(uaecptr addr, uae_u32 val, uae_u32 size, uae_u32 fc)
+{
+       if (regs.cacr & 0x100) {
+               static const uae_u32 mask[3] = { 0xff000000, 0xffff0000, 0xffffffff };
+               struct cache030 *c1, *c2;
+               int lws1, lws2;
+               uae_u32 tag1, tag2;
+               int aligned = addr & 3;
+               int wa = regs.cacr & 0x2000;
+               int width = 8 << size;
+               int offset = 8 * aligned;
+               int hit;
+
+               c1 = getdcache030(dcaches030, addr, &tag1, &lws1);
+               hit = c1->tag == tag1 && c1->fc == fc && c1->valid[lws1];
+
+               // Write-allocate can create new valid cache entry if
+               // long aligned long write and MMU CI is not active.
+               // All writes ignore external CIIN signal.
+
+               if (width == 32 && offset == 0 && wa) {
+                       if (mmu030_cache_inhibit <= 0) {
+                               update_dcache030(c1, val, tag1, fc, lws1);
+#if VALIDATE_68030_DATACACHE
+                               validate_dcache030();
+#endif
+                       } else if (hit) {
+                               // Does real 68030 do this if MMU cache inhibited?
                                c1->valid[lws1] = false;
-               } else if (size == 0) {
+                       }
+                       return;
+               }
+
+               val <<= (32 - width);
+               if (hit || wa) {
                        if (hit) {
-                               c1->data[lws1] &= ~(0xff000000 >> (aligned * 8));
-                               c1->data[lws1] |= (val << 24) >> (aligned * 8);
-                       } else
+                               c1->data[lws1] &= ~(mask[size] >> offset);
+                               c1->data[lws1] |= val >> offset;
+                       } else {
                                c1->valid[lws1] = false;
+                       }
                }
-       }
 
-       // do we need to update a 2nd cache entry ?
-       if ((size == 0) || (size == 1 && aligned <= 2) || (size == 2 && aligned == 0))
-               return;
-
-       c2 = getcache030(dcaches030, addr + 4, &tag2, &lws2);
-       hit = (c2->tag == tag2 && c2->valid[lws2]);
-       if (hit || wa) {
-               if (size == 2) {
-                       if (hit) {
-                               c2->data[lws2] &= 0xffffffff >> (aligned * 8);
-                               c2->data[lws2] |= val << ((4 - aligned) * 8);
-                       } else
-                               c2->valid[lws2] = false;
-               } else if (size == 1) {
-                       if (hit) {
-                               c2->data[lws2] &= 0x00ffffff;
-                               c2->data[lws2] |= val << 24;
-                       } else
-                               c2->valid[lws2] = false;
+               // do we need to update a 2nd cache entry ?
+               if (width + offset > 32) {
+                       c2 = getdcache030(dcaches030, addr + 4, &tag2, &lws2);
+                       hit = c2->tag == tag2 && c2->fc == fc && c2->valid[lws2];
+                       if (hit || wa) {
+                               if (hit) {
+                                       c2->data[lws2] &= ~(mask[size] << (width + offset - 32));
+                                       c2->data[lws2] |= val << (width + offset - 32);
+                               } else {
+                                       c2->valid[lws2] = false;
+                               }
+                       }
                }
+#if VALIDATE_68030_DATACACHE
+               validate_dcache030();
+#endif
        }
 }
 
-void write_dcache030(uaecptr addr, uae_u32 v, int size)
+void write_dcache030(uaecptr addr, uae_u32 v, uae_u32 size, uae_u32 fc)
 {
-       write_dcache030x(addr, v, size);
-       if (currprefs.cpu_memory_cycle_exact) {
-               if (size == 2)
-                       mem_access_delay_long_write_ce020(addr, v);
-               else if (size == 1)
-                       mem_access_delay_word_write_ce020(addr, v);
-               else
-                       mem_access_delay_byte_write_ce020(addr, v);
-       } else {
-               if (size == 2)
-                       put_long(addr, v);
-               else if (size == 1)
-                       put_word(addr, v);
-               else
-                       put_byte(addr, v);
-       }
-#if VALIDATE_68030_DATACACHE
-       validate_dcache030();
-#endif
+       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);
 }
 
-uae_u32 read_dcache030 (uaecptr addr, int size)
+static void dcache030_maybe_burst(uaecptr addr, struct cache030 *c, int lws)
 {
-       struct cache030 *c1, *c2;
-       int lws1, lws2;
-       uae_u32 tag1, tag2;
-       int aligned = addr & 3;
-       uae_u32 v1, v2;
-#if VALIDATE_68030_DATACACHE
-       uae_u32 addr2 = addr;
-#endif
-
-       if (!(regs.cacr & 0x100) || !cancache030 (addr)) { // data cache disabled?
-               if (currprefs.cpu_memory_cycle_exact) {
-                       if (size == 2)
-                               return mem_access_delay_long_read_ce020 (addr);
-                       else if (size == 1)
-                               return mem_access_delay_word_read_ce020 (addr);
-                       else
-                               return mem_access_delay_byte_read_ce020 (addr);
+       if ((c->valid[0] + c->valid[1] + c->valid[2] + c->valid[3] == 1) && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
+               // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
+               int i;
+               uaecptr baddr = addr & ~15;
+               for (i = 0; i < 4; i++) {
+                       if (c->valid[i])
+                               break;
+               }
+               if (currprefs.mmu_model) {
+                       TRY (prb) {
+                               if (currprefs.cpu_cycle_exact)
+                                       do_cycles_ce020(3 * (CPU020_MEM_CYCLE - 1));
+                               for (int j = 0; j < 3; j++) {
+                                       i++;
+                                       i &= 3;
+                                       c->data[i] = dcache030_lget (baddr + i * 4);
+                                       c->valid[i] = true;
+                               }
+                       } CATCH (prb) {
+                               ; // abort burst fetch if bus error
+                       } ENDTRY
                } else {
-                       if (size == 2)
-                               return get_long (addr);
-                       else if (size == 1)
-                               return get_word (addr);
-                       else
-                               return get_byte (addr);
+                       for (int j = 0; j < 3; j++) {
+                               i++;
+                               i &= 3;
+                               c->data[i] = dcache030_lget (baddr + i * 4);
+                               c->valid[i] = true;
+                       }
+                       if (currprefs.cpu_cycle_exact)
+                               do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[i]);
                }
-       }
-       c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
-       addr &= ~3;
-       if (!c1->valid[lws1] || c1->tag != tag1) {
-               v1 = currprefs.cpu_memory_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
-               update_cache030 (c1, v1, tag1, lws1);
 #if VALIDATE_68030_DATACACHE
                validate_dcache030();
 #endif
-       } else {
-               v1 = c1->data[lws1];
-               if (uae_boot_rom_type > 0) {
-                       // 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 != v1) {
-                               write_log(_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
-                                       size, aligned, addr, tv, v1, tag1, lws1, M68K_GETPC);
-                               v1 = tv;
-                       }
-               }
        }
+}
 
-       // only one long fetch needed?
-       if (size == 0) {
-               v1 >>= (3 - aligned) * 8;
+#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;
+       regs.fc030 = fc;
+       if ((regs.cacr & 0x100) && !dcache_complete_inhibit) { // data cache enabled?
+               static const uae_u32 mask[3] = { 0x000000ff, 0x0000ffff, 0xffffffff };
+               struct cache030 *c1, *c2;
+               int lws1, lws2;
+               uae_u32 tag1, tag2;
+               int aligned = addr & 3;
+               uae_u32 v1, v2;
+               int width = 8 << size;
+               int offset = 8 * aligned;
+               uae_u32 out;
+
+               c1 = getdcache030 (dcaches030, addr, &tag1, &lws1);
+               addr &= ~3;
+               if (!c1->valid[lws1] || c1->tag != tag1 || c1->fc != fc) {
+                       // Cache miss and caching inhibited -> normal read
+                       if (mmu030_cache_inhibit || !candcache030(addr))
+                               goto end;
+                       // MMU validate address, returns zero if valid but uncacheable
+                       // throws bus error if invalid
+                       if (!dcache030_check(addr_o, false, size))
+                               goto end;
+                       v1 = dcache030_lget(addr);
+                       update_dcache030 (c1, v1, tag1, fc, lws1);
+                       if (!mmu030_cache_inhibit && (regs.cacr & 0x1100) == 0x1100)
+                               dcache030_maybe_burst(addr, c1, lws1);
 #if VALIDATE_68030_DATACACHE
-               validate_dcache030_read(addr2, v1, size);
+                       validate_dcache030();
 #endif
-               return v1;
-       } else if (size == 1 && aligned <= 2) {
-               v1 >>= (2 - aligned) * 8;
-#if VALIDATE_68030_DATACACHE
-               validate_dcache030_read(addr2, v1, size);
+               } 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
-               return v1;
-       } else if (size == 2 && aligned == 0) {
-               if ((regs.cacr & 0x1100) == 0x1100 && lws1 == 0 && !c1->valid[1] && !c1->valid[2] && !c1->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
-                       // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
-                       c1->data[1] = get_long (addr + 4);
-                       c1->data[2] = get_long (addr + 8);
-                       c1->data[3] = get_long (addr + 12);
-                       do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c1->data[3]);
-                       c1->valid[1] = c1->valid[2] = c1->valid[3] = true;
                }
+
+               // only one long fetch needed?
+               if (width + offset <= 32) {
+                       out = v1 >> (32 - (offset + width));
+                       out &= mask[size];
 #if VALIDATE_68030_DATACACHE
-               validate_dcache030_read(addr2, v1, size);
-               validate_dcache030();
-#endif
-               return v1;
-       }
-       // no, need another one
-       addr += 4;
-       c2 = getcache030 (dcaches030, addr, &tag2, &lws2);
-       if (!c2->valid[lws2] || c2->tag != tag2) {
-               v2 = currprefs.cpu_memory_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
-               update_cache030 (c2, v2, tag2, lws2);
+                       validate_dcache030_read(addr_o, out, size);
+#endif
+                       return out;
+               }
+
+               // no, need another one
+               addr += 4;
+               c2 = getdcache030 (dcaches030, addr, &tag2, &lws2);
+               if (!c2->valid[lws2] || c2->tag != tag2 || c2->fc != fc) {
+                       if (mmu030_cache_inhibit || !candcache030(addr))
+                               goto end;
+                       if (!dcache030_check(addr, false, 2))
+                               goto end;
+                       v2 = dcache030_lget(addr);
+                       update_dcache030 (c2, v2, tag2, fc, lws2);
+                       if (!mmu030_cache_inhibit && (regs.cacr & 0x1100) == 0x1100)
+                               dcache030_maybe_burst(addr, c2, lws2);
 #if VALIDATE_68030_DATACACHE
-               validate_dcache030();
+                       validate_dcache030();
 #endif
-       } else {
-               v2 = c2->data[lws2];
-               if (uae_boot_rom_type > 0) {
-                       uae_u32 tv = get_long(addr);
-                       if (tv != v2) {
-                               write_log (_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
-                                       size, aligned, addr, tv, v2, tag2, lws2, M68K_GETPC);
-                               v2 = tv;
-                       }
-               }
-       }
-
-       uae_u32 ov;
-       if (size == 1 && aligned == 3) {
-               ov = (v1 << 8) | (v2 >> 24);
-       } else if (size == 2 && aligned == 1) {
-               ov = (v1 << 8) | (v2 >> 24);
-       } else if (size == 2 && aligned == 2) {
-               ov = (v1 << 16) | (v2 >> 16);
-       } else if (size == 2 && aligned == 3) {
-               ov =  (v1 << 24) | (v2 >> 8);
-       } else {
-               write_log (_T("dcache030 weirdness!?\n"));
-               ov = 0;
-       }
+               } else {
+                       v2 = c2->data[lws2];
+#if 0
+                       uae_cache_check(addr, &v2, c2, lws2, size);
+#endif
+               }
+
+               uae_u64 v64 = ((uae_u64)v1 << 32) | v2;
+               out = (uae_u32)(v64 >> (64 - (offset + width)));
+               out &= mask[size];
+
 #if VALIDATE_68030_DATACACHE
-       validate_dcache030_read(addr2, ov, size);
+               validate_dcache030_read(addr_o, out, size);
 #endif
-       return ov;
+               return out;
+
+       }
+end:
+       // read from memory, data cache is disabled or inhibited.
+       if (size == 2)
+               return dcache030_lget (addr_o);
+       else if (size == 1)
+               return dcache030_wget (addr_o);
+       else
+               return dcache030_bget (addr_o);
+}
+
+uae_u32 read_dcache030_mmu(uaecptr addr, uae_u32 size)
+{
+       return read_dcache030(addr, size, (regs.s ? 4 : 0) | 1);
+}
+void write_dcache030_mmu(uaecptr addr, uae_u32 val, uae_u32 size)
+{
+       write_dcache030(addr, val, size, (regs.s ? 4 : 0) | 1);
+}
+
+uae_u32 read_dcache030_lrmw_mmu(uaecptr addr, uae_u32 size)
+{
+       mmu030_cache_inhibit = 1;
+       return read_dcache030(addr, size, (regs.s ? 4 : 0) | 1);
+}
+void write_dcache030_lrmw_mmu(uaecptr addr, uae_u32 val, uae_u32 size)
+{
+       mmu030_cache_inhibit = 1;
+       write_dcache030(addr, val, size, (regs.s ? 4 : 0) | 1);
+}
+
+static void do_access_or_bus_error(uaecptr pc, uaecptr pcnow)
+{
+       // TODO: handle external bus errors
+       if (!currprefs.mmu_model)
+               return;
+       if (pc != 0xffffffff)
+               regs.instruction_pc = pc;
+       mmu030_opcode = -1;
+       mmu030_page_fault(pcnow, true, -1, 0);
 }
 
 static uae_u32 get_word_ce030_prefetch_2 (int o)
@@ -8694,23 +8981,30 @@ static uae_u32 get_word_ce030_prefetch_2 (int o)
        uae_u32 pc = m68k_getpc () + o;
        uae_u32 v;
 
-       if (pc & 2) {
-               v = regs.prefetch020[0] & 0xffff;
+       v = regs.prefetch020[0];
+       regs.prefetch020[0] = regs.prefetch020[1];
+       regs.prefetch020[1] = regs.prefetch020[2];
 #if MORE_ACCURATE_68020_PIPELINE
-               pipeline_020(regs.prefetch020[1], pc);
+       pipeline_020(pc);
 #endif
-               regs.prefetch020[0] = regs.prefetch020[1];
+       if (pc & 2) {
                // branch instruction detected in pipeline: stop fetches until branch executed.
                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
                        fill_icache030 (pc + 2 + 4);
-                       regs.prefetch020[1] = regs.cacheholdingdata020;
+               } else {
+                       if (regs.cacheholdingdata_valid > 0)
+                               regs.cacheholdingdata_valid++;
                }
+               regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
        } else {
-               v = regs.prefetch020[0] >> 16;
-#if MORE_ACCURATE_68020_PIPELINE
-               pipeline_020(regs.prefetch020[1] >> 16, pc);
-#endif
+               pc += 4;
+               // cacheholdingdata020 may be invalid if RTE from bus error
+               if ((!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) && regs.cacheholdingaddr020 != pc) {
+                       fill_icache030 (pc);
+               }
+               regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
        }
+       regs.db = regs.prefetch020[0];
        do_cycles_ce020_internal (2);
        return v;
 }
@@ -8724,28 +9018,39 @@ uae_u32 get_word_ce030_prefetch_opcode (int o)
        return get_word_ce030_prefetch_2(o);
 }
 
-uae_u32 get_word_030_prefetch(int o)
+uae_u32 get_word_030_prefetch (int o)
 {
-       uae_u32 pc = m68k_getpc() + o;
+       uae_u32 pc = m68k_getpc () + o;
        uae_u32 v;
 
-       if (pc & 2) {
-               v = regs.prefetch020[0] & 0xffff;
+       v = regs.prefetch020[0];
+       regs.prefetch020[0] = regs.prefetch020[1];
+       regs.prefetch020[1] = regs.prefetch020[2];
+       if (!regs.prefetch020_valid[1]) {
+               do_access_or_bus_error(0xffffffff, pc);
+       }
 #if MORE_ACCURATE_68020_PIPELINE
-               pipeline_020(regs.prefetch020[1], pc);
+       pipeline_020(pc);
 #endif
-               regs.prefetch020[0] = regs.prefetch020[1];
+       if (pc & 2) {
                // branch instruction detected in pipeline: stop fetches until branch executed.
                if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
-                       fill_icache030(pc + 2 + 4);
-                       regs.prefetch020[1] = regs.cacheholdingdata020;
+                       fill_icache030 (pc + 2 + 4);
+               } else {
+                       if (regs.cacheholdingdata_valid > 0)
+                               regs.cacheholdingdata_valid++;
                }
+               regs.prefetch020[2] = regs.cacheholdingdata020 >> 16;
        } else {
-               v = regs.prefetch020[0] >> 16;
-#if MORE_ACCURATE_68020_PIPELINE
-               pipeline_020(regs.prefetch020[1] >> 16, pc);
-#endif
+               pc += 4;
+               // cacheholdingdata020 may be invalid if RTE from bus error
+               if ((!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) && regs.cacheholdingaddr020 != pc) {
+                       fill_icache030 (pc);
+               }
+               regs.prefetch020[2] = (uae_u16)regs.cacheholdingdata020;
        }
+       regs.prefetch020_valid[2] = regs.cacheholdingdata_valid;
+       regs.db = regs.prefetch020[0];
        return v;
 }
 
@@ -9150,69 +9455,165 @@ void check_t0_trace(void)
        }
 }
 
-void fill_prefetch_030_ntx (void)
+static void reset_pipeline_state(void)
+{
+#if MORE_ACCURATE_68020_PIPELINE
+       regs.pipeline_pos = 0;
+       regs.pipeline_stop = 0;
+       regs.pipeline_r8[0] = regs.pipeline_r8[1] = -1;
+#endif
+}
+
+static int add_prefetch_030(int idx, uae_u16 w, uaecptr pc)
+{
+       regs.prefetch020[0] = regs.prefetch020[1];
+       regs.prefetch020_valid[0] = regs.prefetch020_valid[1];
+       regs.prefetch020[1] = regs.prefetch020[2];
+       regs.prefetch020_valid[1] = regs.prefetch020_valid[2];
+       regs.prefetch020[2] = w;
+       regs.prefetch020_valid[2] = regs.cacheholdingdata_valid;
+
+#if MORE_ACCURATE_68020_PIPELINE
+       if (idx >= 1) {
+               pipeline_020(pc);
+       }
+#endif
+
+       if  (!regs.prefetch020_valid[2]) {
+               if (idx == 0 || !regs.pipeline_stop) {
+                       // Pipeline refill and first opcode word is invalid?
+                       // Generate previously detected bus error/MMU fault
+                       do_access_or_bus_error(pc, pc + idx * 2);
+               }
+       }
+       return idx + 1;
+}
+
+void fill_prefetch_030_ntx(void)
 {
        uaecptr pc = m68k_getpc ();
        uaecptr pc2 = pc;
+       int idx = 0;
+
        pc &= ~3;
-       regs.pipeline_pos = 0;
-       regs.pipeline_stop = 0;
+       mmu030_idx = 0;
+       reset_pipeline_state();
+       regs.cacheholdingdata_valid = 1;
+       regs.cacheholdingaddr020 = 0xffffffff;
+       regs.prefetch020_valid[0] = regs.prefetch020_valid[1] = regs.prefetch020_valid[2] = 0;
 
-       fill_icache030 (pc);
+       fill_icache030(pc);
        if (currprefs.cpu_cycle_exact)
                do_cycles_ce020_internal(2);
-       regs.prefetch020[0] = regs.cacheholdingdata020;
+       if (pc2 & 2) {
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc2);
+       } else {
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc2);
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc2);
+       }
 
-       fill_icache030 (pc + 4);
+       fill_icache030(pc + 4);
        if (currprefs.cpu_cycle_exact)
                do_cycles_ce020_internal(2);
-       regs.prefetch020[1] = regs.cacheholdingdata020;
-
-#if MORE_ACCURATE_68020_PIPELINE
        if (pc2 & 2) {
-               pipeline_020(regs.prefetch020[0], pc);
-               pipeline_020(regs.prefetch020[1] >> 16, pc);
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc2);
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc2);
        } else {
-               pipeline_020(regs.prefetch020[0] >> 16, pc);
-               pipeline_020(regs.prefetch020[0], pc);
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc2);
        }
+
+       if (currprefs.cpu_cycle_exact)
+               regs.irc = get_word_ce030_prefetch_opcode (0);
+       else
+               regs.irc = get_word_030_prefetch (0);
+}
+
+void fill_prefetch_030_ntx_continue (void)
+{
+       uaecptr pc = m68k_getpc ();
+       uaecptr pc_orig = pc;
+       int idx = 0;
+
+       mmu030_idx = 0;
+       reset_pipeline_state();
+       regs.cacheholdingdata_valid = 1;
+       regs.cacheholdingaddr020 = 0xffffffff;
+
+       for (int i = 2; i >= 0; i--) {
+               if (!regs.prefetch020_valid[i])
+                       break;
+#if MORE_ACCURATE_68020_PIPELINE
+               if (idx >= 1) {
+                       pipeline_020(pc);
+               }
 #endif
+               pc += 2;
+               idx++;
+       }
+
+       if (idx < 3 && !regs.pipeline_stop) {
+               uaecptr pc2 = pc;
+               pc &= ~3;
+
+               fill_icache030(pc);
+               if (currprefs.cpu_cycle_exact)
+                       do_cycles_ce020_internal(2);
+               if (pc2 & 2) {
+                       idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc_orig);
+               } else {
+                       idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc_orig);
+                       if (idx < 3)
+                               idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc_orig);
+               }
+
+               if (idx < 3) {
+                       fill_icache030(pc + 4);
+                       if (currprefs.cpu_cycle_exact)
+                               do_cycles_ce020_internal(2);
+                       if (pc2 & 2) {
+                               idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc_orig);
+                               if (idx < 3)
+                                       idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc_orig);
+                       } else {
+                               idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc_orig);
+                       }
+               }
+       }
 
        if (currprefs.cpu_cycle_exact)
                regs.irc = get_word_ce030_prefetch_opcode (0);
        else
-               regs.irc = get_word_030_prefetch(0);
+               regs.irc = get_word_030_prefetch (0);
 }
 
 void fill_prefetch_020_ntx(void)
 {
        uaecptr pc = m68k_getpc ();
        uaecptr pc2 = pc;
+       int idx = 0;
+
        pc &= ~3;
-       uae_u32 (*fetch)(uaecptr) = currprefs.cpu_memory_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi;
-       regs.pipeline_pos = 0;
-       regs.pipeline_stop = 0;
-       regs.pipeline_r8[0] = regs.pipeline_r8[1] = -1;
+       reset_pipeline_state();
 
-       fill_icache020 (pc, fetch, true);
+       fill_icache020 (pc, true);
        if (currprefs.cpu_cycle_exact)
                do_cycles_ce020_internal(2);
-       regs.prefetch020[0] = regs.cacheholdingdata020;
+       if (pc2 & 2) {
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc);
+       } else {
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc);
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc);
+       }
 
-       fill_icache020 (pc + 4, fetch, true);
+       fill_icache020 (pc + 4, true);
        if (currprefs.cpu_cycle_exact)
                do_cycles_ce020_internal(2);
-       regs.prefetch020[1] = regs.cacheholdingdata020;
-
-#if MORE_ACCURATE_68020_PIPELINE
        if (pc2 & 2) {
-               pipeline_020(regs.prefetch020[0], pc);
-               pipeline_020(regs.prefetch020[1] >> 16, pc);
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc);
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020, pc);
        } else {
-               pipeline_020(regs.prefetch020[0] >> 16, pc);
-               pipeline_020(regs.prefetch020[0], pc);
+               idx = add_prefetch_030(idx, regs.cacheholdingdata020 >> 16, pc);
        }
-#endif
 
        if (currprefs.cpu_cycle_exact)
                regs.irc = get_word_ce020_prefetch_opcode (0);
@@ -9254,7 +9655,7 @@ void fill_prefetch_030(void)
 
 void fill_prefetch (void)
 {
-       regs.pipeline_pos = 0;
+       reset_pipeline_state();
        if (currprefs.cachesize)
                return;
        if (!currprefs.cpu_compatible)
index 9af217ed5a1b259cb36353ca034e50268b8d89c7..3d33d0e633a5946f85acee477230796b8fbacf8f 100644 (file)
@@ -65,6 +65,7 @@
 #define CPUEMU_31 /* Aranym 68040 MMU */
 #define CPUEMU_32 /* Previous 68030 MMU */
 #define CPUEMU_33 /* 68060 MMU */
+#define CPUEMU_34 /* 68030 MMU + cache */
 #define CPUEMU_40 /* generic 680x0 with JIT direct memory access */
 #define CPUEMU_50 /* generic 680x0 with indirect memory access */
 #define ACTION_REPLAY /* Action Replay 1/2/3 support */