From: Toni Wilen Date: Fri, 12 Jul 2019 16:40:02 +0000 (+0300) Subject: debugmem cpu cache checks. X-Git-Tag: 4300~180 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=4c96ec1e4b1acd6622c662b3227dc214da80f362;p=francis%2Fwinuae.git debugmem cpu cache checks. --- diff --git a/debug.cpp b/debug.cpp index e36b0e06..33822062 100644 --- a/debug.cpp +++ b/debug.cpp @@ -3181,6 +3181,7 @@ static int memwatch_func (uaecptr addr, int rwi, int size, uae_u32 *valp, uae_u3 mwhit.reg = reg; if (mwhit.rwi & 2) mwhit.val = val; + mwhit.pc = M68K_GETPC; memwatch_triggered = i + 1; if (m->reportonly) { memwatch_hit_msg(memwatch_triggered - 1); @@ -7205,7 +7206,6 @@ void debug_init_trainer(const TCHAR *file) } -end: if (tpptrcnt > 0) debug_opcode_watch = true; diff --git a/debugmem.cpp b/debugmem.cpp index 70a4af3f..c7fbbe07 100644 --- a/debugmem.cpp +++ b/debugmem.cpp @@ -216,6 +216,7 @@ static int alloccnt; #define DEBUGMEM_INUSE 0x80 #define DEBUGMEM_PARTIAL 0x100 #define DEBUGMEM_NOSTACKCHECK 0x200 +#define DEBUGMEM_WRITE_NOCACHEFLUSH 0x400 #define DEBUGMEM_STACK 0x1000 struct debugmemdata @@ -348,7 +349,7 @@ static void debugreport(struct debugmemdata *dm, uaecptr addr, int rwi, int size addr_start, addr_start + PAGE_SIZE - 1, !(state & (DEBUGMEM_ALLOCATED | DEBUGMEM_INUSE)) ? 'I' : (state & DEBUGMEM_WRITE) ? 'W' : 'R', (state & DEBUGMEM_WRITE) ? '*' : (state & DEBUGMEM_INITIALIZED) ? '+' : '-', - dm->unused_start, PAGE_SIZE - dm->unused_end); + dm->unused_start, PAGE_SIZE - dm->unused_end - 1); debugmem_break(1); } @@ -551,6 +552,38 @@ bool debugmem_break_stack_push(void) return true; } +void debugmem_flushcache(uaecptr addr, int size) +{ + if (!debugmem_initialized) + return; + if (size < 0) { + for (int i = 0; i < totalmemdata; i++) { + struct debugmemdata* dm = dmd[i]; + if (dm->flags & DEBUGMEM_WRITE_NOCACHEFLUSH) { + for (int j = 0; j < PAGE_SIZE; j++) { + dm->state[j] &= ~DEBUGMEM_WRITE_NOCACHEFLUSH; + } + dm->flags &= ~DEBUGMEM_WRITE_NOCACHEFLUSH; + } + } + return; + } + if (addr + size < debugmem_bank.start || addr >= debugmem_bank.start + debugmem_bank.allocated_size) + return; + for (int i = 0; i < (PAGE_SIZE + size - 1) / PAGE_SIZE; i++) { + uaecptr a = (addr & ~PAGE_SIZE) + i * PAGE_SIZE; + if (a < debugmem_bank.start || a >= debugmem_bank.start + debugmem_bank.allocated_size) + continue; + struct debugmemdata* dm = dmd[(a - debugmem_bank.start) / PAGE_SIZE]; + for (int j = 0; j < PAGE_SIZE; j++) { + uaecptr aa = a + j; + if (aa < addr || aa >= addr + size) + continue; + dm->state[j] &= ~DEBUGMEM_WRITE_NOCACHEFLUSH; + } + } +} + static bool debugmem_func(uaecptr addr, int rwi, int size, uae_u32 val) { bool ret = true; @@ -585,13 +618,16 @@ static bool debugmem_func(uaecptr addr, int rwi, int size, uae_u32 val) } if (!(rwi & DEBUGMEM_NOSTACKCHECK) || ((rwi & DEBUGMEM_NOSTACKCHECK) && !(dm->flags & DEBUGMEM_STACK))) { - if ((rwi & DEBUGMEM_FETCH) && !(state & DEBUGMEM_INITIALIZED)) { + if ((rwi & DEBUGMEM_FETCH) && !(state & DEBUGMEM_INITIALIZED) && !(state & DEBUGMEM_WRITE)) { debugreport(dm, oaddr, rwi, size, _T("Instruction fetch from uninitialized memory")); return false; } - - if ((rwi & DEBUGMEM_FETCH) && (state & DEBUGMEM_WRITE) && !(state & DEBUGMEM_FETCH)) { - debugreport(dm, oaddr, rwi, size, _T("Instruction fetch from memory that was modified")); + if ((rwi & DEBUGMEM_FETCH) && (state & DEBUGMEM_WRITE_NOCACHEFLUSH)) { + debugreport(dm, oaddr, rwi, size, _T("Instruction fetch from memory that was modified without flushing caches")); + return false; + } + if ((rwi & DEBUGMEM_FETCH) && (state & DEBUGMEM_WRITE) && (state & DEBUGMEM_FETCH)) { + debugreport(dm, oaddr, rwi, size, _T("Instruction fetch from memory that was modified after being executed at least once")); return false; } } @@ -611,6 +647,12 @@ static bool debugmem_func(uaecptr addr, int rwi, int size, uae_u32 val) return false; } } + if (rwi & DEBUGMEM_WRITE) { + rwi |= DEBUGMEM_WRITE_NOCACHEFLUSH; + dm->flags |= DEBUGMEM_WRITE_NOCACHEFLUSH; + } + if ((rwi & DEBUGMEM_FETCH) && (state & DEBUGMEM_WRITE)) + state &= ~(DEBUGMEM_WRITE | DEBUGMEM_WRITE_NOCACHEFLUSH); if ((state | rwi) != state) { //console_out_f(_T("addr %08x %d/%d (%02x -> %02x) PC=%08x\n"), addr, i, size, state, rwi, M68K_GETPC); dm->state[offset] |= rwi; diff --git a/include/debugmem.h b/include/debugmem.h index dc1d1c0d..c8aec21e 100644 --- a/include/debugmem.h +++ b/include/debugmem.h @@ -26,6 +26,7 @@ bool debugmem_break_stack_pop(void); bool debugmem_break_stack_push(void); bool debugmem_enable_stackframe(bool enable); bool debugmem_illg(uae_u16); +void debugmem_flushcache(uaecptr, int); extern uae_u32 debugmem_chiplimit; extern uae_u32 debugmem_chiphit(uaecptr addr, uae_u32 v, int size); diff --git a/newcpu.cpp b/newcpu.cpp index 6c431547..8a6d497d 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -1471,10 +1471,12 @@ void flush_cpu_caches(bool force) for (int i = 0; i < CACHELINES020; i++) caches020[i].valid = 0; regs.cacr &= ~0x08; + debugmem_flushcache(0, -1); } if (regs.cacr & 0x04) { // clear entry in instr cache caches020[(regs.caar >> 2) & (CACHELINES020 - 1)].valid = 0; regs.cacr &= ~0x04; + debugmem_flushcache(regs.caar, CACHELINES020); } } else if (currprefs.cpu_model == 68030) { if ((regs.cacr & 0x08) || force) { // clear instr cache @@ -1487,10 +1489,12 @@ void flush_cpu_caches(bool force) } } regs.cacr &= ~0x08; + debugmem_flushcache(0, -1); } if (regs.cacr & 0x04) { // clear entry in instr cache icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0; regs.cacr &= ~0x04; + debugmem_flushcache(regs.caar, CACHELINES030); } if ((regs.cacr & 0x800) || force) { // clear data cache if (doflush) { @@ -1517,6 +1521,7 @@ void flush_cpu_caches(bool force) icaches040[i].valid[j] = false; } } + debugmem_flushcache(0, -1); } } } @@ -1623,6 +1628,7 @@ static void flush_cpu_caches_040_2(int cache, int scope, uaecptr addr, bool push tagmask = cacheitag04060mask; index = (addr >> 4) & cacheisets04060mask; c = &icaches040[index]; + debugmem_flushcache(addr, 16); } else { tagmask = cachedtag04060mask; index = (addr >> 4) & cachedsets04060mask;