From 1070e818e049f81a22815d4f28b70358a67c41ed Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 2 Aug 2015 20:52:52 +0300 Subject: [PATCH] 68030 prefetch/ce pipeline emulation added (68020 was added earlier). --- gencpu.cpp | 25 +++++++++++++---- include/cpu_prefetch.h | 64 ++++++++++++++++++++++++++++++++++++++++++ newcpu.cpp | 62 +++++++++++++++++++++++++++++++++++----- 3 files changed, 139 insertions(+), 12 deletions(-) diff --git a/gencpu.cpp b/gencpu.cpp index 29da6296..67773c4f 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -542,7 +542,7 @@ static const char *gen_nextiword (int flags) } else { if (using_prefetch) { if (flags & GF_NOREFILL) { - sprintf (buffer, "regs.irc", r); + strcpy (buffer, "regs.irc"); } else { sprintf (buffer, "%s (%d)", prefetch_word, r + 2); count_read++; @@ -579,7 +579,7 @@ static const char *gen_nextibyte (int flags) insn_n_cycles += 4; if (using_prefetch) { if (flags & GF_NOREFILL) { - sprintf (buffer, "(uae_u8)regs.irc", r); + strcpy (buffer, "(uae_u8)regs.irc"); } else { sprintf (buffer, "(uae_u8)%s (%d)", prefetch_word, r + 2); insn_n_cycles += 4; @@ -2819,7 +2819,7 @@ static void resetvars (void) do_cycles = "do_cycles_ce020_internal"; nextw = "next_iword_cache040"; nextl = "next_ilong_cache040"; - } else if (using_prefetch_020) { + } else if (using_prefetch_020 == 1) { disp020 = "x_get_disp_ea_020"; prefetch_word = "get_word_020_prefetch"; prefetch_long = "get_long_020_prefetch"; @@ -2834,6 +2834,21 @@ static void resetvars (void) dstb = "x_put_byte"; nextw = "next_iword_020_prefetch"; nextl = "next_ilong_020_prefetch"; + } else if (using_prefetch_020 == 2) { + disp020 = "x_get_disp_ea_020"; + prefetch_word = "get_word_030_prefetch"; + prefetch_long = "get_long_030_prefetch"; + srcli = "x_get_ilong"; + srcwi = "x_get_iword"; + srcbi = "x_get_ibyte"; + srcl = "x_get_long"; + dstl = "x_put_long"; + srcw = "x_get_word"; + dstw = "x_put_word"; + srcb = "x_get_byte"; + dstb = "x_put_byte"; + nextw = "next_iword_030_prefetch"; + nextl = "next_ilong_030_prefetch"; } #if 0 } else if (using_ce020) { @@ -5788,14 +5803,14 @@ static void generate_cpu (int id, int mode) } } else if (id == 20) { // 68020 prefetch cpu_level = 2; - using_prefetch_020 = 2; + using_prefetch_020 = 1; read_counts (); for (rp = 0; rp < nr_cpuop_funcs; rp++) opcode_next_clev[rp] = cpu_level; } else if (id == 21) { // 68020 cycle-exact cpu_level = 2; using_ce020 = 1; - using_prefetch_020 = 2; + using_prefetch_020 = 1; // timing tables are from 030 which has 2 // clock memory accesses, 68020 has 3 clock // memory accesses diff --git a/include/cpu_prefetch.h b/include/cpu_prefetch.h index 035daca0..c479346d 100644 --- a/include/cpu_prefetch.h +++ b/include/cpu_prefetch.h @@ -153,6 +153,70 @@ STATIC_INLINE void m68k_do_rts_ce020 (void) #ifdef CPUEMU_22 +extern uae_u32 get_word_030_prefetch(int); + +STATIC_INLINE void put_long_030(uaecptr addr, uae_u32 v) +{ + write_dcache030(addr, v, 2); +} +STATIC_INLINE void put_word_030(uaecptr addr, uae_u32 v) +{ + write_dcache030(addr, v, 1); +} +STATIC_INLINE void put_byte_030(uaecptr addr, uae_u32 v) +{ + write_dcache030(addr, v, 0); +} +STATIC_INLINE uae_u32 get_long_030(uaecptr addr) +{ + return read_dcache030(addr, 2); +} +STATIC_INLINE uae_u32 get_word_030(uaecptr addr) +{ + return read_dcache030(addr, 1); +} +STATIC_INLINE uae_u32 get_byte_030(uaecptr addr) +{ + return read_dcache030(addr, 0); +} + +STATIC_INLINE uae_u32 get_long_030_prefetch(int o) +{ + uae_u32 v; + v = get_word_030_prefetch(o) << 16; + v |= get_word_030_prefetch(o + 2); + return v; +} + +STATIC_INLINE uae_u32 next_iword_030_prefetch(void) +{ + uae_u32 r = get_word_030_prefetch(0); + m68k_incpci(2); + return r; +} +STATIC_INLINE uae_u32 next_ilong_030_prefetch(void) +{ + uae_u32 r = get_long_030_prefetch(0); + m68k_incpci(4); + return r; +} + +STATIC_INLINE void m68k_do_bsr_030(uaecptr oldpc, uae_s32 offset) +{ + m68k_areg(regs, 7) -= 4; + put_long_030(m68k_areg(regs, 7), oldpc); + m68k_incpci(offset); +} +STATIC_INLINE void m68k_do_rts_030(void) +{ + m68k_setpc(get_long_030(m68k_areg(regs, 7))); + m68k_areg(regs, 7) += 4; +} + +#endif + +#ifdef CPUEMU_23 + extern uae_u32 get_word_ce030_prefetch(int); STATIC_INLINE void put_long_ce030 (uaecptr addr, uae_u32 v) diff --git a/newcpu.cpp b/newcpu.cpp index 513e6a23..79bae779 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -871,11 +871,11 @@ static void set_x_funcs (void) x_do_cycles_post = do_cycles_post; } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) { x_prefetch = get_word_prefetch; - x_get_ilong = get_long_020_prefetch; - x_get_iword = get_word_020_prefetch; + x_get_ilong = get_long_030_prefetch; + x_get_iword = get_word_030_prefetch; x_get_ibyte = NULL; - x_next_iword = next_iword_020_prefetch; - x_next_ilong = next_ilong_020_prefetch; + x_next_iword = next_iword_030_prefetch; + x_next_ilong = next_ilong_030_prefetch; x_put_long = put_long; x_put_word = put_word; x_put_byte = put_byte; @@ -7282,16 +7282,50 @@ uae_u32 get_word_ce030_prefetch (int o) if (pc & 2) { v = regs.prefetch020[0] & 0xffff; +#if MORE_ACCURATE_68020_PIPELINE + pipeline_020(regs.prefetch020[1], pc); +#endif regs.prefetch020[0] = regs.prefetch020[1]; - fill_icache030 (pc + 2 + 4); - regs.prefetch020[1] = regs.cacheholdingdata020; + // branch instruction detected in pipeline: stop fetches until branch executed. + if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) { + fill_icache030 (pc + 2 + 4); + regs.prefetch020[1] = regs.cacheholdingdata020; + } } else { v = regs.prefetch020[0] >> 16; +#if MORE_ACCURATE_68020_PIPELINE + pipeline_020(regs.prefetch020[1] >> 16, pc); +#endif } do_cycles_ce020_internal (2); return v; } +uae_u32 get_word_030_prefetch(int o) +{ + uae_u32 pc = m68k_getpc() + o; + uae_u32 v; + + if (pc & 2) { + v = regs.prefetch020[0] & 0xffff; +#if MORE_ACCURATE_68020_PIPELINE + pipeline_020(regs.prefetch020[1], pc); +#endif + regs.prefetch020[0] = regs.prefetch020[1]; + // branch instruction detected in pipeline: stop fetches until branch executed. + if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) { + fill_icache030(pc + 2 + 4); + regs.prefetch020[1] = regs.cacheholdingdata020; + } + } else { + v = regs.prefetch020[0] >> 16; +#if MORE_ACCURATE_68020_PIPELINE + pipeline_020(regs.prefetch020[1] >> 16, pc); +#endif + } + return v; +} + uae_u32 get_word_icache030(uaecptr addr) { fill_icache030(addr); @@ -7688,6 +7722,7 @@ void flush_dcache (uaecptr addr, int size) void fill_prefetch_030 (void) { uaecptr pc = m68k_getpc (); + uaecptr pc2 = pc; pc &= ~3; regs.pipeline_pos = 0; regs.pipeline_stop = 0; @@ -7702,7 +7737,20 @@ void fill_prefetch_030 (void) do_cycles_ce020_internal(2); regs.prefetch020[1] = regs.cacheholdingdata020; - regs.irc = get_word_ce030_prefetch (0); +#if MORE_ACCURATE_68020_PIPELINE + if (pc2 & 2) { + pipeline_020(regs.prefetch020[0], pc); + pipeline_020(regs.prefetch020[1] >> 16, pc); + } else { + pipeline_020(regs.prefetch020[0] >> 16, pc); + pipeline_020(regs.prefetch020[0], pc); + } +#endif + + if (currprefs.cpu_cycle_exact) + regs.irc = get_word_ce030_prefetch (0); + else + regs.irc = get_word_030_prefetch(0); } void fill_prefetch_020 (void) -- 2.47.3