summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--soft-fp/op-common.h34
-rw-r--r--soft-fp/soft-fp.h5
3 files changed, 50 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 18d1cbcfb6..29a4113dfe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2014-10-09 Joseph Myers <joseph@codesourcery.com>
+ * 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.