From af4616e5029fd1d159c29bca3a36e78615e19454 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Thu, 13 Mar 2014 19:11:27 +0200 Subject: [PATCH] 68040 MMU MOVE16 access fault update. --- cpummu.cpp | 50 +++++++++++++++++++++++++++++++++++++++++--- gencpu.cpp | 9 +++++--- include/cpummu.h | 32 +++------------------------- include/mmu_common.h | 1 + include/newcpu.h | 5 +++-- newcpu.cpp | 31 +++++++++++++++++++-------- 6 files changed, 82 insertions(+), 46 deletions(-) diff --git a/cpummu.cpp b/cpummu.cpp index 15bcf3d7..122e28ba 100644 --- a/cpummu.cpp +++ b/cpummu.cpp @@ -57,6 +57,7 @@ int mmu_atc_ways; int mmu040_movem; uaecptr mmu040_movem_ea; +uae_u32 mmu040_move16[4]; static void mmu_dump_ttr(const TCHAR * label, uae_u32 ttr) { @@ -276,6 +277,9 @@ void mmu_bus_error(uaecptr addr, int fc, bool write, int size, bool rmw, uae_u32 } ssw |= fc & MMU_SSW_TM; /* TM = FC */ + regs.wb3_status = write ? 0x80 | (ssw & 0x7f) : 0; + regs.wb2_status = 0; + switch (size) { case sz_byte: ssw |= MMU_SSW_SIZE_B; @@ -287,13 +291,20 @@ void mmu_bus_error(uaecptr addr, int fc, bool write, int size, bool rmw, uae_u32 ssw |= MMU_SSW_SIZE_L; break; case 16: // MOVE16 - ssw |= MMU_SSW_SIZE_L; // ?? + ssw |= MMU_SSW_SIZE_L; // ?? maybe MMU_SSW_SIZE_CL? ssw |= MMU_SSW_TT0; - write_log (_T("040 MMU MOVE16 FAULT!\n")); + regs.mmu_effective_addr &= ~15; + if (write) { + // clear normal writeback if MOVE16 write + regs.wb3_status &= ~0x80; + // wb2 = cacheline size writeback + regs.wb2_status = 0x80 | MMU_SSW_SIZE_CL | (ssw & 0x1f); + regs.wb2_address = regs.mmu_effective_addr; + write_log (_T("040 MMU MOVE16 WRITE FAULT!\n")); + } break; } - regs.wb3_status = write ? 0x80 | (ssw & 0x7f) : 0; if (!write) ssw |= MMU_SSW_RW; @@ -967,6 +978,39 @@ void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val) ismoves = false; } +void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size) +{ + struct mmu_atc_line *cl; + addr &= ~15; + for (int i = 0; i < 4; i++) { + uaecptr addr2 = addr + i * 4; + // addr,super,data + if ((!regs.mmu_enabled) || (mmu_match_ttr(addr2,regs.s != 0,data,false)!=TTR_NO_MATCH)) + v[i] = phys_get_long(addr2); + else if (likely(mmu_lookup(addr2, data, false, &cl))) + v[i] = phys_get_long(mmu_get_real_address(addr2, cl)); + else + v[i] = mmu_get_long_slow(addr2, regs.s != 0, data, size, false, cl); + } +} + +void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size) +{ + struct mmu_atc_line *cl; + addr &= ~15; + for (int i = 0; i < 4; i++) { + uaecptr addr2 = addr + i * 4; + // addr,super,data + if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr2,regs.s != 0,data,val[i],size,false)==TTR_OK_MATCH)) + phys_put_long(addr2,val[i]); + else if (likely(mmu_lookup(addr2, data, true, &cl))) + phys_put_long(mmu_get_real_address(addr2, cl), val[i]); + else + mmu_put_long_slow(addr2, val[i], regs.s != 0, data, size, false, cl); + } +} + + void REGPARAM2 mmu_op_real(uae_u32 opcode, uae_u16 extra) { bool super = (regs.dfc & 4) != 0; diff --git a/gencpu.cpp b/gencpu.cpp index d4b0fdb9..84c261bf 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -4976,12 +4976,15 @@ static void gen_opcode (unsigned long int opcode) printf ("\tuae_u32 v[4];\n"); genamode (curi, curi->smode, "srcreg", curi->size, "mems", 0, 2, 0); genamode (curi, curi->dmode, "dstreg", curi->size, "memd", 0, 2, 0); - printf ("\tmemsa &= ~15;\n"); - printf ("\tmemda &= ~15;\n"); - if (using_mmu >= 68040) { + if (using_mmu == 68040) { + printf ("\tget_move16_mmu (memsa, mmu040_move16);\n"); + printf ("\tput_move16_mmu (memda, mmu040_move16);\n"); + } else if (using_mmu == 68060) { printf ("\tget_move16_mmu (memsa, v);\n"); printf ("\tput_move16_mmu (memda, v);\n"); } else { + printf ("\tmemsa &= ~15;\n"); + printf ("\tmemda &= ~15;\n"); printf ("\tv[0] = %s (memsa);\n", srcl); printf ("\tv[1] = %s (memsa + 4);\n", srcl); printf ("\tv[2] = %s (memsa + 8);\n", srcl); diff --git a/include/cpummu.h b/include/cpummu.h index ea1aa1b1..458b1972 100644 --- a/include/cpummu.h +++ b/include/cpummu.h @@ -47,6 +47,7 @@ extern int mmu060_state; extern int mmu040_movem; extern uaecptr mmu040_movem_ea; +extern uae_u32 mmu040_move16[4]; extern bool mmu_pagesize_8k; extern uae_u16 mmu_opcode; @@ -384,20 +385,8 @@ static ALWAYS_INLINE uaecptr mmu_get_real_address(uaecptr addr, struct mmu_atc_l return cl->phys | (addr & mmu_pagemask); } -static ALWAYS_INLINE void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size) -{ - struct mmu_atc_line *cl; - for (int i = 0; i < 4; i++) { - uaecptr addr2 = addr + i * 4; - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr2,regs.s != 0,data,false)!=TTR_NO_MATCH)) - v[i] = phys_get_long(addr2); - else if (likely(mmu_lookup(addr2, data, false, &cl))) - v[i] = phys_get_long(mmu_get_real_address(addr2, cl)); - else - v[i] = mmu_get_long_slow(addr2, regs.s != 0, data, size, false, cl); - } -} +extern void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size); +extern void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size); static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, bool data, int size, bool rmw) { @@ -450,21 +439,6 @@ static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int mmu_put_long_slow(addr, val, regs.s != 0, data, size, rmw, cl); } -static ALWAYS_INLINE void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size) -{ - struct mmu_atc_line *cl; - for (int i = 0; i < 4; i++) { - uaecptr addr2 = addr + i * 4; - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr2,regs.s != 0,data,val[i],size,false)==TTR_OK_MATCH)) - phys_put_long(addr2,val[i]); - else if (likely(mmu_lookup(addr2, data, true, &cl))) - phys_put_long(mmu_get_real_address(addr2, cl), val[i]); - else - mmu_put_long_slow(addr2, val[i], regs.s != 0, data, size, false, cl); - } -} - static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, bool data, int size, bool rmw) { struct mmu_atc_line *cl; diff --git a/include/mmu_common.h b/include/mmu_common.h index 63cd7ccb..50241798 100644 --- a/include/mmu_common.h +++ b/include/mmu_common.h @@ -83,6 +83,7 @@ typedef int m68k_exception; #define MMU_SSW_SIZE_B 0x0020 #define MMU_SSW_SIZE_W 0x0040 #define MMU_SSW_SIZE_L 0x0000 +#define MMU_SSW_SIZE_CL 0x0060 #define MMU_SSW_RW 0x0100 #define MMU_SSW_LK 0x0200 #define MMU_SSW_ATC 0x0400 diff --git a/include/newcpu.h b/include/newcpu.h index cf4c0568..2b7fdcd9 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -167,8 +167,8 @@ struct regstruct #ifdef FPUEMU fpdata fp[8]; fpdata fp_result; + uae_u32 fp_result_status; uae_u32 fpcr, fpsr, fpiar; - uae_u32 fpsr_highbyte; uae_u32 fpu_state; uae_u32 fpu_exp_state; fpdata exp_src1, exp_src2; @@ -183,8 +183,9 @@ struct regstruct uae_u32 mmu_fslw; uae_u32 mmu_fault_addr, mmu_effective_addr; uae_u16 mmu_ssw; + uae_u32 wb2_address; uae_u32 wb3_data; - uae_u16 wb3_status; + uae_u8 wb3_status, wb2_status; int mmu_enabled; int mmu_page_size; #endif diff --git a/newcpu.cpp b/newcpu.cpp index 4831d8ab..60bdae08 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -2062,24 +2062,37 @@ static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 x_put_long (m68k_areg (regs, 7), oldpc); break; case 0x7: // access error stack frame (68040) - for (i = 0 ; i < 7 ; i++) { + + for (i = 3; i >= 0; i--) { + // WB1D/PD0,PD1,PD2,PD3 m68k_areg (regs, 7) -= 4; - x_put_long (m68k_areg (regs, 7), 0); - } + x_put_long (m68k_areg (regs, 7), mmu040_move16[i]); + } + m68k_areg (regs, 7) -= 4; - x_put_long (m68k_areg (regs, 7), regs.wb3_data); + x_put_long (m68k_areg (regs, 7), 0); // WB1A + m68k_areg (regs, 7) -= 4; + x_put_long (m68k_areg (regs, 7), 0); // WB2D m68k_areg (regs, 7) -= 4; - x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); + x_put_long (m68k_areg (regs, 7), regs.wb2_address); // WB2A + m68k_areg (regs, 7) -= 4; + x_put_long (m68k_areg (regs, 7), regs.wb3_data); // WB3D m68k_areg (regs, 7) -= 4; - x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); - m68k_areg (regs, 7) -= 2; + x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // WB3A + + m68k_areg (regs, 7) -= 4; + x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // FA + + m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), 0); m68k_areg (regs, 7) -= 2; - x_put_word (m68k_areg (regs, 7), 0); + x_put_word (m68k_areg (regs, 7), regs.wb2_status); + regs.wb2_status = 0; m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), regs.wb3_status); regs.wb3_status = 0; - m68k_areg (regs, 7) -= 2; + + m68k_areg (regs, 7) -= 2; x_put_word (m68k_areg (regs, 7), ssw); m68k_areg (regs, 7) -= 4; x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr); -- 2.47.3