]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
More accurate 68020/030 pipeline emulation.
authorToni Wilen <twilen@winuae.net>
Mon, 13 Jul 2015 16:09:21 +0000 (19:09 +0300)
committerToni Wilen <twilen@winuae.net>
Mon, 13 Jul 2015 16:09:21 +0000 (19:09 +0300)
Totally unusable threaded CPU emulation.

14 files changed:
build68k.cpp
cfgfile.cpp
cia.cpp
custom.cpp
gencpu.cpp
include/cpu_prefetch.h
include/memory.h
include/newcpu.h
include/options.h
include/uae.h
main.cpp
memory.cpp
newcpu.cpp
od-win32/win32.cpp

index 5a9316ddbd44f254afcfa55814a3ba0b7bba8410..37a5c5ec6938c2cca7d9642532fbf9093f909067 100644 (file)
@@ -320,7 +320,7 @@ int main(int argc, char **argv)
                for(i = 0; i < 5; i++) {
                        printf("{%d,%d}%s", flaguse[i], flagset[i], i == 4 ? "" : ",");
                }
-               printf("},%2d,_T(\"%s\"),%2d,%2d,%2d,%2d}", sduse, opstrp, head, tail, clocks, fetchmode);
+               printf("},0x%02x,_T(\"%s\"),%2d,%2d,%2d,%2d}", sduse, opstrp, head, tail, clocks, fetchmode);
     }
     printf("};\nint n_defs68k = %d;\n", no_insns);
     return 0;
index 9dfa373f88a0dbbe7479281213589cbd0a4a1b6b..8a68853443a4b14c6f604c2a5f96e7984b1ff6b6 100644 (file)
@@ -1702,6 +1702,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        cfgfile_write_bool (f, _T("cpu_24bit_addressing"), p->address_space_24);
        /* do not reorder end */
        cfgfile_dwrite_bool(f, _T("cpu_reset_pause"), p->reset_delay);
+       cfgfile_dwrite_bool(f, _T("cpu_threaded"), p->cpu_thread);
        if (p->ppc_mode)
                cfgfile_write_str(f, _T("ppc_implementation"), ppc_implementations[p->ppc_implementation]);
 
@@ -4160,7 +4161,8 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
                || cfgfile_yesno (option, value, _T("ntsc"), &p->ntscmode)
                || cfgfile_yesno (option, value, _T("sana2"), &p->sana2)
                || cfgfile_yesno (option, value, _T("genlock"), &p->genlock)
-               || cfgfile_yesno (option, value, _T("cpu_compatible"), &p->cpu_compatible)
+               || cfgfile_yesno(option, value, _T("cpu_compatible"), &p->cpu_compatible)
+               || cfgfile_yesno(option, value, _T("cpu_threaded"), &p->cpu_thread)
                || cfgfile_yesno(option, value, _T("cpu_24bit_addressing"), &p->address_space_24)
                || cfgfile_yesno(option, value, _T("cpu_reset_pause"), &p->reset_delay)
                || cfgfile_yesno(option, value, _T("parallel_on_demand"), &p->parallel_demand)
@@ -6057,6 +6059,8 @@ void default_prefs (struct uae_prefs *p, int type)
        p->prtname[0] = 0;
        p->sername[0] = 0;
 
+       p->cpu_thread = false;
+
        p->fpu_model = 0;
        p->cpu_model = 68000;
        p->m68k_speed_throttle = 0;
diff --git a/cia.cpp b/cia.cpp
index 57ebf81f1f962cf5aee0cb4fa4b96e800fa25f12..91eeb3f27cd195483f47d667e45c1560f25bbf3f 100644 (file)
--- a/cia.cpp
+++ b/cia.cpp
@@ -1749,7 +1749,7 @@ STATIC_INLINE bool isgayle (void)
 
 static void cia_wait_pre (int cianummask)
 {
-       if (currprefs.cachesize)
+       if (currprefs.cachesize || currprefs.cpu_thread)
                return;
 #ifdef WITH_PPC
        if (ppc_state)
@@ -1788,6 +1788,8 @@ static void cia_wait_post (int cianummask, uae_u32 value)
        if (ppc_state)
                return;
 #endif
+       if (currprefs.cpu_thread)
+               return;
        if (currprefs.cachesize) {
                do_cycles (8 * CYCLE_UNIT /2);
        } else {
index 5de71af69fd876e48399300f3d1368c091a5f3dd..8d0e12c49ae438f4c7b06ab64dbe7387156e4444 100644 (file)
@@ -7982,7 +7982,7 @@ static void hsync_handler_post (bool onvsync)
                port_get_custom (1, out);
        }
 #endif
-       if (currprefs.m68k_speed < 0 && !currprefs.cpu_cycle_exact) {
+       if (!currprefs.cpu_thread && currprefs.m68k_speed < 0 && !currprefs.cpu_cycle_exact) {
                static int sleeps_remaining;
                if (is_last_line ()) {
                        sleeps_remaining = (165 - currprefs.cpu_idle) / 6;
@@ -8039,7 +8039,7 @@ static void hsync_handler_post (bool onvsync)
                                }
                        }
                }
-       } else {
+       } else if (!currprefs.cpu_thread) {
                if (vpos + 1 < maxvpos + lof_store && (vpos == maxvpos_display * 1 / 3 || vpos == maxvpos_display * 2 / 3)) {
                        vsyncmintime += vsynctimeperline;
                        if (!vsync_isdone () && !currprefs.turbo_emulation) {
index d265be2dabb5a4a266635bc0fafd286d16b5b213..f3210324fca580c59155e94370e59405406af6fe 100644 (file)
@@ -76,7 +76,7 @@ static unsigned long *counts;
 static int generate_stbl;
 static int mmufixupcnt;
 static int mmufixupstate;
-static int mmudisp020cnt;
+static int disp020cnt;
 static bool candormw;
 static bool genastore_done;
 static char rmw_varname[100];
@@ -96,7 +96,6 @@ static const char *dstblrmw, *dstwlrmw, *dstllrmw;
 static const char *srcbrmw, *srcwrmw, *srclrmw;
 static const char *dstbrmw, *dstwrmw, *dstlrmw;
 static const char *prefetch_long, *prefetch_word;
-static const char *prefetch_long_buffer, *prefetch_word_buffer;
 static const char *srcli, *srcwi, *srcbi, *nextl, *nextw;
 static const char *srcld, *dstld;
 static const char *srcwd, *dstwd;
@@ -160,9 +159,12 @@ static void read_counts (void)
 static char endlabelstr[80];
 static int endlabelno = 0;
 static int need_endlabel;
+static int genamode_cnt;
 
 static int n_braces, limit_braces;
 static int m68k_pc_offset, m68k_pc_offset_old;
+static int m68k_pc_total;
+static int branch_inst;
 static int insn_n_cycles, insn_n_cycles020;
 static int ir2irc;
 
@@ -469,7 +471,7 @@ static void gen_nextilong2 (const char *type, const char *name, int flags, int m
        add_mmu040_movem (movem);
        if (using_ce020) {
                if (flags & GF_NOREFILL)
-                       printf("\t%s = %s (%d);\n", name, prefetch_long_buffer, r);
+                       printf("\t%s = %s (%d);\n", name, prefetch_long, r);
                else
                        printf("\t%s = %s (%d);\n", name, prefetch_long, r);
                count_read += 2;
@@ -517,7 +519,7 @@ static const char *gen_nextiword (int flags)
 
        if (using_ce020) {
                if (flags & GF_NOREFILL)
-                       sprintf(buffer, "%s (%d)", prefetch_word_buffer, r);
+                       sprintf(buffer, "%s (%d)", prefetch_word, r);
                else
                        sprintf(buffer, "%s (%d)", prefetch_word, r);
                count_read++;
@@ -553,7 +555,7 @@ static const char *gen_nextibyte (int flags)
 
        if (using_ce020 || using_prefetch_020) {
                if (flags & GF_NOREFILL)
-                       sprintf(buffer, "(uae_u8)%s (%d)", prefetch_word_buffer, r);
+                       sprintf(buffer, "(uae_u8)%s (%d)", prefetch_word, r);
                else
                        sprintf(buffer, "(uae_u8)%s (%d)", prefetch_word, r);
                count_read++;
@@ -778,6 +780,13 @@ static void sync_m68k_pc (void)
        if (m68k_pc_offset == 0)
                return;
        incpc ("%d", m68k_pc_offset);
+       m68k_pc_total += m68k_pc_offset;
+       m68k_pc_offset = 0;
+}
+
+static void clear_m68k_offset(void)
+{
+       m68k_pc_total += m68k_pc_offset;
        m68k_pc_offset = 0;
 }
 
@@ -1276,6 +1285,8 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                rmw = true;
        }
 
+       genamode_cnt++;
+
        start_brace ();
 
        switch (mode) {
@@ -1419,7 +1430,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        start_brace ();
                        /* This would ordinarily be done in gen_nextiword, which we bypass.  */
                        insn_n_cycles += 4;
-                       printf ("\t%sa = %s (m68k_areg (regs, %s), %d);\n", name, disp020, reg, mmudisp020cnt++);
+                       printf ("\t%sa = %s (m68k_areg (regs, %s), %d);\n", name, disp020, reg, disp020cnt++);
                } else {
                        if (!(flags & GF_AD8R)) {
                                addcycles000 (2);
@@ -1455,7 +1466,7 @@ static void genamode2x (amodes mode, const char *reg, wordsizes size, const char
                        /* This would ordinarily be done in gen_nextiword, which we bypass.  */
                        insn_n_cycles += 4;
                        printf ("\ttmppc = %s;\n", getpc);
-                       printf ("\t%sa = %s (tmppc, %d);\n", name, disp020, mmudisp020cnt++);
+                       printf ("\t%sa = %s (tmppc, %d);\n", name, disp020, disp020cnt++);
                } else {
                        printf ("\ttmppc = %s + %d;\n", getpc, m68k_pc_offset);
                        if (!(flags & GF_PC8R)) {
@@ -2673,10 +2684,14 @@ static void resetvars (void)
 {
        insn_n_cycles = using_prefetch ? 0 : 4;
        insn_n_cycles020 = 0;
+       genamode_cnt = 0;
+       m68k_pc_total = 0;
+       branch_inst = 0;
+
        ir2irc = 0;
        mmufixupcnt = 0;
        mmufixupstate = 0;
-       mmudisp020cnt = 0;
+       disp020cnt = 0;
        candormw = false;
        genastore_done = false;
        rmw_varname[0] = 0;
@@ -2689,8 +2704,6 @@ static void resetvars (void)
        got_ea_ce020 = false;
        
        prefetch_long = NULL;
-       prefetch_word_buffer = NULL;
-       prefetch_long_buffer = NULL;
        srcli = NULL;
        srcbi = NULL;
        disp000 = "get_disp_ea_000";
@@ -2747,8 +2760,6 @@ static void resetvars (void)
                        disp020 = "x_get_disp_ea_ce020";
                        prefetch_word = "get_word_ce020_prefetch";
                        prefetch_long = "get_long_ce020_prefetch";
-                       prefetch_word_buffer = "get_word_ce020_prefetch_buffer";
-                       prefetch_long_buffer = "get_long_ce020_prefetch_buffer";
                        srcli = "x_get_ilong";
                        srcwi = "x_get_iword";
                        srcbi = "x_get_ibyte";
@@ -2766,8 +2777,6 @@ static void resetvars (void)
                        disp020 = "x_get_disp_ea_ce030";
                        prefetch_long = "get_long_ce030_prefetch";
                        prefetch_word = "get_word_ce030_prefetch";
-                       prefetch_word_buffer = "get_word_ce030_prefetch_buffer";
-                       prefetch_long_buffer = "get_long_ce030_prefetch_buffer";
                        srcli = "x_get_ilong";
                        srcwi = "x_get_iword";
                        srcbi = "x_get_ibyte";
@@ -2801,8 +2810,6 @@ static void resetvars (void)
                        disp020 = "x_get_disp_ea_020";
                        prefetch_word = "get_word_020_prefetch";
                        prefetch_long = "get_long_020_prefetch";
-                       prefetch_word_buffer = "get_word_020_prefetch_buffer";
-                       prefetch_long_buffer = "get_long_020_prefetch_buffer";
                        srcli = "x_get_ilong";
                        srcwi = "x_get_iword";
                        srcbi = "x_get_ibyte";
@@ -2985,10 +2992,6 @@ static void resetvars (void)
                dstwlrmw = dstw;
                dstllrmw = dstl;
        }
-       if (!prefetch_word_buffer)
-               prefetch_word_buffer = prefetch_word;
-       if (!prefetch_long_buffer)
-               prefetch_long_buffer = prefetch_long;
 
 }
 
@@ -3001,6 +3004,7 @@ static void gen_opcode (unsigned int opcode)
        start_brace ();
 
        m68k_pc_offset = 2;
+
        switch (curi->plev) {
        case 0: /* not privileged */
                break;
@@ -3665,7 +3669,8 @@ static void gen_opcode (unsigned int opcode)
                sync_m68k_pc ();
                printf ("\tException (src + 32);\n");
                did_prefetch = 1;
-               m68k_pc_offset = 0;
+               branch_inst = 1;
+               clear_m68k_offset();
                break;
        case i_MVR2USP:
                genamode (curi, curi->smode, "srcreg", curi->size, "src", 1, 0, 0);
@@ -3684,7 +3689,7 @@ static void gen_opcode (unsigned int opcode)
                addcycles000 (128);
                if (using_prefetch) {
                        printf ("\t%s (2);\n", prefetch_word);
-                       m68k_pc_offset = 0;
+                       clear_m68k_offset();
                }
                break;
        case i_NOP:
@@ -3813,9 +3818,10 @@ static void gen_opcode (unsigned int opcode)
                    need_endlabel = 1;
                }
                /* PC is set and prefetch filled. */
-               m68k_pc_offset = 0;
+               clear_m68k_offset();
                tail_ce020_done = true;
                fill_prefetch_full ();
+               branch_inst = 1;
                break;
        case i_RTD:
                addop_ce020 (curi, 0);
@@ -3834,10 +3840,11 @@ static void gen_opcode (unsigned int opcode)
                printf ("\t}\n");
                setpc ("pc");
                /* PC is set and prefetch filled. */
-               m68k_pc_offset = 0;
+               clear_m68k_offset();
                tail_ce020_done = true;
                fill_prefetch_full ();
            need_endlabel = 1;
+               branch_inst = 1;
                break;
        case i_LINK:
                // ce confirmed
@@ -3902,9 +3909,10 @@ static void gen_opcode (unsigned int opcode)
                printf ("\t\tgoto %s;\n", endlabelstr);
                printf ("\t}\n");
                count_read += 2;
-               m68k_pc_offset = 0;
+               clear_m68k_offset();
                fill_prefetch_full ();
            need_endlabel = 1;
+               branch_inst = 1;
                break;
        case i_TRAPV:
                sync_m68k_pc ();
@@ -3930,7 +3938,7 @@ static void gen_opcode (unsigned int opcode)
                printf ("\t\texception3i (0x%04X, faultpc);\n", opcode);
                printf ("\t\tgoto %s;\n", endlabelstr);
                printf ("\t}\n");
-               m68k_pc_offset = 0;
+               clear_m68k_offset();
                fill_prefetch_full ();
            need_endlabel = 1;
                tail_ce020_done = true;
@@ -3952,7 +3960,7 @@ static void gen_opcode (unsigned int opcode)
                        printf ("\t%s (m68k_areg (regs, 7) - 4, oldpc);\n", dstl);
                        printf ("\tm68k_areg (regs, 7) -= 4;\n");
                        setpc ("srca");
-                       m68k_pc_offset = 0;
+                       clear_m68k_offset();
                } else {
                        if (curi->smode == Ad16 || curi->smode == absw || curi->smode == PC16)
                                addcycles000 (2);
@@ -3962,7 +3970,7 @@ static void gen_opcode (unsigned int opcode)
                                        printf ("\toldpc += 2;\n");
                        }
                        setpc ("srca");
-                       m68k_pc_offset = 0;
+                       clear_m68k_offset();
                        fill_prefetch_1 (0);
                        printf ("\tm68k_areg (regs, 7) -= 4;\n");
                        if (using_ce || using_prefetch) {
@@ -3975,6 +3983,7 @@ static void gen_opcode (unsigned int opcode)
                count_write += 2;
                fill_prefetch_full_020 ();
                fill_prefetch_next ();
+               branch_inst = 1;
                break;
        case i_JMP:
                no_prefetch_ce020 = true;
@@ -3991,8 +4000,9 @@ static void gen_opcode (unsigned int opcode)
                if (curi->smode == Ad8r || curi->smode == PC8r)
                        addcycles000 (6);
                setpc ("srca");
-               m68k_pc_offset = 0;
+               clear_m68k_offset();
                fill_prefetch_full ();
+               branch_inst = 1;
                break;
        case i_BSR:
                // .b/.w = idle cycle, store high, store low, 2xprefetch
@@ -4033,8 +4043,9 @@ static void gen_opcode (unsigned int opcode)
                        printf ("\tm68k_do_bsr (%s + %d, s);\n", getpc, m68k_pc_offset);
                }
                count_write += 2;
-               m68k_pc_offset = 0;
+               clear_m68k_offset();
                fill_prefetch_full ();
+               branch_inst = 1;
                break;
        case i_Bcc:
                tail_ce020_done = true;
@@ -4098,6 +4109,8 @@ 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;
 bccl_not68020:
                break;
        case i_LEA:
@@ -4169,7 +4182,7 @@ bccl_not68020:
                printf ("\t}\n");
                pop_ins_cnt();
                setpc ("oldpc + %d", m68k_pc_offset);
-               m68k_pc_offset = 0;
+               clear_m68k_offset();
                get_prefetch_020_0 ();
                fill_prefetch_full_000 ();
                insn_n_cycles = 12;
@@ -5497,6 +5510,14 @@ static char *outopcode (int opcode)
        return out;
 }
 
+struct cputbl_tmp
+{
+       uae_s16 length;
+       uae_u16 disp020;
+       uae_u16 branch;
+};
+static struct cputbl_tmp cputbltmp[65536];
+
 static void generate_one_opcode (int rp, const char *extra)
 {
        int idx;
@@ -5519,10 +5540,11 @@ static void generate_one_opcode (int rp, const char *extra)
        if (opcode_next_clev[rp] != cpu_level) {
                char *name = ua (lookuptab[idx].name);
                if (generate_stbl)
-                       fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d%s), %d }, /* %s */\n",
+                       fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d%s), 0x%04x, %d, %d, %d }, /* %s */\n",
                                (using_ce || using_ce020) ? "(cpuop_func*)" : "",
                                opcode, opcode_last_postfix[rp],
-                               extra, opcode, name);
+                               extra, opcode,
+                               cputbltmp[opcode].length, cputbltmp[opcode].disp020, cputbltmp[opcode].branch, name);
                xfree (name);
                return;
        }
@@ -5632,13 +5654,20 @@ static void generate_one_opcode (int rp, const char *extra)
        opcode_next_clev[rp] = next_cpu_level;
        opcode_last_postfix[rp] = postfix;
 
+       if ((opcode & 0xf000) == 0xf000)
+               m68k_pc_total = -1;
+       cputbltmp[opcode].length = m68k_pc_total;
+       cputbltmp[opcode].disp020 = disp020cnt;
+       cputbltmp[opcode].branch = branch_inst;
+
        if (generate_stbl) {
                char *name = ua (lookuptab[idx].name);
                if (i68000)
                        fprintf (stblfile, "#ifndef CPUEMU_68000_ONLY\n");
-               fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d%s), %d }, /* %s */\n",
+               fprintf (stblfile, "{ %sCPUFUNC(op_%04x_%d%s), 0x%04x, %d, %d, %d }, /* %s */\n",
                        (using_ce || using_ce020) ? "(cpuop_func*)" : "",
-                       opcode, postfix, extra, opcode, name);
+                       opcode, postfix, extra, opcode,
+                       cputbltmp[opcode].length, cputbltmp[opcode].disp020, cputbltmp[opcode].branch, name);
                if (i68000)
                        fprintf (stblfile, "#endif\n");
                xfree (name);
index 6bfdfc7cb415193ac27ead2e4d316215983ab936..12e60fe703887421d759e456b35bad3c4414d387 100644 (file)
@@ -109,7 +109,6 @@ STATIC_INLINE void put_byte_ce020 (uaecptr addr, uae_u32 v)
 }
 
 extern uae_u32 get_word_ce020_prefetch(int);
-extern uae_u32 get_word_ce020_prefetch_buffer(int);
 
 STATIC_INLINE uae_u32 get_long_ce020_prefetch (int o)
 {
@@ -122,17 +121,6 @@ STATIC_INLINE uae_u32 get_long_ce020_prefetch (int o)
        return v;
 }
 
-STATIC_INLINE uae_u32 get_long_ce020_prefetch_buffer(int o)
-{
-       uae_u32 v;
-       uae_u16 tmp;
-       v = get_word_ce020_prefetch_buffer(o) << 16;
-       tmp = regs.db;
-       v |= get_word_ce020_prefetch_buffer(o + 2);
-       regs.db = tmp;
-       return v;
-}
-
 STATIC_INLINE uae_u32 next_iword_020ce (void)
 {
        uae_u32 r = get_word_ce020_prefetch (0);
@@ -164,7 +152,6 @@ STATIC_INLINE void m68k_do_rts_ce020 (void)
 #ifdef CPUEMU_22
 
 extern uae_u32 get_word_ce030_prefetch(int);
-extern uae_u32 get_word_ce030_prefetch_buffer(int);
 
 STATIC_INLINE void put_long_ce030 (uaecptr addr, uae_u32 v)
 {
@@ -199,14 +186,6 @@ STATIC_INLINE uae_u32 get_long_ce030_prefetch (int o)
        return v;
 }
 
-STATIC_INLINE uae_u32 get_long_ce030_prefetch_buffer(int o)
-{
-       uae_u32 v;
-       v = get_word_ce030_prefetch_buffer(o) << 16;
-       v |= get_word_ce030_prefetch_buffer(o + 2);
-       return v;
-}
-
 STATIC_INLINE uae_u32 next_iword_030ce (void)
 {
        uae_u32 r = get_word_ce030_prefetch (0);
index 24e5e8fd29d8f3c5e52e1e7b791141b22c672878..0e0ebd432313f4d00e33c9ada23e41fa8e6eb808 100644 (file)
@@ -399,9 +399,9 @@ extern addrbank *get_mem_bank_real(uaecptr);
 #define put_mem_bank(addr, b, realstart) do { \
        (mem_banks[bankindex(addr)] = (b)); \
        if ((b)->baseaddr) \
-       baseaddr[bankindex(addr)] = (b)->baseaddr - (realstart); \
+               baseaddr[bankindex(addr)] = (b)->baseaddr - (realstart); \
        else \
-       baseaddr[bankindex(addr)] = (uae_u8*)(((uae_u8*)b)+1); \
+               baseaddr[bankindex(addr)] = (uae_u8*)(((uae_u8*)b)+1); \
 } while (0)
 #else
 #define put_mem_bank(addr, b, realstart) \
index 1f625cabed3dd3ac9dfff8c9aaf8c2f5e6cc6906..08694be4883397b1890530af07418c268d9e7103 100644 (file)
@@ -59,6 +59,9 @@ typedef void REGPARAM3 cpuop_func_ce (uae_u32) REGPARAM;
 struct cputbl {
        cpuop_func *handler;
        uae_u16 opcode;
+       uae_s16 length;
+       uae_u16 disp020;
+       uae_u16 branch;
 };
 
 #ifdef JIT
@@ -147,7 +150,7 @@ struct regstruct
        uae_u32 instruction_pc;
 
        uae_u16 irc, ir, db;
-       uae_u32 spcflags;
+       volatile uae_u32 spcflags;
        uae_u32 last_prefetch;
        uae_u32 chipset_latch_rw;
        uae_u32 chipset_latch_read;
@@ -203,6 +206,9 @@ struct regstruct
        uae_u32 prefetch020addr;
        uae_u32 cacheholdingdata020;
        uae_u32 cacheholdingaddr020;
+       int pipeline_pos;
+       bool pipeline_next;
+       int pipeline_stop;
        int ce020memcycles;
        int ce020extracycles;
        bool ce020memcycle_data;
@@ -255,13 +261,29 @@ extern int cpucycleunit;
 extern int m68k_pc_indirect;
 STATIC_INLINE void set_special (uae_u32 x)
 {
+#ifdef WITH_THREADED_CPU
+#ifdef _WIN32
+       _InterlockedOr((volatile long*)&regs.spcflags, x);
+#else
+       regs.spcflags |= x;
+#endif
+#else
        regs.spcflags |= x;
+#endif
        cycles_do_special ();
 }
 
 STATIC_INLINE void unset_special (uae_u32 x)
 {
+#ifdef WITH_THREADED_CPU
+#ifdef _WIN32
+       _InterlockedAnd((volatile long*)&regs.spcflags, ~x);
+#else
        regs.spcflags &= ~x;
+#endif
+#else
+       regs.spcflags &= ~x;
+#endif
 }
 
 #define m68k_dreg(r,num) ((r).regs[(num)])
@@ -660,4 +682,5 @@ extern bool can_cpu_tracer (void);
 #define CPU_HALT_PCI_CONFLICT 8
 #define CPU_HALT_CPU_STUCK 9
 
-
+void cpu_semaphore_get(void);
+void cpu_semaphore_release(void);
index 96b57c603df5033ac61f60edafad88bf1f004361..29404e2d5237def19414618a17cf69523c6942fd 100644 (file)
@@ -559,6 +559,7 @@ struct uae_prefs {
        int ppc_mode;
        TCHAR ppc_model[32];
        bool cpu_compatible;
+       bool cpu_thread;
        bool int_no_unimplemented;
        bool fpu_no_unimplemented;
        bool address_space_24;
index 1c5d65e6c13b75752c24b153e22bf73d5c4ceb26..c0db69fc4de76cf100b0eeaf950d7e3960a4545e 100644 (file)
@@ -12,8 +12,8 @@ extern void leave_program (void);
 extern void real_main (int, TCHAR **);
 extern void usage (void);
 extern void sleep_millis (int ms);
-extern void sleep_millis_main (int ms);
-extern void sleep_millis_busy (int ms);
+extern void sleep_millis_main(int ms);
+extern void sleep_millis_amiga(int ms);
 extern int sleep_resolution;
 
 #define UAE_QUIT 1
index c2525e16b3f9551d4996ead0a346e67ce4bfeb33..54428ba4f56f50f85ddfb52656617eb0b0327473 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -241,6 +241,11 @@ void fixup_cpu (struct uae_prefs *p)
                break;
        }
 
+       if (p->cpu_thread && (p->cpu_compatible || p->ppc_mode || p->cpu_cycle_exact || p->cpu_model < 68020)) {
+               p->cpu_thread = false;
+               error_log(_T("Threaded CPU mode is not compatible with PPC emulation, More compatible or Cycle Exact modes. CPU type must be 68020 or higher."));
+       }
+
        // 1 = "automatic" PPC config
        if (p->ppc_mode == 1) {
                cpuboard_setboard(p,  BOARD_CYBERSTORM, BOARD_CYBERSTORM_SUB_PPC);
index 11d0e06490c8a970c4fe89d032689856f3949f3c..ab89b4631dec94305fadf92cc8b4fdcfa01e1b7e 100644 (file)
@@ -2675,11 +2675,105 @@ void map_banks_cond (addrbank *bank, int start, int size, int realsize)
        map_banks (bank, start, size, realsize);
 }
 
+#ifdef WITH_THREADED_CPU
+
+struct addrbank_thread {
+       addrbank *orig;
+       addrbank ab;
+};
+
+#define MAX_THREAD_BANKS 200
+static addrbank_thread *thread_banks[MAX_THREAD_BANKS];
+static addrbank *thread_mem_banks[MEMORY_BANKS];
+static int thread_banks_used;
+
+static void REGPARAM2 threadcpu_lput(uaecptr addr, uae_u32 l)
+{
+       cpu_semaphore_get();
+       thread_mem_banks[bankindex(addr)]->lput(addr, l);
+       cpu_semaphore_release();
+}
+
+static void REGPARAM2 threadcpu_wput(uaecptr addr, uae_u32 w)
+{
+       cpu_semaphore_get();
+       thread_mem_banks[bankindex(addr)]->wput(addr, w);
+       cpu_semaphore_release();
+}
+
+static void REGPARAM2 threadcpu_bput(uaecptr addr, uae_u32 b)
+{
+       cpu_semaphore_get();
+       thread_mem_banks[bankindex(addr)]->bput(addr, b);
+       cpu_semaphore_release();
+}
+static uae_u32 REGPARAM2 threadcpu_lget(uaecptr addr)
+{
+       cpu_semaphore_get();
+       uae_u32 v = thread_mem_banks[bankindex(addr)]->lget(addr);
+       cpu_semaphore_release();
+       return v;
+}
+static uae_u32 REGPARAM2 threadcpu_wget(uaecptr addr)
+{
+       cpu_semaphore_get();
+       uae_u32 v = thread_mem_banks[bankindex(addr)]->wget(addr);
+       cpu_semaphore_release();
+       return v;
+}
+uae_u32 REGPARAM2 threadcpu_bget(uaecptr addr)
+{
+       cpu_semaphore_get();
+       uae_u32 v = thread_mem_banks[bankindex(addr)]->bget(addr);
+       cpu_semaphore_release();
+       return v;
+}
+
+static addrbank *get_bank_cpu_thread(addrbank *bank)
+{
+       if (bank->flags & ABFLAG_THREADSAFE)
+               return bank;
+       if (bank == &dummy_bank)
+               return bank;
+
+       for (int i = 0; i < thread_banks_used; i++) {
+               if (thread_banks[i]->orig == bank) {
+                       return &thread_banks[i]->ab;
+               }
+       }
+       struct addrbank_thread *at = thread_banks[thread_banks_used];
+       if (!at)
+               at = xcalloc(addrbank_thread, 1);
+       thread_banks[thread_banks_used++] = at;
+       at->orig = bank;
+       memcpy(&at->ab, bank, sizeof addrbank);
+       addrbank *tb = &at->ab;
+       tb->lget = threadcpu_lget;
+       tb->wget = threadcpu_wget;
+       tb->bget = threadcpu_bget;
+       tb->lput = threadcpu_lput;
+       tb->wput = threadcpu_wput;
+       tb->bput = threadcpu_bput;
+       // wgeti/lgeti should always point to real RAM
+       return tb;
+}
+#endif
+
 static void map_banks2 (addrbank *bank, int start, int size, int realsize, int quick)
 {
        int bnr, old;
        unsigned long int hioffs = 0, endhioffs = 0x100;
        uae_u32 realstart = start;
+       addrbank *orig_bank = NULL;
+
+#ifdef WITH_THREADED_CPU
+       if (currprefs.cpu_thread) {
+               addrbank *b = bank;
+               bank = get_bank_cpu_thread(bank);
+               if (b != bank)
+                       orig_bank = b;
+       }
+#endif
 
        if (quick <= 0)
                old = debug_bankchange (-1);
@@ -2710,6 +2804,13 @@ static void map_banks2 (addrbank *bank, int start, int size, int realsize, int q
 #endif
                        }
                        put_mem_bank (bnr << 16, bank, realstart << 16);
+#ifdef WITH_THREADED_CPU
+                       if (currprefs.cpu_thread) {
+                               if (orig_bank)
+                                       put_mem_bank(bnr << 16, orig_bank, realstart << 16);
+                               thread_mem_banks[bnr] = orig_bank;
+                       }
+#endif
                        real_left--;
                }
                if (quick <= 0)
@@ -2734,6 +2835,13 @@ static void map_banks2 (addrbank *bank, int start, int size, int realsize, int q
 #endif
                        }
                        put_mem_bank ((bnr + hioffs) << 16, bank, realstart << 16);
+#ifdef WITH_THREADED_CPU
+                       if (currprefs.cpu_thread) {
+                               if (orig_bank)
+                                       put_mem_bank((bnr + hioffs) << 16, bank, realstart << 16);
+                               thread_mem_banks[bnr + hioffs] = orig_bank;
+                       }
+#endif
                        real_left--;
                }
        }
index 5ba4b113b48fb636052f6894199ce9459a09c2f6..1a6505a471edbe7656284a668c5f4b9d47bb9081 100644 (file)
@@ -11,6 +11,8 @@
 #define EXCEPTION3_DEBUGGER 0
 #define CPUTRACE_DEBUG 0
 
+#define MORE_ACCURATE_68020_PIPELINE 1
+
 #include "sysconfig.h"
 #include "sysdeps.h"
 
@@ -39,6 +41,7 @@
 #include "statusline.h"
 #include "uae/ppc.h"
 #include "cpuboard.h"
+#include "threaddep/thread.h"
 #ifdef JIT
 #include "jit/compemu.h"
 #include <signal.h>
@@ -85,6 +88,14 @@ int movem_next[256];
 
 cpuop_func *cpufunctbl[65536];
 
+struct cputbl_data
+{
+       uae_s16 length;
+       uae_u16 disp020;
+       uae_u16 branch;
+};
+static struct cputbl_data cpudatatbl[65536];
+
 struct mmufixup mmufixup[2];
 
 #define COUNT_INSTRS 0
@@ -1217,14 +1228,21 @@ static void build_cpufunctbl (void)
        for (i = 0; tbl[i].handler != NULL; i++) {
                opcode = tbl[i].opcode;
                cpufunctbl[opcode] = tbl[i].handler;
+               cpudatatbl[opcode].length = tbl[i].length;
+               cpudatatbl[opcode].disp020 = tbl[i].disp020;
+               cpudatatbl[opcode].branch = tbl[i].branch;
        }
 
        /* hack fpu to 68000/68010 mode */
        if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
                tbl = op_smalltbl_3_ff;
                for (i = 0; tbl[i].handler != NULL; i++) {
-                       if ((tbl[i].opcode & 0xfe00) == 0xf200)
+                       if ((tbl[i].opcode & 0xfe00) == 0xf200) {
                                cpufunctbl[tbl[i].opcode] = tbl[i].handler;
+                               cpudatatbl[tbl[i].opcode].length = tbl[i].length;
+                               cpudatatbl[tbl[i].opcode].disp020 = tbl[i].disp020;
+                               cpudatatbl[tbl[i].opcode].branch = tbl[i].branch;
+                       }
                }
        }
 
