summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2010-03-20 22:32:13 +0000
committermarius <marius@FreeBSD.org>2010-03-20 22:32:13 +0000
commit2fa96a801df7acbfdcb0103a9fcb6e54000bab0d (patch)
treef76c624608f8a2259a66a357e3124023774705ea /lib/libc
parent8ab5f9bf652c511a69fdb00dc41d41a4f8810892 (diff)
downloadFreeBSD-src-2fa96a801df7acbfdcb0103a9fcb6e54000bab0d.zip
FreeBSD-src-2fa96a801df7acbfdcb0103a9fcb6e54000bab0d.tar.gz
- While SPARC V9 allows tininess to be detected either before or after
rounding (impl. dep. #55), the SPARC JPS1 responsible for SPARC64 and UltraSPARC processors defines that in all cases tinyness is detected before rounding, therefore rounding up to the smallest normalised number should set the underflow flag. - If an infinite result is rounded down, the result should have an exponent 1 less than the value for infinity. PR: 144900 Submitted by: Peter Jeremy MFC after: 3 days
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/sparc64/fpu/fpu_implode.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/lib/libc/sparc64/fpu/fpu_implode.c b/lib/libc/sparc64/fpu/fpu_implode.c
index 82a8460..2a2a9d0 100644
--- a/lib/libc/sparc64/fpu/fpu_implode.c
+++ b/lib/libc/sparc64/fpu/fpu_implode.c
@@ -329,8 +329,9 @@ __fpu_ftos(fe, fp)
* right to introduce leading zeroes. Rounding then acts
* differently for normals and subnormals: the largest subnormal
* may round to the smallest normal (1.0 x 2^minexp), or may
- * remain subnormal. In the latter case, signal an underflow
- * if the result was inexact or if underflow traps are enabled.
+ * remain subnormal. A number that is subnormal before rounding
+ * will signal an underflow if the result is inexact or if underflow
+ * traps are enabled.
*
* Rounding a normal, on the other hand, always produces another
* normal (although either way the result might be too big for
@@ -345,8 +346,10 @@ __fpu_ftos(fe, fp)
if ((exp = fp->fp_exp + SNG_EXP_BIAS) <= 0) { /* subnormal */
/* -NG for g,r; -SNG_FRACBITS-exp for fraction */
(void) __fpu_shr(fp, FP_NMANT - FP_NG - SNG_FRACBITS - exp);
- if (fpround(fe, fp) && fp->fp_mant[3] == SNG_EXP(1))
+ if (fpround(fe, fp) && fp->fp_mant[3] == SNG_EXP(1)) {
+ fe->fe_cx |= FSR_UF;
return (sign | SNG_EXP(1) | 0);
+ }
if ((fe->fe_cx & FSR_NX) ||
(fe->fe_fsr & (FSR_UF << FSR_TEM_SHIFT)))
fe->fe_cx |= FSR_UF;
@@ -407,6 +410,7 @@ zero: res[1] = 0;
if ((exp = fp->fp_exp + DBL_EXP_BIAS) <= 0) {
(void) __fpu_shr(fp, FP_NMANT - FP_NG - DBL_FRACBITS - exp);
if (fpround(fe, fp) && fp->fp_mant[2] == DBL_EXP(1)) {
+ fe->fe_cx |= FSR_UF;
res[1] = 0;
return (sign | DBL_EXP(1) | 0);
}
@@ -426,7 +430,7 @@ zero: res[1] = 0;
return (sign | DBL_EXP(DBL_EXP_INFNAN) | 0);
}
res[1] = ~0;
- return (sign | DBL_EXP(DBL_EXP_INFNAN) | DBL_MASK);
+ return (sign | DBL_EXP(DBL_EXP_INFNAN - 1) | DBL_MASK);
}
done:
res[1] = fp->fp_mant[3];
@@ -468,6 +472,7 @@ zero: res[1] = res[2] = res[3] = 0;
if ((exp = fp->fp_exp + EXT_EXP_BIAS) <= 0) {
(void) __fpu_shr(fp, FP_NMANT - FP_NG - EXT_FRACBITS - exp);
if (fpround(fe, fp) && fp->fp_mant[0] == EXT_EXP(1)) {
+ fe->fe_cx |= FSR_UF;
res[1] = res[2] = res[3] = 0;
return (sign | EXT_EXP(1) | 0);
}
@@ -487,7 +492,7 @@ zero: res[1] = res[2] = res[3] = 0;
return (sign | EXT_EXP(EXT_EXP_INFNAN) | 0);
}
res[1] = res[2] = res[3] = ~0;
- return (sign | EXT_EXP(EXT_EXP_INFNAN) | EXT_MASK);
+ return (sign | EXT_EXP(EXT_EXP_INFNAN - 1) | EXT_MASK);
}
done:
res[1] = fp->fp_mant[1];
OpenPOWER on IntegriCloud