diff options
author | H. Peter Anvin <hpa@zytor.com> | 2007-10-16 11:48:07 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2007-10-16 11:48:07 -0700 |
commit | fab3a6c9de9c56f1db7770c7c5e0271e33455ea2 (patch) | |
tree | c46a56d27737c008cdd2b8c30edcacf433847379 /float.c | |
parent | 125c878e96b5aeb50ae0c7f68847200262a9340f (diff) | |
download | nasm-fab3a6c9de9c56f1db7770c7c5e0271e33455ea2.tar.gz nasm-fab3a6c9de9c56f1db7770c7c5e0271e33455ea2.tar.bz2 nasm-fab3a6c9de9c56f1db7770c7c5e0271e33455ea2.zip |
Floating-point warning fixes; fix round-to-overflow
Actually generate the appropriate floating-point warnings, and only
one per assembly, pretty please.
Correct the round-to-overflow condition; as written all numbers with a
positive exponent were considered overflows!
Diffstat (limited to 'float.c')
-rw-r--r-- | float.c | 47 |
1 files changed, 37 insertions, 10 deletions
@@ -128,7 +128,8 @@ static bool ieee_flconvert(const char *string, uint16_t * mant, bool started, seendot, warned; p = digits; tenpwr = 0; - started = seendot = warned = false; + started = seendot = false; + warned = (pass0 != 1); while (*string && *string != 'E' && *string != 'e') { if (*string == '.') { if (!seendot) { @@ -541,11 +542,23 @@ static void set_bit(uint16_t *mant, int bit) } /* Test a single bit */ -static int test_bit(uint16_t *mant, int bit) +static int test_bit(const uint16_t *mant, int bit) { return (mant[bit >> 4] >> (~bit & 15)) & 1; } +/* Report if the mantissa value is all zero */ +static bool is_zero(const uint16_t *mant) +{ + int i; + + for (i = 0; i < MANT_WORDS; i++) + if (mant[i]) + return false; + + return true; +} + /* Produce standard IEEE formats, with implicit or explicit integer bit; this makes the following assumptions: @@ -643,11 +656,15 @@ static int to_float(const char *str, int sign, uint8_t * result, exponent >= 2 - expmax - fmt->mantissa) { type = FL_DENORMAL; } else if (exponent > 0) { - error(ERR_WARNING|ERR_WARN_FL_OVERFLOW, - "overflow in floating-point constant"); + if (pass0 == 1) + error(ERR_WARNING|ERR_WARN_FL_OVERFLOW, + "overflow in floating-point constant"); type = FL_INFINITY; } else { /* underflow */ + if (pass0 == 1) + error(ERR_WARNING|ERR_WARN_FL_UNDERFLOW, + "underflow in floating-point constant"); type = FL_ZERO; } } else { @@ -674,9 +691,18 @@ static int to_float(const char *str, int sign, uint8_t * result, if (!fmt->explicit) mant[one_pos] &= ~one_mask; /* remove explicit one */ mant[0] |= exponent << (15 - fmt->exponent); - } else if (daz) { - /* Flush denormals to zero */ - goto zero; + } else { + if (daz || is_zero(mant)) { + /* Flush denormals to zero */ + if (pass0 == 1) + error(ERR_WARNING|ERR_WARN_FL_UNDERFLOW, + "underflow in floating-point constant"); + goto zero; + } else { + if (pass0 == 1) + error(ERR_WARNING|ERR_WARN_FL_DENORM, + "denormal floating-point constant"); + } } break; } @@ -689,9 +715,10 @@ static int to_float(const char *str, int sign, uint8_t * result, if (test_bit(mant, fmt->exponent+fmt->explicit-1)) { ieee_shr(mant, 1); exponent++; - if (exponent >= expmax) { - error(ERR_WARNING|ERR_WARN_FL_OVERFLOW, - "overflow in floating-point constant"); + if (exponent >= (expmax << 1)-1) { + if (pass0 == 1) + error(ERR_WARNING|ERR_WARN_FL_OVERFLOW, + "overflow in floating-point constant"); type = FL_INFINITY; goto overflow; } |