Cleaned up PDP-11/70 configs

This commit is contained in:
Jeff Parsons 2016-10-13 16:35:10 -07:00 committed by Jeff Parsons
commit 854b40c419
28 changed files with 531 additions and 261 deletions

View file

@ -13,6 +13,9 @@ PDPjs is our PDP-11 machine emulation module. The code is being adapted from
the JavaScript [PDP 11/70 Emulator (v1.3)](http://skn.noip.me/pdp11/pdp11.html) written by
[Paul Nankervis](mailto:paulnank@hotmail.com).
See the list of available [PDP-11 Machines](/devices/pdp11/machine/), which includes a
[PDP-11/70 with Front Panel](/devices/pdp11/machine/1170/panel/) and [PDP-11/70 with VT100 Terminal](/devices/pdp11/machine/1170/vt100/).
PDPjs is currently comprised of the following non-shared components, as listed in
[package.json](../../package.json) (see the *pdp11Files* property):

View file

@ -216,7 +216,7 @@ BusPDP11.IOHANDLER = {
* Those fallbacks may not always be appropriate; for example, byte writes to some device registers
* must be zero-extended to update the entire word. For those cases, the fallback's "preliminary" read
* is issued with a zero address so that the handler can distinguish a normal read from one of these
* preliminary reads, and return an appropriate value for the update (ie, zero).
* preliminary reads (aka read-before-write), and return an appropriate value for the update (eg, zero).
*
* If none of these fallback behaviors are appropriate, the device has a simple recourse: register
* handlers for all possible addresses and sizes.
@ -543,10 +543,15 @@ BusPDP11.prototype.reset = function()
*/
BusPDP11.prototype.unknownAccess = function(addr, data, byteFlag)
{
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.WARN)) {
/*
* TODO: For 22-bit machines, let's display addr as a 3-byte value (for a total of 9 octal digits)
*/
this.dbg.printMessage("warning: unknown I/O access (" + this.dbg.toStrBase(addr, 3) + "," + this.dbg.toStrBase(data) + "," + byteFlag + ")", true, true);
this.cpu.setPC(this.cpu.getLastPC());
this.cpu.stopCPU();
}
if (!this.nDisableTraps) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.WARN)) {
this.dbg.printMessage("warning: unrecognized I/O access(" + this.dbg.toStrBase(addr) + "," + this.dbg.toStrBase(data) + "," + byteFlag + ")", true, true);
}
this.cpu.trap(PDP11.TRAP.BUS_ERROR, addr);
}
return 0;

View file

@ -1039,6 +1039,20 @@ PDP11.opDECB = function(opCode)
/**
* opDIV(opCode)
*
* The instruction "DIV SRC,Rn" determines SRC using the DSTMODE portion of the opcode and Rn using
* the SRCMODE portion; Rn can only be a register (and it should be an EVEN-numbered register, lest you
* get unexpected results). The dividend (DST) is then calculated as:
*
* DST = (regs[Rn] << 16) | (regs[Rn|1])
*
* DST is divided by SRC, and the quotient is stored in regs[Rn] and the remainder in regs[Rn|1].
*
* For example:
*
* DIV R4,R0
*
* where R4 = 006400 and R0,R1 = 000000,015000 will result in R0,R1 = 000002,000000.
*
* @this {CPUStatePDP11}
* @param {number} opCode
*/

View file

