#include "config.h"
#include "system.h"
#include "tree.h"
#include "toplev.h"
#ifdef REAL_ARITHMETIC
#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
#define DEC 1
#else
#if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
#define IBM 1
#else
#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
#define C4X 1
#else
#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
#define IEEE
#else
unknown arithmetic type
#define UNK 1
#endif
#endif
#endif
#endif
#define REAL_WORDS_BIG_ENDIAN FLOAT_WORDS_BIG_ENDIAN
#else
#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
#define DEC 1
#else
#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
#define IBM 1
#else
#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
#define IEEE
#else
unknown arithmetic type
#define UNK 1
#endif
#endif
#endif
#define REAL_WORDS_BIG_ENDIAN HOST_FLOAT_WORDS_BIG_ENDIAN
#endif
#if !defined(DEC) && !defined(IBM) && !defined(C4X)
#define INFINITY
#define NANS
#endif
#ifdef NANS
#ifndef INFINITY
#define INFINITY
#endif
#endif
#if HOST_BITS_PER_CHAR >= 16
#define EMUSHORT char
#define EMUSHORT_SIZE HOST_BITS_PER_CHAR
#define EMULONG_SIZE (2 * HOST_BITS_PER_CHAR)
#else
#if HOST_BITS_PER_SHORT >= 16
#define EMUSHORT short
#define EMUSHORT_SIZE HOST_BITS_PER_SHORT
#define EMULONG_SIZE (2 * HOST_BITS_PER_SHORT)
#else
#if HOST_BITS_PER_INT >= 16
#define EMUSHORT int
#define EMUSHORT_SIZE HOST_BITS_PER_INT
#define EMULONG_SIZE (2 * HOST_BITS_PER_INT)
#else
#if HOST_BITS_PER_LONG >= 16
#define EMUSHORT long
#define EMUSHORT_SIZE HOST_BITS_PER_LONG
#define EMULONG_SIZE (2 * HOST_BITS_PER_LONG)
#else
#define EMU_NON_COMPILE
#endif
#endif
#endif
#endif
#if HOST_BITS_PER_SHORT >= EMULONG_SIZE
#define EMULONG short
#else
#if HOST_BITS_PER_INT >= EMULONG_SIZE
#define EMULONG int
#else
#if HOST_BITS_PER_LONG >= EMULONG_SIZE
#define EMULONG long
#else
#if HOST_BITS_PER_LONGLONG >= EMULONG_SIZE
#define EMULONG long long int
#else
#define EMU_NON_COMPILE
#endif
#endif
#endif
#endif
#if EMUSHORT_SIZE != 16
#define EMU_NON_COMPILE
#endif
#ifndef EMU_NON_COMPILE
#if LONG_DOUBLE_TYPE_SIZE == 96
#define NE 6
#define MAXDECEXP 4932
#define MINDECEXP -4956
#define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)
#define PUT_REAL(e,r) \
do { \
if (2*NE < sizeof(*r)) \
bzero((char *)r, sizeof(*r)); \
bcopy ((char *) e, (char *) r, 2*NE); \
} while (0)
#else
#if LONG_DOUBLE_TYPE_SIZE == 128
#define NE 10
#define MAXDECEXP 4932
#define MINDECEXP -4977
#define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE)
#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 2*NE)
#else
#define NE 6
#define MAXDECEXP 4932
#define MINDECEXP -4956
#ifdef REAL_ARITHMETIC
#define GET_REAL(r,e) \
do { \
if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
e53toe ((unsigned EMUSHORT *) (r), (e)); \
else \
{ \
unsigned EMUSHORT w[4]; \
bcopy (((EMUSHORT *) r), &w[3], sizeof (EMUSHORT)); \
bcopy (((EMUSHORT *) r) + 1, &w[2], sizeof (EMUSHORT)); \
bcopy (((EMUSHORT *) r) + 2, &w[1], sizeof (EMUSHORT)); \
bcopy (((EMUSHORT *) r) + 3, &w[0], sizeof (EMUSHORT)); \
e53toe (w, (e)); \
} \
} while (0)
#define PUT_REAL(e,r) \
do { \
if (HOST_FLOAT_WORDS_BIG_ENDIAN == REAL_WORDS_BIG_ENDIAN) \
etoe53 ((e), (unsigned EMUSHORT *) (r)); \
else \
{ \
unsigned EMUSHORT w[4]; \
etoe53 ((e), w); \
bcopy (&w[3], ((EMUSHORT *) r), sizeof (EMUSHORT)); \
bcopy (&w[2], ((EMUSHORT *) r) + 1, sizeof (EMUSHORT)); \
bcopy (&w[1], ((EMUSHORT *) r) + 2, sizeof (EMUSHORT)); \
bcopy (&w[0], ((EMUSHORT *) r) + 3, sizeof (EMUSHORT)); \
} \
} while (0)
#else
#define GET_REAL(r,e) e53toe ((unsigned EMUSHORT *) (r), (e))
#define PUT_REAL(e,r) etoe53 ((e), (unsigned EMUSHORT *) (r))
#endif
#endif
#endif
#define NI (NE+3)
#define E 1
#define M 2
#define NBITS ((NI-4)*16)
#define NDEC (NBITS*8/27)
#define EXONE (0x3fff)
extern int extra_warnings;
extern unsigned EMUSHORT ezero[], ehalf[], eone[], etwo[];
extern unsigned EMUSHORT elog2[], esqrt2[];
static void endian PROTO((unsigned EMUSHORT *, long *,
enum machine_mode));
static void eclear PROTO((unsigned EMUSHORT *));
static void emov PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
#if 0
static void eabs PROTO((unsigned EMUSHORT *));
#endif
static void eneg PROTO((unsigned EMUSHORT *));
static int eisneg PROTO((unsigned EMUSHORT *));
static int eisinf PROTO((unsigned EMUSHORT *));
static int eisnan PROTO((unsigned EMUSHORT *));
static void einfin PROTO((unsigned EMUSHORT *));
static void enan PROTO((unsigned EMUSHORT *, int));
static void emovi PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void emovo PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void ecleaz PROTO((unsigned EMUSHORT *));
static void ecleazs PROTO((unsigned EMUSHORT *));
static void emovz PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void einan PROTO((unsigned EMUSHORT *));
static int eiisnan PROTO((unsigned EMUSHORT *));
static int eiisneg PROTO((unsigned EMUSHORT *));
#if 0
static void eiinfin PROTO((unsigned EMUSHORT *));
#endif
static int eiisinf PROTO((unsigned EMUSHORT *));
static int ecmpm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void eshdn1 PROTO((unsigned EMUSHORT *));
static void eshup1 PROTO((unsigned EMUSHORT *));
static void eshdn8 PROTO((unsigned EMUSHORT *));
static void eshup8 PROTO((unsigned EMUSHORT *));
static void eshup6 PROTO((unsigned EMUSHORT *));
static void eshdn6 PROTO((unsigned EMUSHORT *));
static void eaddm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void esubm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void m16m PROTO((unsigned int, unsigned short *,
unsigned short *));
static int edivm PROTO((unsigned short *, unsigned short *));
static int emulm PROTO((unsigned short *, unsigned short *));
static void emdnorm PROTO((unsigned EMUSHORT *, int, int, EMULONG, int));
static void esub PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
static void eadd PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
static void eadd1 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
static void ediv PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
static void emul PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
static void e53toe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void e64toe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void e113toe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void e24toe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void etoe113 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void toe113 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void etoe64 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void toe64 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void etoe53 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void toe53 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void etoe24 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void toe24 PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static int ecmp PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
#if 0
static void eround PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
#endif
static void ltoe PROTO((HOST_WIDE_INT *, unsigned EMUSHORT *));
static void ultoe PROTO((unsigned HOST_WIDE_INT *, unsigned EMUSHORT *));
static void eifrac PROTO((unsigned EMUSHORT *, HOST_WIDE_INT *,
unsigned EMUSHORT *));
static void euifrac PROTO((unsigned EMUSHORT *, unsigned HOST_WIDE_INT *,
unsigned EMUSHORT *));
static int eshift PROTO((unsigned EMUSHORT *, int));
static int enormlz PROTO((unsigned EMUSHORT *));
#if 0
static void e24toasc PROTO((unsigned EMUSHORT *, char *, int));
static void e53toasc PROTO((unsigned EMUSHORT *, char *, int));
static void e64toasc PROTO((unsigned EMUSHORT *, char *, int));
static void e113toasc PROTO((unsigned EMUSHORT *, char *, int));
#endif
static void etoasc PROTO((unsigned EMUSHORT *, char *, int));
static void asctoe24 PROTO((const char *, unsigned EMUSHORT *));
static void asctoe53 PROTO((const char *, unsigned EMUSHORT *));
static void asctoe64 PROTO((const char *, unsigned EMUSHORT *));
static void asctoe113 PROTO((const char *, unsigned EMUSHORT *));
static void asctoe PROTO((const char *, unsigned EMUSHORT *));
static void asctoeg PROTO((const char *, unsigned EMUSHORT *, int));
static void efloor PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
#if 0
static void efrexp PROTO((unsigned EMUSHORT *, int *,
unsigned EMUSHORT *));
#endif
static void eldexp PROTO((unsigned EMUSHORT *, int, unsigned EMUSHORT *));
#if 0
static void eremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
#endif
static void eiremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void mtherr PROTO((const char *, int));
#ifdef DEC
static void dectoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void etodec PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void todec PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
#endif
#ifdef IBM
static void ibmtoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
static void etoibm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
static void toibm PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
#endif
#ifdef C4X
static void c4xtoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
static void etoc4x PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
static void toc4x PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *,
enum machine_mode));
#endif
static void make_nan PROTO((unsigned EMUSHORT *, int, enum machine_mode));
#if 0
static void uditoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void ditoe PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void etoudi PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void etodi PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void esqrt PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *));
#endif
static void
endian (e, x, mode)
unsigned EMUSHORT e[];
long x[];
enum machine_mode mode;
{
unsigned long th, t;
if (REAL_WORDS_BIG_ENDIAN)
{
switch (mode)
{
case TFmode:
th = (unsigned long) e[6] & 0xffff;
t = (unsigned long) e[7] & 0xffff;
t |= th << 16;
x[3] = (long) t;
case XFmode:
th = (unsigned long) e[4] & 0xffff;
t = (unsigned long) e[5] & 0xffff;
t |= th << 16;
x[2] = (long) t;
case DFmode:
th = (unsigned long) e[2] & 0xffff;
t = (unsigned long) e[3] & 0xffff;
t |= th << 16;
x[1] = (long) t;
case SFmode:
case HFmode:
th = (unsigned long) e[0] & 0xffff;
t = (unsigned long) e[1] & 0xffff;
t |= th << 16;
x[0] = (long) t;
break;
default:
abort ();
}
}
else
{
switch (mode)
{
case TFmode:
th = (unsigned long) e[7] & 0xffff;
t = (unsigned long) e[6] & 0xffff;
t |= th << 16;
x[3] = (long) t;
case XFmode:
th = (unsigned long) e[5] & 0xffff;
t = (unsigned long) e[4] & 0xffff;
t |= th << 16;
x[2] = (long) t;
case DFmode:
th = (unsigned long) e[3] & 0xffff;
t = (unsigned long) e[2] & 0xffff;
t |= th << 16;
x[1] = (long) t;
case SFmode:
case HFmode:
th = (unsigned long) e[1] & 0xffff;
t = (unsigned long) e[0] & 0xffff;
t |= th << 16;
x[0] = (long) t;
break;
default:
abort ();
}
}
}
void
earith (value, icode, r1, r2)
REAL_VALUE_TYPE *value;
int icode;
REAL_VALUE_TYPE *r1;
REAL_VALUE_TYPE *r2;
{
unsigned EMUSHORT d1[NE], d2[NE], v[NE];
enum tree_code code;
GET_REAL (r1, d1);
GET_REAL (r2, d2);
#ifdef NANS
if (eisnan (d1))
{
PUT_REAL (d1, value);
return;
}
if (eisnan (d2))
{
PUT_REAL (d2, value);
return;
}
#endif
code = (enum tree_code) icode;
switch (code)
{
case PLUS_EXPR:
eadd (d2, d1, v);
break;
case MINUS_EXPR:
esub (d2, d1, v);
break;
case MULT_EXPR:
emul (d2, d1, v);
break;
case RDIV_EXPR:
#ifndef REAL_INFINITY
if (ecmp (d2, ezero) == 0)
{
#ifdef NANS
enan (v, eisneg (d1) ^ eisneg (d2));
break;
#else
abort ();
#endif
}
#endif
ediv (d2, d1, v);
break;
case MIN_EXPR:
if (ecmp (d1, d2) < 0)
emov (d1, v);
else
emov (d2, v);
break;
case MAX_EXPR:
if (ecmp (d1, d2) > 0)
emov (d1, v);
else
emov (d2, v);
break;
default:
emov (ezero, v);
break;
}
PUT_REAL (v, value);
}
REAL_VALUE_TYPE
etrunci (x)
REAL_VALUE_TYPE x;
{
unsigned EMUSHORT f[NE], g[NE];
REAL_VALUE_TYPE r;
HOST_WIDE_INT l;
GET_REAL (&x, g);
#ifdef NANS
if (eisnan (g))
return (x);
#endif
eifrac (g, &l, f);
ltoe (&l, g);
PUT_REAL (g, &r);
return (r);
}
REAL_VALUE_TYPE
etruncui (x)
REAL_VALUE_TYPE x;
{
unsigned EMUSHORT f[NE], g[NE];
REAL_VALUE_TYPE r;
unsigned HOST_WIDE_INT l;
GET_REAL (&x, g);
#ifdef NANS
if (eisnan (g))
return (x);
#endif
euifrac (g, &l, f);
ultoe (&l, g);
PUT_REAL (g, &r);
return (r);
}
REAL_VALUE_TYPE
ereal_atof (s, t)
const char *s;
enum machine_mode t;
{
unsigned EMUSHORT tem[NE], e[NE];
REAL_VALUE_TYPE r;
switch (t)
{
#ifdef C4X
case QFmode:
case HFmode:
asctoe53 (s, tem);
e53toe (tem, e);
break;
#else
case HFmode:
#endif
case SFmode:
asctoe24 (s, tem);
e24toe (tem, e);
break;
case DFmode:
asctoe53 (s, tem);
e53toe (tem, e);
break;
case XFmode:
asctoe64 (s, tem);
e64toe (tem, e);
break;
case TFmode:
asctoe113 (s, tem);
e113toe (tem, e);
break;
default:
asctoe (s, e);
}
PUT_REAL (e, &r);
return (r);
}
REAL_VALUE_TYPE
ereal_negate (x)
REAL_VALUE_TYPE x;
{
unsigned EMUSHORT e[NE];
REAL_VALUE_TYPE r;
GET_REAL (&x, e);
eneg (e);
PUT_REAL (e, &r);
return (r);
}
HOST_WIDE_INT
efixi (x)
REAL_VALUE_TYPE x;
{
unsigned EMUSHORT f[NE], g[NE];
HOST_WIDE_INT l;
GET_REAL (&x, f);
#ifdef NANS
if (eisnan (f))
{
warning ("conversion from NaN to int");
return (-1);
}
#endif
eifrac (f, &l, g);
return l;
}
unsigned HOST_WIDE_INT
efixui (x)
REAL_VALUE_TYPE x;
{
unsigned EMUSHORT f[NE], g[NE];
unsigned HOST_WIDE_INT l;
GET_REAL (&x, f);
#ifdef NANS
if (eisnan (f))
{
warning ("conversion from NaN to unsigned int");
return (-1);
}
#endif
euifrac (f, &l, g);
return l;
}
void
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)
{
sign = 1;
high = ~high;
if (low)
low = -low;
else
high += 1;
}
eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
ultoe ((unsigned HOST_WIDE_INT *) &high, dg);
emul (dg, df, dg);
ultoe ((unsigned HOST_WIDE_INT *) &low, df);
eadd (df, dg, dg);
if (sign)
eneg (dg);
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);
}
void
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);
ultoe (&high, dg);
emul (dg, df, dg);
ultoe (&low, df);
eadd (df, dg, dg);
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);
}
void
ereal_to_int (low, high, rr)
HOST_WIDE_INT *low, *high;
REAL_VALUE_TYPE rr;
{
unsigned EMUSHORT d[NE], df[NE], dg[NE], dh[NE];
int s;
GET_REAL (&rr, d);
#ifdef NANS
if (eisnan (d))
{
warning ("conversion from NaN to int");
*low = -1;
*high = -1;
return;
}
#endif
s = 0;
if (eisneg (d))
{
eneg (d);
s = 1;
}
eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
ediv (df, d, dg);
euifrac (dg, (unsigned HOST_WIDE_INT *) high, dh);
emul (df, dh, dg);
euifrac (dg, (unsigned HOST_WIDE_INT *)low, dh);
if (s)
{
*high = ~(*high);
if (*low)
*low = -(*low);
else
*high += 1;
}
}
REAL_VALUE_TYPE
ereal_ldexp (x, n)
REAL_VALUE_TYPE x;
int n;
{
unsigned EMUSHORT e[NE], y[NE];
REAL_VALUE_TYPE r;
GET_REAL (&x, e);
#ifdef NANS
if (eisnan (e))
return (x);
#endif
eldexp (e, n, y);
PUT_REAL (y, &r);
return (r);
}
#ifdef REAL_ARITHMETIC
int
target_isinf (x)
REAL_VALUE_TYPE x;
{
unsigned EMUSHORT e[NE];
#ifdef INFINITY
GET_REAL (&x, e);
return (eisinf (e));
#else
return 0;
#endif
}
int
target_isnan (x)
REAL_VALUE_TYPE x;
{
unsigned EMUSHORT e[NE];
#ifdef NANS
GET_REAL (&x, e);
return (eisnan (e));
#else
return (0);
#endif
}
int
target_negative (x)
REAL_VALUE_TYPE x;
{
return ereal_isneg (x);
}
REAL_VALUE_TYPE
real_value_truncate (mode, arg)
enum machine_mode mode;
REAL_VALUE_TYPE arg;
{
unsigned EMUSHORT e[NE], t[NE];
REAL_VALUE_TYPE r;
GET_REAL (&arg, e);
#ifdef NANS
if (eisnan (e))
return (arg);
#endif
eclear (t);
switch (mode)
{
case TFmode:
etoe113 (e, t);
e113toe (t, t);
break;
case XFmode:
etoe64 (e, t);
e64toe (t, t);
break;
case DFmode:
etoe53 (e, t);
e53toe (t, t);
break;
case SFmode:
#ifndef C4X
case HFmode:
#endif
etoe24 (e, t);
e24toe (t, t);
break;
#ifdef C4X
case HFmode:
case QFmode:
etoe53 (e, t);
e53toe (t, t);
break;
#endif
case SImode:
r = etrunci (arg);
return (r);
default:
return (arg);
}
PUT_REAL (t, &r);
return (r);
}
int
exact_real_inverse (mode, r)
enum machine_mode mode;
REAL_VALUE_TYPE *r;
{
unsigned EMUSHORT e[NE], einv[NE];
REAL_VALUE_TYPE rinv;
int i;
GET_REAL (r, e);
if (eisinf (e) || eisnan (e) || (ecmp (e, ezero) == 0))
return 0;
if (e[NE - 2] != 0x8000)
return 0;
for (i = 0; i < NE - 2; i++)
{
if (e[i] != 0)
return 0;
}
ediv (e, eone, einv);
PUT_REAL (einv, &rinv);
rinv = real_value_truncate (mode, rinv);
#ifdef CHECK_FLOAT_VALUE
i = 0;
if (CHECK_FLOAT_VALUE (mode, rinv, i))
return 0;
#endif
GET_REAL (&rinv, einv);
if (einv[NE - 2] != 0x8000)
return 0;
for (i = 0; i < NE - 2; i++)
{
if (einv[i] != 0)
return 0;
}
if (eisinf (einv) || eisnan (einv) || (ecmp (einv, ezero) == 0))
return 0;
PUT_REAL (einv, r);
return 1;
}
#endif
void
debug_real (r)
REAL_VALUE_TYPE r;
{
char dstr[30];
REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr);
fprintf (stderr, "%s", dstr);
}
void
etartdouble (r, l)
REAL_VALUE_TYPE r;
long l[];
{
unsigned EMUSHORT e[NE];
GET_REAL (&r, e);
etoe113 (e, e);
endian (e, l, TFmode);
}
void
etarldouble (r, l)
REAL_VALUE_TYPE r;
long l[];
{
unsigned EMUSHORT e[NE];
GET_REAL (&r, e);
etoe64 (e, e);
endian (e, l, XFmode);
}
void
etardouble (r, l)
REAL_VALUE_TYPE r;
long l[];
{
unsigned EMUSHORT e[NE];
GET_REAL (&r, e);
etoe53 (e, e);
endian (e, l, DFmode);
}
long
etarsingle (r)
REAL_VALUE_TYPE r;
{
unsigned EMUSHORT e[NE];
long l;
GET_REAL (&r, e);
etoe24 (e, e);
endian (e, &l, SFmode);
return ((long) l);
}
void
ereal_to_decimal (x, s)
REAL_VALUE_TYPE x;
char *s;
{
unsigned EMUSHORT e[NE];
GET_REAL (&x, e);
etoasc (e, s, 20);
}
int
ereal_cmp (x, y)
REAL_VALUE_TYPE x, y;
{
unsigned EMUSHORT ex[NE], ey[NE];
GET_REAL (&x, ex);
GET_REAL (&y, ey);
return (ecmp (ex, ey));
}
int
ereal_isneg (x)
REAL_VALUE_TYPE x;
{
unsigned EMUSHORT ex[NE];
GET_REAL (&x, ex);
return (eisneg (ex));
}
#define DOMAIN 1
#define SING 2
#define OVERFLOW 3
#define UNDERFLOW 4
#define TLOSS 5
#define PLOSS 6
#define INVALID 7
#if LONG_DOUBLE_TYPE_SIZE == 128
unsigned EMUSHORT ezero[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,};
extern unsigned EMUSHORT ezero[];
unsigned EMUSHORT ehalf[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3ffe,};
extern unsigned EMUSHORT ehalf[];
unsigned EMUSHORT eone[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,};
extern unsigned EMUSHORT eone[];
unsigned EMUSHORT etwo[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4000,};
extern unsigned EMUSHORT etwo[];
unsigned EMUSHORT e32[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4004,};
extern unsigned EMUSHORT e32[];
unsigned EMUSHORT elog2[NE] =
{0x40f3, 0xf6af, 0x03f2, 0xb398,
0xc9e3, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
extern unsigned EMUSHORT elog2[];
unsigned EMUSHORT esqrt2[NE] =
{0x1d6f, 0xbe9f, 0x754a, 0x89b3,
0x597d, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
extern unsigned EMUSHORT esqrt2[];
unsigned EMUSHORT epi[NE] =
{0x2902, 0x1cd1, 0x80dc, 0x628b,
0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
extern unsigned EMUSHORT epi[];
#else
unsigned EMUSHORT ezero[NE] =
{0, 0000000, 0000000, 0000000, 0000000, 0000000,};
unsigned EMUSHORT ehalf[NE] =
{0, 0000000, 0000000, 0000000, 0100000, 0x3ffe,};
unsigned EMUSHORT eone[NE] =
{0, 0000000, 0000000, 0000000, 0100000, 0x3fff,};
unsigned EMUSHORT etwo[NE] =
{0, 0000000, 0000000, 0000000, 0100000, 0040000,};
unsigned EMUSHORT e32[NE] =
{0, 0000000, 0000000, 0000000, 0100000, 0040004,};
unsigned EMUSHORT elog2[NE] =
{0xc9e4, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,};
unsigned EMUSHORT esqrt2[NE] =
{0x597e, 0x6484, 0174736, 0171463, 0132404, 0x3fff,};
unsigned EMUSHORT epi[NE] =
{0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,};
#endif
int rndprc = NBITS;
extern int rndprc;
static void
eclear (x)
register unsigned EMUSHORT *x;
{
register int i;
for (i = 0; i < NE; i++)
*x++ = 0;
}
static void
emov (a, b)
register unsigned EMUSHORT *a, *b;
{
register int i;
for (i = 0; i < NE; i++)
*b++ = *a++;
}
#if 0
static void
eabs (x)
unsigned EMUSHORT x[];
{
x[NE - 1] &= 0x7fff;
}
#endif
static void
eneg (x)
unsigned EMUSHORT x[];
{
x[NE - 1] ^= 0x8000;
}
static int
eisneg (x)
unsigned EMUSHORT x[];
{
if (x[NE - 1] & 0x8000)
return (1);
else
return (0);
}
static int
eisinf (x)
unsigned EMUSHORT x[];
{
#ifdef NANS
if (eisnan (x))
return (0);
#endif
if ((x[NE - 1] & 0x7fff) == 0x7fff)
return (1);
else
return (0);
}
static int
eisnan (x)
unsigned EMUSHORT x[];
{
#ifdef NANS
int i;
if ((x[NE - 1] & 0x7fff) != 0x7fff)
return (0);
for (i = 0; i < NE - 1; i++)
{
if (*x++ != 0)
return (1);
}
#endif
return (0);
}
static void
einfin (x)
register unsigned EMUSHORT *x;
{
register int i;
#ifdef INFINITY
for (i = 0; i < NE - 1; i++)
*x++ = 0;
*x |= 32767;
#else
for (i = 0; i < NE - 1; i++)
*x++ = 0xffff;
*x |= 32766;
if (rndprc < NBITS)
{
if (rndprc == 113)
{
*(x - 9) = 0;
*(x - 8) = 0;
}
if (rndprc == 64)
{
*(x - 5) = 0;
}
if (rndprc == 53)
{
*(x - 4) = 0xf800;
}
else
{
*(x - 4) = 0;
*(x - 3) = 0;
*(x - 2) = 0xff00;
}
}
#endif
}
static void
enan (x, sign)
register unsigned EMUSHORT *x;
int sign;
{
register int i;
for (i = 0; i < NE - 2; i++)
*x++ = 0;
*x++ = 0xc000;
*x = (sign << 15) | 0x7fff;
}
static void
emovi (a, b)
unsigned EMUSHORT *a, *b;
{
register unsigned EMUSHORT *p, *q;
int i;
q = b;
p = a + (NE - 1);
if (*p & 0x8000)
*q++ = 0xffff;
else
*q++ = 0;
*q = *p--;
*q++ &= 0x7fff;
#ifdef INFINITY
if ((*(q - 1) & 0x7fff) == 0x7fff)
{
#ifdef NANS
if (eisnan (a))
{
*q++ = 0;
for (i = 3; i < NI; i++)
*q++ = *p--;
return;
}
#endif
for (i = 2; i < NI; i++)
*q++ = 0;
return;
}
#endif
*q++ = 0;
for (i = 0; i < NE - 1; i++)
*q++ = *p--;
*q = 0;
}
static void
emovo (a, b)
unsigned EMUSHORT *a, *b;
{
register unsigned EMUSHORT *p, *q;
unsigned EMUSHORT i;
int j;
p = a;
q = b + (NE - 1);
i = *p++;
if (i)
*q-- = *p++ | 0x8000;
else
*q-- = *p++;
#ifdef INFINITY
if (*(p - 1) == 0x7fff)
{
#ifdef NANS
if (eiisnan (a))
{
enan (b, eiisneg (a));
return;
}
#endif
einfin (b);
return;
}
#endif
++p;
for (j = 0; j < NE - 1; j++)
*q-- = *p++;
}
static void
ecleaz (xi)
register unsigned EMUSHORT *xi;
{
register int i;
for (i = 0; i < NI; i++)
*xi++ = 0;
}
static void
ecleazs (xi)
register unsigned EMUSHORT *xi;
{
register int i;
++xi;
for (i = 0; i < NI - 1; i++)
*xi++ = 0;
}
static void
emovz (a, b)
register unsigned EMUSHORT *a, *b;
{
register int i;
for (i = 0; i < NI - 1; i++)
*b++ = *a++;
*b = 0;
}
static void
einan (x)
unsigned EMUSHORT x[];
{
ecleaz (x);
x[E] = 0x7fff;
x[M + 1] = 0xc000;
}
static int
eiisnan (x)
unsigned EMUSHORT x[];
{
int i;
if ((x[E] & 0x7fff) == 0x7fff)
{
for (i = M + 1; i < NI; i++)
{
if (x[i] != 0)
return (1);
}
}
return (0);
}
static int
eiisneg (x)
unsigned EMUSHORT x[];
{
return x[0] != 0;
}
#if 0
static void
eiinfin (x)
unsigned EMUSHORT x[];
{
ecleaz (x);
x[E] = 0x7fff;
}
#endif
static int
eiisinf (x)
unsigned EMUSHORT x[];
{
#ifdef NANS
if (eiisnan (x))
return (0);
#endif
if ((x[E] & 0x7fff) == 0x7fff)
return (1);
return (0);
}
static int
ecmpm (a, b)
register unsigned EMUSHORT *a, *b;
{
int i;
a += M;
b += M;
for (i = M; i < NI; i++)
{
if (*a++ != *b++)
goto difrnt;
}
return (0);
difrnt:
if (*(--a) > *(--b))
return (1);
else
return (-1);
}
static void
eshdn1 (x)
register unsigned EMUSHORT *x;
{
register unsigned EMUSHORT bits;
int i;
x += M;
bits = 0;
for (i = M; i < NI; i++)
{
if (*x & 1)
bits |= 1;
*x >>= 1;
if (bits & 2)
*x |= 0x8000;
bits <<= 1;
++x;
}
}
static void
eshup1 (x)
register unsigned EMUSHORT *x;
{
register unsigned EMUSHORT bits;
int i;
x += NI - 1;
bits = 0;
for (i = M; i < NI; i++)
{
if (*x & 0x8000)
bits |= 1;
*x <<= 1;
if (bits & 2)
*x |= 1;
bits <<= 1;
--x;
}
}
static void
eshdn8 (x)
register unsigned EMUSHORT *x;
{
register unsigned EMUSHORT newbyt, oldbyt;
int i;
x += M;
oldbyt = 0;
for (i = M; i < NI; i++)
{
newbyt = *x << 8;
*x >>= 8;
*x |= oldbyt;
oldbyt = newbyt;
++x;
}
}
static void
eshup8 (x)
register unsigned EMUSHORT *x;
{
int i;
register unsigned EMUSHORT newbyt, oldbyt;
x += NI - 1;
oldbyt = 0;
for (i = M; i < NI; i++)
{
newbyt = *x >> 8;
*x <<= 8;
*x |= oldbyt;
oldbyt = newbyt;
--x;
}
}
static void
eshup6 (x)
register unsigned EMUSHORT *x;
{
int i;
register unsigned EMUSHORT *p;
p = x + M;
x += M + 1;
for (i = M; i < NI - 1; i++)
*p++ = *x++;
*p = 0;
}
static void
eshdn6 (x)
register unsigned EMUSHORT *x;
{
int i;
register unsigned EMUSHORT *p;
x += NI - 1;
p = x + 1;
for (i = M; i < NI - 1; i++)
*(--p) = *(--x);
*(--p) = 0;
}
static void
eaddm (x, y)
unsigned EMUSHORT *x, *y;
{
register unsigned EMULONG a;
int i;
unsigned int carry;
x += NI - 1;
y += NI - 1;
carry = 0;
for (i = M; i < NI; i++)
{
a = (unsigned EMULONG) (*x) + (unsigned EMULONG) (*y) + carry;
if (a & 0x10000)
carry = 1;
else
carry = 0;
*y = (unsigned EMUSHORT) a;
--x;
--y;
}
}
static void
esubm (x, y)
unsigned EMUSHORT *x, *y;
{
unsigned EMULONG a;
int i;
unsigned int carry;
x += NI - 1;
y += NI - 1;
carry = 0;
for (i = M; i < NI; i++)
{
a = (unsigned EMULONG) (*y) - (unsigned EMULONG) (*x) - carry;
if (a & 0x10000)
carry = 1;
else
carry = 0;
*y = (unsigned EMUSHORT) a;
--x;
--y;
}
}
static unsigned EMUSHORT equot[NI];
#if 0
int
edivm (den, num)
unsigned EMUSHORT den[], num[];
{
int i;
register unsigned EMUSHORT *p, *q;
unsigned EMUSHORT j;
p = &equot[0];
*p++ = num[0];
*p++ = num[1];
for (i = M; i < NI; i++)
{
*p++ = 0;
}
p = &den[M + 2];
if (*p++ == 0)
{
for (i = M + 3; i < NI; i++)
{
if (*p++ != 0)
goto fulldiv;
}
if ((den[M + 1] & 1) != 0)
goto fulldiv;
eshdn1 (num);
eshdn1 (den);
p = &den[M + 1];
q = &num[M + 1];
for (i = 0; i < NBITS + 2; i++)
{
if (*p <= *q)
{
*q -= *p;
j = 1;
}
else
{
j = 0;
}
eshup1 (equot);
equot[NI - 2] |= j;
eshup1 (num);
}
goto divdon;
}
fulldiv:
p = &equot[NI - 2];
for (i = 0; i < NBITS + 2; i++)
{
if (ecmpm (den, num) <= 0)
{
esubm (den, num);
j = 1;
}
else
j = 0;
eshup1 (equot);
*p |= j;
eshup1 (num);
}
divdon:
eshdn1 (equot);
eshdn1 (equot);
p = &num[M];
j = 0;
for (i = M; i < NI; i++)
{
j |= *p++;
}
if (j)
j = 1;
for (i = 0; i < NI; i++)
num[i] = equot[i];
return ((int) j);
}
int
emulm (a, b)
unsigned EMUSHORT a[], b[];
{
unsigned EMUSHORT *p, *q;
int i, j, k;
equot[0] = b[0];
equot[1] = b[1];
for (i = M; i < NI; i++)
equot[i] = 0;
p = &a[NI - 2];
k = NBITS;
while (*p == 0)
{
eshdn6 (a);
k -= 16;
}
if ((*p & 0xff) == 0)
{
eshdn8 (a);
k -= 8;
}
q = &equot[NI - 1];
j = 0;
for (i = 0; i < k; i++)
{
if (*p & 1)
eaddm (b, equot);
if (*q & 1)
j |= 1;
eshdn1 (a);
eshdn1 (equot);
}
for (i = 0; i < NI; i++)
b[i] = equot[i];
return (j);
}
#else
static void
m16m (a, b, c)
unsigned int a;
unsigned EMUSHORT b[], c[];
{
register unsigned EMUSHORT *pp;
register unsigned EMULONG carry;
unsigned EMUSHORT *ps;
unsigned EMUSHORT p[NI];
unsigned EMULONG aa, m;
int i;
aa = a;
pp = &p[NI-2];
*pp++ = 0;
*pp = 0;
ps = &b[NI-1];
for (i=M+1; i<NI; i++)
{
if (*ps == 0)
{
--ps;
--pp;
*(pp-1) = 0;
}
else
{
m = (unsigned EMULONG) aa * *ps--;
carry = (m & 0xffff) + *pp;
*pp-- = (unsigned EMUSHORT)carry;
carry = (carry >> 16) + (m >> 16) + *pp;
*pp = (unsigned EMUSHORT)carry;
*(pp-1) = carry >> 16;
}
}
for (i=M; i<NI; i++)
c[i] = p[i];
}
static int
edivm (den, num)
unsigned EMUSHORT den[], num[];
{
int i;
register unsigned EMUSHORT *p;
unsigned EMULONG tnum;
unsigned EMUSHORT j, tdenm, tquot;
unsigned EMUSHORT tprod[NI+1];
p = &equot[0];
*p++ = num[0];
*p++ = num[1];
for (i=M; i<NI; i++)
{
*p++ = 0;
}
eshdn1 (num);
tdenm = den[M+1];
for (i=M; i<NI; i++)
{
tnum = (((unsigned EMULONG) num[M]) << 16) + num[M+1];
if ((tdenm * (unsigned long)0xffff) < tnum)
tquot = 0xffff;
else
tquot = tnum / tdenm;
m16m ((unsigned int)tquot, den, tprod);
if (ecmpm (tprod, num) > 0)
{
tquot -= 1;
esubm (den, tprod);
if (ecmpm (tprod, num) > 0)
{
tquot -= 1;
esubm (den, tprod);
}
}
esubm (tprod, num);
equot[i] = tquot;
eshup6(num);
}
p = &num[M];
j = 0;
for (i=M; i<NI; i++)
{
j |= *p++;
}
if (j)
j = 1;
for (i=0; i<NI; i++)
num[i] = equot[i];
return ((int)j);
}
static int
emulm (a, b)
unsigned EMUSHORT a[], b[];
{
unsigned EMUSHORT *p, *q;
unsigned EMUSHORT pprod[NI];
unsigned EMUSHORT j;
int i;
equot[0] = b[0];
equot[1] = b[1];
for (i=M; i<NI; i++)
equot[i] = 0;
j = 0;
p = &a[NI-1];
q = &equot[NI-1];
for (i=M+1; i<NI; i++)
{
if (*p == 0)
{
--p;
}
else
{
m16m ((unsigned int) *p--, b, pprod);
eaddm(pprod, equot);
}
j |= *q;
eshdn6(equot);
}
for (i=0; i<NI; i++)
b[i] = equot[i];
return ((int)j);
}
#endif
static int rlast = -1;
static int rw = 0;
static unsigned EMUSHORT rmsk = 0;
static unsigned EMUSHORT rmbit = 0;
static unsigned EMUSHORT rebit = 0;
static int re = 0;
static unsigned EMUSHORT rbit[NI];
static void
emdnorm (s, lost, subflg, exp, rcntrl)
unsigned EMUSHORT s[];
int lost;
int subflg;
EMULONG exp;
int rcntrl;
{
int i, j;
unsigned EMUSHORT r;
j = enormlz (s);
#ifndef INFINITY
if (j > NBITS)
{
ecleazs (s);
return;
}
#endif
exp -= j;
#ifndef INFINITY
if (exp >= 32767L)
goto overf;
#else
if ((j > NBITS) && (exp < 32767))
{
ecleazs (s);
return;
}
#endif
if (exp < 0L)
{
if (exp > (EMULONG) (-NBITS - 1))
{
j = (int) exp;
i = eshift (s, j);
if (i)
lost = 1;
}
else
{
ecleazs (s);
return;
}
}
if (rcntrl == 0)
goto mdfin;
if (rndprc != rlast)
{
ecleaz (rbit);
switch (rndprc)
{
default:
case NBITS:
rw = NI - 1;
rmsk = 0xffff;
rmbit = 0x8000;
re = rw - 1;
rebit = 1;
break;
case 113:
rw = 10;
rmsk = 0x7fff;
rmbit = 0x4000;
rebit = 0x8000;
re = rw;
break;
case 64:
rw = 7;
rmsk = 0xffff;
rmbit = 0x8000;
re = rw - 1;
rebit = 1;
break;
case 56:
rw = 6;
rmsk = 0xff;
rmbit = 0x80;
rebit = 0x100;
re = rw;
break;
case 53:
rw = 6;
rmsk = 0x7ff;
rmbit = 0x0400;
rebit = 0x800;
re = rw;
break;
case 32:
rw = 5;
rmsk = 0xffff;
rmbit = 0x8000;
rebit = 1;
re = rw - 1;
break;
case 24:
rw = 4;
rmsk = 0xff;
rmbit = 0x80;
rebit = 0x100;
re = rw;
break;
}
rbit[re] = rebit;
rlast = rndprc;
}
if ((exp <= 0) && (rndprc != NBITS)
&& ((rndprc != 64) || ((rndprc == 64) && ! REAL_WORDS_BIG_ENDIAN)))
{
lost |= s[NI - 1] & 1;
eshdn1 (s);
}
r = s[rw] & rmsk;
if (rndprc < NBITS)
{
i = rw + 1;
while (i < NI)
{
if (s[i])
r |= 1;
s[i] = 0;
++i;
}
}
s[rw] &= ~rmsk;
if ((r & rmbit) != 0)
{
#ifndef C4X
if (r == rmbit)
{
if (lost == 0)
{
if ((s[re] & rebit) == 0)
goto mddone;
}
else
{
if (subflg != 0)
goto mddone;
}
}
#endif
eaddm (rbit, s);
}
mddone:
if ((exp <= 0) && (rndprc != NBITS)
&& ((rndprc != 64) || ((rndprc == 64) && ! REAL_WORDS_BIG_ENDIAN)))
{
eshup1 (s);
}
if (s[2] != 0)
{
eshdn1 (s);
exp += 1;
}
mdfin:
s[NI - 1] = 0;
if (exp >= 32767L)
{
#ifndef INFINITY
overf:
#endif
#ifdef INFINITY
s[1] = 32767;
for (i = 2; i < NI - 1; i++)
s[i] = 0;
if (extra_warnings)
warning ("floating point overflow");
#else
s[1] = 32766;
s[2] = 0;
for (i = M + 1; i < NI - 1; i++)
s[i] = 0xffff;
s[NI - 1] = 0;
if ((rndprc < 64) || (rndprc == 113))
{
s[rw] &= ~rmsk;
if (rndprc == 24)
{
s[5] = 0;
s[6] = 0;
}
}
#endif
return;
}
if (exp < 0)
s[1] = 0;
else
s[1] = (unsigned EMUSHORT) exp;
}
static int subflg = 0;
static void
esub (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
#ifdef NANS
if (eisnan (a))
{
emov (a, c);
return;
}
if (eisnan (b))
{
emov (b, c);
return;
}
if (eisinf (a) && eisinf (b)
&& ((eisneg (a) ^ eisneg (b)) == 0))
{
mtherr ("esub", INVALID);
enan (c, 0);
return;
}
#endif
subflg = 1;
eadd1 (a, b, c);
}
static void
eadd (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
#ifdef NANS
if (eisnan (a))
{
emov (a, c);
return;
}
if (eisnan (b))
{
emov (b, c);
return;
}
if (eisinf (a) && eisinf (b)
&& ((eisneg (a) ^ eisneg (b)) != 0))
{
mtherr ("esub", INVALID);
enan (c, 0);
return;
}
#endif
subflg = 0;
eadd1 (a, b, c);
}
static void
eadd1 (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
unsigned EMUSHORT ai[NI], bi[NI], ci[NI];
int i, lost, j, k;
EMULONG lt, lta, ltb;
#ifdef INFINITY
if (eisinf (a))
{
emov (a, c);
if (subflg)
eneg (c);
return;
}
if (eisinf (b))
{
emov (b, c);
return;
}
#endif
emovi (a, ai);
emovi (b, bi);
if (subflg)
ai[0] = ~ai[0];
lta = ai[E];
ltb = bi[E];
lt = lta - ltb;
if (lt > 0L)
{
emovz (bi, ci);
emovz (ai, bi);
emovz (ci, ai);
ltb = bi[E];
lt = -lt;
}
lost = 0;
if (lt != 0L)
{
if (lt < (EMULONG) (-NBITS - 1))
goto done;
k = (int) lt;
lost = eshift (ai, k);
}
else
{
i = ecmpm (ai, bi);
if (i == 0)
{
if (ai[0] != bi[0])
{
eclear (c);
return;
}
if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0))
{
eshup1 (bi);
goto done;
}
for (j = 1; j < NI - 1; j++)
{
if (bi[j] != 0)
{
ltb += 1;
if (ltb >= 0x7fff)
{
eclear (c);
if (ai[0] != 0)
eneg (c);
einfin (c);
return;
}
break;
}
}
bi[E] = (unsigned EMUSHORT) ltb;
goto done;
}
if (i > 0)
{
emovz (bi, ci);
emovz (ai, bi);
emovz (ci, ai);
}
}
if (ai[0] == bi[0])
{
eaddm (ai, bi);
subflg = 0;
}
else
{
esubm (ai, bi);
subflg = 1;
}
emdnorm (bi, lost, subflg, ltb, 64);
done:
emovo (bi, c);
}
static void
ediv (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
unsigned EMUSHORT ai[NI], bi[NI];
int i, sign;
EMULONG lt, lta, ltb;
sign = eisneg(a) ^ eisneg(b);
#ifdef NANS
if (eisnan (a))
{
emov (a, c);
return;
}
if (eisnan (b))
{
emov (b, c);
return;
}
if (((ecmp (a, ezero) == 0) && (ecmp (b, ezero) == 0))
|| (eisinf (a) && eisinf (b)))
{
mtherr ("ediv", INVALID);
enan (c, sign);
return;
}
#endif
#ifdef INFINITY
if (eisinf (b))
{
einfin (c);
goto divsign;
}
if (eisinf (a))
{
eclear (c);
goto divsign;
}
#endif
emovi (a, ai);
emovi (b, bi);
lta = ai[E];
ltb = bi[E];
if (bi[E] == 0)
{
for (i = 1; i < NI - 1; i++)
{
if (bi[i] != 0)
{
ltb -= enormlz (bi);
goto dnzro1;
}
}
eclear (c);
goto divsign;
}
dnzro1:
if (ai[E] == 0)
{
for (i = 1; i < NI - 1; i++)
{
if (ai[i] != 0)
{
lta -= enormlz (ai);
goto dnzro2;
}
}
einfin (c);
mtherr ("ediv", SING);
goto divsign;
}
dnzro2:
i = edivm (ai, bi);
lt = ltb - lta + EXONE;
emdnorm (bi, i, 0, lt, 64);
emovo (bi, c);
divsign:
if (sign
#ifndef IEEE
&& (ecmp (c, ezero) != 0)
#endif
)
*(c+(NE-1)) |= 0x8000;
else
*(c+(NE-1)) &= ~0x8000;
}
static void
emul (a, b, c)
unsigned EMUSHORT *a, *b, *c;
{
unsigned EMUSHORT ai[NI], bi[NI];
int i, j, sign;
EMULONG lt, lta, ltb;
sign = eisneg(a) ^ eisneg(b);
#ifdef NANS
if (eisnan (a))
{
emov (a, c);
return;
}
if (eisnan (b))
{
emov (b, c);
return;
}
if ((eisinf (a) && (ecmp (b, ezero) == 0))
|| (eisinf (b) && (ecmp (a, ezero) == 0)))
{
mtherr ("emul", INVALID);
enan (c, sign);
return;
}
#endif
#ifdef INFINITY
if (eisinf (a) || eisinf (b))
{
einfin (c);
goto mulsign;
}
#endif
emovi (a, ai);
emovi (b, bi);
lta = ai[E];
ltb = bi[E];
if (ai[E] == 0)
{
for (i = 1; i < NI - 1; i++)
{
if (ai[i] != 0)
{
lta -= enormlz (ai);
goto mnzer1;
}
}
eclear (c);
goto mulsign;
}
mnzer1:
if (bi[E] == 0)
{
for (i = 1; i < NI - 1; i++)
{
if (bi[i] != 0)
{
ltb -= enormlz (bi);
goto mnzer2;
}
}
eclear (c);
goto mulsign;
}
mnzer2:
j = emulm (ai, bi);
lt = lta + ltb - (EXONE - 1);
emdnorm (bi, j, 0, lt, 64);
emovo (bi, c);
mulsign:
if (sign
#ifndef IEEE
&& (ecmp (c, ezero) != 0)
#endif
)
*(c+(NE-1)) |= 0x8000;
else
*(c+(NE-1)) &= ~0x8000;
}
static void
e53toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
#ifdef DEC
dectoe (pe, y);
#else
#ifdef IBM
ibmtoe (pe, y, DFmode);
#else
#ifdef C4X
c4xtoe (pe, y, HFmode);
#else
register unsigned EMUSHORT r;
register unsigned EMUSHORT *e, *p;
unsigned EMUSHORT yy[NI];
int denorm, k;
e = pe;
denorm = 0;
ecleaz (yy);
if (! REAL_WORDS_BIG_ENDIAN)
e += 3;
r = *e;
yy[0] = 0;
if (r & 0x8000)
yy[0] = 0xffff;
yy[M] = (r & 0x0f) | 0x10;
r &= ~0x800f;
#ifdef INFINITY
if (r == 0x7ff0)
{
#ifdef NANS
if (! REAL_WORDS_BIG_ENDIAN)
{
if (((pe[3] & 0xf) != 0) || (pe[2] != 0)
|| (pe[1] != 0) || (pe[0] != 0))
{
enan (y, yy[0] != 0);
return;
}
}
else
{
if (((pe[0] & 0xf) != 0) || (pe[1] != 0)
|| (pe[2] != 0) || (pe[3] != 0))
{
enan (y, yy[0] != 0);
return;
}
}
#endif
eclear (y);
einfin (y);
if (yy[0])
eneg (y);
return;
}
#endif
r >>= 4;
if (r == 0)
{
denorm = 1;
yy[M] &= ~0x10;
}
r += EXONE - 01777;
yy[E] = r;
p = &yy[M + 1];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
{
*p++ = *(--e);
*p++ = *(--e);
*p++ = *(--e);
}
else
{
++e;
*p++ = *e++;
*p++ = *e++;
*p++ = *e++;
}
#endif
eshift (yy, -5);
if (denorm)
{
if ((k = enormlz (yy)) > NBITS)
ecleazs (yy);
else
yy[E] -= (unsigned EMUSHORT) (k - 1);
}
emovo (yy, y);
#endif
#endif
#endif
}
static void
e64toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
unsigned EMUSHORT yy[NI];
unsigned EMUSHORT *e, *p, *q;
int i;
e = pe;
p = yy;
for (i = 0; i < NE - 5; i++)
*p++ = 0;
#ifdef DEC
for (i = 0; i < 5; i++)
*p++ = *e++;
#endif
#ifdef IBM
p = &yy[0] + (NE - 1);
*p-- = *e++;
++e;
for (i = 0; i < 5; i++)
*p-- = *e++;
#endif
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
{
for (i = 0; i < 5; i++)
*p++ = *e++;
if((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0)
{
unsigned EMUSHORT temp[NI];
emovi(yy, temp);
eshup1(temp);
emovo(temp,y);
return;
}
}
else
{
p = &yy[0] + (NE - 1);
#ifdef ARM_EXTENDED_IEEE_FORMAT
*p-- = (e[0] & 0x8000) | (e[1] & 0x7ffff);
e += 2;
#else
*p-- = *e++;
++e;
#endif
for (i = 0; i < 4; i++)
*p-- = *e++;
}
#endif
#ifdef INFINITY
p = &yy[NE - 1];
if ((*p & 0x7fff) == 0x7fff)
{
#ifdef NANS
if (! REAL_WORDS_BIG_ENDIAN)
{
for (i = 0; i < 4; i++)
{
if ((i != 3 && pe[i] != 0)
|| (i == 3 && pe[i] != 0x8000))
{
enan (y, (*p & 0x8000) != 0);
return;
}
}
}
else
{
#ifdef ARM_EXTENDED_IEEE_FORMAT
for (i = 2; i <= 5; i++)
{
if (pe[i] != 0)
{
enan (y, (*p & 0x8000) != 0);
return;
}
}
#else
if ((pe[2] & 0x7fff) != 0)
goto bigend_nan;
for (i = 3; i <= 5; i++)
{
if (pe[i] != 0)
{
bigend_nan:
enan (y, (*p & 0x8000) != 0);
return;
}
}
#endif
}
#endif
eclear (y);
einfin (y);
if (*p & 0x8000)
eneg (y);
return;
}
#endif
p = yy;
q = y;
for (i = 0; i < NE; i++)
*q++ = *p++;
}
static void
e113toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
register unsigned EMUSHORT r;
unsigned EMUSHORT *e, *p;
unsigned EMUSHORT yy[NI];
int denorm, i;
e = pe;
denorm = 0;
ecleaz (yy);
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
e += 7;
#endif
r = *e;
yy[0] = 0;
if (r & 0x8000)
yy[0] = 0xffff;
r &= 0x7fff;
#ifdef INFINITY
if (r == 0x7fff)
{
#ifdef NANS
if (! REAL_WORDS_BIG_ENDIAN)
{
for (i = 0; i < 7; i++)
{
if (pe[i] != 0)
{
enan (y, yy[0] != 0);
return;
}
}
}
else
{
for (i = 1; i < 8; i++)
{
if (pe[i] != 0)
{
enan (y, yy[0] != 0);
return;
}
}
}
#endif
eclear (y);
einfin (y);
if (yy[0])
eneg (y);
return;
}
#endif
yy[E] = r;
p = &yy[M + 1];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
{
for (i = 0; i < 7; i++)
*p++ = *(--e);
}
else
{
++e;
for (i = 0; i < 7; i++)
*p++ = *e++;
}
#endif
if (r == 0)
{
yy[M] = 0;
}
else
{
yy[M] = 1;
eshift (yy, -1);
}
emovo (yy, y);
}
static void
e24toe (pe, y)
unsigned EMUSHORT *pe, *y;
{
#ifdef IBM
ibmtoe (pe, y, SFmode);
#else
#ifdef C4X
c4xtoe (pe, y, QFmode);
#else
register unsigned EMUSHORT r;
register unsigned EMUSHORT *e, *p;
unsigned EMUSHORT yy[NI];
int denorm, k;
e = pe;
denorm = 0;
ecleaz (yy);
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
e += 1;
#endif
#ifdef DEC
e += 1;
#endif
r = *e;
yy[0] = 0;
if (r & 0x8000)
yy[0] = 0xffff;
yy[M] = (r & 0x7f) | 0200;
r &= ~0x807f;
#ifdef INFINITY
if (r == 0x7f80)
{
#ifdef NANS
if (REAL_WORDS_BIG_ENDIAN)
{
if (((pe[0] & 0x7f) != 0) || (pe[1] != 0))
{
enan (y, yy[0] != 0);
return;
}
}
else
{
if (((pe[1] & 0x7f) != 0) || (pe[0] != 0))
{
enan (y, yy[0] != 0);
return;
}
}
#endif
eclear (y);
einfin (y);
if (yy[0])
eneg (y);
return;
}
#endif
r >>= 7;
if (r == 0)
{
denorm = 1;
yy[M] &= ~0200;
}
r += EXONE - 0177;
yy[E] = r;
p = &yy[M + 1];
#ifdef DEC
*p++ = *(--e);
#endif
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
*p++ = *(--e);
else
{
++e;
*p++ = *e++;
}
#endif
eshift (yy, -8);
if (denorm)
{
if ((k = enormlz (yy)) > NBITS)
ecleazs (yy);
else
yy[E] -= (unsigned EMUSHORT) (k - 1);
}
emovo (yy, y);
#endif
#endif
}
static void
etoe113 (x, e)
unsigned EMUSHORT *x, *e;
{
unsigned EMUSHORT xi[NI];
EMULONG exp;
int rndsav;
#ifdef NANS
if (eisnan (x))
{
make_nan (e, eisneg (x), TFmode);
return;
}
#endif
emovi (x, xi);
exp = (EMULONG) xi[E];
#ifdef INFINITY
if (eisinf (x))
goto nonorm;
#endif
rndsav = rndprc;
rndprc = 113;
emdnorm (xi, 0, 0, exp, 64);
rndprc = rndsav;
nonorm:
toe113 (xi, e);
}
static void
toe113 (a, b)
unsigned EMUSHORT *a, *b;
{
register unsigned EMUSHORT *p, *q;
unsigned EMUSHORT i;
#ifdef NANS
if (eiisnan (a))
{
make_nan (b, eiisneg (a), TFmode);
return;
}
#endif
p = a;
if (REAL_WORDS_BIG_ENDIAN)
q = b;
else
q = b + 7;
if (a[E] != 0)
{
eshup1 (a);
}
i = *p++;
if (REAL_WORDS_BIG_ENDIAN)
{
if (i)
*q++ = *p++ | 0x8000;
else
*q++ = *p++;
}
else
{
if (i)
*q-- = *p++ | 0x8000;
else
*q-- = *p++;
}
++p;
if (REAL_WORDS_BIG_ENDIAN)
{
for (i = 0; i < 7; i++)
*q++ = *p++;
}
else
{
for (i = 0; i < 7; i++)
*q-- = *p++;
}
}
static void
etoe64 (x, e)
unsigned EMUSHORT *x, *e;
{
unsigned EMUSHORT xi[NI];
EMULONG exp;
int rndsav;
#ifdef NANS
if (eisnan (x))
{
make_nan (e, eisneg (x), XFmode);
return;
}
#endif
emovi (x, xi);
exp = (EMULONG) xi[E];
#ifdef INFINITY
if (eisinf (x))
goto nonorm;
#endif
rndsav = rndprc;
rndprc = 64;
emdnorm (xi, 0, 0, exp, 64);
rndprc = rndsav;
nonorm:
toe64 (xi, e);
}
static void
toe64 (a, b)
unsigned EMUSHORT *a, *b;
{
register unsigned EMUSHORT *p, *q;
unsigned EMUSHORT i;
#ifdef NANS
if (eiisnan (a))
{
make_nan (b, eiisneg (a), XFmode);
return;
}
#endif
if ((a[E] == 0) && ! REAL_WORDS_BIG_ENDIAN)
eshdn1 (a);
p = a;
#ifdef IBM
q = b;
#endif
#ifdef DEC
q = b + 4;
#endif
#ifdef IEEE
if (REAL_WORDS_BIG_ENDIAN)
q = b;
else
{
q = b + 4;
#if LONG_DOUBLE_TYPE_SIZE == 96
*(q+1) = 0;
#endif
}
#endif
i = *p++;
#ifdef IBM
if (i)
*q++ = *p++ | 0x8000;
else
*q++ = *p++;
*q++ = 0;
#endif
#ifdef DEC
if (i)
*q-- = *p++ | 0x8000;
else
*q-- = *p++;
#endif
#ifdef IEEE
if (REAL_WORDS_BIG_ENDIAN)
{
#ifdef ARM_EXTENDED_IEEE_FORMAT
*q++ = i ? 0x8000 : 0;
*q++ = *p++;
#else
if (i)
*q++ = *p++ | 0x8000;
else
*q++ = *p++;
*q++ = 0;
#endif
}
else
{
if (i)
*q-- = *p++ | 0x8000;
else
*q-- = *p++;
}
#endif
++p;
#ifdef IBM
for (i = 0; i < 4; i++)
*q++ = *p++;
#endif
#ifdef DEC
for (i = 0; i < 4; i++)
*q-- = *p++;
#endif
#ifdef IEEE
if (REAL_WORDS_BIG_ENDIAN)
{
for (i = 0; i < 4; i++)
*q++ = *p++;
}
else
{
#ifdef INFINITY
if (eiisinf (a))
{
*q-- = 0x8000;
*q-- = 0;
*q-- = 0;
*q = 0;
return;
}
#endif
for (i = 0; i < 4; i++)
*q-- = *p++;
}
#endif
}
#ifdef DEC
static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
etodec (x, e);
}
static void
toe53 (x, y)
unsigned EMUSHORT *x, *y;
{
todec (x, y);
}
#else
#ifdef IBM
static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
etoibm (x, e, DFmode);
}
static void
toe53 (x, y)
unsigned EMUSHORT *x, *y;
{
toibm (x, y, DFmode);
}
#else
#ifdef C4X
static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
etoc4x (x, e, HFmode);
}
static void
toe53 (x, y)
unsigned EMUSHORT *x, *y;
{
toc4x (x, y, HFmode);
}
#else
static void
etoe53 (x, e)
unsigned EMUSHORT *x, *e;
{
unsigned EMUSHORT xi[NI];
EMULONG exp;
int rndsav;
#ifdef NANS
if (eisnan (x))
{
make_nan (e, eisneg (x), DFmode);
return;
}
#endif
emovi (x, xi);
exp = (EMULONG) xi[E] - (EXONE - 0x3ff);
#ifdef INFINITY
if (eisinf (x))
goto nonorm;
#endif
rndsav = rndprc;
rndprc = 53;
emdnorm (xi, 0, 0, exp, 64);
rndprc = rndsav;
nonorm:
toe53 (xi, e);
}
static void
toe53 (x, y)
unsigned EMUSHORT *x, *y;
{
unsigned EMUSHORT i;
unsigned EMUSHORT *p;
#ifdef NANS
if (eiisnan (x))
{
make_nan (y, eiisneg (x), DFmode);
return;
}
#endif
p = &x[0];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
y += 3;
#endif
*y = 0;
if (*p++)
*y = 0x8000;
i = *p++;
if (i >= (unsigned int) 2047)
{
#ifdef INFINITY
*y |= 0x7ff0;
if (! REAL_WORDS_BIG_ENDIAN)
{
*(--y) = 0;
*(--y) = 0;
*(--y) = 0;
}
else
{
++y;
*y++ = 0;
*y++ = 0;
*y++ = 0;
}
#else
*y |= (unsigned EMUSHORT) 0x7fef;
if (! REAL_WORDS_BIG_ENDIAN)
{
*(--y) = 0xffff;
*(--y) = 0xffff;
*(--y) = 0xffff;
}
else
{
++y;
*y++ = 0xffff;
*y++ = 0xffff;
*y++ = 0xffff;
}
#endif
return;
}
if (i == 0)
{
eshift (x, 4);
}
else
{
i <<= 4;
eshift (x, 5);
}
i |= *p++ & (unsigned EMUSHORT) 0x0f;
*y |= (unsigned EMUSHORT) i;
if (! REAL_WORDS_BIG_ENDIAN)
{
*(--y) = *p++;
*(--y) = *p++;
*(--y) = *p;
}
else
{
++y;
*y++ = *p++;
*y++ = *p++;
*y++ = *p++;
}
}
#endif
#endif
#endif
#ifdef IBM
static void
etoe24 (x, e)
unsigned EMUSHORT *x, *e;
{
etoibm (x, e, SFmode);
}
static void
toe24 (x, y)
unsigned EMUSHORT *x, *y;
{
toibm (x, y, SFmode);
}
#else
#ifdef C4X
static void
etoe24 (x, e)
unsigned EMUSHORT *x, *e;
{
etoc4x (x, e, QFmode);
}
static void
toe24 (x, y)
unsigned EMUSHORT *x, *y;
{
toc4x (x, y, QFmode);
}
#else
static void
etoe24 (x, e)
unsigned EMUSHORT *x, *e;
{
EMULONG exp;
unsigned EMUSHORT xi[NI];
int rndsav;
#ifdef NANS
if (eisnan (x))
{
make_nan (e, eisneg (x), SFmode);
return;
}
#endif
emovi (x, xi);
exp = (EMULONG) xi[E] - (EXONE - 0177);
#ifdef INFINITY
if (eisinf (x))
goto nonorm;
#endif
rndsav = rndprc;
rndprc = 24;
emdnorm (xi, 0, 0, exp, 64);
rndprc = rndsav;
nonorm:
toe24 (xi, e);
}
static void
toe24 (x, y)
unsigned EMUSHORT *x, *y;
{
unsigned EMUSHORT i;
unsigned EMUSHORT *p;
#ifdef NANS
if (eiisnan (x))
{
make_nan (y, eiisneg (x), SFmode);
return;
}
#endif
p = &x[0];
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
y += 1;
#endif
#ifdef DEC
y += 1;
#endif
*y = 0;
if (*p++)
*y = 0x8000;
i = *p++;
if (i >= 255)
{
#ifdef INFINITY
*y |= (unsigned EMUSHORT) 0x7f80;
#ifdef DEC
*(--y) = 0;
#endif
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
*(--y) = 0;
else
{
++y;
*y = 0;
}
#endif
#else
*y |= (unsigned EMUSHORT) 0x7f7f;
#ifdef DEC
*(--y) = 0xffff;
#endif
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
*(--y) = 0xffff;
else
{
++y;
*y = 0xffff;
}
#endif
#ifdef ERANGE
errno = ERANGE;
#endif
#endif
return;
}
if (i == 0)
{
eshift (x, 7);
}
else
{
i <<= 7;
eshift (x, 8);
}
i |= *p++ & (unsigned EMUSHORT) 0x7f;
*y |= i;
#ifdef DEC
*(--y) = *p;
#endif
#ifdef IEEE
if (! REAL_WORDS_BIG_ENDIAN)
*(--y) = *p;
else
{
++y;
*y = *p;
}
#endif
}
#endif
#endif
static int
ecmp (a, b)
unsigned EMUSHORT *a, *b;
{
unsigned EMUSHORT ai[NI], bi[NI];
register unsigned EMUSHORT *p, *q;
register int i;
int msign;
#ifdef NANS
if (eisnan (a) || eisnan (b))
return (-2);
#endif
emovi (a, ai);
p = ai;
emovi (b, bi);
q = bi;
if (*p != *q)
{
for (i = 1; i < NI - 1; i++)
{
if (ai[i] != 0)
goto nzro;
if (bi[i] != 0)
goto nzro;
}
return (0);
nzro:
if (*p == 0)
return (1);
else
return (-1);
}
if (*p == 0)
msign = 1;
else
msign = -1;
i = NI - 1;
do
{
if (*p++ != *q++)
{
goto diff;
}
}
while (--i > 0);
return (0);
diff:
if (*(--p) > *(--q))
return (msign);
else
return (-msign);
}
#if 0
static void
eround (x, y)
unsigned EMUSHORT *x, *y;
{
eadd (ehalf, x, y);
efloor (y, y);
}
#endif
static void
ltoe (lp, y)
HOST_WIDE_INT *lp;
unsigned EMUSHORT *y;
{
unsigned EMUSHORT yi[NI];
unsigned HOST_WIDE_INT ll;
int k;
ecleaz (yi);
if (*lp < 0)
{
ll = (unsigned HOST_WIDE_INT) (-(*lp));
yi[0] = 0xffff;
}
else
{
ll = (unsigned HOST_WIDE_INT) (*lp);
}
#if HOST_BITS_PER_WIDE_INT == 64
yi[M] = (unsigned EMUSHORT) (ll >> 48);
yi[M + 1] = (unsigned EMUSHORT) (ll >> 32);
yi[M + 2] = (unsigned EMUSHORT) (ll >> 16);
yi[M + 3] = (unsigned EMUSHORT) ll;
yi[E] = EXONE + 47;
#else
yi[M] = (unsigned EMUSHORT) (ll >> 16);
yi[M + 1] = (unsigned EMUSHORT) ll;
yi[E] = EXONE + 15;
#endif
if ((k = enormlz (yi)) > NBITS)
ecleaz (yi);
else
yi[E] -= (unsigned EMUSHORT) k;
emovo (yi, y);
}
static void
ultoe (lp, y)
unsigned HOST_WIDE_INT *lp;
unsigned EMUSHORT *y;
{
unsigned EMUSHORT yi[NI];
unsigned HOST_WIDE_INT ll;
int k;
ecleaz (yi);
ll = *lp;
#if HOST_BITS_PER_WIDE_INT == 64
yi[M] = (unsigned EMUSHORT) (ll >> 48);
yi[M + 1] = (unsigned EMUSHORT) (ll >> 32);
yi[M + 2] = (unsigned EMUSHORT) (ll >> 16);
yi[M + 3] = (unsigned EMUSHORT) ll;
yi[E] = EXONE + 47;
#else
yi[M] = (unsigned EMUSHORT) (ll >> 16);
yi[M + 1] = (unsigned EMUSHORT) ll;
yi[E] = EXONE + 15;
#endif
if ((k = enormlz (yi)) > NBITS)
ecleaz (yi);
else
yi[E] -= (unsigned EMUSHORT) k;
emovo (yi, y);
}
static void
eifrac (x, i, frac)
unsigned EMUSHORT *x;
HOST_WIDE_INT *i;
unsigned EMUSHORT *frac;
{
unsigned EMUSHORT xi[NI];
int j, k;
unsigned HOST_WIDE_INT ll;
emovi (x, xi);
k = (int) xi[E] - (EXONE - 1);
if (k <= 0)
{
*i = 0L;
emovo (xi, frac);
return;
}
if (k > (HOST_BITS_PER_WIDE_INT - 1))
{
if (xi[0])
*i = ((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1);
else
{
#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
euifrac (x, &ll, frac);
*i = (HOST_WIDE_INT) ll;
return;
#else
*i = (((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1)) - 1;
#endif
}
eshift (xi, k);
if (extra_warnings)
warning ("overflow on truncation to integer");
}
else if (k > 16)
{
j = k - ((k >> 4) << 4);
eshift (xi, j);
ll = xi[M];
k -= j;
do
{
eshup6 (xi);
ll = (ll << 16) | xi[M];
}
while ((k -= 16) > 0);
*i = ll;
if (xi[0])
*i = -(*i);
}
else
{
eshift (xi, k);
*i = (HOST_WIDE_INT) xi[M] & 0xffff;
if (xi[0])
*i = -(*i);
}
xi[0] = 0;
xi[E] = EXONE - 1;
xi[M] = 0;
if ((k = enormlz (xi)) > NBITS)
ecleaz (xi);
else
xi[E] -= (unsigned EMUSHORT) k;
emovo (xi, frac);
}
static void
euifrac (x, i, frac)
unsigned EMUSHORT *x;
unsigned HOST_WIDE_INT *i;
unsigned EMUSHORT *frac;
{
unsigned HOST_WIDE_INT ll;
unsigned EMUSHORT xi[NI];
int j, k;
emovi (x, xi);
k = (int) xi[E] - (EXONE - 1);
if (k <= 0)
{
*i = 0L;
emovo (xi, frac);
return;
}
if (k > HOST_BITS_PER_WIDE_INT)
{
*i = ~(0L);
eshift (xi, k);
if (extra_warnings)
warning ("overflow on truncation to unsigned integer");
}
else if (k > 16)
{
j = k - ((k >> 4) << 4);
eshift (xi, j);
ll = xi[M];
k -= j;
do
{
eshup6 (xi);
ll = (ll << 16) | xi[M];
}
while ((k -= 16) > 0);
*i = ll;
}
else
{
eshift (xi, k);
*i = (HOST_WIDE_INT) xi[M] & 0xffff;
}
if (xi[0])
*i = 0L;
xi[0] = 0;
xi[E] = EXONE - 1;
xi[M] = 0;
if ((k = enormlz (xi)) > NBITS)
ecleaz (xi);
else
xi[E] -= (unsigned EMUSHORT) k;
emovo (xi, frac);
}
static int
eshift (x, sc)
unsigned EMUSHORT *x;
int sc;
{
unsigned EMUSHORT lost;
unsigned EMUSHORT *p;
if (sc == 0)
return (0);
lost = 0;
p = x + NI - 1;
if (sc < 0)
{
sc = -sc;
while (sc >= 16)
{
lost |= *p;
eshdn6 (x);
sc -= 16;
}
while (sc >= 8)
{
lost |= *p & 0xff;
eshdn8 (x);
sc -= 8;
}
while (sc > 0)
{
lost |= *p & 1;
eshdn1 (x);
sc -= 1;
}
}
else
{
while (sc >= 16)
{
eshup6 (x);
sc -= 16;
}
while (sc >= 8)
{
eshup8 (x);
sc -= 8;
}
while (sc > 0)
{
eshup1 (x);
sc -= 1;
}
}
if (lost)
lost = 1;
return ((int) lost);
}
static int
enormlz (x)
unsigned EMUSHORT x[];
{
register unsigned EMUSHORT *p;
int sc;
sc = 0;
p = &x[M];
if (*p != 0)
goto normdn;
++p;
if (*p & 0x8000)
return (0);
while (*p == 0)
{
eshup6 (x);
sc += 16;
if (sc > NBITS)
return (sc);
}
while ((*p & 0xff00) == 0)
{
eshup8 (x);
sc += 8;
}
while ((*p & 0x8000) == 0)
{
eshup1 (x);
sc += 1;
if (sc > NBITS)
{
mtherr ("enormlz", UNDERFLOW);
return (sc);
}
}
return (sc);
normdn:
if (*p & 0xff00)
{
eshdn8 (x);
sc -= 8;
}
while (*p != 0)
{
eshdn1 (x);
sc -= 1;
if (sc < -NBITS)
{
mtherr ("enormlz", OVERFLOW);
return (sc);
}
}
return (sc);
}
#define NTEN 12
#define MAXP 4096
#if LONG_DOUBLE_TYPE_SIZE == 128
static unsigned EMUSHORT etens[NTEN + 1][NE] =
{
{0x6576, 0x4a92, 0x804a, 0x153f,
0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,},
{0x6a32, 0xce52, 0x329a, 0x28ce,
0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,},
{0x526c, 0x50ce, 0xf18b, 0x3d28,
0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
{0x9c66, 0x58f8, 0xbc50, 0x5c54,
0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
{0x851e, 0xeab7, 0x98fe, 0x901b,
0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
{0x0235, 0x0137, 0x36b1, 0x336c,
0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
{0x50f8, 0x25fb, 0xc76b, 0x6b71,
0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
{0x0000, 0x0000, 0x0000, 0x0000,
0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
{0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,},
};
static unsigned EMUSHORT emtens[NTEN + 1][NE] =
{
{0x2030, 0xcffc, 0xa1c3, 0x8123,
0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,},
{0x8264, 0xd2cb, 0xf2ea, 0x12d4,
0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,},
{0xf53f, 0xf698, 0x6bd3, 0x0158,
0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
{0xe731, 0x04d4, 0xe3f2, 0xd332,
0x7132, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
{0xa23e, 0x5308, 0xfefb, 0x1155,
0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
{0xe26d, 0xdbde, 0xd05d, 0xb3f6,
0xac7c, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
{0x2a20, 0x6224, 0x47b3, 0x98d7,
0x3f23, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
{0x0b5b, 0x4af2, 0xa581, 0x18ed,
0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
{0xbf71, 0xa9b3, 0x7989, 0xbe68,
0x4c2e, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
{0x3d4d, 0x7c3d, 0x36ba, 0x0d2b,
0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
{0xc155, 0xa4a8, 0x404e, 0x6113,
0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
{0xd70a, 0x70a3, 0x0a3d, 0xa3d7,
0x3d70, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
{0xcccd, 0xcccc, 0xcccc, 0xcccc,
0xcccc, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,},
};
#else
static unsigned EMUSHORT etens[NTEN + 1][NE] =
{
{0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,},
{0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,},
{0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,},
{0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,},
{0xddbc, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,},
{0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,},
{0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,},
{0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,},
{0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,},
{0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,},
{0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,},
{0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,},
{0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,},
};
static unsigned EMUSHORT emtens[NTEN + 1][NE] =
{
{0x2de4, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,},
{0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,},
{0x87a6, 0xc0bd, 0xda57, 0x82a5, 0xa2a6, 0x32b5,},
{0x7133, 0xd21c, 0xdb23, 0xee32, 0x9049, 0x395a,},
{0xfa91, 0x1939, 0x637a, 0x4325, 0xc031, 0x3cac,},
{0xac7d, 0xe4a0, 0x64bc, 0x467c, 0xddd0, 0x3e55,},
{0x3f24, 0xe9a5, 0xa539, 0xea27, 0xa87f, 0x3f2a,},
{0x67de, 0x94ba, 0x4539, 0x1ead, 0xcfb1, 0x3f94,},
{0x4c2f, 0xe15b, 0xc44d, 0x94be, 0xe695, 0x3fc9,},
{0xfdc2, 0xcefc, 0x8461, 0x7711, 0xabcc, 0x3fe4,},
{0xd3c3, 0x652b, 0xe219, 0x1758, 0xd1b7, 0x3ff1,},
{0x3d71, 0xd70a, 0x70a3, 0x0a3d, 0xa3d7, 0x3ff8,},
{0xcccd, 0xcccc, 0xcccc, 0xcccc, 0xcccc, 0x3ffb,},
};
#endif
#if 0
static void
e24toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
int ndigs;
{
unsigned EMUSHORT w[NI];
e24toe (x, w);
etoasc (w, string, ndigs);
}
static void
e53toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
int ndigs;
{
unsigned EMUSHORT w[NI];
e53toe (x, w);
etoasc (w, string, ndigs);
}
static void
e64toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
int ndigs;
{
unsigned EMUSHORT w[NI];
e64toe (x, w);
etoasc (w, string, ndigs);
}
static void
e113toasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
int ndigs;
{
unsigned EMUSHORT w[NI];
e113toe (x, w);
etoasc (w, string, ndigs);
}
#endif
static char wstring[80];
static void
etoasc (x, string, ndigs)
unsigned EMUSHORT x[];
char *string;
int ndigs;
{
EMUSHORT digit;
unsigned EMUSHORT y[NI], t[NI], u[NI], w[NI];
unsigned EMUSHORT *p, *r, *ten;
unsigned EMUSHORT sign;
int i, j, k, expon, rndsav;
char *s, *ss;
unsigned EMUSHORT m;
rndsav = rndprc;
ss = string;
s = wstring;
*ss = '\0';
*s = '\0';
#ifdef NANS
if (eisnan (x))
{
sprintf (wstring, " NaN ");
goto bxit;
}
#endif
rndprc = NBITS;
emov (x, y);
if (y[NE - 1] & 0x8000)
{
sign = 0xffff;
y[NE - 1] &= 0x7fff;
}
else
{
sign = 0;
}
expon = 0;
ten = &etens[NTEN][0];
emov (eone, t);
if (y[NE - 1] == 0)
{
for (k = 0; k < NE - 1; k++)
{
if (y[k] != 0)
goto tnzro;
}
goto isone;
}
tnzro:
if (y[NE - 1] == 0x7fff)
{
if (sign)
sprintf (wstring, " -Infinity ");
else
sprintf (wstring, " Infinity ");
goto bxit;
}
if ((y[NE - 1] != 0) && ((y[NE - 2] & 0x8000) == 0))
{
mtherr ("etoasc", DOMAIN);
sprintf (wstring, "NaN");
goto bxit;
}
i = ecmp (eone, y);
if (i == 0)
goto isone;
if (i == -2)
abort ();
if (i < 0)
{
emov (y, u);
u[NE - 1] = EXONE + NBITS - 1;
p = &etens[NTEN - 4][0];
m = 16;
do
{
ediv (p, u, t);
efloor (t, w);
for (j = 0; j < NE - 1; j++)
{
if (t[j] != w[j])
goto noint;
}
emov (t, u);
expon += (int) m;
noint:
p += NE;
m >>= 1;
}
while (m != 0);
u[NE - 1] += y[NE - 1] - (unsigned int) (EXONE + NBITS - 1);
emov (u, y);
emov (eone, t);
m = MAXP;
p = &etens[0][0];
while (ecmp (ten, u) <= 0)
{
if (ecmp (p, u) <= 0)
{
ediv (p, u, u);
emul (p, t, t);
expon += (int) m;
}
m >>= 1;
if (m == 0)
break;
p += NE;
}
}
else
{
if (y[NE - 1] == 0)
{
while ((y[NE - 2] & 0x8000) == 0)
{
emul (ten, y, y);
expon -= 1;
}
}
else
{
emovi (y, w);
for (i = 0; i < NDEC + 1; i++)
{
if ((w[NI - 1] & 0x7) != 0)
break;
emovz (w, u);
eshdn1 (u);
eshdn1 (u);
eaddm (w, u);
u[1] += 3;
while (u[2] != 0)
{
eshdn1 (u);
u[1] += 1;
}
if (u[NI - 1] != 0)
break;
if (eone[NE - 1] <= u[1])
break;
emovz (u, w);
expon -= 1;
}
emovo (w, y);
}
k = -MAXP;
p = &emtens[0][0];
r = &etens[0][0];
emov (y, w);
emov (eone, t);
while (ecmp (eone, w) > 0)
{
if (ecmp (p, w) >= 0)
{
emul (r, w, w);
emul (r, t, t);
expon += k;
}
k /= 2;
if (k == 0)
break;
p += NE;
r += NE;
}
ediv (t, eone, t);
}
isone:
emovi (t, w);
emovz (w, t);
emovi (y, w);
emovz (w, y);
eiremain (t, y);
digit = equot[NI - 1];
while ((digit == 0) && (ecmp (y, ezero) != 0))
{
eshup1 (y);
emovz (y, u);
eshup1 (u);
eshup1 (u);
eaddm (u, y);
eiremain (t, y);
digit = equot[NI - 1];
expon -= 1;
}
s = wstring;
if (sign)
*s++ = '-';
else
*s++ = ' ';
if (ndigs < 0)
ndigs = 0;
if (ndigs > NDEC)
ndigs = NDEC;
if (digit == 10)
{
*s++ = '1';
*s++ = '.';
if (ndigs > 0)
{
*s++ = '0';
ndigs -= 1;
}
expon += 1;
}
else
{
*s++ = (char)digit + '0';
*s++ = '.';
}
for (k = 0; k <= ndigs; k++)
{
eshup1 (y);
emovz (y, u);
eshup1 (u);
eshup1 (u);
eaddm (u, y);
eiremain (t, y);
*s++ = (char) equot[NI - 1] + '0';
}
digit = equot[NI - 1];
--s;
ss = s;
if (digit > 4)
{
if (digit == 5)
{
emovo (y, t);
if (ecmp (t, ezero) != 0)
goto roun;
#ifndef C4X
if ((*(s - 1) & 1) == 0)
goto doexp;
#endif
}
roun:
--s;
k = *s & 0x7f;
if (k == '.')
{
--s;
k = *s;
k += 1;
*s = (char) k;
if (k > '9')
{
expon += 1;
*s = '1';
}
goto doexp;
}
k += 1;
*s = (char) k;
if (k > '9')
{
*s = '0';
goto roun;
}
}
doexp:
sprintf (ss, "e%d", expon);
bxit:
rndprc = rndsav;
s = string;
ss = wstring;
while (*ss == ' ')
++ss;
while ((*s++ = *ss++) != '\0')
;
}
static void
asctoe24 (s, y)
const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, 24);
}
static void
asctoe53 (s, y)
const char *s;
unsigned EMUSHORT *y;
{
#if defined(DEC) || defined(IBM)
asctoeg (s, y, 56);
#else
#if defined(C4X)
asctoeg (s, y, 32);
#else
asctoeg (s, y, 53);
#endif
#endif
}
static void
asctoe64 (s, y)
const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, 64);
}
static void
asctoe113 (s, y)
const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, 113);
}
static void
asctoe (s, y)
const char *s;
unsigned EMUSHORT *y;
{
asctoeg (s, y, NBITS);
}
static void
asctoeg (ss, y, oprec)
const char *ss;
unsigned EMUSHORT *y;
int oprec;
{
unsigned EMUSHORT yy[NI], xt[NI], tt[NI];
int esign, decflg, sgnflg, nexp, exp, prec, lost;
int k, trail, c, rndsav;
EMULONG lexp;
unsigned EMUSHORT nsign, *p;
char *sp, *s, *lstr;
int base = 10;
lstr = (char *) alloca (strlen (ss) + 1);
while (*ss == ' ')
++ss;
sp = lstr;
while ((*sp++ = *ss++) != '\0')
;
s = lstr;
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
{
base = 16;
s += 2;
}
rndsav = rndprc;
rndprc = NBITS;
lost = 0;
nsign = 0;
decflg = 0;
sgnflg = 0;
nexp = 0;
exp = 0;
prec = 0;
ecleaz (yy);
trail = 0;
nxtcom:
if (*s >= '0' && *s <= '9')
k = *s - '0';
else if (*s >= 'a')
k = 10 + *s - 'a';
else
k = 10 + *s - 'A';
if ((k >= 0) && (k < base))
{
if ((prec == 0) && (decflg == 0) && (k == 0))
goto donchr;
if ((trail == 0) && (decflg != 0))
{
sp = s;
while ((*sp >= '0' && *sp <= '9')
|| (base == 16 && ((*sp >= 'a' && *sp <= 'f')
|| (*sp >= 'A' && *sp <= 'F'))))
++sp;
c = *sp & 0x7f;
if ((base != 10 || ((c != 'e') && (c != 'E')))
&& (base != 16 || ((c != 'p') && (c != 'P')))
&& (c != '\0')
&& (c != '\n') && (c != '\r') && (c != ' ')
&& (c != ','))
goto error;
--sp;
while (*sp == '0')
*sp-- = 'z';
trail = 1;
if (*s == 'z')
goto donchr;
}
if (yy[2] == 0)
{
if (base == 16)
{
if (decflg)
nexp += 4;
eshup1 (yy);
eshup1 (yy);
eshup1 (yy);
eshup1 (yy);
}
else
{
if (decflg)
nexp += 1;
eshup1 (yy);
emovz (yy, xt);
eshup1 (xt);
eshup1 (xt);
eaddm (xt, yy);
}
ecleaz (xt);
xt[NI - 2] = (unsigned EMUSHORT) k;
eaddm (xt, yy);
}
else
{
lost |= k;
if (decflg == 0)
{
if (base == 10)
nexp -= 1;
else
nexp -= 4;
}
}
prec += 1;
goto donchr;
}
switch (*s)
{
case 'z':
break;
case 'E':
case 'e':
case 'P':
case 'p':
goto expnt;
case '.':
if (decflg)
goto error;
++decflg;
break;
case '-':
nsign = 0xffff;
if (sgnflg)
goto error;
++sgnflg;
break;
case '+':
if (sgnflg)
goto error;
++sgnflg;
break;
case ',':
case ' ':
case '\0':
case '\n':
case '\r':
goto daldone;
case 'i':
case 'I':
goto infinite;
default:
error:
#ifdef NANS
einan (yy);
#else
mtherr ("asctoe", DOMAIN);
eclear (yy);
#endif
goto aexit;
}
donchr:
++s;
goto nxtcom;
expnt:
for (k = 0; k < NI; k++)
{
if (yy[k] != 0)
goto read_expnt;
}
goto aexit;
read_expnt:
esign = 1;
exp = 0;
++s;
if (*s == '-')
{
esign = -1;
++s;
}
if (*s == '+')
++s;
while ((*s >= '0') && (*s <= '9'))
{
exp *= 10;
exp += *s++ - '0';
if (exp > 999999)
break;
}
if (esign < 0)
exp = -exp;
if ((exp > MAXDECEXP) && (base == 10))
{
infinite:
ecleaz (yy);
yy[E] = 0x7fff;
goto aexit;
}
if ((exp < MINDECEXP) && (base == 10))
{
zero:
ecleaz (yy);
goto aexit;
}
daldone:
if (base == 16)
{
if ((k = enormlz (yy)) > NBITS)
{
ecleaz (yy);
goto aexit;
}
lexp = (EXONE - 1 + NBITS) - k + yy[E] + exp - nexp;
if (lexp > 0x7fff)
goto infinite;
if (lexp < 0)
goto zero;
yy[E] = lexp;
goto expdon;
}
nexp = exp - nexp;
while ((nexp > 0) && (yy[2] == 0))
{
emovz (yy, xt);
eshup1 (xt);
eshup1 (xt);
eaddm (yy, xt);
eshup1 (xt);
if (xt[2] != 0)
break;
nexp -= 1;
emovz (xt, yy);
}
if ((k = enormlz (yy)) > NBITS)
{
ecleaz (yy);
goto aexit;
}
lexp = (EXONE - 1 + NBITS) - k;
emdnorm (yy, lost, 0, lexp, 64);
lost = 0;
lexp = yy[E];
if (nexp == 0)
{
k = 0;
goto expdon;
}
esign = 1;
if (nexp < 0)
{
nexp = -nexp;
esign = -1;
if (nexp > 4096)
{
emovi (etens[0], tt);
lexp -= tt[E];
k = edivm (tt, yy);
lexp += EXONE;
nexp -= 4096;
}
}
p = &etens[NTEN][0];
emov (eone, xt);
exp = 1;
do
{
if (exp & nexp)
emul (p, xt, xt);
p -= NE;
exp = exp + exp;
}
while (exp <= MAXP);
emovi (xt, tt);
if (esign < 0)
{
lexp -= tt[E];
k = edivm (tt, yy);
lexp += EXONE;
}
else
{
lexp += tt[E];
k = emulm (tt, yy);
lexp -= EXONE - 1;
}
lost = k;
expdon:
if (oprec == 53)
lexp -= EXONE - 0x3ff;
#ifdef C4X
else if (oprec == 24 || oprec == 32)
lexp -= (EXONE - 0x7f);
#else
#ifdef IBM
else if (oprec == 24 || oprec == 56)
lexp -= EXONE - (0x41 << 2);
#else
else if (oprec == 24)
lexp -= EXONE - 0177;
#endif
#endif
#ifdef DEC
else if (oprec == 56)
lexp -= EXONE - 0201;
#endif
rndprc = oprec;
emdnorm (yy, lost, 0, lexp, 64);
aexit:
rndprc = rndsav;
yy[0] = nsign;
switch (oprec)
{
#ifdef DEC
case 56:
todec (yy, y);
break;
#endif
#ifdef IBM
case 56:
toibm (yy, y, DFmode);
break;
#endif
#ifdef C4X
case 32:
toc4x (yy, y, HFmode);
break;
#endif
case 53:
toe53 (yy, y);
break;
case 24:
toe24 (yy, y);
break;
case 64:
toe64 (yy, y);
break;
case 113:
toe113 (yy, y);
break;
case NBITS:
emovo (yy, y);
break;
}
}
static unsigned EMUSHORT bmask[] =
{
0xffff,
0xfffe,
0xfffc,
0xfff8,
0xfff0,
0xffe0,
0xffc0,
0xff80,
0xff00,
0xfe00,
0xfc00,
0xf800,
0xf000,
0xe000,
0xc000,
0x8000,
0x0000,
};
static void
efloor (x, y)
unsigned EMUSHORT x[], y[];
{
register unsigned EMUSHORT *p;
int e, expon, i;
unsigned EMUSHORT f[NE];
emov (x, f);
expon = (int) f[NE - 1];
e = (expon & 0x7fff) - (EXONE - 1);
if (e <= 0)
{
eclear (y);
goto isitneg;
}
e = NBITS - e;
emov (f, y);
if (e <= 0)
return;
p = &y[0];
while (e >= 16)
{
*p++ = 0;
e -= 16;
}
*p &= bmask[e];
isitneg:
if ((unsigned EMUSHORT) expon & (unsigned EMUSHORT) 0x8000)
{
for (i = 0; i < NE - 1; i++)
{
if (f[i] != y[i])
{
esub (eone, y, y);
break;
}
}
}
}
#if 0
static void
efrexp (x, exp, s)
unsigned EMUSHORT x[];
int *exp;
unsigned EMUSHORT s[];
{
unsigned EMUSHORT xi[NI];
EMULONG li;
emovi (x, xi);
li = (EMULONG) ((EMUSHORT) xi[1]);
if (li == 0)
{
li -= enormlz (xi);
}
xi[1] = 0x3ffe;
emovo (xi, s);
*exp = (int) (li - 0x3ffe);
}
#endif
static void
eldexp (x, pwr2, y)
unsigned EMUSHORT x[];
int pwr2;
unsigned EMUSHORT y[];
{
unsigned EMUSHORT xi[NI];
EMULONG li;
int i;
emovi (x, xi);
li = xi[1];
li += pwr2;
i = 0;
emdnorm (xi, i, i, li, 64);
emovo (xi, y);
}
#if 0
static void
eremain (a, b, c)
unsigned EMUSHORT a[], b[], c[];
{
unsigned EMUSHORT den[NI], num[NI];
#ifdef NANS
if (eisinf (b)
|| (ecmp (a, ezero) == 0)
|| eisnan (a)
|| eisnan (b))
{
enan (c, 0);
return;
}
#endif
if (ecmp (a, ezero) == 0)
{
mtherr ("eremain", SING);
eclear (c);
return;
}
emovi (a, den);
emovi (b, num);
eiremain (den, num);
if (a[0] == b[0])
num[0] = 0;
else
num[0] = 0xffff;
emovo (num, c);
}
#endif
static void
eiremain (den, num)
unsigned EMUSHORT den[], num[];
{
EMULONG ld, ln;
unsigned EMUSHORT j;
ld = den[E];
ld -= enormlz (den);
ln = num[E];
ln -= enormlz (num);
ecleaz (equot);
while (ln >= ld)
{
if (ecmpm (den, num) <= 0)
{
esubm (den, num);
j = 1;
}
else
j = 0;
eshup1 (equot);
equot[NI - 1] |= j;
eshup1 (num);
ln -= 1;
}
emdnorm (num, 0, 0, ln, 0);
}
int merror = 0;
extern int merror;
static void
mtherr (name, code)
const char *name;
int code;
{
if (strcmp (name, "esub") == 0)
name = "subtraction";
else if (strcmp (name, "ediv") == 0)
name = "division";
else if (strcmp (name, "emul") == 0)
name = "multiplication";
else if (strcmp (name, "enormlz") == 0)
name = "normalization";
else if (strcmp (name, "etoasc") == 0)
name = "conversion to text";
else if (strcmp (name, "asctoe") == 0)
name = "parsing";
else if (strcmp (name, "eremain") == 0)
name = "modulus";
else if (strcmp (name, "esqrt") == 0)
name = "square root";
if (extra_warnings)
{
switch (code)
{
case DOMAIN: warning ("%s: argument domain error" , name); break;
case SING: warning ("%s: function singularity" , name); break;
case OVERFLOW: warning ("%s: overflow range error" , name); break;
case UNDERFLOW: warning ("%s: underflow range error" , name); break;
case TLOSS: warning ("%s: total loss of precision" , name); break;
case PLOSS: warning ("%s: partial loss of precision", name); break;
case INVALID: warning ("%s: NaN - producing operation", name); break;
default: abort ();
}
}
merror = code + 1;
}
#ifdef DEC
static void
dectoe (d, e)
unsigned EMUSHORT *d;
unsigned EMUSHORT *e;
{
unsigned EMUSHORT y[NI];
register unsigned EMUSHORT r, *p;
ecleaz (y);
p = y;
r = *d;
if (*d & (unsigned int) 0x8000)
*p = 0xffff;
++p;
r &= 0x7fff;
if (r == 0)
goto done;
r >>= 7;
r += EXONE - 0201;
*p++ = r;
r = *d++;
r &= 0177;
r |= 0200;
*p++ = r;
*p++ = *d++;
*p++ = *d++;
*p = *d;
eshdn8 (y);
done:
emovo (y, e);
}
static void
etodec (x, d)
unsigned EMUSHORT *x, *d;
{
unsigned EMUSHORT xi[NI];
EMULONG exp;
int rndsav;
emovi (x, xi);
exp = (EMULONG) xi[E] - (EXONE - 0201);
rndsav = rndprc;
rndprc = 56;
emdnorm (xi, 0, 0, exp, 64);
rndprc = rndsav;
todec (xi, d);
}
static void
todec (x, y)
unsigned EMUSHORT *x, *y;
{
unsigned EMUSHORT i;
unsigned EMUSHORT *p;
p = x;
*y = 0;
if (*p++)
*y = 0100000;
i = *p++;
if (i == 0)
{
*y++ = 0;
*y++ = 0;
*y++ = 0;
*y++ = 0;
return;
}
if (i > 0377)
{
*y++ |= 077777;
*y++ = 0xffff;
*y++ = 0xffff;
*y++ = 0xffff;
#ifdef ERANGE
errno = ERANGE;
#endif
return;
}
i &= 0377;
i <<= 7;
eshup8 (x);
x[M] &= 0177;
i |= x[M];
*y++ |= i;
*y++ = x[M + 1];
*y++ = x[M + 2];
*y++ = x[M + 3];
}
#endif
#ifdef IBM
static void
ibmtoe (d, e, mode)
unsigned EMUSHORT *d;
unsigned EMUSHORT *e;
enum machine_mode mode;
{
unsigned EMUSHORT y[NI];
register unsigned EMUSHORT r, *p;
int rndsav;
ecleaz (y);
p = y;
r = *d;
if (*d & (unsigned int) 0x8000)
*p = 0xffff;
++p;
r &= 0x7f00;
r >>= 6;
r += EXONE - (0x41 << 2);
*p++ = r;
*p++ = *d++ & 0xff;
if (mode != SFmode)
{
*p++ = *d++;
*p++ = *d++;
}
*p = *d;
if (y[M] == 0 && y[M+1] == 0 && y[M+2] == 0 && y[M+3] == 0)
y[0] = y[E] = 0;
else
y[E] -= 5 + enormlz (y);
emovo (y, e);
}
static void
etoibm (x, d, mode)
unsigned EMUSHORT *x, *d;
enum machine_mode mode;
{
unsigned EMUSHORT xi[NI];
EMULONG exp;
int rndsav;
emovi (x, xi);
exp = (EMULONG) xi[E] - (EXONE - (0x41 << 2));
rndsav = rndprc;
rndprc = 56;
emdnorm (xi, 0, 0, exp, 64);
rndprc = rndsav;
toibm (xi, d, mode);
}
static void
toibm (x, y, mode)
unsigned EMUSHORT *x, *y;
enum machine_mode mode;
{
unsigned EMUSHORT i;
unsigned EMUSHORT *p;
int r;
p = x;
*y = 0;
if (*p++)
*y = 0x8000;
i = *p++;
if (i == 0)
{
*y++ = 0;
*y++ = 0;
if (mode != SFmode)
{
*y++ = 0;
*y++ = 0;
}
return;
}
r = i & 0x3;
i >>= 2;
if (i > 0x7f)
{
*y++ |= 0x7fff;
*y++ = 0xffff;
if (mode != SFmode)
{
*y++ = 0xffff;
*y++ = 0xffff;
}
#ifdef ERANGE
errno = ERANGE;
#endif
return;
}
i &= 0x7f;
*y |= (i << 8);
eshift (x, r + 5);
*y++ |= x[M];
*y++ = x[M + 1];
if (mode != SFmode)
{
*y++ = x[M + 2];
*y++ = x[M + 3];
}
}
#endif
#ifdef C4X
static void
c4xtoe (d, e, mode)
unsigned EMUSHORT *d;
unsigned EMUSHORT *e;
enum machine_mode mode;
{
unsigned EMUSHORT y[NI];
int r;
int isnegative;
int size;
int i;
int carry;
if ((d[0] == 0x8000)
&& (d[1] == 0x0000)
&& ((mode == QFmode) || ((d[2] == 0x0000) && (d[3] == 0x0000))))
{
e[0] = 0;
e[1] = 0;
e[2] = 0;
e[3] = 0;
e[4] = 0;
e[5] = 0;
return;
}
ecleaz (y);
r = d[0];
if (r & (unsigned int) 0x0080)
{
y[0] = 0xffff;
isnegative = TRUE;
}
else
{
isnegative = FALSE;
}
r >>= 8;
if (r & 0x80)
{
r = r | (~0 & ~0xff);
}
if (isnegative)
{
y[M] = d[0] & 0x7f;
y[M+1] = d[1];
if (mode != QFmode)
{
y[M+2] = d[2];
y[M+3] = d[3];
size = 4;
}
else
{
size = 2;
}
eshift(y, -8);
carry = 1;
for (i=size + M; i > M; i--)
{
if (carry && (y[i] == 0x0000))
{
y[i] = carry ? 0x0000 : 0xffff;
}
else
{
y[i] = ((~y[i]) + carry) & 0xffff;
carry = 0;
}
}
if (carry)
{
eshift(y, -1);
y[M+1] |= 0x8000;
r++;
}
y[1] = r + EXONE;
}
else
{
r += EXONE;
y[1] = r;
y[M] = (d[0] & 0x7f) | 0x80;
y[M+1] = d[1];
if (mode != QFmode)
{
y[M+2] = d[2];
y[M+3] = d[3];
}
eshift(y, -8);
}
emovo (y, e);
}
static void
etoc4x (x, d, mode)
unsigned EMUSHORT *x, *d;
enum machine_mode mode;
{
unsigned EMUSHORT xi[NI];
EMULONG exp;
int rndsav;
emovi (x, xi);
exp = (EMULONG) xi[E] - (EXONE - 0x7f);
rndsav = rndprc;
rndprc = mode == QFmode ? 24 : 32;
emdnorm (xi, 0, 0, exp, 64);
rndprc = rndsav;
toc4x (xi, d, mode);
}
static void
toc4x (x, y, mode)
unsigned EMUSHORT *x, *y;
enum machine_mode mode;
{
int i;
int v;
int carry;
if ((x[0] == 0)
&& (x[1] == 0)
&& (x[M] == 0)
&& (x[M+1] == 0)
&& ((mode == QFmode) || ((x[M+2] == 0) && (x[M+3] == 0))))
{
*y++ = 0x8000;
*y++ = 0x0000;
if (mode != QFmode)
{
*y++ = 0x0000;
*y++ = 0x0000;
}
return;
}
*y = 0;
if (x[0])
{
*y = 0x0080;
i = ((int) x[1]) - 0x7f;
if (mode != QFmode)
v = 4 + M;
else
v = 2 + M;
carry = 1;
while (v > M)
{
if (x[v] == 0x0000)
{
x[v] = carry ? 0x0000 : 0xffff;
}
else
{
x[v] = ((~x[v]) + carry) & 0xffff;
carry = 0;
}
v--;
}
if (x[M+1] & 0x8000)
{
eshift(x, 1);
i--;
}
}
else
{
i = ((int) x[1]) - 0x7f;
}
if ((i < -128) || (i > 127))
{
y[0] |= 0xff7f;
y[1] = 0xffff;
if (mode != QFmode)
{
y[2] = 0xffff;
y[3] = 0xffff;
}
#ifdef ERANGE
errno = ERANGE;
#endif
return;
}
y[0] |= ((i & 0xff) << 8);
eshift (x, 8);
y[0] |= x[M] & 0x7f;
y[1] = x[M + 1];
if (mode != QFmode)
{
y[2] = x[M + 2];
y[3] = x[M + 3];
}
}
#endif
#ifdef TFMODE_NAN
TFMODE_NAN;
#else
#ifdef IEEE
unsigned EMUSHORT TFbignan[8] =
{0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
unsigned EMUSHORT TFlittlenan[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0xffff};
#endif
#endif
#ifdef XFMODE_NAN
XFMODE_NAN;
#else
#ifdef IEEE
unsigned EMUSHORT XFbignan[6] =
{0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
unsigned EMUSHORT XFlittlenan[6] = {0, 0, 0, 0xc000, 0xffff, 0};
#endif
#endif
#ifdef DFMODE_NAN
DFMODE_NAN;
#else
#ifdef IEEE
unsigned EMUSHORT DFbignan[4] = {0x7fff, 0xffff, 0xffff, 0xffff};
unsigned EMUSHORT DFlittlenan[4] = {0, 0, 0, 0xfff8};
#endif
#endif
#ifdef SFMODE_NAN
SFMODE_NAN;
#else
#ifdef IEEE
unsigned EMUSHORT SFbignan[2] = {0x7fff, 0xffff};
unsigned EMUSHORT SFlittlenan[2] = {0, 0xffc0};
#endif
#endif
static void
make_nan (nan, sign, mode)
unsigned EMUSHORT *nan;
int sign;
enum machine_mode mode;
{
int n;
unsigned EMUSHORT *p;
switch (mode)
{
#if !defined(DEC) && !defined(IBM) && !defined(C4X)
case TFmode:
n = 8;
if (REAL_WORDS_BIG_ENDIAN)
p = TFbignan;
else
p = TFlittlenan;
break;
case XFmode:
n = 6;
if (REAL_WORDS_BIG_ENDIAN)
p = XFbignan;
else
p = XFlittlenan;
break;
case DFmode:
n = 4;
if (REAL_WORDS_BIG_ENDIAN)
p = DFbignan;
else
p = DFlittlenan;
break;
case SFmode:
case HFmode:
n = 2;
if (REAL_WORDS_BIG_ENDIAN)
p = SFbignan;
else
p = SFlittlenan;
break;
#endif
default:
abort ();
}
if (REAL_WORDS_BIG_ENDIAN)
*nan++ = (sign << 15) | (*p++ & 0x7fff);
while (--n != 0)
*nan++ = *p++;
if (! REAL_WORDS_BIG_ENDIAN)
*nan = (sign << 15) | (*p & 0x7fff);
}
REAL_VALUE_TYPE
ereal_unto_float (f)
long f;
{
REAL_VALUE_TYPE r;
unsigned EMUSHORT s[2];
unsigned EMUSHORT e[NE];
if (REAL_WORDS_BIG_ENDIAN)
{
s[0] = (unsigned EMUSHORT) (f >> 16);
s[1] = (unsigned EMUSHORT) f;
}
else
{
s[0] = (unsigned EMUSHORT) f;
s[1] = (unsigned EMUSHORT) (f >> 16);
}
e24toe (s, e);
PUT_REAL (e, &r);
return r;
}
REAL_VALUE_TYPE
ereal_unto_double (d)
long d[];
{
REAL_VALUE_TYPE r;
unsigned EMUSHORT s[4];
unsigned EMUSHORT e[NE];
if (REAL_WORDS_BIG_ENDIAN)
{
s[0] = (unsigned EMUSHORT) (d[0] >> 16);
s[1] = (unsigned EMUSHORT) d[0];
s[2] = (unsigned EMUSHORT) (d[1] >> 16);
s[3] = (unsigned EMUSHORT) d[1];
}
else
{
s[0] = (unsigned EMUSHORT) d[0];
s[1] = (unsigned EMUSHORT) (d[0] >> 16);
s[2] = (unsigned EMUSHORT) d[1];
s[3] = (unsigned EMUSHORT) (d[1] >> 16);
}
e53toe (s, e);
PUT_REAL (e, &r);
return r;
}
REAL_VALUE_TYPE
ereal_from_float (f)
HOST_WIDE_INT f;
{
REAL_VALUE_TYPE r;
unsigned EMUSHORT s[2];
unsigned EMUSHORT e[NE];
if (REAL_WORDS_BIG_ENDIAN)
{
s[0] = (unsigned EMUSHORT) (f >> 16);
s[1] = (unsigned EMUSHORT) f;
}
else
{
s[0] = (unsigned EMUSHORT) f;
s[1] = (unsigned EMUSHORT) (f >> 16);
}
e24toe (s, e);
PUT_REAL (e, &r);
return r;
}
REAL_VALUE_TYPE
ereal_from_double (d)
HOST_WIDE_INT d[];
{
REAL_VALUE_TYPE r;
unsigned EMUSHORT s[4];
unsigned EMUSHORT e[NE];
if (REAL_WORDS_BIG_ENDIAN)
{
#if HOST_BITS_PER_WIDE_INT == 32
s[0] = (unsigned EMUSHORT) (d[0] >> 16);
s[1] = (unsigned EMUSHORT) d[0];
s[2] = (unsigned EMUSHORT) (d[1] >> 16);
s[3] = (unsigned EMUSHORT) d[1];
#else
s[0] = (unsigned EMUSHORT) (d[0] >> 48);
s[1] = (unsigned EMUSHORT) (d[0] >> 32);
s[2] = (unsigned EMUSHORT) (d[0] >> 16);
s[3] = (unsigned EMUSHORT) d[0];
#endif
}
else
{
s[0] = (unsigned EMUSHORT) d[0];
s[1] = (unsigned EMUSHORT) (d[0] >> 16);
#if HOST_BITS_PER_WIDE_INT == 32
s[2] = (unsigned EMUSHORT) d[1];
s[3] = (unsigned EMUSHORT) (d[1] >> 16);
#else
s[2] = (unsigned EMUSHORT) (d[0] >> 32);
s[3] = (unsigned EMUSHORT) (d[0] >> 48);
#endif
}
e53toe (s, e);
PUT_REAL (e, &r);
return r;
}
#if 0
static void
uditoe (di, e)
unsigned EMUSHORT *di;
unsigned EMUSHORT *e;
{
unsigned EMUSHORT yi[NI];
int k;
ecleaz (yi);
if (WORDS_BIG_ENDIAN)
{
for (k = M; k < M + 4; k++)
yi[k] = *di++;
}
else
{
for (k = M + 3; k >= M; k--)
yi[k] = *di++;
}
yi[E] = EXONE + 47;
if ((k = enormlz (yi)) > NBITS)
ecleaz (yi);
else
yi[E] -= (unsigned EMUSHORT) k;
emovo (yi, e);
}
static void
ditoe (di, e)
unsigned EMUSHORT *di;
unsigned EMUSHORT *e;
{
unsigned EMULONG acc;
unsigned EMUSHORT yi[NI];
unsigned EMUSHORT carry;
int k, sign;
ecleaz (yi);
if (WORDS_BIG_ENDIAN)
{
for (k = M; k < M + 4; k++)
yi[k] = *di++;
}
else
{
for (k = M + 3; k >= M; k--)
yi[k] = *di++;
}
sign = 0;
if (yi[M] & 0x8000)
{
sign = 1;
carry = 0;
for (k = M + 3; k >= M; k--)
{
acc = (unsigned EMULONG) (~yi[k] & 0xffff) + carry;
yi[k] = acc;
carry = 0;
if (acc & 0x10000)
carry = 1;
}
}
yi[E] = EXONE + 47;
if ((k = enormlz (yi)) > NBITS)
ecleaz (yi);
else
yi[E] -= (unsigned EMUSHORT) k;
emovo (yi, e);
if (sign)
eneg (e);
}
static void
etoudi (x, i)
unsigned EMUSHORT *x;
unsigned EMUSHORT *i;
{
unsigned EMUSHORT xi[NI];
int j, k;
emovi (x, xi);
if (xi[0])
{
xi[M] = 0;
goto noshift;
}
k = (int) xi[E] - (EXONE - 1);
if (k <= 0)
{
for (j = 0; j < 4; j++)
*i++ = 0;
return;
}
if (k > 64)
{
for (j = 0; j < 4; j++)
*i++ = 0xffff;
if (extra_warnings)
warning ("overflow on truncation to integer");
return;
}
if (k > 16)
{
j = k - ((k >> 4) << 4);
if (j == 0)
j = 16;
eshift (xi, j);
if (WORDS_BIG_ENDIAN)
*i++ = xi[M];
else
{
i += 3;
*i-- = xi[M];
}
k -= j;
do
{
eshup6 (xi);
if (WORDS_BIG_ENDIAN)
*i++ = xi[M];
else
*i-- = xi[M];
}
while ((k -= 16) > 0);
}
else
{
eshift (xi, k);
noshift:
if (WORDS_BIG_ENDIAN)
{
i += 3;
*i-- = xi[M];
*i-- = 0;
*i-- = 0;
*i = 0;
}
else
{
*i++ = xi[M];
*i++ = 0;
*i++ = 0;
*i = 0;
}
}
}
static void
etodi (x, i)
unsigned EMUSHORT *x;
unsigned EMUSHORT *i;
{
unsigned EMULONG acc;
unsigned EMUSHORT xi[NI];
unsigned EMUSHORT carry;
unsigned EMUSHORT *isave;
int j, k;
emovi (x, xi);
k = (int) xi[E] - (EXONE - 1);
if (k <= 0)
{
for (j = 0; j < 4; j++)
*i++ = 0;
return;
}
if (k > 64)
{
for (j = 0; j < 4; j++)
*i++ = 0xffff;
if (extra_warnings)
warning ("overflow on truncation to integer");
return;
}
isave = i;
if (k > 16)
{
j = k - ((k >> 4) << 4);
if (j == 0)
j = 16;
eshift (xi, j);
if (WORDS_BIG_ENDIAN)
*i++ = xi[M];
else
{
i += 3;
*i-- = xi[M];
}
k -= j;
do
{
eshup6 (xi);
if (WORDS_BIG_ENDIAN)
*i++ = xi[M];
else
*i-- = xi[M];
}
while ((k -= 16) > 0);
}
else
{
eshift (xi, k);
if (WORDS_BIG_ENDIAN)
{
i += 3;
*i = xi[M];
*i-- = 0;
*i-- = 0;
*i = 0;
}
else
{
*i++ = xi[M];
*i++ = 0;
*i++ = 0;
*i = 0;
}
}
if (xi[0])
{
carry = 0;
if (WORDS_BIG_ENDIAN)
isave += 3;
for (k = 0; k < 4; k++)
{
acc = (unsigned EMULONG) (~(*isave) & 0xffff) + carry;
if (WORDS_BIG_ENDIAN)
*isave-- = acc;
else
*isave++ = acc;
carry = 0;
if (acc & 0x10000)
carry = 1;
}
}
}
static int esqinited = 0;
static unsigned short sqrndbit[NI];
static void
esqrt (x, y)
unsigned EMUSHORT *x, *y;
{
unsigned EMUSHORT temp[NI], num[NI], sq[NI], xx[NI];
EMULONG m, exp;
int i, j, k, n, nlups;
if (esqinited == 0)
{
ecleaz (sqrndbit);
sqrndbit[NI - 2] = 1;
esqinited = 1;
}
i = ecmp (x, ezero);
if (i <= 0)
{
if (i == -1)
{
mtherr ("esqrt", DOMAIN);
eclear (y);
}
else
emov (x, y);
return;
}
#ifdef INFINITY
if (eisinf (x))
{
eclear (y);
einfin (y);
return;
}
#endif
emovi (x, xx);
m = (EMULONG) xx[1];
if (m == 0)
m -= enormlz (xx);
m -= 0x3ffe;
exp = (unsigned short) ((m / 2) + 0x3ffe);
if ((m & 1) != 0)
{
if (m > 0)
exp += 1;
eshdn1 (xx);
}
ecleaz (sq);
ecleaz (num);
n = 8;
nlups = rndprc;
j = 0;
while (nlups > 0)
{
if (j < NE)
num[NI - 1] = xx[j + 3];
if (nlups <= 8)
n = nlups + 1;
for (i = 0; i < n; i++)
{
eshup1 (num);
eshup1 (num);
eshup1 (sq);
for (k = 0; k < NI; k++)
temp[k] = sq[k];
eshup1 (temp);
eaddm (sqrndbit, temp);
if (ecmpm (temp, num) <= 0)
{
esubm (temp, num);
sq[NI - 2] |= 1;
}
}
nlups -= n;
j += 1;
}
exp += (NBITS - 1) - rndprc;
k = 0;
for (i = 3; i < NI; i++)
k |= (int) num[i];
emdnorm (sq, k, 0, exp, 64);
emovo (sq, y);
}
#endif
#endif
int
significand_size (mode)
enum machine_mode mode;
{
switch (GET_MODE_BITSIZE (mode))
{
case 32:
#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
return 56;
#endif
return 24;
case 64:
#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
return 53;
#else
#if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
return 56;
#else
#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
return 56;
#else
#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
return 56;
#else
abort ();
#endif
#endif
#endif
#endif
case 96:
return 64;
case 128:
return 113;
default:
abort ();
}
}