80286 triple-fault happily resets now
This commit is contained in:
parent
ec857802d5
commit
9d73a2674e
21 changed files with 402 additions and 261 deletions
|
|
@ -290,7 +290,7 @@ Bus.prototype.getA20 = function()
|
|||
*/
|
||||
Bus.prototype.setA20 = function(fEnable)
|
||||
{
|
||||
Component.assert(fEnable !== undefined);
|
||||
if (DEBUG) this.assert(fEnable !== undefined);
|
||||
if (fEnable !== undefined) {
|
||||
if (this.nBusWidth > 20) {
|
||||
var addrMask = (this.addrMask & ~0x100000) | (fEnable? 0x100000 : 0);
|
||||
|
|
|
|||
|
|
@ -1201,7 +1201,7 @@ ChipSet.prototype.initRTCDate = function(sDate)
|
|||
*/
|
||||
ChipSet.prototype.getRTCByte = function(iRTC)
|
||||
{
|
||||
Component.assert(iRTC >= 0 && iRTC <= ChipSet.CMOS.ADDR.RTC_STATUSD);
|
||||
if (DEBUG) this.assert(iRTC >= 0 && iRTC <= ChipSet.CMOS.ADDR.RTC_STATUSD);
|
||||
|
||||
var b = this.abCMOSData[iRTC];
|
||||
|
||||
|
|
@ -1253,7 +1253,7 @@ ChipSet.prototype.getRTCByte = function(iRTC)
|
|||
*/
|
||||
ChipSet.prototype.setRTCByte = function(iRTC, b)
|
||||
{
|
||||
Component.assert(iRTC >= 0 && iRTC <= ChipSet.CMOS.ADDR.RTC_STATUSD);
|
||||
if (DEBUG) this.assert(iRTC >= 0 && iRTC <= ChipSet.CMOS.ADDR.RTC_STATUSD);
|
||||
|
||||
if (iRTC < ChipSet.CMOS.ADDR.RTC_STATUSA) {
|
||||
var fBCD = false;
|
||||
|
|
@ -1272,7 +1272,7 @@ ChipSet.prototype.setRTCByte = function(iRTC, b)
|
|||
* transformed it to 0x51-0x5C, so we must add 0x30.
|
||||
*/
|
||||
if (b > 12) {
|
||||
Component.assert(b >= 0x51 && b <= 0x5c);
|
||||
if (DEBUG) this.assert(b >= 0x51 && b <= 0x5c);
|
||||
b += 0x30;
|
||||
}
|
||||
}
|
||||
|
|
@ -1306,7 +1306,7 @@ ChipSet.prototype.updateRTCDate = function()
|
|||
*/
|
||||
if (this.nCyclesCMOSLastUpdate >= 0) {
|
||||
nCyclesDelta = nCyclesUpdate - this.nCyclesCMOSLastUpdate;
|
||||
Component.assert(nCyclesDelta >= 0);
|
||||
if (DEBUG) this.assert(nCyclesDelta >= 0);
|
||||
var nSecondsDelta = Math.floor(nCyclesDelta / nCyclesPerSecond);
|
||||
/*
|
||||
* We trust that updateRTCDate() is being called as part of updateAllTimers(), and is therefore
|
||||
|
|
@ -1315,7 +1315,7 @@ ChipSet.prototype.updateRTCDate = function()
|
|||
* (nCyclesDelta % nCyclesPerSecond) back into nCyclesCMOSLastUpdate, so that we will eventually
|
||||
* see a one-second delta.
|
||||
*/
|
||||
Component.assert(nSecondsDelta <= 1);
|
||||
if (DEBUG) this.assert(nSecondsDelta <= 1);
|
||||
if (nSecondsDelta) {
|
||||
if (++this.abCMOSData[ChipSet.CMOS.ADDR.RTC_SEC] >= 60) {
|
||||
this.abCMOSData[ChipSet.CMOS.ADDR.RTC_SEC] = 0;
|
||||
|
|
@ -1397,7 +1397,7 @@ ChipSet.prototype.initCMOSData = function()
|
|||
ChipSet.prototype.setCMOSByte = function(iCMOS, b)
|
||||
{
|
||||
if (this.abCMOSData) {
|
||||
Component.assert(iCMOS >= ChipSet.CMOS.ADDR.FDRIVE && iCMOS < ChipSet.CMOS.ADDR.CHKSUM_HI);
|
||||
if (DEBUG) this.assert(iCMOS >= ChipSet.CMOS.ADDR.FDRIVE && iCMOS < ChipSet.CMOS.ADDR.CHKSUM_HI);
|
||||
this.abCMOSData[iCMOS] = b;
|
||||
this.updateCMOSChecksum();
|
||||
return true;
|
||||
|
|
@ -1449,7 +1449,7 @@ ChipSet.prototype.setCMOSDriveType = function(iDrive, bType)
|
|||
{
|
||||
if (this.abCMOSData) {
|
||||
var b = this.abCMOSData[ChipSet.CMOS.ADDR.HDRIVE];
|
||||
Component.assert(bType > 0 && bType < 0xf);
|
||||
if (DEBUG) this.assert(bType > 0 && bType < 0xf);
|
||||
if (iDrive) {
|
||||
b = (b & ChipSet.CMOS.HDRIVE.D0_MASK) | bType;
|
||||
} else {
|
||||
|
|
@ -1549,7 +1549,7 @@ ChipSet.prototype.restore = function(data)
|
|||
|
||||
a = data[5];
|
||||
if (a) {
|
||||
Component.assert(this.model >= ChipSet.MODEL_5170);
|
||||
if (DEBUG) this.assert(this.model >= ChipSet.MODEL_5170);
|
||||
this.b8042Status = a[0];
|
||||
this.b8042InBuff = a[1];
|
||||
this.b8042CmdData = a[2];
|
||||
|
|
@ -1560,7 +1560,7 @@ ChipSet.prototype.restore = function(data)
|
|||
|
||||
a = data[6];
|
||||
if (a) {
|
||||
Component.assert(this.model >= ChipSet.MODEL_5170);
|
||||
if (DEBUG) this.assert(this.model >= ChipSet.MODEL_5170);
|
||||
this.bMFGData = a[0];
|
||||
this.abDMAPageSpare = a[1];
|
||||
this.bCMOSAddr = a[2];
|
||||
|
|
@ -1592,7 +1592,7 @@ ChipSet.prototype.initDMAController = function(iDMAC, aState)
|
|||
{
|
||||
var controller = this.aDMACs[iDMAC];
|
||||
if (!controller) {
|
||||
Component.assert(!aState);
|
||||
if (DEBUG) this.assert(!aState);
|
||||
controller = {
|
||||
aChannels: new Array(4)
|
||||
};
|
||||
|
|
@ -1623,7 +1623,7 @@ ChipSet.prototype.initDMAChannel = function(controller, iChannel, aState)
|
|||
{
|
||||
var channel = controller.aChannels[iChannel];
|
||||
if (!channel) {
|
||||
Component.assert(!aState);
|
||||
if (DEBUG) this.assert(!aState);
|
||||
channel = {
|
||||
addrInit: [0,0],
|
||||
countInit: [0,0],
|
||||
|
|
@ -1899,7 +1899,7 @@ ChipSet.prototype.getSWFloppyDriveType = function(iDrive)
|
|||
return ChipSet.CMOS.FDRIVE.FD1440;
|
||||
}
|
||||
}
|
||||
Component.assert(false); // we should never get here (else something is out of out sync)
|
||||
if (DEBUG) this.assert(false); // we should never get here (else something is out of out sync)
|
||||
}
|
||||
return ChipSet.CMOS.FDRIVE.NONE;
|
||||
};
|
||||
|
|
@ -1920,7 +1920,7 @@ ChipSet.prototype.getSWFloppyDriveSize = function(iDrive)
|
|||
if (iDrive < this.aFloppyDrives.length) {
|
||||
return this.aFloppyDrives[iDrive];
|
||||
}
|
||||
Component.assert(false); // we should never get here (else something is out of out sync)
|
||||
if (DEBUG) this.assert(false); // we should never get here (else something is out of out sync)
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
|
@ -4020,7 +4020,7 @@ ChipSet.prototype.in8042Status = function(port, addrFrom)
|
|||
ChipSet.prototype.out8042InBuffCmd = function(port, bOut, addrFrom)
|
||||
{
|
||||
this.messagePort(port, bOut, addrFrom, "8042_INBUFF.CMD", Debugger.MESSAGE.C8042);
|
||||
Component.assert(!(this.b8042Status & ChipSet.KBC.STATUS.INBUFF_FULL));
|
||||
if (DEBUG) this.assert(!(this.b8042Status & ChipSet.KBC.STATUS.INBUFF_FULL));
|
||||
this.b8042InBuff = bOut;
|
||||
|
||||
this.b8042Status |= ChipSet.KBC.STATUS.CMD_FLAG;
|
||||
|
|
@ -4103,7 +4103,7 @@ ChipSet.prototype.set8042CmdData = function(b)
|
|||
{
|
||||
var bClockWasEnabled = !(this.b8042CmdData & ChipSet.KBC.DATA.CMD.NO_CLOCK);
|
||||
this.b8042CmdData = b;
|
||||
Component.assert(ChipSet.KBC.DATA.CMD.SYS_FLAG === ChipSet.KBC.STATUS.SYS_FLAG);
|
||||
if (DEBUG) this.assert(ChipSet.KBC.DATA.CMD.SYS_FLAG === ChipSet.KBC.STATUS.SYS_FLAG);
|
||||
this.b8042Status = (this.b8042Status & ~ChipSet.KBC.STATUS.SYS_FLAG) | (b & ChipSet.KBC.DATA.CMD.SYS_FLAG);
|
||||
if (this.kbd) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -883,7 +883,7 @@ CPU.prototype.calcStartTime = function()
|
|||
* in case, I make absolutely sure it cannot happen, since doing so could result in negative
|
||||
* speed calculations.
|
||||
*/
|
||||
Component.assert(this.aCounts.msStartRun <= this.aCounts.msStartThisRun);
|
||||
if (DEBUG) this.assert(this.aCounts.msStartRun <= this.aCounts.msStartThisRun);
|
||||
if (this.aCounts.msStartRun > this.aCounts.msStartThisRun) {
|
||||
this.aCounts.msStartRun = this.aCounts.msStartThisRun;
|
||||
}
|
||||
|
|
@ -1049,7 +1049,7 @@ CPU.prototype.runCPU = function(fOnClick)
|
|||
/**
|
||||
* startCPU(fSetFocus)
|
||||
*
|
||||
* WARNING: Other components must use runCPU() to get the CPU running; this is a runCPU() helper function only.
|
||||
* WARNING: Other components must use runCPU() to get the CPU running; This is a runCPU() helper function only; o
|
||||
*
|
||||
* @param {boolean} [fSetFocus]
|
||||
*/
|
||||
|
|
@ -1145,10 +1145,10 @@ CPU.prototype.yieldCPU = function()
|
|||
this.nStepCycles = 0; // this will break us out of stepCPU()
|
||||
/*
|
||||
* The Debugger calls yieldCPU() after every message() to ensure browser responsiveness, but it looks
|
||||
* odd for those messages to show CPU state changes but for the CPU's own status display to not, so I've
|
||||
* added this call to try to keep things looking synchronized.
|
||||
* odd for those messages to show CPU state changes but for the CPU's own status display to not (ditto
|
||||
* for the Video display), so I've added this call to try to keep things looking synchronized.
|
||||
*/
|
||||
this.displayStatus();
|
||||
this.updateCPU();
|
||||
};
|
||||
|
||||
if (typeof APP_PCJS !== 'undefined') APP_PCJS.CPU = CPU;
|
||||
|
|
|
|||
|
|
@ -1364,6 +1364,7 @@ if (DEBUGGER) {
|
|||
{
|
||||
this.afnDumpers = [];
|
||||
this.bitsMessageEnabled = 0;
|
||||
this.sMessagePrev = null;
|
||||
var aEnable = this.parseCommand(sEnable);
|
||||
if (aEnable.length) {
|
||||
for (var m in Debugger.MESSAGES) {
|
||||
|
|
@ -1544,8 +1545,12 @@ if (DEBUGGER) {
|
|||
*/
|
||||
Debugger.prototype.message = function(sMessage)
|
||||
{
|
||||
if (this.sMessagePrev && sMessage == this.sMessagePrev) return;
|
||||
|
||||
this.println(sMessage); // + " (" + this.cpu.getCycles() + " cycles)"
|
||||
|
||||
this.sMessagePrev = sMessage;
|
||||
|
||||
if (this.cpu) {
|
||||
if (this.bitsMessageEnabled & Debugger.MESSAGE.HALT) {
|
||||
this.cpu.stopCPU();
|
||||
|
|
@ -1727,6 +1732,18 @@ if (DEBUGGER) {
|
|||
return (this.nCycles > 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* stopCPU(s)
|
||||
*
|
||||
* @this {Debugger}
|
||||
* @param {string} [s]
|
||||
*/
|
||||
Debugger.prototype.stopCPU = function(s)
|
||||
{
|
||||
if (s) this.message(s);
|
||||
this.cpu.stopCPU();
|
||||
};
|
||||
|
||||
/**
|
||||
* updateStatus(fRegs, fCompact)
|
||||
*
|
||||
|
|
@ -1993,7 +2010,7 @@ if (DEBUGGER) {
|
|||
* Assert that general-purpose register contents remain within their respective ranges;
|
||||
* this isn't intended to be complete, just a spot-check.
|
||||
*/
|
||||
Component.assert(!(this.cpu.regAX & ~0xffff) && !(this.cpu.regBX & ~0xffff) && !(this.cpu.regCX & ~0xffff) && !(this.cpu.regDX & ~0xffff), "register out of bounds");
|
||||
if (DEBUG) this.assert(!(this.cpu.regAX & ~0xffff) && !(this.cpu.regBX & ~0xffff) && !(this.cpu.regCX & ~0xffff) && !(this.cpu.regDX & ~0xffff), "register out of bounds");
|
||||
|
||||
if (!fSkipBP && this.checkBreakpoint(addr, this.aBreakExec)) {
|
||||
return true;
|
||||
|
|
@ -2112,7 +2129,8 @@ if (DEBUGGER) {
|
|||
* If the selector matches that of any of the CPU segment registers, then return the CPU's segment
|
||||
* register, instead of creating our own dummy segment register. This makes it possible for us to
|
||||
* see what the CPU is seeing at certain critical junctures, such as after an LMSW instruction has
|
||||
* switched the processor from real to protected mode.
|
||||
* switched the processor from real to protected mode. Actually loading the selector from the GDT/LDT
|
||||
* should be done only as a last resort.
|
||||
*
|
||||
* @param {number} sel
|
||||
* @return {X86Seg} seg
|
||||
|
|
@ -2183,7 +2201,7 @@ if (DEBUGGER) {
|
|||
var addr = this.getAddr(aAddr, false, 0);
|
||||
if (addr >= 0) {
|
||||
b = this.bus.getByteDirect(addr);
|
||||
Component.assert((b == (b & 0xff)), "invalid byte (" + b + ") at address: " + this.hexAddr(aAddr));
|
||||
if (DEBUG) this.assert((b == (b & 0xff)), "invalid byte (" + b + ") at address: " + this.hexAddr(aAddr));
|
||||
if (inc !== undefined) this.incAddr(aAddr, inc);
|
||||
}
|
||||
return b;
|
||||
|
|
@ -2203,7 +2221,7 @@ if (DEBUGGER) {
|
|||
var addr = this.getAddr(aAddr, false, 1);
|
||||
if (addr >= 0) {
|
||||
w = this.bus.getWordDirect(addr);
|
||||
Component.assert((w == (w & 0xffff)), "invalid word (" + w + ") at address: " + this.hexAddr(aAddr));
|
||||
if (DEBUG) this.assert((w == (w & 0xffff)), "invalid word (" + w + ") at address: " + this.hexAddr(aAddr));
|
||||
if (inc !== undefined) this.incAddr(aAddr, inc);
|
||||
}
|
||||
return w;
|
||||
|
|
@ -3515,7 +3533,7 @@ if (DEBUGGER) {
|
|||
s += (seg.acc & X86.DESC.ACC.TYPE.CONFORMING)? "conforming," : "nonconforming,";
|
||||
} else {
|
||||
s += "data:";
|
||||
s += (seg.acc & X86.DESC.ACC.TYPE.WRITEABLE)? "writeable," : "readonly,";
|
||||
s += (seg.acc & X86.DESC.ACC.TYPE.WRITABLE)? "writable," : "readonly,";
|
||||
s += (seg.acc & X86.DESC.ACC.TYPE.EXPDOWN)? "expand down," : "expand up,";
|
||||
}
|
||||
s += (seg.acc & X86.DESC.ACC.TYPE.ACCESSED)? "accessed" : "not accessed";
|
||||
|
|
|
|||
|
|
@ -811,7 +811,7 @@ Disk.prototype.doneLoad = function(sDiskFile, sDiskData, nErrorCode, sDiskPath)
|
|||
* pattern, if any, into a dword pattern.
|
||||
*/
|
||||
adw = [];
|
||||
Component.assert((dwPattern & 0xff) == dwPattern);
|
||||
if (DEBUG) this.assert((dwPattern & 0xff) == dwPattern);
|
||||
dwPattern = sector['pattern'] = (dwPattern | (dwPattern << 8) | (dwPattern << 16) | (dwPattern << 24));
|
||||
sector['data'] = adw;
|
||||
} else {
|
||||
|
|
@ -1152,7 +1152,7 @@ Disk.prototype.findDirtySectors = function(fAsync)
|
|||
var sectorNext = this.aDiskData[iCylinder][iHead][i];
|
||||
if (!sectorNext.fDirty) break;
|
||||
var j = this.aDirtySectors.indexOf(sectorNext);
|
||||
Component.assert(j >= 0, "dirty sector (" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ") missing from aDirtySectors");
|
||||
if (DEBUG) this.assert(j >= 0, "dirty sector (" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ") missing from aDirtySectors");
|
||||
if (DEBUG) this.messageDebugger("Disk.findDirtySectors(" + iCylinder + ":" + iHead + ":" + sectorNext['sector'] + ")");
|
||||
this.aDirtySectors.splice(j, 1);
|
||||
this.aDirtyTimestamps.splice(j, 1);
|
||||
|
|
@ -1160,7 +1160,7 @@ Disk.prototype.findDirtySectors = function(fAsync)
|
|||
sectorNext.fDirty = false;
|
||||
nSectors++;
|
||||
}
|
||||
Component.assert(!!abSectors.length, "no data for dirty sector (" + iCylinder + ":" + iHead + ":" + sector['sector'] + ")");
|
||||
if (DEBUG) this.assert(!!abSectors.length, "no data for dirty sector (" + iCylinder + ":" + iHead + ":" + sector['sector'] + ")");
|
||||
var response = this.writeRemoteSectors(iCylinder, iHead, iSector, nSectors, abSectors, fAsync);
|
||||
return fAsync || response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1523,7 +1523,7 @@ FDC.prototype.unloadAllDrives = function(fDiscard)
|
|||
FDC.prototype.addDiskHistory = function(sDisketteName, sDiskettePath, disk)
|
||||
{
|
||||
var i;
|
||||
Component.assert(!!sDiskettePath);
|
||||
if (DEBUG) this.assert(!!sDiskettePath);
|
||||
for (i = 0; i < this.aDiskHistory.length; i++) {
|
||||
if (this.aDiskHistory[i][1] == sDiskettePath) {
|
||||
var nChanges = disk.restore(this.aDiskHistory[i][2]);
|
||||
|
|
@ -1796,7 +1796,7 @@ FDC.prototype.doCmd = function()
|
|||
* Controller docs say that H should always match HD, so I assert that, but what if someone
|
||||
* made a mistake and didn't program them identically -- what would happen? Which should we honor?
|
||||
*/
|
||||
Component.assert(h == bHead);
|
||||
if (DEBUG) this.assert(h == bHead);
|
||||
r = drive.bSector = this.popCmd(FDC.TERMS.R); // R
|
||||
n = this.popCmd(FDC.TERMS.N); // N
|
||||
drive.nBytes = 128 << n; // 0 => 128, 1 => 256, 2 => 512, 3 => 1024
|
||||
|
|
@ -2005,7 +2005,7 @@ FDC.prototype.pushResults = function(drive, bCmd, bHead, c, h, r, n)
|
|||
*/
|
||||
FDC.prototype.popCmd = function(name)
|
||||
{
|
||||
Component.assert((!this.regDataIndex || name !== undefined) && this.regDataIndex < this.regDataTotal);
|
||||
if (DEBUG) this.assert((!this.regDataIndex || name !== undefined) && this.regDataIndex < this.regDataTotal);
|
||||
var bCmd = this.regDataArray[this.regDataIndex];
|
||||
if (DEBUG && DEBUGGER && this.dbg && this.dbg.messageEnabled(Debugger.MESSAGE.FDC)) {
|
||||
var bCmdMasked = bCmd & FDC.REG_DATA.CMD.MASK;
|
||||
|
|
@ -2372,7 +2372,7 @@ FDC.prototype.writeByte = function(drive, b)
|
|||
*/
|
||||
FDC.prototype.advanceSector = function(drive)
|
||||
{
|
||||
Component.assert(drive.bCylinder < drive.nDiskCylinders);
|
||||
if (DEBUG) this.assert(drive.bCylinder < drive.nDiskCylinders);
|
||||
drive.bSector++;
|
||||
var bSectorStart = 1;
|
||||
if (drive.bSector >= drive.nDiskSectors + bSectorStart) {
|
||||
|
|
|
|||
|
|
@ -1399,7 +1399,7 @@ HDC.prototype.inATCData = function(port, addrFrom)
|
|||
* well, then the caller will get 0xff.
|
||||
*/
|
||||
bIn = this.readByte(this.drive);
|
||||
Component.assert(bIn >= 0);
|
||||
if (DEBUG) this.assert(bIn >= 0);
|
||||
|
||||
/*
|
||||
* Now that we've supplied a full sector of data, see if the caller's expecting additional sectors;
|
||||
|
|
@ -1420,7 +1420,7 @@ HDC.prototype.inATCData = function(port, addrFrom)
|
|||
/*
|
||||
* I shouldn't have to set BUSY (or DATA_REQ) again, because it should still be set, no?
|
||||
*/
|
||||
Component.assert(!!(hdc.regStatus & HDC.ATC.STATUS.BUSY));
|
||||
if (DEBUG) this.assert(!!(hdc.regStatus & HDC.ATC.STATUS.BUSY));
|
||||
} else {
|
||||
/*
|
||||
* TODO: It would be nice to be a bit more specific about the error (if any) that just occurred.
|
||||
|
|
@ -1432,7 +1432,7 @@ HDC.prototype.inATCData = function(port, addrFrom)
|
|||
}
|
||||
}, false);
|
||||
} else {
|
||||
Component.assert(this.drive.nBytes == 0);
|
||||
if (DEBUG) this.assert(this.drive.nBytes == 0);
|
||||
this.regStatus = HDC.ATC.STATUS.READY | HDC.ATC.STATUS.SEEK_OK;
|
||||
}
|
||||
}
|
||||
|
|
@ -1475,9 +1475,9 @@ HDC.prototype.outATCData = function(port, bOut, addrFrom)
|
|||
/*
|
||||
* I shouldn't have to set BUSY (or DATA_REQ) again, because it should still be set, no?
|
||||
*/
|
||||
Component.assert(!!(this.regStatus & HDC.ATC.STATUS.BUSY));
|
||||
if (DEBUG) this.assert(!!(this.regStatus & HDC.ATC.STATUS.BUSY));
|
||||
} else {
|
||||
Component.assert(this.drive.nBytes == 0);
|
||||
if (DEBUG) this.assert(this.drive.nBytes == 0);
|
||||
this.regStatus = HDC.ATC.STATUS.READY | HDC.ATC.STATUS.SEEK_OK;
|
||||
}
|
||||
}
|
||||
|
|
@ -1868,8 +1868,8 @@ HDC.prototype.doATCommand = function()
|
|||
* The importance of SECCNT (nSectors) and DRVHD (nHeads) is controlling how multi-sector operations
|
||||
* advance to the next sector; see advanceSector().
|
||||
*/
|
||||
Component.assert(drive.nHeads == nHead + 1);
|
||||
Component.assert(drive.nSectors == nSectors);
|
||||
if (DEBUG) this.assert(drive.nHeads == nHead + 1);
|
||||
if (DEBUG) this.assert(drive.nSectors == nSectors);
|
||||
drive.nHeads = nHead + 1;
|
||||
drive.nSectors = nSectors;
|
||||
fInterrupt = true;
|
||||
|
|
@ -2525,7 +2525,7 @@ HDC.prototype.writeByte = function(drive, b)
|
|||
*/
|
||||
HDC.prototype.advanceSector = function(drive)
|
||||
{
|
||||
Component.assert(drive.wCylinder < drive.nCylinders);
|
||||
if (DEBUG) this.assert(drive.wCylinder < drive.nCylinders);
|
||||
drive.bSector++;
|
||||
var bSectorStart = (1 - drive.bSectorBias);
|
||||
if (drive.bSector >= drive.nSectors + bSectorStart) {
|
||||
|
|
|
|||
|
|
@ -1332,8 +1332,10 @@ Keyboard.prototype.calcReleaseDelay = function(fRepeat)
|
|||
Keyboard.prototype.autoClear = function(notKeyCode)
|
||||
{
|
||||
if (this.prevCharDown && (notKeyCode === undefined || notKeyCode != this.prevCharDown)) {
|
||||
if (DEBUG) this.messageDebugger("autoClear(" + this.prevCharDown + ")");
|
||||
Component.assert(this.aKeyTimers[this.prevCharDown]);
|
||||
if (DEBUG) {
|
||||
this.messageDebugger("autoClear(" + this.prevCharDown + ")");
|
||||
this.assert(this.aKeyTimers[this.prevCharDown]);
|
||||
}
|
||||
clearTimeout(this.aKeyTimers[this.prevCharDown]);
|
||||
this.keySimulateUpOrDown(this.prevCharDown, false, Keyboard.SIMCODE.AUTOCLEAR);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,10 +77,6 @@ if (typeof module !== 'undefined') {
|
|||
* as many new BLOCK_SIZE Memory objects as the ranges require. Partial Memory blocks could be
|
||||
* supported in theory, but in practice, they're not.
|
||||
*
|
||||
* NOTE: Since Memory blocks are low-level objects that have no UI requirements, they do not
|
||||
* inherit from the Component class; so, if you want to use println(), for example, you must
|
||||
* use the methods in the Debugger class.
|
||||
*
|
||||
* Because Memory blocks now allow us to have a "sparse" address space, we could choose to
|
||||
* take the memory hit of allocating 4K arrays per block, where each element stores only one byte,
|
||||
* instead of the more frugal but slightly slower approach of allocating arrays of 32-bit dwords
|
||||
|
|
@ -92,6 +88,10 @@ if (typeof module !== 'undefined') {
|
|||
* probably best, although not all JavaScript implementations support them (IE9 is probably the
|
||||
* only real outlier: it lacks typed arrays but otherwise has all the necessary HTML5 support).
|
||||
*
|
||||
* WARNING: Since Memory blocks are low-level objects that have no UI requirements,
|
||||
* they do not inherit from the Component class, so you should only use class methods
|
||||
* of Component, such as Component.assert(), or Debugger methods if the Debugger is available.
|
||||
*
|
||||
* @constructor
|
||||
* @param {number} addr of block (must be some multiple of bus.blockSize)
|
||||
* @param {number} [size] of block's buffer in bytes (0 for none); must be a multiple of 4
|
||||
|
|
@ -565,14 +565,14 @@ Memory.prototype = {
|
|||
this.resetReadAccess();
|
||||
if (DEBUG) this.dbg.println("all read breakpoints removed from memory block " + str.toHex(this.addr));
|
||||
}
|
||||
Component.assert(this.cReadBreakpoints >= 0);
|
||||
this.dbg.assert(this.cReadBreakpoints >= 0);
|
||||
}
|
||||
else {
|
||||
if (--this.cWriteBreakpoints === 0) {
|
||||
this.resetWriteAccess();
|
||||
if (DEBUG) this.dbg.println("all write breakpoints removed from memory block " + str.toHex(this.addr));
|
||||
}
|
||||
Component.assert(this.cWriteBreakpoints >= 0);
|
||||
this.dbg.assert(this.cWriteBreakpoints >= 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,11 +40,6 @@ if (typeof module !== 'undefined') {
|
|||
/**
|
||||
* State(component, sVersion, sSuffix)
|
||||
*
|
||||
* @constructor
|
||||
* @param {Component} component
|
||||
* @param {string} [sVersion] is used to append a major version number to the key
|
||||
* @param {string} [sSuffix] is used to append any additional suffixes to the key
|
||||
*
|
||||
* State objects are used by components to save/restore their state.
|
||||
*
|
||||
* During a save operation, components add data to a State object via set(),
|
||||
|
|
@ -52,6 +47,15 @@ if (typeof module !== 'undefined') {
|
|||
*
|
||||
* During a restore operation, the Computer component passes the results of each
|
||||
* data() call back to the originating component.
|
||||
*
|
||||
* WARNING: Since State objects are low-level objects that have no UI requirements,
|
||||
* they do not inherit from the Component class, so you should only use class methods
|
||||
* of Component, such as Component.assert(), or Debugger methods if the Debugger is available.
|
||||
*
|
||||
* @constructor
|
||||
* @param {Component} component
|
||||
* @param {string} [sVersion] is used to append a major version number to the key
|
||||
* @param {string} [sSuffix] is used to append any additional suffixes to the key
|
||||
*/
|
||||
function State(component, sVersion, sSuffix) {
|
||||
this.id = component.id;
|
||||
|
|
@ -226,10 +230,10 @@ State.prototype = {
|
|||
/**
|
||||
* value()
|
||||
*
|
||||
* Use this instead of data() if you haven't called parse() yet.
|
||||
*
|
||||
* @this {State}
|
||||
* @return {string}
|
||||
*
|
||||
* Use this instead of data() if you haven't called parse() yet.
|
||||
*/
|
||||
value: function() {
|
||||
return this[this.id];
|
||||
|
|
@ -246,12 +250,12 @@ State.prototype = {
|
|||
/**
|
||||
* load(s)
|
||||
*
|
||||
* WARNING: Make sure you follow this call with either a call to parse() or unload(),
|
||||
* because any stringified data that we've loaded isn't usable until it's been parsed.
|
||||
*
|
||||
* @this {State}
|
||||
* @param {Object|string|null} [s]
|
||||
* @return {boolean} true if state exists in localStorage, false if not
|
||||
*
|
||||
* WARNING: Make sure you follow this call with either a call to parse() or unload(),
|
||||
* because any stringified data that we've loaded isn't usable until it's been parsed.
|
||||
*/
|
||||
load: function(s) {
|
||||
if (s) {
|
||||
|
|
@ -279,12 +283,12 @@ State.prototype = {
|
|||
/**
|
||||
* parse()
|
||||
*
|
||||
* @this {State}
|
||||
* @return {boolean} true if successful, false if error
|
||||
*
|
||||
* This completes the load() operation, by parsing what was loaded, on the assumption there
|
||||
* might be some benefit to deferring parsing until we've given the user a chance to confirm.
|
||||
* Otherwise, load() could have just as easily done this, too.
|
||||
*
|
||||
* @this {State}
|
||||
* @return {boolean} true if successful, false if error
|
||||
*/
|
||||
parse: function() {
|
||||
var fSuccess = true;
|
||||
|
|
@ -337,12 +341,12 @@ State.prototype = {
|
|||
/**
|
||||
* unload(parms)
|
||||
*
|
||||
* @this {State}
|
||||
* @param {Object} [parms]
|
||||
*
|
||||
* This discards any data saved via set() or loaded via load(), creating an empty State object.
|
||||
* Note that you have to follow this call with an explicit call to store() if you want to remove
|
||||
* the state from localStorage as well.
|
||||
*
|
||||
* @this {State}
|
||||
* @param {Object} [parms]
|
||||
*/
|
||||
unload: function(parms) {
|
||||
this[this.id] = {};
|
||||
|
|
@ -352,11 +356,11 @@ State.prototype = {
|
|||
/**
|
||||
* clear(fAll)
|
||||
*
|
||||
* @this {State}
|
||||
* @param {boolean} [fAll] true to unconditionally clear ALL localStorage for the current domain
|
||||
*
|
||||
* This unloads the current state, and then clears ALL localStorage for the current machine,
|
||||
* independent of version, to reduce the chance of orphaned states wasting part of our limited allocation.
|
||||
*
|
||||
* @this {State}
|
||||
* @param {boolean} [fAll] true to unconditionally clear ALL localStorage for the current domain
|
||||
*/
|
||||
clear: function(fAll) {
|
||||
this.unload();
|
||||
|
|
@ -374,10 +378,10 @@ State.prototype = {
|
|||
/**
|
||||
* messageDebugger(sMessage)
|
||||
*
|
||||
* This is a combination of the Debugger's messageEnabled(MESSAGE_STATE) and message() functions, for convenience.
|
||||
*
|
||||
* @this {State}
|
||||
* @param {string} sMessage is any caller-defined message string
|
||||
*
|
||||
* This is a combination of the Debugger's messageEnabled(MESSAGE_STATE) and message() functions, for convenience.
|
||||
*/
|
||||
messageDebugger: function(sMessage) {
|
||||
if (DEBUGGER && this.dbg) {
|
||||
|
|
|
|||
|
|
@ -478,8 +478,7 @@ Video.aEGAMonitorSwitches = {
|
|||
* to enter a "mode" that has no BIOS counterpart (eg, non-standard combinations of frame buffer address,
|
||||
* memory access modes, fonts, display regions, etc). Our hardware emulation routines will cope with those
|
||||
* situations as best they can (and when they don't, it should be considered a bug if some application is
|
||||
* broken as a result), but realistically, this is never going to be a completely accurate hardware emulation
|
||||
* of any video card.
|
||||
* broken as a result), but realistically, this is never going to be a 100% accurate hardware emulation.
|
||||
*/
|
||||
Video.MODES = {};
|
||||
Video.MODES.CGA_40X25_BW = 0;
|
||||
|
|
@ -721,7 +720,9 @@ Video.aEGADWToByte[0x80808080] = 0xf;
|
|||
* Creates an object representing an initial video card state;
|
||||
* can also restore a video card from state data created by saveCard().
|
||||
*
|
||||
* See new Card().
|
||||
* WARNING: Since Card objects are low-level objects that have no UI requirements,
|
||||
* they do not inherit from the Component class, so you should only use class methods
|
||||
* of Component, such as Component.assert(), or Debugger methods if the Debugger is available.
|
||||
*
|
||||
* @constructor
|
||||
* @param {Video} [video]
|
||||
|
|
@ -2694,6 +2695,7 @@ Video.prototype.onROMLoad = function(abROM)
|
|||
/**
|
||||
* getCardColors(nBitsPerPixel)
|
||||
*
|
||||
* @this {Video}
|
||||
* @param {number} [nBitsPerPixel]
|
||||
* @returns {Array}
|
||||
*/
|
||||
|
|
@ -2746,7 +2748,7 @@ Video.prototype.getCardColors = function(nBitsPerPixel)
|
|||
return Video.aCGAColors;
|
||||
}
|
||||
|
||||
Component.assert(this.cardColor === this.cardEGA);
|
||||
if (DEBUG) this.assert(this.cardColor === this.cardEGA);
|
||||
|
||||
var aRegs = (this.cardEGA.aATCRegs[15] != null? this.cardEGA.aATCRegs : Video.aEGAPalDef);
|
||||
for (var i = 0; i < this.aRGB.length; i++) {
|
||||
|
|
@ -4062,7 +4064,7 @@ Video.prototype.updateScreenText = function(addrScreen, addrScreenLimit, iCell,
|
|||
if (iCell == this.iCellCursor) {
|
||||
data |= ((this.cBlinks & 0x1)? (Video.ATTRS.DRAW_CURSOR << 8) : 0);
|
||||
}
|
||||
Component.assert(iCell < this.aCellCache.length);
|
||||
if (DEBUG) this.assert(iCell < this.aCellCache.length);
|
||||
dataCache = this.aCellCache[iCell];
|
||||
if (dataCache != data) {
|
||||
var col = iCell % this.nCols;
|
||||
|
|
@ -4103,7 +4105,7 @@ Video.prototype.updateScreenGraphicsCGA = function(addrScreen, addrScreenLimit)
|
|||
var xDirty = this.nCols, xMaxDirty = 0, yDirty = this.nRows, yMaxDirty = 0;
|
||||
while (addr < addrScreenLimit) {
|
||||
data = this.bus.getWordDirect(addr);
|
||||
Component.assert(iCell < this.aCellCache.length);
|
||||
if (DEBUG) this.assert(iCell < this.aCellCache.length);
|
||||
dataCache = this.aCellCache[iCell];
|
||||
if (dataCache === data) {
|
||||
x += nPixelsPerCell;
|
||||
|
|
@ -4181,9 +4183,9 @@ Video.prototype.updateScreenGraphicsEGA = function(addrScreen, addrScreenLimit)
|
|||
var xDirty = this.nCols, xMaxDirty = 0, yDirty = this.nRows, yMaxDirty = 0;
|
||||
while (addr < addrScreenLimit) {
|
||||
var idw = addr++ - this.addrBuffer;
|
||||
Component.assert(idw >= 0 && idw < adwMemory.length);
|
||||
if (DEBUG) this.assert(idw >= 0 && idw < adwMemory.length);
|
||||
data = adwMemory[idw];
|
||||
Component.assert(iCell < this.aCellCache.length);
|
||||
if (DEBUG) this.assert(iCell < this.aCellCache.length);
|
||||
dataCache = this.aCellCache[iCell];
|
||||
if (dataCache === data) {
|
||||
x += nPixelsPerCell;
|
||||
|
|
@ -4206,10 +4208,10 @@ Video.prototype.updateScreenGraphicsEGA = function(addrScreen, addrScreenLimit)
|
|||
*/
|
||||
if (dwPixel < 0) dwPixel += 0x100000000;
|
||||
/*
|
||||
* Since assertions don't fix problems (only catch them, and only in DEBUG builds), I'm also insuring
|
||||
* Since assertions don't fix problems (only catch them, and only in DEBUG builds), I'm also ensuring
|
||||
* that bPixel will always default to 0 if an undefined value ever slips through again.
|
||||
*/
|
||||
Component.assert(Video.aEGADWToByte[dwPixel] !== undefined);
|
||||
if (DEBUG) this.assert(Video.aEGADWToByte[dwPixel] !== undefined);
|
||||
var bPixel = Video.aEGADWToByte[dwPixel] || 0;
|
||||
this.setPixel(this.imageScreenBuffer, x++, y, aPixelColors[bPixel]);
|
||||
data <<= 1;
|
||||
|
|
@ -4948,7 +4950,7 @@ Video.prototype.inCardStatus = function(card, addrFrom)
|
|||
* monitors the STATUS1 diagnostic bits, waiting for those palette bits to show up. It turns out, however,
|
||||
* that we can easily fool the EGA BIOS by simply toggling the diagnostic bits. So we take the easy way out.
|
||||
*
|
||||
* TODO: Faithful emulation of these bits is certainly doable, so consider doing it at some point.
|
||||
* TODO: Faithful emulation of these bits is certainly doable, so consider doing that at some point.
|
||||
*/
|
||||
b |= ((card.statusReg & Card.STATUS1.DIAGNOSTIC) ^ Card.STATUS1.DIAGNOSTIC);
|
||||
|
||||
|
|
|
|||
|
|
@ -81,15 +81,15 @@ var X86 = {
|
|||
},
|
||||
DESC: { // Descriptor Table Entry
|
||||
LIMIT: {
|
||||
OFFSET: 0x0
|
||||
OFFSET: 0x0
|
||||
},
|
||||
BASE: {
|
||||
OFFSET: 0x2
|
||||
OFFSET: 0x2
|
||||
},
|
||||
ACC: { // bit definitions for the access word (offset 0x4)
|
||||
OFFSET: 0x4,
|
||||
BASE1623: 0x00ff,
|
||||
MASK: 0xff00,
|
||||
OFFSET: 0x4,
|
||||
BASE1623: 0x00ff,
|
||||
MASK: 0xff00,
|
||||
TYPE: {
|
||||
MASK: 0x1f00,
|
||||
SEG: 0x1000,
|
||||
|
|
@ -97,12 +97,12 @@ var X86 = {
|
|||
/*
|
||||
* The following bits apply only when SEG is set
|
||||
*/
|
||||
CODE: 0x0800, // set for CODE, clear for DATA
|
||||
ACCESSED: 0x0100, // set if accessed, clear if not accessed
|
||||
READABLE: 0x0200, // CODE: set if readable, clear if exec-only
|
||||
WRITEABLE: 0x0200, // DATA: set if writable, clear if read-only
|
||||
CONFORMING: 0x0400, // CODE: set if conforming, clear if not
|
||||
EXPDOWN: 0x0400, // DATA: set if expand-down, clear if not
|
||||
CODE: 0x0800, // set for CODE, clear for DATA
|
||||
ACCESSED: 0x0100, // set if accessed, clear if not accessed
|
||||
READABLE: 0x0200, // CODE: set if readable, clear if exec-only
|
||||
WRITABLE: 0x0200, // DATA: set if writable, clear if read-only
|
||||
CONFORMING: 0x0400, // CODE: set if conforming, clear if not
|
||||
EXPDOWN: 0x0400, // DATA: set if expand-down, clear if not
|
||||
/*
|
||||
* The following are all the possible (valid) types (well, except for the variations
|
||||
* of DATA and CODE where the ACCESSED bit (0x0100) may also be set)
|
||||
|
|
@ -116,23 +116,27 @@ var X86 = {
|
|||
GATE_INT: 0x0600,
|
||||
GATE_TRAP: 0x0700,
|
||||
DATA_READONLY: 0x1000,
|
||||
DATA_WRITEABLE: 0x1200,
|
||||
DATA_WRITABLE: 0x1200,
|
||||
DATA_EXPDOWN_READONLY: 0x1400,
|
||||
DATA_EXPDOWN_WRITEABLE: 0x1600,
|
||||
DATA_EXPDOWN_WRITABLE: 0x1600,
|
||||
CODE_EXECONLY: 0x1800,
|
||||
CODE_READABLE: 0x1a00,
|
||||
CODE_CONFORMING_EXECONLY: 0x1c00,
|
||||
CODE_CONFORMING_READABLE: 0x1e00
|
||||
},
|
||||
DPL: {
|
||||
MASK: 0x6000,
|
||||
SHIFT: 13
|
||||
MASK: 0x6000,
|
||||
SHIFT: 13
|
||||
},
|
||||
PRESENT: 0x8000
|
||||
PRESENT: 0x8000
|
||||
},
|
||||
EXT: { // descriptor extension word (reserved on the 80286; "must be zero")
|
||||
OFFSET: 0x6,
|
||||
MASK: 0xffff
|
||||
OFFSET: 0x6,
|
||||
LIMIT1619: 0x000f,
|
||||
AVAIL: 0x0010, // NOTE: set in various descriptors in OS/2
|
||||
DEFSIZE: 0x0040, // clear if default operand/address size is 16-bit, set if 32-bit
|
||||
GRANULARITY: 0x0080, // clear if limit is bytes, set if limit is 4Kb pages
|
||||
BASE2431: 0xff00
|
||||
}
|
||||
},
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -686,15 +686,15 @@ X86CPU.prototype.initProcessor = function()
|
|||
* opOUTSw, opENTER, and opLEAVE.
|
||||
*/
|
||||
this.nShiftCountMask = 0x1f; // on newer processors, all shift counts are MOD 32
|
||||
this.aOps[0x0F] = X86Help.opInvalid;
|
||||
this.aOps[0x0F] = X86OpXX.opInvalid;
|
||||
this.aOps[X86.OPCODE.PUSHA] = X86OpXX.opPUSHA;
|
||||
this.aOps[X86.OPCODE.POPA] = X86OpXX.opPOPA;
|
||||
this.aOps[X86.OPCODE.BOUND] = X86OpXX.opBOUND;
|
||||
this.aOps[0x63] = X86Help.opInvalid;
|
||||
this.aOps[0x64] = X86Help.opInvalid;
|
||||
this.aOps[0x65] = X86Help.opInvalid;
|
||||
this.aOps[0x66] = X86Help.opInvalid;
|
||||
this.aOps[0x67] = X86Help.opInvalid;
|
||||
this.aOps[0x63] = X86OpXX.opInvalid;
|
||||
this.aOps[0x64] = X86OpXX.opInvalid;
|
||||
this.aOps[0x65] = X86OpXX.opInvalid;
|
||||
this.aOps[0x66] = X86OpXX.opInvalid;
|
||||
this.aOps[0x67] = X86OpXX.opInvalid;
|
||||
this.aOps[X86.OPCODE.PUSH16]= X86OpXX.opPUSH16;
|
||||
this.aOps[X86.OPCODE.IMUL16]= X86OpXX.opIMUL16;
|
||||
this.aOps[X86.OPCODE.PUSH8] = X86OpXX.opPUSH8;
|
||||
|
|
@ -787,6 +787,13 @@ X86CPU.prototype.resetRegs = function()
|
|||
this.descIDT = {off: 0, sel: 0, acc: 0, maskPS: -1};
|
||||
this.nIOPL = 0; // this should be set before the first setPS() call
|
||||
|
||||
/*
|
||||
* This is set by opHelpFault() and reset (to -1) by resetRegs() and opIRET(); its initial purpose is to
|
||||
* "help" opHelpFault() determine when a nested fault should be converted into either a double-fault
|
||||
* (DF_FAULT) or a triple-fault (ie, a processor reset).
|
||||
*/
|
||||
this.nFault = -1;
|
||||
|
||||
/*
|
||||
* Segment registers used to be defined as separate variables (eg, regCS and regCS0 stored the
|
||||
* segment number and base physical address, respectively), but all segment registers are now defined
|
||||
|
|
@ -807,6 +814,10 @@ X86CPU.prototype.resetRegs = function()
|
|||
*
|
||||
* while the LDTR and TR are stored as special segment registers: segLDT and segTSS.
|
||||
*
|
||||
* So, yes, our GDTR and IDTR "registers" differ from other segment registers in that we do NOT record
|
||||
* the 16-bit limit specified by the LGDT or LIDT instructions; instead, we immediately calculate the limiting
|
||||
* address and record that instead.
|
||||
*
|
||||
* In addition to different CS:IP reset values, the CS base address must be set to the top of the 16Mb
|
||||
* address space rather than the top of the first 1Mb (which is why the MODEL_5170 ROM must be addressable
|
||||
* at both 0x0F0000 and 0xFF0000; see the ROM component's "alias" parameter).
|
||||
|
|
@ -1147,9 +1158,9 @@ X86CPU.prototype.setMemoryEnabled = function()
|
|||
*/
|
||||
X86CPU.prototype.verifyMemoryEnabled = function()
|
||||
{
|
||||
Component.assert(!(this.regAX & 0xffff0000) && !(this.regBX & 0xffff0000) && !(this.regCX & 0xffff0000) && !(this.regDX & 0xffff0000));
|
||||
Component.assert(!(this.regSI & 0xffff0000) && !(this.regDI & 0xffff0000) && !(this.regBP & 0xffff0000) && !(this.regSP & 0xffff0000));
|
||||
Component.assert((this.getEAByte == this.getEAByteEnabled && this.getEAWord == this.getEAWordEnabled && this.modEAByte == this.modEAByteEnabled && this.modEAWord == this.modEAWordEnabled && this.setEAByte == this.setEAByteEnabled && this.setEAWord == this.setEAWordEnabled), "verifyMemoryEnabled() failed");
|
||||
this.assert(!(this.regAX & 0xffff0000) && !(this.regBX & 0xffff0000) && !(this.regCX & 0xffff0000) && !(this.regDX & 0xffff0000));
|
||||
this.assert(!(this.regSI & 0xffff0000) && !(this.regDI & 0xffff0000) && !(this.regBP & 0xffff0000) && !(this.regSP & 0xffff0000));
|
||||
this.assert((this.getEAByte == this.getEAByteEnabled && this.getEAWord == this.getEAWordEnabled && this.modEAByte == this.modEAByteEnabled && this.modEAWord == this.modEAWordEnabled && this.setEAByte == this.setEAByteEnabled && this.setEAWord == this.setEAWordEnabled), "verifyMemoryEnabled() failed");
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1176,7 +1187,7 @@ X86CPU.prototype.getSeg = function(sName)
|
|||
* HACK: We return a fake segment register object in which only the base physical address is valid,
|
||||
* because that's all the caller provided (ie, we must be restoring from an older state).
|
||||
*/
|
||||
Component.assert(typeof sName == "number");
|
||||
if (DEBUG) this.assert(typeof sName == "number");
|
||||
return [0, sName, 0, 0, ""];
|
||||
}
|
||||
};
|
||||
|
|
@ -1193,12 +1204,14 @@ X86CPU.prototype.getSeg = function(sName)
|
|||
*
|
||||
* @this {X86CPU}
|
||||
* @param {number} nIDT
|
||||
* @return {boolean} true if successful, false if not
|
||||
* @return {boolean} true if successful, false if not (all failure cases currently limited to protected mode)
|
||||
*/
|
||||
X86CPU.prototype.loadIDTEntry = function(nIDT)
|
||||
{
|
||||
Component.assert(nIDT >= 0 && nIDT < 256);
|
||||
var offIDT;
|
||||
|
||||
if (DEBUG) this.assert(nIDT >= 0 && nIDT < 256);
|
||||
|
||||
if (this.regMSW & X86.MSW.PE) {
|
||||
offIDT = this.addrIDT + (nIDT << 3);
|
||||
if (offIDT + 7 <= this.addrIDTLimit) {
|
||||
|
|
@ -1213,20 +1226,26 @@ X86CPU.prototype.loadIDTEntry = function(nIDT)
|
|||
this.descIDT.maskPS = ~(X86.PS.NT | X86.PS.TF);
|
||||
break;
|
||||
default:
|
||||
if (DEBUG) this.assert(false);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
offIDT = this.addrIDT + (nIDT << 2);
|
||||
if (offIDT + 7 <= this.addrIDTLimit) {
|
||||
this.descIDT.off = this.getWord(offIDT);
|
||||
this.descIDT.sel = this.getWord(offIDT + 2);
|
||||
this.descIDT.maskPS = ~(X86.PS.TF | X86.PS.IF);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
if (DEBUG) this.assert(!this.addrIDT && this.addrIDTLimit == 0x03FF);
|
||||
/*
|
||||
* Intel documentation for INT/INTO under "REAL ADDRESS MODE EXCEPTIONS" says:
|
||||
*
|
||||
* "[T]he 80286 will shut down if the SP = 1, 3, or 5 before executing the INT or INTO instruction--due to lack of stack space"
|
||||
*
|
||||
* Huh? Why would real-mode care? See http://localhost:8088/pubs/pc/reference/intel/80286/progref/#page-260
|
||||
*/
|
||||
offIDT = this.addrIDT + (nIDT << 2);
|
||||
this.descIDT.off = this.getWord(offIDT);
|
||||
this.descIDT.sel = this.getWord(offIDT + 2);
|
||||
this.descIDT.maskPS = ~(X86.PS.TF | X86.PS.IF);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1323,7 +1342,7 @@ X86CPU.prototype.setIP = function(off)
|
|||
*/
|
||||
X86CPU.prototype.setCSIP = function(off, sel)
|
||||
{
|
||||
Component.assert((off & 0xffff) == off);
|
||||
if (DEBUG) this.assert((off & 0xffff) == off);
|
||||
this.regEIP = this.segCS.load(sel) + (this.regIP = off);
|
||||
if (PREFETCH) this.flushPrefetch(this.regEIP);
|
||||
};
|
||||
|
|
@ -1655,7 +1674,7 @@ X86CPU.prototype.setPS = function(regPS)
|
|||
/*
|
||||
* Assert that all requested flag bits now agree with our simulated (PS_INDIRECT) bits
|
||||
*/
|
||||
Component.assert((regPS & X86.PS.INDIRECT) == (this.getPS() & X86.PS.INDIRECT));
|
||||
if (DEBUG) this.assert((regPS & X86.PS.INDIRECT) == (this.getPS() & X86.PS.INDIRECT));
|
||||
|
||||
if (this.regPS & X86.PS.TF) {
|
||||
this.intFlags |= X86.INTFLAG.TRAP;
|
||||
|
|
@ -2043,8 +2062,8 @@ X86CPU.prototype.getBytePrefetch = function(addr)
|
|||
if (!EAFUNCS && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
|
||||
var b;
|
||||
if (!this.cbPrefetchQueued) {
|
||||
if (MAXDEBUG) Component.assert(addr == this.addrPrefetchHead, "X86CPU.getBytePrefetch(" + str.toHex(addr) + "): invalid head address (" + str.toHex(this.addrPrefetchHead) + ")");
|
||||
if (MAXDEBUG) Component.assert(this.iPrefetchTail == this.iPrefetchHead, "X86CPU.getBytePrefetch(" + str.toHex(addr) + "): head (" + this.iPrefetchHead + ") does not match tail (" + this.iPrefetchTail + ")");
|
||||
if (MAXDEBUG) this.assert(addr == this.addrPrefetchHead, "X86CPU.getBytePrefetch(" + str.toHex(addr) + "): invalid head address (" + str.toHex(this.addrPrefetchHead) + ")");
|
||||
if (MAXDEBUG) this.assert(this.iPrefetchTail == this.iPrefetchHead, "X86CPU.getBytePrefetch(" + str.toHex(addr) + "): head (" + this.iPrefetchHead + ") does not match tail (" + this.iPrefetchTail + ")");
|
||||
this.fillPrefetch(1);
|
||||
this.nBusCycles += 4;
|
||||
/*
|
||||
|
|
@ -2061,7 +2080,7 @@ X86CPU.prototype.getBytePrefetch = function(addr)
|
|||
}
|
||||
b = this.aPrefetch[this.iPrefetchTail] & 0xff;
|
||||
if (MAXDEBUG) this.messageDebugger(" getBytePrefetch[" + this.iPrefetchTail + "]: " + str.toHex(addr) + ":" + str.toHexByte(b));
|
||||
if (MAXDEBUG) Component.assert(addr == (this.aPrefetch[this.iPrefetchTail] >> 8), "X86CPU.getBytePrefetch(" + str.toHex(addr) + "): invalid tail address (" + str.toHex(this.aPrefetch[this.iPrefetchTail] >> 8) + ")");
|
||||
if (MAXDEBUG) this.assert(addr == (this.aPrefetch[this.iPrefetchTail] >> 8), "X86CPU.getBytePrefetch(" + str.toHex(addr) + "): invalid tail address (" + str.toHex(this.aPrefetch[this.iPrefetchTail] >> 8) + ")");
|
||||
this.iPrefetchTail = (this.iPrefetchTail + 1) & X86CPU.PREFETCH.MASK;
|
||||
this.cbPrefetchQueued--;
|
||||
return b;
|
||||
|
|
@ -2220,7 +2239,7 @@ X86CPU.prototype.popWord = function()
|
|||
*/
|
||||
X86CPU.prototype.pushWord = function(w)
|
||||
{
|
||||
Component.assert((w & 0xffff) == w);
|
||||
if (DEBUG) this.assert((w & 0xffff) == w);
|
||||
this.setSOWord(this.segSS, (this.regSP = (this.regSP - 2) & 0xffff), w);
|
||||
};
|
||||
|
||||
|
|
@ -2295,7 +2314,7 @@ X86CPU.prototype.pushWord = function(w)
|
|||
*/
|
||||
X86CPU.prototype.checkINTR = function()
|
||||
{
|
||||
Component.assert(this.intFlags);
|
||||
if (DEBUG) this.assert(this.intFlags);
|
||||
if (!(this.opFlags & X86.OPFLAG.NOINTR)) {
|
||||
if ((this.intFlags & X86.INTFLAG.INTR) && (this.regPS & X86.PS.IF)) {
|
||||
var nIDT = this.chipset.getIRRVector();
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
if (typeof module !== 'undefined') {
|
||||
var X86 = require("./x86");
|
||||
var X86Help = require("./x86help");
|
||||
var X86OpXX = require("./x86opxx");
|
||||
var Debugger = require("./debugger");
|
||||
}
|
||||
|
||||
|
|
@ -1239,7 +1240,7 @@ var X86Grps = {
|
|||
* @return {number}
|
||||
*/
|
||||
opGrpInvalid: function(dst, src) {
|
||||
X86Help.opInvalid.call(this);
|
||||
X86OpXX.opInvalid.call(this);
|
||||
return dst;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1249,7 +1250,7 @@ var X86Grps = {
|
|||
* @return {number}
|
||||
*/
|
||||
opGrpUndefined: function(dst, src) {
|
||||
X86Help.opUndefined.call(this);
|
||||
X86OpXX.opUndefined.call(this);
|
||||
return dst;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
if (typeof module !== 'undefined') {
|
||||
var X86 = require("./x86");
|
||||
var X86OpXX = require("./x86opxx");
|
||||
var Debugger = require("./debugger");
|
||||
}
|
||||
|
||||
|
|
@ -176,7 +177,7 @@ var X86Help = {
|
|||
*/
|
||||
opHelpLEA: function(dst, src) {
|
||||
if (this.regEA < 0) {
|
||||
X86Help.opUndefined.call(this);
|
||||
X86OpXX.opUndefined.call(this);
|
||||
return dst;
|
||||
}
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLEA;
|
||||
|
|
@ -190,7 +191,7 @@ var X86Help = {
|
|||
*/
|
||||
opHelpLDS: function(dst, src) {
|
||||
if (this.regEA < 0) {
|
||||
X86Help.opUndefined.call(this);
|
||||
X86OpXX.opUndefined.call(this);
|
||||
return dst;
|
||||
}
|
||||
this.setDS(this.getWord(this.regEA + 2));
|
||||
|
|
@ -205,7 +206,7 @@ var X86Help = {
|
|||
*/
|
||||
opHelpLES: function(dst, src) {
|
||||
if (this.regEA < 0) {
|
||||
X86Help.opUndefined.call(this);
|
||||
X86OpXX.opUndefined.call(this);
|
||||
return dst;
|
||||
}
|
||||
this.setES(this.getWord(this.regEA + 2));
|
||||
|
|
@ -223,7 +224,7 @@ var X86Help = {
|
|||
/*
|
||||
* Generate a #UD fault (INT 0x06: Undefined Opcode) if src is not a memory operand.
|
||||
*/
|
||||
X86Help.opInvalid.call(this);
|
||||
X86OpXX.opInvalid.call(this);
|
||||
return dst;
|
||||
}
|
||||
/*
|
||||
|
|
@ -237,7 +238,7 @@ var X86Help = {
|
|||
/*
|
||||
* The INT 0x05 handler must be called with CS:IP pointing to the BOUND instruction.
|
||||
*
|
||||
* TODO: Determine the cycle impact when a BOUND exception is triggered, over and above nOpCyclesBound.
|
||||
* TODO: Determine the cycle cost when a BOUND exception is triggered, over and above nOpCyclesBound.
|
||||
*/
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
X86Help.opHelpINT.call(this, X86.EXCEPTION.BOUND_ERR, null, 0);
|
||||
|
|
@ -416,6 +417,11 @@ var X86Help = {
|
|||
* @param {number} nCycles (in addition to the default of nOpCyclesInt)
|
||||
*/
|
||||
opHelpINT: function(nIDT, nError, nCycles) {
|
||||
/*
|
||||
* TODO: We assess the cycle cost up front, because if loadIDTEntry() fails and we end up in opHelpFault(),
|
||||
* no cost may get assessed. opHelpFault() needs to determine an appropriate cycle cost.
|
||||
*/
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesInt + nCycles;
|
||||
if (this.loadIDTEntry(nIDT)) {
|
||||
this.pushWord(this.getPS());
|
||||
this.regPS &= this.descIDT.maskPS;
|
||||
|
|
@ -423,11 +429,9 @@ var X86Help = {
|
|||
this.pushWord(this.regIP);
|
||||
if (nError != null) this.pushWord(nError);
|
||||
this.setCSIP(this.descIDT.off, this.descIDT.sel);
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesInt + nCycles;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* TODO: Now what?
|
||||
*/
|
||||
X86Help.opHelpFault.call(this, X86.EXCEPTION.GP_FAULT, (nIDT << 3) | X86.ERRCODE.IDT | X86.ERRCODE.EXT, true);
|
||||
},
|
||||
/**
|
||||
* opHelpLMSW(w)
|
||||
|
|
@ -460,7 +464,7 @@ var X86Help = {
|
|||
opHelpDIVOverflow: function() {
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
/*
|
||||
* TODO: Determine the proper cycle count
|
||||
* TODO: Determine the proper cycle cost.
|
||||
*/
|
||||
X86Help.opHelpINT.call(this, X86.EXCEPTION.DIV_ERR, null, 2);
|
||||
},
|
||||
|
|
@ -471,34 +475,61 @@ var X86Help = {
|
|||
* @param {boolean} [fHalt] will halt the CPU if true *and* a Debugger is loaded
|
||||
*/
|
||||
opHelpFault: function(nFault, nError, fHalt) {
|
||||
var fFault = false;
|
||||
if (this.model >= X86.MODEL_80186) {
|
||||
if (this.nFault < 0) {
|
||||
/*
|
||||
* Single-fault (error code is passed through, and the original instruction is restartable)
|
||||
*/
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
fFault = 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;
|
||||
fFault = true;
|
||||
} else {
|
||||
/*
|
||||
* Triple-fault (usually referred to in Intel literature as a "shutdown", but at least on the 80286,
|
||||
* it's actually a "reset")
|
||||
*/
|
||||
X86Help.opHelpFaultMessage.call(this, -1, 0, fHalt);
|
||||
this.resetRegs();
|
||||
return;
|
||||
}
|
||||
}
|
||||
X86Help.opHelpFaultMessage.call(this, nFault, nError, fHalt);
|
||||
if (fFault) X86Help.opHelpINT.call(this, this.nFault = nFault, nError, 0);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
* @param {number} nFault
|
||||
* @param {number} [nError]
|
||||
* @param {boolean} [fHalt] will halt the CPU if true *and* a Debugger is loaded
|
||||
*/
|
||||
opHelpFaultMessage: function(nFault, nError, fHalt) {
|
||||
if (DEBUGGER && this.dbg) {
|
||||
/*
|
||||
* NOTE: By using Debugger.message(), we have the option of setting "m halt on" and halting on messages like this.
|
||||
*/
|
||||
var bOpcode = this.bus.getByteDirect(this.regEIP);
|
||||
if (this.dbg.messageEnabled(Debugger.MESSAGE.CPU)) {
|
||||
this.dbg.message("Fault 0x" + str.toHexByte(nFault) + (nError != null? " (0x" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(this.bus.getByteDirect(this.regEIP)) + " at " + str.toHexAddr(this.regIP, this.segCS.sel));
|
||||
this.dbg.message("Fault 0x" + str.toHexByte(nFault) + (nError != null? " (0x" + str.toHexWord(nError) + ")" : "") + " on opcode 0x" + str.toHexByte(bOpcode) + " at " + str.toHexAddr(this.regIP, this.segCS.sel) + " (%" + str.toHex(this.regEIP) + ")");
|
||||
}
|
||||
if (fHalt) this.stopCPU();
|
||||
/*
|
||||
* OS/2 1.0 uses an INT3 (0xCC) opcode in conjunction with an invalid IDT to trigger a triple-fault
|
||||
* reset and return to real-mode, and these resets happen quite frequently during boot; for example, OS/2
|
||||
* startup messages are displayed using INT 0x10 BIOS calls for each character, and each call requires a
|
||||
* round-trip mode switch.
|
||||
*
|
||||
* Since we really only want to halt on "bad" faults, not "good" (ie, intentional) faults, we take
|
||||
* advantage of the fact that all 3 faults comprising the triple-fault point to the INT3 (0xCC) opcode,
|
||||
* and so whenever we see that opcode, we ignore the caller's fHalt flag.
|
||||
*/
|
||||
if (fHalt && bOpcode != X86.OPCODE.INT3) this.dbg.stopCPU();
|
||||
}
|
||||
if (this.model >= X86.MODEL_80186) {
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
X86Help.opHelpINT.call(this, nFault, nError, 0);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
opInvalid: function() {
|
||||
X86Help.opHelpFault.call(this, X86.EXCEPTION.UD_FAULT);
|
||||
this.stopCPU();
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
opUndefined: function() {
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
this.setError("Undefined opcode 0x" + str.toHexByte(this.bus.getByteDirect(this.regEIP)) + " at " + str.toHexAddr(this.regIP, this.segCS.sel));
|
||||
this.stopCPU();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ if (typeof module !== 'undefined') {
|
|||
var X86Grps = require("./x86grps");
|
||||
var X86Help = require("./x86help");
|
||||
var X86Mods = require("./x86mods");
|
||||
var X86OpXX = require("./x86opxx");
|
||||
}
|
||||
|
||||
var X86Op0F = {
|
||||
|
|
@ -218,7 +219,7 @@ var X86Op0F = {
|
|||
if (this.segVER.load(dst, true) >= 0) {
|
||||
/*
|
||||
* Verify that this is a readable segment; that is, of these four combinations (code+readable,
|
||||
* code+nonreadable, data+writeable, date+nonwriteable), make sure we're not the second combination.
|
||||
* code+nonreadable, data+writable, date+nonwritable), make sure we're not the second combination.
|
||||
*/
|
||||
if ((this.segVER.acc & (X86.DESC.ACC.TYPE.READABLE | X86.DESC.ACC.TYPE.CODE)) != X86.DESC.ACC.TYPE.CODE) {
|
||||
/*
|
||||
|
|
@ -253,9 +254,9 @@ var X86Op0F = {
|
|||
this.nStepCycles -= (14 + (this.regEA < 0? 0 : 2));
|
||||
if (this.segVER.load(dst, true) >= 0) {
|
||||
/*
|
||||
* Verify that this is a writeable data segment
|
||||
* Verify that this is a writable data segment
|
||||
*/
|
||||
if ((this.segVER.acc & (X86.DESC.ACC.TYPE.WRITEABLE | X86.DESC.ACC.TYPE.CODE)) == X86.DESC.ACC.TYPE.WRITEABLE) {
|
||||
if ((this.segVER.acc & (X86.DESC.ACC.TYPE.WRITABLE | X86.DESC.ACC.TYPE.CODE)) == X86.DESC.ACC.TYPE.WRITABLE) {
|
||||
/*
|
||||
* DPL must be greater than or equal to (have less or the same privilege as) both the current
|
||||
* privilege level and the selector's RPL.
|
||||
|
|
@ -277,7 +278,7 @@ var X86Op0F = {
|
|||
*/
|
||||
opSGDT: function(dst, src) {
|
||||
if (this.regEA < 0) {
|
||||
X86Help.opInvalid.call(this);
|
||||
X86OpXX.opInvalid.call(this);
|
||||
} else {
|
||||
/*
|
||||
* We don't need to setWord() the first word of the operand, because the ModRM group decoder that calls
|
||||
|
|
@ -331,7 +332,7 @@ var X86Op0F = {
|
|||
*/
|
||||
opSIDT: function(dst, src) {
|
||||
if (this.regEA < 0) {
|
||||
X86Help.opInvalid.call(this);
|
||||
X86OpXX.opInvalid.call(this);
|
||||
} else {
|
||||
/*
|
||||
* We don't need to setWord() the first word of the operand, because the ModRM group decoder that calls
|
||||
|
|
@ -364,7 +365,7 @@ var X86Op0F = {
|
|||
*/
|
||||
opLGDT: function(dst, src) {
|
||||
if (this.regEA < 0) {
|
||||
X86Help.opInvalid.call(this);
|
||||
X86OpXX.opInvalid.call(this);
|
||||
} else {
|
||||
this.addrGDT = this.getWord(this.regEA + 2) | (this.getByte(this.regEA + 4) << 16);
|
||||
this.addrGDTLimit = this.addrGDT + dst;
|
||||
|
|
@ -387,7 +388,7 @@ var X86Op0F = {
|
|||
*/
|
||||
opLIDT: function(dst, src) {
|
||||
if (this.regEA < 0) {
|
||||
X86Help.opInvalid.call(this);
|
||||
X86OpXX.opInvalid.call(this);
|
||||
} else {
|
||||
this.addrIDT = this.getWord(this.regEA + 2) | (this.getByte(this.regEA + 4) << 16);
|
||||
this.addrIDTLimit = this.addrIDT + dst;
|
||||
|
|
@ -422,73 +423,73 @@ var X86Op0F = {
|
|||
|
||||
X86Op0F.aOps0F = [
|
||||
X86Op0F.opGRP6, X86Op0F.opGRP7, X86Op0F.opLAR, X86Op0F.opLSL, // 0x00-0x03
|
||||
X86Help.opUndefined, X86Op0F.opLOADALL, X86Help.opUndefined, X86Help.opUndefined, // 0x04-0x07
|
||||
X86OpXX.opUndefined, X86Op0F.opLOADALL, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x04-0x07
|
||||
/*
|
||||
* On all processors (except the 8086/8088, of course), 0x0F,0x0B is also referred to as "UD2": an
|
||||
* instruction guaranteed to raise a #UD (Invalid Opcode) exception (INT 0x06) on all future x86 processors.
|
||||
*/
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opInvalid, // 0x08-0x0B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x0C-0x0F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x10-0x13
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x14-0x17
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x18-0x1B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x1C-0x1F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x20-0x23
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x24-0x27
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x28-0x2B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x2C-0x2F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x30-0x33
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x34-0x37
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x38-0x3B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x3C-0x3F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x40-0x43
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x44-0x47
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x48-0x4B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x4C-0x4F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x50-0x53
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x54-0x57
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x58-0x5B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x5C-0x5F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x60-0x63
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x64-0x67
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x68-0x6B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x6C-0x6F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x70-0x73
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x74-0x77
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x78-0x7B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x7C-0x7F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x80-0x83
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x84-0x87
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x88-0x8B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x8C-0x8F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x90-0x93
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x94-0x97
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x98-0x9B
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0x9C-0x9F
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xA0-0xA3
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xA4-0xA7
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xA8-0xAB
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xAC-0xAF
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xB0-0xB3
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xB4-0xB7
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xB8-0xBB
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xBC-0xBF
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xC0-0xC3
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xC4-0xC7
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xC8-0xCB
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xCC-0xCF
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xD0-0xD3
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xD4-0xD7
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xD8-0xDB
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xDC-0xDF
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xE0-0xE3
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xE4-0xE7
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xE8-0xEB
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xEC-0xEF
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xF0-0xF3
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xF4-0xF7
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, // 0xF8-0xFB
|
||||
X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined, X86Help.opUndefined // 0xFC-0xFF
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opInvalid, // 0x08-0x0B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x0C-0x0F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x10-0x13
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x14-0x17
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x18-0x1B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x1C-0x1F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x20-0x23
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x24-0x27
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x28-0x2B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x2C-0x2F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x30-0x33
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x34-0x37
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x38-0x3B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x3C-0x3F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x40-0x43
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x44-0x47
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x48-0x4B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x4C-0x4F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x50-0x53
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x54-0x57
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x58-0x5B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x5C-0x5F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x60-0x63
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x64-0x67
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x68-0x6B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x6C-0x6F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x70-0x73
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x74-0x77
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x78-0x7B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x7C-0x7F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x80-0x83
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x84-0x87
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x88-0x8B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x8C-0x8F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x90-0x93
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x94-0x97
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x98-0x9B
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0x9C-0x9F
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xA0-0xA3
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xA4-0xA7
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xA8-0xAB
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xAC-0xAF
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xB0-0xB3
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xB4-0xB7
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xB8-0xBB
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xBC-0xBF
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xC0-0xC3
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xC4-0xC7
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xC8-0xCB
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xCC-0xCF
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xD0-0xD3
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xD4-0xD7
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xD8-0xDB
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xDC-0xDF
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xE0-0xE3
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xE4-0xE7
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xE8-0xEB
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xEC-0xEF
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xF0-0xF3
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xF4-0xF7
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, // 0xF8-0xFB
|
||||
X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined, X86OpXX.opUndefined // 0xFC-0xFF
|
||||
];
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1741,7 +1741,7 @@ var X86OpXX = {
|
|||
this.regMD16 = this.segDS.sel;
|
||||
break;
|
||||
default:
|
||||
X86Help.opUndefined.call(this);
|
||||
X86OpXX.opUndefined.call(this);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
|
@ -1787,7 +1787,7 @@ var X86OpXX = {
|
|||
break;
|
||||
default:
|
||||
if (this.model >= X86.MODEL_80286) {
|
||||
X86Help.opInvalid.call(this);
|
||||
X86OpXX.opInvalid.call(this);
|
||||
return;
|
||||
}
|
||||
switch(reg) {
|
||||
|
|
@ -1987,7 +1987,7 @@ var X86OpXX = {
|
|||
/*
|
||||
* TODO: Implement
|
||||
*/
|
||||
X86Help.opUndefined.call(this);
|
||||
X86OpXX.opUndefined.call(this);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -2032,7 +2032,7 @@ var X86OpXX = {
|
|||
if (ah & X86.PS.ZF) this.setZF(); else this.clearZF();
|
||||
if (ah & X86.PS.SF) this.setSF(); else this.clearSF();
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesLAHF;
|
||||
Component.assert((this.getPS() & X86.PS.SAHF) == (ah & X86.PS.SAHF));
|
||||
if (DEBUG) this.assert((this.getPS() & X86.PS.SAHF) == (ah & X86.PS.SAHF));
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -2846,10 +2846,8 @@ var X86OpXX = {
|
|||
opIRET: function() {
|
||||
this.setCSIP(this.popWord(), this.popWord());
|
||||
this.setPS(this.popWord());
|
||||
this.nFault = -1;
|
||||
if (this.cIntReturn) this.checkIntReturn(this.regEIP);
|
||||
/*
|
||||
* NOTE: I'm assuming that neither POPF nor IRET are required to set NOINTR like STI does.
|
||||
*/
|
||||
this.nStepCycles -= this.CYCLES.nOpCyclesIRet;
|
||||
},
|
||||
/**
|
||||
|
|
@ -3159,7 +3157,7 @@ var X86OpXX = {
|
|||
* I still treat this as undefined, until I can verify the behavior on real hardware.
|
||||
*/
|
||||
opINT1: function() {
|
||||
X86Help.opUndefined.call(this);
|
||||
X86OpXX.opUndefined.call(this);
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
|
|
@ -3353,6 +3351,21 @@ var X86OpXX = {
|
|||
opGRP4w: function() {
|
||||
X86Mods.aOpModsGrpWord[this.getIPByte()].call(this, X86Grps.aOpGRP4w, X86Grps.opGrpNoSrc);
|
||||
if (EAFUNCS) this.setEAWord = this.setEAWordEnabled;
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
opInvalid: function() {
|
||||
X86Help.opHelpFault.call(this, X86.EXCEPTION.UD_FAULT);
|
||||
this.stopCPU();
|
||||
},
|
||||
/**
|
||||
* @this {X86CPU}
|
||||
*/
|
||||
opUndefined: function() {
|
||||
this.setIP(this.opEA - this.segCS.base);
|
||||
this.setError("Undefined opcode 0x" + str.toHexByte(this.bus.getByteDirect(this.regEIP)) + " at " + str.toHexAddr(this.regIP, this.segCS.sel));
|
||||
this.stopCPU();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ X86Seg.loadReal = function loadReal(sel, fSuppress)
|
|||
* This replaces the segment's default load() function whenever the segment is notified via updateAccess() by the
|
||||
* CPU's setProtMode() that the processor is now in protected-mode.
|
||||
*
|
||||
* Segments in protected-mode are referenced by selectors, which are indexes into descriptor tables (GDT, LDT, IDT) whose
|
||||
* descriptors are 4-word (8-byte) entries:
|
||||
* Segments in protected-mode are referenced by selectors, which are indexes into descriptor tables (GDT, LDT, IDT)
|
||||
* whose descriptors are 4-word (8-byte) entries:
|
||||
*
|
||||
* word 0: segment limit (0-15)
|
||||
* word 1: base address low
|
||||
|
|
@ -112,7 +112,7 @@ X86Seg.loadProt = function loadProt(sel, fSuppress)
|
|||
addrDTLimit = this.cpu.addrGDTLimit;
|
||||
} else {
|
||||
addrDT = this.cpu.segLDT.base;
|
||||
addrDTLimit = this.cpu.segLDT.limit;
|
||||
addrDTLimit = addrDT + this.cpu.segLDT.limit;
|
||||
}
|
||||
var addrDesc = addrDT + (sel & X86.SEL.MASK);
|
||||
if (addrDesc + 7 <= addrDTLimit) {
|
||||
|
|
@ -291,8 +291,9 @@ X86Seg.prototype.loadDesc8 = function(sel, addrDesc)
|
|||
var ext = (DEBUG? this.cpu.getWord(addrDesc + X86.DESC.EXT.OFFSET) : 0);
|
||||
|
||||
if (DEBUG) {
|
||||
this.cpu.messageDebugger("loadDesc8(" + this.sName + "): base=" + str.toHex(base) + " limit=" + str.toHexWord(limit) + " acc=" + str.toHexWord(acc) + (ext? " ext=" + str.toHexWord(ext) : ""));
|
||||
Component.assert(!ext);
|
||||
var ch = (this.sName.length < 3? " " : "");
|
||||
this.cpu.messageDebugger("loadDesc8(" + this.sName + "):" + ch + " base=" + str.toHex(base) + " limit=" + str.toHexWord(limit) + " acc=" + str.toHexWord(acc) + (ext? " ext=" + str.toHexWord(ext) : ""));
|
||||
// this.cpu.assert(!ext);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -400,9 +401,9 @@ X86Seg.prototype.updateAccess = function(fProt)
|
|||
this.checkWrite = X86Seg.checkReadProtDisabled;
|
||||
}
|
||||
/*
|
||||
* If the CODE bit is set, or the the WRITEABLE bit is not set, then disallow writes
|
||||
* If the CODE bit is set, or the the WRITABLE bit is not set, then disallow writes
|
||||
*/
|
||||
if ((this.acc & X86.DESC.ACC.TYPE.CODE) || !(this.acc & X86.DESC.ACC.TYPE.WRITEABLE)) {
|
||||
if ((this.acc & X86.DESC.ACC.TYPE.CODE) || !(this.acc & X86.DESC.ACC.TYPE.WRITABLE)) {
|
||||
this.checkWrite = X86Seg.checkWriteProtDisabled;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,11 +63,6 @@ if (typeof module !== 'undefined') {
|
|||
/**
|
||||
* Component(type, parms, constructor)
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} type
|
||||
* @param {Object} [parms]
|
||||
* @param {Object} [constructor]
|
||||
*
|
||||
* A Component object requires:
|
||||
*
|
||||
* type: a user-defined type name (eg, "CPU")
|
||||
|
|
@ -79,6 +74,11 @@ if (typeof module !== 'undefined') {
|
|||
* comment: component comment string (default is undefined)
|
||||
*
|
||||
* Subclasses that use Component.subclass() to extend Component will likely have additional (parms) properties.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} type
|
||||
* @param {Object} [parms]
|
||||
* @param {Object} [constructor]
|
||||
*/
|
||||
function Component(type, parms, constructor)
|
||||
{
|
||||
|
|
@ -110,9 +110,8 @@ function Component(type, parms, constructor)
|
|||
this[type] = constructor;
|
||||
|
||||
/*
|
||||
* TODO: Decide how to reintegrate this code into the components that still want it....
|
||||
*
|
||||
if (this.initStep) this.initStep(parms);
|
||||
* Gather all the various component flags (booleans) into a single "flags" object, and encourage
|
||||
* subclasses to do the same, to reduce the property clutter we have to wade through while debugging.
|
||||
*/
|
||||
this.aFlags = {
|
||||
fReady: false,
|
||||
|
|
@ -151,8 +150,8 @@ Component.parmsURL = web.getURLParameters();
|
|||
*/
|
||||
Component.inherit = function(p)
|
||||
{
|
||||
if (window) { // an alternative to "if (typeof window === 'undefined')" if require("defines") has been invoked
|
||||
if (!p) throw new TypeError(); // TODO: Why does this barf under Node?
|
||||
if (window) {
|
||||
if (!p) throw new TypeError();
|
||||
if (Object.create) {
|
||||
return Object.create(p);
|
||||
}
|
||||
|
|
@ -257,8 +256,11 @@ Component.log = function(s, type)
|
|||
/**
|
||||
* Component.assert(f, s)
|
||||
*
|
||||
* Used to verify conditions that must be true (for DEBUG builds only; compiled builds should automatically have all
|
||||
* references to Component.assert() removed).
|
||||
* Verifies conditions that must be true (for DEBUG builds only).
|
||||
*
|
||||
* The Closure Compiler should automatically remove all references to Component.assert() in non-DEBUG builds.
|
||||
*
|
||||
* TODO: Add a task to the build process that "asserts" there are no occurrences of "assertion failure" in the final code.
|
||||
*
|
||||
* @param {boolean} f is the expression we are asserting to be true
|
||||
* @param {string} [s] is description of the assertion on failure
|
||||
|
|
@ -268,7 +270,7 @@ Component.assert = function(f, s)
|
|||
if (DEBUG) {
|
||||
if (!f) {
|
||||
/*
|
||||
* TODO: An accompanying source file/line number/function call would be nice, if there was a browser-independent way....
|
||||
* TODO: An accompanying source file/line number/function call (eg, stack trace) would be nice.
|
||||
*/
|
||||
if (!s) s = "assertion failure";
|
||||
Component.log(s);
|
||||
|
|
@ -465,7 +467,7 @@ Component.getComponentParms = function(element)
|
|||
* element.removeAttribute("data-value");
|
||||
* }
|
||||
*/
|
||||
} catch (e) {
|
||||
} catch(e) {
|
||||
Component.error(e.message + " (" + sParms + ")");
|
||||
}
|
||||
}
|
||||
|
|
@ -693,6 +695,49 @@ Component.prototype = {
|
|||
Component.log(s, type || this.id || this.type);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* assert(f, s)
|
||||
*
|
||||
* Verifies conditions that must be true (for DEBUG builds only).
|
||||
*
|
||||
* WARNING: Make sure you preface all calls to this.assert() with "if (DEBUG)", because unlike Component.assert(),
|
||||
* the Closure Compiler can't be sure that this instance method hasn't been overridden, so it refuses to treat it as
|
||||
* dead code in non-DEBUG builds.
|
||||
*
|
||||
* TODO: Add a task to the build process that "asserts" there are no occurrences of "assertion failure" in the final code.
|
||||
*
|
||||
* @param {boolean} f is the expression we are asserting to be true
|
||||
* @param {string} [s] is description of the assertion on failure
|
||||
*/
|
||||
assert: function(f, s) {
|
||||
if (DEBUG) {
|
||||
if (!f) {
|
||||
/*
|
||||
* TODO: An accompanying source file/line number/function call (eg, stack trace) would be nice.
|
||||
*/
|
||||
if (!s) s = "assertion failure in " + (this.id || this.type);
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.stopCPU(s);
|
||||
/*
|
||||
* Why do we throw an Error only to immediately catch it and ignore it? Simply to give our IDE
|
||||
* the opportunity to stop and smell the roses. If the user has no desire to stop on assertions,
|
||||
* then yes, consider this a giant NO-OP.
|
||||
*/
|
||||
try {
|
||||
throw new Error(s);
|
||||
} catch(e) {}
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* If there's no Debugger, or the current component didn't bother saving a reference to the Debugger
|
||||
* (eg, in its initBus() handler), then this component-level assert() the same as the class-level assert(),
|
||||
* except for the (slightly) more detailed log() message.
|
||||
*/
|
||||
this.log(s);
|
||||
throw new Error(s);
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* println(s, type)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ var DEBUG = true; // this @define is overridden by the Closure Com
|
|||
var MAXDEBUG = false; // this @define is overridden by the Closure Compiler (to false) to remove MAXDEBUG-only code
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
global.window = false;
|
||||
global.window = false; // provides an alternative "if (typeof window === 'undefined')" (ie, "if (window) ...")
|
||||
global.APPNAME = APPNAME;
|
||||
global.APPVERSION = APPVERSION;
|
||||
global.SITEHOST = SITEHOST;
|
||||
|
|
|
|||
|
|
@ -107,8 +107,8 @@
|
|||
"./modules/pcjs/lib/x86grps.js",
|
||||
"./modules/pcjs/lib/x86help.js",
|
||||
"./modules/pcjs/lib/x86mods.js",
|
||||
"./modules/pcjs/lib/x86op0f.js",
|
||||
"./modules/pcjs/lib/x86opxx.js",
|
||||
"./modules/pcjs/lib/x86op0f.js",
|
||||
"./modules/pcjs/lib/chipset.js",
|
||||
"./modules/pcjs/lib/rom.js",
|
||||
"./modules/pcjs/lib/ram.js",
|
||||
|
|
|
|||
Loading…
Reference in a new issue