Re: [hatari-devel] MEMWATCH freezes Hatari |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/hatari-devel Archives
]
Le 12/10/2018 à 20:44, Nicolas Pomarède a écrit :
I will try to provide an updated patch for Hatari later this evening.
Here's the corresponding patch for Hatari ; I didn't test it as I don't
know which program Uwe used to trigger the bug
Nicolas
diff -r e87617b4fe45 src/cpu/cpummu030.c
--- a/src/cpu/cpummu030.c Thu Oct 11 18:30:37 2018 +0200
+++ b/src/cpu/cpummu030.c Fri Oct 12 23:18:49 2018 +0200
@@ -69,6 +69,7 @@
int mmu030_fake_prefetch;
uaecptr mmu030_fake_prefetch_addr;
+int mmu030_df_fc;
uae_u16 mmu030_state[3];
uae_u32 mmu030_data_buffer;
@@ -2510,6 +2511,7 @@
mmusr_030 = 0;
mmu030_flush_atc_all();
}
+ mmu030_df_fc = -1;
mmu030_set_funcs();
}
@@ -2538,6 +2540,14 @@
}
}
+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
@@ -2610,6 +2620,14 @@
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;
@@ -2658,6 +2676,7 @@
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;
@@ -2906,6 +2925,13 @@
}
}
+ 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;
}
diff -r e87617b4fe45 src/cpu/cpummu030.h
--- a/src/cpu/cpummu030.h Thu Oct 11 18:30:37 2018 +0200
+++ b/src/cpu/cpummu030.h Fri Oct 12 23:18:49 2018 +0200
@@ -18,6 +18,7 @@
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 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_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_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_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_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_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);
}