diff options
Diffstat (limited to 'contrib/gcc/real.c')
-rw-r--r-- | contrib/gcc/real.c | 569 |
1 files changed, 323 insertions, 246 deletions
diff --git a/contrib/gcc/real.c b/contrib/gcc/real.c index ed854e0..a3fda6d 100644 --- a/contrib/gcc/real.c +++ b/contrib/gcc/real.c @@ -1,6 +1,6 @@ /* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF, and support for XFmode IEEE extended real floating point arithmetic. - Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. + Copyright (C) 1993, 94-98, 1999 Free Software Foundation, Inc. Contributed by Stephen L. Moshier (moshier@world.std.com). This file is part of GNU CC. @@ -79,14 +79,17 @@ netlib.att.com: netlib/cephes. */ `C4X' refers specifically to the floating point format used on Texas Instruments TMS320C3x and TMS320C4x digital signal processors. This supports QFmode (32-bit float, double) and HFmode - (40-bit long double) where BITS_PER_BYTE is 32. + (40-bit long double) where BITS_PER_BYTE is 32. Unlike IEEE + floats, C4x floats are not rounded to be even. The C4x conversions + were contributed by m.hayes@elec.canterbury.ac.nz (Michael Hayes) and + Haj.Ten.Brugge@net.HCC.nl (Herman ten Brugge). If LONG_DOUBLE_TYPE_SIZE = 64 (the default, unless tm.h defines it) then `long double' and `double' are both implemented, but they both mean DFmode. In this case, the software floating-point support available here is activated by writing #define REAL_ARITHMETIC - in tm.h. + in tm.h. The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support and may deactivate XFmode since `long double' is used to refer @@ -245,7 +248,12 @@ unknown arithmetic type #define MAXDECEXP 4932 #define MINDECEXP -4956 #define GET_REAL(r,e) bcopy ((char *) r, (char *) e, 2*NE) -#define PUT_REAL(e,r) bcopy ((char *) e, (char *) r, 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 /* no XFmode */ #if LONG_DOUBLE_TYPE_SIZE == 128 #define NE 10 @@ -261,34 +269,34 @@ unknown arithmetic type /* Emulator uses target format internally but host stores it in host endian-ness. */ -#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]; \ - w[3] = ((EMUSHORT *) r)[0]; \ - w[2] = ((EMUSHORT *) r)[1]; \ - w[1] = ((EMUSHORT *) r)[2]; \ - w[0] = ((EMUSHORT *) r)[3]; \ - e53toe (w, (e)); \ - } \ +#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); \ - *((EMUSHORT *) r) = w[3]; \ - *((EMUSHORT *) r + 1) = w[2]; \ - *((EMUSHORT *) r + 2) = w[1]; \ - *((EMUSHORT *) r + 3) = w[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 /* not REAL_ARITHMETIC */ @@ -406,12 +414,12 @@ static void e64toasc PROTO((unsigned EMUSHORT *, char *, int)); static void e113toasc PROTO((unsigned EMUSHORT *, char *, int)); #endif /* 0 */ static void etoasc PROTO((unsigned EMUSHORT *, char *, int)); -static void asctoe24 PROTO((char *, unsigned EMUSHORT *)); -static void asctoe53 PROTO((char *, unsigned EMUSHORT *)); -static void asctoe64 PROTO((char *, unsigned EMUSHORT *)); -static void asctoe113 PROTO((char *, unsigned EMUSHORT *)); -static void asctoe PROTO((char *, unsigned EMUSHORT *)); -static void asctoeg PROTO((char *, unsigned EMUSHORT *, 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 *, @@ -423,7 +431,7 @@ static void eremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *, unsigned EMUSHORT *)); #endif static void eiremain PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *)); -static void mtherr PROTO((char *, int)); +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 *)); @@ -458,7 +466,7 @@ static void esqrt PROTO((unsigned EMUSHORT *, unsigned EMUSHORT *)); swapping ends if required, into output array of longs. The result is normally passed to fprintf by the ASM_OUTPUT_ macros. */ -static void +static void endian (e, x, mode) unsigned EMUSHORT e[]; long x[]; @@ -555,7 +563,7 @@ endian (e, x, mode) /* This is the implementation of the REAL_ARITHMETIC macro. */ -void +void earith (value, icode, r1, r2) REAL_VALUE_TYPE *value; int icode; @@ -634,7 +642,7 @@ PUT_REAL (v, value); /* Truncate REAL_VALUE_TYPE toward zero to signed HOST_WIDE_INT. implements REAL_VALUE_RNDZINT (x) (etrunci (x)). */ -REAL_VALUE_TYPE +REAL_VALUE_TYPE etrunci (x) REAL_VALUE_TYPE x; { @@ -657,7 +665,7 @@ etrunci (x) /* Truncate REAL_VALUE_TYPE toward zero to unsigned HOST_WIDE_INT; implements REAL_VALUE_UNSIGNED_RNDZINT (x) (etruncui (x)). */ -REAL_VALUE_TYPE +REAL_VALUE_TYPE etruncui (x) REAL_VALUE_TYPE x; { @@ -677,13 +685,13 @@ etruncui (x) } -/* This is the REAL_VALUE_ATOF function. It converts a decimal string to - binary, rounding off as indicated by the machine_mode argument. Then it - promotes the rounded value to REAL_VALUE_TYPE. */ +/* This is the REAL_VALUE_ATOF function. It converts a decimal or hexadecimal + string to binary, rounding off as indicated by the machine_mode argument. + Then it promotes the rounded value to REAL_VALUE_TYPE. */ -REAL_VALUE_TYPE +REAL_VALUE_TYPE ereal_atof (s, t) - char *s; + const char *s; enum machine_mode t; { unsigned EMUSHORT tem[NE], e[NE]; @@ -731,7 +739,7 @@ ereal_atof (s, t) /* Expansion of REAL_NEGATE. */ -REAL_VALUE_TYPE +REAL_VALUE_TYPE ereal_negate (x) REAL_VALUE_TYPE x; { @@ -793,7 +801,7 @@ efixui (x) /* REAL_VALUE_FROM_INT macro. */ -void +void ereal_from_int (d, i, j, mode) REAL_VALUE_TYPE *d; HOST_WIDE_INT i, j; @@ -860,7 +868,7 @@ ereal_from_int (d, i, j, mode) /* REAL_VALUE_FROM_UNSIGNED_INT macro. */ -void +void ereal_from_uint (d, i, j, mode) REAL_VALUE_TYPE *d; unsigned HOST_WIDE_INT i, j; @@ -914,7 +922,7 @@ ereal_from_uint (d, i, j, mode) /* REAL_VALUE_TO_INT macro. */ -void +void ereal_to_int (low, high, rr) HOST_WIDE_INT *low, *high; REAL_VALUE_TYPE rr; @@ -1164,15 +1172,15 @@ debug_real (r) REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr); fprintf (stderr, "%s", dstr); -} +} /* The following routines convert REAL_VALUE_TYPE to the various floating point formats that are meaningful to supported computers. - The results are returned in 32-bit pieces, each piece stored in a `long'. + The results are returned in 32-bit pieces, each piece stored in a `long'. This is so they can be printed by statements like - + fprintf (file, "%lx, %lx", L[0], L[1]); that will work on both narrow- and wide-word host computers. */ @@ -1181,7 +1189,7 @@ debug_real (r) contains four 32-bit pieces of the result, in the order they would appear in memory. */ -void +void etartdouble (r, l) REAL_VALUE_TYPE r; long l[]; @@ -1197,7 +1205,7 @@ etartdouble (r, l) contains three 32-bit pieces of the result, in the order they would appear in memory. */ -void +void etarldouble (r, l) REAL_VALUE_TYPE r; long l[]; @@ -1212,7 +1220,7 @@ etarldouble (r, l) /* Convert R to a double precision value. The output array L contains two 32-bit pieces of the result, in the order they would appear in memory. */ -void +void etardouble (r, l) REAL_VALUE_TYPE r; long l[]; @@ -1310,11 +1318,11 @@ ereal_isneg (x) most significant word first, most significant bit is set) ei[NI-1] low guard word (0x8000 bit is rounding place) - - - + + + Routines for external format e-type numbers - + asctoe (string, e) ASCII string to extended double e type asctoe64 (string, &d) ASCII string to long double asctoe53 (string, &d) ASCII string to double @@ -1361,10 +1369,10 @@ ereal_isneg (x) eisinf (e) 1 if e has maximum exponent (non-IEEE) or is infinite (IEEE) eisnan (e) 1 if e is a NaN - + Routines for internal format exploded e-type numbers - + eaddm (ai, bi) add significands, bi = bi + ai ecleaz (ei) ei = 0 ecleazs (ei) set ei = 0 but leave its sign alone @@ -1396,13 +1404,13 @@ ereal_isneg (x) after each arithmetic operation. Exception flags are NOT fully supported. - + Signaling NaN's are NOT supported; they are treated the same as quiet NaN's. - + Define INFINITY for support of infinity; otherwise a saturation arithmetic is implemented. - + Define NANS for support of Not-a-Number items; otherwise the arithmetic will never produce a NaN output, and might be confused by a NaN input. @@ -1410,7 +1418,7 @@ ereal_isneg (x) either a or b is a NaN. This means asking `if (ecmp (a,b) < 0)' may not be legitimate. Use `if (ecmp (a,b) == -1)' for `less than' if in doubt. - + Denormals are always supported here where appropriate (e.g., not for conversion to DEC numbers). */ @@ -1423,7 +1431,7 @@ ereal_isneg (x) mode, most floating point constants are given as arrays of octal integers to eliminate decimal to binary conversion errors that might be introduced by the compiler. - + For computers, such as IBM PC, that follow the IEEE Standard for Binary Floating Point Arithmetic (ANSI/IEEE Std 754-1985), the symbol IEEE should be defined. @@ -1431,20 +1439,20 @@ ereal_isneg (x) are provided as arrays of hexadecimal 16 bit integers. The endian-ness of generated values is controlled by REAL_WORDS_BIG_ENDIAN. - + To accommodate other types of computer arithmetic, all constants are also provided in a normal decimal radix which one can hope are correctly converted to a suitable format by the available C language compiler. To invoke this mode, the symbol UNK is defined. - + An important difference among these modes is a predefined set of machine arithmetic constants for each. The numbers MACHEP (the machine roundoff error), MAXNUM (largest number represented), and several other parameters are preset by the configuration symbol. Check the file const.c to ensure that these values are correct for your computer. - + For ANSI C compatibility, define ANSIC equal to 1. Currently this affects only the atan2 function and others that use it. */ @@ -1537,7 +1545,7 @@ extern int rndprc; /* Clear out entire e-type number X. */ -static void +static void eclear (x) register unsigned EMUSHORT *x; { @@ -1549,7 +1557,7 @@ eclear (x) /* Move e-type number from A to B. */ -static void +static void emov (a, b) register unsigned EMUSHORT *a, *b; { @@ -1563,18 +1571,18 @@ emov (a, b) #if 0 /* Absolute value of e-type X. */ -static void +static void eabs (x) unsigned EMUSHORT x[]; { /* sign is top bit of last word of external format */ - x[NE - 1] &= 0x7fff; + x[NE - 1] &= 0x7fff; } #endif /* 0 */ /* Negate the e-type number X. */ -static void +static void eneg (x) unsigned EMUSHORT x[]; { @@ -1584,7 +1592,7 @@ eneg (x) /* Return 1 if sign bit of e-type number X is nonzero, else zero. */ -static int +static int eisneg (x) unsigned EMUSHORT x[]; { @@ -1597,7 +1605,7 @@ eisneg (x) /* Return 1 if e-type number X is infinity, else return zero. */ -static int +static int eisinf (x) unsigned EMUSHORT x[]; { @@ -1615,7 +1623,7 @@ eisinf (x) /* Check if e-type number is not a number. The bit pattern is one that we defined, so we know for sure how to detect it. */ -static int +static int eisnan (x) unsigned EMUSHORT x[]; { @@ -1639,7 +1647,7 @@ eisnan (x) /* Fill e-type number X with infinity pattern (IEEE) or largest possible number (non-IEEE). */ -static void +static void einfin (x) register unsigned EMUSHORT *x; { @@ -1682,7 +1690,7 @@ einfin (x) This generates Intel's quiet NaN pattern for extended real. The exponent is 7fff, the leading mantissa word is c000. */ -static void +static void enan (x, sign) register unsigned EMUSHORT *x; int sign; @@ -1697,7 +1705,7 @@ enan (x, sign) /* Move in an e-type number A, converting it to exploded e-type B. */ -static void +static void emovi (a, b) unsigned EMUSHORT *a, *b; { @@ -1744,7 +1752,7 @@ emovi (a, b) /* Move out exploded e-type number A, converting it to e type B. */ -static void +static void emovo (a, b) unsigned EMUSHORT *a, *b; { @@ -1783,7 +1791,7 @@ emovo (a, b) /* Clear out exploded e-type number XI. */ -static void +static void ecleaz (xi) register unsigned EMUSHORT *xi; { @@ -1795,7 +1803,7 @@ ecleaz (xi) /* Clear out exploded e-type XI, but don't touch the sign. */ -static void +static void ecleazs (xi) register unsigned EMUSHORT *xi; { @@ -1808,7 +1816,7 @@ ecleazs (xi) /* Move exploded e-type number from A to B. */ -static void +static void emovz (a, b) register unsigned EMUSHORT *a, *b; { @@ -1836,7 +1844,7 @@ einan (x) /* Return nonzero if exploded e-type X is a NaN. */ -static int +static int eiisnan (x) unsigned EMUSHORT x[]; { @@ -1855,7 +1863,7 @@ eiisnan (x) /* Return nonzero if sign of exploded e-type X is nonzero. */ -static int +static int eiisneg (x) unsigned EMUSHORT x[]; { @@ -1879,7 +1887,7 @@ eiinfin (x) /* Return nonzero if exploded e-type X is infinite. */ -static int +static int eiisinf (x) unsigned EMUSHORT x[]; { @@ -1925,7 +1933,7 @@ ecmpm (a, b) /* Shift significand of exploded e-type X down by 1 bit. */ -static void +static void eshdn1 (x) register unsigned EMUSHORT *x; { @@ -1949,7 +1957,7 @@ eshdn1 (x) /* Shift significand of exploded e-type X up by 1 bit. */ -static void +static void eshup1 (x) register unsigned EMUSHORT *x; { @@ -1974,7 +1982,7 @@ eshup1 (x) /* Shift significand of exploded e-type X down by 8 bits. */ -static void +static void eshdn8 (x) register unsigned EMUSHORT *x; { @@ -1995,7 +2003,7 @@ eshdn8 (x) /* Shift significand of exploded e-type X up by 8 bits. */ -static void +static void eshup8 (x) register unsigned EMUSHORT *x; { @@ -2017,7 +2025,7 @@ eshup8 (x) /* Shift significand of exploded e-type X up by 16 bits. */ -static void +static void eshup6 (x) register unsigned EMUSHORT *x; { @@ -2035,7 +2043,7 @@ eshup6 (x) /* Shift significand of exploded e-type X down by 16 bits. */ -static void +static void eshdn6 (x) register unsigned EMUSHORT *x; { @@ -2053,7 +2061,7 @@ eshdn6 (x) /* Add significands of exploded e-type X and Y. X + Y replaces Y. */ -static void +static void eaddm (x, y) unsigned EMUSHORT *x, *y; { @@ -2079,7 +2087,7 @@ eaddm (x, y) /* Subtract significands of exploded e-type X and Y. Y - X replaces Y. */ -static void +static void esubm (x, y) unsigned EMUSHORT *x, *y; { @@ -2113,7 +2121,7 @@ static unsigned EMUSHORT equot[NI]; /* Divide significands */ -int +int edivm (den, num) unsigned EMUSHORT den[], num[]; { @@ -2211,7 +2219,7 @@ edivm (den, num) /* Multiply significands */ -int +int emulm (a, b) unsigned EMUSHORT a[], b[]; { @@ -2333,7 +2341,7 @@ edivm (den, num) tnum = (((unsigned EMULONG) num[M]) << 16) + num[M+1]; /* Do not execute the divide instruction if it will overflow. */ - if ((tdenm * 0xffffL) < tnum) + if ((tdenm * (unsigned long)0xffff) < tnum) tquot = 0xffff; else tquot = tnum / tdenm; @@ -2417,15 +2425,15 @@ emulm (a, b) The internal format number to be rounded is S. Input LOST is 0 if the value is exact. This is the so-called sticky bit. - + Input SUBFLG indicates whether the number was obtained by a subtraction operation. In that case if LOST is nonzero then the number is slightly smaller than indicated. - + Input EXP is the biased exponent, which may be negative. the exponent field of S is ignored but is replaced by EXP as adjusted by normalization and rounding. - + Input RCNTRL is the rounding control. If it is nonzero, the returned value will be rounded to RNDPRC bits. @@ -2434,7 +2442,7 @@ emulm (a, b) adjusted to be the actual value it would have after conversion to the final floating point type. This adjustment has been implemented for all type conversions (etoe53, etc.) and decimal - conversions, but not for the arithmetic functions (eadd, etc.). + conversions, but not for the arithmetic functions (eadd, etc.). Data types having standard 15-bit exponents are not affected by this, but SFmode and DFmode are affected. For example, ediv with rndprc = 24 will not round correctly to 24-bit precision if the @@ -2448,7 +2456,7 @@ static unsigned EMUSHORT rebit = 0; static int re = 0; static unsigned EMUSHORT rbit[NI]; -static void +static void emdnorm (s, lost, subflg, exp, rcntrl) unsigned EMUSHORT s[]; int lost; @@ -2594,6 +2602,7 @@ emdnorm (s, lost, subflg, exp, rcntrl) s[rw] &= ~rmsk; if ((r & rmbit) != 0) { +#ifndef C4X if (r == rmbit) { if (lost == 0) @@ -2607,6 +2616,7 @@ emdnorm (s, lost, subflg, exp, rcntrl) goto mddone; } } +#endif eaddm (rbit, s); } mddone: @@ -2662,7 +2672,7 @@ emdnorm (s, lost, subflg, exp, rcntrl) static int subflg = 0; -static void +static void esub (a, b, c) unsigned EMUSHORT *a, *b, *c; { @@ -2694,7 +2704,7 @@ esub (a, b, c) /* Add. C = A + B, all e type. */ -static void +static void eadd (a, b, c) unsigned EMUSHORT *a, *b, *c; { @@ -2727,7 +2737,7 @@ eadd (a, b, c) /* Arithmetic common to both addition and subtraction. */ -static void +static void eadd1 (a, b, c) unsigned EMUSHORT *a, *b, *c; { @@ -2838,7 +2848,7 @@ eadd1 (a, b, c) /* Divide: C = B/A, all e type. */ -static void +static void ediv (a, b, c) unsigned EMUSHORT *a, *b, *c; { @@ -2942,7 +2952,7 @@ ediv (a, b, c) /* Multiply e-types A and B, return e-type product C. */ -static void +static void emul (a, b, c) unsigned EMUSHORT *a, *b, *c; { @@ -3132,7 +3142,7 @@ e53toe (pe, y) #endif eshift (yy, -5); if (denorm) - { + { /* If zero exponent, then normalize the significand. */ if ((k = enormlz (yy)) > NBITS) ecleazs (yy); @@ -3147,7 +3157,7 @@ e53toe (pe, y) /* Convert double extended precision float PE to e type Y. */ -static void +static void e64toe (pe, y) unsigned EMUSHORT *pe, *y; { @@ -3269,7 +3279,7 @@ bigend_nan: /* Convert 128-bit long double precision float PE to e type Y. */ -static void +static void e113toe (pe, y) unsigned EMUSHORT *pe, *y; { @@ -3354,7 +3364,7 @@ e113toe (pe, y) /* Convert single precision float PE to e type Y. */ -static void +static void e24toe (pe, y) unsigned EMUSHORT *pe, *y; { @@ -3457,7 +3467,7 @@ e24toe (pe, y) /* Convert e-type X to IEEE 128-bit long double format E. */ -static void +static void etoe113 (x, e) unsigned EMUSHORT *x, *e; { @@ -3490,7 +3500,7 @@ etoe113 (x, e) /* Convert exploded e-type X, that has already been rounded to 113-bit precision, to IEEE 128-bit long double format Y. */ -static void +static void toe113 (a, b) unsigned EMUSHORT *a, *b; { @@ -3548,7 +3558,7 @@ toe113 (a, b) /* Convert e-type X to IEEE double extended format E. */ -static void +static void etoe64 (x, e) unsigned EMUSHORT *x, *e; { @@ -3582,7 +3592,7 @@ etoe64 (x, e) /* Convert exploded e-type X, that has already been rounded to 64-bit precision, to IEEE double extended format Y. */ -static void +static void toe64 (a, b) unsigned EMUSHORT *a, *b; { @@ -3698,7 +3708,7 @@ toe64 (a, b) #ifdef DEC /* Convert e-type X to DEC-format double E. */ -static void +static void etoe53 (x, e) unsigned EMUSHORT *x, *e; { @@ -3708,7 +3718,7 @@ etoe53 (x, e) /* Convert exploded e-type X, that has already been rounded to 56-bit double precision, to DEC double Y. */ -static void +static void toe53 (x, y) unsigned EMUSHORT *x, *y; { @@ -3719,7 +3729,7 @@ toe53 (x, y) #ifdef IBM /* Convert e-type X to IBM 370-format double E. */ -static void +static void etoe53 (x, e) unsigned EMUSHORT *x, *e; { @@ -3729,7 +3739,7 @@ etoe53 (x, e) /* Convert exploded e-type X, that has already been rounded to 56-bit precision, to IBM 370 double Y. */ -static void +static void toe53 (x, y) unsigned EMUSHORT *x, *y; { @@ -3740,7 +3750,7 @@ toe53 (x, y) #ifdef C4X /* Convert e-type X to C4X-format long double E. */ -static void +static void etoe53 (x, e) unsigned EMUSHORT *x, *e; { @@ -3750,7 +3760,7 @@ etoe53 (x, e) /* Convert exploded e-type X, that has already been rounded to 56-bit precision, to IBM 370 double Y. */ -static void +static void toe53 (x, y) unsigned EMUSHORT *x, *y; { @@ -3761,7 +3771,7 @@ toe53 (x, y) /* Convert e-type X to IEEE double E. */ -static void +static void etoe53 (x, e) unsigned EMUSHORT *x, *e; { @@ -3795,7 +3805,7 @@ etoe53 (x, e) /* Convert exploded e-type X, that has already been rounded to 53-bit precision, to IEEE double Y. */ -static void +static void toe53 (x, y) unsigned EMUSHORT *x, *y; { @@ -3892,7 +3902,7 @@ toe53 (x, y) #ifdef IBM /* Convert e-type X to IBM 370 float E. */ -static void +static void etoe24 (x, e) unsigned EMUSHORT *x, *e; { @@ -3902,7 +3912,7 @@ etoe24 (x, e) /* Convert exploded e-type X, that has already been rounded to float precision, to IBM 370 float Y. */ -static void +static void toe24 (x, y) unsigned EMUSHORT *x, *y; { @@ -3914,7 +3924,7 @@ toe24 (x, y) #ifdef C4X /* Convert e-type X to C4X float E. */ -static void +static void etoe24 (x, e) unsigned EMUSHORT *x, *e; { @@ -3924,7 +3934,7 @@ etoe24 (x, e) /* Convert exploded e-type X, that has already been rounded to float precision, to IBM 370 float Y. */ -static void +static void toe24 (x, y) unsigned EMUSHORT *x, *y; { @@ -3935,7 +3945,7 @@ toe24 (x, y) /* Convert e-type X to IEEE float E. DEC float is the same as IEEE float. */ -static void +static void etoe24 (x, e) unsigned EMUSHORT *x, *e; { @@ -3969,7 +3979,7 @@ etoe24 (x, e) /* Convert exploded e-type X, that has already been rounded to float precision, to IEEE float Y. */ -static void +static void toe24 (x, y) unsigned EMUSHORT *x, *y; { @@ -4061,13 +4071,13 @@ toe24 (x, y) #endif /* not C4X */ #endif /* not IBM */ -/* Compare two e type numbers. +/* Compare two e type numbers. Return +1 if a > b 0 if a == b -1 if a < b -2 if either a or b is a NaN. */ -static int +static int ecmp (a, b) unsigned EMUSHORT *a, *b; { @@ -4130,7 +4140,7 @@ ecmp (a, b) #if 0 /* Find e-type nearest integer to X, as floor (X + 0.5). */ -static void +static void eround (x, y) unsigned EMUSHORT *x, *y; { @@ -4141,7 +4151,7 @@ eround (x, y) /* Convert HOST_WIDE_INT LP to e type Y. */ -static void +static void ltoe (lp, y) HOST_WIDE_INT *lp; unsigned EMUSHORT *y; @@ -4183,7 +4193,7 @@ ltoe (lp, y) /* Convert unsigned HOST_WIDE_INT LP to e type Y. */ -static void +static void ultoe (lp, y) unsigned HOST_WIDE_INT *lp; unsigned EMUSHORT *y; @@ -4223,7 +4233,7 @@ ultoe (lp, y) The output e-type fraction FRAC is the positive fractional part of abs (X). */ -static void +static void eifrac (x, i, frac) unsigned EMUSHORT *x; HOST_WIDE_INT *i; @@ -4306,7 +4316,7 @@ eifrac (x, i, frac) FRAC of e-type X. A negative input yields integer output = 0 but correct fraction. */ -static void +static void euifrac (x, i, frac) unsigned EMUSHORT *x; unsigned HOST_WIDE_INT *i; @@ -4375,7 +4385,7 @@ euifrac (x, i, frac) /* Shift the significand of exploded e-type X up or down by SC bits. */ -static int +static int eshift (x, sc) unsigned EMUSHORT *x; int sc; @@ -4441,7 +4451,7 @@ eshift (x, sc) /* Shift normalize the significand area of exploded e-type X. Return the shift count (up = positive). */ -static int +static int enormlz (x) unsigned EMUSHORT x[]; { @@ -4613,7 +4623,7 @@ static unsigned EMUSHORT emtens[NTEN + 1][NE] = /* Convert float value X to ASCII string STRING with NDIG digits after the decimal point. */ -static void +static void e24toasc (x, string, ndigs) unsigned EMUSHORT x[]; char *string; @@ -4628,7 +4638,7 @@ e24toasc (x, string, ndigs) /* Convert double value X to ASCII string STRING with NDIG digits after the decimal point. */ -static void +static void e53toasc (x, string, ndigs) unsigned EMUSHORT x[]; char *string; @@ -4643,7 +4653,7 @@ e53toasc (x, string, ndigs) /* Convert double extended value X to ASCII string STRING with NDIG digits after the decimal point. */ -static void +static void e64toasc (x, string, ndigs) unsigned EMUSHORT x[]; char *string; @@ -4658,7 +4668,7 @@ e64toasc (x, string, ndigs) /* Convert 128-bit long double value X to ASCII string STRING with NDIG digits after the decimal point. */ -static void +static void e113toasc (x, string, ndigs) unsigned EMUSHORT x[]; char *string; @@ -4676,7 +4686,7 @@ e113toasc (x, string, ndigs) static char wstring[80]; /* working storage for ASCII output */ -static void +static void etoasc (x, string, ndigs) unsigned EMUSHORT x[]; char *string; @@ -4932,8 +4942,10 @@ etoasc (x, string, ndigs) emovo (y, t); if (ecmp (t, ezero) != 0) goto roun; /* round to nearest */ +#ifndef C4X if ((*(s - 1) & 1) == 0) goto doexp; /* round to even */ +#endif } /* Round up and propagate carry-outs */ roun: @@ -4992,9 +5004,9 @@ etoasc (x, string, ndigs) /* Convert ASCII string S to single precision float value Y. */ -static void +static void asctoe24 (s, y) - char *s; + const char *s; unsigned EMUSHORT *y; { asctoeg (s, y, 24); @@ -5003,9 +5015,9 @@ asctoe24 (s, y) /* Convert ASCII string S to double precision value Y. */ -static void +static void asctoe53 (s, y) - char *s; + const char *s; unsigned EMUSHORT *y; { #if defined(DEC) || defined(IBM) @@ -5022,9 +5034,9 @@ asctoe53 (s, y) /* Convert ASCII string S to double extended value Y. */ -static void +static void asctoe64 (s, y) - char *s; + const char *s; unsigned EMUSHORT *y; { asctoeg (s, y, 64); @@ -5032,9 +5044,9 @@ asctoe64 (s, y) /* Convert ASCII string S to 128-bit long double Y. */ -static void +static void asctoe113 (s, y) - char *s; + const char *s; unsigned EMUSHORT *y; { asctoeg (s, y, 113); @@ -5042,20 +5054,20 @@ asctoe113 (s, y) /* Convert ASCII string S to e type Y. */ -static void +static void asctoe (s, y) - char *s; + const char *s; unsigned EMUSHORT *y; { asctoeg (s, y, NBITS); } /* Convert ASCII string SS to e type Y, with a specified rounding precision - of OPREC bits. */ + of OPREC bits. BASE is 16 for C9X hexadecimal floating constants. */ -static void +static void asctoeg (ss, y, oprec) - char *ss; + const char *ss; unsigned EMUSHORT *y; int oprec; { @@ -5065,17 +5077,25 @@ asctoeg (ss, y, oprec) EMULONG lexp; unsigned EMUSHORT nsign, *p; char *sp, *s, *lstr; + int base = 10; /* Copy the input string. */ lstr = (char *) alloca (strlen (ss) + 1); - s = ss; - while (*s == ' ') /* skip leading spaces */ - ++s; + + while (*ss == ' ') /* skip leading spaces */ + ++ss; + sp = lstr; - while ((*sp++ = *s++) != '\0') + while ((*sp++ = *ss++) != '\0') ; s = lstr; + if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) + { + base = 16; + s += 2; + } + rndsav = rndprc; rndprc = NBITS; /* Set to full precision */ lost = 0; @@ -5089,8 +5109,13 @@ asctoeg (ss, y, oprec) trail = 0; nxtcom: - k = *s - '0'; - if ((k >= 0) && (k <= 9)) + 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)) { /* Ignore leading zeros */ if ((prec == 0) && (decflg == 0) && (k == 0)) @@ -5099,11 +5124,15 @@ asctoeg (ss, y, oprec) if ((trail == 0) && (decflg != 0)) { sp = s; - while ((*sp >= '0') && (*sp <= '9')) + while ((*sp >= '0' && *sp <= '9') + || (base == 16 && ((*sp >= 'a' && *sp <= 'f') + || (*sp >= 'A' && *sp <= 'F')))) ++sp; /* Check for syntax error */ c = *sp & 0x7f; - if ((c != 'e') && (c != 'E') && (c != '\0') + if ((base != 10 || ((c != 'e') && (c != 'E'))) + && (base != 16 || ((c != 'p') && (c != 'P'))) + && (c != '\0') && (c != '\n') && (c != '\r') && (c != ' ') && (c != ',')) goto error; @@ -5122,13 +5151,28 @@ asctoeg (ss, y, oprec) if (yy[2] == 0) { - if (decflg) - nexp += 1; /* count digits after decimal point */ - eshup1 (yy); /* multiply current number by 10 */ - emovz (yy, xt); - eshup1 (xt); - eshup1 (xt); - eaddm (xt, yy); + if (base == 16) + { + if (decflg) + nexp += 4; /* count digits after decimal point */ + + eshup1 (yy); /* multiply current number by 16 */ + eshup1 (yy); + eshup1 (yy); + eshup1 (yy); + } + else + { + if (decflg) + nexp += 1; /* count digits after decimal point */ + + eshup1 (yy); /* multiply current number by 10 */ + emovz (yy, xt); + eshup1 (xt); + eshup1 (xt); + eaddm (xt, yy); + } + /* Insert the current digit. */ ecleaz (xt); xt[NI - 2] = (unsigned EMUSHORT) k; eaddm (xt, yy); @@ -5139,7 +5183,12 @@ asctoeg (ss, y, oprec) lost |= k; /* Count lost digits before the decimal point. */ if (decflg == 0) - nexp -= 1; + { + if (base == 10) + nexp -= 1; + else + nexp -= 4; + } } prec += 1; goto donchr; @@ -5151,6 +5200,8 @@ asctoeg (ss, y, oprec) break; case 'E': case 'e': + case 'P': + case 'p': goto expnt; case '.': /* decimal point */ if (decflg) @@ -5217,24 +5268,19 @@ read_expnt: { exp *= 10; exp += *s++ - '0'; - if (exp > -(MINDECEXP)) - { - if (esign < 0) - goto zero; - else - goto infinite; - } + if (exp > 999999) + break; } if (esign < 0) exp = -exp; - if (exp > MAXDECEXP) + if ((exp > MAXDECEXP) && (base == 10)) { infinite: ecleaz (yy); yy[E] = 0x7fff; /* infinity */ goto aexit; } - if (exp < MINDECEXP) + if ((exp < MINDECEXP) && (base == 10)) { zero: ecleaz (yy); @@ -5242,6 +5288,25 @@ read_expnt: } daldone: + if (base == 16) + { + /* Base 16 hexadecimal floating constant. */ + if ((k = enormlz (yy)) > NBITS) + { + ecleaz (yy); + goto aexit; + } + /* Adjust the exponent. NEXP is the number of hex digits, + EXP is a power of 2. */ + 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; /* Pad trailing zeros to minimize power of 10, per IEEE spec. */ while ((nexp > 0) && (yy[2] == 0)) @@ -5263,6 +5328,7 @@ read_expnt: } lexp = (EXONE - 1 + NBITS) - k; emdnorm (yy, lost, 0, lexp, 64); + lost = 0; /* Convert to external format: @@ -5318,6 +5384,7 @@ read_expnt: k = emulm (tt, yy); lexp -= EXONE - 1; } + lost = k; expdon: @@ -5341,7 +5408,7 @@ read_expnt: lexp -= EXONE - 0201; #endif rndprc = oprec; - emdnorm (yy, k, 0, lexp, 64); + emdnorm (yy, lost, 0, lexp, 64); aexit: @@ -5409,7 +5476,7 @@ static unsigned EMUSHORT bmask[] = 0x0000, }; -static void +static void efloor (x, y) unsigned EMUSHORT x[], y[]; { @@ -5460,7 +5527,7 @@ efloor (x, y) /* Return S and EXP such that S * 2^EXP = X and .5 <= S < 1. For example, 1.1 = 0.55 * 2^1. */ -static void +static void efrexp (x, exp, s) unsigned EMUSHORT x[]; int *exp; @@ -5485,7 +5552,7 @@ efrexp (x, exp, s) /* Return e type Y = X * 2^PWR2. */ -static void +static void eldexp (x, pwr2, y) unsigned EMUSHORT x[]; int pwr2; @@ -5508,7 +5575,7 @@ eldexp (x, pwr2, y) /* C = remainder after dividing B by A, all e type values. Least significant integer quotient bits left in EQUOT. */ -static void +static void eremain (a, b, c) unsigned EMUSHORT a[], b[], c[]; { @@ -5545,7 +5612,7 @@ eremain (a, b, c) /* Return quotient of exploded e-types NUM / DEN in EQUOT, remainder in NUM. */ -static void +static void eiremain (den, num) unsigned EMUSHORT den[], num[]; { @@ -5575,10 +5642,9 @@ eiremain (den, num) } /* Report an error condition CODE encountered in function NAME. - CODE is one of the following: Mnemonic Value Significance - + DOMAIN 1 argument domain error SING 2 function singularity OVERFLOW 3 overflow range error @@ -5588,42 +5654,53 @@ eiremain (den, num) INVALID 7 NaN - producing operation EDOM 33 Unix domain error code ERANGE 34 Unix range error code - + The order of appearance of the following messages is bound to the error codes defined above. */ -#define NMSGS 8 -static char *ermsg[NMSGS] = -{ - "unknown", /* error code 0 */ - "domain", /* error code 1 */ - "singularity", /* et seq. */ - "overflow", - "underflow", - "total loss of precision", - "partial loss of precision", - "invalid operation" -}; - int merror = 0; extern int merror; -static void +static void mtherr (name, code) - char *name; + const char *name; int code; { - char errstr[80]; - /* The string passed by the calling program is supposed to be the name of the function in which the error occurred. The code argument selects which error message string will be printed. */ - if ((code <= 0) || (code >= NMSGS)) - code = 0; - sprintf (errstr, " %s %s error", name, ermsg[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) - warning (errstr); + { + 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 (); + } + } + /* Set global error message word */ merror = code + 1; } @@ -5631,7 +5708,7 @@ mtherr (name, code) #ifdef DEC /* Convert DEC double precision D to e type E. */ -static void +static void dectoe (d, e) unsigned EMUSHORT *d; unsigned EMUSHORT *e; @@ -5671,7 +5748,7 @@ dectoe (d, e) /* Convert e type X to DEC double precision D. */ -static void +static void etodec (x, d) unsigned EMUSHORT *x, *d; { @@ -5693,7 +5770,7 @@ etodec (x, d) /* Convert exploded e-type X, that has already been rounded to 56-bit precision, to DEC format double Y. */ -static void +static void todec (x, y) unsigned EMUSHORT *x, *y; { @@ -5739,7 +5816,7 @@ todec (x, y) #ifdef IBM /* Convert IBM single/double precision to e type. */ -static void +static void ibmtoe (d, e, mode) unsigned EMUSHORT *d; unsigned EMUSHORT *e; @@ -5783,7 +5860,7 @@ ibmtoe (d, e, mode) /* Convert e type to IBM single/double precision. */ -static void +static void etoibm (x, d, mode) unsigned EMUSHORT *x, *d; enum machine_mode mode; @@ -5802,7 +5879,7 @@ etoibm (x, d, mode) toibm (xi, d, mode); } -static void +static void toibm (x, y, mode) unsigned EMUSHORT *x, *y; enum machine_mode mode; @@ -5860,7 +5937,7 @@ toibm (x, y, mode) #ifdef C4X /* Convert C4X single/double precision to e type. */ -static void +static void c4xtoe (d, e, mode) unsigned EMUSHORT *d; unsigned EMUSHORT *e; @@ -5868,7 +5945,6 @@ c4xtoe (d, e, mode) { unsigned EMUSHORT y[NI]; int r; - int rndsav; int isnegative; int size; int i; @@ -5899,7 +5975,7 @@ c4xtoe (d, e, mode) { isnegative = FALSE; } - + r >>= 8; /* Shift exponent word down 8 bits. */ if (r & 0x80) /* Make the exponent negative if it is. */ { @@ -5911,7 +5987,7 @@ c4xtoe (d, e, mode) /* Now do the high order mantissa. We don't "or" on the high bit because it is 2 (not 1) and is handled a little differently below. */ - y[M] = d[0] & 0x7f; + y[M] = d[0] & 0x7f; y[M+1] = d[1]; if (mode != QFmode) /* There are only 2 words in QFmode. */ @@ -5956,11 +6032,11 @@ c4xtoe (d, e, mode) { /* Add our e type exponent offset to form our exponent. */ r += EXONE; - y[1] = r; + y[1] = r; /* Now do the high order mantissa strip off the exponent and sign bits and add the high 1 bit. */ - y[M] = d[0] & 0x7f | 0x80; + y[M] = (d[0] & 0x7f) | 0x80; y[M+1] = d[1]; if (mode != QFmode) /* There are only 2 words in QFmode. */ @@ -5977,7 +6053,7 @@ c4xtoe (d, e, mode) /* Convert e type to C4X single/double precision. */ -static void +static void etoc4x (x, d, mode) unsigned EMUSHORT *x, *d; enum machine_mode mode; @@ -5999,16 +6075,15 @@ etoc4x (x, d, mode) toc4x (xi, d, mode); } -static void +static void toc4x (x, y, mode) unsigned EMUSHORT *x, *y; enum machine_mode mode; { int i; - int r; int v; int carry; - + /* Short-circuit the zero case */ if ((x[0] == 0) /* Zero exponent and sign */ && (x[1] == 0) @@ -6027,17 +6102,17 @@ toc4x (x, y, mode) } return; } - + *y = 0; - + /* Negative number require a two's complement conversion of the mantissa. */ if (x[0]) { *y = 0x0080; - + i = ((int) x[1]) - 0x7f; - + /* Now add 1 to the inverted data to do the two's complement. */ if (mode != QFmode) v = 4 + M; @@ -6057,7 +6132,7 @@ toc4x (x, y, mode) } v--; } - + /* The following is a special case. The C4X negative float requires a zero in the high bit (because the format is (2 - x) x 2^m), so if a one is in that bit, we have to shift left one to get rid @@ -6089,11 +6164,11 @@ toc4x (x, y, mode) #endif return; } - + y[0] |= ((i & 0xff) << 8); - + eshift (x, 8); - + y[0] |= x[M] & 0x7f; y[1] = x[M + 1]; if (mode != QFmode) @@ -6200,11 +6275,11 @@ make_nan (nan, sign, mode) abort (); } if (REAL_WORDS_BIG_ENDIAN) - *nan++ = (sign << 15) | *p++; + *nan++ = (sign << 15) | (*p++ & 0x7fff); while (--n != 0) *nan++ = *p++; if (! REAL_WORDS_BIG_ENDIAN) - *nan = (sign << 15) | *p; + *nan = (sign << 15) | (*p & 0x7fff); } /* This is the inverse of the function `etarsingle' invoked by @@ -6325,17 +6400,19 @@ ereal_from_double (d) /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces. */ 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]; -#if HOST_BITS_PER_WIDE_INT == 32 s[2] = (unsigned EMUSHORT) (d[1] >> 16); s[3] = (unsigned EMUSHORT) d[1]; #else /* In this case the entire target double is contained in the first array element. The second element of the input is ignored. */ - s[2] = (unsigned EMUSHORT) (d[0] >> 48); - s[3] = (unsigned EMUSHORT) (d[0] >> 32); + 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 @@ -6442,7 +6519,7 @@ ditoe (di, e) /* Convert e-type to unsigned 64-bit int. */ -static void +static void etoudi (x, i) unsigned EMUSHORT *x; unsigned EMUSHORT *i; @@ -6525,7 +6602,7 @@ noshift: /* Convert e-type to signed 64-bit int. */ -static void +static void etodi (x, i) unsigned EMUSHORT *x; unsigned EMUSHORT *i; @@ -6627,7 +6704,7 @@ etodi (x, i) static int esqinited = 0; static unsigned short sqrndbit[NI]; -static void +static void esqrt (x, y) unsigned EMUSHORT *x, *y; { @@ -6748,7 +6825,7 @@ significand_size (mode) switch (GET_MODE_BITSIZE (mode)) { case 32: - + #if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT return 56; #endif |