Fixed Closure Compiler build (the compiler gets easily confused when objects in different class hierarchies have identical method names)
This commit is contained in:
parent
231bc201e7
commit
39af7dbe32
6 changed files with 145 additions and 65 deletions
|
|
@ -61,9 +61,10 @@ if (NODE) {
|
||||||
* addMemory(). If the component needs something more than simple read/write storage,
|
* addMemory(). If the component needs something more than simple read/write storage,
|
||||||
* it must provide a controller with getMemoryBuffer() and getMemoryAccess() methods.
|
* it must provide a controller with getMemoryBuffer() and getMemoryAccess() methods.
|
||||||
*
|
*
|
||||||
* By contrast, all port (I/O) operations are defined by external handlers; they register
|
* All port (I/O) operations are defined by external handlers; they register with us,
|
||||||
* with us, and we manage those registrations, as well as support for I/O breakpoints,
|
* and we manage those registrations and provide support for I/O breakpoints, but the
|
||||||
* but unlike memory accesses, we're not involved with port data accesses.
|
* only default I/O behavior we provide is ignoring writes to any unregistered output
|
||||||
|
* ports and returning 0xff from any unregistered input ports.
|
||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @extends Component
|
* @extends Component
|
||||||
|
|
@ -1266,7 +1267,7 @@ Bus.prototype.getSymbol = function(addr, fNearest)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* saveMemory()
|
* saveMemory(fAll)
|
||||||
*
|
*
|
||||||
* The only memory blocks we save are those marked as dirty, but most likely all of RAM will have been marked dirty,
|
* The only memory blocks we save are those marked as dirty, but most likely all of RAM will have been marked dirty,
|
||||||
* and even if our dirty-memory flags were as smart as our dirty-sector flags (ie, were set only when a write changed
|
* and even if our dirty-memory flags were as smart as our dirty-sector flags (ie, were set only when a write changed
|
||||||
|
|
@ -1291,17 +1292,17 @@ Bus.prototype.getSymbol = function(addr, fNearest)
|
||||||
* helper methods compress() and decompress() to create and expand the compressed data arrays.
|
* helper methods compress() and decompress() to create and expand the compressed data arrays.
|
||||||
*
|
*
|
||||||
* @this {Bus}
|
* @this {Bus}
|
||||||
|
* @param {boolean} [fAll] (true to save all non-ROM memory blocks, regardless of their dirty flags)
|
||||||
* @return {Array} a
|
* @return {Array} a
|
||||||
*/
|
*/
|
||||||
Bus.prototype.saveMemory = function()
|
Bus.prototype.saveMemory = function(fAll)
|
||||||
{
|
{
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var a = [];
|
var a = [];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A quick-and-dirty work-around for 32-bit bus machines, to ensure that all blocks in the 2nd Mb are
|
* A quick-and-dirty work-around for 32-bit bus machines, to ensure that all blocks in the 2nd Mb are
|
||||||
* mapped in before we save. We do this by forcing A20 on, and then turning it back off again before we
|
* mapped in before we save. We do this by forcing A20 on, and then turning it off again before we leave.
|
||||||
* leave.
|
|
||||||
*/
|
*/
|
||||||
var fA20 = this.getA20();
|
var fA20 = this.getA20();
|
||||||
if (!fA20) this.setA20(true);
|
if (!fA20) this.setA20(true);
|
||||||
|
|
@ -1313,7 +1314,7 @@ Bus.prototype.saveMemory = function()
|
||||||
* the memory blocks (eg, video memory), and while cleanMemory() will clear a dirty block's fDirty flag,
|
* the memory blocks (eg, video memory), and while cleanMemory() will clear a dirty block's fDirty flag,
|
||||||
* it also sets the dirty block's fDirtyEver flag, which is left set for the lifetime of the machine.
|
* it also sets the dirty block's fDirtyEver flag, which is left set for the lifetime of the machine.
|
||||||
*/
|
*/
|
||||||
if (block.fDirty || block.fDirtyEver) {
|
if (fAll && block.type != Memory.TYPE.ROM || block.fDirty || block.fDirtyEver) {
|
||||||
a[i++] = iBlock;
|
a[i++] = iBlock;
|
||||||
a[i++] = State.compress(block.save());
|
a[i++] = State.compress(block.save());
|
||||||
}
|
}
|
||||||
|
|
@ -1336,7 +1337,7 @@ Bus.prototype.saveMemory = function()
|
||||||
* it was using when it's restored. And since the CPU is guaranteed to be the last
|
* it was using when it's restored. And since the CPU is guaranteed to be the last
|
||||||
* component to be restored, all those blocks (and their attributes) should be in place now.
|
* component to be restored, all those blocks (and their attributes) should be in place now.
|
||||||
*
|
*
|
||||||
* See saveMemory() for a description of how the memory block contents are saved.
|
* See saveMemory() for more information on how the memory block contents are saved.
|
||||||
*
|
*
|
||||||
* @this {Bus}
|
* @this {Bus}
|
||||||
* @param {Array} a
|
* @param {Array} a
|
||||||
|
|
@ -1466,12 +1467,11 @@ Bus.prototype.checkPortInputNotify = function(port, size, addrLIP)
|
||||||
var dataPort = maskPort;
|
var dataPort = maskPort;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: We need to decide what to do about 8-bit I/O to a 16-bit port
|
* TODO: We need to decide what to do about 8-bit I/O to a 16-bit port (ditto for 16-bit I/O
|
||||||
* (ditto for 16-bit I/O to a 32-bit port). We probably should pass the
|
* to a 32-bit port). We probably should pass the size through to the aNotify[0] handler,
|
||||||
* size through to the aNotify[0] handler, and let it decide what to do,
|
* and let it decide what to do, but I don't feel like changing all the I/O handlers right now.
|
||||||
* but I don't feel like changing all the I/O handlers right now. The
|
* The good news, at least, is that the 8-bit handlers would not have to do anything special.
|
||||||
* good news, at least, is that the 8-bit handlers would not have to do
|
* This assert will warn us if this is a pressing need.
|
||||||
* anything special. This assert will warn us if this is a pressing need.
|
|
||||||
*/
|
*/
|
||||||
this.assert(size >= sizePort);
|
this.assert(size >= sizePort);
|
||||||
|
|
||||||
|
|
@ -1625,12 +1625,11 @@ Bus.prototype.checkPortOutputNotify = function(port, size, data, addrLIP)
|
||||||
var dataPort = (data >>>= shift) & maskPort;
|
var dataPort = (data >>>= shift) & maskPort;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: We need to decide what to do about 8-bit I/O to a 16-bit port
|
* TODO: We need to decide what to do about 8-bit I/O to a 16-bit port (ditto for 16-bit I/O
|
||||||
* (ditto for 16-bit I/O to a 32-bit port). We probably should pass the
|
* to a 32-bit port). We probably should pass the size through to the aNotify[0] handler,
|
||||||
* size through to the aNotify[0] handler, and let it decide what to do,
|
* and let it decide what to do, but I don't feel like changing all the I/O handlers right now.
|
||||||
* but I don't feel like changing all the I/O handlers right now. The
|
* The good news, at least, is that the 8-bit handlers would not have to do anything special.
|
||||||
* good news, at least, is that the 8-bit handlers would not have to do
|
* This assert will warn us if this is a pressing need.
|
||||||
* anything special. This assert will warn us if this is a pressing need.
|
|
||||||
*/
|
*/
|
||||||
this.assert(size >= sizePort);
|
this.assert(size >= sizePort);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,17 @@ Memory.adjustEndian = function(dw) {
|
||||||
Memory.prototype = {
|
Memory.prototype = {
|
||||||
constructor: Memory,
|
constructor: Memory,
|
||||||
parent: null,
|
parent: null,
|
||||||
|
/**
|
||||||
|
* init(addr)
|
||||||
|
*
|
||||||
|
* Quick reinitializer when reusing a Memory block.
|
||||||
|
*
|
||||||
|
* @this {Memory}
|
||||||
|
* @param {number} addr
|
||||||
|
*/
|
||||||
|
init: function(addr) {
|
||||||
|
this.addr = addr;
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* clone(mem, type)
|
* clone(mem, type)
|
||||||
*
|
*
|
||||||
|
|
@ -501,6 +512,7 @@ Memory.prototype = {
|
||||||
* @param {number} offPTE
|
* @param {number} offPTE
|
||||||
*/
|
*/
|
||||||
setPhysBlock: function(blockPhys, blockPDE, offPDE, blockPTE, offPTE) {
|
setPhysBlock: function(blockPhys, blockPDE, offPDE, blockPTE, offPTE) {
|
||||||
|
this.blockPhys = blockPhys;
|
||||||
this.blockPDE = blockPDE;
|
this.blockPDE = blockPDE;
|
||||||
this.iPDE = offPDE >> 2; // convert offPDE into iPDE (an adw index)
|
this.iPDE = offPDE >> 2; // convert offPDE into iPDE (an adw index)
|
||||||
this.blockPTE = blockPTE;
|
this.blockPTE = blockPTE;
|
||||||
|
|
@ -516,9 +528,9 @@ Memory.prototype = {
|
||||||
this.adw = blockPhys.adw;
|
this.adw = blockPhys.adw;
|
||||||
this.setAccess(Memory.afnPagedLE);
|
this.setAccess(Memory.afnPagedLE);
|
||||||
} else {
|
} else {
|
||||||
this.blockPhys = blockPhys;
|
|
||||||
this.bitPTEAccessed = blockPhys? Memory.adjustEndian(X86.PTE.ACCESSED) : 0;
|
this.bitPTEAccessed = blockPhys? Memory.adjustEndian(X86.PTE.ACCESSED) : 0;
|
||||||
this.bitPTEDirty = blockPhys? Memory.adjustEndian(X86.PTE.ACCESSED | X86.PTE.DIRTY) : 0;
|
this.bitPTEDirty = blockPhys? Memory.adjustEndian(X86.PTE.ACCESSED | X86.PTE.DIRTY) : 0;
|
||||||
|
this.setAccess(Memory.afnPaged);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
|
@ -1231,7 +1243,14 @@ Memory.prototype = {
|
||||||
this.ab[off] = b;
|
this.ab[off] = b;
|
||||||
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
|
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
|
||||||
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED | X86.PTE.DIRTY;
|
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED | X86.PTE.DIRTY;
|
||||||
this.fDirty = true;
|
/*
|
||||||
|
* NOTE: Technically, we should be setting the fDirty flag on blockPDE and blockPTE as well, but let's
|
||||||
|
* consider the two sole uses of fDirty. First, we have cleanMemory(), which is currently used only by
|
||||||
|
* the Video component, and video memory should never contain page directories or page tables, so no
|
||||||
|
* worries there. Second, we have saveMemory(), but the CPU now asks that function to save all physical
|
||||||
|
* memory blocks whenever paging is enabled, so no worries there either.
|
||||||
|
*/
|
||||||
|
this.blockPhys.fDirty = true;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* writeShortBE(off, w, addr)
|
* writeShortBE(off, w, addr)
|
||||||
|
|
@ -1287,7 +1306,14 @@ Memory.prototype = {
|
||||||
}
|
}
|
||||||
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
|
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
|
||||||
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED | X86.PTE.DIRTY;
|
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED | X86.PTE.DIRTY;
|
||||||
this.fDirty = true;
|
/*
|
||||||
|
* NOTE: Technically, we should be setting the fDirty flag on blockPDE and blockPTE as well, but let's
|
||||||
|
* consider the two sole uses of fDirty. First, we have cleanMemory(), which is currently used only by
|
||||||
|
* the Video component, and video memory should never contain page directories or page tables, so no
|
||||||
|
* worries there. Second, we have saveMemory(), but the CPU now asks that function to save all physical
|
||||||
|
* memory blocks whenever paging is enabled, so no worries there either.
|
||||||
|
*/
|
||||||
|
this.blockPhys.fDirty = true;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* writeLongBE(off, l, addr)
|
* writeLongBE(off, l, addr)
|
||||||
|
|
@ -1347,7 +1373,14 @@ Memory.prototype = {
|
||||||
}
|
}
|
||||||
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
|
this.blockPDE.adw[this.iPDE] |= X86.PTE.ACCESSED;
|
||||||
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED | X86.PTE.DIRTY;
|
this.blockPTE.adw[this.iPTE] |= X86.PTE.ACCESSED | X86.PTE.DIRTY;
|
||||||
this.fDirty = true;
|
/*
|
||||||
|
* NOTE: Technically, we should be setting the fDirty flag on blockPDE and blockPTE as well, but let's
|
||||||
|
* consider the two sole uses of fDirty. First, we have cleanMemory(), which is currently used only by
|
||||||
|
* the Video component, and video memory should never contain page directories or page tables, so no
|
||||||
|
* worries there. Second, we have saveMemory(), but the CPU now asks that function to save all physical
|
||||||
|
* memory blocks whenever paging is enabled, so no worries there either.
|
||||||
|
*/
|
||||||
|
this.blockPhys.fDirty = true;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* readBackTrackNone(off)
|
* readBackTrackNone(off)
|
||||||
|
|
|
||||||
|
|
@ -278,9 +278,7 @@ State.prototype = {
|
||||||
if (s) {
|
if (s) {
|
||||||
this[this.id] = s;
|
this[this.id] = s;
|
||||||
this.fLoaded = true;
|
this.fLoaded = true;
|
||||||
if (DEBUG && this.messageEnabled()) {
|
if (DEBUG) this.printString("localStorage(" + this.key + "): " + s.length + " bytes loaded");
|
||||||
this.printMessage("localStorage(" + this.key + "): " + s.length + " bytes loaded");
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -317,9 +315,7 @@ State.prototype = {
|
||||||
if (web.hasLocalStorage()) {
|
if (web.hasLocalStorage()) {
|
||||||
var s = JSON.stringify(this[this.id]);
|
var s = JSON.stringify(this[this.id]);
|
||||||
if (web.setLocalStorageItem(this.key, s)) {
|
if (web.setLocalStorageItem(this.key, s)) {
|
||||||
if (DEBUG && this.messageEnabled()) {
|
if (DEBUG) this.printString("localStorage(" + this.key + "): " + s.length + " bytes stored");
|
||||||
this.printMessage("localStorage(" + this.key + "): " + s.length + " bytes stored");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* WARNING: Because browsers tend to disable all alerts() during an "unload" operation,
|
* WARNING: Because browsers tend to disable all alerts() during an "unload" operation,
|
||||||
|
|
@ -377,40 +373,24 @@ State.prototype = {
|
||||||
var sKey = aKeys[i];
|
var sKey = aKeys[i];
|
||||||
if (sKey && (fAll || sKey.substr(0, this.key.length) == this.key)) {
|
if (sKey && (fAll || sKey.substr(0, this.key.length) == this.key)) {
|
||||||
web.removeLocalStorageItem(sKey);
|
web.removeLocalStorageItem(sKey);
|
||||||
if (DEBUG && this.messageEnabled()) {
|
if (DEBUG) this.printString("localStorage(" + sKey + ") removed");
|
||||||
this.printMessage("localStorage(" + sKey + ") removed");
|
|
||||||
}
|
|
||||||
aKeys.splice(i, 1);
|
aKeys.splice(i, 1);
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* messageEnabled(bitsMessage)
|
* printString(s)
|
||||||
*
|
*
|
||||||
* @this {State}
|
* @this {State}
|
||||||
* @param {number} [bitsMessage] is one or more Messages category flag(s)
|
* @param {string} s is any caller-defined string
|
||||||
* @return {boolean}
|
|
||||||
*/
|
*/
|
||||||
messageEnabled: function(bitsMessage) {
|
printString: function(s) {
|
||||||
if (DEBUGGER && this.dbg) {
|
if (DEBUG && DEBUGGER && this.dbg) {
|
||||||
if (bitsMessage == null) {
|
if (this.dbg.messageEnabled(Messages.STATE)) {
|
||||||
bitsMessage = Messages.STATE;
|
this.dbg.message(s);
|
||||||
} else {
|
|
||||||
bitsMessage |= Messages.STATE;
|
|
||||||
}
|
}
|
||||||
return this.dbg.messageEnabled(bitsMessage);
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* printMessage(sMessage)
|
|
||||||
*
|
|
||||||
* @this {State}
|
|
||||||
* @param {string} sMessage is any caller-defined message string
|
|
||||||
*/
|
|
||||||
printMessage: function(sMessage) {
|
|
||||||
if (DEBUGGER && this.dbg) this.dbg.message(sMessage);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,8 @@ if (PREFETCH) {
|
||||||
X86CPU.PFINFO.IP_MASK = ((X86CPU.PFINFO.LENGTH - 1) & ~0x3);
|
X86CPU.PFINFO.IP_MASK = ((X86CPU.PFINFO.LENGTH - 1) & ~0x3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
X86CPU.PAGEBLOCKS_CACHE = 512; // TODO: This seems adequate for 4Mb of RAM, but it should be dynamically reconfigured
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initMemory(aMemBlocks, nBlockShift)
|
* initMemory(aMemBlocks, nBlockShift)
|
||||||
*
|
*
|
||||||
|
|
@ -432,6 +434,12 @@ X86CPU.prototype.enablePageBlocks = function()
|
||||||
* if the Debugger is suppressing faults or calling probeAddr(), returning memEmpty is helpful.
|
* if the Debugger is suppressing faults or calling probeAddr(), returning memEmpty is helpful.
|
||||||
*/
|
*/
|
||||||
this.memEmpty = new Memory();
|
this.memEmpty = new Memory();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize our PAGEBLOCKS cache (see acquirePageBlock() and releasePageBlock()).
|
||||||
|
*/
|
||||||
|
this.aCacheBlocks = new Array(X86CPU.PAGEBLOCKS_CACHE);
|
||||||
|
this.iCacheBlocks = 0;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Our equivalent of a TLB flush. NOTE: We do not attempt to simulate an actual TLB; our
|
* Our equivalent of a TLB flush. NOTE: We do not attempt to simulate an actual TLB; our
|
||||||
|
|
@ -440,12 +448,62 @@ X86CPU.prototype.enablePageBlocks = function()
|
||||||
* a constrained TLB -- at least not from the 80386 era, which is all we're emulating.
|
* a constrained TLB -- at least not from the 80386 era, which is all we're emulating.
|
||||||
*/
|
*/
|
||||||
for (var i = 0; i < this.aBlocksPaged.length; i++) {
|
for (var i = 0; i < this.aBlocksPaged.length; i++) {
|
||||||
this.aMemBlocks[this.aBlocksPaged[i]] = this.blockUnpaged;
|
var iBlock = this.aBlocksPaged[i];
|
||||||
|
this.releasePageBlock(this.aMemBlocks[iBlock]);
|
||||||
|
this.aMemBlocks[iBlock] = this.blockUnpaged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.aBlocksPaged = [];
|
this.aBlocksPaged = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* acquirePageBlock(addr)
|
||||||
|
*
|
||||||
|
* This implements a simple paged memory block cache. Candidates for caching must be released via
|
||||||
|
* releasePageBlock().
|
||||||
|
*
|
||||||
|
* After acquiring a block from this cache, the caller MUST use setPhysBlock() to properly reinitialize
|
||||||
|
* it for the new given linear address.
|
||||||
|
*
|
||||||
|
* @this {X86CPU}
|
||||||
|
* @param {number} addr
|
||||||
|
* @return {Memory}
|
||||||
|
*/
|
||||||
|
X86CPU.prototype.acquirePageBlock = function(addr)
|
||||||
|
{
|
||||||
|
var block;
|
||||||
|
if (this.iCacheBlocks > 0) {
|
||||||
|
block = this.aCacheBlocks[--this.iCacheBlocks];
|
||||||
|
/*
|
||||||
|
* Paged memory blocks are all very generic and contain no memory of their own, so the fact
|
||||||
|
* that we're not calling the Memory constructor to reinitialize it is OK. setPhysBlock() is
|
||||||
|
* what's critical, and the caller will take care of that. However, to avoid any confusion,
|
||||||
|
* especially when debugging, there are a few properties we should reinitialize, hence init().
|
||||||
|
*/
|
||||||
|
block.init(addr);
|
||||||
|
} else {
|
||||||
|
block = new Memory(addr, 0, 0, Memory.TYPE.PAGED);
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* releasePageBlock(block)
|
||||||
|
*
|
||||||
|
* Instead of simply tossing Memory blocks onto the garbage collector's heap, we'll retain a maximum
|
||||||
|
* number (X86CPU.PAGEBLOCKS_CACHE) in aCacheBlocks, with iCacheBlocks pointing to the next free element.
|
||||||
|
*
|
||||||
|
* @this {X86CPU}
|
||||||
|
* @param {Memory} block
|
||||||
|
*/
|
||||||
|
X86CPU.prototype.releasePageBlock = function(block)
|
||||||
|
{
|
||||||
|
this.assert(block && block.type === Memory.TYPE.PAGED);
|
||||||
|
if (this.iCacheBlocks < X86CPU.PAGEBLOCKS_CACHE) {
|
||||||
|
this.aCacheBlocks[this.iCacheBlocks++] = block;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mapPageBlock(addr, fWrite, fSuppress)
|
* mapPageBlock(addr, fWrite, fSuppress)
|
||||||
*
|
*
|
||||||
|
|
@ -535,14 +593,13 @@ X86CPU.prototype.mapPageBlock = function(addr, fWrite, fSuppress)
|
||||||
*
|
*
|
||||||
* Now we can create a new PAGED Memory block and record the physical block info using setPhysBlock().
|
* Now we can create a new PAGED Memory block and record the physical block info using setPhysBlock().
|
||||||
*/
|
*/
|
||||||
var addrPage = addr & ~X86.LADDR.OFFSET;
|
var blockPage = this.acquirePageBlock(addr & ~X86.LADDR.OFFSET);
|
||||||
var blockPage = new Memory(addrPage, 0, 0, Memory.TYPE.PAGED);
|
|
||||||
blockPage.setPhysBlock(blockPhys, blockPDE, offPDE, blockPTE, offPTE);
|
blockPage.setPhysBlock(blockPhys, blockPDE, offPDE, blockPTE, offPTE);
|
||||||
blockPage.copyBreakpoints(this.dbg, block);
|
blockPage.copyBreakpoints(this.dbg, block);
|
||||||
|
|
||||||
this.aMemBlocks[iBlock] = blockPage;
|
this.aMemBlocks[iBlock] = blockPage;
|
||||||
|
|
||||||
this.aBlocksPaged.push(iBlock);
|
this.aBlocksPaged.push(iBlock);
|
||||||
|
|
||||||
return blockPage;
|
return blockPage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -563,6 +620,19 @@ X86CPU.prototype.disablePageBlocks = function()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isPagingEnabled()
|
||||||
|
*
|
||||||
|
* @this {X86CPU}
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
X86CPU.prototype.isPagingEnabled = function()
|
||||||
|
{
|
||||||
|
var fPaging = !!(this.regCR0 & X86.CR0.PG);
|
||||||
|
this.assert((this.aMemBlocks !== this.aBusBlocks) === fPaging);
|
||||||
|
return fPaging;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initProcessor()
|
* initProcessor()
|
||||||
*
|
*
|
||||||
|
|
@ -1717,7 +1787,7 @@ X86CPU.prototype.save = function()
|
||||||
state.set(1, a);
|
state.set(1, a);
|
||||||
state.set(2, [this.segData.sName, this.segStack.sName, this.opFlags, this.opPrefixes, this.intFlags, this.regEA, this.regEAWrite]);
|
state.set(2, [this.segData.sName, this.segStack.sName, this.opFlags, this.opPrefixes, this.intFlags, this.regEA, this.regEAWrite]);
|
||||||
state.set(3, [0, this.nTotalCycles, this.getSpeed()]);
|
state.set(3, [0, this.nTotalCycles, this.getSpeed()]);
|
||||||
state.set(4, this.bus.saveMemory());
|
state.set(4, this.bus.saveMemory(this.isPagingEnabled()));
|
||||||
return state.data();
|
return state.data();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4116,7 +4116,8 @@ X86.fnFaultMessage = function(nFault, nError, fHalt)
|
||||||
var sMessage = "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode " + str.toHexByte(bOpcode);
|
var sMessage = "Fault " + str.toHexByte(nFault) + (nError != null? " (" + str.toHexWord(nError) + ")" : "") + " on opcode " + str.toHexByte(bOpcode);
|
||||||
if (fHalt && fRunning) sMessage += " (blocked by PCjs Debugger)";
|
if (fHalt && fRunning) sMessage += " (blocked by PCjs Debugger)";
|
||||||
|
|
||||||
if (this.printMessage(sMessage, fHalt || bitsMessage, true)) {
|
if (DEBUGGER && this.dbg) {
|
||||||
|
this.printMessage(sMessage, fHalt || bitsMessage, true);
|
||||||
if (fHalt) {
|
if (fHalt) {
|
||||||
/*
|
/*
|
||||||
* By setting fHalt to fRunning (which is true while running but false while single-stepping),
|
* By setting fHalt to fRunning (which is true while running but false while single-stepping),
|
||||||
|
|
@ -4131,8 +4132,8 @@ X86.fnFaultMessage = function(nFault, nError, fHalt)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* If printMessage() returned false, then there's no Debugger, which means that messageEnabled() must have
|
* If there's no Debugger, then messageEnabled() must have returned false, which means that fHalt must
|
||||||
* returned false as well, which means that fHalt must be true. Which means we should shut the machine down.
|
* be true. Which means we should shut the machine down.
|
||||||
*/
|
*/
|
||||||
this.assert(fHalt);
|
this.assert(fHalt);
|
||||||
this.notice(sMessage);
|
this.notice(sMessage);
|
||||||
|
|
|
||||||
|
|
@ -960,16 +960,13 @@ Component.prototype = {
|
||||||
* @param {string} sMessage is any caller-defined message string
|
* @param {string} sMessage is any caller-defined message string
|
||||||
* @param {number|boolean} [bitsMessage] is zero or more MESSAGE_* category flag(s)
|
* @param {number|boolean} [bitsMessage] is zero or more MESSAGE_* category flag(s)
|
||||||
* @param {boolean} [fAddress] is true to display the current address
|
* @param {boolean} [fAddress] is true to display the current address
|
||||||
* @return {boolean} true if Debugger available, false if not
|
|
||||||
*/
|
*/
|
||||||
printMessage: function(sMessage, bitsMessage, fAddress) {
|
printMessage: function(sMessage, bitsMessage, fAddress) {
|
||||||
if (DEBUGGER && this.dbg) {
|
if (DEBUGGER && this.dbg) {
|
||||||
if (bitsMessage === true || this.messageEnabled(bitsMessage | 0)) {
|
if (bitsMessage === true || this.messageEnabled(bitsMessage | 0)) {
|
||||||
this.dbg.message(sMessage, fAddress);
|
this.dbg.message(sMessage, fAddress);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* printMessageIO(port, bOut, addrFrom, name, bIn, bitsMessage)
|
* printMessageIO(port, bOut, addrFrom, name, bIn, bitsMessage)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue