Merge branch 'next-release'
This commit is contained in:
commit
1ad03d1cd4
54 changed files with 4528 additions and 3436 deletions
|
|
@ -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 = "";
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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/).
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue