Cleaned up how memory and IOPAGE traps are triggered, how ODD byte-level IOPAGE accesses are handled, and how memory is dumped by the Debugger
This commit is contained in:
parent
ae4fbeb489
commit
6514836098
31 changed files with 901 additions and 679 deletions
|
|
@ -810,7 +810,7 @@ ChipSet.DIPSW[ChipSet.MODEL_5150][0][ChipSet.SWITCH_TYPE.FPU] = {
|
|||
0: 0x00, // 0 means an FPU is NOT installed
|
||||
1: 0x02 // 1 means an FPU is installed
|
||||
},
|
||||
LABEL: "Coprocessor"
|
||||
LABEL: "FPU"
|
||||
};
|
||||
ChipSet.DIPSW[ChipSet.MODEL_5150][0][ChipSet.SWITCH_TYPE.MONITOR] = {
|
||||
MASK: 0x30,
|
||||
|
|
@ -910,7 +910,7 @@ ChipSet.DIPSW[ChipSet.MODEL_ATT_6300][0][ChipSet.SWITCH_TYPE.FPU] = {
|
|||
0: 0x00,
|
||||
1: 0x10
|
||||
},
|
||||
LABEL: "Coprocessor"
|
||||
LABEL: "FPU"
|
||||
};
|
||||
ChipSet.DIPSW[ChipSet.MODEL_ATT_6300][1][ChipSet.SWITCH_TYPE.FLOPTYPE] = {
|
||||
MASK: 0x01,
|
||||
|
|
@ -2809,7 +2809,7 @@ ChipSet.prototype.updateDIPSwitchDescriptions = function()
|
|||
3: "Monochrome"
|
||||
};
|
||||
sText += this.getDIPMemorySize(true) + "Kb";
|
||||
sText += ", " + (+this.getDIPCoprocessor(true)? "" : "No ") + "Coprocessor";
|
||||
sText += ", " + (+this.getDIPCoprocessor(true)? "" : "No ") + "FPU";
|
||||
sText += ", " + asMonitorTypes[this.getDIPVideoMonitor(true)] + " Monitor";
|
||||
sText += ", " + this.getDIPFloppyDrives(true) + " Floppy Drives";
|
||||
if (this.aDIPSwitches[0][1] != null && this.aDIPSwitches[0][1] != this.aDIPSwitches[0][0] ||
|
||||
|
|
|
|||
|
|
@ -77,9 +77,11 @@ function BusPDP11(parmsBus, cpu, dbg)
|
|||
|
||||
/*
|
||||
* 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).
|
||||
* It is managed by setIOPageRange(). reset() establishes the default (16).
|
||||
*/
|
||||
this.nIOPageRange = 0; // zero means no IOPAGE access (yet)
|
||||
this.prevIOPageBlocks = []; // this saves any memory blocks we had to replace with IOPAGE blocks
|
||||
this.realIOPageBlocks = null; // this saves the memory blocks allocated for IOPAGE, so we can reuse them
|
||||
|
||||
/*
|
||||
* Compute all BusPDP11 memory block parameters, based on the width of the bus. The entire
|
||||
|
|
@ -140,6 +142,7 @@ function BusPDP11(parmsBus, cpu, dbg)
|
|||
*/
|
||||
this.aIOHandlers = [];
|
||||
this.fIOBreakAll = false;
|
||||
this.nDisableTraps = 0;
|
||||
|
||||
/*
|
||||
* Array of RESET notification handlers registered by Device components.
|
||||
|
|
@ -183,19 +186,62 @@ BusPDP11.ERROR = {
|
|||
};
|
||||
|
||||
/*
|
||||
* These are our custom controller functions for all IOPAGE accesses.
|
||||
* Every entry in the aIOHandlers table is an array with the following indexes:
|
||||
*/
|
||||
BusPDP11.IOHANDLER = {
|
||||
READ_BYTE: 0,
|
||||
WRITE_BYTE: 1,
|
||||
READ_WORD: 2,
|
||||
WRITE_WORD: 3,
|
||||
NAME: 4
|
||||
};
|
||||
|
||||
/*
|
||||
* These are our custom IOController functions for all IOPAGE accesses. They look up the IOPAGE
|
||||
* offset in the aIOHandlers table, and if an entry exists, they use the appropriate IOHANDLER indexes
|
||||
* (above) to locate the appropriate read/write handlers.
|
||||
*
|
||||
* Note that we try to have reasonable fall-backs for byte reads when only word read handlers exist,
|
||||
* and word reads if only byte handlers exist. Ditto for writes. These fall-backs may not always be
|
||||
* Note that we try to have reasonable fallbacks for byte reads when only word read handlers exist,
|
||||
* and word reads if only byte handlers exist. Ditto for writes. These fallbacks may not always be
|
||||
* appropriate; for example, when a byte write falls back to a word write, the address must be read
|
||||
* first, and depending on the underlying I/O device, that may or may not have side-effects. It's really
|
||||
* up to the device to know whether that matters, and provide all the necessary handlers if it does.
|
||||
*
|
||||
* TODO: Unlike regular Memory blocks, IOPAGE accesses permit word accesses on ODD addresses; that works
|
||||
* just fine by registering WORD handlers for the appropriate ODD addresses. What is unclear, however,
|
||||
* is what is exactly supposed to happen when the CPU reads or writes a BYTE from an ODD IOPAGE address;
|
||||
* it's likely that our built-in fallbacks are NOT correct for those cases.
|
||||
*
|
||||
* For example, let's imagine that only read/write WORD handlers have been registered for ODD address
|
||||
* 177701 (ie, General Register R1, Set 0). If a readByte(177701) request is made, we would fallback to
|
||||
* reading the word at 177700 and returning the high byte, but that would fetch the contents of General
|
||||
* Register R0 instead of R1, which clearly seems wrong.
|
||||
*
|
||||
* One solution is for the caller to register both BYTE and WORD handlers for ODD addresses, making
|
||||
* the caller responsible for the defining the correct behavior in all cases. However, that's more work
|
||||
* for the caller, and we're just punting the problem instead of solving it.
|
||||
*
|
||||
* Another solution is for addIOHandlers() to detect the ODD address case, and install custom fallback
|
||||
* handlers for read and write BYTE accesses. In the above example, the custom read BYTE handler would
|
||||
* invoke the read WORD handler and mask the result with 0xff, and the custom write BYTE handler would
|
||||
* first call the read WORD handler, insert the new data into the low byte of the result, and then
|
||||
* call the write WORD handler.
|
||||
*
|
||||
* addIOHandlers() currently implements the second solution. Again, we're assuming that's the correct
|
||||
* behavior for ODD IOPAGE accesses, which may not be a valid assumption.
|
||||
*
|
||||
* One of things that gives me pause about the second solution is that when the destination of a MOVB
|
||||
* instruction is a general register, the byte is sign-extended to a word. So it seems to strange to have
|
||||
* a different MOVB behavior when the destination is ODD general register using an ODD IOPAGE address.
|
||||
* Other byte instructions, like CLRB, would function identically when modifying ODD general registers,
|
||||
* regardless how they are referenced.
|
||||
*
|
||||
* TODO: Another small potential improvement would be for addIOHandlers() to predefine fall-backs for all
|
||||
* missing handlers, so there's never a need to check each entry (eg, afn[0], afn[1], etc) before calling
|
||||
* it. However, since there's no avoiding checking afn itself (unless we FULLY populate the aIOHandlers
|
||||
* array), and since these I/O accesses should be pretty infrequent relative to all other memory accesses,
|
||||
* the benefit seems pretty minimal.
|
||||
* missing handlers, in both the ODD and EVEN cases, so there's never a need to check each function index
|
||||
* before calling it. However, since there's no avoiding checking aIOHandlers[off] (unless we FULLY populate
|
||||
* the aIOHandlers array), and since these I/O accesses should be pretty infrequent relative to all other
|
||||
* memory accesses, the benefit seems pretty minimal. Plus, all our fallback assumptions still need to be
|
||||
* verified, so let's wait until that's done before we start optimizing this code.
|
||||
*/
|
||||
BusPDP11.IOController = {
|
||||
|
||||
|
|
@ -213,26 +259,26 @@ BusPDP11.IOController = {
|
|||
var bus = this.controller;
|
||||
var afn = bus.aIOHandlers[off];
|
||||
if (afn) {
|
||||
if (afn[0]) {
|
||||
b = afn[0](addr) & 0xff; // we mask the result of readByte() in case the caller is re-using their readWord() handler
|
||||
} else if (afn[2]) {
|
||||
if (afn[BusPDP11.IOHANDLER.READ_BYTE]) {
|
||||
b = afn[BusPDP11.IOHANDLER.READ_BYTE](addr);
|
||||
} else if (afn[BusPDP11.IOHANDLER.READ_WORD]) {
|
||||
if (!(addr & 0x1)) {
|
||||
b = afn[2](addr) & 0xff;
|
||||
b = afn[BusPDP11.IOHANDLER.READ_WORD](addr) & 0xff;
|
||||
} else {
|
||||
b = afn[2](addr & ~0x1) >> 8;
|
||||
b = afn[BusPDP11.IOHANDLER.READ_WORD](addr & ~0x1) >> 8;
|
||||
}
|
||||
}
|
||||
} else if (addr & 0x1) {
|
||||
afn = bus.aIOHandlers[off & ~0x1];
|
||||
if (afn) {
|
||||
if (afn[2]) {
|
||||
b = afn[2](addr & ~0x1) >> 8;
|
||||
if (afn[BusPDP11.IOHANDLER.READ_WORD]) {
|
||||
b = afn[BusPDP11.IOHANDLER.READ_WORD](addr & ~0x1) >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b >= 0) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
|
||||
this.dbg.printMessage(afn[4] + ".readByte(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(b), true, true);
|
||||
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.NAME] + ".readByte(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(b), true, true);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
|
@ -261,21 +307,21 @@ BusPDP11.IOController = {
|
|||
/*
|
||||
* If a writeByte() handler exists, call it; we're done
|
||||
*/
|
||||
if (afn[1]) {
|
||||
afn[1](b, addr);
|
||||
if (afn[BusPDP11.IOHANDLER.WRITE_BYTE]) {
|
||||
afn[BusPDP11.IOHANDLER.WRITE_BYTE](b, addr);
|
||||
fWrite = true;
|
||||
}
|
||||
/*
|
||||
* If a writeWord() handler exists, call the readWord() handler first to get the original data,
|
||||
* then call writeWord() with the new data pre-inserted into the original data.
|
||||
* then call writeWord() with the new data pre-inserted in the original data.
|
||||
*/
|
||||
else if (afn[3]) {
|
||||
w = afn[2]? afn[2](addr) : 0;
|
||||
else if (afn[BusPDP11.IOHANDLER.WRITE_WORD]) {
|
||||
w = afn[BusPDP11.IOHANDLER.READ_WORD]? afn[BusPDP11.IOHANDLER.READ_WORD](addr) : 0;
|
||||
if (!(addr & 0x1)) {
|
||||
afn[3]((w & ~0xff) | b, addr);
|
||||
afn[BusPDP11.IOHANDLER.WRITE_WORD]((w & ~0xff) | b, addr);
|
||||
fWrite = true;
|
||||
} else {
|
||||
afn[3]((w & 0xff) | (b << 8), addr & ~0x1);
|
||||
afn[BusPDP11.IOHANDLER.WRITE_WORD]((w & 0xff) | (b << 8), addr & ~0x1);
|
||||
fWrite = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -283,21 +329,21 @@ BusPDP11.IOController = {
|
|||
/*
|
||||
* If no handler existed, and this address was odd, then perhaps a handler exists for the even address;
|
||||
* if so, call the readWord() handler first to get the original data, then call writeWord() with the new
|
||||
* data pre-inserted into (the high byte of) the original data.
|
||||
* data pre-inserted in (the high byte of) the original data.
|
||||
*/
|
||||
afn = bus.aIOHandlers[off & ~0x1];
|
||||
if (afn) {
|
||||
if (afn[3]) {
|
||||
if (afn[BusPDP11.IOHANDLER.WRITE_WORD]) {
|
||||
addr &= ~0x1;
|
||||
w = afn[2]? afn[2](addr) : 0;
|
||||
afn[3]((w & 0xff) | (b << 8), addr);
|
||||
w = afn[BusPDP11.IOHANDLER.READ_WORD]? afn[BusPDP11.IOHANDLER.READ_WORD](addr) : 0;
|
||||
afn[BusPDP11.IOHANDLER.WRITE_WORD]((w & 0xff) | (b << 8), addr);
|
||||
fWrite = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fWrite) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
|
||||
this.dbg.printMessage(afn[4] + ".writeByte(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(b) + ")", true, true);
|
||||
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.NAME] + ".writeByte(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(b) + ")", true, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -321,15 +367,15 @@ BusPDP11.IOController = {
|
|||
var bus = this.controller;
|
||||
var afn = bus.aIOHandlers[off];
|
||||
if (afn) {
|
||||
if (afn[2]) {
|
||||
w = afn[2](addr);
|
||||
} else if (afn[0]) {
|
||||
w = afn[0](addr) | (afn[0](addr + 1) << 8);
|
||||
if (afn[BusPDP11.IOHANDLER.READ_WORD]) {
|
||||
w = afn[BusPDP11.IOHANDLER.READ_WORD](addr);
|
||||
} else if (afn[BusPDP11.IOHANDLER.READ_BYTE]) {
|
||||
w = afn[BusPDP11.IOHANDLER.READ_BYTE](addr) | (afn[BusPDP11.IOHANDLER.READ_BYTE](addr + 1) << 8);
|
||||
}
|
||||
}
|
||||
if (w >= 0) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
|
||||
this.dbg.printMessage(afn[4] + ".readWord(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(w), true, true);
|
||||
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.NAME] + ".readWord(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(w), true, true);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
|
@ -354,18 +400,18 @@ BusPDP11.IOController = {
|
|||
var bus = this.controller;
|
||||
var afn = bus.aIOHandlers[off];
|
||||
if (afn) {
|
||||
if (afn[3]) {
|
||||
afn[3](w, addr);
|
||||
if (afn[BusPDP11.IOHANDLER.WRITE_WORD]) {
|
||||
afn[BusPDP11.IOHANDLER.WRITE_WORD](w, addr);
|
||||
fWrite = true;
|
||||
} else if (afn[1]) {
|
||||
afn[1](w & 0xff, addr);
|
||||
afn[1](w >> 8, addr + 1);
|
||||
} else if (afn[BusPDP11.IOHANDLER.WRITE_BYTE]) {
|
||||
afn[BusPDP11.IOHANDLER.WRITE_BYTE](w & 0xff, addr);
|
||||
afn[BusPDP11.IOHANDLER.WRITE_BYTE](w >> 8, addr + 1);
|
||||
fWrite = true;
|
||||
}
|
||||
}
|
||||
if (fWrite) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
|
||||
this.dbg.printMessage(afn[4] + ".writeWord(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(w) + ")", true, true);
|
||||
this.dbg.printMessage(afn[BusPDP11.IOHANDLER.NAME] + ".writeWord(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(w) + ")", true, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -385,13 +431,12 @@ BusPDP11.IOController = {
|
|||
*/
|
||||
BusPDP11.prototype.initMemory = function()
|
||||
{
|
||||
var block = new MemoryPDP11(this.cpu);
|
||||
var block = new MemoryPDP11(this);
|
||||
block.copyBreakpoints(this.dbg);
|
||||
this.aMemBlocks = new Array(this.nBlockTotal);
|
||||
for (var iBlock = 0; iBlock < this.nBlockTotal; iBlock++) {
|
||||
this.aMemBlocks[iBlock] = block;
|
||||
}
|
||||
this.setIOPageRange(16);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -400,8 +445,12 @@ BusPDP11.prototype.initMemory = function()
|
|||
* 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.
|
||||
*
|
||||
* Note that we defer our initial call to this function as long as possible (ie, at the end of reset()) so that
|
||||
* other components have first shot at adding their own memory blocks (if any), because addMemory() only allows
|
||||
* installing memory on top of empty memory blocks.
|
||||
*
|
||||
* @this {BusPDP11}
|
||||
* @param {number} nRange (16, 18 or 22)
|
||||
* @param {number} nRange (16, 18 or 22; 0 removes the IOPAGE altogether)
|
||||
*/
|
||||
BusPDP11.prototype.setIOPageRange = function(nRange)
|
||||
{
|
||||
|
|
@ -409,12 +458,20 @@ BusPDP11.prototype.setIOPageRange = function(nRange)
|
|||
var addr;
|
||||
if (this.nIOPageRange) {
|
||||
addr = (1 << this.nIOPageRange) - BusPDP11.IOPAGE_LENGTH;
|
||||
if (!this.removeMemory(addr, BusPDP11.IOPAGE_LENGTH)) return;
|
||||
this.setMemoryBlocks(addr, BusPDP11.IOPAGE_LENGTH, this.prevIOPageBlocks);
|
||||
this.nIOPageRange = 0;
|
||||
}
|
||||
addr = (1 << nRange) - BusPDP11.IOPAGE_LENGTH;
|
||||
if (!this.addMemory(addr, BusPDP11.IOPAGE_LENGTH, MemoryPDP11.TYPE.CONTROLLER, this)) return;
|
||||
this.nIOPageRange = nRange;
|
||||
if (nRange) {
|
||||
this.nIOPageRange = nRange;
|
||||
addr = (1 << nRange) - BusPDP11.IOPAGE_LENGTH;
|
||||
this.prevIOPageBlocks = this.getMemoryBlocks(addr, BusPDP11.IOPAGE_LENGTH);
|
||||
if (this.realIOPageBlocks) {
|
||||
this.setMemoryBlocks(addr, BusPDP11.IOPAGE_LENGTH, this.realIOPageBlocks);
|
||||
} else {
|
||||
this.addMemory(addr, BusPDP11.IOPAGE_LENGTH, MemoryPDP11.TYPE.CONTROLLER, this);
|
||||
this.realIOPageBlocks = this.getMemoryBlocks(addr, BusPDP11.IOPAGE_LENGTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -460,6 +517,7 @@ BusPDP11.prototype.reset = function()
|
|||
for (var i = 0; i < this.afnReset.length; i++) {
|
||||
this.afnReset[i]();
|
||||
}
|
||||
this.setIOPageRange(16);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -474,13 +532,17 @@ BusPDP11.prototype.reset = function()
|
|||
* @param {number} addr (ie, an IOPAGE address)
|
||||
* @param {number} data (-1 if read, otherwise write)
|
||||
* @param {number} byteFlag (true if byte I/O, otherwise word)
|
||||
* @return {number}
|
||||
*/
|
||||
BusPDP11.prototype.unknownAccess = function(addr, data, byteFlag)
|
||||
{
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.WARN)) {
|
||||
this.dbg.printMessage("warning: unrecognized I/O access(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(data) + "," + byteFlag + ")", true, true);
|
||||
if (!this.nDisableTraps) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.WARN)) {
|
||||
this.dbg.printMessage("warning: unrecognized I/O access(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(data) + "," + byteFlag + ")", true, true);
|
||||
}
|
||||
this.cpu.trap(PDP11.TRAP.BUS_ERROR, addr);
|
||||
}
|
||||
this.cpu.trap(PDP11.TRAP.BUS_ERROR, addr);
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -549,8 +611,13 @@ BusPDP11.prototype.addMemory = function(addr, size, type, controller)
|
|||
var sizeBlock = this.nBlockSize - (addrNext - addrBlock);
|
||||
if (sizeBlock > sizeLeft) sizeBlock = sizeLeft;
|
||||
|
||||
if (block && block.size) {
|
||||
if (block.type == type && block.controller == controller) {
|
||||
/*
|
||||
* addMemory() will now happily replace an existing block when a memory controller is specified;
|
||||
* this is a work-around to make life easier for setIOPageRange(), which otherwise would have to call
|
||||
* removeMemory() first, which would just waste time and memory allocating more (empty) blocks.
|
||||
*/
|
||||
if (!controller && block && block.size) {
|
||||
if (block.type == type /* && block.controller == controller */) {
|
||||
/*
|
||||
* Where there is already a similar block with a non-zero size, we allow the allocation only if:
|
||||
*
|
||||
|
|
@ -575,7 +642,7 @@ BusPDP11.prototype.addMemory = function(addr, size, type, controller)
|
|||
return this.reportError(BusPDP11.ERROR.RANGE_INUSE, addrNext, sizeLeft);
|
||||
}
|
||||
|
||||
var blockNew = new MemoryPDP11(this.cpu, addrNext, sizeBlock, this.nBlockSize, type, controller);
|
||||
var blockNew = new MemoryPDP11(this, addrNext, sizeBlock, this.nBlockSize, type, controller);
|
||||
blockNew.copyBreakpoints(this.dbg, block);
|
||||
this.aMemBlocks[iBlock++] = blockNew;
|
||||
|
||||
|
|
@ -584,7 +651,7 @@ BusPDP11.prototype.addMemory = function(addr, size, type, controller)
|
|||
}
|
||||
|
||||
if (sizeLeft <= 0) {
|
||||
this.status(Math.floor(size / 1024) + "Kb " + MemoryPDP11.TYPE.NAMES[type] + " at " + str.toHexLong(addr));
|
||||
this.status(Math.floor(size / 1024) + "Kb " + MemoryPDP11.TYPE_NAMES[type] + " at " + str.toHexLong(addr));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -713,7 +780,7 @@ BusPDP11.prototype.removeMemory = function(addr, size)
|
|||
var iBlock = addr >>> this.nBlockShift;
|
||||
while (size > 0) {
|
||||
var blockOld = this.aMemBlocks[iBlock];
|
||||
var blockNew = new MemoryPDP11(this.cpu, addr);
|
||||
var blockNew = new MemoryPDP11(this, addr);
|
||||
blockNew.copyBreakpoints(this.dbg, blockOld);
|
||||
this.aMemBlocks[iBlock++] = blockNew;
|
||||
addr = iBlock * this.nBlockSize;
|
||||
|
|
@ -799,7 +866,7 @@ BusPDP11.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
|
|||
this.assert(block);
|
||||
if (!block) break;
|
||||
if (type !== undefined) {
|
||||
var blockNew = new MemoryPDP11(this.cpu, addr);
|
||||
var blockNew = new MemoryPDP11(this, addr);
|
||||
blockNew.clone(block, type, this.dbg);
|
||||
block = blockNew;
|
||||
}
|
||||
|
|
@ -831,7 +898,10 @@ BusPDP11.prototype.getByte = function(addr)
|
|||
*/
|
||||
BusPDP11.prototype.getByteDirect = function(addr)
|
||||
{
|
||||
return this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].readByteDirect(addr & this.nBlockLimit, addr);
|
||||
this.nDisableTraps++;
|
||||
var b = this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].readByteDirect(addr & this.nBlockLimit, addr);
|
||||
this.nDisableTraps--;
|
||||
return b;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -862,12 +932,17 @@ BusPDP11.prototype.getWord = function(addr)
|
|||
*/
|
||||
BusPDP11.prototype.getWordDirect = function(addr)
|
||||
{
|
||||
var w;
|
||||
var off = addr & this.nBlockLimit;
|
||||
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
|
||||
this.nDisableTraps++;
|
||||
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
|
||||
return this.aMemBlocks[iBlock++].readByteDirect(off, addr) | (this.aMemBlocks[iBlock & this.nBlockMask].readByteDirect(0, addr + 1) << 8);
|
||||
w = this.aMemBlocks[iBlock++].readByteDirect(off, addr) | (this.aMemBlocks[iBlock & this.nBlockMask].readByteDirect(0, addr + 1) << 8);
|
||||
} else {
|
||||
w = this.aMemBlocks[iBlock].readWordDirect(off, addr);
|
||||
}
|
||||
return this.aMemBlocks[iBlock].readWordDirect(off, addr);
|
||||
this.nDisableTraps--;
|
||||
return w;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -894,7 +969,9 @@ BusPDP11.prototype.setByte = function(addr, b)
|
|||
*/
|
||||
BusPDP11.prototype.setByteDirect = function(addr, b)
|
||||
{
|
||||
this.nDisableTraps++;
|
||||
this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].writeByteDirect(addr & this.nBlockLimit, b & 0xff, addr);
|
||||
this.nDisableTraps--;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -930,12 +1007,14 @@ BusPDP11.prototype.setWordDirect = function(addr, w)
|
|||
{
|
||||
var off = addr & this.nBlockLimit;
|
||||
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
|
||||
this.nDisableTraps++;
|
||||
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
|
||||
this.aMemBlocks[iBlock++].writeByteDirect(off, w & 0xff, addr);
|
||||
this.aMemBlocks[iBlock & this.nBlockMask].writeByteDirect(0, (w >> 8) & 0xff, addr + 1);
|
||||
return;
|
||||
} else {
|
||||
this.aMemBlocks[iBlock].writeWordDirect(off, w & 0xffff, addr);
|
||||
}
|
||||
this.aMemBlocks[iBlock].writeWordDirect(off, w & 0xffff, addr);
|
||||
this.nDisableTraps--;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1099,13 +1178,41 @@ BusPDP11.prototype.addIOHandlers = function(start, end, fnReadByte, fnWriteByte,
|
|||
BusPDP11.prototype.addIOTable = function(component, table)
|
||||
{
|
||||
for (var port in table) {
|
||||
var addr = +port;
|
||||
var afn = table[port];
|
||||
|
||||
/*
|
||||
* Don't install (ie, ignore) handlers for I/O addresses that are defined with a model number
|
||||
* that is "greater than" than the current model.
|
||||
*/
|
||||
if (afn[5] && afn[5] > this.cpu.model) continue;
|
||||
|
||||
var fnReadByte = afn[0]? afn[0].bind(component) : null;
|
||||
var fnWriteByte = afn[1]? afn[1].bind(component) : null;
|
||||
var fnReadWord = afn[2]? afn[2].bind(component) : null;
|
||||
var fnWriteWord = afn[3]? afn[3].bind(component) : null;
|
||||
this.addIOHandlers(+port, +port, fnReadByte, fnWriteByte, fnReadWord, fnWriteWord, afn[4]);
|
||||
|
||||
/*
|
||||
* As discussed in the IOController comments above, when handlers are being registered for ODD addresses,
|
||||
* we assume that we need different fallback handlers when reading and/or writing bytes.
|
||||
*/
|
||||
if (addr & 0x1) {
|
||||
if (!fnReadByte && fnReadWord) {
|
||||
fnReadByte = function(fnReadWord) {
|
||||
return function(addr) {
|
||||
return fnReadWord(addr) & 0xff;
|
||||
}.bind(component);
|
||||
}(fnReadWord);
|
||||
}
|
||||
if (!fnWriteByte && fnWriteWord && fnReadWord) {
|
||||
fnWriteByte = function(fnWriteWord, fnReadWord) {
|
||||
return function(data, addr) {
|
||||
return fnWriteWord((fnReadWord(addr) & ~0xff) | data, addr);
|
||||
}.bind(component);
|
||||
}(fnWriteWord, fnReadWord);
|
||||
}
|
||||
}
|
||||
this.addIOHandlers(addr, addr, fnReadByte, fnWriteByte, fnReadWord, fnWriteWord, afn[4]);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1120,6 +1227,24 @@ BusPDP11.prototype.addResetHandler = function(fnReset)
|
|||
this.afnReset.push(fnReset);
|
||||
};
|
||||
|
||||
/**
|
||||
* fault(addr)
|
||||
*
|
||||
* Memory interface for signaling alignment errors.
|
||||
*
|
||||
* @this {BusPDP11}
|
||||
* @param {number} addr
|
||||
*/
|
||||
BusPDP11.prototype.fault = function(addr)
|
||||
{
|
||||
if (!this.nDisableTraps) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.WARN)) {
|
||||
this.dbg.printMessage("memory fault on address " + this.dbg.toStrBase(addr), true, true);
|
||||
}
|
||||
this.cpu.trap(PDP11.TRAP.BUS_ERROR, addr);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* reportError(errNum, addr, size, fQuiet)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -205,22 +205,9 @@ 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()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -98,17 +98,6 @@ Component.subclass(CPUStatePDP11, CPUPDP11);
|
|||
*/
|
||||
var InterruptEvent;
|
||||
|
||||
/**
|
||||
* initBusComplete()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.initBusComplete = function()
|
||||
{
|
||||
this.assert(this.bus);
|
||||
this.setMemoryAccess();
|
||||
};
|
||||
|
||||
/**
|
||||
* initProcessor()
|
||||
*
|
||||
|
|
@ -156,7 +145,7 @@ CPUStatePDP11.prototype.initRegs = function()
|
|||
this.regsAlt = [ // Alternate R0 - R5
|
||||
0, 0, 0, 0, 0, 0
|
||||
];
|
||||
this.regsAltStack = [ // Alternate R6 stack pointers (kernel, super, illegal, user)
|
||||
this.regsAltStack = [ // Alternate R6 stack pointers (KERNEL, SUPER, illegal, USER)
|
||||
0, 0, 0, 0
|
||||
];
|
||||
this.mmuMode = 0; // current memory management mode (see PDP11.MODE.KERNEL | SUPER | UNUSED | USER)
|
||||
|
|
@ -1029,19 +1018,6 @@ CPUStatePDP11.prototype.updateSubFlags = function(result, src, dst)
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* fault(addr)
|
||||
*
|
||||
* Memory interface for signaling alignment errors.
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
* @param {number} addr
|
||||
*/
|
||||
CPUStatePDP11.prototype.fault = function(addr)
|
||||
{
|
||||
this.trap(PDP11.TRAP.BUS_ERROR, addr);
|
||||
};
|
||||
|
||||
/**
|
||||
* panic(reason)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -587,12 +587,7 @@ if (DEBUGGER) {
|
|||
var b = 0xff;
|
||||
var addr = this.getAddr(dbgAddr, false, 1);
|
||||
if (addr !== PDP11.ADDR_INVALID) {
|
||||
this.nDisableMessages++;
|
||||
/*
|
||||
* TODO: We also need a Bus interface to disable accesses that could trigger a trap().
|
||||
*/
|
||||
b = this.bus.getByteDirect(addr);
|
||||
this.nDisableMessages--;
|
||||
if (inc) this.incAddr(dbgAddr, inc);
|
||||
}
|
||||
return b;
|
||||
|
|
@ -611,16 +606,7 @@ if (DEBUGGER) {
|
|||
var w = 0xffff;
|
||||
var addr = this.getAddr(dbgAddr, false, 2);
|
||||
if (addr !== PDP11.ADDR_INVALID) {
|
||||
this.nDisableMessages++;
|
||||
/*
|
||||
* TODO: We also need a Bus interface to disable accesses that could trigger a trap().
|
||||
*
|
||||
* NOTE: We don't care if the word address is aligned, because 1) we assume the user knows what
|
||||
* they're doing, and 2) the Bus simply ignores the low address bit anyway. Alignment checks are
|
||||
* performed by the CPU, not the Bus.
|
||||
*/
|
||||
w = this.bus.getWordDirect(addr);
|
||||
this.nDisableMessages--;
|
||||
if (inc) this.incAddr(dbgAddr, inc);
|
||||
}
|
||||
return w;
|
||||
|
|
@ -638,12 +624,7 @@ if (DEBUGGER) {
|
|||
{
|
||||
var addr = this.getAddr(dbgAddr, true, 1);
|
||||
if (addr !== PDP11.ADDR_INVALID) {
|
||||
this.nDisableMessages++;
|
||||
/*
|
||||
* TODO: We also need a Bus interface to disable accesses that could trigger a trap().
|
||||
*/
|
||||
this.bus.setByteDirect(addr, b);
|
||||
this.nDisableMessages--;
|
||||
if (inc) this.incAddr(dbgAddr, inc);
|
||||
this.cpu.updateCPU(true); // we set fForce to true in case video memory was the target
|
||||
}
|
||||
|
|
@ -661,16 +642,7 @@ if (DEBUGGER) {
|
|||
{
|
||||
var addr = this.getAddr(dbgAddr, true, 2);
|
||||
if (addr !== PDP11.ADDR_INVALID) {
|
||||
this.nDisableMessages++;
|
||||
/*
|
||||
* TODO: We also need a Bus interface to disable accesses that could trigger a trap().
|
||||
*
|
||||
* NOTE: We don't care if the word address is aligned, because 1) we assume the user knows what
|
||||
* they're doing, and 2) the Bus simply ignores the low address bit anyway. Alignment checks are
|
||||
* performed by the CPU, not the Bus.
|
||||
*/
|
||||
this.bus.setWordDirect(addr, w);
|
||||
this.nDisableMessages--;
|
||||
if (inc) this.incAddr(dbgAddr, inc);
|
||||
this.cpu.updateCPU(true); // we set fForce to true in case video memory was the target
|
||||
}
|
||||
|
|
@ -879,7 +851,7 @@ if (DEBUGGER) {
|
|||
if (!cPrev++) this.println("...");
|
||||
} else {
|
||||
typePrev = block.type;
|
||||
var sType = MemoryPDP11.TYPE.NAMES[typePrev];
|
||||
var sType = MemoryPDP11.TYPE_NAMES[typePrev];
|
||||
if (block) {
|
||||
this.println(str.toHex(block.id, 8) + " %" + str.toHex(i << this.bus.nBlockShift, 8) + " %%" + str.toHex(block.addr, 8) + " " + str.toHexWord(block.used) + " " + str.toHexWord(block.size) + " " + sType);
|
||||
}
|
||||
|
|
@ -1034,7 +1006,6 @@ if (DEBUGGER) {
|
|||
this.bitsMessage = this.bitsWarning = MessagesPDP11.WARN;
|
||||
this.sMessagePrev = null;
|
||||
this.aMessageBuffer = [];
|
||||
this.nDisableMessages = 0;
|
||||
/*
|
||||
* Internally, we use "key" instead of "keys", since the latter is a method on JavasScript objects,
|
||||
* but externally, we allow the user to specify "keys"; "kbd" is also allowed as shorthand for "keyboard".
|
||||
|
|
@ -1154,26 +1125,6 @@ if (DEBUGGER) {
|
|||
return s;
|
||||
};
|
||||
|
||||
/**
|
||||
* disableMessages(s)
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
*/
|
||||
DebuggerPDP11.prototype.disableMessages = function()
|
||||
{
|
||||
this.nDisableMessages++;
|
||||
};
|
||||
|
||||
/**
|
||||
* enableMessages(s)
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
*/
|
||||
DebuggerPDP11.prototype.enableMessages = function()
|
||||
{
|
||||
this.nDisableMessages--;
|
||||
};
|
||||
|
||||
/**
|
||||
* message(sMessage, fAddress)
|
||||
*
|
||||
|
|
@ -1183,8 +1134,6 @@ if (DEBUGGER) {
|
|||
*/
|
||||
DebuggerPDP11.prototype.message = function(sMessage, fAddress)
|
||||
{
|
||||
if (this.nDisableMessages) return;
|
||||
|
||||
if (fAddress) {
|
||||
sMessage += " @" + this.toStrAddr(this.newAddr(this.cpu.getPC()));
|
||||
}
|
||||
|
|
@ -1632,9 +1581,7 @@ if (DEBUGGER) {
|
|||
*/
|
||||
if (nState >= 0 && this.aaOpcodeCounts.length) {
|
||||
this.cOpcodes++;
|
||||
this.nDisableMessages++;
|
||||
var opCode = this.bus.getWordDirect(addr);
|
||||
this.nDisableMessages--;
|
||||
if (opCode != null) {
|
||||
var dbgAddr = this.aOpcodeHistory[this.iOpcodeHistory];
|
||||
this.setAddr(dbgAddr, cpu.getPC());
|
||||
|
|
@ -2741,9 +2688,8 @@ if (DEBUGGER) {
|
|||
/**
|
||||
* doDump(asArgs)
|
||||
*
|
||||
* The length parameter is interpreted as a number of bytes, in hex, which we convert to the appropriate number
|
||||
* of lines, because we always display whole lines. If the length is omitted/undefined, it defaults to 0x80 (128.)
|
||||
* bytes, which normally translates to 8 lines.
|
||||
* The length parameter is interpreted as a number of bytes (or words, or dwords) to dump, and it is
|
||||
* interpreted using the current base.
|
||||
*
|
||||
* @this {DebuggerPDP11}
|
||||
* @param {Array.<string>} asArgs (formerly sCmd, [sAddr], [sLen] and [sBytes])
|
||||
|
|
@ -2840,27 +2786,31 @@ if (DEBUGGER) {
|
|||
|
||||
var sDump = "";
|
||||
var size = (sCmd == "dd"? 4 : (sCmd == "dw"? 2 : 1));
|
||||
var cb = (size * len) || 128;
|
||||
var cLines = ((cb + 15) >> 4) || 1;
|
||||
var nBytes = (size * len) || 128;
|
||||
var nLines = ((nBytes + 15) >> 4) || 1;
|
||||
|
||||
while (cLines-- && cb > 0) {
|
||||
var data = 0, iByte = 0, i;
|
||||
while (nLines-- && nBytes > 0) {
|
||||
var data = 0, shift = 0, i;
|
||||
var sData = "", sChars = "";
|
||||
sAddr = this.toStrAddr(dbgAddr);
|
||||
/*
|
||||
* Dump 8 bytes per line when using base 8, and dump 16 bytes when using base 16 (or when dumping dwords)
|
||||
* Dump 8 bytes per line when using base 8, and dump 16 bytes when using base 16 (or when dumping dwords).
|
||||
*
|
||||
* And while we used to always call getByte() and assemble them into words or dwords as appropriate, I've
|
||||
* changed the logic below to honor "dw" by calling getWord(), since the Bus interfaces have been updated
|
||||
* to prevent generating traps due to to Debugger access of unaligned memory and/or undefined IOPAGE addresses.
|
||||
*/
|
||||
var nBytes = (size == 4? 16 : this.nBase);
|
||||
for (i = nBytes; i > 0 && cb > 0; i--) {
|
||||
var b = this.getByte(dbgAddr, 1);
|
||||
data |= (b << (iByte++ << 3));
|
||||
if (iByte == size) {
|
||||
for (i = (size == 4? 16 : this.nBase); i > 0 && nBytes > 0; i--) {
|
||||
var n, v = size == 2? this.getWord(dbgAddr, n = 2) : this.getByte(dbgAddr, n = 1);
|
||||
data |= (v << (shift << 3));
|
||||
shift += n;
|
||||
if (shift == size) {
|
||||
sData += this.toStrBase(data, size);
|
||||
sData += (size == 1? (i == 9? '-' : ' ') : " ");
|
||||
data = iByte = 0;
|
||||
data = shift = 0;
|
||||
}
|
||||
sChars += (b >= 32 && b < 128? String.fromCharCode(b) : '.');
|
||||
cb--;
|
||||
sChars += (v >= 32 && v < 128? String.fromCharCode(v) : '.');
|
||||
nBytes--;
|
||||
}
|
||||
if (sDump) sDump += '\n';
|
||||
sDump += sAddr + " " + sData + ((i == 0)? (' ' + sChars) : "");
|
||||
|
|
@ -3568,14 +3518,14 @@ if (DEBUGGER) {
|
|||
|
||||
if (n === undefined) n = 1;
|
||||
|
||||
var cb = 0x100;
|
||||
var nBytes = 0x100;
|
||||
if (sAddrEnd !== undefined) {
|
||||
|
||||
var dbgAddrEnd = this.parseAddr(sAddrEnd, true);
|
||||
if (!dbgAddrEnd || dbgAddrEnd.addr < dbgAddr.addr) return;
|
||||
|
||||
cb = dbgAddrEnd.addr - dbgAddr.addr;
|
||||
if (!DEBUG && cb > 0x100) {
|
||||
nBytes = dbgAddrEnd.addr - dbgAddr.addr;
|
||||
if (!DEBUG && nBytes > 0x100) {
|
||||
/*
|
||||
* Limiting the amount of disassembled code to 256 bytes in non-DEBUG builds is partly to
|
||||
* prevent the user from wedging the browser by dumping too many lines, but also a recognition
|
||||
|
|
@ -3587,10 +3537,10 @@ if (DEBUGGER) {
|
|||
n = -1;
|
||||
}
|
||||
|
||||
var cLines = 0;
|
||||
var nLines = 0;
|
||||
var sInstruction;
|
||||
|
||||
while (cb > 0 && n--) {
|
||||
while (nBytes > 0 && n--) {
|
||||
|
||||
var nSequence = (this.isBusy(false) || this.nStep)? this.nCycles : null;
|
||||
var sComment = (nSequence != null? "cycles" : null);
|
||||
|
|
@ -3599,7 +3549,7 @@ if (DEBUGGER) {
|
|||
var addr = dbgAddr.addr; // we snap dbgAddr.addr *after* calling findSymbol(), which re-evaluates it
|
||||
|
||||
if (aSymbol[0] && n) {
|
||||
if (!cLines && n || aSymbol[0].indexOf('+') < 0) {
|
||||
if (!nLines && n || aSymbol[0].indexOf('+') < 0) {
|
||||
var sLabel = aSymbol[0] + ':';
|
||||
if (aSymbol[2]) sLabel += ' ' + aSymbol[2];
|
||||
this.println(sLabel);
|
||||
|
|
@ -3615,8 +3565,8 @@ if (DEBUGGER) {
|
|||
|
||||
this.println(sInstruction);
|
||||
this.dbgAddrNextCode = dbgAddr;
|
||||
cb -= dbgAddr.addr - addr;
|
||||
cLines++;
|
||||
nBytes -= dbgAddr.addr - addr;
|
||||
nLines++;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,10 +33,12 @@
|
|||
"use strict";
|
||||
|
||||
if (NODE) {
|
||||
var web = require("../../shared/lib/weblib");
|
||||
var Component = require("../../shared/lib/component");
|
||||
var State = require("../../shared/lib/state");
|
||||
var BusPDP11 = require("./bus");
|
||||
var str = require("../../shared/lib/strlib");
|
||||
var web = require("../../shared/lib/weblib");
|
||||
var Component = require("../../shared/lib/component");
|
||||
var State = require("../../shared/lib/state");
|
||||
var BusPDP11 = require("./bus");
|
||||
var MessagesPDP11 = require("./messages");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -55,7 +57,7 @@ if (NODE) {
|
|||
*/
|
||||
function DevicePDP11(parmsDevice)
|
||||
{
|
||||
Component.call(this, "Device", parmsDevice, DevicePDP11);
|
||||
Component.call(this, "Device", parmsDevice, DevicePDP11, MessagesPDP11.DEVICE);
|
||||
|
||||
this.display = {
|
||||
data: 0,
|
||||
|
|
@ -981,6 +983,20 @@ DevicePDP11.prototype.writePSW = function(data, addr)
|
|||
this.cpu.opFlags |= PDP11.OPFLAG.NO_FLAGS;
|
||||
};
|
||||
|
||||
/**
|
||||
* writeIgnored(data, addr)
|
||||
*
|
||||
* @this {DevicePDP11}
|
||||
* @param {number} data
|
||||
* @param {number} addr
|
||||
*/
|
||||
DevicePDP11.prototype.writeIgnored = function(data, addr)
|
||||
{
|
||||
if (this.messageEnabled()) {
|
||||
this.printMessage("writeIgnored(" + str.toOct(addr) + "): " + str.toOct(data), true, true);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* kw11_interrupt()
|
||||
*
|
||||
|
|
@ -1023,28 +1039,28 @@ DevicePDP11.UNIBUS_IOTABLE = {
|
|||
[PDP11.UNIBUS.MMR3]: /* 172516 */ [null, null, DevicePDP11.prototype.readMMR3, DevicePDP11.prototype.writeMMR3, "MMR3"],
|
||||
[PDP11.UNIBUS.LKS]: /* 177546 */ [null, null, DevicePDP11.prototype.readLKS, DevicePDP11.prototype.writeLKS, "LKS"],
|
||||
[PDP11.UNIBUS.MMR0]: /* 177572 */ [null, null, DevicePDP11.prototype.readMMR0, DevicePDP11.prototype.writeMMR0, "MMR0"],
|
||||
[PDP11.UNIBUS.MMR1]: /* 177574 */ [null, null, DevicePDP11.prototype.readMMR1, null, "MMR1"],
|
||||
[PDP11.UNIBUS.MMR2]: /* 177576 */ [null, null, DevicePDP11.prototype.readMMR2, null, "MMR2"],
|
||||
[PDP11.UNIBUS.MMR1]: /* 177574 */ [null, null, DevicePDP11.prototype.readMMR1, DevicePDP11.prototype.writeIgnored, "MMR1"],
|
||||
[PDP11.UNIBUS.MMR2]: /* 177576 */ [null, null, DevicePDP11.prototype.readMMR2, DevicePDP11.prototype.writeIgnored, "MMR2"],
|
||||
[PDP11.UNIBUS.UISDR0]: /* 177600 */ [null, null, DevicePDP11.prototype.readUISDR, DevicePDP11.prototype.writeUISDR, "UISDR"],
|
||||
[PDP11.UNIBUS.UDSDR0]: /* 177620 */ [null, null, DevicePDP11.prototype.readUDSDR, DevicePDP11.prototype.writeUDSDR, "UDSDR"],
|
||||
[PDP11.UNIBUS.UISAR0]: /* 177640 */ [null, null, DevicePDP11.prototype.readUISAR, DevicePDP11.prototype.writeUISAR, "UISAR"],
|
||||
[PDP11.UNIBUS.UDSAR0]: /* 177660 */ [null, null, DevicePDP11.prototype.readUDSAR, DevicePDP11.prototype.writeUDSAR, "UDSAR"],
|
||||
[PDP11.UNIBUS.R0SET0]: /* 177700 */ [DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R0SET0"],
|
||||
[PDP11.UNIBUS.R1SET0]: /* 177701 */ [DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R1SET0"],
|
||||
[PDP11.UNIBUS.R2SET0]: /* 177702 */ [DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R2SET0"],
|
||||
[PDP11.UNIBUS.R3SET0]: /* 177703 */ [DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R3SET0"],
|
||||
[PDP11.UNIBUS.R4SET0]: /* 177704 */ [DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R4SET0"],
|
||||
[PDP11.UNIBUS.R5SET0]: /* 177705 */ [DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R5SET0"],
|
||||
[PDP11.UNIBUS.R6KERNEL]:/* 177706 */ [DevicePDP11.prototype.readR6KERNEL,DevicePDP11.prototype.writeR6KERNEL,DevicePDP11.prototype.readR6KERNEL, DevicePDP11.prototype.writeR6KERNEL,"R6KERNEL"],
|
||||
[PDP11.UNIBUS.R7KERNEL]:/* 177707 */ [DevicePDP11.prototype.readR7KERNEL,DevicePDP11.prototype.writeR7KERNEL,DevicePDP11.prototype.readR7KERNEL, DevicePDP11.prototype.writeR7KERNEL,"R7KERNEL"],
|
||||
[PDP11.UNIBUS.R0SET1]: /* 177710 */ [DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R0SET1"],
|
||||
[PDP11.UNIBUS.R1SET1]: /* 177711 */ [DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R1SET1"],
|
||||
[PDP11.UNIBUS.R2SET1]: /* 177712 */ [DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R2SET1"],
|
||||
[PDP11.UNIBUS.R3SET1]: /* 177713 */ [DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R3SET1"],
|
||||
[PDP11.UNIBUS.R4SET1]: /* 177714 */ [DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R4SET1"],
|
||||
[PDP11.UNIBUS.R5SET1]: /* 177715 */ [DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R5SET1"],
|
||||
[PDP11.UNIBUS.R6SUPER]: /* 177716 */ [DevicePDP11.prototype.readR6SUPER, DevicePDP11.prototype.writeR6SUPER, DevicePDP11.prototype.readR6SUPER, DevicePDP11.prototype.writeR6SUPER, "R6SUPER"],
|
||||
[PDP11.UNIBUS.R6USER]: /* 177717 */ [DevicePDP11.prototype.readR6USER, DevicePDP11.prototype.writeR6USER, DevicePDP11.prototype.readR6USER, DevicePDP11.prototype.writeR6USER, "R6USER"],
|
||||
[PDP11.UNIBUS.R0SET0]: /* 177700 */ [null, null, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R0SET0"],
|
||||
[PDP11.UNIBUS.R1SET0]: /* 177701 */ [null, null, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R1SET0"],
|
||||
[PDP11.UNIBUS.R2SET0]: /* 177702 */ [null, null, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R2SET0"],
|
||||
[PDP11.UNIBUS.R3SET0]: /* 177703 */ [null, null, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R3SET0"],
|
||||
[PDP11.UNIBUS.R4SET0]: /* 177704 */ [null, null, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R4SET0"],
|
||||
[PDP11.UNIBUS.R5SET0]: /* 177705 */ [null, null, DevicePDP11.prototype.readRSET0, DevicePDP11.prototype.writeRSET0, "R5SET0"],
|
||||
[PDP11.UNIBUS.R6KERNEL]:/* 177706 */ [null, null, DevicePDP11.prototype.readR6KERNEL,DevicePDP11.prototype.writeR6KERNEL,"R6KERNEL"],
|
||||
[PDP11.UNIBUS.R7KERNEL]:/* 177707 */ [null, null, DevicePDP11.prototype.readR7KERNEL,DevicePDP11.prototype.writeR7KERNEL,"R7KERNEL"],
|
||||
[PDP11.UNIBUS.R0SET1]: /* 177710 */ [null, null, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R0SET1"],
|
||||
[PDP11.UNIBUS.R1SET1]: /* 177711 */ [null, null, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R1SET1"],
|
||||
[PDP11.UNIBUS.R2SET1]: /* 177712 */ [null, null, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R2SET1"],
|
||||
[PDP11.UNIBUS.R3SET1]: /* 177713 */ [null, null, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R3SET1"],
|
||||
[PDP11.UNIBUS.R4SET1]: /* 177714 */ [null, null, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R4SET1"],
|
||||
[PDP11.UNIBUS.R5SET1]: /* 177715 */ [null, null, DevicePDP11.prototype.readRSET1, DevicePDP11.prototype.writeRSET1, "R5SET1"],
|
||||
[PDP11.UNIBUS.R6SUPER]: /* 177716 */ [null, null, DevicePDP11.prototype.readR6SUPER, DevicePDP11.prototype.writeR6SUPER, "R6SUPER"],
|
||||
[PDP11.UNIBUS.R6USER]: /* 177717 */ [null, null, DevicePDP11.prototype.readR6USER, DevicePDP11.prototype.writeR6USER, "R6USER"],
|
||||
[PDP11.UNIBUS.LAERR]: /* 177740 */ [null, null, DevicePDP11.prototype.readCTRL, DevicePDP11.prototype.writeCTRL, "CTRL", PDP11.MODEL_1170],
|
||||
[PDP11.UNIBUS.LSIZE]: /* 177760 */ [null, null, DevicePDP11.prototype.readSIZE, DevicePDP11.prototype.writeSIZE, "LSIZE", PDP11.MODEL_1170],
|
||||
[PDP11.UNIBUS.HSIZE]: /* 177762 */ [null, null, DevicePDP11.prototype.readSIZE, DevicePDP11.prototype.writeSIZE, "HSIZE", PDP11.MODEL_1170],
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ var littleEndian = (TYPEDARRAYS? (function() {
|
|||
})() : false);
|
||||
|
||||
/**
|
||||
* MemoryPDP11(cpu, addr, used, size, type, controller)
|
||||
* MemoryPDP11(bus, 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.nBlockSize; however,
|
||||
|
|
@ -89,17 +89,17 @@ var littleEndian = (TYPEDARRAYS? (function() {
|
|||
* is available).
|
||||
*
|
||||
* @constructor
|
||||
* @param {CPUStatePDP11} cpu
|
||||
* @param {BusPDP11} bus
|
||||
* @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 MemoryPDP11.TYPE constants (default is MemoryPDP11.TYPE.NONE)
|
||||
* @param {Object} [controller] is an optional memory controller component
|
||||
*/
|
||||
function MemoryPDP11(cpu, addr, used, size, type, controller)
|
||||
function MemoryPDP11(bus, addr, used, size, type, controller)
|
||||
{
|
||||
var i;
|
||||
this.cpu = cpu;
|
||||
this.bus = bus;
|
||||
this.id = (MemoryPDP11.idBlock += 2);
|
||||
this.adw = null;
|
||||
this.offset = 0;
|
||||
|
|
@ -209,10 +209,10 @@ MemoryPDP11.TYPE = {
|
|||
RAM: 1,
|
||||
ROM: 2,
|
||||
VIDEO: 3,
|
||||
CONTROLLER: 4,
|
||||
COLORS: ["black", "blue", "green", "cyan"],
|
||||
NAMES: ["NONE", "RAM", "ROM", "VID", "H/W"]
|
||||
CONTROLLER: 4
|
||||
};
|
||||
MemoryPDP11.TYPE_COLORS = ["black", "blue", "green", "cyan"];
|
||||
MemoryPDP11.TYPE_NAMES = ["NONE", "RAM", "ROM", "VID", "H/W"];
|
||||
|
||||
/*
|
||||
* Last used block ID (used for debugging only)
|
||||
|
|
@ -469,7 +469,7 @@ MemoryPDP11.prototype = {
|
|||
* @param {string} sMessage
|
||||
*/
|
||||
printAddr: function(sMessage) {
|
||||
if (DEBUG && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEM)) {
|
||||
if (DEBUG && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEMORY)) {
|
||||
this.dbg.printMessage(sMessage + ' ' + (this.addr != null? ('@' + this.dbg.toStrBase(this.addr)) : '#' + this.id), true);
|
||||
}
|
||||
},
|
||||
|
|
@ -557,7 +557,7 @@ MemoryPDP11.prototype = {
|
|||
* @return {number}
|
||||
*/
|
||||
readNone: function readNone(off, addr) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEM) /* && !off */) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEMORY) /* && !off */) {
|
||||
this.dbg.printMessage("attempt to read invalid block %" + str.toHex(this.addr), true);
|
||||
this.dbg.stopCPU();
|
||||
}
|
||||
|
|
@ -572,7 +572,7 @@ MemoryPDP11.prototype = {
|
|||
* @param {number} addr
|
||||
*/
|
||||
writeNone: function writeNone(off, v, addr) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEM) /* && !off */) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEMORY) /* && !off */) {
|
||||
this.dbg.printMessage("attempt to write " + str.toHexWord(v) + " to invalid block %" + str.toHex(this.addr), true);
|
||||
this.dbg.stopCPU();
|
||||
}
|
||||
|
|
@ -624,7 +624,7 @@ MemoryPDP11.prototype = {
|
|||
*/
|
||||
readWordMemory: function readWordMemory(off, addr) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
this.bus.fault(addr);
|
||||
}
|
||||
if (BYTEARRAYS) {
|
||||
return this.ab[off] | (this.ab[off + 1] << 8);
|
||||
|
|
@ -668,7 +668,7 @@ MemoryPDP11.prototype = {
|
|||
*/
|
||||
writeWordMemory: function writeWordMemory(off, w, addr) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
this.bus.fault(addr);
|
||||
}
|
||||
if (BYTEARRAYS) {
|
||||
this.ab[off] = (w & 0xff);
|
||||
|
|
@ -763,7 +763,7 @@ MemoryPDP11.prototype = {
|
|||
*/
|
||||
readByteLE: function readByteLE(off, addr) {
|
||||
var b = this.ab[off];
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEM)) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEMORY)) {
|
||||
this.dbg.printMessage("Memory.readByte(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(b), true);
|
||||
}
|
||||
return b;
|
||||
|
|
@ -778,7 +778,7 @@ MemoryPDP11.prototype = {
|
|||
*/
|
||||
readWordBE: function readWordBE(off, addr) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
this.bus.fault(addr);
|
||||
}
|
||||
return this.dv.getUint16(off, true);
|
||||
},
|
||||
|
|
@ -793,7 +793,7 @@ MemoryPDP11.prototype = {
|
|||
readWordLE: function readWordLE(off, addr) {
|
||||
var w;
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
this.bus.fault(addr);
|
||||
}
|
||||
/*
|
||||
* TODO: For non-WORDBUS machines, it remains to be seen if there's any advantage to checking the offset
|
||||
|
|
@ -804,7 +804,7 @@ MemoryPDP11.prototype = {
|
|||
} else {
|
||||
w = this.ab[off] | (this.ab[off+1] << 8);
|
||||
}
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEM)) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEMORY)) {
|
||||
this.dbg.printMessage("Memory.readWord(" + this.dbg.toStrBase(addr) + "): " + this.dbg.toStrBase(w), true);
|
||||
}
|
||||
return w;
|
||||
|
|
@ -832,7 +832,7 @@ MemoryPDP11.prototype = {
|
|||
writeByteLE: function writeByteLE(off, b, addr) {
|
||||
this.ab[off] = b;
|
||||
this.fDirty = true;
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEM)) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEMORY)) {
|
||||
this.dbg.printMessage("Memory.writeByte(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(b) + ")", true);
|
||||
}
|
||||
},
|
||||
|
|
@ -846,7 +846,7 @@ MemoryPDP11.prototype = {
|
|||
*/
|
||||
writeWordBE: function writeWordBE(off, w, addr) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
this.bus.fault(addr);
|
||||
}
|
||||
this.dv.setUint16(off, w, true);
|
||||
this.fDirty = true;
|
||||
|
|
@ -861,7 +861,7 @@ MemoryPDP11.prototype = {
|
|||
*/
|
||||
writeWordLE: function writeWordLE(off, w, addr) {
|
||||
if (PDP11.MEMFAULT && (off & 0x1)) {
|
||||
this.cpu.fault(addr);
|
||||
this.bus.fault(addr);
|
||||
}
|
||||
/*
|
||||
* TODO: For non-WORDBUS machines, it remains to be seen if there's any advantage to checking the offset
|
||||
|
|
@ -874,7 +874,7 @@ MemoryPDP11.prototype = {
|
|||
this.ab[off+1] = w >> 8;
|
||||
}
|
||||
this.fDirty = true;
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEM)) {
|
||||
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.MEMORY)) {
|
||||
this.dbg.printMessage("Memory.writeWord(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(w) + ")", true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ var MessagesPDP11 = {
|
|||
CPU: 0x00000001,
|
||||
TRAP: 0x00000010,
|
||||
BUS: 0x00000040,
|
||||
MEM: 0x00000080,
|
||||
MEMORY: 0x00000080,
|
||||
DEVICE: 0x00000100,
|
||||
KEYBOARD: 0x00010000,
|
||||
KEYS: 0x00020000,
|
||||
DISK: 0x00200000,
|
||||
|
|
@ -67,7 +68,8 @@ MessagesPDP11.CATEGORIES = {
|
|||
"cpu": MessagesPDP11.CPU,
|
||||
"trap": MessagesPDP11.TRAP,
|
||||
"bus": MessagesPDP11.BUS,
|
||||
"mem": MessagesPDP11.MEM,
|
||||
"memory": MessagesPDP11.MEMORY,
|
||||
"device": MessagesPDP11.DEVICE,
|
||||
"keyboard": MessagesPDP11.KEYBOARD, // "kbd" is also allowed as shorthand for "keyboard"; see doMessages()
|
||||
"key": MessagesPDP11.KEYS, // using "key" instead of "keys", since the latter is a method on JavasScript objects
|
||||
"disk": MessagesPDP11.DISK,
|
||||
|
|
|
|||
|
|
@ -83,6 +83,24 @@ RAMPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
this.bus = bus;
|
||||
this.cpu = cpu;
|
||||
this.dbg = dbg;
|
||||
this.initRAM();
|
||||
};
|
||||
|
||||
/**
|
||||
* initRAM()
|
||||
*
|
||||
* @this {RAMPDP11}
|
||||
*/
|
||||
RAMPDP11.prototype.initRAM = function()
|
||||
{
|
||||
if (!this.fAllocated && this.sizeRAM) {
|
||||
if (this.bus.addMemory(this.addrRAM, this.sizeRAM, MemoryPDP11.TYPE.RAM)) {
|
||||
this.fAllocated = true;
|
||||
}
|
||||
}
|
||||
if (!this.fAllocated) {
|
||||
Component.error("No RAM allocated");
|
||||
}
|
||||
this.setReady();
|
||||
};
|
||||
|
||||
|
|
@ -96,15 +114,12 @@ RAMPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
*/
|
||||
RAMPDP11.prototype.powerUp = function(data, fRepower)
|
||||
{
|
||||
if (!fRepower) {
|
||||
/*
|
||||
* The Computer powers up the CPU last, at which point CPUState state is restored,
|
||||
* which includes the Bus state, and since we use the Bus to allocate all our memory,
|
||||
* memory contents are already restored for us, so we don't need the usual restore
|
||||
* logic. We just need to call reset(), to allocate memory for the RAM.
|
||||
*/
|
||||
this.reset();
|
||||
}
|
||||
/*
|
||||
* The Computer powers up the CPU last, at which point CPUState state is restored,
|
||||
* which includes the Bus state, and since we use the Bus to allocate all our memory,
|
||||
* memory contents are already restored for us, so we don't need the usual restore
|
||||
* logic.
|
||||
*/
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
@ -124,7 +139,7 @@ RAMPDP11.prototype.powerDown = function(fSave, fShutdown)
|
|||
* our memory, memory contents are already saved for us, so we don't need the usual
|
||||
* save logic.
|
||||
*/
|
||||
return (fSave)? this.save() : true;
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -134,41 +149,9 @@ RAMPDP11.prototype.powerDown = function(fSave, fShutdown)
|
|||
*/
|
||||
RAMPDP11.prototype.reset = function()
|
||||
{
|
||||
if (!this.fAllocated && this.sizeRAM) {
|
||||
if (this.bus.addMemory(this.addrRAM, this.sizeRAM, MemoryPDP11.TYPE.RAM)) {
|
||||
this.fAllocated = true;
|
||||
}
|
||||
}
|
||||
if (!this.fAllocated) {
|
||||
Component.error("No RAM allocated");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* save()
|
||||
*
|
||||
* This implements save support for the RAMPDP11 component.
|
||||
*
|
||||
* @this {RAMPDP11}
|
||||
* @return {Object}
|
||||
*/
|
||||
RAMPDP11.prototype.save = function()
|
||||
{
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* restore(data)
|
||||
*
|
||||
* This implements restore support for the RAMPDP11 component.
|
||||
*
|
||||
* @this {RAMPDP11}
|
||||
* @param {Object} data
|
||||
* @return {boolean} true if successful, false if failure
|
||||
*/
|
||||
RAMPDP11.prototype.restore = function(data)
|
||||
{
|
||||
return true;
|
||||
/*
|
||||
* If you want to zero RAM on reset, then this would be a good place to do it.
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ Component.subclass(ROMPDP11);
|
|||
* ROM contents, so in that case, having a reset() function that restores the original ROM data
|
||||
* might be useful; then again, it might not, depending on what you're trying to debug.
|
||||
*
|
||||
* If we do add reset(), then we'll want to change copyROM() to hang onto the original
|
||||
* If we do add reset(), then we'll want to change initROM() to hang onto the original
|
||||
* ROM data; currently, we release it after copying it into the read-only memory allocated
|
||||
* via bus.addMemory().
|
||||
*/
|
||||
|
|
@ -139,7 +139,7 @@ ROMPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
this.bus = bus;
|
||||
this.cpu = cpu;
|
||||
this.dbg = dbg;
|
||||
this.copyROM();
|
||||
this.initROM();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -266,11 +266,11 @@ ROMPDP11.prototype.doneLoad = function(sURL, sROMData, nErrorCode)
|
|||
this.abROM[i] = str.parseInt(asHexData[i], 16);
|
||||
}
|
||||
}
|
||||
this.copyROM();
|
||||
this.initROM();
|
||||
};
|
||||
|
||||
/**
|
||||
* copyROM()
|
||||
* initROM()
|
||||
*
|
||||
* This function is called by both initBus() and doneLoad(), but it cannot copy the the ROM data into place
|
||||
* until after initBus() has received the Bus component AND doneLoad() has received the abROM data. When both
|
||||
|
|
@ -278,7 +278,7 @@ ROMPDP11.prototype.doneLoad = function(sURL, sROMData, nErrorCode)
|
|||
*
|
||||
* @this {ROMPDP11}
|
||||
*/
|
||||
ROMPDP11.prototype.copyROM = function()
|
||||
ROMPDP11.prototype.initROM = function()
|
||||
{
|
||||
if (!this.isReady()) {
|
||||
if (!this.sFilePath) {
|
||||
|
|
@ -341,9 +341,7 @@ ROMPDP11.prototype.addROM = function(addr)
|
|||
if (DEBUG) this.log("addROM(): copying ROM to " + str.toHexLong(addr) + " (" + str.toHexLong(this.abROM.length) + " bytes)");
|
||||
var i;
|
||||
for (i = 0; i < this.abROM.length; i++) {
|
||||
if (DEBUGGER && this.dbg) this.dbg.disableMessages();
|
||||
this.bus.setByteDirect(addr + i, this.abROM[i]);
|
||||
if (DEBUGGER && this.dbg) this.dbg.enableMessages();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
}
|
||||
.pcjs-label {
|
||||
font-size: small;
|
||||
line-height: 19px;
|
||||
line-height: 20px;
|
||||
vertical-align: middle;
|
||||
float: left;
|
||||
font-family: Monaco, "Lucida Console", monospace;
|
||||
|
|
@ -52,14 +52,14 @@
|
|||
font-family: Monaco, "Lucida Console", monospace;
|
||||
font-size: small;
|
||||
text-align: center;
|
||||
line-height: 19px;
|
||||
line-height: 20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.pcjs-register {
|
||||
font-family: Monaco, "Lucida Console", monospace;
|
||||
font-size: small;
|
||||
text-align: center;
|
||||
line-height: 19px;
|
||||
line-height: 20px;
|
||||
vertical-align: middle;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
|
@ -101,6 +101,18 @@
|
|||
line-height: 34px; /* the equivalent of "vertical-align: middle" for single-line elements */
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.pcjs-panel-group {
|
||||
color: #ffffff;
|
||||
background-color: #404040;
|
||||
}
|
||||
.pcjs-tripled-label {
|
||||
text-align: right;
|
||||
padding: 8px;
|
||||
}
|
||||
.pcjs-ledpad {
|
||||
line-height: 32px;
|
||||
background-color: #000000;
|
||||
}
|
||||
.pcjs-led {
|
||||
float: left;
|
||||
width: 8px;
|
||||
|
|
@ -108,19 +120,18 @@
|
|||
margin: 4px;
|
||||
border: 1px solid black;
|
||||
text-align: center;
|
||||
line-height: 19px; /* the equivalent of "vertical-align: middle" for single-line elements */
|
||||
vertical-align: middle;
|
||||
background-color: #000000;
|
||||
}
|
||||
.pcjs-rled {
|
||||
float: left;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
margin: 4px;
|
||||
border: 1px solid black;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
line-height: 19px; /* the equivalent of "vertical-align: middle" for single-line elements */
|
||||
background-color: #000000;
|
||||
vertical-align: middle;
|
||||
background-color: #ff0000;
|
||||
}
|
||||
.pcjs-screen {
|
||||
clear: both;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
<!-- author="Jeff Parsons (@jeffpar)" website="http://www.pcjs.org/" created="2012-05-05" modified="2016-04-15" license="http://www.gnu.org/licenses/gpl.html" -->
|
||||
<!DOCTYPE xsl:stylesheet [
|
||||
<!-- XSLT understands these entities only: lt, gt, apos, quot, and amp. Other required entities may be defined below (see http://www.pcjs.org/modules/shared/templates/entities.dtd). -->
|
||||
<!ENTITY nbsp " "> <!ENTITY ne "≠"> <!ENTITY le "≤"> <!ENTITY ge "≥">
|
||||
]>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
|
||||
|
|
@ -331,6 +332,7 @@
|
|||
<xsl:when test="@pos = 'center'">margin:0 auto;</xsl:when>
|
||||
<xsl:when test="@pos">position:<xsl:value-of select="@pos"/>;</xsl:when>
|
||||
<xsl:when test="$left != '' or $top != ''">position:relative;</xsl:when>
|
||||
<xsl:when test="@container">text-align:<xsl:value-of select="@container"/>;</xsl:when>
|
||||
<xsl:otherwise><xsl:if test="$left = ''">float:left;</xsl:if></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
|
@ -412,7 +414,7 @@
|
|||
</form>
|
||||
</xsl:when>
|
||||
<xsl:when test="@type = 'led' or @type = 'rled'">
|
||||
<div class="{$APPCLASS}-binding {$CSSCLASS}-{@type}" data-value="{{{$type},{$binding}}}"><xsl:value-of select="."/></div>
|
||||
<div class="{$APPCLASS}-binding {$CSSCLASS}-{@type}" data-value="{{{$type},{$binding}}}" style="display:inline-block;"><xsl:value-of select="."/></div>
|
||||
</xsl:when>
|
||||
<xsl:when test="@type = 'separator'">
|
||||
<hr/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue