summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-10-16 11:32:58 -0700
committerH. Peter Anvin <hpa@zytor.com>2007-10-16 11:32:58 -0700
commit125c878e96b5aeb50ae0c7f68847200262a9340f (patch)
tree6bce054d902250707e5d7be8cbe0fd0e36327ed6
parent630b52013ab1ebd53e043d9c5dec36fca609a95c (diff)
downloadnasm-125c878e96b5aeb50ae0c7f68847200262a9340f.tar.gz
Handle rounding of denorms correctly; make fp overflow a warning
- Handle rounding of denorms correctly - Make fp overflow a warning, not an error (produces Inf) - Make fp warnings controllable
-rw-r--r--float.c34
-rw-r--r--nasm.c16
-rw-r--r--nasmlib.h20
-rw-r--r--test/floatx.asm15
4 files changed, 59 insertions, 26 deletions
diff --git a/float.c b/float.c
index 6db5fba6..92307817 100644
--- a/float.c
+++ b/float.c
@@ -149,7 +149,7 @@ static bool ieee_flconvert(const char *string, uint16_t * mant,
*p++ = *string - '0';
} else {
if (!warned) {
- error(ERR_WARNING,
+ error(ERR_WARNING|ERR_WARN_FL_TOOLONG,
"floating-point constant significand contains "
"more than %i digits", MANT_DIGITS);
warned = true;
@@ -639,11 +639,11 @@ static int to_float(const char *str, int sign, uint8_t * result,
exponent--;
if (exponent >= 2 - expmax && exponent <= expmax) {
type = FL_NORMAL;
- } else if (!daz && exponent < 2 - expmax &&
+ } else if (exponent < 2 - expmax &&
exponent >= 2 - expmax - fmt->mantissa) {
type = FL_DENORMAL;
} else if (exponent > 0) {
- error(ERR_NONFATAL,
+ error(ERR_WARNING|ERR_WARN_FL_OVERFLOW,
"overflow in floating-point constant");
type = FL_INFINITY;
} else {
@@ -658,6 +658,7 @@ static int to_float(const char *str, int sign, uint8_t * result,
switch (type) {
case FL_ZERO:
+ zero:
memset(mant, 0, sizeof mant);
break;
@@ -666,15 +667,16 @@ static int to_float(const char *str, int sign, uint8_t * result,
shift = -(exponent + expmax - 2 - fmt->exponent)
+ fmt->explicit;
ieee_shr(mant, shift);
- if (ieee_round(sign, mant, fmt->words)
- || (shift > 0 && test_bit(mant, shift-1))) {
- ieee_shr(mant, 1);
- if (!shift) {
- /* XXX: We shifted into the normal range? */
- /* XXX: This is definitely not right... */
- mant[0] |= 0x8000;
- }
- exponent++; /* UNUSED, WTF? */
+ ieee_round(sign, mant, fmt->words);
+ if (mant[one_pos] & one_mask) {
+ /* One's position is set, we rounded up into normal range */
+ exponent = 1;
+ 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;
}
break;
}
@@ -687,7 +689,12 @@ 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++;
- /* XXX: Handle overflow here */
+ if (exponent >= expmax) {
+ error(ERR_WARNING|ERR_WARN_FL_OVERFLOW,
+ "overflow in floating-point constant");
+ type = FL_INFINITY;
+ goto overflow;
+ }
}
if (!fmt->explicit)
@@ -698,6 +705,7 @@ static int to_float(const char *str, int sign, uint8_t * result,
case FL_INFINITY:
case FL_QNAN:
case FL_SNAN:
+ overflow:
memset(mant, 0, sizeof mant);
mant[0] = ((1 << fmt->exponent)-1) << (15 - fmt->exponent);
if (fmt->explicit)
diff --git a/nasm.c b/nasm.c
index fa13460a..3045534a 100644
--- a/nasm.c
+++ b/nasm.c
@@ -92,8 +92,8 @@ static enum op_type operating_mode;
* Which of the suppressible warnings are suppressed. Entry zero
* doesn't do anything. Initial defaults are given here.
*/
-static char suppressed[1 + ERR_WARN_MAX] = {
- 0, true, true, true, false, true
+static bool suppressed[1 + ERR_WARN_MAX] = {
+ 0, true, true, true, false, true, false, true, true, false
};
/*
@@ -102,8 +102,8 @@ static char suppressed[1 + ERR_WARN_MAX] = {
*/
static const char *suppressed_names[1 + ERR_WARN_MAX] = {
NULL, "macro-params", "macro-selfref", "orphan-labels",
- "number-overflow",
- "gnu-elf-extensions"
+ "number-overflow", "gnu-elf-extensions", "float-overflow",
+ "float-denorm", "float-underflow", "float-toolong"
};
/*
@@ -115,8 +115,12 @@ static const char *suppressed_what[1 + ERR_WARN_MAX] = {
"macro calls with wrong no. of params",
"cyclic macro self-references",
"labels alone on lines without trailing `:'",
- "numeric constants greater than 0xFFFFFFFF",
- "using 8- or 16-bit relocation in ELF, a GNU extension"
+ "numeric constants do not fit in 32 bits",
+ "using 8- or 16-bit relocation in ELF32, a GNU extension"
+ "floating point overflow",
+ "floating point denormal",
+ "floating point underflow",
+ "too many digits in floating-point number",
};
/*
diff --git a/nasmlib.h b/nasmlib.h
index 14b28677..08a68a5c 100644
--- a/nasmlib.h
+++ b/nasmlib.h
@@ -59,15 +59,21 @@ typedef void (*efunc) (int severity, const char *fmt, ...);
*/
#define ERR_WARN_MASK 0x0000FF00 /* the mask for this feature */
-#define ERR_WARN_SHR 8 /* how far to shift right */
+#define ERR_WARN_SHR 8 /* how far to shift right */
-#define ERR_WARN_MNP 0x00000100 /* macro-num-parameters warning */
-#define ERR_WARN_MSR 0x00000200 /* macro self-reference */
-#define ERR_WARN_OL 0x00000300 /* orphan label (no colon, and
+#define WARN(x) ((x) << ERR_WARN_SHR)
+
+#define ERR_WARN_MNP WARN(1) /* macro-num-parameters warning */
+#define ERR_WARN_MSR WARN(2) /* macro self-reference */
+#define ERR_WARN_OL WARN(3) /* orphan label (no colon, and
* alone on line) */
-#define ERR_WARN_NOV 0x00000400 /* numeric overflow */
-#define ERR_WARN_GNUELF 0x00000500 /* using GNU ELF extensions */
-#define ERR_WARN_MAX 5 /* the highest numbered one */
+#define ERR_WARN_NOV WARN(4) /* numeric overflow */
+#define ERR_WARN_GNUELF WARN(5) /* using GNU ELF extensions */
+#define ERR_WARN_FL_OVERFLOW WARN(6) /* FP overflow */
+#define ERR_WARN_FL_DENORM WARN(7) /* FP denormal */
+#define ERR_WARN_FL_UNDERFLOW WARN(8) /* FP underflow */
+#define ERR_WARN_FL_TOOLONG WARN(9) /* FP too many digits */
+#define ERR_WARN_MAX 8 /* the highest numbered one */
/*
* Wrappers around malloc, realloc and free. nasm_malloc will
diff --git a/test/floatx.asm b/test/floatx.asm
index 28b805e2..dd6f5118 100644
--- a/test/floatx.asm
+++ b/test/floatx.asm
@@ -28,9 +28,12 @@
dw 0x0.0000123456789p-10
dw 0x1.0p-25 ; Underflow
dw 0x1.0p-24 ; Smallest denorm
+ dw 0x1.ffffffffffffffffffffffffffffp-16 ; Rounds to denorm
dw 0x1.0p-15 ; Denorm
+ dw 0x1.ffffffffffffffffffffffffffffp-15 ; Rounds to normal
dw 0x1.0p-14 ; Smallest non-denorm
dw 0x1.0p+15 ; Biggest possible exponent
+ dw 0x1.ffffffffffffffffffffffffffffp+15 ; Rounds to infinity
dw Inf ; Infinity
dw NaN
@@ -60,9 +63,12 @@
dd 0x123456789.0p+64
dd 0x1.0p-150 ; Underflow
dd 0x1.0p-149 ; Smallest denorm
+ dd 0x1.ffffffffffffffffffffffffffffp-128 ; Rounds to denorm
dd 0x1.0p-127 ; Denorm
+ dd 0x1.ffffffffffffffffffffffffffffp-127 ; Rounds to normal
dd 0x1.0p-126 ; Smallest non-denorm
dd 0x1.0p+127 ; Biggest possible exponent
+ dd 0x1.ffffffffffffffffffffffffffffp+127 ; Rounds to infinity
dd Inf ; Infinity
dd NaN
@@ -92,9 +98,12 @@
dq 0x123456789.0p+300
dq 0x1.0p-1075 ; Underflow
dq 0x1.0p-1074 ; Smallest denorm
+ dq 0x1.ffffffffffffffffffffffffffffp-1024 ; Rounds to denorm
dq 0x1.0p-1023 ; Denorm
+ dq 0x1.ffffffffffffffffffffffffffffp-1023 ; Rounds to normal
dq 0x1.0p-1022 ; Smallest non-denorm
dq 0x1.0p+1023 ; Biggest possible exponent
+ dq 0x1.ffffffffffffffffffffffffffffp+1023 ; Rounds to infinity
dq Inf ; Infinity
dq NaN
@@ -124,9 +133,12 @@
dt 0x123456789.0p+1024
dt 0x1.0p-16446 ; Underflow
dt 0x1.0p-16445 ; Smallest denorm
+ dt 0x1.ffffffffffffffffffffffffffffp-16384 ; Rounds to denorm
dt 0x1.0p-16383 ; Denorm
+ dt 0x1.ffffffffffffffffffffffffffffp-16383 ; Rounds to normal
dt 0x1.0p-16382 ; Smallest non-denorm
dt 0x1.0p+16383 ; Biggest possible exponent
+ dq 0x1.ffffffffffffffffffffffffffffp+16383 ; Rounds to infinity
dt Inf ; Infinity
dt NaN
@@ -156,8 +168,11 @@
do 0x123456789.0p+1024
do 0x1.0p-16495 ; Underflow
do 0x1.0p-16494 ; Smallest denorm
+ do 0x1.ffffffffffffffffffffffffffffffffp-16384 ; Rounds to denorm
do 0x1.0p-16383 ; Denorm
+ do 0x1.ffffffffffffffffffffffffffffffffp-16383 ; Rounds to normal
do 0x1.0p-16382 ; Smallest non-denorm
do 0x1.0p+16383 ; Biggest possible exponent
+ do 0x1.ffffffffffffffffffffffffffffffffp+16383 ; Rounds to infinity
do Inf ; Infinity
do NaN