# HG changeset patch # User TomW # Date 1407958436 -3600 # Node ID bd46c39a78e83420b6e462f7bc8f25621d8be853 # Parent 7734b12d55f075046f48a7c814fbc95a75a408f3 Implemented selector limits on some instructions - fixes LBA2. GPFs in real mode now work. Selectors correctly zeroed on far return to lower privilege. diff -r 7734b12d55f0 -r bd46c39a78e8 src/386.c --- a/src/386.c Sun Aug 03 20:38:04 2014 +0100 +++ b/src/386.c Wed Aug 13 20:33:56 2014 +0100 @@ -10,6 +10,9 @@ #include "timer.h" #include "video.h" + +x86seg *ea_seg; + int nmi_enable = 1; int inscounts[256]; @@ -39,6 +42,27 @@ } \ } +#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 @@ 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 @@ /*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 @@ 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_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 @@ 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 @@ } else { - if (ssegs) ss=oldss; if (stack32) { writememw(ss,ESP-2,flags); @@ -365,7 +393,6 @@ } else { - if (ssegs) ss=oldss; if (stack32) { writememw(ss,ESP-2,flags); @@ -418,7 +445,6 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } if (rep32&0x200) ECX=c; else CX=c; - if (changeds) ds=oldds; // if (output) pclog("%03X %03X\n",rep32,use32); } @@ -1268,8 +1285,12 @@ dontprint=0; + ea_seg = &_ds; + ssegs = 0; + opcodestart: fetchdat = fastreadl(cs + pc); + if (!abrt) { tempc = CF_SET(); @@ -1287,20 +1308,7 @@ } 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 @@ } } -// 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; diff -r 7734b12d55f0 -r bd46c39a78e8 src/808x.c --- a/src/808x.c Sun Aug 03 20:38:04 2014 +0100 +++ b/src/808x.c Wed Aug 13 20:33:56 2014 +0100 @@ -588,15 +588,15 @@ 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 @@ ESP=0; mmu_perm=4; memset(inscounts, 0, sizeof(inscounts)); + x86seg_reset(); } void softresetx86() @@ -665,6 +666,7 @@ //rammask=0xFFFFFFFF; flags=2; idt.base = 0; + x86seg_reset(); } static void setznp8(uint8_t val) diff -r 7734b12d55f0 -r bd46c39a78e8 src/ibm.h --- a/src/ibm.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/ibm.h Wed Aug 13 20:33:56 2014 +0100 @@ -108,15 +108,18 @@ 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 - diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86.h --- a/src/x86.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86.h Wed Aug 13 20:33:56 2014 +0100 @@ -58,7 +58,7 @@ 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 int inscounts[256]; void x86illegal(); + +void x86seg_reset(); diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_call.h --- a/src/x86_ops_call.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_call.h Wed Aug 13 20:33:56 2014 +0100 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ break; case 0x30: /*PUSH l*/ temp = geteal(); if (abrt) return 0; - if (ssegs) ss = oldss; PUSH_L(temp); cycles -= ((mod == 3) ? 2 : 5); break; diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_flag.h --- a/src/x86_ops_flag.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_flag.h Wed Aug 13 20:33:56 2014 +0100 @@ -76,7 +76,6 @@ 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 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 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(uint32_t fetchdat) { uint16_t tempw; - if (ssegs) ss = oldss; if ((eflags & VM_FLAG) && (IOPL < 3)) { @@ -150,7 +146,6 @@ static int opPOPFD(uint32_t fetchdat) { uint32_t templ; - if (ssegs) ss = oldss; if ((eflags & VM_FLAG) && (IOPL < 3)) { diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_jump.h --- a/src/x86_ops_jump.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_jump.h Wed Aug 13 20:33:56 2014 +0100 @@ -198,7 +198,6 @@ 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_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 @@ { uint16_t ret; - if (ssegs) ss=oldss; ret = POP_W(); if (abrt) return 0; pc = ret; @@ -229,7 +226,6 @@ { uint32_t ret; - if (ssegs) ss=oldss; ret = POP_L(); if (abrt) return 0; pc = ret; @@ -242,7 +238,6 @@ 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 @@ 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; diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_misc.h --- a/src/x86_ops_misc.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_misc.h Wed Aug 13 20:33:56 2014 +0100 @@ -515,7 +515,7 @@ x86gpf(NULL,0); return 0; } - if (!((flags&I_FLAG) && pic_intpending && !ssegs)) + if (!((flags&I_FLAG) && pic_intpending)) { cycles -= 100; pc--; diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_mmx_mov.h --- a/src/x86_ops_mmx_mov.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_mmx_mov.h Wed Aug 13 20:33:56 2014 +0100 @@ -57,6 +57,7 @@ } 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 @@ } 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 @@ } 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 @@ } 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; diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_mov.h --- a/src/x86_ops_mov.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_mov.h Wed Aug 13 20:33:56 2014 +0100 @@ -213,7 +213,7 @@ 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_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_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_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_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_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_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 @@ 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_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 @@ else { fetch_ea_16(fetchdat); + CHECK_WRITE(ea_seg, eaaddr, eaaddr); seteab(getr8(reg)); cycles -= is486 ? 1 : 2; } @@ -383,6 +384,7 @@ else { fetch_ea_32(fetchdat); + CHECK_WRITE(ea_seg, eaaddr, eaaddr); seteab(getr8(reg)); cycles -= is486 ? 1 : 2; } @@ -399,6 +401,7 @@ else { fetch_ea_16(fetchdat); + CHECK_WRITE(ea_seg, eaaddr, eaaddr+1); seteaw(regs[reg].w); cycles -= is486 ? 1 : 2; } @@ -415,6 +418,7 @@ else { fetch_ea_32(fetchdat); + CHECK_WRITE(ea_seg, eaaddr, eaaddr+1); seteaw(regs[reg].w); cycles -= is486 ? 1 : 2; } @@ -431,6 +435,7 @@ else { fetch_ea_16(fetchdat); + CHECK_WRITE(ea_seg, eaaddr, eaaddr+3); seteal(regs[reg].l); cycles -= is486 ? 1 : 2; } @@ -447,6 +452,7 @@ else { fetch_ea_32(fetchdat); + CHECK_WRITE(ea_seg, eaaddr, eaaddr+3); seteal(regs[reg].l); cycles -= is486 ? 1 : 2; } @@ -465,6 +471,7 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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 @@ { 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; diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_mov_seg.h --- a/src/x86_ops_mov_seg.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_mov_seg.h Wed Aug 13 20:33:56 2014 +0100 @@ -11,11 +11,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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; diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_prefix.h --- a/src/x86_ops_prefix.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_prefix.h Wed Aug 13 20:33:56 2014 +0100 @@ -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; } diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_ret.h --- a/src/x86_ops_ret.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_ret.h Wed Aug 13 20:33:56 2014 +0100 @@ -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 @@ x86gpf(NULL,0); return 0; } - if (ssegs) ss = oldss; if (msw&1) { optype = IRET; @@ -115,7 +112,6 @@ x86gpf(NULL,0); return 0; } - if (ssegs) ss = oldss; if (msw&1) { optype = IRET; @@ -155,7 +151,6 @@ x86gpf(NULL,0); return 0; } - if (ssegs) ss = oldss; if (msw & 1) { optype = IRET; diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_stack.h --- a/src/x86_ops_stack.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_stack.h Wed Aug 13 20:33:56 2014 +0100 @@ -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 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_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 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_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 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_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 @@ #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 @@ { \ 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 @@ { \ 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; \ diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86_ops_string.h --- a/src/x86_ops_string.h Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86_ops_string.h Wed Aug 13 20:33:56 2014 +0100 @@ -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_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 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_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 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_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 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_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 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_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 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_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 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_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 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_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 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_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 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_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 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_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 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_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); diff -r 7734b12d55f0 -r bd46c39a78e8 src/x86seg.c --- a/src/x86seg.c Sun Aug 03 20:38:04 2014 +0100 +++ b/src/x86seg.c Wed Aug 13 20:33:56 2014 +0100 @@ -57,6 +57,24 @@ 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 @@ }*/ // 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 @@ } +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 @@ } // 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 @@ } 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 @@ 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 @@ 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 @@ { _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 @@ 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 @@ } 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 @@ { _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 @@ 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 @@ 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 @@ #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 @@ 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 @@ { _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 @@ 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 @@ 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 @@ 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>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 @@ 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 @@ } 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 @@ 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 @@ // 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 @@ 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 @@ { // 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 @@ 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 @@ 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 @@ // 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;