]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Fixed return modified register value in 68030 mmu bus error exception handler if...
authorToni Wilen <twilen@winuae.net>
Sun, 5 Jan 2020 19:51:25 +0000 (21:51 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 5 Jan 2020 19:51:25 +0000 (21:51 +0200)
cpummu30.cpp
newcpu_common.cpp

index 6616a16fc219d7e2dbc929291e84b1027bea92d1..4d744c5477a6fb278dc62a6780d24da97ebb6daa 100644 (file)
@@ -1762,17 +1762,35 @@ static void dump_opcode(uae_u16 opcode)
 
 // if CPU is 68030 and faulted access' addressing mode was -(an) or (an)+
 // register content is not restored when exception starts.
-static void mmu030fixupreg(int i)
+static uae_u8 mmu030fixupreg(int i)
 {
        struct mmufixup *m = &mmufixup[i];
+       uae_u8 v = 0;
        if (m->reg < 0)
+               return v;
+       if (!(m->reg & 0x300))
+               return v;
+       v = m->reg & 7;
+       v |= ((m->reg >> 10) & 3) << 3; // size
+       if (m->reg & 0x200) // -(an)?
+               v |= 1 << 5;
+       v |= 1 << 6;
+       return v;
+}
+
+static void mmu030fixupmod(uae_u8 data, int dir, int idx)
+{
+       if (!data)
                return;
-       int size = 1 << ((m->reg >> 10) & 3);
-       if (m->reg & 0x100) {
-               m68k_areg(regs, m->reg & 15) += size;
-       }
-       if (m->reg & 0x200) {
-               m68k_areg(regs, m->reg & 15) -= size;
+       int reg = data & 7;
+       int adj = (data & (1 << 5)) ? -1 : 1;
+       if (dir)
+               adj = -adj;
+       adj <<= (data >> 3) & 3;
+       m68k_areg(regs, reg) += adj;
+       if (idx >= 0) {
+               struct mmufixup *m = &mmufixup[idx];
+               m->value += adj;
        }
 }
 
@@ -1783,9 +1801,17 @@ void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc)
                fc = regs.mmu_ssw & MMU030_SSW_FC_MASK;
                flags = regs.mmu_ssw & ~(MMU030_SSW_FC | MMU030_SSW_RC | MMU030_SSW_FB | MMU030_SSW_RB | MMU030_SSW_RW | 7);
        }
+       regs.wb3_status = 0;
+       regs.wb2_status = 0;
        regs.mmu_fault_addr = addr;
        if (fc & 1) {
                regs.mmu_ssw = MMU030_SSW_DF | (MMU030_SSW_DF << 1);
+               if (!(mmu030_state[1] & MMU030_STATEFLAG1_LASTWRITE)) {
+                       regs.wb2_status = mmu030fixupreg(0);
+                       mmu030fixupmod(regs.wb2_status, 0, 0);
+                       regs.wb3_status = mmu030fixupreg(1);
+                       mmu030fixupmod(regs.wb3_status, 0, 1);
+               }
        } else {
                if (currprefs.cpu_compatible) {
                        if (regs.prefetch020_valid[1] != 1 && regs.prefetch020_valid[2] == 1) {
@@ -1800,10 +1826,6 @@ void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc)
                } else {
                        regs.mmu_ssw = MMU030_SSW_FB | MMU030_SSW_RB;
                }
-               if (!(mmu030_state[1] & MMU030_STATEFLAG1_LASTWRITE)) {
-                       mmu030fixupreg(0);
-                       mmu030fixupreg(1);
-               }
        }
        regs.mmu_ssw |= read ? MMU030_SSW_RW : 0;
        regs.mmu_ssw |= flags;
@@ -2840,12 +2862,17 @@ void m68k_do_rte_mmu030 (uaecptr a7)
                }
 
                uae_u16 v = get_word_mmu030(a7 + 0x36);
-               idxsize = v & 0xff;
-               idxsize_done = (v >> 8) & 0xff;
+               idxsize = v & 0x0f;
+               idxsize_done = (v >> 4) & 0x0f;
                for (int i = 0; i < idxsize_done + 1; i++) {
                        mmu030_ad_v[i].val = get_long_mmu030(a7 + 0x5c - (i + 1) * 4);
                }
 
+               regs.wb2_status = v >> 8;
+               regs.wb3_status = mmu030_state_2 >> 8;
+               mmu030fixupmod(regs.wb2_status, 1, -1);
+               mmu030fixupmod(regs.wb3_status, 1, -1);
+
                // 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
@@ -3286,8 +3313,8 @@ void m68k_do_rte_mmu030c (uaecptr a7)
                }
 
                uae_u16 v = get_word_mmu030c(a7 + 0x36);
-               idxsize = v & 0xff;
-               idxsize_done = (v >> 8) & 0xff;
+               idxsize = v & 0x0f;
+               idxsize_done = (v >> 4) & 0x0f;
                for (int i = 0; i < idxsize_done + 1; i++) {
                        mmu030_ad_v[i].val = get_long_mmu030c(a7 + 0x5c - (i + 1) * 4);
                }
index cbda589510e8845f5f93c79a980cf33dbe0b735a..2d1b95aeaae6d4997c73b51b667f149cfdbee9ac 100644 (file)
@@ -1436,10 +1436,10 @@ void Exception_build_stack_frame(uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int
                }
                // version & internal information (We store index here)
                m68k_areg(regs, 7) -= 2;
-               x_put_word(m68k_areg(regs, 7), (mmu030_idx & 0xff) | ((mmu030_idx_done & 0xff) << 8));
+               x_put_word(m68k_areg(regs, 7), (mmu030_idx & 0xf) | ((mmu030_idx_done & 0xf) << 4) | (regs.wb2_status << 8));
                // 3* internal registers
                m68k_areg(regs, 7) -= 2;
-               x_put_word(m68k_areg(regs, 7), mmu030_state[2]);
+               x_put_word(m68k_areg(regs, 7), mmu030_state[2] | (regs.wb3_status << 8));
                m68k_areg(regs, 7) -= 2;
                x_put_word(m68k_areg(regs, 7), regs.wb2_address); // = mmu030_state[1]
                m68k_areg(regs, 7) -= 2;