@ -534,6 +534,20 @@ CPUStatePDP11.prototype.getPC = function()
return this.regsGen[PDP11.REG.PC];
};
/**
* getLastPC()
*
* @this {CPUStatePDP11}
* @return {number}
*/
CPUStatePDP11.prototype.getLastPC = function()
{
/*
* As long as we're always snapping the PC before every opcode, we might as well use it....
*/
return this.regMMR2;
};
/**
* getPCWord()
*

View file

@ -1152,7 +1152,7 @@ if (DEBUGGER) {
DebuggerPDP11.prototype.message = function(sMessage, fAddress)
{
if (fAddress) {
sMessage += " @" + this.toStrAddr(this.newAddr(this.cpu.getPC()));
sMessage += " @" + this.toStrAddr(this.newAddr(this.cpu.getLastPC()));
}
if (this.bitsMessage & MessagesPDP11.BUFFER) {

View file

@ -421,11 +421,12 @@ var PDP11 = {
LKS: 0o177546, // KW11-L Clock Status
RCSR: 0o177560, // Console Terminal: Receiver Status Register
RBUF: 0o177562, // Console Terminal: Receiver Data Buffer Register
XCSR: 0o177564, // Console Terminal: Transmitter Status Register
XBUF: 0o177566, // Console Terminal: Transmitter Data Buffer Register
DISPLAY: 0o177570, // Console Switch and Display
RCSR: 0o177560, // Display Terminal: Receiver Status Register
RBUF: 0o177562, // Display Terminal: Receiver Data Buffer Register
XCSR: 0o177564, // Display Terminal: Transmitter Status Register
XBUF: 0o177566, // Display Terminal: Transmitter Data Buffer Register
CNSL: 0o177570, // Console Switch and Front Panel Display
MMR0: 0o177572, // 777572 17777572
MMR1: 0o177574, // 777574 17777574

View file

@ -46,10 +46,10 @@ if (NODE) {
*
* The Device component implements the following "default" devices:
*
* KW11
* DISPLAY Registers
* MMU Registers
* CPU Registers (eg, PSW)
* KW11 (KW11-L Line Time Clock)
* CNSL (Console Switch and Front Panel Display)
*
* as well providing access to all the MMU and CPU registers, PSW, etc.
*
* @constructor
* @extends Component
@ -59,14 +59,14 @@ function DevicePDP11(parmsDevice)
{
Component.call(this, "Device", parmsDevice, DevicePDP11, MessagesPDP11.DEVICE);
this.display = {
this.console = { // CNSL registers
data: 0,
address: 0,
misc: 0x14,
switches: 0
};
this.kw11 = {
this.kw11 = { // LW11 registers
csr: 0,
timer: -1 // initBus() will initialize this timer ID
};
@ -167,6 +167,33 @@ DevicePDP11.prototype.writeLKS = function(data, addr)
this.kw11.lks = data & ~PDP11.KW11.LKS.MON;
};
/**
* readCNSL(addr)
*
* If addr is set, then this a normal read, so we should return normal results (ie, switches);
* if addr is NOT set, then this is a read-before-write, so we must return the value being updated (ie, data).
*
* @this {DevicePDP11}
* @param {number} addr (eg, PDP11.UNIBUS.CNSL or 177570)
* @return {number}
*/
DevicePDP11.prototype.readCNSL = function(addr)
{
return (addr? this.console.switches : this.console.data) & 0xffff;
};
/**
* writeCNSL(data, addr)
*
* @this {DevicePDP11}
* @param {number} data
* @param {number} addr (eg, PDP11.UNIBUS.CNSL or 177570)
*/
DevicePDP11.prototype.writeCNSL = function(data, addr)
{
this.console.data = data;
};
/**
* readMMR0(addr)
*
@ -189,7 +216,7 @@ DevicePDP11.prototype.readMMR0 = function(addr)
DevicePDP11.prototype.writeMMR0 = function(data, addr)
{
this.cpu.setMMR0(data);
this.updateDisplayMode();
this.updateConsoleMode();
};
/**
@ -250,21 +277,21 @@ DevicePDP11.prototype.readMMR3 = function(addr)
DevicePDP11.prototype.writeMMR3 = function(data, addr)
{
this.cpu.setMMR3(data);
this.updateDisplayMode();
this.updateConsoleMode();
};
/**
* updateDisplayMode()
* updateConsoleMode()
*
* @this {DevicePDP11}
*/
DevicePDP11.prototype.updateDisplayMode = function()
DevicePDP11.prototype.updateConsoleMode = function()
{
/*
* Set bit to 1 (22-bit), 2 (18-bit), or 4 (16-bit)
*/
var bit = this.cpu.mmuEnable? ((this.cpu.regMMR3 & PDP11.MMR3.MMU_22BIT)? 1 : 2) : 4;
this.display.misc = (this.display.misc & ~7) | bit;
this.console.misc = (this.console.misc & ~7) | bit;
};
/**
@ -1024,7 +1051,7 @@ DevicePDP11.prototype.kw11_interrupt = function()
*/
DevicePDP11.prototype.reset = function()
{
this.display.misc = (this.display.misc & ~0x77) | 0x14; // kernel 16 bit
this.console.misc = (this.console.misc & ~0x77) | 0x14; // kernel 16 bit
this.kw11.lks = 0;
};
@ -1042,6 +1069,7 @@ DevicePDP11.UNIBUS_IOTABLE = {
[PDP11.UNIBUS.KDSAR0]: /* 172360 */ [null, null, DevicePDP11.prototype.readKDSAR, DevicePDP11.prototype.writeKDSAR, "KDSAR"],
[PDP11.UNIBUS.MMR3]: /* 172516 */ [null, null, DevicePDP11.prototype.readMMR3, DevicePDP11.prototype.writeMMR3, "MMR3"],
[PDP11.UNIBUS.LKS]: /* 177546 */ [null, null, DevicePDP11.prototype.readLKS, DevicePDP11.prototype.writeLKS, "LKS"],
[PDP11.UNIBUS.CNSL]: /* 177570 */ [null, null, DevicePDP11.prototype.readCNSL, DevicePDP11.prototype.writeCNSL, "CNSL"],
[PDP11.UNIBUS.MMR0]: /* 177572 */ [null, null, DevicePDP11.prototype.readMMR0, DevicePDP11.prototype.writeMMR0, "MMR0"],
[PDP11.UNIBUS.MMR1]: /* 177574 */ [null, null, DevicePDP11.prototype.readMMR1, DevicePDP11.prototype.writeIgnored, "MMR1"],
[PDP11.UNIBUS.MMR2]: /* 177576 */ [null, null, DevicePDP11.prototype.readMMR2, DevicePDP11.prototype.writeIgnored, "MMR2"],

View file

@ -262,7 +262,7 @@ SerialPortPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
this.triggerReceiveInterrupt = this.cpu.addTrigger(PDP11.DL11.RVEC, PDP11.DL11.PRI);
this.timerReceiveInterrupt = this.cpu.addTimer(function readyReceiver() {
this.timerReceiveInterrupt = this.cpu.addTimer(function() {
if (!(serial.rcsr & PDP11.DL11.RCSR.RD)) {
if (serial.abReceive.length) {
serial.rbuf = serial.abReceive.shift();
@ -276,7 +276,7 @@ SerialPortPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
this.triggerTransmitInterrupt = this.cpu.addTrigger(PDP11.DL11.XVEC, PDP11.DL11.PRI);
this.timerTransmitInterrupt = this.cpu.addTimer(function readyTransmitter() {
this.timerTransmitInterrupt = this.cpu.addTimer(function readyransmitter() {
serial.xcsr |= PDP11.DL11.XCSR.READY;
if (serial.xcsr & PDP11.DL11.XCSR.TIE) {
serial.cpu.setTrigger(serial.triggerTransmitInterrupt);

View file

@ -218,7 +218,7 @@ str.toOct = function(n, cch, fPrefix)
if (cch) {
if (cch > 11) cch = 11;
} else {
cch = (n & ~0xffff)? 11 : 6;
cch = (n & ~0xffff)? 11 : 6; // TODO: For our 22-bit machines, we really don't need more than 8 digits max
}
/*
* An initial "falsey" check for null takes care of both null and undefined;