mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
softfloat: Fix single-to-half precision float conversions
Fix various bugs in the single-to-half-precision conversion code: * input NaNs not correctly converted in IEEE mode (fixed by defining and using a commonNaNToFloat16()) * wrong values returned when converting NaN/Inf into non-IEEE half precision value * wrong values returned for conversion of values which are on the boundary between denormal and zero for the half precision format * zeroes not correctly identified * excessively large results in non-IEEE mode should generate InvalidOp, not Overflow Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
bcd4d9afd4
commit
600e30d2b2
2 changed files with 38 additions and 11 deletions
|
@ -2796,24 +2796,30 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
|
|||
aSign = extractFloat32Sign( a );
|
||||
if ( aExp == 0xFF ) {
|
||||
if (aSig) {
|
||||
/* Make sure correct exceptions are raised. */
|
||||
float32ToCommonNaN(a STATUS_VAR);
|
||||
aSig |= 0x00400000;
|
||||
/* Input is a NaN */
|
||||
float16 r = commonNaNToFloat16( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
|
||||
if (!ieee) {
|
||||
return packFloat16(aSign, 0, 0);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
return packFloat16(aSign, 0x1f, aSig >> 13);
|
||||
/* Infinity */
|
||||
if (!ieee) {
|
||||
float_raise(float_flag_invalid STATUS_VAR);
|
||||
return packFloat16(aSign, 0x1f, 0x3ff);
|
||||
}
|
||||
return packFloat16(aSign, 0x1f, 0);
|
||||
}
|
||||
if (aExp == 0 && aSign == 0) {
|
||||
if (aExp == 0 && aSig == 0) {
|
||||
return packFloat16(aSign, 0, 0);
|
||||
}
|
||||
/* Decimal point between bits 22 and 23. */
|
||||
aSig |= 0x00800000;
|
||||
aExp -= 0x7f;
|
||||
if (aExp < -14) {
|
||||
mask = 0x007fffff;
|
||||
if (aExp < -24) {
|
||||
aExp = -25;
|
||||
} else {
|
||||
mask >>= 24 + aExp;
|
||||
mask = 0x00ffffff;
|
||||
if (aExp >= -24) {
|
||||
mask >>= 25 + aExp;
|
||||
}
|
||||
} else {
|
||||
mask = 0x00001fff;
|
||||
|
@ -2855,7 +2861,7 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
|
|||
}
|
||||
} else {
|
||||
if (aExp > 16) {
|
||||
float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
|
||||
float_raise(float_flag_invalid | float_flag_inexact STATUS_VAR);
|
||||
return packFloat16(aSign, 0x1f, 0x3ff);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue