Implemented 80286 LOADALL

This commit is contained in:
Jeff Parsons 2014-11-01 17:12:20 -07:00 committed by jeffpar
commit 5dce2a1a23
31 changed files with 1831 additions and 1765 deletions

View file

@ -143,14 +143,14 @@ function X86CPU(parmsCPU) {
* stepCPU() call, but it's good form to do so.
*/
this.nBurstCycles = 0;
this.fComplete = this.fDebugCheck = false;
this.aFlags.fComplete = this.aFlags.fDebugCheck = false;
/*
* We're just declaring aMemBlocks and associated Bus parameters here; they'll be initialized by initMemory()
* when the Bus is initialized.
*/
this.aMemBlocks = [];
this.addrLimit = this.addrMask = this.blockShift = this.blockLimit = this.blockMask = 0;
this.addrMemMask = this.blockShift = this.blockLimit = this.blockMask = 0;
/*
* Establish all the default get/set functions for accessing memory; see this function for details.
@ -467,7 +467,7 @@ X86CPU.PREFETCH.MASK = 0x7; // (X86CPU.PREFETCH.ARRAY - 1)
X86CPU.prototype.initMemory = function(aMemBlocks, addrLimit, blockShift, blockLimit, blockMask)
{
this.aMemBlocks = aMemBlocks;
this.addrLimit = this.addrMask = addrLimit;
this.addrMemMask = addrLimit;
this.blockShift = blockShift;
this.blockLimit = blockLimit;
this.blockMask = blockMask;
@ -491,7 +491,7 @@ X86CPU.prototype.initMemory = function(aMemBlocks, addrLimit, blockShift, blockL
*/
X86CPU.prototype.setAddressMask = function(addrMask)
{
this.addrMask = addrMask;
this.addrMemMask = addrMask;
};
/**
@ -727,7 +727,7 @@ X86CPU.prototype.initProcessor = function()
*/
X86CPU.prototype.reset = function()
{
if (this.fRunning) this.haltCPU();
if (this.aFlags.fRunning) this.haltCPU();
this.resetRegs();
this.resetCycles();
this.clearError(); // clear any fatal error/exception that setError() may have flagged
@ -760,9 +760,6 @@ X86CPU.prototype.reset = function()
* which takes both an offset and a segment, or setIP(), whichever is appropriate; in unusual cases where only
* segCS is changing (eg, undocumented 8086 opcodes), use setCS().
*
* On the 80286, another "register" that mirrors segCS is nCPL: whenever CS is updated, nCPL is updated
* with the CS selector's access level.
*
* The other segment registers (DS, SS and ES) have similar setters (for segDS, segSS and segES), but those
* functions do not mirror any special segment:offset values in the same way that regEIP mirrors CS:IP.
*
@ -827,7 +824,7 @@ X86CPU.prototype.resetRegs = function()
/*
* This resets the Processor Status flags (regPS), along with all the internal "result registers";
* we've taken care to ensure that both nCPL and nIOPL are initialized before this first setPS() call.
* we've taken care to ensure that both segCS.cpl and nIOPL are initialized before this first setPS() call.
*/
this.setPS(0);
@ -924,7 +921,7 @@ X86CPU.prototype.checkIntNotify = function(nInt)
}
}
}
else if (DEBUGGER && this.fDebugCheck) {
else if (DEBUGGER && this.aFlags.fDebugCheck) {
/*
* Enabling MESSAGE_INT messages is one of the criteria that's also included in fDebugCheck, so for maximum
* speed, we check fDebugCheck first.
@ -1007,10 +1004,10 @@ X86CPU.prototype.setProtMode = function(fProt)
} else {
X86Op0F.aOpGRP6 = X86Op0F.aOpGRP6Real;
}
this.segCS.setProt(fProt);
this.segDS.setProt(fProt);
this.segSS.setProt(fProt);
this.segES.setProt(fProt);
this.segCS.updateAccess(fProt);
this.segDS.updateAccess(fProt);
this.segSS.updateAccess(fProt);
this.segES.updateAccess(fProt);
};
/**
@ -1048,7 +1045,6 @@ X86CPU.prototype.restoreProtMode = function(a)
this.segLDT.restore(a[5]);
this.segTSS.restore(a[6]);
this.nIOPL = a[7];
this.nCPL = this.segCS.level;
this.setProtMode();
}
};
@ -1122,7 +1118,7 @@ X86CPU.prototype.restore = function(data)
/**
* setMemoryEnabled()
*
* Set the default EA memory access functions (enabled vs. disabled). When FASTDISABLE is true, assorted
* Set the default EA memory access functions (enabled vs. disabled). When EAFUNCS is true, assorted
* CPU opcode functions override the default functions whenever a CPU operation needs to temporarily disable the
* "get" of a source operand (or the "set" of a destination operand, as in the case of a CMP instruction).
*
@ -1248,7 +1244,6 @@ X86CPU.prototype.loadIDTEntry = function(nIDT)
X86CPU.prototype.setCS = function(sel)
{
this.regEIP = this.segCS.load(sel) + this.regIP;
this.nCPL = this.segCS.level;
this.opFlags |= this.OPFLAG_NOINTR8086;
if (PREFETCH) this.flushPrefetch(this.regEIP);
};
@ -1330,7 +1325,6 @@ X86CPU.prototype.setCSIP = function(off, sel)
{
Component.assert((off & 0xffff) == off);
this.regEIP = this.segCS.load(sel) + (this.regIP = off);
this.nCPL = this.segCS.level;
if (PREFETCH) this.flushPrefetch(this.regEIP);
};
@ -1646,13 +1640,13 @@ X86CPU.prototype.setPS = function(regPS)
* Since PS.IOPL and PS.IF are part of PS.DIRECT, we need to take care of any 80286-specific checks before
* setting the PS.DIRECT bits. Specifically, PS.IOPL is unchanged if CPL > 0, and PS.IF is unchanged if CPL > IOPL.
*/
if (!this.nCPL) {
if (!this.segCS.cpl) {
this.nIOPL = (regPS & X86.PS.IOPL.MASK) >> X86.PS.IOPL.SHIFT; // IOPL allowed to change
if (this.nIOPL && !(this.regMSW & X86.MSW.PE)) this.nIOPL = 0; // effective IOPL remains 0
} else {
regPS = (regPS & ~X86.PS.IOPL.MASK) | (this.regPS & X86.PS.IOPL.MASK); // IOPL not allowed to change
}
if (this.nCPL > this.nIOPL) {
if (this.segCS.cpl > this.nIOPL) {
regPS = (regPS & ~X86.PS.IF) | (this.regPS & X86.PS.IF); // IF not allowed to change
}
@ -1744,7 +1738,7 @@ X86CPU.prototype.setBinding = function(sHTMLClass, sHTMLType, sBinding, control)
*/
X86CPU.prototype.getByte = function(addr)
{
return this.aMemBlocks[(addr & this.addrMask) >> this.blockShift].readByte(addr & this.blockLimit);
return this.aMemBlocks[(addr & this.addrMemMask) >> this.blockShift].readByte(addr & this.blockLimit);
};
/**
@ -1757,7 +1751,7 @@ X86CPU.prototype.getByte = function(addr)
X86CPU.prototype.getWord = function(addr)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.addrMask) >> this.blockShift;
var iBlock = (addr & this.addrMemMask) >> this.blockShift;
/*
* On the 8088, it takes 4 cycles to read the additional byte REGARDLESS whether the address is odd or even.
*
@ -1779,7 +1773,7 @@ X86CPU.prototype.getWord = function(addr)
*/
X86CPU.prototype.setByte = function(addr, b)
{
this.aMemBlocks[(addr & this.addrMask) >> this.blockShift].writeByte(addr & this.blockLimit, b & 0xff);
this.aMemBlocks[(addr & this.addrMemMask) >> this.blockShift].writeByte(addr & this.blockLimit, b & 0xff);
};
/**
@ -1792,7 +1786,7 @@ X86CPU.prototype.setByte = function(addr, b)
X86CPU.prototype.setWord = function(addr, w)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.addrMask) >> this.blockShift;
var iBlock = (addr & this.addrMemMask) >> this.blockShift;
/*
* On the 8088, it takes 4 cycles to write the additional byte REGARDLESS whether the address is odd or even.
*
@ -1815,7 +1809,7 @@ X86CPU.prototype.setWord = function(addr, w)
* @param {number} off is a segment-relative offset
* @return {number}
*
X86CPU.prototype.getEAByteDisabled = function(seg, off)
X86CPU.prototype.getEAByteDisabled = function getEAByteDisabled(seg, off)
{
this.segEA = seg;
this.offEA = off;
@ -1836,7 +1830,7 @@ X86CPU.prototype.getEAByteDisabled = function(seg, off)
* @param {number} off is a segment-relative offset
* @return {number}
*/
X86CPU.prototype.getEAWordDisabled = function(seg, off)
X86CPU.prototype.getEAWordDisabled = function getEAWordDisabled(seg, off)
{
this.segEA = seg;
this.offEA = off;
@ -1855,7 +1849,7 @@ X86CPU.prototype.getEAWordDisabled = function(seg, off)
* @param {number} off is a segment-relative offset
* @return {number}
*/
X86CPU.prototype.modEAByteDisabled = function(seg, off)
X86CPU.prototype.modEAByteDisabled = function modEADisabled(seg, off)
{
this.segEA = seg;
this.offEA = off;
@ -1874,7 +1868,7 @@ X86CPU.prototype.modEAWordDisabled = X86CPU.prototype.modEAByteDisabled;
* @this {X86CPU}
* @param {number} w is the word (16-bit) value to write (ignored)
*/
X86CPU.prototype.setEAByteDisabled = function(w)
X86CPU.prototype.setEAByteDisabled = function setEAByteDisabled(w)
{
};
@ -1884,7 +1878,7 @@ X86CPU.prototype.setEAByteDisabled = function(w)
* @this {X86CPU}
* @param {number} w is the word (16-bit) value to write (ignored)
*/
X86CPU.prototype.setEAWordDisabled = function(w)
X86CPU.prototype.setEAWordDisabled = function setEAWordDisabled(w)
{
};
@ -1896,11 +1890,11 @@ X86CPU.prototype.setEAWordDisabled = function(w)
* @param {number} off is a segment-relative offset
* @return {number} byte (8-bit) value at that address
*/
X86CPU.prototype.getEAByteEnabled = function(seg, off)
X86CPU.prototype.getEAByteEnabled = function getEAByteEnabled(seg, off)
{
this.segEA = seg;
this.regEA = seg.checkRead(this.offEA = off, 0);
if (!FASTDISABLE && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
if (!EAFUNCS && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
return this.getByte(this.regEA);
};
@ -1912,11 +1906,11 @@ X86CPU.prototype.getEAByteEnabled = function(seg, off)
* @param {number} off is a segment-relative offset
* @return {number} word (16-bit) value at that address
*/
X86CPU.prototype.getEAWordEnabled = function(seg, off)
X86CPU.prototype.getEAWordEnabled = function getEAWordEnabled(seg, off)
{
this.segEA = seg;
this.regEA = seg.checkRead(this.offEA = off, 1);
if (!FASTDISABLE && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
if (!EAFUNCS && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
return this.getWord(this.regEA);
};
@ -1928,11 +1922,11 @@ X86CPU.prototype.getEAWordEnabled = function(seg, off)
* @param {number} off is a segment-relative offset
* @return {number} byte (8-bit) value at that address
*/
X86CPU.prototype.modEAByteEnabled = function(seg, off)
X86CPU.prototype.modEAByteEnabled = function modEAByteEnabled(seg, off)
{
this.segEA = seg;
this.regEAWrite = this.regEA = seg.checkRead(this.offEA = off, 0);
if (!FASTDISABLE && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
if (!EAFUNCS && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
return this.getByte(this.regEA);
};
@ -1944,11 +1938,11 @@ X86CPU.prototype.modEAByteEnabled = function(seg, off)
* @param {number} off is a segment-relative offset
* @return {number} word (16-bit) value at that address
*/
X86CPU.prototype.modEAWordEnabled = function(seg, off)
X86CPU.prototype.modEAWordEnabled = function modEAWordEnabled(seg, off)
{
this.segEA = seg;
this.regEAWrite = this.regEA = seg.checkRead(this.offEA = off, 1);
if (!FASTDISABLE && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
if (!EAFUNCS && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
return this.getWord(this.regEA);
};
@ -1958,9 +1952,9 @@ X86CPU.prototype.modEAWordEnabled = function(seg, off)
* @this {X86CPU}
* @param {number} b is the byte (8-bit) value to write
*/
X86CPU.prototype.setEAByteEnabled = function(b)
X86CPU.prototype.setEAByteEnabled = function setEAByteEnabled(b)
{
if (!FASTDISABLE && (this.opFlags & X86.OPFLAG.NOWRITE)) return;
if (!EAFUNCS && (this.opFlags & X86.OPFLAG.NOWRITE)) return;
this.setByte(this.segEA.checkWrite(this.offEA, 1), b);
};
@ -1970,9 +1964,9 @@ X86CPU.prototype.setEAByteEnabled = function(b)
* @this {X86CPU}
* @param {number} w is the word (16-bit) value to write
*/
X86CPU.prototype.setEAWordEnabled = function(w)
X86CPU.prototype.setEAWordEnabled = function setEAWordEnabled(w)
{
if (!FASTDISABLE && (this.opFlags & X86.OPFLAG.NOWRITE)) return;
if (!EAFUNCS && (this.opFlags & X86.OPFLAG.NOWRITE)) return;
this.setWord(this.segEA.checkWrite(this.offEA, 2), w);
};
@ -2047,7 +2041,7 @@ X86CPU.prototype.setSOWord = function(seg, off, w)
*/
X86CPU.prototype.getBytePrefetch = function(addr)
{
if (!FASTDISABLE && (this.opFlags & X86.OPFLAG.NOREAD)) return 0;
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) + ")");
@ -2059,10 +2053,10 @@ X86CPU.prototype.getBytePrefetch = function(addr)
* with side-effects we may not want, and in any case, while it seemed to improve Safari's performance slightly,
* it did nothing for the oddball Chrome performance I'm seeing with PREFETCH enabled.
*
* b = this.aMemBlocks[(addr & this.addrMask) >> this.blockShift].readByte(addr & this.blockLimit);
* b = this.aMemBlocks[(addr & this.addrMemMask) >> this.blockShift].readByte(addr & this.blockLimit);
* this.nBusCycles += 4;
* this.cbPrefetchValid = 0;
* this.addrPrefetchHead = (addr + 1) & this.addrMask;
* this.addrPrefetchHead = (addr + 1) & this.addrMemMask;
* return b;
*/
}
@ -2107,10 +2101,10 @@ X86CPU.prototype.fillPrefetch = function(n)
{
while (n-- > 0 && this.cbPrefetchQueued < X86CPU.PREFETCH.QUEUE) {
var addr = this.addrPrefetchHead;
var b = this.aMemBlocks[(addr & this.addrMask) >> this.blockShift].readByte(addr & this.blockLimit);
var b = this.aMemBlocks[(addr & this.addrMemMask) >> this.blockShift].readByte(addr & this.blockLimit);
this.aPrefetch[this.iPrefetchHead] = b | (addr << 8);
if (MAXDEBUG) this.messageDebugger(" fillPrefetch[" + this.iPrefetchHead + "]: " + str.toHex(addr) + ":" + str.toHexByte(b));
this.addrPrefetchHead = (addr + 1) & this.addrMask;
this.addrPrefetchHead = (addr + 1) & this.addrMemMask;
this.iPrefetchHead = (this.iPrefetchHead + 1) & X86CPU.PREFETCH.MASK;
this.cbPrefetchQueued++;
/*
@ -2443,7 +2437,7 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
* Debugger is single-stepping (even when performing multiple single-steps), fRunning is never set,
* so haltCPU() would have no effect as far as the Debugger is concerned.
*/
this.fComplete = true;
this.aFlags.fComplete = true;
/*
* fDebugCheck is true if we need to "check" every instruction with the Debugger. The Debugger will
@ -2460,7 +2454,7 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
* minimum number of cycles to process: one and only one instruction will execute, since every (valid)
* instruction consumes at least 1 cycle.
*/
this.fDebugCheck = (DEBUGGER && nMinCycles && this.dbg && this.dbg.checksEnabled());
var fDebugCheck = this.aFlags.fDebugCheck = (DEBUGGER && nMinCycles && this.dbg && this.dbg.checksEnabled());
/*
* We move the minimum cycle count to nStepCycles (the number of cycles left to step), so that other
@ -2542,7 +2536,7 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
}
}
if (DEBUGGER && this.fDebugCheck && this.dbg.checkInstruction(this.regEIP)) {
if (DEBUGGER && fDebugCheck && this.dbg.checkInstruction(this.regEIP)) {
this.haltCPU();
break;
}
@ -2589,7 +2583,7 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
} while (this.nStepCycles > 0);
return (this.fComplete? this.nBurstCycles - this.nStepCycles : (this.fComplete === undefined? 0 : -1));
return (this.aFlags.fComplete? this.nBurstCycles - this.nStepCycles : (this.aFlags.fComplete === undefined? 0 : -1));
};
/**
@ -2603,7 +2597,7 @@ X86CPU.prototype.stepCPU = function(nMinCycles)
X86CPU.prototype.messageDebugger = function(sMessage)
{
if (DEBUGGER && this.dbg) {
if (this.dbg.messageEnabled(Debugger.MESSAGE_MEM)) {
if (this.dbg.messageEnabled(Debugger.MESSAGE_CPU)) {
this.dbg.message(sMessage);
}
}