From 19d1d44aea20f7b362370d399ff0bfe54e9b1d33 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Mon, 13 Jul 2015 19:09:21 +0300 Subject: [PATCH] More accurate 68020/030 pipeline emulation. Totally unusable threaded CPU emulation. --- build68k.cpp | 2 +- cfgfile.cpp | 6 +- cia.cpp | 4 +- custom.cpp | 4 +- gencpu.cpp | 99 +++++---- include/cpu_prefetch.h | 21 -- include/memory.h | 4 +- include/newcpu.h | 27 ++- include/options.h | 1 + include/uae.h | 4 +- main.cpp | 5 + memory.cpp | 108 ++++++++++ newcpu.cpp | 465 ++++++++++++++++++++++++++++++++++++----- od-win32/win32.cpp | 10 + 14 files changed, 642 insertions(+), 118 deletions(-) diff --git a/build68k.cpp b/build68k.cpp index 5a9316dd..37a5c5ec 100644 --- a/build68k.cpp +++ b/build68k.cpp @@ -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; diff --git a/cfgfile.cpp b/cfgfile.cpp index 9dfa373f..8a688534 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -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 57ebf81f..91eeb3f2 100644 --- 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 { diff --git a/custom.cpp b/custom.cpp index 5de71af6..8d0e12c4 100644 --- a/custom.cpp +++ b/custom.cpp @@ -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) { diff --git a/gencpu.cpp b/gencpu.cpp index d265be2d..f3210324 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -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); diff --git a/include/cpu_prefetch.h b/include/cpu_prefetch.h index 6bfdfc7c..12e60fe7 100644 --- a/include/cpu_prefetch.h +++ b/include/cpu_prefetch.h @@ -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); diff --git a/include/memory.h b/include/memory.h index 24e5e8fd..0e0ebd43 100644 --- a/include/memory.h +++ b/include/memory.h @@ -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) \ diff --git a/include/newcpu.h b/include/newcpu.h index 1f625cab..08694be4 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -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*)®s.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*)®s.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); diff --git a/include/options.h b/include/options.h index 96b57c60..29404e2d 100644 --- a/include/options.h +++ b/include/options.h @@ -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; diff --git a/include/uae.h b/include/uae.h index 1c5d65e6..c0db69fc 100644 --- a/include/uae.h +++ b/include/uae.h @@ -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 diff --git a/main.cpp b/main.cpp index c2525e16..54428ba4 100644 --- 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); diff --git a/memory.cpp b/memory.cpp index 11d0e064..ab89b463 100644 --- a/memory.cpp +++ b/memory.cpp @@ -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--; } } diff --git a/newcpu.cpp b/newcpu.cpp index 5ba4b113..1a6505a4 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -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 @@ -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 +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 = ®s; + + 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 = ®s; 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); diff --git a/od-win32/win32.cpp b/od-win32/win32.cpp index 00ebb1b5..5d022dd3 100644 --- a/od-win32/win32.cpp +++ b/od-win32/win32.cpp @@ -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) { -- 2.47.3