On Fri, Apr 12, 2013 at 04:37:52PM +0100, Peter Maydell wrote: > In handling float64_muladd, if we end up doing a subtraction of the > product and c, and the 128 bit result of this subtraction happens to > have its most significant bit in bit 63, we weren't handling this > correctly when attempting to normalize to put the most significant > bit into bit 126. We would end up doing a right shift by a negative > number (undefined behaviour in C) so at best we would return an > incorrect result to the guest. MSB in bit 63 has to be handled as a > special case separately from MSB in 0..62 and MSB in 63..126. (MSB > in 127 is not possible.) > > Signed-off-by: Peter Maydell <peter.mayd...@linaro.org> > --- > Specific test vector which triggers this: > a = 3fffffffffe00000 b = 3fffffffffe00000 c = c00fffffffc00000 > > Also tested with my usual set of random test vectors. > > fpu/softfloat.c | 12 +++++++++--- > 1 file changed, 9 insertions(+), 3 deletions(-) > > diff --git a/fpu/softfloat.c b/fpu/softfloat.c > index 83ccc4b..7ba51b6 100644 > --- a/fpu/softfloat.c > +++ b/fpu/softfloat.c > @@ -3898,9 +3898,15 @@ float64 float64_muladd(float64 a, float64 b, float64 > c, int flags STATUS_PARAM) > } > zExp -= shiftcount; > } else { > - shiftcount = countLeadingZeros64(zSig1) - 1; > - zSig0 = zSig1 << shiftcount; > - zExp -= (shiftcount + 64); > + shiftcount = countLeadingZeros64(zSig1); > + if (shiftcount == 0) { > + zSig0 = (zSig1 >> 1) | (zSig1 & 1); > + zExp -= 63; > + } else { > + shiftcount--; > + zSig0 = zSig1 << shiftcount; > + zExp -= (shiftcount + 64); > + } > } > return roundAndPackFloat64(zSign, zExp, zSig0 STATUS_VAR); > }
Thanks, applied. -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurel...@aurel32.net http://www.aurel32.net