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

@ -8,8 +8,8 @@ machines:
debugger: true
autoStart: true
autoMount:
RL0:
path: http://archive.pcjs.org/disks/dec/rl02k/RL02K-XXDP.json
RL2:
path: http://archive.pcjs.org/disks/dec/rl01k/RL01K-RSTS-V70.json
---
{% include machine.html id="test1170" %}

View file

@ -21,8 +21,8 @@ As DEC notes in the [PDP-11/70 Maintenance Service Guide](http://archive.pcjs.or
Chapter 4: "There are several useful toggle-ins that are probably not very well known." Excerpts are provided below. If you're
not sure how to "toggle in" code using a Front Panel, check out [Front Panel Basics](/devices/pdp11/panel/1170/#front-panel-basics).
However, since the above machine also includes the PDPjs Debugger, you'll find that it's much easier to use the Debugger commands
described below to load and execute these "toggle-ins".
However, since the above machine also includes the PDPjs Debugger, you'll find that it's much easier to use the
Debugger commands described below to load and execute these "toggle-ins".
### Memory Management
@ -83,6 +83,9 @@ which should produce these results:
R0=000000 R1=000000 R2=000000 R3=000000 R4=000000 R5=000000
SP=000000 PC=000214 PS=000001 SW=00000000 T0 N0 Z0 V0 C1
000214: 000000 HALT
and dumping the contents of virtual address 300 should display 070707:
>> d 300 l1
000300 070707
@ -130,7 +133,7 @@ which should produce these results:
>> e 500 125252
changing 000500 from 000000 to 125252
>> d 17000500 l1
00017000500 125252
00017000500: 125252
>> e 17000700 070707
changing 00017000700 from 000000 to 070707
>> e 17770202 000000
@ -140,16 +143,19 @@ which should produce these results:
>> e 17772516 40
changing 00017772516 from 000000 to 000040
>> d 17000500 l1
00017000500 070707
00017000500: 070707
If you also want to see all the hardware register activity, use the Debugger's "m bus on" command to turn Bus messages on:
If you also want to see all the hardware register activity, use the Debugger's "m bus on; m device on" command
to turn Bus+Device messages on:
>> m bus on
messages on: bus
>> m device on
messages on: device
>> e 500 125252
changing 000500 to 125252
>> d 17000500 l1
00017000500 125252
00017000500: 125252
>> e 17000700 070707
changing 00017000700 to 070707
>> e 17770202 000000
@ -160,9 +166,8 @@ If you also want to see all the hardware register activity, use the Debugger's "
UNIMAP0.writeWord(00017770200,000200)
>> e 17772516 40
changing 00017772516 to 000040
MMR3.writeWord(00017772516,000040)
>> d 17000500 l1
00017000500 070707
00017000500: 070707
### Memory Clear Program
@ -219,10 +224,12 @@ The above "toggle-in" can be entered with the PDPjs Debugger as follows:
e 17772260 000200 021311 003402 005000 000766 005312 000000;
r pc 172240
which should produce the following results when Bus messages are turned on ("m bus on"):
which should produce the following results when Bus+MMU messages are turned on ("m bus on; m mmu on"):
>> m bus on
messages on: bus
>> m mmu on
messages on: mmu
>> e 17772300 077406
changing 00017772300 to 077406
KIPDR0.writeWord(00017772300,077406)
@ -301,9 +308,9 @@ which should produce the following results when Bus messages are turned on ("m b
SIPAR1.readWord(172242): 000020
172240: 012714 000020 MOV #20,@R4
All the "Supervisor I Page Address Register" (SIPAR) and "Supervisor D Page Address Register" (SDPAR) reads and writes
merely reflect where the above code is being loaded and executed from; those registers are essentially being used as scratch
RAM.
All the "Supervisor I Page Address Register" (SIPAR) and "Supervisor D Page Address Register" (SDPAR) reads
and writes merely reflect where the above code is being loaded and executed from; those registers are essentially
being used as scratch RAM.
As the **Maintenance Service Guide** goes on to say:
@ -315,13 +322,13 @@ As the **Maintenance Service Guide** goes on to say:
Note: When loading the program you must be in console physical [i.e., the ADDRESS select switch
must be set to "CONS PHY", which is the default setting of the PDPjs Front Panel].
Before running the above code, you should turn Bus messages off (ie, "m bus off"); otherwise, the quantity of messages will
slow execution to a crawl.
Before running the above code, you should turn messages off (eg, "m bus off"); otherwise, the quantity of
messages will slow execution to a crawl.
If you want to set an execution breakpoint in the above code, make sure you use the appropriate virtual (16-bit) address.
For example, to break on this instruction:
If you want to set an execution breakpoint in the above code, make sure you use the appropriate virtual (16-bit)
address. For example, to break on this instruction:
17772256 062711 ADD #200,(R1) ; Step Page
use the command "bp 172256", because while the code *is* physically located at 17772256, it is being executed at virtual
address 172256, and execution breakpoints operate on virtual addresses.
use the command "bp 172256", because while the code *is* physically located at 17772256, it is being executed at
virtual address 172256, and execution breakpoints operate on virtual addresses.

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,13 +1520,18 @@ CPUStatePDP11.prototype.getTrapStatus = function()
*/
CPUStatePDP11.prototype.mapUnibus = function(addr)
{
/*
* 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.unibusMap[idx] + (addr & 0x1ffe)) & 0x3ffffe;
addr = (this.regsUniMap[idx] + (addr & 0x1ffe)) & 0x3ffffe;
this.assert(addr < BusPDP11.UNIBUS_22BIT || addr >= BusPDP11.IOPAGE_22BIT);
} else {
/*
@ -1531,6 +1543,7 @@ CPUStatePDP11.prototype.mapUnibus = function(addr)
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,8 +918,8 @@ 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)
break;
@ -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;
if (DEBUG && this.messageEnabled(MessagesPDP11.READ)) {
var pos = ((((iCylinder << 1) + iHead) * drive.nSectors) + iSector) * 128;
if (DEBUG && this.messageEnabled(MessagesPDP11.READ)) {
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);
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long