Some improvements for FOOTBALL, including support for the 386 LOADALL instruction

This commit is contained in:
Jeff Parsons 2016-01-28 22:22:36 -08:00
commit a5b9e0cae7
27 changed files with 4431 additions and 3981 deletions

View file

@ -554,11 +554,12 @@ X86.fnCALLw = function(dst, src)
X86.fnCALLF = function(off, sel)
{
/*
* Since we always push the return address AFTER calling setCSIP(), and since either push could trigger
* Since we always push the return address AFTER calling setCSIP(), and since either push could trigger a
* fault (eg, segment fault, page fault, etc), we must not only snapshot regLSP into opLSP, but also the
* current CS into opCS, so that fnFault() can always make CALLF restartable.
* current CS into opCS, so that fnFault() can always make CALLF restartable. Ditto for opSS and the SS register.
*/
this.opCS = this.getCS();
this.opSS = this.getSS();
this.opLSP = this.regLSP;
var oldIP = this.getIP();
var oldSize = (I386? this.sizeData : 2);
@ -572,7 +573,7 @@ X86.fnCALLF = function(off, sel)
this.pushData(oldIP, oldSize, oldSize);
}
this.opLSP = X86.ADDR_INVALID;
this.opCS = -1;
this.opCS = this.opSS = -1;
};
/**
@ -3942,8 +3943,7 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
* Prior to each new burst of instructions, stepCPU() sets fComplete to true, and the only (normal) way
* for fComplete to become false is through stopCPU(), which isn't ordinarily called, except by the Debugger.
*/
this.resetSizes();
this.setIP(this.opLIP - this.segCS.base);
this.setLIP(this.opLIP);
}
else if (this.model >= X86.MODEL_80186) {
@ -3951,16 +3951,24 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
if (this.nFault < 0) {
/*
* Single-fault (error code is passed through, and the responsible instruction is restartable;
* the call to resetSizes() is critical, otherwise setIP() may update IP with the wrong size if
* the current instruction contains an OPERAND size override).
* Single-fault (error code is passed through, and the responsible instruction is restartable.
*/
this.resetSizes();
if (this.opCS != -1) {
/*
* HACK: We must slam 3 into this.segCS.cpl to ensure that loading the original CS segment doesn't
* fail. For example, if we faulted in the middle of a ring transition that loaded CS with a higher
* privilege (lower CPL) code segment, then our attempt here to reload the lower privilege (higher CPL)
* code segment could be viewed as a privilege violation (which it would be outside this context).
*/
this.segCS.cpl = 3;
this.setCS(this.opCS);
this.opCS = -1;
}
this.setIP(this.opLIP - this.segCS.base);
this.setLIP(this.opLIP);
if (this.opSS != -1) {
this.setSS(this.opSS);
this.opSS = -1;
}
if (this.opLSP !== X86.ADDR_INVALID) {
this.setSP((this.regESP & ~this.segSS.maskAddr) | (this.opLSP - this.segSS.base));
this.opLSP = X86.ADDR_INVALID;
@ -3970,22 +3978,24 @@ X86.fnFault = function(nFault, nError, nCycles, fHalt)
/*
* Double-fault (error code is always zero, and the responsible instruction is not restartable)
*/
nError = 0; nFault = X86.EXCEPTION.DF_FAULT;
nError = 0;
nFault = X86.EXCEPTION.DF_FAULT;
}
else {
/*
* Triple-fault (usually referred to in Intel literature as a "shutdown", but at least on the 80286,
* it's actually a "reset")
*/
nFault = -1; nError = 0;
nError = 0;
nFault = -1;
this.resetRegs();
fDispatch = fHalt = false;
}
}
if (X86.fnFaultMessage.call(this, nFault, nError, fHalt)) {
if (X86.fnCheckFault.call(this, nFault, nError, fHalt)) {
/*
* If this is a fault that would normally be dispatched BUT fnFaultMessage() wants us to halt,
* If this is a fault that would normally be dispatched BUT fnCheckFault() 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.
*/
@ -4060,7 +4070,7 @@ X86.fnPageFault = function(addr, fPresent, fWrite)
};
/**
* fnFaultMessage(nFault, nError, fHalt)
* fnCheckFault(nFault, nError, fHalt)
*
* Aside from giving the Debugger an opportunity to report every fault, this also gives us the ability to
* halt exception processing in tracks: return true to prevent the fault handler from being dispatched.
@ -4076,7 +4086,7 @@ X86.fnPageFault = function(addr, fPresent, fWrite)
* @param {boolean} [fHalt] (true to halt the CPU, false to not, undefined if "it depends")
* @return {boolean|undefined} true to block the fault (often desirable when fHalt is true), otherwise dispatch it
*/
X86.fnFaultMessage = function(nFault, nError, fHalt)
X86.fnCheckFault = function(nFault, nError, fHalt)
{
var bitsMessage = Messages.FAULT;