Initial scaffolding for paged memory
This commit is contained in:
parent
bf8148611d
commit
6108fb25ab
8 changed files with 431 additions and 276 deletions
|
|
@ -99,13 +99,13 @@ function Bus(parmsBus, cpu, dbg)
|
|||
* Bus Property Old hard-coded values (when nBusWidth was always 20)
|
||||
* ------------ ----------------------------------------------------
|
||||
* this.busLimit 0xfffff
|
||||
* this.busMask N/A
|
||||
* this.busMask [same as busLimit]
|
||||
* this.blockSize 4096
|
||||
* this.blockLen (this.blockSize >> 2)
|
||||
* this.blockShift 12
|
||||
* this.blockLimit 0xfff
|
||||
* this.blockTotal ((this.busLimit + this.blockSize) / this.blockSize) | 0
|
||||
* this.blockMask (this.blockTotal - 1) (ie, 0xff)
|
||||
* this.blockMask (this.blockTotal - 1) [ie, 0xff]
|
||||
*
|
||||
* Note that we choose a blockShift value (and thus a physical memory block size) based on "buswidth":
|
||||
*
|
||||
|
|
@ -120,7 +120,7 @@ function Bus(parmsBus, cpu, dbg)
|
|||
* requirements. Your choices, for the moment, are either to ensure the allocations are performed in
|
||||
* order, or to choose smaller blockShift values (at the expense of a generating a larger block array).
|
||||
*
|
||||
* However, if PAGEBLOCKS is set, then for a bus width of 32 bits, the block size is fixed at 4Kb.
|
||||
* Note that if PAGEBLOCKS is set, then for a bus width of 32 bits, the block size is fixed at 4Kb.
|
||||
*/
|
||||
this.addrTotal = Math.pow(2, this.nBusWidth);
|
||||
this.busLimit = this.busMask = (this.addrTotal - 1) | 0;
|
||||
|
|
@ -171,6 +171,11 @@ function Bus(parmsBus, cpu, dbg)
|
|||
this.ibtLastDelete = 0;
|
||||
}
|
||||
|
||||
if (PAGEBLOCKS) {
|
||||
this.addrPD = null;
|
||||
this.aPhysBlocks = null;
|
||||
}
|
||||
|
||||
this.setReady();
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +399,9 @@ Bus.prototype.addMemory = function(addr, size, type, controller)
|
|||
return this.reportError(1, addr, size);
|
||||
}
|
||||
block = this.aMemBlocks[iBlock++] = new Memory(addr, sizeBlock, this.blockSize, type, controller);
|
||||
if (DEBUGGER && this.dbg) block.setDebugInfo(this.cpu, this.dbg, addr, this.blockSize);
|
||||
if (DEBUGGER && this.dbg) {
|
||||
block.setDebugger(this.dbg, addr, this.blockSize);
|
||||
}
|
||||
size -= sizeBlock;
|
||||
addr = addrBlock + this.blockSize;
|
||||
}
|
||||
|
|
@ -478,10 +485,10 @@ Bus.prototype.getA20 = function()
|
|||
*
|
||||
* On 32-bit bus machines, I've adopted the approach that Compaq took with DeskPro 386 machines,
|
||||
* which is to map the 1st Mb to the 2nd Mb whenever A20 is disabled, rather than blindly masking
|
||||
* the A20 address bit from all addresses; this is what the DeskPro 386 ROM BIOS requires.
|
||||
* the A20 address bit from all addresses; in fact, this is what the DeskPro 386 ROM BIOS requires.
|
||||
*
|
||||
* For 24-bit bus machines, we take the same approach that most if not all 80286 systems took, which
|
||||
* is simply masking the A20 address bit.
|
||||
* is simply masking the A20 address bit. A lot of 32-bit machines probably took the same approach.
|
||||
*
|
||||
* TODO: On machines with a 32-bit bus, look into whether we can eliminate address masking altogether,
|
||||
* which seems feasible, provided all incoming addresses are already pre-truncated to 32 bits. Also,
|
||||
|
|
@ -579,7 +586,9 @@ Bus.prototype.removeMemory = function(addr, size)
|
|||
while (size > 0) {
|
||||
addr = iBlock * this.blockSize;
|
||||
var block = this.aMemBlocks[iBlock++] = new Memory(addr);
|
||||
if (DEBUGGER && this.dbg) block.setDebugInfo(this.cpu, this.dbg, addr, this.blockSize);
|
||||
if (DEBUGGER && this.dbg) {
|
||||
block.setDebugger(this.dbg, addr, this.blockSize);
|
||||
}
|
||||
size -= this.blockSize;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -631,7 +640,9 @@ Bus.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
|
|||
if (!block) break;
|
||||
if (type !== undefined) {
|
||||
var blockNew = new Memory(addr);
|
||||
if (DEBUGGER && this.dbg) blockNew.setDebugInfo(this.cpu, this.dbg, addr, this.blockSize);
|
||||
if (DEBUGGER && this.dbg) {
|
||||
blockNew.setDebugger(this.dbg, addr, this.blockSize);
|
||||
}
|
||||
blockNew.clone(block, type);
|
||||
block = blockNew;
|
||||
}
|
||||
|
|
@ -640,6 +651,60 @@ Bus.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* enablePageBlocks(addrPD)
|
||||
*
|
||||
* Whenever the CPU turns on paging and/or updates CR3, this function is called to leverage the Bus's
|
||||
* memory-mapping abilities and simulate the effects of the CPU's page directory and page table entries.
|
||||
* Whenever the CPU turns paging off, disablePageBlocks() must be called to restore the original physical
|
||||
* memory mapping.
|
||||
*
|
||||
* This also requires that PAGEBLOCKS be true, ensuring that the Bus is preconfigured with 4Kb memory
|
||||
* mapping granularity.
|
||||
*
|
||||
* The first time this function is called, aMemBlocks is stashed in aPhysBlocks, and aMemBlocks is then
|
||||
* reinitialized with special "unpaged" Memory blocks that know how to perform page directory/page table
|
||||
* lookup and replace themselves with special "paged" Memory blocks that reference memory from the
|
||||
* appropriate block in aPhysBlocks. A parallel array, aMemPaged, keeps track of which blocks have been
|
||||
* "paged", so that whenever CR3 is updated, just those blocks can be "unpaged" again.
|
||||
*
|
||||
* @this {Bus}
|
||||
* @param {number} addrPD is the starting physical address of the CPU's page directory
|
||||
*/
|
||||
Bus.prototype.enablePageBlocks = function(addrPD)
|
||||
{
|
||||
if (!PAGEBLOCKS) {
|
||||
Component.error("PAGEBLOCK support missing");
|
||||
return;
|
||||
}
|
||||
this.addrPD = addrPD;
|
||||
if (!this.aPhysBlocks) {
|
||||
this.aPhysBlocks = this.aMemBlocks;
|
||||
var block = new Memory(null, 0, 0, Memory.TYPE.UNPAGED, null, this);
|
||||
this.aMemBlocks = new Array(this.blockTotal);
|
||||
for (var iBlock = 0; iBlock < this.blockTotal; iBlock++) {
|
||||
this.aMemBlocks[iBlock] = block;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* mapPageBlock(addr)
|
||||
*
|
||||
* If addr is a valid linear address, then we must obtain the following information:
|
||||
*
|
||||
* (1) the physical Memory object corresponding to the linear address in addr
|
||||
* (2) the physical Memory object containing that memory's PTE
|
||||
* (3) the offset within the preceding physical Memory object of that memory's PTE
|
||||
*
|
||||
* Item (1) allows us to convert an "unpaged" Memory block in to a "paged" Memory block, and the combination of
|
||||
* (2) and (3) allows us to efficiently update the PTE whenever the page is accesssed and/or modified.
|
||||
*/
|
||||
Bus.prototype.mapPageBlock = function(addr)
|
||||
{
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* getByte(addr)
|
||||
*
|
||||
|
|
@ -652,7 +717,7 @@ Bus.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
|
|||
*/
|
||||
Bus.prototype.getByte = function(addr)
|
||||
{
|
||||
return this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByte(addr & this.blockLimit);
|
||||
return this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByte(addr & this.blockLimit, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -666,7 +731,7 @@ Bus.prototype.getByte = function(addr)
|
|||
*/
|
||||
Bus.prototype.getByteDirect = function(addr)
|
||||
{
|
||||
return this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByteDirect(addr & this.blockLimit);
|
||||
return this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByteDirect(addr & this.blockLimit, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -685,9 +750,9 @@ Bus.prototype.getShort = function(addr)
|
|||
var off = addr & this.blockLimit;
|
||||
var iBlock = (addr & this.busMask) >>> this.blockShift;
|
||||
if (off != this.blockLimit) {
|
||||
return this.aMemBlocks[iBlock].readShort(off);
|
||||
return this.aMemBlocks[iBlock].readShort(off, addr);
|
||||
}
|
||||
return this.aMemBlocks[iBlock++].readByte(off) | (this.aMemBlocks[iBlock & this.blockMask].readByte(0) << 8);
|
||||
return this.aMemBlocks[iBlock++].readByte(off, addr) | (this.aMemBlocks[iBlock & this.blockMask].readByte(0, addr + 1) << 8);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -704,9 +769,9 @@ Bus.prototype.getShortDirect = function(addr)
|
|||
var off = addr & this.blockLimit;
|
||||
var iBlock = (addr & this.busMask) >>> this.blockShift;
|
||||
if (off != this.blockLimit) {
|
||||
return this.aMemBlocks[iBlock].readShortDirect(off);
|
||||
return this.aMemBlocks[iBlock].readShortDirect(off, addr);
|
||||
}
|
||||
return this.aMemBlocks[iBlock++].readByteDirect(off) | (this.aMemBlocks[iBlock & this.blockMask].readByteDirect(0) << 8);
|
||||
return this.aMemBlocks[iBlock++].readByteDirect(off, addr) | (this.aMemBlocks[iBlock & this.blockMask].readByteDirect(0, addr + 1) << 8);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -725,10 +790,10 @@ Bus.prototype.getLong = function(addr)
|
|||
var off = addr & this.blockLimit;
|
||||
var iBlock = (addr & this.busMask) >>> this.blockShift;
|
||||
if (off < this.blockLimit - 2) {
|
||||
return this.aMemBlocks[iBlock].readLong(off);
|
||||
return this.aMemBlocks[iBlock].readLong(off, addr);
|
||||
}
|
||||
var nShift = (off & 0x3) << 3;
|
||||
return (this.aMemBlocks[iBlock].readLong(off & ~0x3) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLong(0) << (32 - nShift));
|
||||
return (this.aMemBlocks[iBlock].readLong(off & ~0x3, addr) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLong(0, addr + 3) << (32 - nShift));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -745,10 +810,10 @@ Bus.prototype.getLongDirect = function(addr)
|
|||
var off = addr & this.blockLimit;
|
||||
var iBlock = (addr & this.busMask) >>> this.blockShift;
|
||||
if (off < this.blockLimit - 2) {
|
||||
return this.aMemBlocks[iBlock].readLongDirect(off);
|
||||
return this.aMemBlocks[iBlock].readLongDirect(off, addr);
|
||||
}
|
||||
var nShift = (off & 0x3) << 3;
|
||||
return (this.aMemBlocks[iBlock].readLongDirect(off & ~0x3) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLongDirect(0) << (32 - nShift));
|
||||
return (this.aMemBlocks[iBlock].readLongDirect(off & ~0x3, addr) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLongDirect(0, addr + 3) << (32 - nShift));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -763,7 +828,7 @@ Bus.prototype.getLongDirect = function(addr)
|
|||
*/
|
||||
Bus.prototype.setByte = function(addr, b)
|
||||
{
|
||||
this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].writeByte(addr & this.blockLimit, b & 0xff);
|
||||
this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].writeByte(addr & this.blockLimit, b & 0xff, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -778,7 +843,7 @@ Bus.prototype.setByte = function(addr, b)
|
|||
*/
|
||||
Bus.prototype.setByteDirect = function(addr, b)
|
||||
{
|
||||
this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].writeByteDirect(addr & this.blockLimit, b & 0xff);
|
||||
this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].writeByteDirect(addr & this.blockLimit, b & 0xff, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -797,11 +862,11 @@ Bus.prototype.setShort = function(addr, w)
|
|||
var off = addr & this.blockLimit;
|
||||
var iBlock = (addr & this.busMask) >>> this.blockShift;
|
||||
if (off != this.blockLimit) {
|
||||
this.aMemBlocks[iBlock].writeShort(off, w & 0xffff);
|
||||
this.aMemBlocks[iBlock].writeShort(off, w & 0xffff, addr);
|
||||
return;
|
||||
}
|
||||
this.aMemBlocks[iBlock++].writeByte(off, w & 0xff);
|
||||
this.aMemBlocks[iBlock & this.blockMask].writeByte(0, (w >> 8) & 0xff);
|
||||
this.aMemBlocks[iBlock++].writeByte(off, w & 0xff, addr);
|
||||
this.aMemBlocks[iBlock & this.blockMask].writeByte(0, (w >> 8) & 0xff, addr + 1);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -819,11 +884,11 @@ Bus.prototype.setShortDirect = function(addr, w)
|
|||
var off = addr & this.blockLimit;
|
||||
var iBlock = (addr & this.busMask) >>> this.blockShift;
|
||||
if (off != this.blockLimit) {
|
||||
this.aMemBlocks[iBlock].writeShortDirect(off, w & 0xffff);
|
||||
this.aMemBlocks[iBlock].writeShortDirect(off, w & 0xffff, addr);
|
||||
return;
|
||||
}
|
||||
this.aMemBlocks[iBlock++].writeByteDirect(off, w & 0xff);
|
||||
this.aMemBlocks[iBlock & this.blockMask].writeByteDirect(0, (w >> 8) & 0xff);
|
||||
this.aMemBlocks[iBlock++].writeByteDirect(off, w & 0xff, addr);
|
||||
this.aMemBlocks[iBlock & this.blockMask].writeByteDirect(0, (w >> 8) & 0xff, addr + 1);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -847,11 +912,12 @@ Bus.prototype.setLong = function(addr, l)
|
|||
}
|
||||
var lPrev, nShift = (off & 0x3) << 3;
|
||||
off &= ~0x3;
|
||||
lPrev = this.aMemBlocks[iBlock].readLong(off);
|
||||
this.aMemBlocks[iBlock].writeLong(off, (lPrev & ~((0xffffffff|0) << nShift)) | (l << nShift));
|
||||
lPrev = this.aMemBlocks[iBlock].readLong(off, addr);
|
||||
this.aMemBlocks[iBlock].writeLong(off, (lPrev & ~((0xffffffff|0) << nShift)) | (l << nShift), addr);
|
||||
iBlock = (iBlock + 1) & this.blockMask;
|
||||
lPrev = this.aMemBlocks[iBlock].readLong(0);
|
||||
this.aMemBlocks[iBlock].writeLong(0, (lPrev & ((0xffffffff|0) << nShift)) | (l >>> (32 - nShift)));
|
||||
addr += 3;
|
||||
lPrev = this.aMemBlocks[iBlock].readLong(0, addr);
|
||||
this.aMemBlocks[iBlock].writeLong(0, (lPrev & ((0xffffffff|0) << nShift)) | (l >>> (32 - nShift)), addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -869,16 +935,17 @@ Bus.prototype.setLongDirect = function(addr, l)
|
|||
var off = addr & this.blockLimit;
|
||||
var iBlock = (addr & this.busMask) >>> this.blockShift;
|
||||
if (off < this.blockLimit - 2) {
|
||||
this.aMemBlocks[iBlock].writeLongDirect(off, l);
|
||||
this.aMemBlocks[iBlock].writeLongDirect(off, l, addr);
|
||||
return;
|
||||
}
|
||||
var lPrev, nShift = (off & 0x3) << 3;
|
||||
off &= ~0x3;
|
||||
lPrev = this.aMemBlocks[iBlock].readLongDirect(off);
|
||||
this.aMemBlocks[iBlock].writeLongDirect(off, (lPrev & ~((0xffffffff|0) << nShift)) | (l << nShift));
|
||||
lPrev = this.aMemBlocks[iBlock].readLongDirect(off, addr);
|
||||
this.aMemBlocks[iBlock].writeLongDirect(off, (lPrev & ~((0xffffffff|0) << nShift)) | (l << nShift), addr);
|
||||
iBlock = (iBlock + 1) & this.blockMask;
|
||||
lPrev = this.aMemBlocks[iBlock].readLongDirect(0);
|
||||
this.aMemBlocks[iBlock].writeLongDirect(0, (lPrev & ((0xffffffff|0) << nShift)) | (l >>> (32 - nShift)));
|
||||
addr += 3;
|
||||
lPrev = this.aMemBlocks[iBlock].readLongDirect(0, addr);
|
||||
this.aMemBlocks[iBlock].writeLongDirect(0, (lPrev & ((0xffffffff|0) << nShift)) | (l >>> (32 - nShift)), addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2807,7 +2807,7 @@ if (DEBUGGER) {
|
|||
* redoBreakpoints()
|
||||
*
|
||||
* This function is for the Memory component: whenever the Bus allocates a new Memory block, it calls
|
||||
* the block's setDebugInfo() method, which clears the memory block's breakpoint counts. setDebugInfo(),
|
||||
* the block's setDebugger() method, which clears the memory block's breakpoint counts. setDebugger(),
|
||||
* in turn, must call this function to re-apply any existing breakpoints to that block.
|
||||
*
|
||||
* This ensures that, even if a memory region is remapped (which creates new Memory blocks in the process),
|
||||
|
|
|
|||
|
|
@ -861,7 +861,7 @@ FDC.prototype.initDrive = function(drive, iDrive, data)
|
|||
|
||||
/*
|
||||
* resCode used to be an FDC global, but in order to insulate FDC state from the operation of various functions
|
||||
* that operate on drive objects (eg, readByte and writeByte), I've made it a per-drive variable. This choice,
|
||||
* that operate on drive objects (eg, readData and writeData), I've made it a per-drive variable. This choice,
|
||||
* similar to my choice for handling PCN, may be contrary to how the actual hardware works, but I prefer this
|
||||
* approach, as long as it doesn't expose any incompatibilities that any software actually cares about.
|
||||
*/
|
||||
|
|
@ -1110,7 +1110,7 @@ FDC.prototype.copyDrive = function(iDrive)
|
|||
*
|
||||
* Also note that in an actual FDC request, drive.nBytes is initialized to the size of a single sector; the extent
|
||||
* of the entire transfer is actually determined by a count that has been pre-loaded into the DMA controller. The FDC
|
||||
* isn't even aware of the extent of the transfer, so in the case of a read request, all readByte() can do is return
|
||||
* isn't even aware of the extent of the transfer, so in the case of a read request, all readData() can do is return
|
||||
* bytes until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||
*
|
||||
* Since seekDrive() is for use with non-DMA requests, we use nBytes to specify the length of the entire transfer.
|
||||
|
|
@ -1144,7 +1144,7 @@ FDC.prototype.seekDrive = function(drive, iSector, nSectors)
|
|||
drive.resCode = FDC.REG_DATA.RES.NONE;
|
||||
/*
|
||||
* At this point, we've finished simulating what an FDC.REG_DATA.CMD.READ_DATA command would have performed,
|
||||
* up through doRead(). Now it's the caller responsibility to call readByte(), just like the DMA Controller would.
|
||||
* up through doRead(). Now it's the caller responsibility to call readData(), just like the DMA Controller would.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2147,7 +2147,7 @@ FDC.prototype.pushST3 = function(drive)
|
|||
FDC.prototype.dmaRead = function(drive, b, done)
|
||||
{
|
||||
if (b === undefined || b < 0) {
|
||||
this.readByte(drive, done);
|
||||
this.readData(drive, done);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
|
@ -2168,7 +2168,7 @@ FDC.prototype.dmaRead = function(drive, b, done)
|
|||
FDC.prototype.dmaWrite = function(drive, b)
|
||||
{
|
||||
if (b !== undefined && b >= 0)
|
||||
return this.writeByte(drive, b);
|
||||
return this.writeData(drive, b);
|
||||
/*
|
||||
* The DMA controller should be GIVING us data, not ASKING for data; this suggests an internal DMA miscommunication
|
||||
*/
|
||||
|
|
@ -2285,7 +2285,7 @@ FDC.prototype.doFormat = function(drive)
|
|||
};
|
||||
|
||||
/**
|
||||
* readByte(drive, done)
|
||||
* readData(drive, done)
|
||||
*
|
||||
* The following drive properties must have been setup prior to our first call:
|
||||
*
|
||||
|
|
@ -2294,11 +2294,11 @@ FDC.prototype.doFormat = function(drive)
|
|||
* drive.bSector
|
||||
* drive.sector (initialized to null)
|
||||
*
|
||||
* On the first readByte() request, since drive.sector will be null, we ask the Disk object to look
|
||||
* On the first readData() request, since drive.sector will be null, we ask the Disk object to look
|
||||
* up the first sector of the request. We then ask the Disk for bytes from that sector until the sector
|
||||
* is exhausted, and then we look up the next sector and continue the process.
|
||||
*
|
||||
* NOTE: Since the FDC isn't aware of the extent of the transfer, all readByte() can do is return bytes
|
||||
* NOTE: Since the FDC isn't aware of the extent of the transfer, all readData() can do is return bytes
|
||||
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||
*
|
||||
* TODO: Research the requirements, if any, for multi-track I/O and determine what else needs to be done.
|
||||
|
|
@ -2307,7 +2307,7 @@ FDC.prototype.doFormat = function(drive)
|
|||
* @param {Object} drive
|
||||
* @param {function(number,boolean,Object,number)} done (number is next available byte from drive, or -1 if no more bytes available)
|
||||
*/
|
||||
FDC.prototype.readByte = function(drive, done)
|
||||
FDC.prototype.readData = function(drive, done)
|
||||
{
|
||||
var b = -1;
|
||||
var obj = null, off = 0; // these variables are purely for BACKTRACK purposes
|
||||
|
|
@ -2332,7 +2332,7 @@ FDC.prototype.readByte = function(drive, done)
|
|||
drive.ibSector = 0;
|
||||
/*
|
||||
* We "pre-advance" bSector et al now, instead of waiting to advance it right before the seek().
|
||||
* This allows the initial call to readByte() to perform a seek without triggering an unwanted advance.
|
||||
* This allows the initial call to readData() to perform a seek without triggering an unwanted advance.
|
||||
*/
|
||||
this.advanceSector(drive);
|
||||
} while (true);
|
||||
|
|
@ -2341,7 +2341,7 @@ FDC.prototype.readByte = function(drive, done)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByte(drive, b)
|
||||
* writeData(drive, b)
|
||||
*
|
||||
* The following drive properties must have been setup prior to our first call:
|
||||
*
|
||||
|
|
@ -2350,11 +2350,11 @@ FDC.prototype.readByte = function(drive, done)
|
|||
* drive.bSector
|
||||
* drive.sector (initialized to null)
|
||||
*
|
||||
* On the first writeByte() request, since drive.sector will be null, we ask the Disk object to look
|
||||
* On the first writeData() request, since drive.sector will be null, we ask the Disk object to look
|
||||
* up the first sector of the request. We then send the Disk bytes for that sector until the sector
|
||||
* is full, and then we look up the next sector and continue the process.
|
||||
*
|
||||
* NOTE: Since the FDC isn't aware of the extent of the transfer, all writeByte() can do is accept bytes
|
||||
* NOTE: Since the FDC isn't aware of the extent of the transfer, all writeData() can do is accept bytes
|
||||
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||
*
|
||||
* TODO: Research the requirements, if any, for multi-track I/O and determine what else needs to be done.
|
||||
|
|
@ -2364,7 +2364,7 @@ FDC.prototype.readByte = function(drive, done)
|
|||
* @param {number} b containing next byte to write
|
||||
* @return {number} (b unchanged; return -1 if command should be terminated)
|
||||
*/
|
||||
FDC.prototype.writeByte = function(drive, b)
|
||||
FDC.prototype.writeData = function(drive, b)
|
||||
{
|
||||
if (drive.resCode || !drive.disk) return -1;
|
||||
do {
|
||||
|
|
@ -2387,7 +2387,7 @@ FDC.prototype.writeByte = function(drive, b)
|
|||
drive.ibSector = 0;
|
||||
/*
|
||||
* We "pre-advance" bSector et al now, instead of waiting to advance it right before the seek().
|
||||
* This allows the initial call to writeByte() to perform a seek without triggering an unwanted advance.
|
||||
* This allows the initial call to writeData() to perform a seek without triggering an unwanted advance.
|
||||
*/
|
||||
this.advanceSector(drive);
|
||||
} while (true);
|
||||
|
|
@ -2441,7 +2441,7 @@ FDC.prototype.writeFormat = function(drive, b)
|
|||
this.printMessage("writeFormat(head=" + str.toHexByte(drive.bHead) + ",cyl=" + str.toHexByte(drive.bCylinder) + ",sec=" + str.toHexByte(drive.bSector) + ",len=" + str.toHexWord(drive.nBytes) + ")");
|
||||
}
|
||||
for (var i = 0; i < drive.nBytes; i++) {
|
||||
if (this.writeByte(drive, drive.bFiller) < 0) {
|
||||
if (this.writeData(drive, drive.bFiller) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -814,7 +814,7 @@ HDC.prototype.initDrive = function(iDrive, drive, driveConfig, data, fHard)
|
|||
|
||||
/*
|
||||
* errorCode could be an HDC global, but in order to insulate HDC state from the operation of various functions
|
||||
* that operate on drive objects (eg, readByte and writeByte), I've made it a per-drive variable. This choice may
|
||||
* that operate on drive objects (eg, readData and writeData), I've made it a per-drive variable. This choice may
|
||||
* be contrary to how the actual hardware works, but I prefer this approach, as long as it doesn't expose any
|
||||
* incompatibilities that any software actually cares about.
|
||||
*/
|
||||
|
|
@ -1039,7 +1039,7 @@ HDC.prototype.verifyDrive = function(drive, type)
|
|||
*
|
||||
* Also note that in an actual HDC request, drive.nBytes is initialized to the size of a single sector; the extent
|
||||
* of the entire transfer is actually determined by a count that has been pre-loaded into the DMA controller. The HDC
|
||||
* isn't aware of the extent of the transfer, so in the case of a read request, all readByte() can do is return bytes
|
||||
* isn't aware of the extent of the transfer, so in the case of a read request, all readData() can do is return bytes
|
||||
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||
*
|
||||
* Since seekDrive() is for use with non-DMA requests, we use nBytes to specify the length of the entire transfer.
|
||||
|
|
@ -1082,7 +1082,7 @@ HDC.prototype.seekDrive = function(drive, iSector, nSectors)
|
|||
drive.errorCode = HDC.XTC.DATA.ERR.NONE;
|
||||
/*
|
||||
* At this point, we've finished simulating what an HDC.XTC.DATA.CMD.READ_DATA command would have performed,
|
||||
* up through doDMARead(). Now it's the caller responsibility to call readByte(), like the DMA Controller would.
|
||||
* up through doDMARead(). Now it's the caller responsibility to call readData(), like the DMA Controller would.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1389,13 +1389,13 @@ HDC.prototype.inATCData = function(port, addrFrom)
|
|||
|
||||
if (this.drive) {
|
||||
/*
|
||||
* We use the synchronous form of readByte() at this point because we have no choice; an I/O instruction
|
||||
* We use the synchronous form of readData() at this point because we have no choice; an I/O instruction
|
||||
* has just occurred and cannot be delayed. The good news is that doATCommand() should have already primed
|
||||
* the pump; all we can do is assert that the pump has something in it. If bIn is inexplicably negative,
|
||||
* well, then the caller will get 0xff.
|
||||
*/
|
||||
var hdc = this;
|
||||
bIn = this.readByte(this.drive, function(b, fAsync, obj, off) {
|
||||
bIn = this.readData(this.drive, function(b, fAsync, obj, off) {
|
||||
hdc.assert(!fAsync);
|
||||
if (BACKTRACK) {
|
||||
if (!off && obj.file && hdc.messageEnabled(Messages.DISK)) {
|
||||
|
|
@ -1440,7 +1440,7 @@ HDC.prototype.inATCData = function(port, addrFrom)
|
|||
*/
|
||||
if (this.drive.nBytes >= this.drive.cbSector) {
|
||||
hdc.regStatus = HDC.ATC.STATUS.BUSY | HDC.ATC.STATUS.DATA_REQ;
|
||||
this.readByte(this.drive, function(b, fAsync) {
|
||||
this.readData(this.drive, function(b, fAsync) {
|
||||
if (b >= 0) {
|
||||
hdc.setATCIRR();
|
||||
hdc.regStatus = HDC.ATC.STATUS.READY | HDC.ATC.STATUS.SEEK_OK;
|
||||
|
|
@ -1475,7 +1475,7 @@ HDC.prototype.outATCData = function(port, bOut, addrFrom)
|
|||
{
|
||||
if (this.drive) {
|
||||
if (this.drive.nBytes >= this.drive.cbSector) {
|
||||
if (this.writeByte(this.drive, bOut) < 0) {
|
||||
if (this.writeData(this.drive, bOut) < 0) {
|
||||
/*
|
||||
* TODO: It would be nice to be a bit more specific about the error (if any) that just occurred.
|
||||
* Consult drive.errorCode (it uses older XTC error codes, but mapping those codes should be trivial).
|
||||
|
|
@ -1833,11 +1833,11 @@ HDC.prototype.doATC = function()
|
|||
/*
|
||||
* Since the ATC doesn't use DMA, we must now set some additional Drive state for the benefit of any
|
||||
* follow-up I/O instructions. For example, any subsequent inATCData() and outATCData() calls need to
|
||||
* know which drive to talk to ("this.drive"), to issue their own readByte() and writeByte() calls.
|
||||
* know which drive to talk to ("this.drive"), to issue their own readData() and writeData() calls.
|
||||
*
|
||||
* The XTC didn't need this, because it used doDMARead(), doDMAWrite(), doDMAFormat() helper functions,
|
||||
* which reset the current drive's "sector" and "errorCode" properties themselves and then used DMA
|
||||
* functions that delivered drive data with direct calls to readByte() and writeByte().
|
||||
* functions that delivered drive data with direct calls to readData() and writeData().
|
||||
*/
|
||||
drive.sector = null;
|
||||
drive.ibSector = 0;
|
||||
|
|
@ -1856,7 +1856,7 @@ HDC.prototype.doATC = function()
|
|||
this.printMessage("HDC.doRead(" + iDrive + ',' + drive.wCylinder + ':' + drive.bHead + ':' + drive.bSector + ',' + nSectors + ")", true);
|
||||
}
|
||||
/*
|
||||
* We're using a call to readByte() that disables auto-increment, so that once we've got the first
|
||||
* We're using a call to readData() that disables auto-increment, so that once we've got the first
|
||||
* byte of the next sector, we can signal an interrupt without also consuming the first byte, allowing
|
||||
* inATCData() to begin with that byte.
|
||||
*
|
||||
|
|
@ -1865,7 +1865,7 @@ HDC.prototype.doATC = function()
|
|||
*/
|
||||
hdc.regStatus = HDC.ATC.STATUS.BUSY | HDC.ATC.STATUS.DATA_REQ;
|
||||
|
||||
this.readByte(drive, function(b, fAsync) {
|
||||
this.readData(drive, function(b, fAsync) {
|
||||
if (b >= 0 && hdc.chipset) {
|
||||
hdc.setATCIRR();
|
||||
hdc.regStatus = HDC.ATC.STATUS.READY | HDC.ATC.STATUS.SEEK_OK;
|
||||
|
|
@ -2211,7 +2211,7 @@ HDC.prototype.pushResult = function(bResult)
|
|||
HDC.prototype.dmaRead = function(drive, b, done)
|
||||
{
|
||||
if (b === undefined || b < 0) {
|
||||
this.readByte(drive, done);
|
||||
this.readData(drive, done);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
|
@ -2232,7 +2232,7 @@ HDC.prototype.dmaRead = function(drive, b, done)
|
|||
HDC.prototype.dmaWrite = function(drive, b)
|
||||
{
|
||||
if (b !== undefined && b >= 0)
|
||||
return this.writeByte(drive, b);
|
||||
return this.writeData(drive, b);
|
||||
/*
|
||||
* The DMA controller should be GIVING us data, not ASKING for data; this suggests an internal DMA miscommunication
|
||||
*/
|
||||
|
|
@ -2298,7 +2298,7 @@ HDC.prototype.doDMARead = function(drive, done)
|
|||
if (this.chipset) {
|
||||
/*
|
||||
* We need to reverse the original logic, and default to success unless/until an actual error occurs;
|
||||
* otherwise dmaRead()/readByte() will bail on us. The original approach used to work because requestDMA()
|
||||
* otherwise dmaRead()/readData() will bail on us. The original approach used to work because requestDMA()
|
||||
* would immediately call us back with fComplete set to true EVEN if the DMA channel was not yet unmasked;
|
||||
* now the callback is deferred until the DMA channel has been unmasked and the DMA request has finished.
|
||||
*/
|
||||
|
|
@ -2342,7 +2342,7 @@ HDC.prototype.doDMAWrite = function(drive, done)
|
|||
if (this.chipset) {
|
||||
/*
|
||||
* We need to reverse the original logic, and default to success unless/until an actual error occurs;
|
||||
* otherwise dmaWrite()/writeByte() will bail on us. The original approach would work because requestDMA()
|
||||
* otherwise dmaWrite()/writeData() will bail on us. The original approach would work because requestDMA()
|
||||
* would immediately call us back with fComplete set to true EVEN if the DMA channel was not yet unmasked;
|
||||
* now the callback is deferred until the DMA channel has been unmasked and the DMA request has finished.
|
||||
*/
|
||||
|
|
@ -2474,7 +2474,7 @@ HDC.prototype.doDMAFormat = function(drive, done)
|
|||
*/
|
||||
|
||||
/**
|
||||
* readByte(drive, done)
|
||||
* readData(drive, done)
|
||||
*
|
||||
* The following drive variable properties must have been setup prior to our first call:
|
||||
*
|
||||
|
|
@ -2483,11 +2483,11 @@ HDC.prototype.doDMAFormat = function(drive, done)
|
|||
* drive.bSector
|
||||
* drive.sector (initialized to null)
|
||||
*
|
||||
* On the first readByte() request, since drive.sector will be null, we ask the Disk object to look
|
||||
* On the first readData() request, since drive.sector will be null, we ask the Disk object to look
|
||||
* up the first sector of the request. We then ask the Disk for bytes from that sector until the sector
|
||||
* is exhausted, and then we look up the next sector and continue the process.
|
||||
*
|
||||
* NOTE: Since the HDC isn't aware of the extent of the transfer, all readByte() can do is return bytes
|
||||
* NOTE: Since the HDC isn't aware of the extent of the transfer, all readData() can do is return bytes
|
||||
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||
*
|
||||
* @this {HDC}
|
||||
|
|
@ -2496,7 +2496,7 @@ HDC.prototype.doDMAFormat = function(drive, done)
|
|||
* @param {boolean} [fAutoInc] (default is true to auto-increment)
|
||||
* @return {number} the requested byte, or -1 if unavailable
|
||||
*/
|
||||
HDC.prototype.readByte = function(drive, done, fAutoInc)
|
||||
HDC.prototype.readData = function(drive, done, fAutoInc)
|
||||
{
|
||||
var b = -1;
|
||||
var obj = null, off = 0; // these variables are purely for BACKTRACK purposes
|
||||
|
|
@ -2535,7 +2535,7 @@ HDC.prototype.readByte = function(drive, done, fAutoInc)
|
|||
off = drive.ibSector = 0;
|
||||
/*
|
||||
* We "pre-advance" bSector et al now, instead of waiting to advance it right before the seek().
|
||||
* This allows the initial call to readByte() to perform a seek without triggering an unwanted advance.
|
||||
* This allows the initial call to readData() to perform a seek without triggering an unwanted advance.
|
||||
*/
|
||||
hdc.advanceSector(drive);
|
||||
b = drive.disk.read(drive.sector, drive.ibSector);
|
||||
|
|
@ -2554,7 +2554,7 @@ HDC.prototype.readByte = function(drive, done, fAutoInc)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByte(drive, b)
|
||||
* writeData(drive, b)
|
||||
*
|
||||
* The following drive variable properties must have been setup prior to our first call:
|
||||
*
|
||||
|
|
@ -2563,11 +2563,11 @@ HDC.prototype.readByte = function(drive, done, fAutoInc)
|
|||
* drive.bSector
|
||||
* drive.sector (initialized to null)
|
||||
*
|
||||
* On the first writeByte() request, since drive.sector will be null, we ask the Disk object to look
|
||||
* On the first writeData() request, since drive.sector will be null, we ask the Disk object to look
|
||||
* up the first sector of the request. We then send the Disk bytes for that sector until the sector
|
||||
* is full, and then we look up the next sector and continue the process.
|
||||
*
|
||||
* NOTE: Since the HDC isn't aware of the extent of the transfer, all writeByte() can do is accept bytes
|
||||
* NOTE: Since the HDC isn't aware of the extent of the transfer, all writeData() can do is accept bytes
|
||||
* until the current track (or, in the case of a multi-track request, the current cylinder) has been exhausted.
|
||||
*
|
||||
* @this {HDC}
|
||||
|
|
@ -2575,7 +2575,7 @@ HDC.prototype.readByte = function(drive, done, fAutoInc)
|
|||
* @param {number} b containing next byte to write
|
||||
* @return {number} (b unchanged; return -1 if command should be terminated)
|
||||
*/
|
||||
HDC.prototype.writeByte = function(drive, b)
|
||||
HDC.prototype.writeData = function(drive, b)
|
||||
{
|
||||
if (drive.errorCode) return -1;
|
||||
do {
|
||||
|
|
@ -2603,7 +2603,7 @@ HDC.prototype.writeByte = function(drive, b)
|
|||
drive.ibSector = 0;
|
||||
/*
|
||||
* We "pre-advance" bSector et al now, instead of waiting to advance it right before the seek().
|
||||
* This allows the initial call to writeByte() to perform a seek without triggering an unwanted advance.
|
||||
* This allows the initial call to writeData() to perform a seek without triggering an unwanted advance.
|
||||
*/
|
||||
this.advanceSector(drive);
|
||||
} while (true);
|
||||
|
|
@ -2691,7 +2691,7 @@ HDC.prototype.writeFormat = function(drive, b)
|
|||
}
|
||||
|
||||
for (var i = 0; i < drive.nBytes; i++) {
|
||||
if (this.writeByte(drive, drive.bFiller) < 0) {
|
||||
if (this.writeData(drive, drive.bFiller) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,22 +30,6 @@
|
|||
* any copyright as to their contents.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Historical Notes
|
||||
*
|
||||
* To minimize possible future confusion with regard to the 80386's page tables
|
||||
* and page-based virtual memory, the original Page component was converted into
|
||||
* this new Memory component, which provides callers with "blocks" of physical
|
||||
* memory rather than "pages". Callers have been updated to refer to their Memory
|
||||
* allocations as "blocks" as well.
|
||||
*
|
||||
* Note that the Bus component continues to specify a default block size of 4Kb (for
|
||||
* the default "buswidth" of 20), but only because that seems to strike a good balance
|
||||
* between data structure overhead and the memory granularity requirements of most
|
||||
* system components. For larger bus widths, larger physical block sizes may be used;
|
||||
* see the Bus constructor for details.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
|
|
@ -104,13 +88,14 @@ var littleEndian = (TYPEDARRAYS? (function() {
|
|||
* is available).
|
||||
*
|
||||
* @constructor
|
||||
* @param {number} [addr] of lowest used address in block
|
||||
* @param {number|null} [addr] of lowest used address in block
|
||||
* @param {number} [used] portion of block in bytes (0 for none); must be a multiple of 4
|
||||
* @param {number} [size] of block's buffer in bytes (0 for none); must be a multiple of 4
|
||||
* @param {number} [type] is one of the Memory.TYPE constants (default is Memory.TYPE.NONE)
|
||||
* @param {Object} [controller] is an optional memory controller component
|
||||
* @param {Bus} [bus]
|
||||
*/
|
||||
function Memory(addr, used, size, type, controller)
|
||||
function Memory(addr, used, size, type, controller, bus)
|
||||
{
|
||||
var i;
|
||||
this.id = (Memory.idBlock += 2);
|
||||
|
|
@ -122,6 +107,7 @@ function Memory(addr, used, size, type, controller)
|
|||
this.type = type || Memory.TYPE.NONE;
|
||||
this.fReadOnly = (type == Memory.TYPE.ROM);
|
||||
this.controller = null;
|
||||
this.bus = bus;
|
||||
this.fDirty = this.fDirtyEver = false;
|
||||
|
||||
if (BACKTRACK) {
|
||||
|
|
@ -142,7 +128,7 @@ function Memory(addr, used, size, type, controller)
|
|||
|
||||
/*
|
||||
* For empty memory blocks, all we need to do is ensure all access functions
|
||||
* are mapped to "none" handlers.
|
||||
* are mapped to "none" handlers (or "unpaged" handlers if paging is enabled).
|
||||
*/
|
||||
if (!size) {
|
||||
this.setAccess();
|
||||
|
|
@ -168,7 +154,7 @@ function Memory(addr, used, size, type, controller)
|
|||
* know how to deal with this simple 1-1 mapping of addresses to bytes and words.
|
||||
*
|
||||
* TODO: Consider initializing the memory array to random (or pseudo-random) values in DEBUG
|
||||
* mode; pseudo-random might be best, because if it uncovers a bug, the bug should be reproducible.
|
||||
* mode; pseudo-random might be best, to help make any bugs reproducible.
|
||||
*/
|
||||
if (TYPEDARRAYS) {
|
||||
this.buffer = new ArrayBuffer(size);
|
||||
|
|
@ -220,6 +206,7 @@ Memory.TYPE = {
|
|||
ROM: 2,
|
||||
VIDEO: 3,
|
||||
CTRL: 4,
|
||||
UNPAGED:5,
|
||||
NAMES: ["NONE", "RAM", "ROM", "VIDEO", "H/W"],
|
||||
COLORS: ["black", "blue", "green", "cyan"]
|
||||
};
|
||||
|
|
@ -367,12 +354,14 @@ Memory.prototype = {
|
|||
/**
|
||||
* setAccess(afn)
|
||||
*
|
||||
* If no afn is specified, a default is selected based on the Memory type.
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {Array.<function()>} [afn]
|
||||
* @param {boolean} [fDirect]
|
||||
*/
|
||||
setAccess: function(afn, fDirect) {
|
||||
if (!afn) afn = [];
|
||||
afn = afn || (this.type == Memory.TYPE.UNPAGED? Memory.afnUnpaged : Memory.afnNone);
|
||||
if (fDirect === undefined) fDirect = true; // TODO: Verify that this is desired default behavior
|
||||
this.setReadAccess(afn, fDirect);
|
||||
this.setWriteAccess(afn, fDirect);
|
||||
|
|
@ -432,23 +421,31 @@ Memory.prototype = {
|
|||
this.writeLong = this.fReadOnly? this.writeNone : this.writeLongDirect;
|
||||
},
|
||||
/**
|
||||
* setDebugInfo(cpu, dbg, addr, size)
|
||||
* setDebugger(dbg, addr, size)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {X86CPU|Component} cpu
|
||||
* @param {Debugger|Component} dbg
|
||||
* @param {number} addr of block
|
||||
* @param {number} size of block
|
||||
*/
|
||||
setDebugInfo: function(cpu, dbg, addr, size) {
|
||||
setDebugger: function(dbg, addr, size) {
|
||||
if (DEBUGGER) {
|
||||
this.cpu = cpu;
|
||||
this.dbg = dbg;
|
||||
this.cReadBreakpoints = this.cWriteBreakpoints = 0;
|
||||
Component.assert(this.dbg);
|
||||
this.dbg.redoBreakpoints(addr, size);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* setPageBlock(addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} addr
|
||||
* @return {Memory}
|
||||
*/
|
||||
setPageBlock: function(addr) {
|
||||
return this.bus.mapPageBlock(addr);
|
||||
},
|
||||
/**
|
||||
* addBreakpoint(off, fWrite)
|
||||
*
|
||||
|
|
@ -514,85 +511,86 @@ Memory.prototype = {
|
|||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readNone: function readNone(off) {
|
||||
readNone: function readNone(off, addr) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages.MEM) /* && !off */) {
|
||||
this.dbg.message("attempt to read invalid block %" + str.toHex(this.addr) + " from " + this.dbg.hexOffset(this.cpu.getIP(), this.cpu.getCS()));
|
||||
this.dbg.message("attempt to read invalid block %" + str.toHex(this.addr), true);
|
||||
}
|
||||
return 0xff;
|
||||
},
|
||||
/**
|
||||
* writeNone(off, v)
|
||||
* writeNone(off, v, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} v (could be either a byte or word value, since we use the same handler for both kinds of accesses)
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeNone: function writeNone(off, v)
|
||||
{
|
||||
writeNone: function writeNone(off, v, addr) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages.MEM) /* && !off */) {
|
||||
this.dbg.message("attempt to write " + str.toHexWord(v) + " to invalid block %" + str.toHex(this.addr), true);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* readShortDefault(off)
|
||||
* readShortDefault(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readShortDefault: function readShortDefault(off)
|
||||
{
|
||||
return this.readByteDirect(off) | (this.readByteDirect(off + 1) << 8);
|
||||
readShortDefault: function readShortDefault(off, addr) {
|
||||
return this.readByteDirect(off, addr) | (this.readByteDirect(off + 1, addr) << 8);
|
||||
},
|
||||
/**
|
||||
* readLongDefault(off)
|
||||
* readLongDefault(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readLongDefault: function readLongDefault(off)
|
||||
{
|
||||
return this.readByteDirect(off) | (this.readByteDirect(off + 1) << 8) | (this.readByteDirect(off + 2) << 16) | (this.readByteDirect(off + 3) << 24);
|
||||
readLongDefault: function readLongDefault(off, addr) {
|
||||
return this.readByteDirect(off, addr) | (this.readByteDirect(off + 1, addr) << 8) | (this.readByteDirect(off + 2, addr) << 16) | (this.readByteDirect(off + 3, addr) << 24);
|
||||
},
|
||||
/**
|
||||
* writeShortDefault(off, w)
|
||||
* writeShortDefault(off, w, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} w
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeShortDefault: function writeShortDefault(off, w)
|
||||
{
|
||||
writeShortDefault: function writeShortDefault(off, w, addr) {
|
||||
Component.assert(!(w & ~0xffff));
|
||||
this.writeByteDirect(off, w & 0xff);
|
||||
this.writeByteDirect(off + 1, w >> 8);
|
||||
},
|
||||
/**
|
||||
* writeLongDefault(off, w)
|
||||
* writeLongDefault(off, w, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} w
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeLongDefault: function writeLongDefault(off, w)
|
||||
{
|
||||
writeLongDefault: function writeLongDefault(off, w, addr) {
|
||||
this.writeByteDirect(off, w & 0xff);
|
||||
this.writeByteDirect(off + 1, (w >> 8) & 0xff);
|
||||
this.writeByteDirect(off + 2, (w >> 16) & 0xff);
|
||||
this.writeByteDirect(off + 3, (w >>> 24));
|
||||
},
|
||||
/**
|
||||
* readByteMemory(off)
|
||||
* readByteMemory(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readByteMemory: function readByteMemory(off)
|
||||
{
|
||||
readByteMemory: function readByteMemory(off, addr) {
|
||||
Component.assert(off >= 0 && off < this.size);
|
||||
if (FATARRAYS) {
|
||||
return this.ab[off];
|
||||
|
|
@ -600,14 +598,14 @@ Memory.prototype = {
|
|||
return ((this.adw[off >> 2] >>> ((off & 0x3) << 3)) & 0xff);
|
||||
},
|
||||
/**
|
||||
* readShortMemory(off)
|
||||
* readShortMemory(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readShortMemory: function readShortMemory(off)
|
||||
{
|
||||
readShortMemory: function readShortMemory(off, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 1);
|
||||
if (FATARRAYS) {
|
||||
return this.ab[off] | (this.ab[off + 1] << 8);
|
||||
|
|
@ -624,14 +622,14 @@ Memory.prototype = {
|
|||
return w;
|
||||
},
|
||||
/**
|
||||
* readLongMemory(off)
|
||||
* readLongMemory(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readLongMemory: function readLongMemory(off)
|
||||
{
|
||||
readLongMemory: function readLongMemory(off, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 3);
|
||||
if (FATARRAYS) {
|
||||
return this.ab[off] | (this.ab[off + 1] << 8) | (this.ab[off + 2] << 16) | (this.ab[off + 3] << 24);
|
||||
|
|
@ -646,14 +644,14 @@ Memory.prototype = {
|
|||
return l;
|
||||
},
|
||||
/**
|
||||
* writeByteMemory(off, b)
|
||||
* writeByteMemory(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeByteMemory: function writeByteMemory(off, b)
|
||||
{
|
||||
writeByteMemory: function writeByteMemory(off, b, addr) {
|
||||
Component.assert(off >= 0 && off < this.size && (b & 0xff) == b);
|
||||
if (FATARRAYS) {
|
||||
this.ab[off] = b;
|
||||
|
|
@ -665,14 +663,14 @@ Memory.prototype = {
|
|||
this.fDirty = true;
|
||||
},
|
||||
/**
|
||||
* writeShortMemory(off, w)
|
||||
* writeShortMemory(off, w, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} w
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeShortMemory: function writeShortMemory(off, w)
|
||||
{
|
||||
writeShortMemory: function writeShortMemory(off, w, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 1 && (w & 0xffff) == w);
|
||||
if (FATARRAYS) {
|
||||
this.ab[off] = (w & 0xff);
|
||||
|
|
@ -696,14 +694,14 @@ Memory.prototype = {
|
|||
this.fDirty = true;
|
||||
},
|
||||
/**
|
||||
* writeLongMemory(off, l)
|
||||
* writeLongMemory(off, l, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} l
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeLongMemory: function writeLongMemory(off, l)
|
||||
{
|
||||
writeLongMemory: function writeLongMemory(off, l, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 3);
|
||||
if (FATARRAYS) {
|
||||
this.ab[off] = (l & 0xff);
|
||||
|
|
@ -730,85 +728,85 @@ Memory.prototype = {
|
|||
this.fDirty = true;
|
||||
},
|
||||
/**
|
||||
* readByteChecked(off)
|
||||
* readByteChecked(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readByteChecked: function readByteChecked(off)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) this.dbg.checkMemoryRead(this.addr + off);
|
||||
return this.readByteDirect(off);
|
||||
readByteChecked: function readByteChecked(off, addr) {
|
||||
if (DEBUGGER && this.dbg) this.dbg.checkMemoryRead(addr);
|
||||
return this.readByteDirect(off, addr);
|
||||
},
|
||||
/**
|
||||
* readShortChecked(off)
|
||||
* readShortChecked(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readShortChecked: function readShortChecked(off)
|
||||
{
|
||||
readShortChecked: function readShortChecked(off, addr) {
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryRead(this.addr + off) ||
|
||||
this.dbg.checkMemoryRead(this.addr + off + 1);
|
||||
this.dbg.checkMemoryRead(addr) ||
|
||||
this.dbg.checkMemoryRead(addr + 1);
|
||||
}
|
||||
return this.readShortDirect(off);
|
||||
return this.readShortDirect(off, addr);
|
||||
},
|
||||
/**
|
||||
* readLongChecked(off)
|
||||
* readLongChecked(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readLongChecked: function readLongChecked(off)
|
||||
{
|
||||
readLongChecked: function readLongChecked(off, addr) {
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryRead(this.addr + off) ||
|
||||
this.dbg.checkMemoryRead(this.addr + off + 1) ||
|
||||
this.dbg.checkMemoryRead(this.addr + off + 2) ||
|
||||
this.dbg.checkMemoryRead(this.addr + off + 3);
|
||||
this.dbg.checkMemoryRead(addr) ||
|
||||
this.dbg.checkMemoryRead(addr + 1) ||
|
||||
this.dbg.checkMemoryRead(addr + 2) ||
|
||||
this.dbg.checkMemoryRead(addr + 3);
|
||||
}
|
||||
return this.readLongDirect(off);
|
||||
return this.readLongDirect(off, addr);
|
||||
},
|
||||
/**
|
||||
* writeByteChecked(off, b)
|
||||
* writeByteChecked(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @param {number} b
|
||||
*/
|
||||
writeByteChecked: function writeByteChecked(off, b)
|
||||
{
|
||||
if (DEBUGGER && this.dbg) this.dbg.checkMemoryWrite(this.addr + off);
|
||||
this.writeByteDirect(off, b);
|
||||
writeByteChecked: function writeByteChecked(off, b, addr) {
|
||||
if (DEBUGGER && this.dbg) this.dbg.checkMemoryWrite(addr);
|
||||
this.writeByteDirect(off, b, addr);
|
||||
},
|
||||
/**
|
||||
* writeShortChecked(off, w)
|
||||
* writeShortChecked(off, w, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @param {number} w
|
||||
*/
|
||||
writeShortChecked: function writeShortChecked(off, w)
|
||||
{
|
||||
writeShortChecked: function writeShortChecked(off, w, addr) {
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryWrite(this.addr + off) ||
|
||||
this.dbg.checkMemoryWrite(this.addr + off + 1);
|
||||
this.dbg.checkMemoryWrite(addr) ||
|
||||
this.dbg.checkMemoryWrite(addr + 1);
|
||||
}
|
||||
this.writeShortDirect(off, w);
|
||||
this.writeShortDirect(off, w, addr);
|
||||
},
|
||||
/**
|
||||
* writeLongChecked(off, l)
|
||||
* writeLongChecked(off, l, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} l
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeLongChecked: function writeLongChecked(off, l)
|
||||
{
|
||||
writeLongChecked: function writeLongChecked(off, l, addr) {
|
||||
if (DEBUGGER && this.dbg) {
|
||||
this.dbg.checkMemoryWrite(this.addr + off) ||
|
||||
this.dbg.checkMemoryWrite(this.addr + off + 1) ||
|
||||
|
|
@ -818,50 +816,116 @@ Memory.prototype = {
|
|||
this.writeLongDirect(off, l);
|
||||
},
|
||||
/**
|
||||
* readByteBigEndian(off)
|
||||
* readByteUnpaged(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readByteBigEndian: function readByteBigEndian(off)
|
||||
{
|
||||
readByteUnpaged: function readByteUnpaged(off, addr) {
|
||||
return this.setPageBlock(addr).readByte(off, addr);
|
||||
},
|
||||
/**
|
||||
* readShortUnpaged(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readShortUnpaged: function readShortUnpaged(off, addr) {
|
||||
return this.setPageBlock(addr).readShort(off, addr);
|
||||
},
|
||||
/**
|
||||
* readLongUnpaged(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readLongUnpaged: function readLongUnpaged(off, addr) {
|
||||
return this.setPageBlock(addr).readLong(off, addr);
|
||||
},
|
||||
/**
|
||||
* writeByteUnpaged(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeByteUnpaged: function writeByteUnpaged(off, b, addr) {
|
||||
this.setPageBlock(addr).writeByte(off, b, addr);
|
||||
},
|
||||
/**
|
||||
* writeShortUnpaged(off, w, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} w
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeShortUnpaged: function writeShortUnpaged(off, w, addr) {
|
||||
this.setPageBlock(addr).writeShort(off, w, addr);
|
||||
},
|
||||
/**
|
||||
* writeLongUnpaged(off, l, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} l
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeLongUnpaged: function writeLongUnpaged(off, l, addr) {
|
||||
this.setPageBlock(addr).writeLong(off, l, addr);
|
||||
},
|
||||
/**
|
||||
* readByteBigEndian(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readByteBigEndian: function readByteBigEndian(off, addr) {
|
||||
Component.assert(off >= 0 && off < this.size);
|
||||
return this.ab[off];
|
||||
},
|
||||
/**
|
||||
* readByteLittleEndian(off)
|
||||
* readByteLittleEndian(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readByteLittleEndian: function readByteLittleEndian(off)
|
||||
{
|
||||
readByteLittleEndian: function readByteLittleEndian(off, addr) {
|
||||
Component.assert(off >= 0 && off < this.size);
|
||||
return this.ab[off];
|
||||
},
|
||||
/**
|
||||
* readShortBigEndian(off)
|
||||
* readShortBigEndian(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readShortBigEndian: function readShortBigEndian(off)
|
||||
{
|
||||
readShortBigEndian: function readShortBigEndian(off, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 1);
|
||||
return this.dv.getUint16(off, true);
|
||||
},
|
||||
/**
|
||||
* readShortLittleEndian(off)
|
||||
* readShortLittleEndian(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readShortLittleEndian: function readShortLittleEndian(off)
|
||||
{
|
||||
readShortLittleEndian: function readShortLittleEndian(off, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 1);
|
||||
/*
|
||||
* TODO: It remains to be seen if there's any advantage to checking the offset
|
||||
|
|
@ -871,26 +935,26 @@ Memory.prototype = {
|
|||
return (off & 0x1)? (this.ab[off] | (this.ab[off+1] << 8)) : this.aw[off >> 1];
|
||||
},
|
||||
/**
|
||||
* readLongBigEndian(off)
|
||||
* readLongBigEndian(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readLongBigEndian: function readLongBigEndian(off)
|
||||
{
|
||||
readLongBigEndian: function readLongBigEndian(off, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 3);
|
||||
return this.dv.getInt32(off, true);
|
||||
},
|
||||
/**
|
||||
* readLongLittleEndian(off)
|
||||
* readLongLittleEndian(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @return {number}
|
||||
*/
|
||||
readLongLittleEndian: function readLongLittleEndian(off)
|
||||
{
|
||||
readLongLittleEndian: function readLongLittleEndian(off, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 3);
|
||||
/*
|
||||
* TODO: It remains to be seen if there's any advantage to checking the offset
|
||||
|
|
@ -900,53 +964,53 @@ Memory.prototype = {
|
|||
return (off & 0x3)? (this.ab[off] | (this.ab[off+1] << 8) | (this.ab[off+2] << 16) | (this.ab[off+3] << 24)) : this.adw[off >> 2];
|
||||
},
|
||||
/**
|
||||
* writeByteBigEndian(off, b)
|
||||
* writeByteBigEndian(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeByteBigEndian: function writeByteBigEndian(off, b)
|
||||
{
|
||||
writeByteBigEndian: function writeByteBigEndian(off, b, addr) {
|
||||
Component.assert(off >= 0 && off < this.size);
|
||||
this.ab[off] = b;
|
||||
this.fDirty = true;
|
||||
},
|
||||
/**
|
||||
* writeByteLittleEndian(off, b)
|
||||
* writeByteLittleEndian(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @param {number} b
|
||||
*/
|
||||
writeByteLittleEndian: function writeByteLittleEndian(off, b)
|
||||
{
|
||||
writeByteLittleEndian: function writeByteLittleEndian(off, b, addr) {
|
||||
Component.assert(off >= 0 && off < this.size);
|
||||
this.ab[off] = b;
|
||||
this.fDirty = true;
|
||||
},
|
||||
/**
|
||||
* writeShortBigEndian(off, w)
|
||||
* writeShortBigEndian(off, w, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @param {number} w
|
||||
*/
|
||||
writeShortBigEndian: function writeShortBigEndian(off, w)
|
||||
{
|
||||
writeShortBigEndian: function writeShortBigEndian(off, w, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 1);
|
||||
this.dv.setUint16(off, w, true);
|
||||
this.fDirty = true;
|
||||
},
|
||||
/**
|
||||
* writeShortLittleEndian(off, w)
|
||||
* writeShortLittleEndian(off, w, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} addr
|
||||
* @param {number} w
|
||||
*/
|
||||
writeShortLittleEndian: function writeShortLittleEndian(off, w)
|
||||
{
|
||||
writeShortLittleEndian: function writeShortLittleEndian(off, w, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 1);
|
||||
/*
|
||||
* TODO: It remains to be seen if there's any advantage to checking the offset
|
||||
|
|
@ -962,27 +1026,27 @@ Memory.prototype = {
|
|||
this.fDirty = true;
|
||||
},
|
||||
/**
|
||||
* writeLongBigEndian(off, l)
|
||||
* writeLongBigEndian(off, l, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} l
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeLongBigEndian: function writeLongBigEndian(off, l)
|
||||
{
|
||||
writeLongBigEndian: function writeLongBigEndian(off, l, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 3);
|
||||
this.dv.setInt32(off, l, true);
|
||||
this.fDirty = true;
|
||||
},
|
||||
/**
|
||||
* writeLongLittleEndian(off, l)
|
||||
* writeLongLittleEndian(off, l, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} l
|
||||
* @param {number} addr
|
||||
*/
|
||||
writeLongLittleEndian: function writeLongLittleEndian(off, l)
|
||||
{
|
||||
writeLongLittleEndian: function writeLongLittleEndian(off, l, addr) {
|
||||
Component.assert(off >= 0 && off < this.size - 3);
|
||||
/*
|
||||
* TODO: It remains to be seen if there's any advantage to checking the offset
|
||||
|
|
@ -1006,8 +1070,7 @@ Memory.prototype = {
|
|||
* @param {number} off
|
||||
* @return {number}
|
||||
*/
|
||||
readBackTrackNone: function readBackTrackNone(off)
|
||||
{
|
||||
readBackTrackNone: function readBackTrackNone(off) {
|
||||
return 0;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1017,8 +1080,7 @@ Memory.prototype = {
|
|||
* @param {number} off
|
||||
* @param {number} bti
|
||||
*/
|
||||
writeBackTrackNone: function writeBackTrackNone(off, bti)
|
||||
{
|
||||
writeBackTrackNone: function writeBackTrackNone(off, bti) {
|
||||
},
|
||||
/**
|
||||
* modBackTrackNone(fMod)
|
||||
|
|
@ -1026,8 +1088,7 @@ Memory.prototype = {
|
|||
* @this {Memory}
|
||||
* @param {boolean} fMod
|
||||
*/
|
||||
modBackTrackNone: function modBackTrackNone(fMod)
|
||||
{
|
||||
modBackTrackNone: function modBackTrackNone(fMod) {
|
||||
return false;
|
||||
},
|
||||
/**
|
||||
|
|
@ -1037,8 +1098,7 @@ Memory.prototype = {
|
|||
* @param {number} off
|
||||
* @return {number}
|
||||
*/
|
||||
readBackTrackIndex: function readBackTrackIndex(off)
|
||||
{
|
||||
readBackTrackIndex: function readBackTrackIndex(off) {
|
||||
Component.assert(off >= 0 && off < this.size);
|
||||
return this.abtIndexes[off];
|
||||
},
|
||||
|
|
@ -1050,8 +1110,7 @@ Memory.prototype = {
|
|||
* @param {number} bti
|
||||
* @return {number} previous bti (0 if none)
|
||||
*/
|
||||
writeBackTrackIndex: function writeBackTrackIndex(off, bti)
|
||||
{
|
||||
writeBackTrackIndex: function writeBackTrackIndex(off, bti) {
|
||||
var btiPrev;
|
||||
Component.assert(off >= 0 && off < this.size);
|
||||
btiPrev = this.abtIndexes[off];
|
||||
|
|
@ -1065,20 +1124,32 @@ Memory.prototype = {
|
|||
* @param {boolean} fMod
|
||||
* @return {boolean} previous value
|
||||
*/
|
||||
modBackTrackIndex: function modBackTrackIndex(fMod)
|
||||
{
|
||||
modBackTrackIndex: function modBackTrackIndex(fMod) {
|
||||
var fModPrev = this.fModBackTrack;
|
||||
this.fModBackTrack = fMod;
|
||||
return fModPrev;
|
||||
}
|
||||
};
|
||||
|
||||
Memory.afnMemory = [Memory.prototype.readByteMemory, Memory.prototype.readShortMemory, Memory.prototype.readLongMemory, Memory.prototype.writeByteMemory, Memory.prototype.writeShortMemory, Memory.prototype.writeLongMemory];
|
||||
Memory.afnChecked = [Memory.prototype.readByteChecked, Memory.prototype.readShortChecked, Memory.prototype.readLongChecked, Memory.prototype.writeByteChecked, Memory.prototype.writeShortChecked, Memory.prototype.writeLongChecked];
|
||||
/*
|
||||
* This is the effective definition of afnNone, but we need not fully define it, because setAccess() already
|
||||
* uses these defaults when any of the 6 handlers (ie, 3 read handlers followed by 3 write handlers) are undefined.
|
||||
*
|
||||
Memory.afnNone = [Memory.prototype.readNone, Memory.prototype.readShortDefault, Memory.prototype.readLongDefault, Memory.prototype.writeNone, Memory.prototype.writeShortDefault, Memory.prototype.writeLongDefault];
|
||||
*/
|
||||
|
||||
Memory.afnNone = [];
|
||||
Memory.afnMemory = [Memory.prototype.readByteMemory, Memory.prototype.readShortMemory, Memory.prototype.readLongMemory, Memory.prototype.writeByteMemory, Memory.prototype.writeShortMemory, Memory.prototype.writeLongMemory];
|
||||
Memory.afnChecked = [Memory.prototype.readByteChecked, Memory.prototype.readShortChecked, Memory.prototype.readLongChecked, Memory.prototype.writeByteChecked, Memory.prototype.writeShortChecked, Memory.prototype.writeLongChecked];
|
||||
|
||||
if (PAGEBLOCKS) {
|
||||
// Memory.afnPaged = [Memory.prototype.readBytePaged, Memory.prototype.readShortPaged, Memory.prototype.readLongPaged, Memory.prototype.writeBytePaged, Memory.prototype.writeShortPaged, Memory.prototype.writeLongPaged];
|
||||
Memory.afnUnpaged = [Memory.prototype.readByteUnpaged, Memory.prototype.readShortUnpaged, Memory.prototype.readLongUnpaged, Memory.prototype.writeByteUnpaged, Memory.prototype.writeShortUnpaged, Memory.prototype.writeLongUnpaged];
|
||||
}
|
||||
|
||||
if (TYPEDARRAYS) {
|
||||
Memory.afnBigEndian = [Memory.prototype.readByteBigEndian, Memory.prototype.readShortBigEndian, Memory.prototype.readLongBigEndian, Memory.prototype.writeByteBigEndian, Memory.prototype.writeShortBigEndian, Memory.prototype.writeLongBigEndian];
|
||||
Memory.afnLittleEndian = [Memory.prototype.readByteLittleEndian, Memory.prototype.readShortLittleEndian, Memory.prototype.readLongLittleEndian, Memory.prototype.writeByteLittleEndian, Memory.prototype.writeShortLittleEndian, Memory.prototype.writeLongLittleEndian];
|
||||
Memory.afnBigEndian = [Memory.prototype.readByteBigEndian, Memory.prototype.readShortBigEndian, Memory.prototype.readLongBigEndian, Memory.prototype.writeByteBigEndian, Memory.prototype.writeShortBigEndian, Memory.prototype.writeLongBigEndian];
|
||||
Memory.afnLittleEndian = [Memory.prototype.readByteLittleEndian, Memory.prototype.readShortLittleEndian, Memory.prototype.readLongLittleEndian, Memory.prototype.writeByteLittleEndian, Memory.prototype.writeShortLittleEndian, Memory.prototype.writeLongLittleEndian];
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined') module.exports = Memory;
|
||||
|
|
|
|||
|
|
@ -383,13 +383,14 @@ CompaqController.RAMSETUP = {
|
|||
};
|
||||
|
||||
/**
|
||||
* readByte(off)
|
||||
* readByte(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off (relative to 0x80C00000)
|
||||
* @param {number} [addr]
|
||||
* @return {number}
|
||||
*/
|
||||
CompaqController.readByte = function readCompaqControllerByte(off)
|
||||
CompaqController.readByte = function readCompaqControllerByte(off, addr)
|
||||
{
|
||||
var b = 0xff;
|
||||
if (off < 0x02) {
|
||||
|
|
@ -400,19 +401,20 @@ CompaqController.readByte = function readCompaqControllerByte(off)
|
|||
}
|
||||
if (DEBUG) {
|
||||
this.controller.ram.printMessage("CompaqController.readByte(" + str.toHexWord(off) + ") returned " + str.toHexByte(b), true, true);
|
||||
if (MAXDEBUG && DEBUGGER && off >= 0x2) this.cpu.stopCPU();
|
||||
if (MAXDEBUG && DEBUGGER && off >= 0x2) this.dbg.stopCPU();
|
||||
}
|
||||
return b;
|
||||
};
|
||||
|
||||
/**
|
||||
* writeByte(off, b)
|
||||
* writeByte(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off (relative to 0x80C00000)
|
||||
* @param {number} b
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
CompaqController.writeByte = function writeCompaqControllerByte(off, b)
|
||||
CompaqController.writeByte = function writeCompaqControllerByte(off, b, addr)
|
||||
{
|
||||
var controller = this.controller;
|
||||
|
||||
|
|
@ -443,7 +445,7 @@ CompaqController.writeByte = function writeCompaqControllerByte(off, b)
|
|||
}
|
||||
}
|
||||
controller.wMappings = (controller.wMappings & ~0xff) | b;
|
||||
if (MAXDEBUG && DEBUGGER) this.cpu.stopCPU();
|
||||
if (MAXDEBUG && DEBUGGER) this.dbg.stopCPU();
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
@ -451,7 +453,7 @@ CompaqController.writeByte = function writeCompaqControllerByte(off, b)
|
|||
*/
|
||||
else if (off == 0x2) {
|
||||
controller.wRAMSetup = (controller.wRAMSetup & ~0xff) | b;
|
||||
if (MAXDEBUG && DEBUGGER) this.cpu.stopCPU();
|
||||
if (MAXDEBUG && DEBUGGER) this.dbg.stopCPU();
|
||||
}
|
||||
/*
|
||||
* All bits in 0x80C00001 and 0x80C00003 are reserved, so we can simply ignore those writes.
|
||||
|
|
|
|||
|
|
@ -1241,13 +1241,14 @@ Card.ACCESS.WRITE.MODE2XOR = 0xE000;
|
|||
Card.ACCESS.WRITE.MASK = 0xff00;
|
||||
|
||||
/**
|
||||
* readByteMode0(off)
|
||||
* readByteMode0(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} [addr]
|
||||
* @return {number}
|
||||
*/
|
||||
Card.ACCESS.readByteMode0 = function readByteMode0(off)
|
||||
Card.ACCESS.readByteMode0 = function readByteMode0(off, addr)
|
||||
{
|
||||
off += this.offset;
|
||||
var dw = this.controller.latches = this.adw[off];
|
||||
|
|
@ -1255,13 +1256,14 @@ Card.ACCESS.readByteMode0 = function readByteMode0(off)
|
|||
};
|
||||
|
||||
/**
|
||||
* readByteMode0EvenOdd(off)
|
||||
* readByteMode0EvenOdd(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} [addr]
|
||||
* @return {number}
|
||||
*/
|
||||
Card.ACCESS.readByteMode0EvenOdd = function readByteMode0EvenOdd(off)
|
||||
Card.ACCESS.readByteMode0EvenOdd = function readByteMode0EvenOdd(off, addr)
|
||||
{
|
||||
off += this.offset;
|
||||
var idw = off & ~0x1;
|
||||
|
|
@ -1269,13 +1271,14 @@ Card.ACCESS.readByteMode0EvenOdd = function readByteMode0EvenOdd(off)
|
|||
};
|
||||
|
||||
/**
|
||||
* readByteMode1(off)
|
||||
* readByteMode1(off, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} [addr]
|
||||
* @return {number}
|
||||
*/
|
||||
Card.ACCESS.readByteMode1 = function readByteMode1(off)
|
||||
Card.ACCESS.readByteMode1 = function readByteMode1(off, addr)
|
||||
{
|
||||
off += this.offset;
|
||||
var dw = this.adw[off];
|
||||
|
|
@ -1290,13 +1293,14 @@ Card.ACCESS.readByteMode1 = function readByteMode1(off)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode0(off, b)
|
||||
* writeByteMode0(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode0 = function writeByteMode0(off, b)
|
||||
Card.ACCESS.writeByteMode0 = function writeByteMode0(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
var dw = b | (b << 8) | (b << 16) | (b << 24);
|
||||
|
|
@ -1309,13 +1313,14 @@ Card.ACCESS.writeByteMode0 = function writeByteMode0(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode0EvenOdd(off, b)
|
||||
* writeByteMode0EvenOdd(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode0EvenOdd = function writeByteMode0EvenOdd(off, b)
|
||||
Card.ACCESS.writeByteMode0EvenOdd = function writeByteMode0EvenOdd(off, b, addr)
|
||||
{
|
||||
off += this.offset;
|
||||
var dw = b | (b << 8) | (b << 16) | (b << 24);
|
||||
|
|
@ -1334,7 +1339,7 @@ Card.ACCESS.writeByteMode0EvenOdd = function writeByteMode0EvenOdd(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode0Rot(off, b)
|
||||
* writeByteMode0Rot(off, b, addr)
|
||||
*
|
||||
* Supporting Set/Reset means that for every plane for which Set/Reset is enabled, we must
|
||||
* replace the corresponding byte in "dw" with a byte of zeros or ones. This is accomplished with
|
||||
|
|
@ -1352,8 +1357,9 @@ Card.ACCESS.writeByteMode0EvenOdd = function writeByteMode0EvenOdd(off, b)
|
|||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode0Rot = function writeByteMode0Rot(off, b)
|
||||
Card.ACCESS.writeByteMode0Rot = function writeByteMode0Rot(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
b = ((b >> this.controller.nDataRotate) | (b << (8 - this.controller.nDataRotate)) & 0xff);
|
||||
|
|
@ -1368,13 +1374,14 @@ Card.ACCESS.writeByteMode0Rot = function writeByteMode0Rot(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode0And(off, b)
|
||||
* writeByteMode0And(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode0And = function writeByteMode0And(off, b)
|
||||
Card.ACCESS.writeByteMode0And = function writeByteMode0And(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
b = ((b >> this.controller.nDataRotate) | (b << (8 - this.controller.nDataRotate)) & 0xff);
|
||||
|
|
@ -1390,13 +1397,14 @@ Card.ACCESS.writeByteMode0And = function writeByteMode0And(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode0Or(off, b)
|
||||
* writeByteMode0Or(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode0Or = function writeByteMode0Or(off, b)
|
||||
Card.ACCESS.writeByteMode0Or = function writeByteMode0Or(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
b = ((b >> this.controller.nDataRotate) | (b << (8 - this.controller.nDataRotate)) & 0xff);
|
||||
|
|
@ -1412,13 +1420,14 @@ Card.ACCESS.writeByteMode0Or = function writeByteMode0Or(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode0Xor(off, b)
|
||||
* writeByteMode0Xor(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode0Xor = function writeByteMode0Xor(off, b)
|
||||
Card.ACCESS.writeByteMode0Xor = function writeByteMode0Xor(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
b = ((b >> this.controller.nDataRotate) | (b << (8 - this.controller.nDataRotate)) & 0xff);
|
||||
|
|
@ -1434,13 +1443,14 @@ Card.ACCESS.writeByteMode0Xor = function writeByteMode0Xor(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode1(off, b)
|
||||
* writeByteMode1(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (ignored; the EGA latches provide the source data)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode1 = function writeByteMode1(off, b)
|
||||
Card.ACCESS.writeByteMode1 = function writeByteMode1(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
var dw = (this.adw[idw] & ~this.controller.nWriteMapMask) | (this.controller.latches & this.controller.nWriteMapMask);
|
||||
|
|
@ -1451,13 +1461,14 @@ Card.ACCESS.writeByteMode1 = function writeByteMode1(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode2(off, b)
|
||||
* writeByteMode2(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode2 = function writeByteMode2(off, b)
|
||||
Card.ACCESS.writeByteMode2 = function writeByteMode2(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
var dw = Video.aEGAByteToDW[b & 0xf];
|
||||
|
|
@ -1470,13 +1481,14 @@ Card.ACCESS.writeByteMode2 = function writeByteMode2(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode2And(off, b)
|
||||
* writeByteMode2And(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode2And = function writeByteMode2And(off, b)
|
||||
Card.ACCESS.writeByteMode2And = function writeByteMode2And(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
var dw = Video.aEGAByteToDW[b & 0xf];
|
||||
|
|
@ -1490,13 +1502,14 @@ Card.ACCESS.writeByteMode2And = function writeByteMode2And(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode2Or(off, b)
|
||||
* writeByteMode2Or(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode2Or = function writeByteMode2Or(off, b)
|
||||
Card.ACCESS.writeByteMode2Or = function writeByteMode2Or(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
var dw = Video.aEGAByteToDW[b & 0xf];
|
||||
|
|
@ -1510,13 +1523,14 @@ Card.ACCESS.writeByteMode2Or = function writeByteMode2Or(off, b)
|
|||
};
|
||||
|
||||
/**
|
||||
* writeByteMode2Xor(off, b)
|
||||
* writeByteMode2Xor(off, b, addr)
|
||||
*
|
||||
* @this {Memory}
|
||||
* @param {number} off
|
||||
* @param {number} b (which should already be pre-masked to 8 bits; see Bus.prototype.setByteDirect)
|
||||
* @param {number} [addr]
|
||||
*/
|
||||
Card.ACCESS.writeByteMode2Xor = function writeByteMode2Xor(off, b)
|
||||
Card.ACCESS.writeByteMode2Xor = function writeByteMode2Xor(off, b, addr)
|
||||
{
|
||||
var idw = off + this.offset;
|
||||
var dw = Video.aEGAByteToDW[b & 0xf];
|
||||
|
|
|
|||
|
|
@ -2525,7 +2525,7 @@ X86CPU.prototype.setBinding = function(sHTMLType, sBinding, control)
|
|||
X86CPU.prototype.getByte = function(addr)
|
||||
{
|
||||
if (BACKTRACK) this.backTrack.btiMemLo = this.bus.readBackTrack(addr);
|
||||
return this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByte(addr & this.blockLimit);
|
||||
return this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByte(addr & this.blockLimit, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2550,9 +2550,9 @@ X86CPU.prototype.getShort = function(addr)
|
|||
this.backTrack.btiMemHi = this.bus.readBackTrack(addr + 1);
|
||||
}
|
||||
if (off < this.blockLimit) {
|
||||
return this.aMemBlocks[iBlock].readShort(off);
|
||||
return this.aMemBlocks[iBlock].readShort(off, addr);
|
||||
}
|
||||
return this.aMemBlocks[iBlock].readByte(off) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readByte(0) << 8);
|
||||
return this.aMemBlocks[iBlock].readByte(off, addr) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readByte(0, addr + 1) << 8);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2571,10 +2571,10 @@ X86CPU.prototype.getLong = function(addr)
|
|||
this.backTrack.btiMemHi = this.bus.readBackTrack(addr + 1);
|
||||
}
|
||||
if (off < this.blockLimit - 2) {
|
||||
return this.aMemBlocks[iBlock].readLong(off);
|
||||
return this.aMemBlocks[iBlock].readLong(off, addr);
|
||||
}
|
||||
var nShift = (off & 0x3) << 3;
|
||||
return (this.aMemBlocks[iBlock].readLong(off & ~0x3) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLong(0) << (32 - nShift));
|
||||
return (this.aMemBlocks[iBlock].readLong(off & ~0x3, addr) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLong(0, addr + 3) << (32 - nShift));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2587,7 +2587,7 @@ X86CPU.prototype.getLong = function(addr)
|
|||
X86CPU.prototype.setByte = function(addr, b)
|
||||
{
|
||||
if (BACKTRACK) this.bus.writeBackTrack(addr, this.backTrack.btiMemLo);
|
||||
this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].writeByte(addr & this.blockLimit, b & 0xff);
|
||||
this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].writeByte(addr & this.blockLimit, b & 0xff, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2612,11 +2612,11 @@ X86CPU.prototype.setShort = function(addr, w)
|
|||
this.bus.writeBackTrack(addr + 1, this.backTrack.btiMemHi);
|
||||
}
|
||||
if (off < this.blockLimit) {
|
||||
this.aMemBlocks[iBlock].writeShort(off, w & 0xffff);
|
||||
this.aMemBlocks[iBlock].writeShort(off, w & 0xffff, addr);
|
||||
return;
|
||||
}
|
||||
this.aMemBlocks[iBlock++].writeByte(off, w & 0xff);
|
||||
this.aMemBlocks[iBlock & this.blockMask].writeByte(0, (w >> 8) & 0xff);
|
||||
this.aMemBlocks[iBlock++].writeByte(off, w & 0xff, addr);
|
||||
this.aMemBlocks[iBlock & this.blockMask].writeByte(0, (w >> 8) & 0xff, addr + 1);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2637,16 +2637,17 @@ X86CPU.prototype.setLong = function(addr, l)
|
|||
this.bus.writeBackTrack(addr + 1, this.backTrack.btiMemHi);
|
||||
}
|
||||
if (off < this.blockLimit - 2) {
|
||||
this.aMemBlocks[iBlock].writeLong(off, l);
|
||||
this.aMemBlocks[iBlock].writeLong(off, l, addr);
|
||||
return;
|
||||
}
|
||||
var lPrev, nShift = (off & 0x3) << 3;
|
||||
off &= ~0x3;
|
||||
lPrev = this.aMemBlocks[iBlock].readLong(off);
|
||||
this.aMemBlocks[iBlock].writeLong(off, (lPrev & ~(-1 << nShift)) | (l << nShift));
|
||||
lPrev = this.aMemBlocks[iBlock].readLong(off, addr);
|
||||
this.aMemBlocks[iBlock].writeLong(off, (lPrev & ~(-1 << nShift)) | (l << nShift), addr);
|
||||
iBlock = (iBlock + 1) & this.blockMask;
|
||||
lPrev = this.aMemBlocks[iBlock].readLong(0);
|
||||
this.aMemBlocks[iBlock].writeLong(0, (lPrev & (-1 << nShift)) | (l >>> (32 - nShift)));
|
||||
addr += 3;
|
||||
lPrev = this.aMemBlocks[iBlock].readLong(0, addr);
|
||||
this.aMemBlocks[iBlock].writeLong(0, (lPrev & (-1 << nShift)) | (l >>> (32 - nShift)), addr);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2950,7 +2951,7 @@ 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.busMask) >>> this.blockShift].readByte(addr & this.blockLimit);
|
||||
* b = this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByte(addr & this.blockLimit, addr);
|
||||
* this.nBusCycles += 4;
|
||||
* this.cbPrefetchValid = 0;
|
||||
* this.addrPrefetchHead = (addr + 1) & this.busMask;
|
||||
|
|
@ -3027,7 +3028,7 @@ X86CPU.prototype.fillPrefetch = function(n)
|
|||
{
|
||||
while (n-- > 0 && this.cbPrefetchQueued < X86CPU.PREFETCH.QUEUE) {
|
||||
var addr = this.addrPrefetchHead;
|
||||
var b = this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByte(addr & this.blockLimit);
|
||||
var b = this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByte(addr & this.blockLimit, addr);
|
||||
this.aPrefetch[this.iPrefetchHead] = b | (addr << 8);
|
||||
if (MAXDEBUG) this.printMessage(" fillPrefetch[" + this.iPrefetchHead + "]: " + str.toHex(addr) + ":" + str.toHexByte(b));
|
||||
this.addrPrefetchHead = (addr + 1) & this.busMask;
|
||||
|
|
|
|||
Loading…
Reference in a new issue