#define DEBUGMEM_INUSE 0x80
#define DEBUGMEM_PARTIAL 0x100
#define DEBUGMEM_NOSTACKCHECK 0x200
+#define DEBUGMEM_WRITE_NOCACHEFLUSH 0x400
#define DEBUGMEM_STACK 0x1000
struct debugmemdata
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);
}
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;
}
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;
}
}
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;
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
}
}
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) {
icaches040[i].valid[j] = false;
}
}
+ debugmem_flushcache(0, -1);
}
}
}
tagmask = cacheitag04060mask;
index = (addr >> 4) & cacheisets04060mask;
c = &icaches040[index];
+ debugmem_flushcache(addr, 16);
} else {
tagmask = cachedtag04060mask;
index = (addr >> 4) & cachedsets04060mask;