Improvements to code and stack limit checks (still not perfect, but better)
This commit is contained in:
parent
5f29c9967b
commit
cfd02bb4ae
4 changed files with 138 additions and 74 deletions
|
|
@ -1821,8 +1821,8 @@ X86CPU.prototype.getCS = function()
|
|||
X86CPU.prototype.setCS = function(sel)
|
||||
{
|
||||
var regEIP = this.getIP();
|
||||
this.regLIP = this.segCS.load(sel) + regEIP;
|
||||
this.regLIPLimit = this.segCS.base + this.segCS.limit;
|
||||
this.regLIP = (this.segCS.load(sel) + regEIP)|0;
|
||||
this.regLIPLimit = (this.segCS.base + this.segCS.limit)|0;
|
||||
if (I386) this.resetSizes();
|
||||
if (!BUGS_8086) this.opFlags |= this.OPFLAG_NOINTR_8086;
|
||||
if (PREFETCH) this.flushPrefetch(this.regLIP);
|
||||
|
|
@ -1872,12 +1872,12 @@ X86CPU.prototype.getSS = function()
|
|||
X86CPU.prototype.setSS = function(sel, fInterruptable)
|
||||
{
|
||||
var regESP = this.getSP();
|
||||
this.regLSP = this.segSS.load(sel) + regESP;
|
||||
this.regLSP = (this.segSS.load(sel) + regESP)|0;
|
||||
if (this.segSS.fExpDown) {
|
||||
this.regLSPLimit = this.segSS.base + this.segSS.addrMask;
|
||||
this.regLSPLimitLow = this.segSS.base + this.segSS.limit;
|
||||
this.regLSPLimit = (this.segSS.base + this.segSS.addrMask)|0;
|
||||
this.regLSPLimitLow = (this.segSS.base + this.segSS.limit)|0;
|
||||
} else {
|
||||
this.regLSPLimit = this.segSS.base + this.segSS.limit;
|
||||
this.regLSPLimit = (this.segSS.base + this.segSS.limit)|0;
|
||||
this.regLSPLimitLow = this.segSS.base;
|
||||
}
|
||||
if (!BUGS_8086 && !fInterruptable) this.opFlags |= X86.OPFLAG.NOINTR;
|
||||
|
|
@ -1966,7 +1966,7 @@ X86CPU.prototype.setGS = function(sel)
|
|||
*/
|
||||
X86CPU.prototype.getIP = function()
|
||||
{
|
||||
return this.regLIP - this.segCS.base;
|
||||
return (this.regLIP - this.segCS.base)|0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1983,7 +1983,7 @@ X86CPU.prototype.getIP = function()
|
|||
*/
|
||||
X86CPU.prototype.setIP = function(off)
|
||||
{
|
||||
this.regLIP = this.segCS.base + (off & (I386? this.dataMask : 0xffff));
|
||||
this.regLIP = (this.segCS.base + (off & (I386? this.dataMask : 0xffff)))|0;
|
||||
if (PREFETCH) this.flushPrefetch(this.regLIP);
|
||||
};
|
||||
|
||||
|
|
@ -2018,8 +2018,8 @@ X86CPU.prototype.setCSIP = function(off, sel, fCall)
|
|||
this.regEIP = off;
|
||||
var base = this.segCS.load(sel);
|
||||
if (base !== X86.ADDR_INVALID) {
|
||||
this.regLIP = base + (this.regEIP & (I386? this.dataMask : 0xffff));
|
||||
this.regLIPLimit = base + this.segCS.limit;
|
||||
this.regLIP = (base + (this.regEIP & (I386? this.dataMask : 0xffff)))|0;
|
||||
this.regLIPLimit = (base + this.segCS.limit)|0;
|
||||
if (I386) this.resetSizes();
|
||||
if (PREFETCH) this.flushPrefetch(this.regLIP);
|
||||
return this.segCS.fStackSwitch;
|
||||
|
|
@ -2039,23 +2039,76 @@ X86CPU.prototype.setCSBase = function(addr)
|
|||
{
|
||||
var regIP = this.getIP();
|
||||
addr = this.segCS.setBase(addr);
|
||||
this.regLIP = addr + regIP;
|
||||
this.regLIPLimit = addr + this.segCS.limit;
|
||||
this.regLIP = (addr + regIP)|0;
|
||||
this.regLIPLimit = (addr + this.segCS.limit)|0;
|
||||
};
|
||||
|
||||
/**
|
||||
* advanceIP(inc)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} inc (may be +/-)
|
||||
* @param {number} inc (positive)
|
||||
*/
|
||||
X86CPU.prototype.advanceIP = function(inc)
|
||||
{
|
||||
this.regLIP += inc;
|
||||
if (this.regLIP <= this.regLIPLimit) {
|
||||
if (PREFETCH) this.advancePrefetch(inc);
|
||||
} else {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
this.assert(inc > 0);
|
||||
this.regLIP = (this.regLIP + inc)|0;
|
||||
/*
|
||||
* Properly comparing regLIP to regLIPLimit would normally require coercing both to unsigned
|
||||
* (ie, floating-point) values. But instead, we do a subtraction, (regLIPLimit - regLIP), and
|
||||
* if the result is negative, we need only be concerned if the signs of both numbers are the same
|
||||
* (ie, the sign of their XOR'ed union is positive).
|
||||
*
|
||||
* TODO: I'm combining the old 8088 address-wrap check with the new segment-limit check,
|
||||
* even though the correct time to do the latter is immediately BEFORE a fetch, not AFTER; eg,
|
||||
* consider the following code:
|
||||
*
|
||||
* AX=0100 BX=0015 CX=0080 DX=F859 SP=0A62 BP=0A98 SI=0000 DI=0000
|
||||
* SS=0038[1759E0,0B5F] DS=02E8[0107A0,017F] ES=0970[009700,6949] A20=ON
|
||||
* CS=02E0[010080,06FB] LD=0028[000000,0000] GD=[11AEE0,4977] ID=[120082,03FF]
|
||||
* TR=0010 MS=FFF3 PS=3202 V0 D0 I1 T0 S0 Z0 A0 P0 C0
|
||||
* 02E0:06F9 C20400 RET 0004
|
||||
*
|
||||
* After fetching the 3rd byte of the "RET 0004" opcode at CS:06FB, the CPU wants to automatically
|
||||
* advance IP to 06FC, which of course, exceeds the limit, but that doesn't matter unless we actually
|
||||
* fetch a byte from 06FC, which won't happen. I'm working around this for now by applying a -1
|
||||
* fudge factor to the fault check.
|
||||
*/
|
||||
var off = (this.regLIPLimit - this.regLIP)|0;
|
||||
if (off < 0 && (this.regLIPLimit ^ this.regLIP) >= 0) {
|
||||
if (this.model <= X86.MODEL_8088) {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
} else if (off < -1) { // fudge factor
|
||||
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* rewindIP(dec)
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} dec (negative)
|
||||
*/
|
||||
X86CPU.prototype.rewindIP = function(dec)
|
||||
{
|
||||
this.assert(dec < 0);
|
||||
this.regLIP = (this.regLIP + dec)|0;
|
||||
/*
|
||||
* Properly comparing regLIP to regLIPLimit would normally require coercing both to unsigned
|
||||
* (ie, floating-point) values. But instead, we do a subtraction, (regLIPLimit - regLIP), and
|
||||
* if the result is negative, we need only be concerned if the signs of both numbers are the same
|
||||
* (ie, the sign of their XOR'ed union is positive).
|
||||
*/
|
||||
if (((this.regLIPLimit - this.regLIP)|0) >= 0) {
|
||||
if (PREFETCH) this.advancePrefetch(dec);
|
||||
}
|
||||
else if ((this.regLIPLimit ^ this.regLIP) >= 0) {
|
||||
if (this.model <= X86.MODEL_8088) {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
} else {
|
||||
X86.fnFault.call(this, X86.EXCEPTION.GP_FAULT, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2071,7 +2124,7 @@ X86CPU.prototype.getSP = function()
|
|||
this.assert(!((this.regLSP - this.segSS.base) & ~this.segSS.addrMask));
|
||||
return (this.regESP & ~this.segSS.addrMask) | (this.regLSP - this.segSS.base);
|
||||
}
|
||||
return this.regLSP - this.segSS.base;
|
||||
return (this.regLSP - this.segSS.base)|0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2084,9 +2137,9 @@ X86CPU.prototype.setSP = function(off)
|
|||
{
|
||||
if (I386) {
|
||||
this.regESP = off;
|
||||
this.regLSP = this.segSS.base + (off & this.segSS.addrMask);
|
||||
this.regLSP = (this.segSS.base + (off & this.segSS.addrMask))|0;
|
||||
} else {
|
||||
this.regLSP = this.segSS.base + off;
|
||||
this.regLSP = (this.segSS.base + off)|0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -3366,9 +3419,7 @@ X86CPU.prototype.getIPByte = function()
|
|||
{
|
||||
var b = (PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP));
|
||||
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
if (++this.regLIP > this.regLIPLimit) {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
}
|
||||
this.advanceIP(1);
|
||||
return b;
|
||||
};
|
||||
|
||||
|
|
@ -3385,10 +3436,7 @@ X86CPU.prototype.getIPShort = function()
|
|||
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMemHi);
|
||||
}
|
||||
this.regLIP += 2;
|
||||
if (this.regLIP > this.regLIPLimit) {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
}
|
||||
this.advanceIP(2);
|
||||
return w;
|
||||
};
|
||||
|
||||
|
|
@ -3405,10 +3453,7 @@ X86CPU.prototype.getIPLong = function()
|
|||
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMemHi);
|
||||
}
|
||||
this.regLIP += 4;
|
||||
if (this.regLIP > this.regLIPLimit) {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
}
|
||||
this.advanceIP(4);
|
||||
return l;
|
||||
};
|
||||
|
||||
|
|
@ -3428,10 +3473,7 @@ X86CPU.prototype.getIPAddr = function()
|
|||
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMemHi);
|
||||
}
|
||||
this.regLIP += this.addrSize;
|
||||
if (this.regLIP > this.regLIPLimit) {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
}
|
||||
this.advanceIP(this.addrSize);
|
||||
return w;
|
||||
};
|
||||
|
||||
|
|
@ -3448,10 +3490,7 @@ X86CPU.prototype.getIPWord = function()
|
|||
this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
this.bus.updateBackTrackCode(this.regLIP + 1, this.backTrack.btiMemHi);
|
||||
}
|
||||
this.regLIP += this.dataSize;
|
||||
if (this.regLIP > this.regLIPLimit) {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
}
|
||||
this.advanceIP(this.dataSize);
|
||||
return w;
|
||||
};
|
||||
|
||||
|
|
@ -3465,9 +3504,7 @@ X86CPU.prototype.getIPDisp = function()
|
|||
{
|
||||
var w = ((PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP)) << 24) >> 24;
|
||||
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
if (++this.regLIP > this.regLIPLimit) {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
}
|
||||
this.advanceIP(1);
|
||||
return w;
|
||||
};
|
||||
|
||||
|
|
@ -3482,9 +3519,7 @@ X86CPU.prototype.getSIBAddr = function(mod)
|
|||
{
|
||||
var b = PREFETCH? this.getBytePrefetch(this.regLIP) : this.getByte(this.regLIP);
|
||||
if (BACKTRACK) this.bus.updateBackTrackCode(this.regLIP, this.backTrack.btiMemLo);
|
||||
if (++this.regLIP > this.regLIPLimit) {
|
||||
this.setIP(this.regLIP - this.segCS.base);
|
||||
}
|
||||
this.advanceIP(1);
|
||||
return X86ModSIB.aOpModSIB[b].call(this, mod);
|
||||
};
|
||||
|
||||
|
|
@ -3497,10 +3532,24 @@ X86CPU.prototype.getSIBAddr = function(mod)
|
|||
X86CPU.prototype.popWord = function()
|
||||
{
|
||||
var w = this.getWord(this.regLSP);
|
||||
this.regLSP += (I386? this.dataSize : 2);
|
||||
if (this.regLSP > this.regLSPLimit) {
|
||||
// TODO: Generate exception in protected mode
|
||||
this.setSP(this.regLSP - this.segSS.base);
|
||||
this.regLSP = (this.regLSP + (I386? this.dataSize : 2))|0;
|
||||
/*
|
||||
* 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
|
||||
* if the result is negative, we need only be concerned if the signs of both numbers are the same
|
||||
* (ie, the sign of their XOR'ed union is positive).
|
||||
*
|
||||
* TODO: I'm combining the old 8088 address-wrap check with the new segment-limit check,
|
||||
* even though the correct time to do the latter is immediately BEFORE the fetch, not AFTER;
|
||||
* I'm working around this for now by applying a -1 fudge factor to the fault check.
|
||||
*/
|
||||
var off = ((this.regLSPLimit - this.regLSP)|0);
|
||||
if (off < 0 && (this.regLSPLimit ^ this.regLSP) >= 0) {
|
||||
if (this.model <= X86.MODEL_8088) {
|
||||
this.setSP(this.regLSP - this.segSS.base);
|
||||
} else if (off < -1) { // fudge factor
|
||||
X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
|
||||
}
|
||||
}
|
||||
return w;
|
||||
};
|
||||
|
|
@ -3514,10 +3563,19 @@ X86CPU.prototype.popWord = function()
|
|||
X86CPU.prototype.pushWord = function(w)
|
||||
{
|
||||
this.assert((w & this.dataMask) == w);
|
||||
this.regLSP -= (I386? this.dataSize : 2);
|
||||
if (this.regLSP < this.regLSPLimitLow) {
|
||||
// TODO: Generate exception in protected mode (and bail)
|
||||
this.setSP(this.regLSP - this.segSS.base);
|
||||
this.regLSP = (this.regLSP - (I386? this.dataSize : 2))|0;
|
||||
/*
|
||||
* 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
|
||||
* if the result is negative, we need only be concerned if the signs of both numbers are the same
|
||||
* (ie, the sign of their XOR'ed union is positive).
|
||||
*/
|
||||
if (((this.regLSP - this.regLSPLimitLow)|0) < 0 && (this.regLSPLimitLow ^ this.regLSP) >= 0) {
|
||||
if (this.model <= X86.MODEL_8088) {
|
||||
this.setSP(this.regLSP - this.segSS.base);
|
||||
} else {
|
||||
X86.fnFault.call(this, X86.EXCEPTION.SS_FAULT, 0);
|
||||
}
|
||||
}
|
||||
this.setWord(this.regLSP, w);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1197,8 +1197,9 @@ X86.fnINCw = function INCw(dst, src)
|
|||
* only knows how to load GDT and LDT descriptors, whereas interrupts must use setCS.loadIDT(), which
|
||||
* deals exclusively with IDT descriptors.
|
||||
*
|
||||
* This means we must take care to replicate critical features of setCSIP(); eg, setting segCS.fCall
|
||||
* before calling loadIDT(), updating LIP, and flushing the prefetch queue.
|
||||
* This means we must take care to replicate critical features of setCSIP(); ie, setting segCS.fCall
|
||||
* BEFORE calling loadIDT(), and updating regLIP and regLIPLimit, resetting default operand and address sizes,
|
||||
* and flushing the prefetch queue AFTER calling loadIDT().
|
||||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} nIDT
|
||||
|
|
@ -1217,13 +1218,15 @@ X86.fnINT = function INT(nIDT, nError, nCycles)
|
|||
var oldIP = this.getIP();
|
||||
var addr = this.segCS.loadIDT(nIDT);
|
||||
if (addr !== X86.ADDR_INVALID) {
|
||||
this.regLIP = addr;
|
||||
if (PREFETCH) this.flushPrefetch(this.regLIP);
|
||||
this.pushWord(oldPS);
|
||||
this.pushWord(oldCS);
|
||||
this.pushWord(oldIP);
|
||||
if (nError != null) this.pushWord(nError);
|
||||
this.nFault = -1;
|
||||
this.regLIP = addr;
|
||||
this.regLIPLimit = (this.segCS.base + this.segCS.limit)|0;
|
||||
if (I386) this.resetSizes();
|
||||
if (PREFETCH) this.flushPrefetch(this.regLIP);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1483,7 +1483,7 @@ X86.opINSb = function INSb()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(-2); // this instruction does not support multiple overrides
|
||||
this.rewindIP(-2); // this instruction does not support multiple overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -1540,7 +1540,7 @@ X86.opINSw = function INSw()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(-2); // this instruction does not support multiple overrides
|
||||
this.rewindIP(-2); // this instruction does not support multiple overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -1585,7 +1585,7 @@ X86.opOUTSb = function OUTSb()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(-2); // this instruction does not support multiple overrides
|
||||
this.rewindIP(-2); // this instruction does not support multiple overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -1640,7 +1640,7 @@ X86.opOUTSw = function OUTSw()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(-2); // this instruction does not support multiple overrides
|
||||
this.rewindIP(-2); // this instruction does not support multiple overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2558,7 +2558,7 @@ X86.opMOVSb = function MOVSb()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.rewindIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2593,7 +2593,7 @@ X86.opMOVSw = function MOVSw()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.rewindIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2638,7 +2638,7 @@ X86.opCMPSb = function CMPSb()
|
|||
*/
|
||||
if (nReps && this.getZF() == (this.opPrefixes & X86.OPFLAG.REPZ)) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.rewindIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2683,7 +2683,7 @@ X86.opCMPSw = function CMPSw()
|
|||
*/
|
||||
if (nReps && this.getZF() == (this.opPrefixes & X86.OPFLAG.REPZ)) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.rewindIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2741,7 +2741,7 @@ X86.opSTOSb = function STOSb()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(-2); // this instruction does not support multiple overrides
|
||||
this.rewindIP(-2); // this instruction does not support multiple overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2783,7 +2783,7 @@ X86.opSTOSw = function STOSw()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(-2); // this instruction does not support multiple overrides
|
||||
this.rewindIP(-2); // this instruction does not support multiple overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2817,7 +2817,7 @@ X86.opLODSb = function LODSb()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.rewindIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2853,7 +2853,7 @@ X86.opLODSw = function LODSw()
|
|||
this.regECX = (this.regECX & ~this.addrMask) | ((this.regECX - nDelta) & this.addrMask);
|
||||
if (nReps) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.rewindIP(((this.opPrefixes & X86.OPFLAG.SEG)? -3 : -2));
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2894,7 +2894,7 @@ X86.opSCASb = function SCASb()
|
|||
*/
|
||||
if (nReps && this.getZF() == (this.opPrefixes & X86.OPFLAG.REPZ)) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(-2); // this instruction does not support multiple overrides
|
||||
this.rewindIP(-2); // this instruction does not support multiple overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -2935,7 +2935,7 @@ X86.opSCASw = function SCASw()
|
|||
*/
|
||||
if (nReps && this.getZF() == (this.opPrefixes & X86.OPFLAG.REPZ)) {
|
||||
if (BUGS_8086) {
|
||||
this.advanceIP(-2); // this instruction does not support multiple overrides
|
||||
this.rewindIP(-2); // this instruction does not support multiple overrides
|
||||
this.assert(this.regLIP == this.opLIP);
|
||||
} else {
|
||||
this.regLIP = this.opLIP;
|
||||
|
|
@ -3806,7 +3806,7 @@ X86.opHLT = function HLT()
|
|||
* on the theory that whoever's using the Debugger would like to see HLTs.
|
||||
*/
|
||||
if (DEBUGGER && this.dbg && this.messageEnabled(Messages.HALT)) {
|
||||
this.advanceIP(-1); // this is purely for the Debugger's benefit, to show the HLT
|
||||
this.rewindIP(-1); // this is purely for the Debugger's benefit, to show the HLT
|
||||
this.stopCPU();
|
||||
return;
|
||||
}
|
||||
|
|
@ -3815,7 +3815,7 @@ X86.opHLT = function HLT()
|
|||
* in the water (we have no NMI generation mechanism at the moment).
|
||||
*/
|
||||
if (!this.getIF()) {
|
||||
if (DEBUGGER && this.dbg) this.advanceIP(-1);
|
||||
if (DEBUGGER && this.dbg) this.rewindIP(-1);
|
||||
this.stopCPU();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -853,6 +853,9 @@ X86Seg.prototype.switchTSS = function switchTSS(selNew, fNest)
|
|||
* but the CS base must be set to 0x00FF0000 or 0xFFFF0000, respectively. To simplify life for setBase()
|
||||
* callers, we allow them to specify 32-bit bases, which we then truncate to 24 bits as needed.
|
||||
*
|
||||
* WARNING: Since the CPU must maintain regLIP as the sum of the CS base and the current IP, all calls
|
||||
* to segCS.setBase() need to go through setCSBase().
|
||||
*
|
||||
* @this {X86Seg}
|
||||
* @param {number} addr
|
||||
* @return {number} addr, truncated as needed
|
||||
|
|
|
|||
Loading…
Reference in a new issue