Implemented (but have not yet tested) ASHC opcode for PDP-10

This commit is contained in:
Jeff 2017-03-05 14:14:14 -08:00 committed by Jeff Parsons
commit 286a122b05
5 changed files with 626 additions and 374 deletions

View file

@ -1404,7 +1404,7 @@ PDP10.opASH = function(op, acc)
*/
var s = ((this.regEA << 14) >> 14) % 256;
if (s) {
var w = this.readWord(acc), bitsShifted;
var w = this.readWord(acc), bits;
/*
* Convert the unsigned word (w) to a signed value (i), for convenience.
*/
@ -1412,15 +1412,15 @@ PDP10.opASH = function(op, acc)
if (s > 0) {
if (s >= 35) {
i = (i < 0? PDP10.INT_LIMIT : 0);
bitsShifted = PDP10.INT_MASK;
bits = PDP10.INT_MASK;
} else {
i = (i * Math.pow(2, s)) % PDP10.INT_LIMIT;
/*
* bitsShifted must be set to the mask of all magnitude bits shifted out of
* bits must be set to the mask of all magnitude bits shifted out of
* the original word. Using 8-bit signed words as an example, this table shows
* the bitsShifted values that would correspond to shifting 1-7 bits left:
* the bits values that would correspond to shifting 1-7 bits left:
*
* shifts bitsShifted value calculation
* shifts bits value calculation
* ------ ----------- ------ -----------
* 1 0b01000000 128-64 128-Math.pow(2, 7-1)
* 2 0b01100000 128-32 128-Math.pow(2, 7-2)
@ -1428,22 +1428,22 @@ PDP10.opASH = function(op, acc)
* ...
* 7 0b01111111 128-1 128-Math.pow(2, 7-7)
*/
bitsShifted = PDP10.INT_LIMIT - Math.pow(2, 35-s);
bits = PDP10.INT_LIMIT - Math.pow(2, 35 - s);
}
if (w <= PDP10.MAX_POS36) {
/*
* Since w was positive, overflow occurs ONLY if any of the bits we shifted out were 1s.
* If all those bits in the original value (w) were 0s, then adding bitsShifted to it could NOT
* If all those bits in the original value (w) were 0s, then adding bits to it could NOT
* produce a value > MAX_POS36.
*/
if (w + bitsShifted > PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
if (w + bits > PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
} else {
/*
* Since w was negative, overflow occurs ONLY if any of the bits we shifted out were 0s.
* If all those bits in the original value (w) were 1s, subtracting bitsShifted from it could NOT
* If all those bits in the original value (w) were 1s, subtracting bits from it could NOT
* produce a value <= MAX_POS36.
*/
if (w - bitsShifted <= PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
if (w - bits <= PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
}
} else {
if (s <= -35) {
@ -1576,7 +1576,133 @@ PDP10.opJFFO = function(op, acc)
*/
PDP10.opASHC = function(op, acc)
{
this.opUndefined(op);
/*
* Convert the unsigned 18-bit value in regEA to a signed 8-bit value (+/-255).
*/
var s = ((this.regEA << 14) >> 14) % 256;
if (s) {
var bits;
var wLeft = this.readWord(acc);
var wRight = this.readWord((acc + 1) & 0o17);
if (s > 0) {
/*
* Handle all the left shift cases below, which don't need to worry about sign-extension
* but DO need to worry about overflow.
*/
var wLeftOrig = wLeft;
if (s >= 36) {
/*
* Since all wLeft bits are being shifted out, any positive value other than zero OR any negative value
* other than WORD_MASK indicates an overflow.
*/
if (wLeft > 0 && wLeft < PDP10.INT_LIMIT || wLeft > PDP10.INT_MASK && wLeft < PDP10.WORD_MASK) {
this.regPS |= PDP10.PSFLAG.OVFL;
}
if (s >= 71) {
/*
* Since all wRight bits are being shifted out, any positive value other than zero OR any negative value
* other than WORD_MASK indicates an overflow.
*/
if (wRight > 0 && wRight < PDP10.INT_LIMIT || wRight > PDP10.INT_MASK && wRight < PDP10.WORD_MASK) {
this.regPS |= PDP10.PSFLAG.OVFL;
}
wLeft = 0;
} else {
/*
* Left shift 36-70 bits.
*/
wLeft = (wRight * Math.pow(2, s - 35)) % PDP10.INT_LIMIT;
bits = PDP10.INT_LIMIT - Math.pow(2, 70 - s);
if (wLeftOrig <= PDP10.MAX_POS36) {
/*
* Since wLeft was positive, overflow occurs ONLY if any of the bits we shifted out were 1s.
* If all those bits in the original value were 0s, then adding bits to it could NOT produce
* a value > MAX_POS36.
*/
if (wRight + bits > PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
} else {
/*
* Since wLeft was negative, overflow occurs ONLY if any of the bits we shifted out were 0s.
* If all those bits in the original value were 1s, subtracting bits from it could NOT produce
* a value <= MAX_POS36.
*/
if (wRight - bits <= PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
}
}
wRight = 0;
if (wLeftOrig > PDP10.INT_MASK) {
wLeft += PDP10.INT_LIMIT;
wRight += PDP10.INT_LIMIT;
}
} else {
/*
* Left shift 1-35 bits.
*/
wLeft = ((wLeft * Math.pow(2, s)) % PDP10.INT_LIMIT) + Math.trunc((wRight % PDP10.INT_LIMIT) / Math.pow(2, 35 - s));
wRight = (wRight * Math.pow(2, s)) % PDP10.INT_LIMIT;
/*
* Determine overflow and update the sign bits.
*/
bits = PDP10.INT_LIMIT - Math.pow(2, 35 - s);
if (wLeftOrig <= PDP10.MAX_POS36) {
/*
* Since wLeft was positive, overflow occurs ONLY if any of the bits we shifted out were 1s.
* If all those bits in the original value were 0s, then adding bits to it could NOT produce
* a value > MAX_POS36.
*/
if (wLeftOrig + bits > PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
} else {
/*
* Since wLeft was negative, overflow occurs ONLY if any of the bits we shifted out were 0s.
* If all those bits in the original value were 1s, subtracting bits from it could NOT produce
* a value <= MAX_POS36.
*/
if (wLeftOrig - bits <= PDP10.MAX_POS36) this.regPS |= PDP10.PSFLAG.OVFL;
/*
* Last but not least, update the sign bits of wLeft and wRight to indicate negative values.
*/
wLeft += PDP10.INT_LIMIT;
wRight += PDP10.INT_LIMIT;
}
}
} else {
/*
* Handle all the right shift cases below, which don't need to worry about overflow but DO
* need to worry about sign-extension.
*/
if (s <= -36) {
if (s <= -72) {
wRight = (wLeft > PDP10.INT_MASK? PDP10.WORD_MASK : 0);
} else {
wRight = Math.trunc((wLeft % PDP10.INT_LIMIT) / Math.pow(2, -s - 35));
}
if (wLeft <= PDP10.INT_MASK) {
wLeft = 0;
} else {
wLeft = PDP10.WORD_MASK;
wRight += PDP10.INT_LIMIT;
}
} else {
/*
* For this right shift of 1-35 bits, determine the value of bits shifted in from the left.
*/
bits = (wLeft > PDP10.INT_MASK? PDP10.WORD_LIMIT - Math.pow(2, 36 - s) : 0);
/*
* The bits that we add to wRight from wLeft must be shifted right one additional bit, because
* they must "skip over" the sign bit of wRight. This means we must zero the sign bit of wRight,
* which can be done by performing a "mod" with INT_LIMIT.
*/
wRight = Math.trunc((wRight % PDP10.INT_LIMIT) / Math.pow(2, -s)) + (((wLeft % PDP10.INT_LIMIT) * Math.pow(2, 35 + s)) % PDP10.INT_LIMIT);
wLeft = Math.trunc(wLeft / Math.pow(2, -s)) + bits;
/*
* Last but not least, we must set the sign of wRight to the sign of wLeft.
*/
if (wLeft > PDP10.INT_MASK) wRight += PDP10.INT_LIMIT;
}
}
this.writeWord(acc, wLeft);
this.writeWord((acc + 1) & 0o17, wRight);
}
};
/**
@ -1644,24 +1770,24 @@ PDP10.opLSHC = function(op, acc)
var wRight = this.readWord((acc + 1) & 0o17);
if (s > 0) {
if (s >= 36) {
wRight = 0;
if (s >= 72) {
wLeft = 0;
} else {
wLeft = (wRight * Math.pow(2, s - 36)) % PDP10.WORD_LIMIT;
}
wRight = 0;
} else {
wLeft = ((wLeft * Math.pow(2, s)) % PDP10.WORD_LIMIT) + Math.trunc(wRight / Math.pow(2, 36 - s));
wRight = (wRight * Math.pow(2, s)) % PDP10.WORD_LIMIT;
}
} else {
if (s <= -36) {
wLeft = 0;
if (s <= -72) {
wRight = 0;
} else {
wRight = Math.trunc(wLeft / Math.pow(2, -s - 36));
}
wLeft = 0;
} else {
wRight = Math.trunc(wRight / Math.pow(2, -s)) + ((wLeft * Math.pow(2, 36 + s)) % PDP10.WORD_LIMIT);
wLeft = Math.trunc(wLeft / Math.pow(2, -s));

View file

@ -109,17 +109,18 @@ var PDP10 = {
* values as unsigned quantities, these are the unsigned equivalents.
*/
WORD_INVALID: -1,
HALF_MASK: Math.pow(2, 18) - 1, // 262,143 (000000 777777): unsigned half-word mask
HALF_SHIFT: Math.pow(2, 18), // 262,144 (000001 000000): unsigned half-word shift
INT_MASK: Math.pow(2, 35) - 1, // 34,359,738,367 (377777 777777): signed word (magnitude) mask
INT_LIMIT: Math.pow(2, 35), // -34,359,738,368 (400000 000000): signed word (magnitude) limit
INT_LIMIT: Math.pow(2, 35), // 34,359,738,368 (400000 000000): signed word (magnitude) limit
WORD_MASK: Math.pow(2, 36) - 1, // 68,719,476,735 (777777 777777): unsigned word mask
WORD_LIMIT: Math.pow(2, 36), // 68,719,476,735 (1 000000 000000): unsigned word limit
HALF_MASK: Math.pow(2, 18) - 1, // unsigned half-word mask
HALF_SHIFT: Math.pow(2, 18), // unsigned half-word shift
WORD_LIMIT: Math.pow(2, 36), // 68,719,476,736 (1 000000 000000): unsigned word limit
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)
TWO_POW32: Math.pow(2, 32),