]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
68020/30 prefetch pipeline update.
authorToni Wilen <twilen@winuae.net>
Fri, 17 Jul 2015 17:38:50 +0000 (20:38 +0300)
committerToni Wilen <twilen@winuae.net>
Fri, 17 Jul 2015 17:38:50 +0000 (20:38 +0300)
gencpu.cpp
include/cpu_prefetch.h
include/newcpu.h
newcpu.cpp

index e7b7b32036ab51f4e29c4b86707cff8349a19a83..d1d2d9091e974fdbb991f04c765f1a18157356a9 100644 (file)
@@ -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) {
index 12e60fe703887421d759e456b35bad3c4414d387..035daca0ffe0113cd476781957d34bca4aaafbda 100644 (file)
@@ -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)
index 14a96a538926b4efb209ef57420f2987c8e21727..b43e91678dee2296fc2ef3ef9fd815d85b377c35 100644 (file)
@@ -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;
index 44ba56e1707c83843b5afc56a9fda57cb5efd1f9..ab0e6b72a9800445b5f66daee30cf835732afbbe 100644 (file)
@@ -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)