Simplified the I/O registration function, added support for Panel debugger messages, and added some new Panel behavior on the RESET instruction
This commit is contained in:
parent
365b24c684
commit
5bc0c8cca9
12 changed files with 327 additions and 246 deletions
|
|
@ -1272,7 +1272,7 @@ BusPDP11.prototype.getMemorySize = function(type)
|
|||
};
|
||||
|
||||
/**
|
||||
* addIOHandlers(start, end, fnReadByte, fnWriteByte, fnReadWord, fnWriteWord, sName)
|
||||
* addIOHandlers(start, end, fnReadByte, fnWriteByte, fnReadWord, fnWriteWord, msgCategory, sName)
|
||||
*
|
||||
* Add I/O notification handlers to the master list (aIOHandlers). The start and end addresses are typically
|
||||
* relative to the starting IOPAGE address, but they can also be absolute; we simply mask all addresses with
|
||||
|
|
@ -1281,7 +1281,9 @@ BusPDP11.prototype.getMemorySize = function(type)
|
|||
* CAVEATS: If a conflict is reported, a partial set of handlers may still have been added. There is no mechanism
|
||||
* for removing handlers, since this is considered an initialization function. And finally, when a range of addresses
|
||||
* is used, each successive address is advanced by 2, so if you really want to add a handler for a "+1" (usually odd)
|
||||
* address, then you must add it individually.
|
||||
* address, then you must add it individually. Failure to do is not necessarily fatal, because the IOController's
|
||||
* fallback behavior for an odd address is to call the byte handler for the preceding even address, but the byte
|
||||
* handler must be prepared for that (the handlers installed by ROM component's addROM() function are a good example).
|
||||
*
|
||||
* @this {BusPDP11}
|
||||
* @param {number} start address
|
||||
|
|
@ -1309,18 +1311,16 @@ BusPDP11.prototype.addIOHandlers = function(start, end, fnReadByte, fnWriteByte,
|
|||
};
|
||||
|
||||
/**
|
||||
* addIOTable(component, table, msgCategory, sName)
|
||||
* addIOTable(component, table)
|
||||
*
|
||||
* Add I/O notification handlers from the specified table (a batch version of addIOHandlers).
|
||||
*
|
||||
* @this {BusPDP11}
|
||||
* @param {Component} component
|
||||
* @param {Object} table
|
||||
* @param {number} [msgCategory] (default is BUS)
|
||||
* @param {string} [sName]
|
||||
* @return {boolean} (true if entire range successfully registered, false if any conflicts)
|
||||
*/
|
||||
BusPDP11.prototype.addIOTable = function(component, table, msgCategory, sName)
|
||||
BusPDP11.prototype.addIOTable = function(component, table)
|
||||
{
|
||||
for (var port in table) {
|
||||
var addr = +port;
|
||||
|
|
@ -1336,7 +1336,6 @@ BusPDP11.prototype.addIOTable = function(component, table, msgCategory, sName)
|
|||
var fnWriteByte = afn[1]? afn[1].bind(component) : null;
|
||||
var fnReadWord = afn[2]? afn[2].bind(component) : null;
|
||||
var fnWriteWord = afn[3]? afn[3].bind(component) : null;
|
||||
var nRegs = afn[5] || 1;
|
||||
|
||||
/*
|
||||
* As discussed in the IOController comments above, when handlers are being registered for these
|
||||
|
|
@ -1360,9 +1359,11 @@ BusPDP11.prototype.addIOTable = function(component, table, msgCategory, sName)
|
|||
}
|
||||
|
||||
var sReg = afn[4];
|
||||
var nRegs = afn[5] || 1;
|
||||
|
||||
for (var iReg = 0; iReg < nRegs; iReg++, addr += 2) {
|
||||
if (sReg && nRegs > 1) sReg = afn[4] + iReg;
|
||||
if (!this.addIOHandlers(addr, addr, fnReadByte, fnWriteByte, fnReadWord, fnWriteWord, msgCategory || MessagesPDP11.BUS, sReg || sName)) {
|
||||
if (!this.addIOHandlers(addr, addr, fnReadByte, fnWriteByte, fnReadWord, fnWriteWord, component.bitsMessage || MessagesPDP11.BUS, sReg || component.idComponent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1471,6 +1471,42 @@ PDP11.opRESET = function(opCode)
|
|||
{
|
||||
if (!(this.regPSW & PDP11.PSW.CMODE)) {
|
||||
this.resetCPU();
|
||||
|
||||
if (this.panel) {
|
||||
/*
|
||||
* The PDP-11/70 XXDP test "EKBBF0" reports the following, with PANEL messages on ("m panel on"):
|
||||
*
|
||||
* CNSW.writeWord(177570,000101) @033502
|
||||
* CNSW.readWord(177570): 000000 @032114
|
||||
* LOOK AT THE CONSOLE LIGHTS
|
||||
* THE DATA LIGHTS SHOULD READ 166667
|
||||
* THE ADDRESS LIGHTS SHOULD READ CNSW.readWord(177570): 000000 @032150
|
||||
* 032236
|
||||
* CHANGE SWITCH 7 TO CONTINUE
|
||||
* CNSW.readWord(177570): 000000 @032236
|
||||
* stopped (31518011 instructions, 358048873 cycles, 58644 ms, 6105465 hz)
|
||||
* R0=166667 R1=002362 R2=000000 R3=000000 R4=000000 R5=026642
|
||||
* SP=001074 PC=032236 PS=000344 SR=00000000 T0 N0 Z1 V0 C0
|
||||
* 032236: 032737 000200 177570 BIT #200,@#177570
|
||||
* >> tr
|
||||
* CNSW.readWord(177570): 000000 @032236 (cpu halted)
|
||||
* R0=166667 R1=002362 R2=000000 R3=000000 R4=000000 R5=026642
|
||||
* SP=001074 PC=032244 PS=000344 SR=00000000 T0 N0 Z1 V0 C0
|
||||
* 032244: 001773 BEQ 032234 ;cycles=0
|
||||
* >> tr
|
||||
* R0=166667 R1=002362 R2=000000 R3=000000 R4=000000 R5=026642
|
||||
* SP=001074 PC=032234 PS=000344 SR=00000000 T0 N0 Z1 V0 C0
|
||||
* 032234: 000005 RESET ;cycles=5
|
||||
*
|
||||
* It's a little hard to see why the DATA lights should read 166667, since the PANEL messages indicate
|
||||
* that the last CNSW.writeWord(177570) was for 000101, not 166667. So I'm guessing that the RESET
|
||||
* instruction is supposed to propagate R0 to the console's DISPLAY register.
|
||||
*
|
||||
* This is similar to what we do for the HALT instruction on the PDP-11/20. None of these Console features
|
||||
* seem to be very well documented (assuming they exist).
|
||||
*/
|
||||
this.panel.setData(this.regsGen[0], true);
|
||||
}
|
||||
}
|
||||
this.nStepCycles -= 667; // TODO: Review (but it's definitely a big number)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ CPUStatePDP11.prototype.initRegs = function()
|
|||
this.dstMode = this.dstReg = this.dstAddr = 0;
|
||||
|
||||
this.trapPSW = -1;
|
||||
this.resetRegs();
|
||||
this.resetMMU();
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -233,15 +233,15 @@ CPUStatePDP11.prototype.initRegs = function()
|
|||
CPUStatePDP11.prototype.resetCPU = function()
|
||||
{
|
||||
this.bus.reset();
|
||||
this.resetRegs();
|
||||
this.resetMMU();
|
||||
};
|
||||
|
||||
/**
|
||||
* resetRegs()
|
||||
* resetMMU()
|
||||
*
|
||||
* @this {CPUStatePDP11}
|
||||
*/
|
||||
CPUStatePDP11.prototype.resetRegs = function()
|
||||
CPUStatePDP11.prototype.resetMMU = function()
|
||||
{
|
||||
this.regSL = 0xff; // 177774
|
||||
this.regErr = 0; // 177766
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ var MessagesPDP11 = {
|
|||
MEMORY: 0x00000080,
|
||||
ROM: 0x00000100,
|
||||
DEVICE: 0x00000200,
|
||||
PANEL: 0x00000400,
|
||||
KEYBOARD: 0x00010000,
|
||||
KEYS: 0x00020000,
|
||||
PAPER: 0x00100000,
|
||||
|
|
@ -75,6 +76,7 @@ MessagesPDP11.CATEGORIES = {
|
|||
"memory": MessagesPDP11.MEMORY,
|
||||
"rom": MessagesPDP11.ROM,
|
||||
"device": MessagesPDP11.DEVICE,
|
||||
"panel": MessagesPDP11.PANEL,
|
||||
"keyboard": MessagesPDP11.KEYBOARD, // "kbd" is also allowed as shorthand for "keyboard"; see doMessages()
|
||||
"key": MessagesPDP11.KEYS, // using "key" instead of "keys", since the latter is a method on JavasScript objects
|
||||
"paper": MessagesPDP11.PAPER,
|
||||
|
|
|
|||
|
|
@ -33,13 +33,14 @@
|
|||
"use strict";
|
||||
|
||||
if (NODE) {
|
||||
var str = require("../../shared/lib/strlib");
|
||||
var usr = require("../../shared/lib/usrlib");
|
||||
var web = require("../../shared/lib/weblib");
|
||||
var Component = require("../../shared/lib/component");
|
||||
var PDP11 = require("./defines");
|
||||
var BusPDP11 = require("./bus");
|
||||
var MemoryPDP11 = require("./memory");
|
||||
var str = require("../../shared/lib/strlib");
|
||||
var usr = require("../../shared/lib/usrlib");
|
||||
var web = require("../../shared/lib/weblib");
|
||||
var Component = require("../../shared/lib/component");
|
||||
var PDP11 = require("./defines");
|
||||
var BusPDP11 = require("./bus");
|
||||
var MemoryPDP11 = require("./memory");
|
||||
var MessagesPDP11 = require("./messages");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -53,7 +54,7 @@ if (NODE) {
|
|||
*/
|
||||
function PanelPDP11(parmsPanel)
|
||||
{
|
||||
Component.call(this, "Panel", parmsPanel, PanelPDP11);
|
||||
Component.call(this, "Panel", parmsPanel, PanelPDP11, MessagesPDP11.PANEL);
|
||||
|
||||
/*
|
||||
* If there are any live registers, LEDs, etc, to display, this will provide a count.
|
||||
|
|
@ -573,8 +574,7 @@ PanelPDP11.prototype.processStart = function(value, index)
|
|||
* is depressed, "the computer system will be cleared." I take it to mean that it performs
|
||||
* the equivalent of a RESET instruction.
|
||||
*/
|
||||
this.bus.reset();
|
||||
this.cpu.resetRegs();
|
||||
this.cpu.resetCPU();
|
||||
/*
|
||||
* The PDP-11/70 Handbook goes on to say: "If the system needs to be initialized but execution
|
||||
* is not wanted, the START switch should be depressed while the HALT/ENABLE switch is in the HALT
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ RL11.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
|
||||
this.triggerInterrupt = this.cpu.addTrigger(PDP11.RL11.VEC, PDP11.RL11.PRI);
|
||||
|
||||
bus.addIOTable(this, RL11.UNIBUS_IOTABLE, MessagesPDP11.DISK);
|
||||
bus.addIOTable(this, RL11.UNIBUS_IOTABLE);
|
||||
bus.addResetHandler(this.reset.bind(this));
|
||||
|
||||
this.addDisk("None", RL11.SOURCE.NONE, true);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ if (NODE) {
|
|||
*/
|
||||
function ROMPDP11(parmsROM)
|
||||
{
|
||||
Component.call(this, "ROM", parmsROM, ROMPDP11);
|
||||
Component.call(this, "ROM", parmsROM, ROMPDP11, MessagesPDP11.ROM);
|
||||
|
||||
this.abInit = null;
|
||||
this.aSymbols = null;
|
||||
|
|
@ -289,11 +289,16 @@ ROMPDP11.prototype.addROM = function(addr)
|
|||
* of the IOPAGE address space, by installing I/O handlers for the entire range that return the corresponding
|
||||
* bytes of the current ROM image on reads, and ignore any writes (which I'm only assuming is how a typical
|
||||
* ROM "device" deals with writes; if we remove the write handler, then writes will fault).
|
||||
*
|
||||
* TODO: It would be more efficient if we parsed ROM data as words rather than bytes, and then installed
|
||||
* only word handlers instead of only byte handlers. It was done this way purely for historical reasons (ie,
|
||||
* because that's how other PCjs machines parse their ROMs). For now, all this means is that executing code
|
||||
* out of ROM will be slower than out of RAM -- although that's often true in the real world as well.
|
||||
*/
|
||||
var IOTable = {
|
||||
[addr]: [ROMPDP11.prototype.readROMByte, ROMPDP11.prototype.writeROMByte, null, null, null, this.sizeROM >> 1]
|
||||
};
|
||||
if (this.bus.addIOTable(this, IOTable, MessagesPDP11.ROM, this.idComponent)) {
|
||||
if (this.bus.addIOTable(this, IOTable)) {
|
||||
this.fRetainROM = true;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue