Fixed the accumulator update logic in all the PDP-10 half-word self-mode instructions, and started work on EXCH, BLT, and MOVE instructions (the BLT is a real odd-ball, and SIMH does some very strange things with the accumulator used by BLT, which we do NOT attempt to replicate; the strangeness is most noticeable when the accumulator is part of the range being transferred)
This commit is contained in:
parent
3508b1050e
commit
e870fd6eec
6 changed files with 373 additions and 279 deletions
|
|
@ -583,40 +583,84 @@ PDP10.opFDVRB = function(op)
|
|||
};
|
||||
|
||||
/**
|
||||
* opMOV(0o200000)
|
||||
* opMOVE(0o200000)
|
||||
*
|
||||
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
|
||||
*
|
||||
* Move one word from the source to the destination specified by M. The source is unaffected,
|
||||
* the original contents of the destination are lost.
|
||||
*
|
||||
* NOTE: This is a "Basic" mode instruction: the source is [E] and the destination is [A] (opposite of "Memory").
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
*/
|
||||
PDP10.opMOV = function(op)
|
||||
PDP10.opMOVE = function(op)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
this.writeWord(op & PDP10.OPCODE.A_MASK, this.readWord(this.regEA));
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVI(0o201000)
|
||||
* opMOVEI(0o201000)
|
||||
*
|
||||
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
|
||||
*
|
||||
* Move one word from the source to the destination specified by M. The source is unaffected,
|
||||
* the original contents of the destination are lost.
|
||||
*
|
||||
* SIDEBAR: MOVEI loads the word 0,E into AC and is thus equivalent to HRRZI.
|
||||
*
|
||||
* NOTE: This is an "Immediate" mode instruction: the source is the word 0,E and the destination is [A].
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
*/
|
||||
PDP10.opMOVI = function(op)
|
||||
PDP10.opMOVEI = function(op)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
this.writeWord(op & PDP10.OPCODE.A_MASK, this.regEA);
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVM(0o200000)
|
||||
* opMOVEM(0o202000)
|
||||
*
|
||||
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
|
||||
*
|
||||
* Move one word from the source to the destination specified by M. The source is unaffected,
|
||||
* the original contents of the destination are lost.
|
||||
*
|
||||
* NOTE: This is a "Memory" mode instruction: the source is [A] and the destination is [E] (opposite of "Basic").
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
*/
|
||||
PDP10.opMOVM = function(op)
|
||||
PDP10.opMOVEM = function(op)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
this.writeWord(this.regEA, this.readWord(op & PDP10.OPCODE.A_MASK));
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVS(0o200000)
|
||||
* opMOVES(0o203000)
|
||||
*
|
||||
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
|
||||
*
|
||||
* Move one word from the source to the destination specified by M. The source is unaffected,
|
||||
* the original contents of the destination are lost.
|
||||
*
|
||||
* SIDEBAR: If A is zero, MOVES is a no-op; otherwise it is equivalent to MOVE.
|
||||
*
|
||||
* NOTE: This is a "Self" mode instruction: the source AND destination is [E] (and also [A] if A is non-zero).
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
*/
|
||||
PDP10.opMOVES = function(op)
|
||||
{
|
||||
var acc = op & PDP10.OPCODE.A_MASK;
|
||||
if (acc) this.writeWord(acc, this.readWord(this.regEA));
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVS(0o204000)
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
|
|
@ -703,6 +747,17 @@ PDP10.opMOVNS = function(op)
|
|||
this.opUndefined(op);
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVM(0o214000)
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
*/
|
||||
PDP10.opMOVM = function(op)
|
||||
{
|
||||
this.opUndefined(op);
|
||||
};
|
||||
|
||||
/**
|
||||
* opMOVMI(0o215000)
|
||||
*
|
||||
|
|
@ -1025,23 +1080,30 @@ PDP10.opEXCH = function(op)
|
|||
* is the final location being loaded. Furthermore, the program cannot assume that AC is the same after the BLT
|
||||
* as it was before.
|
||||
*
|
||||
* NOTE: As currently implemented, we will NEVER acknowledge an interrupt during a block transfer, so the above
|
||||
* caution can be ignored (for now).
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
*/
|
||||
PDP10.opBLT = function(op)
|
||||
{
|
||||
var fDone = false;
|
||||
var acc = op & PDP10.OPCODE.A_MASK;
|
||||
var addrDst = this.readWord(acc);
|
||||
var addrSrc = (addrDst / PDP10.WORD_SHIFT)|0;
|
||||
addrDst &= PDP10.WORD_MASK;
|
||||
while (true) {
|
||||
while (!fDone) {
|
||||
this.writeWord(addrDst, this.readWord(addrSrc));
|
||||
if (addrDst == this.regEA) break;
|
||||
if (addrDst == this.regEA) fDone = true;
|
||||
addrSrc = (addrSrc + 1) & PDP10.WORD_MASK;
|
||||
addrDst = (addrDst + 1) & PDP10.WORD_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);
|
||||
if (!fDone) this.advancePC(-1);
|
||||
fDone = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -2759,7 +2821,7 @@ PDP10.opHLLM = function(op)
|
|||
*
|
||||
* SIDEBAR: If A is zero, HLLS is a no-op, otherwise it is equivalent to HLL.
|
||||
*
|
||||
* For HLLS, the source is [E] and the destination is [E] (and also [A] if A is non-zero).
|
||||
* For HLLS, the source AND destination is [E] (and also [A] if A is non-zero).
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
|
|
@ -2767,12 +2829,10 @@ PDP10.opHLLM = function(op)
|
|||
PDP10.opHLLS = function(op)
|
||||
{
|
||||
var dst = this.readWord(this.regEA);
|
||||
this.writeWord(this.regEA, PDP10.setHR(op, dst, dst));
|
||||
dst = PDP10.setHR(op, dst, dst);
|
||||
this.writeWord(this.regEA, dst);
|
||||
var acc = op & PDP10.OPCODE.A_MASK;
|
||||
if (acc) {
|
||||
dst = this.readWord(acc);
|
||||
this.writeWord(acc, PDP10.setHR(op, dst, dst));
|
||||
}
|
||||
if (acc) this.writeWord(acc, dst);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2850,7 +2910,7 @@ PDP10.opHRLM = function(op)
|
|||
* The source and the destination right half are unaffected; the original contents of the destination left
|
||||
* half are lost.
|
||||
*
|
||||
* For HRLS, the source is [E] and the destination is [E] (and also [A] if A is non-zero).
|
||||
* For HRLS, the source AND destination is [E] (and also [A] if A is non-zero).
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
|
|
@ -2859,13 +2919,10 @@ PDP10.opHRLS = function(op)
|
|||
{
|
||||
var dst = this.readWord(this.regEA);
|
||||
var src = (dst & PDP10.WORD_MASK) * PDP10.WORD_SHIFT;
|
||||
this.writeWord(this.regEA, PDP10.getHR(op, dst, src) + src);
|
||||
dst = PDP10.getHR(op, dst, src) + src;
|
||||
this.writeWord(this.regEA, dst);
|
||||
var acc = op & PDP10.OPCODE.A_MASK;
|
||||
if (acc) {
|
||||
dst = this.readWord(acc);
|
||||
src = (dst & PDP10.WORD_MASK) * PDP10.WORD_SHIFT;
|
||||
this.writeWord(acc, PDP10.getHR(op, dst, src) + src);
|
||||
}
|
||||
if (acc) this.writeWord(acc, dst);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -2944,7 +3001,7 @@ PDP10.opHRRM = function(op)
|
|||
*
|
||||
* SIDEBAR: If A is zero, HRRS is a no-op; otherwise it is equivalent to HRR.
|
||||
*
|
||||
* For HRRS, the source is [E] and the destination is [E] (and also [A] if A is non-zero).
|
||||
* For HRRS, the source AND destination is [E] (and also [A] if A is non-zero).
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
|
|
@ -2952,12 +3009,10 @@ PDP10.opHRRM = function(op)
|
|||
PDP10.opHRRS = function(op)
|
||||
{
|
||||
var dst = this.readWord(this.regEA);
|
||||
this.writeWord(this.regEA, PDP10.setHL(op, dst, dst));
|
||||
dst = PDP10.setHL(op, dst, dst);
|
||||
this.writeWord(this.regEA, dst);
|
||||
var acc = op & PDP10.OPCODE.A_MASK;
|
||||
if (acc) {
|
||||
dst = this.readWord(acc);
|
||||
this.writeWord(acc, PDP10.setHL(op, dst, dst));
|
||||
}
|
||||
if (acc) this.writeWord(acc, dst);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -3032,7 +3087,7 @@ PDP10.opHLRM = function(op)
|
|||
* Move the left half of the source word specified by M to the right half of the specified destination.
|
||||
* The source and the destination left half are unaffected; the original contents of the destination right half are lost.
|
||||
*
|
||||
* For HLRS, the source is [E] and the destination is [E] (and also [A] if A is non-zero).
|
||||
* For HLRS, the source AND destination is [E] (and also [A] if A is non-zero).
|
||||
*
|
||||
* @this {CPUStatePDP10}
|
||||
* @param {number} op
|
||||
|
|
@ -3041,13 +3096,10 @@ PDP10.opHLRS = function(op)
|
|||
{
|
||||
var dst = this.readWord(this.regEA);
|
||||
var src = (dst / PDP10.WORD_SHIFT)|0;
|
||||
this.writeWord(this.regEA, PDP10.getHL(op, dst, src) + src);
|
||||
dst = PDP10.getHL(op, dst, src) + src;
|
||||
this.writeWord(this.regEA, dst);
|
||||
var acc = op & PDP10.OPCODE.A_MASK;
|
||||
if (acc) {
|
||||
dst = this.readWord(acc);
|
||||
src = (dst / PDP10.WORD_SHIFT)|0;
|
||||
this.writeWord(acc, PDP10.getHL(op, dst, src) + src);
|
||||
}
|
||||
if (acc) this.writeWord(acc, dst);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -4164,10 +4216,10 @@ PDP10.aOpXXX_KA10 = [
|
|||
PDP10.opFDVRI, // 0o175xxx
|
||||
PDP10.opFDVRM, // 0o176xxx
|
||||
PDP10.opFDVRB, // 0o177xxx
|
||||
PDP10.opMOV, // 0o200xxx
|
||||
PDP10.opMOVI, // 0o201xxx
|
||||
PDP10.opMOVM, // 0o202xxx
|
||||
PDP10.opMOVS, // 0o203xxx
|
||||
PDP10.opMOVE, // 0o200xxx
|
||||
PDP10.opMOVEI, // 0o201xxx
|
||||
PDP10.opMOVEM, // 0o202xxx
|
||||
PDP10.opMOVES, // 0o203xxx
|
||||
PDP10.opMOVS, // 0o204xxx
|
||||
PDP10.opMOVSI, // 0o205xxx
|
||||
PDP10.opMOVSM, // 0o206xxx
|
||||
|
|
|
|||
|
|
@ -3738,7 +3738,7 @@ if (DEBUGGER) {
|
|||
HRL: 5, HRLZ: 6, HRLO: 7, HRLE: 8,
|
||||
HRR: 9, HRRZ: 10, HRRO: 11, HRRE: 12,
|
||||
HLR: 13, HLRZ: 14, HLRO: 15, HLRE: 16,
|
||||
MOV: 17, MOVS: 18, MOVN: 19, MOVM: 20,
|
||||
MOVE: 17, MOVS: 18, MOVN: 19, MOVM: 20,
|
||||
EXCH: 21, BLT: 22, PUSH: 23, POP: 24,
|
||||
LDB: 25, DPB: 26, IBP: 27, ILDB: 28,
|
||||
IDPB: 29, SETZ: 30, SETO: 31, SETA: 32,
|
||||
|
|
@ -3771,7 +3771,7 @@ if (DEBUGGER) {
|
|||
"HRL", "HRLZ", "HRLO", "HRLE",
|
||||
"HRR", "HRRZ", "HRRO", "HRRE",
|
||||
"HLR", "HLRZ", "HLRO", "HLRE",
|
||||
"MOV", "MOVS", "MOVN", "MOVM",
|
||||
"MOVE", "MOVS", "MOVN", "MOVM",
|
||||
"EXCH", "BLT", "PUSH", "POP",
|
||||
"LDB", "DPB", "IBP", "ILDB",
|
||||
"IDPB", "SETZ", "SETO", "SETA",
|
||||
|
|
@ -3856,7 +3856,7 @@ if (DEBUGGER) {
|
|||
0o16400: DebuggerPDP10.OPS.FMPR,
|
||||
0o17000: DebuggerPDP10.OPS.FDV,
|
||||
0o17400: DebuggerPDP10.OPS.FDVR,
|
||||
0o20000: DebuggerPDP10.OPS.MOV,
|
||||
0o20000: DebuggerPDP10.OPS.MOVE,
|
||||
0o20400: DebuggerPDP10.OPS.MOVS,
|
||||
0o21000: DebuggerPDP10.OPS.MOVN,
|
||||
0o21400: DebuggerPDP10.OPS.MOVM,
|
||||
|
|
|
|||
Loading…
Reference in a new issue