Eliminated test386 multiplication differences, now on to division differences

This commit is contained in:
Jeff Parsons 2015-10-30 13:23:57 -07:00
commit 05c261f849
4 changed files with 438 additions and 450 deletions

View file

@ -1104,6 +1104,69 @@ X86.fnIMUL8 = function(dst, src)
return result;
};
/**
* fnIMULn(dst, src)
*
* 80286_and_80287_Programmers_Reference_Manual_1987.pdf, p.B-44 (p.254) notes that:
*
* "The low 16 bits of the product of a 16-bit signed multiply are the same as those of an
* unsigned multiply. The three operand IMUL instruction can be used for unsigned operands as well."
*
* However, we still sign-extend the operands before multiplying, making it easier to range-check the result.
*
* (80186/80188 and up)
*
* @this {X86CPU}
* @param {number} dst (not used)
* @param {number} src
* @return {number}
*/
X86.fnIMULn = function(dst, src)
{
var result;
dst = this.getIPWord();
if (this.sizeData == 2) {
result = X86.fnIMULrw.call(this, dst, src);
} else {
result = X86.fnIMULrd.call(this, dst, src);
}
/*
* NOTE: The above functions already accounted for 80386 cycle counts, so we are simply accounting for the
* increased time on an 80286; the 80186/80188 have even larger values, but we'll worry about that another day.
*/
if (this.model < X86.MODEL_80386) this.nStepCycles -= 12;
return result;
};
/**
* fnIMUL32(dst, src)
*
* This sets regMDHi:regMDLo to the 64-bit result of dst * src, both of which are treated as signed.
*
* @this {X86CPU}
* @param {number} dst (any 32-bit number, treated as signed)
* @param {number} src (any 32-bit number, treated as signed)
*/
X86.fnIMUL32 = function(dst, src)
{
var fNeg = false;
if (src < 0) {
src = -src|0;
fNeg = !fNeg;
}
if (dst < 0) {
dst = -dst|0;
fNeg = !fNeg;
}
X86.fnMUL32.call(this, dst, src);
if (fNeg) {
this.regMDLo = (~this.regMDLo + 1)|0;
this.regMDHi = (~this.regMDHi + (this.regMDLo? 0 : 1))|0;
}
};
/**
* fnIMULb(dst, src)
*
@ -1140,81 +1203,6 @@ X86.fnIMULb = function(dst, src)
return dst;
};
/**
* fnIMULn(dst, src)
*
* 80286_and_80287_Programmers_Reference_Manual_1987.pdf, p.B-44 (p.254) notes that:
*
* "The low 16 bits of the product of a 16-bit signed multiply are the same as those of an
* unsigned multiply. The three operand IMUL instruction can be used for unsigned operands as well."
*
* However, we still sign-extend the operands before multiplying, making it easier to range-check the result.
*
* (80186/80188 and up)
*
* @this {X86CPU}
* @param {number} dst (not used)
* @param {number} src
* @return {number}
*/
X86.fnIMULn = function(dst, src)
{
var fOverflow, result;
dst = this.getIPWord();
if (this.sizeData == 2) {
result = (((src << 16) >> 16) * ((dst << 16) >> 16))|0;
fOverflow = (result > 32767 || result < -32768);
} else {
result = (src * dst);
fOverflow = (result > 2147483647 || result < -2147483648);
this.assert(fOverflow == (result != (result|0)));
}
if (fOverflow) {
this.setCF(); this.setOF();
} else {
this.clearCF(); this.clearOF();
}
result &= this.maskData;
/*
* NOTE: These are the cycle counts for the 80286; the 80186/80188 have slightly different values (ranges):
* 22-25 and 29-32 instead of 21 and 24, respectively. However, accurate cycle counts for the 80186/80188 is
* not super-critical. TODO: Fix this someday.
*/
this.nStepCycles -= (this.regEA === X86.ADDR_INVALID? 21 : 24);
return result;
};
/**
* fnIMUL32(dst, src)
*
* This sets regMDHi:regMDLo to the 64-bit result of dst * src, both of which are treated as signed.
*
* @this {X86CPU}
* @param {number} dst (any 32-bit number, treated as signed)
* @param {number} src (any 32-bit number, treated as signed)
*/
X86.fnIMUL32 = function(dst, src)
{
var fNeg = false;
if (src < 0) {
src = -src|0;
fNeg = !fNeg;
}
if (dst < 0) {
dst = -dst|0;
fNeg = !fNeg;
}
X86.fnMUL32.call(this, dst, src);
if (fNeg) {
this.regMDLo = (~this.regMDLo + 1)|0;
this.regMDHi = (~this.regMDHi + (this.regMDLo? 0 : 1))|0;
}
};
/**
* fnIMULw(dst, src)
*
@ -1233,7 +1221,7 @@ X86.fnIMUL32 = function(dst, src)
* @this {X86CPU}
* @param {number} dst
* @param {number} src (null; AX or EAX is the implied src)
* @return {number} (we return dst unchanged, since it's actually DX:AX that's modified)
* @return {number} (we return dst unchanged, since it's actually DX:AX or EDX:EAX that's modified)
*/
X86.fnIMULw = function(dst, src)
{