From: Toni Wilen Date: Fri, 17 Jul 2015 17:38:50 +0000 (+0300) Subject: 68020/30 prefetch pipeline update. X-Git-Tag: 3200~131 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=e90cce11c4453430bcdeae4c6e8d556c2da4e0c0;p=francis%2Fwinuae.git 68020/30 prefetch pipeline update. --- diff --git a/gencpu.cpp b/gencpu.cpp index e7b7b320..d1d2d909 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -253,6 +253,15 @@ static void get_prefetch_020_0 (void) return; printf ("\tregs.irc = %s (0);\n", prefetch_word); } +static void get_prefetch_020_continue(void) +{ + if (!isprefetch020()) + return; + if (using_ce020) + printf("\tcontinue_ce020_prefetch();\n"); + else + printf ("\tcontinue_020_prefetch();\n"); +} static void returntail (bool iswrite) { @@ -4100,7 +4109,7 @@ static void gen_opcode (unsigned int opcode) need_endlabel = 1; sync_m68k_pc (); addcycles000 (2); - get_prefetch_020_0 (); + get_prefetch_020_continue (); if (curi->size == sz_byte) { irc2ir (); add_head_cycs (4); @@ -4113,8 +4122,7 @@ static void gen_opcode (unsigned int opcode) fill_prefetch_full_000 (); } insn_n_cycles = curi->size == sz_byte ? 8 : 12; - if (curi->cc == 0) - branch_inst = 1; + branch_inst = 1; bccl_not68020: break; case i_LEA: @@ -4187,10 +4195,11 @@ bccl_not68020: pop_ins_cnt(); setpc ("oldpc + %d", m68k_pc_offset); clear_m68k_offset(); - get_prefetch_020_0 (); + get_prefetch_020_continue (); fill_prefetch_full_000 (); insn_n_cycles = 12; need_endlabel = 1; + branch_inst = 1; break; case i_Scc: // confirmed @@ -5517,7 +5526,7 @@ static char *outopcode (int opcode) struct cputbl_tmp { uae_s16 length; - uae_u8 disp020[2]; + uae_s8 disp020[2]; uae_u8 branch; }; static struct cputbl_tmp cputbltmp[65536]; @@ -5661,8 +5670,14 @@ static void generate_one_opcode (int rp, const char *extra) if ((opcode & 0xf000) == 0xf000) m68k_pc_total = -1; cputbltmp[opcode].length = m68k_pc_total; - cputbltmp[opcode].disp020[0] = genamode8r_offset[0]; - cputbltmp[opcode].disp020[1] = genamode8r_offset[1]; + + cputbltmp[opcode].disp020[0] = 0; + if (genamode8r_offset[0] > 0) + cputbltmp[opcode].disp020[0] = m68k_pc_total - genamode8r_offset[0] + 2; + cputbltmp[opcode].disp020[1] = 0; + if (genamode8r_offset[1] > 0) + cputbltmp[opcode].disp020[1] = m68k_pc_total - genamode8r_offset[1] + 2; + cputbltmp[opcode].branch = branch_inst; if (generate_stbl) { diff --git a/include/cpu_prefetch.h b/include/cpu_prefetch.h index 12e60fe7..035daca0 100644 --- a/include/cpu_prefetch.h +++ b/include/cpu_prefetch.h @@ -2,6 +2,7 @@ #ifdef CPUEMU_20 extern uae_u32 get_word_020_prefetch (int); +extern void continue_020_prefetch(void); STATIC_INLINE uae_u32 next_iword_020_prefetch (void) { @@ -108,6 +109,7 @@ STATIC_INLINE void put_byte_ce020 (uaecptr addr, uae_u32 v) mem_access_delay_byte_write_ce020 (addr, v); } +extern void continue_ce020_prefetch(void); extern uae_u32 get_word_ce020_prefetch(int); STATIC_INLINE uae_u32 get_long_ce020_prefetch (int o) diff --git a/include/newcpu.h b/include/newcpu.h index 14a96a53..b43e9167 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -60,7 +60,7 @@ struct cputbl { cpuop_func *handler; uae_u16 opcode; uae_s8 length; - uae_u8 disp020[2]; + uae_s8 disp020[2]; uae_u8 branch; }; @@ -207,7 +207,7 @@ struct regstruct uae_u32 cacheholdingdata020; uae_u32 cacheholdingaddr020; int pipeline_pos; - bool pipeline_r8[2]; + int pipeline_r8[2]; int pipeline_stop; int ce020memcycles; int ce020extracycles; diff --git a/newcpu.cpp b/newcpu.cpp index 44ba56e1..ab0e6b72 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -91,7 +91,7 @@ cpuop_func *cpufunctbl[65536]; struct cputbl_data { uae_s16 length; - uae_u8 disp020[2]; + uae_s8 disp020[2]; uae_u8 branch; }; static struct cputbl_data cpudatatbl[65536]; @@ -6609,6 +6609,8 @@ static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr)) struct cache020 *c; addr &= ~3; + if (regs.cacheholdingaddr020 == addr) + return; index = (addr >> 2) & (CACHELINES020 - 1); tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1)); c = &caches020[index]; @@ -6641,54 +6643,67 @@ static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr)) } #if MORE_ACCURATE_68020_PIPELINE +#define PIPELINE_DEBUG 0 +#if PIPELINE_DEBUG +static uae_u16 pipeline_opcode; +#endif static void pipeline_020(uae_u16 w, uaecptr pc) { - if (regs.pipeline_pos < 0) - return; - if (regs.pipeline_pos > 2) { - regs.pipeline_pos -= 2; + if (regs.pipeline_pos < 0) return; - } - if (regs.pipeline_pos == 2) { - if (regs.pipeline_r8[0]) { + if (regs.pipeline_pos > 0) { + // handle annoying 68020+ addressing modes + if (regs.pipeline_pos == regs.pipeline_r8[0]) { regs.pipeline_r8[0] = 0; - // disp 020+ word if (w & 0x100) { + int extra = 0; if ((w & 0x30) == 0x20) - regs.pipeline_pos += 2; + extra += 2; if ((w & 0x30) == 0x30) - regs.pipeline_pos += 4; + extra += 4; if ((w & 0x03) == 0x02) - regs.pipeline_pos += 2; + extra += 2; if ((w & 0x03) == 0x03) - regs.pipeline_pos += 4; + extra += 4; + regs.pipeline_pos += extra; } return; } - if (regs.pipeline_r8[1]) { + if (regs.pipeline_pos == regs.pipeline_r8[1]) { regs.pipeline_r8[1] = 0; - // disp 020+ word if (w & 0x100) { + int extra = 0; if ((w & 0x30) == 0x20) - regs.pipeline_pos += 2; + extra += 2; if ((w & 0x30) == 0x30) - regs.pipeline_pos += 4; + extra += 4; if ((w & 0x03) == 0x02) - regs.pipeline_pos += 2; + extra += 2; if ((w & 0x03) == 0x03) - regs.pipeline_pos += 4; + extra += 4; + regs.pipeline_pos += extra; } return; } } + if (regs.pipeline_pos > 2) { + regs.pipeline_pos -= 2; + // If stop set, prefetches stop 1 word early. + if (regs.pipeline_stop > 0 && regs.pipeline_pos == 2) + regs.pipeline_stop = -1; + return; + } if (regs.pipeline_stop) { regs.pipeline_stop = -1; return; } - regs.pipeline_r8[0] = cpudatatbl[w].disp020[0] != 0; - regs.pipeline_r8[1] = cpudatatbl[w].disp020[1] != 0; +#if PIPELINE_DEBUG + pipeline_opcode = w; +#endif + regs.pipeline_r8[0] = cpudatatbl[w].disp020[0]; + regs.pipeline_r8[1] = cpudatatbl[w].disp020[1]; regs.pipeline_pos = cpudatatbl[w].length; -#if 0 +#if PIPELINE_DEBUG if (!regs.pipeline_pos) { write_log(_T("Opcode %04x has no size PC=%08x!\n"), w, pc); } @@ -6697,13 +6712,25 @@ static void pipeline_020(uae_u16 w, uaecptr pc) if (regs.pipeline_pos > 0 && branch) { // Short branches (Bcc.s) still do one more prefetch. // RTS and other unconditional single opcode instruction stop immediately. - regs.pipeline_pos -= 1 * 2; - if (branch == 2) - regs.pipeline_stop = -1; // immediate stop - else + if (branch == 2) { + // Immediate stop + regs.pipeline_stop = -1; + } else { + // Stop 1 word early than normally regs.pipeline_stop = 1; + } } } + +// Not exactly right, requires logic analyzer checks. +void continue_ce020_prefetch(void) +{ + fill_prefetch_020(); +} +void continue_020_prefetch(void) +{ + fill_prefetch_020(); +} #endif uae_u32 get_word_ce020_prefetch (int o) @@ -7022,6 +7049,8 @@ static void fill_icache030 (uae_u32 addr) struct cache030 *c; addr &= ~3; + if (regs.cacheholdingaddr020 == addr) + return; c = getcache030 (icaches030, addr, &tag, &lws); if (c->valid[lws] && c->tag == tag) { // cache hit @@ -7683,6 +7712,7 @@ void fill_prefetch_020 (void) uae_u32 (*fetch)(uaecptr) = currprefs.cpu_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi; regs.pipeline_pos = 0; regs.pipeline_stop = 0; + regs.pipeline_r8[0] = regs.pipeline_r8[1] = -1; fill_icache020 (pc, fetch); if (currprefs.cpu_cycle_exact)