Fix guest x86/amd64 helper_fprem/helper_fprem1, by Julian Seward.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2588 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
2d0e944d1c
commit
7524c84d82
@ -3139,30 +3139,51 @@ void helper_fprem1(void)
|
|||||||
CPU86_LDouble dblq, fpsrcop, fptemp;
|
CPU86_LDouble dblq, fpsrcop, fptemp;
|
||||||
CPU86_LDoubleU fpsrcop1, fptemp1;
|
CPU86_LDoubleU fpsrcop1, fptemp1;
|
||||||
int expdif;
|
int expdif;
|
||||||
int q;
|
signed long long int q;
|
||||||
|
|
||||||
|
if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
|
||||||
|
ST0 = 0.0 / 0.0; /* NaN */
|
||||||
|
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fpsrcop = ST0;
|
fpsrcop = ST0;
|
||||||
fptemp = ST1;
|
fptemp = ST1;
|
||||||
fpsrcop1.d = fpsrcop;
|
fpsrcop1.d = fpsrcop;
|
||||||
fptemp1.d = fptemp;
|
fptemp1.d = fptemp;
|
||||||
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
|
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
|
||||||
|
|
||||||
|
if (expdif < 0) {
|
||||||
|
/* optimisation? taken from the AMD docs */
|
||||||
|
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||||
|
/* ST0 is unchanged */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (expdif < 53) {
|
if (expdif < 53) {
|
||||||
dblq = fpsrcop / fptemp;
|
dblq = fpsrcop / fptemp;
|
||||||
dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
|
/* round dblq towards nearest integer */
|
||||||
ST0 = fpsrcop - fptemp*dblq;
|
dblq = rint(dblq);
|
||||||
q = (int)dblq; /* cutting off top bits is assumed here */
|
ST0 = fpsrcop - fptemp * dblq;
|
||||||
|
|
||||||
|
/* convert dblq to q by truncating towards zero */
|
||||||
|
if (dblq < 0.0)
|
||||||
|
q = (signed long long int)(-dblq);
|
||||||
|
else
|
||||||
|
q = (signed long long int)dblq;
|
||||||
|
|
||||||
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||||
/* (C0,C1,C3) <-- (q2,q1,q0) */
|
/* (C0,C3,C1) <-- (q2,q1,q0) */
|
||||||
env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
|
env->fpus |= (q & 0x4) << (8 - 2); /* (C0) <-- q2 */
|
||||||
env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
|
env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
|
||||||
env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
|
env->fpus |= (q & 0x1) << (9 - 0); /* (C1) <-- q0 */
|
||||||
} else {
|
} else {
|
||||||
env->fpus |= 0x400; /* C2 <-- 1 */
|
env->fpus |= 0x400; /* C2 <-- 1 */
|
||||||
fptemp = pow(2.0, expdif-50);
|
fptemp = pow(2.0, expdif - 50);
|
||||||
fpsrcop = (ST0 / ST1) / fptemp;
|
fpsrcop = (ST0 / ST1) / fptemp;
|
||||||
/* fpsrcop = integer obtained by rounding to the nearest */
|
/* fpsrcop = integer obtained by chopping */
|
||||||
fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
|
fpsrcop = (fpsrcop < 0.0) ?
|
||||||
floor(fpsrcop): ceil(fpsrcop);
|
-(floor(fabs(fpsrcop))) : floor(fpsrcop);
|
||||||
ST0 -= (ST1 * fpsrcop * fptemp);
|
ST0 -= (ST1 * fpsrcop * fptemp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3172,30 +3193,52 @@ void helper_fprem(void)
|
|||||||
CPU86_LDouble dblq, fpsrcop, fptemp;
|
CPU86_LDouble dblq, fpsrcop, fptemp;
|
||||||
CPU86_LDoubleU fpsrcop1, fptemp1;
|
CPU86_LDoubleU fpsrcop1, fptemp1;
|
||||||
int expdif;
|
int expdif;
|
||||||
int q;
|
signed long long int q;
|
||||||
|
|
||||||
fpsrcop = ST0;
|
if (isinf(ST0) || isnan(ST0) || isnan(ST1) || (ST1 == 0.0)) {
|
||||||
fptemp = ST1;
|
ST0 = 0.0 / 0.0; /* NaN */
|
||||||
|
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fpsrcop = (CPU86_LDouble)ST0;
|
||||||
|
fptemp = (CPU86_LDouble)ST1;
|
||||||
fpsrcop1.d = fpsrcop;
|
fpsrcop1.d = fpsrcop;
|
||||||
fptemp1.d = fptemp;
|
fptemp1.d = fptemp;
|
||||||
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
|
expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
|
||||||
if ( expdif < 53 ) {
|
|
||||||
dblq = fpsrcop / fptemp;
|
if (expdif < 0) {
|
||||||
dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
|
/* optimisation? taken from the AMD docs */
|
||||||
ST0 = fpsrcop - fptemp*dblq;
|
|
||||||
q = (int)dblq; /* cutting off top bits is assumed here */
|
|
||||||
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||||
/* (C0,C1,C3) <-- (q2,q1,q0) */
|
/* ST0 is unchanged */
|
||||||
env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
|
return;
|
||||||
env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
|
}
|
||||||
env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
|
|
||||||
|
if ( expdif < 53 ) {
|
||||||
|
dblq = fpsrcop/*ST0*/ / fptemp/*ST1*/;
|
||||||
|
/* round dblq towards zero */
|
||||||
|
dblq = (dblq < 0.0) ? ceil(dblq) : floor(dblq);
|
||||||
|
ST0 = fpsrcop/*ST0*/ - fptemp * dblq;
|
||||||
|
|
||||||
|
/* convert dblq to q by truncating towards zero */
|
||||||
|
if (dblq < 0.0)
|
||||||
|
q = (signed long long int)(-dblq);
|
||||||
|
else
|
||||||
|
q = (signed long long int)dblq;
|
||||||
|
|
||||||
|
env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
|
||||||
|
/* (C0,C3,C1) <-- (q2,q1,q0) */
|
||||||
|
env->fpus |= (q & 0x4) << (8 - 2); /* (C0) <-- q2 */
|
||||||
|
env->fpus |= (q & 0x2) << (14 - 1); /* (C3) <-- q1 */
|
||||||
|
env->fpus |= (q & 0x1) << (9 - 0); /* (C1) <-- q0 */
|
||||||
} else {
|
} else {
|
||||||
|
int N = 32 + (expdif % 32); /* as per AMD docs */
|
||||||
env->fpus |= 0x400; /* C2 <-- 1 */
|
env->fpus |= 0x400; /* C2 <-- 1 */
|
||||||
fptemp = pow(2.0, expdif-50);
|
fptemp = pow(2.0, (double)(expdif - N));
|
||||||
fpsrcop = (ST0 / ST1) / fptemp;
|
fpsrcop = (ST0 / ST1) / fptemp;
|
||||||
/* fpsrcop = integer obtained by chopping */
|
/* fpsrcop = integer obtained by chopping */
|
||||||
fpsrcop = (fpsrcop < 0.0)?
|
fpsrcop = (fpsrcop < 0.0) ?
|
||||||
-(floor(fabs(fpsrcop))): floor(fpsrcop);
|
-(floor(fabs(fpsrcop))) : floor(fpsrcop);
|
||||||
ST0 -= (ST1 * fpsrcop * fptemp);
|
ST0 -= (ST1 * fpsrcop * fptemp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user