@@ -1264,6 +1282,7 @@ static void build_cpufunctbl (void)
                        if (f == op_illg_1)
                                abort ();
                        cpufunctbl[opcode] = f;
+                       memcpy(&cpudatatbl[opcode], &cpudatatbl[idx], sizeof cputbl_data);
                        opcnt++;
                }
        }
@@ -3314,6 +3333,9 @@ static void check_uae_int_request(void)
 
 void cpu_sleep_millis(int ms)
 {
+#ifdef WITH_THREADED_CPU
+       cpu_semaphore_release();
+#endif
 #ifdef WITH_PPC
        int state = ppc_state;
        if (state)
@@ -3324,6 +3346,9 @@ void cpu_sleep_millis(int ms)
        if (state)
                uae_ppc_spinlock_get();
 #endif
+#ifdef WITH_THREADED_CPU
+       cpu_semaphore_get();
+#endif
 }
 
 #define PPC_HALTLOOP_SCANLINES 25
@@ -3987,13 +4012,218 @@ static uae_u16 get_word_020_prefetchf (uae_u32 pc)
 }
 #endif
 
+#ifdef WITH_THREADED_CPU
+static volatile int cpu_thread_active;
+
+#define SPINLOCK_DEBUG 0
+static volatile int m68k_spinlock_cnt;
+static volatile long m68k_spinlock_waiting;
+#ifdef _WIN32
+#define CRITICAL_SECTION_SPIN_COUNT 5000
+static CRITICAL_SECTION m68k_cs1;
+static bool m68k_cs_initialized;
+static DWORD m68k_cs_owner;
+#else
+#include <glib.h>
+static GMutex mutex;
+#endif
+
+static int do_specialties_thread(void)
+{
+       if (regs.spcflags & SPCFLAG_MODE_CHANGE)
+               return 1;
+
+       if (regs.spcflags & SPCFLAG_CHECK) {
+               if (regs.halted) {
+                       if (haltloop())
+                               return 1;
+               }
+               if (m68k_reset_delay) {
+                       int vsynccnt = 60;
+                       int vsyncstate = -1;
+                       while (vsynccnt > 0) {
+                               int vp = vpos;
+                               while (vp == vpos) {
+                                       sleep_millis(1);
+                               }
+                               vsynccnt--;
+                       }
+               }
+               m68k_reset_delay = 0;
+               unset_special(SPCFLAG_CHECK);
+       }
+       
+#ifdef JIT
+       unset_special(SPCFLAG_END_COMPILE);   /* has done its job */
+#endif
+
+       if (regs.spcflags & SPCFLAG_DOTRACE)
+               Exception(9);
+
+       if (regs.spcflags & SPCFLAG_TRAP) {
+               unset_special(SPCFLAG_TRAP);
+               Exception(3);
+       }
+       bool first = true;
+       while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) {
+               if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
+                       int intr = intlev();
+                       unset_special(SPCFLAG_INT | SPCFLAG_DOINT);
+                       if (intr > 0 && intr > regs.intmask)
+                               do_interrupt(intr);
+               }
+
+               if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
+                       m68k_resumestopped();
+                       return 1;
+               }
+       }
+
+       if (regs.spcflags & SPCFLAG_TRACE)
+               do_trace();
+
+       if (regs.spcflags & SPCFLAG_INT) {
+               int intr = intlev();
+               unset_special(SPCFLAG_INT | SPCFLAG_DOINT);
+               if (intr > 0 && (intr > regs.intmask || intr == 7))
+                       do_interrupt(intr);
+       }
+
+       if (regs.spcflags & SPCFLAG_DOINT) {
+               unset_special(SPCFLAG_DOINT);
+               set_special(SPCFLAG_INT);
+       }
+
+       if (regs.spcflags & SPCFLAG_BRK) {
+               return 1;
+       }
+
+       return 0;
+}
+
+void cpu_semaphore_get(void)
+{
+       if (!currprefs.cpu_thread)
+               return;
+       DWORD tid = GetCurrentThreadId();
+
+       if (tid == m68k_cs_owner) {
+               m68k_spinlock_cnt++;
+               return;
+       }
+
+#ifdef _WIN32
+       _InterlockedIncrement(&m68k_spinlock_waiting);
+       EnterCriticalSection(&m68k_cs1);
+       _InterlockedDecrement(&m68k_spinlock_waiting);
+       m68k_cs_owner = tid;
+       m68k_spinlock_cnt++;
+#else
+       g_mutex_lock(&mutex); // FIXME
+#endif
+}
+void cpu_semaphore_release(void)
+{
+       if (!currprefs.cpu_thread)
+               return;
+#ifdef _WIN32
+       m68k_spinlock_cnt--;
+       if (m68k_spinlock_cnt == 0) {
+               m68k_cs_owner = 0;
+               LeaveCriticalSection(&m68k_cs1);
+       }
+#else
+       g_mutex_unlock(&mutex); // FIXME
+#endif
+}
+
+static void init_cpu_thread(void)
+{
+       if (!currprefs.cpu_thread)
+               return;
+#ifdef _WIN32
+       if (m68k_cs_initialized) {
+               DeleteCriticalSection(&m68k_cs1);
+       }
+       InitializeCriticalSectionAndSpinCount(&m68k_cs1, CRITICAL_SECTION_SPIN_COUNT);
+#endif
+}
+
+static void run_cpu_thread(void *(*f)(void *))
+{
+       cpu_thread_active = 0;
+#if SPINLOCK_DEBUG
+       m68k_spinlock_cnt = 0;
+#endif
+       m68k_cs_initialized = true;
+       if (uae_start_thread(_T("cpu"), f, NULL, NULL)) {
+               while (!cpu_thread_active) {
+                       sleep_millis(1);
+               }
+               while (!(regs.spcflags & SPCFLAG_MODE_CHANGE)) {
+
+                       cpu_semaphore_get();
+                       frame_time_t c = read_processor_time();
+                       while (cpu_thread_active) {
+                               int vsynctimeperline = vsynctimebase / (maxvpos_display + 1);
+
+                               int vp = vpos;
+                               while ((int)read_processor_time() - (int)c > -vsynctimebase / 10) {
+                                       if (vp != vpos) {
+                                               vp = vpos;
+                                               if (vpos + 1 == maxvpos + lof_store) {
+                                                       c = read_processor_time();
+                                               }
+                                               c += vsynctimeperline;
+                                       }
+                                       cycles_do_special();
+                                       do_cycles(maxhpos / 2 * CYCLE_UNIT);
+                                       if (regs.spcflags & SPCFLAG_COPPER) {
+                                               do_copper();
+                                       }
+                                       check_uae_int_request();
+                                       int w = m68k_spinlock_waiting;
+                                       if (w) {
+                                               cpu_semaphore_release();
+                                               while (m68k_spinlock_waiting == w);
+                                               cpu_semaphore_get();
+                                       }
+                               }
+                               cpu_semaphore_release();
+                               sleep_millis(1);
+                               cpu_semaphore_get();
+                               while ((int)read_processor_time() - (int)c < 0) {
+                                       check_uae_int_request();
+                                       int w = m68k_spinlock_waiting;
+                                       if (w) {
+                                               cpu_semaphore_release();
+                                               while (m68k_spinlock_waiting == w);
+                                               cpu_semaphore_get();
+                                       }
+                               }
+                       }
+                       cpu_semaphore_release();
+
+                       unset_special(SPCFLAG_BRK);
+#ifdef DEBUGGER
+                       if (debugging) {
+                               debug();
+                       }
+#endif
+               }
+       }
+}
+#endif
+
 #ifdef JIT  /* Completely different run_2 replacement */
 
 void do_nothing (void)
 {
-       /* What did you expect this to do? */
-       do_cycles (0);
-       /* I bet you didn't expect *that* ;-) */
+       if (!currprefs.cpu_thread) {
+               /* What did you expect this to do? */
+               do_cycles (0);
+               /* I bet you didn't expect *that* ;-) */
+       }
 }
 
 void exec_nostats (void)
@@ -4009,12 +4239,15 @@ void exec_nostats (void)
                }
                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
                cpu_cycles = adjust_cycles (cpu_cycles);
-               do_cycles (cpu_cycles);
+
+               if (!currprefs.cpu_thread) {
+                       do_cycles (cpu_cycles);
 
 #ifdef WITH_PPC
-               if (ppc_state)
-                       ppc_interrupt(intlev());
+                       if (ppc_state)
+                               ppc_interrupt(intlev());
 #endif
+               }
 
                if (end_block(r->opcode) || r->spcflags || uae_int_requested || uaenet_int_requested)
                        return; /* We will deal with the spcflags in the caller */
@@ -4048,8 +4281,10 @@ void execute_normal (void)
                pc_hist[blocklen].location = (uae_u16*)r->pc_p;
 
                cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
-               cpu_cycles = adjust_cycles (cpu_cycles);
-               do_cycles (cpu_cycles);
+               cpu_cycles = adjust_cycles(cpu_cycles);
+               if (!currprefs.cpu_thread) {
+                       do_cycles (cpu_cycles);
+               }
                total_cycles += cpu_cycles;
                pc_hist[blocklen].specmem = special_mem;
                blocklen++;
@@ -4069,8 +4304,33 @@ void execute_normal (void)
 
 typedef void compiled_handler (void);
 
-static void m68k_run_jit (void)
+#ifdef WITH_THREADED_CPU
+static void *cpu_thread_run_jit(void *v)
 {
+       cpu_thread_active = 1;
+       for (;;) {
+               ((compiled_handler*)(pushall_call_handler))();
+               /* Whenever we return from that, we should check spcflags */
+               if (regs.spcflags) {
+                       if (do_specialties_thread()) {
+                               break;
+                       }
+               }
+       }
+       cpu_thread_active = 0;
+       return 0;
+}
+#endif
+
+static void m68k_run_jit(void)
+{
+#ifdef WITH_THREADED_CPU
+       if (currprefs.cpu_thread) {
+               run_cpu_thread(cpu_thread_run_jit);
+               return;
+       }
+#endif
+
        for (;;) {
                ((compiled_handler*)(pushall_call_handler))();
                /* Whenever we return from that, we should check spcflags */
@@ -4600,12 +4860,52 @@ static void m68k_run_2p (void)
 
 #endif
 
-//static int used[65536];
+#ifdef WITH_THREADED_CPU
+static void *cpu_thread_run_2(void *v)
+{
+       bool exit = false;
+       struct regstruct *r = &regs;
+
+       cpu_thread_active = 1;
+       while (!exit) {
+               TRY(prb)
+               {
+                       while (!exit) {
+                               r->instruction_pc = m68k_getpc();
+
+                               r->opcode = x_get_iword(0);
+
+                               (*cpufunctbl[r->opcode])(r->opcode);
+
+                               if (r->spcflags) {
+                                       if (do_specialties_thread())
+                                               exit = true;
+                               }
+                       }
+               } CATCH(prb)
+               {
+                       bus_error();
+                       if (r->spcflags) {
+                               if (do_specialties_thread())
+                                       exit = true;
+                       }
+               } ENDTRY
+       }
+       cpu_thread_active = 0;
+       return 0;
+}
+#endif
 
 /* Same thing, but don't use prefetch to get opcode.  */
 static void m68k_run_2 (void)
 {
-//     static int done;
+#ifdef WITH_THREADED_CPU
+       if (currprefs.cpu_thread) {
+               run_cpu_thread(cpu_thread_run_2);
+               return;
+       }
+#endif
+
        struct regstruct *r = &regs;
        bool exit = false;
 
@@ -4684,6 +4984,9 @@ void m68k_go (int may_quit)
        int hardboot = 1;
        int startup = 1;
 
+#ifdef WITH_THREADED_CPU
+       init_cpu_thread();
+#endif
        if (in_m68k_go || !may_quit) {
                write_log (_T("Bug! m68k_go is not reentrant.\n"));
                abort ();
@@ -6335,41 +6638,86 @@ static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr))
        regs.cacheholdingdata020 = data;
 }
 
-uae_u32 get_word_ce020_prefetch (int o)
+#if MORE_ACCURATE_68020_PIPELINE
+static void pipeline_020(uae_u16 w, uaecptr pc)
 {
-       uae_u32 pc = m68k_getpc () + o;
-       uae_u32 v;
+       if (regs.pipeline_pos <  0)
+               return;
+#if 0
+       if (regs.pipeline_pos > 2 && regs.pipeline_next) {
+               // disp 020+ second word
+               if (w & 0x100) {
+                       if ((w & 0x30) == 0x20)
+                               regs.pipeline_pos += 2;
+                       if ((w & 0x30) == 0x30)
+                               regs.pipeline_pos += 4;
+                       if ((w & 0x3) == 0x2)
+                               regs.pipeline_pos += 2;
+                       if ((w & 0x3) == 0x3)
+                               regs.pipeline_pos += 4;
+               }
+               regs.pipeline_next = false;
+       }
+#endif
+       if (regs.pipeline_pos > 2) {
+               regs.pipeline_pos -= 2;
+               return;
+       }
+       if (regs.pipeline_stop) {
+               regs.pipeline_stop = -1;
+               return;
+       }
+       regs.pipeline_pos = cpudatatbl[w].length;
+       regs.pipeline_next = false;
+#if 0
+       if (!regs.pipeline_pos) {
+               write_log(_T("Opcode %04x has no size PC=%08x!\n"), w, pc);
+       }
+#endif
+       if (cpudatatbl[w].disp020) {
+               // not supported yet
+               regs.pipeline_pos = -1;
+#if 0
+               regs.pipeline_next = true;
+               regs.pipeline_pos += 2;
+#endif
+       }
 
-       if (pc & 2) {
-               v = regs.prefetch020[0] & 0xffff;
-               regs.prefetch020[0] = regs.prefetch020[1];
-               fill_icache020 (pc + 2 + 4, mem_access_delay_longi_read_ce020);
-               regs.prefetch020[1] = regs.cacheholdingdata020;
-               regs.db = regs.prefetch020[0] >> 16;
-       } else {
-               v = regs.prefetch020[0] >> 16;
-               regs.db = regs.prefetch020[1] >> 16;
+       if (regs.pipeline_pos > 0 && cpudatatbl[w].branch) {
+               regs.pipeline_pos -= 1 * 2;
+               if (regs.pipeline_pos <= 0)
+                       regs.pipeline_stop = -1;
+               else
+                       regs.pipeline_stop = 1;
        }
-       do_cycles_ce020_internal (2);
-       return v;
 }
+#endif
 
-uae_u32 get_word_ce020_prefetch_buffer(int o)
+uae_u32 get_word_ce020_prefetch (int o)
 {
-       uae_u32 pc = m68k_getpc() + 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];
-               //fill_icache020(pc + 2 + 4, mem_access_delay_longi_read_ce020);
-               //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_icache020 (pc + 2 + 4, mem_access_delay_longi_read_ce020);
+                       regs.prefetch020[1] = regs.cacheholdingdata020;
+               }
                regs.db = regs.prefetch020[0] >> 16;
        } else {
                v = regs.prefetch020[0] >> 16;
+#if MORE_ACCURATE_68020_PIPELINE
+               pipeline_020(regs.prefetch020[1] >> 16, pc);
+#endif
                regs.db = regs.prefetch020[1] >> 16;
        }
-       do_cycles_ce020_internal(2);
+       do_cycles_ce020_internal (2);
        return v;
 }
 
@@ -6380,12 +6728,20 @@ uae_u32 get_word_020_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_icache020 (pc + 2 + 4, get_longi);
-               regs.prefetch020[1] = regs.cacheholdingdata020;
+               if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
+                       fill_icache020 (pc + 2 + 4, get_longi);
+                       regs.prefetch020[1] = regs.cacheholdingdata020;
+               }
                regs.db = regs.prefetch020[0] >> 16;
        } else {
                v = regs.prefetch020[0] >> 16;
+#if MORE_ACCURATE_68020_PIPELINE
+               pipeline_020(regs.prefetch020[1] >> 16, pc);
+#endif
                regs.db = regs.prefetch020[0];
        }
        return v;
@@ -6893,23 +7249,6 @@ uae_u32 get_word_ce030_prefetch (int o)
        return v;
 }
 
-uae_u32 get_word_ce030_prefetch_buffer(int o)
-{
-       uae_u32 pc = m68k_getpc() + o;
-       uae_u32 v;
-
-       if (pc & 2) {
-               v = regs.prefetch020[0] & 0xffff;
-               regs.prefetch020[0] = regs.prefetch020[1];
-               //fill_icache030(pc + 2 + 4);
-               //regs.prefetch020[1] = regs.cacheholdingdata020;
-       } else {
-               v = regs.prefetch020[0] >> 16;
-       }
-       do_cycles_ce020_internal(2);
-       return v;
-}
-
 uae_u32 get_word_icache030(uaecptr addr)
 {
        fill_icache030(addr);
@@ -7307,30 +7646,51 @@ void fill_prefetch_030 (void)
 {
        uaecptr pc = m68k_getpc ();
        pc &= ~3;
+       regs.pipeline_pos = 0;
+       regs.pipeline_stop = 0;
+
        fill_icache030 (pc);
        if (currprefs.cpu_cycle_exact)
                do_cycles_ce020_internal(2);
        regs.prefetch020[0] = regs.cacheholdingdata020;
+
        fill_icache030 (pc + 4);
        if (currprefs.cpu_cycle_exact)
                do_cycles_ce020_internal(2);
        regs.prefetch020[1] = regs.cacheholdingdata020;
+
        regs.irc = get_word_ce030_prefetch (0);
 }
 
 void fill_prefetch_020 (void)
 {
        uaecptr pc = m68k_getpc ();
-       uae_u32 (*fetch)(uaecptr) = currprefs.cpu_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi;
+       uaecptr pc2 = pc;
        pc &= ~3;
+       uae_u32 (*fetch)(uaecptr) = currprefs.cpu_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi;
+       regs.pipeline_pos = 0;
+       regs.pipeline_stop = 0;
+
        fill_icache020 (pc, fetch);
        if (currprefs.cpu_cycle_exact)
                do_cycles_ce020_internal(2);
        regs.prefetch020[0] = regs.cacheholdingdata020;
+
        fill_icache020 (pc + 4, fetch);
        if (currprefs.cpu_cycle_exact)
                do_cycles_ce020_internal(2);
        regs.prefetch020[1] = regs.cacheholdingdata020;
+
+#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_ce020_prefetch (0);
        else
@@ -7339,8 +7699,11 @@ void fill_prefetch_020 (void)
 
 void fill_prefetch (void)
 {
+       regs.pipeline_pos = 0;
        if (currprefs.cachesize)
                return;
+       if (!currprefs.cpu_compatible)
+               return;
        if (currprefs.cpu_model >= 68040) {
                if (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) {
                        fill_icache040(m68k_getpc() + 16);
index 00ebb1b573961f9e54ca47ed76e312d49943451d..5d022dd3b31e09f5c85077006d3ef490f8c39c0b 100644 (file)
@@ -296,6 +296,16 @@ void sleep_millis (int ms)
        sleep_millis2 (ms, false);
 }
 
+void sleep_millis_amiga(int ms)
+{
+#ifdef WITH_THREADED_CPU
+       cpu_semaphore_release();
+#endif
+       sleep_millis_main(ms);
+#ifdef WITH_THREADED_CPU
+       cpu_semaphore_get();
+#endif
+}
 
 frame_time_t read_processor_time_qpf (void)
 {