mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-02-11 19:05:01 +00:00
Commit word-mode compare ops and miscellaneous improvements in Processor.
This commit is contained in:
@@ -1311,6 +1311,75 @@ B5500Processor.prototype.singlePrecisionAdd = function(adding) {
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.singlePrecisionCompare = function() {
|
||||
/* Algebraically compares the B register to the A register. Function returns
|
||||
-1 if B<A, 0 if B=A, or +1 if B>A. Exits with AROF=0, BROF=1, and A and B as is */
|
||||
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 sa; // mantissa sign of A (0=positive)
|
||||
var sb; // mantissa sign of B (ditto)
|
||||
|
||||
this.cycleCount += 4; // estimate some general overhead
|
||||
this.adjustABFull();
|
||||
this.AROF = 0; // A is unconditionally marked empty
|
||||
ma = this.A % 0x8000000000; // extract the A mantissa
|
||||
mb = this.B % 0x8000000000; // extract the B mantissa
|
||||
|
||||
if (ma == 0) { // if A mantissa is zero
|
||||
ea = sa = 0; // consider A to be completely zero
|
||||
} else {
|
||||
ea = (this.A - ma)/0x8000000000;
|
||||
sa = ((ea >>> 7) & 0x01);
|
||||
ea = (ea & 0x40 ? -(ea & 0x3F) : (ea & 0x3F));
|
||||
}
|
||||
if (mb == 0) { // if B mantissa is zero
|
||||
eb = sb = 0; // consider B to be completely zero
|
||||
} else { // rats, we actually have to do this
|
||||
eb = (this.B - mb)/0x8000000000;
|
||||
sb = (eb >>> 7) & 0x01;
|
||||
eb = (eb & 0x40 ? -(eb & 0x3F) : (eb & 0x3F));
|
||||
}
|
||||
|
||||
// If the exponents are unequal, normalize each until the high-order octade
|
||||
// is non-zero or the exponents are equal
|
||||
if (ma) { // Normalize A
|
||||
while (ma < 0x1000000000 && ea != eb) {
|
||||
this.cycleCount++;
|
||||
ma *= 8; // shift left
|
||||
ea--;
|
||||
}
|
||||
}
|
||||
if (mb) { // Normalize B
|
||||
while (mb < 0x1000000000 && eb != ea) {
|
||||
this.cycleCount++;
|
||||
mb *= 8; // shift left
|
||||
eb--;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare signs, exponents, and normalized magnitudes, in that order
|
||||
if (sb == sa) { // if signs are equal:
|
||||
if (eb == ea) { // if exponents are equal:
|
||||
if (mb = ma) { // if magnitudes are equal:
|
||||
return 0; // then the operands are equal
|
||||
} else if (mb > ma) { // otherwise, if magnitude of B > A:
|
||||
return (sb ? -1 : 1); // B<A if B negative, B>A if B positive
|
||||
} else { // otherwise, if magnitude of B < A:
|
||||
return (sb ? 1 : -1); // B>A if B negative, B<A if B positive
|
||||
}
|
||||
} else if (eb > ea) { // otherwise, if exponent of B > A:
|
||||
return (sb ? -1 : 1); // B<A if B negative, B>A if B positive
|
||||
} else { // otherwise, if exponent of B < A
|
||||
return (sb ? 1 : -1); // B>A if B negative, B<A if B positive
|
||||
}
|
||||
} else { // otherwise, if signs are different:
|
||||
return (sa < sb ? -1 : 1); // B<A if B negative, B>A if B positive
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500Processor.prototype.singlePrecisionMultiply = function() {
|
||||
/* Multiplies the contents of the A register to the B register, leaving the
|
||||
@@ -2821,6 +2890,7 @@ B5500Processor.prototype.run = function() {
|
||||
break;
|
||||
|
||||
case 0x36: // XX66: OCV=Output convert
|
||||
this.streamOutputConvert(variant);
|
||||
break;
|
||||
|
||||
case 0x37: // XX67: ICV=Input convert
|
||||
@@ -3152,18 +3222,16 @@ B5500Processor.prototype.run = function() {
|
||||
|
||||
case 0x15: // XX25: comparison & misc. stack ops
|
||||
switch (variant) {
|
||||
case 0x01: // 0125: CEQ=compare B greater or equal to A
|
||||
case 0x01: // 0125: GEQ=compare B greater or equal to A
|
||||
this.B = (this.singlePrecisionCompare() >= 0 ? 1 : 0);
|
||||
break;
|
||||
|
||||
case 0x02: // 0225: CGR=compare B greater to A
|
||||
case 0x02: // 0225: GTR=compare B greater to A
|
||||
this.B = (this.singlePrecisionCompare() > 0 ? 1 : 0);
|
||||
break;
|
||||
|
||||
case 0x04: // 0425: NEQ=compare B not equal to A
|
||||
// assert(this.AROF == 1 && this.BROF == 1);
|
||||
// TODO: should this be excluding the flag bit in the comparison?
|
||||
this.B = (this.A != this.B) ? 1 : 0;
|
||||
this.AROF = 0;
|
||||
this.BROF = 1;
|
||||
this.B = (this.singlePrecisionCompare() != 0 ? 1 : 0);
|
||||
break;
|
||||
|
||||
case 0x08: // 1025: XCH=exchange TOS words
|
||||
@@ -3174,37 +3242,30 @@ B5500Processor.prototype.run = function() {
|
||||
break;
|
||||
|
||||
case 0x10: // 2025: DUP=Duplicate TOS
|
||||
this.adjustAEmpty();
|
||||
this.adjustBFull();
|
||||
this.A = this.B;
|
||||
this.AROF = 1;
|
||||
if (this.AROF) {
|
||||
this.AdjustBEmpty();
|
||||
this.B = this.A;
|
||||
this.BROF = 1;
|
||||
} else {
|
||||
this.adjustBFull();
|
||||
this.A = this.B;
|
||||
this.AROF = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1C: // 3425: FTF=F field to F field
|
||||
break;
|
||||
|
||||
case 0x21: // 4125: LEQ=compare B less or equal to A
|
||||
// assert(this.AROF == 1 && this.BROF == 1);
|
||||
// TODO: should this be excluding the flag bit in the comparison?
|
||||
this.B = (this.A >= this.B) ? 1 : 0;
|
||||
this.AROF = 0;
|
||||
this.BROF = 1;
|
||||
this.B = (this.singlePrecisionCompare() <= 0 ? 1 : 0);
|
||||
break;
|
||||
|
||||
case 0x22: // 4225: LSS=compare B less to A
|
||||
// assert(this.AROF == 1 && this.BROF == 1);
|
||||
// TODO: should this be excluding the flag bit in the comparison?
|
||||
this.B = (this.A > this.B) ? 1 : 0;
|
||||
this.AROF = 0;
|
||||
this.BROF = 1;
|
||||
this.B = (this.singlePrecisionCompare() < 0 ? 1 : 0);
|
||||
break;
|
||||
|
||||
case 0x24: // 4425: EQL=compare B equal to A
|
||||
// assert(this.AROF == 1 && this.BROF == 1);
|
||||
// TODO: should this be excluding the flag bit in the comparison?
|
||||
this.B = (this.A == this.B) ? 1 : 0;
|
||||
this.AROF = 0;
|
||||
this.BROF = 1;
|
||||
this.B = (this.singlePrecisionCompare() == 0 ? 1 : 0);
|
||||
break;
|
||||
|
||||
case 0x2C: // 5425: CTC=core field to C field
|
||||
|
||||
@@ -44,6 +44,9 @@ function getOctal(id) {
|
||||
var text = e.value; // text of element
|
||||
var v; // parsed value of element text
|
||||
|
||||
if (text.search(/\S/) < 0) {
|
||||
text = "0";
|
||||
}
|
||||
if (text.search(/[-+eE.]/) < 0) {
|
||||
v = parseInt(text, 8);
|
||||
} else {
|
||||
@@ -123,14 +126,17 @@ function reg_onChange(ev) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function testIt(index) {
|
||||
function stepIt() {
|
||||
/* Simple test driver for the Processor arithmetic ops */
|
||||
var opcode = 0x02D; // NOOP (XX55) by default
|
||||
var opList = document.getElementById("OpList")
|
||||
var text;
|
||||
var title;
|
||||
var value;
|
||||
|
||||
cc.P1.X = cc.P1.I = 0;
|
||||
|
||||
title = opList.options[opList.selectedIndex].text
|
||||
value = opList.options[opList.selectedIndex].value;
|
||||
opcode = parseInt(value, 8);
|
||||
|
||||
value = getOctal("AReg");
|
||||
if (!isNaN(value)) {
|
||||
@@ -143,34 +149,10 @@ function testIt(index) {
|
||||
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;
|
||||
case 5:
|
||||
title = "Integer Divide";
|
||||
opcode = 0x601; // IDV (3001)
|
||||
break;
|
||||
case 6:
|
||||
title = "Remainder Divide";
|
||||
opcode = 0xE01; // RDV (7001)
|
||||
break;
|
||||
}
|
||||
|
||||
cc.P1.I = 0; // reset any interrupts
|
||||
cc.IAR = 0;
|
||||
|
||||
cc.P1.X = 0;
|
||||
cc.P1.T = opcode;
|
||||
cc.P1.step();
|
||||
|
||||
@@ -259,12 +241,33 @@ window.onload = function() {
|
||||
</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)">
|
||||
<input name=IntDiv type=button value="Int Div" onclick="return testIt(5)">
|
||||
<input name=Remide type=button value="Rem Div" onclick="return testIt(6)">
|
||||
-->
|
||||
|
||||
Syllable:
|
||||
<select id=OpList name=OpList>
|
||||
<option value="0055" selected>NOP : No Operation
|
||||
<option value="0101">ADD : Add
|
||||
<option value="0301">SUB : Subtract
|
||||
<option value="0401">MUL : Multiply
|
||||
<option value="1001">DIV : Divide
|
||||
<option value="3001">IDV : Integer Divide
|
||||
<option value="7001">RDV : Remainder Divide
|
||||
<option value="0125">GEQ : B Greater or Equal A
|
||||
<option value="0225">GTR : B Greater Than A
|
||||
<option value="0425">NEQ : B Not Equal A
|
||||
<option value="4125">LEQ : B Less or Equal A
|
||||
<option value="4225">LSS : B Less Than A
|
||||
<option value="4425">EQL : B Equal A
|
||||
</select>
|
||||
|
||||
<input id=Step name=Step type=button value="Step" onclick="return stepIt()">
|
||||
</p>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user