Stricter instruction restart checks, and some machine config cleanup
This commit is contained in:
parent
0d7fdbcf00
commit
6c6decc7ae
29 changed files with 1802 additions and 1215 deletions
|
|
@ -265,21 +265,28 @@ Component.subclass(ChipSet);
|
|||
*
|
||||
* Unless otherwise noted, all BIOS references refer to the *original* BIOS released with each model.
|
||||
*/
|
||||
ChipSet.MODEL_5150 = 5150; // used in reference to the 1st 5150 BIOS, dated Apr 24, 1981
|
||||
ChipSet.MODEL_5160 = 5160; // used in reference to the 1st 5160 BIOS, dated Nov 8, 1982
|
||||
ChipSet.MODEL_5170 = 5170; // used in reference to the 1st 5170 BIOS, dated Jan 10, 1984
|
||||
ChipSet.MODEL_5150 = 5150; // used in reference to the 1st 5150 BIOS, dated Apr 24, 1981
|
||||
ChipSet.MODEL_5160 = 5160; // used in reference to the 1st 5160 BIOS, dated Nov 8, 1982
|
||||
ChipSet.MODEL_5170 = 5170; // used in reference to the 1st 5170 BIOS, dated Jan 10, 1984
|
||||
|
||||
/*
|
||||
* The following are fake model numbers, used only to document issues/features in later IBM PC AT BIOS revisions.
|
||||
*/
|
||||
ChipSet.MODEL_5170_REV2 = 5170.2; // used in reference to the 2nd 5170 BIOS, dated Jun 10, 1985
|
||||
ChipSet.MODEL_5170_REV3 = 5170.3; // used in reference to the 3rd 5170 BIOS, dated Nov 15, 1985
|
||||
ChipSet.MODEL_5170_REV2 = 5170.2; // used in reference to the 2nd 5170 BIOS, dated Jun 10, 1985
|
||||
ChipSet.MODEL_5170_REV3 = 5170.3; // used in reference to the 3rd 5170 BIOS, dated Nov 15, 1985
|
||||
|
||||
/*
|
||||
* The following are even more fake model numbers, as we begin to depart from the IBM lineage. All that
|
||||
* really matters at this point is that MODEL_DESKPRO386 > MODEL_5170.
|
||||
* The following are even more fake model numbers, as we begin to depart more significantly from the IBM lineage.
|
||||
* All that really matters at this point is that MODEL_COMPAQ_DESKPRO386 > MODEL_5170.
|
||||
*/
|
||||
ChipSet.MODEL_DESKPRO386 = 5180;
|
||||
ChipSet.MODEL_COMPAQ_PORTABLE = 5150.1; // COMPAQ Portable (COMPAQ's first PC)
|
||||
ChipSet.MODEL_COMPAQ_DESKPRO386 = 5180.1; // COMPAQ DeskPro 386 (COMPAQ's first 80386-based PC)
|
||||
|
||||
/*
|
||||
* More assorted non-IBM models
|
||||
*/
|
||||
ChipSet.MODEL_CDP_MPC1600 = 5150.2; // Columbia Data Products MPC 1600
|
||||
ChipSet.MODEL_ZENITH_Z150 = 5150.3; // Zenith Data Systems Z-150
|
||||
|
||||
/*
|
||||
* Last but not least, a complete list of supported model strings, and corresponding internal model numbers.
|
||||
|
|
@ -288,7 +295,9 @@ ChipSet.MODELS = {
|
|||
"5150": ChipSet.MODEL_5150,
|
||||
"5160": ChipSet.MODEL_5160,
|
||||
"5170": ChipSet.MODEL_5170,
|
||||
"deskpro386": ChipSet.MODEL_DESKPRO386
|
||||
"deskpro386": ChipSet.MODEL_COMPAQ_DESKPRO386,
|
||||
"mpc1600": ChipSet.MODEL_CDP_MPC1600,
|
||||
"z150": ChipSet.MODEL_ZENITH_Z150
|
||||
};
|
||||
|
||||
ChipSet.CONTROLS = {
|
||||
|
|
@ -573,7 +582,7 @@ ChipSet.PIT0 = {
|
|||
};
|
||||
|
||||
ChipSet.PIT1 = {
|
||||
PORT: 0x48, // MODEL_DESKPRO386 only
|
||||
PORT: 0x48, // MODEL_COMPAQ_DESKPRO386 only
|
||||
TIMER3: 0, // used for fail-safe clock
|
||||
TIMER4: 1, // N/A
|
||||
TIMER5: 2 // used for refresher request extend/speed control
|
||||
|
|
@ -1180,8 +1189,8 @@ ChipSet.prototype.reset = function(fHard)
|
|||
* as TIMER3, TIMER4 and TIMER5; that numbering also matches their indexes in the aTimers array.
|
||||
*/
|
||||
this.bPIT1Ctrl = null; // tracks writes to port 0x43
|
||||
this.bPIT2Ctrl = null; // tracks writes to port 0x4B (MODEL_DESKPRO386 only)
|
||||
this.aTimers = new Array(this.model == ChipSet.MODEL_DESKPRO386? 6 : 3);
|
||||
this.bPIT2Ctrl = null; // tracks writes to port 0x4B (MODEL_COMPAQ_DESKPRO386 only)
|
||||
this.aTimers = new Array(this.model == ChipSet.MODEL_COMPAQ_DESKPRO386? 6 : 3);
|
||||
for (i = 0; i < this.aTimers.length; i++) {
|
||||
this.initTimer(i);
|
||||
}
|
||||
|
|
@ -1226,7 +1235,7 @@ ChipSet.prototype.reset = function(fHard)
|
|||
this.b8042InPort |= ChipSet.KBC.INPORT.MONO;
|
||||
}
|
||||
|
||||
if (COMPAQ386 && this.model == ChipSet.MODEL_DESKPRO386) {
|
||||
if (COMPAQ386 && this.model == ChipSet.MODEL_COMPAQ_DESKPRO386) {
|
||||
this.b8042InPort |= ChipSet.KBC.INPORT.COMPAQ_NO80387 | ChipSet.KBC.INPORT.COMPAQ_NOWEITEK;
|
||||
}
|
||||
|
||||
|
|
@ -2819,7 +2828,7 @@ ChipSet.prototype.outDMAPageSpare = function(iSpare, port, bOut, addrFrom)
|
|||
* TODO: Remove this DEBUG-only DESKPRO386 code once we're done debugging DeskPro 386 ROMs;
|
||||
* it enables logging of all DeskPro ROM checkpoint I/O to port 0x84.
|
||||
*/
|
||||
if (this.messageEnabled(Messages.DMA | Messages.PORT) || DEBUG && this.model == ChipSet.MODEL_DESKPRO386 && port == 0x84) {
|
||||
if (this.messageEnabled(Messages.DMA | Messages.PORT) || DEBUG && this.model == ChipSet.MODEL_COMPAQ_DESKPRO386 && port == 0x84) {
|
||||
this.printMessageIO(port, bOut, addrFrom, "DMA.SPARE" + iSpare + ".PAGE", null, true);
|
||||
}
|
||||
this.abDMAPageSpare[iSpare] = bOut;
|
||||
|
|
|
|||
|
|
@ -610,7 +610,7 @@ HDC.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
|
||||
if (this.fATC) {
|
||||
this.iDriveTable++;
|
||||
if (this.chipset && this.chipset.model == ChipSet.MODEL_DESKPRO386) this.iDriveTable++;
|
||||
if (this.chipset && this.chipset.model == ChipSet.MODEL_COMPAQ_DESKPRO386) this.iDriveTable++;
|
||||
this.iDriveTypeDefault = 2;
|
||||
bus.addPortInputWidth(HDC.ATC.DATA.PORT, 2);
|
||||
bus.addPortOutputWidth(HDC.ATC.DATA.PORT, 2);
|
||||
|
|
@ -1556,10 +1556,10 @@ HDC.prototype.inATCByte = function(port, addrFrom)
|
|||
/*
|
||||
* Due to the way I'm immediately triggering an interrupt whenever more data is available,
|
||||
* I must take a "shotgun approach' to regStatus bits in order to make the MODEL_5170_REV1,
|
||||
* MODEL_5170_REV3, and MODEL_DESKPRO386 all happy.
|
||||
* MODEL_5170_REV3, and MODEL_COMPAQ_DESKPRO386 all happy.
|
||||
*
|
||||
* In general, it's fine for all of STATUS.READY, STATUS.SEEK_OK and STATUS.DATA_REQ to be
|
||||
* set now; the MODEL_5170_REV3 requires at least the first two, and the MODEL_DESKPRO386
|
||||
* set now; the MODEL_5170_REV3 requires at least the first two, and the MODEL_COMPAQ_DESKPRO386
|
||||
* requires the third. Unfortunately, the outlier is the MODEL_5170_REV1, which also needs
|
||||
* the STATUS.BUSY to be set on the first regStatus read after it finishes reading a sector;
|
||||
* otherwise, the MODEL_5170_REV1 BIOS will never read any remaining sectors.
|
||||
|
|
@ -1567,10 +1567,10 @@ HDC.prototype.inATCByte = function(port, addrFrom)
|
|||
* Technically, it doesn't make sense for both BUSY and READY to be set at the same time,
|
||||
* so we fix that in inATCStatus() by clearing BUSY whenever READY is detected *after* that
|
||||
* first read. In addition, since this hack is really only needed for the MODEL_5170_REV1,
|
||||
* we clear BUSY immediately on the MODEL_DESKPRO386 (which makes the Windows 95 protected-mode
|
||||
* disk driver much happier).
|
||||
* we clear BUSY immediately on the MODEL_COMPAQ_DESKPRO386 (which makes the Windows 95
|
||||
* protected-mode disk driver much happier).
|
||||
*/
|
||||
if (hdc.chipset && hdc.chipset.model == ChipSet.MODEL_DESKPRO386) hdc.regStatus = 0;
|
||||
if (hdc.chipset && hdc.chipset.model == ChipSet.MODEL_COMPAQ_DESKPRO386) hdc.regStatus = 0;
|
||||
hdc.regStatus |= HDC.ATC.STATUS.READY | HDC.ATC.STATUS.SEEK_OK | HDC.ATC.STATUS.DATA_REQ;
|
||||
} else {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -752,25 +752,43 @@ X86.helpFault = function(nFault, nError, nCycles, fHalt)
|
|||
if (this.nFault < 0) {
|
||||
/*
|
||||
* Single-fault (error code is passed through, and the responsible instruction is restartable.
|
||||
*
|
||||
* TODO: The following opCS/opLIP/opSS/opLSP checks are primarily required for 80386-based machines
|
||||
* with paging enabled, because page faults introduce a new set of complex faults that our current
|
||||
* segment load "probes" are insufficient to catch. So as a stop-gap measure, we rely on these FOUR
|
||||
* "snapshot" registers to temporarily resolve the general instruction restartability problem.
|
||||
*
|
||||
* If you want to closely examine the underlying causes of these more complex faults, set breakpoints
|
||||
* where indicated below, and examine the stack trace.
|
||||
*/
|
||||
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);
|
||||
if (this.opCS !== this.segCS.sel) {
|
||||
/*
|
||||
* HACK: We slam the RPL 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 = this.opCS & 0x3; // set breakpoint here to inspect complex faults
|
||||
this.setCS(this.opCS);
|
||||
}
|
||||
this.opCS = -1;
|
||||
}
|
||||
this.setLIP(this.opLIP);
|
||||
if (this.opLIP !== this.regLIP) {
|
||||
this.setLIP(this.opLIP); // set breakpoint here to inspect complex faults
|
||||
this.assert(this.opLIP === this.regLIP);
|
||||
}
|
||||
if (this.opSS != -1) {
|
||||
this.setSS(this.opSS);
|
||||
if (this.opSS !== this.segSS.sel) {
|
||||
this.setSS(this.opSS); // set breakpoint here to inspect complex faults
|
||||
}
|
||||
this.opSS = -1;
|
||||
}
|
||||
if (this.opLSP !== X86.ADDR_INVALID) {
|
||||
this.setSP((this.regESP & ~this.segSS.maskAddr) | (this.opLSP - this.segSS.base));
|
||||
if (this.opLSP !== this.regLSP) { // set breakpoint below to inspect complex faults
|
||||
this.setSP((this.regESP & ~this.segSS.maskAddr) | (this.opLSP - this.segSS.base));
|
||||
this.assert(this.opLSP === this.regLSP);
|
||||
}
|
||||
this.opLSP = X86.ADDR_INVALID;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue