Merge branch 'next-release'

This commit is contained in:
Jeff Parsons 2016-11-14 15:28:11 -08:00
commit 1ad03d1cd4
54 changed files with 4528 additions and 3436 deletions

View file

@ -55,7 +55,6 @@ var DumpAPI = require("../../shared/lib/dumpapi");
*/
function FileDump(sFormat, fComments, fDecimal, offDump, nWidthDump, sServerRoot)
{
this.addrLoad = null;
this.fDebug = false;
this.sFormat = (sFormat || DumpAPI.FORMAT.JSON);
this.fJSONNative = (this.sFormat == DumpAPI.FORMAT.JSON && !fComments);
@ -68,6 +67,8 @@ function FileDump(sFormat, fComments, fDecimal, offDump, nWidthDump, sServerRoot
this.fLocal = !sServerRoot;
this.sServerRoot = sServerRoot || process.cwd();
this.buf = null;
this.addrLoad = null;
this.addrExec = null;
/*
* TODO: Decide what to do with this usage info; we can't use it as a default, because setting this.json
* causes outputFile() to ignore this.buf indiscriminately (ie, it breaks non-JSON output modes).
@ -99,7 +100,8 @@ FileDump.asBadExts = [
* Usage
* ---
* filedump --file=({path}|{URL}) [--merge=({path}|{url})] [--format=(json|data|hex|octal|bytes|words|rom)]
* [--comments] [--decimal] [--offset={number}] [--width={number}] [--output={path}] [--overwrite]
* [--comments] [--decimal] [--offset={number}] [--width={number}] [--load={number}] [--exec={number}]
* [--output={path}] [--overwrite]
*
* Arguments
* ---
@ -173,6 +175,10 @@ FileDump.CLI = function()
for (sMergeFile in argv['merge']) asMergeFiles.push(sMergeFile);
}
}
file.addrLoad = str.parseInt(argv['load']);
file.addrExec = str.parseInt(argv['exec']);
var cMergesPending = asMergeFiles.length;
var iStart = 0, nSkip = cMergesPending;
file.loadFile(sFile, iStart++, nSkip, function(err) {
@ -482,15 +488,15 @@ FileDump.prototype.dumpBuffer = function(sKey, buf, len, cbItem, offDump, nWidth
nWidthDump = nWidthDump || this.nWidthDump;
var sDump = "";
if (this.addrLoad != null) {
/*
* TODO: We need command-line overrides (eg, --load and --exec) to allow the user to specify the
* correct load (and exec) addresses. For now, we're simply inferring that the first address parsed
* in parseListing() is both the load and exec address.
*/
var sAddr = str.toHexWord(this.addrLoad) + (nBase == 8? "/*" + str.toOct(this.addrLoad, 6) + "*/" : "");
sDump += this.dumpLine(2, '"load":' + sAddr + ',"exec":' + sAddr + ',');
var addrs = {'load': this.addrLoad, 'exec': this.addrExec};
for (var prop in addrs) {
var addr = addrs[prop];
if (addr != null) {
sDump += this.dumpLine(2, '"' + prop + '":' + str.toHexWord(addr) + (nBase == 8? "/*" + str.toOct(addr, 6) + "*/" : "") + ',');
}
}
sDump += this.dumpLine(2, (sKey? '"' + sKey + '":' : "") + this.sJSONWhitespace + chOpen);
var sLine = "";

View file

@ -288,12 +288,13 @@ MarkOut.prototype.getBuildOptions = function()
* generateID(sText)
*
* Generate an ID from the given text, by basically converting it to lower case, converting anything
* that's not a letter or a digit to a hyphen (-), and stripping all leading and trailing hyphens from
* that's not a letter or a digit to a dash (-), and stripping all leading and trailing dashes from
* the result. Furthermore, if the generated ID is not unique (among the set of ALL generated IDs),
* then no ID is produced.
*
* UPDATE: Revised the algorithm to be more Jekyll-like (ie, REMOVING anything not a letter or digit or
* space, then removing any leading or trailing spaces, and then replacing any remaining spaces with a hyphen).
* space or dash, then removing any leading or trailing spaces, and then replacing any remaining spaces
* with a dash).
*
* @this {MarkOut}
* @param {string} sText
@ -301,7 +302,7 @@ MarkOut.prototype.getBuildOptions = function()
*/
MarkOut.prototype.generateID = function(sText)
{
var sID = sText.replace(/[^A-Z0-9 ]+/gi, '').replace(/^ +| +$/g, '').replace(/ +/g, '-').toLowerCase();
var sID = sText.replace(/[^A-Z0-9 -]+/gi, '').replace(/^ +| +$/g, '').replace(/ +/g, '-').toLowerCase();
if (this.aIDs.indexOf(sID) < 0) {
this.aIDs.push(sID);
return sID;
@ -535,7 +536,7 @@ MarkOut.prototype.convertMD = function(sIndent)
}
/*
* Convert all lone series of three or more hyphens/underscores/asterisks into horizontal rules.
* Convert all lone series of three or more dashes/underscores/asterisks into horizontal rules.
*/
sMD = sMD.replace(/(^|\n\n+)(-\s*-\s*-+|_\s*_\s*_+|\*\s*\*\s*\*+)\s*(\n\n+|$)+/g, "$1<hr/>$3");

View file

@ -10,8 +10,8 @@ PDP-11 Machine Emulation Module (PDPjs)
Overview
---
PDPjs, our PDP-11 machine emulation module, is adapted from
the [PDP 11/70 Emulator (v1.4)](http://skn.noip.me/pdp11/pdp11.html) written by
[Paul Nankervis](mailto:paulnank@hotmail.com).
the [PDP-11/70 Emulator (v1.4)](http://skn.noip.me/pdp11/pdp11.html) written by
Paul Nankervis.
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/debugger/) and [PDP-11/70 with VT100 Terminal](/devices/pdp11/machine/1170/vt100/debugger/).

View file

@ -283,7 +283,7 @@ BusPDP11.IOController = {
}
bus.fault(addr, PDP11.CPUERR.TIMEOUT, PDP11.ACCESS.READ_BYTE);
b = 0xff;
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(afn[BusPDP11.IOHANDLER.MSG_CATEGORY])) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
this.dbg.printMessage("warning: unconverted read access to byte @" + this.dbg.toStrBase(addr) + ": " + this.dbg.toStrBase(b), true, !bus.nDisableFaults);
}
return b;
@ -360,6 +360,7 @@ BusPDP11.IOController = {
* then presumably the handler is prepared for it (certainly, writeROMByte() is).
*/
afn[BusPDP11.IOHANDLER.WRITE_BYTE](b, addrMasked);
fWrite = true;
}
}
}
@ -370,7 +371,7 @@ BusPDP11.IOController = {
return;
}
bus.fault(addr, PDP11.CPUERR.TIMEOUT, PDP11.ACCESS.WRITE_BYTE);
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(afn[BusPDP11.IOHANDLER.MSG_CATEGORY])) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
this.dbg.printMessage("warning: unconverted write access to byte @" + this.dbg.toStrBase(addr) + ": " + this.dbg.toStrBase(b), true, !bus.nDisableFaults);
}
},
@ -410,7 +411,7 @@ BusPDP11.IOController = {
}
bus.fault(addr, PDP11.CPUERR.TIMEOUT, PDP11.ACCESS.READ_WORD);
w = 0xffff;
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(afn[BusPDP11.IOHANDLER.MSG_CATEGORY])) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
this.dbg.printMessage("warning: unconverted read access to word @" + this.dbg.toStrBase(addr) + ": " + this.dbg.toStrBase(w), true, !bus.nDisableFaults);
}
return w;
@ -453,7 +454,7 @@ BusPDP11.IOController = {
return;
}
bus.fault(addr, PDP11.CPUERR.TIMEOUT, PDP11.ACCESS.WRITE_WORD);
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(afn[BusPDP11.IOHANDLER.MSG_CATEGORY])) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(MessagesPDP11.BUS)) {
this.dbg.printMessage("warning: unconverted write access to word @" + this.dbg.toStrBase(addr) + ": " + this.dbg.toStrBase(w), true, !bus.nDisableFaults);
}
}

