aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1995-08-15 17:57:41 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1995-08-15 17:57:41 -0400
commitd56390c488c8dba706d06220b2d2a750c9e3c6bf (patch)
tree901fd3ba32cfc6cef114ac588283b5ef1723462a /gcc
parentf4510f3757fc32ae871aa5e7c77a078590b173ed (diff)
downloadgcc-d56390c488c8dba706d06220b2d2a750c9e3c6bf.zip
gcc-d56390c488c8dba706d06220b2d2a750c9e3c6bf.tar.gz
gcc-d56390c488c8dba706d06220b2d2a750c9e3c6bf.tar.bz2
(ediv, emul): Set sign bit of IEEE -0.0 result.
From-SVN: r10244
Diffstat (limited to 'gcc')
-rw-r--r--gcc/real.c74
1 files changed, 41 insertions, 33 deletions
diff --git a/gcc/real.c b/gcc/real.c
index 5432ed3..082cfd0 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -2635,9 +2635,13 @@ ediv (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
unsigned EMUSHORT ai[NI], bi[NI];
- int i;
+ int i, sign;
EMULONG lt, lta, ltb;
+/* IEEE says if result is not a NaN, the sign is "-" if and only if
+ operands have opposite signs -- but flush -0 to 0 later if not IEEE. */
+ sign = eisneg(a) ^ eisneg(b);
+
#ifdef NANS
/* Return any NaN input. */
if (eisnan (a))
@@ -2655,7 +2659,7 @@ ediv (a, b, c)
|| (eisinf (a) && eisinf (b)))
{
mtherr ("ediv", INVALID);
- enan (c, eisneg (a) ^ eisneg (b));
+ enan (c, sign);
return;
}
#endif
@@ -2663,18 +2667,14 @@ ediv (a, b, c)
#ifdef INFINITY
if (eisinf (b))
{
- if (eisneg (a) ^ eisneg (b))
- *(c + (NE - 1)) = 0x8000;
- else
- *(c + (NE - 1)) = 0;
einfin (c);
- return;
+ goto divsign;
}
/* Anything else over infinity is zero. */
if (eisinf (a))
{
eclear (c);
- return;
+ goto divsign;
}
#endif
emovi (a, ai);
@@ -2692,7 +2692,7 @@ ediv (a, b, c)
}
}
eclear (c);
- return;
+ goto divsign;
}
dnzro1:
@@ -2706,15 +2706,11 @@ ediv (a, b, c)
goto dnzro2;
}
}
- if (ai[0] == bi[0])
- *(c + (NE - 1)) = 0;
- else
- *(c + (NE - 1)) = 0x8000;
/* Divide by zero is not an invalid operation.
It is a divide-by-zero operation! */
einfin (c);
mtherr ("ediv", SING);
- return;
+ goto divsign;
}
dnzro2:
@@ -2722,12 +2718,18 @@ ediv (a, b, c)
/* calculate exponent */
lt = ltb - lta + EXONE;
emdnorm (bi, i, 0, lt, 64);
- /* set the sign */
- if (ai[0] == bi[0])
- bi[0] = 0;
- else
- bi[0] = 0Xffff;
emovo (bi, c);
+
+ divsign:
+
+ if (sign
+#ifndef IEEE
+ && (ecmp (c, ezero) != 0)
+#endif
+ )
+ *(c+(NE-1)) |= 0x8000;
+ else
+ *(c+(NE-1)) &= ~0x8000;
}
/* Multiply e-types A and B, return e-type product C. */
@@ -2737,9 +2739,13 @@ emul (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
unsigned EMUSHORT ai[NI], bi[NI];
- int i, j;
+ int i, j, sign;
EMULONG lt, lta, ltb;
+/* IEEE says if result is not a NaN, the sign is "-" if and only if
+ operands have opposite signs -- but flush -0 to 0 later if not IEEE. */
+ sign = eisneg(a) ^ eisneg(b);
+
#ifdef NANS
/* NaN times anything is the same NaN. */
if (eisnan (a))
@@ -2757,7 +2763,7 @@ emul (a, b, c)
|| (eisinf (b) && (ecmp (a, ezero) == 0)))
{
mtherr ("emul", INVALID);
- enan (c, eisneg (a) ^ eisneg (b));
+ enan (c, sign);
return;
}
#endif
@@ -2765,12 +2771,8 @@ emul (a, b, c)
#ifdef INFINITY
if (eisinf (a) || eisinf (b))
{
- if (eisneg (a) ^ eisneg (b))
- *(c + (NE - 1)) = 0x8000;
- else
- *(c + (NE - 1)) = 0;
einfin (c);
- return;
+ goto mulsign;
}
#endif
emovi (a, ai);
@@ -2788,7 +2790,7 @@ emul (a, b, c)
}
}
eclear (c);
- return;
+ goto mulsign;
}
mnzer1:
@@ -2803,7 +2805,7 @@ emul (a, b, c)
}
}
eclear (c);
- return;
+ goto mulsign;
}
mnzer2:
@@ -2812,12 +2814,18 @@ emul (a, b, c)
/* calculate exponent */
lt = lta + ltb - (EXONE - 1);
emdnorm (bi, j, 0, lt, 64);
- /* calculate sign of product */
- if (ai[0] == bi[0])
- bi[0] = 0;
- else
- bi[0] = 0xffff;
emovo (bi, c);
+
+ mulsign:
+
+ if (sign
+#ifndef IEEE
+ && (ecmp (c, ezero) != 0)
+#endif
+ )
+ *(c+(NE-1)) |= 0x8000;
+ else
+ *(c+(NE-1)) &= ~0x8000;
}
/* Convert double precision PE to e-type Y. */