]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68030 MMU update. Unaligned accesses are now new exception handler emulation compatib...
authorToni Wilen <twilen@winuae.net>
Fri, 23 Nov 2018 20:14:39 +0000 (22:14 +0200)
committerToni Wilen <twilen@winuae.net>
Fri, 23 Nov 2018 20:14:39 +0000 (22:14 +0200)
cpummu.cpp
cpummu30.cpp
fpp.cpp
gencpu.cpp
include/cpummu.h
include/cpummu030.h
include/mmu_common.h
newcpu.cpp

index 6c9927c183155f091ba8b5ca000edbc50564b72a..9d76d39b2a04f8cb2f7eef17e4075ec25bb03042 100644 (file)
@@ -1109,7 +1109,7 @@ uae_u32 REGPARAM2 sfc_get_long(uaecptr addr)
        uae_u32 res;
 
        ismoves = true;
-       if (likely(!is_unaligned(addr, 4))) {
+       if (likely(!is_unaligned_page(addr, 4))) {
                res = mmu_get_user_long(addr, super, false, sz_long, false);
        } else {
                if (likely(!(addr & 1))) {
@@ -1151,7 +1151,7 @@ uae_u16 REGPARAM2 sfc_get_word(uaecptr addr)
        uae_u16 res;
 
        ismoves = true;
-       if (likely(!is_unaligned(addr, 2))) {
+       if (likely(!is_unaligned_page(addr, 2))) {
                res = mmu_get_user_word(addr, super, false, sz_word, false);
        } else {
                res = (uae_u16)mmu_get_user_byte(addr, super, false, sz_word, false) << 8;
@@ -1188,7 +1188,7 @@ void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val)
        ismoves = true;
        SAVE_EXCEPTION;
        TRY(prb) {
-               if (likely(!is_unaligned(addr, 4))) {
+               if (likely(!is_unaligned_page(addr, 4))) {
                        mmu_put_user_long(addr, val, super, sz_long, false);
                } else if (likely(!(addr & 1))) {
                        mmu_put_user_word(addr, val >> 16, super, sz_long, false);
@@ -1217,7 +1217,7 @@ void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val)
        ismoves = true;
        SAVE_EXCEPTION;
        TRY(prb) {
-               if (likely(!is_unaligned(addr, 2))) {
+               if (likely(!is_unaligned_page(addr, 2))) {
                        mmu_put_user_word(addr, val, super, sz_word, false);
                } else {
                        mmu_put_user_byte(addr, val >> 8, super, sz_word, false);
@@ -1593,13 +1593,13 @@ void uae_mmu_put_lrmw (uaecptr addr, uae_u32 v, int size, int type)
        if (size == sz_byte) {
                mmu_put_user_byte(addr, v, regs.s, sz_byte, true);
        } else if (size == sz_word) {
-               if (unlikely(is_unaligned(addr, 2))) {
+               if (unlikely(is_unaligned_page(addr, 2))) {
                        mmu_put_lrmw_word_unaligned(addr, v);
                } else {
                        mmu_put_user_word(addr, v, regs.s != 0, sz_word, true);
                }
        } else {
-               if (unlikely(is_unaligned(addr, 4)))
+               if (unlikely(is_unaligned_page(addr, 4)))
                        mmu_put_lrmw_long_unaligned(addr, v);
                else
                        mmu_put_user_long(addr, v, regs.s, sz_long, true);
@@ -1613,13 +1613,13 @@ uae_u32 uae_mmu_get_lrmw (uaecptr addr, int size, int type)
        if (size == sz_byte) {
                v = mmu_get_user_byte(addr, regs.s != 0, true, sz_byte, true);
        } else if (size == sz_word) {
-               if (unlikely(is_unaligned(addr, 2))) {
+               if (unlikely(is_unaligned_page(addr, 2))) {
                        v = mmu_get_lrmw_word_unaligned(addr);
                } else {
                        v = mmu_get_user_word(addr, regs.s != 0, true, sz_word, true);
                }
        } else {
-               if (unlikely(is_unaligned(addr, 4)))
+               if (unlikely(is_unaligned_page(addr, 4)))
                        v = mmu_get_lrmw_long_unaligned(addr);
                else
                        v = mmu_get_user_long(addr, regs.s != 0, true, sz_long, true);
index e7d43989d4169bd58d39d25e6156117124e4c2f6..326c6c5a9715a70a088c493e92a33b76733edd90 100644 (file)
@@ -66,11 +66,11 @@ int mmu030_fake_prefetch;
 uaecptr mmu030_fake_prefetch_addr;
 
 uae_u16 mmu030_state[3];
-uae_u32 mmu030_data_buffer;
+uae_u32 mmu030_data_buffer_out;
 uae_u32 mmu030_disp_store[2];
 uae_u32 mmu030_fmovem_store[2];
 uae_u8 mmu030_cache_state;
-struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS];
+struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS + 1];
 
 static void mmu030_ptest_atc_search(uaecptr logical_addr, uae_u32 fc, bool write);
 static uae_u32 mmu030_table_search(uaecptr addr, uae_u32 fc, bool write, int level);
@@ -1700,6 +1700,38 @@ static void mmu030_ptest_atc_search(uaecptr logical_addr, uae_u32 fc, bool write
 #define ATC030_PHYS_CI  0x04000000
 #define ATC030_PHYS_BE  0x08000000
 
+#if MMUDEBUG
+static void dump_opcode(uae_u16 opcode)
+{
+       struct mnemolookup *lookup;
+       struct instr *dp;
+       char size = '_';
+
+       dp = table68k + opcode;
+       if (dp->mnemo == i_ILLG) {
+               opcode = 0x4AFC;
+               dp = table68k + opcode;
+       }
+       for (lookup = lookuptab; lookup->mnemo != dp->mnemo; lookup++);
+
+       if (!dp->unsized) {
+               switch (dp->size)
+               {
+               case sz_byte:
+               size = 'B';
+               break;
+               case sz_word:
+               size = 'W';
+               break;
+               case sz_long:
+               size = 'L';
+               break;
+               }
+       }
+       write_log(_T("%04x %s.%c"), opcode, lookup->name, size);
+}
+#endif
+
 void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc)
 {
        if (flags < 0) {
@@ -1728,10 +1760,22 @@ void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc)
        regs.mmu_ssw |= fc;
     bBusErrorReadWrite = read; 
        mm030_stageb_address = addr;
+
 #if MMUDEBUG
-       write_log(_T("MMU: page fault (logical addr=%08X SSW=%04x read=%d size=%d fc=%d pc=%08x ob=%08x ins=%04X)\n"),
+       write_log(_T("MMU: la=%08X SSW=%04x read=%d size=%d fc=%d pc=%08x ob=%08x "),
                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);
+               regs.instruction_pc, mmu030_data_buffer_out, mmu030_opcode & 0xffff);
+       dump_opcode(mmu030_opcode & 0xffff);
+       write_log(_T("\n"));
+#endif
+
+#if 0
+       if (addr == 0xBFE201)
+               write_log("!");
+       if (mmu030_state[1] & MMU030_STATEFLAG1_SUBACCESS0)
+               write_log("!");
+       if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1)
+               write_log("!");
 #endif
 
        THROW(2);
@@ -2277,12 +2321,12 @@ uae_u32 uae_mmu030_get_lrmw_fcx(uaecptr addr, int size, int fc)
        if (size == sz_byte) {
                return mmu030_get_generic(addr, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_B);
        } else if (size == sz_word) {
-               if (unlikely(is_unaligned(addr, 2)))
+               if (unlikely(is_unaligned_bus(addr, 2)))
                        return mmu030_get_word_unaligned(addr, fc, MMU030_SSW_RM);
                else
                        return mmu030_get_generic(addr, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_W);
        } else {
-               if (unlikely(is_unaligned(addr, 4)))
+               if (unlikely(is_unaligned_bus(addr, 4)))
                        return mmu030_get_long_unaligned(addr, fc, MMU030_SSW_RM);
                else
                        return mmu030_get_generic(addr, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_L);
@@ -2299,12 +2343,12 @@ void uae_mmu030_put_lrmw_fcx(uaecptr addr, uae_u32 val, int size, int fc)
        if (size == sz_byte) {
                mmu030_put_generic(addr, val, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_B);
        } else if (size == sz_word) {
-               if (unlikely(is_unaligned(addr, 2)))
+               if (unlikely(is_unaligned_bus(addr, 2)))
                        mmu030_put_word_unaligned(addr, val, fc, MMU030_SSW_RM);
                else
                        mmu030_put_generic(addr, val, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_W);
        } else {
-               if (unlikely(is_unaligned(addr, 4)))
+               if (unlikely(is_unaligned_bus(addr, 4)))
                        mmu030_put_long_unaligned(addr, val, fc, MMU030_SSW_RM);
                else
                        mmu030_put_generic(addr, val, fc, size, MMU030_SSW_RM | MMU030_SSW_SIZE_L);
@@ -2316,29 +2360,10 @@ void uae_mmu030_put_lrmw(uaecptr addr, uae_u32 val, int size)
        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;
-    
-       flags |= MMU030_SSW_SIZE_W;
-       res = (uae_u16)mmu030_get_generic(addr, fc, sz_byte, flags) << 8;
-       SAVE_EXCEPTION;
-       TRY(prb) {
-               res |= mmu030_get_generic(addr + 1, fc, sz_byte, flags);
-               RESTORE_EXCEPTION;
-       }
-       CATCH(prb) {
-               RESTORE_EXCEPTION;
-               THROW_AGAIN(prb);
-       } ENDTRY
-       return res;
-}
-
 uae_u32 REGPARAM2 mmu030_get_ilong_unaligned(uaecptr addr, uae_u32 fc, int flags)
 {
        uae_u32 res;
 
-       flags |= MMU030_SSW_SIZE_L;
        res = (uae_u32)mmu030_get_iword(addr, fc) << 16;
        SAVE_EXCEPTION;
        TRY(prb) {
@@ -2352,77 +2377,79 @@ uae_u32 REGPARAM2 mmu030_get_ilong_unaligned(uaecptr addr, uae_u32 fc, int flags
        return res;
 }
 
+static void unalign_init(bool l, bool l2)
+{
+       if (l2)
+               mmu030_state[1] |= MMU030_STATEFLAG1_SUBACCESSX;
+       if (l)
+               mmu030_state[1] |= MMU030_STATEFLAG1_SUBACCESSL;
+       mmu030_state[1] |= MMU030_STATEFLAG1_SUBACCESS0;
+}
+static void unalign_set(int state)
+{
+       mmu030_state[1] |= (1 << state) << (MMU030_STATEFLAG1_SUBACCESS_SHIFT + 1);
+}
+static void unalign_clear(void)
+{
+       mmu030_state[1] &= ~(MMU030_STATEFLAG1_SUBACCESSL | MMU030_STATEFLAG1_SUBACCESSX |
+               MMU030_STATEFLAG1_SUBACCESS0 | MMU030_STATEFLAG1_SUBACCESS1 | MMU030_STATEFLAG1_SUBACCESS2 | MMU030_STATEFLAG1_SUBACCESS3);
+}
+
+uae_u16 REGPARAM2 mmu030_get_word_unaligned(uaecptr addr, uae_u32 fc, int flags)
+{
+       unalign_init(false, false);
+       mmu030_data_buffer_out = (uae_u16)mmu030_get_generic(addr, fc, sz_byte, flags | MMU030_SSW_SIZE_W) << 8;
+       unalign_set(0);
+       mmu030_data_buffer_out |= mmu030_get_generic(addr + 1, fc, sz_byte, flags | MMU030_SSW_SIZE_B);
+       unalign_clear();
+       return mmu030_data_buffer_out;
+}
+
 uae_u32 REGPARAM2 mmu030_get_long_unaligned(uaecptr addr, uae_u32 fc, int flags)
 {
-       uae_u32 res;
-    
-       flags |= MMU030_SSW_SIZE_L;
        if (likely(!(addr & 1))) {
-               res = (uae_u32)mmu030_get_generic(addr, fc, sz_word, flags) << 16;
-               SAVE_EXCEPTION;
-               TRY(prb) {
-                       res |= mmu030_get_generic(addr + 2, fc, sz_word, flags);
-                       RESTORE_EXCEPTION;
-               }
-               CATCH(prb) {
-                       RESTORE_EXCEPTION;
-                       THROW_AGAIN(prb);
-               } ENDTRY
+               unalign_init(true, false);
+               mmu030_data_buffer_out = (uae_u32)mmu030_get_generic(addr, fc, sz_word, flags | MMU030_SSW_SIZE_L) << 16;
+               unalign_set(0);
+               mmu030_data_buffer_out |= mmu030_get_generic(addr + 2, fc, sz_word, flags | MMU030_SSW_SIZE_W);
        } else {
-               res = (uae_u32)mmu030_get_generic(addr, fc, sz_byte, flags) << 8;
-               SAVE_EXCEPTION;
-               TRY(prb) {
-                       res = (res | mmu030_get_generic(addr + 1, fc, sz_byte, flags)) << 8;
-                       res = (res | mmu030_get_generic(addr + 2, fc, sz_byte, flags)) << 8;
-                       res |= mmu030_get_generic(addr + 3, fc, sz_byte, flags);
-                       RESTORE_EXCEPTION;
-               }
-               CATCH(prb) {
-                       RESTORE_EXCEPTION;
-                       THROW_AGAIN(prb);
-               } ENDTRY
+               unalign_init(true, true);
+               mmu030_data_buffer_out = (uae_u32)mmu030_get_generic(addr, fc, sz_byte, flags | MMU030_SSW_SIZE_L) << 24;
+               unalign_set(0);
+               mmu030_data_buffer_out |= mmu030_get_generic(addr + 1, fc, sz_word, flags | MMU030_SSW_SIZE_W) << 8;
+               unalign_set(1);
+               mmu030_data_buffer_out |= mmu030_get_generic(addr + 3, fc, sz_byte, flags | MMU030_SSW_SIZE_B);
        }
-       return res;
+       unalign_clear();
+       return mmu030_data_buffer_out;
 }
 
 
 void REGPARAM2 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc, int flags)
 {
-       flags |= MMU030_SSW_SIZE_L;
-       SAVE_EXCEPTION;
-       TRY(prb) {
-               if (likely(!(addr & 1))) {
-                       mmu030_put_generic(addr, val >> 16, fc, sz_word, flags);
-                       mmu030_put_generic(addr + 2, val, fc, sz_word, flags);
-               } else {
-                       mmu030_put_generic(addr, val >> 24, fc, sz_byte, flags);
-                       mmu030_put_generic(addr + 1, val >> 16, fc, sz_byte, flags);
-                       mmu030_put_generic(addr + 2, val >> 8, fc, sz_byte, flags);
-                       mmu030_put_generic(addr + 3, val, fc, sz_byte, flags);
-               }
-               RESTORE_EXCEPTION;
+       if (likely(!(addr & 1))) {
+               unalign_init(true, false);
+               mmu030_put_generic(addr, val >> 16, fc, sz_word, flags | MMU030_SSW_SIZE_L);
+               unalign_set(0);
+               mmu030_put_generic(addr + 2, val, fc, sz_word, flags | MMU030_SSW_SIZE_W);
+       } else {
+               unalign_init(true, true);
+               mmu030_put_generic(addr, val >> 24, fc, sz_byte, flags | MMU030_SSW_SIZE_L);
+               unalign_set(0);
+               mmu030_put_generic(addr + 1, val >> 8, fc, sz_word, flags | MMU030_SSW_SIZE_W);
+               unalign_set(1);
+               mmu030_put_generic(addr + 3, val, fc, sz_byte, flags | MMU030_SSW_SIZE_B);
        }
-       CATCH(prb) {
-               RESTORE_EXCEPTION;
-               regs.wb3_data = val;
-               THROW_AGAIN(prb);
-       } ENDTRY
+       unalign_clear();
 }
 
 void REGPARAM2 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc, int flags)
 {
-       flags |= MMU030_SSW_SIZE_W;
-       SAVE_EXCEPTION;
-       TRY(prb) {
-               mmu030_put_generic(addr, val >> 8, fc, sz_byte, flags);
-               mmu030_put_generic(addr + 1, val, fc, sz_byte, flags);
-               RESTORE_EXCEPTION;
-       }
-       CATCH(prb) {
-               RESTORE_EXCEPTION;
-               regs.wb3_data = val;
-               THROW_AGAIN(prb);
-       } ENDTRY
+       unalign_init(false, false);
+       mmu030_put_generic(addr, val >> 8, fc, sz_byte, flags | MMU030_SSW_SIZE_W);
+       unalign_set(0);
+       mmu030_put_generic(addr + 1, val, fc, sz_byte, flags | MMU030_SSW_SIZE_B);
+       unalign_clear();
 }
 
 
@@ -2530,39 +2557,130 @@ void mmu030_set_funcs(void)
        }
 }
 
-static void dump_opcode(uae_u16 opcode)
+#define unalign_done(f) \
+       st |= f; \
+       mmu030_state[1] = st;
+
+static void mmu030_unaligned_read_continue(uaecptr addr, int fc)
 {
-       struct mnemolookup *lookup;
-       struct instr *dp;
-       char size = '_';
+       uae_u32 st = mmu030_state[1];
 
-       dp = table68k + opcode;
-       if (dp->mnemo == i_ILLG) {
-               opcode = 0x4AFC;
-               dp = table68k + opcode;
+#if MMUDEBUG
+       write_log(_T("unaligned_read_continue: %08x %d %08x %08x\n"), addr, fc, mmu030_data_buffer_out, st);
+#endif
+
+       if (st & MMU030_STATEFLAG1_SUBACCESSL) {
+               if (st & MMU030_STATEFLAG1_SUBACCESSX) {
+                       // odd long access: byte + word + byte
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS1)) {
+                               mmu030_data_buffer_out &= 0x00ffffff;
+                               mmu030_data_buffer_out |= mmu030_get_generic(addr, fc, sz_byte, MMU030_SSW_SIZE_L) << 24;
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS1);
+                               addr++;
+                       }
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS2)) {
+                               mmu030_data_buffer_out &= 0xff0000ff;
+                               mmu030_data_buffer_out |= mmu030_get_generic(addr, fc, sz_word, MMU030_SSW_SIZE_W) << 8;
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS2);
+                               addr += 2;
+                       }
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS3)) {
+                               mmu030_data_buffer_out &= 0xffffff00;
+                               mmu030_data_buffer_out |= mmu030_get_generic(addr, fc, sz_byte, MMU030_SSW_SIZE_B) << 0;
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS3);
+                       }
+               } else {
+                       // even but unaligned long access: word + word
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS1)) {
+                               mmu030_data_buffer_out &= 0x0000ffff;
+                               mmu030_data_buffer_out |= mmu030_get_generic(addr, fc, sz_word, MMU030_SSW_SIZE_L) << 16;
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS1);
+                               addr += 2;
+                       }
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS2)) {
+                               mmu030_data_buffer_out &= 0xffff0000;
+                               mmu030_data_buffer_out |= mmu030_get_generic(addr, fc, sz_word, MMU030_SSW_SIZE_W) << 0;
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS2);
+                       }
+               }
+       } else {
+               // odd word access: byte + byte
+               if (!(st & MMU030_STATEFLAG1_SUBACCESS1)) {
+                       mmu030_data_buffer_out &= 0x00ff;
+                       mmu030_data_buffer_out |= mmu030_get_generic(addr, fc, sz_byte, MMU030_SSW_SIZE_W) << 8;
+                       unalign_done(MMU030_STATEFLAG1_SUBACCESS1);
+                       addr++;
+               }
+               if (!(st & MMU030_STATEFLAG1_SUBACCESS2)) {
+                       mmu030_data_buffer_out &= 0xff00;
+                       mmu030_data_buffer_out |= mmu030_get_generic(addr, fc, sz_byte, MMU030_SSW_SIZE_B) << 0;
+                       unalign_done(MMU030_STATEFLAG1_SUBACCESS2);
+               }
        }
-       for (lookup = lookuptab; lookup->mnemo != dp->mnemo; lookup++);
 
-       if (!dp->unsized) {
-               switch (dp->size)
-               {
-               case sz_byte:
-               size = 'B';
-               break;
-               case sz_word:
-               size = 'W';
-               break;
-               case sz_long:
-               size = 'L';
-               break;
+#if MMUDEBUG
+       write_log(_T("unaligned_read_continue_end: %08x %d %08x %08x\n"), addr, fc, mmu030_data_buffer_out, st);
+#endif
+}
+
+static void mmu030_unaligned_write_continue(uaecptr addr, int fc)
+{
+       uae_u32 st = mmu030_state[1];
+
+#if MMUDEBUG
+       write_log(_T("unaligned_write_continue: %08x %d %08x %08x\n"), addr, fc, mmu030_data_buffer_out, st);
+#endif
+
+       if (st & MMU030_STATEFLAG1_SUBACCESSL) {
+               // odd long access: byte + word + byte
+               if (st & MMU030_STATEFLAG1_SUBACCESSX) {
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS1)) {
+                               mmu030_put_generic(addr, mmu030_data_buffer_out >> 24, fc, sz_byte, MMU030_SSW_SIZE_L);
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS1);
+                               addr++;
+                       }
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS2)) {
+                               mmu030_put_generic(addr, mmu030_data_buffer_out >> 8, fc, sz_word, MMU030_SSW_SIZE_W);
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS2);
+                               addr += 2;
+                       }
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS3)) {
+                               mmu030_put_generic(addr, mmu030_data_buffer_out >> 0, fc, sz_byte, MMU030_SSW_SIZE_B);
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS3);
+                       }
+               } else {
+                       // even but unaligned long access: word + word
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS1)) {
+                               mmu030_put_generic(addr, mmu030_data_buffer_out >> 16, fc, sz_word, MMU030_SSW_SIZE_L);
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS1);
+                               addr += 2;
+                       }
+                       if (!(st & MMU030_STATEFLAG1_SUBACCESS2)) {
+                               mmu030_put_generic(addr, mmu030_data_buffer_out >> 0, fc, sz_word, MMU030_SSW_SIZE_W);
+                               unalign_done(MMU030_STATEFLAG1_SUBACCESS2);
+                       }
+               }
+       } else {
+               // odd word access: byte + byte
+               if (!(st & MMU030_STATEFLAG1_SUBACCESS1)) {
+                       mmu030_put_generic(addr, mmu030_data_buffer_out >> 8, fc, sz_byte, MMU030_SSW_SIZE_W);
+                       unalign_done(MMU030_STATEFLAG1_SUBACCESS1);
+                       addr++;
+               }
+               if (!(st & MMU030_STATEFLAG1_SUBACCESS2)) {
+                       mmu030_put_generic(addr, mmu030_data_buffer_out >> 0, fc, sz_byte, MMU030_SSW_SIZE_B);
+                       unalign_done(MMU030_STATEFLAG1_SUBACCESS2);
                }
        }
-       write_log(_T("%04x %s.%c\n"), opcode, lookup->name, size);
+
+#if MMUDEBUG
+       write_log(_T("unaligned_write_continue_end: %08x %d %08x %08x\n"), addr, fc, mmu030_data_buffer_out, st);
+#endif
 }
 
 void m68k_do_rte_mmu030 (uaecptr a7)
 {
-       struct mmu030_access mmu030_ad_v[MAX_MMU030_ACCESS];
+       struct mmu030_access mmu030_ad_v[MAX_MMU030_ACCESS + 1];
 
        // Restore access error exception state
 
@@ -2583,14 +2701,14 @@ void m68k_do_rte_mmu030 (uaecptr a7)
        // Internal register, our opcode storage area
        uae_u32 oc = get_long_mmu030(a7 + 0x14);
        // Movem write data
-       uae_u32 mdata = get_long_mmu030(a7 + 0x18);
+       uae_u32 mmu030_data_buffer_out_v = get_long_mmu030(a7 + 0x18);
        // get_disp_ea_020
        uae_u32 mmu030_disp_store_0 = get_long_mmu030(a7 + 0x1c);
        uae_u32 mmu030_disp_store_1 = get_long_mmu030(a7 + 0x1c + 4);
        // Internal register, misc flags
        uae_u32 ps = get_long_mmu030(a7 + 0x28);
        // Data buffer
-       uae_u32 mmu030_data_buffer_v = get_long_mmu030(a7 + 0x2c);;
+       uae_u32 mmu030_data_buffer_in_v = get_long_mmu030(a7 + 0x2c);;
 
        uae_u32 mmu030_opcode_v = (ps & 0x80000000) ? -1 : (oc & 0xffff);
        // Misc state data
@@ -2620,6 +2738,7 @@ void m68k_do_rte_mmu030 (uaecptr a7)
                // 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
+                       mmu030_data_buffer_out_v = mmu030_data_buffer_in_v;
                        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);
@@ -2631,20 +2750,20 @@ void m68k_do_rte_mmu030 (uaecptr a7)
                                mmu030_ad_v[idxsize].done = true;
                                if (ssw & MMU030_SSW_RW) {
                                        // Read and no DF: use value in data input buffer
-                                       mmu030_ad_v[idxsize].val = mmu030_data_buffer_v;
+                                       mmu030_ad_v[idxsize].val = mmu030_data_buffer_in_v;
                                }
                        }
                }
                // did we have ins fault and RB bit cleared?
                if ((ssw & MMU030_SSW_FB) && !(ssw & MMU030_SSW_RB)) {
                        uae_u16 stageb = get_word_mmu030 (a7 + 0x0e);
-                       if (mmu030_opcode == -1) {
+                       if (mmu030_opcode_v == -1) {
                                mmu030_opcode_stageb = stageb;
                                write_log (_T("Software fixed stage B! opcode = %04x\n"), stageb);
                        } else {
                                mmu030_ad_v[idxsize].done = true;
                                mmu030_ad_v[idxsize].val = stageb;
-                               write_log (_T("Software fixed stage B! opcode = %04X, opword = %04x\n"), mmu030_opcode, stageb);
+                               write_log (_T("Software fixed stage B! opcode = %04X, opword = %04x\n"), mmu030_opcode_v, stageb);
                        }
                }
 
@@ -2659,7 +2778,7 @@ void m68k_do_rte_mmu030 (uaecptr a7)
                mmu030_disp_store[1] = mmu030_disp_store_1;
                mmu030_fmovem_store[0] = mmu030_fmovem_store_0;
                mmu030_fmovem_store[1] = mmu030_fmovem_store_1;
-               mmu030_data_buffer = mmu030_data_buffer_v;
+               mmu030_data_buffer_out = mmu030_data_buffer_out_v;
                mmu030_idx = idxsize;
                for (int i = 0; i <= mmu030_idx + 1; i++) {
                        mmu030_ad[i].done = mmu030_ad_v[i].done;
@@ -2675,17 +2794,6 @@ 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) && (ssw & MMU030_SSW_RM)) {
 
                        // Locked-Read-Modify-Write restarts whole instruction.
@@ -2699,49 +2807,64 @@ void m68k_do_rte_mmu030 (uaecptr a7)
                        int size = (ssw & MMU030_SSW_SIZE_B) ? sz_byte : ((ssw & MMU030_SSW_SIZE_W) ? sz_word : sz_long);
                        int fc = ssw & MMU030_SSW_FC_MASK;
                        
+#if MMU030_DEBUG
+                       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"));
+                               }
+                       }
+                       if (mmu030_ad[idxsize].done) {
+                               write_log(_T("68030 MMU ins %04x retry but it was already marked as done!?\n"));
+                       }
+#endif
+
 #if 0
                        write_log(_T("%08x %08x %08x %08x %08x %d %d %d "), mmu030_state[1], mmu030_state[2], mmu030_disp_store[0], mmu030_disp_store[1], addr, read, size, fc);
                        dump_opcode(mmu030_opcode);
 #endif
 
                        if (read) {
-                               uae_u32 val = 0;
-                               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_out = mmu030_ad[idxsize].val;
+                               }
+                               if (mmu030_state[1] & MMU030_STATEFLAG1_SUBACCESS0) {
+                                       mmu030_unaligned_read_continue(addr, fc);
+                               } else {
+                                       switch (size)
+                                       {
+                                               case sz_byte:
+                                               mmu030_data_buffer_out = uae_mmu030_get_byte_fcx(addr, fc);
+                                               break;
+                                               case sz_word:
+                                               mmu030_data_buffer_out = uae_mmu030_get_word_fcx(addr, fc);
+                                               break;
+                                               case sz_long:
+                                               mmu030_data_buffer_out = 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 {
-                                       mmu030_ad[idxsize].val = val;
+                                       mmu030_ad[idxsize].val = mmu030_data_buffer_out;
                                        mmu030_ad[idxsize].done = true;
                                }
                        } else {
-                               uae_u32 val;
-                               if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1)
-                                       val = mdata;
-                               else
-                                       val = mmu030_ad[idxsize].val;
-                               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_SUBACCESS0) {
+                                       mmu030_unaligned_write_continue(addr, fc);
+                               } else {
+                                       switch (size)
+                                       {
+                                               case sz_byte:
+                                               uae_mmu030_put_byte_fcx(addr, mmu030_data_buffer_out, fc);
+                                               break;
+                                               case sz_word:
+                                               uae_mmu030_put_word_fcx(addr, mmu030_data_buffer_out, fc);
+                                               break;
+                                               case sz_long:
+                                               uae_mmu030_put_long_fcx(addr, mmu030_data_buffer_out, fc);
+                                               break;
+                                       }
                                }
                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
                                        mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
@@ -2752,6 +2875,12 @@ void m68k_do_rte_mmu030 (uaecptr a7)
 
                }
 
+#if MMU030_DEBUG
+               if (mmu030_idx >= MAX_MMU030_ACCESS) {
+                       write_log(_T("mmu030_idx (RTE) out of bounds! %d >= %d\n"), mmu030_idx, MAX_MMU030_ACCESS);
+               }
+#endif
+
        } else {
                m68k_areg (regs, 7) += 32;
        }
@@ -2940,7 +3069,7 @@ uae_u32 REGPARAM2 get_disp_ea_020_mmu030c (uae_u32 base, int idx)
 
 void m68k_do_rte_mmu030c (uaecptr a7)
 {
-       struct mmu030_access mmu030_ad_v[MAX_MMU030_ACCESS];
+       struct mmu030_access mmu030_ad_v[MAX_MMU030_ACCESS + 1];
 
        // Restore access error exception state
 
@@ -2962,14 +3091,14 @@ void m68k_do_rte_mmu030c (uaecptr a7)
        // Internal register, our opcode storage area
        uae_u32 oc = get_long_mmu030c(a7 + 0x14);
        // Movem write data
-       uae_u32 mdata = get_long_mmu030c(a7 + 0x18);
+       uae_u32 mmu030_data_buffer_out_v = get_long_mmu030c(a7 + 0x18);
        // get_disp_ea_020
        uae_u32 mmu030_disp_store_0 = get_long_mmu030c(a7 + 0x1c);
        uae_u32 mmu030_disp_store_1 = get_long_mmu030c(a7 + 0x1c + 4);
        // Internal register, misc flags
        uae_u32 ps = get_long_mmu030c(a7 + 0x28);
        // Data buffer
-       uae_u32 mmu030_data_buffer_v = get_long_mmu030c(a7 + 0x2c);;
+       uae_u32 mmu030_data_buffer_in_v = get_long_mmu030c(a7 + 0x2c);;
 
        uae_u32 mmu030_opcode_v = (ps & 0x80000000) ? -1 : (oc & 0xffff);
        // Misc state data
@@ -2994,9 +3123,11 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                        mmu030_ad_v[i].val = get_long_mmu030c(a7 + 0x5c - (i + 1) * 4);
                }
                mmu030_ad_v[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
+                       mmu030_data_buffer_out_v = mmu030_data_buffer_in_v;
                        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);
@@ -3005,10 +3136,10 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                                // if movem, skip next move
                                mmu030_state_1 |= MMU030_STATEFLAG1_MOVEM2;
                        } else {
-                               mmu030_ad[idxsize].done = true;
+                               mmu030_ad_v[idxsize].done = true;
                                if (ssw & MMU030_SSW_RW) {
                                        // Read and no DF: use value in data input buffer
-                                       mmu030_ad[idxsize].val = mmu030_data_buffer;
+                                       mmu030_ad_v[idxsize].val = mmu030_data_buffer_in_v;
                                }
                        }
                }
@@ -3036,6 +3167,7 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                        write_log (_T("Software fixed stage C! opcode = %04x\n"), regs.prefetch020[1]);
                }
 
+               // restore global state variables
                mmu030_opcode = mmu030_opcode_v;
                mmu030_state[0] = mmu030_state_0;
                mmu030_state[1] = mmu030_state_1;
@@ -3044,13 +3176,12 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                mmu030_disp_store[1] = mmu030_disp_store_1;
                mmu030_fmovem_store[0] = mmu030_fmovem_store_0;
                mmu030_fmovem_store[1] = mmu030_fmovem_store_1;
-               mmu030_data_buffer = mmu030_data_buffer_v;
+               mmu030_data_buffer_out = mmu030_data_buffer_out_v;
                mmu030_idx = idxsize;
-               for (int i = 0; i < mmu030_idx + 1; i++) {
+               for (int i = 0; i <= mmu030_idx + 1; i++) {
                        mmu030_ad[i].done = mmu030_ad_v[i].done;
                        mmu030_ad[i].val = mmu030_ad_v[i].val;
                }
-               mmu030_ad[mmu030_idx + 1].done = false;
 
                m68k_areg (regs, 7) += 92;
                regs.sr = sr;
@@ -3061,6 +3192,17 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                }
                m68k_setpci (pc);
 
+#if MMU030_DEBUG
+               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 << 1))) {
                        if (!regs.prefetch020_valid[0] && regs.prefetch020_valid[2]) {
                                // Prefetch was software fixed, continue pipeline refill
@@ -3075,7 +3217,12 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                        }
                }
 
-               if (ssw & MMU030_SSW_DF) {
+               if ((ssw & MMU030_SSW_DF) && (ssw & MMU030_SSW_RM)) {
+
+                       // Locked-Read-Modify-Write restarts whole instruction.
+                       mmu030_ad[0].done = false;
+
+               } else if (ssw & MMU030_SSW_DF) {
                        // retry faulted access
                        uaecptr addr = fault_addr;
                        bool read = (ssw & MMU030_SSW_RW) != 0;
@@ -3083,50 +3230,45 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                        int fc = ssw & 7;
 
                        if (read) {
-                               uae_u32 val = 0;
-                               if (ssw & MMU030_SSW_RM) {
-                                       val = read_dcache030_lrmw_mmu_fcx(addr, size, fc);
+                               if (!(mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1)) {
+                                       mmu030_data_buffer_out = mmu030_ad[idxsize].val;
+                               }
+                               if (mmu030_state[1] & MMU030_STATEFLAG1_SUBACCESS0) {
+                                       mmu030_unaligned_read_continue(addr, fc);
                                } else {
                                        switch (size)
                                        {
                                                case sz_byte:
-                                               val = read_dcache030_bget(addr, fc);
+                                               mmu030_data_buffer_out = read_dcache030_bget(addr, fc);
                                                break;
                                                case sz_word:
-                                               val = read_dcache030_wget(addr, fc);
+                                               mmu030_data_buffer_out = read_dcache030_wget(addr, fc);
                                                break;
                                                case sz_long:
-                                               val = read_dcache030_lget(addr, fc);
+                                               mmu030_data_buffer_out = read_dcache030_lget(addr, fc);
                                                break;
                                        }
                                }
                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
-                                       mmu030_data_buffer = val;
                                        mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
                                } else {
-                                       mmu030_ad[idxsize].val = val;
+                                       mmu030_ad[idxsize].val = mmu030_data_buffer_out;
                                        mmu030_ad[idxsize].done = true;
-                                       mmu030_ad[idxsize + 1].done = false;
                                }
                        } else {
-                               uae_u32 val;
-                               if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1)
-                                       val = mdata;
-                               else
-                                       val = mmu030_ad[idxsize].val;
-                               if (ssw & MMU030_SSW_RM) {
-                                       write_dcache030_lrmw_mmu_fcx(addr, val, size, fc);
+                               if (mmu030_state[1] & MMU030_STATEFLAG1_SUBACCESS0) {
+                                       mmu030_unaligned_write_continue(addr, fc);
                                } else {
                                        switch (size)
                                        {
                                                case sz_byte:
-                                               write_dcache030_bput(addr, val, fc);
+                                               write_dcache030_bput(addr, mmu030_data_buffer_out, fc);
                                                break;
                                                case sz_word:
-                                               write_dcache030_wput(addr, val, fc);
+                                               write_dcache030_wput(addr, mmu030_data_buffer_out, fc);
                                                break;
                                                case sz_long:
-                                               write_dcache030_lput(addr, val, fc);
+                                               write_dcache030_lput(addr, mmu030_data_buffer_out, fc);
                                                break;
                                        }
                                }
@@ -3134,7 +3276,6 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                                        mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
                                } else {
                                        mmu030_ad[idxsize].done = true;
-                                       mmu030_ad[idxsize + 1].done = false;
                                }
                        }
                }
