Implemented selector limits on some instructions - fixes LBA2.

GPFs in real mode now work.
Selectors correctly zeroed on far return to lower privilege.
This commit is contained in:
TomW 2014-08-13 20:33:56 +01:00
commit cd2c3b47ed
16 changed files with 404 additions and 462 deletions

256
src/386.c
View file

@ -10,6 +10,9 @@
#include "timer.h"
#include "video.h"
x86seg *ea_seg;
int nmi_enable = 1;
int inscounts[256];
@ -39,6 +42,27 @@ int trap;
} \
}
#define CHECK_READ(seg, low, high) \
if ((low < (seg)->limit_low) || (high > (seg)->limit_high)) \
{ \
x86gpf("Limit check", 0); \
return 0; \
}
#define CHECK_WRITE(seg, low, high) \
if ((low < (seg)->limit_low) || (high > (seg)->limit_high)) \
{ \
x86gpf("Limit check", 0); \
return 0; \
}
#define CHECK_WRITE_REP(seg, low, high) \
if ((low < (seg)->limit_low) || (high > (seg)->limit_high)) \
{ \
x86gpf("Limit check", 0); \
break; \
}
int cpl_override=0;
@ -206,8 +230,8 @@ uint32_t *mod1seg[8];
static inline void fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = ds;
ea_rseg = DS;
easeg = ea_seg->base;
ea_rseg = ea_seg->seg;
if (rm == 4)
{
uint8_t sib = rmdat >> 8;
@ -231,10 +255,11 @@ static inline void fetch_ea_32_long(uint32_t rmdat)
/*SIB byte present*/
if ((sib & 7) == 5 && !mod)
eaaddr = getlong();
else if ((sib & 6) == 4)
else if ((sib & 6) == 4 && !ssegs)
{
easeg = ss;
ea_rseg = SS;
ea_seg = &_ss;
}
if (((sib >> 3) & 7) != 4)
eaaddr += regs[(sib >> 3) & 7].l << (sib >> 6);
@ -244,10 +269,11 @@ static inline void fetch_ea_32_long(uint32_t rmdat)
eaaddr = regs[rm].l;
if (mod)
{
if (rm == 5)
if (rm == 5 && !ssegs)
{
easeg = ss;
ea_rseg = SS;
ea_seg = &_ss;
}
if (mod == 1)
{
@ -276,11 +302,11 @@ static inline void fetch_ea_32_long(uint32_t rmdat)
static inline void fetch_ea_16_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = ea_seg->base;
ea_rseg = ea_seg->seg;
if (!mod && rm == 6)
{
eaaddr = getword();
easeg = ds;
ea_rseg = DS;
}
else
{
@ -297,9 +323,12 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
break;
}
eaaddr += (*mod1add[0][rm]) + (*mod1add[1][rm]);
easeg = *mod1seg[rm];
if (mod1seg[rm] == &ss) ea_rseg = SS;
else ea_rseg = DS;
if (mod1seg[rm] == &ss && !ssegs)
{
easeg = ss;
ea_rseg = SS;
ea_seg = &_ss;
}
eaaddr &= 0xFFFF;
}
if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC)
@ -328,7 +357,6 @@ void x86_int(int num)
}
else
{
if (ssegs) ss=oldss;
if (stack32)
{
writememw(ss,ESP-2,flags);
@ -365,7 +393,6 @@ void x86_int_sw(int num)
}
else
{
if (ssegs) ss=oldss;
if (stack32)
{
writememw(ss,ESP-2,flags);
@ -418,7 +445,6 @@ void rep386(int fv)
uint8_t temp2;
uint16_t tempw,tempw2,of;
uint32_t ipc=oldpc;//pc-1;
int changeds=0;
uint32_t oldds;
uint32_t rep32=op32;
uint32_t templ,templ2;
@ -446,43 +472,23 @@ void rep386(int fv)
pc=ipc+1;
break;
case 0x26: case 0x126: case 0x226: case 0x326: /*ES:*/
oldds=ds;
ds=es;
rds=ES;
changeds=1;
ea_seg = &_es;
goto startrep;
break;
case 0x2E: case 0x12E: case 0x22E: case 0x32E: /*CS:*/
oldds=ds;
ds=cs;
rds=CS;
changeds=1;
ea_seg = &_cs;
goto startrep;
break;
case 0x36: case 0x136: case 0x236: case 0x336: /*SS:*/
oldds=ds;
ds=ss;
rds=SS;
changeds=1;
ea_seg = &_ss;
goto startrep;
break;
case 0x3E: case 0x13E: case 0x23E: case 0x33E: /*DS:*/
oldds=ds;
ds=ds;
changeds=1;
ea_seg = &_ds;
goto startrep;
break;
case 0x64: case 0x164: case 0x264: case 0x364: /*FS:*/
oldds=ds;
ds=fs;
rds=FS;
changeds=1;
ea_seg = &_fs;
goto startrep;
case 0x65: case 0x165: case 0x265: case 0x365: /*GS:*/
oldds=ds;
ds=gs;
rds=GS;
changeds=1;
ea_seg = &_gs;
goto startrep;
case 0x66: case 0x166: case 0x266: case 0x366: /*Data size prefix*/
rep32^=0x100;
@ -502,7 +508,7 @@ void rep386(int fv)
c--;
cycles-=15;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x26C: case 0x36C: /*REP INSB*/
@ -517,7 +523,7 @@ void rep386(int fv)
c--;
cycles-=15;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x6D: /*REP INSW*/
@ -531,7 +537,7 @@ void rep386(int fv)
c--;
cycles-=15;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x16D: /*REP INSL*/
@ -545,7 +551,7 @@ void rep386(int fv)
c--;
cycles-=15;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x26D: /*REP INSW*/
@ -559,7 +565,7 @@ void rep386(int fv)
c--;
cycles-=15;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x36D: /*REP INSL*/
@ -573,13 +579,13 @@ void rep386(int fv)
c--;
cycles-=15;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x6E: case 0x16E: /*REP OUTSB*/
if (c>0)
{
temp2=readmemb(ds,SI);
temp2 = readmemb(ea_seg->base, SI);
if (abrt) break;
checkio_perm(DX);
outb(DX,temp2);
@ -588,13 +594,13 @@ void rep386(int fv)
c--;
cycles-=14;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x26E: case 0x36E: /*REP OUTSB*/
if (c>0)
{
temp2=readmemb(ds,ESI);
temp2 = readmemb(ea_seg->base, ESI);
if (abrt) break;
checkio_perm(DX);
outb(DX,temp2);
@ -603,13 +609,13 @@ void rep386(int fv)
c--;
cycles-=14;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x6F: /*REP OUTSW*/
if (c>0)
{
tempw=readmemw(ds,SI);
tempw = readmemw(ea_seg->base, SI);
if (abrt) break;
// pclog("OUTSW %04X -> %04X\n",SI,tempw);
outw(DX,tempw);
@ -618,13 +624,13 @@ void rep386(int fv)
c--;
cycles-=14;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x16F: /*REP OUTSL*/
if (c > 0)
{
templ = readmeml(ds, SI);
templ = readmeml(ea_seg->base, SI);
if (abrt) break;
outl(DX, templ);
if (flags & D_FLAG) SI -= 4;
@ -632,13 +638,13 @@ void rep386(int fv)
c--;
cycles -= 14;
}
if (c > 0) { firstrepcycle = 0; pc = ipc; if (ssegs) ssegs++; }
if (c > 0) { firstrepcycle = 0; pc = ipc; }
else firstrepcycle = 1;
break;
case 0x26F: /*REP OUTSW*/
if (c>0)
{
tempw=readmemw(ds,ESI);
tempw = readmemw(ea_seg->base, ESI);
if (abrt) break;
outw(DX,tempw);
if (flags&D_FLAG) ESI-=2;
@ -646,13 +652,13 @@ void rep386(int fv)
c--;
cycles-=14;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x36F: /*REP OUTSL*/
if (c > 0)
{
templ = readmeml(ds, ESI);
templ = readmeml(ea_seg->base, ESI);
if (abrt) break;
outl(DX, templ);
if (flags & D_FLAG) ESI -= 4;
@ -660,7 +666,7 @@ void rep386(int fv)
c--;
cycles -= 14;
}
if (c > 0) { firstrepcycle = 0; pc = ipc; if (ssegs) ssegs++; }
if (c > 0) { firstrepcycle = 0; pc = ipc; }
else firstrepcycle = 1;
break;
case 0x90: case 0x190: /*REP NOP*/
@ -669,7 +675,8 @@ void rep386(int fv)
case 0xA4: case 0x1A4: /*REP MOVSB*/
if (c>0)
{
temp2=readmemb(ds,SI); if (abrt) break;
CHECK_WRITE_REP(&_es, DI, DI);
temp2 = readmemb(ea_seg->base, SI); if (abrt) break;
writememb(es,DI,temp2); if (abrt) break;
// if (output==3) pclog("MOVSB %08X:%04X -> %08X:%04X %02X\n",ds,SI,es,DI,temp2);
if (flags&D_FLAG) { DI--; SI--; }
@ -677,39 +684,42 @@ void rep386(int fv)
c--;
cycles-=(is486)?3:4;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x2A4: case 0x3A4: /*REP MOVSB*/
if (c>0)
{
temp2=readmemb(ds,ESI); if (abrt) break;
CHECK_WRITE_REP(&_es, EDI, EDI);
temp2 = readmemb(ea_seg->base, ESI); if (abrt) break;
writememb(es,EDI,temp2); if (abrt) break;
if (flags&D_FLAG) { EDI--; ESI--; }
else { EDI++; ESI++; }
c--;
cycles-=(is486)?3:4;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0xA5: /*REP MOVSW*/
if (c>0)
{
tempw=readmemw(ds,SI); if (abrt) break;
CHECK_WRITE_REP(&_es, DI, DI+1);
tempw = readmemw(ea_seg->base, SI); if (abrt) break;
writememw(es,DI,tempw); if (abrt) break;
if (flags&D_FLAG) { DI-=2; SI-=2; }
else { DI+=2; SI+=2; }
c--;
cycles-=(is486)?3:4;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x1A5: /*REP MOVSL*/
if (c>0)
{
templ=readmeml(ds,SI); if (abrt) break;
CHECK_WRITE_REP(&_es, DI, DI+3);
templ = readmeml(ea_seg->base, SI); if (abrt) break;
// pclog("MOVSD %08X from %08X to %08X (%04X:%08X)\n", templ, ds+SI, es+DI, CS, pc);
writememl(es,DI,templ); if (abrt) break;
if (flags&D_FLAG) { DI-=4; SI-=4; }
@ -717,13 +727,14 @@ void rep386(int fv)
c--;
cycles-=(is486)?3:4;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x2A5: /*REP MOVSW*/
if (c>0)
{
tempw=readmemw(ds,ESI); if (abrt) break;
CHECK_WRITE_REP(&_es, EDI, EDI+1);
tempw = readmemw(ea_seg->base, ESI); if (abrt) break;
writememw(es,EDI,tempw); if (abrt) break;
// if (output) pclog("Written %04X from %08X to %08X %i %08X %04X %08X %04X\n",tempw,ds+ESI,es+EDI,c,ds,ES,es,ES);
if (flags&D_FLAG) { EDI-=2; ESI-=2; }
@ -731,13 +742,14 @@ void rep386(int fv)
c--;
cycles-=(is486)?3:4;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x3A5: /*REP MOVSL*/
if (c>0)
{
templ=readmeml(ds,ESI); if (abrt) break;
CHECK_WRITE_REP(&_es, EDI, EDI+3);
templ = readmeml(ea_seg->base, ESI); if (abrt) break;
// if ((EDI&0xFFFF0000)==0xA0000) cycles-=12;
writememl(es,EDI,templ); if (abrt) break;
// if (output) pclog("Load %08X from %08X to %08X %04X %08X %04X %08X\n",templ,ESI,EDI,DS,ds,ES,es);
@ -746,14 +758,14 @@ void rep386(int fv)
c--;
cycles-=(is486)?3:4;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0xA6: case 0x1A6: /*REP CMPSB*/
tempz = (fv) ? 1 : 0;
if ((c>0) && (fv==tempz))
{
temp=readmemb(ds,SI);
temp = readmemb(ea_seg->base, SI);
temp2=readmemb(es,DI);
if (abrt) { flags=of; break; }
if (flags&D_FLAG) { DI--; SI--; }
@ -763,14 +775,14 @@ void rep386(int fv)
setsub8(temp,temp2);
tempz = (ZF_SET()) ? 1 : 0;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0x2A6: case 0x3A6: /*REP CMPSB*/
tempz = (fv) ? 1 : 0;
if ((c>0) && (fv==tempz))
{
temp=readmemb(ds,ESI);
temp = readmemb(ea_seg->base, ESI);
temp2=readmemb(es,EDI);
if (abrt) { flags=of; break; }
if (flags&D_FLAG) { EDI--; ESI--; }
@ -780,7 +792,7 @@ void rep386(int fv)
setsub8(temp,temp2);
tempz = (ZF_SET()) ? 1 : 0;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0xA7: /*REP CMPSW*/
@ -788,7 +800,7 @@ void rep386(int fv)
if ((c>0) && (fv==tempz))
{
// pclog("CMPSW %05X %05X %08X %08X ", ds+SI, es+DI, readlookup2[(ds+SI)>>12], readlookup2[(es+DI)>>12]);
tempw=readmemw(ds,SI);
tempw = readmemw(ea_seg->base, SI);
tempw2=readmemw(es,DI);
// pclog("%04X %04X %02X\n", tempw, tempw2, ram[8]);
@ -800,14 +812,14 @@ void rep386(int fv)
setsub16(tempw,tempw2);
tempz = (ZF_SET()) ? 1 : 0;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0x1A7: /*REP CMPSL*/
tempz = (fv) ? 1 : 0;
if ((c>0) && (fv==tempz))
{
templ=readmeml(ds,SI);
templ = readmeml(ea_seg->base, SI);
templ2=readmeml(es,DI);
if (abrt) { flags=of; break; }
if (flags&D_FLAG) { DI-=4; SI-=4; }
@ -817,14 +829,14 @@ void rep386(int fv)
setsub32(templ,templ2);
tempz = (ZF_SET()) ? 1 : 0;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0x2A7: /*REP CMPSW*/
tempz = (fv) ? 1 : 0;
if ((c>0) && (fv==tempz))
{
tempw=readmemw(ds,ESI);
tempw = readmemw(ea_seg->base, ESI);
tempw2=readmemw(es,EDI);
if (abrt) { flags=of; break; }
if (flags&D_FLAG) { EDI-=2; ESI-=2; }
@ -834,14 +846,14 @@ void rep386(int fv)
setsub16(tempw,tempw2);
tempz = (ZF_SET()) ? 1 : 0;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0x3A7: /*REP CMPSL*/
tempz = (fv) ? 1 : 0;
if ((c>0) && (fv==tempz))
{
templ=readmeml(ds,ESI);
templ = readmeml(ea_seg->base, ESI);
templ2=readmeml(es,EDI);
if (abrt) { flags=of; break; }
if (flags&D_FLAG) { EDI-=4; ESI-=4; }
@ -851,13 +863,14 @@ void rep386(int fv)
setsub32(templ,templ2);
tempz = (ZF_SET()) ? 1 : 0;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0xAA: case 0x1AA: /*REP STOSB*/
if (c>0)
{
CHECK_WRITE_REP(&_es, DI, DI);
writememb(es,DI,AL);
if (abrt) break;
if (flags&D_FLAG) DI--;
@ -865,12 +878,13 @@ void rep386(int fv)
c--;
cycles-=(is486)?4:5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x2AA: case 0x3AA: /*REP STOSB*/
if (c>0)
{
CHECK_WRITE_REP(&_es, EDI, EDI);
writememb(es,EDI,AL);
if (abrt) break;
if (flags&D_FLAG) EDI--;
@ -878,12 +892,13 @@ void rep386(int fv)
c--;
cycles-=(is486)?4:5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0xAB: /*REP STOSW*/
if (c>0)
{
CHECK_WRITE_REP(&_es, DI, DI+1);
writememw(es,DI,AX);
if (abrt) break;
if (flags&D_FLAG) DI-=2;
@ -891,12 +906,13 @@ void rep386(int fv)
c--;
cycles-=(is486)?4:5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x2AB: /*REP STOSW*/
if (c>0)
{
CHECK_WRITE_REP(&_es, EDI, EDI+1);
writememw(es,EDI,AX);
if (abrt) break;
if (flags&D_FLAG) EDI-=2;
@ -904,12 +920,13 @@ void rep386(int fv)
c--;
cycles-=(is486)?4:5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x1AB: /*REP STOSL*/
if (c>0)
{
CHECK_WRITE_REP(&_es, DI, DI+3);
writememl(es,DI,EAX);
if (abrt) break;
if (flags&D_FLAG) DI-=4;
@ -917,12 +934,13 @@ void rep386(int fv)
c--;
cycles-=(is486)?4:5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x3AB: /*REP STOSL*/
if (c>0)
{
CHECK_WRITE_REP(&_es, EDI, EDI+3);
writememl(es,EDI,EAX);
if (abrt) break;
if (flags&D_FLAG) EDI-=4;
@ -930,91 +948,91 @@ void rep386(int fv)
c--;
cycles-=(is486)?4:5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0xAC: case 0x1AC: /*REP LODSB*/
// if (ds==0xFFFFFFFF) pclog("Null selector REP LODSB %04X(%06X):%06X\n",CS,cs,pc);
if (c>0)
{
AL=readmemb(ds,SI);
AL = readmemb(ea_seg->base, SI);
if (abrt) break;
if (flags&D_FLAG) SI--;
else SI++;
c--;
cycles-=5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x2AC: case 0x3AC: /*REP LODSB*/
// if (ds==0xFFFFFFFF) pclog("Null selector REP LODSB %04X(%06X):%06X\n",CS,cs,pc);
if (c>0)
{
AL=readmemb(ds,ESI);
AL = readmemb(ea_seg->base, ESI);
if (abrt) break;
if (flags&D_FLAG) ESI--;
else ESI++;
c--;
cycles-=5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0xAD: /*REP LODSW*/
// if (ds==0xFFFFFFFF) pclog("Null selector REP LODSW %04X(%06X):%06X\n",CS,cs,pc);
if (c>0)
{
AX=readmemw(ds,SI);
AX = readmemw(ea_seg->base, SI);
if (abrt) break;
if (flags&D_FLAG) SI-=2;
else SI+=2;
c--;
cycles-=5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x1AD: /*REP LODSL*/
// if (ds==0xFFFFFFFF) pclog("Null selector REP LODSL %04X(%06X):%06X\n",CS,cs,pc);
if (c>0)
{
EAX=readmeml(ds,SI);
EAX = readmeml(ea_seg->base, SI);
if (abrt) break;
if (flags&D_FLAG) SI-=4;
else SI+=4;
c--;
cycles-=5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x2AD: /*REP LODSW*/
// if (ds==0xFFFFFFFF) pclog("Null selector REP LODSW %04X(%06X):%06X\n",CS,cs,pc);
if (c>0)
{
AX=readmemw(ds,ESI);
AX = readmemw(ea_seg->base, ESI);
if (abrt) break;
if (flags&D_FLAG) ESI-=2;
else ESI+=2;
c--;
cycles-=5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0x3AD: /*REP LODSL*/
// if (ds==0xFFFFFFFF) pclog("Null selector REP LODSL %04X(%06X):%06X\n",CS,cs,pc);
if (c>0)
{
EAX=readmeml(ds,ESI);
EAX = readmeml(ea_seg->base, ESI);
if (abrt) break;
if (flags&D_FLAG) ESI-=4;
else ESI+=4;
c--;
cycles-=5;
}
if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; }
if (c>0) { firstrepcycle=0; pc=ipc; }
else firstrepcycle=1;
break;
case 0xAE: case 0x1AE: /*REP SCASB*/
@ -1032,7 +1050,7 @@ void rep386(int fv)
c--;
cycles-=(is486)?5:8;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0x2AE: case 0x3AE: /*REP SCASB*/
@ -1051,7 +1069,7 @@ void rep386(int fv)
c--;
cycles-=(is486)?5:8;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0xAF: /*REP SCASW*/
@ -1068,7 +1086,7 @@ void rep386(int fv)
c--;
cycles-=(is486)?5:8;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0x1AF: /*REP SCASL*/
@ -1085,7 +1103,7 @@ void rep386(int fv)
c--;
cycles-=(is486)?5:8;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0x2AF: /*REP SCASW*/
@ -1102,7 +1120,7 @@ void rep386(int fv)
c--;
cycles-=(is486)?5:8;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
case 0x3AF: /*REP SCASL*/
@ -1119,7 +1137,7 @@ void rep386(int fv)
c--;
cycles-=(is486)?5:8;
}
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; }
if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
else firstrepcycle=1;
break;
@ -1132,7 +1150,6 @@ void rep386(int fv)
}
if (rep32&0x200) ECX=c;
else CX=c;
if (changeds) ds=oldds;
// if (output) pclog("%03X %03X\n",rep32,use32);
}
@ -1268,8 +1285,12 @@ opcode_realstart:
dontprint=0;
ea_seg = &_ds;
ssegs = 0;
opcodestart:
fetchdat = fastreadl(cs + pc);
if (!abrt)
{
tempc = CF_SET();
@ -1287,20 +1308,7 @@ opcodestart:
}
if (!use32) pc &= 0xffff;
/* if (ins == 74400000)
{
pclog("Output on\n");
output = 3;
}*/
if ((cs + pc) == 0xc)
fatal("Dead\n");
if (ssegs)
{
ds=oldds;
ss=oldss;
rds=DS;
ssegs=0;
}
if (abrt)
{
flags_rebuild();
@ -1397,23 +1405,15 @@ opcodestart:
}
}
// tempi = ZF_SET() ? Z_FLAG : 0;
// if (tempi != (flags & Z_FLAG))
// fatal("Z flag mismatch %02X %08X\n", opcode, fetchdat);
ins++;
insc++;
/*output = 3;
if (ins == 1372108)
fatal("here2\n");
if (ins == 50966339)
fatal("here\n");*/
if (timetolive)
{
timetolive--;
if (!timetolive)
fatal("Life expired\n");
}
// if (ins == 97300000) output = 3;
}
tsc += cycdiff;

View file

@ -588,15 +588,15 @@ chdir(pcempath);
printf("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real");
else
printf("In %s mode\n",(msw&1)?"protected":"real");
printf("CS : base=%06X limit=%04X access=%02X\n",cs,_cs.limit,_cs.access);
printf("DS : base=%06X limit=%04X access=%02X\n",ds,_ds.limit,_ds.access);
printf("ES : base=%06X limit=%04X access=%02X\n",es,_es.limit,_es.access);
printf("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high);
printf("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high);
printf("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high);
if (is386)
{
printf("FS : base=%06X limit=%04X access=%02X\n",fs,_fs.limit,_fs.access);
printf("GS : base=%06X limit=%04X access=%02X\n",gs,_gs.limit,_gs.access);
printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high);
printf("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high);
}
printf("SS : base=%06X limit=%04X access=%02X\n",ss,_ss.limit,_ss.access);
printf("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high);
printf("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit);
printf("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit);
printf("IDT : base=%06X limit=%04X\n",idt.base,idt.limit);
@ -646,6 +646,7 @@ void resetx86()
ESP=0;
mmu_perm=4;
memset(inscounts, 0, sizeof(inscounts));
x86seg_reset();
}
void softresetx86()
@ -665,6 +666,7 @@ void softresetx86()
//rammask=0xFFFFFFFF;
flags=2;
idt.base = 0;
x86seg_reset();
}
static void setznp8(uint8_t val)

View file

@ -108,15 +108,18 @@ extern int cycdiff;
typedef struct
{
uint32_t base;
uint32_t limit,limitw;
uint32_t limit;
uint8_t access;
uint16_t seg;
uint32_t limit_low, limit_high;
} x86seg;
x86seg gdt,ldt,idt,tr;
x86seg _cs,_ds,_es,_ss,_fs,_gs;
x86seg _oldds;
extern x86seg *ea_seg;
uint32_t pccache;
uint8_t *pccache2;
/*Segments -

View file

@ -58,7 +58,7 @@ extern uint16_t *mod1add[2][8];
extern uint32_t *mod1seg[8];
#define IRQTEST ((flags&I_FLAG) && (pic.pend&~pic.mask) && !ssegs && !noint)
#define IRQTEST ((flags&I_FLAG) && (pic.pend&~pic.mask) && !noint)
extern int cgate32;
@ -99,3 +99,5 @@ extern uint32_t rmdat32;
extern int inscounts[256];
void x86illegal();
void x86seg_reset();

View file

@ -1,7 +1,6 @@
#define CALL_FAR_w(new_seg, new_pc) \
old_cs = CS; \
old_pc = pc; \
if (ssegs) ss = oldss; \
oxpc = pc; \
pc = new_pc; \
optype = CALL; \
@ -27,7 +26,6 @@
#define CALL_FAR_l(new_seg, new_pc) \
old_cs = CS; \
old_pc = pc; \
if (ssegs) ss = oldss; \
oxpc = pc; \
pc = new_pc; \
optype = CALL; \
@ -54,7 +52,6 @@
#define CALL_FAR_nr(new_seg, new_pc) \
old_cs = CS; \
old_pc = pc; \
if (ssegs) ss = oldss; \
oxpc = pc; \
pc = new_pc; \
optype = CALL; \
@ -130,7 +127,6 @@ static int opFF_w_a16(uint32_t fetchdat)
break;
case 0x10: /*CALL*/
new_pc = geteaw(); if (abrt) return 0;
if (ssegs) ss = oldss;
PUSH_W(pc);
pc = new_pc;
if (is486) cycles -= 5;
@ -160,7 +156,6 @@ static int opFF_w_a16(uint32_t fetchdat)
break;
case 0x30: /*PUSH w*/
temp = geteaw(); if (abrt) return 0;
if (ssegs) ss = oldss;
PUSH_W(temp);
cycles -= ((mod == 3) ? 2 : 5);
break;
@ -196,7 +191,6 @@ static int opFF_w_a32(uint32_t fetchdat)
break;
case 0x10: /*CALL*/
new_pc = geteaw(); if (abrt) return 0;
if (ssegs) ss = oldss;
PUSH_W(pc);
pc = new_pc;
if (is486) cycles -= 5;
@ -226,7 +220,6 @@ static int opFF_w_a32(uint32_t fetchdat)
break;
case 0x30: /*PUSH w*/
temp = geteaw(); if (abrt) return 0;
if (ssegs) ss = oldss;
PUSH_W(temp);
cycles -= ((mod == 3) ? 2 : 5);
break;
@ -263,7 +256,6 @@ static int opFF_l_a16(uint32_t fetchdat)
break;
case 0x10: /*CALL*/
new_pc = geteal(); if (abrt) return 0;
if (ssegs) ss = oldss;
PUSH_L(pc);
pc = new_pc;
if (is486) cycles -= 5;
@ -293,7 +285,6 @@ static int opFF_l_a16(uint32_t fetchdat)
break;
case 0x30: /*PUSH l*/
temp = geteal(); if (abrt) return 0;
if (ssegs) ss = oldss;
PUSH_L(temp);
cycles -= ((mod == 3) ? 2 : 5);
break;
@ -329,7 +320,6 @@ static int opFF_l_a32(uint32_t fetchdat)
break;
case 0x10: /*CALL*/
new_pc = geteal(); if (abrt) return 0;
if (ssegs) ss = oldss;
PUSH_L(pc); if (abrt) return 0;
pc = new_pc;
if (is486) cycles -= 5;
@ -359,7 +349,6 @@ static int opFF_l_a32(uint32_t fetchdat)
break;
case 0x30: /*PUSH l*/
temp = geteal(); if (abrt) return 0;
if (ssegs) ss = oldss;
PUSH_L(temp);
cycles -= ((mod == 3) ? 2 : 5);
break;

View file

@ -76,7 +76,6 @@ static int opLAHF(uint32_t fetchdat)
static int opPUSHF(uint32_t fetchdat)
{
if (ssegs) ss = oldss;
if ((eflags & VM_FLAG) && (IOPL < 3))
{
x86gpf(NULL,0);
@ -90,7 +89,6 @@ static int opPUSHF(uint32_t fetchdat)
static int opPUSHFD(uint32_t fetchdat)
{
uint16_t tempw;
if (ssegs) ss=oldss;
if ((eflags & VM_FLAG) && (IOPL < 3))
{
x86gpf(NULL, 0);
@ -107,7 +105,6 @@ static int opPUSHFD(uint32_t fetchdat)
static int opPOPF_286(uint32_t fetchdat)
{
uint16_t tempw;
if (ssegs) ss = oldss;
if ((eflags & VM_FLAG) && (IOPL < 3))
{
@ -129,7 +126,6 @@ static int opPOPF_286(uint32_t fetchdat)
static int opPOPF(uint32_t fetchdat)
{
uint16_t tempw;
if (ssegs) ss = oldss;
if ((eflags & VM_FLAG) && (IOPL < 3))
{
@ -150,7 +146,6 @@ static int opPOPF(uint32_t fetchdat)
static int opPOPFD(uint32_t fetchdat)
{
uint32_t templ;
if (ssegs) ss = oldss;
if ((eflags & VM_FLAG) && (IOPL < 3))
{

View file

@ -198,7 +198,6 @@ static int opJMP_far_a32(uint32_t fetchdat)
int opCALL_r16(uint32_t fetchdat)
{
int16_t addr = (int16_t)getwordf();
if (ssegs) ss=oldss;
PUSH_W(pc);
pc += addr;
cycles -= (is486) ? 3 : 7;
@ -207,7 +206,6 @@ int opCALL_r16(uint32_t fetchdat)
int opCALL_r32(uint32_t fetchdat)
{
int32_t addr = getlong(); if (abrt) return 0;
if (ssegs) ss=oldss;
PUSH_L(pc);
pc += addr;
cycles -= (is486) ? 3 : 7;
@ -218,7 +216,6 @@ int opRET_w(uint32_t fetchdat)
{
uint16_t ret;
if (ssegs) ss=oldss;
ret = POP_W(); if (abrt) return 0;
pc = ret;
@ -229,7 +226,6 @@ int opRET_l(uint32_t fetchdat)
{
uint32_t ret;
if (ssegs) ss=oldss;
ret = POP_L(); if (abrt) return 0;
pc = ret;
@ -242,7 +238,6 @@ int opRET_w_imm(uint32_t fetchdat)
uint16_t offset = getwordf();
uint16_t ret;
if (ssegs) ss=oldss;
ret = POP_W(); if (abrt) return 0;
if (stack32) ESP += offset;
else SP += offset;
@ -256,7 +251,6 @@ int opRET_l_imm(uint32_t fetchdat)
uint16_t offset = getwordf();
uint32_t ret;
if (ssegs) ss=oldss;
ret = POP_L(); if (abrt) return 0;
if (stack32) ESP += offset;
else SP += offset;

View file

@ -515,7 +515,7 @@ static int opHLT(uint32_t fetchdat)
x86gpf(NULL,0);
return 0;
}
if (!((flags&I_FLAG) && pic_intpending && !ssegs))
if (!((flags&I_FLAG) && pic_intpending))
{
cycles -= 100;
pc--;

View file

@ -57,6 +57,7 @@ int opMOVD_mm_l_a16(uint32_t fetchdat)
}
else
{
CHECK_WRITE(ea_seg, eaaddr, eaaddr + 3);
writememl(easeg, eaaddr, MM[reg].l[0]); if (abrt) return 0;
cycles -= 2;
}
@ -74,6 +75,7 @@ int opMOVD_mm_l_a32(uint32_t fetchdat)
}
else
{
CHECK_WRITE(ea_seg, eaaddr, eaaddr + 3);
writememl(easeg, eaaddr, MM[reg].l[0]); if (abrt) return 0;
cycles -= 2;
}
@ -137,6 +139,7 @@ int opMOVQ_mm_q_a16(uint32_t fetchdat)
}
else
{
CHECK_WRITE(ea_seg, eaaddr, eaaddr + 7);
writememl(easeg, eaaddr, MM[reg].l[0]);
writememl(easeg, eaaddr + 4, MM[reg].l[1]); if (abrt) return 0;
cycles -= 2;
@ -155,6 +158,7 @@ int opMOVQ_mm_q_a32(uint32_t fetchdat)
}
else
{
CHECK_WRITE(ea_seg, eaaddr, eaaddr + 7);
writememl(easeg, eaaddr, MM[reg].l[0]);
writememl(easeg, eaaddr + 4, MM[reg].l[1]); if (abrt) return 0;
cycles -= 2;

View file

@ -213,7 +213,7 @@ static int opMOV_l_imm_a32(uint32_t fetchdat)
static int opMOV_AL_a16(uint32_t fetchdat)
{
uint16_t addr = getwordf();
uint8_t temp = readmemb(ds, addr); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, addr); if (abrt) return 0;
AL = temp;
cycles -= (is486) ? 1 : 4;
return 0;
@ -221,7 +221,7 @@ static int opMOV_AL_a16(uint32_t fetchdat)
static int opMOV_AL_a32(uint32_t fetchdat)
{
uint32_t addr = getlong();
uint8_t temp = readmemb(ds, addr); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, addr); if (abrt) return 0;
AL = temp;
cycles -= (is486) ? 1 : 4;
return 0;
@ -229,7 +229,7 @@ static int opMOV_AL_a32(uint32_t fetchdat)
static int opMOV_AX_a16(uint32_t fetchdat)
{
uint16_t addr = getwordf();
uint16_t temp = readmemw(ds, addr); if (abrt) return 0;
uint16_t temp = readmemw(ea_seg->base, addr); if (abrt) return 0;
AX = temp;
cycles -= (is486) ? 1 : 4;
return 0;
@ -237,7 +237,7 @@ static int opMOV_AX_a16(uint32_t fetchdat)
static int opMOV_AX_a32(uint32_t fetchdat)
{
uint32_t addr = getlong();
uint16_t temp = readmemw(ds, addr); if (abrt) return 0;
uint16_t temp = readmemw(ea_seg->base, addr); if (abrt) return 0;
AX = temp;
cycles -= (is486) ? 1 : 4;
return 0;
@ -245,7 +245,7 @@ static int opMOV_AX_a32(uint32_t fetchdat)
static int opMOV_EAX_a16(uint32_t fetchdat)
{
uint16_t addr = getwordf(); if (abrt) return 0;
uint32_t temp = readmeml(ds, addr); if (abrt) return 0;
uint32_t temp = readmeml(ea_seg->base, addr); if (abrt) return 0;
EAX = temp;
cycles -= (is486) ? 1 : 4;
return 0;
@ -253,7 +253,7 @@ static int opMOV_EAX_a16(uint32_t fetchdat)
static int opMOV_EAX_a32(uint32_t fetchdat)
{
uint32_t addr = getlong(); if (abrt) return 0;
uint32_t temp = readmeml(ds, addr); if (abrt) return 0;
uint32_t temp = readmeml(ea_seg->base, addr); if (abrt) return 0;
EAX = temp;
cycles -= (is486) ? 1 : 4;
return 0;
@ -262,42 +262,42 @@ static int opMOV_EAX_a32(uint32_t fetchdat)
static int opMOV_a16_AL(uint32_t fetchdat)
{
uint16_t addr = getwordf();
writememb(ds, addr, AL);
writememb(ea_seg->base, addr, AL);
cycles -= (is486) ? 1 : 2;
return 0;
}
static int opMOV_a32_AL(uint32_t fetchdat)
{
uint32_t addr = getlong();
writememb(ds, addr, AL);
writememb(ea_seg->base, addr, AL);
cycles -= (is486) ? 1 : 2;
return 0;
}
static int opMOV_a16_AX(uint32_t fetchdat)
{
uint16_t addr = getwordf();
writememw(ds, addr, AX);
writememw(ea_seg->base, addr, AX);
cycles -= (is486) ? 1 : 2;
return 0;
}
static int opMOV_a32_AX(uint32_t fetchdat)
{
uint32_t addr = getlong();
writememw(ds, addr, AX);
writememw(ea_seg->base, addr, AX);
cycles -= (is486) ? 1 : 2;
return 0;
}
static int opMOV_a16_EAX(uint32_t fetchdat)
{
uint16_t addr = getwordf();
writememl(ds, addr, EAX);
writememl(ea_seg->base, addr, EAX);
cycles -= (is486) ? 1 : 2;
return 0;
}
static int opMOV_a32_EAX(uint32_t fetchdat)
{
uint32_t addr = getlong();
writememl(ds, addr, EAX);
writememl(ea_seg->base, addr, EAX);
cycles -= (is486) ? 1 : 2;
return 0;
}
@ -342,7 +342,7 @@ static int opLEA_l_a32(uint32_t fetchdat)
int opXLAT_a16(uint32_t fetchdat)
{
uint32_t addr = (BX + AL)&0xFFFF;
uint8_t temp = readmemb(ds, addr); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, addr); if (abrt) return 0;
AL = temp;
cycles -= 5;
return 0;
@ -350,7 +350,7 @@ int opXLAT_a16(uint32_t fetchdat)
int opXLAT_a32(uint32_t fetchdat)
{
uint32_t addr = EBX + AL;
uint8_t temp = readmemb(ds, addr); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, addr); if (abrt) return 0;
AL = temp;
cycles -= 5;
return 0;
@ -367,6 +367,7 @@ static int opMOV_b_r_a16(uint32_t fetchdat)
else
{
fetch_ea_16(fetchdat);
CHECK_WRITE(ea_seg, eaaddr, eaaddr);
seteab(getr8(reg));
cycles -= is486 ? 1 : 2;
}
@ -383,6 +384,7 @@ static int opMOV_b_r_a32(uint32_t fetchdat)
else
{
fetch_ea_32(fetchdat);
CHECK_WRITE(ea_seg, eaaddr, eaaddr);
seteab(getr8(reg));
cycles -= is486 ? 1 : 2;
}
@ -399,6 +401,7 @@ static int opMOV_w_r_a16(uint32_t fetchdat)
else
{
fetch_ea_16(fetchdat);
CHECK_WRITE(ea_seg, eaaddr, eaaddr+1);
seteaw(regs[reg].w);
cycles -= is486 ? 1 : 2;
}
@ -415,6 +418,7 @@ static int opMOV_w_r_a32(uint32_t fetchdat)
else
{
fetch_ea_32(fetchdat);
CHECK_WRITE(ea_seg, eaaddr, eaaddr+1);
seteaw(regs[reg].w);
cycles -= is486 ? 1 : 2;
}
@ -431,6 +435,7 @@ static int opMOV_l_r_a16(uint32_t fetchdat)
else
{
fetch_ea_16(fetchdat);
CHECK_WRITE(ea_seg, eaaddr, eaaddr+3);
seteal(regs[reg].l);
cycles -= is486 ? 1 : 2;
}
@ -447,6 +452,7 @@ static int opMOV_l_r_a32(uint32_t fetchdat)
else
{
fetch_ea_32(fetchdat);
CHECK_WRITE(ea_seg, eaaddr, eaaddr+3);
seteal(regs[reg].l);
cycles -= is486 ? 1 : 2;
}
@ -465,6 +471,7 @@ static int opMOV_r_b_a16(uint32_t fetchdat)
{
uint8_t temp;
fetch_ea_16(fetchdat);
CHECK_READ(ea_seg, eaaddr, eaaddr);
temp = geteab(); if (abrt) return 0;
setr8(reg, temp);
cycles -= is486 ? 1 : 4;
@ -483,6 +490,7 @@ static int opMOV_r_b_a32(uint32_t fetchdat)
{
uint8_t temp;
fetch_ea_32(fetchdat);
CHECK_READ(ea_seg, eaaddr, eaaddr);
temp = geteab(); if (abrt) return 0;
setr8(reg, temp);
cycles -= is486 ? 1 : 4;
@ -501,6 +509,7 @@ static int opMOV_r_w_a16(uint32_t fetchdat)
{
uint16_t temp;
fetch_ea_16(fetchdat);
CHECK_READ(ea_seg, eaaddr, eaaddr+1);
temp = geteaw(); if (abrt) return 0;
regs[reg].w = temp;
cycles -= (is486) ? 1 : 4;
@ -519,6 +528,7 @@ static int opMOV_r_w_a32(uint32_t fetchdat)
{
uint16_t temp;
fetch_ea_32(fetchdat);
CHECK_READ(ea_seg, eaaddr, eaaddr+1);
temp = geteaw(); if (abrt) return 0;
regs[reg].w = temp;
cycles -= (is486) ? 1 : 4;
@ -537,6 +547,7 @@ static int opMOV_r_l_a16(uint32_t fetchdat)
{
uint32_t temp;
fetch_ea_16(fetchdat);
CHECK_READ(ea_seg, eaaddr, eaaddr+3);
temp = geteal(); if (abrt) return 0;
regs[reg].l = temp;
cycles -= is486 ? 1 : 4;
@ -555,6 +566,7 @@ static int opMOV_r_l_a32(uint32_t fetchdat)
{
uint32_t temp;
fetch_ea_32(fetchdat);
CHECK_READ(ea_seg, eaaddr, eaaddr+3);
temp = geteal(); if (abrt) return 0;
regs[reg].l = temp;
cycles -= is486 ? 1 : 4;

View file

@ -11,11 +11,9 @@ static int opMOV_w_seg_a16(uint32_t fetchdat)
seteaw(CS);
break;
case 0x18: /*DS*/
if (ssegs) ds = oldds;
seteaw(DS);
break;
case 0x10: /*SS*/
if (ssegs) ss = oldss;
seteaw(SS);
break;
case 0x20: /*FS*/
@ -42,11 +40,9 @@ static int opMOV_w_seg_a32(uint32_t fetchdat)
seteaw(CS);
break;
case 0x18: /*DS*/
if (ssegs) ds = oldds;
seteaw(DS);
break;
case 0x10: /*SS*/
if (ssegs) ss = oldss;
seteaw(SS);
break;
case 0x20: /*FS*/
@ -76,12 +72,10 @@ static int opMOV_l_seg_a16(uint32_t fetchdat)
else seteaw(CS);
break;
case 0x18: /*DS*/
if (ssegs) ds = oldds;
if (mod == 3) regs[rm].l = DS;
else seteaw(DS);
break;
case 0x10: /*SS*/
if (ssegs) ss = oldss;
if (mod == 3) regs[rm].l = SS;
else seteaw(SS);
break;
@ -113,12 +107,10 @@ static int opMOV_l_seg_a32(uint32_t fetchdat)
else seteaw(CS);
break;
case 0x18: /*DS*/
if (ssegs) ds = oldds;
if (mod == 3) regs[rm].l = DS;
else seteaw(DS);
break;
case 0x10: /*SS*/
if (ssegs) ss = oldss;
if (mod == 3) regs[rm].l = SS;
else seteaw(SS);
break;
@ -151,16 +143,9 @@ static int opMOV_seg_w_a16(uint32_t fetchdat)
break;
case 0x18: /*DS*/
loadseg(new_seg, &_ds);
if (ssegs) oldds = ds;
break;
case 0x10: /*SS*/
loadseg(new_seg, &_ss);
if (ssegs)
{
ds = oldds;
rds = DS;
ssegs = 0;
}
op32 = use32;
return 1;
case 0x20: /*FS*/
@ -189,16 +174,9 @@ static int opMOV_seg_w_a32(uint32_t fetchdat)
break;
case 0x18: /*DS*/
loadseg(new_seg, &_ds);
if (ssegs) oldds = ds;
break;
case 0x10: /*SS*/
loadseg(new_seg, &_ss);
if (ssegs)
{
ds = oldds;
rds = DS;
ssegs = 0;
}
op32 = use32;
return 1;
case 0x20: /*FS*/
@ -224,7 +202,6 @@ static int opLDS_w_a16(uint32_t fetchdat)
seg = readmemw(easeg, eaaddr + 2); if (abrt) return 0;
loadseg(seg, &_ds); if (abrt) return 0;
regs[reg].w = addr;
if (ssegs) oldds = ds;
cycles -= 7;
return 0;
@ -239,7 +216,6 @@ static int opLDS_w_a32(uint32_t fetchdat)
seg = readmemw(easeg, eaaddr + 2); if (abrt) return 0;
loadseg(seg, &_ds); if (abrt) return 0;
regs[reg].w = addr;
if (ssegs) oldds = ds;
cycles -= 7;
return 0;
@ -255,7 +231,6 @@ static int opLDS_l_a16(uint32_t fetchdat)
seg = readmemw(easeg, eaaddr + 4); if (abrt) return 0;
loadseg(seg, &_ds); if (abrt) return 0;
regs[reg].l = addr;
if (ssegs) oldds = ds;
cycles -= 7;
return 0;
@ -271,7 +246,6 @@ static int opLDS_l_a32(uint32_t fetchdat)
seg = readmemw(easeg, eaaddr + 4); if (abrt) return 0;
loadseg(seg, &_ds); if (abrt) return 0;
regs[reg].l = addr;
if (ssegs) oldds = ds;
cycles -= 7;
return 0;

View file

@ -1,59 +1,42 @@
static int op_CS(uint32_t fetchdat)
{
oldss = ss;
oldds = ds;
ds = ss = cs;
rds = CS;
ssegs = 2;
ea_seg = &_cs;
ssegs = 1;
cycles -= 4;
return 1;
}
static int op_DS(uint32_t fetchdat)
{
oldss = ss;
oldds = ds;
ds = ss = ds;
ssegs = 2;
ea_seg = &_ds;
ssegs = 1;
cycles -= 4;
return 1;
}
static int op_ES(uint32_t fetchdat)
{
oldss = ss;
oldds = ds;
ds = ss = es;
rds = ES;
ssegs = 2;
ea_seg = &_es;
ssegs = 1;
cycles -= 4;
return 1;
}
static int op_FS(uint32_t fetchdat)
{
oldss = ss;
oldds = ds;
rds = FS;
ds = ss = fs;
ssegs = 2;
ea_seg = &_fs;
ssegs = 1;
cycles -= 4;
return 1;
}
static int op_GS(uint32_t fetchdat)
{
oldss = ss;
oldds = ds;
rds = GS;
ds = ss = gs;
ssegs = 2;
ea_seg = &_gs;
ssegs = 1;
cycles -= 4;
return 1;
}
static int op_SS(uint32_t fetchdat)
{
oldss = ss;
oldds = ds;
ds = ss = ss;
rds = SS;
ssegs = 2;
ea_seg = &_ss;
ssegs = 1;
cycles -= 4;
return 1;
}

View file

@ -4,7 +4,6 @@
pmoderetf(0, stack_offset); \
return 0; \
} \
if (ssegs) ss = oldss; \
oxpc = pc; \
if (stack32) \
{ \
@ -27,7 +26,6 @@
pmoderetf(1, stack_offset); \
return 0; \
} \
if (ssegs) ss = oldss; \
oxpc = pc; \
if (stack32) \
{ \
@ -75,7 +73,6 @@ static int opIRET_286(uint32_t fetchdat)
x86gpf(NULL,0);
return 0;
}
if (ssegs) ss = oldss;
if (msw&1)
{
optype = IRET;
@ -115,7 +112,6 @@ static int opIRET(uint32_t fetchdat)
x86gpf(NULL,0);
return 0;
}
if (ssegs) ss = oldss;
if (msw&1)
{
optype = IRET;
@ -155,7 +151,6 @@ static int opIRETD(uint32_t fetchdat)
x86gpf(NULL,0);
return 0;
}
if (ssegs) ss = oldss;
if (msw & 1)
{
optype = IRET;

View file

@ -1,7 +1,6 @@
#define PUSH_W_OP(reg) \
static int opPUSH_ ## reg (uint32_t fetchdat) \
{ \
if (ssegs) ss=oldss; \
PUSH_W(reg); \
cycles -= (is486) ? 1 : 2; \
return 0; \
@ -10,7 +9,6 @@
#define PUSH_L_OP(reg) \
static int opPUSH_ ## reg (uint32_t fetchdat) \
{ \
if (ssegs) ss=oldss; \
PUSH_L(reg); \
cycles -= (is486) ? 1 : 2; \
return 0; \
@ -19,7 +17,6 @@
#define POP_W_OP(reg) \
static int opPOP_ ## reg (uint32_t fetchdat) \
{ \
if (ssegs) ss=oldss; \
reg = POP_W(); \
cycles -= (is486) ? 1 : 4; \
return 0; \
@ -28,7 +25,6 @@
#define POP_L_OP(reg) \
static int opPOP_ ## reg (uint32_t fetchdat) \
{ \
if (ssegs) ss=oldss; \
reg = POP_L(); \
cycles -= (is486) ? 1 : 4; \
return 0; \
@ -188,7 +184,6 @@ static int opPOPA_l(uint32_t fetchdat)
static int opPUSH_imm_w(uint32_t fetchdat)
{
uint16_t val = getwordf();
if (ssegs) ss=oldss;
PUSH_W(val);
cycles -= 2;
return 0;
@ -196,7 +191,6 @@ static int opPUSH_imm_w(uint32_t fetchdat)
static int opPUSH_imm_l(uint32_t fetchdat)
{
uint32_t val = getlong();
if (ssegs) ss=oldss;
PUSH_L(val);
cycles -= 2;
return 0;
@ -226,9 +220,8 @@ static int opPUSH_imm_bl(uint32_t fetchdat)
static int opPOPW_a16(uint32_t fetchdat)
{
uint16_t temp;
uint32_t tempseg = ssegs ? oldss : ss;
temp = POP_W_seg(tempseg); if (abrt) return 0;
temp = POP_W(); if (abrt) return 0;
fetch_ea_16(fetchdat);
seteaw(temp);
@ -245,9 +238,8 @@ static int opPOPW_a16(uint32_t fetchdat)
static int opPOPW_a32(uint32_t fetchdat)
{
uint16_t temp;
uint32_t tempseg = ssegs ? oldss : ss;
temp = POP_W_seg(tempseg); if (abrt) return 0;
temp = POP_W(); if (abrt) return 0;
fetch_ea_32(fetchdat);
seteaw(temp);
@ -265,9 +257,8 @@ static int opPOPW_a32(uint32_t fetchdat)
static int opPOPL_a16(uint32_t fetchdat)
{
uint32_t temp;
uint32_t tempseg = ssegs ? oldss : ss;
temp = POP_L_seg(tempseg); if (abrt) return 0;
temp = POP_L(); if (abrt) return 0;
fetch_ea_16(fetchdat);
seteal(temp);
@ -284,9 +275,8 @@ static int opPOPL_a16(uint32_t fetchdat)
static int opPOPL_a32(uint32_t fetchdat)
{
uint32_t temp;
uint32_t tempseg = ssegs ? oldss : ss;
temp = POP_L_seg(tempseg); if (abrt) return 0;
temp = POP_L(); if (abrt) return 0;
fetch_ea_32(fetchdat);
seteal(temp);
@ -401,14 +391,12 @@ static int opLEAVE_l(uint32_t fetchdat)
#define PUSH_SEG_OPS(seg) \
static int opPUSH_ ## seg ## _w(uint32_t fetchdat) \
{ \
if (ssegs) ss=oldss; \
PUSH_W(seg); \
cycles -= 2; \
return 0; \
} \
static int opPUSH_ ## seg ## _l(uint32_t fetchdat) \
{ \
if (ssegs) ss=oldss; \
PUSH_L(seg); \
cycles -= 2; \
return 0; \
@ -419,7 +407,6 @@ static int opLEAVE_l(uint32_t fetchdat)
{ \
uint16_t temp_seg; \
uint32_t temp_esp = ESP; \
if (ssegs) ss=oldss; \
temp_seg = POP_W(); if (abrt) return 0; \
loadseg(temp_seg, realseg); if (abrt) ESP = temp_esp; \
cycles -= is486 ? 3 : 7; \
@ -429,7 +416,6 @@ static int opLEAVE_l(uint32_t fetchdat)
{ \
uint32_t temp_seg; \
uint32_t temp_esp = ESP; \
if (ssegs) ss=oldss; \
temp_seg = POP_L(); if (abrt) return 0; \
loadseg(temp_seg & 0xffff, realseg); if (abrt) ESP = temp_esp; \
cycles -= is486 ? 3 : 7; \

View file

@ -1,6 +1,6 @@
static int opMOVSB_a16(uint32_t fetchdat)
{
uint8_t temp = readmemb(ds,SI); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, SI); if (abrt) return 0;
writememb(es, DI, temp); if (abrt) return 0;
if (flags & D_FLAG) { DI--; SI--; }
else { DI++; SI++; }
@ -9,7 +9,7 @@ static int opMOVSB_a16(uint32_t fetchdat)
}
static int opMOVSB_a32(uint32_t fetchdat)
{
uint8_t temp = readmemb(ds,ESI); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, ESI); if (abrt) return 0;
writememb(es, EDI, temp); if (abrt) return 0;
if (flags & D_FLAG) { EDI--; ESI--; }
else { EDI++; ESI++; }
@ -19,7 +19,7 @@ static int opMOVSB_a32(uint32_t fetchdat)
static int opMOVSW_a16(uint32_t fetchdat)
{
uint16_t temp = readmemw(ds,SI); if (abrt) return 0;
uint16_t temp = readmemw(ea_seg->base, SI); if (abrt) return 0;
writememw(es, DI, temp); if (abrt) return 0;
if (flags & D_FLAG) { DI -= 2; SI -= 2; }
else { DI += 2; SI += 2; }
@ -28,7 +28,7 @@ static int opMOVSW_a16(uint32_t fetchdat)
}
static int opMOVSW_a32(uint32_t fetchdat)
{
uint16_t temp = readmemw(ds,ESI); if (abrt) return 0;
uint16_t temp = readmemw(ea_seg->base, ESI); if (abrt) return 0;
writememw(es, EDI, temp); if (abrt) return 0;
if (flags & D_FLAG) { EDI -= 2; ESI -= 2; }
else { EDI += 2; ESI += 2; }
@ -38,7 +38,7 @@ static int opMOVSW_a32(uint32_t fetchdat)
static int opMOVSL_a16(uint32_t fetchdat)
{
uint32_t temp = readmeml(ds,SI); if (abrt) return 0;
uint32_t temp = readmeml(ea_seg->base, SI); if (abrt) return 0;
writememl(es, DI, temp); if (abrt) return 0;
if (flags & D_FLAG) { DI -= 4; SI -= 4; }
else { DI += 4; SI += 4; }
@ -47,7 +47,7 @@ static int opMOVSL_a16(uint32_t fetchdat)
}
static int opMOVSL_a32(uint32_t fetchdat)
{
uint32_t temp = readmeml(ds,ESI); if (abrt) return 0;
uint32_t temp = readmeml(ea_seg->base, ESI); if (abrt) return 0;
writememl(es, EDI, temp); if (abrt) return 0;
if (flags & D_FLAG) { EDI -= 4; ESI -= 4; }
else { EDI += 4; ESI += 4; }
@ -58,7 +58,7 @@ static int opMOVSL_a32(uint32_t fetchdat)
static int opCMPSB_a16(uint32_t fetchdat)
{
uint8_t src = readmemb(ds, SI);
uint8_t src = readmemb(ea_seg->base, SI);
uint8_t dst = readmemb(es, DI); if (abrt) return 0;
setsub8(src, dst);
if (flags & D_FLAG) { DI--; SI--; }
@ -68,7 +68,7 @@ static int opCMPSB_a16(uint32_t fetchdat)
}
static int opCMPSB_a32(uint32_t fetchdat)
{
uint8_t src = readmemb(ds, ESI);
uint8_t src = readmemb(ea_seg->base, ESI);
uint8_t dst = readmemb(es, EDI); if (abrt) return 0;
setsub8(src, dst);
if (flags & D_FLAG) { EDI--; ESI--; }
@ -79,7 +79,7 @@ static int opCMPSB_a32(uint32_t fetchdat)
static int opCMPSW_a16(uint32_t fetchdat)
{
uint16_t src = readmemw(ds, SI);
uint16_t src = readmemw(ea_seg->base, SI);
uint16_t dst = readmemw(es, DI); if (abrt) return 0;
setsub16(src, dst);
if (flags & D_FLAG) { DI -= 2; SI -= 2; }
@ -89,7 +89,7 @@ static int opCMPSW_a16(uint32_t fetchdat)
}
static int opCMPSW_a32(uint32_t fetchdat)
{
uint16_t src = readmemw(ds, ESI);
uint16_t src = readmemw(ea_seg->base, ESI);
uint16_t dst = readmemw(es, EDI); if (abrt) return 0;
setsub16(src, dst);
if (flags & D_FLAG) { EDI -= 2; ESI -= 2; }
@ -100,7 +100,7 @@ static int opCMPSW_a32(uint32_t fetchdat)
static int opCMPSL_a16(uint32_t fetchdat)
{
uint32_t src = readmeml(ds, SI);
uint32_t src = readmeml(ea_seg->base, SI);
uint32_t dst = readmeml(es, DI); if (abrt) return 0;
setsub32(src, dst);
if (flags & D_FLAG) { DI -= 4; SI -= 4; }
@ -110,7 +110,7 @@ static int opCMPSL_a16(uint32_t fetchdat)
}
static int opCMPSL_a32(uint32_t fetchdat)
{
uint32_t src = readmeml(ds, ESI);
uint32_t src = readmeml(ea_seg->base, ESI);
uint32_t dst = readmeml(es, EDI); if (abrt) return 0;
setsub32(src, dst);
if (flags & D_FLAG) { EDI -= 4; ESI -= 4; }
@ -173,7 +173,7 @@ static int opSTOSL_a32(uint32_t fetchdat)
static int opLODSB_a16(uint32_t fetchdat)
{
uint8_t temp = readmemb(ds, SI); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, SI); if (abrt) return 0;
AL = temp;
if (flags & D_FLAG) SI--;
else SI++;
@ -182,7 +182,7 @@ static int opLODSB_a16(uint32_t fetchdat)
}
static int opLODSB_a32(uint32_t fetchdat)
{
uint8_t temp = readmemb(ds, ESI); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, ESI); if (abrt) return 0;
AL = temp;
if (flags & D_FLAG) ESI--;
else ESI++;
@ -192,7 +192,7 @@ static int opLODSB_a32(uint32_t fetchdat)
static int opLODSW_a16(uint32_t fetchdat)
{
uint16_t temp = readmemw(ds, SI); if (abrt) return 0;
uint16_t temp = readmemw(ea_seg->base, SI); if (abrt) return 0;
AX = temp;
if (flags & D_FLAG) SI -= 2;
else SI += 2;
@ -201,7 +201,7 @@ static int opLODSW_a16(uint32_t fetchdat)
}
static int opLODSW_a32(uint32_t fetchdat)
{
uint16_t temp = readmemw(ds, ESI); if (abrt) return 0;
uint16_t temp = readmemw(ea_seg->base, ESI); if (abrt) return 0;
AX = temp;
if (flags & D_FLAG) ESI -= 2;
else ESI += 2;
@ -211,7 +211,7 @@ static int opLODSW_a32(uint32_t fetchdat)
static int opLODSL_a16(uint32_t fetchdat)
{
uint32_t temp = readmeml(ds, SI); if (abrt) return 0;
uint32_t temp = readmeml(ea_seg->base, SI); if (abrt) return 0;
EAX = temp;
if (flags & D_FLAG) SI -= 4;
else SI += 4;
@ -220,7 +220,7 @@ static int opLODSL_a16(uint32_t fetchdat)
}
static int opLODSL_a32(uint32_t fetchdat)
{
uint32_t temp = readmeml(ds, ESI); if (abrt) return 0;
uint32_t temp = readmeml(ea_seg->base, ESI); if (abrt) return 0;
EAX = temp;
if (flags & D_FLAG) ESI -= 4;
else ESI += 4;
@ -365,7 +365,7 @@ static int opINSL_a32(uint32_t fetchdat)
static int opOUTSB_a16(uint32_t fetchdat)
{
uint8_t temp = readmemb(ds, SI); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, SI); if (abrt) return 0;
check_io_perm(DX);
if (flags & D_FLAG) SI--;
else SI++;
@ -375,7 +375,7 @@ static int opOUTSB_a16(uint32_t fetchdat)
}
static int opOUTSB_a32(uint32_t fetchdat)
{
uint8_t temp = readmemb(ds, ESI); if (abrt) return 0;
uint8_t temp = readmemb(ea_seg->base, ESI); if (abrt) return 0;
check_io_perm(DX);
if (flags & D_FLAG) ESI--;
else ESI++;
@ -386,7 +386,7 @@ static int opOUTSB_a32(uint32_t fetchdat)
static int opOUTSW_a16(uint32_t fetchdat)
{
uint16_t temp = readmemw(ds, SI); if (abrt) return 0;
uint16_t temp = readmemw(ea_seg->base, SI); if (abrt) return 0;
check_io_perm(DX);
check_io_perm(DX + 1);
if (flags & D_FLAG) SI -= 2;
@ -397,7 +397,7 @@ static int opOUTSW_a16(uint32_t fetchdat)
}
static int opOUTSW_a32(uint32_t fetchdat)
{
uint16_t temp = readmemw(ds, ESI); if (abrt) return 0;
uint16_t temp = readmemw(ea_seg->base, ESI); if (abrt) return 0;
check_io_perm(DX);
check_io_perm(DX + 1);
if (flags & D_FLAG) ESI -= 2;
@ -409,7 +409,7 @@ static int opOUTSW_a32(uint32_t fetchdat)
static int opOUTSL_a16(uint32_t fetchdat)
{
uint32_t temp = readmeml(ds, SI); if (abrt) return 0;
uint32_t temp = readmeml(ea_seg->base, SI); if (abrt) return 0;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
@ -422,7 +422,7 @@ static int opOUTSL_a16(uint32_t fetchdat)
}
static int opOUTSL_a32(uint32_t fetchdat)
{
uint32_t temp = readmeml(ds, ESI); if (abrt) return 0;
uint32_t temp = readmeml(ea_seg->base, ESI); if (abrt) return 0;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);

View file

@ -57,6 +57,24 @@ void x86abort(const char *format, ...)
uint8_t opcode2;
static void seg_reset(x86seg *s)
{
s->access = 0 << 5;
s->limit = 0xFFFF;
s->limit_low = 0;
s->limit_high = 0xffff;
}
void x86seg_reset()
{
seg_reset(&_cs);
seg_reset(&_ds);
seg_reset(&_es);
seg_reset(&_fs);
seg_reset(&_gs);
seg_reset(&_ss);
}
void x86_doabrt(int x86_abrt)
{
// ingpf = 1;
@ -73,7 +91,33 @@ void x86_doabrt(int x86_abrt)
}*/
// pclog("GPF! - error %04X %04X(%08X):%08X %02X %02X %i %04X %i %i\n",error,CS,cs,pc,opcode,opcode2,ins,flags&I_FLAG,IOPL, dtimes);
pmodeint(x86_abrt, 0);
if (msw & 1)
pmodeint(x86_abrt, 0);
else
{
uint32_t addr = (x86_abrt << 2) + idt.base;
if (stack32)
{
writememw(ss,ESP-2,flags);
writememw(ss,ESP-4,CS);
writememw(ss,ESP-6,pc);
ESP-=6;
}
else
{
writememw(ss,((SP-2)&0xFFFF),flags);
writememw(ss,((SP-4)&0xFFFF),CS);
writememw(ss,((SP-6)&0xFFFF),pc);
SP-=6;
}
flags&=~I_FLAG;
flags&=~T_FLAG;
oxpc=pc;
pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
return;
}
if (abrt) return;
@ -132,12 +176,90 @@ void x86np(char *s, uint16_t error)
}
static void do_seg_load(x86seg *s, uint16_t *segdat)
{
s->limit = segdat[0] | ((segdat[3] & 0xF) << 16);
if (segdat[3] & 0x80)
s->limit = (s->limit << 12) | 0xFFF;
s->base = segdat[1] | ((segdat[2] & 0xFF) << 16);
if (is386)
s->base |= ((segdat[3] >> 8) << 24);
s->access = segdat[2] >> 8;
if ((segdat[2] & 0x1800) != 0x1000 || !(segdat[2] & (1 << 10))) /*expand-down*/
{
s->limit_high = s->limit;
s->limit_low = 0;
}
else
{
s->limit_high = (segdat[3] & 0x40) ? 0xffffffff : 0xffff;
s->limit_low = s->limit + 1;
}
// if (output) pclog("SEG : base=%08x limit=%08x low=%08x high=%08x\n", s->base, s->limit, s->limit_low, s->limit_high);
}
static void do_seg_v86_init(x86seg *s)
{
s->access = 3 << 5;
s->limit = 0xffff;
s->limit_low = 0;
s->limit_high = 0xffff;
}
static void check_seg_valid(x86seg *s)
{
int dpl = (s->access >> 5) & 3;
int valid = 1;
if (s->seg & 4)
{
if ((s->seg & ~7) >= ldt.limit)
{
// pclog("Bigger than LDT limit %04X %04X %02X %02X %02X\n", s->seg, ldt.limit, opcode, opcode2, rmdat);
valid = 0;
}
}
else
{
if ((s->seg & ~7) >= gdt.limit)
{
// pclog("Bigger than GDT limit %04X %04X\n", s->seg, gdt.limit);
valid = 0;
}
}
switch (s->access & 0x1f)
{
case 0x10: case 0x11: case 0x12: case 0x13: /*Data segments*/
case 0x14: case 0x15: case 0x16: case 0x17:
case 0x1A: case 0x1B: /*Readable non-conforming code*/
if ((s->seg & 3) > dpl || (CPL) > dpl)
{
// pclog("Data seg fail - %04X:%08X %04X %i\n", CS, pc, s->seg, dpl);
valid = 0;
break;
}
break;
case 0x1E: case 0x1F: /*Readable conforming code*/
break;
default:
valid = 0;
break;
}
if (!valid)
loadseg(0, s);
}
void loadseg(uint16_t seg, x86seg *s)
{
uint16_t segdat[4];
uint32_t addr;
int dpl;
if (output) pclog("Load seg %04X\n",seg);
if (msw&1 && !(eflags&VM_FLAG))
{
// intcount++;
@ -153,6 +275,7 @@ void loadseg(uint16_t seg, x86seg *s)
}
// if (s->base!=-1) pclog("NEW! ");
s->seg=0;
s->access = 0;
s->base=-1;
// pclog("NULL selector %s%s%s%s %04X(%06X):%06X\n",(s==&_ds)?"DS":"",(s==&_es)?"ES":"",(s==&_fs)?"FS":"",(s==&_gs)?"GS":"",CS,cs,pc);
return;
@ -224,7 +347,7 @@ void loadseg(uint16_t seg, x86seg *s)
}
if (segdat[3]&0x40) stack32=1;
else stack32=0;
// pclog("Load SS\n");
// pclog("Load SS %04x %04x %04x %04x\n", segdat[0], segdat[1], segdat[2], segdat[3]);
}
else if (s!=&_cs)
{
@ -248,71 +371,38 @@ void loadseg(uint16_t seg, x86seg *s)
break;
default:
pclog("Invalid segment type for %04X! %04X\n",seg&0xFFFC,segdat[2]);
// if ((seg & ~3) == 0x1508) btimes++;
// if (btimes == 2) output = 3;
// dumpregs();
// exit(-1);
x86gpf(NULL,seg&~3);
// x86abort("Invalid segment type for %04X!\n",seg&0xFFFC);
return;
}
}
// #endif
// }
// if (!(segdat[2]&0x8000)) x86abort("Data segment not present!\n");
// if (!(segdat[2]&0x800) || !(segdat[2]&0x400))
// {
if (!(segdat[2]&0x8000))
{
x86np("Load data seg not present", seg & 0xfffc);
return;
}
s->seg=seg;
s->limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) s->limit=(s->limit<<12)|0xFFF;
s->limitw=(segdat[2]&0x200)?1:0;
s->base=segdat[1];
s->base|=((segdat[2]&0xFF)<<16);
if (is386) s->base|=((segdat[3]>>8)<<24);
s->access=segdat[2]>>8;
if ((segdat[2]>>8) & 4)
s->limit = 0xffffffff;
// if (output) pclog("SS limit %08X\n", s->limit);
// pclog("Seg Write %04X to %08X\n",segdat[2]|0x100,addr+4);
if (!(segdat[2] & 0x8000))
{
x86np("Load data seg not present", seg & 0xfffc);
return;
}
s->seg = seg;
do_seg_load(s, segdat);
#ifndef CS_ACCESSED
if (s != &_cs)
{
if (s != &_cs)
{
#endif
#ifdef SEL_ACCESSED
cpl_override = 1;
writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
cpl_override = 0;
cpl_override = 1;
writememw(0, addr+4, segdat[2] | 0x100); /*Set accessed bit*/
cpl_override = 0;
#endif
#ifndef CS_ACCESSED
}
}
#endif
// pclog("Access=%02X Limit=%04X Limitw=%04X %08X %i %04X:%04X\n",s->access,s->limit,s->limitw, _ss.limit, ins, CS, pc);
// if (s==&_es && s->base>0x180000) s->base=0x180000;
// }
// pclog("base=%06X limit=%04X access=%02X %06X %04X %04X %04X %04X\n",s->base,s->limit,s->access,addr,segdat[0],segdat[1],segdat[2],seg);
// dumpregs();
// exit(-1);
}
else
{
s->base=seg<<4;
s->limit=0xFFFF;
s->seg=seg;
if (eflags&VM_FLAG) s->access=3<<5;
else s->access=0<<5;
if (s==&_ss) stack32=0;
/* if (s==&_ds)
{
pclog("DS! %04X %06X %04X:%04X\n",DS,ds,CS,pc);
}*/
s->base = seg << 4;
s->seg = seg;
if (s == &_ss)
stack32 = 0;
}
}
@ -397,12 +487,7 @@ void loadcs(uint16_t seg)
if (segdat[3]&0x40) use32=0x300;
else use32=0;
CS=(seg&~3)|CPL;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
use32=(segdat[3]&0x40)?0x300:0;
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
@ -437,6 +522,8 @@ void loadcs(uint16_t seg)
{
_cs.base=seg<<4;
_cs.limit=0xFFFF;
_cs.limit_low = 0;
_cs.limit_high = 0xffff;
CS=seg;
if (eflags&VM_FLAG) _cs.access=3<<5;
else _cs.access=0<<5;
@ -526,13 +613,8 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
CS = (seg & ~3) | CPL;
segdat[2] = (segdat[2] & ~(3 << (5+8))) | (CPL << (5+8));
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
}
@ -627,12 +709,7 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
}
case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
CS=seg2;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
pc=newpc;
@ -679,6 +756,8 @@ void loadcsjmp(uint16_t seg, uint32_t oxpc)
{
_cs.base=seg<<4;
_cs.limit=0xFFFF;
_cs.limit_low = 0;
_cs.limit_high = 0xffff;
CS=seg;
if (eflags&VM_FLAG) _cs.access=3<<5;
else _cs.access=0<<5;
@ -858,12 +937,7 @@ void loadcscall(uint16_t seg)
else /*On non-conforming segments, set RPL = CPL*/
seg = (seg & ~3) | CPL;
CS=seg;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
if (csout) pclog("Complete\n");
@ -1031,16 +1105,8 @@ void loadcscall(uint16_t seg)
stack32=segdat2[3]&0x40;
if (stack32) ESP=newsp;
else SP=newsp;
_ss.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
if (segdat2[3]&0x80) _ss.limit=(_ss.limit<<12)|0xFFF;
if ((segdat2[2]>>8) & 4)
_ss.limit = 0xffffffff;
_ss.limitw=(segdat2[2]&0x200)?1:0;
_ss.base=segdat2[1];
_ss.base|=((segdat2[2]&0xFF)<<16);
if (is386) _ss.base|=((segdat2[3]>>8)<<24);
_ss.access=segdat2[2]>>8;
do_seg_load(&_ss, segdat2);
if (output) pclog("Set access 1\n");
@ -1051,12 +1117,7 @@ void loadcscall(uint16_t seg)
#endif
CS=seg2;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
pc=newpc;
@ -1159,12 +1220,7 @@ void loadcscall(uint16_t seg)
PUSHW(oldpc); if (abrt) return;
}*/
CS=seg2;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
pc=newpc;
@ -1206,6 +1262,8 @@ void loadcscall(uint16_t seg)
{
_cs.base=seg<<4;
_cs.limit=0xFFFF;
_cs.limit_low = 0;
_cs.limit_high = 0xffff;
CS=seg;
if (eflags&VM_FLAG) _cs.access=3<<5;
else _cs.access=0<<5;
@ -1334,12 +1392,7 @@ void pmoderetf(int is32, uint16_t off)
if (segdat[2] & 0x400)
segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8));
CS = seg;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
@ -1472,15 +1525,7 @@ void pmoderetf(int is32, uint16_t off)
stack32=segdat2[3]&0x40;
if (stack32) ESP=newsp;
else SP=newsp;
_ss.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
if (segdat2[3]&0x80) _ss.limit=(_ss.limit<<12)|0xFFF;
if ((segdat2[2]>>8) & 4)
_ss.limit = 0xffffffff;
_ss.limitw=(segdat2[2]&0x200)?1:0;
_ss.base=segdat2[1];
_ss.base|=((segdat2[2]&0xFF)<<16);
if (is386) _ss.base|=((segdat2[3]>>8)<<24);
_ss.access=segdat2[2]>>8;
do_seg_load(&_ss, segdat2);
#ifdef SEL_ACCESSED
cpl_override = 1;
@ -1497,24 +1542,24 @@ void pmoderetf(int is32, uint16_t off)
pc=newpc;
CS=seg;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
if (stack32) ESP+=off;
else SP+=off;
check_seg_valid(&_ds);
check_seg_valid(&_es);
check_seg_valid(&_fs);
check_seg_valid(&_gs);
// pclog("CPL<RPL return to %04X:%08X %04X:%08X\n",CS,pc,SS,ESP);
}
}
void restore_stack()
{
ss=oldss; _ss.limit=oldsslimit; _ss.limitw=oldsslimitw;
ss=oldss; _ss.limit=oldsslimit;
}
void pmodeint(int num, int soft)
@ -1527,6 +1572,7 @@ void pmodeint(int num, int soft)
uint32_t newsp;
uint16_t seg;
int stack_changed=0;
// if (!num) pclog("Pmode int 0 at %04X(%06X):%08X\n",CS,cs,pc);
// pclog("Pmode int %02X %i %04X:%08X %04X:%08X %i\n",num,soft,CS,pc, SS, ESP, abrt);
if (eflags&VM_FLAG && IOPL!=3 && soft)
@ -1728,15 +1774,7 @@ void pmodeint(int num, int soft)
stack32=segdat3[3]&0x40;
if (stack32) ESP=newsp;
else SP=newsp;
_ss.limit=segdat3[0]|((segdat3[3]&0xF)<<16);
if (segdat3[3]&0x80) _ss.limit=(_ss.limit<<12)|0xFFF;
if ((segdat3[2]>>8) & 4)
_ss.limit = 0xffffffff;
_ss.limitw=(segdat3[2]&0x200)?1:0;
_ss.base=segdat3[1];
_ss.base|=((segdat3[2]&0xFF)<<16);
if (is386) _ss.base|=((segdat3[3]>>8)<<24);
_ss.access=segdat3[2]>>8;
do_seg_load(&_ss, segdat3);
#ifdef CS_ACCESSED
cpl_override = 1;
@ -1805,7 +1843,7 @@ void pmodeint(int num, int soft)
x86gpf(NULL,seg&~3);
return;
}
if (!stack_changed && ssegs) restore_stack();
// if (!stack_changed && ssegs) restore_stack();
if (type>0x800)
{
PUSHL(flags|(eflags<<16));
@ -1830,12 +1868,7 @@ void pmodeint(int num, int soft)
}
CS=(seg&~3)|CPL;
// pclog("New CS = %04X\n",CS);
_cs.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
if (segdat2[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat2[1];
_cs.base|=((segdat2[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat2[3]>>8)<<24);
_cs.access=segdat2[2]>>8;
do_seg_load(&_cs, segdat2);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
if (type>0x800) pc=segdat[0]|(segdat[3]<<16);
else pc=segdat[0];
@ -1943,6 +1976,8 @@ void pmodeiret(int is32)
pc=newpc;
_cs.base=seg<<4;
_cs.limit=0xFFFF;
_cs.limit_low = 0;
_cs.limit_high = 0xffff;
CS=seg;
flags=(flags&0x3000)|(tempflags&0xCFD5)|2;
return;
@ -2011,9 +2046,13 @@ void pmodeiret(int is32)
// pclog("Pop stack %04X:%04X\n",newss,newsp);
eflags=tempflags>>16;
loadseg(segs[0],&_es);
do_seg_v86_init(&_es);
loadseg(segs[1],&_ds);
do_seg_v86_init(&_ds);
loadseg(segs[2],&_fs);
do_seg_v86_init(&_fs);
loadseg(segs[3],&_gs);
do_seg_v86_init(&_gs);
// pclog("V86 IRET %04X:%08X\n",SS,ESP);
// output=3;
@ -2021,12 +2060,15 @@ void pmodeiret(int is32)
pc=newpc;
_cs.base=seg<<4;
_cs.limit=0xFFFF;
_cs.limit_low = 0;
_cs.limit_high = 0xffff;
CS=seg;
_cs.access=3<<5;
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
ESP=newsp;
loadseg(newss,&_ss);
do_seg_v86_init(&_ss);
use32=0;
flags=(tempflags&0xFFD5)|2;
@ -2137,12 +2179,7 @@ void pmodeiret(int is32)
{
// pclog("Same level\n");
CS=seg;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
@ -2240,15 +2277,7 @@ void pmodeiret(int is32)
stack32=segdat2[3]&0x40;
if (stack32) ESP=newsp;
else SP=newsp;
_ss.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
if (segdat2[3]&0x80) _ss.limit=(_ss.limit<<12)|0xFFF;
if ((segdat2[2]>>8) & 4)
_ss.limit = 0xffffffff;
_ss.limitw=(segdat2[2]&0x200)?1:0;
_ss.base=segdat2[1];
_ss.base|=((segdat2[2]&0xFF)<<16);
if (is386) _ss.base|=((segdat2[3]>>8)<<24);
_ss.access=segdat2[2]>>8;
do_seg_load(&_ss, segdat2);
#ifdef SEL_ACCESSED
cpl_override = 1;
@ -2264,35 +2293,14 @@ void pmodeiret(int is32)
segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8));
CS=seg;
_cs.limit=segdat[0]|((segdat[3]&0xF)<<16);
if (segdat[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat[1];
_cs.base|=((segdat[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat[3]>>8)<<24);
_cs.access=segdat[2]>>8;
do_seg_load(&_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat[3]&0x40)?0x300:0;
if (CPL>((_ds.access>>5)&3))
{
_ds.seg=0;
_ds.base=-1;
}
if (CPL>((_es.access>>5)&3))
{
_es.seg=0;
_es.base=-1;
}
if (CPL>((_fs.access>>5)&3))
{
_fs.seg=0;
_fs.base=-1;
}
if (CPL>((_gs.access>>5)&3))
{
_gs.seg=0;
_gs.base=-1;
}
check_seg_valid(&_ds);
check_seg_valid(&_es);
check_seg_valid(&_fs);
check_seg_valid(&_gs);
}
pc=newpc;
flags=(flags&~flagmask)|(tempflags&flagmask&0xFFD5)|2;
@ -2501,12 +2509,7 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
// if (output) pclog("new_cs %04X\n",new_cs);
CS=new_cs;
_cs.limit=segdat2[0]|((segdat2[3]&0xF)<<16);
if (segdat2[3]&0x80) _cs.limit=(_cs.limit<<12)|0xFFF;
_cs.base=segdat2[1];
_cs.base|=((segdat2[2]&0xFF)<<16);
if (is386) _cs.base|=((segdat2[3]>>8)<<24);
_cs.access=segdat2[2]>>8;
do_seg_load(&_cs, segdat2);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
use32=(segdat2[3]&0x40)?0x300:0;