When halting on faults in the Debugger, interrupt the instruction in the same manner as the actual fault would

This commit is contained in:
Jeff Parsons 2016-01-27 13:04:52 -08:00
commit 763b02794b
2 changed files with 53 additions and 65 deletions

View file

@ -360,7 +360,6 @@ X86.fnBTMem = function(dst, src)
if (this.regEA === X86.ADDR_INVALID) {
return X86.fnBT.call(this, dst, src);
}
/*
* TODO: Consider a worker function that performs the following block of code for: BT, BTC, BTR, and BTS.
* It's somewhat inconvenient, because it needs to provide two results: an updated src AND an updated dst.
@ -409,7 +408,6 @@ X86.fnBTCMem = function(dst, src)
if (this.regEA === X86.ADDR_INVALID) {
return X86.fnBTC.call(this, dst, src);
}
/*
* src is usually positive BUT can also be negative (as the IA32 spec says: "The offset operand then selects
* a bit position within the range 231 to 231 1 for a register offset and 0 to 31 for an immediate offset.")
@ -451,7 +449,6 @@ X86.fnBTRMem = function(dst, src)
if (this.regEA === X86.ADDR_INVALID) {
return X86.fnBTR.call(this, dst, src);
}
/*
* src is usually positive BUT can also be negative (as the IA32 spec says: "The offset operand then selects
* a bit position within the range 231 to 231 1 for a register offset and 0 to 31 for an immediate offset.")
@ -493,7 +490,6 @@ X86.fnBTSMem = function(dst, src)
if (this.regEA === X86.ADDR_INVALID) {
return X86.fnBTS.call(this, dst, src);
}
/*
* src is usually positive BUT can also be negative (as the IA32 spec says: "The offset operand then selects
* a bit position within the range 231 to 231 1 for a register offset and 0 to 31 for an immediate offset.")
@ -3939,7 +3935,7 @@ X86.fnTrap = function(nIDT, nCycles)
*/
X86.fnFault = function(nFault, nError, nCycles, fHalt)
{
var fDispatch = null;
var fDispatch = false;
if (!this.aFlags.fComplete) {
/*
@ -3950,6 +3946,9 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
this.setIP(this.opLIP - this.segCS.base);
}
else if (this.model >= X86.MODEL_80186) {
fDispatch = true;
if (this.nFault < 0) {
/*
* Single-fault (error code is passed through, and the responsible instruction is restartable;
@ -3966,14 +3965,12 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
this.setSP((this.regESP & ~this.segSS.maskAddr) | (this.opLSP - this.segSS.base));
this.opLSP = X86.ADDR_INVALID;
}
fDispatch = true;
}
else if (this.nFault != X86.EXCEPTION.DF_FAULT) {
/*
* Double-fault (error code is always zero, and the responsible instruction is not restartable)
*/
nError = 0; nFault = X86.EXCEPTION.DF_FAULT;
fDispatch = true;
}
else {
/*
@ -3982,12 +3979,17 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
*/
nFault = -1; nError = 0;
this.resetRegs();
fHalt = false;
fDispatch = fHalt = false;
}
}
if (X86.fnFaultMessage.call(this, nFault, nError, fHalt)) {
fDispatch = false;
/*
* If this is a fault that would normally be dispatched BUT fnFaultMessage() wants us to halt,
* then we throw a bogus fault number (-1), simply to interrupt the current instruction in exactly
* the same way that a dispatched fault would interrupt it.
*/
if (fDispatch) throw -1;
}
if (fDispatch) {

View file

@ -1652,12 +1652,11 @@ X86.opINSb = function()
if (!this.checkIOPM(port, 1, true)) return;
var b = this.bus.checkPortInputNotify(port, 1, this.regLIP - nDelta - 1);
this.setSOByte(this.segES, this.regEDI & maskAddr, b);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
if (BACKTRACK) this.backTrack.btiMem0 = this.backTrack.btiIO;
this.regEDI = (this.regEDI & ~maskAddr) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -1 : 1)) & maskAddr);
this.regECX = (this.regECX & ~maskAddr) | ((this.regECX - nDelta) & maskAddr);
@ -1706,12 +1705,11 @@ X86.opINSw = function()
this.backTrack.btiMem1 = this.backTrack.btiIO;
}
this.setSOWord(this.segES, this.regEDI & maskAddr, w);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
this.regEDI = (this.regEDI & ~maskAddr) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -this.sizeData : this.sizeData)) & maskAddr);
this.regECX = (this.regECX & ~maskAddr) | ((this.regECX - nDelta) & maskAddr);
this.nStepCycles -= nCycles;
@ -1753,12 +1751,11 @@ X86.opOUTSb = function()
var port = this.regEDX & 0xffff;
if (!this.checkIOPM(port, 1, false)) return;
var b = this.getSOByte(this.segDS, this.regESI & maskAddr);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
if (BACKTRACK) this.backTrack.btiIO = this.backTrack.btiMem0;
this.bus.checkPortOutputNotify(port, 1, b, this.regLIP - nDelta - 1);
this.regESI = (this.regESI & ~maskAddr) | ((this.regESI + ((this.regPS & X86.PS.DF)? -1 : 1)) & maskAddr);
@ -1800,12 +1797,11 @@ X86.opOUTSw = function()
}
if (nReps--) {
var w = this.getSOWord(this.segDS, this.regESI & maskAddr);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
var port = this.regEDX & 0xffff;
if (!this.checkIOPM(port, this.sizeData, false)) return;
if (BACKTRACK) {
@ -2803,12 +2799,11 @@ X86.opMOVSb = function()
}
if (nReps--) {
this.setSOByte(this.segES, this.regEDI & maskAddr, this.getSOByte(this.segData, this.regESI & maskAddr));
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
var nInc = ((this.regPS & X86.PS.DF)? -1 : 1);
this.regESI = (this.regESI & ~maskAddr) | ((this.regESI + nInc) & maskAddr);
this.regEDI = (this.regEDI & ~maskAddr) | ((this.regEDI + nInc) & maskAddr);
@ -2841,12 +2836,11 @@ X86.opMOVSw = function()
}
if (nReps--) {
this.setSOWord(this.segES, this.regEDI & maskAddr, this.getSOWord(this.segData, this.regESI & maskAddr));
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
var nInc = ((this.regPS & X86.PS.DF)? -this.sizeData : this.sizeData);
this.regESI = (this.regESI & ~maskAddr) | ((this.regESI + nInc) & maskAddr);
this.regEDI = (this.regEDI & ~maskAddr) | ((this.regEDI + nInc) & maskAddr);
@ -2880,12 +2874,11 @@ X86.opCMPSb = function()
if (nReps--) {
var bDst = this.getEAByte(this.segData, this.regESI & maskAddr);
var bSrc = this.modEAByte(this.segES, this.regEDI & maskAddr);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
X86.fnCMPb.call(this, bDst, bSrc);
var nInc = ((this.regPS & X86.PS.DF)? -1 : 1);
this.regESI = (this.regESI & ~maskAddr) | ((this.regESI + nInc) & maskAddr);
@ -2928,12 +2921,11 @@ X86.opCMPSw = function()
if (nReps--) {
var wDst = this.getEAWord(this.segData, this.regESI & maskAddr);
var wSrc = this.modEAWord(this.segES, this.regEDI & maskAddr);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
X86.fnCMPw.call(this, wDst, wSrc);
var nInc = ((this.regPS & X86.PS.DF)? -this.sizeData : this.sizeData);
this.regESI = (this.regESI & ~maskAddr) | ((this.regESI + nInc) & maskAddr);
@ -2999,12 +2991,11 @@ X86.opSTOSb = function()
}
if (nReps--) {
this.setSOByte(this.segES, this.regEDI & maskAddr, this.regEAX);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
if (BACKTRACK) this.backTrack.btiMem0 = this.backTrack.btiAL;
this.regECX = (this.regECX & ~maskAddr) | ((this.regECX - nDelta) & maskAddr);
@ -3058,12 +3049,11 @@ X86.opSTOSw = function()
}
if (nReps--) {
this.setSOWord(this.segES, this.regEDI & maskAddr, this.regEAX);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
if (BACKTRACK) {
this.backTrack.btiMem0 = this.backTrack.btiAL; this.backTrack.btiMem1 = this.backTrack.btiAH;
}
@ -3097,12 +3087,11 @@ X86.opLODSb = function()
}
if (nReps--) {
var b = this.getSOByte(this.segData, this.regESI & maskAddr);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
this.regEAX = (this.regEAX & ~0xff) | b;
if (BACKTRACK) this.backTrack.btiAL = this.backTrack.btiMem0;
this.regESI = (this.regESI & ~maskAddr) | ((this.regESI + ((this.regPS & X86.PS.DF)? -1 : 1)) & maskAddr);
@ -3135,12 +3124,11 @@ X86.opLODSw = function()
}
if (nReps--) {
var w = this.getSOWord(this.segData, this.regESI & maskAddr);
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
this.regEAX = (this.regEAX & ~this.maskData) | w;
if (BACKTRACK) {
this.backTrack.btiAL = this.backTrack.btiMem0; this.backTrack.btiAH = this.backTrack.btiMem1;
@ -3175,12 +3163,11 @@ X86.opSCASb = function()
}
if (nReps--) {
X86.fnCMPb.call(this, this.regEAX & 0xff, this.modEAByte(this.segES, this.regEDI & maskAddr));
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
this.regEDI = (this.regEDI & ~maskAddr) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -1 : 1)) & maskAddr);
this.regECX = (this.regECX & ~maskAddr) | ((this.regECX - nDelta) & maskAddr);
/*
@ -3219,12 +3206,11 @@ X86.opSCASw = function()
}
if (nReps--) {
X86.fnCMPw.call(this, this.regEAX & this.maskData, this.modEAWord(this.segES, this.regEDI & maskAddr));
/*
* TODO: Remove this once we've done enough testing of fnFault() throwing exceptions
* fnFault() throws exceptions now, so inline checks of X86.OPFLAG.FAULT should no longer be necessary.
*
* if (this.opFlags & X86.OPFLAG.FAULT) return;
*/
if (this.opFlags & X86.OPFLAG.FAULT) return;
this.regEDI = (this.regEDI & ~maskAddr) | ((this.regEDI + ((this.regPS & X86.PS.DF)? -this.sizeData : this.sizeData)) & maskAddr);
this.regECX = (this.regECX & ~maskAddr) | ((this.regECX - nDelta) & maskAddr);
/*