Lots of memory interface cleanup; still can't boot RSTS/E though....
This commit is contained in:
parent
c0a2a7c39a
commit
cacff66983
13 changed files with 704 additions and 676 deletions
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue