From 97beeaddc8b9d44b59b582bd434a65566ea59a42 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Wed, 14 Oct 2015 20:11:05 +0300 Subject: [PATCH] DMA/memory only cycle-exact mode. --- blitter.cpp | 4 +- cfgfile.cpp | 53 ++++++--- cia.cpp | 18 ++- cpummu.cpp | 2 +- custom.cpp | 20 ++-- include/cpu_prefetch.h | 103 +---------------- include/memory.h | 3 +- include/options.h | 2 + main.cpp | 11 +- newcpu.cpp | 244 +++++++++++++++++++++++++++++++++++++---- 10 files changed, 296 insertions(+), 164 deletions(-) diff --git a/blitter.cpp b/blitter.cpp index 9fa0577a..12b604d3 100644 --- a/blitter.cpp +++ b/blitter.cpp @@ -1599,7 +1599,7 @@ static void do_blitter2 (int hpos, int copper) blit_cyclecounter = cycles * (blit_dmacount2 + (blit_nod ? 0 : 1)); event2_newevent (ev2_blitter, blit_cyclecounter, 0); - if (dmaen (DMA_BLITTER) && (currprefs.cpu_model >= 68020 || !currprefs.cpu_cycle_exact)) { + if (dmaen (DMA_BLITTER) && (currprefs.cpu_model >= 68020 || !currprefs.cpu_memory_cycle_exact)) { if (currprefs.waiting_blits) { // wait immediately if all cycles in use and blitter nastry if (blit_dmacount == blit_diag[0] && (regs.spcflags & SPCFLAG_BLTNASTY)) { @@ -1646,7 +1646,7 @@ void maybe_blit (int hpos, int hack) if (savestate_state) return; - if (dmaen (DMA_BLITTER) && (currprefs.cpu_model >= 68020 || !currprefs.cpu_cycle_exact)) { + if (dmaen (DMA_BLITTER) && (currprefs.cpu_model >= 68020 || !currprefs.cpu_memory_cycle_exact)) { bool doit = false; if (currprefs.waiting_blits == 3) { // always doit = true; diff --git a/cfgfile.cpp b/cfgfile.cpp index 47a2c34b..b027acee 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -332,12 +332,11 @@ static TCHAR *cfgfile_option_find_it(const TCHAR *s, const TCHAR *option, bool c *tmpp++ = 0; if (checkequals) { tmpp2 = _tcschr(p, '='); - if (!tmpp2) - return NULL; - *tmpp2++ = 0; + if (tmpp2) + *tmpp2++ = 0; } if (!strcasecmp(p, option)) { - if (checkequals) + if (checkequals && tmpp2) return tmpp2; return p; } @@ -962,6 +961,12 @@ static void write_filesys_config (struct uae_prefs *p, struct zfile *f) _tcscat(tmp, extras); _tcscat(tmp3, extras); } + if (ci->unit_special_flags) { + TCHAR tmpx[32]; + _stprintf(tmpx, _T(",flags=0x%x"), ci->unit_special_flags); + _tcscat(tmp, tmpx); + _tcscat(tmp3, tmpx); + } if (ci->type == UAEDEV_HDF) cfgfile_write_str (f, _T("hardfile2"), tmp); #if 0 @@ -1853,6 +1858,8 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) } cfgfile_write_bool (f, _T("cpu_cycle_exact"), p->cpu_cycle_exact); + // must be after cpu_cycle_exact + cfgfile_write_bool (f, _T("cpu_memory_cycle_exact"), p->cpu_memory_cycle_exact); cfgfile_write_bool (f, _T("blitter_cycle_exact"), p->blitter_cycle_exact); cfgfile_write_bool (f, _T("cycle_exact"), p->cpu_cycle_exact && p->blitter_cycle_exact ? 1 : 0); cfgfile_dwrite_bool (f, _T("fpu_no_unimplemented"), p->fpu_no_unimplemented); @@ -3847,6 +3854,11 @@ static int cfgfile_parse_newfilesys (struct uae_prefs *p, int nr, int type, TCHA else if (cfgfile_option_find(tmpp2, _T("HD"))) uci.controller_media_type = 0; + TCHAR *pflags; + if ((pflags = cfgfile_option_get(tmpp2, _T("flags")))) { + getintval(&pflags, &uci.unit_special_flags, 0); + } + if (cfgfile_option_find(tmpp2, _T("SCSI2"))) uci.unit_feature_level = HD_LEVEL_SCSI_2; else if (cfgfile_option_find(tmpp2, _T("SCSI1"))) @@ -4188,17 +4200,27 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH bool tmpbool, dummybool; TCHAR tmpbuf[CONFIG_BLEN]; - if (cfgfile_yesno (option, value, _T("cpu_cycle_exact"), &p->cpu_cycle_exact) - || cfgfile_yesno (option, value, _T("blitter_cycle_exact"), &p->blitter_cycle_exact)) { - if (p->cpu_model >= 68020 && p->cachesize > 0) - p->cpu_cycle_exact = p->blitter_cycle_exact = 0; - /* we don't want cycle-exact in 68020/40+JIT modes */ - return 1; + if (cfgfile_yesno (option, value, _T("cpu_cycle_exact"), &p->cpu_cycle_exact)) { + /* we don't want cycle-exact in 68020/40+JIT modes */ + if (p->cpu_model >= 68020 && p->cachesize > 0) + p->cpu_cycle_exact = p->cpu_memory_cycle_exact = p->blitter_cycle_exact = 0; + p->cpu_memory_cycle_exact = p->cpu_cycle_exact; + return 1; + } + if (cfgfile_yesno (option, value, _T("blitter_cycle_exact"), &p->blitter_cycle_exact)) { + if (p->cpu_model >= 68020 && p->cachesize > 0) + p->cpu_cycle_exact = p->cpu_memory_cycle_exact = p->blitter_cycle_exact = 0; + return 1; + } + if (cfgfile_yesno (option, value, _T("cpu_memory_cycle_exact"), &p->cpu_memory_cycle_exact)) { + if (!p->cpu_memory_cycle_exact) + p->cpu_cycle_exact = false; + return 1; } if (cfgfile_yesno (option, value, _T("cycle_exact"), &tmpbool)) { - p->cpu_cycle_exact = p->blitter_cycle_exact = tmpbool; + p->cpu_cycle_exact = p->cpu_memory_cycle_exact = p->blitter_cycle_exact = tmpbool; if (p->cpu_model >= 68020 && p->cachesize > 0) - p->cpu_cycle_exact = p->blitter_cycle_exact = false; + p->cpu_cycle_exact = p->cpu_memory_cycle_exact = p->blitter_cycle_exact = false; // if old version and CE and fastest possible: set to approximate if (p->cpu_cycle_exact && p->config_version < ((2 << 16) | (8 << 8) | (2 << 0)) && p->m68k_speed < 0) p->m68k_speed = 0; @@ -6168,6 +6190,7 @@ void default_prefs (struct uae_prefs *p, int type) p->cpu_compatible = 1; p->address_space_24 = 1; p->cpu_cycle_exact = 0; + p->cpu_memory_cycle_exact = 0; p->blitter_cycle_exact = 0; p->chipset_mask = CSMASK_ECS_AGNUS; p->genlock = 0; @@ -6319,6 +6342,7 @@ static void buildin_default_prefs (struct uae_prefs *p) p->cpu_compatible = 1; p->address_space_24 = 1; p->cpu_cycle_exact = 0; + p->cpu_memory_cycle_exact = 0; p->blitter_cycle_exact = 0; p->chipset_mask = CSMASK_ECS_AGNUS; p->immediate_blits = 0; @@ -6394,6 +6418,7 @@ static void set_68020_compa (struct uae_prefs *p, int compa, int cd32) p->m68k_speed = 0; if (p->cpu_model == 68020 && p->cachesize == 0) { p->cpu_cycle_exact = 1; + p->cpu_memory_cycle_exact = 1; p->cpu_clock_multiplier = 4 << 8; } break; @@ -6426,7 +6451,7 @@ static void set_68000_compa (struct uae_prefs *p, int compa) switch (compa) { case 0: - p->cpu_cycle_exact = p->blitter_cycle_exact = 1; + p->cpu_cycle_exact = p->cpu_memory_cycle_exact = p->blitter_cycle_exact = 1; break; case 1: break; @@ -6991,7 +7016,7 @@ int built_in_prefs (struct uae_prefs *p, int model, int config, int compa, int r v = bip_super (p, config, compa, romcheck); break; } - if ((p->cpu_model >= 68020 || !p->cpu_cycle_exact) && !p->immediate_blits) + if ((p->cpu_model >= 68020 || !p->cpu_cycle_exact || !p->cpu_memory_cycle_exact) && !p->immediate_blits) p->waiting_blits = 1; if (p->sound_filter_type == FILTER_SOUND_TYPE_A500 && (p->chipset_mask & CSMASK_AGA)) p->sound_filter_type = FILTER_SOUND_TYPE_A1200; diff --git a/cia.cpp b/cia.cpp index 454868cc..8443d5cf 100644 --- a/cia.cpp +++ b/cia.cpp @@ -745,7 +745,7 @@ static int ciab_tod_event_state; static void CIAB_tod_inc (bool irq) { ciab_tod_event_state = 3; // done - if (!ciaatodon) + if (!ciabtodon) return; ciabtod++; ciabtod &= 0xFFFFFF; @@ -1795,7 +1795,7 @@ static void cia_wait_post (int cianummask, uae_u32 value) do_cycles (8 * CYCLE_UNIT /2); } else { int c = 6 * CYCLE_UNIT / 2; - if (currprefs.cpu_cycle_exact) + if (currprefs.cpu_memory_cycle_exact) x_do_cycles_post (c, value); else do_cycles (c); @@ -1846,7 +1846,7 @@ static uae_u32 REGPARAM2 cia_bget (uaecptr addr) uae_u8 v = 0xff; if (isgarynocia(addr)) - return dummy_get(addr, 1, false); + return dummy_get(addr, 1, false, 0); if (!isgaylenocia (addr)) return v; @@ -1898,7 +1898,7 @@ static uae_u32 REGPARAM2 cia_wget (uaecptr addr) uae_u16 v = 0xffff; if (isgarynocia(addr)) - return dummy_get(addr, 2, false); + return dummy_get(addr, 2, false, 0); if (!isgaylenocia (addr)) return v; @@ -2178,7 +2178,7 @@ void rtc_hardreset (void) static uae_u32 REGPARAM2 clock_lget (uaecptr addr) { if ((addr & 0xffff) >= 0x8000 && currprefs.cs_fatgaryrev >= 0) - return dummy_get(addr, 4, false); + return dummy_get(addr, 4, false, 0); return (clock_wget (addr) << 16) | clock_wget (addr + 2); } @@ -2186,7 +2186,7 @@ static uae_u32 REGPARAM2 clock_lget (uaecptr addr) static uae_u32 REGPARAM2 clock_wget (uaecptr addr) { if ((addr & 0xffff) >= 0x8000 && currprefs.cs_fatgaryrev >= 0) - return dummy_get(addr, 2, false); + return dummy_get(addr, 2, false, 0); return (clock_bget (addr) << 8) | clock_bget (addr + 1); } @@ -2197,7 +2197,7 @@ static uae_u32 REGPARAM2 clock_bget (uaecptr addr) uae_u8 v = 0; if ((addr & 0xffff) >= 0x8000 && currprefs.cs_fatgaryrev >= 0) - return dummy_get(addr, 1, false); + return dummy_get(addr, 1, false, 0); #ifdef CDTV if (currprefs.cs_cdtvram && (addr & 0xffff) >= 0x8000) @@ -2206,9 +2206,7 @@ static uae_u32 REGPARAM2 clock_bget (uaecptr addr) addr &= 0x3f; if ((addr & 3) == 2 || (addr & 3) == 0 || currprefs.cs_rtc == 0) { - if (currprefs.cpu_model == 68000 && currprefs.cpu_compatible) - v = regs.irc >> 8; - return v; + return dummy_get_safe(addr, 1, false, v); } time_t t = time (0); t += currprefs.cs_rtc_adjust; diff --git a/cpummu.cpp b/cpummu.cpp index 233d0c75..114fa995 100644 --- a/cpummu.cpp +++ b/cpummu.cpp @@ -1246,7 +1246,7 @@ void REGPARAM2 mmu_set_funcs(void) { if (currprefs.mmu_model != 68040 && currprefs.mmu_model != 68060) return; - if (currprefs.cpu_cycle_exact || currprefs.cpu_compatible) { + if (currprefs.cpu_memory_cycle_exact || currprefs.cpu_compatible) { x_phys_get_iword = get_word_icache040; x_phys_get_ilong = get_long_icache040; x_phys_get_byte = get_byte_cache_040; diff --git a/custom.cpp b/custom.cpp index 4bf58c67..72960a36 100644 --- a/custom.cpp +++ b/custom.cpp @@ -446,7 +446,7 @@ STATIC_INLINE int ecsshres(void) STATIC_INLINE int nodraw (void) { - return !currprefs.cpu_cycle_exact && framecnt != 0; + return !currprefs.cpu_memory_cycle_exact && framecnt != 0; } static int doflickerfix (void) @@ -7251,7 +7251,7 @@ static bool framewait (void) int clockadjust = 0; int vstb = vsynctimebase; - if (currprefs.m68k_speed < 0 && !currprefs.cpu_cycle_exact) { + if (currprefs.m68k_speed < 0 && !currprefs.cpu_memory_cycle_exact) { #if 0 static uae_u32 prevtick; @@ -7904,7 +7904,7 @@ static void hsync_handler_post (bool onvsync) { last_copper_hpos = 0; #ifdef CPUEMU_13 - if (currprefs.cpu_cycle_exact || currprefs.blitter_cycle_exact) { + if (currprefs.cpu_memory_cycle_exact || currprefs.blitter_cycle_exact) { memset (cycle_line, 0, sizeof cycle_line); } #endif @@ -7996,7 +7996,7 @@ static void hsync_handler_post (bool onvsync) } #ifdef CPUEMU_13 - if (currprefs.cpu_cycle_exact || currprefs.blitter_cycle_exact) { + if (currprefs.cpu_memory_cycle_exact || currprefs.blitter_cycle_exact) { int hp = maxhpos - 1, i; for (i = 0; i < 4; i++) { alloc_cycle (hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH); /* strobe */ @@ -8037,7 +8037,7 @@ static void hsync_handler_post (bool onvsync) port_get_custom (1, out); } #endif - if (!currprefs.cpu_thread && currprefs.m68k_speed < 0 && !currprefs.cpu_cycle_exact) { + if (!currprefs.cpu_thread && currprefs.m68k_speed < 0 && !currprefs.cpu_memory_cycle_exact) { static int sleeps_remaining; if (is_last_line ()) { sleeps_remaining = (165 - currprefs.cpu_idle) / 6; @@ -8757,7 +8757,7 @@ static uae_u32 REGPARAM2 custom_wget (uaecptr addr) uae_u32 v; if ((addr & 0xffff) < 0x8000 && currprefs.cs_fatgaryrev >= 0) - return dummy_get(addr, 2, false); + return dummy_get(addr, 2, false, 0); if (addr & 1) { /* think about move.w $dff005,d0.. (68020+ only) */ addr &= ~1; @@ -8772,7 +8772,7 @@ static uae_u32 REGPARAM2 custom_bget (uaecptr addr) { uae_u32 v; if ((addr & 0xffff) < 0x8000 && currprefs.cs_fatgaryrev >= 0) - return dummy_get(addr, 1, false); + return dummy_get(addr, 1, false, 0); v = custom_wget2 (addr & ~1, true); v >>= (addr & 1 ? 0 : 8); return v; @@ -8781,7 +8781,7 @@ static uae_u32 REGPARAM2 custom_bget (uaecptr addr) static uae_u32 REGPARAM2 custom_lget (uaecptr addr) { if ((addr & 0xffff) < 0x8000 && currprefs.cs_fatgaryrev >= 0) - return dummy_get(addr, 4, false); + return dummy_get(addr, 4, false, 0); return ((uae_u32)custom_wget (addr) << 16) | custom_wget (addr + 2); } static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int noget) @@ -9755,9 +9755,9 @@ static int dma_cycle (void) blitter_nasty = 1; if (cpu_tracer < 0) return current_hpos (); - if (!currprefs.cpu_cycle_exact) + if (!currprefs.cpu_memory_cycle_exact) return current_hpos (); - while (currprefs.cpu_cycle_exact) { + while (currprefs.cpu_memory_cycle_exact) { int bpldma; int blitpri = dmacon & DMA_BLITPRI; hpos_old = current_hpos (); diff --git a/include/cpu_prefetch.h b/include/cpu_prefetch.h index acf9e5b1..96604d13 100644 --- a/include/cpu_prefetch.h +++ b/include/cpu_prefetch.h @@ -333,104 +333,11 @@ STATIC_INLINE void ipl_fetch (void) regs.ipl = regs.ipl_pin; } -STATIC_INLINE uae_u32 mem_access_delay_word_read (uaecptr addr) -{ - uae_u32 v; - switch (ce_banktype[addr >> 16]) - { - case CE_MEMBANK_CHIP16: - case CE_MEMBANK_CHIP32: - v = wait_cpu_cycle_read (addr, 1); - break; - case CE_MEMBANK_FAST16: - case CE_MEMBANK_FAST32: - v = get_word (addr); - x_do_cycles_post (4 * cpucycleunit, v); - break; - default: - v = get_word (addr); - break; - } - regs.db = v; - return v; -} -STATIC_INLINE uae_u32 mem_access_delay_wordi_read (uaecptr addr) -{ - uae_u32 v; - switch (ce_banktype[addr >> 16]) - { - case CE_MEMBANK_CHIP16: - case CE_MEMBANK_CHIP32: - v = wait_cpu_cycle_read (addr, 1); - break; - case CE_MEMBANK_FAST16: - case CE_MEMBANK_FAST32: - v = get_wordi (addr); - x_do_cycles_post (4 * cpucycleunit, v); - break; - default: - v = get_wordi (addr); - break; - } - regs.db = v; - return v; -} - -STATIC_INLINE uae_u32 mem_access_delay_byte_read (uaecptr addr) -{ - uae_u32 v; - switch (ce_banktype[addr >> 16]) - { - case CE_MEMBANK_CHIP16: - case CE_MEMBANK_CHIP32: - v = wait_cpu_cycle_read (addr, 0); - break; - case CE_MEMBANK_FAST16: - case CE_MEMBANK_FAST32: - v = get_byte (addr); - x_do_cycles_post (4 * cpucycleunit, v); - break; - default: - v = get_byte (addr); - break; - } - regs.db = (v << 8) | v; - return v; -} -STATIC_INLINE void mem_access_delay_byte_write (uaecptr addr, uae_u32 v) -{ - regs.db = (v << 8) | v; - switch (ce_banktype[addr >> 16]) - { - case CE_MEMBANK_CHIP16: - case CE_MEMBANK_CHIP32: - wait_cpu_cycle_write (addr, 0, v); - return; - case CE_MEMBANK_FAST16: - case CE_MEMBANK_FAST32: - put_byte (addr, v); - x_do_cycles_post (4 * cpucycleunit, v); - return; - } - put_byte (addr, v); -} -STATIC_INLINE void mem_access_delay_word_write (uaecptr addr, uae_u32 v) -{ - regs.db = v; - switch (ce_banktype[addr >> 16]) - { - case CE_MEMBANK_CHIP16: - case CE_MEMBANK_CHIP32: - wait_cpu_cycle_write (addr, 1, v); - return; - case CE_MEMBANK_FAST16: - case CE_MEMBANK_FAST32: - put_word (addr, v); - x_do_cycles_post (4 * cpucycleunit, v); - return; - } - put_word (addr, v); -} +uae_u32 mem_access_delay_word_read (uaecptr addr); +uae_u32 mem_access_delay_wordi_read (uaecptr addr); +uae_u32 mem_access_delay_byte_read (uaecptr addr); +void mem_access_delay_byte_write (uaecptr addr, uae_u32 v); +void mem_access_delay_word_write (uaecptr addr, uae_u32 v); STATIC_INLINE uae_u32 get_long_ce000 (uaecptr addr) { diff --git a/include/memory.h b/include/memory.h index 33838329..65160037 100644 --- a/include/memory.h +++ b/include/memory.h @@ -283,7 +283,8 @@ extern uae_u32 last_custom_value1; /* Default memory access functions */ extern void dummy_put (uaecptr addr, int size, uae_u32 val); -extern uae_u32 dummy_get (uaecptr addr, int size, bool inst); +extern uae_u32 dummy_get (uaecptr addr, int size, bool inst, uae_u32 defvalue); +extern uae_u32 dummy_get_safe(uaecptr addr, int size, bool inst, uae_u32 defvalue); extern int REGPARAM3 default_check(uaecptr addr, uae_u32 size) REGPARAM; extern uae_u8 *REGPARAM3 default_xlate(uaecptr addr) REGPARAM; diff --git a/include/options.h b/include/options.h index 20da48b7..386b1b51 100644 --- a/include/options.h +++ b/include/options.h @@ -170,6 +170,7 @@ struct uaedev_config_info { int controller_unit; int controller_media_type; // 1 = CF IDE, 0 = normal int unit_feature_level; + int unit_special_flags; bool physical_geometry; // if false: use defaults int pcyls, pheads, psecs; int flags; @@ -454,6 +455,7 @@ struct uae_prefs { int cpu_clock_multiplier; int cpu_frequency; bool blitter_cycle_exact; + bool cpu_memory_cycle_exact; int floppy_speed; int floppy_write_length; int floppy_random_bits_min; diff --git a/main.cpp b/main.cpp index c68e4d3f..598298c5 100644 --- a/main.cpp +++ b/main.cpp @@ -246,7 +246,7 @@ 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)) { + if (p->cpu_thread && (p->cpu_compatible || p->ppc_mode || p->cpu_cycle_exact || p->cpu_memory_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.")); } @@ -270,6 +270,9 @@ void fixup_cpu (struct uae_prefs *p) error_log (_T("JIT requires 68020 or better CPU.")); } + if (!p->cpu_memory_cycle_exact && p->cpu_cycle_exact) + p->cpu_memory_cycle_exact = true; + if (p->cpu_model >= 68040 && p->cachesize && p->cpu_compatible) p->cpu_compatible = false; @@ -278,7 +281,7 @@ void fixup_cpu (struct uae_prefs *p) p->mmu_model = 0; } - if (p->cachesize && p->cpu_cycle_exact) { + if (p->cachesize && (p->cpu_cycle_exact || p->cpu_memory_cycle_exact)) { error_log (_T("JIT and cycle-exact can't be enabled simultaneously.")); p->cachesize = 0; } @@ -302,10 +305,10 @@ void fixup_cpu (struct uae_prefs *p) error_log (_T("Immediate blitter and waiting blits can't be enabled simultaneously.\n")); p->waiting_blits = 0; } - if (p->cpu_cycle_exact) + if (p->cpu_cycle_exact || p->cpu_memory_cycle_exact) p->cpu_compatible = true; - if (p->cpu_cycle_exact && p->produce_sound == 0) { + if ((p->cpu_cycle_exact || p->cpu_memory_cycle_exact) && p->produce_sound == 0) { p->produce_sound = 1; error_log(_T("Cycle-exact mode requires at least Disabled but emulated sound setting.")); } diff --git a/newcpu.cpp b/newcpu.cpp index 56d14192..e24d4fbb 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -819,7 +819,25 @@ static void set_x_funcs (void) x_do_cycles = do_cycles_ce; x_do_cycles_pre = do_cycles_ce; x_do_cycles_post = do_cycles_ce_post; + } else if (currprefs.cpu_memory_cycle_exact) { + // cpu_memory_cycle_exact + cpu_compatible + x_prefetch = get_word_prefetch; + x_get_ilong = NULL; + x_get_iword = get_iiword; + x_get_ibyte = get_iibyte; + x_next_iword = NULL; + x_next_ilong = NULL; + x_put_long = put_long_ce000; + x_put_word = put_word_ce000; + x_put_byte = put_byte_ce000; + x_get_long = get_long_ce000; + x_get_word = get_word_ce000; + x_get_byte = get_byte_ce000; + x_do_cycles = do_cycles; + x_do_cycles_pre = do_cycles; + x_do_cycles_post = do_cycles_post; } else if (currprefs.cpu_compatible) { + // cpu_compatible only x_prefetch = get_word_prefetch; x_get_ilong = NULL; x_get_iword = get_iiword; @@ -854,7 +872,73 @@ static void set_x_funcs (void) } } else if (!currprefs.cpu_cycle_exact) { // 68020+ no ce - if (currprefs.cpu_compatible) { + if (currprefs.cpu_memory_cycle_exact) { + // cpu_memory_cycle_exact + cpu_compatible + if (currprefs.cpu_model == 68020 && !currprefs.cachesize) { + x_prefetch = get_word_020_prefetch; + x_get_ilong = get_long_020_prefetch; + x_get_iword = get_word_020_prefetch; + x_get_ibyte = NULL; + x_next_iword = next_iword_020_prefetch; + x_next_ilong = next_ilong_020_prefetch; + x_put_long = put_long_ce020; + x_put_word = put_word_ce020; + x_put_byte = put_byte_ce020; + x_get_long = get_long_ce020; + x_get_word = get_word_ce020; + x_get_byte = get_byte_ce020; + x_do_cycles = do_cycles; + x_do_cycles_pre = do_cycles; + x_do_cycles_post = do_cycles_post; + } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) { + x_prefetch = get_word_030_prefetch; + x_get_ilong = get_long_030_prefetch; + x_get_iword = get_word_030_prefetch; + x_get_ibyte = NULL; + x_next_iword = next_iword_030_prefetch; + x_next_ilong = next_ilong_030_prefetch; + x_put_long = put_long_ce030; + x_put_word = put_word_ce030; + x_put_byte = put_byte_ce030; + x_get_long = get_long_ce030; + x_get_word = get_word_ce030; + x_get_byte = get_byte_ce030; + x_do_cycles = do_cycles; + x_do_cycles_pre = do_cycles; + x_do_cycles_post = do_cycles_post; + } else if (currprefs.cpu_model < 68040) { + // JIT or 68030+ does not have real prefetch only emulation + x_prefetch = NULL; + set_x_ifetches(); + x_put_long = put_long; + x_put_word = put_word; + x_put_byte = put_byte; + x_get_long = get_long; + x_get_word = get_word; + x_get_byte = get_byte; + x_do_cycles = do_cycles; + x_do_cycles_pre = do_cycles; + x_do_cycles_post = do_cycles_post; + } else { + // 68040+ (same as below) + x_prefetch = NULL; + x_get_ilong = get_ilong_cache_040; + x_get_iword = get_iword_cache_040; + x_get_ibyte = NULL; + x_next_iword = next_iword_cache040; + x_next_ilong = next_ilong_cache040; + x_put_long = put_long_cache_040; + x_put_word = put_word_cache_040; + x_put_byte = put_byte_cache_040; + x_get_long = get_long_cache_040; + x_get_word = get_word_cache_040; + x_get_byte = get_byte_cache_040; + x_do_cycles = do_cycles; + x_do_cycles_pre = do_cycles; + x_do_cycles_post = do_cycles_post; + } + } else if (currprefs.cpu_compatible) { + // cpu_compatible only if (currprefs.cpu_model == 68020 && !currprefs.cachesize) { x_prefetch = get_word_prefetch; x_get_ilong = get_long_020_prefetch; @@ -1049,7 +1133,7 @@ static void set_x_funcs (void) bool can_cpu_tracer (void) { - return (currprefs.cpu_model == 68000 || currprefs.cpu_model == 68020) && currprefs.cpu_cycle_exact; + return (currprefs.cpu_model == 68000 || currprefs.cpu_model == 68020) && currprefs.cpu_memory_cycle_exact; } bool is_cpu_tracer (void) @@ -1079,7 +1163,7 @@ bool set_cpu_tracer (bool state) void flush_cpu_caches(bool force) { - bool doflush = currprefs.cpu_compatible || currprefs.cpu_cycle_exact; + bool doflush = currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact; if (currprefs.cpu_model == 68020) { if (regs.cacr & 0x08) { // clear instr cache @@ -1301,7 +1385,7 @@ static void build_cpufunctbl (void) } write_log (_T("Building CPU, %d opcodes (%d %d %d)\n"), opcnt, lvl, - currprefs.cpu_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0, currprefs.address_space_24); + currprefs.cpu_cycle_exact ? -2 : currprefs.cpu_memory_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0, currprefs.address_space_24); #ifdef JIT write_log(_T("JIT: &countdown = %p\n"), &countdown); write_log(_T("JIT: &build_comp = %p\n"), &build_comp); @@ -1330,6 +1414,8 @@ static void build_cpufunctbl (void) write_log(_T(" prefetch and cycle-exact")); else write_log(_T(" ~cycle-exact")); + } else if (currprefs.cpu_memory_cycle_exact) { + write_log(_T(" ~memory-cycle-exact")); } else if (currprefs.cpu_compatible) { if (currprefs.cpu_model <= 68020) { write_log(_T(" prefetch")); @@ -1422,6 +1508,7 @@ static void prefs_changed_cpu (void) currprefs.mmu_model = changed_prefs.mmu_model; currprefs.cpu_compatible = changed_prefs.cpu_compatible; currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact; + currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact; currprefs.int_no_unimplemented = changed_prefs.int_no_unimplemented; currprefs.fpu_no_unimplemented = changed_prefs.fpu_no_unimplemented; currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact; @@ -1441,7 +1528,8 @@ static int check_prefs_changed_cpu2(void) || currprefs.int_no_unimplemented != changed_prefs.int_no_unimplemented || currprefs.fpu_no_unimplemented != changed_prefs.fpu_no_unimplemented || currprefs.cpu_compatible != changed_prefs.cpu_compatible - || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact) { + || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact + || currprefs.cpu_memory_cycle_exact != changed_prefs.cpu_memory_cycle_exact) { cpu_prefs_changed_flag |= 1; } if (changed @@ -5358,9 +5446,9 @@ static const TCHAR *movemregs[] = _T("FP5"), _T("FP6"), _T("FP7"), - _T("FPCR"), + _T("FPIAR"), _T("FPSR"), - _T("FPIAR") + _T("FPCR") }; static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode) @@ -6009,6 +6097,7 @@ uae_u8 *restore_cpu (uae_u8 *src) currprefs.address_space_24 = changed_prefs.address_space_24; currprefs.cpu_compatible = changed_prefs.cpu_compatible; currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact; + currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact; currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact; currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0; currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0; @@ -6301,6 +6390,9 @@ uae_u8 *restore_cpu_extra (uae_u8 *src) uae_u32 flags = restore_u32 (); currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = (flags & 1) ? true : false; + currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact = currprefs.cpu_cycle_exact; + if ((flags & 32) && !(flags & 1)) + currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact = true; currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact = currprefs.cpu_cycle_exact; currprefs.cpu_compatible = changed_prefs.cpu_compatible = (flags & 2) ? true : false; currprefs.cpu_frequency = changed_prefs.cpu_frequency = restore_u32 (); @@ -6335,6 +6427,7 @@ uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr) flags |= currprefs.m68k_speed < 0 ? 4 : 0; flags |= currprefs.cachesize > 0 ? 8 : 0; flags |= currprefs.m68k_speed > 0 ? 16 : 0; + flags |= currprefs.cpu_memory_cycle_exact ? 32 : 0; if (currprefs.m68k_speed > 0) flags |= (currprefs.m68k_speed / CYCLE_UNIT) << 24; save_u32 (flags); @@ -6584,7 +6677,7 @@ void cpureset (void) m68k_reset_delay = currprefs.reset_delay; set_special(SPCFLAG_CHECK); send_internalevent(INTERNALEVENT_CPURESET); - if ((currprefs.cpu_compatible || currprefs.cpu_cycle_exact) && currprefs.cpu_model <= 68020) { + if ((currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact) && currprefs.cpu_model <= 68020) { custom_reset (false, false); return; } @@ -6640,6 +6733,107 @@ void m68k_resumestopped (void) unset_special (SPCFLAG_STOP); } + +uae_u32 mem_access_delay_word_read (uaecptr addr) +{ + uae_u32 v; + switch (ce_banktype[addr >> 16]) + { + case CE_MEMBANK_CHIP16: + case CE_MEMBANK_CHIP32: + v = wait_cpu_cycle_read (addr, 1); + break; + case CE_MEMBANK_FAST16: + case CE_MEMBANK_FAST32: + v = get_word (addr); + x_do_cycles_post (4 * cpucycleunit, v); + break; + default: + v = get_word (addr); + break; + } + regs.db = v; + return v; +} +uae_u32 mem_access_delay_wordi_read (uaecptr addr) +{ + uae_u32 v; + switch (ce_banktype[addr >> 16]) + { + case CE_MEMBANK_CHIP16: + case CE_MEMBANK_CHIP32: + v = wait_cpu_cycle_read (addr, 1); + break; + case CE_MEMBANK_FAST16: + case CE_MEMBANK_FAST32: + v = get_wordi (addr); + x_do_cycles_post (4 * cpucycleunit, v); + break; + default: + v = get_wordi (addr); + break; + } + regs.db = v; + return v; +} + +uae_u32 mem_access_delay_byte_read (uaecptr addr) +{ + uae_u32 v; + switch (ce_banktype[addr >> 16]) + { + case CE_MEMBANK_CHIP16: + case CE_MEMBANK_CHIP32: + v = wait_cpu_cycle_read (addr, 0); + break; + case CE_MEMBANK_FAST16: + case CE_MEMBANK_FAST32: + v = get_byte (addr); + x_do_cycles_post (4 * cpucycleunit, v); + break; + default: + v = get_byte (addr); + break; + } + regs.db = (v << 8) | v; + return v; +} +void mem_access_delay_byte_write (uaecptr addr, uae_u32 v) +{ + regs.db = (v << 8) | v; + switch (ce_banktype[addr >> 16]) + { + case CE_MEMBANK_CHIP16: + case CE_MEMBANK_CHIP32: + wait_cpu_cycle_write (addr, 0, v); + return; + case CE_MEMBANK_FAST16: + case CE_MEMBANK_FAST32: + put_byte (addr, v); + x_do_cycles_post (4 * cpucycleunit, v); + return; + } + put_byte (addr, v); +} +void mem_access_delay_word_write (uaecptr addr, uae_u32 v) +{ + regs.db = v; + switch (ce_banktype[addr >> 16]) + { + case CE_MEMBANK_CHIP16: + case CE_MEMBANK_CHIP32: + wait_cpu_cycle_write (addr, 1, v); + return; + case CE_MEMBANK_FAST16: + case CE_MEMBANK_FAST32: + put_word (addr, v); + x_do_cycles_post (4 * cpucycleunit, v); + return; + } + put_word (addr, v); +} + + // this one is really simple and easy static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr)) { @@ -6818,7 +7012,7 @@ uae_u32 get_word_020_prefetch (int o) #endif regs.prefetch020[0] = regs.prefetch020[1]; if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) { - fill_icache020 (pc + 2 + 4, get_longi); + fill_icache020 (pc + 2 + 4, currprefs.cpu_memory_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi); regs.prefetch020[1] = regs.cacheholdingdata020; } regs.db = regs.prefetch020[0] >> 16; @@ -7114,6 +7308,8 @@ static void fill_icache030 (uae_u32 addr) // add as available "free" internal CPU time. cycs = get_cycles () - cycs; regs.ce020memcycles += cycs; + } else if (currprefs.cpu_memory_cycle_exact) { + data = mem_access_delay_longi_read_ce020 (addr); } else { data = get_longi (addr); } @@ -7210,7 +7406,7 @@ static void write_dcache030x(uaecptr addr, uae_u32 val, int size) void write_dcache030(uaecptr addr, uae_u32 v, int size) { write_dcache030x(addr, v, size); - if (currprefs.cpu_cycle_exact) { + if (currprefs.cpu_memory_cycle_exact) { if (size == 2) mem_access_delay_long_write_ce020(addr, v); else if (size == 1) @@ -7236,7 +7432,7 @@ uae_u32 read_dcache030 (uaecptr addr, int size) uae_u32 v1, v2; if (!(regs.cacr & 0x100) || !cancache030 (addr)) { // data cache disabled? - if (currprefs.cpu_cycle_exact) { + if (currprefs.cpu_memory_cycle_exact) { if (size == 2) return mem_access_delay_long_read_ce020 (addr); else if (size == 1) @@ -7255,7 +7451,7 @@ uae_u32 read_dcache030 (uaecptr addr, int size) c1 = getcache030 (dcaches030, addr, &tag1, &lws1); addr &= ~3; if (!c1->valid[lws1] || c1->tag != tag1) { - v1 = currprefs.cpu_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr); + v1 = currprefs.cpu_memory_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr); update_cache030 (c1, v1, tag1, lws1); } else { v1 = c1->data[lws1]; @@ -7293,7 +7489,7 @@ uae_u32 read_dcache030 (uaecptr addr, int size) addr += 4; c2 = getcache030 (dcaches030, addr, &tag2, &lws2); if (!c2->valid[lws2] || c2->tag != tag2) { - v2 = currprefs.cpu_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr); + v2 = currprefs.cpu_memory_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr); update_cache030 (c2, v2, tag2, lws2); } else { v2 = c2->data[lws2]; @@ -7401,7 +7597,7 @@ uae_u32 fill_icache040(uae_u32 addr) if (regs.prefetch020addr == addr2) return regs.prefetch020[lws]; regs.prefetch020addr = addr2; - if (currprefs.cpu_cycle_exact) { + if (currprefs.cpu_memory_cycle_exact) { regs.prefetch020[0] = mem_access_delay_longi_read_ce020(addr2 + 0); regs.prefetch020[1] = mem_access_delay_longi_read_ce020(addr2 + 4); regs.prefetch020[2] = mem_access_delay_longi_read_ce020(addr2 + 8); @@ -7441,7 +7637,7 @@ uae_u32 fill_icache040(uae_u32 addr) } c->tag[line] = tag; c->valid[line] = true; - if (currprefs.cpu_cycle_exact) { + if (currprefs.cpu_memory_cycle_exact) { c->data[line][0] = mem_access_delay_longi_read_ce020(addr + 0); c->data[line][1] = mem_access_delay_longi_read_ce020(addr + 4); c->data[line][2] = mem_access_delay_longi_read_ce020(addr + 8); @@ -7596,7 +7792,7 @@ uae_u32 get_iword_cache_040(int o) STATIC_INLINE bool nocache040(uaecptr addr) { - if (!currprefs.cpu_cycle_exact) + if (!currprefs.cpu_memory_cycle_exact) return false; if (!(regs.cacr & 0x80000000)) return true; @@ -7618,7 +7814,7 @@ void put_long_cache_040(uaecptr addr, uae_u32 v) if ((addr & 2) == 0) { if (is_dcache040(addr)) write_dcache040(addr, v); - else if (currprefs.cpu_cycle_exact) + else if (currprefs.cpu_memory_cycle_exact) mem_access_delay_long_write_ce020(addr, v); else put_long(addr, v); @@ -7629,7 +7825,7 @@ void put_long_cache_040(uaecptr addr, uae_u32 v) vp &= 0xffff0000; vp |= v >> 16; write_dcache040(addr, vp); - } else if (currprefs.cpu_cycle_exact) { + } else if (currprefs.cpu_memory_cycle_exact) { mem_access_delay_word_write_ce020(addr + 0, v >> 16); } else { put_word(addr + 0, v >> 16); @@ -7639,7 +7835,7 @@ void put_long_cache_040(uaecptr addr, uae_u32 v) vp &= 0x0000ffff; vp |= v << 16; write_dcache040(addr + 4, vp); - } else if (currprefs.cpu_cycle_exact) { + } else if (currprefs.cpu_memory_cycle_exact) { mem_access_delay_word_write_ce020(addr + 2, v); } else { put_word(addr + 2, v); @@ -7666,7 +7862,7 @@ void put_word_cache_040(uaecptr addr, uae_u32 v) vp |= v << 16; } write_dcache040(addr, vp); - } else if (currprefs.cpu_cycle_exact) { + } else if (currprefs.cpu_memory_cycle_exact) { mem_access_delay_word_write_ce020(addr, v); } else { put_word(addr, v); @@ -7688,7 +7884,7 @@ void put_byte_cache_040(uaecptr addr, uae_u32 v) vp &= ~mask; vp |= (v << (3 - (addr & 3))) & mask; write_dcache040(addr, vp); - } else if (currprefs.cpu_cycle_exact) { + } else if (currprefs.cpu_memory_cycle_exact) { mem_access_delay_byte_write_ce020(addr, v); } else { put_byte(addr, v); @@ -7751,7 +7947,7 @@ uae_u32 next_ilong_cache040(void) void flush_dcache (uaecptr addr, int size) { - if (!currprefs.cpu_cycle_exact && !currprefs.cpu_compatible) + if (!currprefs.cpu_memory_cycle_exact && !currprefs.cpu_compatible) return; if (currprefs.cpu_model >= 68030) { for (int i = 0; i < CACHELINES030; i++) { @@ -7802,7 +7998,7 @@ void fill_prefetch_020 (void) uaecptr pc = m68k_getpc (); uaecptr pc2 = pc; pc &= ~3; - uae_u32 (*fetch)(uaecptr) = currprefs.cpu_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi; + uae_u32 (*fetch)(uaecptr) = currprefs.cpu_memory_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; @@ -7841,7 +8037,7 @@ void fill_prefetch (void) if (!currprefs.cpu_compatible) return; if (currprefs.cpu_model >= 68040) { - if (currprefs.cpu_compatible || currprefs.cpu_cycle_exact) { + if (currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact) { fill_icache040(m68k_getpc() + 16); fill_icache040(m68k_getpc()); } -- 2.47.3