Started executing basic PDP-10 instruction diagnostic #1

This commit is contained in:
Jeff 2017-03-17 00:01:49 -07:00 committed by Jeff Parsons
commit 9c96ec14ad
7 changed files with 362 additions and 288 deletions

View file

@ -2232,7 +2232,31 @@ PDP10.opAOBJN = function(op, acc)
*/
PDP10.opJRST = function(op, acc)
{
this.opUndefined(op);
if (acc & 0b0001) {
/*
* Enter user mode.
*/
this.setUserMode();
}
if (acc & 0b0010) {
/*
* Restore the flags.
*/
this.setPS(this.regLA);
}
if (acc & 0b0100) {
/*
* Halt the processor.
*/
this.stopCPU();
}
if (acc & 0b1000) {
/*
* Restore interrupt channel.
*/
this.opUndefined(op);
}
this.setPC(this.regEA);
};
/**

View file

@ -174,7 +174,12 @@ class CPUStatePDP10 extends CPUPDP10 {
*/
initCPU()
{
this.regEA = this.regRA = this.regOP = 0;
/*
* regEA is the last effective address, while regLA is the last fetch from an effective address
* calculation. regRA is the last reference address used to calculate the last effective address.
*/
this.regEA = this.regRA = 0;
this.regLA = this.regOP = 0;
this.regPC = this.lastPC = this.addrReset;
this.regXC = -1; // if >= 0 this supersedes regPC (refers to an opcode from XCT)
this.regBP = -1; // active byte pointer (-1 if none)
@ -287,6 +292,7 @@ class CPUStatePDP10 extends CPUPDP10 {
state.set(0, [
this.regEA,
this.regRA,
this.regLA,
this.regOP,
this.regPC,
this.regXC,
@ -320,6 +326,7 @@ class CPUStatePDP10 extends CPUPDP10 {
[
this.regEA,
this.regRA,
this.regLA,
this.regOP,
this.regPC,
this.regXC,
@ -355,6 +362,38 @@ class CPUStatePDP10 extends CPUPDP10 {
return (this.regPS & PDP10.HALF_MASK) * PDP10.HALF_SHIFT;
}
/**
* setPS(w)
*
* Sets the processor state flags in the format used by various program control operations (eg, JRST).
*
* @this {CPUStatePDP10}
* @param {number} w
*/
setPS(w)
{
w = (w / PDP10.HALF_SHIFT)|0;
this.regPS = (this.regPS & ~PDP10.PSFLAG.SET_MASK) | (w & PDP10.PSFLAG.SET_MASK);
this.regPS |= (w & PDP10.PSFLAG.USER_MODE);
if (!(w & PDP10.PSFLAG.USER_IO)) {
this.regPS &= ~PDP10.PSFLAG.USER_IO;
} else {
if (!(this.regPS & PDP10.PSFLAG.USER_MODE)) this.regPS |= PDP10.PSFLAG.USER_IO;
}
}
/**
* setUserMode()
*
* Sets the processor's USER_MODE flag.
*
* @this {CPUStatePDP10}
*/
setUserMode()
{
this.regPS |= PDP10.PSFLAG.USER_MODE;
}
/**
* readFlags()
*
@ -401,7 +440,7 @@ class CPUStatePDP10 extends CPUPDP10 {
getOpcode()
{
if ((this.regRA & PDP10.OPCODE.I_BIT)) {
this.regRA = this.readWord(this.regEA);
this.regRA = this.regLA = this.readWord(this.regEA);
} else if (this.regXC >= 0) {
this.regRA = this.regOP = this.readWord(this.regXC);
this.regXC = -1;
@ -429,7 +468,7 @@ class CPUStatePDP10 extends CPUPDP10 {
*/
this.regEA = this.regRA & PDP10.OPCODE.Y_MASK;
var x = (this.regRA >> PDP10.OPCODE.X_SHIFT) & PDP10.OPCODE.X_MASK;
if (x) this.regEA = (this.regEA + this.readWord(x)) & PDP10.ADDR_MASK;
if (x) this.regEA = (this.regEA + (this.regLA = this.readWord(x))) & PDP10.ADDR_MASK;
return (this.regRA & PDP10.OPCODE.I_BIT)? -1 : ((this.regOP / PDP10.OPCODE.A_SCALE)|0);
}

View file

@ -1546,14 +1546,13 @@ class DebuggerPDP10 extends Debugger {
} else {
n = (opCode >> PDP10.OPCODE.A_SHIFT) & PDP10.OPCODE.A_MASK;
sOperand = this.toStrBase(n, -1);
if (n) {
for (var m = 0; m < DebuggerPDP10.ALTOPS.length; m++) {
if (opNum == DebuggerPDP10.ALTOPS[m][0]) {
var opAlt = DebuggerPDP10.ALTOPS[m][n];
if (opAlt) {
sOperation = DebuggerPDP10.OPNAMES[opAlt];
sOperand = "";
}
for (var m = 0; sOperand && m < DebuggerPDP10.ALTOPS.length; m++) {
if (opNum == DebuggerPDP10.ALTOPS[m][0]) {
var opAlt = DebuggerPDP10.ALTOPS[m][n];
if (opAlt) {
sOperation = DebuggerPDP10.OPNAMES[opAlt];
sOperand = "";
break;
}
}
}
@ -2476,20 +2475,20 @@ class DebuggerPDP10 extends Debugger {
*/
loadBin(aWords, addrLoad)
{
/*
* TODO: Decide what to do about addrLoad; either drop it or use it.
*/
var nWords = 0;
var bus = this.bus;
var dbg = this.dbg;
aWords.forEach(function(w, addr) {
bus.setWordDirect(addr, w);
if (addrLoad == null) addrLoad = addr;
nWords++;
});
if (!nWords) {
this.println("no data");
} else {
this.println(nWords + " words loaded at " + this.toStrBase(addrLoad) + '-' + this.toStrBase(addrLoad + nWords - 1));
this.cpu.setPC(addrLoad || 0);
this.updateStatus();
}
}
@ -2850,7 +2849,7 @@ class DebuggerPDP10 extends Debugger {
if (dbgAddr.nBase) this.nBase = dbgAddr.nBase;
var size = (sCmd == "db"? 1 : 2);
var nWords = len || 16;
var nWords = len || 32;
var nWordsPerLine = (size == 1? 1 : 4);
var nLines = (((nWords + nWordsPerLine - 1) / nWordsPerLine)|0) || 1;
@ -2875,7 +2874,7 @@ class DebuggerPDP10 extends Debugger {
var shift = 36 - nBits;
for (var i = 0; size == 1 && shift >= 0; i++) {
var c = ((w / Math.pow(2, shift)) % Math.pow(2, nBits));
sData += this.toStrBase(c, nBits) + ' ';
sData += this.toStrBase(c, nBits);
c += (nBits == 6? 0x20 : 0);
sChars += (c < 0x20? '.' : String.fromCharCode(c));
shift -= nBits;

View file

@ -201,15 +201,16 @@ var PDP10 = {
* binary, the only options you can set relate to the operating system to be run -- which seems very hacky.
*/
PSFLAG: {
OVFL: 0o400000, // Overflow
CARRY0: 0o200000, // Carry 0
CARRY1: 0o100000, // Carry 1
FP_OVFL: 0o040000, // Floating-Point Overflow
BYTE_INT: 0o020000, // Byte Interrupt
USER_MODE: 0o010000, // Processor is in User Mode
USER_IO: 0o004000, // User I/O
FP_UNFL: 0o000100, // Floating-Point Underflow
NO_DIVIDE: 0o000040, // No Divide
OVFL: 0o400000, // Overflow
CARRY0: 0o200000, // Carry 0
CARRY1: 0o100000, // Carry 1
FP_OVFL: 0o040000, // Floating-Point Overflow
BYTE_INT: 0o020000, // Byte Interrupt
USER_MODE: 0o010000, // Processor is in User Mode
USER_IO: 0o004000, // User I/O
FP_UNFL: 0o000100, // Floating-Point Underflow
NO_DIVIDE: 0o000040, // No Divide
SET_MASK: 0o760140, // the flags that are always settable/clearable
/*
* Only the low 18 bits (above) are returned by getPS(); the following (bits 18 to 31)
* are defined for internal use only.

View file

@ -603,14 +603,18 @@ class Debugger extends Component
/**
* parseArray(asValues, iValue, iLimit, nBase, fQuiet)
*
* Helper function for parseExpression().
* parseExpression() takes a complete expression and divides it into array elements, where even elements
* are values (which may be empty if two or more operators appear consecutively) and odd elements are operators.
*
* Imagine the original expression was "2*{3+{4/2}}". parseExpression() divides it into array elements:
* For example, if the original expression was "2*{3+{4/2}}", parseExpression() would call parseArray() with:
*
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
* - - - - - - - - - - -- -- -- -- --
* 2 * _ { 3 + _ { 4 / 2 } _ } _
*
* This function takes care of recursively processing sub-expressions, by processing subsets of the array,
* as well as handling certain base overrides (eg, temporarily switching to base-10 for binary shift suffixes).
*
* @param {Array.<string>} asValues
* @param {number} iValue
* @param {number} iLimit
@ -742,11 +746,13 @@ class Debugger extends Component
/*
* The default grouping characters for sub-expressions are braces; they can be changed by altering
* achGroup, but when that happens, we replace them all with braces anyway, for consistent parsing.
* achGroup, but when that happens, instead of changing our regular expressions and operator tables,
* we simply replace all achGroup characters with braces in the given expression.
*
* Why not just always use parentheses for sub-expressions? Because some debuggers use parseReference()
* to perform parenthetical value replacements in message strings, and they don't want parentheses taking
* on a new meaning in those strings.
* on a different meaning. And for some machines, like the PDP-10, the convention is to use parentheses
* for indexed addressing and angle brackets for sub-expressions.
*/
if (this.achGroup[0] != '{') {
sExp = sExp.split(this.achGroup[0]).join('{').split(this.achGroup[1]).join('}');
@ -758,7 +764,7 @@ class Debugger extends Component
* matches along with the non-matches. This effectively means that, in the set of expressions that we
* support, all even entries in asValues will contain "values" and all odd entries will contain "operators".
*
* Although I starting listing the operators in the RegExp in "precedential" order, that's not important;
* Although I started listing the operators in the RegExp in "precedential" order, that's not important;
* what IS important is listing operators than contain shorter operators first. For example, bitwise
* shift operators must be listed BEFORE the logical less-than or greater-than operators.
*
@ -767,11 +773,12 @@ class Debugger extends Component
* I've added '!' as an alias for '|' to perform bitwise inclusive-or.
*
* The MACRO-10 binary shifting suffix ('B') is a bit more problematic, since a capital B can also appear
* inside symbols. So I pre-scan for that operator and replace appropriate occurrences with an internal
* inside symbols. So I pre-scan for that operator and replace non-symbolic occurrences with an internal
* operator ('><').
*
* Note that Str.parseInt(), which parseValue() relies on, supports both the MACRO-10 base prefix overrides
* and the binary shifting suffix.
* and the binary shifting suffix. But since the B suffix can also be a bracketed expression, we have to
* support it here as well.
*
* MACRO-10 supports only a subset of all the PCjs operators; for example, MACRO-10 doesn't support bitwise
* exclusive-or, shift operators, or any of the boolean logical/compare operators. But unless we run into
@ -1063,9 +1070,9 @@ if (DEBUGGER) {
'%': 9, // remainder
'/': 9, // division
'*': 9, // multiplication
'><': 10, // internal binary shifting (MACRO-10-style)
'{': 11,
'}': 11
'><': 10, // internal binary shift operator (MACRO-10-style; converted from a 'B' suffix)
'{': 11, // open sub-expression (achGroup[0] default)
'}': 11 // close sub-expression (achGroup[1] default)
};
/*