Added getTrapStatus() so that the Debugger can display trap information whenever a trap has just occurred, updated FileDump to store 'load' and 'exec' properties in MACRO-11 listing dumps (so that the individual machine files don't have to specify hard-coded 'load' and 'exec' values themselves), and added a new SerialPort parameter (upperCase) that can be used to force all received data to upper-case

This commit is contained in:
Jeff Parsons 2016-10-21 21:07:26 -07:00 committed by Jeff Parsons
commit 5808778351
24 changed files with 269 additions and 182 deletions

View file

@ -55,6 +55,7 @@ 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);
@ -297,7 +298,6 @@ FileDump.prototype.parseListing = function(sListing)
var ab = [];
var matchLine;
var re = /^( [0-9 ]{8}|)([0-7]{6})[: ]+([0-7]+)[ ]*([0-7']+|)[ ]+([0-7']+|)[ ]+(.*)$/gm;
var addrStart = null;
while (matchLine = re.exec(sListing)) {
/*
* matchLine[1]: line # (optional)
@ -307,7 +307,7 @@ FileDump.prototype.parseListing = function(sListing)
* matchLine[5]: 6-digit operand (with optional apostrophe) or 3-digit data
*/
var addrLine = parseInt(matchLine[2], 8);
if (addrStart == null) addrStart = addrLine;
if (this.addrLoad == null) this.addrLoad = addrLine;
for (var i = 3, s; i <= 5 && (s = matchLine[i]); i++) {
var data = parseInt(s.substr(0, 6), 8);
if (s.length == 3) {
@ -481,7 +481,17 @@ FileDump.prototype.dumpBuffer = function(sKey, buf, len, cbItem, offDump, nWidth
offDump = offDump || this.offDump;
nWidthDump = nWidthDump || this.nWidthDump;
var sDump = this.dumpLine(2, (sKey? '"' + sKey + '":' : "") + this.sJSONWhitespace + chOpen);
var sDump = "";
if (this.addrLoad) {
/*
* 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 + ',');
}
sDump += this.dumpLine(2, (sKey? '"' + sKey + '":' : "") + this.sJSONWhitespace + chOpen);
var sLine = "";
var sASCII = "";

View file

@ -1162,6 +1162,13 @@ CPUStatePDP11.prototype.trap = function(vector, reason)
this.opFlags &= ~PDP11.OPFLAG.TRAP_MASK; // lose interest in traps after an abort
this.trapPSW = -1; // reset flag that we have a trap within a trap
/*
* These next properties are purely for bookkeeping purposes; see getTrapStatus()
*/
this.opFlags |= PDP11.OPFLAG.TRAP;
this.trapVector = vector;
this.trapReason = reason;
if (reason != PDP11.REASON.INTERRUPT) throw vector;
};
@ -1192,6 +1199,17 @@ CPUStatePDP11.prototype.trapReturn = function()
this.opFlags &= ~PDP11.OPFLAG.TRAP_TF;
};
/**
* getTrapStatus()
*
* @this {CPUStatePDP11}
* @return {number}
*/
CPUStatePDP11.prototype.getTrapStatus = function()
{
return (this.opFlags & PDP11.OPFLAG.TRAP)? (this.trapVector | this.trapReason << 8) : 0;
};
/**
* mapUnibus(unibusAddress)
*

View file

@ -1369,6 +1369,13 @@ if (DEBUGGER) {
if (fRegs === undefined) fRegs = true;
var trapStatus = this.cpu.getTrapStatus();
if (trapStatus) {
var trapReason = trapStatus >> 8;
var sReason = trapReason? (" (" + this.toStrBase(trapReason) + ")") : "";
this.println("trapped to " + this.toStrBase(trapStatus & 0xff, 1) + sReason);
}
this.dbgAddrNextCode = this.newAddr(this.cpu.getPC());
/*
* this.nStep used to be a simple boolean, but now it's 0 (or undefined)

View file

@ -199,6 +199,7 @@ var PDP11 = {
INTQ_SPL: 0x01, // INTQ triggered by SPL
INTQ: 0x02, // call checkInterrupts()
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_MMU: 0x20,
TRAP_SP: 0x40,

View file

@ -61,6 +61,10 @@ if (NODE) {
* tabSize: set to a non-zero number to convert tabs to spaces (applies only to output to
* the above binding); default is 0 (no conversion)
*
* upperCase: if true, all received input is upper-cased; it is normally the responsibility
* of the sending device to ensure this, but sometimes it's more convenient to enforce
* on the receiving end.
*
* NOTE: Since the XSL file defines the 'adapter' and 'baud' properties as numbers, not strings,
* there's no need to use parseInt(), and as an added benefit, we don't need to worry about whether
* a hex or decimal format was used.
@ -74,6 +78,7 @@ function SerialPortPDP11(parmsSerial) {
this.iAdapter = parmsSerial['adapter'];
this.nBaudReceive = parmsSerial['baudReceive'] || PDP11.DL11.RCSR.BAUD;
this.nBaudTransmit = parmsSerial['baudTransmit'] || PDP11.DL11.XCSR.BAUD;
this.fUpperCase = parmsSerial['upperCase'];
/**
* consoleOutput becomes a string that records serial port output if the 'binding' property is set to the
@ -279,6 +284,16 @@ SerialPortPDP11.prototype.initBus = function(cmp, bus, cpu, dbg)
* the data assigned to RBUF with 0xff.
*/
serial.rbuf = serial.abReceive.shift() & 0xff;
if (serial.fUpperCase) {
/*
* Automatically transform lower-case ASCII codes to upper-case; fUpperCase should
* only be set when a terminal or some sort of pseudo-display is being used and we don't
* trust it to have its CAPS-LOCK setting correct.
*/
if (serial.rbuf >= 0x61 && serial.rbuf < 0x7A) {
serial.rbuf -= 0x20;
}
}
serial.rcsr |= PDP11.DL11.RCSR.RD;
if (serial.rcsr & PDP11.DL11.RCSR.RIE) {
serial.cpu.setTrigger(serial.triggerReceiveInterrupt);

View file

@ -889,10 +889,17 @@
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="upperCase">
<xsl:choose>
<xsl:when test="@uppercase"><xsl:value-of select="@uppercase"/></xsl:when>
<xsl:when test="@upperCase"><xsl:value-of select="@upperCase"/></xsl:when>
<xsl:otherwise>false</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="component">
<xsl:with-param name="machine" select="$machine"/>
<xsl:with-param name="class">serial</xsl:with-param>
<xsl:with-param name="parms">,adapter:<xsl:value-of select="$adapter"/>,baudReceive:<xsl:value-of select="$baudReceive"/>,baudTransmit:<xsl:value-of select="$baudTransmit"/>,binding:'<xsl:value-of select="$binding"/>',tabSize:<xsl:value-of select="$tabSize"/>,charBOL:<xsl:value-of select="$charBOL"/></xsl:with-param>
<xsl:with-param name="parms">,adapter:<xsl:value-of select="$adapter"/>,baudReceive:<xsl:value-of select="$baudReceive"/>,baudTransmit:<xsl:value-of select="$baudTransmit"/>,binding:'<xsl:value-of select="$binding"/>',tabSize:<xsl:value-of select="$tabSize"/>,charBOL:<xsl:value-of select="$charBOL"/>,upperCase:<xsl:value-of select="$upperCase"/></xsl:with-param>
</xsl:call-template>
</xsl:template>