From 7dfd7f276dd2faeefa1f4b2fdc9712b4ffa46f52 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Mon, 5 Jan 2015 13:32:41 +0200 Subject: [PATCH] Simple prefetch emulation when 68030 MMU is switched on or off. Some programs switch on MMU and then assume at least next opcode word (JMP (An)) has already been prefetched. Fix crash when switching MMU emulation on/off on the fly. --- cpummu30.cpp | 37 ++++++++++++++++++++++++++++++++----- include/cpummu030.h | 3 ++- newcpu.cpp | 45 ++++++++++----------------------------------- 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/cpummu30.cpp b/cpummu30.cpp index 7f204164..66a1594c 100644 --- a/cpummu30.cpp +++ b/cpummu30.cpp @@ -60,6 +60,7 @@ uae_u32 mm030_stageb_address; bool mmu030_retry; int mmu030_opcode; int mmu030_opcode_stageb; +int mmu030_fake_prefetch; uae_u16 mmu030_state[3]; uae_u32 mmu030_data_buffer; uae_u32 mmu030_disp_store[2]; @@ -709,15 +710,35 @@ int mmu030_do_match_lrmw_ttr(uae_u32 tt, TT_info comp, uaecptr addr, uae_u32 fc) #define TC_TIC_MASK 0x000000F0 #define TC_TID_MASK 0x0000000F +static void mmu030_do_fake_prefetch(void) +{ + uaecptr pc = m68k_getpci(); + // fetch next opcode before MMU state switches. + // There are programs that do following: + // - enable MMU + // - JMP (An) + // "enable MMU" unmaps memory under us. + TRY (prb) { + mmu030_fake_prefetch = x_prefetch(0); + } CATCH (prb) { + // didn't work, oh well.. + mmu030_fake_prefetch = -1; + } ENDTRY + write_log(_T("MMU030 fake prefetched %04X\n"), mmu030_fake_prefetch); +} -bool mmu030_decode_tc(uae_u32 TC) { - +bool mmu030_decode_tc(uae_u32 TC) +{ /* Set MMU condition */ if (TC & TC_ENABLE_TRANSLATION) { + if (!mmu030.enabled) + mmu030_do_fake_prefetch(); mmu030.enabled = true; } else { - if (mmu030.enabled) + if (mmu030.enabled) { + mmu030_do_fake_prefetch(); write_log(_T("MMU disabled\n")); + } mmu030.enabled = false; return false; } @@ -1957,8 +1978,7 @@ uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc) { if (atc_line_num >= 0) { return mmu030_get_iword_atc(addr, atc_line_num, fc); - } - else { + } else { mmu030_table_search(addr, fc, false, 0); return mmu030_get_iword_atc(addr, mmu030_logical_is_in_atc(addr, fc, false), fc); } @@ -2288,6 +2308,13 @@ void mmu030_reset(int hardreset) mmusr_030 = 0; mmu030_flush_atc_all(); } + mmu030_set_funcs(); +} + +void mmu030_set_funcs(void) +{ + if (currprefs.mmu_model != 68030) + return; if (currprefs.cpu_cycle_exact || currprefs.cpu_compatible) { x_phys_get_iword = get_word_icache030; x_phys_get_ilong = get_long_icache030; diff --git a/include/cpummu030.h b/include/cpummu030.h index 9136bcaf..577f5ab3 100644 --- a/include/cpummu030.h +++ b/include/cpummu030.h @@ -11,7 +11,7 @@ extern uae_u16 mmusr_030; extern uae_u32 mm030_stageb_address; extern int mmu030_idx; extern bool mmu030_retry; -extern int mmu030_opcode, mmu030_opcode_stageb; +extern int mmu030_opcode, mmu030_opcode_stageb, mmu030_fake_prefetch; extern uae_u16 mmu030_state[3]; extern uae_u32 mmu030_data_buffer; extern uae_u32 mmu030_disp_store[2]; @@ -74,6 +74,7 @@ void mmu030_flush_atc_page(uaecptr logical_addr); void mmu030_flush_atc_page_fc(uaecptr logical_addr, uae_u32 fc_base, uae_u32 fc_mask); void mmu030_flush_atc_all(void); void mmu030_reset(int hardreset); +void mmu030_set_funcs(void); uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write); int mmu030_match_ttr(uaecptr addr, uae_u32 fc, bool write); diff --git a/newcpu.cpp b/newcpu.cpp index 86d51022..2676898d 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -1016,6 +1016,7 @@ static void set_x_funcs (void) } set_x_cp_funcs(); + mmu030_set_funcs(); } @@ -2460,7 +2461,7 @@ static void Exception_mmu (int nr, uaecptr oldpc) Exception_build_stack_frame(oldpc, currpc, regs.mmu_fslw, nr, 0x4); } else if (nr == 3) { // address error Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2); - write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long (regs.vbr + 4 * nr)); + write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long_debug (regs.vbr + 4 * nr)); } else if (nr == 5 || nr == 6 || nr == 7 || nr == 9) { Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2); } else if (regs.m && interrupt) { /* M + Interrupt */ @@ -3587,37 +3588,6 @@ isstopped: } #endif -#if 0 - if (!uae_int_requested && !uaenet_int_requested && currprefs.cpu_idle && currprefs.m68k_speed != 0 && (regs.spcflags & SPCFLAG_STOP) -#ifdef WITH_PPC - && ppc_state != PPC_STATE_ACTIVE -#endif - ) { - /* sleep 1ms if STOP-instruction is executed - * but only if we have free frametime left to prevent slowdown - */ - { - static int sleepcnt, lvpos, zerocnt; - if (vpos != lvpos) { - lvpos = vpos; - frame_time_t rpt = read_processor_time (); - if ((int)rpt - (int)vsyncmaxtime < 0) { - sleepcnt--; -#if 0 - if (pissoff == 0 && currprefs.cachesize && --zerocnt < 0) { - sleepcnt = -1; - zerocnt = IDLETIME / 4; - } -#endif - if (sleepcnt < 0) { - sleepcnt = IDLETIME / 2; - cpu_sleep_millis(1); - } - } - } - } - } -#endif } if (regs.spcflags & SPCFLAG_TRACE) @@ -4229,6 +4199,7 @@ static void m68k_run_mmu030 (void) struct flag_struct f; mmu030_opcode_stageb = -1; + mmu030_fake_prefetch = -1; retry: TRY (prb) { for (;;) { @@ -4240,8 +4211,11 @@ insretry: mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0; mmu030_opcode = -1; - if (mmu030_opcode_stageb < 0) { - regs.opcode = get_iword_mmu030 (0); + if (mmu030_fake_prefetch >= 0) { + regs.opcode = mmu030_fake_prefetch; + mmu030_fake_prefetch = -1; + } else if (mmu030_opcode_stageb < 0) { + regs.opcode = x_prefetch (0); } else { regs.opcode = mmu030_opcode_stageb; mmu030_opcode_stageb = -1; @@ -4257,6 +4231,7 @@ insretry: count_instr (regs.opcode); do_cycles (cpu_cycles); mmu030_retry = false; + cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode); cnt--; // so that we don't get in infinite loop if things go horribly wrong if (!mmu030_retry) @@ -4375,8 +4350,8 @@ retry: goto retry; } ENDTRY } -/* "cycle exact" 68020/030 */ +/* "cycle exact" 68020/030 */ static void m68k_run_2ce (void) { -- 2.47.3