diff options
| author | Nicolas Pomarede <npomarede@corp.free.fr> | 2020-05-21 20:10:15 (GMT) |
|---|---|---|
| committer | Nicolas Pomarede <npomarede@corp.free.fr> | 2020-05-21 20:10:15 (GMT) |
| commit | 759d60f9dcf3f2971aabd905adb3d7404e8d3b19 (patch) | |
| tree | dba48df130236b6e93ebef55f5c8ad5fa874da0c | |
| parent | 51e9489d04109c1bb07b79f0645f245cf9f0e912 (diff) | |
| download | hatari-759d60f9dcf3f2971aabd905adb3d7404e8d3b19.zip hatari-759d60f9dcf3f2971aabd905adb3d7404e8d3b19.tar.gz | |
68030 MMU fixes. Software fixed pipeline stage fixes and more compatible (prefetch) locked rmw and mmufixup fix (from WinUAE 4.4.0 beta3+ 2020/05/21)
| -rw-r--r-- | src/cpu/cpummu030.c | 40 | ||||
| -rw-r--r-- | src/cpu/cpummu030.h | 16 | ||||
| -rw-r--r-- | src/cpu/gencpu.c | 12 | ||||
| -rw-r--r-- | src/cpu/newcpu.c | 88 | ||||
| -rw-r--r-- | src/cpu/winuae_readme.txt | 4 |
5 files changed, 131 insertions, 29 deletions
diff --git a/src/cpu/cpummu030.c b/src/cpu/cpummu030.c index 736472a..f9c740a 100644 --- a/src/cpu/cpummu030.c +++ b/src/cpu/cpummu030.c @@ -78,7 +78,7 @@ 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 + 1]; -bool ismoves030; +bool ismoves030, islrmw030; 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); @@ -1809,7 +1809,6 @@ 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); } - ismoves030 = false; regs.wb3_status = 0; regs.wb2_status = 0; regs.mmu_fault_addr = addr; @@ -1823,6 +1822,10 @@ void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc) } } else { if (currprefs.cpu_compatible) { + regs.wb2_status = mmu030fixupreg(0); + mmu030fixupmod(regs.wb2_status, 0, 0); + regs.wb3_status = mmu030fixupreg(1); + mmu030fixupmod(regs.wb3_status, 0, 1); if (regs.prefetch020_valid[1] != 1 && regs.prefetch020_valid[2] == 1) { regs.mmu_ssw = MMU030_SSW_FC | MMU030_SSW_RC; } else if (regs.prefetch020_valid[2] != 1) { @@ -1839,6 +1842,7 @@ void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc) regs.mmu_ssw |= read ? MMU030_SSW_RW : 0; regs.mmu_ssw |= flags; regs.mmu_ssw |= fc; + regs.mmu_ssw |= islrmw030 ? MMU030_SSW_RM : 0; // temporary store in 68040+ variables because stack frame creation may modify them. regs.wb3_data = mmu030_data_buffer_out; regs.wb2_address = mmu030_state[1]; @@ -1854,8 +1858,11 @@ void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc) write_log(_T("\n")); #endif + ismoves030 = false; + islrmw030 = false; + #if 0 - if (addr == 0x00016060) + if (addr == 0xc1026ea0) write_log("!"); #endif #if 0 @@ -2447,7 +2454,7 @@ uae_u8 uae_mmu030_check_fc(uaecptr addr, bool write, uae_u32 size) } /* Locked RMW is rarely used */ -uae_u32 uae_mmu030_get_lrmw_fcx(uaecptr addr, int size, int fc) +static 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); @@ -2466,10 +2473,13 @@ uae_u32 uae_mmu030_get_lrmw_fcx(uaecptr addr, int size, int fc) uae_u32 uae_mmu030_get_lrmw(uaecptr addr, int size) { uae_u32 fc = (regs.s ? 4 : 0) | 1; - return uae_mmu030_get_lrmw_fcx(addr, size, fc); + islrmw030 = true; + uae_u32 v = uae_mmu030_get_lrmw_fcx(addr, size, fc); + islrmw030 = false; + return v; } -void uae_mmu030_put_lrmw_fcx(uaecptr addr, uae_u32 val, int size, int fc) +static 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); @@ -2488,7 +2498,9 @@ void uae_mmu030_put_lrmw_fcx(uaecptr addr, uae_u32 val, int size, int fc) void uae_mmu030_put_lrmw(uaecptr addr, uae_u32 val, int size) { uae_u32 fc = (regs.s ? 4 : 0) | 1; + islrmw030 = true; uae_mmu030_put_lrmw_fcx(addr, val, size, fc); + islrmw030 = false; } uae_u32 REGPARAM2 mmu030_get_ilong_unaligned(uaecptr addr, uae_u32 fc, int flags) @@ -2953,8 +2965,8 @@ void m68k_do_rte_mmu030 (uaecptr a7) mmu030_opcode_stageb = stageb; write_log(_T("Software fixed stage B! opcode = %04x\n"), stageb); } else { - mmu030_ad_v[idxsize].val = stageb; - idxsize_done = idxsize; + mmu030_ad_v[idxsize_done].val = stageb; + idxsize_done++; write_log(_T("Software fixed stage B! opcode = %04X, opword = %04x\n"), mmu030_opcode_v, stageb); } } @@ -3013,9 +3025,6 @@ void m68k_do_rte_mmu030 (uaecptr a7) write_log(_T("68030 MMU MOVEM %04x retry but MMU030_STATEFLAG1_MOVEM2 was already set!?\n"), mmu030_opcode); } } - if (idxsize >= 0 && mmu030_ad[idxsize].done) { - write_log(_T("68030 MMU ins %04x retry but it was already marked as done!?\n"), mmu030_opcode); - } #endif #if MMU030_DEBUG @@ -3372,6 +3381,11 @@ void m68k_do_rte_mmu030c (uaecptr a7) mmu030_ad_v[i].val = get_long_mmu030c(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 @@ -3480,10 +3494,6 @@ void m68k_do_rte_mmu030c (uaecptr a7) if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM2) { write_log(_T("68030 MMU MOVEM %04x retry but MMU030_STATEFLAG1_MOVEM2 was already set!?\n"), mmu030_opcode); } - } else { - if (idxsize >= 0 && mmu030_ad[idxsize].done) { - write_log(_T("68030 MMU ins %04x retry but it was already marked as done!?\n"), mmu030_opcode); - } } #endif if (read) { diff --git a/src/cpu/cpummu030.h b/src/cpu/cpummu030.h index 85a6d53..13691ac 100644 --- a/src/cpu/cpummu030.h +++ b/src/cpu/cpummu030.h @@ -26,7 +26,7 @@ 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; -extern bool ismoves030; +extern bool ismoves030, islrmw030; #define MMU030_STATEFLAG1_FMOVEM 0x2000 #define MMU030_STATEFLAG1_MOVEM1 0x4000 @@ -84,9 +84,7 @@ uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc); uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc); uae_u32 uae_mmu030_get_lrmw(uaecptr addr, int size); -uae_u32 uae_mmu030_get_lrmw_fcx(uaecptr addr, int size, int fc); void uae_mmu030_put_lrmw(uaecptr addr, uae_u32 val, int size); -void uae_mmu030_put_lrmw_fcx(uaecptr addr, uae_u32 val, int size, int fc); void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int flags); uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int flags); @@ -750,9 +748,11 @@ STATIC_INLINE void put_byte_mmu030c_state (uaecptr addr, uae_u32 v) } STATIC_INLINE void put_lrmw_byte_mmu030c_state (uaecptr addr, uae_u32 v) { + islrmw030 = true; ACCESS_CHECK_PUT write_dcache030_lrmw_mmu(addr, v, 0); ACCESS_EXIT_PUT + islrmw030 = false; } STATIC_INLINE void put_word_mmu030c_state (uaecptr addr, uae_u32 v) { @@ -762,9 +762,11 @@ STATIC_INLINE void put_word_mmu030c_state (uaecptr addr, uae_u32 v) } STATIC_INLINE void put_lrmw_word_mmu030c_state (uaecptr addr, uae_u32 v) { + islrmw030 = true; ACCESS_CHECK_PUT write_dcache030_lrmw_mmu(addr, v, 1); ACCESS_EXIT_PUT + islrmw030 = false; } STATIC_INLINE void put_long_mmu030c_state (uaecptr addr, uae_u32 v) { @@ -774,9 +776,11 @@ STATIC_INLINE void put_long_mmu030c_state (uaecptr addr, uae_u32 v) } STATIC_INLINE void put_lrmw_long_mmu030c_state (uaecptr addr, uae_u32 v) { + islrmw030 = true; ACCESS_CHECK_PUT write_dcache030_lrmw_mmu(addr, v, 2); ACCESS_EXIT_PUT + islrmw030 = false; } STATIC_INLINE uae_u32 get_byte_mmu030c_state (uaecptr addr) @@ -790,9 +794,11 @@ STATIC_INLINE uae_u32 get_byte_mmu030c_state (uaecptr addr) STATIC_INLINE uae_u32 get_lrmw_byte_mmu030c_state (uaecptr addr) { uae_u32 v; + islrmw030 = true; ACCESS_CHECK_GET v = read_dcache030_lrmw_mmu(addr, 0); ACCESS_EXIT_GET + islrmw030 = false; return v; } @@ -807,9 +813,11 @@ STATIC_INLINE uae_u32 get_word_mmu030c_state (uaecptr addr) STATIC_INLINE uae_u32 get_lrmw_word_mmu030c_state (uaecptr addr) { uae_u32 v; + islrmw030 = true; ACCESS_CHECK_GET v = read_dcache030_lrmw_mmu(addr, 1); ACCESS_EXIT_GET + islrmw030 = false; return v; } STATIC_INLINE uae_u32 get_long_mmu030c_state (uaecptr addr) @@ -823,9 +831,11 @@ STATIC_INLINE uae_u32 get_long_mmu030c_state (uaecptr addr) STATIC_INLINE uae_u32 get_lrmw_long_mmu030c_state (uaecptr addr) { uae_u32 v; + islrmw030 = true; ACCESS_CHECK_GET v = read_dcache030_lrmw_mmu(addr, 2); ACCESS_EXIT_GET + islrmw030 = false; return v; } diff --git a/src/cpu/gencpu.c b/src/cpu/gencpu.c index a0a6720..5ae6afa 100644 --- a/src/cpu/gencpu.c +++ b/src/cpu/gencpu.c @@ -421,8 +421,18 @@ static bool needmmufixup(void) } if (!using_mmu) return false; - if (using_mmu == 68040 && (mmufixupstate || mmufixupcnt > 0)) + if (using_mmu == 68040 && (mmufixupstate || mmufixupcnt > 0)) { return false; + } + if (using_mmu == 68030) { + switch (g_instr->mnemo) + { + case i_LINK: + case i_RTD: + case i_RTR: + return false; + } + } return true; } diff --git a/src/cpu/newcpu.c b/src/cpu/newcpu.c index f0f5f75..874cd95 100644 --- a/src/cpu/newcpu.c +++ b/src/cpu/newcpu.c @@ -852,6 +852,7 @@ static void put_byte030_cicheck(uaecptr addr, uae_u32 v) } static uae_u32 (*icache_fetch)(uaecptr); +static uae_u16 (*icache_fetch_word)(uaecptr); static uae_u32 (*dcache_lget)(uaecptr); static uae_u32 (*dcache_wget)(uaecptr); static uae_u32 (*dcache_bget)(uaecptr); @@ -1445,6 +1446,7 @@ static void set_x_funcs (void) dcache_check = dcache_check_nommu; icache_fetch = get_longi; + icache_fetch_word = NULL; if (currprefs.cpu_cycle_exact) { icache_fetch = mem_access_delay_longi_read_ce020; } @@ -1493,8 +1495,10 @@ static void set_x_funcs (void) if (currprefs.mmu_model) { if (currprefs.cpu_compatible) { icache_fetch = uae_mmu030_get_ilong_fc; + icache_fetch_word = uae_mmu030_get_iword_fc; } else { icache_fetch = uae_mmu030_get_ilong; + icache_fetch_word = uae_mmu030_get_iword_fc; } dcache_lput = uae_mmu030_put_long_fc; dcache_wput = uae_mmu030_put_word_fc; @@ -9331,7 +9335,28 @@ STATIC_INLINE void update_dcache030 (struct cache030 *c, uae_u32 val, uae_u32 ta c->data[lws] = val; } -static void fill_icache030 (uae_u32 addr) +static bool maybe_icache030(uae_u32 addr) +{ + int lws; + uae_u32 tag; + uae_u32 data; + struct cache030 *c; + + regs.fc030 = (regs.s ? 4 : 0) | 2; + addr &= ~3; + if (regs.cacheholdingaddr020 == addr || regs.cacheholdingdata_valid == 0) + return true; + c = geticache030(icaches030, addr, &tag, &lws); + if ((regs.cacr & 1) && c->valid[lws] && c->tag == tag) { + // cache hit + regs.cacheholdingaddr020 = addr; + regs.cacheholdingdata020 = c->data[lws]; + return true; + } + return false; +} + +static void fill_icache030(uae_u32 addr) { int lws; uae_u32 tag; @@ -9945,6 +9970,10 @@ uae_u32 get_word_030_prefetch (int o) regs.prefetch020_valid[1] = regs.prefetch020_valid[2]; regs.prefetch020_valid[2] = false; if (!regs.prefetch020_valid[1]) { + if (regs.pipeline_stop) { + regs.db = regs.prefetch020[0]; + return v; + } do_access_or_bus_error(0xffffffff, pc + 4); } #if MORE_ACCURATE_68020_PIPELINE @@ -10735,15 +10764,59 @@ void fill_prefetch_030_ntx_continue (void) regs.cacheholdingdata_valid = 1; regs.cacheholdingaddr020 = 0xffffffff; - for (int i = 2; i >= 0; i--) { - if (!regs.prefetch020_valid[i]) - break; + if (regs.prefetch020_valid[0] && regs.prefetch020_valid[1] && regs.prefetch020_valid[2]) { + for (int i = 2; i >= 0; i--) { + regs.prefetch020[i + 1] = regs.prefetch020[i]; + } + for (int i = 1; i <= 3; i++) { +#if MORE_ACCURATE_68020_PIPELINE + pipeline_020(pc); +#endif + regs.prefetch020[i - 1] = regs.prefetch020[i]; + pc += 2; + idx++; + } + } else if (regs.prefetch020_valid[2] && !regs.prefetch020_valid[1]) { + regs.prefetch020_valid[1] = regs.prefetch020_valid[2]; + regs.prefetch020[1] = regs.prefetch020[2]; + regs.prefetch020_valid[2] = 0; + pc += 2; + idx++; +#if MORE_ACCURATE_68020_PIPELINE + pipeline_020(pc); +#endif + if (!regs.pipeline_stop) { + if (maybe_icache030(pc)) { + regs.prefetch020[2] = regs.cacheholdingdata020 >> (regs.cacheholdingaddr020 == pc ? 16 : 0); + } else { + regs.prefetch020[2] = icache_fetch_word(pc); + } + regs.prefetch020_valid[2] = 1; + pc += 2; + idx++; #if MORE_ACCURATE_68020_PIPELINE - if (idx >= 1) { pipeline_020(pc); +#endif } + + } else if (regs.prefetch020_valid[2] && regs.prefetch020_valid[1]) { + pc += 2; +#if MORE_ACCURATE_68020_PIPELINE + pipeline_020(pc); #endif pc += 2; +#if MORE_ACCURATE_68020_PIPELINE + pipeline_020(pc); +#endif + idx += 2; + } + + while (idx < 2) { + regs.prefetch020[0] = regs.prefetch020[1]; + regs.prefetch020[1] = regs.prefetch020[2]; + regs.prefetch020_valid[0] = regs.prefetch020_valid[1]; + regs.prefetch020_valid[1] = regs.prefetch020_valid[2]; + regs.prefetch020_valid[2] = false; idx++; } @@ -10774,10 +10847,9 @@ void fill_prefetch_030_ntx_continue (void) ipl_fetch(); if (currprefs.cpu_cycle_exact) - regs.irc = get_word_ce030_prefetch_opcode (0); + regs.irc = get_word_ce030_prefetch_opcode(0); else - regs.irc = get_word_030_prefetch (0); -//fprintf ( stderr , "fill_prefetch_030_ntx4 %d\n" , currcycle); + regs.irc = get_word_030_prefetch(0); } void fill_prefetch_020_ntx(void) diff --git a/src/cpu/winuae_readme.txt b/src/cpu/winuae_readme.txt index 076042f..e84cf3d 100644 --- a/src/cpu/winuae_readme.txt +++ b/src/cpu/winuae_readme.txt @@ -1,9 +1,9 @@ The CPU core in this directory is based on - WinUAE 4.4.0 beta2 (2020/05/02) + WinUAE 4.4.0 beta3 (2020/05/21) To update to a newer WinUAE's version, a diff should be made between -WinUAE 4.4.0 beta2 sources and the newer sources, then the resulting patch +WinUAE 4.4.0 beta3 sources and the newer sources, then the resulting patch should be applied to the files in this directory. Most files are similar to WinUAE's ones, so patches should apply in |
