]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68030 MMU retry update, unaligned accesses were not retried as unaligned.
authorToni Wilen <twilen@winuae.net>
Mon, 22 Oct 2018 17:34:12 +0000 (20:34 +0300)
committerToni Wilen <twilen@winuae.net>
Mon, 22 Oct 2018 17:34:12 +0000 (20:34 +0300)
cpummu30.cpp
include/cpummu030.h

index 79cbd7100181782f87963f6f3e7a68fcc367994d..7f0cf982d6c4550f679ae24c0bf64499382f5e84 100644 (file)
@@ -2272,9 +2272,8 @@ uae_u8 uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size)
 }
 
 /* Locked RMW is rarely used */
-uae_u32 uae_mmu030_get_lrmw(uaecptr addr, int size)
+uae_u32 uae_mmu030_get_lrmw_fcx(uaecptr addr, int size, int fc)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 1;
        if (size == sz_byte) {
                return mmu030_get_generic(addr, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_B);
        } else if (size == sz_word) {
@@ -2289,9 +2288,14 @@ uae_u32 uae_mmu030_get_lrmw(uaecptr addr, int size)
                        return mmu030_get_generic(addr, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_L);
        }
 }
-void uae_mmu030_put_lrmw(uaecptr addr, uae_u32 val, int size)
+uae_u32 uae_mmu030_get_lrmw(uaecptr addr, int size)
+{
+       uae_u32 fc = (regs.s ? 4 : 0) | 1;
+       return uae_mmu030_get_lrmw_fcx(addr, size, fc);
+}
+
+void uae_mmu030_put_lrmw_fcx(uaecptr addr, uae_u32 val, int size, int fc)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 1;
        if (size == sz_byte) {
                mmu030_put_generic(addr, val, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_B);
        } else if (size == sz_word) {
@@ -2306,6 +2310,12 @@ void uae_mmu030_put_lrmw(uaecptr addr, uae_u32 val, int size)
                        mmu030_put_generic(addr, val, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_L);
        }
 }
+void uae_mmu030_put_lrmw(uaecptr addr, uae_u32 val, int size)
+{
+       uae_u32 fc = (regs.s ? 4 : 0) | 1;
+       uae_mmu030_put_lrmw_fcx(addr, val, size, fc);
+}
+
 uae_u16 REGPARAM2 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc, int flags)
 {
        uae_u16 res;
@@ -2609,36 +2619,49 @@ void m68k_do_rte_mmu030 (uaecptr a7)
                }
                m68k_setpci(pc);
 
+#if MMUDEBUG
+               if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
+                       if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM2) {
+                               write_log(_T("68030 MMU MOVEM %04x retry but MMU030_STATEFLAG1_MOVEM2 was already set!?\n"));
+                       }
+               } else {
+                       if (mmu030_ad[idxsize].done) {
+                               write_log(_T("68030 MMU ins %04x retry but it was already marked as done!?\n"));
+                       }
+               }
+#endif
+
                if (ssw & MMU030_SSW_DF) {
                        // retry faulted access
                        uaecptr addr = fault_addr;
                        bool read = (ssw & MMU030_SSW_RW) != 0;
-                       int size = (ssw & MMU030_SSW_SIZE_B) ? 1 : ((ssw & MMU030_SSW_SIZE_W) ? 2 : 4);
+                       int size = (ssw & MMU030_SSW_SIZE_B) ? sz_byte : ((ssw & MMU030_SSW_SIZE_W) ? sz_word : sz_long);
                        int fc = ssw & 7;
                        
                        if (read) {
                                uae_u32 val = 0;
-                               switch (size)
-                               {
-                                       case 1:
-                                       val = mmu030_get_byte(addr, fc);
-                                       break;
-                                       case 2:
-                                       val = mmu030_get_word(addr, fc);
-                                       break;
-                                       case 4:
-                                       val = mmu030_get_long(addr, fc);
-                                       break;
+                               if (ssw & MMU030_SSW_RM) {
+                                       val = uae_mmu030_get_lrmw_fcx(addr, size, fc);
+                               } else {
+                                       switch (size)
+                                       {
+                                               case sz_byte:
+                                               val = uae_mmu030_get_byte_fcx(addr, fc);
+                                               break;
+                                               case sz_word:
+                                               val = uae_mmu030_get_word_fcx(addr, fc);
+                                               break;
+                                               case sz_long:
+                                               val = uae_mmu030_get_long_fcx(addr, fc);
+                                               break;
+                                       }
                                }
                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
                                        mmu030_data_buffer = val;
                                        mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
-                               } else if (mmu030_state[1] & MMU030_STATEFLAG1_SKIP_INS) {
-                                       mmu030_state[0]++;
                                } else {
                                        mmu030_ad[idxsize].val = val;
                                        mmu030_ad[idxsize].done = true;
-                                       mmu030_ad[idxsize + 1].done = false;
                                }
                        } else {
                                uae_u32 val;
@@ -2646,25 +2669,26 @@ void m68k_do_rte_mmu030 (uaecptr a7)
                                        val = mdata;
                                else
                                        val = mmu030_ad[idxsize].val;
-                               switch (size)
-                               {
-                                       case 1:
-                                       mmu030_put_byte(addr, val, fc);
-                                       break;
-                                       case 2:
-                                       mmu030_put_word(addr, val, fc);
-                                       break;
-                                       case 4:
-                                       mmu030_put_long(addr, val, fc);
-                                       break;
+                               if (ssw & MMU030_SSW_RM) {
+                                       uae_mmu030_put_lrmw_fcx(addr, val, size, fc);
+                               } else {
+                                       switch (size)
+                                       {
+                                               case sz_byte:
+                                               uae_mmu030_put_byte_fcx(addr, val, fc);
+                                               break;
+                                               case sz_word:
+                                               uae_mmu030_put_word_fcx(addr, val, fc);
+                                               break;
+                                               case sz_long:
+                                               uae_mmu030_put_long_fcx(addr, val, fc);
+                                               break;
+                                       }
                                }
                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
                                        mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
-                               } else if (mmu030_state[1] & MMU030_STATEFLAG1_SKIP_INS) {
-                                       mmu030_state[0]++;
                                } else {
                                        mmu030_ad[idxsize].done = true;
-                                       mmu030_ad[idxsize + 1].done = false;
                                }
                        }
                }
