Implemented (but have not yet tested) ASHC opcode for PDP-10
This commit is contained in:
parent
61e64bf3fc
commit
286a122b05
5 changed files with 626 additions and 374 deletions
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue