Started work on PDP-10 logical operations

This commit is contained in:
Jeff 2017-03-03 11:30:34 -08:00 committed by Jeff Parsons
commit 616f9d4cda
7 changed files with 468 additions and 503 deletions

View file

@ -216,7 +216,7 @@ PDP10.opIBP = function(op, acc)
* but I would like to keep PTR_MASK distinct from both the P and S fields.
*/
w = (p * PDP10.OPCODE.P_SCALE) + (s << PDP10.OPCODE.S_SHIFT) + (w & PDP10.OPCODE.PTR_MASK);
if (inc) w = (w + inc) % PDP10.DATA_LIMIT;
if (inc) w = (w + inc) % PDP10.WORD_LIMIT;
this.writeWord(this.regEA, w);
};
@ -293,7 +293,12 @@ PDP10.opLDB = function(op, acc)
var p = (this.regPS / PDP10.OPCODE.P_SCALE) & PDP10.OPCODE.P_MASK;
var s = (this.regPS >> PDP10.OPCODE.S_SHIFT) & PDP10.OPCODE.S_MASK;
if (p + s <= 32) {
w = (w >> p) & ((1 << s) - 1);
/*
* WARNING: When using JavaScript's 32-bit operators with values that could set bit 31 and produce a
* negative value, it's critical to perform a final right-shift of 0, ensuring that the final result is
* positive.
*/
w = ((w >> p) & ((1 << s) - 1)) >>> 0;
} else {
/*
* Regarding the SPECIAL CONSIDERATIONS above, even if the P ("shift") and/or S ("mask") values are
@ -382,7 +387,7 @@ PDP10.opDPB = function(op, acc)
* over-large, we "mask" the resulting byte value (b) to 36 bits, so that when we re-assemble the final
* result (w), there shouldn't be any overlap or overflow.
*/
var b = ((this.readWord(acc) % Math.pow(2, s)) * Math.pow(2, p)) % PDP10.DATA_LIMIT;
var b = ((this.readWord(acc) % Math.pow(2, s)) * Math.pow(2, p)) % PDP10.WORD_LIMIT;
w = (w - (w % Math.pow(2, p + s))) + b + (w % Math.pow(2, p));
this.writeWord(this.regEA, w);
this.regPS = -1;
@ -782,6 +787,8 @@ PDP10.opFDVRB = function(op, acc)
*
* NOTE: This is a "Basic" mode instruction: the source is [E] and the destination is [A] (opposite of "Memory").
*
* Equivalents: opSETM(0o414000) and opSETMB(0o417000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
@ -803,6 +810,8 @@ PDP10.opMOVE = function(op, acc)
*
* NOTE: This is an "Immediate" mode instruction: the source is the word 0,E and the destination is [A].
*
* Equivalents: opSETMI(0o415000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
@ -822,6 +831,8 @@ PDP10.opMOVEI = function(op, acc)
*
* NOTE: This is a "Memory" mode instruction: the source is [A] and the destination is [E] (opposite of "Basic").
*
* Equivalents: opSETAM(0o426000) and opSETAB(0o427000).
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
@ -869,7 +880,7 @@ PDP10.opMOVES = function(op, acc)
PDP10.opMOVS = function(op, acc)
{
var src = this.readWord(this.regEA);
src = (src / PDP10.WORD_SHIFT) | ((src & PDP10.WORD_MASK) * PDP10.WORD_SHIFT);
src = ((src / PDP10.HALF_SHIFT)|0) + ((src % PDP10.HALF_SHIFT) * PDP10.HALF_SHIFT);
this.writeWord(acc, src);
};
@ -891,7 +902,7 @@ PDP10.opMOVS = function(op, acc)
*/
PDP10.opMOVSI = function(op, acc)
{
this.writeWord(acc, this.regEA * PDP10.WORD_SHIFT);
this.writeWord(acc, this.regEA * PDP10.HALF_SHIFT);
};
/**
@ -911,7 +922,7 @@ PDP10.opMOVSI = function(op, acc)
PDP10.opMOVSM = function(op, acc)
{
var src = this.readWord(acc);
src = (src / PDP10.WORD_SHIFT) | ((src & PDP10.WORD_MASK) * PDP10.WORD_SHIFT);
src = ((src / PDP10.HALF_SHIFT)|0) + ((src % PDP10.HALF_SHIFT) * PDP10.HALF_SHIFT);
this.writeWord(this.regEA, src);
};
@ -932,7 +943,7 @@ PDP10.opMOVSM = function(op, acc)
PDP10.opMOVSS = function(op, acc)
{
var src = this.readWord(this.regEA);
src = (src / PDP10.WORD_SHIFT) | ((src & PDP10.WORD_MASK) * PDP10.WORD_SHIFT);
src = ((src / PDP10.HALF_SHIFT)|0) + ((src % PDP10.HALF_SHIFT) * PDP10.HALF_SHIFT);
this.writeWord(this.regEA, src);
if (acc) this.writeWord(acc, src)
};
@ -1475,19 +1486,19 @@ PDP10.opBLT = function(op, acc)
{
var fDone = false;
var addrDst = this.readWord(acc);
var addrSrc = (addrDst / PDP10.WORD_SHIFT)|0;
addrDst &= PDP10.WORD_MASK;
var addrSrc = (addrDst / PDP10.HALF_SHIFT)|0;
addrDst &= PDP10.HALF_MASK;
while (!fDone) {
this.writeWord(addrDst, this.readWord(addrSrc));
if (addrDst == this.regEA) fDone = true;
addrSrc = (addrSrc + 1) & PDP10.WORD_MASK;
addrDst = (addrDst + 1) & PDP10.WORD_MASK;
addrSrc = (addrSrc + 1) & PDP10.HALF_MASK;
addrDst = (addrDst + 1) & PDP10.HALF_MASK;
if (!this.isRunning()) {
/*
* Since the CPU isn't currently running, the CPU is presumably being stepped, so we'll treat that the
* same as the "priority interrupt" condition described above, update the accumulator, rewind the PC, and leave.
*/
this.writeWord(acc, addrSrc * PDP10.WORD_SHIFT + addrDst);
this.writeWord(acc, addrSrc * PDP10.HALF_SHIFT + addrDst);
if (!fDone) this.advancePC(-1);
fDone = true;
}
@ -1602,18 +1613,18 @@ PDP10.opPUSH = function(op, acc)
* This is the behavior that is clearly documented by DEC.
*/
p += 0o000001000001;
this.writeWord(p & PDP10.WORD_MASK, this.readWord(this.regEA));
if (p >= PDP10.DATA_LIMIT) p -= PDP10.DATA_LIMIT;
if (!((p / PDP10.WORD_SHIFT) | 0)) this.fPDOverflow = true;
this.writeWord(p & PDP10.HALF_MASK, this.readWord(this.regEA));
if (p >= PDP10.WORD_LIMIT) p -= PDP10.WORD_LIMIT;
if (!((p / PDP10.HALF_SHIFT)|0)) this.fPDOverflow = true;
} else {
/*
* This is the SIMH behavior, which appears to increment each half of AC independently.
*/
var addr = (p + 1) & PDP10.WORD_MASK;
var addr = (p + 1) & PDP10.HALF_MASK;
this.writeWord(addr, this.readWord(this.regEA));
p = (p + 0o000001000000) - (p & PDP10.WORD_MASK) + addr;
if (p >= PDP10.DATA_LIMIT) {
p -= PDP10.DATA_LIMIT;
p = (p + 0o000001000000) - (p & PDP10.HALF_MASK) + addr;
if (p >= PDP10.WORD_LIMIT) {
p -= PDP10.WORD_LIMIT;
this.fPDOverflow = true;
}
}
@ -1639,12 +1650,12 @@ PDP10.opPUSH = function(op, acc)
PDP10.opPOP = function(op, acc)
{
var p = this.readWord(acc);
var src = this.readWord(p & PDP10.WORD_MASK);
var src = this.readWord(p & PDP10.HALF_MASK);
this.writeWord(this.regEA, src);
if (this.regEA == acc) p = src; // this avoids re-reading the accumulator if the write just overwrote it
p -= 0o000001000001;
if (p < 0) p += PDP10.DATA_LIMIT;
if (((p / PDP10.WORD_SHIFT) | 0) == PDP10.WORD_MASK) this.fPDOverflow = true;
if (p < 0) p += PDP10.WORD_LIMIT;
if (((p / PDP10.HALF_SHIFT)|0) == PDP10.HALF_MASK) this.fPDOverflow = true;
this.writeWord(acc, p);
};
@ -2573,7 +2584,7 @@ PDP10.opSOSG = function(op, acc)
};
/**
* opSETZ(0o400000)
* opSETZ(0o400000) and opSETZI(0o401000)
*
* @this {CPUStatePDP10}
* @param {number} op
@ -2581,19 +2592,7 @@ PDP10.opSOSG = function(op, acc)
*/
PDP10.opSETZ = function(op, acc)
{
this.opUndefined(op);
};
/**
* opSETZI(0o401000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETZI = function(op, acc)
{
this.opUndefined(op);
this.writeWord(acc, 0);
};
/**
@ -2605,7 +2604,7 @@ PDP10.opSETZI = function(op, acc)
*/
PDP10.opSETZM = function(op, acc)
{
this.opUndefined(op);
this.writeWord(this.regEA, 0);
};
/**
@ -2617,55 +2616,66 @@ PDP10.opSETZM = function(op, acc)
*/
PDP10.opSETZB = function(op, acc)
{
this.opUndefined(op);
this.writeWord(acc, 0);
this.writeWord(this.regEA, 0);
};
/**
* opAND(0o404000)
*
* Change the contents of the destination specified by M ([AC]) to the AND function of the specified operand ([E]) and [AC].
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opAND = function(op, acc)
{
this.opUndefined(op);
this.writeWord(acc, PDP10.doAND(this.readWord(acc), this.readWord(this.regEA)));
};
/**
* opANDI(0o405000)
*
* Change the contents of the destination specified by M ([AC]) to the AND function of the specified operand (E) and [AC].
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opANDI = function(op, acc)
{
this.opUndefined(op);
this.writeWord(acc, PDP10.doAND(this.readWord(acc), this.regEA));
};
/**
* opANDM(0o406000)
*
* Change the contents of the destination specified by M ([E]) to the AND function of the specified operand ([E]) and [AC].
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opANDM = function(op, acc)
{
this.opUndefined(op);
this.writeWord(this.regEA, PDP10.doAND(this.readWord(acc), this.readWord(this.regEA)));
};
/**
* opANDB(0o407000)
*
* Change the contents of the destination specified by M ([E] and [AC]) to the AND function of the specified operand ([E]) and [AC].
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opANDB = function(op, acc)
{
this.opUndefined(op);
var result = PDP10.doAND(this.readWord(acc), this.readWord(this.regEA));
this.writeWord(this.regEA, result);
this.writeWord(acc, result);
};
/**
@ -2716,54 +2726,6 @@ PDP10.opANDCAB = function(op, acc)
this.opUndefined(op);
};
/**
* opSETM(0o414000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETM = function(op, acc)
{
this.opUndefined(op);
};
/**
* opSETMI(0o415000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETMI = function(op, acc)
{
this.opUndefined(op);
};
/**
* opSETMM(0o416000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETMM = function(op, acc)
{
this.opUndefined(op);
};
/**
* opSETMB(0o417000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETMB = function(op, acc)
{
this.opUndefined(op);
};
/**
* opANDCM(0o420000)
*
@ -2812,54 +2774,6 @@ PDP10.opANDCMB = function(op, acc)
this.opUndefined(op);
};
/**
* opSETA(0o424000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETA = function(op, acc)
{
this.opUndefined(op);
};
/**
* opSETAI(0o425000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETAI = function(op, acc)
{
this.opUndefined(op);
};
/**
* opSETAM(0o426000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETAM = function(op, acc)
{
this.opUndefined(op);
};
/**
* opSETAB(0o427000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETAB = function(op, acc)
{
this.opUndefined(op);
};
/**
* opXOR(0o430000)
*
@ -3053,7 +2967,9 @@ PDP10.opEQVB = function(op, acc)
};
/**
* opSETCA(0o450000)
* opSETCA(0o450000) and opSETCAI(0o451000)
*
* Change the contents of the destination specified by M ([AC]) to the complement of [AC].
*
* @this {CPUStatePDP10}
* @param {number} op
@ -3061,43 +2977,37 @@ PDP10.opEQVB = function(op, acc)
*/
PDP10.opSETCA = function(op, acc)
{
this.opUndefined(op);
};
/**
* opSETCAI(0o451000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETCAI = function(op, acc)
{
this.opUndefined(op);
this.writeWord(acc, PDP10.WORD_MASK - this.readWord(acc));
};
/**
* opSETCAM(0o452000)
*
* Change the contents of the destination specified by M ([E]) to the complement of [AC].
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETCAM = function(op, acc)
{
this.opUndefined(op);
this.writeWord(this.regEA, PDP10.WORD_MASK - this.readWord(acc));
};
/**
* opSETCAB(0o453000)
*
* Change the contents of the destination specified by M ([E] and [AC]) to the complement of [AC].
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETCAB = function(op, acc)
{
this.opUndefined(op);
var dst = PDP10.WORD_MASK - this.readWord(acc);
this.writeWord(acc, dst);
this.writeWord(this.regEA, dst);
};
/**
@ -3151,49 +3061,59 @@ PDP10.opORCAB = function(op, acc)
/**
* opSETCM(0o460000)
*
* Change the contents of the destination specified by M ([AC]) to the complement of the specified source operand ([E]).
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETCM = function(op, acc)
{
this.opUndefined(op);
this.writeWord(acc, PDP10.WORD_MASK - this.readWord(this.regEA));
};
/**
* opSETCMI(0o461000)
*
* Change the contents of the destination specified by M ([AC]) to the complement of the specified source operand (E).
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETCMI = function(op, acc)
{
this.opUndefined(op);
this.writeWord(acc, PDP10.WORD_MASK - this.regEA);
};
/**
* opSETCMM(0o462000)
*
* Change the contents of the destination specified by M ([E]) to the complement of the specified source operand ([E]).
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETCMM = function(op, acc)
{
this.opUndefined(op);
this.writeWord(this.regEA, PDP10.WORD_MASK - this.readWord(this.regEA));
};
/**
* opSETCMB(0o463000)
*
* Change the contents of the destination specified by M ([E] and [AC]) to the complement of the specified source operand ([E]).
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETCMB = function(op, acc)
{
this.opUndefined(op);
var dst = PDP10.WORD_MASK - this.readWord(this.regEA);
this.writeWord(acc, dst);
this.writeWord(this.regEA, dst);
};
/**
@ -3293,7 +3213,9 @@ PDP10.opORCBB = function(op, acc)
};
/**
* opSETO(0o474000)
* opSETO(0o474000) and opSETOI(0o475000)
*
* Change the contents of the destination specified by M (AC) to all 1s.
*
* @this {CPUStatePDP10}
* @param {number} op
@ -3301,43 +3223,36 @@ PDP10.opORCBB = function(op, acc)
*/
PDP10.opSETO = function(op, acc)
{
this.opUndefined(op);
};
/**
* opSETOI(0o475000)
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETOI = function(op, acc)
{
this.opUndefined(op);
this.writeWord(acc, PDP10.WORD_MASK);
};
/**
* opSETOM(0o476000)
*
* Change the contents of the destination specified by M ([E]) to all 1s.
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETOM = function(op, acc)
{
this.opUndefined(op);
this.writeWord(this.regEA, PDP10.WORD_MASK);
};
/**
* opSETOB(0o477000)
*
* Change the contents of the destination specified by M ([E] and [AC]) to all 1s.
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opSETOB = function(op, acc)
{
this.opUndefined(op);
this.writeWord(acc, PDP10.WORD_MASK);
this.writeWord(this.regEA, PDP10.WORD_MASK);
};
/**
@ -3358,7 +3273,7 @@ PDP10.opHLL = function(op, acc)
{
var src = this.readWord(this.regEA);
var dst = this.readWord(acc);
this.writeWord(acc, PDP10.getHR(op, dst, src) + (src - (src & PDP10.WORD_MASK)));
this.writeWord(acc, PDP10.getHR(op, dst, src) + (src - (src & PDP10.HALF_MASK)));
};
/**
@ -3402,7 +3317,7 @@ PDP10.opHLLM = function(op, acc)
{
var src = this.readWord(acc);
var dst = this.readWord(this.regEA);
this.writeWord(this.regEA, PDP10.getHR(op, dst, src) + (src - (src & PDP10.WORD_MASK)));
this.writeWord(this.regEA, PDP10.getHR(op, dst, src) + (src - (src & PDP10.HALF_MASK)));
};
/**
@ -3446,7 +3361,7 @@ PDP10.opHLLS = function(op, acc)
*/
PDP10.opHRL = function(op, acc)
{
var src = (this.readWord(this.regEA) & PDP10.WORD_MASK) * PDP10.WORD_SHIFT;
var src = (this.readWord(this.regEA) & PDP10.HALF_MASK) * PDP10.HALF_SHIFT;
var dst = this.readWord(acc);
this.writeWord(acc, PDP10.getHR(op, dst, src) + src);
};
@ -3468,7 +3383,7 @@ PDP10.opHRL = function(op, acc)
*/
PDP10.opHRLI = function(op, acc)
{
var src = this.regEA * PDP10.WORD_SHIFT;
var src = this.regEA * PDP10.HALF_SHIFT;
var dst = this.readWord(acc);
this.writeWord(acc, PDP10.getHR(op, dst, src) + src);
};
@ -3490,7 +3405,7 @@ PDP10.opHRLI = function(op, acc)
*/
PDP10.opHRLM = function(op, acc)
{
var src = (this.readWord(acc) & PDP10.WORD_MASK) * PDP10.WORD_SHIFT;
var src = (this.readWord(acc) & PDP10.HALF_MASK) * PDP10.HALF_SHIFT;
var dst = this.readWord(this.regEA);
this.writeWord(this.regEA, PDP10.getHR(op, dst, src) + src);
};
@ -3513,7 +3428,7 @@ PDP10.opHRLM = function(op, acc)
PDP10.opHRLS = function(op, acc)
{
var dst = this.readWord(this.regEA);
var src = (dst & PDP10.WORD_MASK) * PDP10.WORD_SHIFT;
var src = (dst & PDP10.HALF_MASK) * PDP10.HALF_SHIFT;
dst = PDP10.getHR(op, dst, src) + src;
this.writeWord(this.regEA, dst);
if (acc) this.writeWord(acc, dst);
@ -3536,7 +3451,7 @@ PDP10.opHRLS = function(op, acc)
*/
PDP10.opHRR = function(op, acc)
{
var src = this.readWord(this.regEA) & PDP10.WORD_MASK;
var src = this.readWord(this.regEA) & PDP10.HALF_MASK;
var dst = this.readWord(acc);
this.writeWord(acc, PDP10.getHL(op, dst, src) + src);
};
@ -3579,7 +3494,7 @@ PDP10.opHRRI = function(op, acc)
*/
PDP10.opHRRM = function(op, acc)
{
var src = this.readWord(acc) & PDP10.WORD_MASK;
var src = this.readWord(acc) & PDP10.HALF_MASK;
var dst = this.readWord(this.regEA);
this.writeWord(this.regEA, PDP10.getHL(op, dst, src) + src);
};
@ -3625,7 +3540,7 @@ PDP10.opHRRS = function(op, acc)
*/
PDP10.opHLR = function(op, acc)
{
var src = (this.readWord(this.regEA) / PDP10.WORD_SHIFT)|0;
var src = (this.readWord(this.regEA) / PDP10.HALF_SHIFT)|0;
var dst = this.readWord(acc);
this.writeWord(acc, PDP10.getHL(op, dst, src) + src);
};
@ -3668,7 +3583,7 @@ PDP10.opHLRI = function(op, acc)
*/
PDP10.opHLRM = function(op, acc)
{
var src = (this.readWord(acc) / PDP10.WORD_SHIFT)|0;
var src = (this.readWord(acc) / PDP10.HALF_SHIFT)|0;
var dst = this.readWord(this.regEA);
this.writeWord(this.regEA, PDP10.getHL(op, dst, src) + src);
};
@ -3690,7 +3605,7 @@ PDP10.opHLRM = function(op, acc)
PDP10.opHLRS = function(op, acc)
{
var dst = this.readWord(this.regEA);
var src = (dst / PDP10.WORD_SHIFT)|0;
var src = (dst / PDP10.HALF_SHIFT)|0;
dst = PDP10.getHL(op, dst, src) + src;
this.writeWord(this.regEA, dst);
if (acc) this.writeWord(acc, dst);
@ -4572,6 +4487,19 @@ PDP10.opIO = function(op, acc)
this.opUndefined(op);
};
/**
* opNOP(op, acc)
*
* Used for all "defined" operations that, in fact, do nothing (eg, SETA and SETAI).
*
* @this {CPUStatePDP10}
* @param {number} op
* @param {number} acc
*/
PDP10.opNOP = function(op, acc)
{
};
/**
* opUndefined(op, acc)
*
@ -4600,16 +4528,16 @@ PDP10.getHL = function(op, dst, src)
{
switch(op & 0o600) {
case 0o000:
dst -= (dst & PDP10.WORD_MASK);
dst -= (dst & PDP10.HALF_MASK);
break;
case 0o200:
dst = 0;
break;
case 0o400:
dst = (PDP10.WORD_MASK * PDP10.WORD_SHIFT);
dst = (PDP10.HALF_MASK * PDP10.HALF_SHIFT);
break;
case 0o600:
dst = (src > PDP10.MAX_POS18? (PDP10.WORD_MASK * PDP10.WORD_SHIFT) : 0);
dst = (src > PDP10.MAX_POS18? (PDP10.HALF_MASK * PDP10.HALF_SHIFT) : 0);
break;
}
return dst;
@ -4628,13 +4556,13 @@ PDP10.getHL = function(op, dst, src)
PDP10.setHL = function(op, dst, src)
{
if (op &= 0o600) {
dst &= PDP10.WORD_MASK;
dst &= PDP10.HALF_MASK;
switch(op) {
case 0o400:
dst += (PDP10.WORD_MASK * PDP10.WORD_SHIFT);
dst += (PDP10.HALF_MASK * PDP10.HALF_SHIFT);
break;
case 0o600:
dst += (src > PDP10.MAX_POS18? (PDP10.WORD_MASK * PDP10.WORD_SHIFT) : 0);
dst += (src > PDP10.MAX_POS18? (PDP10.HALF_MASK * PDP10.HALF_SHIFT) : 0);
break;
}
}
@ -4655,16 +4583,16 @@ PDP10.getHR = function(op, dst, src)
{
switch(op & 0o600) {
case 0o000:
dst = (dst & PDP10.WORD_MASK);
dst = (dst & PDP10.HALF_MASK);
break;
case 0o200:
dst = 0;
break;
case 0o400:
dst = PDP10.WORD_MASK;
dst = PDP10.HALF_MASK;
break;
case 0o600:
dst = (src > PDP10.MAX_POS36? PDP10.WORD_MASK : 0);
dst = (src > PDP10.MAX_POS36? PDP10.HALF_MASK : 0);
break;
}
return dst;
@ -4683,19 +4611,41 @@ PDP10.getHR = function(op, dst, src)
PDP10.setHR = function(op, dst, src)
{
if (op &= 0o600) {
dst -= (dst & PDP10.WORD_MASK);
dst -= (dst & PDP10.HALF_MASK);
switch(op) {
case 0o400:
dst += PDP10.WORD_MASK;
dst += PDP10.HALF_MASK;
break;
case 0o600:
dst += (src > PDP10.MAX_POS36? PDP10.WORD_MASK : 0);
dst += (src > PDP10.MAX_POS36? PDP10.HALF_MASK : 0);
break;
}
}
return dst;
};
/**
* doAND(dst, src)
*
* Used by callers to perform a logical "AND" of two 36-bit operands.
*
* @param {number} dst (36-bit value)
* @param {number} src (36-bit value)
* @return {number} (dst & src)
*/
PDP10.doAND = function(dst, src)
{
/*
* Since dst and src are 36-bit values, we must "AND" the low 32 bits separately from the higher bits,
* and then combine them with addition.
*
* WARNING: When using JavaScript's 32-bit operators with values that could set bit 31 and produce a
* negative value, it's critical to perform a final right-shift of 0, ensuring that the final result is
* positive.
*/
return ((((dst / PDP10.TWO_POW32)|0) & ((src / PDP10.TWO_POW32)|0)) * PDP10.TWO_POW32) + ((dst & src) >>> 0);
};
/*
* If we want the basic half-word operations to handle all the sub-operations; ie:
*
@ -4755,6 +4705,18 @@ PDP10.opHLREI = PDP10.opHLRI;
PDP10.opHLREM = PDP10.opHLRM;
PDP10.opHLRES = PDP10.opHLRS;
PDP10.opSETZI = PDP10.opSETZ;
PDP10.opSETOI = PDP10.opSETO;
PDP10.opSETCAI = PDP10.opSETCA;
PDP10.opSETA = PDP10.opNOP;
PDP10.opSETAI = PDP10.opNOP;
PDP10.opSETAM = PDP10.opMOVEM;
PDP10.opSETAB = PDP10.opMOVEM;
PDP10.opSETM = PDP10.opMOVE;
PDP10.opSETMI = PDP10.opMOVEI;
PDP10.opSETMM = PDP10.opNOP;
PDP10.opSETMB = PDP10.opMOVE;
PDP10.aOpXXX_KA10 = [
PDP10.opUUO, // 0o000xxx
PDP10.opUUO, // 0o001xxx

View file

@ -459,7 +459,7 @@ class DebuggerPDP10 extends Debugger {
*/
getWord(dbgAddr, inc)
{
var w = PDP10.DATA_INVALID;
var w = PDP10.WORD_INVALID;
var addr = this.getAddr(dbgAddr, false);
if (addr !== PDP10.ADDR_INVALID) {
w = this.bus.getWordDirect(addr);
@ -590,14 +590,14 @@ class DebuggerPDP10 extends Debugger {
* toStrWord(w)
*
* @this {DebuggerPDP10}
* @param {number} w (up to, but not including, DATA_LIMIT)
* @param {number} w (up to, but not including, WORD_LIMIT)
* @return {string} octal representation of the 36-bit word, as two 18-bit values
*/
toStrWord(w)
{
/*
* ADDR_LIMIT is not derived from DATA_LIMIT; we're just taking advantage of the fact
* that ADDR_LIMIT happens to be exactly half of DATA_LIMIT, and they are both powers of two.
* ADDR_LIMIT is not derived from WORD_LIMIT; we're just taking advantage of the fact
* that ADDR_LIMIT happens to be exactly half of WORD_LIMIT, and they are both powers of two.
*/
return Str.toOct(w / PDP10.ADDR_LIMIT, 6) + ' ' + Str.toOct(w % PDP10.ADDR_LIMIT, 6);
}
@ -3891,7 +3891,7 @@ if (DEBUGGER) {
0o23400: DebuggerPDP10.OPS.DIV,
0o27000: DebuggerPDP10.OPS.ADD,
0o27400: DebuggerPDP10.OPS.SUB,
0o40000: DebuggerPDP10.OPS.SETZ,
0o40000: DebuggerPDP10.OPS.SETZ, // MACRO alias: CLEAR
0o40400: DebuggerPDP10.OPS.AND,
0o41000: DebuggerPDP10.OPS.ANDCA,
0o41400: DebuggerPDP10.OPS.SETM,

View file

@ -103,10 +103,11 @@ var PDP10 = {
ADDR_INVALID: -1,
ADDR_LIMIT: Math.pow(2, 18),
ADDR_MASK: Math.pow(2, 18) - 1,
DATA_INVALID: -1,
DATA_LIMIT: Math.pow(2, 36),
WORD_SHIFT: Math.pow(2, 18),
WORD_MASK: 0o777777,
WORD_INVALID: -1,
WORD_LIMIT: Math.pow(2, 36),
WORD_MASK: Math.pow(2, 36) - 1,
HALF_SHIFT: Math.pow(2, 18),
HALF_MASK: Math.pow(2, 18) - 1,
/*
* 18-bit and 36-bit largest positive (and smallest negative) values; however, since we store all
@ -117,6 +118,7 @@ var PDP10 = {
MAX_POS36: Math.pow(2, 35) - 1, // 34,359,738,367 (377777 777777)
MIN_NEG36: Math.pow(2, 35), // -34,359,738,368 (400000 000000)
TWO_POW36: Math.pow(2, 36), // the two's complement of a 36-bit value is (value? TWO_POW36 - value : 0)
TWO_POW32: Math.pow(2, 32),
/*
* PDP-10 opcodes are 36-bit values, most of which use the following layout:

View file

@ -396,7 +396,7 @@ class MemoryPDP10 {
this.dbg.printMessage("attempt to read invalid address " + this.dbg.toStrBase(addr), true);
}
this.bus.fault(addr);
return PDP10.DATA_INVALID;
return PDP10.WORD_INVALID;
}
/**

View file

@ -1043,7 +1043,7 @@ class PanelPDP10 extends Component {
*/
updateData(value)
{
this.regData = value % PDP10.DATA_LIMIT;
this.regData = value % PDP10.WORD_LIMIT;
if (this.ledData !== this.regData) {
this.ledData = this.regData;
this.updateLEDArray("D", this.ledData, 16);