Added prefetch timing approximation for 286/386 CPUs, with configurable memory timing.
This commit is contained in:
parent
c5889e311f
commit
1b73963997
33 changed files with 1139 additions and 261 deletions
|
|
@ -274,6 +274,89 @@ void x86illegal()
|
|||
x86_int(6);
|
||||
}
|
||||
|
||||
/*Prefetch emulation is a fairly simplistic model:
|
||||
- All instruction bytes must be fetched before it starts.
|
||||
- Cycles used for non-instruction memory accesses are counted and subtracted
|
||||
from the total cycles taken
|
||||
- Any remaining cycles are used to refill the prefetch queue.
|
||||
|
||||
Note that this is only used for 286 / 386 systems. It is disabled when the
|
||||
internal cache on 486+ CPUs is enabled.
|
||||
*/
|
||||
static int prefetch_bytes = 0;
|
||||
static int prefetch_prefixes = 0;
|
||||
|
||||
static void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32)
|
||||
{
|
||||
int mem_cycles = reads*cpu_cycles_read + reads_l*cpu_cycles_read_l + writes*cpu_cycles_write + writes_l*cpu_cycles_write_l;
|
||||
|
||||
if (instr_cycles < mem_cycles)
|
||||
instr_cycles = mem_cycles;
|
||||
|
||||
prefetch_bytes -= prefetch_prefixes;
|
||||
prefetch_bytes -= bytes;
|
||||
if (modrm != -1)
|
||||
{
|
||||
if (ea32)
|
||||
{
|
||||
if ((modrm & 7) == 4)
|
||||
{
|
||||
if ((modrm & 0x700) == 0x500)
|
||||
prefetch_bytes -= 5;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modrm & 0xc7) == 0x05)
|
||||
prefetch_bytes -= 4;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes--;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modrm & 0xc7) == 0x06)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) != 0xc0)
|
||||
prefetch_bytes -= ((modrm & 0xc0) >> 6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill up prefetch queue */
|
||||
while (prefetch_bytes < 0)
|
||||
{
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
/* Subtract cycles used for memory access by instruction */
|
||||
instr_cycles -= mem_cycles;
|
||||
|
||||
while (instr_cycles >= cpu_prefetch_cycles)
|
||||
{
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
instr_cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
prefetch_prefixes = 0;
|
||||
}
|
||||
|
||||
static void prefetch_flush()
|
||||
{
|
||||
prefetch_bytes = 0;
|
||||
}
|
||||
|
||||
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \
|
||||
do { if (cpu_prefetch_cycles) prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); } while (0)
|
||||
|
||||
#define PREFETCH_PREFIX() prefetch_prefixes++
|
||||
#define PREFETCH_FLUSH() prefetch_flush()
|
||||
|
||||
|
||||
int rep386(int fv)
|
||||
{
|
||||
|
|
@ -291,6 +374,7 @@ int rep386(int fv)
|
|||
that high frequency timers still work okay. This amount is different
|
||||
for interpreter and recompiler*/
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100);
|
||||
int reads = 0, reads_l = 0, writes = 0, writes_l = 0, total_cycles = 0;
|
||||
|
||||
if (trap)
|
||||
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/
|
||||
|
|
@ -319,28 +403,36 @@ int rep386(int fv)
|
|||
break;
|
||||
case 0x26: case 0x126: case 0x226: case 0x326: /*ES:*/
|
||||
cpu_state.ea_seg = &_es;
|
||||
PREFETCH_PREFIX();
|
||||
goto startrep;
|
||||
break;
|
||||
case 0x2E: case 0x12E: case 0x22E: case 0x32E: /*CS:*/
|
||||
cpu_state.ea_seg = &_cs;
|
||||
PREFETCH_PREFIX();
|
||||
goto startrep;
|
||||
case 0x36: case 0x136: case 0x236: case 0x336: /*SS:*/
|
||||
cpu_state.ea_seg = &_ss;
|
||||
PREFETCH_PREFIX();
|
||||
goto startrep;
|
||||
case 0x3E: case 0x13E: case 0x23E: case 0x33E: /*DS:*/
|
||||
cpu_state.ea_seg = &_ds;
|
||||
PREFETCH_PREFIX();
|
||||
goto startrep;
|
||||
case 0x64: case 0x164: case 0x264: case 0x364: /*FS:*/
|
||||
cpu_state.ea_seg = &_fs;
|
||||
PREFETCH_PREFIX();
|
||||
goto startrep;
|
||||
case 0x65: case 0x165: case 0x265: case 0x365: /*GS:*/
|
||||
cpu_state.ea_seg = &_gs;
|
||||
PREFETCH_PREFIX();
|
||||
goto startrep;
|
||||
case 0x66: case 0x166: case 0x266: case 0x366: /*Data size prefix*/
|
||||
rep32 = (rep32 & 0x200) | ((use32 ^ 0x100) & 0x100);
|
||||
PREFETCH_PREFIX();
|
||||
goto startrep;
|
||||
case 0x67: case 0x167: case 0x267: case 0x367: /*Address size prefix*/
|
||||
rep32 = (rep32 & 0x100) | ((use32 ^ 0x200) & 0x200);
|
||||
PREFETCH_PREFIX();
|
||||
goto startrep;
|
||||
case 0x6C: case 0x16C: /*REP INSB*/
|
||||
// cpu_notreps++;
|
||||
|
|
@ -354,6 +446,7 @@ int rep386(int fv)
|
|||
else DI++;
|
||||
c--;
|
||||
cycles-=15;
|
||||
reads++; writes++; total_cycles += 15;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -370,6 +463,7 @@ int rep386(int fv)
|
|||
else EDI++;
|
||||
c--;
|
||||
cycles-=15;
|
||||
reads++; writes++; total_cycles += 15;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -386,6 +480,7 @@ int rep386(int fv)
|
|||
else DI+=2;
|
||||
c--;
|
||||
cycles-=15;
|
||||
reads++; writes++; total_cycles += 15;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -401,6 +496,7 @@ int rep386(int fv)
|
|||
else DI+=4;
|
||||
c--;
|
||||
cycles-=15;
|
||||
reads_l++; writes_l++; total_cycles += 15;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -416,6 +512,7 @@ int rep386(int fv)
|
|||
else EDI+=2;
|
||||
c--;
|
||||
cycles-=15;
|
||||
reads++; writes++; total_cycles += 15;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -431,6 +528,7 @@ int rep386(int fv)
|
|||
else EDI+=4;
|
||||
c--;
|
||||
cycles-=15;
|
||||
reads_l++; writes_l++; total_cycles += 15;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -447,6 +545,7 @@ int rep386(int fv)
|
|||
else SI++;
|
||||
c--;
|
||||
cycles-=14;
|
||||
reads++; writes++; total_cycles += 14;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -463,6 +562,7 @@ int rep386(int fv)
|
|||
else ESI++;
|
||||
c--;
|
||||
cycles-=14;
|
||||
reads++; writes++; total_cycles += 14;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -479,6 +579,7 @@ int rep386(int fv)
|
|||
else SI+=2;
|
||||
c--;
|
||||
cycles-=14;
|
||||
reads++; writes++; total_cycles += 14;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -494,6 +595,7 @@ int rep386(int fv)
|
|||
else SI += 4;
|
||||
c--;
|
||||
cycles -= 14;
|
||||
reads_l++; writes_l++; total_cycles += 14;
|
||||
}
|
||||
if (c > 0) { firstrepcycle = 0; cpu_state.pc = ipc; }
|
||||
else firstrepcycle = 1;
|
||||
|
|
@ -509,6 +611,7 @@ int rep386(int fv)
|
|||
else ESI+=2;
|
||||
c--;
|
||||
cycles-=14;
|
||||
reads++; writes++; total_cycles += 14;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -524,6 +627,7 @@ int rep386(int fv)
|
|||
else ESI += 4;
|
||||
c--;
|
||||
cycles -= 14;
|
||||
reads_l++; writes_l++; total_cycles += 14;
|
||||
}
|
||||
if (c > 0) { firstrepcycle = 0; cpu_state.pc = ipc; }
|
||||
else firstrepcycle = 1;
|
||||
|
|
@ -544,6 +648,7 @@ int rep386(int fv)
|
|||
c--;
|
||||
cycles-=(is486)?3:4;
|
||||
ins++;
|
||||
reads++; writes++; total_cycles += is486 ? 3 : 4;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
}
|
||||
|
|
@ -562,6 +667,7 @@ int rep386(int fv)
|
|||
c--;
|
||||
cycles-=(is486)?3:4;
|
||||
ins++;
|
||||
reads++; writes++; total_cycles += is486 ? 3 : 4;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
}
|
||||
|
|
@ -580,6 +686,7 @@ int rep386(int fv)
|
|||
c--;
|
||||
cycles-=(is486)?3:4;
|
||||
ins++;
|
||||
reads++; writes++; total_cycles += is486 ? 3 : 4;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
}
|
||||
|
|
@ -599,6 +706,7 @@ int rep386(int fv)
|
|||
c--;
|
||||
cycles-=(is486)?3:4;
|
||||
ins++;
|
||||
reads_l++; writes_l++; total_cycles += is486 ? 3 : 4;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
}
|
||||
|
|
@ -618,6 +726,7 @@ int rep386(int fv)
|
|||
c--;
|
||||
cycles-=(is486)?3:4;
|
||||
ins++;
|
||||
reads++; writes++; total_cycles += is486 ? 3 : 4;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
}
|
||||
|
|
@ -638,6 +747,7 @@ int rep386(int fv)
|
|||
c--;
|
||||
cycles-=(is486)?3:4;
|
||||
ins++;
|
||||
reads_l++; writes_l++; total_cycles += is486 ? 3 : 4;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
}
|
||||
|
|
@ -657,6 +767,7 @@ int rep386(int fv)
|
|||
else { DI++; SI++; }
|
||||
c--;
|
||||
cycles-=(is486)?7:9;
|
||||
reads += 2; total_cycles += is486 ? 7 : 9;
|
||||
setsub8(temp,temp2);
|
||||
tempz = (ZF_SET()) ? 1 : 0;
|
||||
}
|
||||
|
|
@ -675,6 +786,7 @@ int rep386(int fv)
|
|||
else { EDI++; ESI++; }
|
||||
c--;
|
||||
cycles-=(is486)?7:9;
|
||||
reads += 2; total_cycles += is486 ? 7 : 9;
|
||||
setsub8(temp,temp2);
|
||||
tempz = (ZF_SET()) ? 1 : 0;
|
||||
}
|
||||
|
|
@ -696,6 +808,7 @@ int rep386(int fv)
|
|||
else { DI+=2; SI+=2; }
|
||||
c--;
|
||||
cycles-=(is486)?7:9;
|
||||
reads += 2; total_cycles += is486 ? 7 : 9;
|
||||
setsub16(tempw,tempw2);
|
||||
tempz = (ZF_SET()) ? 1 : 0;
|
||||
}
|
||||
|
|
@ -714,6 +827,7 @@ int rep386(int fv)
|
|||
else { DI+=4; SI+=4; }
|
||||
c--;
|
||||
cycles-=(is486)?7:9;
|
||||
reads_l += 2; total_cycles += is486 ? 7 : 9;
|
||||
setsub32(templ,templ2);
|
||||
tempz = (ZF_SET()) ? 1 : 0;
|
||||
}
|
||||
|
|
@ -732,6 +846,7 @@ int rep386(int fv)
|
|||
else { EDI+=2; ESI+=2; }
|
||||
c--;
|
||||
cycles-=(is486)?7:9;
|
||||
reads += 2; total_cycles += is486 ? 7 : 9;
|
||||
setsub16(tempw,tempw2);
|
||||
tempz = (ZF_SET()) ? 1 : 0;
|
||||
}
|
||||
|
|
@ -750,6 +865,7 @@ int rep386(int fv)
|
|||
else { EDI+=4; ESI+=4; }
|
||||
c--;
|
||||
cycles-=(is486)?7:9;
|
||||
reads_l += 2; total_cycles += is486 ? 7 : 9;
|
||||
setsub32(templ,templ2);
|
||||
tempz = (ZF_SET()) ? 1 : 0;
|
||||
}
|
||||
|
|
@ -767,6 +883,7 @@ int rep386(int fv)
|
|||
else DI++;
|
||||
c--;
|
||||
cycles-=(is486)?4:5;
|
||||
writes++; total_cycles += is486 ? 4 : 5;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -785,6 +902,7 @@ int rep386(int fv)
|
|||
else EDI++;
|
||||
c--;
|
||||
cycles-=(is486)?4:5;
|
||||
writes++; total_cycles += is486 ? 4 : 5;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -803,6 +921,7 @@ int rep386(int fv)
|
|||
else DI+=2;
|
||||
c--;
|
||||
cycles-=(is486)?4:5;
|
||||
writes++; total_cycles += is486 ? 4 : 5;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -821,6 +940,7 @@ int rep386(int fv)
|
|||
else EDI+=2;
|
||||
c--;
|
||||
cycles-=(is486)?4:5;
|
||||
writes++; total_cycles += is486 ? 4 : 5;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -839,6 +959,7 @@ int rep386(int fv)
|
|||
else DI+=4;
|
||||
c--;
|
||||
cycles-=(is486)?4:5;
|
||||
writes_l++; total_cycles += is486 ? 4 : 5;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -857,6 +978,7 @@ int rep386(int fv)
|
|||
else EDI+=4;
|
||||
c--;
|
||||
cycles-=(is486)?4:5;
|
||||
writes_l++; total_cycles += is486 ? 4 : 5;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -876,6 +998,7 @@ int rep386(int fv)
|
|||
else SI++;
|
||||
c--;
|
||||
cycles-=5;
|
||||
reads++; total_cycles += 5;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -891,6 +1014,7 @@ int rep386(int fv)
|
|||
else ESI++;
|
||||
c--;
|
||||
cycles-=5;
|
||||
reads++; total_cycles += 5;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -906,6 +1030,7 @@ int rep386(int fv)
|
|||
else SI+=2;
|
||||
c--;
|
||||
cycles-=5;
|
||||
reads++; total_cycles += 5;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -921,6 +1046,7 @@ int rep386(int fv)
|
|||
else SI+=4;
|
||||
c--;
|
||||
cycles-=5;
|
||||
reads_l++; total_cycles += 5;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -936,6 +1062,7 @@ int rep386(int fv)
|
|||
else ESI+=2;
|
||||
c--;
|
||||
cycles-=5;
|
||||
reads++; total_cycles += 5;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -951,6 +1078,7 @@ int rep386(int fv)
|
|||
else ESI+=4;
|
||||
c--;
|
||||
cycles-=5;
|
||||
reads_l++; total_cycles += 5;
|
||||
}
|
||||
if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; }
|
||||
else firstrepcycle=1;
|
||||
|
|
@ -970,6 +1098,7 @@ int rep386(int fv)
|
|||
else DI++;
|
||||
c--;
|
||||
cycles-=(is486)?5:8;
|
||||
reads++; total_cycles += is486 ? 5 : 8;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -994,6 +1123,7 @@ int rep386(int fv)
|
|||
else EDI++;
|
||||
c--;
|
||||
cycles-=(is486)?5:8;
|
||||
reads++; total_cycles += is486 ? 5 : 8;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -1016,6 +1146,7 @@ int rep386(int fv)
|
|||
else DI+=2;
|
||||
c--;
|
||||
cycles-=(is486)?5:8;
|
||||
reads++; total_cycles += is486 ? 5 : 8;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -1038,6 +1169,7 @@ int rep386(int fv)
|
|||
else DI+=4;
|
||||
c--;
|
||||
cycles-=(is486)?5:8;
|
||||
reads_l++; total_cycles += is486 ? 5 : 8;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -1060,6 +1192,7 @@ int rep386(int fv)
|
|||
else EDI+=2;
|
||||
c--;
|
||||
cycles-=(is486)?5:8;
|
||||
reads++; total_cycles += is486 ? 5 : 8;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -1082,6 +1215,7 @@ int rep386(int fv)
|
|||
else EDI+=4;
|
||||
c--;
|
||||
cycles-=(is486)?5:8;
|
||||
reads_l++; total_cycles += is486 ? 5 : 8;
|
||||
ins++;
|
||||
if (cycles < cycles_end)
|
||||
break;
|
||||
|
|
@ -1100,6 +1234,7 @@ int rep386(int fv)
|
|||
if (rep32&0x200) ECX=c;
|
||||
else CX=c;
|
||||
CPU_BLOCK_END();
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, reads_l, writes, writes_l, 0);
|
||||
return cpu_state.abrt;
|
||||
//pclog("rep cpu_block_end=%d %p\n", cpu_block_end, (void *)&cpu_block_end);
|
||||
// if (output) pclog("%03X %03X\n",rep32,use32);
|
||||
|
|
|
|||
Loading…
Reference in a new issue