summaryrefslogtreecommitdiff
path: root/float.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-10-16 11:48:07 -0700
committerH. Peter Anvin <hpa@zytor.com>2007-10-16 11:48:07 -0700
commitfab3a6c9de9c56f1db7770c7c5e0271e33455ea2 (patch)
treec46a56d27737c008cdd2b8c30edcacf433847379 /float.c
parent125c878e96b5aeb50ae0c7f68847200262a9340f (diff)
downloadnasm-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.c47
1 files changed, 37 insertions, 10 deletions
diff --git a/float.c b/float.c
index 9230781..18156ef 100644
--- a/float.c
+++ b/float.c
@@ -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;
}