From 95e3eb00c9e620d2707b71a435a573019ed69d1c Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Tue, 11 Jul 2017 21:05:50 +0300 Subject: [PATCH] MMU emulation updates, experimental caching. --- cpummu.cpp | 801 +++++++++++++++++++++++------------------ cpummu30.cpp | 753 ++++++++++++++++++++------------------- include/cpummu.h | 848 +++++++++++++++++++++++--------------------- include/cpummu030.h | 25 +- newcpu.cpp | 9 +- 5 files changed, 1287 insertions(+), 1149 deletions(-) diff --git a/cpummu.cpp b/cpummu.cpp index 489be33e..980cbb6a 100644 --- a/cpummu.cpp +++ b/cpummu.cpp @@ -45,21 +45,40 @@ uae_u32 mmu_is_super; uae_u32 mmu_tagmask, mmu_pagemask, mmu_pagemaski; -struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS]; +struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_SLOTS][ATC_WAYS]; bool mmu_pagesize_8k; +int mmu_pageshift, mmu_pageshift1m; int mmu060_state; uae_u16 mmu_opcode; bool mmu_restart; static bool locked_rmw_cycle; static bool ismoves; -bool mmu_ttr_enabled; +bool mmu_ttr_enabled, mmu_ttr_enabled_ins, mmu_ttr_enabled_data; int mmu_atc_ways; +int way_random; int mmu040_movem; uaecptr mmu040_movem_ea; uae_u32 mmu040_move16[4]; +#if MMU_ICACHE +struct mmu_icache mmu_icache_data[MMU_ICACHE_SZ]; +#endif +#if MMU_IPAGECACHE +uae_u32 atc_last_ins_laddr, atc_last_ins_paddr; +#endif +#if MMU_DPAGECACHE +struct mmufastcache atc_data_cache_read[MMUFASTCACHE_ENTRIES]; +struct mmufastcache atc_data_cache_write[MMUFASTCACHE_ENTRIES]; +#endif + +#if CACHE_HIT_COUNT +int mmu_ins_hit, mmu_ins_miss; +int mmu_data_read_hit, mmu_data_read_miss; +int mmu_data_write_hit, mmu_data_write_miss; +#endif + static void mmu_dump_ttr(const TCHAR * label, uae_u32 ttr) { DUNUSED(label); @@ -104,7 +123,9 @@ void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode) void mmu_tt_modified (void) { - mmu_ttr_enabled = ((regs.dtt0 | regs.dtt1 | regs.itt0 | regs.itt1) & MMU_TTR_BIT_ENABLED) != 0; + mmu_ttr_enabled_ins = ((regs.itt0 | regs.itt1) & MMU_TTR_BIT_ENABLED) != 0; + mmu_ttr_enabled_data = ((regs.dtt0 | regs.dtt1) & MMU_TTR_BIT_ENABLED) != 0; + mmu_ttr_enabled = mmu_ttr_enabled_ins || mmu_ttr_enabled_data; } @@ -314,14 +335,23 @@ void mmu_dump_tables(void) } /* }}} */ -static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, bool super, bool write, uae_u32 *status); +static void flush_shortcut_cache(void) +{ +#if MMU_IPAGECACHE + atc_last_ins_laddr = mmu_pagemask; +#endif +#if MMU_DPAGECACHE + memset(&atc_data_cache_read, 0xff, sizeof atc_data_cache_read); + memset(&atc_data_cache_write, 0xff, sizeof atc_data_cache_write); +#endif +} static ALWAYS_INLINE int mmu_get_fc(bool super, bool data) { return (super ? 4 : 0) | (data ? 1 : 2); } -void mmu_bus_error(uaecptr addr, int fc, bool write, int size, bool rmw, uae_u32 status, bool nonmmu) +void mmu_bus_error(uaecptr addr, uae_u32 val, int fc, bool write, int size, bool rmw, uae_u32 status, bool nonmmu) { if (currprefs.mmu_model == 68040) { uae_u16 ssw = 0; @@ -354,6 +384,7 @@ void mmu_bus_error(uaecptr addr, int fc, bool write, int size, bool rmw, uae_u32 } regs.wb3_status = write ? 0x80 | (ssw & 0x7f) : 0; + regs.wb3_data = val; regs.wb2_status = 0; if (!write) ssw |= MMU_SSW_RW; @@ -448,6 +479,7 @@ void mmu_bus_error(uaecptr addr, int fc, bool write, int size, bool rmw, uae_u32 } regs.mmu_fault_addr = addr; + flush_shortcut_cache(); #if 0 if (m68k_getpc () == 0x0004B0AC) { @@ -461,107 +493,86 @@ void mmu_bus_error(uaecptr addr, int fc, bool write, int size, bool rmw, uae_u32 THROW(2); } -void mmu_bus_error_ttr_write_fault(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool rmw) -{ - uae_u32 status = 0; - - if (currprefs.mmu_model == 68060) { - status |= MMU_FSLW_TTR; - } - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc (super, data), true, size, false, status, false); -} - - /* - * Update the atc line for a given address by doing a mmu lookup. + * mmu access is a 4 step process: + * if mmu is not enabled just read physical + * check transparent region, if transparent, read physical + * check ATC (address translation cache), read immediatly if HIT + * read from mmu with the long path (and allocate ATC entry if needed) */ -static uaecptr mmu_fill_atc(uaecptr addr, bool super, bool data, bool write, struct mmu_atc_line *l, uae_u32 *status) -{ - uae_u32 desc; - *status = 0; - SAVE_EXCEPTION; - TRY(prb) { - desc = mmu_lookup_pagetable(addr, super, write, status); -#if MMUDEBUG > 2 - write_log(_T("translate: %x,%u,%u,%u -> %x\n"), addr, super, write, data, desc); -#endif - RESTORE_EXCEPTION; - } - CATCH(prb) { - RESTORE_EXCEPTION; - /* bus error during table search */ - desc = 0; - *status = MMU_FSLW_TWE; - // goto fail; - } ENDTRY - if ((desc & 1) && (!super && desc & MMU_MMUSR_S)) { - *status |= MMU_FSLW_SP; -#if MMUDEBUG > 1 - write_log (_T("MMU: supervisor protected %x\n"), addr); -#endif - l->valid = 0; - l->global = 0; - } else if ((desc & 1) == 0) { - l->valid = 0; - l->global = 0; - } else { - l->valid = 1; - l->phys = desc & mmu_pagemaski; - l->global = (desc & MMU_MMUSR_G) != 0; - l->modified = (desc & MMU_MMUSR_M) != 0; - l->write_protect = (desc & MMU_MMUSR_W) != 0; +/* check if an address matches a ttr */ +static int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super) +{ + if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */ + uae_u8 msb, mask; + + msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24; + mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16; + + if (!(msb & ~mask)) { + + if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) { + if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) { + return TTR_NO_MATCH; + } + } + + return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH; + } } - - return desc; + return TTR_NO_MATCH; } -static ALWAYS_INLINE bool mmu_fill_atc_try(uaecptr addr, bool super, bool data, bool write, struct mmu_atc_line *l1, uae_u32 *status) +int mmu_match_ttr_ins(uaecptr addr, bool super) { - mmu_fill_atc(addr,super,data,write,l1, status); - if (!(l1->valid)) { -#if MMUDEBUG > 2 - write_log(_T("MMU: non-resident page (%x,%x)!\n"), addr, regs.pc); -#endif - goto fail; - } - if (write) { - if (l1->write_protect) { - *status |= MMU_FSLW_WP; -#if MMUDEBUG > 0 - write_log(_T("MMU: write protected %x by atc \n"), addr); -#endif - mmu_dump_atc(); - goto fail; - } + int res; + + if (!mmu_ttr_enabled_ins) + return TTR_NO_MATCH; + res = mmu_do_match_ttr(regs.itt0, addr, super); + if (res == TTR_NO_MATCH) + res = mmu_do_match_ttr(regs.itt1, addr, super); + return res; +} +int mmu_match_ttr(uaecptr addr, bool super, bool data) +{ + int res; + + if (!mmu_ttr_enabled) + return TTR_NO_MATCH; + if (data) { + res = mmu_do_match_ttr(regs.dtt0, addr, super); + if (res == TTR_NO_MATCH) + res = mmu_do_match_ttr(regs.dtt1, addr, super); + } else { + res = mmu_do_match_ttr(regs.itt0, addr, super); + if (res == TTR_NO_MATCH) + res = mmu_do_match_ttr(regs.itt1, addr, super); } - return true; + return res; +} -fail: - return false; +void mmu_bus_error_ttr_write_fault(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool rmw) + { + uae_u32 status = 0; + + if (currprefs.mmu_model == 68060) { + status |= MMU_FSLW_TTR; + } + mmu_bus_error(addr, val, mmu_get_fc (super, data), true, size, false, status, false); } -uaecptr REGPARAM2 mmu_translate(uaecptr addr, bool super, bool data, bool write) +int mmu_match_ttr_write(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool rmw) { - struct mmu_atc_line *l; - uae_u32 status = 0; - - // this should return a miss but choose a valid line - mmu_user_lookup(addr, super, data, write, &l); - - mmu_fill_atc(addr, super, data, write, l, &status); - if (!l->valid || (write && l->write_protect)) { -#if MMUDEBUG > 2 - write_log(_T("[MMU] mmu_translate error")); -#endif - mmu_bus_error(addr, mmu_get_fc(super, data), write, 0, false, status, false); - return 0; + int res = TTR_NO_MATCH; + if (mmu_ttr_enabled) { + res = mmu_match_ttr(addr, super, data); } - - return l->phys | (addr & mmu_pagemask); - + if (res == TTR_NO_WRITE || (res == TTR_NO_MATCH && !regs.mmu_enabled && (regs.tcr & MMU_TCR_DWO))) + mmu_bus_error_ttr_write_fault(addr, super, data, val, size, rmw); + return res; } /* @@ -573,92 +584,245 @@ static uaecptr REGPARAM2 mmu_lookup_pagetable(uaecptr addr, bool super, bool wri { uae_u32 desc, desc_addr, wp; int i; - + wp = 0; desc = super ? regs.srp : regs.urp; - + /* fetch root table descriptor */ i = (addr >> 23) & 0x1fc; desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; - desc = phys_get_long(desc_addr); - if ((desc & 2) == 0) { + + SAVE_EXCEPTION; + TRY(prb) { + desc = phys_get_long(desc_addr); + if ((desc & 2) == 0) { #if MMUDEBUG > 1 - write_log(_T("MMU: invalid root descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"), - addr, desc_addr, desc); + write_log(_T("MMU: invalid root descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"), + addr, desc_addr, desc); #endif - *status |= MMU_FSLW_PTA; - return 0; - } - - wp |= desc; - if ((desc & MMU_DES_USED) == 0) - phys_put_long(desc_addr, desc | MMU_DES_USED); - - /* fetch pointer table descriptor */ - i = (addr >> 16) & 0x1fc; - desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; - desc = phys_get_long(desc_addr); - if ((desc & 2) == 0) { + *status |= MMU_FSLW_PTA; + desc = 0; + goto fail; + } + + wp |= desc; + if ((desc & MMU_DES_USED) == 0) + phys_put_long(desc_addr, desc | MMU_DES_USED); + + /* fetch pointer table descriptor */ + i = (addr >> 16) & 0x1fc; + desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i; + desc = phys_get_long(desc_addr); + if ((desc & 2) == 0) { #if MMUDEBUG > 1 - write_log(_T("MMU: invalid ptr descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"), - addr, desc_addr, desc); + write_log(_T("MMU: invalid ptr descriptor %s for %x desc at %x desc=%x\n"), super ? _T("srp"):_T("urp"), + addr, desc_addr, desc); #endif - *status |= MMU_FSLW_PTB; - return 0; - } - wp |= desc; - if ((desc & MMU_DES_USED) == 0) - phys_put_long(desc_addr, desc | MMU_DES_USED); - - /* fetch page table descriptor */ - if (mmu_pagesize_8k) { - i = (addr >> 11) & 0x7c; - desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_8) + i; - } else { - i = (addr >> 10) & 0xfc; - desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) + i; - } - - desc = phys_get_long(desc_addr); - if ((desc & 3) == 2) { - /* indirect */ - desc_addr = desc & MMU_PAGE_INDIRECT_MASK; + *status |= MMU_FSLW_PTB; + desc = 0; + goto fail; + } + wp |= desc; + if ((desc & MMU_DES_USED) == 0) + phys_put_long(desc_addr, desc | MMU_DES_USED); + + /* fetch page table descriptor */ + if (mmu_pagesize_8k) { + i = (addr >> 11) & 0x7c; + desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_8) + i; + } else { + i = (addr >> 10) & 0xfc; + desc_addr = (desc & MMU_PTR_PAGE_ADDR_MASK_4) + i; + } + desc = phys_get_long(desc_addr); - } - if ((desc & 1) == 0) { + if ((desc & 3) == 2) { + /* indirect */ + desc_addr = desc & MMU_PAGE_INDIRECT_MASK; + desc = phys_get_long(desc_addr); + } + if ((desc & 1) == 0) { #if MMUDEBUG > 2 - write_log(_T("MMU: invalid page descriptor log=%0x desc=%08x @%08x\n"), addr, desc, desc_addr); + write_log(_T("MMU: invalid page descriptor log=%0x desc=%08x @%08x\n"), addr, desc, desc_addr); #endif - if ((desc & 3) == 2) { - *status |= MMU_FSLW_IL; + if ((desc & 3) == 2) { + *status |= MMU_FSLW_IL; #if MMUDEBUG > 1 - write_log(_T("MMU: double indirect descriptor log=%0x desc=%08x @%08x\n"), addr, desc, desc_addr); -#endif - } else { - *status |= MMU_FSLW_PF; + write_log(_T("MMU: double indirect descriptor log=%0x desc=%08x @%08x\n"), addr, desc, desc_addr); +#endif + } else { + *status |= MMU_FSLW_PF; + } + goto fail; } - return desc; - } - - desc |= wp & MMU_DES_WP; - if (write) { - if (desc & MMU_DES_WP) { + wp |= desc; + + if (write) { + if ((wp & MMU_DES_WP) || (!super && (desc & MMU_DES_SUPER))) { + // write protect or supervisor violation: MMU_DES_USED only + if ((desc & MMU_DES_USED) == 0) { + desc |= MMU_DES_USED; + phys_put_long(desc_addr, desc); + } + } else { + // write: MMU_DES_USED and MMU_DES_MODIFIED + if (((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) != (MMU_DES_USED|MMU_DES_MODIFIED))) { + desc |= MMU_DES_USED|MMU_DES_MODIFIED; + phys_put_long(desc_addr, desc); + } + } + } else { + // read: MMU_DES_USED only if ((desc & MMU_DES_USED) == 0) { desc |= MMU_DES_USED; phys_put_long(desc_addr, desc); } - } else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) != - (MMU_DES_USED|MMU_DES_MODIFIED)) { - desc |= MMU_DES_USED|MMU_DES_MODIFIED; - phys_put_long(desc_addr, desc); } + + desc |= wp & MMU_DES_WP; + + /* this will cause a bus error exception */ + if (!super && (desc & MMU_DES_SUPER)) { + *status |= MMU_FSLW_SP; + } else if (write && (desc & MMU_DES_WP)) { + *status |= MMU_FSLW_WP; + } + fail: + RESTORE_EXCEPTION; + } CATCH(prb) { + RESTORE_EXCEPTION; + /* bus error during table search */ + desc = 0; + *status = MMU_FSLW_TWE; +#if MMUDEBUG > 0 + write_log(_T("MMU: bus error during table search.\n")); +#endif + } ENDTRY + + return desc; +} + +/* + * Update the atc line for a given address by doing a mmu lookup. + */ +static bool mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, struct mmu_atc_line *l, uae_u32 *status) +{ + uae_u32 desc; + + *status = 0; + + desc = mmu_lookup_pagetable(addr, super, write, status); + +#if MMUDEBUG > 2 + write_log(_T("translate: %x,%u,%u -> %x\n"), addr, super, write, desc); +#endif + + l->valid = 1; + l->tag = tag; + if (desc & MMU_MMUSR_R) { + l->status = desc & (MMU_MMUSR_G|MMU_MMUSR_Ux|MMU_MMUSR_S|MMU_MMUSR_CM|MMU_MMUSR_M|MMU_MMUSR_W|MMU_MMUSR_R); + l->phys = desc & mmu_pagemaski; } else { - if ((desc & MMU_DES_USED) == 0) { - desc |= MMU_DES_USED; - phys_put_long(desc_addr, desc); + // Fault while looking page table: + // 68040: = Create resident ATC entry + // 68060: = Do not create ATC entry + if (currprefs.cpu_model == 68060) + l->valid = 0; + l->status = 0; + l->phys = 0; + } + + return (*status != MMU_FSLW_TWE); // FIXME: find a better way to report bus error during table search +} + +uaecptr mmu_translate(uaecptr addr, uae_u32 val, bool super, bool data, bool write, int size, bool rmw) +{ + int way, i, index, way_invalid; + struct mmu_atc_line *l; + uae_u32 status = 0; + uae_u32 tag = ((super ? 0x80000000 : 0x00000000) | (addr >> 1)) & mmu_tagmask; + + if (mmu_pagesize_8k) + index=(addr & 0x0001E000)>>13; + else + index=(addr & 0x0000F000)>>12; + way_invalid = ATC_WAYS; + way_random++; + + for (i = 0; i < ATC_WAYS; i++) { + way = mmu_atc_ways; + // if we have this + l = &mmu_atc_array[data][index][way]; + if (l->valid && tag == l->tag) { +atc_retry: + // check if we need to cause a page fault + if (((l->status&(MMU_MMUSR_W|MMU_MMUSR_S|MMU_MMUSR_R))!=MMU_MMUSR_R)) { + if (((l->status&MMU_MMUSR_W) && write) || + ((l->status&MMU_MMUSR_S) && !super) || + !(l->status&MMU_MMUSR_R)) { + + if ((l->status&MMU_MMUSR_S) && !super) + status |= MMU_FSLW_SP; + if ((l->status&MMU_MMUSR_W) && write) + status |= MMU_FSLW_WP; + + mmu_bus_error(addr, val, mmu_get_fc(super, data), write, size, rmw, status, false); + return 0; // never reach, bus error longjumps out of the function + } + } + // if first write to this page initiate table search to set M bit (but modify this slot) + if (!(l->status&MMU_MMUSR_M) && write) { + way_invalid = way; + break; + } +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); +#endif + if (!data) { +#if MMU_IPAGECACHE + uae_u32 laddr = (addr & mmu_pagemaski) | (super ? 1 : 0); + atc_last_ins_laddr = laddr; + atc_last_ins_paddr = l->phys; +#else + ; +#endif +#if MMU_DPAGECACHE + } else if (write) { + if (idx2 < MMUFASTCACHE_ENTRIES - 1) { + atc_data_cache_write[idx2].log = idx1; + atc_data_cache_write[idx2].phys = l->phys; + } + } else { + if (idx2 < MMUFASTCACHE_ENTRIES - 1) { + atc_data_cache_read[idx2].log = idx1; + atc_data_cache_read[idx2].phys = l->phys; + } +#endif + } + // return translated addr + return l->phys | (addr & mmu_pagemask); + } else { + way_invalid = way; } + mmu_atc_ways++; + mmu_atc_ways %= ATC_WAYS; } - return desc; + // no entry found, we need to create a new one, first find an atc line to replace + way_random %= ATC_WAYS; + mmu_atc_ways = (way_invalid < ATC_WAYS) ? way_invalid : way_random; + way = mmu_atc_ways; + + // then initiate table search and create a new entry + l = &mmu_atc_array[data][index][way]; + mmu_fill_atc(addr, super, tag, write, l, &status); + + // and retry the ATC search + way_random++; + goto atc_retry; + + // never reach + return 0; } static void misalignednotfirst(uaecptr addr) @@ -752,10 +916,10 @@ static uae_u16 REGPARAM2 mmu_get_lrmw_word_unaligned(uaecptr addr) { uae_u16 res; - res = (uae_u16)mmu_get_user_byte(addr, regs.s != 0, true, true, sz_word) << 8; + res = (uae_u16)mmu_get_user_byte(addr, regs.s != 0, true, sz_word) << 8; SAVE_EXCEPTION; TRY(prb) { - res |= mmu_get_user_byte(addr + 1, regs.s != 0, true, true, sz_word); + res |= mmu_get_user_byte(addr + 1, regs.s != 0, true, sz_word); RESTORE_EXCEPTION; } CATCH(prb) { @@ -771,10 +935,10 @@ static uae_u32 REGPARAM2 mmu_get_lrmw_long_unaligned(uaecptr addr) uae_u32 res; if (likely(!(addr & 1))) { - res = (uae_u32)mmu_get_user_word(addr, regs.s != 0, true, true, sz_long) << 16; + res = (uae_u32)mmu_get_user_word(addr, regs.s != 0, true, sz_long) << 16; SAVE_EXCEPTION; TRY(prb) { - res |= mmu_get_user_word(addr + 2, regs.s != 0, true, true, sz_long); + res |= mmu_get_user_word(addr + 2, regs.s != 0, true, sz_long); RESTORE_EXCEPTION; } CATCH(prb) { @@ -783,12 +947,12 @@ static uae_u32 REGPARAM2 mmu_get_lrmw_long_unaligned(uaecptr addr) THROW_AGAIN(prb); } ENDTRY } else { - res = (uae_u32)mmu_get_user_byte(addr, regs.s != 0, true, true, sz_long) << 8; + res = (uae_u32)mmu_get_user_byte(addr, regs.s != 0, true, sz_long) << 8; SAVE_EXCEPTION; TRY(prb) { - res = (res | mmu_get_user_byte(addr + 1, regs.s != 0, true, true, sz_long)) << 8; - res = (res | mmu_get_user_byte(addr + 2, regs.s != 0, true, true, sz_long)) << 8; - res |= mmu_get_user_byte(addr + 3, regs.s != 0, true, true, sz_long); + res = (res | mmu_get_user_byte(addr + 1, regs.s != 0, true, sz_long)) << 8; + res = (res | mmu_get_user_byte(addr + 2, regs.s != 0, true, sz_long)) << 8; + res |= mmu_get_user_byte(addr + 3, regs.s != 0, true, sz_long); RESTORE_EXCEPTION; } CATCH(prb) { @@ -799,58 +963,6 @@ static uae_u32 REGPARAM2 mmu_get_lrmw_long_unaligned(uaecptr addr) } return res; } -uae_u8 REGPARAM2 mmu_get_byte_slow(uaecptr addr, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) -{ - uae_u32 status; - if (!mmu_fill_atc_try(addr, super, data, 0, cl, &status)) { - mmu_bus_error(addr, mmu_get_fc(super, data), 0, size, rmw, status, false); - return 0; - } - return x_phys_get_byte(mmu_get_real_address(addr, cl)); -} - -uae_u16 REGPARAM2 mmu_get_word_slow(uaecptr addr, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) -{ - uae_u32 status; - if (!mmu_fill_atc_try(addr, super, data, 0, cl, &status)) { - mmu_bus_error(addr, mmu_get_fc(super, data), 0, size, rmw, status, false); - return 0; - } - return x_phys_get_word(mmu_get_real_address(addr, cl)); -} -uae_u16 REGPARAM2 mmu_get_iword_slow(uaecptr addr, bool super, - int size, struct mmu_atc_line *cl) -{ - uae_u32 status; - if (!mmu_fill_atc_try(addr, super, false, 0, cl, &status)) { - mmu_bus_error(addr, mmu_get_fc(super, false), 0, size, false, status, false); - return 0; - } - return x_phys_get_iword(mmu_get_real_address(addr, cl)); -} - -uae_u32 REGPARAM2 mmu_get_long_slow(uaecptr addr, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) -{ - uae_u32 status; - if (!mmu_fill_atc_try(addr, super, data, 0, cl, &status)) { - mmu_bus_error(addr, mmu_get_fc(super, data), 0, size, rmw, status, false); - return 0; - } - return x_phys_get_long(mmu_get_real_address(addr, cl)); -} -uae_u32 REGPARAM2 mmu_get_ilong_slow(uaecptr addr, bool super, - int size, struct mmu_atc_line *cl) -{ - uae_u32 status; - if (!mmu_fill_atc_try(addr, super, false, 0, cl, &status)) { - mmu_bus_error(addr, mmu_get_fc(super, false), 0, size, false, status, false); - return 0; - } - return x_phys_get_ilong(mmu_get_real_address(addr, cl)); -} void REGPARAM2 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data, bool rmw) { @@ -891,57 +1003,20 @@ void REGPARAM2 mmu_put_word_unaligned(uaecptr addr, uae_u16 val, bool data, bool } ENDTRY } -void REGPARAM2 mmu_put_byte_slow(uaecptr addr, uae_u8 val, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) -{ - uae_u32 status; - if (!mmu_fill_atc_try(addr, super, data, 1, cl, &status)) { - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc(super, data), 1, size, rmw, status, false); - return; - } - x_phys_put_byte(mmu_get_real_address(addr, cl), val); -} - -void REGPARAM2 mmu_put_word_slow(uaecptr addr, uae_u16 val, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) -{ - uae_u32 status; - if (!mmu_fill_atc_try(addr, super, data, 1, cl, &status)) { - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc(super, data), 1, size, rmw, status, false); - return; - } - x_phys_put_word(mmu_get_real_address(addr, cl), val); -} - -void REGPARAM2 mmu_put_long_slow(uaecptr addr, uae_u32 val, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) -{ - uae_u32 status; - if (!mmu_fill_atc_try(addr, super, data, 1, cl, &status)) { - regs.wb3_data = val; - mmu_bus_error(addr, mmu_get_fc(super, data), 1, size, rmw, status, false); - return; - } - x_phys_put_long(mmu_get_real_address(addr, cl), val); -} - uae_u32 REGPARAM2 sfc_get_long(uaecptr addr) { bool super = (regs.sfc & 4) != 0; - bool data = true; uae_u32 res; ismoves = true; if (likely(!is_unaligned(addr, 4))) { - res = mmu_get_user_long(addr, super, data, false, sz_long); + res = mmu_get_user_long(addr, super, false, sz_long); } else { if (likely(!(addr & 1))) { - res = (uae_u32)mmu_get_user_word(addr, super, data, false, sz_long) << 16; + res = (uae_u32)mmu_get_user_word(addr, super, false, sz_long) << 16; SAVE_EXCEPTION; TRY(prb) { - res |= mmu_get_user_word(addr + 2, super, data, false, sz_long); + res |= mmu_get_user_word(addr + 2, super, false, sz_long); RESTORE_EXCEPTION; } CATCH(prb) { @@ -950,12 +1025,12 @@ uae_u32 REGPARAM2 sfc_get_long(uaecptr addr) THROW_AGAIN(prb); } ENDTRY } else { - res = (uae_u32)mmu_get_user_byte(addr, super, data, false, sz_long) << 8; + res = (uae_u32)mmu_get_user_byte(addr, super, false, sz_long) << 8; SAVE_EXCEPTION; TRY(prb) { - res = (res | mmu_get_user_byte(addr + 1, super, data, false, sz_long)) << 8; - res = (res | mmu_get_user_byte(addr + 2, super, data, false, sz_long)) << 8; - res |= mmu_get_user_byte(addr + 3, super, data, false, sz_long); + res = (res | mmu_get_user_byte(addr + 1, super, false, sz_long)) << 8; + res = (res | mmu_get_user_byte(addr + 2, super, false, sz_long)) << 8; + res |= mmu_get_user_byte(addr + 3, super, false, sz_long); RESTORE_EXCEPTION; } CATCH(prb) { @@ -973,17 +1048,16 @@ uae_u32 REGPARAM2 sfc_get_long(uaecptr addr) uae_u16 REGPARAM2 sfc_get_word(uaecptr addr) { bool super = (regs.sfc & 4) != 0; - bool data = true; uae_u16 res; ismoves = true; if (likely(!is_unaligned(addr, 2))) { - res = mmu_get_user_word(addr, super, data, false, sz_word); + res = mmu_get_user_word(addr, super, false, sz_word); } else { - res = (uae_u16)mmu_get_user_byte(addr, super, data, false, sz_word) << 8; + res = (uae_u16)mmu_get_user_byte(addr, super, false, sz_word) << 8; SAVE_EXCEPTION; TRY(prb) { - res |= mmu_get_user_byte(addr + 1, super, data, false, sz_word); + res |= mmu_get_user_byte(addr + 1, super, false, sz_word); RESTORE_EXCEPTION; } CATCH(prb) { @@ -999,11 +1073,10 @@ uae_u16 REGPARAM2 sfc_get_word(uaecptr addr) uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr) { bool super = (regs.sfc & 4) != 0; - bool data = true; uae_u8 res; ismoves = true; - res = mmu_get_user_byte(addr, super, data, false, sz_byte); + res = mmu_get_user_byte(addr, super, false, sz_byte); ismoves = false; return res; } @@ -1011,21 +1084,20 @@ uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr) void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val) { bool super = (regs.dfc & 4) != 0; - bool data = true; ismoves = true; SAVE_EXCEPTION; TRY(prb) { - if (likely(!is_unaligned(addr, 4))) - mmu_put_user_long(addr, val, super, data, sz_long); - else if (likely(!(addr & 1))) { - mmu_put_user_word(addr, val >> 16, super, data, sz_long); - mmu_put_user_word(addr + 2, val, super, data, sz_long); + if (likely(!is_unaligned(addr, 4))) { + mmu_put_user_long(addr, val, super, sz_long); + } else if (likely(!(addr & 1))) { + mmu_put_user_word(addr, val >> 16, super, sz_long); + mmu_put_user_word(addr + 2, val, super, sz_long); } else { - mmu_put_user_byte(addr, val >> 24, super, data, sz_long); - mmu_put_user_byte(addr + 1, val >> 16, super, data, sz_long); - mmu_put_user_byte(addr + 2, val >> 8, super, data, sz_long); - mmu_put_user_byte(addr + 3, val, super, data, sz_long); + mmu_put_user_byte(addr, val >> 24, super, sz_long); + mmu_put_user_byte(addr + 1, val >> 16, super, sz_long); + mmu_put_user_byte(addr + 2, val >> 8, super, sz_long); + mmu_put_user_byte(addr + 3, val, super, sz_long); } RESTORE_EXCEPTION; } @@ -1041,16 +1113,15 @@ void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val) void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val) { bool super = (regs.dfc & 4) != 0; - bool data = true; ismoves = true; SAVE_EXCEPTION; TRY(prb) { - if (likely(!is_unaligned(addr, 2))) - mmu_put_user_word(addr, val, super, data, sz_word); - else { - mmu_put_user_byte(addr, val >> 8, super, data, sz_word); - mmu_put_user_byte(addr + 1, val, super, data, sz_word); + if (likely(!is_unaligned(addr, 2))) { + mmu_put_user_word(addr, val, super, sz_word); + } else { + mmu_put_user_byte(addr, val >> 8, super, sz_word); + mmu_put_user_byte(addr + 1, val, super, sz_word); } RESTORE_EXCEPTION; } @@ -1066,12 +1137,11 @@ void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val) void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val) { bool super = (regs.dfc & 4) != 0; - bool data = true; ismoves = true; SAVE_EXCEPTION; TRY(prb) { - mmu_put_user_byte(addr, val, super, data, sz_byte); + mmu_put_user_byte(addr, val, super, sz_byte); RESTORE_EXCEPTION; } CATCH(prb) { @@ -1084,33 +1154,27 @@ void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val) void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size) { - struct mmu_atc_line *cl; + bool super = regs.s != 0; + addr &= ~15; + if ((!mmu_ttr_enabled || mmu_match_ttr(addr,super,data) == TTR_NO_MATCH) && regs.mmu_enabled) { + addr = mmu_translate(addr, 0, super, data, false, size, false); + } for (int i = 0; i < 4; i++) { - uaecptr addr2 = addr + i * 4; - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr2,regs.s != 0,data,false)!=TTR_NO_MATCH)) - v[i] = x_phys_get_long(addr2); - else if (likely(mmu_lookup(addr2, data, false, &cl))) - v[i] = x_phys_get_long(mmu_get_real_address(addr2, cl)); - else - v[i] = mmu_get_long_slow(addr2, regs.s != 0, data, size, false, cl); + v[i] = phys_get_long(addr + i * 4); } } void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size) { - struct mmu_atc_line *cl; + bool super = regs.s != 0; + addr &= ~15; + if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,super,data,val[0],size,false) == TTR_NO_MATCH) && regs.mmu_enabled) { + addr = mmu_translate(addr, val[0], super, data, true, size, false); + } for (int i = 0; i < 4; i++) { - uaecptr addr2 = addr + i * 4; - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr2,regs.s != 0,data,val[i],size,false)==TTR_OK_MATCH)) - x_phys_put_long(addr2,val[i]); - else if (likely(mmu_lookup(addr2, data, true, &cl))) - x_phys_put_long(mmu_get_real_address(addr2, cl), val[i]); - else - mmu_put_long_slow(addr2, val[i], regs.s != 0, data, size, false, cl); + phys_put_long(addr + i * 4, val[i]); } } @@ -1155,46 +1219,67 @@ void REGPARAM2 mmu_op_real(uae_u32 opcode, uae_u16 extra) #if MMUINSDEBUG > 0 write_log(_T("PTEST%c (A%d) %08x DFC=%d\n"), write ? 'W' : 'R', regno, addr, regs.dfc); #endif - mmu_flush_atc(addr, super, true); - SAVE_EXCEPTION; - TRY(prb) { - struct mmu_atc_line *l; - uae_u32 desc; - bool data = (regs.dfc & 3) != 2; + if (!currprefs.mmu_ec) { + mmu_flush_atc(addr, super, true); + SAVE_EXCEPTION; + TRY(prb) { + struct mmu_atc_line *l; + bool data = (regs.dfc & 3) != 2; - if (mmu_match_ttr(addr,super,data, false)!=TTR_NO_MATCH) { - regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R; - } else { - uae_u32 status; - mmu_user_lookup(addr, super, data, write, &l); - desc = mmu_fill_atc(addr, super, data, write, l, &status); - if (!(l->valid)) { - regs.mmusr = MMU_MMUSR_B; + if (mmu_match_ttr(addr,super,data)!=TTR_NO_MATCH) { + regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R; } else { - regs.mmusr = desc & (~0xfff|MMU_MMUSR_G|MMU_MMUSR_Ux|MMU_MMUSR_S| - MMU_MMUSR_CM|MMU_MMUSR_M|MMU_MMUSR_W); - regs.mmusr |= MMU_MMUSR_R; + int way; + uae_u32 index; + uae_u32 status; + uae_u32 tag = ((super ? 0x80000000 : 0x00000000) | (addr >> 1)) & mmu_tagmask; + if (mmu_pagesize_8k) + index=(addr & 0x0001E000)>>13; + else + index=(addr & 0x0000F000)>>12; + + for (way = 0; way < ATC_WAYS; way++) { + if (!mmu_atc_array[data][index][way].valid) + break; + } + if (way >= ATC_WAYS) { + way = way_random % ATC_WAYS; + } + l=&mmu_atc_array[data][index][way]; + + if (mmu_fill_atc(addr, super, tag, write, l, &status)) { + regs.mmusr = l->phys | l->status; + } else { + regs.mmusr = MMU_MMUSR_B; + } } } - } - CATCH(prb) { - regs.mmusr = MMU_MMUSR_B; - } ENDTRY - RESTORE_EXCEPTION; + CATCH(prb) { + regs.mmusr = MMU_MMUSR_B; + } ENDTRY + RESTORE_EXCEPTION; #if MMUINSDEBUG > 0 - write_log(_T("PTEST result: mmusr %08x\n"), regs.mmusr); + write_log(_T("PTEST result: mmusr %08x\n"), regs.mmusr); #endif + } } else if ((opcode & 0xFFB8) == 0xF588) { // PLPA (68060) int write = (opcode & 0x40) == 0; int regno = opcode & 7; uae_u32 addr = m68k_areg (regs, regno); bool data = (regs.dfc & 3) != 2; + int ttr; #if MMUINSDEBUG > 0 write_log(_T("PLPA%c param: %08x\n"), write ? 'W' : 'R', addr); #endif - if (mmu_match_ttr(addr,super,data,false)==TTR_NO_MATCH) { - m68k_areg (regs, regno) = mmu_translate (addr, super, data, write != 0); + if (write) + ttr = mmu_match_ttr_write(addr, super, data, 0, 1, false); + else + ttr = mmu_match_ttr(addr,super,data); + if (ttr == TTR_NO_MATCH) { + if (!currprefs.mmu_ec) { + m68k_areg (regs, regno) = mmu_translate(addr, 0, super, data, write, 1, false); + } } #if MMUINSDEBUG > 0 write_log(_T("PLPA%c result: %08x\n"), write ? 'W' : 'R', m68k_areg (regs, regno)); @@ -1216,28 +1301,34 @@ void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global) index=(addr & 0x0000F000)>>12; for (type=0;typestatus & MMU_MMUSR_G)) continue; // if we have this - if ((tag == mmu_atc_array[type][way][index].tag) && (mmu_atc_array[type][way][index].valid)) { - mmu_atc_array[type][way][index].valid=false; + if (tag == l->tag && l->valid) { + l->valid=false; } } } + flush_shortcut_cache(); + mmu_flush_cache(); } void REGPARAM2 mmu_flush_atc_all(bool global) { - unsigned int way,slot,type; + int way,slot,type; for (type=0;typestatus&MMU_MMUSR_G)) continue; - mmu_atc_array[type][way][slot].valid=false; + l->valid=false; } } } + flush_shortcut_cache(); + mmu_flush_cache(); } void REGPARAM2 mmu_set_funcs(void) @@ -1273,12 +1364,18 @@ void REGPARAM2 mmu_reset(void) void REGPARAM2 mmu_set_tc(uae_u16 tc) { + if (currprefs.mmu_ec) + tc &= ~(0x8000 | 0x4000); + regs.mmu_enabled = (tc & 0x8000) != 0; mmu_pagesize_8k = (tc & 0x4000) != 0; + mmu_tagmask = mmu_pagesize_8k ? 0xFFFF0000 : 0xFFFF8000; mmu_pagemask = mmu_pagesize_8k ? 0x00001FFF : 0x00000FFF; mmu_pagemaski = ~mmu_pagemask; regs.mmu_page_size = mmu_pagesize_8k ? 8192 : 4096; + mmu_pageshift = mmu_pagesize_8k ? 13 : 12; + mmu_pageshift1m = mmu_pageshift - 1; mmu_flush_atc_all(true); @@ -1294,6 +1391,14 @@ void REGPARAM2 mmu_set_super(bool super) mmu_is_super = super ? 0x80000000 : 0; } +void REGPARAM2 mmu_flush_cache(void) +{ +#if MMU_ICACHE + int len = sizeof(mmu_icache_data); + memset(&mmu_icache_data, 0xff, sizeof(mmu_icache_data)); +#endif +} + void m68k_do_rte_mmu040 (uaecptr a7) { uae_u16 ssr = get_word_mmu040 (a7 + 8 + 4); @@ -1323,7 +1428,9 @@ void m68k_do_rte_mmu060 (uaecptr a7) void flush_mmu040 (uaecptr addr, int n) { + mmu_flush_cache(); } + void m68k_do_rts_mmu040 (void) { uaecptr stack = m68k_areg (regs, 7); @@ -1341,7 +1448,9 @@ void m68k_do_bsr_mmu040 (uaecptr oldpc, uae_s32 offset) void flush_mmu060 (uaecptr addr, int n) { + mmu_flush_cache(); } + void m68k_do_rts_mmu060 (void) { uaecptr stack = m68k_areg (regs, 7); @@ -1381,18 +1490,18 @@ uae_u32 uae_mmu_get_lrmw (uaecptr addr, int size, int type) uae_u32 v; locked_rmw_cycle = true; if (size == sz_byte) { - v = mmu_get_user_byte(addr, regs.s != 0, true, true, sz_byte); + v = mmu_get_user_byte(addr, regs.s != 0, true, sz_byte); } else if (size == sz_word) { if (unlikely(is_unaligned(addr, 2))) { v = mmu_get_lrmw_word_unaligned(addr); } else { - v = mmu_get_user_word(addr, regs.s != 0, true, true, sz_word); + v = mmu_get_user_word(addr, regs.s != 0, true, sz_word); } } else { if (unlikely(is_unaligned(addr, 4))) v = mmu_get_lrmw_long_unaligned(addr); else - v = mmu_get_user_long(addr, regs.s != 0, true, true, sz_long); + v = mmu_get_user_long(addr, regs.s != 0, true, sz_long); } locked_rmw_cycle = false; return v; @@ -1481,16 +1590,16 @@ static int s_try_stack_size=0; static jmp_buf s_try_stack[MAX_TRY_STACK]; jmp_buf* __poptry(void) { if (s_try_stack_size>0) { - s_try_stack_size--; - if (s_try_stack_size == 0) - return NULL; - memcpy(&__exbuf,&s_try_stack[s_try_stack_size-1],sizeof(jmp_buf)); - // fprintf(stderr,"pop jmpbuf=%08x\n",s_try_stack[s_try_stack_size][0]); - return &s_try_stack[s_try_stack_size-1]; - } + s_try_stack_size--; + if (s_try_stack_size == 0) + return NULL; + memcpy(&__exbuf,&s_try_stack[s_try_stack_size-1],sizeof(jmp_buf)); + // fprintf(stderr,"pop jmpbuf=%08x\n",s_try_stack[s_try_stack_size][0]); + return &s_try_stack[s_try_stack_size-1]; + } else { fprintf(stderr,"try stack underflow...\n"); - // return (NULL); + // return (NULL); abort(); } } diff --git a/cpummu30.cpp b/cpummu30.cpp index 06a36e1c..aeeeddb7 100644 --- a/cpummu30.cpp +++ b/cpummu30.cpp @@ -70,6 +70,17 @@ uae_u32 mmu030_disp_store[2]; uae_u32 mmu030_fmovem_store[2]; struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS]; +#if MMU_DPAGECACHE030 +#define MMUFASTCACHE_ENTRIES 256 +struct mmufastcache +{ + uae_u32 log; + uae_u32 phys; +}; +extern struct mmufastcache atc_data_cache_read[MMUFASTCACHE_ENTRIES]; +extern struct mmufastcache atc_data_cache_write[MMUFASTCACHE_ENTRIES]; +#endif + /* for debugging messages */ char table_letter[4] = {'A','B','C','D'}; @@ -112,7 +123,8 @@ static struct { struct { uae_u32 mask; uae_u32 imask; - uae_u8 size; + uae_u32 size; + uae_u32 size1m; } page; uae_u8 init_shift; @@ -132,15 +144,17 @@ static struct { bool enabled; uae_u16 status; - /* Last access cache */ - uae_u32 mmu030_last_fc; +#if MMU_IPAGECACHE030 +#if MMU_DIRECT_ACCESS + uae_u8 *mmu030_last_physical_address_real; +#else uae_u32 mmu030_last_physical_address; +#endif uae_u32 mmu030_last_logical_address; +#endif } mmu030; - - /* MMU Status Register * * ---x ---x x-xx x--- @@ -181,7 +195,79 @@ static struct { #define MMUSR_TRANSP_ACCESS 0x0040 #define MMUSR_NUM_LEVELS_MASK 0x0007 +/* -- ATC flushing functions -- */ + +static void mmu030_flush_cache(void) +{ +#if MMU_IPAGECACHE030 + mmu030.mmu030_last_logical_address = 0xffffffff; +#endif +#if MMU_DPAGECACHE030 + memset(&atc_data_cache_read, 0xff, sizeof atc_data_cache_read); + memset(&atc_data_cache_write, 0xff, sizeof atc_data_cache_write); +#endif +} + +/* This function flushes ATC entries depending on their function code */ +static void mmu030_flush_atc_fc(uae_u32 fc_base, uae_u32 fc_mask) { + int i; + for (i=0; i> 20; + mmu030.translation.page.size1m = mmu030.translation.page.size - 3; mmu030.translation.init_shift = (TC & TC_IS_MASK) >> 16; regs.mmu_page_size = 1 << mmu030.translation.page.size; @@ -934,7 +961,24 @@ bool mmu030_decode_rp(uae_u64 RP) { #endif } - +static void mmu030_atc_handle_history_bit(int entry_num) { + int j; + mmu030.atc[entry_num].mru = 1; + for (j=0; j> mmu030.translation.page.size1m) | fc; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (idx2 < MMUFASTCACHE_ENTRIES - 1) { + atc_data_cache_read[idx2].log = idx1; + atc_data_cache_read[idx2].phys = phys; + } #endif - physical_addr += page_index; - - if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) { - mmu030_page_fault(addr, false, MMU030_SSW_SIZE_L, fc); - return; - } - - x_phys_put_long(physical_addr, val); } -void mmu030_put_word_atc(uaecptr addr, uae_u16 val, int l, uae_u32 fc) { - uae_u32 page_index = addr & mmu030.translation.page.mask; - uae_u32 addr_mask = mmu030.translation.page.imask; - - uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask; -#if MMU030_ATC_DBG_MSG - write_log(_T("ATC match(%i): page addr = %08X, index = %08X (wput %04X)\n"), - l, physical_addr, page_index, val); +static void mmu030_add_data_write_cache(uaecptr addr, uaecptr phys, uae_u32 fc) +{ +#if MMU_DPAGECACHE030 + uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size1m) | fc; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (idx2 < MMUFASTCACHE_ENTRIES - 1) { + atc_data_cache_write[idx2].log = idx1; + atc_data_cache_write[idx2].phys = phys; + } #endif - physical_addr += page_index; - - if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) { - mmu030_page_fault(addr, false, MMU030_SSW_SIZE_W, fc); - return; - } - - x_phys_put_word(physical_addr, val); } -void mmu030_put_byte_atc(uaecptr addr, uae_u8 val, int l, uae_u32 fc) { +static uaecptr mmu030_put_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) { uae_u32 page_index = addr & mmu030.translation.page.mask; uae_u32 addr_mask = mmu030.translation.page.imask; - uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask; + #if MMU030_ATC_DBG_MSG - write_log(_T("ATC match(%i): page addr = %08X, index = %08X (bput %02X)\n"), - l, physical_addr, page_index, val); + write_log(_T("ATC match(%i): page addr = %08X, index = %08X\n"), + l, physical_addr, page_index); #endif - physical_addr += page_index; if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) { mmu030_page_fault(addr, false, MMU030_SSW_SIZE_B, fc); - return; - } - - x_phys_put_byte(physical_addr, val); -} - -uae_u32 mmu030_get_long_atc(uaecptr addr, int l, uae_u32 fc) { - uae_u32 page_index = addr & mmu030.translation.page.mask; - uae_u32 addr_mask = mmu030.translation.page.imask; - - uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask; -#if MMU030_ATC_DBG_MSG - write_log(_T("ATC match(%i): page addr = %08X, index = %08X (lget %08X)\n"), l, - physical_addr, page_index, phys_get_long(physical_addr+page_index)); -#endif - physical_addr += page_index; - - if (mmu030.atc[l].physical.bus_error) { - mmu030_page_fault(addr, true, MMU030_SSW_SIZE_L, fc); return 0; } - return x_phys_get_long(physical_addr); -} - -static uae_u32 mmu030_get_ilong_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 *phys) { - uae_u32 page_index = addr & mmu030.translation.page.mask; - uae_u32 addr_mask = mmu030.translation.page.imask; - - uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask; - *phys = physical_addr; -#if MMU030_ATC_DBG_MSG - write_log(_T("ATC match(%i): page addr = %08X, index = %08X (lget %08X)\n"), l, - physical_addr, page_index, phys_get_long(physical_addr + page_index)); -#endif - physical_addr += page_index; - - if (mmu030.atc[l].physical.bus_error) { - mmu030_page_fault(addr, true, MMU030_SSW_SIZE_L, fc); - return 0; - } + mmu030_add_data_write_cache(addr, physical_addr, fc); - return x_phys_get_ilong(physical_addr); + return physical_addr + page_index; } -uae_u16 mmu030_get_word_atc(uaecptr addr, int l, uae_u32 fc) { +static uaecptr mmu030_get_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) { uae_u32 page_index = addr & mmu030.translation.page.mask; uae_u32 addr_mask = mmu030.translation.page.imask; - uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask; + #if MMU030_ATC_DBG_MSG - write_log(_T("ATC match(%i): page addr = %08X, index = %08X (wget %04X)\n"), l, - physical_addr, page_index, phys_get_word(physical_addr+page_index)); + write_log(_T("ATC match(%i): page addr = %08X, index = %08X\n"), l, + physical_addr, page_index); #endif - physical_addr += page_index; - + if (mmu030.atc[l].physical.bus_error) { - mmu030_page_fault(addr, true, MMU030_SSW_SIZE_W, fc); + mmu030_page_fault(addr, true, size, fc); return 0; } - - return x_phys_get_word(physical_addr); + + mmu030_add_data_read_cache(addr, physical_addr, fc); + + return physical_addr + page_index; } -static uae_u16 mmu030_get_iword_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 *phys) { +static uaecptr mmu030_get_i_atc(uaecptr addr, int l, uae_u32 fc, uae_u32 size) { uae_u32 page_index = addr & mmu030.translation.page.mask; uae_u32 addr_mask = mmu030.translation.page.imask; - uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask; + #if MMU030_ATC_DBG_MSG - write_log(_T("ATC match(%i): page addr = %08X, index = %08X (wget %04X)\n"), l, - physical_addr, page_index, phys_get_word(physical_addr + page_index)); + write_log(_T("ATC match(%i): page addr = %08X, index = %08X\n"), l, + physical_addr, page_index); #endif - *phys = physical_addr; - physical_addr += page_index; if (mmu030.atc[l].physical.bus_error) { - mmu030_page_fault(addr, true, MMU030_SSW_SIZE_W, fc); + mmu030_page_fault(addr, true, size, fc); return 0; } - return x_phys_get_iword(physical_addr); -} - -uae_u8 mmu030_get_byte_atc(uaecptr addr, int l, uae_u32 fc) { - uae_u32 page_index = addr & mmu030.translation.page.mask; - uae_u32 addr_mask = mmu030.translation.page.imask; - - uae_u32 physical_addr = mmu030.atc[l].physical.addr&addr_mask; -#if MMU030_ATC_DBG_MSG - write_log(_T("ATC match(%i): page addr = %08X, index = %08X (bget %02X)\n"), l, - physical_addr, page_index, phys_get_byte(physical_addr+page_index)); +#if MMU_IPAGECACHE030 +#if MMU_DIRECT_ACCESS + mmu030.mmu030_last_physical_address_real = get_real_address(physical_addr); +#else + mmu030.mmu030_last_physical_address = physical_addr; +#endif + mmu030.mmu030_last_logical_address = (addr & mmu030.translation.page.imask) | fc; #endif - physical_addr += page_index; - - if (mmu030.atc[l].physical.bus_error) { - mmu030_page_fault(addr, true, MMU030_SSW_SIZE_B, fc); - return 0; - } - return x_phys_get_byte(physical_addr); + return physical_addr + page_index; } /* Generic versions of above */ -void mmu030_put_atc_generic(uaecptr addr, uae_u32 val, int l, uae_u32 fc, int size, int flags) { +static uaecptr mmu030_put_atc_generic(uaecptr addr, int l, uae_u32 fc, int flags) { uae_u32 page_index = addr & mmu030.translation.page.mask; uae_u32 addr_mask = mmu030.translation.page.imask; - uae_u32 physical_addr = mmu030.atc[l].physical.addr & addr_mask; + #if MMU030_ATC_DBG_MSG write_log(_T("ATC match(%i): page addr = %08X, index = %08X (bput %02X)\n"), l, physical_addr, page_index, val); #endif - physical_addr += page_index; if (mmu030.atc[l].physical.write_protect || mmu030.atc[l].physical.bus_error) { mmu030_page_fault(addr, false, flags, fc); - return; + return 0; } - if (size == sz_byte) - x_phys_put_byte(physical_addr, val); - else if (size == sz_word) - x_phys_put_word(physical_addr, val); - else - x_phys_put_long(physical_addr, val); + mmu030_add_data_write_cache(addr, physical_addr, fc); + + return physical_addr + page_index; } -uae_u32 mmu030_get_atc_generic(uaecptr addr, int l, uae_u32 fc, int size, int flags, bool checkwrite) { +uae_u32 mmu030_get_atc_generic(uaecptr addr, int l, uae_u32 fc, int flags, bool checkwrite) { uae_u32 page_index = addr & mmu030.translation.page.mask; uae_u32 addr_mask = mmu030.translation.page.imask; - uae_u32 physical_addr = mmu030.atc[l].physical.addr & addr_mask; + #if MMU030_ATC_DBG_MSG - write_log(_T("ATC match(%i): page addr = %08X, index = %08X (bget %02X)\n"), l, - physical_addr, page_index, phys_get_byte(physical_addr+page_index)); + write_log(_T("ATC match(%i): page addr = %08X, index = %08X\n"), l, + physical_addr, page_index); #endif - physical_addr += page_index; if (mmu030.atc[l].physical.bus_error || (checkwrite && mmu030.atc[l].physical.write_protect)) { mmu030_page_fault(addr, true, flags, fc); return 0; } - if (size == sz_byte) - return x_phys_get_byte(physical_addr); - else if (size == sz_word) - return x_phys_get_word(physical_addr); - return x_phys_get_long(physical_addr); + + mmu030_add_data_read_cache(addr, physical_addr, fc); + + return physical_addr + page_index; } @@ -1842,7 +1817,7 @@ uae_u32 mmu030_get_atc_generic(uaecptr addr, int l, uae_u32 fc, int size, int fl * by comparing the logical address and function code to the values * stored in the ATC entries. If a matching entry is found it sets * the history bit and returns the cache index of the entry. */ -int mmu030_logical_is_in_atc(uaecptr addr, uae_u32 fc, bool write) { +static int mmu030_logical_is_in_atc(uaecptr addr, uae_u32 fc, bool write) { uaecptr logical_addr = 0; uae_u32 addr_mask = mmu030.translation.page.imask; uae_u32 maddr = addr & addr_mask; @@ -1876,26 +1851,6 @@ int mmu030_logical_is_in_atc(uaecptr addr, uae_u32 fc, bool write) { return -1; } -void mmu030_atc_handle_history_bit(int entry_num) { - int j; - mmu030.atc[entry_num].mru = 1; - for (j=0; j=0) { - mmu030_put_long_atc(addr, val, atc_line_num, fc); + addr = mmu030_put_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_L); } else { mmu030_table_search(addr,fc,true,0); - mmu030_put_long_atc(addr, val, mmu030_logical_is_in_atc(addr,fc,true), fc); + addr = mmu030_put_atc(addr, mmu030_logical_is_in_atc(addr,fc,true), fc, MMU030_SSW_SIZE_L); } + x_phys_put_long(addr,val); } void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,true)) || (fc==7)) { + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,true)) || (!mmu030.enabled)) { x_phys_put_word(addr,val); return; } int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); - if (atc_line_num>=0) { - mmu030_put_word_atc(addr, val, atc_line_num, fc); + addr = mmu030_put_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_W); } else { mmu030_table_search(addr, fc, true, 0); - mmu030_put_word_atc(addr, val, mmu030_logical_is_in_atc(addr,fc,true), fc); + addr = mmu030_put_atc(addr, mmu030_logical_is_in_atc(addr,fc,true), fc, MMU030_SSW_SIZE_W); } + x_phys_put_word(addr,val); } void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, true)) || (fc==7)) { + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,true)) || (!mmu030.enabled)) { x_phys_put_byte(addr,val); return; } int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); - if (atc_line_num>=0) { - mmu030_put_byte_atc(addr, val, atc_line_num, fc); + addr = mmu030_put_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_B); } else { mmu030_table_search(addr, fc, true, 0); - mmu030_put_byte_atc(addr, val, mmu030_logical_is_in_atc(addr,fc,true), fc); + addr = mmu030_put_atc(addr, mmu030_logical_is_in_atc(addr,fc,true), fc, MMU030_SSW_SIZE_B); } + x_phys_put_byte(addr,val); } -uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc) { - - if (mmu030.mmu030_last_fc == fc && (addr & mmu030.translation.page.imask) == mmu030.mmu030_last_logical_address) { - return x_phys_get_ilong(mmu030.mmu030_last_physical_address + (addr & mmu030.translation.page.mask)); - } - - mmu030.mmu030_last_fc = 0xffffffff; - // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, false)) || (fc == 7)) { - return x_phys_get_ilong(addr); - } - - int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); - if (atc_line_num >= 0) { - uae_u32 v = mmu030_get_ilong_atc(addr, atc_line_num, fc, &mmu030.mmu030_last_physical_address); - mmu030.mmu030_last_logical_address = addr & mmu030.translation.page.imask; - mmu030.mmu030_last_fc = fc; - return v; - } - else { - mmu030_table_search(addr, fc, false, 0); - uae_u32 v = mmu030_get_ilong_atc(addr, mmu030_logical_is_in_atc(addr, fc, false), fc, &mmu030.mmu030_last_physical_address); - mmu030.mmu030_last_logical_address = addr & mmu030.translation.page.imask; - mmu030.mmu030_last_fc = fc; - return v; - } -} uae_u32 mmu030_get_long(uaecptr addr, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) { + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,false)) || (!mmu030.enabled)) { return x_phys_get_long(addr); } - int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); - +#if MMU_DPAGECACHE030 + uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size1m) | fc; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_read[idx2].log == idx1) { + addr = atc_data_cache_read[idx2].phys | (addr & mmu030.translation.page.mask); + return x_phys_get_long(addr); + } +#endif + + int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); if (atc_line_num>=0) { - return mmu030_get_long_atc(addr, atc_line_num, fc); + addr = mmu030_get_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_L); } else { mmu030_table_search(addr, fc, false, 0); - return mmu030_get_long_atc(addr, mmu030_logical_is_in_atc(addr,fc,false), fc); + addr = mmu030_get_atc(addr, mmu030_logical_is_in_atc(addr,fc,false), fc, MMU030_SSW_SIZE_L); } + return x_phys_get_long(addr); } -uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc) { - - if (mmu030.mmu030_last_fc == fc && (addr & mmu030.translation.page.imask) == mmu030.mmu030_last_logical_address) { - return x_phys_get_iword(mmu030.mmu030_last_physical_address + (addr & mmu030.translation.page.mask)); - } - - mmu030.mmu030_last_fc = 0xffffffff; - // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, false)) || (fc == 7)) { - return x_phys_get_iword(addr); - } - - int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); - - if (atc_line_num >= 0) { - uae_u16 v = mmu030_get_iword_atc(addr, atc_line_num, fc, &mmu030.mmu030_last_physical_address); - mmu030.mmu030_last_logical_address = addr & mmu030.translation.page.imask; - mmu030.mmu030_last_fc = fc; - return v; - } else { - mmu030_table_search(addr, fc, false, 0); - uae_u16 v = mmu030_get_iword_atc(addr, mmu030_logical_is_in_atc(addr, fc, false), fc, &mmu030.mmu030_last_physical_address); - mmu030.mmu030_last_logical_address = addr & mmu030.translation.page.imask; - mmu030.mmu030_last_fc = fc; - return v; - } -} uae_u16 mmu030_get_word(uaecptr addr, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) { + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,false)) || (!mmu030.enabled)) { return x_phys_get_word(addr); } - int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); - +#if MMU_DPAGECACHE030 + uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size1m) | fc; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_read[idx2].log == idx1) { + addr = atc_data_cache_read[idx2].phys | (addr & mmu030.translation.page.mask); + return x_phys_get_word(addr); + } +#endif + + int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); if (atc_line_num>=0) { - return mmu030_get_word_atc(addr, atc_line_num, fc); + addr = mmu030_get_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_W); } else { mmu030_table_search(addr, fc, false, 0); - return mmu030_get_word_atc(addr, mmu030_logical_is_in_atc(addr,fc,false), fc); + addr = mmu030_get_atc(addr, mmu030_logical_is_in_atc(addr,fc,false), fc, MMU030_SSW_SIZE_W); } + return x_phys_get_word(addr); } uae_u8 mmu030_get_byte(uaecptr addr, uae_u32 fc) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) { + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,false)) || (!mmu030.enabled)) { return x_phys_get_byte(addr); } - int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); - +#if MMU_DPAGECACHE030 + uae_u32 idx1 = ((addr & mmu030.translation.page.imask) >> mmu030.translation.page.size1m) | fc; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_read[idx2].log == idx1) { + addr = atc_data_cache_read[idx2].phys | (addr & mmu030.translation.page.mask); + return x_phys_get_byte(addr); + } +#endif + + int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); if (atc_line_num>=0) { - return mmu030_get_byte_atc(addr, atc_line_num, fc); + addr = mmu030_get_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_B); } else { mmu030_table_search(addr, fc, false, 0); - return mmu030_get_byte_atc(addr, mmu030_logical_is_in_atc(addr,fc,false), fc); + addr = mmu030_get_atc(addr, mmu030_logical_is_in_atc(addr,fc,false), fc, MMU030_SSW_SIZE_B); } + return x_phys_get_byte(addr); +} + + +uae_u32 mmu030_get_ilong(uaecptr addr, uae_u32 fc) { + +#if MMU_IPAGECACHE030 + if (((addr & mmu030.translation.page.imask) | fc) == mmu030.mmu030_last_logical_address) { +#if MMU_DIRECT_ACCESS + uae_u8 *p = &mmu030.mmu030_last_physical_address_real[addr & mmu030.translation.page.mask]; + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]); +#else + return x_phys_get_ilong(mmu030.mmu030_last_physical_address + (addr & mmu030.translation.page.mask)); +#endif + } + mmu030.mmu030_last_logical_address = 0xffffffff; +#endif + + // addr,super,write + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,false)) || (!mmu030.enabled)) { + return x_phys_get_ilong(addr); + } + + int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); + if (atc_line_num >= 0) { + addr = mmu030_get_i_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_L); + } else { + mmu030_table_search(addr, fc, false, 0); + addr = mmu030_get_i_atc(addr, mmu030_logical_is_in_atc(addr, fc, false), fc, MMU030_SSW_SIZE_L); + } + return x_phys_get_ilong(addr); +} + +uae_u16 mmu030_get_iword(uaecptr addr, uae_u32 fc) { + +#if MMU_IPAGECACHE030 + if (((addr & mmu030.translation.page.imask) | fc) == mmu030.mmu030_last_logical_address) { +#if MMU_DIRECT_ACCESS + uae_u8 *p = &mmu030.mmu030_last_physical_address_real[addr & mmu030.translation.page.mask]; + return (p[0] << 8) | p[1]; +#else + return x_phys_get_iword(mmu030.mmu030_last_physical_address + (addr & mmu030.translation.page.mask)); +#endif + } + mmu030.mmu030_last_logical_address = 0xffffffff; +#endif + + // addr,super,write + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,false)) || (!mmu030.enabled)) { + return x_phys_get_iword(addr); + } + + int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); + if (atc_line_num >= 0) { + addr = mmu030_get_i_atc(addr, atc_line_num, fc, MMU030_SSW_SIZE_W); + } else { + mmu030_table_search(addr, fc, false, 0); + addr = mmu030_get_i_atc(addr, mmu030_logical_is_in_atc(addr, fc, false), fc, MMU030_SSW_SIZE_W); + } + return x_phys_get_iword(addr); } /* Not commonly used access function */ void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int accesssize, int flags) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr, fc, true)) || (fc==7)) { + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,true)) || (!mmu030.enabled)) { if (size == sz_byte) x_phys_put_byte(addr, val); else if (size == sz_word) @@ -2077,23 +2064,30 @@ void mmu030_put_generic(uaecptr addr, uae_u32 val, uae_u32 fc, int size, int acc return; } + if (accesssize == sz_byte) + flags |= MMU030_SSW_SIZE_B; + else if (accesssize == sz_word) + flags |= MMU030_SSW_SIZE_W; int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); if (atc_line_num>=0) { - mmu030_put_atc_generic(addr, val, atc_line_num, fc, size, flags); + addr = mmu030_put_atc_generic(addr, atc_line_num, fc, flags); } else { mmu030_table_search(addr, fc, true, 0); atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); - if (accesssize == sz_byte) - flags |= MMU030_SSW_SIZE_B; - else if (accesssize == sz_word) - flags |= MMU030_SSW_SIZE_W; - mmu030_put_atc_generic(addr, val, atc_line_num, fc, size, flags); + addr = mmu030_put_atc_generic(addr, atc_line_num, fc, flags); } + if (size == sz_byte) + x_phys_put_byte(addr, val); + else if (size == sz_word) + x_phys_put_word(addr, val); + else + x_phys_put_long(addr, val); } + static uae_u32 mmu030_get_generic_lrmw(uaecptr addr, uae_u32 fc, int size, int accesssize, int flags) { // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_lrmw_ttr_access(addr,fc)) || (fc==7)) { + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,false)) || (!mmu030.enabled)) { if (size == sz_byte) return x_phys_get_byte(addr); else if (size == sz_word) @@ -2101,25 +2095,32 @@ static uae_u32 mmu030_get_generic_lrmw(uaecptr addr, uae_u32 fc, int size, int a return x_phys_get_long(addr); } + if (accesssize == sz_byte) + flags |= MMU030_SSW_SIZE_B; + else if (accesssize == sz_word) + flags |= MMU030_SSW_SIZE_W; int atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); if (atc_line_num>=0) { - return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, true); + addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, true); } else { mmu030_table_search(addr, fc, true, 0); atc_line_num = mmu030_logical_is_in_atc(addr, fc, true); - if (accesssize == sz_byte) - flags |= MMU030_SSW_SIZE_B; - else if (accesssize == sz_word) - flags |= MMU030_SSW_SIZE_W; - return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, true); + addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, true); } + + if (size == sz_byte) + return x_phys_get_byte(addr); + else if (size == sz_word) + return x_phys_get_word(addr); + return x_phys_get_long(addr); } + uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int accesssize, int flags) { if (flags & MMU030_SSW_RM) { return mmu030_get_generic_lrmw(addr, fc, size, accesssize, flags); } // addr,super,write - if ((!mmu030.enabled) || (mmu030_match_ttr_access(addr,fc,false)) || (fc==7)) { + if ((fc==7) || (tt_enabled && mmu030_match_ttr_access(addr,fc,false)) || (!mmu030.enabled)) { if (size == sz_byte) return x_phys_get_byte(addr); else if (size == sz_word) @@ -2127,18 +2128,24 @@ uae_u32 mmu030_get_generic(uaecptr addr, uae_u32 fc, int size, int accesssize, i return x_phys_get_long(addr); } + if (accesssize == sz_byte) + flags |= MMU030_SSW_SIZE_B; + else if (accesssize == sz_word) + flags |= MMU030_SSW_SIZE_W; int atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); if (atc_line_num>=0) { - return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, false); + addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, false); } else { mmu030_table_search(addr, fc, false, 0); atc_line_num = mmu030_logical_is_in_atc(addr, fc, false); - if (accesssize == sz_byte) - flags |= MMU030_SSW_SIZE_B; - else if (accesssize == sz_word) - flags |= MMU030_SSW_SIZE_W; - return mmu030_get_atc_generic(addr, atc_line_num, fc, size, flags, false); + addr = mmu030_get_atc_generic(addr, atc_line_num, fc, flags, false); } + + if (size == sz_byte) + return x_phys_get_byte(addr); + else if (size == sz_word) + return x_phys_get_word(addr); + return x_phys_get_long(addr); } @@ -2300,7 +2307,7 @@ static uaecptr mmu030_get_addr_atc(uaecptr addr, int l, uae_u32 fc, bool write) uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write) { int fc = (super ? 4 : 0) | (data ? 1 : 2); - if ((!mmu030.enabled) || (mmu030_match_ttr(addr,fc,write)&TT_OK_MATCH) || (fc==7)) { + if ((fc==7) || (mmu030_match_ttr(addr,fc,write)&TT_OK_MATCH) || (!mmu030.enabled)) { return addr; } int atc_line_num = mmu030_logical_is_in_atc(addr, fc, write); @@ -2343,7 +2350,9 @@ void mmu030_reset(int hardreset) { /* A CPU reset causes the E-bits of TC and TT registers to be zeroed. */ mmu030.enabled = false; - mmu030.mmu030_last_fc = 0xffffffff; +#if MMU_IPAGECACHE030 + mmu030.mmu030_last_logical_address = 0xffffffff; +#endif regs.mmu_page_size = 0; if (hardreset >= 0) { tc_030 &= ~TC_ENABLE_TRANSLATION; diff --git a/include/cpummu.h b/include/cpummu.h index 79372c50..ac9688bf 100644 --- a/include/cpummu.h +++ b/include/cpummu.h @@ -29,6 +29,12 @@ #include "uae/types.h" +#define MMU_ICACHE 0 +#define MMU_IPAGECACHE 1 +#define MMU_DPAGECACHE 1 + +#define CACHE_HIT_COUNT 0 + #include "mmu_common.h" #ifndef FULLMMU @@ -52,62 +58,10 @@ extern uaecptr mmu040_movem_ea; extern uae_u32 mmu040_move16[4]; extern bool mmu_pagesize_8k; +extern int mmu_pageshift, mmu_pageshift1m; extern uae_u16 mmu_opcode; extern bool mmu_restart; -extern bool mmu_ttr_enabled; - -//typedef uae_u8 flagtype; - -//static m68k_exception except; - -struct xttrx { - uae_u32 log_addr_base : 8; - uae_u32 log_addr_mask : 8; - uae_u32 enable : 1; - uae_u32 s_field : 2; - uae_u32 : 3; - uae_u32 usr1 : 1; - uae_u32 usr0 : 1; - uae_u32 : 1; - uae_u32 cmode : 2; - uae_u32 : 2; - uae_u32 write : 1; - uae_u32 : 2; -}; - -struct mmusr_t { - uae_u32 phys_addr : 20; - uae_u32 bus_err : 1; - uae_u32 global : 1; - uae_u32 usr1 : 1; - uae_u32 usr0 : 1; - uae_u32 super : 1; - uae_u32 cmode : 2; - uae_u32 modif : 1; - uae_u32 : 1; - uae_u32 write : 1; - uae_u32 ttrhit : 1; - uae_u32 resident : 1; -}; - -struct log_addr4 { - uae_u32 rif : 7; - uae_u32 pif : 7; - uae_u32 paif : 6; - uae_u32 poff : 12; -}; - -struct log_addr8 { - uae_u32 rif : 7; - uae_u32 pif : 7; - uae_u32 paif : 5; - uae_u32 poff : 13; -}; - -#define MMU_TEST_PTEST 1 -#define MMU_TEST_VERBOSE 2 -#define MMU_TEST_FORCE_TABLE_SEARCH 4 -#define MMU_TEST_NO_BUSERR 8 +extern bool mmu_ttr_enabled, mmu_ttr_enabled_ins, mmu_ttr_enabled_data; extern void mmu_dump_tables(void); @@ -158,6 +112,24 @@ extern void mmu_dump_tables(void); #define MMU_MMUSR_T (1 << 1) #define MMU_MMUSR_R (1 << 0) +// 68040 and 68060 +#define MMU_TCR_E 0x8000 +#define MMU_TCR_P 0x4000 +// 68060 only +#define MMU_TCR_NAD 0x2000 +#define MMU_TCR_NAI 0x1000 +#define MMU_TCR_FOTC 0x0800 +#define MMU_TCR_FITC 0x0400 +#define MMU_TCR_DCO1 0x0200 +#define MMU_TCR_DCO0 0x0100 +#define MMU_TCR_DUO1 0x0080 +#define MMU_TCR_DUO0 0x0040 +#define MMU_TCR_DWO 0x0020 +#define MMU_TCR_DCI1 0x0010 +#define MMU_TCR_DCI0 0x0008 +#define MMU_TCR_DUI1 0x0004 +#define MMU_TCR_DUI0 0x0002 + #define TTR_I0 4 #define TTR_I1 5 #define TTR_D0 6 @@ -169,10 +141,8 @@ extern void mmu_dump_tables(void); struct mmu_atc_line { uaecptr tag; // tag is 16 or 17 bits S+logical - unsigned valid : 1; - unsigned global : 1; - unsigned modified : 1; - unsigned write_protect : 1; + uae_u32 valid; + uae_u32 status; uaecptr phys; // phys base address }; @@ -189,135 +159,15 @@ struct mmu_atc_line { #define ATC_TYPE 2 extern uae_u32 mmu_is_super; -extern uae_u32 mmu_tagmask, mmu_pagemask; -extern struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_WAYS][ATC_SLOTS]; - -/* Last matched ATC index, next lookup starts from this index as an optimization */ -extern int mmu_atc_ways; +extern uae_u32 mmu_tagmask, mmu_pagemask, mmu_pagemaski; +extern struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_SLOTS][ATC_WAYS]; -/* - * mmu access is a 4 step process: - * if mmu is not enabled just read physical - * check transparent region, if transparent, read physical - * check ATC (address translation cache), read immediatly if HIT - * read from mmu with the long path (and allocate ATC entry if needed) - */ -static ALWAYS_INLINE bool mmu_lookup(uaecptr addr, bool data, bool write, - struct mmu_atc_line **cl) -{ - int way, i, index; - static int way_miss=0; - - uae_u32 tag = (mmu_is_super | (addr >> 1)) & mmu_tagmask; - if (mmu_pagesize_8k) - index=(addr & 0x0001E000)>>13; - else - index=(addr & 0x0000F000)>>12; - for (i = 0; i < ATC_WAYS; i++) { - way = mmu_atc_ways; - // if we have this - if ((tag == mmu_atc_array[data][way][index].tag) && (mmu_atc_array[data][way][index].valid)) { - *cl=&mmu_atc_array[data][way][index]; - // if first write to this take slow path (but modify this slot) - if ((!mmu_atc_array[data][way][index].modified & write) || (mmu_atc_array[data][way][index].write_protect & write)) - return false; - return true; - } - mmu_atc_ways++; - mmu_atc_ways %= ATC_WAYS; - } - // we select a random way to void - *cl=&mmu_atc_array[data][way_miss%ATC_WAYS][index]; - (*cl)->tag = tag; - way_miss++; - return false; -} - -/* - */ -static ALWAYS_INLINE bool mmu_user_lookup(uaecptr addr, bool super, bool data, - bool write, struct mmu_atc_line **cl) -{ - int way, i, index; - static int way_miss=0; - - uae_u32 tag = ((super ? 0x80000000 : 0x00000000) | (addr >> 1)) & mmu_tagmask; - if (mmu_pagesize_8k) - index=(addr & 0x0001E000)>>13; - else - index=(addr & 0x0000F000)>>12; - for (i = 0; i < ATC_WAYS; i++) { - way = mmu_atc_ways; - // if we have this - if ((tag == mmu_atc_array[data][way][index].tag) && (mmu_atc_array[data][way][index].valid)) { - *cl=&mmu_atc_array[data][way][index]; - // if first write to this take slow path (but modify this slot) - if ((!mmu_atc_array[data][way][index].modified & write) || (mmu_atc_array[data][way][index].write_protect & write)) - return false; - return true; - } - mmu_atc_ways++; - mmu_atc_ways %= ATC_WAYS; - } - // we select a random way to void - *cl=&mmu_atc_array[data][way_miss%ATC_WAYS][index]; - (*cl)->tag = tag; - way_miss++; - return false; -} - -/* check if an address matches a ttr */ -STATIC_INLINE int mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super) -{ - if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */ - uae_u8 msb, mask; - - msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24; - mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16; - - if (!(msb & ~mask)) { - - if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) { - if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) { - return TTR_NO_MATCH; - } - } - - return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH; - } - } - return TTR_NO_MATCH; -} - -STATIC_INLINE int mmu_match_ttr(uaecptr addr, bool super, bool data, bool rmw) -{ - int res; - - if (!mmu_ttr_enabled) - return TTR_NO_MATCH; - if (data) { - res = mmu_do_match_ttr(regs.dtt0, addr, super); - if (res == TTR_NO_MATCH) - res = mmu_do_match_ttr(regs.dtt1, addr, super); - } else { - res = mmu_do_match_ttr(regs.itt0, addr, super); - if (res == TTR_NO_MATCH) - res = mmu_do_match_ttr(regs.itt1, addr, super); - } - return res; -} +extern void mmu_tt_modified(void); +extern int mmu_match_ttr_ins(uaecptr addr, bool super); +extern int mmu_match_ttr(uaecptr addr, bool super, bool data); extern void mmu_bus_error_ttr_write_fault(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool rmw); -STATIC_INLINE int mmu_match_ttr_write(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool rmw) -{ - if (!mmu_ttr_enabled) - return TTR_NO_MATCH; - int res = mmu_match_ttr(addr, super, data, rmw); - if (res == TTR_NO_WRITE) - mmu_bus_error_ttr_write_fault(addr, super, data, val, size, rmw); - return res; -} - -extern void mmu_tt_modified (void); +extern int mmu_match_ttr_write(uaecptr addr, bool super, bool data, uae_u32 val, int size, bool rmw); +extern uaecptr mmu_translate(uaecptr addr, uae_u32 val, bool super, bool data, bool write, int size, bool rmw); extern uae_u32 REGPARAM3 mmu060_get_rmw_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width) REGPARAM; extern void REGPARAM3 mmu060_put_rmw_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width) REGPARAM; @@ -327,35 +177,15 @@ extern uae_u32 REGPARAM3 mmu_get_long_unaligned(uaecptr addr, bool data, bool rm extern uae_u32 REGPARAM3 mmu_get_ilong_unaligned(uaecptr addr) REGPARAM; -extern uae_u8 REGPARAM3 mmu_get_byte_slow(uaecptr addr, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) REGPARAM; -extern uae_u16 REGPARAM3 mmu_get_word_slow(uaecptr addr, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) REGPARAM; -extern uae_u32 REGPARAM3 mmu_get_long_slow(uaecptr addr, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) REGPARAM; - -extern uae_u16 REGPARAM3 mmu_get_iword_slow(uaecptr addr, bool super, - int size, struct mmu_atc_line *cl) REGPARAM; -extern uae_u32 REGPARAM3 mmu_get_ilong_slow(uaecptr addr, bool super, - int size, struct mmu_atc_line *cl) REGPARAM; - extern void REGPARAM3 mmu_put_word_unaligned(uaecptr addr, uae_u16 val, bool data, bool rmw) REGPARAM; extern void REGPARAM3 mmu_put_long_unaligned(uaecptr addr, uae_u32 val, bool data, bool rmw) REGPARAM; -extern void REGPARAM3 mmu_put_byte_slow(uaecptr addr, uae_u8 val, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) REGPARAM; -extern void REGPARAM3 mmu_put_word_slow(uaecptr addr, uae_u16 val, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) REGPARAM; -extern void REGPARAM3 mmu_put_long_slow(uaecptr addr, uae_u32 val, bool super, bool data, - int size, bool rmw, struct mmu_atc_line *cl) REGPARAM; - extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode); #define FC_DATA (regs.s ? 5 : 1) #define FC_INST (regs.s ? 6 : 2) -extern uaecptr REGPARAM3 mmu_translate(uaecptr addr, bool super, bool data, bool write) REGPARAM; -extern void mmu_bus_error(uaecptr addr, int fc, bool write, int size, bool rmw, uae_u32 status, bool nonmmu); +extern void mmu_bus_error(uaecptr addr, uae_u32 val, int fc, bool write, int size, bool rmw, uae_u32 status, bool nonmmu); extern uae_u32 REGPARAM3 sfc_get_long(uaecptr addr) REGPARAM; extern uae_u16 REGPARAM3 sfc_get_word(uaecptr addr) REGPARAM; @@ -389,240 +219,448 @@ extern void REGPARAM3 mmu_reset(void) REGPARAM; extern void REGPARAM3 mmu_set_funcs(void) REGPARAM; extern void REGPARAM3 mmu_set_tc(uae_u16 tc) REGPARAM; extern void REGPARAM3 mmu_set_super(bool super) REGPARAM; +extern void REGPARAM3 mmu_flush_cache(void) REGPARAM; static ALWAYS_INLINE uaecptr mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl) { - return cl->phys | (addr & mmu_pagemask); + return cl->phys | (addr & mmu_pagemask); } extern void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size); extern void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size); -static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, bool data, int size, bool rmw) +#if MMU_IPAGECACHE +extern uae_u32 atc_last_ins_laddr, atc_last_ins_paddr; +#endif + +#if MMU_DPAGECACHE +#define MMUFASTCACHE_ENTRIES 256 +struct mmufastcache { - struct mmu_atc_line *cl; + uae_u32 log; + uae_u32 phys; +}; +extern struct mmufastcache atc_data_cache_read[MMUFASTCACHE_ENTRIES]; +extern struct mmufastcache atc_data_cache_write[MMUFASTCACHE_ENTRIES]; +#endif - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data,rmw)!=TTR_NO_MATCH)) - return x_phys_get_long(addr); - if (likely(mmu_lookup(addr, data, false, &cl))) - return x_phys_get_long(mmu_get_real_address(addr, cl)); - return mmu_get_long_slow(addr, regs.s != 0, data, size, rmw, cl); -} +#if CACHE_HIT_COUNT +extern int mmu_ins_hit, mmu_ins_miss; +extern int mmu_data_read_hit, mmu_data_read_miss; +extern int mmu_data_write_hit, mmu_data_write_miss; +#endif static ALWAYS_INLINE uae_u32 mmu_get_ilong(uaecptr addr, int size) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr, regs.s != 0, false, false) != TTR_NO_MATCH)) - return x_phys_get_ilong(addr); - if (likely(mmu_lookup(addr, false, false, &cl))) - return x_phys_get_ilong(mmu_get_real_address(addr, cl)); - return mmu_get_ilong_slow(addr, regs.s != 0, size, cl); + if ((!mmu_ttr_enabled_ins || mmu_match_ttr_ins(addr,regs.s!=0) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_IPAGECACHE + if (((addr & mmu_pagemaski) | regs.s) == atc_last_ins_laddr) { +#if CACHE_HIT_COUNT + mmu_ins_hit++; +#endif + addr = atc_last_ins_paddr | (addr & mmu_pagemask); + } else { +#if CACHE_HIT_COUNT + mmu_ins_miss++; +#endif +#endif + addr = mmu_translate(addr, 0, regs.s!=0, false, false, size, false); +#if MMU_IPAGECACHE + } +#endif + } + return phys_get_long(addr); } -static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, bool data, int size, bool rmw) +static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data,rmw)!=TTR_NO_MATCH)) - return x_phys_get_word(addr); - if (likely(mmu_lookup(addr, data, false, &cl))) - return x_phys_get_word(mmu_get_real_address(addr, cl)); - return mmu_get_word_slow(addr, regs.s != 0, data, size, rmw, cl); + if ((!mmu_ttr_enabled_ins || mmu_match_ttr_ins(addr,regs.s!=0) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_IPAGECACHE + if (((addr & mmu_pagemaski) | regs.s) == atc_last_ins_laddr) { +#if CACHE_HIT_COUNT + mmu_ins_hit++; +#endif + addr = atc_last_ins_paddr | (addr & mmu_pagemask); + } else { +#if CACHE_HIT_COUNT + mmu_ins_miss++; +#endif +#endif + addr = mmu_translate(addr, 0, regs.s!=0, false, false, size, false); +#if MMU_IPAGECACHE + } +#endif + } + return phys_get_word(addr); } -static ALWAYS_INLINE uae_u16 mmu_get_iword(uaecptr addr, int size) + +static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, bool data, int size, bool rmw) { - struct mmu_atc_line *cl; + if ((!mmu_ttr_enabled || mmu_match_ttr(addr,regs.s!=0,data) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_read[idx2].log == idx1) { + addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_read_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_read_miss++; +#endif +#endif + addr = mmu_translate(addr, 0, regs.s!=0, data, false, size, rmw); +#if MMU_DPAGECACHE + } +#endif + } + return phys_get_long(addr); +} - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr, regs.s != 0, false, false) != TTR_NO_MATCH)) - return x_phys_get_iword(addr); - if (likely(mmu_lookup(addr, false, false, &cl))) - return x_phys_get_iword(mmu_get_real_address(addr, cl)); - return mmu_get_iword_slow(addr, regs.s != 0, size, cl); +static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, bool data, int size, bool rmw) +{ + if ((!mmu_ttr_enabled || mmu_match_ttr(addr,regs.s!=0,data) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_read[idx2].log == idx1) { + addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_read_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_read_miss++; +#endif +#endif + addr = mmu_translate(addr, 0, regs.s!=0, data, false, size, rmw); +#if MMU_DPAGECACHE + } +#endif + } + return phys_get_word(addr); } static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, bool data, int size, bool rmw) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,regs.s != 0,data,rmw)!=TTR_NO_MATCH)) - return x_phys_get_byte(addr); - if (likely(mmu_lookup(addr, data, false, &cl))) - return x_phys_get_byte(mmu_get_real_address(addr, cl)); - return mmu_get_byte_slow(addr, regs.s != 0, data, size, rmw, cl); + if ((!mmu_ttr_enabled || mmu_match_ttr(addr,regs.s!=0,data) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_read[idx2].log == idx1) { + addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_read_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_read_miss++; +#endif +#endif + addr = mmu_translate(addr, 0, regs.s!=0, data, false, size, rmw); +#if MMU_DPAGECACHE + } +#endif +} + return phys_get_byte(addr); } static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, bool data, int size, bool rmw) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || mmu_match_ttr_write(addr,regs.s != 0,data,val,size,rmw)==TTR_OK_MATCH) { - x_phys_put_long(addr,val); - return; + if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,regs.s!=0,data,val,size,rmw) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_write[idx2].log == idx1) { + addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_write_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_write_miss++; +#endif +#endif + addr = mmu_translate(addr, val, regs.s!=0, data, true, size, rmw); +#if MMU_DPAGECACHE + } +#endif } - if (likely(mmu_lookup(addr, data, true, &cl))) - x_phys_put_long(mmu_get_real_address(addr, cl), val); - else - mmu_put_long_slow(addr, val, regs.s != 0, data, size, rmw, cl); + phys_put_long(addr, val); } static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, bool data, int size, bool rmw) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr,regs.s != 0,data,val,size,rmw)==TTR_OK_MATCH)) { - x_phys_put_word(addr,val); - return; + if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,regs.s!=0,data,val,size,rmw) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_write[idx2].log == idx1) { + addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_write_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_write_miss++; +#endif +#endif + addr = mmu_translate(addr, val, regs.s!=0, data, true, size, rmw); +#if MMU_DPAGECACHE + } +#endif } - if (likely(mmu_lookup(addr, data, true, &cl))) - x_phys_put_word(mmu_get_real_address(addr, cl), val); - else - mmu_put_word_slow(addr, val, regs.s != 0, data, size, rmw, cl); + phys_put_word(addr, val); } static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, bool data, int size, bool rmw) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr_write(addr,regs.s != 0,data,val,size,rmw)==TTR_OK_MATCH)) { - x_phys_put_byte(addr,val); - return; + if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,regs.s!=0,data,val,size,rmw) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | regs.s; + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_write[idx2].log == idx1) { + addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_write_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_write_miss++; +#endif +#endif + addr = mmu_translate(addr, val, regs.s!=0, data, true, size, rmw); +#if MMU_DPAGECACHE + } +#endif } - if (likely(mmu_lookup(addr, data, true, &cl))) - x_phys_put_byte(mmu_get_real_address(addr, cl), val); - else - mmu_put_byte_slow(addr, val, regs.s != 0, data, size, rmw, cl); + phys_put_byte(addr, val); } -static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool data, bool write, int size) +static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, bool super, bool write, int size) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)!=TTR_NO_MATCH)) - return x_phys_get_long(addr); - if (likely(mmu_user_lookup(addr, super, data, write, &cl))) - return x_phys_get_long(mmu_get_real_address(addr, cl)); - return mmu_get_long_slow(addr, super, data, size, false, cl); + if ((!mmu_ttr_enabled || mmu_match_ttr(addr,super,true) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0); + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_read[idx2].log == idx1) { + addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_read_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_read_miss++; +#endif +#endif + addr = mmu_translate(addr, 0, super, true, write, size, false); +#if MMU_DPAGECACHE + } +#endif + } + return phys_get_long(addr); } -static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool data, bool write, int size) +static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, bool super, bool write, int size) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)!=TTR_NO_MATCH)) - return x_phys_get_word(addr); - if (likely(mmu_user_lookup(addr, super, data, write, &cl))) - return x_phys_get_word(mmu_get_real_address(addr, cl)); - return mmu_get_word_slow(addr, super, data, size, false, cl); + if ((!mmu_ttr_enabled || mmu_match_ttr(addr,super,true) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0); + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_read[idx2].log == idx1) { + addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_read_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_read_miss++; +#endif +#endif + addr = mmu_translate(addr, 0, super, true, write, size, false); +#if MMU_DPAGECACHE + } +#endif + } + return phys_get_word(addr); } -static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool data, bool write, int size) +static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, bool super, bool write, int size) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)!=TTR_NO_MATCH)) - return x_phys_get_byte(addr); - if (likely(mmu_user_lookup(addr, super, data, write, &cl))) - return x_phys_get_byte(mmu_get_real_address(addr, cl)); - return mmu_get_byte_slow(addr, super, data, size, false, cl); + if ((!mmu_ttr_enabled || mmu_match_ttr(addr,super,true) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0); + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_read[idx2].log == idx1) { + addr = atc_data_cache_read[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_read_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_read_miss++; +#endif +#endif + addr = mmu_translate(addr, 0, super, true, write, size, false); +#if MMU_DPAGECACHE + } +#endif + } + return phys_get_byte(addr); } -static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool super, bool data, int size) +static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, bool super, int size) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)==TTR_OK_MATCH)) { - x_phys_put_long(addr,val); - return; + if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,super,true,val,size,false) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0); + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_write[idx2].log == idx1) { + addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_write_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_write_miss++; +#endif +#endif + addr = mmu_translate(addr, val, super, true, true, size, false); +#if MMU_DPAGECACHE + } +#endif } - if (likely(mmu_user_lookup(addr, super, data, true, &cl))) - x_phys_put_long(mmu_get_real_address(addr, cl), val); - else - mmu_put_long_slow(addr, val, super, data, size, false, cl); + phys_put_long(addr, val); } -static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool super, bool data, int size) +static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, bool super, int size) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)==TTR_OK_MATCH)) { - x_phys_put_word(addr,val); - return; + if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,super,true,val,size,false) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0); + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_write[idx2].log == idx1) { + addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_write_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_write_miss++; +#endif +#endif + addr = mmu_translate(addr, val, super, true, true, size, false); +#if MMU_DPAGECACHE + } +#endif } - if (likely(mmu_user_lookup(addr, super, data, true, &cl))) - x_phys_put_word(mmu_get_real_address(addr, cl), val); - else - mmu_put_word_slow(addr, val, super, data, size, false, cl); + phys_put_word(addr, val); } -static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super, bool data, int size) +static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, bool super, int size) { - struct mmu_atc_line *cl; - - // addr,super,data - if ((!regs.mmu_enabled) || (mmu_match_ttr(addr,super,data,false)==TTR_OK_MATCH)) { - x_phys_put_byte(addr,val); - return; + if ((!mmu_ttr_enabled || mmu_match_ttr_write(addr,super,true,val,size,false) == TTR_NO_MATCH) && regs.mmu_enabled) { +#if MMU_DPAGECACHE + uae_u32 idx1 = ((addr & mmu_pagemaski) >> mmu_pageshift1m) | (super ? 1 : 0); + uae_u32 idx2 = idx1 & (MMUFASTCACHE_ENTRIES - 1); + if (atc_data_cache_write[idx2].log == idx1) { + addr = atc_data_cache_write[idx2].phys | (addr & mmu_pagemask); +#if CACHE_HIT_COUNT + mmu_data_write_hit++; +#endif + } else { +#if CACHE_HIT_COUNT + mmu_data_write_miss++; +#endif +#endif + addr = mmu_translate(addr, val, super, true, true, size, false); +#if MMU_DPAGECACHE + } +#endif } - if (likely(mmu_user_lookup(addr, super, data, true, &cl))) - x_phys_put_byte(mmu_get_real_address(addr, cl), val); - else - mmu_put_byte_slow(addr, val, super, data, size, false, cl); + phys_put_byte(addr, val); } static ALWAYS_INLINE void HWput_l(uaecptr addr, uae_u32 l) { - put_long (addr, l); + put_long (addr, l); } static ALWAYS_INLINE void HWput_w(uaecptr addr, uae_u32 w) { - put_word (addr, w); + put_word (addr, w); } static ALWAYS_INLINE void HWput_b(uaecptr addr, uae_u32 b) { - put_byte (addr, b); + put_byte (addr, b); } static ALWAYS_INLINE uae_u32 HWget_l(uaecptr addr) { - return get_long (addr); + return get_long (addr); } static ALWAYS_INLINE uae_u32 HWget_w(uaecptr addr) { - return get_word (addr); + return get_word (addr); } static ALWAYS_INLINE uae_u32 HWget_b(uaecptr addr) { - return get_byte (addr); + return get_byte (addr); } -static ALWAYS_INLINE uae_u32 uae_mmu040_get_ilong(uaecptr addr) +#if MMU_ICACHE +#define MMU_ICACHE_SZ 4096 +struct mmu_icache { - if (unlikely(is_unaligned(addr, 4))) - return mmu_get_ilong_unaligned(addr); - return mmu_get_ilong(addr, sz_long); + uae_u16 data; + uae_u32 addr; +}; + +extern struct mmu_icache mmu_icache_data[MMU_ICACHE_SZ]; + +static ALWAYS_INLINE uae_u16 uae_mmu040_getc_iword(uaecptr addr) +{ + int icidx = (addr & (MMU_ICACHE_SZ - 1)) | regs.s; + if (addr != mmu_icache_data[icidx].addr || !(regs.cacr & 0x8000)) { + mmu_icache_data[icidx].data = mmu_get_iword(addr, sz_word); + mmu_icache_data[icidx].addr = addr; + return mmu_icache_data[icidx].data; + } else { + return mmu_icache_data[icidx].data; + } } +#endif + static ALWAYS_INLINE uae_u16 uae_mmu040_get_iword(uaecptr addr) { +#if MMU_ICACHE + return uae_mmu040_getc_iword(addr); +#else return mmu_get_iword(addr, sz_word); +#endif +} +static ALWAYS_INLINE uae_u32 uae_mmu040_get_ilong(uaecptr addr) +{ +#if MMU_ICACHE + uae_u32 result = uae_mmu040_getc_iword(addr); + result <<= 16; + result |= uae_mmu040_getc_iword(addr + 2); + return result; +#else + if (unlikely(is_unaligned(addr, 4))) + return mmu_get_ilong_unaligned(addr); + return mmu_get_ilong(addr, sz_long); +#endif } static ALWAYS_INLINE uae_u16 uae_mmu040_get_ibyte(uaecptr addr) { +#if MMU_ICACHE + uae_u16 result = uae_mmu040_getc_iword(addr & ~1); + return (addr & 1) ? result & 0xFF : result >> 8; +#else return mmu_get_byte(addr, false, sz_byte, false); +#endif } static ALWAYS_INLINE uae_u32 uae_mmu040_get_long(uaecptr addr) { @@ -724,193 +762,193 @@ static ALWAYS_INLINE void uae_mmu_put_move16(uaecptr addr, uae_u32 *val) // normal 040 STATIC_INLINE void put_byte_mmu040 (uaecptr addr, uae_u32 v) { - uae_mmu040_put_byte (addr, v); + uae_mmu040_put_byte (addr, v); } STATIC_INLINE void put_word_mmu040 (uaecptr addr, uae_u32 v) { - uae_mmu040_put_word (addr, v); + uae_mmu040_put_word (addr, v); } STATIC_INLINE void put_long_mmu040 (uaecptr addr, uae_u32 v) { - uae_mmu040_put_long (addr, v); + uae_mmu040_put_long (addr, v); } STATIC_INLINE uae_u32 get_byte_mmu040 (uaecptr addr) { - return uae_mmu040_get_byte (addr); + return uae_mmu040_get_byte (addr); } STATIC_INLINE uae_u32 get_word_mmu040 (uaecptr addr) { - return uae_mmu040_get_word (addr); + return uae_mmu040_get_word (addr); } STATIC_INLINE uae_u32 get_long_mmu040 (uaecptr addr) { - return uae_mmu040_get_long (addr); + return uae_mmu040_get_long (addr); } // normal 060 STATIC_INLINE void put_byte_mmu060 (uaecptr addr, uae_u32 v) { - uae_mmu060_put_byte (addr, v, false); + uae_mmu060_put_byte (addr, v, false); } STATIC_INLINE void put_word_mmu060 (uaecptr addr, uae_u32 v) { - uae_mmu060_put_word (addr, v, false); + uae_mmu060_put_word (addr, v, false); } STATIC_INLINE void put_long_mmu060 (uaecptr addr, uae_u32 v) { - uae_mmu060_put_long (addr, v, false); + uae_mmu060_put_long (addr, v, false); } STATIC_INLINE uae_u32 get_byte_mmu060 (uaecptr addr) { - return uae_mmu060_get_byte (addr, false); + return uae_mmu060_get_byte (addr, false); } STATIC_INLINE uae_u32 get_word_mmu060 (uaecptr addr) { - return uae_mmu060_get_word (addr, false); + return uae_mmu060_get_word (addr, false); } STATIC_INLINE uae_u32 get_long_mmu060 (uaecptr addr) { - return uae_mmu060_get_long (addr, false); + return uae_mmu060_get_long (addr, false); } STATIC_INLINE void get_move16_mmu (uaecptr addr, uae_u32 *v) { - uae_mmu_get_move16 (addr, v); + uae_mmu_get_move16 (addr, v); } STATIC_INLINE void put_move16_mmu (uaecptr addr, uae_u32 *v) { - uae_mmu_put_move16 (addr, v); + uae_mmu_put_move16 (addr, v); } // locked rmw 060 STATIC_INLINE void put_lrmw_byte_mmu060 (uaecptr addr, uae_u32 v) { - uae_mmu_put_lrmw (addr, v, sz_byte, 1); + uae_mmu_put_lrmw (addr, v, sz_byte, 1); } STATIC_INLINE void put_lrmw_word_mmu060 (uaecptr addr, uae_u32 v) { - uae_mmu_put_lrmw (addr, v, sz_word, 1); + uae_mmu_put_lrmw (addr, v, sz_word, 1); } STATIC_INLINE void put_lrmw_long_mmu060 (uaecptr addr, uae_u32 v) { - uae_mmu_put_lrmw (addr, v, sz_long, 1); + uae_mmu_put_lrmw (addr, v, sz_long, 1); } STATIC_INLINE uae_u32 get_lrmw_byte_mmu060 (uaecptr addr) { - return uae_mmu_get_lrmw (addr, sz_byte, 1); + return uae_mmu_get_lrmw (addr, sz_byte, 1); } STATIC_INLINE uae_u32 get_lrmw_word_mmu060 (uaecptr addr) { - return uae_mmu_get_lrmw (addr, sz_word, 1); + return uae_mmu_get_lrmw (addr, sz_word, 1); } STATIC_INLINE uae_u32 get_lrmw_long_mmu060 (uaecptr addr) { - return uae_mmu_get_lrmw (addr, sz_long, 1); + return uae_mmu_get_lrmw (addr, sz_long, 1); } // normal rmw 060 STATIC_INLINE void put_rmw_byte_mmu060 (uaecptr addr, uae_u32 v) { - uae_mmu060_put_byte (addr, v, true); + uae_mmu060_put_byte (addr, v, true); } STATIC_INLINE void put_rmw_word_mmu060 (uaecptr addr, uae_u32 v) { - uae_mmu060_put_word (addr, v, true); + uae_mmu060_put_word (addr, v, true); } STATIC_INLINE void put_rmw_long_mmu060 (uaecptr addr, uae_u32 v) { - uae_mmu060_put_long (addr, v, true); + uae_mmu060_put_long (addr, v, true); } STATIC_INLINE uae_u32 get_rmw_byte_mmu060 (uaecptr addr) { - return uae_mmu060_get_byte (addr, true); + return uae_mmu060_get_byte (addr, true); } STATIC_INLINE uae_u32 get_rmw_word_mmu060 (uaecptr addr) { - return uae_mmu060_get_word (addr, true); + return uae_mmu060_get_word (addr, true); } STATIC_INLINE uae_u32 get_rmw_long_mmu060 (uaecptr addr) { - return uae_mmu060_get_long (addr, true); + return uae_mmu060_get_long (addr, true); } // locked rmw 040 STATIC_INLINE void put_lrmw_byte_mmu040 (uaecptr addr, uae_u32 v) { - uae_mmu_put_lrmw (addr, v, sz_byte, 0); + uae_mmu_put_lrmw (addr, v, sz_byte, 0); } STATIC_INLINE void put_lrmw_word_mmu040 (uaecptr addr, uae_u32 v) { - uae_mmu_put_lrmw (addr, v, sz_word, 0); + uae_mmu_put_lrmw (addr, v, sz_word, 0); } STATIC_INLINE void put_lrmw_long_mmu040 (uaecptr addr, uae_u32 v) { - uae_mmu_put_lrmw (addr, v, sz_long, 0); + uae_mmu_put_lrmw (addr, v, sz_long, 0); } STATIC_INLINE uae_u32 get_lrmw_byte_mmu040 (uaecptr addr) { - return uae_mmu_get_lrmw (addr, sz_byte, 0); + return uae_mmu_get_lrmw (addr, sz_byte, 0); } STATIC_INLINE uae_u32 get_lrmw_word_mmu040 (uaecptr addr) { - return uae_mmu_get_lrmw (addr, sz_word, 0); + return uae_mmu_get_lrmw (addr, sz_word, 0); } STATIC_INLINE uae_u32 get_lrmw_long_mmu040 (uaecptr addr) { - return uae_mmu_get_lrmw (addr, sz_long, 0); + return uae_mmu_get_lrmw (addr, sz_long, 0); } STATIC_INLINE uae_u32 get_ibyte_mmu040 (int o) { - uae_u32 pc = m68k_getpci () + o; - return uae_mmu040_get_iword (pc); + uae_u32 pc = m68k_getpci () + o; + return uae_mmu040_get_iword (pc); } STATIC_INLINE uae_u32 get_iword_mmu040 (int o) { - uae_u32 pc = m68k_getpci () + o; - return uae_mmu040_get_iword (pc); + uae_u32 pc = m68k_getpci () + o; + return uae_mmu040_get_iword (pc); } STATIC_INLINE uae_u32 get_ilong_mmu040 (int o) { - uae_u32 pc = m68k_getpci () + o; - return uae_mmu040_get_ilong (pc); + uae_u32 pc = m68k_getpci () + o; + return uae_mmu040_get_ilong (pc); } STATIC_INLINE uae_u32 next_iword_mmu040 (void) { - uae_u32 pc = m68k_getpci (); - m68k_incpci (2); - return uae_mmu040_get_iword (pc); + uae_u32 pc = m68k_getpci (); + m68k_incpci (2); + return uae_mmu040_get_iword (pc); } STATIC_INLINE uae_u32 next_ilong_mmu040 (void) { - uae_u32 pc = m68k_getpci (); - m68k_incpci (4); - return uae_mmu040_get_ilong (pc); + uae_u32 pc = m68k_getpci (); + m68k_incpci (4); + return uae_mmu040_get_ilong (pc); } STATIC_INLINE uae_u32 get_ibyte_mmu060 (int o) { - uae_u32 pc = m68k_getpci () + o; - return uae_mmu060_get_iword (pc); + uae_u32 pc = m68k_getpci () + o; + return uae_mmu060_get_iword (pc); } STATIC_INLINE uae_u32 get_iword_mmu060 (int o) { - uae_u32 pc = m68k_getpci () + o; - return uae_mmu060_get_iword (pc); + uae_u32 pc = m68k_getpci () + o; + return uae_mmu060_get_iword (pc); } STATIC_INLINE uae_u32 get_ilong_mmu060 (int o) { - uae_u32 pc = m68k_getpci () + o; - return uae_mmu060_get_ilong (pc); + uae_u32 pc = m68k_getpci () + o; + return uae_mmu060_get_ilong (pc); } STATIC_INLINE uae_u32 next_iword_mmu060 (void) { - uae_u32 pc = m68k_getpci (); - m68k_incpci (2); - return uae_mmu060_get_iword (pc); + uae_u32 pc = m68k_getpci (); + m68k_incpci (2); + return uae_mmu060_get_iword (pc); } STATIC_INLINE uae_u32 next_ilong_mmu060 (void) { - uae_u32 pc = m68k_getpci (); - m68k_incpci (4); - return uae_mmu060_get_ilong (pc); + uae_u32 pc = m68k_getpci (); + m68k_incpci (4); + return uae_mmu060_get_ilong (pc); } extern void flush_mmu040 (uaecptr, int); diff --git a/include/cpummu030.h b/include/cpummu030.h index 81ec935e..c72b8140 100644 --- a/include/cpummu030.h +++ b/include/cpummu030.h @@ -5,6 +5,9 @@ #include "mmu_common.h" +#define MMU_DPAGECACHE030 1 +#define MMU_IPAGECACHE030 1 + extern uae_u64 srp_030, crp_030; extern uae_u32 tt0_030, tt1_030, tc_030; extern uae_u16 mmusr_030; @@ -60,33 +63,11 @@ TT_info mmu030_decode_tt(uae_u32 TT); bool mmu030_decode_tc(uae_u32 TC, bool); bool mmu030_decode_rp(uae_u64 RP); -int mmu030_logical_is_in_atc(uaecptr addr, uae_u32 fc, bool write); -void mmu030_atc_handle_history_bit(int entry_num); - -void mmu030_put_long_atc(uaecptr addr, uae_u32 val, int l, uae_u32 fc); -void mmu030_put_word_atc(uaecptr addr, uae_u16 val, int l, uae_u32 fc); -void mmu030_put_byte_atc(uaecptr addr, uae_u8 val, int l, uae_u32 fc); -uae_u32 mmu030_get_long_atc(uaecptr addr, int l, uae_u32 fc); -uae_u16 mmu030_get_word_atc(uaecptr addr, int l, uae_u32 fc); -uae_u8 mmu030_get_byte_atc(uaecptr addr, int l, uae_u32 fc); - -void mmu030_put_atc_generic(uaecptr addr, uae_u32 val, int l, uae_u32 fc, int size, int flags); -uae_u32 mmu030_get_atc_generic(uaecptr addr, int l, uae_u32 fc, int size, int flags, bool checkwrite); - -void mmu030_flush_atc_fc(uae_u32 fc_base, uae_u32 fc_mask); -void mmu030_flush_atc_page(uaecptr logical_addr); -void mmu030_flush_atc_page_fc(uaecptr logical_addr, uae_u32 fc_base, uae_u32 fc_mask); void mmu030_flush_atc_all(void); void mmu030_reset(int hardreset); void mmu030_set_funcs(void); uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write); -int mmu030_match_ttr(uaecptr addr, uae_u32 fc, bool write); -int mmu030_match_ttr_access(uaecptr addr, uae_u32 fc, bool write); -int mmu030_match_lrmw_ttr_access(uaecptr addr, uae_u32 fc); -int mmu030_do_match_ttr(uae_u32 tt, TT_info masks, uaecptr addr, uae_u32 fc, bool write); -int mmu030_do_match_lrmw_ttr(uae_u32 tt, TT_info masks, uaecptr addr, uae_u32 fc); - void mmu030_put_long(uaecptr addr, uae_u32 val, uae_u32 fc); void mmu030_put_word(uaecptr addr, uae_u16 val, uae_u32 fc); void mmu030_put_byte(uaecptr addr, uae_u8 val, uae_u32 fc); diff --git a/newcpu.cpp b/newcpu.cpp index 8635057f..0995c212 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -1232,6 +1232,7 @@ void flush_cpu_caches(bool force) regs.cacr &= ~0x400; } } else if (currprefs.cpu_model >= 68040) { + mmu_flush_cache(); icachelinecnt = 0; dcachelinecnt = 0; if (doflush) { @@ -1249,7 +1250,7 @@ void flush_cpu_caches_040(uae_u16 opcode) { int cache = (opcode >> 6) & 3; if (!(cache & 2)) - return; + return; flush_cpu_caches(true); } @@ -2449,7 +2450,7 @@ static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 } #endif - switch (format) { + switch (format) { case 0x0: // four word stack frame case 0x1: // throwaway four word stack frame break; @@ -4806,7 +4807,7 @@ static void opcodedebug (uae_u32 pc, uae_u16 opcode, bool full) ; fault = 0; TRY(prb) { - addr = mmu_translate (pc, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0); + addr = mmu_translate (pc, 0, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0, sz_word, false); } CATCH (prb) { fault = 1; } ENDTRY @@ -7698,7 +7699,7 @@ void exception2 (uaecptr addr, bool read, int size, uae_u32 fc) uae_u32 flags = size == 1 ? MMU030_SSW_SIZE_B : (size == 2 ? MMU030_SSW_SIZE_W : MMU030_SSW_SIZE_L); mmu030_page_fault (addr, read, flags, fc); } else { - mmu_bus_error (addr, fc, read == false, size, false, 0, true); + mmu_bus_error (addr, 0, fc, read == false, size, false, 0, true); } } else { last_addr_for_exception_3 = m68k_getpc() + bus_error_offset; -- 2.47.3