diff --git a/fpp.cpp b/fpp.cpp
index c68de15e942303cb68ad821f0b142b6eb4dcba2a..cb3d082e813c1cb93df0814a337c756022b39987 100644 (file)
--- a/fpp.cpp
+++ b/fpp.cpp
@@ -2449,7 +2449,7 @@ static uaecptr fmovem2mem (uaecptr ad, uae_u32 list, int incr, int regdir)
                                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM2) {
                                                        mmu030_state[1] &= ~MMU030_STATEFLAG1_MOVEM2;
                                                } else {
-                                                       mmu030_data_buffer = wrd[i];
+                                                       mmu030_data_buffer_out = wrd[i];
                                                        x_put_long(ad + i * 4, wrd[i]);
                                                }
                                                mmu030_state[0]++;
@@ -2504,7 +2504,7 @@ static uaecptr fmovem2fpp (uaecptr ad, uae_u32 list, int incr, int regdir)
                                        if (mmu030_state[0] == idx * 3 + i) {
                                                if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM2) {
                                                        mmu030_state[1] &= ~MMU030_STATEFLAG1_MOVEM2;
-                                                       wrd[i] = mmu030_data_buffer;
+                                                       wrd[i] = mmu030_data_buffer_out;
                                                } else {
                                                        wrd[i] = x_get_long (ad + i * 4);
                                                }
index bf94c3b62dfd4ea535744ba5075afd73888a7e8a..1a0e571b06f2c62b399d0790ee310aac382b7f07 100644 (file)
@@ -2194,10 +2194,10 @@ static void movem_mmu030 (const char *code, int size, bool put, bool aipi, bool
                printf ("\t\t\tif (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM2) {\n");
                printf ("\t\t\t\tmmu030_state[1] &= ~MMU030_STATEFLAG1_MOVEM2;\n");
                if (!put)
-                       printf ("\t\t\t\tval = %smmu030_data_buffer;\n", size == 2 ? "(uae_s32)(uae_s16)" : "");
+                       printf ("\t\t\t\tval = %smmu030_data_buffer_out;\n", size == 2 ? "(uae_s32)(uae_s16)" : "");
                printf ("\t\t\t} else {\n");
                if (put)
-                       printf ("\t\t\t\t%s, (mmu030_data_buffer = m68k_%creg (regs, %s[%cmask])));\n", code, reg, index, reg);
+                       printf ("\t\t\t\t%s, (mmu030_data_buffer_out = m68k_%creg (regs, %s[%cmask])));\n", code, reg, index, reg);
                else
                        printf ("\t\t\t\tval = %s;\n", code);
                printf ("\t\t\t}\n");
index 7ff8f95d270275baac5eda90a18530a75dd92105..b645197eff0a5ccd4a25fee8e01ff1f8f8cca217 100644 (file)
@@ -698,7 +698,7 @@ static ALWAYS_INLINE uae_u32 uae_mmu040_get_ilong(uaecptr addr)
        result |= uae_mmu040_getc_iword(addr + 2);
        return result;
 #else
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_page(addr, 4)))
                return mmu_get_ilong_unaligned(addr);
        return mmu_get_ilong(addr, sz_long);
 #endif
@@ -714,13 +714,13 @@ static ALWAYS_INLINE uae_u16 uae_mmu040_get_ibyte(uaecptr addr)
 }
 static ALWAYS_INLINE uae_u32 uae_mmu040_get_long(uaecptr addr)
 {
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_page(addr, 4)))
                return mmu_get_long_unaligned(addr, true);
        return mmu_get_long(addr, true, sz_long);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu040_get_word(uaecptr addr)
 {
-       if (unlikely(is_unaligned(addr, 2)))
+       if (unlikely(is_unaligned_page(addr, 2)))
                return mmu_get_word_unaligned(addr, true);
        return mmu_get_word(addr, true, sz_word);
 }
@@ -731,7 +731,7 @@ static ALWAYS_INLINE uae_u8 uae_mmu040_get_byte(uaecptr addr)
 
 static ALWAYS_INLINE void uae_mmu040_put_word(uaecptr addr, uae_u16 val)
 {
-       if (unlikely(is_unaligned(addr, 2)))
+       if (unlikely(is_unaligned_page(addr, 2)))
                mmu_put_word_unaligned(addr, val, true);
        else
                mmu_put_word(addr, val, true, sz_word);
@@ -742,7 +742,7 @@ static ALWAYS_INLINE void uae_mmu040_put_byte(uaecptr addr, uae_u8 val)
 }
 static ALWAYS_INLINE void uae_mmu040_put_long(uaecptr addr, uae_u32 val)
 {
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_page(addr, 4)))
                mmu_put_long_unaligned(addr, val, true);
        else
                mmu_put_long(addr, val, true, sz_long);
@@ -751,7 +751,7 @@ static ALWAYS_INLINE void uae_mmu040_put_long(uaecptr addr, uae_u32 val)
 
 static ALWAYS_INLINE uae_u32 uae_mmu060_get_ilong(uaecptr addr)
 {
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_page(addr, 4)))
                return mmu_get_ilong_unaligned(addr);
        return mmu_get_ilong(addr, sz_long);
 }
@@ -765,13 +765,13 @@ static ALWAYS_INLINE uae_u16 uae_mmu060_get_ibyte(uaecptr addr)
 }
 static ALWAYS_INLINE uae_u32 uae_mmu060_get_long(uaecptr addr)
 {
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_page(addr, 4)))
                return mmu_get_long_unaligned(addr, true);
        return mmu_get_long(addr, true, sz_long);
 }
 static ALWAYS_INLINE uae_u16 uae_mmu060_get_word(uaecptr addr)
 {
-       if (unlikely(is_unaligned(addr, 2)))
+       if (unlikely(is_unaligned_page(addr, 2)))
                return mmu_get_word_unaligned(addr, true);
        return mmu_get_word(addr, true, sz_word);
 }
