Added VME emulation to Intel DX4, Pentium and Pentium MMX.

Temporarily disabled recompilation of CLI and STI.
This commit is contained in:
SarahW
2017-06-30 20:42:19 +01:00
parent 8fbebead19
commit 1f33b52451
11 changed files with 263 additions and 66 deletions

Binary file not shown.

View File

@@ -7,6 +7,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc);
void pmoderetf(int is32, uint16_t off);
void pmodeiret(int is32);
void x86_int_sw(int num);
int x86_int_sw_rm(int num);
int divl(uint32_t val);
int idivl(int32_t val);

View File

@@ -263,6 +263,38 @@ void x86_int_sw(int num)
CPU_BLOCK_END();
}
int x86_int_sw_rm(int num)
{
uint32_t addr;
uint16_t new_pc, new_cs;
flags_rebuild();
cycles -= timing_int;
addr = num << 2;
new_pc = readmemw(0, addr);
new_cs = readmemw(0, addr + 2);
if (cpu_state.abrt) return 1;
writememw(ss,((SP-2)&0xFFFF),flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; }
writememw(ss,((SP-4)&0xFFFF),CS);
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; }
SP-=6;
eflags &= ~VIF_FLAG;
flags &= ~T_FLAG;
cpu_state.pc = new_pc;
loadcs(new_cs);
oxpc=cpu_state.pc;
cycles -= timing_int_rm;
trap = 0;
CPU_BLOCK_END();
return 0;
}
void x86illegal()
{
// pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode);

View File

@@ -602,7 +602,7 @@ chdir(pcempath);
if (is386)
{
printf("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit");
printf("CR0=%08X CR2=%08X CR3=%08X\n",cr0,cr2,cr3);
printf("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4);
}
printf("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum);
for (c=0;c<1024*1024;c++)

View File

@@ -16,11 +16,13 @@ static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32
static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
return 0;
CLEAR_BITS((uintptr_t)&flags, I_FLAG);
return op_pc;
}
static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
return 0;
SET_BITS((uintptr_t)&flags, I_FLAG);
return op_pc;
}

View File

@@ -51,6 +51,7 @@ OpFn *x86_opcodes_df_a32;
enum
{
CPUID_FPU = (1 << 0),
CPUID_VME = (1 << 1),
CPUID_TSC = (1 << 4),
CPUID_MSR = (1 << 5),
CPUID_CMPXCHG8B = (1 << 8),
@@ -67,6 +68,7 @@ int cpu_busspeed;
int cpu_hasrdtsc;
int cpu_hasMMX, cpu_hasMSR;
int cpu_hasCR4;
int cpu_hasVME;
int cpu_use_dynarec;
int cpu_cyrix_alignment;
@@ -294,8 +296,8 @@ CPU cpus_i486[] =
{"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6},
{"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6},
{"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6},
{"iDX4/75", CPU_i486DX, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9}, /*CPUID available on DX4, >= 75 MHz*/
{"iDX4/100", CPU_i486DX,10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
{"iDX4/75", CPU_iDX4, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9}, /*CPUID available on DX4, >= 75 MHz*/
{"iDX4/100", CPU_iDX4, 10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
{"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7},
{"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8},
{"", -1, 0, 0, 0}
@@ -761,7 +763,11 @@ void cpu_set()
timing_jmp_pm_gate = 37;
timing_misaligned = 3;
break;
case CPU_iDX4:
cpu_hasCR4 = 1;
cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME;
case CPU_i486SX:
case CPU_i486DX:
timing_rr = 1; /*register dest - register src*/
@@ -971,7 +977,8 @@ void cpu_set()
cpu_hasMMX = 0;
cpu_hasMSR = 1;
cpu_hasCR4 = 1;
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
codegen_timing_set(&codegen_timing_pentium);
break;
@@ -1011,7 +1018,8 @@ void cpu_set()
cpu_hasMMX = 1;
cpu_hasMSR = 1;
cpu_hasCR4 = 1;
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
codegen_timing_set(&codegen_timing_pentium);
break;
@@ -1197,6 +1205,24 @@ void cpu_CPUID()
EAX = 0;
break;
case CPU_iDX4:
if (!EAX)
{
EAX = 0x00000001;
EBX = 0x756e6547;
EDX = 0x49656e69;
ECX = 0x6c65746e;
}
else if (EAX == 1)
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_VME;
}
else
EAX = 0;
break;
case CPU_Am486SX:
if (!EAX)
{
@@ -1273,7 +1299,7 @@ void cpu_CPUID()
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
EDX = CPUID_FPU | CPUID_VME | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
}
else
EAX = 0;
@@ -1291,7 +1317,7 @@ void cpu_CPUID()
{
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX;
EDX = CPUID_FPU | CPUID_VME | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX;
}
else
EAX = 0;

View File

@@ -23,16 +23,17 @@ extern int cpu, cpu_manufacturer;
#define CPU_i486DX 10
#define CPU_Am486DX 11
#define CPU_Cx486DX 12
#define CPU_Cx5x86 13
#define CPU_iDX4 13
#define CPU_Cx5x86 14
/*586 class CPUs*/
#define CPU_WINCHIP 14
#define CPU_PENTIUM 15
#define CPU_PENTIUMMMX 16
#define CPU_Cx6x86 17
#define CPU_Cx6x86MX 18
#define CPU_Cx6x86L 19
#define CPU_CxGX1 20
#define CPU_WINCHIP 15
#define CPU_PENTIUM 16
#define CPU_PENTIUMMMX 17
#define CPU_Cx6x86 18
#define CPU_Cx6x86MX 19
#define CPU_Cx6x86L 20
#define CPU_CxGX1 21
#define MANU_INTEL 0
#define MANU_AMD 1
@@ -106,6 +107,7 @@ extern int cpu_hasrdtsc;
extern int cpu_hasMSR;
extern int cpu_hasMMX;
extern int cpu_hasCR4;
extern int cpu_hasVME;
#define CR4_TSD (1 << 2)
#define CR4_DE (1 << 3)

View File

@@ -244,9 +244,14 @@ uint32_t dr[8];
#define V_FLAG 0x0800
#define NT_FLAG 0x4000
#define VM_FLAG 0x0002 /*In EFLAGS*/
#define VIF_FLAG 0x0008 /*In EFLAGS*/
#define VIP_FLAG 0x0010 /*In EFLAGS*/
#define WP_FLAG 0x10000 /*In CR0*/
#define CR4_VME (1 << 0)
#define CR4_PVI (1 << 1)
#define IOPL ((flags>>12)&3)
#define IOPLp ((!(msw&1)) || (CPL<=IOPL))

View File

@@ -27,8 +27,16 @@ static int opCLI(uint32_t fetchdat)
{
if (!IOPLp)
{
x86gpf(NULL,0);
return 1;
if ((!(eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
((eflags & VM_FLAG) && (cr4 & CR4_VME)))
{
eflags &= ~VIF_FLAG;
}
else
{
x86gpf(NULL,0);
return 1;
}
}
else
flags &= ~I_FLAG;
@@ -57,8 +65,22 @@ static int opSTI(uint32_t fetchdat)
{
if (!IOPLp)
{
x86gpf(NULL,0);
return 1;
if ((!(eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
((eflags & VM_FLAG) && (cr4 & CR4_VME)))
{
if (eflags & VIP_FLAG)
{
x86gpf(NULL,0);
return 1;
}
else
eflags |= VIF_FLAG;
}
else
{
x86gpf(NULL,0);
return 1;
}
}
else
flags |= I_FLAG;
@@ -94,11 +116,27 @@ static int opPUSHF(uint32_t fetchdat)
{
if ((eflags & VM_FLAG) && (IOPL < 3))
{
x86gpf(NULL,0);
return 1;
if (cr4 & CR4_VME)
{
uint16_t temp;
flags_rebuild();
temp = (flags & ~I_FLAG) | 0x3000;
if (eflags & VIF_FLAG)
temp |= I_FLAG;
PUSH_W(temp);
}
else
{
x86gpf(NULL,0);
return 1;
}
}
else
{
flags_rebuild();
PUSH_W(flags);
}
flags_rebuild();
PUSH_W(flags);
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0);
return cpu_state.abrt;
@@ -111,8 +149,9 @@ static int opPUSHFD(uint32_t fetchdat)
x86gpf(NULL, 0);
return 1;
}
if (CPUID) tempw = eflags & 0x24;
else tempw = eflags & 4;
if (cpu_CR4_mask & CR4_VME) tempw = eflags & 0x3c;
else if (CPUID) tempw = eflags & 0x24;
else tempw = eflags & 4;
flags_rebuild();
PUSH_L(flags | (tempw << 16));
CLOCK_CYCLES(4);
@@ -151,15 +190,48 @@ static int opPOPF(uint32_t fetchdat)
if ((eflags & VM_FLAG) && (IOPL < 3))
{
x86gpf(NULL, 0);
return 1;
}
tempw = POP_W(); if (cpu_state.abrt) return 1;
if (cr4 & CR4_VME)
{
uint32_t old_esp = ESP;
if (!(CPL) || !(msw & 1)) flags = (tempw & 0x7fd5) | 2;
else if (IOPLp) flags = (flags & 0x3000) | (tempw & 0x4fd5) | 2;
else flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2;
tempw = POP_W();
if (cpu_state.abrt)
{
ESP = old_esp;
return 1;
}
if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (eflags & VIP_FLAG)))
{
ESP = old_esp;
x86gpf(NULL, 0);
return 1;
}
if (tempw & I_FLAG)
eflags |= VIF_FLAG;
else
eflags &= ~VIF_FLAG;
flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2;
}
else
{
x86gpf(NULL, 0);
return 1;
}
}
else
{
tempw = POP_W();
if (cpu_state.abrt)
return 1;
if (!(CPL) || !(msw & 1))
flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
flags = (flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2;
}
flags_extract();
CLOCK_CYCLES(5);
@@ -185,11 +257,12 @@ static int opPOPFD(uint32_t fetchdat)
else if (IOPLp) flags = (flags & 0x3000) | (templ & 0x4fd5) | 2;
else flags = (flags & 0x3200) | (templ & 0x4dd5) | 2;
templ &= is486 ? 0x240000 : 0;
templ &= is486 ? 0x3c0000 : 0;
templ |= ((eflags&3) << 16);
if (CPUID) eflags = (templ >> 16) & 0x27;
else if (is486) eflags = (templ >> 16) & 7;
else eflags = (templ >> 16) & 3;
if (cpu_CR4_mask & CR4_VME) eflags = (templ >> 16) & 0x3f;
else if (CPUID) eflags = (templ >> 16) & 0x27;
else if (is486) eflags = (templ >> 16) & 7;
else eflags = (templ >> 16) & 3;
flags_extract();

View File

@@ -29,15 +29,39 @@ static int opINT1(uint32_t fetchdat)
static int opINT(uint32_t fetchdat)
{
int cycles_old = cycles; UNUSED(cycles_old);
uint8_t temp;
/*if (msw&1) pclog("INT %i %i %i\n",cr0&1,eflags&VM_FLAG,IOPL);*/
uint8_t temp = getbytef();
if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
{
if (cr4 & CR4_VME)
{
uint16_t t;
uint8_t d;
cpl_override = 1;
t = readmemw(tr.base, 0x66) - 32;
cpl_override = 0;
if (cpu_state.abrt) return 1;
t += (temp >> 3);
if (t <= tr.limit)
{
cpl_override = 1;
d = readmemb(tr.base, t);// + (temp >> 3));
cpl_override = 0;
if (cpu_state.abrt) return 1;
if (!(d & (1 << (temp & 7))))
{
x86_int_sw_rm(temp);
PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0);
return 1;
}
}
}
x86gpf(NULL,0);
return 1;
}
temp = getbytef();
// /*if (temp == 0x10 && AH == 0xe) */pclog("INT %02X : %04X %04X %04X %04X %c %04X:%04X\n", temp, AX, BX, CX, DX, (AL < 32) ? ' ' : AL, CS, pc);
// if (CS == 0x0028 && pc == 0xC03813C0)
// output = 3;

View File

@@ -141,35 +141,67 @@ static int opIRET(uint32_t fetchdat)
if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
{
x86gpf(NULL,0);
return 1;
}
if (msw&1)
{
optype = IRET;
pmodeiret(0);
optype = 0;
}
else
{
uint16_t new_cs;
oxpc = cpu_state.pc;
if (stack32)
if (cr4 & CR4_VME)
{
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
uint16_t new_pc, new_cs, new_flags;
new_pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
new_flags = readmemw(ss, ((SP + 4) & 0xffff));
if (cpu_state.abrt)
return 1;
if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (eflags & VIP_FLAG)))
{
x86gpf(NULL, 0);
return 1;
}
SP += 6;
if (new_flags & I_FLAG)
eflags |= VIF_FLAG;
else
eflags &= ~VIF_FLAG;
flags = (flags & 0x3300) | (new_flags & 0x4cd5) | 2;
loadcs(new_cs);
cpu_state.pc = new_pc;
cycles -= timing_iret_rm;
}
else
{
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2;
SP += 6;
x86gpf(NULL,0);
return 1;
}
}
else
{
if (msw&1)
{
optype = IRET;
pmodeiret(0);
optype = 0;
}
else
{
uint16_t new_cs;
oxpc = cpu_state.pc;
if (stack32)
{
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
}
else
{
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2;
SP += 6;
}
loadcs(new_cs);
cycles -= timing_iret_rm;
}
loadcs(new_cs);
cycles -= timing_iret_rm;
}
flags_extract();
nmi_enable = 1;