Lots of memory interface cleanup; still can't boot RSTS/E though....

This commit is contained in:
Jeff Parsons 2016-11-29 14:48:26 -08:00 committed by Jeff Parsons
commit cacff66983
13 changed files with 704 additions and 676 deletions

View file

@ -127,7 +127,6 @@ function BusPDP11(parmsBus, cpu, dbg)
this.fIOBreakAll = false;
this.nDisableFaults = 0;
this.fFault = false;
this.cbRAM = 0;
/*
* Array of RESET notification handlers registered by Device components.
@ -669,9 +668,6 @@ BusPDP11.prototype.addMemory = function(addr, size, type, controller)
}
if (sizeLeft <= 0) {
if (type == MemoryPDP11.TYPE.RAM) {
this.cbRAM += size;
}
this.status((size >> 10) + "Kb " + MemoryPDP11.TYPE_NAMES[type] + " at " + str.toOct(addr));
return true;
}
@ -914,7 +910,6 @@ BusPDP11.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
*/
BusPDP11.prototype.getByte = function(addr)
{
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.cpu.mapUnibus(addr);
return this.aMemBlocks[(addr & this.nMemMask) >>> this.nBlockShift].readByte(addr & this.nBlockLimit, addr);
};
@ -933,7 +928,7 @@ BusPDP11.prototype.getBlockDirect = function(addr)
/**
* getByteDirect(addr)
*
* This is useful for the Debugger and other components that want to access physical memory without side-effects.
* This is used for device I/O and Debugger physical memory requests, not the CPU.
*
* @this {BusPDP11}
* @param {number} addr is a physical address
@ -943,7 +938,6 @@ BusPDP11.prototype.getByteDirect = function(addr)
{
this.fFault = false;
this.nDisableFaults++;
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.cpu.mapUnibus(addr);
var b = this.getBlockDirect(addr).readByteDirect(addr & this.nBlockLimit, addr);
this.nDisableFaults--;
return b;
@ -958,7 +952,6 @@ BusPDP11.prototype.getByteDirect = function(addr)
*/
BusPDP11.prototype.getWord = function(addr)
{
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.cpu.mapUnibus(addr);
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
@ -970,7 +963,7 @@ BusPDP11.prototype.getWord = function(addr)
/**
* getWordDirect(addr)
*
* This is useful for the Debugger and other components that want to bypass getWord() breakpoint detection.
* This is used for device I/O and Debugger physical memory requests, not the CPU.
*
* @this {BusPDP11}
* @param {number} addr is a physical address
@ -981,7 +974,6 @@ BusPDP11.prototype.getWordDirect = function(addr)
var w;
this.fFault = false;
this.nDisableFaults++;
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.cpu.mapUnibus(addr);
var off = addr & this.nBlockLimit;
var block = this.getBlockDirect(addr);
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
@ -1002,15 +994,13 @@ BusPDP11.prototype.getWordDirect = function(addr)
*/
BusPDP11.prototype.setByte = function(addr, b)
{
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.cpu.mapUnibus(addr);
this.aMemBlocks[(addr & this.nMemMask) >>> this.nBlockShift].writeByte(addr & this.nBlockLimit, b & 0xff, addr);
};
/**
* setByteDirect(addr, b)
*
* This is useful for the Debugger and other components that want to bypass breakpoint detection AND read-only
* memory protection (for example, this is an interface the ROM component could use to initialize ROM contents).
* This is used for device I/O and Debugger physical memory requests, not the CPU.
*
* @this {BusPDP11}
* @param {number} addr is a physical address
@ -1020,7 +1010,6 @@ BusPDP11.prototype.setByteDirect = function(addr, b)
{
this.fFault = false;
this.nDisableFaults++;
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.cpu.mapUnibus(addr);
this.getBlockDirect(addr).writeByteDirect(addr & this.nBlockLimit, b & 0xff, addr);
this.nDisableFaults--;
};
@ -1034,7 +1023,6 @@ BusPDP11.prototype.setByteDirect = function(addr, b)
*/
BusPDP11.prototype.setWord = function(addr, w)
{
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.cpu.mapUnibus(addr);
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nMemMask) >>> this.nBlockShift;
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
@ -1048,8 +1036,7 @@ BusPDP11.prototype.setWord = function(addr, w)
/**
* setWordDirect(addr, w)
*
* This is useful for the Debugger and other components that want to bypass breakpoint detection AND read-only
* memory protection (for example, this is an interface the ROM component could use to initialize ROM contents).
* This is used for device I/O and Debugger physical memory requests, not the CPU.
*
* @this {BusPDP11}
* @param {number} addr is a physical address
@ -1059,7 +1046,6 @@ BusPDP11.prototype.setWordDirect = function(addr, w)
{
this.fFault = false;
this.nDisableFaults++;
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.cpu.mapUnibus(addr);
var off = addr & this.nBlockLimit;
var block = this.getBlockDirect(addr);
if (!PDP11.WORDBUS && off == this.nBlockLimit) {
@ -1192,24 +1178,22 @@ BusPDP11.prototype.restoreMemory = function(a)
};
/**
* getMemorySize(type)
*
* NOTE: The original pdp11.js defined a constant named MAX_MEMORY equal to UNIBUS_22BIT - 16384,
* where UNIBUS_22BIT is 4Mb less 256Kb, from which it then subtracted another 16Kb "for BSD 2.9 boot."
* getMemoryLimit(type)
*
* @this {BusPDP11}
* @param {number} type is one of the MemoryPDP11.TYPE constants (only RAM is currently supported)
* @return {number} (size of initial allocation, in bytes)
* @param {number} type is one of the MemoryPDP11.TYPE constants
* @return {number} (the limiting address of the specified memory type, zero if none)
*/
BusPDP11.prototype.getMemorySize = function(type)
BusPDP11.prototype.getMemoryLimit = function(type)
{
var cb = 0;
switch(type) {
case MemoryPDP11.TYPE.RAM:
cb = this.cbRAM;
break;
var addr = 0;
for (var iBlock = 0; iBlock < this.aBusBlocks.length; iBlock++) {
var block = this.aBusBlocks[iBlock];
if (block.type == type) {
addr = block.addr + block.used;
}
}
return cb;
return addr;
};
/**

View file

@ -832,7 +832,6 @@ PDP11.opBPL = function(opCode)
PDP11.opBPT = function(opCode)
{
this.trap(PDP11.TRAP.BPT, 0, PDP11.REASON.OPCODE);
this.nStepCycles -= (4 + 1);
};
/**
@ -1106,7 +1105,7 @@ PDP11.opDIV = function(opCode)
PDP11.opEMT = function(opCode)
{
this.trap(PDP11.TRAP.EMT, 0, PDP11.REASON.OPCODE);
this.nStepCycles -= (22 + 3);
this.nStepCycles -= (22 + 3 - 5);
};
/**
@ -1206,7 +1205,7 @@ PDP11.opINCB = function(opCode)
PDP11.opIOT = function(opCode)
{
this.trap(PDP11.TRAP.IOT, 0, PDP11.REASON.OPCODE);
this.nStepCycles -= (22 + 3);
this.nStepCycles -= (22 + 3 - 5);
};
PDP11.JMP_CYCLES = [
@ -1789,7 +1788,6 @@ PDP11.opSXT = function(opCode)
PDP11.opTRAP = function(opCode)
{
this.trap(PDP11.TRAP.TRAP, 0, PDP11.REASON.OPCODE);
this.nStepCycles -= (4 + 1);
};
/**

View file

@ -216,7 +216,7 @@ CPUStatePDP11.prototype.initRegs = function()
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], // mode 2 (not used)
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] // USER (8 UIPDR regs followed by 8 UDPDR regs)
];
this.unibusMap = [ // 32 unibus map registers
this.regsUniMap = [ // 32 UNIBUS map registers
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
];
this.regsControl = [ // various control registers (177740-177756) we don't really care about
@ -278,7 +278,7 @@ CPUStatePDP11.prototype.resetMMU = function()
if (this.bus) {
this.setMemoryAccess();
this.addrInvalid = this.bus.getMemorySize(MemoryPDP11.TYPE.RAM);
this.addrInvalid = this.bus.getMemoryLimit(MemoryPDP11.TYPE.RAM);
}
};
@ -1393,6 +1393,13 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
this.pushWord(this.regsGen[7], fRed);
this.setPC(newPC);
/*
* TODO: Determine the appropriate number of cycles for traps; all I've done for now is move the
* cycle charge from opTrap() to here, and reduced the amount the other opcode handlers that call
* trap() charge by a corresponding amount (5).
*/
this.nStepCycles -= (4 + 1);
/*
* DEC's "TRAP TEST" (MAINDEC-11-D0NA-PB) triggers a RESERVED trap with an invalid opcode and the
* stack deliberately set too low, and expects the stack overflow trap to be "sprung" immediately
@ -1513,22 +1520,28 @@ CPUStatePDP11.prototype.getTrapStatus = function()
*/
CPUStatePDP11.prototype.mapUnibus = function(addr)
{
var idx = (addr >> 13) & 0x1f;
if (idx < 31) {
if (this.regMMR3 & PDP11.MMR3.UNIBUS_MAP) {
/*
* The UNIBUS map relocation is enabled
*/
addr = (this.unibusMap[idx] + (addr & 0x1ffe)) & 0x3ffffe;
this.assert(addr < BusPDP11.UNIBUS_22BIT || addr >= BusPDP11.IOPAGE_22BIT);
} else {
/*
* Since UNIBUS map relocation is NOT enabled, then as explained above:
*
* If the UNIBUS map relocation is not enabled, an incoming 18-bit UNIBUS address has 4 leading zeroes added for
* referencing a 22-bit physical address. The lower 18 bits are the same. No relocation is performed.
*/
addr &= ~BusPDP11.UNIBUS_22BIT;
/*
* NOTE: Most callers check the first condition themselves (addr >= BusPDP11.UNIBUS_22BIT) to avoid
* making unnecessary function calls.
*/
if (addr >= BusPDP11.UNIBUS_22BIT) {
var idx = (addr >> 13) & 0x1f;
if (idx < 31) {
if (this.regMMR3 & PDP11.MMR3.UNIBUS_MAP) {
/*
* The UNIBUS map relocation is enabled
*/
addr = (this.regsUniMap[idx] + (addr & 0x1ffe)) & 0x3ffffe;
this.assert(addr < BusPDP11.UNIBUS_22BIT || addr >= BusPDP11.IOPAGE_22BIT);
} else {
/*
* Since UNIBUS map relocation is NOT enabled, then as explained above:
*
* If the UNIBUS map relocation is not enabled, an incoming 18-bit UNIBUS address has 4 leading zeroes added for
* referencing a 22-bit physical address. The lower 18 bits are the same. No relocation is performed.
*/
addr &= ~BusPDP11.UNIBUS_22BIT;
}
}
}
return addr;
@ -1559,7 +1572,7 @@ CPUStatePDP11.prototype.mapUnibus = function(addr)
* A PDP-11/70 is different from other PDP-11s in that the highest 18 bit space (017000000 & above)
* maps directly to UNIBUS space - including low memory. This doesn't appear to be particularly
* useful as it restricts maximum system memory - although it does appear to allow software
* testing of the unibus map. This feature also appears to confuse some OSes which test consecutive
* testing of the UNIBUS map. This feature also appears to confuse some OSes which test consecutive
* memory locations to find maximum memory -- and on a full memory system find themselves accessing
* low memory again at high addresses.
*
@ -1594,13 +1607,11 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(addrVirtual, access)
var page, pdr, addr;
/*
* This can happen when the DSTMODE (MAINT) bit of MMR0 is set but *not* the ENABLED bit.
* This can happen when the DSTMODE (MAINT) bit of MMR0 is set but not the ENABLED bit.
*/
if (!(access & this.mmuEnable)) {
addr = addrVirtual & 0xffff;
if (addr >= BusPDP11.IOPAGE_16BIT) {
addr |= this.addrIOPage;
}
if (addr >= BusPDP11.IOPAGE_16BIT) addr |= this.addrIOPage;
return addr;
}
@ -1609,9 +1620,7 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(addrVirtual, access)
pdr = this.mmuPDR[this.mmuMode][page];
addr = ((this.mmuPAR[this.mmuMode][page] << 6) + (addrVirtual & 0x1fff)) & this.mmuMask;
if (addr >= BusPDP11.UNIBUS_22BIT) {
addr = this.mapUnibus(addr);
}
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.mapUnibus(addr);
if (this.nDisableTraps) return addr;
@ -2009,20 +2018,16 @@ CPUStatePDP11.prototype.checkStackLimit1145 = function(access, step, addr)
};
/**
* getByteDirect(addr)
* getByteSafe(addr)
*
* This interface is expressly for the Debugger, to access virtual memory without faulting;
* note that if the MMU is not enabled, this is effectively the same as using the Bus interface.
* This interface is expressly for the Debugger, to access virtual memory without faulting.
*
* @this {CPUStatePDP11}
* @param {number} addr
* @return {number}
*/
CPUStatePDP11.prototype.getByteDirect = function(addr)
CPUStatePDP11.prototype.getByteSafe = function(addr)
{
if (!this.mmuEnable) {
return this.bus.getByteDirect(addr);
}
this.nDisableTraps++;
var b = this.readByteFromPhysical(this.mapVirtualToPhysical(addr, PDP11.ACCESS.READ_BYTE));
this.nDisableTraps--;
@ -2030,20 +2035,16 @@ CPUStatePDP11.prototype.getByteDirect = function(addr)
};
/**
* getWordDirect(addr)
* getWordSafe(addr)
*
* This interface is expressly for the Debugger, to access virtual memory without faulting;
* note that if the MMU is not enabled, this is effectively the same as using the Bus interface.
* This interface is expressly for the Debugger, to access virtual memory without faulting.
*
* @this {CPUStatePDP11}
* @param {number} addr
* @return {number}
*/
CPUStatePDP11.prototype.getWordDirect = function(addr)
CPUStatePDP11.prototype.getWordSafe = function(addr)
{
if (!this.mmuEnable) {
return this.bus.getWordDirect(addr);
}
this.nDisableTraps++;
var w = this.readWordFromPhysical(this.mapVirtualToPhysical(addr, PDP11.ACCESS.READ_WORD));
this.nDisableTraps--;
@ -2051,42 +2052,32 @@ CPUStatePDP11.prototype.getWordDirect = function(addr)
};
/**
* setByteDirect(addr, data)
* setByteSafe(addr, data)
*
* This interface is expressly for the Debugger, to access virtual memory without faulting;
* note that if the MMU is not enabled, this is effectively the same as using the Bus interface.
* This interface is expressly for the Debugger, to access virtual memory without faulting.
*
* @this {CPUStatePDP11}
* @param {number} addr
* @param {number} data
*/
CPUStatePDP11.prototype.setByteDirect = function(addr, data)
CPUStatePDP11.prototype.setByteSafe = function(addr, data)
{
if (!this.mmuEnable) {
this.bus.setByteDirect(addr, data);
return;
}
this.nDisableTraps++;
this.writeByteToPhysical(this.mapVirtualToPhysical(addr, PDP11.ACCESS.WRITE_BYTE), data);
this.nDisableTraps--;
};
/**
* setWordDirect(addr, data)
* setWordSafe(addr, data)
*
* This interface is expressly for the Debugger, to access virtual memory without faulting;
* note that if the MMU is not enabled, this is effectively the same as using the Bus interface.
* This interface is expressly for the Debugger, to access virtual memory without faulting.
*
* @this {CPUStatePDP11}
* @param {number} addr
* @param {number} data
*/
CPUStatePDP11.prototype.setWordDirect = function(addr, data)
CPUStatePDP11.prototype.setWordSafe = function(addr, data)
{
if (!this.mmuEnable) {
this.bus.setWordDirect(addr, data);
return;
}
this.nDisableTraps++;
this.writeWordToPhysical(this.mapVirtualToPhysical(addr, PDP11.ACCESS.WRITE_WORD), data);
this.nDisableTraps--;
@ -2105,7 +2096,9 @@ CPUStatePDP11.prototype.setWordDirect = function(addr, data)
*/
CPUStatePDP11.prototype.getPhysicalAddrByMode = function(mode, reg, access)
{
return this.getAddrByMode(mode, reg, access);
var addr = this.getAddrByMode(mode, reg, access);
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.mapUnibus(addr);
return addr;
};
/**
@ -2135,6 +2128,7 @@ CPUStatePDP11.prototype.getVirtualAddrByMode = function(mode, reg, access)
*/
CPUStatePDP11.prototype.readWordFromPhysical = function(addr)
{
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.mapUnibus(addr);
return this.bus.getWord(this.addrLast = addr);
};
@ -2163,6 +2157,7 @@ CPUStatePDP11.prototype.readWordFromVirtual = function(addrVirtual)
*/
CPUStatePDP11.prototype.writeWordToPhysical = function(addr, data)
{
if (addr >= BusPDP11.UNIBUS_22BIT) addr = this.mapUnibus(addr);
this.bus.setWord(this.addrLast = addr, data & 0xffff);
};

View file

@ -659,7 +659,7 @@ if (DEBUGGER) {
var b = 0xff;
var addr = this.getAddr(dbgAddr, false, 1);
if (addr !== PDP11.ADDR_INVALID) {
b = dbgAddr.fPhysical? this.bus.getByteDirect(addr) : this.cpu.getByteDirect(addr);
b = (dbgAddr.fPhysical || addr > 0xffff)? this.bus.getByteDirect(this.cpu.mapUnibus(addr)) : this.cpu.getByteSafe(addr);
if (inc) this.incAddr(dbgAddr, inc);
}
return b;
@ -678,7 +678,7 @@ if (DEBUGGER) {
var w = 0xffff;
var addr = this.getAddr(dbgAddr, false, 2);
if (addr !== PDP11.ADDR_INVALID) {
w = dbgAddr.fPhysical? this.bus.getWordDirect(addr) : this.cpu.getWordDirect(addr);
w = (dbgAddr.fPhysical || addr > 0xffff)? this.bus.getWordDirect(this.cpu.mapUnibus(addr)) : this.cpu.getWordSafe(addr);
if (inc) this.incAddr(dbgAddr, inc);
}
return w;
@ -696,10 +696,10 @@ if (DEBUGGER) {
{
var addr = this.getAddr(dbgAddr, true, 1);
if (addr !== PDP11.ADDR_INVALID) {
if (dbgAddr.fPhysical) {
this.bus.setByteDirect(addr, b);
if (dbgAddr.fPhysical || addr > 0xffff) {
this.bus.setByteDirect(this.cpu.mapUnibus(addr), b);
} else {
this.cpu.setByteDirect(addr, b);
this.cpu.setByteSafe(addr, b);
}
if (inc) this.incAddr(dbgAddr, inc);
this.cmp.updateDisplays(-1);
@ -718,10 +718,10 @@ if (DEBUGGER) {
{
var addr = this.getAddr(dbgAddr, true, 2);
if (addr !== PDP11.ADDR_INVALID) {
if (dbgAddr.fPhysical) {
this.bus.setWordDirect(addr, w);
if (dbgAddr.fPhysical || addr > 0xffff) {
this.bus.setWordDirect(this.cpu.mapUnibus(addr), w);
} else {
this.cpu.setWordDirect(addr, w);
this.cpu.setWordSafe(addr, w);
}
if (inc) this.incAddr(dbgAddr, inc);
this.cmp.updateDisplays(-1);
@ -1706,7 +1706,7 @@ if (DEBUGGER) {
* for that here by skipping over the HALT if/when the machine starts up again.
*/
if (!nState) {
opCode = this.cpu.getWordDirect(addr);
opCode = this.cpu.getWordSafe(addr);
if (opCode == PDP11.OPCODE.HALT) {
addr = this.cpu.advancePC(2);
}
@ -1733,7 +1733,7 @@ if (DEBUGGER) {
if (nState >= 0 && this.aInstructionHistory.length) {
this.cInstructions++;
if (opCode < 0) {
opCode = this.cpu.getWordDirect(addr);
opCode = this.cpu.getWordSafe(addr);
}
if ((opCode & 0xffff) != PDP11.OPCODE.INVALID) {
var dbgAddr = this.aInstructionHistory[this.iInstructionHistory];
@ -3118,7 +3118,7 @@ if (DEBUGGER) {
data = shift = 0;
}
i -= n; nBytes -= n;
while (n--) {
while (size == 1 && n--) {
var c = v & 0xff;
sChars += (c >= 32 && c < 128? String.fromCharCode(c) : '.');
v >>= 8;
@ -3128,7 +3128,7 @@ if (DEBUGGER) {
if (fJSON) {
sDump += sData + ",";
} else {
sDump += sAddr + " " + sData + ((i == 0)? (' ' + sChars) : "");
sDump += sAddr + ": " + sData + ((i == 0)? (' ' + sChars) : "");
}
}
@ -3859,12 +3859,22 @@ if (DEBUGGER) {
var dbg = this;
var fRegs = (sCmd != "t");
var nCount = this.parseValue(sCount, null, true) || 1;
var nCycles = (nCount == 1? 0 : 1);
/*
* We used to set nCycles to 1 when a count > 1 was specified, because nCycles set
* to 0 used to mean "execute the next instruction without checking for interrupts".
* Well, this machine's stepCPU() doesn't do that; it ALWAYS checks for interrupts,
* so we should leave nCycles set to 0, so that if an interrupt is dispatched, we will
* get to see the first instruction of the interrupt handler.
*/
var nCycles = 0; // (nCount == 1? 0 : 1);
if (sCmd == "tc") {
nCycles = nCount;
nCount = 1;
}
this.sTraceCmdPrev = sCmd;
web.onCountRepeat(
nCount,
function onCountStep() {

View file

@ -301,7 +301,7 @@ DevicePDP11.prototype.writeMMR3 = function(data, addr)
DevicePDP11.prototype.readUNIMAP = function(addr)
{
var word = (addr >> 1) & 0x3f, reg = word >> 1;
var data = this.cpu.unibusMap[reg];
var data = this.cpu.regsUniMap[reg];
return (word & 1)? (data >> 16) : (data & 0xffff);
};
@ -318,9 +318,9 @@ DevicePDP11.prototype.writeUNIMAP = function(data, addr)
{
var word = (addr >> 1) & 0x3f, reg = word >> 1;
if (word & 1) {
this.cpu.unibusMap[reg] = (this.cpu.unibusMap[reg] & 0xffff) | ((data & 0x003f) << 16);
this.cpu.regsUniMap[reg] = (this.cpu.regsUniMap[reg] & 0xffff) | ((data & 0x003f) << 16);
} else {
this.cpu.unibusMap[reg] = (this.cpu.unibusMap[reg] & ~0xffff) | (data & 0xfffe);
this.cpu.regsUniMap[reg] = (this.cpu.regsUniMap[reg] & ~0xffff) | (data & 0xfffe);
}
};
@ -454,10 +454,7 @@ DevicePDP11.prototype.readKIPDR = function(addr)
DevicePDP11.prototype.writeKIPDR = function(data, addr)
{
var reg = (addr >> 1) & 7;
this.cpu.mmuPDR[0][reg] = data &= 0xff0f;
if (this.messageEnabled(MessagesPDP11.MMU)) {
this.printMessage("writeKIPDR[" + reg + "]: " + str.toOct(data), true);
}
this.cpu.mmuPDR[0][reg] = data & 0xff0f;
};
/**
@ -892,13 +889,7 @@ DevicePDP11.prototype.writeCTRL = function(data, addr)
*/
DevicePDP11.prototype.readSIZE = function(addr)
{
/*
* TODO: getMemorySize() returns an aggregate total, so if there are multiple discontiguous
* chunks of RAM, this could return the wrong result; another interface, getHighestAddress(),
* might be required. Then again, perhaps multiple discontiguous chunks of RAM are not permitted
* in PDP-11 machines.
*/
return addr == PDP11.UNIBUS.LSIZE? ((this.bus.getMemorySize(MemoryPDP11.TYPE.RAM) >> 6) - 1) : 0;
return addr == PDP11.UNIBUS.LSIZE? ((this.bus.getMemoryLimit(MemoryPDP11.TYPE.RAM) >> 6) - 1) : 0;
};
/**

View file

@ -760,12 +760,15 @@ PanelPDP11.prototype.processDeposit = function(value, index)
if (this.fDeposit) this.advanceAddr();
var w = this.updateData(this.regSwitches);
if (this.nAddrSel == PanelPDP11.ADDRSEL.CONS_PHY) {
/*
* TODO: Determine if this needs to take the UNIBUS map into consideration.
*/
this.bus.setWordDirect(this.regAddr, w);
} else {
/*
* TODO: This code is obviously incomplete, since it doesn't take into account the precise ADDRSEL mode.
*/
this.cpu.setWordDirect(this.regAddr, w);
this.cpu.setWordSafe(this.regAddr, w);
}
}
};
@ -783,12 +786,15 @@ PanelPDP11.prototype.processExamine = function(value, index)
var w;
if (this.fExamine) this.advanceAddr();
if (this.nAddrSel == PanelPDP11.ADDRSEL.CONS_PHY) {
/*
* TODO: Determine if this needs to take the UNIBUS map into consideration.
*/
w = this.bus.getWordDirect(this.regAddr);
} else {
/*
* TODO: This code is obviously incomplete, since it doesn't take into account the precise ADDRSEL mode.
*/
w = this.cpu.getWordDirect(this.regAddr);
w = this.cpu.getWordSafe(this.regAddr);
}
this.updateData(w);
}

View file

@ -349,7 +349,7 @@ RAMPDP11.prototype.loadImage = function(aBytes, addrLoad, addrExec, addrInit, fR
} else {
this.printMessage("loading " + str.toHexWord(cbData) + " bytes at " + str.toHexWord(addr) + "-" + str.toHexWord(addr + cbData - 1), MessagesPDP11.PAPER);
while (cbData--) {
this.cpu.setByteDirect(addr++, aBytes[offData++] & 0xff);
this.bus.setByteDirect(addr++, aBytes[offData++] & 0xff);
}
}
fLoaded = true;
@ -359,7 +359,7 @@ RAMPDP11.prototype.loadImage = function(aBytes, addrLoad, addrExec, addrInit, fR
if (addrLoad == null) addrLoad = addrInit;
if (addrLoad != null) {
for (var i = 0; i < aBytes.length; i++) {
this.cpu.setByteDirect(addrLoad + i, aBytes[i]);
this.bus.setByteDirect(addrLoad + i, aBytes[i]);
}
fLoaded = true;
}

View file

@ -1017,10 +1017,13 @@ RK11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, add
err = PDP11.RK11.RKER.NXS;
break;
}
this.bus.setWordDirect(addr, data = b0 | (b1 << 8));
if (DEBUG && this.messageEnabled(MessagesPDP11.READ) && sWords.length < 56) {
this.bus.setWordDirect(this.cpu.mapUnibus(addr), data = b0 | (b1 << 8));
if (DEBUG && this.messageEnabled(MessagesPDP11.READ)) {
sWords += str.toOct(data) + ' ';
if (sWords.length >= 56) this.printMessage(sWords + '\n', true);
if (sWords.length >= 56) {
this.printMessage(sWords + '\n', true);
sWords = "";
}
}
if (this.bus.checkFault()) {
err = PDP11.RK11.RKER.NXM;
@ -1069,7 +1072,7 @@ RK11.prototype.writeData = function(drive, iCylinder, iHead, iSector, nWords, ad
}
while (nWords--) {
var data = this.bus.getWordDirect(addr);
var data = this.bus.getWordDirect(this.cpu.mapUnibus(addr));
if (this.bus.checkFault()) {
err = PDP11.RK11.RKER.NXM;
break;

View file

@ -918,10 +918,10 @@ RL11.prototype.processCommand = function()
break;
case PDP11.RL11.FUNC.STATUS:
if (this.dar & PDP11.RL11.RLDA.GS_RST) {
this.csr &= 0x3F; // TODO: Review
if (this.mpr & PDP11.RL11.RLMP.GS_BH) {
this.csr &= (PDP11.RL11.RLCS.DRDY | PDP11.RL11.RLCS.FUNC | PDP11.RL11.RLCS.BAE); // TODO: Review
}
this.mpr = drive.status | (this.darInternal & PDP11.RL11.RLDA.RW_HS); // bit 6: Head Select, bit 7: Drive Type (1=RL02)
this.mpr = drive.status | (this.darInternal & PDP11.RL11.RLDA.RW_HS); // bit 6: Head Select, bit 7: Drive Type (1=RL02)
break;
case PDP11.RL11.FUNC.SEEK:
@ -956,11 +956,11 @@ RL11.prototype.processCommand = function()
}
addr = (((this.ber & PDP11.RL11.RLBE.MASK)) << 16) | this.bar; // 22 bit mode
nWords = (0x10000 - this.mpr) & 0xffff;
var pos = ((((iCylinder << 1) + iHead) * drive.nSectors) + iSector) * 128;
if (DEBUG && this.messageEnabled(MessagesPDP11.READ)) {
var pos = ((((iCylinder << 1) + iHead) * drive.nSectors) + iSector) * 128;
this.printMessage((fnReadWrite == this.readData? "readData" : "writeData") + "(pos=" + pos + ",addr=" + str.toOct(addr) + ",bytes=" + (nWords * 2) + ")", true, true);
}
fInterrupt = fnReadWrite.call(this, drive, iCylinder, iHead, iSector, nWords, addr, this.endReadWrite.bind(this));
fInterrupt = fnReadWrite.call(this, drive, pos, iCylinder, iHead, iSector, nWords, addr, this.endReadWrite.bind(this));
break;
default:
@ -973,8 +973,6 @@ RL11.prototype.processCommand = function()
}
};
/**
* endReadWrite(err, iCylinder, iHead, iSector, nWords, addr)
*
@ -1002,10 +1000,11 @@ RL11.prototype.endReadWrite = function(err, iCylinder, iHead, iSector, nWords, a
};
/**
* readData(drive, iCylinder, iHead, iSector, nWords, addr, done)
* readData(drive, pos, iCylinder, iHead, iSector, nWords, addr, done)
*
* @this {RL11}
* @param {Object} drive
* @param {number} pos
* @param {number} iCylinder
* @param {number} iHead
* @param {number} iSector
@ -1014,9 +1013,10 @@ RL11.prototype.endReadWrite = function(err, iCylinder, iHead, iSector, nWords, a
* @param {function(...)} done
* @return {boolean} true if complete, false if queued
*/
RL11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, addr, done)
RL11.prototype.readData = function(drive, pos, iCylinder, iHead, iSector, nWords, addr, done)
{
var err = 0;
var checksum = 0;
var disk = drive.disk;
var sector = null, ibSector;
@ -1025,6 +1025,7 @@ RL11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, add
nWords = 0;
}
var sWords = "", fDump = (addr == 0);
while (nWords--) {
if (!sector) {
sector = drive.disk.seek(iCylinder, iHead, iSector + 1);
@ -1034,17 +1035,25 @@ RL11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, add
}
ibSector = 0;
}
var b0, b1;
var b0, b1, data;
if ((b0 = drive.disk.read(sector, ibSector++)) < 0 || (b1 = drive.disk.read(sector, ibSector++)) < 0) {
err = PDP11.RL11.ERRC.HNF;
break;
}
var data = this.bus.setWordDirect(addr, b0 | (b1 << 8));
this.bus.setWordDirect(this.cpu.mapUnibus(addr), data = b0 | (b1 << 8));
if (DEBUG && fDump && this.messageEnabled(MessagesPDP11.READ)) {
sWords += str.toOct(data) + ' ';
if (sWords.length >= 56) {
this.println(sWords);
sWords = "";
}
}
if (this.bus.checkFault()) {
err = PDP11.RL11.ERRC.NXM;
break;
}
addr += 2;
checksum += data;
if (ibSector >= disk.cbSector) {
sector = null;
if (++iSector >= disk.nSectors) {
@ -1059,14 +1068,23 @@ RL11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, add
}
}
}
if (DEBUG && this.messageEnabled(MessagesPDP11.READ)) {
this.printMessage("checksum: " + (checksum|0), true);
if (pos == 732160) {
this.cpu.stopCPU();
}
}
return done(err, iCylinder, iHead, iSector, nWords, addr);
};
/**
* writeData(drive, iCylinder, iHead, iSector, nWords, addr, done)
* writeData(drive, pos, iCylinder, iHead, iSector, nWords, addr, done)
*
* @this {RL11}
* @param {Object} drive
* @param {number} pos
* @param {number} iCylinder
* @param {number} iHead
* @param {number} iSector
@ -1075,9 +1093,10 @@ RL11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, add
* @param {function(...)} done
* @return {boolean} true if complete, false if queued
*/
RL11.prototype.writeData = function(drive, iCylinder, iHead, iSector, nWords, addr, done)
RL11.prototype.writeData = function(drive, pos, iCylinder, iHead, iSector, nWords, addr, done)
{
var err = 0;
var checksum = 0;
var disk = drive.disk;
var sector = null, ibSector;
@ -1086,13 +1105,22 @@ RL11.prototype.writeData = function(drive, iCylinder, iHead, iSector, nWords, ad
nWords = 0;
}
var sWords = "", fDump = (pos = 946944);
while (nWords--) {
var data = this.bus.getWordDirect(addr);
var data = this.bus.getWordDirect(this.cpu.mapUnibus(addr));
if (this.bus.checkFault()) {
err = PDP11.RL11.ERRC.NXM;
break;
}
if (DEBUG && fDump && this.messageEnabled(MessagesPDP11.READ)) {
sWords += str.toOct(data) + ' ';
if (sWords.length >= 56) {
this.println(sWords);
sWords = "";
}
}
addr += 2;
checksum += data;
if (!sector) {
sector = drive.disk.seek(iCylinder, iHead, iSector + 1, true);
if (!sector) {
@ -1119,6 +1147,11 @@ RL11.prototype.writeData = function(drive, iCylinder, iHead, iSector, nWords, ad
}
}
}
if (DEBUG && this.messageEnabled(MessagesPDP11.READ)) {
this.printMessage("checksum: " + (checksum|0), true);
}
return done(err, iCylinder, iHead, iSector, nWords, addr);
};