Fixed ECX corruption in LOOP instructions

This commit is contained in:
Jeff Parsons 2015-08-26 14:54:59 -07:00
commit 8c945bac17
8 changed files with 2085 additions and 1978 deletions

View file

@ -1576,8 +1576,8 @@ if (DEBUGGER) {
Debugger.prototype.newAddr = function(off, sel, addr, fProt, fData32, fAddr32) Debugger.prototype.newAddr = function(off, sel, addr, fProt, fData32, fAddr32)
{ {
if (fProt === undefined) fProt = this.getProtMode(); if (fProt === undefined) fProt = this.getProtMode();
if (fData32 === undefined) fData32 = (this.cpu && this.cpu.segCS.dataSize == 4); if (fData32 === undefined) fData32 = (this.cpu && this.cpu.segCS.sizeData == 4);
if (fAddr32 === undefined) fAddr32 = (this.cpu && this.cpu.segCS.addrSize == 4); if (fAddr32 === undefined) fAddr32 = (this.cpu && this.cpu.segCS.sizeAddr == 4);
return {off: off || 0, sel: sel, addr: addr, fProt: fProt || false, fTempBreak: false, fData32: fData32 || false, fAddr32: fAddr32 || false}; return {off: off || 0, sel: sel, addr: addr, fProt: fProt || false, fTempBreak: false, fData32: fData32 || false, fAddr32: fAddr32 || false};
}; };
@ -1617,7 +1617,7 @@ if (DEBUGGER) {
if (dbgAddr.sel != null) { if (dbgAddr.sel != null) {
var seg = this.getSegment(dbgAddr.sel, dbgAddr.fProt); var seg = this.getSegment(dbgAddr.sel, dbgAddr.fProt);
if (seg) { if (seg) {
var off = dbgAddr.off & seg.addrMask; var off = dbgAddr.off & seg.maskAddr;
if ((off >>> 0) >= seg.offMax) return false; if ((off >>> 0) >= seg.offMax) return false;
dbgAddr.off = off; dbgAddr.off = off;
} }
@ -3064,8 +3064,8 @@ if (DEBUGGER) {
dbgAddr.sel = this.cpu.getCS(); dbgAddr.sel = this.cpu.getCS();
dbgAddr.addr = addr; dbgAddr.addr = addr;
dbgAddr.fProt = this.getProtMode(); dbgAddr.fProt = this.getProtMode();
dbgAddr.fData32 = (this.cpu && this.cpu.segCS.dataSize == 4); dbgAddr.fData32 = (this.cpu && this.cpu.segCS.sizeData == 4);
dbgAddr.fAddr32 = (this.cpu && this.cpu.segCS.addrSize == 4); dbgAddr.fAddr32 = (this.cpu && this.cpu.segCS.sizeAddr == 4);
if (++this.iOpcodeHistory == this.aOpcodeHistory.length) this.iOpcodeHistory = 0; if (++this.iOpcodeHistory == this.aOpcodeHistory.length) this.iOpcodeHistory = 0;
} }
} }
@ -6346,8 +6346,8 @@ if (DEBUGGER) {
* both fields must be set to match the size of the current code segment. * both fields must be set to match the size of the current code segment.
*/ */
if (fNonPrefix) { if (fNonPrefix) {
dbgAddr.fData32 = (this.cpu.segCS.dataSize == 4); dbgAddr.fData32 = (this.cpu.segCS.sizeData == 4);
dbgAddr.fAddr32 = (this.cpu.segCS.addrSize == 4); dbgAddr.fAddr32 = (this.cpu.segCS.sizeAddr == 4);
} }
/* /*
* We also use dbgAddr.fComplete to record whether the caller (ie, getInstruction()) is reporting that * We also use dbgAddr.fComplete to record whether the caller (ie, getInstruction()) is reporting that

View file

@ -201,6 +201,17 @@ function X86CPU(parmsCPU)
* so that if/when we call restore(), it will have something to fill in. * so that if/when we call restore(), it will have something to fill in.
*/ */
this.resetRegs(); this.resetRegs();
/*
* Register frames have proven to be a useful tool for catching register corruption bugs (eg, LOOP instructions
* improperly zeroing the high bits of ECX), but they shouldn't be enabled by default, because the associated
* functions (pushRegFrame() and popRegFrame()) can produce false positives, and weeding those out is a nuisance.
*
* In a perfect world, every time we IRET'ed to the CS:EIP where a hardware interrupt was injected, we could
* assume that the current register values will ALWAYS match the original register values (ie, at the time
* of injection). But we can't assume that; there's too much clever code out there.
*/
// if (DEBUG) this.aRegFrames = [];
} }
Component.subclass(X86CPU, CPU); Component.subclass(X86CPU, CPU);
@ -1451,10 +1462,10 @@ X86CPU.prototype.zeroSeg = function(seg)
*/ */
X86CPU.prototype.setAddrSize = function(size) X86CPU.prototype.setAddrSize = function(size)
{ {
if (this.addrSize != size) { if (this.sizeAddr != size) {
this.opPrefixes |= X86.OPFLAG.ADDRSIZE; this.opPrefixes |= X86.OPFLAG.ADDRSIZE;
this.addrSize = size; this.sizeAddr = size;
this.addrMask = (size == 2? 0xffff : (0xffffffff|0)); this.maskAddr = (size == 2? 0xffff : (0xffffffff|0));
this.updateAddrSize(); this.updateAddrSize();
} }
}; };
@ -1463,7 +1474,7 @@ X86CPU.prototype.setAddrSize = function(size)
* updateAddrSize() * updateAddrSize()
* *
* Select the appropriate ModRM dispatch tables, based on the current ADDRESS size (addrSize), which * Select the appropriate ModRM dispatch tables, based on the current ADDRESS size (addrSize), which
* is based foremost on segCS.addrSize, but can also be overridden by an ADDRESS size instruction prefix. * is based foremost on segCS.sizeAddr, but can also be overridden by an ADDRESS size instruction prefix.
* *
* @this {X86CPU} * @this {X86CPU}
*/ */
@ -1478,7 +1489,7 @@ X86CPU.prototype.updateAddrSize = function()
this.aOpModMemWord = X86ModW.aOpModMem; this.aOpModMemWord = X86ModW.aOpModMem;
this.aOpModGrpWord = X86ModW.aOpModGrp; this.aOpModGrpWord = X86ModW.aOpModGrp;
} else { } else {
if (this.addrSize == 2) { if (this.sizeAddr == 2) {
this.getAddr = this.getShort; this.getAddr = this.getShort;
this.aOpModRegByte = X86ModB16.aOpModReg; this.aOpModRegByte = X86ModB16.aOpModReg;
this.aOpModMemByte = X86ModB16.aOpModMem; this.aOpModMemByte = X86ModB16.aOpModMem;
@ -1509,10 +1520,10 @@ X86CPU.prototype.updateAddrSize = function()
*/ */
X86CPU.prototype.setDataSize = function(size) X86CPU.prototype.setDataSize = function(size)
{ {
if (this.dataSize != size) { if (this.sizeData != size) {
this.opPrefixes |= X86.OPFLAG.DATASIZE; this.opPrefixes |= X86.OPFLAG.DATASIZE;
this.dataSize = size; this.sizeData = size;
this.dataMask = (size == 2? 0xffff : (0xffffffff|0)); this.maskData = (size == 2? 0xffff : (0xffffffff|0));
this.updateDataSize(); this.updateDataSize();
} }
}; };
@ -1524,12 +1535,12 @@ X86CPU.prototype.setDataSize = function(size)
*/ */
X86CPU.prototype.updateDataSize = function() X86CPU.prototype.updateDataSize = function()
{ {
if (this.dataSize == 2) { if (this.sizeData == 2) {
this.dataType = X86.RESULT.WORD; this.typeData = X86.RESULT.WORD;
this.getWord = this.getShort; this.getWord = this.getShort;
this.setWord = this.setShort; this.setWord = this.setShort;
} else { } else {
this.dataType = X86.RESULT.DWORD; this.typeData = X86.RESULT.DWORD;
this.getWord = this.getLong; this.getWord = this.getLong;
this.setWord = this.setLong; this.setWord = this.setLong;
} }
@ -1547,15 +1558,15 @@ X86CPU.prototype.resetSizes = function()
* masks for isolating the (src) bits of an address and clearing the (dst) bits of an address. Like the * masks for isolating the (src) bits of an address and clearing the (dst) bits of an address. Like the
* OPERAND size properties, these are reset to their segCS counterparts at the start of every new instruction. * OPERAND size properties, these are reset to their segCS counterparts at the start of every new instruction.
*/ */
this.addrSize = this.segCS.addrSize; this.sizeAddr = this.segCS.sizeAddr;
this.addrMask = this.segCS.addrMask; this.maskAddr = this.segCS.maskAddr;
/* /*
* It's also worth noting that instructions that implicitly use the stack also rely on STACK size, * It's also worth noting that instructions that implicitly use the stack also rely on STACK size,
* which is based on the BIG bit of the last descriptor loaded into SS; use the following segSS properties: * which is based on the BIG bit of the last descriptor loaded into SS; use the following segSS properties:
* *
* segSS.addrSize (2 or 4) * segSS.sizeAddr (2 or 4)
* segSS.addrMask (0xffff or 0xffffffff) * segSS.maskAddr (0xffff or 0xffffffff)
* *
* As there is no STACK size instruction prefix override, there's no need to propagate these segSS properties * As there is no STACK size instruction prefix override, there's no need to propagate these segSS properties
* to separate X86CPU properties, as we do for the OPERAND size and ADDRESS size properties. * to separate X86CPU properties, as we do for the OPERAND size and ADDRESS size properties.
@ -1568,8 +1579,8 @@ X86CPU.prototype.resetSizes = function()
* for isolating the (src) bits of an OPERAND and clearing the (dst) bits of an OPERAND. These are reset to * for isolating the (src) bits of an OPERAND and clearing the (dst) bits of an OPERAND. These are reset to
* their segCS counterparts at the start of every new instruction, but are also set here for documentation purposes. * their segCS counterparts at the start of every new instruction, but are also set here for documentation purposes.
*/ */
this.dataSize = this.segCS.dataSize; this.sizeData = this.segCS.sizeData;
this.dataMask = this.segCS.dataMask; this.maskData = this.segCS.maskData;
this.updateDataSize(); this.updateDataSize();
@ -2160,7 +2171,7 @@ X86CPU.prototype.setSS = function(sel, fInterruptable)
if (regLSP !== X86.ADDR_INVALID) { if (regLSP !== X86.ADDR_INVALID) {
this.regLSP = (regLSP + regESP)|0; this.regLSP = (regLSP + regESP)|0;
if (this.segSS.fExpDown) { if (this.segSS.fExpDown) {
this.regLSPLimit = (this.segSS.base + this.segSS.addrMask)|0; this.regLSPLimit = (this.segSS.base + this.segSS.maskAddr)|0;
this.regLSPLimitLow = (this.segSS.base + this.segSS.limit)|0; this.regLSPLimitLow = (this.segSS.base + this.segSS.limit)|0;
} else { } else {
this.regLSPLimit = (this.segSS.base + this.segSS.limit)|0; this.regLSPLimit = (this.segSS.base + this.segSS.limit)|0;
@ -2278,7 +2289,7 @@ X86CPU.prototype.getIP = function()
*/ */
X86CPU.prototype.setIP = function(off) X86CPU.prototype.setIP = function(off)
{ {
this.regLIP = (this.segCS.base + (off & (I386? this.dataMask : 0xffff)))|0; this.regLIP = (this.segCS.base + (off & (I386? this.maskData : 0xffff)))|0;
if (PREFETCH) this.flushPrefetch(this.regLIP); if (PREFETCH) this.flushPrefetch(this.regLIP);
}; };
@ -2316,7 +2327,7 @@ X86CPU.prototype.setCSIP = function(off, sel, fCall)
* TODO: Should this code be factored into a setLIP() function? The other primary client would be fnINT(). * TODO: Should this code be factored into a setLIP() function? The other primary client would be fnINT().
*/ */
if (I386) this.resetSizes(); if (I386) this.resetSizes();
this.regLIP = (base + (this.regEIP & (I386? this.dataMask : 0xffff)))|0; this.regLIP = (base + (this.regEIP & (I386? this.maskData : 0xffff)))|0;
this.regLIPLimit = (base + this.segCS.limit)|0; this.regLIPLimit = (base + this.segCS.limit)|0;
this.nCPL = this.segCS.cpl; // cache the current CPL where it's more convenient this.nCPL = this.segCS.cpl; // cache the current CPL where it's more convenient
if (PREFETCH) this.flushPrefetch(this.regLIP); if (PREFETCH) this.flushPrefetch(this.regLIP);
@ -2379,7 +2390,7 @@ X86CPU.prototype.advanceIP = function(inc)
* There's no such thing as a GP fault on the 8086/8088, and I'm assuming that, on newer * There's no such thing as a GP fault on the 8086/8088, and I'm assuming that, on newer
* processors, when the segment limit is set to the maximum, it's OK for IP to wrap. * processors, when the segment limit is set to the maximum, it's OK for IP to wrap.
*/ */
if (this.model <= X86.MODEL_8088 || this.segCS.limit == this.segCS.addrMask) { if (this.model <= X86.MODEL_8088 || this.segCS.limit == this.segCS.maskAddr) {
this.setIP(this.regLIP - this.segCS.base); this.setIP(this.regLIP - this.segCS.base);
} else if (off < -1) { // fudge factor } else if (off < -1) { // fudge factor
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0); X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
@ -2414,8 +2425,8 @@ X86CPU.prototype.rewindIP = function(dec)
X86CPU.prototype.getSP = function() X86CPU.prototype.getSP = function()
{ {
if (I386) { if (I386) {
// assert(!((this.regLSP - this.segSS.base) & ~this.segSS.addrMask)); // assert(!((this.regLSP - this.segSS.base) & ~this.segSS.maskAddr));
return (this.regESP & ~this.segSS.addrMask) | (this.regLSP - this.segSS.base); return (this.regESP & ~this.segSS.maskAddr) | (this.regLSP - this.segSS.base);
} }
return (this.regLSP - this.segSS.base)|0; return (this.regLSP - this.segSS.base)|0;
}; };
@ -2430,7 +2441,7 @@ X86CPU.prototype.setSP = function(off)
{ {
if (I386) { if (I386) {
this.regESP = off; this.regESP = off;
this.regLSP = (this.segSS.base + (off & this.segSS.addrMask))|0; this.regLSP = (this.segSS.base + (off & this.segSS.maskAddr))|0;
} else { } else {
this.regLSP = (this.segSS.base + off)|0; this.regLSP = (this.segSS.base + off)|0;
} }
@ -3339,7 +3350,7 @@ X86CPU.prototype.getEAByte = function(seg, off)
*/ */
X86CPU.prototype.getEAByteData = function(off) X86CPU.prototype.getEAByteData = function(off)
{ {
return this.getEAByte(this.segData, off & (I386? this.addrMask : 0xffff)); return this.getEAByte(this.segData, off & (I386? this.maskAddr : 0xffff));
}; };
/** /**
@ -3351,7 +3362,7 @@ X86CPU.prototype.getEAByteData = function(off)
*/ */
X86CPU.prototype.getEAByteStack = function(off) X86CPU.prototype.getEAByteStack = function(off)
{ {
return this.getEAByte(this.segStack, off & (I386? this.addrMask : 0xffff)); return this.getEAByte(this.segStack, off & (I386? this.maskAddr : 0xffff));
}; };
/** /**
@ -3365,7 +3376,7 @@ X86CPU.prototype.getEAByteStack = function(off)
X86CPU.prototype.getEAWord = function(seg, off) X86CPU.prototype.getEAWord = function(seg, off)
{ {
this.segEA = seg; this.segEA = seg;
this.regEA = seg.checkRead(this.offEA = off, (I386? this.dataSize : 2)); this.regEA = seg.checkRead(this.offEA = off, (I386? this.sizeData : 2));
if (this.opFlags & X86.OPFLAG.NOREAD) return 0; if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var w = this.getWord(this.regEA); var w = this.getWord(this.regEA);
if (BACKTRACK) { if (BACKTRACK) {
@ -3384,7 +3395,7 @@ X86CPU.prototype.getEAWord = function(seg, off)
*/ */
X86CPU.prototype.getEAWordData = function(off) X86CPU.prototype.getEAWordData = function(off)
{ {
return this.getEAWord(this.segData, off & (I386? this.addrMask : 0xffff)); return this.getEAWord(this.segData, off & (I386? this.maskAddr : 0xffff));
}; };
/** /**
@ -3396,7 +3407,7 @@ X86CPU.prototype.getEAWordData = function(off)
*/ */
X86CPU.prototype.getEAWordStack = function(off) X86CPU.prototype.getEAWordStack = function(off)
{ {
return this.getEAWord(this.segStack, off & (I386? this.addrMask : 0xffff)); return this.getEAWord(this.segStack, off & (I386? this.maskAddr : 0xffff));
}; };
/** /**
@ -3426,7 +3437,7 @@ X86CPU.prototype.modEAByte = function(seg, off)
*/ */
X86CPU.prototype.modEAByteData = function(off) X86CPU.prototype.modEAByteData = function(off)
{ {
return this.modEAByte(this.segData, off & (I386? this.addrMask : 0xffff)); return this.modEAByte(this.segData, off & (I386? this.maskAddr : 0xffff));
}; };
/** /**
@ -3438,7 +3449,7 @@ X86CPU.prototype.modEAByteData = function(off)
*/ */
X86CPU.prototype.modEAByteStack = function(off) X86CPU.prototype.modEAByteStack = function(off)
{ {
return this.modEAByte(this.segStack, off & (I386? this.addrMask : 0xffff)); return this.modEAByte(this.segStack, off & (I386? this.maskAddr : 0xffff));
}; };
/** /**
@ -3452,7 +3463,7 @@ X86CPU.prototype.modEAByteStack = function(off)
X86CPU.prototype.modEAWord = function(seg, off) X86CPU.prototype.modEAWord = function(seg, off)
{ {
this.segEA = seg; this.segEA = seg;
this.regEAWrite = this.regEA = seg.checkRead(this.offEA = off, (I386? this.dataSize : 2)); this.regEAWrite = this.regEA = seg.checkRead(this.offEA = off, (I386? this.sizeData : 2));
if (this.opFlags & X86.OPFLAG.NOREAD) return 0; if (this.opFlags & X86.OPFLAG.NOREAD) return 0;
var w = this.getWord(this.regEA); var w = this.getWord(this.regEA);
if (BACKTRACK) { if (BACKTRACK) {
@ -3471,7 +3482,7 @@ X86CPU.prototype.modEAWord = function(seg, off)
*/ */
X86CPU.prototype.modEAWordData = function(off) X86CPU.prototype.modEAWordData = function(off)
{ {
return this.modEAWord(this.segData, off & (I386? this.addrMask : 0xffff)); return this.modEAWord(this.segData, off & (I386? this.maskAddr : 0xffff));
}; };
/** /**
@ -3483,7 +3494,7 @@ X86CPU.prototype.modEAWordData = function(off)
*/ */
X86CPU.prototype.modEAWordStack = function(off) X86CPU.prototype.modEAWordStack = function(off)
{ {
return this.modEAWord(this.segStack, off & (I386? this.addrMask : 0xffff)); return this.modEAWord(this.segStack, off & (I386? this.maskAddr : 0xffff));
}; };
/** /**
@ -3515,7 +3526,7 @@ X86CPU.prototype.setEAWord = function(w)
if (!I386) { if (!I386) {
this.setShort(this.segEA.checkWrite(this.offEA, 2), w); this.setShort(this.segEA.checkWrite(this.offEA, 2), w);
} else { } else {
this.setWord(this.segEA.checkWrite(this.offEA, this.dataSize), w); this.setWord(this.segEA.checkWrite(this.offEA, this.sizeData), w);
} }
}; };
@ -3549,7 +3560,7 @@ X86CPU.prototype.getSOWord = function(seg, off)
if (!I386) { if (!I386) {
return this.getShort(seg.checkRead(off, 2)); return this.getShort(seg.checkRead(off, 2));
} else { } else {
return this.getWord(seg.checkRead(off, this.dataSize)); return this.getWord(seg.checkRead(off, this.sizeData));
} }
}; };
@ -3583,7 +3594,7 @@ X86CPU.prototype.setSOWord = function(seg, off, w)
if (!I386) { if (!I386) {
this.setShort(seg.checkWrite(off, 2), w); this.setShort(seg.checkWrite(off, 2), w);
} else { } else {
this.setWord(seg.checkWrite(off, this.dataSize), w); this.setWord(seg.checkWrite(off, this.sizeData), w);
} }
}; };
@ -3675,7 +3686,7 @@ X86CPU.prototype.getLongPrefetch = function(addr)
*/ */
X86CPU.prototype.getWordPrefetch = function(addr) X86CPU.prototype.getWordPrefetch = function(addr)
{ {
return (I386 && this.dataSize == 4? this.getLongPrefetch(addr) : this.getShortPrefetch(addr)); return (I386 && this.sizeData == 4? this.getLongPrefetch(addr) : this.getShortPrefetch(addr));
}; };
/** /**
@ -3810,7 +3821,7 @@ X86CPU.prototype.getIPAddr = function()
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0); this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1); this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1);
} }
this.advanceIP(this.addrSize); this.advanceIP(this.sizeAddr);
return w; return w;
}; };
@ -3827,7 +3838,7 @@ X86CPU.prototype.getIPWord = function()
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0); this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMem0);
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1); this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMem1);
} }
this.advanceIP(this.dataSize); this.advanceIP(this.sizeData);
return w; return w;
}; };
@ -3869,7 +3880,7 @@ X86CPU.prototype.getSIBAddr = function(mod)
X86CPU.prototype.popWord = function() X86CPU.prototype.popWord = function()
{ {
var w = this.getWord(this.regLSP); var w = this.getWord(this.regLSP);
this.regLSP = (this.regLSP + (I386? this.dataSize : 2))|0; this.regLSP = (this.regLSP + (I386? this.sizeData : 2))|0;
/* /*
* Properly comparing regLSP to regLSPLimit would normally require coercing both to unsigned * Properly comparing regLSP to regLSPLimit would normally require coercing both to unsigned
* (ie, floating-point) values. But instead, we do a subtraction, (regLSPLimit - regLSP), and * (ie, floating-point) values. But instead, we do a subtraction, (regLSPLimit - regLSP), and
@ -3886,8 +3897,8 @@ X86CPU.prototype.popWord = function()
* There's no such thing as an SS fault on the 8086/8088, and I'm assuming that, on newer * There's no such thing as an SS fault on the 8086/8088, and I'm assuming that, on newer
* processors, when the stack segment limit is set to the maximum, it's OK for the stack to wrap. * processors, when the stack segment limit is set to the maximum, it's OK for the stack to wrap.
*/ */
if (this.model <= X86.MODEL_8088 || !this.segSS.fExpDown && this.segSS.limit == this.segSS.addrMask || this.segSS.fExpDown && !this.segSS.limit) { if (this.model <= X86.MODEL_8088 || !this.segSS.fExpDown && this.segSS.limit == this.segSS.maskAddr || this.segSS.fExpDown && !this.segSS.limit) {
this.setSP((this.regLSP - this.segSS.base) & this.segSS.addrMask); this.setSP((this.regLSP - this.segSS.base) & this.segSS.maskAddr);
} else if (off < -1) { // fudge factor } else if (off < -1) { // fudge factor
X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0); X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
} }
@ -3908,12 +3919,12 @@ X86CPU.prototype.pushWord = function(w)
* thus sign-extending the byte as appropriate. And since sign-extension necessarily affects the entire 32-bit * thus sign-extending the byte as appropriate. And since sign-extension necessarily affects the entire 32-bit
* value, this assertion could fail when dataMask is 16 bits. * value, this assertion could fail when dataMask is 16 bits.
* *
* this.assert((w & this.dataMask) == w); * this.assert((w & this.maskData) == w);
* *
* setWord() calls setShort() or setLong() as appropriate, and setShort() truncates incoming values, so the fact * setWord() calls setShort() or setLong() as appropriate, and setShort() truncates incoming values, so the fact
* that any incoming signed values will not be truncated to 16 bits should not be a concern. * that any incoming signed values will not be truncated to 16 bits should not be a concern.
*/ */
this.regLSP = (this.regLSP - (I386? this.dataSize : 2))|0; this.regLSP = (this.regLSP - (I386? this.sizeData : 2))|0;
/* /*
* Properly comparing regLSP to regLSPLimitLow would normally require coercing both to unsigned * Properly comparing regLSP to regLSPLimitLow would normally require coercing both to unsigned
* (ie, floating-point) values. But instead, we do a subtraction, (regLSP - regLSPLimitLow), and * (ie, floating-point) values. But instead, we do a subtraction, (regLSP - regLSPLimitLow), and
@ -3925,8 +3936,8 @@ X86CPU.prototype.pushWord = function(w)
* There's no such thing as an SS fault on the 8086/8088, and I'm assuming that, on newer * There's no such thing as an SS fault on the 8086/8088, and I'm assuming that, on newer
* processors, when the stack segment limit is set to the maximum, it's OK for the stack to wrap. * processors, when the stack segment limit is set to the maximum, it's OK for the stack to wrap.
*/ */
if (this.model <= X86.MODEL_8088 || !this.segSS.fExpDown && this.segSS.limit == this.segSS.addrMask || this.segSS.fExpDown && !this.segSS.limit) { if (this.model <= X86.MODEL_8088 || !this.segSS.fExpDown && this.segSS.limit == this.segSS.maskAddr || this.segSS.fExpDown && !this.segSS.limit) {
this.setSP((this.regLSP - this.segSS.base) & this.segSS.addrMask); this.setSP((this.regLSP - this.segSS.base) & this.segSS.maskAddr);
} else { } else {
X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0); X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
} }
@ -3954,6 +3965,71 @@ X86CPU.prototype.pushWord = function(w)
}; };
*/ */
/**
* newRegFrame()
*
* @this {X86CPU}
* @return {Array}
*
X86CPU.prototype.newRegFrame = function()
{
return [this.getIP(), this.segCS.sel, this.segDS.sel, this.segES.sel, this.segSS.sel,
this.regEAX, this.regEBX, this.regECX, this.regEDX, this.regESI, this.regEDI, this.regEBP, this.getSP(),
this.dbg? this.dbg.cOpcodes : 0];
};
*/
/**
* pushRegFrame()
*
* Call this immediately before injecting a hardware interrupt. Subsequent IRET instructions will check the most
* recent frame to verify that all registers have been restored to their original values.
*
* @this {X86CPU}
*
X86CPU.prototype.pushRegFrame = function()
{
this.aRegFrames.push(this.newRegFrame());
if (this.aRegFrames.length > 10) {
this.println("frame overflow");
this.stopCPU();
}
};
*/
/**
* popRegFrame()
*
* Call this immediately after an IRET. If EIP and CS match the most recent frame, check the rest of the registers.
*
* @this {X86CPU}
*
X86CPU.prototype.popRegFrame = function()
{
if (this.aRegFrames.length) {
var a = this.aRegFrames[this.aRegFrames.length-1];
if (a[1] !== this.segCS.sel || a[0] !== this.getIP()) {
return;
}
var fMatch = true;
var b = this.newRegFrame(), i;
for (i = 2; i < a.length-2; i++) {
if (a[i] !== b[i]) {
this.println("frame mismatch at " + i + ": original=" + str.toHex(a[i]) + ", current=" + str.toHex(b[i]));
fMatch = false;
this.stopCPU();
}
}
if (!fMatch) {
i++;
this.println("opcode delta: " + (b[i] - a[i]));
}
this.aRegFrames.pop();
}
};
*/
/** /**
* checkINTR() * checkINTR()
* *
@ -4023,6 +4099,7 @@ X86CPU.prototype.checkINTR = function()
this.intFlags &= ~X86.INTFLAG.INTR; this.intFlags &= ~X86.INTFLAG.INTR;
if (nIDT >= 0) { if (nIDT >= 0) {
this.intFlags &= ~X86.INTFLAG.HALT; this.intFlags &= ~X86.INTFLAG.HALT;
// if (DEBUG) this.pushRegFrame(); // the corresponding popRegFrame() is in opIRET()
X86.fnINT.call(this, nIDT, null, 11); X86.fnINT.call(this, nIDT, null, 11);
return true; return true;
} }
@ -4383,7 +4460,6 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
this.fillPrefetch(nSpareCycles >> 2); // for every 4 spare cycles, fetch 1 instruction byte this.fillPrefetch(nSpareCycles >> 2); // for every 4 spare cycles, fetch 1 instruction byte
} }
} }
if (DEBUG) { if (DEBUG) {
// //
// Make sure that every instruction is assessing a cycle cost, and that the cost is a net positive. // Make sure that every instruction is assessing a cycle cost, and that the cost is a net positive.

View file

@ -65,9 +65,9 @@ X86.fnADCb = function ADCb(dst, src)
X86.fnADCw = function ADCw(dst, src) X86.fnADCw = function ADCw(dst, src)
{ {
var w = (dst + src + this.getCarry())|0; var w = (dst + src + this.getCarry())|0;
this.setArithResult(dst, src, w, this.dataType | X86.RESULT.ALL); this.setArithResult(dst, src, w, this.typeData | X86.RESULT.ALL);
this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR); this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR);
return w & this.dataMask; return w & this.maskData;
}; };
/** /**
@ -97,9 +97,9 @@ X86.fnADDb = function ADDb(dst, src)
X86.fnADDw = function ADDw(dst, src) X86.fnADDw = function ADDw(dst, src)
{ {
var w = (dst + src)|0; var w = (dst + src)|0;
this.setArithResult(dst, src, w, this.dataType | X86.RESULT.ALL); this.setArithResult(dst, src, w, this.typeData | X86.RESULT.ALL);
this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR); this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR);
return w & this.dataMask; return w & this.maskData;
}; };
/** /**
@ -129,7 +129,7 @@ X86.fnANDb = function ANDb(dst, src)
X86.fnANDw = function ANDw(dst, src) X86.fnANDw = function ANDw(dst, src)
{ {
this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR); this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR);
return this.setLogicResult(dst & src, this.dataType); return this.setLogicResult(dst & src, this.typeData);
}; };
/** /**
@ -196,8 +196,8 @@ X86.fnBOUND = function BOUND(dst, src)
*/ */
var wIndex = dst; var wIndex = dst;
var wLower = this.getWord(this.regEA); var wLower = this.getWord(this.regEA);
var wUpper = this.getWord(this.regEA + this.dataSize); var wUpper = this.getWord(this.regEA + this.sizeData);
if (this.dataSize == 2) { if (this.sizeData == 2) {
wIndex = (dst << 16) >> 16; wIndex = (dst << 16) >> 16;
wLower = (wLower << 16) >> 16; wLower = (wLower << 16) >> 16;
wUpper = (wUpper << 16) >> 16; wUpper = (wUpper << 16) >> 16;
@ -239,7 +239,7 @@ X86.fnBSF = function BSF(dst, src)
} else { } else {
this.clearZF(); this.clearZF();
var bit = 0x1; var bit = 0x1;
while (bit & this.dataMask) { while (bit & this.maskData) {
if (src & bit) { if (src & bit) {
dst = n; dst = n;
break; break;
@ -274,7 +274,7 @@ X86.fnBSR = function BSR(dst, src)
this.setZF(); this.setZF();
} else { } else {
this.clearZF(); this.clearZF();
var i = (this.dataSize == 2? 15 : 31), bit = 1 << i; var i = (this.sizeData == 2? 15 : 31), bit = 1 << i;
while (bit) { while (bit) {
if (src & bit) { if (src & bit) {
dst = i; dst = i;
@ -403,7 +403,7 @@ X86.fnCALLFdw = function CALLFdw(dst, src)
if (this.regEA === X86.ADDR_INVALID) { if (this.regEA === X86.ADDR_INVALID) {
return X86.fnGRPUndefined.call(this, dst, src); return X86.fnGRPUndefined.call(this, dst, src);
} }
X86.fnCALLF.call(this, dst, this.getShort(this.regEA + this.dataSize)); X86.fnCALLF.call(this, dst, this.getShort(this.regEA + this.sizeData));
this.nStepCycles -= this.cycleCounts.nOpCyclesCallDM; this.nStepCycles -= this.cycleCounts.nOpCyclesCallDM;
this.opFlags |= X86.OPFLAG.NOWRITE; this.opFlags |= X86.OPFLAG.NOWRITE;
return dst; return dst;
@ -437,7 +437,7 @@ X86.fnCMPb = function CMPb(dst, src)
X86.fnCMPw = function CMPw(dst, src) X86.fnCMPw = function CMPw(dst, src)
{ {
var w = (dst - src)|0; var w = (dst - src)|0;
this.setArithResult(dst, src, w, this.dataType | X86.RESULT.ALL, true); this.setArithResult(dst, src, w, this.typeData | X86.RESULT.ALL, true);
this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesCompareRM) : this.cycleCounts.nOpCyclesArithRM); this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesCompareRM) : this.cycleCounts.nOpCyclesArithRM);
this.opFlags |= X86.OPFLAG.NOWRITE; this.opFlags |= X86.OPFLAG.NOWRITE;
return dst; return dst;
@ -469,9 +469,9 @@ X86.fnDECb = function DECb(dst, src)
X86.fnDECr = function DECr(w) X86.fnDECr = function DECr(w)
{ {
var result = (w - 1)|0; var result = (w - 1)|0;
this.setArithResult(w, 1, result, this.dataType | X86.RESULT.NOTCF, true); this.setArithResult(w, 1, result, this.typeData | X86.RESULT.NOTCF, true);
this.nStepCycles -= 2; // the register form of DEC takes 2 cycles on all CPUs this.nStepCycles -= 2; // the register form of DEC takes 2 cycles on all CPUs
return (w & ~this.dataMask) | (result & this.dataMask); return (w & ~this.maskData) | (result & this.maskData);
}; };
/** /**
@ -485,9 +485,9 @@ X86.fnDECr = function DECr(w)
X86.fnDECw = function DECw(dst, src) X86.fnDECw = function DECw(dst, src)
{ {
var w = (dst - 1)|0; var w = (dst - 1)|0;
this.setArithResult(dst, 1, w, this.dataType | X86.RESULT.NOTCF, true); this.setArithResult(dst, 1, w, this.typeData | X86.RESULT.NOTCF, true);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesIncR : this.cycleCounts.nOpCyclesIncM); this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesIncR : this.cycleCounts.nOpCyclesIncM);
return w & this.dataMask; return w & this.maskData;
}; };
/** /**
@ -700,7 +700,7 @@ X86.fnDIVb = function DIVb(dst, src)
*/ */
X86.fnDIVw = function DIVw(dst, src) X86.fnDIVw = function DIVw(dst, src)
{ {
if (this.dataSize == 2) { if (this.sizeData == 2) {
/* /*
* Detect zero divisor * Detect zero divisor
*/ */
@ -742,7 +742,7 @@ X86.fnDIVw = function DIVw(dst, src)
* dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src. * dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src.
*/ */
if (DEBUG && DEBUGGER) { if (DEBUG && DEBUGGER) {
if (this.dataSize == 2) { if (this.sizeData == 2) {
this.traceLog('DIVw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16)); this.traceLog('DIVw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
} else { } else {
this.traceLog('DIVd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi); this.traceLog('DIVd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
@ -829,7 +829,7 @@ X86.fnIDIVb = function IDIVb(dst, src)
*/ */
X86.fnIDIVw = function IDIVw(dst, src) X86.fnIDIVw = function IDIVw(dst, src)
{ {
if (this.dataSize == 2) { if (this.sizeData == 2) {
/* /*
* Detect zero divisor * Detect zero divisor
*/ */
@ -879,7 +879,7 @@ X86.fnIDIVw = function IDIVw(dst, src)
* dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src. * dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src.
*/ */
if (DEBUG && DEBUGGER) { if (DEBUG && DEBUGGER) {
if (this.dataSize == 2) { if (this.sizeData == 2) {
this.traceLog('IDIVw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16)); this.traceLog('IDIVw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
} else { } else {
this.traceLog('IDIVd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi); this.traceLog('IDIVd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
@ -998,7 +998,7 @@ X86.fnIMULn = function IMULn(dst, src)
{ {
var fOverflow, result; var fOverflow, result;
dst = this.getIPWord(); dst = this.getIPWord();
if (this.dataSize == 2) { if (this.sizeData == 2) {
result = (((src << 16) >> 16) * ((dst << 16) >> 16))|0; result = (((src << 16) >> 16) * ((dst << 16) >> 16))|0;
fOverflow = (result > 32767 || result < -32768); fOverflow = (result > 32767 || result < -32768);
} else { } else {
@ -1013,7 +1013,7 @@ X86.fnIMULn = function IMULn(dst, src)
this.clearCF(); this.clearOF(); this.clearCF(); this.clearOF();
} }
result &= this.dataMask; result &= this.maskData;
if (DEBUG && DEBUGGER) this.traceLog('IMULn', dst, src, null, this.getPS(), result); if (DEBUG && DEBUGGER) this.traceLog('IMULn', dst, src, null, this.getPS(), result);
/* /*
@ -1085,7 +1085,7 @@ X86.fnIMUL32 = function IMUL32(dst, src)
X86.fnIMULw = function IMULw(dst, src) X86.fnIMULw = function IMULw(dst, src)
{ {
var fOverflow; var fOverflow;
if (this.dataSize == 2) { if (this.sizeData == 2) {
src = this.regEAX & 0xffff; src = this.regEAX & 0xffff;
var result = (((src << 16) >> 16) * ((dst << 16) >> 16))|0; var result = (((src << 16) >> 16) * ((dst << 16) >> 16))|0;
this.fMDSet = true; this.fMDSet = true;
@ -1110,7 +1110,7 @@ X86.fnIMULw = function IMULw(dst, src)
* dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src. * dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src.
*/ */
if (DEBUG && DEBUGGER) { if (DEBUG && DEBUGGER) {
if (this.dataSize == 2) { if (this.sizeData == 2) {
this.traceLog('IMULw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16)); this.traceLog('IMULw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
} else { } else {
this.traceLog('IMULd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi); this.traceLog('IMULd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
@ -1189,9 +1189,9 @@ X86.fnINCb = function INCb(dst, src)
X86.fnINCr = function INCr(w) X86.fnINCr = function INCr(w)
{ {
var result = (w + 1)|0; var result = (w + 1)|0;
this.setArithResult(w, 1, result, this.dataType | X86.RESULT.NOTCF); this.setArithResult(w, 1, result, this.typeData | X86.RESULT.NOTCF);
this.nStepCycles -= 2; // the register form of INC takes 2 cycles on all CPUs this.nStepCycles -= 2; // the register form of INC takes 2 cycles on all CPUs
return (w & ~this.dataMask) | (result & this.dataMask); return (w & ~this.maskData) | (result & this.maskData);
}; };
/** /**
@ -1205,9 +1205,9 @@ X86.fnINCr = function INCr(w)
X86.fnINCw = function INCw(dst, src) X86.fnINCw = function INCw(dst, src)
{ {
var w = (dst + 1)|0; var w = (dst + 1)|0;
this.setArithResult(dst, 1, w, this.dataType | X86.RESULT.NOTCF); this.setArithResult(dst, 1, w, this.typeData | X86.RESULT.NOTCF);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesIncR : this.cycleCounts.nOpCyclesIncM); this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesIncR : this.cycleCounts.nOpCyclesIncM);
return w & this.dataMask; return w & this.maskData;
}; };
/** /**
@ -1360,7 +1360,7 @@ X86.fnJMPFdw = function JMPFdw(dst, src)
if (this.regEA === X86.ADDR_INVALID) { if (this.regEA === X86.ADDR_INVALID) {
return X86.fnGRPUndefined.call(this, dst, src); return X86.fnGRPUndefined.call(this, dst, src);
} }
this.setCSIP(dst, this.getShort(this.regEA + this.dataSize)); this.setCSIP(dst, this.getShort(this.regEA + this.sizeData));
if (MAXDEBUG && this.cIntReturn) this.checkIntReturn(this.regLIP); if (MAXDEBUG && this.cIntReturn) this.checkIntReturn(this.regLIP);
this.nStepCycles -= this.cycleCounts.nOpCyclesJmpDM; this.nStepCycles -= this.cycleCounts.nOpCyclesJmpDM;
this.opFlags |= X86.OPFLAG.NOWRITE; this.opFlags |= X86.OPFLAG.NOWRITE;
@ -1390,7 +1390,7 @@ X86.fnLAR = function LAR(dst, src)
if (this.segVER.dpl >= this.nCPL && this.segVER.dpl >= (src & X86.SEL.RPL)) { if (this.segVER.dpl >= this.nCPL && this.segVER.dpl >= (src & X86.SEL.RPL)) {
this.setZF(); this.setZF();
dst = this.segVER.acc & ~X86.DESC.ACC.BASE1623; dst = this.segVER.acc & ~X86.DESC.ACC.BASE1623;
if (this.dataSize > 2) { if (this.sizeData > 2) {
dst |= ((this.segVER.ext & ~X86.DESC.EXT.BASE2431) << 16); dst |= ((this.segVER.ext & ~X86.DESC.EXT.BASE2431) << 16);
} }
} }
@ -1452,7 +1452,7 @@ X86.fnLDS = function LDS(dst, src)
X86.opUndefined.call(this); X86.opUndefined.call(this);
return dst; return dst;
} }
this.setDS(this.getShort(this.regEA + this.dataSize)); this.setDS(this.getShort(this.regEA + this.sizeData));
this.nStepCycles -= this.cycleCounts.nOpCyclesLS; this.nStepCycles -= this.cycleCounts.nOpCyclesLS;
return src; return src;
}; };
@ -1498,7 +1498,7 @@ X86.fnLES = function LES(dst, src)
X86.opUndefined.call(this); X86.opUndefined.call(this);
return dst; return dst;
} }
this.setES(this.getShort(this.regEA + this.dataSize)); this.setES(this.getShort(this.regEA + this.sizeData));
this.nStepCycles -= this.cycleCounts.nOpCyclesLS; this.nStepCycles -= this.cycleCounts.nOpCyclesLS;
return src; return src;
}; };
@ -1517,7 +1517,7 @@ X86.fnLFS = function LFS(dst, src)
X86.opUndefined.call(this); X86.opUndefined.call(this);
return dst; return dst;
} }
this.setFS(this.getShort(this.regEA + this.dataSize)); this.setFS(this.getShort(this.regEA + this.sizeData));
this.nStepCycles -= this.cycleCounts.nOpCyclesLS; this.nStepCycles -= this.cycleCounts.nOpCyclesLS;
return src; return src;
}; };
@ -1552,7 +1552,7 @@ X86.fnLGDT = function LGDT(dst, src)
* Hopefully it won't hurt to always fetch a 32-bit base address (even on an 80286), which we then * Hopefully it won't hurt to always fetch a 32-bit base address (even on an 80286), which we then
* mask apppropriately. * mask apppropriately.
*/ */
this.addrGDT = this.getLong(this.regEA + 2) & (this.dataMask | (this.dataMask << 8)); this.addrGDT = this.getLong(this.regEA + 2) & (this.maskData | (this.maskData << 8));
/* /*
* An idiosyncrasy of our ModRM decoders is that, if the OPERAND size is 32 bits, then it will have * An idiosyncrasy of our ModRM decoders is that, if the OPERAND size is 32 bits, then it will have
* fetched a 32-bit dst operand; we mask off those extra bits now. * fetched a 32-bit dst operand; we mask off those extra bits now.
@ -1579,7 +1579,7 @@ X86.fnLGS = function LGS(dst, src)
X86.opUndefined.call(this); X86.opUndefined.call(this);
return dst; return dst;
} }
this.setGS(this.getShort(this.regEA + this.dataSize)); this.setGS(this.getShort(this.regEA + this.sizeData));
this.nStepCycles -= this.cycleCounts.nOpCyclesLS; this.nStepCycles -= this.cycleCounts.nOpCyclesLS;
return src; return src;
}; };
@ -1614,7 +1614,7 @@ X86.fnLIDT = function LIDT(dst, src)
* Hopefully it won't hurt to always fetch a 32-bit base address (even on an 80286), which we then * Hopefully it won't hurt to always fetch a 32-bit base address (even on an 80286), which we then
* mask apppropriately. * mask apppropriately.
*/ */
this.addrIDT = this.getLong(this.regEA + 2) & (this.dataMask | (this.dataMask << 8)); this.addrIDT = this.getLong(this.regEA + 2) & (this.maskData | (this.maskData << 8));
/* /*
* An idiosyncrasy of our ModRM decoders is that, if the OPERAND size is 32 bits, then it will have * An idiosyncrasy of our ModRM decoders is that, if the OPERAND size is 32 bits, then it will have
* fetched a 32-bit dst operand; we mask off those extra bits now. * fetched a 32-bit dst operand; we mask off those extra bits now.
@ -1715,7 +1715,7 @@ X86.fnLSS = function LSS(dst, src)
X86.opUndefined.call(this); X86.opUndefined.call(this);
return dst; return dst;
} }
this.setSS(this.getShort(this.regEA + this.dataSize)); this.setSS(this.getShort(this.regEA + this.sizeData));
this.nStepCycles -= this.cycleCounts.nOpCyclesLS; this.nStepCycles -= this.cycleCounts.nOpCyclesLS;
return src; return src;
}; };
@ -1881,7 +1881,7 @@ X86.fnMUL32 = function MUL32(dst, src)
*/ */
X86.fnMULw = function MULw(dst, src) X86.fnMULw = function MULw(dst, src)
{ {
if (this.dataSize == 2) { if (this.sizeData == 2) {
src = this.regEAX & 0xffff; src = this.regEAX & 0xffff;
var result = (src * dst)|0; var result = (src * dst)|0;
this.fMDSet = true; this.fMDSet = true;
@ -1904,7 +1904,7 @@ X86.fnMULw = function MULw(dst, src)
* dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src. * dst unchanged). So, to make traceLog() more consistent, we reverse the order of dst and src.
*/ */
if (DEBUG && DEBUGGER) { if (DEBUG && DEBUGGER) {
if (this.dataSize == 2) { if (this.sizeData == 2) {
this.traceLog('MULw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16)); this.traceLog('MULw', src, dst, null, this.getPS(), this.regMDLo | (this.regMDHi << 16));
} else { } else {
this.traceLog('MULd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi); this.traceLog('MULd', src, dst, null, this.getPS(), this.regMDLo, this.regMDHi);
@ -1942,9 +1942,9 @@ X86.fnNEGb = function NEGb(dst, src)
X86.fnNEGw = function NEGw(dst, src) X86.fnNEGw = function NEGw(dst, src)
{ {
var w = (-dst)|0; var w = (-dst)|0;
this.setArithResult(0, dst, w, this.dataType | X86.RESULT.ALL, true); this.setArithResult(0, dst, w, this.typeData | X86.RESULT.ALL, true);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesNegR : this.cycleCounts.nOpCyclesNegM); this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesNegR : this.cycleCounts.nOpCyclesNegM);
return w & this.dataMask; return w & this.maskData;
}; };
/** /**
@ -1972,7 +1972,7 @@ X86.fnNOTb = function NOTb(dst, src)
X86.fnNOTw = function NOTw(dst, src) X86.fnNOTw = function NOTw(dst, src)
{ {
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesNegR : this.cycleCounts.nOpCyclesNegM); this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesNegR : this.cycleCounts.nOpCyclesNegM);
return dst ^ this.dataMask; return dst ^ this.maskData;
}; };
/** /**
@ -2000,7 +2000,7 @@ X86.fnORb = function ORb(dst, src)
X86.fnORw = function ORw(dst, src) X86.fnORw = function ORw(dst, src)
{ {
this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR); this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR);
return this.setLogicResult(dst | src, this.dataType); return this.setLogicResult(dst | src, this.typeData);
}; };
/** /**
@ -2526,9 +2526,9 @@ X86.fnSBBb = function SBBb(dst, src)
X86.fnSBBw = function SBBw(dst, src) X86.fnSBBw = function SBBw(dst, src)
{ {
var w = (dst - src - this.getCarry())|0; var w = (dst - src - this.getCarry())|0;
this.setArithResult(dst, src, w, this.dataType | X86.RESULT.ALL, true); this.setArithResult(dst, src, w, this.typeData | X86.RESULT.ALL, true);
this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR); this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR);
return w & this.dataMask; return w & this.maskData;
}; };
/** /**
@ -2816,7 +2816,7 @@ X86.fnSGDT = function SGDT(dst, src)
addr |= (0xff000000|0); addr |= (0xff000000|0);
} }
else if (this.model >= X86.MODEL_80386) { else if (this.model >= X86.MODEL_80386) {
if (this.dataSize == 2) { if (this.sizeData == 2) {
addr &= 0x00ffffff; addr &= 0x00ffffff;
} else { } else {
dst |= (addr << 16); dst |= (addr << 16);
@ -3179,7 +3179,7 @@ X86.fnSIDT = function SIDT(dst, src)
addr |= (0xff000000|0); addr |= (0xff000000|0);
} }
else if (this.model >= X86.MODEL_80386) { else if (this.model >= X86.MODEL_80386) {
if (this.dataSize == 2) { if (this.sizeData == 2) {
addr &= 0x00ffffff; addr &= 0x00ffffff;
} else { } else {
dst |= (addr << 16); dst |= (addr << 16);
@ -3266,9 +3266,9 @@ X86.fnSUBb = function SUBb(dst, src)
X86.fnSUBw = function SUBw(dst, src) X86.fnSUBw = function SUBw(dst, src)
{ {
var w = (dst - src)|0; var w = (dst - src)|0;
this.setArithResult(dst, src, w, this.dataType | X86.RESULT.ALL, true); this.setArithResult(dst, src, w, this.typeData | X86.RESULT.ALL, true);
this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR); this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR);
return w & this.dataMask; return w & this.maskData;
}; };
/** /**
@ -3299,7 +3299,7 @@ X86.fnTESTib = function TESTib(dst, src)
X86.fnTESTiw = function TESTiw(dst, src) X86.fnTESTiw = function TESTiw(dst, src)
{ {
src = this.getIPWord(); src = this.getIPWord();
this.setLogicResult(dst & src, this.dataType); this.setLogicResult(dst & src, this.typeData);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesTestRI : this.cycleCounts.nOpCyclesTestMI); this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesTestRI : this.cycleCounts.nOpCyclesTestMI);
this.opFlags |= X86.OPFLAG.NOWRITE; this.opFlags |= X86.OPFLAG.NOWRITE;
return dst; return dst;
@ -3331,7 +3331,7 @@ X86.fnTESTb = function TESTb(dst, src)
*/ */
X86.fnTESTw = function TESTw(dst, src) X86.fnTESTw = function TESTw(dst, src)
{ {
this.setLogicResult(dst & src, this.dataType); this.setLogicResult(dst & src, this.typeData);
this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesTestRR : this.cycleCounts.nOpCyclesTestRM) : this.cycleCounts.nOpCyclesTestRM); this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesTestRR : this.cycleCounts.nOpCyclesTestRM) : this.cycleCounts.nOpCyclesTestRM);
this.opFlags |= X86.OPFLAG.NOWRITE; this.opFlags |= X86.OPFLAG.NOWRITE;
return dst; return dst;
@ -3511,31 +3511,31 @@ X86.fnXCHGrw = function XCHGRw(dst, src)
/* /*
* Decode which register was src * Decode which register was src
*/ */
this.assert(!(dst & ~this.dataMask)); // confirm that dst contains only 16 or 32 bits this.assert(!(dst & ~this.maskData)); // confirm that dst contains only 16 or 32 bits
switch (this.bModRM & 0x7) { switch (this.bModRM & 0x7) {
case 0x0: // [E]AX case 0x0: // [E]AX
this.regEAX = (this.regEAX & ~this.dataMask) | dst; this.regEAX = (this.regEAX & ~this.maskData) | dst;
break; break;
case 0x1: // [E]CX case 0x1: // [E]CX
this.regECX = (this.regECX & ~this.dataMask) | dst; this.regECX = (this.regECX & ~this.maskData) | dst;
break; break;
case 0x2: // [E]DX case 0x2: // [E]DX
this.regEDX = (this.regEDX & ~this.dataMask) | dst; this.regEDX = (this.regEDX & ~this.maskData) | dst;
break; break;
case 0x3: // [E]BX case 0x3: // [E]BX
this.regEBX = (this.regEBX & ~this.dataMask) | dst; this.regEBX = (this.regEBX & ~this.maskData) | dst;
break; break;
case 0x4: // [E]SP case 0x4: // [E]SP
this.setSP((this.getSP() & ~this.dataMask) | dst); this.setSP((this.getSP() & ~this.maskData) | dst);
break; break;
case 0x5: // [E]BP case 0x5: // [E]BP
this.regEBP = (this.regEBX & ~this.dataMask) | dst; this.regEBP = (this.regEBX & ~this.maskData) | dst;
break; break;
case 0x6: // [E]SI case 0x6: // [E]SI
this.regESI = (this.regESI & ~this.dataMask) | dst; this.regESI = (this.regESI & ~this.maskData) | dst;
break; break;
case 0x7: // [E]DI case 0x7: // [E]DI
this.regEDI = (this.regEDI & ~this.dataMask) | dst; this.regEDI = (this.regEDI & ~this.maskData) | dst;
break; break;
default: default:
break; // there IS no other case, but JavaScript inspections don't know that break; // there IS no other case, but JavaScript inspections don't know that
@ -3581,7 +3581,7 @@ X86.fnXORb = function XORb(dst, src)
X86.fnXORw = function XORw(dst, src) X86.fnXORw = function XORw(dst, src)
{ {
this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR); this.nStepCycles -= (this.regEAWrite === X86.ADDR_INVALID? (this.regEA === X86.ADDR_INVALID? this.cycleCounts.nOpCyclesArithRR : this.cycleCounts.nOpCyclesArithRM) : this.cycleCounts.nOpCyclesArithMR);
return this.setLogicResult(dst ^ src, this.dataType); return this.setLogicResult(dst ^ src, this.typeData);
}; };
/** /**
@ -3734,7 +3734,7 @@ X86.fnFault = function(nFault, nError, fHalt, nCycles)
*/ */
this.setIP(this.opLIP - this.segCS.base); this.setIP(this.opLIP - this.segCS.base);
if (this.opLSP != X86.ADDR_INVALID) { if (this.opLSP != X86.ADDR_INVALID) {
this.setSP((this.regESP & ~this.segSS.addrMask) | (this.opLSP - this.segSS.base)); this.setSP((this.regESP & ~this.segSS.maskAddr) | (this.opLSP - this.segSS.base));
this.opLSP = X86.ADDR_INVALID; this.opLSP = X86.ADDR_INVALID;
} }
fDispatch = true; fDispatch = true;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1141,7 +1141,7 @@ X86.opBT = function BT()
*/ */
X86.opSHLDn = function SHLDn() X86.opSHLDn = function SHLDn()
{ {
this.aOpModMemWord[this.getIPByte()].call(this, this.dataSize == 2? X86.fnSHLDwi : X86.fnSHLDdi); this.aOpModMemWord[this.getIPByte()].call(this, this.sizeData == 2? X86.fnSHLDwi : X86.fnSHLDdi);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7); this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7);
}; };
@ -1154,7 +1154,7 @@ X86.opSHLDn = function SHLDn()
*/ */
X86.opSHLDcl = function SHLDcl() X86.opSHLDcl = function SHLDcl()
{ {
this.aOpModMemWord[this.getIPByte()].call(this, this.dataSize == 2? X86.fnSHLDwCL : X86.fnSHLDdCL); this.aOpModMemWord[this.getIPByte()].call(this, this.sizeData == 2? X86.fnSHLDwCL : X86.fnSHLDdCL);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7); this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7);
}; };
@ -1208,7 +1208,7 @@ X86.opBTS = function BTS()
*/ */
X86.opSHRDn = function SHRDn() X86.opSHRDn = function SHRDn()
{ {
this.aOpModMemWord[this.getIPByte()].call(this, this.dataSize == 2? X86.fnSHRDwi : X86.fnSHRDdi); this.aOpModMemWord[this.getIPByte()].call(this, this.sizeData == 2? X86.fnSHRDwi : X86.fnSHRDdi);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7); this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7);
}; };
@ -1221,7 +1221,7 @@ X86.opSHRDn = function SHRDn()
*/ */
X86.opSHRDcl = function SHRDcl() X86.opSHRDcl = function SHRDcl()
{ {
this.aOpModMemWord[this.getIPByte()].call(this, this.dataSize == 2? X86.fnSHRDwCL : X86.fnSHRDdCL); this.aOpModMemWord[this.getIPByte()].call(this, this.sizeData == 2? X86.fnSHRDwCL : X86.fnSHRDdCL);
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7); this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 3 : 7);
}; };
@ -1234,7 +1234,7 @@ X86.opSHRDcl = function SHRDcl()
*/ */
X86.opIMUL = function IMUL() X86.opIMUL = function IMUL()
{ {
this.aOpModRegWord[this.getIPByte()].call(this, this.dataSize == 2? X86.fnIMULrw : X86.fnIMULrd); this.aOpModRegWord[this.getIPByte()].call(this, this.sizeData == 2? X86.fnIMULrw : X86.fnIMULrd);
}; };
/** /**
@ -1333,31 +1333,31 @@ X86.opMOVZXb = function MOVZXb()
this.aOpModRegByte[bModRM].call(this, X86.fnMOVX); this.aOpModRegByte[bModRM].call(this, X86.fnMOVX);
switch(reg) { switch(reg) {
case 0x0: case 0x0:
this.regEAX = (this.regEAX & ~this.dataMask) | (this.regEAX & 0xff); this.regEAX = (this.regEAX & ~this.maskData) | (this.regEAX & 0xff);
break; break;
case 0x1: case 0x1:
this.regECX = (this.regECX & ~this.dataMask) | (this.regECX & 0xff); this.regECX = (this.regECX & ~this.maskData) | (this.regECX & 0xff);
break; break;
case 0x2: case 0x2:
this.regEDX = (this.regEDX & ~this.dataMask) | (this.regEDX & 0xff); this.regEDX = (this.regEDX & ~this.maskData) | (this.regEDX & 0xff);
break; break;
case 0x3: case 0x3:
this.regEBX = (this.regEBX & ~this.dataMask) | (this.regEBX & 0xff); this.regEBX = (this.regEBX & ~this.maskData) | (this.regEBX & 0xff);
break; break;
case 0x4: case 0x4:
this.regESP = (this.regESP & ~this.dataMask) | ((this.regEAX >> 8) & 0xff); this.regESP = (this.regESP & ~this.maskData) | ((this.regEAX >> 8) & 0xff);
this.regEAX = temp; this.regEAX = temp;
break; break;
case 0x5: case 0x5:
this.regEBP = (this.regEBP & ~this.dataMask) | ((this.regECX >> 8) & 0xff); this.regEBP = (this.regEBP & ~this.maskData) | ((this.regECX >> 8) & 0xff);
this.regECX = temp; this.regECX = temp;
break; break;
case 0x6: case 0x6:
this.regESI = (this.regESI & ~this.dataMask) | ((this.regEDX >> 8) & 0xff); this.regESI = (this.regESI & ~this.maskData) | ((this.regEDX >> 8) & 0xff);
this.regEDX = temp; this.regEDX = temp;
break; break;
case 0x7: case 0x7:
this.regEDI = (this.regEDI & ~this.dataMask) | ((this.regEBX >> 8) & 0xff); this.regEDI = (this.regEDI & ~this.maskData) | ((this.regEBX >> 8) & 0xff);
this.regEBX = temp; this.regEBX = temp;
break; break;
} }
@ -1493,31 +1493,31 @@ X86.opMOVSXb = function MOVSXb()
this.aOpModRegByte[bModRM].call(this, X86.fnMOVX); this.aOpModRegByte[bModRM].call(this, X86.fnMOVX);
switch(reg) { switch(reg) {
case 0x0: case 0x0:
this.regEAX = (this.regEAX & ~this.dataMask) | ((((this.regEAX & 0xff) << 24) >> 24) & this.dataMask); this.regEAX = (this.regEAX & ~this.maskData) | ((((this.regEAX & 0xff) << 24) >> 24) & this.maskData);
break; break;
case 0x1: case 0x1:
this.regECX = (this.regECX & ~this.dataMask) | ((((this.regECX & 0xff) << 24) >> 24) & this.dataMask); this.regECX = (this.regECX & ~this.maskData) | ((((this.regECX & 0xff) << 24) >> 24) & this.maskData);
break; break;
case 0x2: case 0x2:
this.regEDX = (this.regEDX & ~this.dataMask) | ((((this.regEDX & 0xff) << 24) >> 24) & this.dataMask); this.regEDX = (this.regEDX & ~this.maskData) | ((((this.regEDX & 0xff) << 24) >> 24) & this.maskData);
break; break;
case 0x3: case 0x3:
this.regEBX = (this.regEBX & ~this.dataMask) | ((((this.regEBX & 0xff) << 24) >> 24) & this.dataMask); this.regEBX = (this.regEBX & ~this.maskData) | ((((this.regEBX & 0xff) << 24) >> 24) & this.maskData);
break; break;
case 0x4: case 0x4:
this.regESP = (this.regESP & ~this.dataMask) | (((this.regEAX << 16) >> 24) & this.dataMask); this.regESP = (this.regESP & ~this.maskData) | (((this.regEAX << 16) >> 24) & this.maskData);
this.regEAX = temp; this.regEAX = temp;
break; break;
case 0x5: case 0x5:
this.regEBP = (this.regEBP & ~this.dataMask) | (((this.regECX << 16) >> 24) & this.dataMask); this.regEBP = (this.regEBP & ~this.maskData) | (((this.regECX << 16) >> 24) & this.maskData);
this.regECX = temp; this.regECX = temp;
break; break;
case 0x6: case 0x6:
this.regESI = (this.regESI & ~this.dataMask) | (((this.regEDX << 16) >> 24) & this.dataMask); this.regESI = (this.regESI & ~this.maskData) | (((this.regEDX << 16) >> 24) & this.maskData);
this.regEDX = temp; this.regEDX = temp;
break; break;
case 0x7: case 0x7:
this.regEDI = (this.regEDI & ~this.dataMask) | (((this.regEBX << 16) >> 24) & this.dataMask); this.regEDI = (this.regEDI & ~this.maskData) | (((this.regEBX << 16) >> 24) & this.maskData);
this.regEBX = temp; this.regEBX = temp;
break; break;
} }

File diff suppressed because it is too large Load diff

View file

@ -94,8 +94,8 @@ function X86Seg(cpu, id, sName, fProt)
this.ext = 0; this.ext = 0;
this.cpl = this.dpl = 0; this.cpl = this.dpl = 0;
this.addrDesc = X86.ADDR_INVALID; this.addrDesc = X86.ADDR_INVALID;
this.dataSize = this.addrSize = 2; this.sizeData = this.sizeAddr = 2;
this.dataMask = this.addrMask = 0xffff; this.maskData = this.maskAddr = 0xffff;
this.loadV86 = this.loadReal; this.loadV86 = this.loadReal;
this.checkReadV86 = this.checkReadReal; this.checkReadV86 = this.checkReadReal;
@ -1215,10 +1215,10 @@ X86Seg.prototype.save = function()
this.cpl, this.cpl,
this.dpl, this.dpl,
this.addrDesc, this.addrDesc,
this.addrSize, this.sizeAddr,
this.addrMask, this.maskAddr,
this.dataSize, this.sizeData,
this.dataMask, this.maskData,
this.type, this.type,
this.offMax this.offMax
]; ];
@ -1248,10 +1248,10 @@ X86Seg.prototype.restore = function(a)
this.cpl = a[6]; this.cpl = a[6];
this.dpl = a[7]; this.dpl = a[7];
this.addrDesc = a[8]; this.addrDesc = a[8];
this.addrSize = a[9] || 2; this.sizeAddr = a[9] || 2;
this.addrMask = a[10] || 0xffff; this.maskAddr = a[10] || 0xffff;
this.dataSize = a[11] || 2; this.sizeData = a[11] || 2;
this.dataMask = a[12] || 0xffff; this.maskData = a[12] || 0xffff;
this.type = a[13] || (this.acc & X86.DESC.ACC.TYPE.MASK); this.type = a[13] || (this.acc & X86.DESC.ACC.TYPE.MASK);
this.offMax = a[14] || (this.limit >>> 0) + 1; this.offMax = a[14] || (this.limit >>> 0) + 1;
} }
@ -1301,11 +1301,11 @@ X86Seg.prototype.updateMode = function(fLoad, fProt, fV86)
* remain set to whatever was in effect in protected-mode. * remain set to whatever was in effect in protected-mode.
*/ */
this.cpl = this.dpl = 3; this.cpl = this.dpl = 3;
this.dataSize = this.addrSize = 2; this.sizeData = this.sizeAddr = 2;
this.dataMask = this.addrMask = 0xffff; this.maskData = this.maskAddr = 0xffff;
this.limit = 0xffff; this.limit = 0xffff;
this.offMax = this.limit + 1; this.offMax = this.limit + 1;
this.addrSize = this.dataSize; this.sizeAddr = this.sizeData;
this.addrDesc = X86.ADDR_INVALID; this.addrDesc = X86.ADDR_INVALID;
this.fStackSwitch = false; this.fStackSwitch = false;
return; return;
@ -1376,14 +1376,14 @@ X86Seg.prototype.updateMode = function(fLoad, fProt, fV86)
this.cpl = this.sel & X86.SEL.RPL; this.cpl = this.sel & X86.SEL.RPL;
this.dpl = (this.acc & X86.DESC.ACC.DPL.MASK) >> X86.DESC.ACC.DPL.SHIFT; this.dpl = (this.acc & X86.DESC.ACC.DPL.MASK) >> X86.DESC.ACC.DPL.SHIFT;
if (this.cpu.model < X86.MODEL_80386 || !(this.ext & X86.DESC.EXT.BIG)) { if (this.cpu.model < X86.MODEL_80386 || !(this.ext & X86.DESC.EXT.BIG)) {
this.dataSize = 2; this.sizeData = 2;
this.dataMask = 0xffff; this.maskData = 0xffff;
} else { } else {
this.dataSize = 4; this.sizeData = 4;
this.dataMask = (0xffffffff|0); this.maskData = (0xffffffff|0);
} }
this.addrSize = this.dataSize; this.sizeAddr = this.sizeData;
this.addrMask = this.dataMask; this.maskAddr = this.maskData;
} }
return; return;
} }