@@ -787,14 +787,14 @@ static ALWAYS_INLINE void uae_mmu_get_move16(uaecptr addr, uae_u32 *val)
 
 static ALWAYS_INLINE void uae_mmu060_put_long(uaecptr addr, uae_u32 val)
 {
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_page(addr, 4)))
                mmu_put_long_unaligned(addr, val, true);
        else
                mmu_put_long(addr, val, true, sz_long);
 }
 static ALWAYS_INLINE void uae_mmu060_put_word(uaecptr addr, uae_u16 val)
 {
-       if (unlikely(is_unaligned(addr, 2)))
+       if (unlikely(is_unaligned_page(addr, 2)))
                mmu_put_word_unaligned(addr, val, true);
        else
                mmu_put_word(addr, val, true, sz_word);
index f1114e6ef5bbeded91a52dadabf83cd0b1c06a09..35848816df5a106d4b654ee39c29342d7685f320 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef UAE_CPUMMU030_H
 #define UAE_CPUMMU030_H
 
+#define MMU030_DEBUG 1
+
 #include "uae/types.h"
 
 #include "mmu_common.h"
@@ -12,7 +14,7 @@ extern uae_u64 srp_030, crp_030;
 extern uae_u32 tt0_030, tt1_030, tc_030;
 extern uae_u16 mmusr_030;
 
-#define MAX_MMU030_ACCESS 10
+#define MAX_MMU030_ACCESS 9
 extern uae_u32 mm030_stageb_address;
 extern int mmu030_idx;
 extern bool mmu030_retry;
@@ -20,7 +22,7 @@ extern int mmu030_opcode, mmu030_opcode_stageb;
 extern int mmu030_fake_prefetch;
 extern uaecptr mmu030_fake_prefetch_addr;
 extern uae_u16 mmu030_state[3];
-extern uae_u32 mmu030_data_buffer;
+extern uae_u32 mmu030_data_buffer_out;
 extern uae_u32 mmu030_disp_store[2];
 extern uae_u32 mmu030_fmovem_store[2];
 extern uae_u8 mmu030_cache_state, mmu030_cache_state_default;
@@ -31,12 +33,20 @@ extern uae_u8 mmu030_cache_state, mmu030_cache_state_default;
 #define MMU030_STATEFLAG1_DISP0 0x0001
 #define MMU030_STATEFLAG1_DISP1 0x0002
 
+#define MMU030_STATEFLAG1_SUBACCESS0 0x0004
+#define MMU030_STATEFLAG1_SUBACCESS1 0x0008
+#define MMU030_STATEFLAG1_SUBACCESS2 0x0010
+#define MMU030_STATEFLAG1_SUBACCESS3 0x0020
+#define MMU030_STATEFLAG1_SUBACCESSX 0x0040
+#define MMU030_STATEFLAG1_SUBACCESSL 0x0080
+#define MMU030_STATEFLAG1_SUBACCESS_SHIFT 2
+
 struct mmu030_access
 {
        bool done;
        uae_u32 val;
 };
-extern struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS];
+extern struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS + 1];
 
 void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc);
 
@@ -98,7 +108,7 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong(uaecptr addr)
 {
        uae_u32 fc = uae_mmu030_get_fc_code();
 
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_bus(addr, 4)))
                return mmu030_get_ilong_unaligned(addr, fc, 0);
        return mmu030_get_ilong(addr, fc);
 }
@@ -119,7 +129,7 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_long(uaecptr addr)
 {
        uae_u32 fc = uae_mmu030_get_fc_data();
 
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_bus(addr, 4)))
                return mmu030_get_long_unaligned(addr, fc, 0);
        return mmu030_get_long(addr, fc);
 }
@@ -127,7 +137,7 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_word(uaecptr addr)
 {
        uae_u32 fc = uae_mmu030_get_fc_data();
 
-       if (unlikely(is_unaligned(addr, 2)))
+       if (unlikely(is_unaligned_bus(addr, 2)))
                return mmu030_get_word_unaligned(addr, fc, 0);
        return mmu030_get_word(addr, fc);
 }
@@ -142,7 +152,7 @@ static ALWAYS_INLINE void uae_mmu030_put_long(uaecptr addr, uae_u32 val)
 {
        uae_u32 fc = uae_mmu030_get_fc_data();
 
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_bus(addr, 4)))
                mmu030_put_long_unaligned(addr, val, fc, 0);
        else
                mmu030_put_long(addr, val, fc);
@@ -151,7 +161,7 @@ static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u32 val)
 {
        uae_u32 fc = uae_mmu030_get_fc_data();
 
-       if (unlikely(is_unaligned(addr, 2)))
+       if (unlikely(is_unaligned_bus(addr, 2)))
                mmu030_put_word_unaligned(addr, val, fc, 0);
        else
                mmu030_put_word(addr, val, fc);
@@ -165,7 +175,7 @@ static ALWAYS_INLINE void uae_mmu030_put_byte(uaecptr addr, uae_u32 val)
 
 static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong_fc(uaecptr addr)
 {
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_bus(addr, 4)))
                return mmu030_get_ilong_unaligned(addr, regs.fc030, 0);
        return mmu030_get_ilong(addr, regs.fc030);
 }
@@ -179,13 +189,13 @@ static ALWAYS_INLINE uae_u16 uae_mmu030_get_ibyte_fc(uaecptr addr)
 }
 static ALWAYS_INLINE uae_u32 uae_mmu030_get_long_fc(uaecptr addr)
 {
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_bus(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)))
+       if (unlikely(is_unaligned_bus(addr, 2)))
                return mmu030_get_word_unaligned(addr, regs.fc030, 0);
        return mmu030_get_word(addr, regs.fc030);
 }
@@ -195,14 +205,14 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_byte_fc(uaecptr addr)
 }
 static ALWAYS_INLINE void uae_mmu030_put_long_fc(uaecptr addr, uae_u32 val)
 {
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_bus(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)))
+       if (unlikely(is_unaligned_bus(addr, 2)))
                mmu030_put_word_unaligned(addr, val,  regs.fc030, 0);
        else
                mmu030_put_word(addr, val, regs.fc030);
@@ -215,13 +225,13 @@ 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)))
+       if (unlikely(is_unaligned_bus(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)))
+       if (unlikely(is_unaligned_bus(addr, 2)))
                return mmu030_get_word_unaligned(addr, fc, 0);
        return mmu030_get_word(addr, fc);
 }
@@ -231,14 +241,14 @@ static ALWAYS_INLINE uae_u32 uae_mmu030_get_byte_fcx(uaecptr addr, int fc)
 }
 static ALWAYS_INLINE void uae_mmu030_put_long_fcx(uaecptr addr, uae_u32 val, int fc)
 {
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_bus(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)))
+       if (unlikely(is_unaligned_bus(addr, 2)))
                mmu030_put_word_unaligned(addr, val, fc, 0);
        else
                mmu030_put_word(addr, val, fc);
@@ -251,7 +261,7 @@ static ALWAYS_INLINE void uae_mmu030_put_byte_fcx(uaecptr addr, uae_u32 val, int
 
 #define ACCESS_CHECK_PUT \
        if (!mmu030_ad[mmu030_idx].done) { \
-               mmu030_ad[mmu030_idx].val = v; \
+               mmu030_data_buffer_out = v; \
        } else if (mmu030_ad[mmu030_idx].done) { \
                mmu030_idx++; \
                return; \
@@ -273,6 +283,7 @@ static ALWAYS_INLINE void uae_mmu030_put_byte_fcx(uaecptr addr, uae_u32 val, int
        }
 
 #define ACCESS_EXIT_PUT \
+       mmu030_ad[mmu030_idx].val = mmu030_data_buffer_out; \
        mmu030_ad[mmu030_idx].done = true; \
        mmu030_idx++; \
        mmu030_ad[mmu030_idx].done = false;
@@ -291,7 +302,7 @@ static ALWAYS_INLINE uae_u32 sfc030_get_long(uaecptr addr)
 #if MMUDEBUG > 2
        write_log(_T("sfc030_get_long: FC = %i\n"),fc);
 #endif
-       if (unlikely(is_unaligned(addr, 4)))
+       if (unlikely(is_unaligned_bus(addr, 4)))
                return mmu030_get_long_unaligned(addr, fc, 0);
        return mmu030_get_long(addr, fc);
 }
@@ -302,7 +313,7 @@ static ALWAYS_INLINE uae_u16 sfc030_get_word(uaecptr addr)
 #if MMUDEBUG > 2
        write_log(_T("sfc030_get_word: FC = %i\n"),fc);
 #endif
-    if (unlikely(is_unaligned(addr, 2)))
+    if (unlikely(is_unaligned_bus(addr, 2)))
                return mmu030_get_word_unaligned(addr, fc, 0);
        return mmu030_get_word(addr, fc);
 }
@@ -322,7 +333,7 @@ static ALWAYS_INLINE void dfc030_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
-    if (unlikely(is_unaligned(addr, 4)))
+    if (unlikely(is_unaligned_bus(addr, 4)))
                mmu030_put_long_unaligned(addr, val, fc, 0);
        else
                mmu030_put_long(addr, val, fc);
@@ -334,7 +345,7 @@ static ALWAYS_INLINE void dfc030_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
-       if (unlikely(is_unaligned(addr, 2)))
+       if (unlikely(is_unaligned_bus(addr, 2)))
                mmu030_put_word_unaligned(addr, val, fc, 0);
        else
                mmu030_put_word(addr, val, fc);
index 3a14495e9db9f87e2b00aaf617488e24392bdc36..a04c954e73429f82d735360fd7552331ae737e9f 100644 (file)
@@ -109,17 +109,14 @@ typedef  int m68k_exception;
 #define ALWAYS_INLINE __inline
 
 // take care of 2 kinds of alignment, bus size and page
-#if 1
-static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size)
+static ALWAYS_INLINE bool is_unaligned_page(uaecptr addr, int size)
 {
     return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & regs.mmu_page_size);
 }
-#else
-static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size)
+static ALWAYS_INLINE bool is_unaligned_bus(uaecptr addr, int size)
 {
     return (addr & (size - 1));
 }
-#endif
 
 static ALWAYS_INLINE void phys_put_long(uaecptr addr, uae_u32 l)
 {
index a88589a215672cab710f01731acd3a6c3160b454..c88d3e73eaed1062f26e5c2fbdaaaff24f5dfb03 100644 (file)
@@ -1369,12 +1369,12 @@ static void set_x_funcs (void)
                        } else {
                                icache_fetch = uae_mmu030_get_ilong;
                        }
-                       dcache_lput = uae_mmu030_put_long;
-                       dcache_wput = uae_mmu030_put_word;
-                       dcache_bput = uae_mmu030_put_byte;
-                       dcache_lget = uae_mmu030_get_long;
-                       dcache_wget = uae_mmu030_get_word;
-                       dcache_bget = uae_mmu030_get_byte;
+                       dcache_lput = uae_mmu030_put_long_fc;
+                       dcache_wput = uae_mmu030_put_word_fc;
+                       dcache_bput = uae_mmu030_put_byte_fc;
+                       dcache_lget = uae_mmu030_get_long_fc;
+                       dcache_wget = uae_mmu030_get_word_fc;
+                       dcache_bget = uae_mmu030_get_byte_fc;
                        if (currprefs.cpu_data_cache) {
                                read_data_030_bget = read_dcache030_mmu_bget;
                                read_data_030_wget = read_dcache030_mmu_wget;
@@ -1382,12 +1382,6 @@ static void set_x_funcs (void)
                                write_data_030_bput = write_dcache030_mmu_bput;
                                write_data_030_wput = write_dcache030_mmu_wput;
                                write_data_030_lput = write_dcache030_mmu_lput;
-                               dcache_lput = uae_mmu030_put_long_fc;
-                               dcache_wput = uae_mmu030_put_word_fc;
-                               dcache_bput = uae_mmu030_put_byte_fc;
-                               dcache_lget = uae_mmu030_get_long_fc;
-                               dcache_wget = uae_mmu030_get_word_fc;
-                               dcache_bget = uae_mmu030_get_byte_fc;
                                dcache_check = uae_mmu030_check_fc;
                        } else {
                                read_data_030_bget = uae_mmu030_get_byte;
@@ -3136,18 +3130,28 @@ static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32
                        // our PC always points at start of instruction but A frame assumes
                        // it is + 2 and handling this properly is not easy.
                        // Store state information to internal register space
+#if MMU030_DEBUG
+                       if (mmu030_idx >= MAX_MMU030_ACCESS) {
+                               write_log(_T("mmu030_idx out of bounds! %d >= %d\n"), mmu030_idx, MAX_MMU030_ACCESS);
+                       }
+#endif
                        for (i = 0; i < mmu030_idx + 1; i++) {
                                m68k_areg (regs, 7) -= 4;
                                x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val);
                        }
-                       while (i < 9) {
+                       while (i < MAX_MMU030_ACCESS) {
                                uae_u32 v = 0;
                                m68k_areg (regs, 7) -= 4;
                                // mmu030_idx is always small enough if instruction is FMOVEM.
                                if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) {
-                                       if (i == 7)
+#if MMU030_DEBUG
+                                       if (mmu030_idx >= MAX_MMU030_ACCESS - 2) {
+                                               write_log(_T("mmu030_idx (FMOVEM) out of bounds! %d >= %d\n"), mmu030_idx, MAX_MMU030_ACCESS - 2);
+                                       }
+#endif
+                                       if (i == MAX_MMU030_ACCESS - 2)
                                                v = mmu030_fmovem_store[0];
-                                       else if (i == 8)
+                                       else if (i == MAX_MMU030_ACCESS - 1)
                                                v = mmu030_fmovem_store[1];
                                }
                                x_put_long (m68k_areg (regs, 7), v);
@@ -3189,8 +3193,8 @@ 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), mmu030_disp_store[0]);
                        m68k_areg (regs, 7) -= 4;
-                        // Data output buffer = value that was going to be written
-                       x_put_long (m68k_areg (regs, 7), mmu030_data_buffer);
+                       // Data output buffer = value that was going to be written
+                       x_put_long (m68k_areg (regs, 7), mmu030_data_buffer_out);
                        m68k_areg (regs, 7) -= 4;
                        x_put_long (m68k_areg (regs, 7), (mmu030_opcode & 0xffff) | (regs.prefetch020[0] << 16));  // Internal register (opcode storage)
                        m68k_areg (regs, 7) -= 4;
@@ -3292,7 +3296,7 @@ static void Exception_mmu030 (int nr, uaecptr oldpc)
     } else if (nr == 3) {
                regs.mmu_fault_addr = last_fault_for_exception_3;
                mmu030_state[0] = mmu030_state[1] = 0;
-               mmu030_data_buffer = 0;
+               mmu030_data_buffer_out = 0;
         Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr,  0xA);
        } else {
                Exception_build_stack_frame_common(oldpc, currpc, regs.mmu_ssw, nr);