@@ -2972,28 +2996,26 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                        // retry faulted access
                        uaecptr addr = fault_addr;
                        bool read = (ssw & MMU030_SSW_RW) != 0;
-                       int size = (ssw & MMU030_SSW_SIZE_B) ? 1 : ((ssw & MMU030_SSW_SIZE_W) ? 2 : 4);
+                       int size = (ssw & MMU030_SSW_SIZE_B) ? sz_byte : ((ssw & MMU030_SSW_SIZE_W) ? sz_word : sz_long);
                        int fc = ssw & 7;
 
                        if (read) {
                                uae_u32 val = 0;
                                switch (size)
                                {
-                                       case 1:
+                                       case sz_byte:
                                        val = read_dcache030_bget(addr, fc);
                                        break;
-                                       case 2:
+                                       case sz_word:
                                        val = read_dcache030_wget(addr, fc);
                                        break;
-                                       case 4:
+                                       case sz_long:
                                        val = read_dcache030_lget(addr, fc);
                                        break;
                                }
                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
                                        mmu030_data_buffer = val;
                                        mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
-                               } else if (mmu030_state[1] & MMU030_STATEFLAG1_SKIP_INS) {
-                                       mmu030_state[0]++;
                                } else {
                                        mmu030_ad[idxsize].val = val;
                                        mmu030_ad[idxsize].done = true;
@@ -3007,20 +3029,18 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                                        val = mmu030_ad[idxsize].val;
                                switch (size)
                                {
-                                       case 1:
+                                       case sz_byte:
                                        write_dcache030_bput(addr, val, fc);
                                        break;
-                                       case 2:
+                                       case sz_word:
                                        write_dcache030_wput(addr, val, fc);
                                        break;
-                                       case 4:
+                                       case sz_long:
                                        write_dcache030_lput(addr, val, fc);
                                        break;
                                }
                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
                                        mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
-                               } else if (mmu030_state[1] & MMU030_STATEFLAG1_SKIP_INS) {
-                                       mmu030_state[0]++;
                                } else {
                                        mmu030_ad[idxsize].done = true;
                                        mmu030_ad[idxsize + 1].done = false;
index b123f838705a1e0cdf9726d726d12b4ed020421e..b5f52d9db28fbc1cb6f97f7acb715cbb348baaeb 100644 (file)
@@ -25,7 +25,6 @@ extern uae_u32 mmu030_disp_store[2];
 extern uae_u32 mmu030_fmovem_store[2];
 extern uae_u8 mmu030_cache_state, mmu030_cache_state_default;
 
-#define MMU030_STATEFLAG1_SKIP_INS 0x1000
 #define MMU030_STATEFLAG1_FMOVEM 0x2000
 #define MMU030_STATEFLAG1_MOVEM1 0x4000
 #define MMU030_STATEFLAG1_MOVEM2 0x8000
@@ -70,7 +69,9 @@ uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc);
 uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc);
 
 uae_u32 uae_mmu030_get_lrmw(uaecptr addr, int size);
+uae_u32 uae_mmu030_get_lrmw_fcx(uaecptr addr, int size, int fc);
 void uae_mmu030_put_lrmw(uaecptr addr, uae_u32 val, int size);
+void uae_mmu030_put_lrmw_fcx(uaecptr addr, uae_u32 val, int size, int fc);
 
 void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int flags);
 uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int flags);
@@ -212,6 +213,42 @@ static ALWAYS_INLINE void uae_mmu030_put_byte_fc(uaecptr addr, uae_u32 val)
 }
 uae_u8 uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size);
 
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_long_fcx(uaecptr addr, int fc)
+{
+       if (unlikely(is_unaligned(addr, 4)))
+               return mmu030_get_long_unaligned(addr, fc, 0);
+       return mmu030_get_long(addr, fc);
+}
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_word_fcx(uaecptr addr, int fc)
+{
+       if (unlikely(is_unaligned(addr, 2)))
+               return mmu030_get_word_unaligned(addr, fc, 0);
+       return mmu030_get_word(addr, fc);
+}
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_byte_fcx(uaecptr addr, int fc)
+{
+       return mmu030_get_byte(addr, fc);
+}
+static ALWAYS_INLINE void uae_mmu030_put_long_fcx(uaecptr addr, uae_u32 val, int fc)
+{
+       if (unlikely(is_unaligned(addr, 4)))
+               mmu030_put_long_unaligned(addr, val, fc, 0);
+       else
+               mmu030_put_long(addr, val, fc);
+}
+static ALWAYS_INLINE void uae_mmu030_put_word_fcx(uaecptr addr, uae_u32 val, int fc)
+{
+       if (unlikely(is_unaligned(addr, 2)))
+               mmu030_put_word_unaligned(addr, val, fc, 0);
+       else
+               mmu030_put_word(addr, val, fc);
+}
+static ALWAYS_INLINE void uae_mmu030_put_byte_fcx(uaecptr addr, uae_u32 val, int fc)
+{
+       mmu030_put_byte(addr, val, fc);
+}
+
+
 #define ACCESS_CHECK_PUT \
        if (!mmu030_ad[mmu030_idx].done) { \
                mmu030_ad[mmu030_idx].val = v; \