Cleaned up PDP-11/70 configs
This commit is contained in:
parent
2a1be67727
commit
854b40c419
28 changed files with 531 additions and 261 deletions
|
|
@ -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):
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"],
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue