diff --git a/ChangeLog b/ChangeLog index 18d1cbcfb6..29a4113dfe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2014-10-09 Joseph Myers + * soft-fp/soft-fp.h (FP_DENORM_ZERO): New macro. + * soft-fp/op-common.h (_FP_UNPACK_CANONICAL): Check + FP_DENORM_ZERO. + (_FP_CHECK_FLUSH_ZERO): New macro. + (_FP_ADD_INTERNAL): Call _FP_CHECK_FLUSH_ZERO. + (_FP_CMP): Likewise. + (_FP_CMP_EQ): Likewise. + (_FP_TO_INT): Do not set inexact for subnormal arguments if + FP_DENORM_ZERO. + (FP_EXTEND): Call _FP_CHECK_FLUSH_ZERO. + (FP_TRUNC): Likewise. + * soft-fp/op-common.h (_FP_TO_INT): Ensure maximum exponent is treated as invalid conversion, not as normal exponent. diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h index e0a108a6ee..3da234ba33 100644 --- a/soft-fp/op-common.h +++ b/soft-fp/op-common.h @@ -63,6 +63,12 @@ case 0: \ if (_FP_FRAC_ZEROP_##wc (X)) \ X##_c = FP_CLS_ZERO; \ + else if (FP_DENORM_ZERO) \ + { \ + X##_c = FP_CLS_ZERO; \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + } \ else \ { \ /* A denormalized number. */ \ @@ -99,6 +105,21 @@ other classification is not done. */ #define _FP_UNPACK_SEMIRAW(fs, wc, X) _FP_FRAC_SLL_##wc (X, _FP_WORKBITS) +/* Check whether a raw or semi-raw input value should be flushed to + zero, and flush it to zero if so. */ +#define _FP_CHECK_FLUSH_ZERO(fs, wc, X) \ + do \ + { \ + if (FP_DENORM_ZERO \ + && X##_e == 0 \ + && !_FP_FRAC_ZEROP_##wc (X)) \ + { \ + _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ + FP_SET_EXCEPTION (FP_EX_DENORM); \ + } \ + } \ + while (0) + /* A semi-raw value has overflowed to infinity. Adjust the mantissa and exponent appropriately. */ #define _FP_OVERFLOW_SEMIRAW(fs, wc, X) \ @@ -387,6 +408,8 @@ #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \ do \ { \ + _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ + _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ if (X##_s == Y##_s) \ { \ /* Addition. */ \ @@ -1222,6 +1245,9 @@ int _FP_CMP_is_zero_x; \ int _FP_CMP_is_zero_y; \ \ + _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ + _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ + \ _FP_CMP_is_zero_x \ = (!X##_e && _FP_FRAC_ZEROP_##wc (X)) ? 1 : 0; \ _FP_CMP_is_zero_y \ @@ -1264,6 +1290,9 @@ } \ else \ { \ + _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ + _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ + \ ret = !(X##_e == Y##_e \ && _FP_FRAC_EQ_##wc (X, Y) \ && (X##_s == Y##_s || (!X##_e && _FP_FRAC_ZEROP_##wc (X)))); \ @@ -1361,7 +1390,8 @@ { \ if (!_FP_FRAC_ZEROP_##wc (X)) \ { \ - FP_SET_EXCEPTION (FP_EX_INEXACT); \ + if (!FP_DENORM_ZERO) \ + FP_SET_EXCEPTION (FP_EX_INEXACT); \ FP_SET_EXCEPTION (FP_EX_DENORM); \ } \ } \ @@ -1540,6 +1570,7 @@ { \ if (S##_e == 0) \ { \ + _FP_CHECK_FLUSH_ZERO (sfs, swc, S); \ if (_FP_FRAC_ZEROP_##swc (S)) \ D##_e = 0; \ else if (_FP_EXPBIAS_##dfs \ @@ -1625,6 +1656,7 @@ { \ if (S##_e == 0) \ { \ + _FP_CHECK_FLUSH_ZERO (sfs, swc, S); \ D##_e = 0; \ if (_FP_FRAC_ZEROP_##swc (S)) \ _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \ diff --git a/soft-fp/soft-fp.h b/soft-fp/soft-fp.h index 4018b0ee91..3ac269ecf7 100644 --- a/soft-fp/soft-fp.h +++ b/soft-fp/soft-fp.h @@ -123,6 +123,11 @@ # define FP_HANDLE_EXCEPTIONS do {} while (0) #endif +/* Whether to flush subnormal inputs to zero with the same sign. */ +#ifndef FP_DENORM_ZERO +# define FP_DENORM_ZERO 0 +#endif + #ifndef FP_INHIBIT_RESULTS /* By default we write the results always. sfp-machine may override this and e.g.