]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68030 + MMU + caches + "cycle-exact" support. 68040 MMU cache inhibit (CI) and full...
authorToni Wilen <twilen@winuae.net>
Tue, 1 Aug 2017 19:06:47 +0000 (22:06 +0300)
committerToni Wilen <twilen@winuae.net>
Tue, 1 Aug 2017 19:06:47 +0000 (22:06 +0300)
cpummu.cpp
cpummu30.cpp
gencpu.cpp
include/cpummu.h
include/newcpu.h
newcpu.cpp
od-win32/sysconfig.h

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