summaryrefslogtreecommitdiff
path: root/gcc/real.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1996-04-14 12:53:43 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1996-04-14 12:53:43 +0000
commit29e608937034c2fd1df96e630d3055fc23c8e35c (patch)
tree2be7c84d1b2d454e09d66c00d9e936b43ddc0089 /gcc/real.c
parent24460e25851eea59dd6c881b16c5d0ee6bfef0f5 (diff)
downloadgcc-29e608937034c2fd1df96e630d3055fc23c8e35c.tar.gz
(ereal_from_{int,uint}): New arg, MODE.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@11763 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/real.c')
-rw-r--r--gcc/real.c70
1 files changed, 68 insertions, 2 deletions
diff --git a/gcc/real.c b/gcc/real.c
index e8f78ad73cf..b5e29859658 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -758,14 +758,17 @@ efixui (x)
/* REAL_VALUE_FROM_INT macro. */
void
-ereal_from_int (d, i, j)
+ereal_from_int (d, i, j, mode)
REAL_VALUE_TYPE *d;
HOST_WIDE_INT i, j;
+ enum machine_mode mode;
{
unsigned EMUSHORT df[NE], dg[NE];
HOST_WIDE_INT low, high;
int sign;
+ if (GET_MODE_CLASS (mode) != MODE_FLOAT)
+ abort ();
sign = 0;
low = i;
if ((high = j) < 0)
@@ -785,6 +788,36 @@ ereal_from_int (d, i, j)
eadd (df, dg, dg);
if (sign)
eneg (dg);
+
+ /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS.
+ Avoid double-rounding errors later by rounding off now from the
+ extra-wide internal format to the requested precision. */
+ switch (GET_MODE_BITSIZE (mode))
+ {
+ case 32:
+ etoe24 (dg, df);
+ e24toe (df, dg);
+ break;
+
+ case 64:
+ etoe53 (dg, df);
+ e53toe (df, dg);
+ break;
+
+ case 96:
+ etoe64 (dg, df);
+ e64toe (df, dg);
+ break;
+
+ case 128:
+ etoe113 (dg, df);
+ e113toe (df, dg);
+ break;
+
+ default:
+ abort ();
+ }
+
PUT_REAL (dg, d);
}
@@ -792,13 +825,16 @@ ereal_from_int (d, i, j)
/* REAL_VALUE_FROM_UNSIGNED_INT macro. */
void
-ereal_from_uint (d, i, j)
+ereal_from_uint (d, i, j, mode)
REAL_VALUE_TYPE *d;
unsigned HOST_WIDE_INT i, j;
+ enum machine_mode mode;
{
unsigned EMUSHORT df[NE], dg[NE];
unsigned HOST_WIDE_INT low, high;
+ if (GET_MODE_CLASS (mode) != MODE_FLOAT)
+ abort ();
low = i;
high = j;
eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
@@ -806,6 +842,36 @@ ereal_from_uint (d, i, j)
emul (dg, df, dg);
ultoe (&low, df);
eadd (df, dg, dg);
+
+ /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS.
+ Avoid double-rounding errors later by rounding off now from the
+ extra-wide internal format to the requested precision. */
+ switch (GET_MODE_BITSIZE (mode))
+ {
+ case 32:
+ etoe24 (dg, df);
+ e24toe (df, dg);
+ break;
+
+ case 64:
+ etoe53 (dg, df);
+ e53toe (df, dg);
+ break;
+
+ case 96:
+ etoe64 (dg, df);
+ e64toe (df, dg);
+ break;
+
+ case 128:
+ etoe113 (dg, df);
+ e113toe (df, dg);
+ break;
+
+ default:
+ abort ();
+ }
+
PUT_REAL (dg, d);
}