View file

@ -1122,7 +1122,34 @@ PDP11.opHALT = function(opCode)
this.trap(PDP11.TRAP.BUS, 0, PDP11.REASON.HALT);
} else {
if (this.panel) {
this.panel.setData(this.regsGen[0], true);
/*
* The PDP-11/20 Handbook (1971) says that HALT does the following:
*
* Causes the processor operation to cease. The console is given control of the bus.
* The console data lights display the contents of RO; the console address lights display
* the address after the halt instruction. Transfers on the UNIBUS are terminated immediately.
* The PC points to the next instruction to be executed. Pressing the continue key on the
* console causes processor operation to resume. No INIT signal is given.
*
* However, the PDP-11/70 Handbook (1979) suggests some slight differences:
*
* Causes the processor operation to cease. The console is given control of the processor.
* The data lights display the contents of the PC (which is the address of the HALT instruction
* plus 2). Transfers on the UNIBUS are terminated immediately. Pressing the continue key on
* the console causes processor operation to resume.
*
* Given that the 11/70 doesn't saying anything about displaying R0 on a HALT, and also given that
* the 11/70 CPU EXERCISER diagnostic writes a value to the Console Switch/Display Register immediately
* before HALT'ing, I'm going to assume that updating the data display with R0 is unique to the 11/20.
*
* Also, I'm a little suspicious of the 11/70 comment that the "data lights display the contents of
* the PC," since previous models display the PC on the ADDRESS lights, not the DATA lights. And as
* I already explained, doing anything to the data lights at this point would undo what the 11/70
* diagnostics do.
*/
if (this.model == PDP11.MODEL_1120) {
this.panel.setData(this.regsGen[0], true);
}
}
if (!this.dbg) {
/*
@ -1443,8 +1470,7 @@ PDP11.opNOP = function(opCode)
PDP11.opRESET = function(opCode)
{
if (!(this.regPSW & PDP11.PSW.CMODE)) {
this.bus.reset();
this.resetRegs();
this.resetCPU();
}
this.nStepCycles -= 667; // TODO: Review (but it's definitely a big number)
};
@ -1507,7 +1533,12 @@ PDP11.opRTI = function(opCode)
{
this.trapReturn();
/*
* Unlike RTT, RTI enables immediate trace
* Unlike RTT, RTI permits an immediate trace, which we resolve by propagating PSW.TF to OPFLAG.TRAP_TF
* (which, as written below, requires that both flags have the same bit value; see defines.js).
*
* NOTE: This RTI trace behavior is NEW for machines that have both RTI and RTT. Early models didn't have RTT,
* so the old RTI behaved exactly like the new RTT. Which is why the 11/20 jump table below calls opRTT() instead
* of opRTI() for RTI.
*/
this.opFlags |= (this.regPSW & PDP11.PSW.TF);
this.nStepCycles -= (10 + 3);
@ -1528,7 +1559,7 @@ PDP11.opRTS = function(opCode)
var src = this.popWord();
var reg = opCode & PDP11.OPREG.MASK;
/*
* When the popular "RTS PC" form is used, we might as well eliminate the useless setting of PC to
* When the popular "RTS PC" form is used, we might as well eliminate the useless setting of PC...
*/
if (reg == PDP11.REG.PC) {
this.setPC(src);
@ -2057,7 +2088,7 @@ PDP11.aOp00Xn_1120 = [
PDP11.aOp000X_1120 = [
PDP11.opHALT, // 0x0000 000000 11/20+ 1.8
PDP11.opWAIT, // 0x0001 000001 11/20+ 1.8
PDP11.opRTI, // 0x0002 000002 11/20+ 4.8
PDP11.opRTT, // 0x0002 000002 11/20+ 4.8 (this is really RTI, but on the 11/20, it behaves like RTT)
PDP11.opBPT, // 0x0003
PDP11.opIOT, // 0x0004 000004 11/20+ 9.3
PDP11.opRESET, // 0x0005 000005 11/20+ 20ms

View file

@ -225,6 +225,17 @@ CPUStatePDP11.prototype.initRegs = function()
this.resetRegs();
};
/**
* resetCPU()
*
* @this {CPUStatePDP11}
*/
CPUStatePDP11.prototype.resetCPU = function()
{
this.bus.reset();
this.resetRegs();
};
/**
* resetRegs()
*
@ -394,7 +405,11 @@ CPUStatePDP11.prototype.setMMR3 = function(newMMR3)
CPUStatePDP11.prototype.setReset = function(addr, fReset)
{
this.addrReset = addr;
this.resetCPU();
this.setPC(addr);
this.setPSW(0);
if (!fReset && this.dbg) {
/*
* TODO: Review the decision to always stop the CPU if the Debugger is loaded. Note that
@ -745,7 +760,7 @@ CPUStatePDP11.prototype.removeTrigger = function(trigger)
triggerPrev = triggerNext;
}
}
// We could also set trigger.next to null now, but strictly speaking, that shouldn't be necessary
// We could also set trigger.next to null now, but strictly speaking, that shouldn't be necessary.
};
/**
@ -757,16 +772,12 @@ CPUStatePDP11.prototype.removeTrigger = function(trigger)
*/
CPUStatePDP11.prototype.setTrigger = function(trigger)
{
/*
* We COULD dispatch interrupts immediately, but there are compatibility reasons for ONLY doing so
* inside the stepCPU() loop; see that function for details.
*
* if (this.dispatchInterrupt(trigger.vector, trigger.priority)) {
* return true;
* }
*/
this.insertTrigger(trigger);
this.opFlags |= PDP11.OPFLAG.INTQ;
/*
* See the writeXCSR() function for an explanation of why signalling an INTQ hardware interrupt condition
* should be done using INTQ_DELAY rather than setting INTQ directly.
*/
this.opFlags |= PDP11.OPFLAG.INTQ_DELAY;
return false;
};
@ -2347,7 +2358,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
* nDebugCheck is 1 if we want the Debugger's checkInstruction() to check every instruction,
* -1 if we want it to check just the first instruction, and 0 if there's no need for any checks.
*/
var nDebugCheck = (DEBUGGER && this.dbg && this.dbg.checksEnabled())? 1 : (this.flags.starting? -1 : 0);
var nDebugCheck = (DEBUGGER && this.dbg)? (this.dbg.checksEnabled()? 1 : (this.flags.starting? -1 : 0)) : 0;
/*
* nDebugState is needed only when nDebugCheck is non-zero; it is -1 if this is a single-step, 0 if
@ -2371,7 +2382,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
do {
if (DEBUGGER && nDebugCheck) {
if (this.dbg && this.dbg.checkInstruction(this.getPC(), nDebugState)) {
if (this.dbg.checkInstruction(this.getPC(), nDebugState)) {
this.stopCPU();
break;
}
@ -2380,6 +2391,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
}
if (this.opFlags) {
/*
* If we're in the INTQ or WAIT state, check for any pending interrupts.
*
@ -2390,6 +2402,10 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
*/
if ((this.opFlags & (PDP11.OPFLAG.INTQ_MASK | PDP11.OPFLAG.WAIT)) /* && nDebugState >= 0 */) {
if (this.checkInterrupts()) {
if (DEBUGGER && nDebugCheck && this.dbg.checkInstruction(this.getPC(), nDebugState)) {
this.stopCPU();
break;
}
/*
* Since an interrupt was just dispatched, altering the normal flow of time and changing
* the future as we knew it, let's break out immediately if we're single-stepping, so that
@ -2400,6 +2416,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
if (nDebugState < 0) break;
}
}
/*
* Next, check for any pending traps (which, as noted above, must be done after checkInterrupts()).
*
@ -2409,6 +2426,10 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
*/
if (this.opFlags & PDP11.OPFLAG.TRAP_MASK) {
if (this.checkTraps()) {
if (DEBUGGER && nDebugCheck && this.dbg.checkInstruction(this.getPC(), nDebugState)) {
this.stopCPU();
break;
}
if (nDebugState < 0) break;
}
}

View file

@ -266,7 +266,7 @@ if (DEBUGGER) {
* Register numbers 0-7 are reserved for cpu.regsGen, 8-15 are reserved for cpu.regsAlt, and 16-19 for cpu.regsStack.
*/
DebuggerPDP11.REG_PSW = 20;
DebuggerPDP11.REG_SW = 21;
DebuggerPDP11.REG_SR = 21; // SWITCH register; see Panel's getSR() and setSR()
/*
* Operand type masks; anything that's not covered by OP_SRC or OP_DST must be a OP_OTHER value.
@ -1127,7 +1127,7 @@ if (DEBUGGER) {
case "PC":
iReg = 7;
break;
case "SW":
case "SR":
iReg = 21;
break;
default:
@ -1156,7 +1156,7 @@ if (DEBUGGER) {
* getRegValue(iReg)
*
* Register numbers 0-7 are reserved for cpu.regsGen, 8-15 are reserved for cpu.regsAlt,
* 16-19 for cpu.regsAltStack, 20 for regPSW, and 21 for regSW.
* 16-19 for cpu.regsAltStack, 20 for regPSW, and 21 for SR (SWITCH register).
*
* @this {DebuggerPDP11}
* @param {number} iReg
@ -1178,8 +1178,8 @@ if (DEBUGGER) {
else if (iReg == DebuggerPDP11.REG_PSW) {
value = this.cpu.getPSW();
}
else if (iReg == DebuggerPDP11.REG_SW && this.panel && this.panel.hasSwitches()) {
value = this.panel.getSW();
else if (iReg == DebuggerPDP11.REG_SR && this.panel && this.panel.hasSwitches()) {
value = this.panel.getSR();
}
}
return value;
@ -2392,8 +2392,8 @@ if (DEBUGGER) {
else if (iReg == DebuggerPDP11.REG_PSW) {
sReg = "PS=" + this.toStrBase(cpu.getPSW());
}
else if (iReg == DebuggerPDP11.REG_SW && this.panel && this.panel.hasSwitches()) {
sReg = "SW=" + this.toStrBase(this.panel.getSW(), 3);
else if (iReg == DebuggerPDP11.REG_SR && this.panel && this.panel.hasSwitches()) {
sReg = "SR=" + this.toStrBase(this.panel.getSR(), 3);
}
if (sReg) sReg += ' ';
return sReg;
@ -2419,7 +2419,7 @@ if (DEBUGGER) {
}
sDump += '\n';
sDump += this.getRegOutput(PDP11.REG.SP) + this.getRegOutput(PDP11.REG.PC);
sDump += this.getRegOutput(DebuggerPDP11.REG_PSW) + this.getRegOutput(DebuggerPDP11.REG_SW);
sDump += this.getRegOutput(DebuggerPDP11.REG_PSW) + this.getRegOutput(DebuggerPDP11.REG_SR);
sDump += this.getFlagOutput('T') + this.getFlagOutput('N') + this.getFlagOutput('Z') + this.getFlagOutput('V') + this.getFlagOutput('C');
return sDump;
};
@ -3435,9 +3435,9 @@ if (DEBUGGER) {
case "C":
if (w) cpu.setCF(); else cpu.clearCF();
break;
case "SW":
case "SR":
if (this.panel && this.panel.hasSwitches()) {
this.panel.setSW(w);
this.panel.setSR(w);
break;
}
/* falls through */

View file

@ -158,7 +158,7 @@ var PDP11 = {
MASK: 0x3
},
/*
* Processor Status flag definitions (stored in regPSW)
* Processor Status Word definitions (stored in regPSW)
*/
PSW: {
CF: 0x0001, // bit 0 (000001) Carry Flag
@ -185,6 +185,49 @@ var PDP11 = {
CMODE: 14
}
},
/*
* PDP-11 trap vectors
*/
TRAP: {
UNDEFINED: 0x00, // 000 (reserved)
BUS: 0x04, // 004 unaligned address, non-existent memory, illegal instruction, etc
RESERVED: 0x08, // 010 reserved instructions
BPT: 0x0C, // 014 BPT: breakpoint trap (trace)
IOT: 0x10, // 020 IOT: input/output trap
PF: 0x14, // 024 power fail
EMT: 0x18, // 030 EMT: emulator trap
TRAP: 0x1C, // 034 TRAP instruction
PIRQ: 0xA0, // 240 PIRQ: program interrupt request
MMU: 0xA8 // 250 MMU: aborts and traps
},
/*
* PDP-11 trap reasons; the reason may also be a non-negative address indicating a BUS memory error
* (unaligned address or non-existent memory). Any reason >= RED (which includes BUS memory errors) generate
* immediate (thrown) traps, as they are considered ABORTs; the rest generate synchronous traps.
*/
REASON: {
ABORT: -1, // immediate MMU fault
ILLEGAL: -2, // immediate invalid opcode (BUS)
RED: -3, // immediate stack overflow fault (BUS)
YELLOW: -4, // deferred stack overflow fault (BUS)
FAULT: -5, // deferred MMU fault
TRACE: -6, // deferred TF fault (BPT)
HALT: -7, // illegal HALT (BUS)
OPCODE: -8, // opcode-generated trap (eg, BPT, EMT, IOT, TRAP, or RESERVED opcode)
INTERRUPT: -9, // device-generated trap (vector is device-specific)
},
REASONS: [
"UNKNOWN",
"ABORT",
"ILLEGAL",
"RED",
"YELLOW",
"FAULT",
"TRACE",
"HALT",
"OPCODE",
"INTERRUPT"
],
/*
* Assorted common opcodes
*/
@ -202,7 +245,7 @@ var PDP11 = {
INTQ_MASK: 0x03,
WAIT: 0x04, // WAIT operation in progress
TRAP: 0x08, // set if last operation was a trap (see trapLast for the vector, and trapReason for the reason)
TRAP_TF: 0x10, // aka PDP11.PSW.TF
TRAP_TF: 0x10, // aka PDP11.PSW.TF (WARNING: do not change this bit, or you will likely break opRTI())
TRAP_SP: 0x20, // set for a deferred BUS trap (due to a "yellow" stack overflow condition)
TRAP_MMU: 0x40,
TRAP_MASK: 0x70,
@ -246,48 +289,6 @@ var PDP11 = {
SP: 6,
PC: 7,
},
/*
* PDP-11 trap vectors
*/
TRAP: {
UNDEFINED: 0x00, // 000 (reserved)
BUS: 0x04, // 004 unaligned address, non-existent memory, illegal instruction, etc
RESERVED: 0x08, // 010 reserved instructions
BPT: 0x0C, // 014 BPT: breakpoint trap (trace)
IOT: 0x10, // 020 IOT: input/output trap
PF: 0x14, // 024 power fail
EMT: 0x18, // 030 EMT: emulator trap
TRAP: 0x1C, // 034 TRAP instruction
PIRQ: 0xA0, // 240 PIRQ: program interrupt request
MMU: 0xA8 // 250 MMU: aborts and traps
},
/*
* PDP-11 trap reasons; the reason may also be a non-negative address indicating a BUS memory error
* (unaligned address or non-existent memory). Any reason >= RED (which includes BUS memory errors) generate
* immediate (thrown) traps; the rest generate synchronous traps.
*/
REASON: {
ABORT: -1, // immediate MMU fault
ILLEGAL: -2, // immediate invalid opcode (BUS)
RED: -3, // immediate stack overflow fault (BUS)
YELLOW: -4, // deferred stack overflow fault (BUS)
FAULT: -5, // deferred MMU fault
TRACE: -6, // deferred TF fault (BPT)
HALT: -7, // illegal HALT (BUS)
OPCODE: -8, // opcode-generated trap (eg, BPT, EMT, IOT, TRAP, or RESERVED opcode)
INTERRUPT: -9, // device-generated trap (vector is device-specific)
},
REASONS: [
"ABORT",
"ILLEGAL",
"RED",
"YELLOW",
"FAULT",
"TRACE",
"HALT",
"OPCODE",
"INTERRUPT"
],
/*
* Internal memory access flags
*/
@ -458,7 +459,7 @@ var PDP11 = {
XCSR: 0o177564, // Display Terminal: Transmitter Status Register
XBUF: 0o177566, // Display Terminal: Transmitter Data Buffer Register
CNSW: 0o177570, // Console (Front Panel) Switch Register
CNSW: 0o177570, // Console (Front Panel) Switch/Display Register
MMR0: 0o177572, // 777572 17777572
MMR1: 0o177574, // 777574 17777574

View file

@ -176,23 +176,23 @@ PanelPDP11.LED = {
};
/**
* getSW()
* getSR()
*
* @this {PanelPDP11}
* @return {number}
* @return {number} (current SWITCH register)
*/
PanelPDP11.prototype.getSW = function()
PanelPDP11.prototype.getSR = function()
{
return this.regSwitches;
};
/**
* setSW(value)
* setSR(value)
*
* @this {PanelPDP11}
* @param {number} value
* @param {number} value (new SWITCH register)
*/
PanelPDP11.prototype.setSW = function(value)
PanelPDP11.prototype.setSR = function(value)
{
this.setSwitches(value);
};

View file

@ -543,6 +543,11 @@ SerialPortPDP11.prototype.transmitByte = function(b)
}
}
/*
* TODO: Why do DEC diagnostics like to output bytes with bit 7 set?
*/
b &= 0x7F;
if (this.controlIOBuffer) {
if (b == 0x0D) {
this.iLogicalCol = 0;
@ -657,10 +662,19 @@ SerialPortPDP11.prototype.readXCSR = function(addr)
SerialPortPDP11.prototype.writeXCSR = function(data, addr)
{
/*
* If the device is READY, and TIE is being set, then request an interrupt.
* If the device is READY, and TIE is being set, then request a hardware interrupt.
*
* Conversely, if TIE is being cleared, remove the request; this satisfies a test in MAINDEC TEST 15,
* which appears to clear, set, and clear the Transmitter Interrupt Enable (TIE) bit in rapid succession,
* with the expectation that NO interrupt will be generated. However, this fix also requires a
* complementary change in setTrigger(), to request hardware interrupts with INTQ_DELAY rather than INTQ.
*/
if ((this.xcsr & PDP11.DL11.XCSR.READY) && (data & PDP11.DL11.XCSR.TIE)) {
this.cpu.setTrigger(this.triggerTransmitInterrupt);
if (this.xcsr & PDP11.DL11.XCSR.READY) {
if (data & PDP11.DL11.XCSR.TIE) {
this.cpu.setTrigger(this.triggerTransmitInterrupt);
} else {
this.cpu.removeTrigger(this.triggerTransmitInterrupt);
}
}
this.xcsr = (this.xcsr & ~PDP11.DL11.XCSR.WMASK) | (data & PDP11.DL11.XCSR.WMASK);
};

View file

@ -565,7 +565,7 @@ str.aASCIICodes = {
// 0x0A: "LF", // (CTRL_J) Line Feed (New Line)
0x0B: "VT", // (CTRL_K) Vertical Tab
0x0C: "FF", // (CTRL_L) Form Feed (New Page)
0x0D: "CR", // (CTRL_M) Carriage Return
// 0x0D: "CR", // (CTRL_M) Carriage Return
0x0E: "SO", // (CTRL_N) Shift Out
0x0F: "SI", // (CTRL_O) Shift In
0x10: "DLE", // (CTRL_P) Data Link Escape