Added the PDP-10's four arithmetic flags along with a negate() function -- the first of our functions that actually needs to set those flags

This commit is contained in:
Jeff 2017-03-01 17:23:54 -08:00 committed by Jeff Parsons
commit 202374dd09
6 changed files with 417 additions and 283 deletions

View file

@ -583,7 +583,7 @@ PDP10.opFDVRB = function(op)
};
/**
* opMOVE(0o200000)
* opMOVE(0o200000): Move
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
@ -601,7 +601,7 @@ PDP10.opMOVE = function(op)
};
/**
* opMOVEI(0o201000)
* opMOVEI(0o201000): Move Immediate
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
@ -621,7 +621,7 @@ PDP10.opMOVEI = function(op)
};
/**
* opMOVEM(0o202000)
* opMOVEM(0o202000): Move to Memory
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
@ -639,7 +639,7 @@ PDP10.opMOVEM = function(op)
};
/**
* opMOVES(0o203000)
* opMOVES(0o203000): Move to Self
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
@ -660,62 +660,128 @@ PDP10.opMOVES = function(op)
};
/**
* opMOVS(0o204000)
* opMOVS(0o204000): Move Swapped
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
* Interchange the left and right halves of the word from the source specified by M and move it to the
* specified destination. 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.opMOVS = function(op)
{
this.opUndefined(op);
var src = this.readWord(this.regEA);
src = (src / PDP10.WORD_SHIFT) | ((src & PDP10.WORD_MASK) * PDP10.WORD_SHIFT);
this.writeWord(op & PDP10.OPCODE.A_MASK, src);
};
/**
* opMOVSI(0o205000)
* opMOVSI(0o205000): Move Swapped Immediate
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
* Interchange the left and right halves of the word from the source specified by M and move it to the
* specified destination. The source is unaffected, the original contents of the destination are lost.
*
* SIDEBAR: Swapping halves in immediate mode loads the word E,0 into AC. MOVSI is thus equivalent to HRLZI.
*
* 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.opMOVSI = function(op)
{
this.opUndefined(op);
this.writeWord(op & PDP10.OPCODE.A_MASK, this.regEA * PDP10.WORD_SHIFT);
};
/**
* opMOVSM(0o206000)
* opMOVSM(0o206000): Move Swapped to Memory
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
* Interchange the left and right halves of the word from the source specified by M and move it to the
* specified destination. 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.opMOVSM = function(op)
{
this.opUndefined(op);
var src = this.readWord(op & PDP10.OPCODE.A_MASK);
src = (src / PDP10.WORD_SHIFT) | ((src & PDP10.WORD_MASK) * PDP10.WORD_SHIFT);
this.writeWord(this.regEA, src);
};
/**
* opMOVSS(0o207000)
* opMOVSS(0o207000): Move Swapped to Self
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
* Interchange the left and right halves of the word from the source specified by M and move it to the
* specified destination. The source is unaffected, the original contents of the destination are lost.
*
* 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.opMOVSS = function(op)
{
this.opUndefined(op);
var src = this.readWord(this.regEA);
src = (src / PDP10.WORD_SHIFT) | ((src & PDP10.WORD_MASK) * PDP10.WORD_SHIFT);
this.writeWord(this.regEA, src);
var acc = op & PDP10.OPCODE.A_MASK;
if (acc) this.writeWord(acc, src)
};
/**
* opMOVN(0o210000)
* opMOVN(0o210000): Move Negative
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
* Negate the word from the source specified by M and move it to the specified destination.
* If the source word is fixed point -2^35 (400000 000000) set the Overflow and Carry 1 flags.
*
* (Negating the equivalent floating point -1 * 2^127 sets the flags, but this is not a normalized
* number).
*
* If the source word is zero, set Carry 0 and Carry 1. 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.opMOVN = function(op)
{
this.opUndefined(op);
this.writeWord(op & PDP10.OPCODE.A_MASK, this.negate(this.readWord(this.regEA)));
};
/**
* opMOVNI(0o211000)
* opMOVNI(0o211000): Move Negative Immediate
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
* Negate the word from the source specified by M and move it to the specified destination.
* If the source word is fixed point -2^35 (400000 000000) set the Overflow and Carry 1 flags.
*
* (Negating the equivalent floating point -1 * 2^127 sets the flags, but this is not a normalized
* number).
*
* If the source word is zero, set Carry 0 and Carry 1. The source is unaffected, the original
* contents of the destination are lost.
*
* SIDEBAR: MOVNI loads AC with the negative of the word 0,E and can set no flags.
*
* NOTE: This is an "Immediate" mode instruction: the source is the word 0,E and the destination is [A].
*
* @this {CPUStatePDP10}
* @param {number} op
@ -726,7 +792,20 @@ PDP10.opMOVNI = function(op)
};
/**
* opMOVNM(0o212000)
* opMOVNM(0o212000): Move Negative to Memory
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
* Negate the word from the source specified by M and move it to the specified destination.
* If the source word is fixed point -2^35 (400000 000000) set the Overflow and Carry 1 flags.
*
* (Negating the equivalent floating point -1 * 2^127 sets the flags, but this is not a normalized
* number).
*
* If the source word is zero, set Carry 0 and Carry 1. 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
@ -737,7 +816,20 @@ PDP10.opMOVNM = function(op)
};
/**
* opMOVNS(0o213000)
* opMOVNS(0o213000): Move Negative to Self
*
* From the DEC PDP-10 System Reference Manual (May 1968), p. 2-11:
*
* Negate the word from the source specified by M and move it to the specified destination.
* If the source word is fixed point -2^35 (400000 000000) set the Overflow and Carry 1 flags.
*
* (Negating the equivalent floating point -1 * 2^127 sets the flags, but this is not a normalized
* number).
*
* If the source word is zero, set Carry 0 and Carry 1. The source is unaffected, the original
* contents of the destination are lost.
*
* 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
@ -3996,7 +4088,7 @@ PDP10.getHR = function(op, dst, src)
dst = PDP10.WORD_MASK;
break;
case 0o600:
dst = (src > PDP10.MAX_POS? PDP10.WORD_MASK : 0);
dst = (src > PDP10.MAX_POS36? PDP10.WORD_MASK : 0);
break;
}
return dst;
@ -4021,7 +4113,7 @@ PDP10.setHR = function(op, dst, src)
dst += PDP10.WORD_MASK;
break;
case 0o600:
dst += (src > PDP10.MAX_POS? PDP10.WORD_MASK : 0);
dst += (src > PDP10.MAX_POS36? PDP10.WORD_MASK : 0);
break;
}
}

View file

@ -176,6 +176,7 @@ class CPUStatePDP10 extends CPUPDP10 {
{
this.regEA = this.regRA = this.regOP = 0;
this.regPC = this.lastPC = this.addrReset;
this.fOverflow = this.fCarry0 = this.fCarry1 = this.fNoDivide = false;
/*
* This is queried and displayed by the Panel when it's not displaying its own ADDRESS register
@ -327,25 +328,29 @@ class CPUStatePDP10 extends CPUPDP10 {
/**
* getOpcode()
*
* Normally, this fetches the next opcode in regOP, decodes the low 23 bits (I,X,Y), records the effective
* address (E) in regEA, updates regPC, and returns the high 13 bits of the opcode for further decoding.
* Normally, this fetches the next opcode in regOP, decodes the low 23 bits (I,X,Y), records
* the effective address (E) in regEA, updates regPC, and returns the high 13 bits of the opcode
* for further decoding.
*
* However, if a reference address still needs to be decoded (due to indirection), we take care of that first.
* However, if a reference address (R) in regRA still needs to be decoded (due to indirection),
* we take care of that first.
*
* @this {CPUStatePDP10}
* @return {number} (-1 if the reference address in regRA has not yet been fully decoded)
*/
getOpcode()
{
if ((this.regRA & PDP10.OPCODE.I_BIT)) {
this.regRA = this.readWord(this.regEA);
} else {
this.regRA = this.regOP = this.readWord(this.lastPC = this.regPC);
}
/*
* Technically, we don't REALLY need to mask regRA with R_MASK, because all regRA accesses
* ignore any higher opcode bits, but let's keep things tidy.
* ignore any higher bits, but let's keep things tidy.
*/
if ((this.regRA & PDP10.OPCODE.I_BIT)) {
this.regRA = this.readWord(this.regEA) & PDP10.OPCODE.R_MASK;
} else {
this.regRA = (this.regOP = this.readWord(this.lastPC = this.regPC)) & PDP10.OPCODE.R_MASK;
}
this.regRA &= PDP10.OPCODE.R_MASK;
/*
* Bits 0-22 (I,X,Y) contain what we call a "reference address" (R), which is used to calculate an
@ -433,6 +438,32 @@ class CPUStatePDP10 extends CPUPDP10 {
this.regPC = addr % PDP10.ADDR_LIMIT;
}
/**
* negate(src)
*
* @this {CPUStatePDP10}
* @param {number} src (36-bit)
* @return {number} (negated 36-bit src)
*/
negate(src)
{
if (!src) {
this.fCarry = this.fCarry1 = true;
}
else {
/*
* In the non-zero case, it's always safe to subtract src from TWO_POW36, but since we have to check for
* the MIN_NEG36 case anyway, and since subtraction in that case doesn't alter src, we skip the subtraction.
*/
if (src == PDP10.MIN_NEG36) {
this.fOverflow = this.fCarry1 = true;
} else {
src = PDP10.TWO_POW36 - src;
}
}
return src;
}
/**
* addIRQ(vector, priority, message)
*

View file

@ -102,8 +102,16 @@ var PDP10 = {
DATA_LIMIT: Math.pow(2, 36),
WORD_SHIFT: Math.pow(2, 18),
WORD_MASK: 0o777777,
MAX_POS18: Math.pow(2, 17) - 1,
MAX_POS: Math.pow(2, 35) - 1,
/*
* 18-bit and 36-bit largest positive (and smallest negative) values; however, since we store all
* values as unsigned quantities, these are the unsigned equivalents.
*/
MAX_POS18: Math.pow(2, 17) - 1, // 131,071 (377777)
MIN_NEG18: Math.pow(2, 17), // -131,072 (400000)
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)
/*
* PDP-10 opcodes are 36-bit values, most of which use the following layout: