diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index 4d182d4c0..d9201f997 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -39,6 +39,9 @@ #define do_mmut_rb(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) do_mmutranslate((s)+(a), b, 1, 0) #define do_mmut_rw(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 0) #define do_mmut_rl(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) do_mmutranslate((s)+(a), b, 4, 0) +#define do_mmut_rb2(s,a,b) old_rl2 = readlookup2[(uint32_t)((s)+(a))>>12]; if (old_rl2==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) do_mmutranslate((s)+(a), b, 1, 0) +#define do_mmut_rw2(s,a,b) old_rl2 = readlookup2[(uint32_t)((s)+(a))>>12]; if (old_rl2==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 0) +#define do_mmut_rl2(s,a,b) old_rl2 = readlookup2[(uint32_t)((s)+(a))>>12]; if (old_rl2==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) do_mmutranslate((s)+(a), b, 4, 0) #define do_mmut_wb(s,a,b) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF) do_mmutranslate((s)+(a), b, 1, 1) #define do_mmut_ww(s,a,b) if (writelookup2[(uint32_t)((s)+(a))>>12]==(uintptr_t)LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 1) diff --git a/src/cpu/x86_ops_rep.h b/src/cpu/x86_ops_rep.h index 4d1f0ea61..d76613151 100644 --- a/src/cpu/x86_ops_rep.h +++ b/src/cpu/x86_ops_rep.h @@ -519,14 +519,18 @@ static int opREP_CMPSB_ ## size(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); \ SEG_CHECK_READ(&cpu_state.seg_es); \ CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ - high_page = 0; \ + high_page = uncached = 0; \ do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \ if (cpu_state.abrt) return 1; \ CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - do_mmut_rb(es, DEST_REG, &addr64_2); \ + do_mmut_rb2(es, DEST_REG, &addr64_2); \ if (cpu_state.abrt) return 1; \ temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); if (cpu_state.abrt) return 1; \ + if (uncached) \ + readlookup2[(uint32_t)(es+DEST_REG)>>12] = old_rl2; \ temp2 = readmemb_n(es, DEST_REG, addr64_2); if (cpu_state.abrt) return 1; \ + if (uncached) \ + readlookup2[(uint32_t)(es+DEST_REG)>>12] = (uintptr_t) LOOKUP_INV; \ \ if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ else { DEST_REG++; SRC_REG++; } \ @@ -559,14 +563,18 @@ static int opREP_CMPSW_ ## size(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); \ SEG_CHECK_READ(&cpu_state.seg_es); \ CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \ - high_page = 0; \ + high_page = uncached = 0; \ do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \ if (cpu_state.abrt) return 1; \ CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \ - do_mmut_rw(es, DEST_REG, addr64a_2); \ + do_mmut_rw2(es, DEST_REG, addr64a_2); \ if (cpu_state.abrt) return 1; \ temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); if (cpu_state.abrt) return 1; \ + if (uncached) \ + readlookup2[(uint32_t)(es+DEST_REG)>>12] = old_rl2; \ temp2 = readmemw_n(es, DEST_REG, addr64a_2); if (cpu_state.abrt) return 1; \ + if (uncached) \ + readlookup2[(uint32_t)(es+DEST_REG)>>12] = (uintptr_t) LOOKUP_INV; \ \ if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ else { DEST_REG += 2; SRC_REG += 2; } \ @@ -599,14 +607,18 @@ static int opREP_CMPSL_ ## size(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); \ SEG_CHECK_READ(&cpu_state.seg_es); \ CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \ - high_page = 0; \ + high_page = uncached = 0; \ do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \ if (cpu_state.abrt) return 1; \ CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \ - do_mmut_rl(es, DEST_REG, addr64a_2); \ + do_mmut_rl2(es, DEST_REG, addr64a_2); \ if (cpu_state.abrt) return 1; \ temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); if (cpu_state.abrt) return 1; \ + if (uncached) \ + readlookup2[(uint32_t)(es+DEST_REG)>>12] = old_rl2; \ temp2 = readmeml_n(es, DEST_REG, addr64a_2); if (cpu_state.abrt) return 1; \ + if (uncached) \ + readlookup2[(uint32_t)(es+DEST_REG)>>12] = (uintptr_t) LOOKUP_INV; \ \ if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ else { DEST_REG += 4; SRC_REG += 4; } \ diff --git a/src/cpu/x86_ops_string.h b/src/cpu/x86_ops_string.h index 675489aed..fbec20dd9 100644 --- a/src/cpu/x86_ops_string.h +++ b/src/cpu/x86_ops_string.h @@ -139,14 +139,18 @@ static int opCMPSB_a16(uint32_t fetchdat) addr64 = addr64_2 = 0x00000000; SEG_CHECK_READ(cpu_state.ea_seg); - high_page = 0; + high_page = uncached = 0; do_mmut_rb(cpu_state.ea_seg->base, SI, &addr64); if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - do_mmut_rb(es, DI, &addr64_2); + do_mmut_rb2(es, DI, &addr64_2); if (cpu_state.abrt) return 1; src = readmemb_n(cpu_state.ea_seg->base, SI, addr64); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+DI)>>12] = old_rl2; dst = readmemb_n(es, DI, addr64_2); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+DI)>>12] = (uintptr_t) LOOKUP_INV; setsub8(src, dst); if (cpu_state.flags & D_FLAG) { DI--; SI--; } else { DI++; SI++; } @@ -161,14 +165,18 @@ static int opCMPSB_a32(uint32_t fetchdat) addr64 = addr64_2 = 0x00000000; SEG_CHECK_READ(cpu_state.ea_seg); - high_page = 0; + high_page = uncached = 0; do_mmut_rb(cpu_state.ea_seg->base, ESI, &addr64); if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - do_mmut_rb(es, EDI, &addr64_2); + do_mmut_rb2(es, EDI, &addr64_2); if (cpu_state.abrt) return 1; src = readmemb_n(cpu_state.ea_seg->base, ESI, addr64); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+EDI)>>12] = old_rl2; dst = readmemb_n(es, EDI, addr64_2); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+EDI)>>12] = (uintptr_t) LOOKUP_INV; setsub8(src, dst); if (cpu_state.flags & D_FLAG) { EDI--; ESI--; } else { EDI++; ESI++; } @@ -185,14 +193,18 @@ static int opCMPSW_a16(uint32_t fetchdat) addr64a_2[0] = addr64a_2[1] = 0x00000000; SEG_CHECK_READ(cpu_state.ea_seg); - high_page = 0; + high_page = uncached = 0; do_mmut_rw(cpu_state.ea_seg->base, SI, addr64a); if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - do_mmut_rw(es, DI, addr64a_2); + do_mmut_rw2(es, DI, addr64a_2); if (cpu_state.abrt) return 1; src = readmemw_n(cpu_state.ea_seg->base, SI, addr64a); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+DI)>>12] = old_rl2; dst = readmemw_n(es, DI, addr64a_2); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+DI)>>12] = (uintptr_t) LOOKUP_INV; setsub16(src, dst); if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; } else { DI += 2; SI += 2; } @@ -208,14 +220,18 @@ static int opCMPSW_a32(uint32_t fetchdat) addr64a_2[0] = addr64a_2[1] = 0x00000000; SEG_CHECK_READ(cpu_state.ea_seg); - high_page = 0; + high_page = uncached = 0; do_mmut_rw(cpu_state.ea_seg->base, ESI, addr64a); if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - do_mmut_rw(es, EDI, addr64a_2); + do_mmut_rw2(es, EDI, addr64a_2); if (cpu_state.abrt) return 1; src = readmemw_n(cpu_state.ea_seg->base, ESI, addr64a); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+EDI)>>12] = old_rl2; dst = readmemw_n(es, EDI, addr64a_2); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+EDI)>>12] = (uintptr_t) LOOKUP_INV; setsub16(src, dst); if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; } else { EDI += 2; ESI += 2; } @@ -232,14 +248,18 @@ static int opCMPSL_a16(uint32_t fetchdat) addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; SEG_CHECK_READ(cpu_state.ea_seg); - high_page = 0; + high_page = uncached = 0; do_mmut_rl(cpu_state.ea_seg->base, SI, addr64a); if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - do_mmut_rl(es, DI, addr64a_2); + do_mmut_rl2(es, DI, addr64a_2); if (cpu_state.abrt) return 1; src = readmeml_n(cpu_state.ea_seg->base, SI, addr64a); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+DI)>>12] = old_rl2; dst = readmeml_n(es, DI, addr64a_2); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+DI)>>12] = (uintptr_t) LOOKUP_INV; setsub32(src, dst); if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; } else { DI += 4; SI += 4; } @@ -255,14 +275,18 @@ static int opCMPSL_a32(uint32_t fetchdat) addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; SEG_CHECK_READ(cpu_state.ea_seg); - high_page = 0; + high_page = uncached = 0; do_mmut_rl(cpu_state.ea_seg->base, ESI, addr64a); if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - do_mmut_rl(es, EDI, addr64a_2); + do_mmut_rl2(es, EDI, addr64a_2); if (cpu_state.abrt) return 1; src = readmeml_n(cpu_state.ea_seg->base, ESI, addr64a); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+EDI)>>12] = old_rl2; dst = readmeml_n(es, EDI, addr64a_2); if (cpu_state.abrt) return 1; + if (uncached) + readlookup2[(uint32_t)(es+EDI)>>12] = (uintptr_t) LOOKUP_INV; setsub32(src, dst); if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; } else { EDI += 4; ESI += 4; } diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index 52e1ba810..07d89c406 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -191,6 +191,8 @@ extern uint32_t biosmask, biosaddr; extern int readlookup[256]; extern uintptr_t * readlookup2; +extern uintptr_t old_rl2; +extern uint8_t uncached; extern int readlnext; extern int writelookup[256]; extern uintptr_t * writelookup2; diff --git a/src/mem/mem.c b/src/mem/mem.c index 73f89b3eb..000937341 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -82,6 +82,8 @@ uint8_t *pccache2; int readlnext; int readlookup[256]; uintptr_t *readlookup2; +uintptr_t old_rl2; +uint8_t uncached = 0; int writelnext; int writelookup[256]; uintptr_t *writelookup2; @@ -584,8 +586,11 @@ addreadlookup(uint32_t virt, uint32_t phys) if (readlookup2[virt>>12] != (uintptr_t) LOOKUP_INV) return; - if (readlookup[readlnext] != (int) 0xffffffff) + if (readlookup[readlnext] != (int) 0xffffffff) { + if ((readlookup[readlnext] == ((es + DI) >> 12)) || (readlookup[readlnext] == ((es + EDI) >> 12))) + uncached = 1; readlookup2[readlookup[readlnext]] = LOOKUP_INV; + } #if (defined __amd64__ || defined _M_X64) a = ((uint64_t)(phys & ~0xfff) - (uint64_t)(virt & ~0xfff)); @@ -1596,9 +1601,9 @@ void do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) { int i, cond = 1; - uint32_t old_addr = addr; + uint32_t last_addr = addr + (num - 1); uint64_t a = 0x0000000000000000ULL; - + for (i = 0; i < num; i++) a64[i] = (uint64_t) addr; @@ -1619,11 +1624,8 @@ do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) a64[i] = (uint32_t) a; high_page = high_page || (!cpu_state.abrt && (a > 0xffffffffULL)); - - if ((a <= 0xffffffffULL) && pages[addr >> 12].write_b) - write ? addwritelookup(addr, a64[i]) : addreadlookup(addr, a64[i]); } else if (!(addr & 0xfff)) { - a = mmutranslatereal(old_addr + (num - 1), write); + a = mmutranslatereal(last_addr, write); a64[i] = (uint32_t) a; high_page = high_page || (!cpu_state.abrt && (a64[i] > 0xffffffffULL)); @@ -1632,9 +1634,6 @@ do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); a64[i] = (uint32_t) a; } - - if ((a <= 0xffffffffULL) && pages[addr >> 12].write_b) - write ? addwritelookup(addr, a64[i]) : addreadlookup(addr, a64[i]); } else { a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); a64[i] = (uint32_t) a;