diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index ed4bc84d7..61f68b693 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -21,16 +21,30 @@ #include +#define readmemb_n(s,a,b) ((readlookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF)?readmembl_no_mmut((s)+(a),b): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uintptr_t)((s) + (a))) ) +#define readmemw_n(s,a,b) ((readlookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl_no_mmut((s)+(a),b):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) +#define readmeml_n(s,a,b) ((readlookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll_no_mmut((s)+(a),b):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) #define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uintptr_t)((s) + (a))) ) #define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) #define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a)))) #define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uintptr_t)((s)+(a)))) +#define writememb_n(s,a,b,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF) writemembl_no_mmut((s)+(a),b,v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v +#define writememw_n(s,a,b,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl_no_mmut((s)+(a),b,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v +#define writememl_n(s,a,b,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll_no_mmut((s)+(a),b,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v #define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF) writemembl((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v #define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v #define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v #define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 7)) writememql((s)+(a),v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uintptr_t)((s) + (a))) = v +#define do_mmut_rb(s,a,b) if (readlookup2[(uint32_t)((s)+(a))>>12]==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]==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]==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]==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]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) do_mmutranslate((s)+(a), b, 2, 1) +#define do_mmut_wl(s,a,b) if (writelookup2[(uint32_t)((s)+(a))>>12]==LOOKUP_INV || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) do_mmutranslate((s)+(a), b, 4, 1) + int checkio(int port); @@ -82,12 +96,6 @@ int checkio(int port); else \ x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ return 1; \ - } \ - if (cr0 >> 31) { \ - (void) mmutranslatereal((chseg)->base + low, 0); \ - (void) mmutranslatereal((chseg)->base + high, 0); \ - if (cpu_state.abrt) \ - return 1; \ } #define CHECK_READ_REP(chseg, low, high) \ @@ -103,12 +111,6 @@ int checkio(int port); else \ x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ break; \ - } \ - if (cr0 >> 31) { \ - (void) mmutranslatereal((chseg)->base + low, 0); \ - (void) mmutranslatereal((chseg)->base + high, 0); \ - if (cpu_state.abrt) \ - break; \ } #define CHECK_WRITE_COMMON(chseg, low, high) \ @@ -127,13 +129,7 @@ int checkio(int port); } #define CHECK_WRITE(chseg, low, high) \ - CHECK_WRITE_COMMON(chseg, low, high) \ - if (cr0 >> 31) { \ - (void) mmutranslatereal((chseg)->base + low, 1); \ - (void) mmutranslatereal((chseg)->base + high, 1); \ - if (cpu_state.abrt) \ - return 1; \ - } + CHECK_WRITE_COMMON(chseg, low, high) #define CHECK_WRITE_REP(chseg, low, high) \ if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \ @@ -148,12 +144,6 @@ int checkio(int port); else \ x86np("Write (REP) to seg not present", (chseg)->seg & 0xfffc); \ break; \ - } \ - if (cr0 >> 31) { \ - (void) mmutranslatereal((chseg)->base + low, 1); \ - (void) mmutranslatereal((chseg)->base + high, 1); \ - if (cpu_state.abrt) \ - break; \ } diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 062ba292a..1d17496fa 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -262,6 +262,10 @@ int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer; int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate; int timing_misaligned; +uint8_t do_translate = 0, do_translate2 = 0; + +void (*cpu_exec)(int cycs); + static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6; @@ -1872,6 +1876,18 @@ cpu_set(void) default: x87_timings = x87_timings_486; } + + if (is386) { +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + cpu_exec = exec386_dynarec; + else +#endif + cpu_exec = exec386; + } else if (cpu_s->cpu_type >= CPU_286) + cpu_exec = exec386; + else + cpu_exec = execx86; } diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index c340cbebb..e3e90a845 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -614,4 +614,7 @@ typedef struct extern cyrix_t cyrix; +extern void (*cpu_exec)(int cycs); +extern uint8_t do_translate, do_translate2; + #endif /*EMU_CPU_H*/ diff --git a/src/cpu/x86_ops_rep.h b/src/cpu/x86_ops_rep.h index eb422e16d..e276fe90e 100644 --- a/src/cpu/x86_ops_rep.h +++ b/src/cpu/x86_ops_rep.h @@ -2,6 +2,7 @@ static int opREP_INSB_ ## size(uint32_t fetchdat) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ + uint64_t addr64 = 0x0000000000000000ULL; \ \ if (CNT_REG > 0) \ { \ @@ -10,8 +11,10 @@ static int opREP_INSB_ ## size(uint32_t fetchdat) SEG_CHECK_WRITE(&cpu_state.seg_es); \ check_io_perm(DX); \ CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \ + do_mmut_wb(es, DEST_REG, &addr64); \ + if (cpu_state.abrt) return 1; \ temp = inb(DX); \ - writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + writememb_n(es, DEST_REG, addr64, temp); if (cpu_state.abrt) return 1; \ \ if (cpu_state.flags & D_FLAG) DEST_REG--; \ else DEST_REG++; \ @@ -31,6 +34,7 @@ static int opREP_INSB_ ## size(uint32_t fetchdat) static int opREP_INSW_ ## size(uint32_t fetchdat) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ + uint64_t addr64[2]; \ \ if (CNT_REG > 0) \ { \ @@ -40,8 +44,10 @@ static int opREP_INSW_ ## size(uint32_t fetchdat) check_io_perm(DX); \ check_io_perm(DX+1); \ CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \ + do_mmut_ww(es, DEST_REG, addr64); \ + if (cpu_state.abrt) return 1; \ temp = inw(DX); \ - writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + writememw_n(es, DEST_REG, addr64, temp); if (cpu_state.abrt) return 1; \ \ if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ else DEST_REG += 2; \ @@ -61,6 +67,7 @@ static int opREP_INSW_ ## size(uint32_t fetchdat) static int opREP_INSL_ ## size(uint32_t fetchdat) \ { \ int reads = 0, writes = 0, total_cycles = 0; \ + uint64_t addr64[4]; \ \ if (CNT_REG > 0) \ { \ @@ -72,8 +79,10 @@ static int opREP_INSL_ ## size(uint32_t fetchdat) check_io_perm(DX+2); \ check_io_perm(DX+3); \ CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \ + do_mmut_wl(es, DEST_REG, addr64); \ + if (cpu_state.abrt) return 1; \ temp = inl(DX); \ - writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + writememl_n(es, DEST_REG, addr64, temp); if (cpu_state.abrt) return 1; \ \ if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ else DEST_REG += 4; \ @@ -181,6 +190,8 @@ static int opREP_MOVSB_ ## size(uint32_t fetchdat) { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + uint64_t addr64r = 0x0000000000000000ULL; \ + uint64_t addr64w = 0x0000000000000000ULL; \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ if (CNT_REG > 0) \ @@ -193,9 +204,13 @@ static int opREP_MOVSB_ ## size(uint32_t fetchdat) uint8_t temp; \ \ CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ + do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64r); \ + if (cpu_state.abrt) break; \ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + do_mmut_wb(es, DEST_REG, &addr64w); \ + if (cpu_state.abrt) break; \ + temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64r); if (cpu_state.abrt) return 1; \ + writememb_n(es, DEST_REG, addr64w, temp); if (cpu_state.abrt) return 1; \ \ if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ else { DEST_REG++; SRC_REG++; } \ @@ -218,6 +233,8 @@ static int opREP_MOVSW_ ## size(uint32_t fetchdat) { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + uint64_t addr64r[2]; \ + uint64_t addr64w[2]; \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ if (CNT_REG > 0) \ @@ -230,9 +247,13 @@ static int opREP_MOVSW_ ## size(uint32_t fetchdat) uint16_t temp; \ \ CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1); \ + do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64r); \ + if (cpu_state.abrt) break; \ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \ - temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + do_mmut_ww(es, DEST_REG, addr64w); \ + if (cpu_state.abrt) break; \ + temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64r); if (cpu_state.abrt) return 1; \ + writememw_n(es, DEST_REG, addr64w, temp); if (cpu_state.abrt) return 1; \ \ if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ else { DEST_REG += 2; SRC_REG += 2; } \ @@ -255,6 +276,8 @@ static int opREP_MOVSL_ ## size(uint32_t fetchdat) { \ int reads = 0, writes = 0, total_cycles = 0; \ int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ + uint64_t addr64r[4]; \ + uint64_t addr64w[4]; \ if (trap) \ cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ if (CNT_REG > 0) \ @@ -267,9 +290,13 @@ static int opREP_MOVSL_ ## size(uint32_t fetchdat) uint32_t temp; \ \ CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3); \ + do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64r); \ + if (cpu_state.abrt) break; \ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \ - temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ + do_mmut_wl(es, DEST_REG, addr64w); \ + if (cpu_state.abrt) break; \ + temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64r); if (cpu_state.abrt) return 1; \ + writememl_n(es, DEST_REG, addr64w, temp); if (cpu_state.abrt) return 1; \ \ if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ else { DEST_REG += 4; SRC_REG += 4; } \ @@ -467,10 +494,15 @@ static int opREP_LODSL_ ## size(uint32_t fetchdat) } \ +#define CHEK_READ(a, b, c) + + #define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ static int opREP_CMPSB_ ## size(uint32_t fetchdat) \ { \ int reads = 0, total_cycles = 0, tempz; \ + uint64_t addr64 = 0x0000000000000000ULL; \ + uint64_t addr642 = 0x0000000000000000ULL; \ \ tempz = FV; \ if ((CNT_REG > 0) && (FV == tempz)) \ @@ -479,9 +511,12 @@ 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); \ + do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \ CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ - temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \ + do_mmut_rb(es, DEST_REG, &addr642); \ + if (cpu_state.abrt) return 1; \ + temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \ + temp2 = readmemb_n(es, DEST_REG, addr642); if (cpu_state.abrt) return 1; \ \ if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ else { DEST_REG++; SRC_REG++; } \ @@ -503,6 +538,8 @@ static int opREP_CMPSB_ ## size(uint32_t fetchdat) static int opREP_CMPSW_ ## size(uint32_t fetchdat) \ { \ int reads = 0, total_cycles = 0, tempz; \ + uint64_t addr64[2]; \ + uint64_t addr642[2]; \ \ tempz = FV; \ if ((CNT_REG > 0) && (FV == tempz)) \ @@ -511,9 +548,12 @@ 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 + 1); \ + do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64); \ CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \ - temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ - temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \ + do_mmut_rw(es, DEST_REG, addr642); \ + if (cpu_state.abrt) return 1; \ + temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64); \ + temp2 = readmemw_n(es, DEST_REG, addr642); if (cpu_state.abrt) return 1; \ \ if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ else { DEST_REG += 2; SRC_REG += 2; } \ @@ -535,6 +575,8 @@ static int opREP_CMPSW_ ## size(uint32_t fetchdat) static int opREP_CMPSL_ ## size(uint32_t fetchdat) \ { \ int reads = 0, total_cycles = 0, tempz; \ + uint64_t addr64[4]; \ + uint64_t addr642[4]; \ \ tempz = FV; \ if ((CNT_REG > 0) && (FV == tempz)) \ @@ -543,9 +585,12 @@ 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 + 3); \ + do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64); \ CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \ - temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ - temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \ + do_mmut_rl(es, DEST_REG, addr642); \ + if (cpu_state.abrt) return 1; \ + temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64); \ + temp2 = readmeml_n(es, DEST_REG, addr642); if (cpu_state.abrt) return 1; \ \ 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 c02725138..2cdbd7959 100644 --- a/src/cpu/x86_ops_string.h +++ b/src/cpu/x86_ops_string.h @@ -1,11 +1,17 @@ static int opMOVSB_a16(uint32_t fetchdat) { uint8_t temp; + uint64_t addr64r; + uint64_t addr64w; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rb(cpu_state.ea_seg->base, SI, &addr64r); + if (cpu_state.abrt) return 1; SEG_CHECK_WRITE(&cpu_state.seg_es); - temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - writememb(es, DI, temp); if (cpu_state.abrt) return 1; + do_mmut_wb(es, DI, &addr64w); + if (cpu_state.abrt) return 1; + temp = readmemb_n(cpu_state.ea_seg->base, SI, addr64r); if (cpu_state.abrt) return 1; + writememb_n(es, DI, addr64w, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) { DI--; SI--; } else { DI++; SI++; } CLOCK_CYCLES(7); @@ -15,11 +21,17 @@ static int opMOVSB_a16(uint32_t fetchdat) static int opMOVSB_a32(uint32_t fetchdat) { uint8_t temp; + uint64_t addr64r; + uint64_t addr64w; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rb(cpu_state.ea_seg->base, ESI, &addr64r); + if (cpu_state.abrt) return 1; SEG_CHECK_WRITE(&cpu_state.seg_es); - temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - writememb(es, EDI, temp); if (cpu_state.abrt) return 1; + do_mmut_wb(es, EDI, &addr64w); + if (cpu_state.abrt) return 1; + temp = readmemb_n(cpu_state.ea_seg->base, ESI, addr64r); if (cpu_state.abrt) return 1; + writememb_n(es, EDI, addr64w, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) { EDI--; ESI--; } else { EDI++; ESI++; } CLOCK_CYCLES(7); @@ -30,11 +42,17 @@ static int opMOVSB_a32(uint32_t fetchdat) static int opMOVSW_a16(uint32_t fetchdat) { uint16_t temp; + uint64_t addr64r[2]; + uint64_t addr64w[2]; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rw(cpu_state.ea_seg->base, SI, addr64r); + if (cpu_state.abrt) return 1; SEG_CHECK_WRITE(&cpu_state.seg_es); - temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - writememw(es, DI, temp); if (cpu_state.abrt) return 1; + do_mmut_ww(es, DI, addr64w); + if (cpu_state.abrt) return 1; + temp = readmemw_n(cpu_state.ea_seg->base, SI, addr64r); if (cpu_state.abrt) return 1; + writememw_n(es, DI, addr64w, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; } else { DI += 2; SI += 2; } CLOCK_CYCLES(7); @@ -44,11 +62,17 @@ static int opMOVSW_a16(uint32_t fetchdat) static int opMOVSW_a32(uint32_t fetchdat) { uint16_t temp; + uint64_t addr64r[2]; + uint64_t addr64w[2]; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rw(cpu_state.ea_seg->base, ESI, addr64r); + if (cpu_state.abrt) return 1; SEG_CHECK_WRITE(&cpu_state.seg_es); - temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - writememw(es, EDI, temp); if (cpu_state.abrt) return 1; + do_mmut_ww(es, EDI, addr64w); + if (cpu_state.abrt) return 1; + temp = readmemw_n(cpu_state.ea_seg->base, ESI, addr64r); if (cpu_state.abrt) return 1; + writememw_n(es, EDI, addr64w, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; } else { EDI += 2; ESI += 2; } CLOCK_CYCLES(7); @@ -59,11 +83,17 @@ static int opMOVSW_a32(uint32_t fetchdat) static int opMOVSL_a16(uint32_t fetchdat) { uint32_t temp; + uint64_t addr64r[4]; + uint64_t addr64w[4]; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rl(cpu_state.ea_seg->base, SI, addr64r); + if (cpu_state.abrt) return 1; SEG_CHECK_WRITE(&cpu_state.seg_es); - temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1; - writememl(es, DI, temp); if (cpu_state.abrt) return 1; + do_mmut_wl(es, DI, addr64w); + if (cpu_state.abrt) return 1; + temp = readmeml_n(cpu_state.ea_seg->base, SI, addr64r); if (cpu_state.abrt) return 1; + writememl_n(es, DI, addr64w, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; } else { DI += 4; SI += 4; } CLOCK_CYCLES(7); @@ -73,11 +103,17 @@ static int opMOVSL_a16(uint32_t fetchdat) static int opMOVSL_a32(uint32_t fetchdat) { uint32_t temp; + uint64_t addr64r[4]; + uint64_t addr64w[4]; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rl(cpu_state.ea_seg->base, ESI, addr64r); + if (cpu_state.abrt) return 1; SEG_CHECK_WRITE(&cpu_state.seg_es); - temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1; - writememl(es, EDI, temp); if (cpu_state.abrt) return 1; + do_mmut_wl(es, EDI, addr64w); + if (cpu_state.abrt) return 1; + temp = readmeml_n(cpu_state.ea_seg->base, ESI, addr64r); if (cpu_state.abrt) return 1; + writememl_n(es, EDI, addr64w, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; } else { EDI += 4; ESI += 4; } CLOCK_CYCLES(7); @@ -89,11 +125,17 @@ static int opMOVSL_a32(uint32_t fetchdat) static int opCMPSB_a16(uint32_t fetchdat) { uint8_t src, dst; + uint64_t addr64; + uint64_t addr642; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rb(cpu_state.ea_seg->base, SI, &addr64); + if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - src = readmemb(cpu_state.ea_seg->base, SI); - dst = readmemb(es, DI); if (cpu_state.abrt) return 1; + do_mmut_rb(es, DI, &addr642); + if (cpu_state.abrt) return 1; + src = readmemb_n(cpu_state.ea_seg->base, SI, addr64); + dst = readmemb_n(es, DI, addr642); if (cpu_state.abrt) return 1; setsub8(src, dst); if (cpu_state.flags & D_FLAG) { DI--; SI--; } else { DI++; SI++; } @@ -104,11 +146,17 @@ static int opCMPSB_a16(uint32_t fetchdat) static int opCMPSB_a32(uint32_t fetchdat) { uint8_t src, dst; + uint64_t addr64; + uint64_t addr642; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rb(cpu_state.ea_seg->base, ESI, &addr64); + if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - src = readmemb(cpu_state.ea_seg->base, ESI); - dst = readmemb(es, EDI); if (cpu_state.abrt) return 1; + do_mmut_rb(es, EDI, &addr642); + if (cpu_state.abrt) return 1; + src = readmemb_n(cpu_state.ea_seg->base, ESI, addr64); + dst = readmemb_n(es, EDI, addr642); if (cpu_state.abrt) return 1; setsub8(src, dst); if (cpu_state.flags & D_FLAG) { EDI--; ESI--; } else { EDI++; ESI++; } @@ -120,11 +168,17 @@ static int opCMPSB_a32(uint32_t fetchdat) static int opCMPSW_a16(uint32_t fetchdat) { uint16_t src, dst; + uint64_t addr64[2]; + uint64_t addr642[2]; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rw(cpu_state.ea_seg->base, SI, addr64); + if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - src = readmemw(cpu_state.ea_seg->base, SI); - dst = readmemw(es, DI); if (cpu_state.abrt) return 1; + do_mmut_rw(es, DI, addr642); + if (cpu_state.abrt) return 1; + src = readmemw_n(cpu_state.ea_seg->base, SI, addr64); + dst = readmemw_n(es, DI, addr642); if (cpu_state.abrt) return 1; setsub16(src, dst); if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; } else { DI += 2; SI += 2; } @@ -135,11 +189,17 @@ static int opCMPSW_a16(uint32_t fetchdat) static int opCMPSW_a32(uint32_t fetchdat) { uint16_t src, dst; + uint64_t addr64[2]; + uint64_t addr642[2]; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rw(cpu_state.ea_seg->base, ESI, addr64); + if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - src = readmemw(cpu_state.ea_seg->base, ESI); - dst = readmemw(es, EDI); if (cpu_state.abrt) return 1; + do_mmut_rw(es, EDI, addr642); + if (cpu_state.abrt) return 1; + src = readmemw_n(cpu_state.ea_seg->base, ESI, addr64); + dst = readmemw_n(es, EDI, addr642); if (cpu_state.abrt) return 1; setsub16(src, dst); if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; } else { EDI += 2; ESI += 2; } @@ -151,11 +211,17 @@ static int opCMPSW_a32(uint32_t fetchdat) static int opCMPSL_a16(uint32_t fetchdat) { uint32_t src, dst; + uint64_t addr64[4]; + uint64_t addr642[4]; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rl(cpu_state.ea_seg->base, SI, addr64); + if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - src = readmeml(cpu_state.ea_seg->base, SI); - dst = readmeml(es, DI); if (cpu_state.abrt) return 1; + do_mmut_rl(es, DI, addr642); + if (cpu_state.abrt) return 1; + src = readmeml_n(cpu_state.ea_seg->base, SI, addr64); + dst = readmeml_n(es, DI, addr642); if (cpu_state.abrt) return 1; setsub32(src, dst); if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; } else { DI += 4; SI += 4; } @@ -166,11 +232,17 @@ static int opCMPSL_a16(uint32_t fetchdat) static int opCMPSL_a32(uint32_t fetchdat) { uint32_t src, dst; + uint64_t addr64[4]; + uint64_t addr642[4]; SEG_CHECK_READ(cpu_state.ea_seg); + do_mmut_rl(cpu_state.ea_seg->base, ESI, addr64); + if (cpu_state.abrt) return 1; SEG_CHECK_READ(&cpu_state.seg_es); - src = readmeml(cpu_state.ea_seg->base, ESI); - dst = readmeml(es, EDI); if (cpu_state.abrt) return 1; + do_mmut_rl(es, EDI, addr642); + if (cpu_state.abrt) return 1; + src = readmeml_n(cpu_state.ea_seg->base, ESI, addr64); + dst = readmeml_n(es, EDI, addr642); if (cpu_state.abrt) return 1; setsub32(src, dst); if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; } else { EDI += 4; ESI += 4; } @@ -409,11 +481,13 @@ static int opSCASL_a32(uint32_t fetchdat) static int opINSB_a16(uint32_t fetchdat) { uint8_t temp; + uint64_t addr64 = 0x0000000000000000ULL; SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); + do_mmut_wb(es, DI, &addr64); if (cpu_state.abrt) return 1; temp = inb(DX); - writememb(es, DI, temp); if (cpu_state.abrt) return 1; + writememb_n(es, DI, addr64, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) DI--; else DI++; CLOCK_CYCLES(15); @@ -423,11 +497,13 @@ static int opINSB_a16(uint32_t fetchdat) static int opINSB_a32(uint32_t fetchdat) { uint8_t temp; + uint64_t addr64 = 0x0000000000000000ULL; SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); + do_mmut_wb(es, EDI, &addr64); if (cpu_state.abrt) return 1; temp = inb(DX); - writememb(es, EDI, temp); if (cpu_state.abrt) return 1; + writememb_n(es, EDI, addr64, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) EDI--; else EDI++; CLOCK_CYCLES(15); @@ -438,12 +514,14 @@ static int opINSB_a32(uint32_t fetchdat) static int opINSW_a16(uint32_t fetchdat) { uint16_t temp; + uint64_t addr64[2]; SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); + do_mmut_ww(es, DI, addr64); if (cpu_state.abrt) return 1; temp = inw(DX); - writememw(es, DI, temp); if (cpu_state.abrt) return 1; + writememw_n(es, DI, addr64, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) DI -= 2; else DI += 2; CLOCK_CYCLES(15); @@ -453,12 +531,14 @@ static int opINSW_a16(uint32_t fetchdat) static int opINSW_a32(uint32_t fetchdat) { uint16_t temp; + uint64_t addr64[2]; SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); + do_mmut_ww(es, EDI, addr64); if (cpu_state.abrt) return 1; temp = inw(DX); - writememw(es, EDI, temp); if (cpu_state.abrt) return 1; + writememw_n(es, EDI, addr64, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) EDI -= 2; else EDI += 2; CLOCK_CYCLES(15); @@ -469,14 +549,16 @@ static int opINSW_a32(uint32_t fetchdat) static int opINSL_a16(uint32_t fetchdat) { uint32_t temp; + uint64_t addr64[4]; SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); check_io_perm(DX + 3); + do_mmut_wl(es, DI, addr64); if (cpu_state.abrt) return 1; temp = inl(DX); - writememl(es, DI, temp); if (cpu_state.abrt) return 1; + writememl_n(es, DI, addr64, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) DI -= 4; else DI += 4; CLOCK_CYCLES(15); @@ -486,14 +568,16 @@ static int opINSL_a16(uint32_t fetchdat) static int opINSL_a32(uint32_t fetchdat) { uint32_t temp; + uint64_t addr64[4]; SEG_CHECK_WRITE(&cpu_state.seg_es); check_io_perm(DX); check_io_perm(DX + 1); check_io_perm(DX + 2); check_io_perm(DX + 3); + do_mmut_wl(es, DI, addr64); if (cpu_state.abrt) return 1; temp = inl(DX); - writememl(es, EDI, temp); if (cpu_state.abrt) return 1; + writememl_n(es, EDI, addr64, temp); if (cpu_state.abrt) return 1; if (cpu_state.flags & D_FLAG) EDI -= 4; else EDI += 4; CLOCK_CYCLES(15); diff --git a/src/dma.c b/src/dma.c index 55338e9e4..fca5a4796 100644 --- a/src/dma.c +++ b/src/dma.c @@ -1661,4 +1661,6 @@ dma_bm_write(uint32_t PhysAddress, const uint8_t *DataWrite, uint32_t TotalSize, memcpy(bytes, (void *) &(DataWrite[n]), n2); mem_write_phys((void *) bytes, PhysAddress + n, TransferSize); } + + mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); } diff --git a/src/mem/mem.c b/src/mem/mem.c index ae716718e..fcb6ccde2 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -112,8 +112,6 @@ uint64_t *byte_code_present_mask; uint32_t purgable_page_list_head = 0; int purgeable_page_count = 0; -int use_phys_exec = 0; - /* FIXME: re-do this with a 'mem_ops' struct. */ static mem_mapping_t *base_mapping, *last_mapping; @@ -275,6 +273,7 @@ mem_flush_write_page(uint32_t addr, uint32_t virt) #define rammap(x) ((uint32_t *)(_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 2) & MEM_GRANULARITY_QMASK] #define rammap64(x) ((uint64_t *)(_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 3) & MEM_GRANULARITY_PMASK] + static __inline uint64_t mmutranslatereal_normal(uint32_t addr, int rw) { @@ -415,6 +414,10 @@ mmutranslatereal_pae(uint32_t addr, int rw) uint64_t mmutranslatereal(uint32_t addr, int rw) { + /* Fast path to return invalid without any call if an exception has occurred beforehand. */ + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + if (cr4 & CR4_PAE) return mmutranslatereal_pae(addr, rw); else @@ -426,6 +429,10 @@ mmutranslatereal(uint32_t addr, int rw) uint32_t mmutranslatereal32(uint32_t addr, int rw) { + /* Fast path to return invalid without any call if an exception has occurred beforehand. */ + if (cpu_state.abrt) + return (uint32_t) 0xffffffffffffffffULL; + return (uint32_t) mmutranslatereal(addr, rw); } @@ -507,6 +514,10 @@ mmutranslate_noabrt_pae(uint32_t addr, int rw) uint64_t mmutranslate_noabrt(uint32_t addr, int rw) { + /* Fast path to return invalid without any call if an exception has occurred beforehand. */ + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + if (cr4 & CR4_PAE) return mmutranslate_noabrt_pae(addr, rw); else @@ -764,8 +775,6 @@ readmembl(uint32_t addr) if (cr0 >> 31) { addr64 = mmutranslate_read(addr); - if (addr64 == 0xffffffffffffffffULL) - return 0xff; if (addr64 > 0xffffffffULL) return 0xff; } @@ -793,8 +802,6 @@ writemembl(uint32_t addr, uint8_t val) if (cr0 >> 31) { addr64 = mmutranslate_write(addr); - if (addr64 == 0xffffffffffffffffULL) - return; if (addr64 > 0xffffffffULL) return; } @@ -806,95 +813,117 @@ writemembl(uint32_t addr, uint8_t val) } -void -rwmembl(uint32_t raddr, uint32_t waddr, uint8_t val) +/* Read a byte from memory without MMU translation - result of previous MMU translation passed as value. */ +uint8_t +readmembl_no_mmut(uint32_t addr, uint64_t addr64) { - uint64_t raddr64 = (uint64_t) raddr; - uint64_t waddr64 = (uint64_t) waddr; - mem_mapping_t *rmap, *wmap; - uint8_t temp = 0xff; - - mem_logical_addr = raddr; - - if (cr0 >> 31) { - raddr64 = mmutranslate_read(raddr); - if (raddr64 == 0xffffffffffffffffULL) - goto do_writebl; - if (raddr64 > 0xffffffffULL) - goto do_writebl; - } - raddr = (uint32_t) (raddr64 & rammask); - - rmap = read_mapping[raddr >> MEM_GRANULARITY_BITS]; - if (rmap && rmap->read_b) - temp = rmap->read_b(raddr, rmap->p); - -do_writebl: - if (cpu_state.abrt) - return; - - mem_logical_addr = waddr; - - if (page_lookup[waddr >> 12] && page_lookup[waddr >> 12]->write_b) { - page_lookup[waddr >> 12]->write_b(waddr, temp, page_lookup[waddr >> 12]); - return; - } - - if (cr0 >> 31) { - waddr64 = mmutranslate_write(waddr); - if (waddr64 == 0xffffffffffffffffULL) - return; - if (waddr64 > 0xffffffffULL) - return; - } - waddr = (uint32_t) (waddr64 & rammask); - - wmap = write_mapping[waddr >> MEM_GRANULARITY_BITS]; - if (wmap && wmap->write_b) - wmap->write_b(waddr, temp, wmap->p); -} - - -#ifdef USE_NEW_DYNAREC -uint16_t -readmemwl(uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; mem_mapping_t *map; mem_logical_addr = addr; - if (addr64 & 1) { - if (!cpu_cyrix_alignment || (addr64 & 7) == 7) - cycles -= timing_misaligned; - if ((addr64 & 0xfff) > 0xffe) { - if (cr0 >> 31) { - if (mmutranslate_read(addr) == 0xffffffffffffffffULL) - return 0xffff; - if (mmutranslate_read(addr+1) == 0xffffffffffffffffULL) - return 0xffff; - } - return readmembl(addr)|(readmembl(addr+1)<<8); - } else if (readlookup2[addr >> 12] != LOOKUP_INV) - return *(uint16_t *)(readlookup2[addr >> 12] + addr); - } - if (cr0>>31) { - addr64 = mmutranslate_read(addr); - if (addr64 == 0xffffffffffffffffULL) - return 0xffff; + if (cr0 >> 31) { if (addr64 > 0xffffffffULL) - return 0xffff; + return 0xff; + + addr = (uint32_t) (addr64 & rammask); + } else + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_b) + return map->read_b(addr, map->p); + + return 0xff; +} + + +/* Write a byte to memory without MMU translation - result of previous MMU translation passed as value. */ +void +writemembl_no_mmut(uint32_t addr, uint64_t addr64, uint8_t val) +{ + mem_mapping_t *map; + mem_logical_addr = addr; + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_b) { + page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); + return; } - addr = (uint32_t) (addr64 & rammask); + if (cr0 >> 31) { + if (addr64 > 0xffffffffULL) + return; + + addr = (uint32_t) (addr64 & rammask); + } else + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->write_b) + map->write_b(addr, val, map->p); +} + + +uint16_t +readmemwl(uint32_t addr) +{ + uint64_t addr64[2]; + mem_mapping_t *map; + int i; + uint16_t ret = 0x0000; + uint32_t prev_page = 0xffffffff; + + addr64[0] = (uint64_t) addr; + addr64[1] = (uint64_t) (addr + 1); + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + for (i = 0; i < 2; i++) { + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + if ((i > 0) && (((addr + i) & ~0xfff) == prev_page)) + addr64[i] = (addr64[i - 1] & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + else + addr64[i] = mmutranslate_read(addr + i); + + prev_page = ((addr + i) & ~0xfff); + + if (addr64[i] > 0xffffffffULL) + return 0xffff; + } + } + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + for (i = 0; i < 2; i++) + ret |= (readmembl_no_mmut(addr + i, addr64[i]) << (i << 3)); + + return ret; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) + return *(uint16_t *)(readlookup2[addr >> 12] + addr); + } + + if (cr0 >> 31) { + addr64[0] = mmutranslate_read(addr); + if (addr64[0] > 0xffffffffULL) + return 0xffff; + } else + addr64[0] = (uint64_t) addr; + + addr = (uint32_t) (addr64[0] & rammask); map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_w) return map->read_w(addr, map->p); - if (map && map->read_b) - return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); + if (map && map->read_b) { + return map->read_b(addr, map->p) | + ((uint16_t) (map->read_b(addr + 1, map->p)) << 8); + } return 0xffff; } @@ -903,52 +932,181 @@ readmemwl(uint32_t addr) void writememwl(uint32_t addr, uint16_t val) { - uint64_t addr64 = (uint64_t) addr; + uint64_t addr64[2]; mem_mapping_t *map; + int i; + uint32_t prev_page = 0xffffffff; + + addr64[0] = (uint64_t) addr; + addr64[1] = (uint64_t) (addr + 1); mem_logical_addr = addr; if (addr & 1) { if (!cpu_cyrix_alignment || (addr & 7) == 7) cycles -= timing_misaligned; - if ((addr & 0xFFF) > 0xFFE) { + if ((addr & 0xfff) > 0xffe) { if (cr0 >> 31) { - if (mmutranslate_write(addr) == 0xffffffff) - return; - if (mmutranslate_write(addr+1) == 0xffffffff) - return; + for (i = 0; i < 2; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + if ((i > 0) && (((addr + i) & ~0xfff) == prev_page)) + addr64[i] = (addr64[i - 1] & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + else + addr64[i] = mmutranslate_write(addr + i); + + prev_page = ((addr + i) & ~0xfff); + + if (addr64[i] > 0xffffffffULL) + return; + } else + prev_page = 0xffffffff; + } } - writemembl(addr,val); - writemembl(addr+1,val>>8); + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + for (i = 0; i < 2; i++) + writemembl_no_mmut(addr + i, addr64[i], val >> (i << 3)); + return; - } else if (writelookup2[addr >> 12] != LOOKUP_INV) { + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { *(uint16_t *)(writelookup2[addr >> 12] + addr) = val; return; } } - if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_w) { - page_lookup[addr>>12]->write_w(addr, val, page_lookup[addr>>12]); + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { + page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); return; } - if (cr0>>31) { - addr64 = mmutranslate_write(addr); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } - addr = (uint32_t) (addr64 & rammask); + if (cr0 >> 31) { + addr64[0] = mmutranslate_write(addr); + if (addr64[0] > 0xffffffffULL) + return; + } else + addr64[0] = (uint64_t) addr; + + addr = (uint32_t) (addr64[0] & rammask); map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_w) - map->write_w(addr, val, map->p); - else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); + + if (map && map->write_w) { + map->write_w(addr, val, map->p); + return; + } + + if (map && map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + return; + } +} + + +/* Read a word from memory without MMU translation - results of previous MMU translation passed as array. */ +uint16_t +readmemwl_no_mmut(uint32_t addr, uint64_t *addr64) +{ + mem_mapping_t *map; + int i; + uint16_t ret = 0x0000; + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + for (i = 0; i < 2; i++) { + if ((cr0 >> 31) && (addr64[i] > 0xffffffffULL)) + return 0xffff; + + ret |= (readmembl_no_mmut(addr + i, addr64[i]) << (i << 3)); + } + + return ret; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) + return *(uint16_t *)(readlookup2[addr >> 12] + addr); + } + + if (cr0 >> 31) { + if (addr64[0] > 0xffffffffULL) + return 0xffff; + + addr = (uint32_t) (addr64[0] & rammask); + } else + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + return map->read_w(addr, map->p); + + if (map && map->read_b) { + return map->read_b(addr, map->p) | + ((uint16_t) (map->read_b(addr + 1, map->p)) << 8); + } + + return 0xffff; +} + + +/* Write a word to memory without MMU translation - results of previous MMU translation passed as array. */ +void +writememwl_no_mmut(uint32_t addr, uint64_t *addr64, uint16_t val) +{ + mem_mapping_t *map; + int i; + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + for (i = 0; i < 2; i++) { + if ((cr0 >> 31) && (addr64[i] > 0xffffffffULL)) + return; + + writemembl_no_mmut(addr + i, addr64[i], val >> (i << 3)); + } + + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + *(uint16_t *)(writelookup2[addr >> 12] + addr) = val; + return; } + } else + addr &= rammask; + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { + page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); + return; + } + + if (cr0 >> 31) { + if (addr64[0] > 0xffffffffULL) + return; + + addr = (uint32_t) (addr64[0] & rammask); + } else + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_w) { + map->write_w(addr, val, map->p); + return; + } + + if (map && map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + return; } } @@ -956,8 +1114,14 @@ writememwl(uint32_t addr, uint16_t val) uint32_t readmemll(uint32_t addr) { - uint64_t addr64 = (uint64_t) addr; + uint64_t addr64[4]; mem_mapping_t *map; + int i; + uint32_t ret = 0x00000000; + uint32_t prev_page = 0xffffffff; + + for (i = 0; i < 4; i++) + addr64[i] = (uint64_t) (addr + i); mem_logical_addr = addr; @@ -965,39 +1129,54 @@ readmemll(uint32_t addr) if (!cpu_cyrix_alignment || (addr & 7) > 4) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { - if (cr0>>31) { - if (mmutranslate_read(addr) == 0xffffffffffffffffULL) - return 0xffffffff; - if (mmutranslate_read(addr+3) == 0xffffffffffffffffULL) - return 0xffffffff; + if (cr0 >> 31) { + for (i = 0; i < 4; i++) { + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + if ((i > 0) && (((addr + i) & ~0xfff) == prev_page)) + addr64[i] = (addr64[i - 1] & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + else + addr64[i] = mmutranslate_read(addr + i); + + prev_page = ((addr + i) & ~0xfff); + + if (addr64[i] > 0xffffffffULL) + return 0xffff; + } } - return readmemwl(addr)|(readmemwl(addr+2)<<16); - } else if (readlookup2[addr >> 12] != LOOKUP_INV) + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + for (i = 0; i < 4; i += 2) + ret |= (readmemwl_no_mmut(addr + i, &(addr64[i])) << (i << 3)); + + return ret; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) return *(uint32_t *)(readlookup2[addr >> 12] + addr); } if (cr0 >> 31) { - addr64 = mmutranslate_read(addr); - if (addr64 == 0xffffffffffffffffULL) + addr64[0] = mmutranslate_read(addr); + if (addr64[0] > 0xffffffffULL) return 0xffffffff; - if (addr64 > 0xffffffffULL) - return 0xffffffff; - } + } else + addr64[0] = (uint64_t) addr; - addr = (uint32_t) (addr64 & rammask); + addr = (uint32_t) (addr64[0] & rammask); map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->read_l) - return map->read_l(addr, map->p); - if (map->read_w) - return map->read_w(addr, map->p) | (map->read_w(addr + 2, map->p) << 16); + if (map && map->read_l) + return map->read_l(addr, map->p); - if (map->read_b) - return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8) | - (map->read_b(addr + 2, map->p) << 16) | (map->read_b(addr + 3, map->p) << 24); - } + if (map && map->read_w) + return map->read_w(addr, map->p) | + ((uint32_t) (map->read_w(addr + 2, map->p)) << 16); + + if (map && map->read_b) + return map->read_b(addr, map->p) | + ((uint32_t) (map->read_b(addr + 1, map->p)) << 8) | + ((uint32_t) (map->read_b(addr + 2, map->p)) << 16) | + ((uint32_t) (map->read_b(addr + 3, map->p)) << 24); return 0xffffffff; } @@ -1006,371 +1185,196 @@ readmemll(uint32_t addr) void writememll(uint32_t addr, uint32_t val) { - uint64_t addr64 = (uint64_t) addr; + uint64_t addr64[4]; mem_mapping_t *map; + int i; + uint32_t prev_page = 0xffffffff; + + for (i = 0; i < 4; i++) + addr64[i] = (uint64_t) (addr + i); mem_logical_addr = addr; if (addr & 3) { if (!cpu_cyrix_alignment || (addr & 7) > 4) cycles -= timing_misaligned; - if ((addr & 0xFFF) > 0xFFC) { - if (cr0>>31) { - if (mmutranslate_write(addr) == 0xffffffffffffffffULL) - return; - if (mmutranslate_write(addr+3) == 0xffffffffffffffffULL) - return; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + for (i = 0; i < 4; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + if ((i > 0) && (((addr + i) & ~0xfff) == prev_page)) + addr64[i] = (addr64[i - 1] & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + else + addr64[i] = mmutranslate_write(addr + i); + + prev_page = ((addr + i) & ~0xfff); + + if (addr64[i] > 0xffffffffULL) + return; + } else + prev_page = 0xffffffff; + } } - writememwl(addr,val); - writememwl(addr+2,val>>16); + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + for (i = 0; i < 4; i += 2) + writememwl_no_mmut(addr + i, &(addr64[i]), val >> (i << 3)); + return; - } else if (writelookup2[addr >> 12] != LOOKUP_INV) { + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { *(uint32_t *)(writelookup2[addr >> 12] + addr) = val; return; } } - if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_l) { - page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { + page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); return; } - if (cr0>>31) { - addr64 = mmutranslate_write(addr); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } - addr = (uint32_t) (addr64 & rammask); + if (cr0 >> 31) { + addr64[0] = mmutranslate_write(addr); + if (addr64[0] > 0xffffffffULL) + return; + } else + addr64[0] = (uint64_t) addr; + + addr = (uint32_t) (addr64[0] & rammask); map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_l) - map->write_l(addr, val, map->p); - else if (map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - } else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - } + + if (map && map->write_l) { + map->write_l(addr, val, map->p); + return; + } + if (map && map->write_w) { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + return; + } + if (map && map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + return; } } -uint64_t -readmemql(uint32_t addr) +/* Read a long from memory without MMU translation - results of previous MMU translation passed as array. */ +uint32_t +readmemll_no_mmut(uint32_t addr, uint64_t *addr64) { - uint64_t addr64 = (uint64_t) addr; mem_mapping_t *map; + int i; + uint32_t ret = 0x00000000; mem_logical_addr = addr; - if (addr & 7) { - cycles -= timing_misaligned; - if ((addr & 0xFFF) > 0xFF8) { - if (cr0>>31) { - if (mmutranslate_read(addr) == 0xffffffffffffffffULL) - return 0xffffffffffffffffULL; - if (mmutranslate_read(addr+7) == 0xffffffffffffffffULL) - return 0xffffffffffffffffULL; + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + for (i = 0; i < 4; i += 2) { + if ((cr0 >> 31) && (addr64[i] > 0xffffffffULL)) + return 0xffffffff; + + ret |= (readmemwl_no_mmut(addr + i, &(addr64[i])) << (i << 3)); } - return readmemll(addr)|((uint64_t)readmemll(addr+4)<<32); - } else if (readlookup2[addr >> 12] != LOOKUP_INV) - return *(uint64_t *)(readlookup2[addr >> 12] + addr); + + return ret; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) + return *(uint32_t *)(readlookup2[addr >> 12] + addr); } - if (cr0>>31) { - addr64 = mmutranslate_read(addr); - if (addr64 == 0xffffffffffffffffULL) - return 0xffffffffffffffffULL; - if (addr64 > 0xffffffffULL) - return 0xffffffffffffffffULL; - } + if (cr0 >> 31) { + if (addr64[0] > 0xffffffffULL) + return 0xffffffff; - addr = (uint32_t) (addr64 & rammask); + addr = (uint32_t) (addr64[0] & rammask); + } else + addr &= rammask; map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_l) - return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32); - - return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32); -} - - -void -writememql(uint32_t addr, uint64_t val) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 7) { - cycles -= timing_misaligned; - if ((addr & 0xFFF) > 0xFF8) { - if (cr0>>31) { - if (mmutranslate_write(addr) == 0xffffffffffffffffULL) - return; - if (mmutranslate_write(addr+7) == 0xffffffffffffffffULL) - return; - } - writememll(addr, val); - writememll(addr+4, val >> 32); - return; - } else if (writelookup2[addr >> 12] != LOOKUP_INV) { - *(uint64_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } - } - if (page_lookup[addr>>12] && page_lookup[addr>>12]->write_l) { - page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); - page_lookup[addr>>12]->write_l(addr + 4, val >> 32, page_lookup[addr>>12]); - return; - } - if (cr0>>31) { - addr64 = mmutranslate_write(addr); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } - - addr = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_l) { - map->write_l(addr, val, map->p); - map->write_l(addr + 4, val >> 32, map->p); - } else if (map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - map->write_w(addr + 4, val >> 32, map->p); - map->write_w(addr + 6, val >> 48, map->p); - } else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - map->write_b(addr + 4, val >> 32, map->p); - map->write_b(addr + 5, val >> 40, map->p); - map->write_b(addr + 6, val >> 48, map->p); - map->write_b(addr + 7, val >> 56, map->p); - } - } -} -#else -uint16_t -readmemwl(uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = addr; - - if (addr2 & 1) { - if (!cpu_cyrix_alignment || (addr2 & 7) == 7) - cycles -= timing_misaligned; - if ((addr2 & 0xfff) > 0xffe) { - if (cr0 >> 31) { - if (mmutranslate_read(addr2) == 0xffffffffffffffffULL) - return 0xffff; - if (mmutranslate_read(addr2+1) == 0xffffffffffffffffULL) - return 0xffff; - } - return readmembl(addr)|(((uint16_t) readmembl(addr+1))<<8); - } else if (readlookup2[addr2 >> 12] != (uintptr_t) LOOKUP_INV) - return *(uint16_t *)(readlookup2[addr2 >> 12] + addr2); - } - - if (cr0 >> 31) { - addr64 = mmutranslate_read(addr2); - if (addr64 == 0xffffffffffffffffULL) - return 0xffff; - if (addr64 > 0xffffffffULL) - return 0xffff; - } else - addr64 = (uint64_t) addr2; - - addr2 = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr2 >> MEM_GRANULARITY_BITS]; - - if (map && map->read_w) - return map->read_w(addr2, map->p); - - if (map && map->read_b) { - return map->read_b(addr2, map->p) | - ((uint16_t) (map->read_b(addr2 + 1, map->p)) << 8); - } - - return 0xffff; -} - - -void -writememwl(uint32_t addr, uint16_t val) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = addr; - - if (addr2 & 1) { - if (!cpu_cyrix_alignment || (addr2 & 7) == 7) - cycles -= timing_misaligned; - if ((addr2 & 0xFFF) > 0xffe) { - if (cr0 >> 31) { - if (mmutranslate_write(addr2) == 0xffffffffffffffffULL) return; - if (mmutranslate_write(addr2+1) == 0xffffffffffffffffULL) return; - } - writemembl(addr,val); - writemembl(addr+1,val>>8); - return; - } else if (writelookup2[addr2 >> 12] != (uintptr_t) LOOKUP_INV) { - *(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val; - return; - } - } - - if (page_lookup[addr2>>12] && page_lookup[addr2>>12]->write_w) { - page_lookup[addr2>>12]->write_w(addr2, val, page_lookup[addr2>>12]); - return; - } - - if (cr0 >> 31) { - addr64 = mmutranslate_write(addr2); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) - return; - } else - addr64 = (uint64_t) addr2; - - addr2 = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr2 >> MEM_GRANULARITY_BITS]; - - if (map && map->write_w) { - map->write_w(addr2, val, map->p); - return; - } - - if (map && map->write_b) { - map->write_b(addr2, val, map->p); - map->write_b(addr2 + 1, val >> 8, map->p); - return; - } -} - - -uint32_t -readmemll(uint32_t addr) -{ - uint64_t addr64 = (uint64_t) addr; - mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = addr; - - if (addr2 & 3) { - if (!cpu_cyrix_alignment || (addr2 & 7) > 4) - cycles -= timing_misaligned; - if ((addr2 & 0xfff) > 0xffc) { - if (cr0 >> 31) { - if (mmutranslate_read(addr2) == 0xffffffffffffffffULL) return 0xffffffff; - if (mmutranslate_read(addr2+3) == 0xffffffffffffffffULL) return 0xffffffff; - } - return readmemwl(addr)|(readmemwl(addr+2)<<16); - } else if (readlookup2[addr2 >> 12] != (uintptr_t) LOOKUP_INV) - return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2); - } - - if (cr0 >> 31) { - addr64 = mmutranslate_read(addr2); - if (addr64 == 0xffffffffffffffffULL) - return 0xffffffff; - if (addr64 > 0xffffffffULL) - return 0xffffffff; - } else - addr64 = (uint64_t) addr2; - - addr2 = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr2 >> MEM_GRANULARITY_BITS]; if (map && map->read_l) - return map->read_l(addr2, map->p); + return map->read_l(addr, map->p); if (map && map->read_w) - return map->read_w(addr2, map->p) | - ((uint32_t) (map->read_w(addr2 + 2, map->p)) << 16); + return map->read_w(addr, map->p) | + ((uint32_t) (map->read_w(addr + 2, map->p)) << 16); if (map && map->read_b) - return map->read_b(addr2, map->p) | - ((uint32_t) (map->read_b(addr2 + 1, map->p)) << 8) | - ((uint32_t) (map->read_b(addr2 + 2, map->p)) << 16) | - ((uint32_t) (map->read_b(addr2 + 3, map->p)) << 24); + return map->read_b(addr, map->p) | + ((uint32_t) (map->read_b(addr + 1, map->p)) << 8) | + ((uint32_t) (map->read_b(addr + 2, map->p)) << 16) | + ((uint32_t) (map->read_b(addr + 3, map->p)) << 24); return 0xffffffff; } +/* Write a long to memory without MMU translation - results of previous MMU translation passed as array. */ void -writememll(uint32_t addr, uint32_t val) +writememll_no_mmut(uint32_t addr, uint64_t *addr64, uint32_t val) { - uint64_t addr64 = (uint64_t) addr; mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = addr; + int i; - if (addr2 & 3) { - if (!cpu_cyrix_alignment || (addr2 & 7) > 4) + mem_logical_addr = addr; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) cycles -= timing_misaligned; - if ((addr2 & 0xfff) > 0xffc) { - if (cr0 >> 31) { - if (mmutranslate_write(addr2) == 0xffffffffffffffffULL) return; - if (mmutranslate_write(addr2+3) == 0xffffffffffffffffULL) return; + if ((addr & 0xfff) > 0xffc) { + for (i = 0; i < 4; i += 2) { + if ((cr0 >> 31) && (addr64[i] > 0xffffffffULL)) + return; + + writememwl_no_mmut(addr + i, &(addr64[i]), val >> (i << 3)); } - writememwl(addr,val); - writememwl(addr+2,val>>16); + return; - } else if (writelookup2[addr2 >> 12] != (uintptr_t) LOOKUP_INV) { - *(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + *(uint32_t *)(writelookup2[addr >> 12] + addr) = val; return; } } - if (page_lookup[addr2>>12] && page_lookup[addr2>>12]->write_l) { - page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { + page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); return; } if (cr0 >> 31) { - addr64 = mmutranslate_write(addr2); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) + if (addr64[0] > 0xffffffffULL) return; + + addr = (uint32_t) (addr64[0] & rammask); } else - addr64 = (uint32_t) addr2; + addr &= rammask; - addr2 = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr2 >> MEM_GRANULARITY_BITS]; + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_l) { - map->write_l(addr2, val, map->p); + map->write_l(addr, val, map->p); return; } if (map && map->write_w) { - map->write_w(addr2, val, map->p); - map->write_w(addr2 + 2, val >> 16, map->p); + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); return; } if (map && map->write_b) { - map->write_b(addr2, val, map->p); - map->write_b(addr2 + 1, val >> 8, map->p); - map->write_b(addr2 + 2, val >> 16, map->p); - map->write_b(addr2 + 3, val >> 24, map->p); + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); return; } } @@ -1379,108 +1383,189 @@ writememll(uint32_t addr, uint32_t val) uint64_t readmemql(uint32_t addr) { - uint64_t addr64 = (uint64_t) addr; + uint64_t addr64[8]; mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = addr; + int i; + uint64_t ret = 0x0000000000000000ULL; + uint32_t prev_page = 0xffffffff; - if (addr2 & 7) { + for (i = 0; i < 8; i++) + addr64[i] = (uint64_t) (addr + i); + + mem_logical_addr = addr; + + if (addr & 7) { cycles -= timing_misaligned; - if ((addr2 & 0xfff) > 0xff8) { + if ((addr & 0xfff) > 0xff8) { if (cr0 >> 31) { - if (mmutranslate_read(addr2) == 0xffffffffffffffffULL) return 0xffffffffffffffffULL; - if (mmutranslate_read(addr2+7) == 0xffffffffffffffffULL) return 0xffffffffffffffffULL; + for (i = 0; i < 8; i++) { + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + if ((i > 0) && (((addr + i) & ~0xfff) == prev_page)) + addr64[i] = (addr64[i - 1] & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + else + addr64[i] = mmutranslate_read(addr + i); + + prev_page = ((addr + i) & ~0xfff); + + if (addr64[i] > 0xffffffffULL) + return 0xffff; + } } - return readmemll(addr)|((uint64_t)readmemll(addr+4)<<32); - } else if (readlookup2[addr2 >> 12] != (uintptr_t) LOOKUP_INV) - return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2); + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + for (i = 0; i < 8; i += 4) + ret |= (readmemll_no_mmut(addr + i, &(addr64[i])) << (i << 3)); + + return ret; + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) + return *(uint64_t *)(readlookup2[addr >> 12] + addr); } if (cr0 >> 31) { - addr64 = mmutranslate_read(addr2); - if (addr64 == 0xffffffffffffffffULL) - return 0xffffffffffffffffULL; - if (addr64 > 0xffffffffULL) + addr64[0] = mmutranslate_read(addr); + if (addr64[0] > 0xffffffffULL) return 0xffffffffffffffffULL; } else - addr64 = (uint64_t) addr2; + addr64[0] = (uint64_t) addr; - addr2 = (uint32_t) (addr64 & rammask); + addr = (uint32_t) (addr64[0] & rammask); - map = read_mapping[addr2 >> MEM_GRANULARITY_BITS]; + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->read_l) - return map->read_l(addr2, map->p) | ((uint64_t)map->read_l(addr2 + 4, map->p) << 32); + return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32); - return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32); + return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32); } void writememql(uint32_t addr, uint64_t val) { - uint64_t addr64 = (uint64_t) addr; + uint64_t addr64[8]; mem_mapping_t *map; - uint32_t addr2 = mem_logical_addr = addr; + int i; + uint32_t prev_page = 0xffffffff; - if (addr2 & 7) { + for (i = 0; i < 8; i++) + addr64[i] = (uint64_t) (addr + i); + + mem_logical_addr = addr; + + if (addr & 7) { cycles -= timing_misaligned; - if ((addr2 & 0xfff) > 0xff8) { + if ((addr & 0xfff) > 0xff8) { if (cr0 >> 31) { - if (mmutranslate_write(addr2) == 0xffffffffffffffffULL) return; - if (mmutranslate_write(addr2+7) == 0xffffffffffffffffULL) return; + for (i = 0; i < 8; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + if ((i > 0) && (((addr + i) & ~0xfff) == prev_page)) + addr64[i] = (addr64[i - 1] & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + else + addr64[i] = mmutranslate_write(addr + i); + + prev_page = ((addr + i) & ~0xfff); + + if (addr64[i] > 0xffffffffULL) + return; + } else + prev_page = 0xffffffff; + } } - writememll(addr, val); - writememll(addr+4, val >> 32); + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + for (i = 0; i < 8; i += 4) + writememll_no_mmut(addr + i, &(addr64[i]), val >> (i << 3)); + return; - } else if (writelookup2[addr2 >> 12] != (uintptr_t) LOOKUP_INV) { - *(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + *(uint64_t *)(writelookup2[addr >> 12] + addr) = val; return; } } - if (page_lookup[addr2>>12] && page_lookup[addr2>>12]->write_l) { - page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]); - page_lookup[addr2>>12]->write_l(addr2 + 4, val >> 32, page_lookup[addr2>>12]); + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { + page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); + page_lookup[addr >> 12]->write_l(addr + 4, val >> 32, page_lookup[addr >> 12]); return; } if (cr0 >> 31) { - addr64 = mmutranslate_write(addr2); - if (addr64 == 0xffffffffffffffffULL) - return; - if (addr64 > 0xffffffffULL) + addr64[0] = mmutranslate_write(addr); + if (addr64[0] > 0xffffffffULL) return; } else - addr64 = (uint64_t) addr2; + addr64[0] = (uint64_t) addr; - addr2 = (uint32_t) (addr64 & rammask); + addr = (uint32_t) (addr64[0] & rammask); - map = write_mapping[addr2 >> MEM_GRANULARITY_BITS]; + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; if (map && map->write_l) { - map->write_l(addr2, val, map->p); - map->write_l(addr2+4, val >> 32, map->p); + map->write_l(addr, val, map->p); + map->write_l(addr + 4, val >> 32, map->p); return; } if (map && map->write_w) { - map->write_w(addr2, val, map->p); - map->write_w(addr2 + 2, val >> 16, map->p); - map->write_w(addr2 + 4, val >> 32, map->p); - map->write_w(addr2 + 6, val >> 48, map->p); + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + map->write_w(addr + 4, val >> 32, map->p); + map->write_w(addr + 6, val >> 48, map->p); return; } if (map && map->write_b) { - map->write_b(addr2, val, map->p); - map->write_b(addr2 + 1, val >> 8, map->p); - map->write_b(addr2 + 2, val >> 16, map->p); - map->write_b(addr2 + 3, val >> 24, map->p); - map->write_b(addr2 + 4, val >> 32, map->p); - map->write_b(addr2 + 5, val >> 40, map->p); - map->write_b(addr2 + 6, val >> 48, map->p); - map->write_b(addr2 + 7, val >> 56, map->p); + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + map->write_b(addr + 4, val >> 32, map->p); + map->write_b(addr + 5, val >> 40, map->p); + map->write_b(addr + 6, val >> 48, map->p); + map->write_b(addr + 7, val >> 56, map->p); return; } } -#endif + + +void +do_mmutranslate(uint32_t addr, uint64_t *addr64, int num, int write) +{ + int i, cond = 1; + uint32_t prev_page = 0xffffffff; + + for (i = 0; i < num; i++) { + addr64[i] = (uint64_t) (addr + i); + + if (cr0 >> 31) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (write) + cond = (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b); + + if (cond) { + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + if ((i > 0) && (((addr + i) & ~0xfff) == prev_page)) + addr64[i] = (addr64[i - 1] & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + else + addr64[i] = mmutranslatereal(addr + i, write); + + prev_page = ((addr + i) & ~0xfff); + + if (addr64[i] == 0xffffffffffffffffULL) + return; + if (addr64[i] > 0xffffffffULL) + return; + if (cpu_state.abrt) + return; + } else + prev_page = 0xffffffff; + } + } +} int @@ -1507,7 +1592,7 @@ mem_readb_phys(uint32_t addr) mem_logical_addr = 0xffffffff; - if (use_phys_exec && _mem_exec[addr >> MEM_GRANULARITY_BITS]) + if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) return _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]; else if (map && map->read_b) return map->read_b(addr, map->p); @@ -1524,7 +1609,7 @@ mem_readw_phys(uint32_t addr) mem_logical_addr = 0xffffffff; - if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { p = (uint16_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); return *p; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w)) @@ -1546,7 +1631,7 @@ mem_readl_phys(uint32_t addr) mem_logical_addr = 0xffffffff; - if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { p = (uint32_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); return *p; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l)) @@ -1587,7 +1672,7 @@ mem_writeb_phys(uint32_t addr, uint8_t val) mem_logical_addr = 0xffffffff; - if (use_phys_exec && _mem_exec[addr >> MEM_GRANULARITY_BITS]) + if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK] = val; else if (map && map->write_b) map->write_b(addr, val, map->p); @@ -1602,7 +1687,7 @@ mem_writew_phys(uint32_t addr, uint16_t val) mem_logical_addr = 0xffffffff; - if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { p = (uint16_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); *p = val; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->write_w)) @@ -1622,7 +1707,7 @@ mem_writel_phys(uint32_t addr, uint32_t val) mem_logical_addr = 0xffffffff; - if (use_phys_exec && ((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (_mem_exec[addr >> MEM_GRANULARITY_BITS])) { p = (uint32_t *) &(_mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]); *p = val; } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l)) @@ -2066,6 +2151,9 @@ mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { uint64_t mask; #ifdef USE_NEW_DYNAREC + int byte_offset; + uint64_t byte_mask; + uint32_t i; page_t *p; start_addr &= ~PAGE_MASK_MASK; @@ -2078,10 +2166,18 @@ mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); p = &pages[start_addr >> 12]; - p->dirty_mask |= mask; if ((p->code_present_mask & mask) && !page_in_evict_list(p)) page_add_to_evict_list(p); + + for (i = start_addr; (i <= end_addr) && (i < (start_addr + (1 << PAGE_MASK_SHIFT))); i++) { + byte_offset = (i >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + byte_mask = (uint64_t)1 << (i & PAGE_BYTE_MASK_MASK); + + p->byte_dirty_mask[byte_offset] |= byte_mask; + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } } #else uint32_t cur_addr; diff --git a/src/pc.c b/src/pc.c index efe6f0967..4a1161221 100644 --- a/src/pc.c +++ b/src/pc.c @@ -162,7 +162,6 @@ int fps, framecount; /* emulator % */ extern int CPUID; extern int output; int atfullspeed; -int clockrate; wchar_t exe_path[2048]; /* path (dir) of executable */ wchar_t usr_path[1024]; /* path (dir) of user data */ @@ -172,7 +171,7 @@ int scrnsz_x = SCREEN_RES_X, /* current screen size, X */ scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */ int config_changed; /* config has changed */ int title_update; -int64_t main_time; +int framecountx = 0; int unscaled_size_x = SCREEN_RES_X, /* current unscaled size X */ @@ -180,6 +179,9 @@ int unscaled_size_x = SCREEN_RES_X, /* current unscaled size X */ efscrnsz_y = SCREEN_RES_Y; +static wchar_t mouse_msg[2][200]; + + #ifndef RELEASE_BUILD static char buff[1024]; static int seen = 0; @@ -729,6 +731,8 @@ pc_reset_hard_close(void) void pc_reset_hard_init(void) { + wchar_t wcpufamily[2048], wcpu[2048], wmachine[2048], *wcp; + /* * First, we reset the modules that are not part of * the actual machine, but which support some of the @@ -829,6 +833,20 @@ pc_reset_hard_init(void) pc_full_speed(); cycles = cycles_main = 0; + + mbstowcs(wmachine, machine_getname(), strlen(machine_getname())+1); + mbstowcs(wcpufamily, cpu_f->name, + strlen(cpu_f->name)+1); + wcp = wcschr(wcpufamily, L'('); + if (wcp) /* remove parentheses */ + *(wcp - 1) = L'\0'; + mbstowcs(wcpu, cpu_s->name, strlen(cpu_s->name)+1); + swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls", + EMU_NAME_W, EMU_VERSION_W, wmachine, wcpufamily, wcpu, + plat_get_string(IDS_2077)); + swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls", + EMU_NAME_W, EMU_VERSION_W, wmachine, wcpufamily, wcpu, + (mouse_get_buttons() > 2) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079)); } @@ -910,123 +928,28 @@ pc_close(thread_t *ptr) } -/* - * The main thread runs the actual emulator code. - * - * We basically run until the upper layers terminate us, by - * setting the variable 'quited' there to 1. We get a pointer - * to that variable as our function argument. - */ void -pc_thread(void *param) +pc_run(void) { - wchar_t temp[200], wcpufamily[2048], wcpu[2048]; - wchar_t wmachine[2048], *wcp; - uint64_t start_time, end_time; - uint32_t old_time, new_time; - int done, drawits, frames; - int *quitp = (int *)param; - int framecountx; + wchar_t temp[200]; - pc_log("PC: starting main thread...\n"); + /* Run a block of code. */ + cpu_exec(cpu_s->rspeed / 100); + mouse_process(); + joystick_process(); - main_time = 0; - framecountx = 0; - title_update = 1; - old_time = plat_get_ticks(); - done = drawits = frames = 0; - while (! *quitp) { - /* See if it is time to run a frame of code. */ - new_time = plat_get_ticks(); - drawits += (new_time - old_time); - old_time = new_time; - if (drawits > 0 && !dopause) { - /* Yes, so do one frame now. */ - start_time = plat_timer_read(); - drawits -= 10; - if (drawits > 50) - drawits = 0; - - /* Run a block of code. */ - startblit(); - clockrate = cpu_s->rspeed; - - if (is386) { -#ifdef USE_DYNAREC - if (cpu_use_dynarec) - exec386_dynarec(clockrate/100); - else -#endif - exec386(clockrate/100); - } else if (cpu_s->cpu_type >= CPU_286) { - exec386(clockrate/100); - } else { - execx86(clockrate/100); - } - - mouse_process(); - - joystick_process(); - - endblit(); - - /* Done with this frame, update statistics. */ - framecount++; - if (++framecountx >= 100) { - framecountx = 0; - - readlnum = writelnum = 0; - egareads = egawrites = 0; - mmuflush = 0; - frames = 0; - } - - if (title_update) { - mbstowcs(wmachine, machine_getname(), strlen(machine_getname())+1); - mbstowcs(wcpufamily, cpu_f->name, - strlen(cpu_f->name)+1); - wcp = wcschr(wcpufamily, L'('); - if (wcp) /* remove parentheses */ - *(wcp - 1) = L'\0'; - mbstowcs(wcpu, cpu_s->name, - strlen(cpu_s->name)+1); - swprintf(temp, sizeof_w(temp), - L"%ls v%ls - %i%% - %ls - %ls/%ls - %ls", - EMU_NAME_W,EMU_VERSION_W,fps,wmachine,wcpufamily,wcpu, - (!mouse_capture) ? plat_get_string(IDS_2077) - : (mouse_get_buttons() > 2) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079)); - - ui_window_title(temp); - - title_update = 0; - } - - /* One more frame done! */ - done++; - - /* Every 200 frames we save the machine status. */ - if (++frames >= 200 && nvr_dosave) { - nvr_save(); - nvr_dosave = 0; - frames = 0; - } - - end_time = plat_timer_read(); - main_time += (end_time - start_time); - } else { - /* Just so we dont overload the host OS. */ - plat_delay_ms(1); - } - - /* If needed, handle a screen resize. */ - if (doresize && !video_fullscreen) { - plat_resize(scrnsz_x, scrnsz_y); - - doresize = 0; - } + /* Done with this frame, update statistics. */ + framecount++; + if (++framecountx >= 100) { + framecountx = 0; + frames = 0; } - pc_log("PC: main thread done.\n"); + if (title_update) { + swprintf(temp, sizeof_w(temp), mouse_msg[!!mouse_capture], fps); + ui_window_title(temp); + title_update = 0; + } } @@ -1090,9 +1013,8 @@ set_screen_size(int x, int y) } } unscaled_size_y = (int)dy; - } else { + } else unscaled_size_y = efscrnsz_y; - } switch(scale) { case 0: /* 50% */ diff --git a/src/win/win.c b/src/win/win.c index b8c78eb73..a47de48c0 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -39,6 +39,8 @@ #include <86box/device.h> #include <86box/keyboard.h> #include <86box/mouse.h> +#include <86box/timer.h> +#include <86box/nvr.h> #include <86box/video.h> #define GLOBAL #include <86box/plat.h> @@ -80,6 +82,9 @@ static rc_str_t *lpRCstr2048, *lpRCstr7168; static int vid_api_inited = 0; static wchar_t *argbuf; +static int first_use = 1; +static LARGE_INTEGER StartingTime; +static LARGE_INTEGER Frequency; static const struct { @@ -101,6 +106,9 @@ static const struct { }; +extern int title_update; + + #ifdef ENABLE_WIN_LOG int win_do_log = ENABLE_WIN_LOG; @@ -414,6 +422,47 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) } +void +main_thread(void *param) +{ + uint32_t old_time, new_time; + int drawits, frames; + + title_update = 1; + old_time = GetTickCount(); + drawits = frames = 0; + while (!quited) { + /* See if it is time to run a frame of code. */ + new_time = GetTickCount(); + drawits += (new_time - old_time); + old_time = new_time; + if (drawits > 0 && !dopause) { + /* Yes, so do one frame now. */ + drawits -= 10; + if (drawits > 50) + drawits = 0; + + /* Run a block of code. */ + pc_run(); + + /* Every 200 frames we save the machine status. */ + if (++frames >= 200 && nvr_dosave) { + nvr_save(); + nvr_dosave = 0; + frames = 0; + } + } else /* Just so we dont overload the host OS. */ + Sleep(1); + + /* If needed, handle a screen resize. */ + if (doresize && !video_fullscreen) { + plat_resize(scrnsz_x, scrnsz_y); + doresize = 0; + } + } +} + + /* * We do this here since there is platform-specific stuff * going on here, and we do it in a function separate from @@ -434,7 +483,7 @@ do_start(void) win_log("Main timer precision: %llu\n", timer_freq); /* Start the emulator, really. */ - thMain = thread_create(pc_thread, &quited); + thMain = thread_create(main_thread, &quited); SetThreadPriority(thMain, THREAD_PRIORITY_HIGHEST); } @@ -667,7 +716,26 @@ plat_timer_read(void) uint32_t plat_get_ticks(void) { - return(GetTickCount()); + LARGE_INTEGER EndingTime, ElapsedMicroseconds; + + if (first_use) { + QueryPerformanceFrequency(&Frequency); + QueryPerformanceCounter(&StartingTime); + first_use = 0; + } + + QueryPerformanceCounter(&EndingTime); + ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart; + + /* We now have the elapsed number of ticks, along with the + number of ticks-per-second. We use these values + to convert to the number of elapsed microseconds. + To guard against loss-of-precision, we convert + to microseconds *before* dividing by ticks-per-second. */ + ElapsedMicroseconds.QuadPart *= 1000000; + ElapsedMicroseconds.QuadPart /= Frequency.QuadPart; + + return (uint32_t) (ElapsedMicroseconds.QuadPart / 1000); }