1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-02-13 11:44:33 +00:00

Commit initial singlePrecisionMultiply() and webUI/B5500TestArithmetics.html implementations; corrections to singlePrecisionAdd().

This commit is contained in:
paul
2012-11-12 02:21:51 +00:00
parent f0c9ba7346
commit a28ba1b642
3 changed files with 485 additions and 93 deletions

View File

@@ -190,7 +190,7 @@ B5500Processor.prototype.access = function(eValue) {
break;
}
this.cycleCount += 6; // assume 6 us memory cycle time (the other option is 4 usec)
this.cycleCount += 6; // assume 6 us memory cycle time (the other option was 4 usec)
if (acc.MAED) {
this.I |= 0x02; // set I02F - memory address/inhibit error
if (this.NCSF || this !== this.cc.P1) {
@@ -444,11 +444,11 @@ B5500Processor.prototype.compareSourceWithDest = function(count) {
if (count) {
if (this.BROF) {
if (this.K == 0) {
this.Q |= 0x80; // set Q04F -- at start of word, no need to store B later
this.Q |= 0x08; // set Q04F -- at start of word, no need to store B later
}
} else {
this.access(0x03); // B = [S]
this.Q |= 0x80; // set Q04F -- just loaded B, no need to store it later
this.Q |= 0x08; // set Q04F -- just loaded B, no need to store it later
}
if (!this.AROF) {
this.access(0x04); // A = [M]
@@ -467,9 +467,9 @@ B5500Processor.prototype.compareSourceWithDest = function(count) {
if (this.Q & 0x04) { // inequality already detected -- just count down
if (count >= 8) {
count -= 8;
if (!(this.Q & 0x80)) { // test Q04F to see if B may be dirty
if (!(this.Q & 0x08)) { // test Q04F to see if B may be dirty
this.access(0x0B); // [S] = B
this.Q |= 0x80; // set Q04F so we won't store B anymore
this.Q |= 0x08; // set Q04F so we won't store B anymore
}
this.BROF = 0;
this.S++;
@@ -480,9 +480,9 @@ B5500Processor.prototype.compareSourceWithDest = function(count) {
if (this.K < 7) {
this.K++;
} else {
if (!(this.Q & 0x80)) { // test Q04F to see if B may be dirty
if (!(this.Q & 0x08)) { // test Q04F to see if B may be dirty
this.access(0x0B); // [S] = B
this.Q |= 0x80; // set Q04F so we won't store B anymore
this.Q |= 0x08; // set Q04F so we won't store B anymore
}
this.K = 0;
this.BROF = 0;
@@ -508,9 +508,9 @@ B5500Processor.prototype.compareSourceWithDest = function(count) {
} else {
bBit = 0;
this.K = 0;
if (!(this.Q & 0x80)) { // test Q04F to see if B may be dirty
if (!(this.Q & 0x08)) { // test Q04F to see if B may be dirty
this.access(0x0B); // [S] = B
this.Q |= 0x80; // set Q04F so we won't store B anymore
this.Q |= 0x08; // set Q04F so we won't store B anymore
}
this.S++;
this.access(0x03); // B = [S]
@@ -531,10 +531,10 @@ B5500Processor.prototype.compareSourceWithDest = function(count) {
};
/**************************************/
B5500Processor.prototype.fieldArithmetic = function(count, subtract) {
B5500Processor.prototype.fieldArithmetic = function(count, adding) {
/* Handles the Field Add (FAD) or Field Subtract (FSU) syllables.
"count" indicates the length of the fields to be operated upon.
"subtract" will be true if this call is for FSU, otherwise it's for FAD */
"adding" will be false if this call is for FSU, otherwise it's for FAD */
var aBit; // A register bit nr
var bBit; // B register bit nr
var carry = 0; // carry/borrow bit
@@ -581,7 +581,7 @@ B5500Processor.prototype.fieldArithmetic = function(count, subtract) {
bBit = this.K*6; // B-bit number
yd = this.cc.fieldIsolate(this.A, aBit, 2); // get the source sign
zd = this.cc.fieldIsolate(this.B, bBit, 2); // get the dest sign
compl = (yd == zd ? subtract : !subtract ); // determine if complement needed
compl = (yd == zd ? !adding : adding ); // determine if complement needed
resultNegative = !( // determine sign of result
(zd == 0 && !compl) ||
(zd == 0 && Q03F && !MSFF) ||
@@ -877,7 +877,7 @@ B5500Processor.prototype.streamInputConvert = function(count) {
if (a) { // zero results have sign bit reset
if (this.Y & 0x30 == 0x20) {
a += 0x400000000000; // set the sign bit
}
}
}
this.A = a;
this.access(0x0A); // [S] = A
@@ -916,7 +916,7 @@ B5500Processor.prototype.streamOutputConvert = function(count) {
count = ((count-1) & 0x07) + 1; // limit the count to 8
a = this.A % 0x8000000000; // get absolute mantissa value, ignore exponent
if (a) { // mantissa is non-zero, so conversion is required
if ((this.A % 800000000000) >= 0x400000000000) {
if ((this.A % 0x800000000000) >= 0x400000000000) {
b = 0x20; // result is negative, so preset the sign in the low-order digit
}
do { // Convert the binary value in A to BIC digits in B
@@ -949,7 +949,7 @@ B5500Processor.prototype.streamOutputConvert = function(count) {
this.S++;
if (count > 1) {
this.access(0x03); // B = [S]
} else
} else {
this.BROF = 0;
}
}
@@ -961,7 +961,7 @@ B5500Processor.prototype.streamOutputConvert = function(count) {
B5500Processor.prototype.storeForInterrupt = function(forTest) {
/* Implements the 3011=SFI operator and the parts of 3411=SFT that are
common to it. "forTest" implies use from SFT */
var forced = this.Q & 0x0040; // Q07F: Hardware-induced SFI syllable
var forced = this.Q & 0x40; // Q07F: Hardware-induced SFI syllable
var saveAROF = this.AROF;
var saveBROF = this.BROF;
var temp;
@@ -1192,9 +1192,9 @@ B5500Processor.prototype.initiate = function(forTest) {
};
/**************************************/
B5500Processor.prototype.singePrecisionAdd = function(subtract) {
B5500Processor.prototype.singlePrecisionAdd = function(adding) {
/* Adds the contents of the A register to the B register, leaving the result
in B and invalidating A. If "subtract" is true, the sign of A is complemented
in B and invalidating A. If "adding" is not true, the sign of A is complemented
to accomplish subtraction instead of addition. 42-bit arithmetic is done on
the mantissas to allow for a rounding digit in the low-order octade (in the
hardware, shifts off the low-order end of the word went into the X register) */
@@ -1205,16 +1205,22 @@ B5500Processor.prototype.singePrecisionAdd = function(subtract) {
var sa; // mantissa sign of A (0=positive)
var sb; // mantissa sign of B (ditto)
this.cycleCount += 4; // estimate some general overhead
this.adjustABFull();
ma = this.A % 0x8000000000;
mb = this.B % 0x8000000000;
if (ma == 0) { // if A is zero, result is B
this.B %= 0x800000000000; // reset the flag bit
} else if (mb == 0) { // otherwise, if B is zero, result is A
this.B = this.A % 0x800000000000;
ma = this.A % 0x8000000000; // extract the A mantissa
mb = this.B % 0x8000000000; // extract the B mantissa
if (ma == 0) { // if A mantissa is zero
if (mb == 0) { // and B mantissa is zero
this.B = 0; // result is all zeroes
} else {
this.B %= 0x800000000000; // otherwise, result is B with flag bit reset
}
} else if (mb == 0 && adding) { // otherwise, if B is zero and we're adding,
this.B = this.A % 0x800000000000; // result is A with flag bit reset
} else { // rats, we actually have to do this
ea = (this.A - ma)/0x8000000000;
sa = ((ea >>> 7) & 0x01) ^ (subtract ? 1 : 0);
sa = ((ea >>> 7) & 0x01) ^ (adding ? 0 : 1);
ea = (ea & 0x40 ? -(ea & 0x3F) : (ea & 0x3F));
ma *= 8; // shift A left an octade to provide a guard digit
@@ -1226,25 +1232,29 @@ B5500Processor.prototype.singePrecisionAdd = function(subtract) {
// If the exponents are unequal, normalize the larger and scale the smaller
// until they are in alignment, or one of the mantissas (mantissae?) becomes zero
if (ea > eb) {
// Normalize A
// Normalize A for 42 bits (14 octades)
while (ma < 0x8000000000 && ea != eb) {
ma *= 8;
this.cycleCount++;
ma *= 8; // shift left
ea--;
}
// Scale B until its exponent matches or mantissa goes to zero
while (ea != eb && mb) {
mb = (mb - mb%8)/8;
this.cycleCount++;
mb = (mb - mb%8)/8; // shift right
eb++;
}
} else if (ea < eb) {
// Normalize B
// Normalize B for 42 bits (14 octades)
while (mb < 0x8000000000 && eb != ea) {
mb *= 8;
this.cycleCount++;
mb *= 8; // shift left
eb--;
}
// Scale A until its exponent matches or mantissa goes to zero
while (eb != ea && ma) {
ma = (ma - ma%8)/8;
this.cycleCount++;
ma = (ma - ma%8)/8; // shift right
ea++;
}
}
@@ -1264,15 +1274,25 @@ B5500Processor.prototype.singePrecisionAdd = function(subtract) {
mb = -mb;
}
// Round and normalize as necessary
// Normalize and round as necessary
ma = mb % 8; // reuse ma for the guard digit;
mb = (mb - ma)/8; // shift back to a 39-bit mantissa
if (mb >= 0x8000000000) {
this.cycleCount++;
ma = mb % 8;
mb = (mb - ma)/8; // renormalize due to overflow
eb++;
}
mb += (ma >>> 2); // add in the rounding bit (what about overflow ??)
// Note: the Training Manual does not say that rounding is suppressed
// for add/subtract when the mantissa is all ones, but it does say so
// for multiply/divide, so we assume it's also the case here.
if (ma & 0x04) { // if the guard digit >= 4
if (mb < 0x7FFFFFFFFF) {// and rounding would not cause overflow
this.cycleCount++;
mb++; // round up the result
}
}
// Check for exponent overflow
if (eb > 63) {
@@ -1285,12 +1305,138 @@ B5500Processor.prototype.singePrecisionAdd = function(subtract) {
eb = (-eb) | 0x40; // set the exponent sign bit
}
this.B = (sb*64 + eb)*0x8000000000 + mb; // Final Answer
this.B = (sb*128 + eb)*0x8000000000 + mb; // Final Answer
}
}
this.AROF = 0;
};
/**************************************/
B5500Processor.prototype.singlePrecisionMultiply = function() {
/* Multiplies the contents of the A register to the B register, leaving the
result in B and invalidating A. A double-precision mantissa is developed and
then normalized and rounded */
var d; // current multiplier digit (octal)
var ea; // signed exponent of A
var eb; // signed exponent of B
var ma; // absolute mantissa of A
var mb; // absolute mantissa of B
var mx = 0; // local copy of X for product extension
var n = 0; // local copy of N (octade counter)
var sa; // mantissa sign of A (0=positive)
var sb; // mantissa sign of B (ditto)
var xx; // local copy of X for multiplier
this.cycleCount += 4; // estimate some general overhead
this.adjustABFull();
ma = this.A % 0x8000000000; // extract the A mantissa
mb = this.B % 0x8000000000; // extract the B mantissa
if (ma == 0) { // if A mantissa is zero
this.B = 0; // result is all zeroes
} else if (mb == 0) { // otherwise, if B is zero,
this.B = 0; // result is all zeroes
} else { // otherwise, let the games begin
ea = (this.A - ma)/0x8000000000;
sa = ((ea >>> 7) & 0x01);
ea = (ea & 0x40 ? -(ea & 0x3F) : (ea & 0x3F));
eb = (this.B - mb)/0x8000000000;
sb = (eb >>> 7) & 0x01;
eb = (eb & 0x40 ? -(eb & 0x3F) : (eb & 0x3F));
// If the exponents are BOTH zero, perform an integer multiply.
// Otherwise, normalize both operands
if (ea == 0 && eb == 0) {
this.Q |= 0x10; // integer multiply operation: set Q05F
} else {
// Normalize A for 39 bits (13 octades)
while (ma < 0x1000000000) {
this.cycleCount++;
ma *= 8; // shift left
ea--;
}
// Normalize B for 39 bits (13 octades)
while (mb < 0x1000000000) {
this.cycleCount++;
mb *= 8; // shift left
eb--;
}
}
// Determine resulting mantissa sign; initialize the product
sb ^= sa; // positive if signs are same, negative if different
xx = mb; // move multiplier to X
mb = 0; // initialize high-order part of product
//Now we step through the 13 octades of the multiplier, developing the product
do {
d = xx % 8; // extract the current multiplier digit
xx = (xx - d)/8; // shift the multiplier right one octade
if (d == 0) { // if multiplier digit is zero
this.cycleCount++; // hardware optimizes this case
} else {
this.cycleCount += 3; // just estimate the average number of clocks
mb += ma*d; // develop the partial product
}
d = mb % 8; // get the low-order octade of partial product in B
mb = (mb - d)/8; // shift B right one octade
mx = mx/8 + d*0x1000000000; // shift B octade into high-order end of extension
} while (++n < 13);
// Normalize the result
if (this.Q & 0x10 && mb == 0) { // if it's integer multiply (Q05F) with integer result
mb = mx; // just use the low-order 39 bits
eb = 0; // and don't normalize
} else {
eb += ea+13; // compute resulting exponent from multiply
while (mb < 0x1000000000) {
this.cycleCount++;
ma = mx % 0x1000000000; // reuse ma: get low-order 36 bits of mantissa extension
d = (mx - ma)/0x1000000000; // get high-order octade of extension
mb = mb*8 + d; // shift high-order extension octade into B
mx = ma*8; // shift extension left one octade
eb--;
}
}
// Round the result
if (xx >= 0x4000000000) { // if high-order bit of remaining extension is 1
if (mb < 0x7FFFFFFFFF) { // if the rounding would not cause overflow
this.cycleCount++;
mb++; // round up the result
}
}
if (mb == 0) { // don't see how this could be necessary here, but
this.B = 0; // the TM says to do it anyway
} else {
// Check for exponent overflow
if (eb > 63) {
eb %= 64;
if (this.NCSF) {
this.I = (this.I & 0x0F) | 0xB0; // set I05/6/8: exponent-overflow
this.cc.signalInterrupt();
}
} else if (eb < -63) {
eb = ((-eb) % 64) | 0x40; // mod the exponent and set its sign
if (this.NCSF) {
this.I = (this.I & 0x0F) | 0xA0; // set I06/8: exponent-underflow
this.cc.signalInterrupt();
}
} else if (eb < 0) {
eb = (-eb) | 0x40; // set the exponent sign bit
}
this.B = (sb*128 + eb)*0x8000000000 + mb; // Final Answer
}
}
this.AROF = 0;
this.X = mx; // for display purposes only
};
/**************************************/
B5500Processor.prototype.computeRelativeAddr = function(offset, cEnabled) {
/* Computes an absolute memory address from the relative "offset" parameter
@@ -1349,49 +1495,52 @@ B5500Processor.prototype.indexDescriptor = function() {
var xe; // index exponent
var xm; // index mantissa
var xo; // last index octade shifted off
var xs; // index mantissa sign
var xt; // index exponent sign
this.adjustBFull();
bw = this.B;
xm = (bw % 0x8000000000);
xe = this.cc.fieldIsolate(bw, 3, 6);
xe = (bw - xm)/8;
xs = (xe >>> 7) & 0x01;
xt = (xe >>> 6) & 0x01;
xe = (xt ? -(xe & 0x3F) : (xe & 0x3F));
// Normalize the index, if necessary
if (xe > 0) { // index is not an integer
if (this.cc.bit(bw, 2)) { // index exponent is negative
do {
xo = xm % 8;
xm = (xm - xo)/8;
this.cycleCount++;
} while (--xe > 0);
if (xo >= 4) {
xm++;
}
} else { // index exponent is positive
do {
if (xm < 0x1000000000) {
xm *= 8;
} else { // oops... integer overflow normalizing the index
xe = 0; // kill the loop
interrupted = 1;
if (this.NCSF) {
this.I = (this.I & 0x0F) | 0xC0; // set I07/8: int-overflow
this.cc.signalInterrupt();
}
}
this.cycleCount++;
} while (--xe > 0);
if (xe < 0) { // index exponent is negative
do {
this.cycleCount++;
xo = xm % 8;
xm = (xm - xo)/8;
} while (++xe < 0);
if (xo >= 4) {
xm++; // round the index
}
} else if (xe > 0) { // index exponent is positive
do {
this.cycleCount++;
if (xm < 0x1000000000) {
xm *= 8;
} else { // oops... integer overflow normalizing the index
xe = 0; // kill the loop
interrupted = 1;
if (this.NCSF) {
this.I = (this.I & 0x0F) | 0xC0; // set I07/8: int-overflow
this.cc.signalInterrupt();
}
}
} while (--xe > 0);
}
// Now we have an integerized index value in xm
if (!interrupted) {
if (xm && this.cc.bit(bw, 1)) { // oops... negative index
if (xs) { // oops... negative index
interrupted = 1;
if (this.NCSF) {
this.I = (this.I & 0x0F) | 0x90; // set I05/8: invalid-index
this.cc.signalInterrupt();
}
} else if (xm >= this.cc.fieldIsolate(bw, 8, 10)) {
} else if (xm >= this.cc.fieldIsolate(aw, 8, 10)) {
interrupted = 1; // oops... index out of bounds
if (this.NCSF) {
this.I = (this.I & 0x0F) | 0x90; // set I05/8: invalid-index
@@ -1439,15 +1588,15 @@ B5500Processor.prototype.applyMSCW = function(word) {
Word in the "word" parameter */
var f;
f = word % 0x8000; // [33:15]
f = word % 0x8000; // [33:15], not used
word = (word-f)/0x8000;
this.F = f = word % 0x8000; // [18:15]
this.F = f = word % 0x8000; // [18:15], F register
word = (word-f)/0x8000;
this.SALF = f = word % 2; // [17:1]
word = (word-f)/0x02;
this.MSFF = word % 0x02; // [16:1]
word = (word - word%0x04)/0x04;
this.R = word % 0x200; // [6:9]
this.SALF = f = word % 2; // [17:1], SALF
word = (word-f)/2;
this.MSFF = word % 2; // [16:1], MSFF
word = (word - word%4)/4;
this.R = word % 0x200; // [6:9], R
};
/**************************************/
@@ -1471,28 +1620,28 @@ B5500Processor.prototype.applyRCW = function(word, inline) {
the RCW. Returns the state of the OPDC/DESC bit [2:1] */
var f;
f = word % 0x8000; // [33:15]
f = word % 0x8000; // [33:15], C
if (!inline) {
this.C = f;
this.access(0x30); // P = [C], fetch new program word
}
word = (word-f)/0x8000;
this.F = f = word % 0x8000; // [18:15]
this.F = f = word % 0x8000; // [18:15], F
word = (word-f)/0x8000;
this.K = f = word % 0x08; // [15:3]
word = (word-f)/0x08;
this.G = f = word % 0x08; // [12:3]
word = (word-f)/0x08;
f = word % 0x04; // [10:2]
this.K = f = word % 8; // [15:3], K
word = (word-f)/8;
this.G = f = word % 8; // [12:3], G
word = (word-f)/8;
f = word % 4; // [10:2], L
if (!inline) {
this.L = f;
}
word = (word-f)/0x04;
this.V = f = word % 0x08; // [7:3]
word = (word-f)/0x08;
this.H = word % 0x08; // [4:3]
word = (word-f)/4;
this.V = f = word % 8; // [7:3], V
word = (word-f)/8;
this.H = word % 8; // [4:3], H
word = (word - word % 0x10)/0x10;
return word % 0x02; // [2:1]
return word % 2; // [2:1], DESC bit
};
/**************************************/
@@ -1623,7 +1772,7 @@ B5500Processor.prototype.exitSubroutine = function(inline) {
do {
this.S = (this.B % 0x40000000) >>> 15;
this.access(0x03); // B = [S], fetch prior MSCW
} while (((this.B - this.B % 0x40000000)/0x40000000) % 0x04 == 3); // MSFF & SALF
} while (((this.B - this.B % 0x40000000)/0x40000000) % 4 == 3); // MSFF & SALF
this.S = (this.R*64) + 7;
this.access(0x0B); // [S] = B, store last MSCW at [R]+7
}
@@ -1694,9 +1843,9 @@ B5500Processor.prototype.operandCall = function() {
/**************************************/
B5500Processor.prototype.descriptorCall = function() {
/* DESC, the moral equivalent of "load address" on lesser
machines. Assumes the syllable has already loaded a word into A, and
that the address of that word is in M.
/* DESC, the moral equivalent of "load address" on lesser machines.
Assumes the syllable has already loaded a word into A, and that the
address of that word is in M.
See Figures 6-2, 6-3, and 6-4 in the B5500 Reference Manual */
var aw = this.A; // local copy of A reg value
var interrupted = 0; // interrupt occurred
@@ -2059,11 +2208,11 @@ B5500Processor.prototype.run = function() {
break;
case 0x1A: // XX32: ---=Field subtract (aux) !! ??
this.fieldArithmetic(variant, true);
this.fieldArithmetic(variant, false);
break;
case 0x1B: // XX33: ---=Field add (aux) !! ??
this.fieldArithmetic(variant, false);
this.fieldArithmetic(variant, true);
break;
case 0x1C: // XX34: TEL=Test for equal or less
@@ -2372,11 +2521,11 @@ B5500Processor.prototype.run = function() {
break;
case 0x3A: // XX72: FSU=Field subtract
this.fieldArithmetic(variant, true);
this.fieldArithmetic(variant, false);
break;
case 0x3B: // XX73: FAD=Field add
this.fieldArithmetic(variant, false);
this.fieldArithmetic(variant, true);
break;
case 0x3C: // XX74: TRP=Transfer program characters
@@ -2482,14 +2631,15 @@ B5500Processor.prototype.run = function() {
case 0x01: // XX01: single-precision numerics
switch (variant) {
case 0x01: // 0101: ADD=single-precision add
this.singlePrecisionAdd(false);
break;
case 0x03: // 0301: SUB=single-precision subtract
this.singlePrecisionAdd(true);
break;
case 0x03: // 0301: SUB=single-precision subtract
this.singlePrecisionAdd(false);
break;
case 0x04: // 0401: MUL=single-precision multiply
this.singlePrecisionMultiply();
break;
case 0x08: // 1001: DIV=single-precision floating divide

View File

@@ -137,5 +137,13 @@ IMG#BurroughsLogoImage {
padding-left: 8px;
padding-right: 8px}
P.center {
.center {
text-align: center}
.data {
font-family: Courier New, Courier, monospace;
text-align: left}
.number {
font-family: Courier New, Courier, monospace;
text-align: right}

View File

@@ -0,0 +1,234 @@
<!DOCTYPE html>
<head>
<title>B5500 Emulator Arithmetic Testbed</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Nigel Williams & Paul Kimpel">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500DistributionAndDisplay.css">
<script src="../emulator/B5500SystemConfiguration.js"></script>
<script src="../emulator/B5500CentralControl.js"></script>
<script src="../emulator/B5500Processor.js"></script>
<script>
"use strict";
var cc;
function setText(id, text) {
/* Replaces the children of the node having id="id" with the "text" */
var e = document.getElementById(id);
var f;
if (!e) {
alert("Invalid node id \"" + id + "\"");
} else {
while (f = e.firstChild) {
e.removeChild(f);
}
e.appendChild(document.createTextNode(text));
}
}
function getOctal(id) {
/* Obtains the .value from the element "id", parses it, and returns the
result as a B5500 numeric word. If the element text contains any of "-+eE."
the text is parsed as a decimal integer or floating point number, otherwise
it is parsed as an octal value */
var e = document.getElementById(id);
var ev = 0; // exponent of parsed value
var mv; // mantissa of parsed value
var sv = 0; // sign of parsed value
var tv = 0; // sign of parsed value exponent
var text = e.value; // text of element
var v; // parsed value of element text
if (text.search(/[-+eE.]/) < 0) {
v = parseInt(text, 8);
} else {
v = parseFloat(text);
if (!isNaN(v)) {
if (v < 0) {
sv = 1;
v = -v;
}
while (v < 0x1000000000) {
v *= 8;
ev--;
}
while (v >= 0x8000000000) {
v /= 8;
ev++;
}
mv = Math.floor(v);
if (ev >= -13) {
while (ev < 0 && mv%8 == 0) {
mv /= 8;
ev++;
}
}
if (ev < 0) {
tv = 1;
ev = -ev;
}
v = (((sv*2) + tv)*64 + ev%64)*0x8000000000 + mv; // to B5500 format
}
}
if (isNaN(v)) {
e.style.backgroundColor = "red";
} else {
e.style.backgroundColor = "";
}
return v;
}
function putOctal(id, value) {
/* Formats the "value" as octal and set the "id".value property with the result */
var e = document.getElementById(id);
e.value = value.toString(8);
}
function putNumber(id, value) {
/* Converts the "value" as a B5500 number to a Javascript Number() object and
formats it as the text content of node "id" */
var m = value % 0x8000000000; // get the mantissa
var e = (value - m)/0x8000000000; // get the exponent and sign bits
var s = (e & 0x80) >>> 7; // get the mantissa sign
var t = (e & 0x40) >>> 6; // get the exponent sign
e = (t ? -(e & 0x3F) : (e & 0x3F)); // get signed value of exponent
setText(id, (Math.pow(8, e)*(s ? -m : m)).toPrecision(12));
}
function testIt(index) {
/* Simple test driver for the Processor arithmetic ops */
var opcode = 0x02D; // NOOP (XX55) by default
var text;
var title;
var value;
cc.P1.X = cc.P1.I = 0;
value = getOctal("AReg");
if (!isNaN(value)) {
cc.P1.A = value;
cc.P1.AROF = 1;
setText("ARegOrig", value.toString(8));
value = getOctal("BReg");
if (!isNaN(value)) {
cc.P1.B = value;
cc.P1.BROF = 1;
setText("BRegOrig", value.toString(8));
switch(index) {
case 1:
title = "Add";
opcode = 0x041; // ADD (0101)
break;
case 2:
title = "Subtract";
opcode = 0x0C1; // SUB (0301)
break;
case 3:
title = "Multiply";
opcode = 0x101; // MUL (0401)
break;
case 4:
title = "Divide";
opcode = 0x201; // DIV (1001)
break;
}
cc.P1.T = opcode;
cc.P1.step();
putOctal("AReg", cc.P1.A);
putNumber("ARegValue", cc.P1.A);
putOctal("BReg", cc.P1.B);
putNumber("BRegValue", cc.P1.B);
putOctal("XReg", cc.P1.X);
putNumber("XRegValue", cc.P1.X);
putOctal("IReg", cc.P1.I);
}
}
setText("Caption", title);
}
window.onload = function() {
cc = new B5500CentralControl();
cc.powerOn();
cc.clear();
//cc.MemMod[0][0x10] = 0x00400C215415;// LITC 1, LITC 3, XCH, DUP
cc.P1.S = 0x100; // stack at @400
cc.P1.R = 0x005; // PRT at @500 (R has addr div 64)
cc.P1.C = 0x10; // execute from address @20
cc.P1.access(0x30); // P = [C]
cc.P1.T = cc.fieldIsolate(cc.P1.P, 0, 12);
cc.P1.TROF = 1;
cc.P1.L = 1; // point to the next instruction
cc.P1.NCSF = 1; // run test in normal state
}
</script>
</head>
<body style="position:relative">
<div style="position:absolute; background-color:#666; width:230px; height: 136px; right:0; top:0">
<div id=BurroughsLogo>
<img id=BurroughsLogoImage src="Burroughs-Logo-Neg.jpg">
</div>
<div id=B5500Logo>B 5500
</div>
</div>
<h3>Arithmetic Testbed</h3>
<div id=Caption>&nbsp;</div>
<table border=1 cellpadding=4 cellspacing=0>
<thead>
<tr>
<th>Reg
<th>Current (octal)
<th>FP Value
<th>Original (octal)
<tbody>
<tr>
<td class=center>A
<td><input id=AReg name=AReg type=text class=number size=16 maxlength=16>
<td id=ARegValue class=number>
<td id=ARegOrig class=number>
<tr>
<td class=center>B
<td><input id=BReg name=BReg type=text class=number size=16 maxlength=16>
<td id=BRegValue class=number>
<td id=BRegOrig class=number>
<tr>
<td class=center>X
<td><input id=XReg name=XReg type=text class=number size=13 maxlength=13>
<td id=XRegValue class=number>
<td id=XRegOrig class=number>
<tr>
<td class=center>I
<td><input id=IReg name=IReg type=text class=number size=3 maxlength=3>
<td id=IRegValue class=number>
<td id=IRegOrig class=number>
</table>
<p>
<input name=Add type=button value=Add onclick="return testIt(1)">
<input name=Subtract type=button value=Subtract onclick="return testIt(2)">
<input name=Multiply type=button value=Multiply onclick="return testIt(3)">
<input name=Divide type=button value=Divide onclick="return testIt(4)" DISABLED >
</p>
</body>
</html>