Update ACCESSED bits in GDT/LDT descriptors (finally)

This commit is contained in:
Jeff Parsons 2015-05-11 13:11:30 -07:00 committed by jeffpar
commit 5eed275008
7 changed files with 229 additions and 182 deletions

View file

@ -85,13 +85,13 @@ function Bus(parmsBus, cpu, dbg)
*
* Regarding blockTotal, we want to avoid using block overflow expressions like:
*
* iBlock < this.blockTotal? iBlock : 0
* iBlock < this.nBlockTotal? iBlock : 0
*
* As long as we know that blockTotal is a power of two (eg, 256 or 0x100, in the case of
* nBusWidth == 20 and blockSize == 4096), we can define blockMask as (blockTotal - 1) and
* rewrite the previous expression as:
*
* iBlock & this.blockMask
* iBlock & this.nBlockMask
*
* Similarly, we mask addresses with busMask to enforce "A20 wrap" on 20-bit busses.
* For larger busses, A20 wrap can be simulated by either clearing bit 20 of busMask or by
@ -99,16 +99,16 @@ function Bus(parmsBus, cpu, dbg)
*
* Bus Property Old hard-coded values (when nBusWidth was always 20)
* ------------ ----------------------------------------------------
* this.busLimit 0xfffff
* 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.nBusLimit 0xfffff
* this.nBusMask [same as busLimit]
* this.nBlockSize 4096
* this.nBlockLen (this.nBlockSize >> 2)
* this.nBlockShift 12
* this.nBlockLimit 0xfff
* this.nBlockTotal ((this.nBusLimit + this.nBlockSize) / this.nBlockSize) | 0
* this.nBlockMask (this.nBlockTotal - 1) [ie, 0xff]
*
* Note that we choose a blockShift value (and thus a physical memory block size) based on "buswidth":
* Note that we choose a nBlockShift value (and thus a physical memory block size) based on "buswidth":
*
* Bus Width Block Shift Block Size
* --------- ----------- ----------
@ -119,19 +119,19 @@ function Bus(parmsBus, cpu, dbg)
* The coarser block granularities (ie, 16Kb and 32Kb) may cause problems for certain RAM and/or ROM
* allocations that are contiguous but are allocated out of order, or that have different controller
* 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).
* order, or to choose smaller nBlockShift values (at the expense of a generating a larger block array).
*
* 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;
this.blockShift = (PAGEBLOCKS && this.nBusWidth == 32 || this.nBusWidth <= 20)? 12 : (this.nBusWidth <= 24? 14 : 15);
this.blockSize = 1 << this.blockShift;
this.blockLen = this.blockSize >> 2;
this.blockLimit = this.blockSize - 1;
this.blockTotal = (this.addrTotal / this.blockSize) | 0;
this.blockMask = this.blockTotal - 1;
this.assert(this.blockMask <= Bus.BlockInfo.num.mask);
this.nBusLimit = this.nBusMask = (this.addrTotal - 1) | 0;
this.nBlockShift = (PAGEBLOCKS && this.nBusWidth == 32 || this.nBusWidth <= 20)? 12 : (this.nBusWidth <= 24? 14 : 15);
this.nBlockSize = 1 << this.nBlockShift;
this.nBlockLen = this.nBlockSize >> 2;
this.nBlockLimit = this.nBlockSize - 1;
this.nBlockTotal = (this.addrTotal / this.nBlockSize) | 0;
this.nBlockMask = this.nBlockTotal - 1;
this.assert(this.nBlockMask <= Bus.BlockInfo.num.mask);
/*
* Lists of I/O notification functions: aPortInputNotify and aPortOutputNotify are arrays, indexed by
@ -288,12 +288,12 @@ var BusInfo;
Bus.prototype.initMemory = function()
{
var block = new Memory();
this.aMemBlocks = new Array(this.blockTotal);
for (var iBlock = 0; iBlock < this.blockTotal; iBlock++) {
this.aMemBlocks = new Array(this.nBlockTotal);
for (var iBlock = 0; iBlock < this.nBlockTotal; iBlock++) {
this.aMemBlocks[iBlock] = block;
}
this.cpu.initMemory(this.aMemBlocks, this.blockShift);
this.cpu.setAddressMask(this.busMask);
this.cpu.initMemory(this.aMemBlocks, this.nBlockShift);
this.cpu.setAddressMask(this.nBusMask);
};
/**
@ -363,11 +363,11 @@ Bus.prototype.powerUp = function(data, fRepower)
*/
Bus.prototype.addMemory = function(addr, size, type, controller)
{
var iBlock = addr >>> this.blockShift;
var iBlock = addr >>> this.nBlockShift;
while (size > 0 && iBlock < this.aMemBlocks.length) {
var block = this.aMemBlocks[iBlock];
var addrBlock = iBlock * this.blockSize;
var sizeBlock = size > this.blockSize? this.blockSize : size;
var addrBlock = iBlock * this.nBlockSize;
var sizeBlock = size > this.nBlockSize? this.nBlockSize : size;
if (block && block.size) {
if (block.type == type && block.controller == controller) {
@ -388,18 +388,18 @@ Bus.prototype.addMemory = function(addr, size, type, controller)
if (sizeAvail > size) sizeAvail = size;
block.used = addr - block.addr + sizeAvail;
size -= sizeAvail;
addr = addrBlock + this.blockSize;
addr = addrBlock + this.nBlockSize;
continue;
}
}
return this.reportError(1, addr, size);
}
block = this.aMemBlocks[iBlock++] = new Memory(addr, sizeBlock, this.blockSize, type, controller);
block = this.aMemBlocks[iBlock++] = new Memory(addr, sizeBlock, this.nBlockSize, type, controller);
if (DEBUGGER && this.dbg) {
block.setDebugger(this.dbg, addr, this.blockSize);
block.setDebugger(this.dbg, addr, this.nBlockSize);
}
size -= sizeBlock;
addr = addrBlock + this.blockSize;
addr = addrBlock + this.nBlockSize;
}
if (size > 0) {
return this.reportError(2, addr, size);
@ -418,13 +418,13 @@ Bus.prototype.addMemory = function(addr, size, type, controller)
Bus.prototype.cleanMemory = function(addr, size)
{
var fClean = true;
var iBlock = addr >>> this.blockShift;
var iBlock = addr >>> this.nBlockShift;
while (size > 0 && iBlock < this.aMemBlocks.length) {
if (this.aMemBlocks[iBlock].fDirty) {
this.aMemBlocks[iBlock].fDirty = fClean = false;
this.aMemBlocks[iBlock].fDirtyEver = true;
}
size -= this.blockSize;
size -= this.nBlockSize;
iBlock++;
}
return fClean;
@ -447,8 +447,8 @@ Bus.prototype.scanMemory = function(info, addr, size)
if (size == null) size = (this.addrTotal - addr) | 0;
if (info == null) info = {cbTotal: 0, cBlocks: 0, aBlocks: []};
var iBlock = addr >>> this.blockShift;
var iBlockMax = ((addr + size - 1) >>> this.blockShift);
var iBlock = addr >>> this.nBlockShift;
var iBlockMax = ((addr + size - 1) >>> this.nBlockShift);
info.cbTotal = 0;
info.cBlocks = 0;
@ -473,7 +473,7 @@ Bus.prototype.scanMemory = function(info, addr, size)
*/
Bus.prototype.getA20 = function()
{
return !this.aBlocks2Mb && this.busLimit == this.busMask;
return !this.aBlocks2Mb && this.nBusLimit == this.nBusMask;
};
/**
@ -510,9 +510,9 @@ Bus.prototype.setA20 = function(fEnable)
}
}
else if (this.nBusWidth > 20) {
var addrMask = (this.busMask & ~0x100000) | (fEnable? 0x100000 : 0);
if (addrMask != this.busMask) {
this.busMask = addrMask;
var addrMask = (this.nBusMask & ~0x100000) | (fEnable? 0x100000 : 0);
if (addrMask != this.nBusMask) {
this.nBusMask = addrMask;
if (this.cpu) this.cpu.setAddressMask(addrMask);
}
}
@ -544,15 +544,15 @@ Bus.prototype.getWidth = function()
*/
Bus.prototype.setMemoryAccess = function(addr, size, afn)
{
if (!(addr & this.blockLimit) && size && !(size & this.blockLimit)) {
var iBlock = addr >>> this.blockShift;
if (!(addr & this.nBlockLimit) && size && !(size & this.nBlockLimit)) {
var iBlock = addr >>> this.nBlockShift;
while (size > 0) {
var block = this.aMemBlocks[iBlock];
if (!block.controller) {
return this.reportError(5, addr, size);
}
block.setAccess(afn);
size -= this.blockSize;
size -= this.nBlockSize;
iBlock++;
}
return true;
@ -574,15 +574,15 @@ Bus.prototype.setMemoryAccess = function(addr, size, afn)
*/
Bus.prototype.removeMemory = function(addr, size)
{
if (!(addr & this.blockLimit) && size && !(size & this.blockLimit)) {
var iBlock = addr >>> this.blockShift;
if (!(addr & this.nBlockLimit) && size && !(size & this.nBlockLimit)) {
var iBlock = addr >>> this.nBlockShift;
while (size > 0) {
addr = iBlock * this.blockSize;
addr = iBlock * this.nBlockSize;
var block = this.aMemBlocks[iBlock++] = new Memory(addr);
if (DEBUGGER && this.dbg) {
block.setDebugger(this.dbg, addr, this.blockSize);
block.setDebugger(this.dbg, addr, this.nBlockSize);
}
size -= this.blockSize;
size -= this.nBlockSize;
}
return true;
}
@ -600,10 +600,10 @@ Bus.prototype.removeMemory = function(addr, size)
Bus.prototype.getMemoryBlocks = function(addr, size)
{
var aBlocks = [];
var iBlock = addr >>> this.blockShift;
var iBlock = addr >>> this.nBlockShift;
while (size > 0 && iBlock < this.aMemBlocks.length) {
aBlocks.push(this.aMemBlocks[iBlock++]);
size -= this.blockSize;
size -= this.nBlockSize;
}
return aBlocks;
};
@ -626,7 +626,7 @@ Bus.prototype.getMemoryBlocks = function(addr, size)
Bus.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
{
var i = 0;
var iBlock = addr >>> this.blockShift;
var iBlock = addr >>> this.nBlockShift;
while (size > 0 && iBlock < this.aMemBlocks.length) {
var block = aBlocks[i++];
this.assert(block);
@ -634,13 +634,13 @@ Bus.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
if (type !== undefined) {
var blockNew = new Memory(addr);
if (DEBUGGER && this.dbg) {
blockNew.setDebugger(this.dbg, addr, this.blockSize);
blockNew.setDebugger(this.dbg, addr, this.nBlockSize);
}
blockNew.clone(block, type);
block = blockNew;
}
this.aMemBlocks[iBlock++] = block;
size -= this.blockSize;
size -= this.nBlockSize;
}
};
@ -655,7 +655,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, addr);
return this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].readByte(addr & this.nBlockLimit, addr);
};
/**
@ -669,7 +669,7 @@ Bus.prototype.getByte = function(addr)
*/
Bus.prototype.getByteDirect = function(addr)
{
return this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readByteDirect(addr & this.blockLimit, addr);
return this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].readByteDirect(addr & this.nBlockLimit, addr);
};
/**
@ -683,12 +683,12 @@ Bus.prototype.getByteDirect = function(addr)
*/
Bus.prototype.getShort = function(addr)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.busMask) >>> this.blockShift;
if (off != this.blockLimit) {
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
if (off != this.nBlockLimit) {
return this.aMemBlocks[iBlock].readShort(off, addr);
}
return this.aMemBlocks[iBlock++].readByte(off, addr) | (this.aMemBlocks[iBlock & this.blockMask].readByte(0, addr + 1) << 8);
return this.aMemBlocks[iBlock++].readByte(off, addr) | (this.aMemBlocks[iBlock & this.nBlockMask].readByte(0, addr + 1) << 8);
};
/**
@ -702,12 +702,12 @@ Bus.prototype.getShort = function(addr)
*/
Bus.prototype.getShortDirect = function(addr)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.busMask) >>> this.blockShift;
if (off != this.blockLimit) {
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
if (off != this.nBlockLimit) {
return this.aMemBlocks[iBlock].readShortDirect(off, addr);
}
return this.aMemBlocks[iBlock++].readByteDirect(off, addr) | (this.aMemBlocks[iBlock & this.blockMask].readByteDirect(0, addr + 1) << 8);
return this.aMemBlocks[iBlock++].readByteDirect(off, addr) | (this.aMemBlocks[iBlock & this.nBlockMask].readByteDirect(0, addr + 1) << 8);
};
/**
@ -721,13 +721,13 @@ Bus.prototype.getShortDirect = function(addr)
*/
Bus.prototype.getLong = function(addr)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.busMask) >>> this.blockShift;
if (off < this.blockLimit - 2) {
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
if (off < this.nBlockLimit - 2) {
return this.aMemBlocks[iBlock].readLong(off, addr);
}
var nShift = (off & 0x3) << 3;
return (this.aMemBlocks[iBlock].readLong(off & ~0x3, addr) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLong(0, addr + 3) << (32 - nShift));
return (this.aMemBlocks[iBlock].readLong(off & ~0x3, addr) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.nBlockMask].readLong(0, addr + 3) << (32 - nShift));
};
/**
@ -741,13 +741,13 @@ Bus.prototype.getLong = function(addr)
*/
Bus.prototype.getLongDirect = function(addr)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.busMask) >>> this.blockShift;
if (off < this.blockLimit - 2) {
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
if (off < this.nBlockLimit - 2) {
return this.aMemBlocks[iBlock].readLongDirect(off, addr);
}
var nShift = (off & 0x3) << 3;
return (this.aMemBlocks[iBlock].readLongDirect(off & ~0x3, addr) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLongDirect(0, addr + 3) << (32 - nShift));
return (this.aMemBlocks[iBlock].readLongDirect(off & ~0x3, addr) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.nBlockMask].readLongDirect(0, addr + 3) << (32 - nShift));
};
/**
@ -761,7 +761,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, addr);
this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].writeByte(addr & this.nBlockLimit, b & 0xff, addr);
};
/**
@ -776,7 +776,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, addr);
this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].writeByteDirect(addr & this.nBlockLimit, b & 0xff, addr);
};
/**
@ -790,14 +790,14 @@ Bus.prototype.setByteDirect = function(addr, b)
*/
Bus.prototype.setShort = function(addr, w)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.busMask) >>> this.blockShift;
if (off != this.blockLimit) {
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
if (off != this.nBlockLimit) {
this.aMemBlocks[iBlock].writeShort(off, w & 0xffff, addr);
return;
}
this.aMemBlocks[iBlock++].writeByte(off, w & 0xff, addr);
this.aMemBlocks[iBlock & this.blockMask].writeByte(0, (w >> 8) & 0xff, addr + 1);
this.aMemBlocks[iBlock & this.nBlockMask].writeByte(0, (w >> 8) & 0xff, addr + 1);
};
/**
@ -812,14 +812,14 @@ Bus.prototype.setShort = function(addr, w)
*/
Bus.prototype.setShortDirect = function(addr, w)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.busMask) >>> this.blockShift;
if (off != this.blockLimit) {
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
if (off != this.nBlockLimit) {
this.aMemBlocks[iBlock].writeShortDirect(off, w & 0xffff, addr);
return;
}
this.aMemBlocks[iBlock++].writeByteDirect(off, w & 0xff, addr);
this.aMemBlocks[iBlock & this.blockMask].writeByteDirect(0, (w >> 8) & 0xff, addr + 1);
this.aMemBlocks[iBlock & this.nBlockMask].writeByteDirect(0, (w >> 8) & 0xff, addr + 1);
};
/**
@ -833,9 +833,9 @@ Bus.prototype.setShortDirect = function(addr, w)
*/
Bus.prototype.setLong = function(addr, l)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.busMask) >>> this.blockShift;
if (off < this.blockLimit - 2) {
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
if (off < this.nBlockLimit - 2) {
this.aMemBlocks[iBlock].writeLong(off, l);
return;
}
@ -843,7 +843,7 @@ Bus.prototype.setLong = function(addr, l)
off &= ~0x3;
lPrev = this.aMemBlocks[iBlock].readLong(off, addr);
this.aMemBlocks[iBlock].writeLong(off, (lPrev & ~((0xffffffff|0) << nShift)) | (l << nShift), addr);
iBlock = (iBlock + 1) & this.blockMask;
iBlock = (iBlock + 1) & this.nBlockMask;
addr += 3;
lPrev = this.aMemBlocks[iBlock].readLong(0, addr);
this.aMemBlocks[iBlock].writeLong(0, (lPrev & ((0xffffffff|0) << nShift)) | (l >>> (32 - nShift)), addr);
@ -861,9 +861,9 @@ Bus.prototype.setLong = function(addr, l)
*/
Bus.prototype.setLongDirect = function(addr, l)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.busMask) >>> this.blockShift;
if (off < this.blockLimit - 2) {
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
if (off < this.nBlockLimit - 2) {
this.aMemBlocks[iBlock].writeLongDirect(off, l, addr);
return;
}
@ -871,7 +871,7 @@ Bus.prototype.setLongDirect = function(addr, l)
off &= ~0x3;
lPrev = this.aMemBlocks[iBlock].readLongDirect(off, addr);
this.aMemBlocks[iBlock].writeLongDirect(off, (lPrev & ~((0xffffffff|0) << nShift)) | (l << nShift), addr);
iBlock = (iBlock + 1) & this.blockMask;
iBlock = (iBlock + 1) & this.nBlockMask;
addr += 3;
lPrev = this.aMemBlocks[iBlock].readLongDirect(0, addr);
this.aMemBlocks[iBlock].writeLongDirect(0, (lPrev & ((0xffffffff|0) << nShift)) | (l >>> (32 - nShift)), addr);
@ -983,7 +983,7 @@ Bus.prototype.writeBackTrackObject = function(addr, bto, off)
Bus.prototype.readBackTrack = function(addr)
{
if (BACKTRACK) {
return this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].readBackTrack(addr & this.blockLimit);
return this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].readBackTrack(addr & this.nBlockLimit);
}
return 0;
};
@ -999,8 +999,8 @@ Bus.prototype.writeBackTrack = function(addr, bti)
{
if (BACKTRACK) {
var slot = bti >>> Bus.BACKTRACK.SLOT_SHIFT;
var iBlock = (addr & this.busMask) >>> this.blockShift;
var btiPrev = this.aMemBlocks[iBlock].writeBackTrack(addr & this.blockLimit, bti);
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
var btiPrev = this.aMemBlocks[iBlock].writeBackTrack(addr & this.nBlockLimit, bti);
var slotPrev = btiPrev >>> Bus.BACKTRACK.SLOT_SHIFT;
if (slot != slotPrev) {
this.aMemBlocks[iBlock].modBackTrack(true);
@ -1101,7 +1101,7 @@ Bus.prototype.updateBackTrackCode = function(addr, bti)
} else {
return;
}
this.aMemBlocks[(addr & this.busMask) >>> this.blockShift].writeBackTrack(addr & this.blockLimit, bti);
this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].writeBackTrack(addr & this.nBlockLimit, bti);
}
};
@ -1204,7 +1204,7 @@ Bus.prototype.saveMemory = function()
{
var i = 0;
var a = [];
for (var iBlock = 0; iBlock < this.blockTotal; iBlock++) {
for (var iBlock = 0; iBlock < this.nBlockTotal; iBlock++) {
var block = this.aMemBlocks[iBlock];
/*
* We have to check both fDirty and fDirtyEver, because we may have called cleanMemory() on some of
@ -1243,8 +1243,8 @@ Bus.prototype.restoreMemory = function(a)
for (i = 0; i < a.length - 1; i += 2) {
var iBlock = a[i];
var adw = a[i+1];
if (adw && adw.length < this.blockLen) {
adw = State.decompress(adw, this.blockLen);
if (adw && adw.length < this.nBlockLen) {
adw = State.decompress(adw, this.nBlockLen);
}
var block = this.aMemBlocks[iBlock];
if (!block || !block.restore(adw)) {
@ -1271,8 +1271,8 @@ Bus.prototype.restoreMemory = function(a)
Bus.prototype.addMemBreak = function(addr, fWrite)
{
if (DEBUGGER) {
var iBlock = addr >>> this.blockShift;
this.aMemBlocks[iBlock].addBreakpoint(addr & this.blockLimit, fWrite);
var iBlock = addr >>> this.nBlockShift;
this.aMemBlocks[iBlock].addBreakpoint(addr & this.nBlockLimit, fWrite);
}
};
@ -1286,8 +1286,8 @@ Bus.prototype.addMemBreak = function(addr, fWrite)
Bus.prototype.removeMemBreak = function(addr, fWrite)
{
if (DEBUGGER) {
var iBlock = addr >>> this.blockShift;
this.aMemBlocks[iBlock].removeBreakpoint(addr & this.blockLimit, fWrite);
var iBlock = addr >>> this.nBlockShift;
this.aMemBlocks[iBlock].removeBreakpoint(addr & this.nBlockLimit, fWrite);
}
};

View file

@ -903,8 +903,8 @@ if (DEBUGGER) {
0x03: [Debugger.INS.LSL, Debugger.TYPE_REG | Debugger.TYPE_WORD | Debugger.TYPE_OUT | Debugger.TYPE_80286, Debugger.TYPE_MEM | Debugger.TYPE_WORD | Debugger.TYPE_IN],
0x05: [Debugger.INS.LOADALL,Debugger.TYPE_80286],
0x06: [Debugger.INS.CLTS, Debugger.TYPE_80286],
0x20: [Debugger.INS.MOV, Debugger.TYPE_MODRM | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_CTLREG | Debugger.TYPE_DWORD | Debugger.TYPE_IN],
0x22: [Debugger.INS.MOV, Debugger.TYPE_CTLREG | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_MODRM | Debugger.TYPE_DWORD | Debugger.TYPE_IN],
0x20: [Debugger.INS.MOV, Debugger.TYPE_REG | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_CTLREG | Debugger.TYPE_DWORD | Debugger.TYPE_IN],
0x22: [Debugger.INS.MOV, Debugger.TYPE_CTLREG | Debugger.TYPE_DWORD | Debugger.TYPE_OUT | Debugger.TYPE_80386, Debugger.TYPE_REG | Debugger.TYPE_DWORD | Debugger.TYPE_IN],
0x80: [Debugger.INS.JO, Debugger.TYPE_IMMREL | Debugger.TYPE_VWORD | Debugger.TYPE_IN | Debugger.TYPE_80386],
0x81: [Debugger.INS.JNO, Debugger.TYPE_IMMREL | Debugger.TYPE_VWORD | Debugger.TYPE_IN | Debugger.TYPE_80386],
0x82: [Debugger.INS.JC, Debugger.TYPE_IMMREL | Debugger.TYPE_VWORD | Debugger.TYPE_IN | Debugger.TYPE_80386],
@ -1282,7 +1282,7 @@ if (DEBUGGER) {
if (MAXDEBUG) this.chipset = cmp.getComponentByType("ChipSet");
this.cchAddr = bus.getWidth() >> 2;
this.maskAddr = bus.busLimit;
this.maskAddr = bus.nBusLimit;
this.aaOpDescs = Debugger.aaOpDescs;
if (this.cpu.model >= X86.MODEL_80186) {
@ -1790,7 +1790,7 @@ if (DEBUGGER) {
for (var i = 0; i < this.cpu.aMemBlocks.length; i++) {
var block = this.cpu.aBusBlocks[i];
if (block.type === Memory.TYPE.NONE) continue;
this.println(str.toHex(block.id) + " %" + str.toHex(i << this.cpu.blockShift) + ": " + str.toHex(block.addr) + " " + str.toHexWord(block.used) + " " + str.toHexWord(block.size) + " " + Memory.TYPE.NAMES[block.type]);
this.println(str.toHex(block.id) + " %" + str.toHex(i << this.cpu.nBlockShift) + ": " + str.toHex(block.addr) + " " + str.toHexWord(block.used) + " " + str.toHexWord(block.size) + " " + Memory.TYPE.NAMES[block.type]);
}
};
@ -3620,7 +3620,7 @@ if (DEBUGGER) {
* done later, by getAddr(), which returns X86.ADDR_INVALID for invalid segments, out-of-range offsets,
* etc. The Debugger's low-level get/set memory functions verify all getAddr() results, but even if an
* invalid address is passed through to the Bus memory interfaces, the address will simply be masked with
* Bus.busLimit; in the case of X86.ADDR_INVALID, that will generally refer to the top of the physical
* Bus.nBusLimit; in the case of X86.ADDR_INVALID, that will generally refer to the top of the physical
* address space.
*
* @this {Debugger}
@ -3794,7 +3794,7 @@ if (DEBUGGER) {
* should be relocated to the top 64Kb of the first 1Mb, so that we're immune from any changes
* to the A20 line.
*/
if ((dbgAddr.addr & ~0xffff) == (this.bus.busLimit & ~0xffff)) {
if ((dbgAddr.addr & ~0xffff) == (this.bus.nBusLimit & ~0xffff)) {
dbgAddr.addr &= 0x000fffff;
}
symbol['p'] = dbgAddr.addr;
@ -5209,7 +5209,7 @@ if (DEBUGGER) {
if (dbgAddr.off == null) return;
if (n === undefined) n = 1;
var dbgAddrEnd = this.newAddr(this.maskReg, dbgAddr.sel, this.bus.busLimit);
var dbgAddrEnd = this.newAddr(this.maskReg, dbgAddr.sel, this.bus.nBusLimit);
var cb = 0x100;
if (sAddrEnd !== undefined) {

View file

@ -59,8 +59,8 @@ var littleEndian = (TYPEDARRAYS? (function() {
* Memory(addr, used, size, type, controller)
*
* The Bus component allocates Memory objects so that each has a memory buffer with a
* block-granular starting address and an address range equal to bus.blockSize; however,
* the size of any given Memory object's underlying buffer can be either zero or bus.blockSize;
* block-granular starting address and an address range equal to bus.nBlockSize; however,
* the size of any given Memory object's underlying buffer can be either zero or bus.nBlockSize;
* memory read/write functions for empty (buffer-less) blocks are mapped to readNone/writeNone.
*
* The Bus allocates empty blocks for the entire address space during initialization, so that
@ -239,6 +239,19 @@ Memory.TYPE = {
*/
Memory.idBlock = 0;
/**
* adjustEndian(dw)
*
* @param {number} dw
* @return {number}
*/
Memory.adjustEndian = function(dw) {
if (TYPEDARRAYS && !littleEndian) {
dw = (dw << 24) | ((dw << 8) & 0x00ff0000) | ((dw >> 8) & 0x0000ff00) | (dw >>> 24);
}
return dw;
};
Memory.prototype = {
constructor: Memory,
parent: null,
@ -467,19 +480,6 @@ Memory.prototype = {
this.dbg.redoBreakpoints(addr, size);
}
},
/**
* adjustEndian(dw)
*
* @this {Memory}
* @param {number} dw
* @return {number}
*/
adjustEndian: function(dw) {
if (TYPEDARRAYS && !littleEndian) {
dw = (dw << 24) | ((dw << 8) & 0x00ff0000) | ((dw >> 8) & 0x0000ff00) | (dw >>> 24);
}
return dw;
},
/**
* getPageBlock(addr, fWrite)
*
@ -513,8 +513,8 @@ Memory.prototype = {
this.iPDE = offPDE >> 2; // convert offPDE into iPDE (an adw index)
this.blockPTE = blockPTE;
this.iPTE = offPTE >> 2; // convert offPTE into iPTE (an adw index)
this.bitPTEDirty = this.adjustEndian(X86.PTE.ACCESSED | X86.PTE.DIRTY);
this.bitPTEAccessed = this.adjustEndian(X86.PTE.ACCESSED);
this.bitPTEDirty = Memory.adjustEndian(X86.PTE.ACCESSED | X86.PTE.DIRTY);
this.bitPTEAccessed = Memory.adjustEndian(X86.PTE.ACCESSED);
},
/**
* addBreakpoint(off, fWrite)

View file

@ -487,8 +487,8 @@ Panel.prototype.findAddress = function(x, y)
y -= rect.y;
var region = this.busInfo.aRegions[i];
var iBlock = usr.getBitField(Bus.BlockInfo.num, this.busInfo.aBlocks[region.iBlock]);
var addr = iBlock * this.bus.blockSize;
var addrLimit = (iBlock + region.cBlocks) * this.bus.blockSize - 1;
var addr = iBlock * this.bus.nBlockSize;
var addrLimit = (iBlock + region.cBlocks) * this.bus.nBlockSize - 1;
/*
* If you want memory to be arranged "vertically" instead of "horizontally", do this:
@ -528,7 +528,7 @@ Panel.prototype.updateAnimation = function()
/*
* Calculate the pixel-to-memory-address ratio
*/
this.ratioMemoryToPixels = (this.busInfo.cBlocks * this.bus.blockSize) / (Panel.LIVEMEM.CX * Panel.LIVEMEM.CY);
this.ratioMemoryToPixels = (this.busInfo.cBlocks * this.bus.nBlockSize) / (Panel.LIVEMEM.CX * Panel.LIVEMEM.CY);
/*
* Update the BusInfo object with region information (cRegions and aRegions); return true if region
* information has changed since the last call.
@ -568,7 +568,7 @@ Panel.prototype.updateAnimation = function()
rect = this.busInfo.aRects[i];
rect.drawWith(this.contextLiveMem, Memory.TYPE.COLORS[region.type]);
this.centerPen(rect);
this.centerText(Memory.TYPE.NAMES[region.type] + " (" + (((region.cBlocks * this.bus.blockSize) / 1024) | 0) + "Kb)");
this.centerText(Memory.TYPE.NAMES[region.type] + " (" + (((region.cBlocks * this.bus.nBlockSize) / 1024) | 0) + "Kb)");
}
}
if (DEBUG) this.log("end scanMemory(): total bytes: " + this.busInfo.cbTotal + ", total blocks: " + this.busInfo.cBlocks + ", total regions: " + this.busInfo.cRegions);
@ -628,7 +628,7 @@ Panel.prototype.findRegions = function()
}
typeRegion = typeBlock;
iBlockRegion = iBlock;
addrRegion = nBlockCurr << this.bus.blockShift;
addrRegion = nBlockCurr << this.bus.nBlockShift;
}
nBlockPrev = nBlockCurr;
}

View file

@ -114,6 +114,7 @@ var X86 = {
BASE1623: 0x00ff,
MASK: 0xff00,
TYPE: {
OFFSET: 0x5,
MASK: 0x1f00,
SEG: 0x1000,
NONSEG: 0x0f00,

View file

@ -166,8 +166,9 @@ function X86CPU(parmsCPU)
* when the Bus is initialized.
*/
this.aBusBlocks = this.aMemBlocks = [];
this.busMask = this.memMask = 0;
this.blockShift = this.blockSize = this.blockLimit = this.blockTotal = this.blockMask = 0;
this.nBusMask = this.nMemMask = 0;
this.nBlockShift = this.nBlockSize = this.nBlockLimit = this.nBlockTotal = this.nBlockMask = 0;
this.blockDummy = null;
if (SAMPLER) {
/*
@ -576,7 +577,7 @@ X86CPU.PREFETCH = {
};
/**
* initMemory(aMemBlocks, blockShift)
* initMemory(aMemBlocks, nBlockShift)
*
* Notification from Bus.initMemory(), giving us direct access to the entire memory space
* (aMemBlocks).
@ -619,9 +620,9 @@ X86CPU.PREFETCH = {
*
* @this {X86CPU}
* @param {Array} aMemBlocks
* @param {number} blockShift
* @param {number} nBlockShift
*/
X86CPU.prototype.initMemory = function(aMemBlocks, blockShift)
X86CPU.prototype.initMemory = function(aMemBlocks, nBlockShift)
{
/*
* aBusBlocks preserves the Bus block array for the life of the machine, whereas aMemBlocks
@ -630,11 +631,11 @@ X86CPU.prototype.initMemory = function(aMemBlocks, blockShift)
*/
this.aBusBlocks = aMemBlocks;
this.aMemBlocks = aMemBlocks;
this.blockShift = blockShift;
this.blockSize = 1 << this.blockShift;
this.blockLimit = this.blockSize - 1;
this.blockTotal = aMemBlocks.length;
this.blockMask = this.blockTotal - 1;
this.nBlockShift = nBlockShift;
this.nBlockSize = 1 << this.nBlockShift;
this.nBlockLimit = this.nBlockSize - 1;
this.nBlockTotal = aMemBlocks.length;
this.nBlockMask = this.nBlockTotal - 1;
if (PREFETCH) {
this.nBusCycles = 0;
this.aPrefetch = new Array(X86CPU.PREFETCH.ARRAY);
@ -646,17 +647,17 @@ X86CPU.prototype.initMemory = function(aMemBlocks, blockShift)
};
/**
* setAddressMask(busMask)
* setAddressMask(nBusMask)
*
* Notification from Bus.initMemory() and Bus.setA20(); the latter calls us whenever the physical
* A20 line changes (note that on a 20-bit bus machine, address lines A20 and higher are always zero).
*
* For 32-bit bus machines (eg, 80386), busMask is never changed after the initial call, because A20
* wrap-around is simulated by changing the physical memory map rather than altering the A20 bit in busMask.
* For 32-bit bus machines (eg, 80386), nBusMask is never changed after the initial call, because A20
* wrap-around is simulated by changing the physical memory map rather than altering the A20 bit in nBusMask.
*
* We maintain memMask separate from busMask, because when paging is enabled on the 80386, the CPU memory
* We maintain memMask separate from nBusMask, because when paging is enabled on the 80386, the CPU memory
* functions are now dealing with linear addresses rather than physical addresses, so it would be incorrect
* to apply busMask to those addresses; memMask must remain 0xffffffff (-1) for the duration. If we change
* to apply nBusMask to those addresses; memMask must remain 0xffffffff (-1) for the duration. If we change
* how A20 is simulated on the 80386, then enablePageBlocks() and disablePageBlocks() will need to override
* memMask appropriately.
*
@ -664,11 +665,11 @@ X86CPU.prototype.initMemory = function(aMemBlocks, blockShift)
* sets of memory access functions for different machines.
*
* @this {X86CPU}
* @param {number} busMask
* @param {number} nBusMask
*/
X86CPU.prototype.setAddressMask = function(busMask)
X86CPU.prototype.setAddressMask = function(nBusMask)
{
this.busMask = this.memMask = busMask;
this.nBusMask = this.nMemMask = nBusMask;
};
/**
@ -695,9 +696,9 @@ X86CPU.prototype.enablePageBlocks = function()
return;
}
if (this.aMemBlocks === this.aBusBlocks) {
this.aMemBlocks = new Array(this.blockTotal);
this.aMemBlocks = new Array(this.nBlockTotal);
this.blockUnpaged = new Memory(null, 0, 0, Memory.TYPE.UNPAGED, null, this);
for (var iBlock = 0; iBlock < this.blockTotal; iBlock++) {
for (var iBlock = 0; iBlock < this.nBlockTotal; iBlock++) {
this.aMemBlocks[iBlock] = this.blockUnpaged;
}
} else {
@ -716,11 +717,11 @@ X86CPU.prototype.enablePageBlocks = function()
* the current page will go directly to that block, instead of coming here through the UNPAGED block
* handlers.
*
* Note that since the incoming address (addr) is a linear address, we never need to mask it with busMask,
* Note that since the incoming address (addr) is a linear address, we never need to mask it with nBusMask,
* but all the intermediate (PDE, PTE) and final physical addresses we calculate should still be masked.
*
* Granted, busMask on a 32-bit bus is generally going to be 0xffffffff (-1), so making might seem like
* a waste of time; however, if we decide to once again rely on busMask for emulating A20 wrap-around
* Granted, nBusMask on a 32-bit bus is generally going to be 0xffffffff (-1), so making might seem like
* a waste of time; however, if we decide to once again rely on nBusMask for emulating A20 wrap-around
* (instead of changing the physical memory map to alias the 2nd Mb to the 1st Mb), then performing
* consistent masking will be important.
*
@ -747,9 +748,9 @@ X86CPU.prototype.mapPageBlock = function(addr, fWrite, fSuppress)
/*
* bus.getLong(addrPDE) would be simpler, but setPhysBlock() needs to know blockPDE and offPDE, too.
* TODO: Since we're immediately shifting addrPDE by blockShift, then we could also skip adding offPDE.
* TODO: Since we're immediately shifting addrPDE by nBlockShift, then we could also skip adding offPDE.
*/
var blockPDE = this.aBusBlocks[(addrPDE & this.busMask) >>> this.blockShift];
var blockPDE = this.aBusBlocks[(addrPDE & this.nBusMask) >>> this.nBlockShift];
var pde = blockPDE.readLong(offPDE);
if (!(pde & X86.PTE.PRESENT)) {
@ -767,9 +768,9 @@ X86CPU.prototype.mapPageBlock = function(addr, fWrite, fSuppress)
/*
* bus.getLong(addrPTE) would be simpler, but setPhysBlock() needs to know blockPTE and offPTE, too.
* TODO: Since we're immediately shifting addrPDE by blockShift, then we could also skip adding offPTE.
* TODO: Since we're immediately shifting addrPDE by nBlockShift, then we could also skip adding offPTE.
*/
var blockPTE = this.aBusBlocks[(addrPTE & this.busMask) >>> this.blockShift];
var blockPTE = this.aBusBlocks[(addrPTE & this.nBusMask) >>> this.nBlockShift];
var pte = blockPTE.readLong(offPTE);
if (!(pte & X86.PTE.PRESENT) && !fSuppress) {
@ -784,9 +785,9 @@ X86CPU.prototype.mapPageBlock = function(addr, fWrite, fSuppress)
var addrPhys = (pte & X86.PTE.FRAME) + (addr & X86.LADDR.OFFSET);
/*
* TODO: Since we're immediately shifting addrPhys by blockShift, we could also skip adding the addr's offset.
* TODO: Since we're immediately shifting addrPhys by nBlockShift, we could also skip adding the addr's offset.
*/
var blockPhys = this.aBusBlocks[(addrPhys & this.busMask) >>> this.blockShift];
var blockPhys = this.aBusBlocks[(addrPhys & this.nBusMask) >>> this.nBlockShift];
if (fSuppress) return blockPhys;
/*
@ -798,7 +799,7 @@ X86CPU.prototype.mapPageBlock = function(addr, fWrite, fSuppress)
var blockPage = new Memory(addrPage, 0, 0, Memory.TYPE.PAGED);
blockPage.setPhysBlock(blockPhys, blockPDE, offPDE, blockPTE, offPTE);
var iBlock = addr >>> this.blockShift;
var iBlock = addr >>> this.nBlockShift;
this.aMemBlocks[iBlock] = blockPage;
this.aBlocksPaged.push(iBlock);
return blockPage;
@ -2718,12 +2719,12 @@ X86CPU.prototype.setBinding = function(sHTMLType, sBinding, control)
*/
X86CPU.prototype.probeAddr = function(addr)
{
var block = this.aMemBlocks[(addr & this.memMask) >>> this.blockShift];
var block = this.aMemBlocks[(addr & this.nMemMask) >>> this.nBlockShift];
if (block.type == Memory.TYPE.UNPAGED) {
block = this.mapPageBlock(addr, false, true);
if (!block) return null;
}
return block.readByteDirect(addr & this.blockLimit, addr);
return block.readByteDirect(addr & this.nBlockLimit, addr);
};
/**
@ -2739,7 +2740,7 @@ X86CPU.prototype.probeAddr = function(addr)
X86CPU.prototype.getByte = function getByte(addr)
{
if (BACKTRACK) this.backTrack.btiMemLo = this.bus.readBackTrack(addr);
return this.aMemBlocks[(addr & this.memMask) >>> this.blockShift].readByte(addr & this.blockLimit, addr);
return this.aMemBlocks[(addr & this.nMemMask) >>> this.nBlockShift].readByte(addr & this.nBlockLimit, addr);
};
/**
@ -2754,8 +2755,8 @@ X86CPU.prototype.getByte = function getByte(addr)
*/
X86CPU.prototype.getShort = function getShort(addr)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.memMask) >>> this.blockShift;
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
/*
* On the 8088, it takes 4 cycles to read the additional byte REGARDLESS whether the address is odd or even.
* TODO: For the 8086, the penalty is actually "(addr & 0x1) << 2" (4 additional cycles only when the address is odd).
@ -2766,10 +2767,10 @@ X86CPU.prototype.getShort = function getShort(addr)
this.backTrack.btiMemLo = this.bus.readBackTrack(addr);
this.backTrack.btiMemHi = this.bus.readBackTrack(addr + 1);
}
if (off < this.blockLimit) {
if (off < this.nBlockLimit) {
return this.aMemBlocks[iBlock].readShort(off, addr);
}
return this.aMemBlocks[iBlock].readByte(off, addr) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readByte(0, addr + 1) << 8);
return this.aMemBlocks[iBlock].readByte(off, addr) | (this.aMemBlocks[(iBlock + 1) & this.nBlockMask].readByte(0, addr + 1) << 8);
};
/**
@ -2784,17 +2785,17 @@ X86CPU.prototype.getShort = function getShort(addr)
*/
X86CPU.prototype.getLong = function getLong(addr)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.memMask) >>> this.blockShift;
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
if (BACKTRACK) {
this.backTrack.btiMemLo = this.bus.readBackTrack(addr);
this.backTrack.btiMemHi = this.bus.readBackTrack(addr + 1);
}
if (off < this.blockLimit - 2) {
if (off < this.nBlockLimit - 2) {
return this.aMemBlocks[iBlock].readLong(off, addr);
}
var nShift = (off & 0x3) << 3;
return (this.aMemBlocks[iBlock].readLong(off & ~0x3, addr) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.blockMask].readLong(0, addr + 3) << (32 - nShift));
return (this.aMemBlocks[iBlock].readLong(off & ~0x3, addr) >>> nShift) | (this.aMemBlocks[(iBlock + 1) & this.nBlockMask].readLong(0, addr + 3) << (32 - nShift));
};
/**
@ -2810,7 +2811,7 @@ X86CPU.prototype.getLong = function getLong(addr)
X86CPU.prototype.setByte = function setByte(addr, b)
{
if (BACKTRACK) this.bus.writeBackTrack(addr, this.backTrack.btiMemLo);
this.aMemBlocks[(addr & this.memMask) >>> this.blockShift].writeByte(addr & this.blockLimit, b & 0xff, addr);
this.aMemBlocks[(addr & this.nMemMask) >>> this.nBlockShift].writeByte(addr & this.nBlockLimit, b & 0xff, addr);
};
/**
@ -2825,8 +2826,8 @@ X86CPU.prototype.setByte = function setByte(addr, b)
*/
X86CPU.prototype.setShort = function setShort(addr, w)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.memMask) >>> this.blockShift;
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
/*
* On the 8088, it takes 4 cycles to write the additional byte REGARDLESS whether the address is odd or even.
* TODO: For the 8086, the penalty is actually "(addr & 0x1) << 2" (4 additional cycles only when the address is odd).
@ -2837,12 +2838,12 @@ X86CPU.prototype.setShort = function setShort(addr, w)
this.bus.writeBackTrack(addr, this.backTrack.btiMemLo);
this.bus.writeBackTrack(addr + 1, this.backTrack.btiMemHi);
}
if (off < this.blockLimit) {
if (off < this.nBlockLimit) {
this.aMemBlocks[iBlock].writeShort(off, w & 0xffff, addr);
return;
}
this.aMemBlocks[iBlock++].writeByte(off, w & 0xff, addr);
this.aMemBlocks[iBlock & this.blockMask].writeByte(0, (w >> 8) & 0xff, addr + 1);
this.aMemBlocks[iBlock & this.nBlockMask].writeByte(0, (w >> 8) & 0xff, addr + 1);
};
/**
@ -2857,15 +2858,15 @@ X86CPU.prototype.setShort = function setShort(addr, w)
*/
X86CPU.prototype.setLong = function setLong(addr, l)
{
var off = addr & this.blockLimit;
var iBlock = (addr & this.memMask) >>> this.blockShift;
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
this.nStepCycles -= this.cycleCounts.nWordCyclePenalty;
if (BACKTRACK) {
this.bus.writeBackTrack(addr, this.backTrack.btiMemLo);
this.bus.writeBackTrack(addr + 1, this.backTrack.btiMemHi);
}
if (off < this.blockLimit - 2) {
if (off < this.nBlockLimit - 2) {
this.aMemBlocks[iBlock].writeLong(off, l, addr);
return;
}
@ -2873,7 +2874,7 @@ X86CPU.prototype.setLong = function setLong(addr, l)
off &= ~0x3;
lPrev = this.aMemBlocks[iBlock].readLong(off, addr);
this.aMemBlocks[iBlock].writeLong(off, (lPrev & ~(-1 << nShift)) | (l << nShift), addr);
iBlock = (iBlock + 1) & this.blockMask;
iBlock = (iBlock + 1) & this.nBlockMask;
addr += 3;
lPrev = this.aMemBlocks[iBlock].readLong(0, addr);
this.aMemBlocks[iBlock].writeLong(0, (lPrev & (-1 << nShift)) | (l >>> (32 - nShift)), addr);
@ -3180,10 +3181,10 @@ X86CPU.prototype.getBytePrefetch = function(addr)
* with side-effects we may not want, and in any case, while it seemed to improve Safari's performance slightly,
* it did nothing for the oddball Chrome performance I'm seeing with PREFETCH enabled.
*
* b = this.aMemBlocks[(addr & this.memMask) >>> this.blockShift].readByte(addr & this.blockLimit, addr);
* b = this.aMemBlocks[(addr & this.nMemMask) >>> this.nBlockShift].readByte(addr & this.nBlockLimit, addr);
* this.nBusCycles += 4;
* this.cbPrefetchValid = 0;
* this.addrPrefetchHead = (addr + 1) & this.memMask;
* this.addrPrefetchHead = (addr + 1) & this.nMemMask;
* return b;
*/
}
@ -3257,10 +3258,10 @@ X86CPU.prototype.fillPrefetch = function(n)
{
while (n-- > 0 && this.cbPrefetchQueued < X86CPU.PREFETCH.QUEUE) {
var addr = this.addrPrefetchHead;
var b = this.aMemBlocks[(addr & this.memMask) >>> this.blockShift].readByte(addr & this.blockLimit, addr);
var b = this.aMemBlocks[(addr & this.nMemMask) >>> this.nBlockShift].readByte(addr & this.nBlockLimit, 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.memMask;
this.addrPrefetchHead = (addr + 1) & this.nMemMask;
this.iPrefetchHead = (this.iPrefetchHead + 1) & X86CPU.PREFETCH.MASK;
this.cbPrefetchQueued++;
/*

View file

@ -35,6 +35,7 @@
if (typeof module !== 'undefined') {
var str = require("../../shared/lib/strlib");
var Messages = require("./messages");
var Memory = require("./memory");
var X86 = require("./x86");
}
@ -308,6 +309,7 @@ X86Seg.prototype.checkReadProt = function checkReadProt(off, cb, fSuppress)
* it to an unsigned value using ">>>"; offMax was already converted at segment load time.
*/
if ((off >>> 0) + cb <= this.offMax) {
this.blockACC.adw[this.iACC] |= this.bitACC;
return (this.base + off)|0;
}
return this.checkReadProtDisallowed(off, cb, fSuppress);
@ -329,6 +331,7 @@ X86Seg.prototype.checkReadProtDown = function checkReadProtDown(off, cb, fSuppre
* it to an unsigned value using ">>>"; offMax was already converted at segment load time.
*/
if ((off >>> 0) + cb > this.offMax) {
this.blockACC.adw[this.iACC] |= this.bitACC;
return (this.base + off)|0;
}
return this.checkReadProtDisallowed(off, cb, fSuppress);
@ -367,6 +370,7 @@ X86Seg.prototype.checkWriteProt = function checkWriteProt(off, cb, fSuppress)
* it to an unsigned value using ">>>"; offMax was already converted at segment load time.
*/
if ((off >>> 0) + cb <= this.offMax) {
this.blockACC.adw[this.iACC] |= this.bitACC;
return (this.base + off)|0;
}
return this.checkWriteProtDisallowed(off, cb, fSuppress);
@ -388,6 +392,7 @@ X86Seg.prototype.checkWriteProtDown = function checkWriteProtDown(off, cb, fSupp
* it to an unsigned value using ">>>"; offMax was already converted at segment load time.
*/
if ((off >>> 0) + cb > this.offMax) {
this.blockACC.adw[this.iACC] |= this.bitACC;
return (this.base + off)|0;
}
return this.checkWriteProtDisallowed(off, cb, fSuppress);
@ -946,6 +951,46 @@ X86Seg.prototype.updateMode = function(fLoad, fProt)
this.fExpDown = true;
}
}
/*
* Here begins the four-step process of computing the block, index and bit mask required
* to update the descriptor's ACCESSED bit whenever the segment is accessed.
*
* Step 1: Compute address of the descriptor byte containing the ACCESSED bit (offset 0x5);
* note that it's perfectly normal for addrDesc to occasionally be invalid (eg, when the CPU
* is creating protected-mode-only segment registers like LDT and TSS, or when the CPU has
* transitioned from real-mode to protected-mode and new selector(s) have not been loaded yet).
*/
this.iACC = this.bitACC = 0;
if (this.addrDesc != X86.ADDR_INVALID) {
var addrAcc = this.addrDesc + X86.DESC.ACC.TYPE.OFFSET;
/*
* Step 2: Compute the logical block number containing that byte, and record the block.
*/
this.blockACC = this.cpu.aMemBlocks[(addrAcc & this.cpu.nMemMask) >>> this.cpu.nBlockShift];
this.cpu.assert(this.blockACC && this.blockACC.adw);
/*
* It's critical that we check fReadOnly, because ROMs often use GDTs that are also located
* in ROM, in which case the ACCESSED bit cannot be set (ie, we must ensure that blockACC is
* set to a dummy block).
*/
if (this.blockACC && !this.blockACC.fReadOnly && this.blockACC.adw) {
/*
* Step 3: Compute the index of the DWORD (adw entry) containing that byte.
*/
this.iACC = (addrAcc & this.cpu.nBlockLimit) >> 2;
/*
* Step 4: Compute the bit that must be OR'ed into that DWORD in order to set the ACCESSED bit;
* we right-shift the bit into byte 0, and then left-shift it into byte 0, 1, 2 or 3 as appropriate.
*/
this.bitACC = Memory.adjustEndian((X86.DESC.ACC.TYPE.ACCESSED >> 8) << ((addrAcc & 0x3) << 3));
}
}
if (!this.bitACC) {
if (!this.cpu.blockDummy) this.cpu.blockDummy = new Memory(0, 0, 4);
this.blockACC = this.cpu.blockDummy;
}
if (fLoad) {
/*
* Any update to the following properties must occur only on segment loads, not simply when