Re: [hatari-devel] MEMWATCH freezes Hatari

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


Here is simple and quick but not optimal (extra check needed in common
path) patch that should implement missing handling of modified SSW FC
bits when data fault is retried.

Please confirm. Obviously I don't have any tests cases :)

diff --git a/include/cpummu030.h b/include/cpummu030.h
index e321c9d0..221ceaa0 100644
--- a/include/cpummu030.h
+++ b/include/cpummu030.h
@@ -18,6 +18,7 @@ extern int mmu030_idx;
 extern bool mmu030_retry;
 extern int mmu030_opcode, mmu030_opcode_stageb;
 extern int mmu030_fake_prefetch;
+extern int mmu030_df_fc;
 extern uaecptr mmu030_fake_prefetch_addr;
 extern uae_u16 mmu030_state[3];
 extern uae_u32 mmu030_data_buffer;
@@ -82,9 +83,26 @@ extern uae_u32 REGPARAM3 mmu030_get_lrmw_long_unaligned(uaecptr addr, uae_u32 fc
 extern void REGPARAM3 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc, int flags) REGPARAM;
 extern void REGPARAM3 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc, int flags) REGPARAM;
 
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_fc_code(void)
+{
+	return (regs.s ? 4 : 0) | 2;
+}
+
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_fc_data(void)
+{
+	uae_u32 fc;
+	if (mmu030_df_fc < 0) {
+		fc = (regs.s ? 4 : 0) | 1;
+	} else {
+		fc = mmu030_df_fc;
+		mmu030_df_fc = -1;
+	}
+	return fc;
+}
+
 static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong(uaecptr addr)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 2;
+	uae_u32 fc = uae_mmu030_get_fc_code();
 
 	if (unlikely(is_unaligned(addr, 4)))
 		return mmu030_get_ilong_unaligned(addr, fc, 0);
@@ -92,18 +110,20 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong(uaecptr addr)
 }
 static ALWAYS_INLINE uae_u16 uae_mmu030_get_iword(uaecptr addr)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 2;
+	uae_u32 fc = uae_mmu030_get_fc_code();
+
 	return mmu030_get_iword(addr, fc);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu030_get_ibyte(uaecptr addr)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 2;
+	uae_u32 fc = uae_mmu030_get_fc_code();
 
 	return mmu030_get_byte(addr, fc);
 }
+
 static ALWAYS_INLINE uae_u32 uae_mmu030_get_long(uaecptr addr)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 1;
+	uae_u32 fc = uae_mmu030_get_fc_data();
 
 	if (unlikely(is_unaligned(addr, 4)))
 		return mmu030_get_long_unaligned(addr, fc, 0);
@@ -111,7 +131,7 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_long(uaecptr addr)
 }
 static ALWAYS_INLINE uae_u32 uae_mmu030_get_word(uaecptr addr)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 1;
+	uae_u32 fc = uae_mmu030_get_fc_data();
 
 	if (unlikely(is_unaligned(addr, 2)))
 		return mmu030_get_word_unaligned(addr, fc, 0);
@@ -119,14 +139,15 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_word(uaecptr addr)
 }
 static ALWAYS_INLINE uae_u32 uae_mmu030_get_byte(uaecptr addr)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 1;
+	uae_u32 fc = uae_mmu030_get_fc_data();
 
 	return mmu030_get_byte(addr, fc);
 }
+
 static ALWAYS_INLINE void uae_mmu030_put_long(uaecptr addr, uae_u32 val)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 1;
-    
+	uae_u32 fc = uae_mmu030_get_fc_data();
+
 	if (unlikely(is_unaligned(addr, 4)))
 		mmu030_put_long_unaligned(addr, val, fc, 0);
 	else
@@ -134,7 +155,7 @@ static ALWAYS_INLINE void uae_mmu030_put_long(uaecptr addr, uae_u32 val)
 }
 static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u32 val)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 1;
+	uae_u32 fc = uae_mmu030_get_fc_data();
 
 	if (unlikely(is_unaligned(addr, 2)))
 		mmu030_put_word_unaligned(addr, val, fc, 0);
@@ -143,7 +164,7 @@ static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u32 val)
 }
 static ALWAYS_INLINE void uae_mmu030_put_byte(uaecptr addr, uae_u32 val)
 {
-    uae_u32 fc = (regs.s ? 4 : 0) | 1;
+	uae_u32 fc = uae_mmu030_get_fc_data();
 
 	mmu030_put_byte(addr, val, fc);
 }
diff --git a/cpummu30.cpp b/cpummu30.cpp
index fd2493a3..36930b1a 100644
--- a/cpummu30.cpp
+++ b/cpummu30.cpp
@@ -64,6 +64,7 @@ int mmu030_opcode_stageb;
 
 int mmu030_fake_prefetch;
 uaecptr mmu030_fake_prefetch_addr;
+int mmu030_df_fc;
 
 uae_u16 mmu030_state[3];
 uae_u32 mmu030_data_buffer;
@@ -2492,6 +2493,7 @@ void mmu030_reset(int hardreset)
         mmusr_030 = 0;
         mmu030_flush_atc_all();
 	}
+	mmu030_df_fc = -1;
 	mmu030_set_funcs();
 }
 
@@ -2520,6 +2522,14 @@ void mmu030_set_funcs(void)
 	}
 }
 
+static bool fccanuse(uae_u16 opcode)
+{
+	// MOVES: don't set mmu030_df_fc.
+	if ((opcode & 0xff00) == 0x0e00)
+		return false;
+	return true;
+}
+
 void m68k_do_rte_mmu030 (uaecptr a7)
 {
 	// Restore access error exception state
@@ -2592,6 +2602,14 @@ void m68k_do_rte_mmu030 (uaecptr a7)
 				write_log (_T("Software fixed stage B! opcode = %04X, opword = %04x\n"), mmu030_opcode, stageb);
 			}
 		}
+
+		if ((ssw & MMU030_SSW_DF) && fccanuse(mmu030_opcode)) {
+			// If Data Fault: data fetch is retried using SSW FC mode.
+			mmu030_df_fc = ssw & 7;
+		} else {
+			mmu030_df_fc = -1;
+		}
+
 		m68k_areg (regs, 7) += 92;
 	} else {
 		m68k_areg (regs, 7) += 32;
@@ -2888,6 +2906,13 @@ void m68k_do_rte_mmu030c (uaecptr a7)
 			}
 		}
 
+		if ((ssw & MMU030_SSW_DF) && fccanuse(mmu030_opcode)) {
+			// If Data Fault: data fetch is retried using SSW FC mode.
+			mmu030_df_fc = ssw & 7;
+		} else {
+			mmu030_df_fc = -1;
+		}
+
 	} else {
 		m68k_areg (regs, 7) += 32;
 	}


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/