Improved IOPAGE management
This commit is contained in:
parent
0ee3a091b4
commit
ae4fbeb489
7 changed files with 469 additions and 422 deletions
|
|
@ -42,7 +42,7 @@ if (NODE) {
|
|||
}
|
||||
|
||||
/**
|
||||
* BusPDP11(cpu, dbg)
|
||||
* BusPDP11(parmsBus, cpu, dbg)
|
||||
*
|
||||
* The BusPDP11 component manages physical memory and I/O address spaces.
|
||||
*
|
||||
|
|
@ -69,8 +69,18 @@ function BusPDP11(parmsBus, cpu, dbg)
|
|||
this.cpu = cpu;
|
||||
this.dbg = dbg;
|
||||
|
||||
/*
|
||||
* Supported values for nBusWidth are 16 (default), 18, and 22. This represents the maximum size
|
||||
* of the bus for the life of the machine, regardless what memory management mode the CPU has enabled.
|
||||
*/
|
||||
this.nBusWidth = parmsBus['busWidth'] || 16;
|
||||
|
||||
/*
|
||||
* This controls the location of the IOPAGE (ie, at the top of 16-bit, 18-bit, or 22-bit address range).
|
||||
* It is managed by setIOPageRange(). initMemory() establishes the default (16).
|
||||
*/
|
||||
this.nIOPageRange = 0; // zero means no IOPAGE access (yet)
|
||||
|
||||
/*
|
||||
* Compute all BusPDP11 memory block parameters, based on the width of the bus. The entire
|
||||
* address space is divided into blocks, using a block size that is (hopefully) appropriate to
|
||||
|
|
@ -130,10 +140,26 @@ function BusPDP11(parmsBus, cpu, dbg)
|
|||
*/
|
||||
this.aIOHandlers = [];
|
||||
this.fIOBreakAll = false;
|
||||
|
||||
/*
|
||||
* Array of RESET notification handlers registered by Device components.
|
||||
*/
|
||||
this.afnReset = [];
|
||||
|
||||
/*
|
||||
* Allocate empty Memory blocks to span the entire physical address space.
|
||||
* Before we can add any memory blocks that declare our component as a custom memory controller,
|
||||
* we must initialize the array that the getControllerAccess() method supplies to the Memory component.
|
||||
*/
|
||||
this.afnIOPage = [
|
||||
BusPDP11.IOController.readByte,
|
||||
BusPDP11.IOController.writeByte,
|
||||
BusPDP11.IOController.readWord,
|
||||
BusPDP11.IOController.writeWord
|
||||
];
|
||||
|
||||
/*
|
||||
* We're ready to allocate empty Memory blocks to span the entire physical address space, including the
|
||||
* initial location of the IOPAGE.
|
||||
*/
|
||||
this.initMemory();
|
||||
|
||||
|
|
@ -142,7 +168,7 @@ function BusPDP11(parmsBus, cpu, dbg)
|
|||
|
||||
Component.subclass(BusPDP11);
|
||||
|
||||
BusPDP11.IOPAGE_VIRT = 0xE000; /*000160000*/
|
||||
BusPDP11.IOPAGE_16BIT = 0xE000; /*000160000*/ // eg, PDP-11/20
|
||||
BusPDP11.IOPAGE_18BIT = 0x3E000; /*000760000*/ // eg, PDP-11/45
|
||||
BusPDP11.IOPAGE_UNIBUS = 0x3C0000; /*017000000*/
|
||||
BusPDP11.IOPAGE_22BIT = 0x3FE000; /*017760000*/ // eg, PDP-11/70
|
||||
|
|
@ -365,18 +391,31 @@ BusPDP11.prototype.initMemory = function()
|
|||
for (var iBlock = 0; iBlock < this.nBlockTotal; iBlock++) {
|
||||
this.aMemBlocks[iBlock] = block;
|
||||
}
|
||||
this.afnIOPage = new Array(4);
|
||||
this.afnIOPage[0] = BusPDP11.IOController.readByte;
|
||||
this.afnIOPage[1] = BusPDP11.IOController.writeByte;
|
||||
this.afnIOPage[2] = BusPDP11.IOController.readWord;
|
||||
this.afnIOPage[3] = BusPDP11.IOController.writeWord;
|
||||
/*
|
||||
* Map IOPAGE at the top of the address space (as determined by nBusWidth), as well as at IOPAGE_VIRT
|
||||
* (which is the only place that 16-bit code can reach the IOPAGE when memory management is not enabled).
|
||||
*/
|
||||
var addr = this.addrTotal - BusPDP11.IOPAGE_LENGTH;
|
||||
this.addMemory(addr, BusPDP11.IOPAGE_LENGTH, MemoryPDP11.TYPE.CONTROLLER, this);
|
||||
this.addMemory(BusPDP11.IOPAGE_VIRT, BusPDP11.IOPAGE_LENGTH, MemoryPDP11.TYPE.CONTROLLER, this);
|
||||
this.setIOPageRange(16);
|
||||
};
|
||||
|
||||
/**
|
||||
* setIOPageRange(nRange)
|
||||
*
|
||||
* We can define the IOPAGE address range with a single number, because the size of the IOPAGE is fixed at 8Kb.
|
||||
* The bottom of the range is (2 ^ nRange) - IOPAGE_LENGTH, and the top is (2 ^ nRange) - 1.
|
||||
*
|
||||
* @this {BusPDP11}
|
||||
* @param {number} nRange (16, 18 or 22)
|
||||
*/
|
||||
BusPDP11.prototype.setIOPageRange = function(nRange)
|
||||
{
|
||||
if (nRange != this.nIOPageRange) {
|
||||
var addr;
|
||||
if (this.nIOPageRange) {
|
||||
addr = (1 << this.nIOPageRange) - BusPDP11.IOPAGE_LENGTH;
|
||||
if (!this.removeMemory(addr, BusPDP11.IOPAGE_LENGTH)) return;
|
||||
this.nIOPageRange = 0;
|
||||
}
|
||||
addr = (1 << nRange) - BusPDP11.IOPAGE_LENGTH;
|
||||
if (!this.addMemory(addr, BusPDP11.IOPAGE_LENGTH, MemoryPDP11.TYPE.CONTROLLER, this)) return;
|
||||
this.nIOPageRange = nRange;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -390,6 +429,9 @@ BusPDP11.prototype.initMemory = function()
|
|||
*/
|
||||
BusPDP11.prototype.getControllerBuffer = function(addr)
|
||||
{
|
||||
/*
|
||||
* No buffer is required; all accesses go to a registered I/O handler or the bit-bucket.
|
||||
*/
|
||||
return [null, 0];
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -197,11 +197,6 @@ CPUPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
if (control) this.cmp.setBinding(null, CPUPDP11.BUTTONS[i], control);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach the ChipSet component to the CPU so that it can be notified whenever the CPU stops and starts.
|
||||
*/
|
||||
this.chipset = null; // /** @type {ChipSetPDP11} */ (cmp.getMachineComponent("ChipSet"));
|
||||
|
||||
/*
|
||||
* We've already saved the parmsCPU 'autoStart' setting, but there may be a machine (or URL) override.
|
||||
*/
|
||||
|
|
@ -210,12 +205,27 @@ CPUPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
this.flags.autoStart = (sAutoStart == "true"? true : (sAutoStart == "false"? false : !!sAutoStart));
|
||||
}
|
||||
|
||||
this.initBusComplete();
|
||||
|
||||
this.setReady();
|
||||
};
|
||||
|
||||
/**
|
||||
* initBusComplete()
|
||||
*
|
||||
* Stub for Bus finalization (overridden by the CPUStatePDP11 component).
|
||||
*
|
||||
* @this {CPUPDP11}
|
||||
*/
|
||||
CPUPDP11.prototype.initBusComplete = function()
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* reset()
|
||||
*
|
||||
* Stub for reset notification (overridden by the CPUStatePDP11 component).
|
||||
*
|
||||
* @this {CPUPDP11}
|
||||
*/
|
||||
CPUPDP11.prototype.reset = function()
|
||||
|
|
@ -225,7 +235,7 @@ CPUPDP11.prototype.reset = function()
|
|||
/**
|
||||
* save()
|
||||
*
|
||||
* This is a placeholder for save support (overridden by the CPUStatePDP11 component).
|
||||
* Stub for save support (overridden by the CPUStatePDP11 component).
|
||||
*
|
||||
* @this {CPUPDP11}
|
||||
* @return {Object|null}
|
||||
|
|
@ -238,7 +248,7 @@ CPUPDP11.prototype.save = function()
|
|||
/**
|
||||
* restore(data)
|
||||
*
|
||||
* This is a placeholder for restore support (overridden by the CPUStatePDP11 component).
|
||||
* Stub for restore support (overridden by the CPUStatePDP11 component).
|
||||
*
|
||||
* @this {CPUPDP11}
|
||||
* @param {Object} data
|
||||
|
|
@ -552,40 +562,6 @@ CPUPDP11.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
return fBound;
|
||||
};
|
||||
|
||||
/**
|
||||
* setBurstCycles(nCycles)
|
||||
*
|
||||
* This function is used by the ChipSet component whenever a very low timer count is set,
|
||||
* in anticipation of the timer requiring an update sooner than the normal nCyclesPerYield
|
||||
* period in runCPU() would normally provide.
|
||||
*
|
||||
* NOTE: In this context, "timer" refers to a timer chip (eg, an Intel 8253) being emulated by
|
||||
* by the ChipSet component, not the timers managed by the CPU (eg, addTimer(), setTimer(), etc).
|
||||
*
|
||||
* @this {CPUPDP11}
|
||||
* @param {number} nCycles is the target number of cycles to drop the current burst to
|
||||
* @return {boolean}
|
||||
*/
|
||||
CPUPDP11.prototype.setBurstCycles = function(nCycles)
|
||||
{
|
||||
if (this.flags.running) {
|
||||
var nDelta = this.nStepCycles - nCycles;
|
||||
/*
|
||||
* NOTE: If nDelta is negative, we will actually be increasing nStepCycles and nBurstCycles.
|
||||
* Which is OK, but if we're also taking snapshots of the cycle counts, to make sure that instruction
|
||||
* costs are being properly assessed, then we need to update nSnapCycles as well.
|
||||
*
|
||||
* TODO: If the delta is negative, we could simply ignore the request, but we must first carefully
|
||||
* consider the impact on the ChipSet timers, if any.
|
||||
*/
|
||||
// if (DEBUG) this.nSnapCycles -= nDelta;
|
||||
this.nStepCycles -= nDelta;
|
||||
this.nBurstCycles -= nDelta;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* addCycles(nCycles, fEndStep)
|
||||
*
|
||||
|
|
@ -1183,7 +1159,6 @@ CPUPDP11.prototype.startCPU = function(fUpdateFocus)
|
|||
this.setSpeed();
|
||||
this.flags.running = true;
|
||||
this.flags.starting = true;
|
||||
if (this.chipset) this.chipset.start();
|
||||
var controlRun = this.bindings["run"];
|
||||
if (controlRun) controlRun.textContent = "Halt";
|
||||
if (this.cmp) {
|
||||
|
|
@ -1227,7 +1202,6 @@ CPUPDP11.prototype.stopCPU = function(fComplete)
|
|||
this.addCycles(this.nRunCycles);
|
||||
this.nRunCycles = 0;
|
||||
this.flags.running = false;
|
||||
if (this.chipset) this.chipset.stop();
|
||||
var controlRun = this.bindings["run"];
|
||||
if (controlRun) controlRun.textContent = "Run";
|
||||
if (this.cmp) {
|
||||
|
|
|
|||
|
|
@ -98,6 +98,17 @@ Component.subclass(CPUStatePDP11, CPUPDP11);
|
|||
*/
|
||||
var InterruptEvent;
|
||||
|
||||
/**
|
||||
* initBusComplete()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.initBusComplete = function()
|
||||
{
|
||||
this.assert(this.bus);
|
||||
this.setMemoryAccess();
|
||||
};
|
||||
|
||||
/**
|
||||
* initProcessor()
|
||||
*
|
||||
|
|
@ -216,11 +227,12 @@ CPUStatePDP11.prototype.resetRegs = function()
|
|||
/** @type {Array.<InterruptEvent>} */
|
||||
this.interruptQueue = [];
|
||||
this.opFlags |= PDP11.OPFLAG.INTQ;
|
||||
this.initMemoryAccess();
|
||||
|
||||
if (this.bus) this.setMemoryAccess();
|
||||
};
|
||||
|
||||
/**
|
||||
* initMemoryAccess()
|
||||
* setMemoryAccess()
|
||||
*
|
||||
* Define handlers and DSPACE setting appropriate for the current MMU mode, in order to eliminate
|
||||
* unnecessary calls to mapVirtualToPhysical().
|
||||
|
|
@ -231,18 +243,20 @@ CPUStatePDP11.prototype.resetRegs = function()
|
|||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.initMemoryAccess = function()
|
||||
CPUStatePDP11.prototype.setMemoryAccess = function()
|
||||
{
|
||||
if (this.mmuEnable) {
|
||||
this.addrDSpace = PDP11.ACCESS.DSPACE;
|
||||
this.getAddrByMode = this.getVirtualAddrByMode;
|
||||
this.readWordFromAddr = this.readWordFromVirtual;
|
||||
this.writeWordToAddr = this.writeWordToVirtual;
|
||||
this.bus.setIOPageRange((this.regMMR3 & PDP11.MMR3.MMU_22BIT)? 22 : 18);
|
||||
} else {
|
||||
this.addrDSpace = 0;
|
||||
this.getAddrByMode = this.getPhysicalAddrByMode;
|
||||
this.readWordFromAddr = this.readWordFromPhysical;
|
||||
this.writeWordToAddr = this.writeWordToPhysical;
|
||||
this.bus.setIOPageRange(16);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -265,19 +279,23 @@ CPUStatePDP11.prototype.getMMR0 = function()
|
|||
*/
|
||||
CPUStatePDP11.prototype.setMMR0 = function(newMMR0)
|
||||
{
|
||||
this.regMMR0 = newMMR0 &= 0xf381;
|
||||
this.mmuLastMode = (newMMR0 >> 5) & 3;
|
||||
this.mmuLastPage = (newMMR0 >> 1) & 0xf;
|
||||
if (newMMR0 & 0x101) {
|
||||
if (newMMR0 & 0x1) {
|
||||
this.mmuEnable = PDP11.ACCESS.READ | PDP11.ACCESS.WRITE;
|
||||
} else {
|
||||
this.mmuEnable = PDP11.ACCESS.WRITE;
|
||||
newMMR0 &= 0xf381;
|
||||
if (this.regMMR0 != newMMR0) {
|
||||
this.regMMR0 = newMMR0;
|
||||
this.mmuLastMode = (newMMR0 >> 5) & 3;
|
||||
this.mmuLastPage = (newMMR0 >> 1) & 0xf;
|
||||
var mmuEnable = 0;
|
||||
if (newMMR0 & 0x101) {
|
||||
mmuEnable = PDP11.ACCESS.WRITE;
|
||||
if (newMMR0 & 0x1) {
|
||||
mmuEnable |= PDP11.ACCESS.READ;
|
||||
}
|
||||
}
|
||||
if (this.mmuEnable != mmuEnable) {
|
||||
this.mmuEnable = mmuEnable;
|
||||
this.setMemoryAccess();
|
||||
}
|
||||
} else {
|
||||
this.mmuEnable = 0;
|
||||
}
|
||||
this.initMemoryAccess();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -309,13 +327,16 @@ CPUStatePDP11.prototype.setMMR3 = function(newMMR3)
|
|||
if (this.cpuType !== 70) {
|
||||
newMMR3 &= ~(PDP11.MMR3.MMU_22BIT | PDP11.MMR3.UNIBUS_MAP);
|
||||
}
|
||||
this.regMMR3 = newMMR3;
|
||||
if (this.regMMR3 & PDP11.MMR3.MMU_22BIT) {
|
||||
this.mmuMask = 0x3fffff;
|
||||
this.mmuMemorySize = BusPDP11.MAX_MEMORY;
|
||||
} else {
|
||||
this.mmuMask = 0x3ffff;
|
||||
this.mmuMemorySize = BusPDP11.IOPAGE_18BIT;
|
||||
if (this.regMMR3 != newMMR3) {
|
||||
this.regMMR3 = newMMR3;
|
||||
if (newMMR3 & PDP11.MMR3.MMU_22BIT) {
|
||||
this.mmuMask = 0x3fffff;
|
||||
this.mmuMemorySize = BusPDP11.MAX_MEMORY;
|
||||
} else {
|
||||
this.mmuMask = 0x3ffff;
|
||||
this.mmuMemorySize = BusPDP11.IOPAGE_18BIT;
|
||||
}
|
||||
this.setMemoryAccess();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1515,7 +1536,7 @@ CPUStatePDP11.prototype.getAddress = function(mode, reg, accessFlags)
|
|||
/**
|
||||
* getPhysicalAddrByMode(mode, reg, accessFlags)
|
||||
*
|
||||
* This is a handler set up by initMemoryAccess(). All calls should go through getAddrByMode().
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through getAddrByMode().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} mode
|
||||
|
|
@ -1531,7 +1552,7 @@ CPUStatePDP11.prototype.getPhysicalAddrByMode = function(mode, reg, accessFlags)
|
|||
/**
|
||||
* getVirtualAddrByMode(mode, reg, accessFlags)
|
||||
*
|
||||
* This is a handler set up by initMemoryAccess(). All calls should go through getAddrByMode().
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through getAddrByMode().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} mode
|
||||
|
|
@ -1547,7 +1568,7 @@ CPUStatePDP11.prototype.getVirtualAddrByMode = function(mode, reg, accessFlags)
|
|||
/**
|
||||
* readWordFromPhysical(physicalAddress)
|
||||
*
|
||||
* This is a handler set up by initMemoryAccess(). All calls should go through readWordFromAddr().
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through readWordFromAddr().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} physicalAddress
|
||||
|
|
@ -1561,7 +1582,7 @@ CPUStatePDP11.prototype.readWordFromPhysical = function(physicalAddress)
|
|||
/**
|
||||
* readWordFromVirtual(virtualAddress)
|
||||
*
|
||||
* This is a handler set up by initMemoryAccess(). All calls should go through readWordFromAddr().
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through readWordFromAddr().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} virtualAddress (input address is 17 bit (I&D))
|
||||
|
|
@ -1575,7 +1596,7 @@ CPUStatePDP11.prototype.readWordFromVirtual = function(virtualAddress)
|
|||
/**
|
||||
* writeWordToPhysical(physicalAddress, data)
|
||||
*
|
||||
* This is a handler set up by initMemoryAccess(). All calls should go through writeWordToAddr().
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through writeWordToAddr().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} physicalAddress
|
||||
|
|
@ -1589,7 +1610,7 @@ CPUStatePDP11.prototype.writeWordToPhysical = function(physicalAddress, data)
|
|||
/**
|
||||
* writeWordToVirtual(virtualAddress, data)
|
||||
*
|
||||
* This is a handler set up by initMemoryAccess(). All calls should go through writeWordToAddr().
|
||||
* This is a handler set up by setMemoryAccess(). All calls should go through writeWordToAddr().
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} virtualAddress (input address is 17 bit (I&D))
|
||||
|
|
@ -1659,7 +1680,7 @@ CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, dat
|
|||
* TODO: Consider replacing the following code with writeWordToAddr(), by adding optional mmuMode
|
||||
* parameters for each of the discrete mapVirtualToPhysical() and bus.setWord() operations, because
|
||||
* as it stands, this is the only remaining call to mapVirtualToPhysical() outside of our
|
||||
* initMemoryAccess() handlers.
|
||||
* setMemoryAccess() handlers.
|
||||
*/
|
||||
this.mmuMode = (this.regPSW >> 12) & 3;
|
||||
addr = this.mapVirtualToPhysical(addr | (accessFlags & PDP11.ACCESS.DSPACE), PDP11.ACCESS.WRITE);
|
||||
|
|
|
|||
|
|
@ -79,16 +79,24 @@ var BYTEARRAYS = false;
|
|||
var TYPEDARRAYS = (typeof ArrayBuffer !== 'undefined');
|
||||
|
||||
/**
|
||||
* WORDBUS forces the Bus and Memory interfaces to assume even addresses when accessing words. Since PDPjs inherited
|
||||
* its Bus component from PCx86, it originally supported both aligned and unaligned word accesses by default, but since
|
||||
* the PDP-11 requires aligned (even) word addresses, we can turn off support for unaligned accesses and get some
|
||||
* performance gains.
|
||||
* MEMFAULT forces the Memory interfaces to signal a CPU fault when a word is accessed using an odd (unaligned) address.
|
||||
*
|
||||
* When WORDBUS is true, the Bus and Memory components simply ignore the low bit of word addresses, because it is the
|
||||
* CPU, not the Bus, that's responsible for validating addresses and generating the appropriate traps.
|
||||
* Since PDPjs inherited its Bus component from PCx86, it included support for both aligned and unaligned word accesses
|
||||
* by default. However, the PDP-11 adds a wrinkle: when an odd address is used to access a memory word, a BUS_ERROR trap
|
||||
* must be generated. Note that odd IOPAGE word accesses are fine; this only affects the Memory component.
|
||||
*
|
||||
* Don't worry that the source code looks MORE complicated rather than LESS with the additional WORDBUS checks, because
|
||||
* the Closure Compiler eliminates those checks and throws away the (unreachable) code blocks that deal with unaligned
|
||||
* When the MMU is enabled, these checks may also be performed at a higher level, eliminating the need for them at the
|
||||
* physical memory level.
|
||||
*/
|
||||
var MEMFAULT = true;
|
||||
|
||||
/**
|
||||
* WORDBUS turns off support for unaligned memory words. Whereas MEMFAULT necessarily slows down memory word accesses
|
||||
* slightly, WORDBUS is able to speed them up slightly, by assuming that all word accesses (which didn't fault) must be
|
||||
* aligned. This affects all word accesses, even IOPAGE accesses, because it also eliminates cross-block boundary checks.
|
||||
*
|
||||
* Don't worry that the source code looks MORE complicated rather than LESS with the additional MEMFAULT and WORDBUS checks,
|
||||
* because the Closure Compiler eliminates those checks and throws away the (unreachable) code blocks that deal with unaligned
|
||||
* accesses.
|
||||
*/
|
||||
var WORDBUS = true;
|
||||
|
|
@ -109,6 +117,7 @@ var PDP11 = {
|
|||
MAXDEBUG: MAXDEBUG, // shared
|
||||
PRIVATE: PRIVATE, // shared
|
||||
TYPEDARRAYS:TYPEDARRAYS,
|
||||
MEMFAULT: MEMFAULT,
|
||||
WORDBUS: WORDBUS,
|
||||
SITEHOST: SITEHOST, // shared
|
||||
XMLVERSION: XMLVERSION, // shared
|
||||
|
|
|
|||
|
|
@ -623,7 +623,7 @@ MemoryPDP11.prototype = {
|
|||
* @return {number}
|
||||
*/
|
||||
readWordMemory: function readWordMemory(off, addr) {
|
||||
if (PDP11.WORDBUS && (off & 0x1)) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
}
|
||||
if (BYTEARRAYS) {
|
||||
|
|
@ -667,7 +667,7 @@ MemoryPDP11.prototype = {
|
|||
* @param {number} addr
|
||||
*/
|
||||
writeWordMemory: function writeWordMemory(off, w, addr) {
|
||||
if (PDP11.WORDBUS && (off & 0x1)) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
}
|
||||
if (BYTEARRAYS) {
|
||||
|
|
@ -777,7 +777,7 @@ MemoryPDP11.prototype = {
|
|||
* @return {number}
|
||||
*/
|
||||
readWordBE: function readWordBE(off, addr) {
|
||||
if (PDP11.WORDBUS && (off & 0x1)) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
}
|
||||
return this.dv.getUint16(off, true);
|
||||
|
|
@ -791,15 +791,15 @@ MemoryPDP11.prototype = {
|
|||
* @return {number}
|
||||
*/
|
||||
readWordLE: function readWordLE(off, addr) {
|
||||
var w;
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
}
|
||||
/*
|
||||
* TODO: For non-WORDBUS machines, it remains to be seen if there's any advantage to checking the offset
|
||||
* for an aligned read vs. always reading the bytes separately.
|
||||
*/
|
||||
var w;
|
||||
if (PDP11.WORDBUS && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
}
|
||||
if (!(off & 0x1)) {
|
||||
if (PDP11.WORDBUS || !(off & 0x1)) {
|
||||
w = this.aw[off >> 1];
|
||||
} else {
|
||||
w = this.ab[off] | (this.ab[off+1] << 8);
|
||||
|
|
@ -845,7 +845,7 @@ MemoryPDP11.prototype = {
|
|||
* @param {number} w
|
||||
*/
|
||||
writeWordBE: function writeWordBE(off, w, addr) {
|
||||
if (PDP11.WORDBUS && (off & 0x1)) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
}
|
||||
this.dv.setUint16(off, w, true);
|
||||
|
|
@ -860,14 +860,14 @@ MemoryPDP11.prototype = {
|
|||
* @param {number} w
|
||||
*/
|
||||
writeWordLE: function writeWordLE(off, w, addr) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
}
|
||||
/*
|
||||
* TODO: For non-WORDBUS machines, it remains to be seen if there's any advantage to checking the offset
|
||||
* for an aligned write vs. always writing the bytes separately.
|
||||
*/
|
||||
if (PDP11.WORDBUS && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
}
|
||||
if (!(off & 0x1)) {
|
||||
if (PDP11.WORDBUS || !(off & 0x1)) {
|
||||
this.aw[off >> 1] = w;
|
||||
} else {
|
||||
this.ab[off] = w;
|
||||
|
|
|
|||
Loading…
Reference in a new issue