I *think* all the PDP-10 DAKAL multiplication tests pass now. Division tests, alas, are a different story.

This commit is contained in:
Jeff 2017-04-01 23:06:41 -07:00 committed by Jeff Parsons
commit 493ae6c310
5 changed files with 121 additions and 95 deletions

View file

@ -6407,23 +6407,43 @@ PDP10.doMUL = function(dst, src, fTruncate, fExternal)
}
}
ext = PDP10.split72.call(this, res, ext, fExternal);
if (fTruncate) {
/*
* If ext is something OTHER than an extension of the res sign bit, then we have overflow.
* Special code for IMUL. I originally tried to avoid calling split72() in this case, but the PDP-10
* still appears to be splitting the result of the multiplication into separately signed 36-bit values,
* so the simplest solution is to call split72() in both cases.
*/
res = this.regEX;
if (!fExternal) {
/*
* Regarding IMUL overflows, the original spec says:
*
* Set Overflow if the product is >= 2^35 or < -2^35 (ie, if the high order word of the double
* length product is not null); the high order word is lost.
*
* However, when the DAKAL diagnostic performs a sequence like this:
*
* 00=000000000000 01=000000000000 02=000000000000 03=400000036755
* 04=400000000000 05=000000000003 06=400000000000 07=000000000004
* 10=000000000000 11=000000000011 12=777777400000 13=777777777776
* 14=000000200000 15=400000037134 16=000000000016 17=000000000000
* PC=037145 RA=00400000 EA=400000 PS=000000 OV=0 C0=0 C1=0 ND=0 PD=0
* 037145: 220600 000013 IMUL 14,13 ;cycles=1
*
* it sets 14=777777400000 and leaves overflow clear; since the 'high order word" would be 777777777777,
* not null, I think the spec over-simplifies. So our check is more exhaustive: it verifies that ext is
* nothing more than an extension of the sign bit of res (ie, 0 if res is positive, -1 if res is negative).
* Any other combination of values implies an overflow.
*/
if ((ext || res > PDP10.INT_MASK) && (ext != PDP10.WORD_MASK || res <= PDP10.INT_MASK)) {
this.regPS |= PDP10.PSFLAG.AROV;
}
}
/*
* Also note that, in the truncate case, we return the low order bits (res), rather than the
* the high order bits (ext) that split72() does.
*/
return res;
ext = res;
}
return PDP10.split72.call(this, res, ext, fExternal);
return ext;
};
/**
@ -6531,8 +6551,9 @@ PDP10.split72 = function(res, ext, fExternal)
var sign = ext - (ext % PDP10.INT_LIMIT);
ext = ((ext * 2) % PDP10.WORD_LIMIT) + Math.trunc(res / PDP10.INT_LIMIT);
res = sign + (res % PDP10.INT_LIMIT);
var signNew = ext - (ext % PDP10.INT_LIMIT);
if (sign != signNew) {
if (signNew != sign) {
/*
* I used to restore ext's original sign (ext = sign + (ext - signNew)), but the PDP-10's defined
* behavior for multiplication overflow (ie, whenever both operands are 0o400000000000) is to set both
@ -6543,9 +6564,13 @@ PDP10.split72 = function(res, ext, fExternal)
* If both operands are -2^35 set Overflow; the double length result stored is -2^70.
*/
res = ext;
if (!fExternal) this.regPS |= PDP10.PSFLAG.AROV;
}
if (fExternal) return res;
if (res == PDP10.INT_LIMIT && ext == PDP10.INT_LIMIT) {
this.regPS |= PDP10.PSFLAG.AROV;
}
this.regEX = res;
return ext;
};

View file

@ -510,7 +510,7 @@ class CPUStatePDP10 extends CPUPDP10 {
*/
getXC()
{
return this.regXC >= 0? this.regXC : this.regPC;
return this.regXC >= 0? this.regXC : ((this.regRA & PDP10.OPCODE.I_FIELD)? this.lastPC : this.regPC);
}
/**
@ -546,8 +546,9 @@ class CPUStatePDP10 extends CPUPDP10 {
*/
setPC(addr)
{
this.regPC = addr % PDP10.ADDR_LIMIT;
this.regRA = 0;
this.regXC = -1;
this.regPC = addr % PDP10.ADDR_LIMIT;
}
/**