X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gcc%2Freal.c;fp=gcc%2Freal.c;h=d4a3941e67e59fbef153e2699ccddb34b2437f2a;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=1dcd5492344b069d4dcbf3bdb1a126c8a3e71e6a;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/real.c b/gcc/real.c index 1dcd5492..d4a3941e 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -1,7000 +1,4941 @@ -/* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF, - and support for XFmode IEEE extended real floating point arithmetic. - Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2002 Free Software Foundation, Inc. +/* real.c - software floating point emulation. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002, + 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Stephen L. Moshier (moshier@world.std.com). + Re-written by Richard Henderson -This file is part of GCC. + This file is part of GCC. -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version. + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3, or (at your option) any later + version. -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" #include "toplev.h" +#include "real.h" #include "tm_p.h" - -/* To enable support of XFmode extended real floating point, define -LONG_DOUBLE_TYPE_SIZE 96 in the tm.h file (m68k.h or i386.h). - -To support cross compilation between IEEE, VAX and IBM floating -point formats, define REAL_ARITHMETIC in the tm.h file. - -In either case the machine files (tm.h) must not contain any code -that tries to use host floating point arithmetic to convert -REAL_VALUE_TYPEs from `double' to `float', pass them to fprintf, -etc. In cross-compile situations a REAL_VALUE_TYPE may not -be intelligible to the host computer's native arithmetic. - -The emulator defaults to the host's floating point format so that -its decimal conversion functions can be used if desired (see -real.h). - -The first part of this file interfaces gcc to a floating point -arithmetic suite that was not written with gcc in mind. Avoid -changing the low-level arithmetic routines unless you have suitable -test programs available. A special version of the PARANOIA floating -point arithmetic tester, modified for this purpose, can be found on -usc.edu: /pub/C-numanal/ieeetest.zoo. Other tests, and libraries of -XFmode and TFmode transcendental functions, can be obtained by ftp from -netlib.att.com: netlib/cephes. */ - -/* Type of computer arithmetic. - Only one of DEC, IBM, IEEE, C4X, or UNK should get defined. - - `IEEE', when REAL_WORDS_BIG_ENDIAN is non-zero, refers generically - to big-endian IEEE floating-point data structure. This definition - should work in SFmode `float' type and DFmode `double' type on - virtually all big-endian IEEE machines. If LONG_DOUBLE_TYPE_SIZE - has been defined to be 96, then IEEE also invokes the particular - XFmode (`long double' type) data structure used by the Motorola - 680x0 series processors. - - `IEEE', when REAL_WORDS_BIG_ENDIAN is zero, refers generally to - little-endian IEEE machines. In this case, if LONG_DOUBLE_TYPE_SIZE - has been defined to be 96, then IEEE also invokes the particular - XFmode `long double' data structure used by the Intel 80x86 series - processors. - - `DEC' refers specifically to the Digital Equipment Corp PDP-11 - and VAX floating point data structure. This model currently - supports no type wider than DFmode. - - `IBM' refers specifically to the IBM System/370 and compatible - floating point data structure. This model currently supports - no type wider than DFmode. The IBM conversions were contributed by - frank@atom.ansto.gov.au (Frank Crawford). - - `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. 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. - - The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support - and may deactivate XFmode since `long double' is used to refer - to both modes. Defining INTEL_EXTENDED_IEEE_FORMAT to non-zero - at the same time enables 80387-style 80-bit floats in a 128-bit - padded image, as seen on IA-64. - - The macros FLOAT_WORDS_BIG_ENDIAN, HOST_FLOAT_WORDS_BIG_ENDIAN, - contributed by Richard Earnshaw , - separate the floating point unit's endian-ness from that of - the integer addressing. This permits one to define a big-endian - FPU on a little-endian machine (e.g., ARM). An extension to - BYTES_BIG_ENDIAN may be required for some machines in the future. - These optional macros may be defined in tm.h. In real.h, they - default to WORDS_BIG_ENDIAN, etc., so there is no need to define - them for any normal host or target machine on which the floats - and the integers have the same endian-ness. */ - - -/* The following converts gcc macros into the ones used by this file. */ - -/* REAL_ARITHMETIC defined means that macros in real.h are - defined to call emulator functions. */ -#ifdef REAL_ARITHMETIC - -#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT -/* PDP-11, Pro350, VAX: */ -#define DEC 1 -#else /* it's not VAX */ -#if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT -/* IBM System/370 style */ -#define IBM 1 -#else /* it's also not an IBM */ -#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT -/* TMS320C3x/C4x style */ -#define C4X 1 -#else /* it's also not a C4X */ -#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT -#define IEEE -#else /* it's not IEEE either */ -/* UNKnown arithmetic. We don't support this and can't go on. */ -unknown arithmetic type -#define UNK 1 -#endif /* not IEEE */ -#endif /* not C4X */ -#endif /* not IBM */ -#endif /* not VAX */ - -#define REAL_WORDS_BIG_ENDIAN FLOAT_WORDS_BIG_ENDIAN - -#else -/* REAL_ARITHMETIC not defined means that the *host's* data - structure will be used. It may differ by endian-ness from the - target machine's structure and will get its ends swapped - accordingly (but not here). Probably only the decimal <-> binary - functions in this file will actually be used in this case. */ - -#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT -#define DEC 1 -#else /* it's not VAX */ -#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT -/* IBM System/370 style */ -#define IBM 1 -#else /* it's also not an IBM */ -#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT -#define IEEE -#else /* it's not IEEE either */ -unknown arithmetic type -#define UNK 1 -#endif /* not IEEE */ -#endif /* not IBM */ -#endif /* not VAX */ - -#define REAL_WORDS_BIG_ENDIAN HOST_FLOAT_WORDS_BIG_ENDIAN - -#endif /* REAL_ARITHMETIC not defined */ - -/* Define INFINITY for support of infinity. - Define NANS for support of Not-a-Number's (NaN's). */ -#if !defined(DEC) && !defined(IBM) && !defined(C4X) -#define INFINITY -#define NANS -#endif - -/* Support of NaNs requires support of infinity. */ -#ifdef NANS -#ifndef INFINITY -#define INFINITY -#endif -#endif +#include "dfp.h" + +/* The floating point model used internally is not exactly IEEE 754 + compliant, and close to the description in the ISO C99 standard, + section 5.2.4.2.2 Characteristics of floating types. + + Specifically + + x = s * b^e * \sum_{k=1}^p f_k * b^{-k} + + where + s = sign (+- 1) + b = base or radix, here always 2 + e = exponent + p = precision (the number of base-b digits in the significand) + f_k = the digits of the significand. + + We differ from typical IEEE 754 encodings in that the entire + significand is fractional. Normalized significands are in the + range [0.5, 1.0). + + A requirement of the model is that P be larger than the largest + supported target floating-point type by at least 2 bits. This gives + us proper rounding when we truncate to the target type. In addition, + E must be large enough to hold the smallest supported denormal number + in a normalized form. + + Both of these requirements are easily satisfied. The largest target + significand is 113 bits; we store at least 160. The smallest + denormal number fits in 17 exponent bits; we store 27. + + Note that the decimal string conversion routines are sensitive to + rounding errors. Since the raw arithmetic routines do not themselves + have guard digits or rounding, the computation of 10**exp can + accumulate more than a few digits of error. The previous incarnation + of real.c successfully used a 144-bit fraction; given the current + layout of REAL_VALUE_TYPE we're forced to expand to at least 160 bits. */ + + +/* Used to classify two numbers simultaneously. */ +#define CLASS2(A, B) ((A) << 2 | (B)) + +#if HOST_BITS_PER_LONG != 64 && HOST_BITS_PER_LONG != 32 + #error "Some constant folding done by hand to avoid shift count warnings" +#endif + +static void get_zero (REAL_VALUE_TYPE *, int); +static void get_canonical_qnan (REAL_VALUE_TYPE *, int); +static void get_canonical_snan (REAL_VALUE_TYPE *, int); +static void get_inf (REAL_VALUE_TYPE *, int); +static bool sticky_rshift_significand (REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *, unsigned int); +static void rshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, + unsigned int); +static void lshift_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, + unsigned int); +static void lshift_significand_1 (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); +static bool add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *); +static bool sub_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *, int); +static void neg_significand (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); +static int cmp_significands (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); +static int cmp_significand_0 (const REAL_VALUE_TYPE *); +static void set_significand_bit (REAL_VALUE_TYPE *, unsigned int); +static void clear_significand_bit (REAL_VALUE_TYPE *, unsigned int); +static bool test_significand_bit (REAL_VALUE_TYPE *, unsigned int); +static void clear_significand_below (REAL_VALUE_TYPE *, unsigned int); +static bool div_significands (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *); +static void normalize (REAL_VALUE_TYPE *); + +static bool do_add (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *, int); +static bool do_multiply (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *); +static bool do_divide (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, + const REAL_VALUE_TYPE *); +static int do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int); +static void do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); + +static unsigned long rtd_divmod (REAL_VALUE_TYPE *, REAL_VALUE_TYPE *); +static void decimal_from_integer (REAL_VALUE_TYPE *); +static void decimal_integer_string (char *, const REAL_VALUE_TYPE *, + size_t); + +static const REAL_VALUE_TYPE * ten_to_ptwo (int); +static const REAL_VALUE_TYPE * ten_to_mptwo (int); +static const REAL_VALUE_TYPE * real_digit (int); +static void times_pten (REAL_VALUE_TYPE *, int); + +static void round_for_format (const struct real_format *, REAL_VALUE_TYPE *); -/* Find a host integer type that is at least 16 bits wide, - and another type at least twice whatever that size is. */ - -#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 -/* You will have to modify this program to have a smaller unit size. */ -#define EMU_NON_COMPILE -#endif -#endif -#endif -#endif - -/* If no 16-bit type has been found and the compiler is GCC, try HImode. */ -#if defined(__GNUC__) && EMUSHORT_SIZE != 16 -typedef int HItype __attribute__ ((mode (HI))); -typedef unsigned int UHItype __attribute__ ((mode (HI))); -#undef EMUSHORT -#undef EMUSHORT_SIZE -#undef EMULONG_SIZE -#define EMUSHORT HItype -#define UEMUSHORT UHItype -#define EMUSHORT_SIZE 16 -#define EMULONG_SIZE 32 -#else -#define UEMUSHORT unsigned EMUSHORT -#endif +/* Initialize R with a positive zero. */ -#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 -/* You will have to modify this program to have a smaller unit size. */ -#define EMU_NON_COMPILE -#endif -#endif -#endif -#endif +static inline void +get_zero (REAL_VALUE_TYPE *r, int sign) +{ + memset (r, 0, sizeof (*r)); + r->sign = sign; +} +/* Initialize R with the canonical quiet NaN. */ -/* The host interface doesn't work if no 16-bit size exists. */ -#if EMUSHORT_SIZE != 16 -#define EMU_NON_COMPILE -#endif +static inline void +get_canonical_qnan (REAL_VALUE_TYPE *r, int sign) +{ + memset (r, 0, sizeof (*r)); + r->cl = rvc_nan; + r->sign = sign; + r->canonical = 1; +} -/* OK to continue compilation. */ -#ifndef EMU_NON_COMPILE - -/* Construct macros to translate between REAL_VALUE_TYPE and e type. - In GET_REAL and PUT_REAL, r and e are pointers. - A REAL_VALUE_TYPE is guaranteed to occupy contiguous locations - in memory, with no holes. */ - -#if MAX_LONG_DOUBLE_TYPE_SIZE == 96 || \ - ((INTEL_EXTENDED_IEEE_FORMAT != 0) && MAX_LONG_DOUBLE_TYPE_SIZE == 128) -/* Number of 16 bit words in external e type format */ -# define NE 6 -# define MAXDECEXP 4932 -# define MINDECEXP -4956 -# define GET_REAL(r,e) memcpy ((e), (r), 2*NE) -# define PUT_REAL(e,r) \ - do { \ - memcpy ((r), (e), 2*NE); \ - if (2*NE < sizeof (*r)) \ - memset ((char *) (r) + 2*NE, 0, sizeof (*r) - 2*NE); \ - } while (0) -# else /* no XFmode */ -# if MAX_LONG_DOUBLE_TYPE_SIZE == 128 -# define NE 10 -# define MAXDECEXP 4932 -# define MINDECEXP -4977 -# define GET_REAL(r,e) memcpy ((e), (r), 2*NE) -# define PUT_REAL(e,r) \ - do { \ - memcpy ((r), (e), 2*NE); \ - if (2*NE < sizeof (*r)) \ - memset ((char *) (r) + 2*NE, 0, sizeof (*r) - 2*NE); \ - } while (0) -#else -#define NE 6 -#define MAXDECEXP 4932 -#define MINDECEXP -4956 -#ifdef REAL_ARITHMETIC -/* 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 ((const UEMUSHORT *) (r), (e)); \ - else \ - { \ - UEMUSHORT w[4]; \ - memcpy (&w[3], ((const EMUSHORT *) r), sizeof (EMUSHORT)); \ - memcpy (&w[2], ((const EMUSHORT *) r) + 1, sizeof (EMUSHORT)); \ - memcpy (&w[1], ((const EMUSHORT *) r) + 2, sizeof (EMUSHORT)); \ - memcpy (&w[0], ((const EMUSHORT *) r) + 3, 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), (UEMUSHORT *) (r)); \ - else \ - { \ - UEMUSHORT w[4]; \ - etoe53 ((e), w); \ - memcpy (((EMUSHORT *) r), &w[3], sizeof (EMUSHORT)); \ - memcpy (((EMUSHORT *) r) + 1, &w[2], sizeof (EMUSHORT)); \ - memcpy (((EMUSHORT *) r) + 2, &w[1], sizeof (EMUSHORT)); \ - memcpy (((EMUSHORT *) r) + 3, &w[0], sizeof (EMUSHORT)); \ - } \ - } while (0) - -#else /* not REAL_ARITHMETIC */ - -/* emulator uses host format */ -#define GET_REAL(r,e) e53toe ((const UEMUSHORT *) (r), (e)) -#define PUT_REAL(e,r) etoe53 ((e), (UEMUSHORT *) (r)) - -#endif /* not REAL_ARITHMETIC */ -#endif /* not TFmode */ -#endif /* not XFmode */ - - -/* Number of 16 bit words in internal format */ -#define NI (NE+3) - -/* Array offset to exponent */ -#define E 1 - -/* Array offset to high guard word */ -#define M 2 - -/* Number of bits of precision */ -#define NBITS ((NI-4)*16) - -/* Maximum number of decimal digits in ASCII conversion - * = NBITS*log10(2) - */ -#define NDEC (NBITS*8/27) - -/* The exponent of 1.0 */ -#define EXONE (0x3fff) - -#if defined(HOST_EBCDIC) -/* bit 8 is significant in EBCDIC */ -#define CHARMASK 0xff -#else -#define CHARMASK 0x7f -#endif +static inline void +get_canonical_snan (REAL_VALUE_TYPE *r, int sign) +{ + memset (r, 0, sizeof (*r)); + r->cl = rvc_nan; + r->sign = sign; + r->signalling = 1; + r->canonical = 1; +} -extern int extra_warnings; -extern const UEMUSHORT ezero[NE], ehalf[NE], eone[NE], etwo[NE]; -extern const UEMUSHORT elog2[NE], esqrt2[NE]; +static inline void +get_inf (REAL_VALUE_TYPE *r, int sign) +{ + memset (r, 0, sizeof (*r)); + r->cl = rvc_inf; + r->sign = sign; +} -static void endian PARAMS ((const UEMUSHORT *, long *, - enum machine_mode)); -static void eclear PARAMS ((UEMUSHORT *)); -static void emov PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -#if 0 -static void eabs PARAMS ((UEMUSHORT *)); -#endif -static void eneg PARAMS ((UEMUSHORT *)); -static int eisneg PARAMS ((const UEMUSHORT *)); -static int eisinf PARAMS ((const UEMUSHORT *)); -static int eisnan PARAMS ((const UEMUSHORT *)); -static void einfin PARAMS ((UEMUSHORT *)); -#ifdef NANS -static void enan PARAMS ((UEMUSHORT *, int)); -static void einan PARAMS ((UEMUSHORT *)); -static int eiisnan PARAMS ((const UEMUSHORT *)); -static int eiisneg PARAMS ((const UEMUSHORT *)); -static void make_nan PARAMS ((UEMUSHORT *, int, enum machine_mode)); -#endif -static void emovi PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void emovo PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void ecleaz PARAMS ((UEMUSHORT *)); -static void ecleazs PARAMS ((UEMUSHORT *)); -static void emovz PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -#if 0 -static void eiinfin PARAMS ((UEMUSHORT *)); -#endif -#ifdef INFINITY -static int eiisinf PARAMS ((const UEMUSHORT *)); -#endif -static int ecmpm PARAMS ((const UEMUSHORT *, const UEMUSHORT *)); -static void eshdn1 PARAMS ((UEMUSHORT *)); -static void eshup1 PARAMS ((UEMUSHORT *)); -static void eshdn8 PARAMS ((UEMUSHORT *)); -static void eshup8 PARAMS ((UEMUSHORT *)); -static void eshup6 PARAMS ((UEMUSHORT *)); -static void eshdn6 PARAMS ((UEMUSHORT *)); -static void eaddm PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void esubm PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void m16m PARAMS ((unsigned int, const UEMUSHORT *, UEMUSHORT *)); -static int edivm PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static int emulm PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void emdnorm PARAMS ((UEMUSHORT *, int, int, EMULONG, int)); -static void esub PARAMS ((const UEMUSHORT *, const UEMUSHORT *, - UEMUSHORT *)); -static void eadd PARAMS ((const UEMUSHORT *, const UEMUSHORT *, - UEMUSHORT *)); -static void eadd1 PARAMS ((const UEMUSHORT *, const UEMUSHORT *, - UEMUSHORT *)); -static void ediv PARAMS ((const UEMUSHORT *, const UEMUSHORT *, - UEMUSHORT *)); -static void emul PARAMS ((const UEMUSHORT *, const UEMUSHORT *, - UEMUSHORT *)); -static void e53toe PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void e64toe PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) -static void e113toe PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -#endif -static void e24toe PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) -static void etoe113 PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void toe113 PARAMS ((UEMUSHORT *, UEMUSHORT *)); -#endif -static void etoe64 PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void toe64 PARAMS ((UEMUSHORT *, UEMUSHORT *)); -static void etoe53 PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void toe53 PARAMS ((UEMUSHORT *, UEMUSHORT *)); -static void etoe24 PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void toe24 PARAMS ((UEMUSHORT *, UEMUSHORT *)); -static int ecmp PARAMS ((const UEMUSHORT *, const UEMUSHORT *)); -#if 0 -static void eround PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -#endif -static void ltoe PARAMS ((const HOST_WIDE_INT *, UEMUSHORT *)); -static void ultoe PARAMS ((const unsigned HOST_WIDE_INT *, UEMUSHORT *)); -static void eifrac PARAMS ((const UEMUSHORT *, HOST_WIDE_INT *, - UEMUSHORT *)); -static void euifrac PARAMS ((const UEMUSHORT *, unsigned HOST_WIDE_INT *, - UEMUSHORT *)); -static int eshift PARAMS ((UEMUSHORT *, int)); -static int enormlz PARAMS ((UEMUSHORT *)); -#if 0 -static void e24toasc PARAMS ((const UEMUSHORT *, char *, int)); -static void e53toasc PARAMS ((const UEMUSHORT *, char *, int)); -static void e64toasc PARAMS ((const UEMUSHORT *, char *, int)); -static void e113toasc PARAMS ((const UEMUSHORT *, char *, int)); -#endif /* 0 */ -static void etoasc PARAMS ((const UEMUSHORT *, char *, int)); -static void asctoe24 PARAMS ((const char *, UEMUSHORT *)); -static void asctoe53 PARAMS ((const char *, UEMUSHORT *)); -static void asctoe64 PARAMS ((const char *, UEMUSHORT *)); -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) -static void asctoe113 PARAMS ((const char *, UEMUSHORT *)); -#endif -static void asctoe PARAMS ((const char *, UEMUSHORT *)); -static void asctoeg PARAMS ((const char *, UEMUSHORT *, int)); -static void efloor PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -#if 0 -static void efrexp PARAMS ((const UEMUSHORT *, int *, - UEMUSHORT *)); -#endif -static void eldexp PARAMS ((const UEMUSHORT *, int, UEMUSHORT *)); -#if 0 -static void eremain PARAMS ((const UEMUSHORT *, const UEMUSHORT *, - UEMUSHORT *)); -#endif -static void eiremain PARAMS ((UEMUSHORT *, UEMUSHORT *)); -static void mtherr PARAMS ((const char *, int)); -#ifdef DEC -static void dectoe PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void etodec PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void todec PARAMS ((UEMUSHORT *, UEMUSHORT *)); -#endif -#ifdef IBM -static void ibmtoe PARAMS ((const UEMUSHORT *, UEMUSHORT *, - enum machine_mode)); -static void etoibm PARAMS ((const UEMUSHORT *, UEMUSHORT *, - enum machine_mode)); -static void toibm PARAMS ((UEMUSHORT *, UEMUSHORT *, - enum machine_mode)); -#endif -#ifdef C4X -static void c4xtoe PARAMS ((const UEMUSHORT *, UEMUSHORT *, - enum machine_mode)); -static void etoc4x PARAMS ((const UEMUSHORT *, UEMUSHORT *, - enum machine_mode)); -static void toc4x PARAMS ((UEMUSHORT *, UEMUSHORT *, - enum machine_mode)); -#endif -#if 0 -static void uditoe PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void ditoe PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void etoudi PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void etodi PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -static void esqrt PARAMS ((const UEMUSHORT *, UEMUSHORT *)); -#endif -/* Copy 32-bit numbers obtained from array containing 16-bit numbers, - swapping ends if required, into output array of longs. The - result is normally passed to fprintf by the ASM_OUTPUT_ macros. */ +/* Right-shift the significand of A by N bits; put the result in the + significand of R. If any one bits are shifted out, return true. */ -static void -endian (e, x, mode) - const UEMUSHORT e[]; - long x[]; - enum machine_mode mode; +static bool +sticky_rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, + unsigned int n) { - unsigned long th, t; + unsigned long sticky = 0; + unsigned int i, ofs = 0; + + if (n >= HOST_BITS_PER_LONG) + { + for (i = 0, ofs = n / HOST_BITS_PER_LONG; i < ofs; ++i) + sticky |= a->sig[i]; + n &= HOST_BITS_PER_LONG - 1; + } - if (REAL_WORDS_BIG_ENDIAN) + if (n != 0) { - switch (mode) + sticky |= a->sig[ofs] & (((unsigned long)1 << n) - 1); + for (i = 0; i < SIGSZ; ++i) { - case TFmode: -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) - /* Swap halfwords in the fourth long. */ - th = (unsigned long) e[6] & 0xffff; - t = (unsigned long) e[7] & 0xffff; - t |= th << 16; - x[3] = (long) t; -#else - x[3] = 0; -#endif - /* FALLTHRU */ - - case XFmode: - /* Swap halfwords in the third long. */ - th = (unsigned long) e[4] & 0xffff; - t = (unsigned long) e[5] & 0xffff; - t |= th << 16; - x[2] = (long) t; - /* FALLTHRU */ - - case DFmode: - /* Swap halfwords in the second word. */ - th = (unsigned long) e[2] & 0xffff; - t = (unsigned long) e[3] & 0xffff; - t |= th << 16; - x[1] = (long) t; - /* FALLTHRU */ - - case SFmode: - case HFmode: - /* Swap halfwords in the first word. */ - th = (unsigned long) e[0] & 0xffff; - t = (unsigned long) e[1] & 0xffff; - t |= th << 16; - x[0] = (long) t; - break; - - default: - abort (); + r->sig[i] + = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n) + | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1]) + << (HOST_BITS_PER_LONG - n))); } } else { - /* Pack the output array without swapping. */ - - switch (mode) - { - case TFmode: -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) - /* Pack the fourth long. */ - th = (unsigned long) e[7] & 0xffff; - t = (unsigned long) e[6] & 0xffff; - t |= th << 16; - x[3] = (long) t; -#else - x[3] = 0; -#endif - /* FALLTHRU */ - - case XFmode: - /* Pack the third long. - Each element of the input REAL_VALUE_TYPE array has 16 useful bits - in it. */ - th = (unsigned long) e[5] & 0xffff; - t = (unsigned long) e[4] & 0xffff; - t |= th << 16; - x[2] = (long) t; - /* FALLTHRU */ - - case DFmode: - /* Pack the second long */ - th = (unsigned long) e[3] & 0xffff; - t = (unsigned long) e[2] & 0xffff; - t |= th << 16; - x[1] = (long) t; - /* FALLTHRU */ - - case SFmode: - case HFmode: - /* Pack the first long */ - th = (unsigned long) e[1] & 0xffff; - t = (unsigned long) e[0] & 0xffff; - t |= th << 16; - x[0] = (long) t; - break; - - default: - abort (); - } + for (i = 0; ofs + i < SIGSZ; ++i) + r->sig[i] = a->sig[ofs + i]; + for (; i < SIGSZ; ++i) + r->sig[i] = 0; } -} + return sticky != 0; +} -/* This is the implementation of the REAL_ARITHMETIC macro. */ +/* Right-shift the significand of A by N bits; put the result in the + significand of R. */ -void -earith (value, icode, r1, r2) - REAL_VALUE_TYPE *value; - int icode; - REAL_VALUE_TYPE *r1; - REAL_VALUE_TYPE *r2; +static void +rshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, + unsigned int n) { - UEMUSHORT d1[NE], d2[NE], v[NE]; - enum tree_code code; - - GET_REAL (r1, d1); - GET_REAL (r2, d2); -#ifdef NANS -/* Return NaN input back to the caller. */ - 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; + unsigned int i, ofs = n / HOST_BITS_PER_LONG; - case MINUS_EXPR: - esub (d2, d1, v); /* d1 - d2 */ - break; - - case MULT_EXPR: - emul (d2, d1, v); - break; - - case RDIV_EXPR: -#ifndef REAL_INFINITY - if (ecmp (d2, ezero) == 0) + n &= HOST_BITS_PER_LONG - 1; + if (n != 0) + { + for (i = 0; i < SIGSZ; ++i) { -#ifdef NANS - enan (v, eisneg (d1) ^ eisneg (d2)); - break; -#else - abort (); -#endif + r->sig[i] + = (((ofs + i >= SIGSZ ? 0 : a->sig[ofs + i]) >> n) + | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[ofs + i + 1]) + << (HOST_BITS_PER_LONG - n))); } -#endif - ediv (d2, d1, v); /* d1/d2 */ - break; - - case MIN_EXPR: /* min (d1,d2) */ - if (ecmp (d1, d2) < 0) - emov (d1, v); - else - emov (d2, v); - break; - - case MAX_EXPR: /* max (d1,d2) */ - if (ecmp (d1, d2) > 0) - emov (d1, v); - else - emov (d2, v); - break; - default: - emov (ezero, v); - break; } -PUT_REAL (v, value); + else + { + for (i = 0; ofs + i < SIGSZ; ++i) + r->sig[i] = a->sig[ofs + i]; + for (; i < SIGSZ; ++i) + r->sig[i] = 0; + } } +/* Left-shift the significand of A by N bits; put the result in the + significand of R. */ -/* Truncate REAL_VALUE_TYPE toward zero to signed HOST_WIDE_INT. - implements REAL_VALUE_RNDZINT (x) (etrunci (x)). */ - -REAL_VALUE_TYPE -etrunci (x) - REAL_VALUE_TYPE x; +static void +lshift_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, + unsigned int n) { - UEMUSHORT f[NE], g[NE]; - REAL_VALUE_TYPE r; - HOST_WIDE_INT l; + unsigned int i, ofs = n / HOST_BITS_PER_LONG; - 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); + n &= HOST_BITS_PER_LONG - 1; + if (n == 0) + { + for (i = 0; ofs + i < SIGSZ; ++i) + r->sig[SIGSZ-1-i] = a->sig[SIGSZ-1-i-ofs]; + for (; i < SIGSZ; ++i) + r->sig[SIGSZ-1-i] = 0; + } + else + for (i = 0; i < SIGSZ; ++i) + { + r->sig[SIGSZ-1-i] + = (((ofs + i >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs]) << n) + | ((ofs + i + 1 >= SIGSZ ? 0 : a->sig[SIGSZ-1-i-ofs-1]) + >> (HOST_BITS_PER_LONG - n))); + } } +/* Likewise, but N is specialized to 1. */ -/* Truncate REAL_VALUE_TYPE toward zero to unsigned HOST_WIDE_INT; - implements REAL_VALUE_UNSIGNED_RNDZINT (x) (etruncui (x)). */ - -REAL_VALUE_TYPE -etruncui (x) - REAL_VALUE_TYPE x; +static inline void +lshift_significand_1 (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) { - UEMUSHORT f[NE], g[NE]; - REAL_VALUE_TYPE r; - unsigned HOST_WIDE_INT l; + unsigned int i; - 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); + for (i = SIGSZ - 1; i > 0; --i) + r->sig[i] = (a->sig[i] << 1) | (a->sig[i-1] >> (HOST_BITS_PER_LONG - 1)); + r->sig[0] = a->sig[0] << 1; } +/* Add the significands of A and B, placing the result in R. Return + true if there was carry out of the most significant word. */ -/* 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 -ereal_atof (s, t) - const char *s; - enum machine_mode t; +static inline bool +add_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, + const REAL_VALUE_TYPE *b) { - UEMUSHORT tem[NE], e[NE]; - REAL_VALUE_TYPE r; + bool carry = false; + int i; - switch (t) + for (i = 0; i < SIGSZ; ++i) { -#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 TFmode: -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) - asctoe113 (s, tem); - e113toe (tem, e); - break; -#endif - /* FALLTHRU */ + unsigned long ai = a->sig[i]; + unsigned long ri = ai + b->sig[i]; - case XFmode: - asctoe64 (s, tem); - e64toe (tem, e); - break; + if (carry) + { + carry = ri < ai; + carry |= ++ri == 0; + } + else + carry = ri < ai; - default: - asctoe (s, e); + r->sig[i] = ri; } - PUT_REAL (e, &r); - return (r); -} - - -/* Expansion of REAL_NEGATE. */ - -REAL_VALUE_TYPE -ereal_negate (x) - REAL_VALUE_TYPE x; -{ - UEMUSHORT e[NE]; - REAL_VALUE_TYPE r; - GET_REAL (&x, e); - eneg (e); - PUT_REAL (e, &r); - return (r); + return carry; } +/* Subtract the significands of A and B, placing the result in R. CARRY is + true if there's a borrow incoming to the least significant word. + Return true if there was borrow out of the most significant word. */ -/* Round real toward zero to HOST_WIDE_INT; - implements REAL_VALUE_FIX (x). */ - -HOST_WIDE_INT -efixi (x) - REAL_VALUE_TYPE x; +static inline bool +sub_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, + const REAL_VALUE_TYPE *b, int carry) { - UEMUSHORT f[NE], g[NE]; - HOST_WIDE_INT l; + int i; - GET_REAL (&x, f); -#ifdef NANS - if (eisnan (f)) + for (i = 0; i < SIGSZ; ++i) { - warning ("conversion from NaN to int"); - return (-1); - } -#endif - eifrac (f, &l, g); - return l; -} - -/* Round real toward zero to unsigned HOST_WIDE_INT - implements REAL_VALUE_UNSIGNED_FIX (x). - Negative input returns zero. */ + unsigned long ai = a->sig[i]; + unsigned long ri = ai - b->sig[i]; -unsigned HOST_WIDE_INT -efixui (x) - REAL_VALUE_TYPE x; -{ - UEMUSHORT f[NE], g[NE]; - unsigned HOST_WIDE_INT l; + if (carry) + { + carry = ri > ai; + carry |= ~--ri == 0; + } + else + carry = ri > ai; - GET_REAL (&x, f); -#ifdef NANS - if (eisnan (f)) - { - warning ("conversion from NaN to unsigned int"); - return (-1); + r->sig[i] = ri; } -#endif - euifrac (f, &l, g); - return l; -} + return carry; +} -/* REAL_VALUE_FROM_INT macro. */ +/* Negate the significand A, placing the result in R. */ -void -ereal_from_int (d, i, j, mode) - REAL_VALUE_TYPE *d; - HOST_WIDE_INT i, j; - enum machine_mode mode; +static inline void +neg_significand (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) { - UEMUSHORT df[NE], dg[NE]; - HOST_WIDE_INT low, high; - int sign; + bool carry = true; + int i; - if (GET_MODE_CLASS (mode) != MODE_FLOAT) - abort (); - sign = 0; - low = i; - if ((high = j) < 0) + for (i = 0; i < SIGSZ; ++i) { - sign = 1; - /* complement and add 1 */ - high = ~high; - if (low) - low = -low; + unsigned long ri, ai = a->sig[i]; + + if (carry) + { + if (ai) + { + ri = -ai; + carry = false; + } + else + ri = ai; + } 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); + ri = ~ai; - /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS. - Avoid double-rounding errors later by rounding off now from the - extra-wide internal format to the requested precision. */ - switch (GET_MODE_BITSIZE (mode)) - { - case 32: - etoe24 (dg, df); - e24toe (df, dg); - break; + r->sig[i] = ri; + } +} - case 64: - etoe53 (dg, df); - e53toe (df, dg); - break; +/* Compare significands. Return tri-state vs zero. */ - case 96: - etoe64 (dg, df); - e64toe (df, dg); - break; +static inline int +cmp_significands (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b) +{ + int i; - case 128: -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) - etoe113 (dg, df); - e113toe (df, dg); -#else - etoe64 (dg, df); - e64toe (df, dg); -#endif - break; + for (i = SIGSZ - 1; i >= 0; --i) + { + unsigned long ai = a->sig[i]; + unsigned long bi = b->sig[i]; - default: - abort (); - } + if (ai > bi) + return 1; + if (ai < bi) + return -1; + } - PUT_REAL (dg, d); + return 0; } +/* Return true if A is nonzero. */ -/* REAL_VALUE_FROM_UNSIGNED_INT macro. */ - -void -ereal_from_uint (d, i, j, mode) - REAL_VALUE_TYPE *d; - unsigned HOST_WIDE_INT i, j; - enum machine_mode mode; +static inline int +cmp_significand_0 (const REAL_VALUE_TYPE *a) { - UEMUSHORT 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); - - /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS. - Avoid double-rounding errors later by rounding off now from the - extra-wide internal format to the requested precision. */ - switch (GET_MODE_BITSIZE (mode)) - { - case 32: - etoe24 (dg, df); - e24toe (df, dg); - break; - - case 64: - etoe53 (dg, df); - e53toe (df, dg); - break; - - case 96: - etoe64 (dg, df); - e64toe (df, dg); - break; - - case 128: -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) - etoe113 (dg, df); - e113toe (df, dg); -#else - etoe64 (dg, df); - e64toe (df, dg); -#endif - break; + int i; - default: - abort (); - } + for (i = SIGSZ - 1; i >= 0; --i) + if (a->sig[i]) + return 1; - PUT_REAL (dg, d); + return 0; } +/* Set bit N of the significand of R. */ -/* REAL_VALUE_TO_INT macro. */ - -void -ereal_to_int (low, high, rr) - HOST_WIDE_INT *low, *high; - REAL_VALUE_TYPE rr; +static inline void +set_significand_bit (REAL_VALUE_TYPE *r, unsigned int n) { - UEMUSHORT 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 - /* convert positive value */ - s = 0; - if (eisneg (d)) - { - eneg (d); - s = 1; - } - eldexp (eone, HOST_BITS_PER_WIDE_INT, df); - ediv (df, d, dg); /* dg = d / 2^32 is the high word */ - euifrac (dg, (unsigned HOST_WIDE_INT *) high, dh); - emul (df, dh, dg); /* fractional part is the low word */ - euifrac (dg, (unsigned HOST_WIDE_INT *) low, dh); - if (s) - { - /* complement and add 1 */ - *high = ~(*high); - if (*low) - *low = -(*low); - else - *high += 1; - } + r->sig[n / HOST_BITS_PER_LONG] + |= (unsigned long)1 << (n % HOST_BITS_PER_LONG); } +/* Clear bit N of the significand of R. */ -/* REAL_VALUE_LDEXP macro. */ - -REAL_VALUE_TYPE -ereal_ldexp (x, n) - REAL_VALUE_TYPE x; - int n; +static inline void +clear_significand_bit (REAL_VALUE_TYPE *r, unsigned int n) { - UEMUSHORT 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); + r->sig[n / HOST_BITS_PER_LONG] + &= ~((unsigned long)1 << (n % HOST_BITS_PER_LONG)); } -/* These routines are conditionally compiled because functions - of the same names may be defined in fold-const.c. */ +/* Test bit N of the significand of R. */ -#ifdef REAL_ARITHMETIC +static inline bool +test_significand_bit (REAL_VALUE_TYPE *r, unsigned int n) +{ + /* ??? Compiler bug here if we return this expression directly. + The conversion to bool strips the "&1" and we wind up testing + e.g. 2 != 0 -> true. Seen in gcc version 3.2 20020520. */ + int t = (r->sig[n / HOST_BITS_PER_LONG] >> (n % HOST_BITS_PER_LONG)) & 1; + return t; +} -/* Check for infinity in a REAL_VALUE_TYPE. */ +/* Clear bits 0..N-1 of the significand of R. */ -int -target_isinf (x) - REAL_VALUE_TYPE x ATTRIBUTE_UNUSED; +static void +clear_significand_below (REAL_VALUE_TYPE *r, unsigned int n) { -#ifdef INFINITY - UEMUSHORT e[NE]; + int i, w = n / HOST_BITS_PER_LONG; - GET_REAL (&x, e); - return (eisinf (e)); -#else - return 0; -#endif + for (i = 0; i < w; ++i) + r->sig[i] = 0; + + r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1); } -/* Check whether a REAL_VALUE_TYPE item is a NaN. */ +/* Divide the significands of A and B, placing the result in R. Return + true if the division was inexact. */ -int -target_isnan (x) - REAL_VALUE_TYPE x ATTRIBUTE_UNUSED; +static inline bool +div_significands (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, + const REAL_VALUE_TYPE *b) { -#ifdef NANS - UEMUSHORT e[NE]; + REAL_VALUE_TYPE u; + int i, bit = SIGNIFICAND_BITS - 1; + unsigned long msb, inexact; - GET_REAL (&x, e); - return (eisnan (e)); -#else - return (0); -#endif -} + u = *a; + memset (r->sig, 0, sizeof (r->sig)); + msb = 0; + goto start; + do + { + msb = u.sig[SIGSZ-1] & SIG_MSB; + lshift_significand_1 (&u, &u); + start: + if (msb || cmp_significands (&u, b) >= 0) + { + sub_significands (&u, &u, b, 0); + set_significand_bit (r, bit); + } + } + while (--bit >= 0); -/* Check for a negative REAL_VALUE_TYPE number. - This just checks the sign bit, so that -0 counts as negative. */ + for (i = 0, inexact = 0; i < SIGSZ; i++) + inexact |= u.sig[i]; -int -target_negative (x) - REAL_VALUE_TYPE x; -{ - return ereal_isneg (x); + return inexact != 0; } -/* Expansion of REAL_VALUE_TRUNCATE. - The result is in floating point, rounded to nearest or even. */ +/* Adjust the exponent and significand of R such that the most + significant bit is set. We underflow to zero and overflow to + infinity here, without denormals. (The intermediate representation + exponent is large enough to handle target denormals normalized.) */ -REAL_VALUE_TYPE -real_value_truncate (mode, arg) - enum machine_mode mode; - REAL_VALUE_TYPE arg; +static void +normalize (REAL_VALUE_TYPE *r) { - UEMUSHORT 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: -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) - etoe113 (e, t); - e113toe (t, t); - break; -#endif - /* FALLTHRU */ + int shift = 0, exp; + int i, j; - case XFmode: - etoe64 (e, t); - e64toe (t, t); - break; + if (r->decimal) + return; - case DFmode: - etoe53 (e, t); - e53toe (t, t); + /* Find the first word that is nonzero. */ + for (i = SIGSZ - 1; i >= 0; i--) + if (r->sig[i] == 0) + shift += HOST_BITS_PER_LONG; + else break; - case SFmode: -#ifndef C4X - case HFmode: -#endif - etoe24 (e, t); - e24toe (t, t); - break; + /* Zero significand flushes to zero. */ + if (i < 0) + { + r->cl = rvc_zero; + SET_REAL_EXP (r, 0); + return; + } -#ifdef C4X - case HFmode: - case QFmode: - etoe53 (e, t); - e53toe (t, t); + /* Find the first bit that is nonzero. */ + for (j = 0; ; j++) + if (r->sig[i] & ((unsigned long)1 << (HOST_BITS_PER_LONG - 1 - j))) break; -#endif - - case SImode: - r = etrunci (arg); - return (r); + shift += j; - /* If an unsupported type was requested, presume that - the machine files know something useful to do with - the unmodified value. */ - - default: - return (arg); + if (shift > 0) + { + exp = REAL_EXP (r) - shift; + if (exp > MAX_EXP) + get_inf (r, r->sign); + else if (exp < -MAX_EXP) + get_zero (r, r->sign); + else + { + SET_REAL_EXP (r, exp); + lshift_significand (r, r, shift); + } } - PUT_REAL (t, &r); - return (r); } + +/* Calculate R = A + (SUBTRACT_P ? -B : B). Return true if the + result may be inexact due to a loss of precision. */ + +static bool +do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, + const REAL_VALUE_TYPE *b, int subtract_p) +{ + int dexp, sign, exp; + REAL_VALUE_TYPE t; + bool inexact = false; + + /* Determine if we need to add or subtract. */ + sign = a->sign; + subtract_p = (sign ^ b->sign) ^ subtract_p; + + switch (CLASS2 (a->cl, b->cl)) + { + case CLASS2 (rvc_zero, rvc_zero): + /* -0 + -0 = -0, -0 - +0 = -0; all other cases yield +0. */ + get_zero (r, sign & !subtract_p); + return false; + + case CLASS2 (rvc_zero, rvc_normal): + case CLASS2 (rvc_zero, rvc_inf): + case CLASS2 (rvc_zero, rvc_nan): + /* 0 + ANY = ANY. */ + case CLASS2 (rvc_normal, rvc_nan): + case CLASS2 (rvc_inf, rvc_nan): + case CLASS2 (rvc_nan, rvc_nan): + /* ANY + NaN = NaN. */ + case CLASS2 (rvc_normal, rvc_inf): + /* R + Inf = Inf. */ + *r = *b; + r->sign = sign ^ subtract_p; + return false; + + case CLASS2 (rvc_normal, rvc_zero): + case CLASS2 (rvc_inf, rvc_zero): + case CLASS2 (rvc_nan, rvc_zero): + /* ANY + 0 = ANY. */ + case CLASS2 (rvc_nan, rvc_normal): + case CLASS2 (rvc_nan, rvc_inf): + /* NaN + ANY = NaN. */ + case CLASS2 (rvc_inf, rvc_normal): + /* Inf + R = Inf. */ + *r = *a; + return false; + + case CLASS2 (rvc_inf, rvc_inf): + if (subtract_p) + /* Inf - Inf = NaN. */ + get_canonical_qnan (r, 0); + else + /* Inf + Inf = Inf. */ + *r = *a; + return false; -/* Try to change R into its exact multiplicative inverse in machine mode - MODE. Return nonzero function value if successful. */ - -int -exact_real_inverse (mode, r) - enum machine_mode mode; - REAL_VALUE_TYPE *r; -{ - UEMUSHORT e[NE], einv[NE]; - REAL_VALUE_TYPE rinv; - int i; - - GET_REAL (r, e); - - /* Test for input in range. Don't transform IEEE special values. */ - if (eisinf (e) || eisnan (e) || (ecmp (e, ezero) == 0)) - return 0; + case CLASS2 (rvc_normal, rvc_normal): + break; - /* Test for a power of 2: all significand bits zero except the MSB. - We are assuming the target has binary (or hex) arithmetic. */ - if (e[NE - 2] != 0x8000) - return 0; + default: + gcc_unreachable (); + } - for (i = 0; i < NE - 2; i++) + /* Swap the arguments such that A has the larger exponent. */ + dexp = REAL_EXP (a) - REAL_EXP (b); + if (dexp < 0) { - if (e[i] != 0) - return 0; + const REAL_VALUE_TYPE *t; + t = a, a = b, b = t; + dexp = -dexp; + sign ^= subtract_p; } + exp = REAL_EXP (a); - /* Compute the inverse and truncate it to the required mode. */ - ediv (e, eone, einv); - PUT_REAL (einv, &rinv); - rinv = real_value_truncate (mode, rinv); - -#ifdef CHECK_FLOAT_VALUE - /* This check is not redundant. It may, for example, flush - a supposedly IEEE denormal value to zero. */ - i = 0; - if (CHECK_FLOAT_VALUE (mode, rinv, i)) - return 0; -#endif - GET_REAL (&rinv, einv); + /* If the exponents are not identical, we need to shift the + significand of B down. */ + if (dexp > 0) + { + /* If the exponents are too far apart, the significands + do not overlap, which makes the subtraction a noop. */ + if (dexp >= SIGNIFICAND_BITS) + { + *r = *a; + r->sign = sign; + return true; + } - /* Check the bits again, because the truncation might have - generated an arbitrary saturation value on overflow. */ - if (einv[NE - 2] != 0x8000) - return 0; + inexact |= sticky_rshift_significand (&t, b, dexp); + b = &t; + } - for (i = 0; i < NE - 2; i++) + if (subtract_p) { - if (einv[i] != 0) - return 0; + if (sub_significands (r, a, b, inexact)) + { + /* We got a borrow out of the subtraction. That means that + A and B had the same exponent, and B had the larger + significand. We need to swap the sign and negate the + significand. */ + sign ^= 1; + neg_significand (r, r); + } + } + else + { + if (add_significands (r, a, b)) + { + /* We got carry out of the addition. This means we need to + shift the significand back down one bit and increase the + exponent. */ + inexact |= sticky_rshift_significand (r, r, 1); + r->sig[SIGSZ-1] |= SIG_MSB; + if (++exp > MAX_EXP) + { + get_inf (r, sign); + return true; + } + } } - /* Fail if the computed inverse is out of range. */ - if (eisinf (einv) || eisnan (einv) || (ecmp (einv, ezero) == 0)) - return 0; - - /* Output the reciprocal and return success flag. */ - PUT_REAL (einv, r); - return 1; -} -#endif /* REAL_ARITHMETIC defined */ + r->cl = rvc_normal; + r->sign = sign; + SET_REAL_EXP (r, exp); + /* Zero out the remaining fields. */ + r->signalling = 0; + r->canonical = 0; + r->decimal = 0; -/* Used for debugging--print the value of R in human-readable format - on stderr. */ + /* Re-normalize the result. */ + normalize (r); -void -debug_real (r) - REAL_VALUE_TYPE r; -{ - char dstr[30]; + /* Special case: if the subtraction results in zero, the result + is positive. */ + if (r->cl == rvc_zero) + r->sign = 0; + else + r->sig[0] |= inexact; + + return inexact; +} + +/* Calculate R = A * B. Return true if the result may be inexact. */ + +static bool +do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, + const REAL_VALUE_TYPE *b) +{ + REAL_VALUE_TYPE u, t, *rr; + unsigned int i, j, k; + int sign = a->sign ^ b->sign; + bool inexact = false; + + switch (CLASS2 (a->cl, b->cl)) + { + case CLASS2 (rvc_zero, rvc_zero): + case CLASS2 (rvc_zero, rvc_normal): + case CLASS2 (rvc_normal, rvc_zero): + /* +-0 * ANY = 0 with appropriate sign. */ + get_zero (r, sign); + return false; + + case CLASS2 (rvc_zero, rvc_nan): + case CLASS2 (rvc_normal, rvc_nan): + case CLASS2 (rvc_inf, rvc_nan): + case CLASS2 (rvc_nan, rvc_nan): + /* ANY * NaN = NaN. */ + *r = *b; + r->sign = sign; + return false; + + case CLASS2 (rvc_nan, rvc_zero): + case CLASS2 (rvc_nan, rvc_normal): + case CLASS2 (rvc_nan, rvc_inf): + /* NaN * ANY = NaN. */ + *r = *a; + r->sign = sign; + return false; + + case CLASS2 (rvc_zero, rvc_inf): + case CLASS2 (rvc_inf, rvc_zero): + /* 0 * Inf = NaN */ + get_canonical_qnan (r, sign); + return false; + + case CLASS2 (rvc_inf, rvc_inf): + case CLASS2 (rvc_normal, rvc_inf): + case CLASS2 (rvc_inf, rvc_normal): + /* Inf * Inf = Inf, R * Inf = Inf */ + get_inf (r, sign); + return false; + + case CLASS2 (rvc_normal, rvc_normal): + break; - REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr); - fprintf (stderr, "%s", dstr); -} + default: + gcc_unreachable (); + } - -/* The following routines convert REAL_VALUE_TYPE to the various floating - point formats that are meaningful to supported computers. + if (r == a || r == b) + rr = &t; + else + rr = r; + get_zero (rr, 0); - The results are returned in 32-bit pieces, each piece stored in a `long'. - This is so they can be printed by statements like + /* Collect all the partial products. Since we don't have sure access + to a widening multiply, we split each long into two half-words. - fprintf (file, "%lx, %lx", L[0], L[1]); + Consider the long-hand form of a four half-word multiplication: - that will work on both narrow- and wide-word host computers. */ + A B C D + * E F G H + -------------- + DE DF DG DH + CE CF CG CH + BE BF BG BH + AE AF AG AH -/* Convert R to a 128-bit long double precision value. The output array L - contains four 32-bit pieces of the result, in the order they would appear - in memory. */ + We construct partial products of the widened half-word products + that are known to not overlap, e.g. DF+DH. Each such partial + product is given its proper exponent, which allows us to sum them + and obtain the finished product. */ -void -etartdouble (r, l) - REAL_VALUE_TYPE r; - long l[]; -{ - UEMUSHORT e[NE]; + for (i = 0; i < SIGSZ * 2; ++i) + { + unsigned long ai = a->sig[i / 2]; + if (i & 1) + ai >>= HOST_BITS_PER_LONG / 2; + else + ai &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1; - GET_REAL (&r, e); -#if INTEL_EXTENDED_IEEE_FORMAT == 0 - etoe113 (e, e); -#else - etoe64 (e, e); -#endif - endian (e, l, TFmode); -} + if (ai == 0) + continue; -/* Convert R to a double extended precision value. The output array L - contains three 32-bit pieces of the result, in the order they would - appear in memory. */ + for (j = 0; j < 2; ++j) + { + int exp = (REAL_EXP (a) - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2) + + (REAL_EXP (b) - (1-j)*(HOST_BITS_PER_LONG/2))); -void -etarldouble (r, l) - REAL_VALUE_TYPE r; - long l[]; -{ - UEMUSHORT e[NE]; + if (exp > MAX_EXP) + { + get_inf (r, sign); + return true; + } + if (exp < -MAX_EXP) + { + /* Would underflow to zero, which we shouldn't bother adding. */ + inexact = true; + continue; + } - GET_REAL (&r, e); - etoe64 (e, e); - endian (e, l, XFmode); -} + memset (&u, 0, sizeof (u)); + u.cl = rvc_normal; + SET_REAL_EXP (&u, exp); -/* 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. */ + for (k = j; k < SIGSZ * 2; k += 2) + { + unsigned long bi = b->sig[k / 2]; + if (k & 1) + bi >>= HOST_BITS_PER_LONG / 2; + else + bi &= ((unsigned long)1 << (HOST_BITS_PER_LONG / 2)) - 1; -void -etardouble (r, l) - REAL_VALUE_TYPE r; - long l[]; -{ - UEMUSHORT e[NE]; + u.sig[k / 2] = ai * bi; + } - GET_REAL (&r, e); - etoe53 (e, e); - endian (e, l, DFmode); -} + normalize (&u); + inexact |= do_add (rr, rr, &u, 0); + } + } -/* Convert R to a single precision float value stored in the least-significant - bits of a `long'. */ + rr->sign = sign; + if (rr != r) + *r = t; + + return inexact; +} + +/* Calculate R = A / B. Return true if the result may be inexact. */ + +static bool +do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a, + const REAL_VALUE_TYPE *b) +{ + int exp, sign = a->sign ^ b->sign; + REAL_VALUE_TYPE t, *rr; + bool inexact; + + switch (CLASS2 (a->cl, b->cl)) + { + case CLASS2 (rvc_zero, rvc_zero): + /* 0 / 0 = NaN. */ + case CLASS2 (rvc_inf, rvc_inf): + /* Inf / Inf = NaN. */ + get_canonical_qnan (r, sign); + return false; + + case CLASS2 (rvc_zero, rvc_normal): + case CLASS2 (rvc_zero, rvc_inf): + /* 0 / ANY = 0. */ + case CLASS2 (rvc_normal, rvc_inf): + /* R / Inf = 0. */ + get_zero (r, sign); + return false; + + case CLASS2 (rvc_normal, rvc_zero): + /* R / 0 = Inf. */ + case CLASS2 (rvc_inf, rvc_zero): + /* Inf / 0 = Inf. */ + get_inf (r, sign); + return false; + + case CLASS2 (rvc_zero, rvc_nan): + case CLASS2 (rvc_normal, rvc_nan): + case CLASS2 (rvc_inf, rvc_nan): + case CLASS2 (rvc_nan, rvc_nan): + /* ANY / NaN = NaN. */ + *r = *b; + r->sign = sign; + return false; + + case CLASS2 (rvc_nan, rvc_zero): + case CLASS2 (rvc_nan, rvc_normal): + case CLASS2 (rvc_nan, rvc_inf): + /* NaN / ANY = NaN. */ + *r = *a; + r->sign = sign; + return false; + + case CLASS2 (rvc_inf, rvc_normal): + /* Inf / R = Inf. */ + get_inf (r, sign); + return false; + + case CLASS2 (rvc_normal, rvc_normal): + break; -long -etarsingle (r) - REAL_VALUE_TYPE r; -{ - UEMUSHORT e[NE]; - long l; + default: + gcc_unreachable (); + } - GET_REAL (&r, e); - etoe24 (e, e); - endian (e, &l, SFmode); - return ((long) l); -} + if (r == a || r == b) + rr = &t; + else + rr = r; -/* Convert X to a decimal ASCII string S for output to an assembly - language file. Note, there is no standard way to spell infinity or - a NaN, so these values may require special treatment in the tm.h - macros. */ + /* Make sure all fields in the result are initialized. */ + get_zero (rr, 0); + rr->cl = rvc_normal; + rr->sign = sign; -void -ereal_to_decimal (x, s) - REAL_VALUE_TYPE x; - char *s; -{ - UEMUSHORT e[NE]; + exp = REAL_EXP (a) - REAL_EXP (b) + 1; + if (exp > MAX_EXP) + { + get_inf (r, sign); + return true; + } + if (exp < -MAX_EXP) + { + get_zero (r, sign); + return true; + } + SET_REAL_EXP (rr, exp); - GET_REAL (&x, e); - etoasc (e, s, 20); -} + inexact = div_significands (rr, a, b); -/* Compare X and Y. Return 1 if X > Y, 0 if X == Y, -1 if X < Y, - or -2 if either is a NaN. */ + /* Re-normalize the result. */ + normalize (rr); + rr->sig[0] |= inexact; -int -ereal_cmp (x, y) - REAL_VALUE_TYPE x, y; -{ - UEMUSHORT ex[NE], ey[NE]; + if (rr != r) + *r = t; - GET_REAL (&x, ex); - GET_REAL (&y, ey); - return (ecmp (ex, ey)); + return inexact; } -/* Return 1 if the sign bit of X is set, else return 0. */ - -int -ereal_isneg (x) - REAL_VALUE_TYPE x; -{ - UEMUSHORT ex[NE]; +/* Return a tri-state comparison of A vs B. Return NAN_RESULT if + one of the two operands is a NaN. */ - GET_REAL (&x, ex); - return (eisneg (ex)); -} +static int +do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b, + int nan_result) +{ + int ret; + + switch (CLASS2 (a->cl, b->cl)) + { + case CLASS2 (rvc_zero, rvc_zero): + /* Sign of zero doesn't matter for compares. */ + return 0; + + case CLASS2 (rvc_normal, rvc_zero): + /* Decimal float zero is special and uses rvc_normal, not rvc_zero. */ + if (a->decimal) + return decimal_do_compare (a, b, nan_result); + /* Fall through. */ + case CLASS2 (rvc_inf, rvc_zero): + case CLASS2 (rvc_inf, rvc_normal): + return (a->sign ? -1 : 1); + + case CLASS2 (rvc_inf, rvc_inf): + return -a->sign - -b->sign; + + case CLASS2 (rvc_zero, rvc_normal): + /* Decimal float zero is special and uses rvc_normal, not rvc_zero. */ + if (b->decimal) + return decimal_do_compare (a, b, nan_result); + /* Fall through. */ + case CLASS2 (rvc_zero, rvc_inf): + case CLASS2 (rvc_normal, rvc_inf): + return (b->sign ? 1 : -1); + + case CLASS2 (rvc_zero, rvc_nan): + case CLASS2 (rvc_normal, rvc_nan): + case CLASS2 (rvc_inf, rvc_nan): + case CLASS2 (rvc_nan, rvc_nan): + case CLASS2 (rvc_nan, rvc_zero): + case CLASS2 (rvc_nan, rvc_normal): + case CLASS2 (rvc_nan, rvc_inf): + return nan_result; + + case CLASS2 (rvc_normal, rvc_normal): + break; -/* End of REAL_ARITHMETIC interface */ - -/* - Extended precision IEEE binary floating point arithmetic routines + default: + gcc_unreachable (); + } - Numbers are stored in C language as arrays of 16-bit unsigned - short integers. The arguments of the routines are pointers to - the arrays. + if (a->sign != b->sign) + return -a->sign - -b->sign; - External e type data structure, similar to Intel 8087 chip - temporary real format but possibly with a larger significand: + if (a->decimal || b->decimal) + return decimal_do_compare (a, b, nan_result); - NE-1 significand words (least significant word first, - most significant bit is normally set) - exponent (value = EXONE for 1.0, - top bit is the sign) + if (REAL_EXP (a) > REAL_EXP (b)) + ret = 1; + else if (REAL_EXP (a) < REAL_EXP (b)) + ret = -1; + else + ret = cmp_significands (a, b); + return (a->sign ? -ret : ret); +} - Internal exploded e-type data structure of a number (a "word" is 16 bits): +/* Return A truncated to an integral value toward zero. */ - ei[0] sign word (0 for positive, 0xffff for negative) - ei[1] biased exponent (value = EXONE for the number 1.0) - ei[2] high guard word (always zero after normalization) - ei[3] - to ei[NI-2] significand (NI-4 significand words, - most significant word first, - most significant bit is set) - ei[NI-1] low guard word (0x8000 bit is rounding place) +static void +do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) +{ + *r = *a; + switch (r->cl) + { + case rvc_zero: + case rvc_inf: + case rvc_nan: + break; + case rvc_normal: + if (r->decimal) + { + decimal_do_fix_trunc (r, a); + return; + } + if (REAL_EXP (r) <= 0) + get_zero (r, r->sign); + else if (REAL_EXP (r) < SIGNIFICAND_BITS) + clear_significand_below (r, SIGNIFICAND_BITS - REAL_EXP (r)); + break; - Routines for external format e-type numbers + default: + gcc_unreachable (); + } +} - 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 - asctoe24 (string, &f) ASCII string to single - asctoeg (string, e, prec) ASCII string to specified precision - e24toe (&f, e) IEEE single precision to e type - e53toe (&d, e) IEEE double precision to e type - e64toe (&d, e) IEEE long double precision to e type - e113toe (&d, e) 128-bit long double precision to e type -#if 0 - eabs (e) absolute value -#endif - eadd (a, b, c) c = b + a - eclear (e) e = 0 - ecmp (a, b) Returns 1 if a > b, 0 if a == b, - -1 if a < b, -2 if either a or b is a NaN. - ediv (a, b, c) c = b / a - efloor (a, b) truncate to integer, toward -infinity - efrexp (a, exp, s) extract exponent and significand - eifrac (e, &l, frac) e to HOST_WIDE_INT and e type fraction - euifrac (e, &l, frac) e to unsigned HOST_WIDE_INT and e type fraction - einfin (e) set e to infinity, leaving its sign alone - eldexp (a, n, b) multiply by 2**n - emov (a, b) b = a - emul (a, b, c) c = b * a - eneg (e) e = -e -#if 0 - eround (a, b) b = nearest integer value to a -#endif - esub (a, b, c) c = b - a -#if 0 - e24toasc (&f, str, n) single to ASCII string, n digits after decimal - e53toasc (&d, str, n) double to ASCII string, n digits after decimal - e64toasc (&d, str, n) 80-bit long double to ASCII string - e113toasc (&d, str, n) 128-bit long double to ASCII string -#endif - etoasc (e, str, n) e to ASCII string, n digits after decimal - etoe24 (e, &f) convert e type to IEEE single precision - etoe53 (e, &d) convert e type to IEEE double precision - etoe64 (e, &d) convert e type to IEEE long double precision - ltoe (&l, e) HOST_WIDE_INT to e type - ultoe (&l, e) unsigned HOST_WIDE_INT to e type - eisneg (e) 1 if sign bit of e != 0, else 0 - 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 - ecmpm (ai, bi) compare significands, return 1, 0, or -1 - edivm (ai, bi) divide significands, bi = bi / ai - emdnorm (ai,l,s,exp) normalize and round off - emovi (a, ai) convert external a to internal ai - emovo (ai, a) convert internal ai to external a - emovz (ai, bi) bi = ai, low guard word of bi = 0 - emulm (ai, bi) multiply significands, bi = bi * ai - enormlz (ei) left-justify the significand - eshdn1 (ai) shift significand and guards down 1 bit - eshdn8 (ai) shift down 8 bits - eshdn6 (ai) shift down 16 bits - eshift (ai, n) shift ai n bits up (or down if n < 0) - eshup1 (ai) shift significand and guards up 1 bit - eshup8 (ai) shift up 8 bits - eshup6 (ai) shift up 16 bits - esubm (ai, bi) subtract significands, bi = bi - ai - eiisinf (ai) 1 if infinite - eiisnan (ai) 1 if a NaN - eiisneg (ai) 1 if sign bit of ai != 0, else 0 - einan (ai) set ai = NaN -#if 0 - eiinfin (ai) set ai = infinity -#endif +/* Perform the binary or unary operation described by CODE. + For a unary operation, leave OP1 NULL. This function returns + true if the result may be inexact due to loss of precision. */ - The result is always normalized and rounded to NI-4 word precision - 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. - If NaN's are supported, the output of `ecmp (a,b)' is -2 if - 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). */ - -/* Definitions for error codes that are passed to the common error handling - routine mtherr. - - For Digital Equipment PDP-11 and VAX computers, certain - IBM systems, and others that use numbers with a 56-bit - significand, the symbol DEC should be defined. In this - 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. - These numbers have 53-bit significands. In this mode, constants - 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. */ - -/* Constant definitions for math error conditions. */ - -#define DOMAIN 1 /* argument domain error */ -#define SING 2 /* argument singularity */ -#define OVERFLOW 3 /* overflow range error */ -#define UNDERFLOW 4 /* underflow range error */ -#define TLOSS 5 /* total loss of precision */ -#define PLOSS 6 /* partial loss of precision */ -#define INVALID 7 /* NaN-producing operation */ - -/* e type constants used by high precision check routines */ - -#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && (INTEL_EXTENDED_IEEE_FORMAT == 0) -/* 0.0 */ -const UEMUSHORT ezero[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,}; - -/* 5.0E-1 */ -const UEMUSHORT ehalf[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3ffe,}; - -/* 1.0E0 */ -const UEMUSHORT eone[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff,}; - -/* 2.0E0 */ -const UEMUSHORT etwo[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4000,}; - -/* 3.2E1 */ -const UEMUSHORT e32[NE] = - {0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x4004,}; - -/* 6.93147180559945309417232121458176568075500134360255E-1 */ -const UEMUSHORT elog2[NE] = - {0x40f3, 0xf6af, 0x03f2, 0xb398, - 0xc9e3, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,}; - -/* 1.41421356237309504880168872420969807856967187537695E0 */ -const UEMUSHORT esqrt2[NE] = - {0x1d6f, 0xbe9f, 0x754a, 0x89b3, - 0x597d, 0x6484, 0174736, 0171463, 0132404, 0x3fff,}; - -/* 3.14159265358979323846264338327950288419716939937511E0 */ -const UEMUSHORT epi[NE] = - {0x2902, 0x1cd1, 0x80dc, 0x628b, - 0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,}; - -#else -/* LONG_DOUBLE_TYPE_SIZE is other than 128 */ -const UEMUSHORT ezero[NE] = - {0, 0000000, 0000000, 0000000, 0000000, 0000000,}; -const UEMUSHORT ehalf[NE] = - {0, 0000000, 0000000, 0000000, 0100000, 0x3ffe,}; -const UEMUSHORT eone[NE] = - {0, 0000000, 0000000, 0000000, 0100000, 0x3fff,}; -const UEMUSHORT etwo[NE] = - {0, 0000000, 0000000, 0000000, 0100000, 0040000,}; -const UEMUSHORT e32[NE] = - {0, 0000000, 0000000, 0000000, 0100000, 0040004,}; -const UEMUSHORT elog2[NE] = - {0xc9e4, 0x79ab, 0150717, 0013767, 0130562, 0x3ffe,}; -const UEMUSHORT esqrt2[NE] = - {0x597e, 0x6484, 0174736, 0171463, 0132404, 0x3fff,}; -const UEMUSHORT epi[NE] = - {0xc4c6, 0xc234, 0020550, 0155242, 0144417, 0040000,}; -#endif +bool +real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0, + const REAL_VALUE_TYPE *op1) +{ + enum tree_code code = icode; -/* Control register for rounding precision. - This can be set to 113 (if NE=10), 80 (if NE=6), 64, 56, 53, or 24 bits. */ + if (op0->decimal || (op1 && op1->decimal)) + return decimal_real_arithmetic (r, icode, op0, op1); -int rndprc = NBITS; -extern int rndprc; + switch (code) + { + case PLUS_EXPR: + return do_add (r, op0, op1, 0); -/* Clear out entire e-type number X. */ + case MINUS_EXPR: + return do_add (r, op0, op1, 1); -static void -eclear (x) - UEMUSHORT *x; -{ - int i; + case MULT_EXPR: + return do_multiply (r, op0, op1); - for (i = 0; i < NE; i++) - *x++ = 0; -} + case RDIV_EXPR: + return do_divide (r, op0, op1); -/* Move e-type number from A to B. */ + case MIN_EXPR: + if (op1->cl == rvc_nan) + *r = *op1; + else if (do_compare (op0, op1, -1) < 0) + *r = *op0; + else + *r = *op1; + break; -static void -emov (a, b) - const UEMUSHORT *a; - UEMUSHORT *b; -{ - int i; + case MAX_EXPR: + if (op1->cl == rvc_nan) + *r = *op1; + else if (do_compare (op0, op1, 1) < 0) + *r = *op1; + else + *r = *op0; + break; - for (i = 0; i < NE; i++) - *b++ = *a++; -} + case NEGATE_EXPR: + *r = *op0; + r->sign ^= 1; + break; + case ABS_EXPR: + *r = *op0; + r->sign = 0; + break; -#if 0 -/* Absolute value of e-type X. */ + case FIX_TRUNC_EXPR: + do_fix_trunc (r, op0); + break; -static void -eabs (x) - UEMUSHORT x[]; -{ - /* sign is top bit of last word of external format */ - x[NE - 1] &= 0x7fff; + default: + gcc_unreachable (); + } + return false; } -#endif /* 0 */ -/* Negate the e-type number X. */ +/* Legacy. Similar, but return the result directly. */ -static void -eneg (x) - UEMUSHORT x[]; +REAL_VALUE_TYPE +real_arithmetic2 (int icode, const REAL_VALUE_TYPE *op0, + const REAL_VALUE_TYPE *op1) { - - x[NE - 1] ^= 0x8000; /* Toggle the sign bit */ + REAL_VALUE_TYPE r; + real_arithmetic (&r, icode, op0, op1); + return r; } -/* Return 1 if sign bit of e-type number X is nonzero, else zero. */ - -static int -eisneg (x) - const UEMUSHORT x[]; +bool +real_compare (int icode, const REAL_VALUE_TYPE *op0, + const REAL_VALUE_TYPE *op1) { + enum tree_code code = icode; - if (x[NE - 1] & 0x8000) - return (1); - else - return (0); -} - -/* Return 1 if e-type number X is infinity, else return zero. */ - -static int -eisinf (x) - const UEMUSHORT x[]; -{ + switch (code) + { + case LT_EXPR: + return do_compare (op0, op1, 1) < 0; + case LE_EXPR: + return do_compare (op0, op1, 1) <= 0; + case GT_EXPR: + return do_compare (op0, op1, -1) > 0; + case GE_EXPR: + return do_compare (op0, op1, -1) >= 0; + case EQ_EXPR: + return do_compare (op0, op1, -1) == 0; + case NE_EXPR: + return do_compare (op0, op1, -1) != 0; + case UNORDERED_EXPR: + return op0->cl == rvc_nan || op1->cl == rvc_nan; + case ORDERED_EXPR: + return op0->cl != rvc_nan && op1->cl != rvc_nan; + case UNLT_EXPR: + return do_compare (op0, op1, -1) < 0; + case UNLE_EXPR: + return do_compare (op0, op1, -1) <= 0; + case UNGT_EXPR: + return do_compare (op0, op1, 1) > 0; + case UNGE_EXPR: + return do_compare (op0, op1, 1) >= 0; + case UNEQ_EXPR: + return do_compare (op0, op1, 0) == 0; + case LTGT_EXPR: + return do_compare (op0, op1, 0) != 0; -#ifdef NANS - if (eisnan (x)) - return (0); -#endif - if ((x[NE - 1] & 0x7fff) == 0x7fff) - return (1); - else - return (0); + default: + gcc_unreachable (); + } } -/* 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. */ +/* Return floor log2(R). */ -static int -eisnan (x) - const UEMUSHORT x[] ATTRIBUTE_UNUSED; +int +real_exponent (const REAL_VALUE_TYPE *r) { -#ifdef NANS - int i; - - /* NaN has maximum exponent */ - if ((x[NE - 1] & 0x7fff) != 0x7fff) - return (0); - /* ... and non-zero significand field. */ - for (i = 0; i < NE - 1; i++) + switch (r->cl) { - if (*x++ != 0) - return (1); + case rvc_zero: + return 0; + case rvc_inf: + case rvc_nan: + return (unsigned int)-1 >> 1; + case rvc_normal: + return REAL_EXP (r); + default: + gcc_unreachable (); } -#endif - - return (0); } -/* Fill e-type number X with infinity pattern (IEEE) - or largest possible number (non-IEEE). */ +/* R = OP0 * 2**EXP. */ -static void -einfin (x) - UEMUSHORT *x; +void +real_ldexp (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, int exp) { - 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) + *r = *op0; + switch (r->cl) { - if (rndprc == 113) - { - *(x - 9) = 0; - *(x - 8) = 0; - } - if (rndprc == 64) - { - *(x - 5) = 0; - } - if (rndprc == 53) - { - *(x - 4) = 0xf800; - } + case rvc_zero: + case rvc_inf: + case rvc_nan: + break; + + case rvc_normal: + exp += REAL_EXP (op0); + if (exp > MAX_EXP) + get_inf (r, r->sign); + else if (exp < -MAX_EXP) + get_zero (r, r->sign); else - { - *(x - 4) = 0; - *(x - 3) = 0; - *(x - 2) = 0xff00; - } + SET_REAL_EXP (r, exp); + break; + + default: + gcc_unreachable (); } -#endif } -/* Output an e-type NaN. - This generates Intel's quiet NaN pattern for extended real. - The exponent is 7fff, the leading mantissa word is c000. */ +/* Determine whether a floating-point value X is infinite. */ -#ifdef NANS -static void -enan (x, sign) - UEMUSHORT *x; - int sign; +bool +real_isinf (const REAL_VALUE_TYPE *r) { - int i; - - for (i = 0; i < NE - 2; i++) - *x++ = 0; - *x++ = 0xc000; - *x = (sign << 15) | 0x7fff; + return (r->cl == rvc_inf); } -#endif /* NANS */ -/* Move in an e-type number A, converting it to exploded e-type B. */ +/* Determine whether a floating-point value X is a NaN. */ -static void -emovi (a, b) - const UEMUSHORT *a; - UEMUSHORT *b; +bool +real_isnan (const REAL_VALUE_TYPE *r) { - const UEMUSHORT *p; - UEMUSHORT *q; - int i; - - q = b; - p = a + (NE - 1); /* point to last word of external number */ - /* get the sign bit */ - if (*p & 0x8000) - *q++ = 0xffff; - else - *q++ = 0; - /* get the exponent */ - *q = *p--; - *q++ &= 0x7fff; /* delete the sign bit */ -#ifdef INFINITY - if ((*(q - 1) & 0x7fff) == 0x7fff) - { -#ifdef NANS - if (eisnan (a)) - { - *q++ = 0; - for (i = 3; i < NI; i++) - *q++ = *p--; - return; - } -#endif + return (r->cl == rvc_nan); +} - for (i = 2; i < NI; i++) - *q++ = 0; - return; - } -#endif +/* Determine whether a floating-point value X is finite. */ - /* clear high guard word */ - *q++ = 0; - /* move in the significand */ - for (i = 0; i < NE - 1; i++) - *q++ = *p--; - /* clear low guard word */ - *q = 0; +bool +real_isfinite (const REAL_VALUE_TYPE *r) +{ + return (r->cl != rvc_nan) && (r->cl != rvc_inf); } -/* Move out exploded e-type number A, converting it to e type B. */ +/* Determine whether a floating-point value X is negative. */ -static void -emovo (a, b) - const UEMUSHORT *a; - UEMUSHORT *b; +bool +real_isneg (const REAL_VALUE_TYPE *r) { - const UEMUSHORT *p; - UEMUSHORT *q; - UEMUSHORT i; - int j; - - p = a; - q = b + (NE - 1); /* point to output exponent */ - /* combine sign and exponent */ - 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 - /* skip over guard word */ - ++p; - /* move the significand */ - for (j = 0; j < NE - 1; j++) - *q-- = *p++; + return r->sign; } -/* Clear out exploded e-type number XI. */ +/* Determine whether a floating-point value X is minus zero. */ -static void -ecleaz (xi) - UEMUSHORT *xi; +bool +real_isnegzero (const REAL_VALUE_TYPE *r) { - int i; - - for (i = 0; i < NI; i++) - *xi++ = 0; + return r->sign && r->cl == rvc_zero; } -/* Clear out exploded e-type XI, but don't touch the sign. */ +/* Compare two floating-point objects for bitwise identity. */ -static void -ecleazs (xi) - UEMUSHORT *xi; +bool +real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b) { int i; - ++xi; - for (i = 0; i < NI - 1; i++) - *xi++ = 0; -} + if (a->cl != b->cl) + return false; + if (a->sign != b->sign) + return false; -/* Move exploded e-type number from A to B. */ + switch (a->cl) + { + case rvc_zero: + case rvc_inf: + return true; -static void -emovz (a, b) - const UEMUSHORT *a; - UEMUSHORT *b; -{ - int i; + case rvc_normal: + if (a->decimal != b->decimal) + return false; + if (REAL_EXP (a) != REAL_EXP (b)) + return false; + break; - for (i = 0; i < NI - 1; i++) - *b++ = *a++; - /* clear low guard word */ - *b = 0; -} + case rvc_nan: + if (a->signalling != b->signalling) + return false; + /* The significand is ignored for canonical NaNs. */ + if (a->canonical || b->canonical) + return a->canonical == b->canonical; + break; -/* Generate exploded e-type NaN. - The explicit pattern for this is maximum exponent and - top two significant bits set. */ + default: + gcc_unreachable (); + } -#ifdef NANS -static void -einan (x) - UEMUSHORT x[]; -{ + for (i = 0; i < SIGSZ; ++i) + if (a->sig[i] != b->sig[i]) + return false; - ecleaz (x); - x[E] = 0x7fff; - x[M + 1] = 0xc000; + return true; } -#endif /* NANS */ -/* Return nonzero if exploded e-type X is a NaN. */ +/* Try to change R into its exact multiplicative inverse in machine + mode MODE. Return true if successful. */ -#ifdef NANS -static int -eiisnan (x) - const UEMUSHORT x[]; +bool +exact_real_inverse (enum machine_mode mode, REAL_VALUE_TYPE *r) { + const REAL_VALUE_TYPE *one = real_digit (1); + REAL_VALUE_TYPE u; int i; - if ((x[E] & 0x7fff) == 0x7fff) - { - for (i = M + 1; i < NI; i++) + if (r->cl != rvc_normal) + return false; + + /* Check for a power of two: all significand bits zero except the MSB. */ + for (i = 0; i < SIGSZ-1; ++i) + if (r->sig[i] != 0) + return false; + if (r->sig[SIGSZ-1] != SIG_MSB) + return false; + + /* Find the inverse and truncate to the required mode. */ + do_divide (&u, one, r); + real_convert (&u, mode, &u); + + /* The rounding may have overflowed. */ + if (u.cl != rvc_normal) + return false; + for (i = 0; i < SIGSZ-1; ++i) + if (u.sig[i] != 0) + return false; + if (u.sig[SIGSZ-1] != SIG_MSB) + return false; + + *r = u; + return true; +} + +/* Return true if arithmetic on values in IMODE that were promoted + from values in TMODE is equivalent to direct arithmetic on values + in TMODE. */ + +bool +real_can_shorten_arithmetic (enum machine_mode imode, enum machine_mode tmode) +{ + const struct real_format *tfmt, *ifmt; + tfmt = REAL_MODE_FORMAT (tmode); + ifmt = REAL_MODE_FORMAT (imode); + /* These conditions are conservative rather than trying to catch the + exact boundary conditions; the main case to allow is IEEE float + and double. */ + return (ifmt->b == tfmt->b + && ifmt->p > 2 * tfmt->p + && ifmt->emin < 2 * tfmt->emin - tfmt->p - 2 + && ifmt->emin < tfmt->emin - tfmt->emax - tfmt->p - 2 + && ifmt->emax > 2 * tfmt->emax + 2 + && ifmt->emax > tfmt->emax - tfmt->emin + tfmt->p + 2 + && ifmt->round_towards_zero == tfmt->round_towards_zero + && (ifmt->has_sign_dependent_rounding + == tfmt->has_sign_dependent_rounding) + && ifmt->has_nans >= tfmt->has_nans + && ifmt->has_inf >= tfmt->has_inf + && ifmt->has_signed_zero >= tfmt->has_signed_zero + && !MODE_COMPOSITE_P (tmode) + && !MODE_COMPOSITE_P (imode)); +} + +/* Render R as an integer. */ + +HOST_WIDE_INT +real_to_integer (const REAL_VALUE_TYPE *r) +{ + unsigned HOST_WIDE_INT i; + + switch (r->cl) + { + case rvc_zero: + underflow: + return 0; + + case rvc_inf: + case rvc_nan: + overflow: + i = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1); + if (!r->sign) + i--; + return i; + + case rvc_normal: + if (r->decimal) + return decimal_real_to_integer (r); + + if (REAL_EXP (r) <= 0) + goto underflow; + /* Only force overflow for unsigned overflow. Signed overflow is + undefined, so it doesn't matter what we return, and some callers + expect to be able to use this routine for both signed and + unsigned conversions. */ + if (REAL_EXP (r) > HOST_BITS_PER_WIDE_INT) + goto overflow; + + if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG) + i = r->sig[SIGSZ-1]; + else { - if (x[i] != 0) - return (1); + gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG); + i = r->sig[SIGSZ-1]; + i = i << (HOST_BITS_PER_LONG - 1) << 1; + i |= r->sig[SIGSZ-2]; } - } - return (0); -} -#endif /* NANS */ -/* Return nonzero if sign of exploded e-type X is nonzero. */ + i >>= HOST_BITS_PER_WIDE_INT - REAL_EXP (r); -#ifdef NANS -static int -eiisneg (x) - const UEMUSHORT x[]; -{ + if (r->sign) + i = -i; + return i; - return x[0] != 0; + default: + gcc_unreachable (); + } } -#endif /* NANS */ -#if 0 -/* Fill exploded e-type X with infinity pattern. - This has maximum exponent and significand all zeros. */ +/* Likewise, but to an integer pair, HI+LOW. */ -static void -eiinfin (x) - UEMUSHORT x[]; +void +real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh, + const REAL_VALUE_TYPE *r) { + REAL_VALUE_TYPE t; + HOST_WIDE_INT low, high; + int exp; - ecleaz (x); - x[E] = 0x7fff; -} -#endif /* 0 */ + switch (r->cl) + { + case rvc_zero: + underflow: + low = high = 0; + break; -/* Return nonzero if exploded e-type X is infinite. */ + case rvc_inf: + case rvc_nan: + overflow: + high = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1); + if (r->sign) + low = 0; + else + { + high--; + low = -1; + } + break; -#ifdef INFINITY -static int -eiisinf (x) - const UEMUSHORT x[]; -{ + case rvc_normal: + if (r->decimal) + { + decimal_real_to_integer2 (plow, phigh, r); + return; + } + + exp = REAL_EXP (r); + if (exp <= 0) + goto underflow; + /* Only force overflow for unsigned overflow. Signed overflow is + undefined, so it doesn't matter what we return, and some callers + expect to be able to use this routine for both signed and + unsigned conversions. */ + if (exp > 2*HOST_BITS_PER_WIDE_INT) + goto overflow; + + rshift_significand (&t, r, 2*HOST_BITS_PER_WIDE_INT - exp); + if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG) + { + high = t.sig[SIGSZ-1]; + low = t.sig[SIGSZ-2]; + } + else + { + gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG); + high = t.sig[SIGSZ-1]; + high = high << (HOST_BITS_PER_LONG - 1) << 1; + high |= t.sig[SIGSZ-2]; + + low = t.sig[SIGSZ-3]; + low = low << (HOST_BITS_PER_LONG - 1) << 1; + low |= t.sig[SIGSZ-4]; + } -#ifdef NANS - if (eiisnan (x)) - return (0); -#endif - if ((x[E] & 0x7fff) == 0x7fff) - return (1); - return (0); -} -#endif /* INFINITY */ + if (r->sign) + { + if (low == 0) + high = -high; + else + low = -low, high = ~high; + } + break; + + default: + gcc_unreachable (); + } -/* Compare significands of numbers in internal exploded e-type format. - Guard words are included in the comparison. + *plow = low; + *phigh = high; +} - Returns +1 if a > b - 0 if a == b - -1 if a < b */ +/* A subroutine of real_to_decimal. Compute the quotient and remainder + of NUM / DEN. Return the quotient and place the remainder in NUM. + It is expected that NUM / DEN are close enough that the quotient is + small. */ -static int -ecmpm (a, b) - const UEMUSHORT *a, *b; +static unsigned long +rtd_divmod (REAL_VALUE_TYPE *num, REAL_VALUE_TYPE *den) { - int i; + unsigned long q, msb; + int expn = REAL_EXP (num), expd = REAL_EXP (den); - a += M; /* skip up to significand area */ - b += M; - for (i = M; i < NI; i++) + if (expn < expd) + return 0; + + q = msb = 0; + goto start; + do { - if (*a++ != *b++) - goto difrnt; + msb = num->sig[SIGSZ-1] & SIG_MSB; + q <<= 1; + lshift_significand_1 (num, num); + start: + if (msb || cmp_significands (num, den) >= 0) + { + sub_significands (num, num, den, 0); + q |= 1; + } } - return (0); + while (--expn >= expd); - difrnt: - if (*(--a) > *(--b)) - return (1); - else - return (-1); + SET_REAL_EXP (num, expd); + normalize (num); + + return q; } -/* Shift significand of exploded e-type X down by 1 bit. */ +/* Render R as a decimal floating point constant. Emit DIGITS significant + digits in the result, bounded by BUF_SIZE. If DIGITS is 0, choose the + maximum for the representation. If CROP_TRAILING_ZEROS, strip trailing + zeros. If MODE is VOIDmode, round to nearest value. Otherwise, round + to a string that, when parsed back in mode MODE, yields the same value. */ -static void -eshdn1 (x) - UEMUSHORT *x; -{ - UEMUSHORT bits; - int i; +#define M_LOG10_2 0.30102999566398119521 - x += M; /* point to significand area */ +void +real_to_decimal_for_mode (char *str, const REAL_VALUE_TYPE *r_orig, + size_t buf_size, size_t digits, + int crop_trailing_zeros, enum machine_mode mode) +{ + const struct real_format *fmt = NULL; + const REAL_VALUE_TYPE *one, *ten; + REAL_VALUE_TYPE r, pten, u, v; + int dec_exp, cmp_one, digit; + size_t max_digits; + char *p, *first, *last; + bool sign; + bool round_up; + + if (mode != VOIDmode) + { + fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt); + } + + r = *r_orig; + switch (r.cl) + { + case rvc_zero: + strcpy (str, (r.sign ? "-0.0" : "0.0")); + return; + case rvc_normal: + break; + case rvc_inf: + strcpy (str, (r.sign ? "-Inf" : "+Inf")); + return; + case rvc_nan: + /* ??? Print the significand as well, if not canonical? */ + sprintf (str, "%c%cNaN", (r_orig->sign ? '-' : '+'), + (r_orig->signalling ? 'S' : 'Q')); + return; + default: + gcc_unreachable (); + } - bits = 0; - for (i = M; i < NI; i++) + if (r.decimal) { - if (*x & 1) - bits |= 1; - *x >>= 1; - if (bits & 2) - *x |= 0x8000; - bits <<= 1; - ++x; + decimal_real_to_decimal (str, &r, buf_size, digits, crop_trailing_zeros); + return; } -} -/* Shift significand of exploded e-type X up by 1 bit. */ + /* Bound the number of digits printed by the size of the representation. */ + max_digits = SIGNIFICAND_BITS * M_LOG10_2; + if (digits == 0 || digits > max_digits) + digits = max_digits; -static void -eshup1 (x) - UEMUSHORT *x; -{ - UEMUSHORT bits; - int i; + /* Estimate the decimal exponent, and compute the length of the string it + will print as. Be conservative and add one to account for possible + overflow or rounding error. */ + dec_exp = REAL_EXP (&r) * M_LOG10_2; + for (max_digits = 1; dec_exp ; max_digits++) + dec_exp /= 10; + + /* Bound the number of digits printed by the size of the output buffer. */ + max_digits = buf_size - 1 - 1 - 2 - max_digits - 1; + gcc_assert (max_digits <= buf_size); + if (digits > max_digits) + digits = max_digits; + + one = real_digit (1); + ten = ten_to_ptwo (0); - x += NI - 1; - bits = 0; + sign = r.sign; + r.sign = 0; - for (i = M; i < NI; i++) + dec_exp = 0; + pten = *one; + + cmp_one = do_compare (&r, one, 0); + if (cmp_one > 0) { - if (*x & 0x8000) - bits |= 1; - *x <<= 1; - if (bits & 2) - *x |= 1; - bits <<= 1; - --x; - } -} + int m; + /* Number is greater than one. Convert significand to an integer + and strip trailing decimal zeros. */ -/* Shift significand of exploded e-type X down by 8 bits. */ + u = r; + SET_REAL_EXP (&u, SIGNIFICAND_BITS - 1); -static void -eshdn8 (x) - UEMUSHORT *x; -{ - UEMUSHORT newbyt, oldbyt; - int i; + /* Largest M, such that 10**2**M fits within SIGNIFICAND_BITS. */ + m = floor_log2 (max_digits); + + /* Iterate over the bits of the possible powers of 10 that might + be present in U and eliminate them. That is, if we find that + 10**2**M divides U evenly, keep the division and increase + DEC_EXP by 2**M. */ + do + { + REAL_VALUE_TYPE t; + + do_divide (&t, &u, ten_to_ptwo (m)); + do_fix_trunc (&v, &t); + if (cmp_significands (&v, &t) == 0) + { + u = t; + dec_exp += 1 << m; + } + } + while (--m >= 0); + + /* Revert the scaling to integer that we performed earlier. */ + SET_REAL_EXP (&u, REAL_EXP (&u) + REAL_EXP (&r) + - (SIGNIFICAND_BITS - 1)); + r = u; - x += M; - oldbyt = 0; - for (i = M; i < NI; i++) + /* Find power of 10. Do this by dividing out 10**2**M when + this is larger than the current remainder. Fill PTEN with + the power of 10 that we compute. */ + if (REAL_EXP (&r) > 0) + { + m = floor_log2 ((int)(REAL_EXP (&r) * M_LOG10_2)) + 1; + do + { + const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m); + if (do_compare (&u, ptentwo, 0) >= 0) + { + do_divide (&u, &u, ptentwo); + do_multiply (&pten, &pten, ptentwo); + dec_exp += 1 << m; + } + } + while (--m >= 0); + } + else + /* We managed to divide off enough tens in the above reduction + loop that we've now got a negative exponent. Fall into the + less-than-one code to compute the proper value for PTEN. */ + cmp_one = -1; + } + if (cmp_one < 0) { - newbyt = *x << 8; - *x >>= 8; - *x |= oldbyt; - oldbyt = newbyt; - ++x; + int m; + + /* Number is less than one. Pad significand with leading + decimal zeros. */ + + v = r; + while (1) + { + /* Stop if we'd shift bits off the bottom. */ + if (v.sig[0] & 7) + break; + + do_multiply (&u, &v, ten); + + /* Stop if we're now >= 1. */ + if (REAL_EXP (&u) > 0) + break; + + v = u; + dec_exp -= 1; + } + r = v; + + /* Find power of 10. Do this by multiplying in P=10**2**M when + the current remainder is smaller than 1/P. Fill PTEN with the + power of 10 that we compute. */ + m = floor_log2 ((int)(-REAL_EXP (&r) * M_LOG10_2)) + 1; + do + { + const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m); + const REAL_VALUE_TYPE *ptenmtwo = ten_to_mptwo (m); + + if (do_compare (&v, ptenmtwo, 0) <= 0) + { + do_multiply (&v, &v, ptentwo); + do_multiply (&pten, &pten, ptentwo); + dec_exp -= 1 << m; + } + } + while (--m >= 0); + + /* Invert the positive power of 10 that we've collected so far. */ + do_divide (&pten, one, &pten); } -} -/* Shift significand of exploded e-type X up by 8 bits. */ + p = str; + if (sign) + *p++ = '-'; + first = p++; -static void -eshup8 (x) - UEMUSHORT *x; -{ - int i; - UEMUSHORT newbyt, oldbyt; + /* At this point, PTEN should contain the nearest power of 10 smaller + than R, such that this division produces the first digit. - x += NI - 1; - oldbyt = 0; + Using a divide-step primitive that returns the complete integral + remainder avoids the rounding error that would be produced if + we were to use do_divide here and then simply multiply by 10 for + each subsequent digit. */ - for (i = M; i < NI; i++) + digit = rtd_divmod (&r, &pten); + + /* Be prepared for error in that division via underflow ... */ + if (digit == 0 && cmp_significand_0 (&r)) { - newbyt = *x >> 8; - *x <<= 8; - *x |= oldbyt; - oldbyt = newbyt; - --x; + /* Multiply by 10 and try again. */ + do_multiply (&r, &r, ten); + digit = rtd_divmod (&r, &pten); + dec_exp -= 1; + gcc_assert (digit != 0); + } + + /* ... or overflow. */ + if (digit == 10) + { + *p++ = '1'; + if (--digits > 0) + *p++ = '0'; + dec_exp += 1; + } + else + { + gcc_assert (digit <= 10); + *p++ = digit + '0'; } -} -/* Shift significand of exploded e-type X up by 16 bits. */ + /* Generate subsequent digits. */ + while (--digits > 0) + { + do_multiply (&r, &r, ten); + digit = rtd_divmod (&r, &pten); + *p++ = digit + '0'; + } + last = p; -static void -eshup6 (x) - UEMUSHORT *x; -{ - int i; - UEMUSHORT *p; + /* Generate one more digit with which to do rounding. */ + do_multiply (&r, &r, ten); + digit = rtd_divmod (&r, &pten); - p = x + M; - x += M + 1; + /* Round the result. */ + if (fmt && fmt->round_towards_zero) + { + /* If the format uses round towards zero when parsing the string + back in, we need to always round away from zero here. */ + if (cmp_significand_0 (&r)) + digit++; + round_up = digit > 0; + } + else + { + if (digit == 5) + { + /* Round to nearest. If R is nonzero there are additional + nonzero digits to be extracted. */ + if (cmp_significand_0 (&r)) + digit++; + /* Round to even. */ + else if ((p[-1] - '0') & 1) + digit++; + } - for (i = M; i < NI - 1; i++) - *p++ = *x++; + round_up = digit > 5; + } - *p = 0; -} + if (round_up) + { + while (p > first) + { + digit = *--p; + if (digit == '9') + *p = '0'; + else + { + *p = digit + 1; + break; + } + } -/* Shift significand of exploded e-type X down by 16 bits. */ + /* Carry out of the first digit. This means we had all 9's and + now have all 0's. "Prepend" a 1 by overwriting the first 0. */ + if (p == first) + { + first[1] = '1'; + dec_exp++; + } + } -static void -eshdn6 (x) - UEMUSHORT *x; -{ - int i; - UEMUSHORT *p; + /* Insert the decimal point. */ + first[0] = first[1]; + first[1] = '.'; - x += NI - 1; - p = x + 1; + /* If requested, drop trailing zeros. Never crop past "1.0". */ + if (crop_trailing_zeros) + while (last > first + 3 && last[-1] == '0') + last--; - for (i = M; i < NI - 1; i++) - *(--p) = *(--x); + /* Append the exponent. */ + sprintf (last, "e%+d", dec_exp); - *(--p) = 0; +#ifdef ENABLE_CHECKING + /* Verify that we can read the original value back in. */ + if (mode != VOIDmode) + { + real_from_string (&r, str); + real_convert (&r, mode, &r); + gcc_assert (real_identical (&r, r_orig)); + } +#endif } -/* Add significands of exploded e-type X and Y. X + Y replaces Y. */ +/* Likewise, except always uses round-to-nearest. */ -static void -eaddm (x, y) - const UEMUSHORT *x; - UEMUSHORT *y; +void +real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size, + size_t digits, int crop_trailing_zeros) { - 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 = (UEMUSHORT) a; - --x; - --y; - } + real_to_decimal_for_mode (str, r_orig, buf_size, + digits, crop_trailing_zeros, VOIDmode); } -/* Subtract significands of exploded e-type X and Y. Y - X replaces Y. */ +/* Render R as a hexadecimal floating point constant. Emit DIGITS + significant digits in the result, bounded by BUF_SIZE. If DIGITS is 0, + choose the maximum for the representation. If CROP_TRAILING_ZEROS, + strip trailing zeros. */ -static void -esubm (x, y) - const UEMUSHORT *x; - UEMUSHORT *y; +void +real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size, + size_t digits, int crop_trailing_zeros) { - unsigned EMULONG a; - int i; - unsigned int carry; + int i, j, exp = REAL_EXP (r); + char *p, *first; + char exp_buf[16]; + size_t max_digits; - x += NI - 1; - y += NI - 1; - carry = 0; - for (i = M; i < NI; i++) + switch (r->cl) { - a = (unsigned EMULONG) (*y) - (unsigned EMULONG) (*x) - carry; - if (a & 0x10000) - carry = 1; - else - carry = 0; - *y = (UEMUSHORT) a; - --x; - --y; + case rvc_zero: + exp = 0; + break; + case rvc_normal: + break; + case rvc_inf: + strcpy (str, (r->sign ? "-Inf" : "+Inf")); + return; + case rvc_nan: + /* ??? Print the significand as well, if not canonical? */ + sprintf (str, "%c%cNaN", (r->sign ? '-' : '+'), + (r->signalling ? 'S' : 'Q')); + return; + default: + gcc_unreachable (); } -} + if (r->decimal) + { + /* Hexadecimal format for decimal floats is not interesting. */ + strcpy (str, "N/A"); + return; + } + + if (digits == 0) + digits = SIGNIFICAND_BITS / 4; + + /* Bound the number of digits printed by the size of the output buffer. */ + + sprintf (exp_buf, "p%+d", exp); + max_digits = buf_size - strlen (exp_buf) - r->sign - 4 - 1; + gcc_assert (max_digits <= buf_size); + if (digits > max_digits) + digits = max_digits; -static UEMUSHORT equot[NI]; + p = str; + if (r->sign) + *p++ = '-'; + *p++ = '0'; + *p++ = 'x'; + *p++ = '0'; + *p++ = '.'; + first = p; + for (i = SIGSZ - 1; i >= 0; --i) + for (j = HOST_BITS_PER_LONG - 4; j >= 0; j -= 4) + { + *p++ = "0123456789abcdef"[(r->sig[i] >> j) & 15]; + if (--digits == 0) + goto out; + } -#if 0 -/* Radix 2 shift-and-add versions of multiply and divide */ + out: + if (crop_trailing_zeros) + while (p > first + 1 && p[-1] == '0') + p--; + sprintf (p, "p%+d", exp); +} -/* Divide significands */ +/* Initialize R from a decimal or hexadecimal string. The string is + assumed to have been syntax checked already. Return -1 if the + value underflows, +1 if overflows, and 0 otherwise. */ int -edivm (den, num) - UEMUSHORT den[], num[]; +real_from_string (REAL_VALUE_TYPE *r, const char *str) { - int i; - UEMUSHORT *p, *q; - UEMUSHORT j; + int exp = 0; + bool sign = false; - p = &equot[0]; - *p++ = num[0]; - *p++ = num[1]; + get_zero (r, 0); - for (i = M; i < NI; i++) + if (*str == '-') { - *p++ = 0; + sign = true; + str++; } + else if (*str == '+') + str++; - /* Use faster compare and subtraction if denominator has only 15 bits of - significance. */ + if (!strncmp (str, "QNaN", 4)) + { + get_canonical_qnan (r, sign); + return 0; + } + else if (!strncmp (str, "SNaN", 4)) + { + get_canonical_snan (r, sign); + return 0; + } + else if (!strncmp (str, "Inf", 3)) + { + get_inf (r, sign); + return 0; + } - p = &den[M + 2]; - if (*p++ == 0) + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { - for (i = M + 3; i < NI; i++) + /* Hexadecimal floating point. */ + int pos = SIGNIFICAND_BITS - 4, d; + + str += 2; + + while (*str == '0') + str++; + while (1) + { + d = hex_value (*str); + if (d == _hex_bad) + break; + if (pos >= 0) + { + r->sig[pos / HOST_BITS_PER_LONG] + |= (unsigned long) d << (pos % HOST_BITS_PER_LONG); + pos -= 4; + } + else if (d) + /* Ensure correct rounding by setting last bit if there is + a subsequent nonzero digit. */ + r->sig[0] |= 1; + exp += 4; + str++; + } + if (*str == '.') { - if (*p++ != 0) - goto fulldiv; + str++; + if (pos == SIGNIFICAND_BITS - 4) + { + while (*str == '0') + str++, exp -= 4; + } + while (1) + { + d = hex_value (*str); + if (d == _hex_bad) + break; + if (pos >= 0) + { + r->sig[pos / HOST_BITS_PER_LONG] + |= (unsigned long) d << (pos % HOST_BITS_PER_LONG); + pos -= 4; + } + else if (d) + /* Ensure correct rounding by setting last bit if there is + a subsequent nonzero digit. */ + r->sig[0] |= 1; + str++; + } } - if ((den[M + 1] & 1) != 0) - goto fulldiv; - eshdn1 (num); - eshdn1 (den); - p = &den[M + 1]; - q = &num[M + 1]; + /* If the mantissa is zero, ignore the exponent. */ + if (!cmp_significand_0 (r)) + goto is_a_zero; - for (i = 0; i < NBITS + 2; i++) + if (*str == 'p' || *str == 'P') { - if (*p <= *q) + bool exp_neg = false; + + str++; + if (*str == '-') { - *q -= *p; - j = 1; + exp_neg = true; + str++; } - else + else if (*str == '+') + str++; + + d = 0; + while (ISDIGIT (*str)) { - j = 0; + d *= 10; + d += *str - '0'; + if (d > MAX_EXP) + { + /* Overflowed the exponent. */ + if (exp_neg) + goto underflow; + else + goto overflow; + } + str++; } - eshup1 (equot); - equot[NI - 2] |= j; - eshup1 (num); - } - goto divdon; - } + if (exp_neg) + d = -d; - /* The number of quotient bits to calculate is NBITS + 1 scaling guard - bit + 1 roundoff bit. */ + exp += d; + } - fulldiv: + r->cl = rvc_normal; + SET_REAL_EXP (r, exp); - p = &equot[NI - 2]; - for (i = 0; i < NBITS + 2; i++) + normalize (r); + } + else { - if (ecmpm (den, num) <= 0) + /* Decimal floating point. */ + const REAL_VALUE_TYPE *ten = ten_to_ptwo (0); + int d; + + while (*str == '0') + str++; + while (ISDIGIT (*str)) { - esubm (den, num); - j = 1; /* quotient bit = 1 */ + d = *str++ - '0'; + do_multiply (r, r, ten); + if (d) + do_add (r, r, real_digit (d), 0); + } + if (*str == '.') + { + str++; + if (r->cl == rvc_zero) + { + while (*str == '0') + str++, exp--; + } + while (ISDIGIT (*str)) + { + d = *str++ - '0'; + do_multiply (r, r, ten); + if (d) + do_add (r, r, real_digit (d), 0); + exp--; + } } - else - j = 0; - eshup1 (equot); - *p |= j; - eshup1 (num); - } - divdon: + /* If the mantissa is zero, ignore the exponent. */ + if (r->cl == rvc_zero) + goto is_a_zero; - eshdn1 (equot); - eshdn1 (equot); + if (*str == 'e' || *str == 'E') + { + bool exp_neg = false; - /* test for nonzero remainder after roundoff bit */ - p = &num[M]; - j = 0; - for (i = M; i < NI; i++) - { - j |= *p++; - } - if (j) - j = 1; + str++; + if (*str == '-') + { + exp_neg = true; + str++; + } + else if (*str == '+') + str++; + d = 0; + while (ISDIGIT (*str)) + { + d *= 10; + d += *str - '0'; + if (d > MAX_EXP) + { + /* Overflowed the exponent. */ + if (exp_neg) + goto underflow; + else + goto overflow; + } + str++; + } + if (exp_neg) + d = -d; + exp += d; + } - for (i = 0; i < NI; i++) - num[i] = equot[i]; - return ((int) j); -} + if (exp) + times_pten (r, exp); + } + r->sign = sign; + return 0; -/* Multiply significands */ + is_a_zero: + get_zero (r, sign); + return 0; -int -emulm (a, b) - UEMUSHORT a[], b[]; -{ - UEMUSHORT *p, *q; - int i, j, k; + underflow: + get_zero (r, sign); + return -1; - equot[0] = b[0]; - equot[1] = b[1]; - for (i = M; i < NI; i++) - equot[i] = 0; + overflow: + get_inf (r, sign); + return 1; +} - p = &a[NI - 2]; - k = NBITS; - while (*p == 0) /* significand is not supposed to be zero */ - { - eshdn6 (a); - k -= 16; - } - if ((*p & 0xff) == 0) - { - eshdn8 (a); - k -= 8; - } +/* Legacy. Similar, but return the result directly. */ - q = &equot[NI - 1]; - j = 0; - for (i = 0; i < k; i++) - { - if (*p & 1) - eaddm (b, equot); - /* remember if there were any nonzero bits shifted out */ - if (*q & 1) - j |= 1; - eshdn1 (a); - eshdn1 (equot); - } +REAL_VALUE_TYPE +real_from_string2 (const char *s, enum machine_mode mode) +{ + REAL_VALUE_TYPE r; - for (i = 0; i < NI; i++) - b[i] = equot[i]; + real_from_string (&r, s); + if (mode != VOIDmode) + real_convert (&r, mode, &r); - /* return flag for lost nonzero bits */ - return (j); + return r; } -#else +/* Initialize R from string S and desired MODE. */ + +void +real_from_string3 (REAL_VALUE_TYPE *r, const char *s, enum machine_mode mode) +{ + if (DECIMAL_FLOAT_MODE_P (mode)) + decimal_real_from_string (r, s); + else + real_from_string (r, s); -/* Radix 65536 versions of multiply and divide. */ + if (mode != VOIDmode) + real_convert (r, mode, r); +} -/* Multiply significand of e-type number B - by 16-bit quantity A, return e-type result to C. */ +/* Initialize R from the integer pair HIGH+LOW. */ -static void -m16m (a, b, c) - unsigned int a; - const UEMUSHORT b[]; - UEMUSHORT c[]; +void +real_from_integer (REAL_VALUE_TYPE *r, enum machine_mode mode, + unsigned HOST_WIDE_INT low, HOST_WIDE_INT high, + int unsigned_p) { - UEMUSHORT *pp; - unsigned EMULONG carry; - const UEMUSHORT *ps; - UEMUSHORT p[NI]; - unsigned EMULONG aa, m; - int i; + if (low == 0 && high == 0) + get_zero (r, 0); + else + { + memset (r, 0, sizeof (*r)); + r->cl = rvc_normal; + r->sign = high < 0 && !unsigned_p; + SET_REAL_EXP (r, 2 * HOST_BITS_PER_WIDE_INT); - aa = a; - pp = &p[NI-2]; - *pp++ = 0; - *pp = 0; - ps = &b[NI-1]; + if (r->sign) + { + high = ~high; + if (low == 0) + high += 1; + else + low = -low; + } - for (i=M+1; isig[SIGSZ-1] = high; + r->sig[SIGSZ-2] = low; } else { - m = (unsigned EMULONG) aa * *ps--; - carry = (m & 0xffff) + *pp; - *pp-- = (UEMUSHORT) carry; - carry = (carry >> 16) + (m >> 16) + *pp; - *pp = (UEMUSHORT) carry; - *(pp-1) = carry >> 16; + gcc_assert (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT); + r->sig[SIGSZ-1] = high >> (HOST_BITS_PER_LONG - 1) >> 1; + r->sig[SIGSZ-2] = high; + r->sig[SIGSZ-3] = low >> (HOST_BITS_PER_LONG - 1) >> 1; + r->sig[SIGSZ-4] = low; } + + normalize (r); } - for (i=M; i 0) - { - tquot -= 1; - esubm (den, tprod); - if (ecmpm (tprod, num) > 0) - { - tquot -= 1; - esubm (den, tprod); - } - } - esubm (tprod, num); - equot[i] = tquot; - eshup6 (num); - } - /* test for nonzero remainder after roundoff bit */ - p = &num[M]; - j = 0; - for (i=M; i= 0 && digit <= 9); + *p++ = digit + '0'; + while (--digits > 0) { - j |= *p++; + times_pten (&r, 1); + digit = rtd_divmod (&r, &pten); + *p++ = digit + '0'; } - if (j) - j = 1; + *p++ = '.'; + *p++ = '\0'; +} - for (i=0; i= 0); + gcc_assert (n < EXP_BITS); - j = 0; - p = &a[NI-1]; - q = &equot[NI-1]; - for (i=M+1; i= 0); + gcc_assert (n < EXP_BITS); -/* Normalize and round off. + if (tens[n].cl == rvc_zero) + do_divide (&tens[n], real_digit (1), ten_to_ptwo (n)); + + return &tens[n]; +} - 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. +/* Returns N. */ - 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. +static const REAL_VALUE_TYPE * +real_digit (int n) +{ + static REAL_VALUE_TYPE num[10]; - 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. + gcc_assert (n >= 0); + gcc_assert (n <= 9); - Input RCNTRL is the rounding control. If it is nonzero, the - returned value will be rounded to RNDPRC bits. + if (n > 0 && num[n].cl == rvc_zero) + real_from_integer (&num[n], VOIDmode, n, 0, 1); - For future reference: In order for emdnorm to round off denormal - significands at the right point, the input exponent must be - 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.). - 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 - result is denormal. */ + return &num[n]; +} -static int rlast = -1; -static int rw = 0; -static UEMUSHORT rmsk = 0; -static UEMUSHORT rmbit = 0; -static UEMUSHORT rebit = 0; -static int re = 0; -static UEMUSHORT rbit[NI]; +/* Multiply R by 10**EXP. */ static void -emdnorm (s, lost, subflg, exp, rcntrl) - UEMUSHORT s[]; - int lost; - int subflg; - EMULONG exp; - int rcntrl; +times_pten (REAL_VALUE_TYPE *r, int exp) { - int i, j; - UEMUSHORT r; - - /* Normalize */ - j = enormlz (s); + REAL_VALUE_TYPE pten, *rr; + bool negative = (exp < 0); + int i; - /* a blank significand could mean either zero or infinity. */ -#ifndef INFINITY - if (j > NBITS) + if (negative) { - ecleazs (s); - return; + exp = -exp; + pten = *real_digit (1); + rr = &pten; } -#endif - exp -= j; -#ifndef INFINITY - if (exp >= 32767L) - goto overf; -#else - if ((j > NBITS) && (exp < 32767)) + else + rr = r; + + for (i = 0; exp > 0; ++i, exp >>= 1) + if (exp & 1) + do_multiply (rr, rr, ten_to_ptwo (i)); + + if (negative) + do_divide (r, r, &pten); +} + +/* Returns the special REAL_VALUE_TYPE corresponding to 'e'. */ + +const REAL_VALUE_TYPE * +dconst_e_ptr (void) +{ + static REAL_VALUE_TYPE value; + + /* Initialize mathematical constants for constant folding builtins. + These constants need to be given to at least 160 bits precision. */ + if (value.cl == rvc_zero) { - ecleazs (s); - return; + mpfr_t m; + mpfr_init2 (m, SIGNIFICAND_BITS); + mpfr_set_ui (m, 1, GMP_RNDN); + mpfr_exp (m, m, GMP_RNDN); + real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN); + mpfr_clear (m); + } -#endif - if (exp < 0L) - { - if (exp > (EMULONG) (-NBITS - 1)) - { - j = (int) exp; - i = eshift (s, j); - if (i) - lost = 1; - } - else - { - ecleazs (s); - return; - } - } - /* Round off, unless told not to by rcntrl. */ - if (rcntrl == 0) - goto mdfin; - /* Set up rounding parameters if the control register changed. */ - if (rndprc != rlast) - { - ecleaz (rbit); - switch (rndprc) - { - default: - case NBITS: - rw = NI - 1; /* low guard word */ - 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; - - /* For DEC or IBM arithmetic */ - 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; - - /* For C4x arithmetic */ - 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; - } - - /* Shift down 1 temporarily if the data structure has an implied - most significant bit and the number is denormal. - Intel long double denormals also lose one bit of precision. */ - if ((exp <= 0) && (rndprc != NBITS) - && ((rndprc != 64) || ((rndprc == 64) && ! REAL_WORDS_BIG_ENDIAN))) - { - lost |= s[NI - 1] & 1; - eshdn1 (s); - } - /* Clear out all bits below the rounding bit, - remembering in r if any were nonzero. */ - 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) - { /* round to even */ - if ((s[re] & rebit) == 0) - goto mddone; - } - else - { - if (subflg != 0) - goto mddone; - } - } -#endif - eaddm (rbit, s); - } - mddone: -/* Undo the temporary shift for denormal values. */ - if ((exp <= 0) && (rndprc != NBITS) - && ((rndprc != 64) || ((rndprc == 64) && ! REAL_WORDS_BIG_ENDIAN))) - { - eshup1 (s); - } - if (s[2] != 0) - { /* overflow on roundoff */ - 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] = (UEMUSHORT) exp; -} - -/* Subtract. C = B - A, all e type numbers. */ - -static int subflg = 0; - -static void -esub (a, b, c) - const UEMUSHORT *a, *b; - UEMUSHORT *c; -{ - -#ifdef NANS - if (eisnan (a)) - { - emov (a, c); - return; - } - if (eisnan (b)) - { - emov (b, c); - return; - } -/* Infinity minus infinity is a NaN. - Test for subtracting infinities of the same sign. */ - if (eisinf (a) && eisinf (b) - && ((eisneg (a) ^ eisneg (b)) == 0)) - { - mtherr ("esub", INVALID); - enan (c, 0); - return; - } -#endif - subflg = 1; - eadd1 (a, b, c); -} - -/* Add. C = A + B, all e type. */ - -static void -eadd (a, b, c) - const UEMUSHORT *a, *b; - UEMUSHORT *c; -{ - -#ifdef NANS -/* NaN plus anything is a NaN. */ - if (eisnan (a)) - { - emov (a, c); - return; - } - if (eisnan (b)) - { - emov (b, c); - return; - } -/* Infinity minus infinity is a NaN. - Test for adding infinities of opposite signs. */ - if (eisinf (a) && eisinf (b) - && ((eisneg (a) ^ eisneg (b)) != 0)) - { - mtherr ("esub", INVALID); - enan (c, 0); - return; - } -#endif - subflg = 0; - eadd1 (a, b, c); -} - -/* Arithmetic common to both addition and subtraction. */ - -static void -eadd1 (a, b, c) - const UEMUSHORT *a, *b; - UEMUSHORT *c; -{ - UEMUSHORT 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]; - - /* compare exponents */ - lta = ai[E]; - ltb = bi[E]; - lt = lta - ltb; - if (lt > 0L) - { /* put the larger number in bi */ - 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; /* answer same as larger addend */ - k = (int) lt; - lost = eshift (ai, k); /* shift the smaller number down */ - } - else - { - /* exponents were the same, so must compare significands */ - i = ecmpm (ai, bi); - if (i == 0) - { /* the numbers are identical in magnitude */ - /* if different signs, result is zero */ - if (ai[0] != bi[0]) - { - eclear (c); - return; - } - /* if same sign, result is double */ - /* double denormalized tiny number */ - if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0)) - { - eshup1 (bi); - goto done; - } - /* add 1 to exponent unless both are zero! */ - 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] = (UEMUSHORT) ltb; - goto done; - } - if (i > 0) - { /* put the larger number in bi */ - 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); -} - -/* Divide: C = B/A, all e type. */ - -static void -ediv (a, b, c) - const UEMUSHORT *a, *b; - UEMUSHORT *c; -{ - UEMUSHORT ai[NI], bi[NI]; - int i, sign; - EMULONG lt, lta, ltb; - -/* IEEE says if result is not a NaN, the sign is "-" if and only if - operands have opposite signs -- but flush -0 to 0 later if not IEEE. */ - sign = eisneg (a) ^ eisneg (b); - -#ifdef NANS -/* Return any NaN input. */ - if (eisnan (a)) - { - emov (a, c); - return; - } - if (eisnan (b)) - { - emov (b, c); - return; - } -/* Zero over zero, or infinity over infinity, is a NaN. */ - if (((ecmp (a, ezero) == 0) && (ecmp (b, ezero) == 0)) - || (eisinf (a) && eisinf (b))) - { - mtherr ("ediv", INVALID); - enan (c, sign); - return; - } -#endif -/* Infinity over anything else is infinity. */ -#ifdef INFINITY - if (eisinf (b)) - { - einfin (c); - goto divsign; - } -/* Anything else over infinity is zero. */ - if (eisinf (a)) - { - eclear (c); - goto divsign; - } -#endif - emovi (a, ai); - emovi (b, bi); - lta = ai[E]; - ltb = bi[E]; - if (bi[E] == 0) - { /* See if numerator is zero. */ - 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) - { /* possible divide by zero */ - for (i = 1; i < NI - 1; i++) - { - if (ai[i] != 0) - { - lta -= enormlz (ai); - goto dnzro2; - } - } -/* Divide by zero is not an invalid operation. - It is a divide-by-zero operation! */ - einfin (c); - mtherr ("ediv", SING); - goto divsign; - } - dnzro2: - - i = edivm (ai, bi); - /* calculate exponent */ - 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; -} - -/* Multiply e-types A and B, return e-type product C. */ - -static void -emul (a, b, c) - const UEMUSHORT *a, *b; - UEMUSHORT *c; -{ - UEMUSHORT ai[NI], bi[NI]; - int i, j, sign; - EMULONG lt, lta, ltb; - -/* IEEE says if result is not a NaN, the sign is "-" if and only if - operands have opposite signs -- but flush -0 to 0 later if not IEEE. */ - sign = eisneg (a) ^ eisneg (b); - -#ifdef NANS -/* NaN times anything is the same NaN. */ - if (eisnan (a)) - { - emov (a, c); - return; - } - if (eisnan (b)) - { - emov (b, c); - return; - } -/* Zero times infinity is a NaN. */ - if ((eisinf (a) && (ecmp (b, ezero) == 0)) - || (eisinf (b) && (ecmp (a, ezero) == 0))) - { - mtherr ("emul", INVALID); - enan (c, sign); - return; - } -#endif -/* Infinity times anything else is infinity. */ -#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: - - /* Multiply significands */ - j = emulm (ai, bi); - /* calculate exponent */ - 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; -} - -/* Convert double precision PE to e-type Y. */ - -static void -e53toe (pe, y) - const UEMUSHORT *pe; - UEMUSHORT *y; -{ -#ifdef DEC - - dectoe (pe, y); - -#else -#ifdef IBM - - ibmtoe (pe, y, DFmode); - -#else -#ifdef C4X - - c4xtoe (pe, y, HFmode); - -#else - UEMUSHORT r; - const UEMUSHORT *e; - UEMUSHORT *p; - UEMUSHORT yy[NI]; - int denorm, k; - - e = pe; - denorm = 0; /* flag if denormalized number */ - 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; /* strip sign and 4 significand bits */ -#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 /* NANS */ - eclear (y); - einfin (y); - if (yy[0]) - eneg (y); - return; - } -#endif /* INFINITY */ - r >>= 4; - /* If zero exponent, then the significand is denormalized. - So take back the understood high significand bit. */ - - 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 zero exponent, then normalize the significand. */ - if ((k = enormlz (yy)) > NBITS) - ecleazs (yy); - else - yy[E] -= (UEMUSHORT) (k - 1); - } - emovo (yy, y); -#endif /* not C4X */ -#endif /* not IBM */ -#endif /* not DEC */ -} - -/* Convert double extended precision float PE to e type Y. */ - -static void -e64toe (pe, y) - const UEMUSHORT *pe; - UEMUSHORT *y; -{ - UEMUSHORT yy[NI]; - const UEMUSHORT *e; - UEMUSHORT *p, *q; - int i; - - e = pe; - p = yy; - for (i = 0; i < NE - 5; i++) - *p++ = 0; -/* This precision is not ordinarily supported on DEC or IBM. */ -#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++; - - /* For denormal long double Intel format, shift significand up one - -- but only if the top significand bit is zero. A top bit of 1 - is "pseudodenormal" when the exponent is zero. */ - if ((yy[NE-1] & 0x7fff) == 0 && (yy[NE-2] & 0x8000) == 0) - { - UEMUSHORT temp[NI]; - - emovi (yy, temp); - eshup1 (temp); - emovo (temp,y); - return; - } - } - else - { - p = &yy[0] + (NE - 1); -#ifdef ARM_EXTENDED_IEEE_FORMAT - /* For ARMs, the exponent is in the lowest 15 bits of the word. */ - *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 - /* Point to the exponent field and check max exponent cases. */ - 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) - /* Anything but 0x8000 here, including 0, is a NaN. */ - || (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 /* not ARM */ - /* In Motorola extended precision format, the most significant - bit of an infinity mantissa could be either 1 or 0. It is - the lower order bits that tell whether the value is a NaN. */ - 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 /* not ARM */ - } -#endif /* NANS */ - eclear (y); - einfin (y); - if (*p & 0x8000) - eneg (y); - return; - } -#endif /* INFINITY */ - p = yy; - q = y; - for (i = 0; i < NE; i++) - *q++ = *p++; -} - -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) -/* Convert 128-bit long double precision float PE to e type Y. */ - -static void -e113toe (pe, y) - const UEMUSHORT *pe; - UEMUSHORT *y; -{ - UEMUSHORT r; - const UEMUSHORT *e; - UEMUSHORT *p; - UEMUSHORT 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 /* NANS */ - eclear (y); - einfin (y); - if (yy[0]) - eneg (y); - return; - } -#endif /* INFINITY */ - 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 denormal, remove the implied bit; else shift down 1. */ - if (r == 0) - { - yy[M] = 0; - } - else - { - yy[M] = 1; - eshift (yy, -1); - } - emovo (yy, y); -} -#endif - -/* Convert single precision float PE to e type Y. */ - -static void -e24toe (pe, y) - const UEMUSHORT *pe; - UEMUSHORT *y; -{ -#ifdef IBM - - ibmtoe (pe, y, SFmode); - -#else - -#ifdef C4X - - c4xtoe (pe, y, QFmode); - -#else - - UEMUSHORT r; - const UEMUSHORT *e; - UEMUSHORT *p; - UEMUSHORT yy[NI]; - int denorm, k; - - e = pe; - denorm = 0; /* flag if denormalized number */ - 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; /* strip sign and 7 significand bits */ -#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 /* NANS */ - eclear (y); - einfin (y); - if (yy[0]) - eneg (y); - return; - } -#endif /* INFINITY */ - r >>= 7; - /* If zero exponent, then the significand is denormalized. - So take back the understood high significand bit. */ - 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 zero exponent, then normalize the significand */ - if ((k = enormlz (yy)) > NBITS) - ecleazs (yy); - else - yy[E] -= (UEMUSHORT) (k - 1); - } - emovo (yy, y); -#endif /* not C4X */ -#endif /* not IBM */ -} - -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) -/* Convert e-type X to IEEE 128-bit long double format E. */ - -static void -etoe113 (x, e) - const UEMUSHORT *x; - UEMUSHORT *e; -{ - UEMUSHORT 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 - /* round off to nearest or even */ - rndsav = rndprc; - rndprc = 113; - emdnorm (xi, 0, 0, exp, 64); - rndprc = rndsav; -#ifdef INFINITY - nonorm: -#endif - toe113 (xi, 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 -toe113 (a, b) - UEMUSHORT *a, *b; -{ - UEMUSHORT *p, *q; - UEMUSHORT 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; /* point to output exponent */ - - /* If not denormal, delete the implied bit. */ - if (a[E] != 0) - { - eshup1 (a); - } - /* combine sign and exponent */ - i = *p++; - if (REAL_WORDS_BIG_ENDIAN) - { - if (i) - *q++ = *p++ | 0x8000; - else - *q++ = *p++; - } - else - { - if (i) - *q-- = *p++ | 0x8000; - else - *q-- = *p++; - } - /* skip over guard word */ - ++p; - /* move the significand */ - if (REAL_WORDS_BIG_ENDIAN) - { - for (i = 0; i < 7; i++) - *q++ = *p++; - } - else - { - for (i = 0; i < 7; i++) - *q-- = *p++; - } -} -#endif - -/* Convert e-type X to IEEE double extended format E. */ - -static void -etoe64 (x, e) - const UEMUSHORT *x; - UEMUSHORT *e; -{ - UEMUSHORT xi[NI]; - EMULONG exp; - int rndsav; - -#ifdef NANS - if (eisnan (x)) - { - make_nan (e, eisneg (x), XFmode); - return; - } -#endif - emovi (x, xi); - /* adjust exponent for offset */ - exp = (EMULONG) xi[E]; -#ifdef INFINITY - if (eisinf (x)) - goto nonorm; -#endif - /* round off to nearest or even */ - rndsav = rndprc; - rndprc = 64; - emdnorm (xi, 0, 0, exp, 64); - rndprc = rndsav; -#ifdef INFINITY - nonorm: -#endif - toe64 (xi, e); -} - -/* Convert exploded e-type X, that has already been rounded to - 64-bit precision, to IEEE double extended format Y. */ - -static void -toe64 (a, b) - UEMUSHORT *a, *b; -{ - UEMUSHORT *p, *q; - UEMUSHORT i; - -#ifdef NANS - if (eiisnan (a)) - { - make_nan (b, eiisneg (a), XFmode); - return; - } -#endif - /* Shift denormal long double Intel format significand down one bit. */ - 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; /* point to output exponent */ - /* Clear the last two bytes of 12-byte Intel format. q is pointing - into an array of size 6 (e.g. x[NE]), so the last two bytes are - always there, and there are never more bytes, even when we are using - INTEL_EXTENDED_IEEE_FORMAT. */ - *(q+1) = 0; - } -#endif - - /* combine sign and exponent */ - 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 - /* The exponent is in the lowest 15 bits of the first word. */ - *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 - /* skip over guard word */ - ++p; - /* move the significand */ -#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)) - { - /* Intel long double infinity significand. */ - *q-- = 0x8000; - *q-- = 0; - *q-- = 0; - *q = 0; - return; - } -#endif - for (i = 0; i < 4; i++) - *q-- = *p++; - } -#endif -} - -/* e type to double precision. */ - -#ifdef DEC -/* Convert e-type X to DEC-format double E. */ - -static void -etoe53 (x, e) - const UEMUSHORT *x; - UEMUSHORT *e; -{ - etodec (x, e); /* see etodec.c */ -} - -/* Convert exploded e-type X, that has already been rounded to - 56-bit double precision, to DEC double Y. */ - -static void -toe53 (x, y) - UEMUSHORT *x, *y; -{ - todec (x, y); -} - -#else -#ifdef IBM -/* Convert e-type X to IBM 370-format double E. */ - -static void -etoe53 (x, e) - const UEMUSHORT *x; - UEMUSHORT *e; -{ - etoibm (x, e, DFmode); -} - -/* Convert exploded e-type X, that has already been rounded to - 56-bit precision, to IBM 370 double Y. */ - -static void -toe53 (x, y) - UEMUSHORT *x, *y; -{ - toibm (x, y, DFmode); -} - -#else /* it's neither DEC nor IBM */ -#ifdef C4X -/* Convert e-type X to C4X-format long double E. */ - -static void -etoe53 (x, e) - const UEMUSHORT *x; - UEMUSHORT *e; -{ - etoc4x (x, e, HFmode); -} - -/* Convert exploded e-type X, that has already been rounded to - 56-bit precision, to IBM 370 double Y. */ - -static void -toe53 (x, y) - UEMUSHORT *x, *y; -{ - toc4x (x, y, HFmode); + return &value; } -#else /* it's neither DEC nor IBM nor C4X */ - -/* Convert e-type X to IEEE double E. */ +/* Returns the special REAL_VALUE_TYPE corresponding to 1/3. */ -static void -etoe53 (x, e) - const UEMUSHORT *x; - UEMUSHORT *e; +const REAL_VALUE_TYPE * +dconst_third_ptr (void) { - UEMUSHORT xi[NI]; - EMULONG exp; - int rndsav; + static REAL_VALUE_TYPE value; -#ifdef NANS - if (eisnan (x)) + /* Initialize mathematical constants for constant folding builtins. + These constants need to be given to at least 160 bits precision. */ + if (value.cl == rvc_zero) { - make_nan (e, eisneg (x), DFmode); - return; + real_arithmetic (&value, RDIV_EXPR, &dconst1, real_digit (3)); } -#endif - emovi (x, xi); - /* adjust exponent for offsets */ - exp = (EMULONG) xi[E] - (EXONE - 0x3ff); -#ifdef INFINITY - if (eisinf (x)) - goto nonorm; -#endif - /* round off to nearest or even */ - rndsav = rndprc; - rndprc = 53; - emdnorm (xi, 0, 0, exp, 64); - rndprc = rndsav; -#ifdef INFINITY - nonorm: -#endif - toe53 (xi, e); + return &value; } -/* Convert exploded e-type X, that has already been rounded to - 53-bit precision, to IEEE double Y. */ +/* Returns the special REAL_VALUE_TYPE corresponding to sqrt(2). */ -static void -toe53 (x, y) - UEMUSHORT *x, *y; +const REAL_VALUE_TYPE * +dconst_sqrt2_ptr (void) { - UEMUSHORT i; - UEMUSHORT *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; /* output high order */ - if (*p++) - *y = 0x8000; /* output sign bit */ + static REAL_VALUE_TYPE value; - i = *p++; - if (i >= (unsigned int) 2047) - { - /* Saturate at largest number less than infinity. */ -#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 |= (UEMUSHORT) 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++ & (UEMUSHORT) 0x0f; /* *p = xi[M] */ - *y |= (UEMUSHORT) i; /* high order output already has sign bit set */ - if (! REAL_WORDS_BIG_ENDIAN) - { - *(--y) = *p++; - *(--y) = *p++; - *(--y) = *p; - } - else + /* Initialize mathematical constants for constant folding builtins. + These constants need to be given to at least 160 bits precision. */ + if (value.cl == rvc_zero) { - ++y; - *y++ = *p++; - *y++ = *p++; - *y++ = *p++; + mpfr_t m; + mpfr_init2 (m, SIGNIFICAND_BITS); + mpfr_sqrt_ui (m, 2, GMP_RNDN); + real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN); + mpfr_clear (m); } + return &value; } -#endif /* not C4X */ -#endif /* not IBM */ -#endif /* not DEC */ - - - -/* e type to single precision. */ - -#ifdef IBM -/* Convert e-type X to IBM 370 float E. */ - -static void -etoe24 (x, e) - const UEMUSHORT *x; - UEMUSHORT *e; -{ - etoibm (x, e, SFmode); -} - -/* Convert exploded e-type X, that has already been rounded to - float precision, to IBM 370 float Y. */ - -static void -toe24 (x, y) - UEMUSHORT *x, *y; -{ - toibm (x, y, SFmode); -} - -#else - -#ifdef C4X -/* Convert e-type X to C4X float E. */ - -static void -etoe24 (x, e) - const UEMUSHORT *x; - UEMUSHORT *e; -{ - etoc4x (x, e, QFmode); -} - -/* Convert exploded e-type X, that has already been rounded to - float precision, to IBM 370 float Y. */ - -static void -toe24 (x, y) - UEMUSHORT *x, *y; -{ - toc4x (x, y, QFmode); -} - -#else - -/* Convert e-type X to IEEE float E. DEC float is the same as IEEE float. */ +/* Fills R with +Inf. */ -static void -etoe24 (x, e) - const UEMUSHORT *x; - UEMUSHORT *e; +void +real_inf (REAL_VALUE_TYPE *r) { - EMULONG exp; - UEMUSHORT xi[NI]; - int rndsav; - -#ifdef NANS - if (eisnan (x)) - { - make_nan (e, eisneg (x), SFmode); - return; - } -#endif - emovi (x, xi); - /* adjust exponent for offsets */ - exp = (EMULONG) xi[E] - (EXONE - 0177); -#ifdef INFINITY - if (eisinf (x)) - goto nonorm; -#endif - /* round off to nearest or even */ - rndsav = rndprc; - rndprc = 24; - emdnorm (xi, 0, 0, exp, 64); - rndprc = rndsav; -#ifdef INFINITY - nonorm: -#endif - toe24 (xi, e); + get_inf (r, 0); } -/* Convert exploded e-type X, that has already been rounded to - float precision, to IEEE float Y. */ +/* Fills R with a NaN whose significand is described by STR. If QUIET, + we force a QNaN, else we force an SNaN. The string, if not empty, + is parsed as a number and placed in the significand. Return true + if the string was successfully parsed. */ -static void -toe24 (x, y) - UEMUSHORT *x, *y; +bool +real_nan (REAL_VALUE_TYPE *r, const char *str, int quiet, + enum machine_mode mode) { - UEMUSHORT i; - UEMUSHORT *p; + const struct real_format *fmt; -#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; /* output high order */ - if (*p++) - *y = 0x8000; /* output sign bit */ + fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt); - i = *p++; -/* Handle overflow cases. */ - if (i >= 255) + if (*str == 0) { -#ifdef INFINITY - *y |= (UEMUSHORT) 0x7f80; -#ifdef DEC - *(--y) = 0; -#endif -#ifdef IEEE - if (! REAL_WORDS_BIG_ENDIAN) - *(--y) = 0; - else - { - ++y; - *y = 0; - } -#endif -#else /* no INFINITY */ - *y |= (UEMUSHORT) 0x7f7f; -#ifdef DEC - *(--y) = 0xffff; -#endif -#ifdef IEEE - if (! REAL_WORDS_BIG_ENDIAN) - *(--y) = 0xffff; + if (quiet) + get_canonical_qnan (r, 0); else - { - ++y; - *y = 0xffff; - } -#endif -#ifdef ERANGE - errno = ERANGE; -#endif -#endif /* no INFINITY */ - return; - } - if (i == 0) - { - eshift (x, 7); - } - else - { - i <<= 7; - eshift (x, 8); + get_canonical_snan (r, 0); } - i |= *p++ & (UEMUSHORT) 0x7f; /* *p = xi[M] */ - /* High order output already has sign bit set. */ - *y |= i; -#ifdef DEC - *(--y) = *p; -#endif -#ifdef IEEE - if (! REAL_WORDS_BIG_ENDIAN) - *(--y) = *p; else { - ++y; - *y = *p; - } -#endif -} -#endif /* not C4X */ -#endif /* not IBM */ + int base = 10, d; -/* 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. */ + memset (r, 0, sizeof (*r)); + r->cl = rvc_nan; -static int -ecmp (a, b) - const UEMUSHORT *a, *b; -{ - UEMUSHORT ai[NI], bi[NI]; - UEMUSHORT *p, *q; - int i; - int msign; + /* Parse akin to strtol into the significand of R. */ -#ifdef NANS - if (eisnan (a) || eisnan (b)) - return (-2); -#endif - emovi (a, ai); - p = ai; - emovi (b, bi); - q = bi; - - if (*p != *q) - { /* the signs are different */ - /* -0 equals + 0 */ - for (i = 1; i < NI - 1; i++) + while (ISSPACE (*str)) + str++; + if (*str == '-') + str++; + else if (*str == '+') + str++; + if (*str == '0') { - if (ai[i] != 0) - goto nzro; - if (bi[i] != 0) - goto nzro; + str++; + if (*str == 'x' || *str == 'X') + { + base = 16; + str++; + } + else + base = 8; } - return (0); - nzro: - if (*p == 0) - return (1); - else - return (-1); - } - /* both are the same sign */ - if (*p == 0) - msign = 1; - else - msign = -1; - i = NI - 1; - do - { - if (*p++ != *q++) + + while ((d = hex_value (*str)) < base) { - goto diff; + REAL_VALUE_TYPE u; + + switch (base) + { + case 8: + lshift_significand (r, r, 3); + break; + case 16: + lshift_significand (r, r, 4); + break; + case 10: + lshift_significand_1 (&u, r); + lshift_significand (r, r, 3); + add_significands (r, r, &u); + break; + default: + gcc_unreachable (); + } + + get_zero (&u, 0); + u.sig[0] = d; + add_significands (r, r, &u); + + str++; } - } - while (--i > 0); - return (0); /* equality */ + /* Must have consumed the entire string for success. */ + if (*str != 0) + return false; - diff: + /* Shift the significand into place such that the bits + are in the most significant bits for the format. */ + lshift_significand (r, r, SIGNIFICAND_BITS - fmt->pnan); - if (*(--p) > *(--q)) - return (msign); /* p is bigger */ - else - return (-msign); /* p is littler */ -} + /* Our MSB is always unset for NaNs. */ + r->sig[SIGSZ-1] &= ~SIG_MSB; -#if 0 -/* Find e-type nearest integer to X, as floor (X + 0.5). */ + /* Force quiet or signalling NaN. */ + r->signalling = !quiet; + } -static void -eround (x, y) - const UEMUSHORT *x; - UEMUSHORT *y; -{ - eadd (ehalf, x, y); - efloor (y, y); + return true; } -#endif /* 0 */ -/* Convert HOST_WIDE_INT LP to e type Y. */ +/* Fills R with the largest finite value representable in mode MODE. + If SIGN is nonzero, R is set to the most negative finite value. */ -static void -ltoe (lp, y) - const HOST_WIDE_INT *lp; - UEMUSHORT *y; +void +real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode) { - UEMUSHORT yi[NI]; - unsigned HOST_WIDE_INT ll; - int k; + const struct real_format *fmt; + int np2; - ecleaz (yi); - if (*lp < 0) - { - /* make it positive */ - ll = (unsigned HOST_WIDE_INT) (-(*lp)); - yi[0] = 0xffff; /* put correct sign in the e type number */ - } + fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt); + memset (r, 0, sizeof (*r)); + + if (fmt->b == 10) + decimal_real_maxval (r, sign, mode); else { - ll = (unsigned HOST_WIDE_INT) (*lp); - } - /* move the long integer to yi significand area */ -#if HOST_BITS_PER_WIDE_INT == 64 - yi[M] = (UEMUSHORT) (ll >> 48); - yi[M + 1] = (UEMUSHORT) (ll >> 32); - yi[M + 2] = (UEMUSHORT) (ll >> 16); - yi[M + 3] = (UEMUSHORT) ll; - yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */ -#else - yi[M] = (UEMUSHORT) (ll >> 16); - yi[M + 1] = (UEMUSHORT) ll; - yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */ -#endif + r->cl = rvc_normal; + r->sign = sign; + SET_REAL_EXP (r, fmt->emax); - if ((k = enormlz (yi)) > NBITS)/* normalize the significand */ - ecleaz (yi); /* it was zero */ - else - yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */ - emovo (yi, y); /* output the answer */ + np2 = SIGNIFICAND_BITS - fmt->p; + memset (r->sig, -1, SIGSZ * sizeof (unsigned long)); + clear_significand_below (r, np2); + + if (fmt->pnan < fmt->p) + /* This is an IBM extended double format made up of two IEEE + doubles. The value of the long double is the sum of the + values of the two parts. The most significant part is + required to be the value of the long double rounded to the + nearest double. Rounding means we need a slightly smaller + value for LDBL_MAX. */ + clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan - 1); + } } -/* Convert unsigned HOST_WIDE_INT LP to e type Y. */ +/* Fills R with 2**N. */ -static void -ultoe (lp, y) - const unsigned HOST_WIDE_INT *lp; - UEMUSHORT *y; +void +real_2expN (REAL_VALUE_TYPE *r, int n, enum machine_mode fmode) { - UEMUSHORT yi[NI]; - unsigned HOST_WIDE_INT ll; - int k; - - ecleaz (yi); - ll = *lp; - - /* move the long integer to ayi significand area */ -#if HOST_BITS_PER_WIDE_INT == 64 - yi[M] = (UEMUSHORT) (ll >> 48); - yi[M + 1] = (UEMUSHORT) (ll >> 32); - yi[M + 2] = (UEMUSHORT) (ll >> 16); - yi[M + 3] = (UEMUSHORT) ll; - yi[E] = EXONE + 47; /* exponent if normalize shift count were 0 */ -#else - yi[M] = (UEMUSHORT) (ll >> 16); - yi[M + 1] = (UEMUSHORT) ll; - yi[E] = EXONE + 15; /* exponent if normalize shift count were 0 */ -#endif + memset (r, 0, sizeof (*r)); - if ((k = enormlz (yi)) > NBITS)/* normalize the significand */ - ecleaz (yi); /* it was zero */ + n++; + if (n > MAX_EXP) + r->cl = rvc_inf; + else if (n < -MAX_EXP) + ; else - yi[E] -= (UEMUSHORT) k; /* subtract shift count from exponent */ - emovo (yi, y); /* output the answer */ + { + r->cl = rvc_normal; + SET_REAL_EXP (r, n); + r->sig[SIGSZ-1] = SIG_MSB; + } + if (DECIMAL_FLOAT_MODE_P (fmode)) + decimal_real_convert (r, fmode, r); } - -/* Find signed HOST_WIDE_INT integer I and floating point fractional - part FRAC of e-type (packed internal format) floating point input X. - The integer output I has the sign of the input, except that - positive overflow is permitted if FIXUNS_TRUNC_LIKE_FIX_TRUNC. - The output e-type fraction FRAC is the positive fractional - part of abs (X). */ - + static void -eifrac (x, i, frac) - const UEMUSHORT *x; - HOST_WIDE_INT *i; - UEMUSHORT *frac; +round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) { - UEMUSHORT xi[NI]; - int j, k; - unsigned HOST_WIDE_INT ll; + int p2, np2, i, w; + int emin2m1, emax2; + bool round_up = false; - emovi (x, xi); - k = (int) xi[E] - (EXONE - 1); - if (k <= 0) - { - /* if exponent <= 0, integer = 0 and real output is fraction */ - *i = 0L; - emovo (xi, frac); - return; - } - if (k > (HOST_BITS_PER_WIDE_INT - 1)) + if (r->decimal) { - /* long integer overflow: output large integer - and correct fraction */ - if (xi[0]) - *i = ((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1); - else + if (fmt->b == 10) { -#ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC - /* In this case, let it overflow and convert as if unsigned. */ - euifrac (x, &ll, frac); - *i = (HOST_WIDE_INT) ll; + decimal_round_for_format (fmt, r); return; -#else - /* In other cases, return the largest positive integer. */ - *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) - { - /* Shift more than 16 bits: first shift up k-16 mod 16, - then shift up by 16's. */ - 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); + /* FIXME. We can come here via fp_easy_constant + (e.g. -O0 on '_Decimal32 x = 1.0 + 2.0dd'), but have not + investigated whether this convert needs to be here, or + something else is missing. */ + decimal_real_convert (r, DFmode, r); } - else - { - /* shift not more than 16 bits */ - 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] -= (UEMUSHORT) k; - - emovo (xi, frac); -} - -/* Find unsigned HOST_WIDE_INT integer I and floating point fractional part - FRAC of e-type X. A negative input yields integer output = 0 but - correct fraction. */ - -static void -euifrac (x, i, frac) - const UEMUSHORT *x; - unsigned HOST_WIDE_INT *i; - UEMUSHORT *frac; -{ - unsigned HOST_WIDE_INT ll; - UEMUSHORT xi[NI]; - int j, k; + p2 = fmt->p; + emin2m1 = fmt->emin - 1; + emax2 = fmt->emax; - emovi (x, xi); - k = (int) xi[E] - (EXONE - 1); - if (k <= 0) + np2 = SIGNIFICAND_BITS - p2; + switch (r->cl) { - /* if exponent <= 0, integer = 0 and argument is fraction */ - *i = 0L; - emovo (xi, frac); + underflow: + get_zero (r, r->sign); + case rvc_zero: + if (!fmt->has_signed_zero) + r->sign = 0; return; - } - if (k > HOST_BITS_PER_WIDE_INT) - { - /* Long integer overflow: output large integer - and correct fraction. - Note, the BSD MicroVAX compiler says that ~(0UL) - is a syntax error. */ - *i = ~(0L); - eshift (xi, k); - if (extra_warnings) - warning ("overflow on truncation to unsigned integer"); - } - else if (k > 16) - { - /* Shift more than 16 bits: first shift up k-16 mod 16, - then shift up by 16's. */ - 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 - { - /* shift not more than 16 bits */ - eshift (xi, k); - *i = (HOST_WIDE_INT) xi[M] & 0xffff; - } - - if (xi[0]) /* A negative value yields unsigned integer 0. */ - *i = 0L; - - xi[0] = 0; - xi[E] = EXONE - 1; - xi[M] = 0; - if ((k = enormlz (xi)) > NBITS) - ecleaz (xi); - else - xi[E] -= (UEMUSHORT) k; - - emovo (xi, frac); -} - -/* Shift the significand of exploded e-type X up or down by SC bits. */ - -static int -eshift (x, sc) - UEMUSHORT *x; - int sc; -{ - UEMUSHORT lost; - UEMUSHORT *p; - - if (sc == 0) - return (0); - lost = 0; - p = x + NI - 1; + overflow: + get_inf (r, r->sign); + case rvc_inf: + return; - if (sc < 0) - { - sc = -sc; - while (sc >= 16) - { - lost |= *p; /* remember lost bits */ - eshdn6 (x); - sc -= 16; - } + case rvc_nan: + clear_significand_below (r, np2); + return; - while (sc >= 8) - { - lost |= *p & 0xff; - eshdn8 (x); - sc -= 8; - } + case rvc_normal: + break; - while (sc > 0) - { - lost |= *p & 1; - eshdn1 (x); - sc -= 1; - } + default: + gcc_unreachable (); } - else + + /* Check the range of the exponent. If we're out of range, + either underflow or overflow. */ + if (REAL_EXP (r) > emax2) + goto overflow; + else if (REAL_EXP (r) <= emin2m1) { - while (sc >= 16) - { - eshup6 (x); - sc -= 16; - } + int diff; - while (sc >= 8) + if (!fmt->has_denorm) { - eshup8 (x); - sc -= 8; + /* Don't underflow completely until we've had a chance to round. */ + if (REAL_EXP (r) < emin2m1) + goto underflow; } - - while (sc > 0) + else { - eshup1 (x); - sc -= 1; - } - } - if (lost) - lost = 1; - return ((int) lost); -} - -/* Shift normalize the significand area of exploded e-type X. - Return the shift count (up = positive). */ - -static int -enormlz (x) - UEMUSHORT x[]; -{ - UEMUSHORT *p; - int sc; - - sc = 0; - p = &x[M]; - if (*p != 0) - goto normdn; - ++p; - if (*p & 0x8000) - return (0); /* already normalized */ - while (*p == 0) - { - eshup6 (x); - sc += 16; + diff = emin2m1 - REAL_EXP (r) + 1; + if (diff > p2) + goto underflow; - /* With guard word, there are NBITS+16 bits available. - Return true if all are zero. */ - if (sc > NBITS) - return (sc); - } - /* see if high byte is zero */ - while ((*p & 0xff00) == 0) - { - eshup8 (x); - sc += 8; - } - /* now shift 1 bit at a time */ - while ((*p & 0x8000) == 0) - { - eshup1 (x); - sc += 1; - if (sc > NBITS) - { - mtherr ("enormlz", UNDERFLOW); - return (sc); + /* De-normalize the significand. */ + r->sig[0] |= sticky_rshift_significand (r, r, diff); + SET_REAL_EXP (r, REAL_EXP (r) + diff); } } - return (sc); - /* Normalize by shifting down out of the high guard word - of the significand */ - normdn: - - if (*p & 0xff00) + if (!fmt->round_towards_zero) { - eshdn8 (x); - sc -= 8; + /* There are P2 true significand bits, followed by one guard bit, + followed by one sticky bit, followed by stuff. Fold nonzero + stuff into the sticky bit. */ + unsigned long sticky; + bool guard, lsb; + + sticky = 0; + for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i) + sticky |= r->sig[i]; + sticky |= r->sig[w] + & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1); + + guard = test_significand_bit (r, np2 - 1); + lsb = test_significand_bit (r, np2); + + /* Round to even. */ + round_up = guard && (sticky || lsb); } - while (*p != 0) + + if (round_up) { - eshdn1 (x); - sc -= 1; + REAL_VALUE_TYPE u; + get_zero (&u, 0); + set_significand_bit (&u, np2); - if (sc < -NBITS) + if (add_significands (r, r, &u)) { - mtherr ("enormlz", OVERFLOW); - return (sc); + /* Overflow. Means the significand had been all ones, and + is now all zeros. Need to increase the exponent, and + possibly re-normalize it. */ + SET_REAL_EXP (r, REAL_EXP (r) + 1); + if (REAL_EXP (r) > emax2) + goto overflow; + r->sig[SIGSZ-1] = SIG_MSB; } } - return (sc); -} -/* Powers of ten used in decimal <-> binary conversions. */ + /* Catch underflow that we deferred until after rounding. */ + if (REAL_EXP (r) <= emin2m1) + goto underflow; -#define NTEN 12 -#define MAXP 4096 + /* Clear out trailing garbage. */ + clear_significand_below (r, np2); +} -#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && (INTEL_EXTENDED_IEEE_FORMAT == 0) -static const UEMUSHORT etens[NTEN + 1][NE] = -{ - {0x6576, 0x4a92, 0x804a, 0x153f, - 0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */ - {0x6a32, 0xce52, 0x329a, 0x28ce, - 0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */ - {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,}, /* 10**1 */ -}; - -static const UEMUSHORT emtens[NTEN + 1][NE] = -{ - {0x2030, 0xcffc, 0xa1c3, 0x8123, - 0x2de3, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */ - {0x8264, 0xd2cb, 0xf2ea, 0x12d4, - 0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */ - {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,}, /* 10**-1 */ -}; -#else -/* LONG_DOUBLE_TYPE_SIZE is other than 128 */ -static const UEMUSHORT etens[NTEN + 1][NE] = +/* Extend or truncate to a new mode. */ + +void +real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode, + const REAL_VALUE_TYPE *a) { - {0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */ - {0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */ - {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,}, /* 10**1 */ -}; - -static const UEMUSHORT emtens[NTEN + 1][NE] = + const struct real_format *fmt; + + fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt); + + *r = *a; + + if (a->decimal || fmt->b == 10) + decimal_real_convert (r, mode, a); + + round_for_format (fmt, r); + + /* round_for_format de-normalizes denormals. Undo just that part. */ + if (r->cl == rvc_normal) + normalize (r); +} + +/* Legacy. Likewise, except return the struct directly. */ + +REAL_VALUE_TYPE +real_value_truncate (enum machine_mode mode, REAL_VALUE_TYPE a) { - {0x2de4, 0x9fde, 0xd2ce, 0x04c8, 0xa6dd, 0x0ad8,}, /* 10**-4096 */ - {0x4925, 0x2de4, 0x3436, 0x534f, 0xceae, 0x256b,}, /* 10**-2048 */ - {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,}, /* 10**-1 */ -}; -#endif + REAL_VALUE_TYPE r; + real_convert (&r, mode, &a); + return r; +} -#if 0 -/* Convert float value X to ASCII string STRING with NDIG digits after - the decimal point. */ +/* Return true if truncating to MODE is exact. */ -static void -e24toasc (x, string, ndigs) - const UEMUSHORT x[]; - char *string; - int ndigs; +bool +exact_real_truncate (enum machine_mode mode, const REAL_VALUE_TYPE *a) { - UEMUSHORT w[NI]; + const struct real_format *fmt; + REAL_VALUE_TYPE t; + int emin2m1; + + fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt); - e24toe (x, w); - etoasc (w, string, ndigs); + /* Don't allow conversion to denormals. */ + emin2m1 = fmt->emin - 1; + if (REAL_EXP (a) <= emin2m1) + return false; + + /* After conversion to the new mode, the value must be identical. */ + real_convert (&t, mode, a); + return real_identical (&t, a); } -/* Convert double value X to ASCII string STRING with NDIG digits after - the decimal point. */ +/* Write R to the given target format. Place the words of the result + in target word order in BUF. There are always 32 bits in each + long, no matter the size of the host long. -static void -e53toasc (x, string, ndigs) - const UEMUSHORT x[]; - char *string; - int ndigs; + Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE. */ + +long +real_to_target_fmt (long *buf, const REAL_VALUE_TYPE *r_orig, + const struct real_format *fmt) { - UEMUSHORT w[NI]; + REAL_VALUE_TYPE r; + long buf1; + + r = *r_orig; + round_for_format (fmt, &r); - e53toe (x, w); - etoasc (w, string, ndigs); + if (!buf) + buf = &buf1; + (*fmt->encode) (fmt, buf, &r); + + return *buf; } -/* Convert double extended value X to ASCII string STRING with NDIG digits - after the decimal point. */ +/* Similar, but look up the format from MODE. */ -static void -e64toasc (x, string, ndigs) - const UEMUSHORT x[]; - char *string; - int ndigs; +long +real_to_target (long *buf, const REAL_VALUE_TYPE *r, enum machine_mode mode) { - UEMUSHORT w[NI]; + const struct real_format *fmt; + + fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt); - e64toe (x, w); - etoasc (w, string, ndigs); + return real_to_target_fmt (buf, r, fmt); } -/* Convert 128-bit long double value X to ASCII string STRING with NDIG digits - after the decimal point. */ +/* Read R from the given target format. Read the words of the result + in target word order in BUF. There are always 32 bits in each + long, no matter the size of the host long. */ -static void -e113toasc (x, string, ndigs) - const UEMUSHORT x[]; - char *string; - int ndigs; +void +real_from_target_fmt (REAL_VALUE_TYPE *r, const long *buf, + const struct real_format *fmt) { - UEMUSHORT w[NI]; - - e113toe (x, w); - etoasc (w, string, ndigs); + (*fmt->decode) (fmt, r, buf); } -#endif /* 0 */ -/* Convert e-type X to ASCII string STRING with NDIGS digits after - the decimal point. */ +/* Similar, but look up the format from MODE. */ + +void +real_from_target (REAL_VALUE_TYPE *r, const long *buf, enum machine_mode mode) +{ + const struct real_format *fmt; -static char wstring[80]; /* working storage for ASCII output */ + fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt); -static void -etoasc (x, string, ndigs) - const UEMUSHORT x[]; - char *string; - int ndigs; + (*fmt->decode) (fmt, r, buf); +} + +/* Return the number of bits of the largest binary value that the + significand of MODE will hold. */ +/* ??? Legacy. Should get access to real_format directly. */ + +int +significand_size (enum machine_mode mode) { - EMUSHORT digit; - UEMUSHORT y[NI], t[NI], u[NI], w[NI]; - const UEMUSHORT *p, *r, *ten; - UEMUSHORT sign; - int i, j, k, expon, rndsav; - char *s, *ss; - UEMUSHORT m; - - - rndsav = rndprc; - ss = string; - s = wstring; - *ss = '\0'; - *s = '\0'; -#ifdef NANS - if (eisnan (x)) + const struct real_format *fmt; + + fmt = REAL_MODE_FORMAT (mode); + if (fmt == NULL) + return 0; + + if (fmt->b == 10) { - sprintf (wstring, " NaN "); - goto bxit; + /* Return the size in bits of the largest binary value that can be + held by the decimal coefficient for this mode. This is one more + than the number of bits required to hold the largest coefficient + of this mode. */ + double log2_10 = 3.3219281; + return fmt->p * log2_10; } -#endif - rndprc = NBITS; /* set to full precision */ - emov (x, y); /* retain external format */ - if (y[NE - 1] & 0x8000) + return fmt->p; +} + +/* Return a hash value for the given real value. */ +/* ??? The "unsigned int" return value is intended to be hashval_t, + but I didn't want to pull hashtab.h into real.h. */ + +unsigned int +real_hash (const REAL_VALUE_TYPE *r) +{ + unsigned int h; + size_t i; + + h = r->cl | (r->sign << 2); + switch (r->cl) { - sign = 0xffff; - y[NE - 1] &= 0x7fff; + case rvc_zero: + case rvc_inf: + return h; + + case rvc_normal: + h |= REAL_EXP (r) << 3; + break; + + case rvc_nan: + if (r->signalling) + h ^= (unsigned int)-1; + if (r->canonical) + return h; + break; + + default: + gcc_unreachable (); } + + if (sizeof(unsigned long) > sizeof(unsigned int)) + for (i = 0; i < SIGSZ; ++i) + { + unsigned long s = r->sig[i]; + h ^= s ^ (s >> (HOST_BITS_PER_LONG / 2)); + } else + for (i = 0; i < SIGSZ; ++i) + h ^= r->sig[i]; + + return h; +} + +/* IEEE single-precision format. */ + +static void encode_ieee_single (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_ieee_single (const struct real_format *, + REAL_VALUE_TYPE *, const long *); + +static void +encode_ieee_single (const struct real_format *fmt, long *buf, + const REAL_VALUE_TYPE *r) +{ + unsigned long image, sig, exp; + unsigned long sign = r->sign; + bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; + + image = sign << 31; + sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff; + + switch (r->cl) { - sign = 0; - } - expon = 0; - ten = &etens[NTEN][0]; - emov (eone, t); - /* Test for zero exponent */ - if (y[NE - 1] == 0) - { - for (k = 0; k < NE - 1; k++) + case rvc_zero: + break; + + case rvc_inf: + if (fmt->has_inf) + image |= 255 << 23; + else + image |= 0x7fffffff; + break; + + case rvc_nan: + if (fmt->has_nans) { - if (y[k] != 0) - goto tnzro; /* denormalized number */ + if (r->canonical) + sig = (fmt->canonical_nan_lsbs_set ? (1 << 22) - 1 : 0); + if (r->signalling == fmt->qnan_msb_set) + sig &= ~(1 << 22); + else + sig |= 1 << 22; + if (sig == 0) + sig = 1 << 21; + + image |= 255 << 23; + image |= sig; } - goto isone; /* valid all zeros */ - } - tnzro: + else + image |= 0x7fffffff; + break; - /* Test for infinity. */ - if (y[NE - 1] == 0x7fff) - { - if (sign) - sprintf (wstring, " -Infinity "); + case rvc_normal: + /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, + whereas the intermediate representation is 0.F x 2**exp. + Which means we're off by one. */ + if (denormal) + exp = 0; else - sprintf (wstring, " Infinity "); - goto bxit; - } + exp = REAL_EXP (r) + 127 - 1; + image |= exp << 23; + image |= sig; + break; - /* Test for exponent nonzero but significand denormalized. - * This is an error condition. - */ - if ((y[NE - 1] != 0) && ((y[NE - 2] & 0x8000) == 0)) - { - mtherr ("etoasc", DOMAIN); - sprintf (wstring, "NaN"); - goto bxit; + default: + gcc_unreachable (); } - /* Compare to 1.0 */ - i = ecmp (eone, y); - if (i == 0) - goto isone; + buf[0] = image; +} - if (i == -2) - abort (); +static void +decode_ieee_single (const struct real_format *fmt, REAL_VALUE_TYPE *r, + const long *buf) +{ + unsigned long image = buf[0] & 0xffffffff; + bool sign = (image >> 31) & 1; + int exp = (image >> 23) & 0xff; - if (i < 0) - { /* Number is greater than 1 */ - /* Convert significand to an integer and strip trailing decimal zeros. */ - emov (y, u); - u[NE - 1] = EXONE + NBITS - 1; + memset (r, 0, sizeof (*r)); + image <<= HOST_BITS_PER_LONG - 24; + image &= ~SIG_MSB; - 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); - - /* Rescale from integer significand */ - u[NE - 1] += y[NE - 1] - (unsigned int) (EXONE + NBITS - 1); - emov (u, y); - /* Find power of 10 */ - emov (eone, t); - m = MAXP; - p = &etens[0][0]; - /* An unordered compare result shouldn't happen here. */ - while (ecmp (ten, u) <= 0) + if (exp == 0) + { + if (image && fmt->has_denorm) { - if (ecmp (p, u) <= 0) - { - ediv (p, u, u); - emul (p, t, t); - expon += (int) m; - } - m >>= 1; - if (m == 0) - break; - p += NE; + r->cl = rvc_normal; + r->sign = sign; + SET_REAL_EXP (r, -126); + r->sig[SIGSZ-1] = image << 1; + normalize (r); } + else if (fmt->has_signed_zero) + r->sign = sign; } - else - { /* Number is less than 1.0 */ - /* Pad significand with trailing decimal zeros. */ - if (y[NE - 1] == 0) + else if (exp == 255 && (fmt->has_nans || fmt->has_inf)) + { + if (image) { - while ((y[NE - 2] & 0x8000) == 0) - { - emul (ten, y, y); - expon -= 1; - } + r->cl = rvc_nan; + r->sign = sign; + r->signalling = (((image >> (HOST_BITS_PER_LONG - 2)) & 1) + ^ fmt->qnan_msb_set); + r->sig[SIGSZ-1] = image; } else { - emovi (y, w); - for (i = 0; i < NDEC + 1; i++) - { - if ((w[NI - 1] & 0x7) != 0) - break; - /* multiply by 10 */ - 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; + r->cl = rvc_inf; + r->sign = sign; } - ediv (t, eone, t); - } - isone: - /* Find the first (leading) digit. */ - 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++ = ' '; - /* Examine number of digits requested by caller. */ - 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; + r->cl = rvc_normal; + r->sign = sign; + SET_REAL_EXP (r, exp - 127 + 1); + r->sig[SIGSZ-1] = image | SIG_MSB; } - else +} + +const struct real_format ieee_single_format = + { + encode_ieee_single, + decode_ieee_single, + 2, + 24, + 24, + -125, + 128, + 31, + 31, + false, + true, + true, + true, + true, + true, + true, + false + }; + +const struct real_format mips_single_format = + { + encode_ieee_single, + decode_ieee_single, + 2, + 24, + 24, + -125, + 128, + 31, + 31, + false, + true, + true, + true, + true, + true, + false, + true + }; + +const struct real_format motorola_single_format = + { + encode_ieee_single, + decode_ieee_single, + 2, + 24, + 24, + -125, + 128, + 31, + 31, + false, + true, + true, + true, + true, + true, + true, + true + }; + +/* SPU Single Precision (Extended-Range Mode) format is the same as IEEE + single precision with the following differences: + - Infinities are not supported. Instead MAX_FLOAT or MIN_FLOAT + are generated. + - NaNs are not supported. + - The range of non-zero numbers in binary is + (001)[1.]000...000 to (255)[1.]111...111. + - Denormals can be represented, but are treated as +0.0 when + used as an operand and are never generated as a result. + - -0.0 can be represented, but a zero result is always +0.0. + - the only supported rounding mode is trunction (towards zero). */ +const struct real_format spu_single_format = + { + encode_ieee_single, + decode_ieee_single, + 2, + 24, + 24, + -125, + 129, + 31, + 31, + true, + false, + false, + false, + true, + true, + false, + false + }; + +/* IEEE double-precision format. */ + +static void encode_ieee_double (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_ieee_double (const struct real_format *, + REAL_VALUE_TYPE *, const long *); + +static void +encode_ieee_double (const struct real_format *fmt, long *buf, + const REAL_VALUE_TYPE *r) +{ + unsigned long image_lo, image_hi, sig_lo, sig_hi, exp; + bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; + + image_hi = r->sign << 31; + image_lo = 0; + + if (HOST_BITS_PER_LONG == 64) { - *s++ = (char) digit + '0'; - *s++ = '.'; + sig_hi = r->sig[SIGSZ-1]; + sig_lo = (sig_hi >> (64 - 53)) & 0xffffffff; + sig_hi = (sig_hi >> (64 - 53 + 1) >> 31) & 0xfffff; } - /* Generate digits after the decimal point. */ - for (k = 0; k <= ndigs; k++) + else { - /* multiply current number by 10, without normalizing */ - eshup1 (y); - emovz (y, u); - eshup1 (u); - eshup1 (u); - eaddm (u, y); - eiremain (t, y); - *s++ = (char) equot[NI - 1] + '0'; + sig_hi = r->sig[SIGSZ-1]; + sig_lo = r->sig[SIGSZ-2]; + sig_lo = (sig_hi << 21) | (sig_lo >> 11); + sig_hi = (sig_hi >> 11) & 0xfffff; } - digit = equot[NI - 1]; - --s; - ss = s; - /* round off the ASCII string */ - if (digit > 4) + + switch (r->cl) { - /* Test for critical rounding case in ASCII output. */ - if (digit == 5) + case rvc_zero: + break; + + case rvc_inf: + if (fmt->has_inf) + image_hi |= 2047 << 20; + else { - 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 + image_hi |= 0x7fffffff; + image_lo = 0xffffffff; } - /* Round up and propagate carry-outs */ - roun: - --s; - k = *s & CHARMASK; - /* Carry out to most significant digit? */ - if (k == '.') + break; + + case rvc_nan: + if (fmt->has_nans) { - --s; - k = *s; - k += 1; - *s = (char) k; - /* Most significant digit carries to 10? */ - if (k > '9') + if (r->canonical) { - expon += 1; - *s = '1'; + if (fmt->canonical_nan_lsbs_set) + { + sig_hi = (1 << 19) - 1; + sig_lo = 0xffffffff; + } + else + { + sig_hi = 0; + sig_lo = 0; + } } - goto doexp; + if (r->signalling == fmt->qnan_msb_set) + sig_hi &= ~(1 << 19); + else + sig_hi |= 1 << 19; + if (sig_hi == 0 && sig_lo == 0) + sig_hi = 1 << 18; + + image_hi |= 2047 << 20; + image_hi |= sig_hi; + image_lo = sig_lo; } - /* Round up and carry out from less significant digits */ - k += 1; - *s = (char) k; - if (k > '9') + else { - *s = '0'; - goto roun; + image_hi |= 0x7fffffff; + image_lo = 0xffffffff; } - } - doexp: - /* - if (expon >= 0) - sprintf (ss, "e+%d", expon); - else - sprintf (ss, "e%d", expon); - */ - sprintf (ss, "e%d", expon); - bxit: - rndprc = rndsav; - /* copy out the working string */ - s = string; - ss = wstring; - while (*ss == ' ') /* strip possible leading space */ - ++ss; - while ((*s++ = *ss++) != '\0') - ; -} - - -/* Convert ASCII string to floating point. - - Numeric input is a free format decimal number of any length, with - or without decimal point. Entering E after the number followed by an - integer number causes the second number to be interpreted as a power of - 10 to be multiplied by the first number (i.e., "scientific" notation). */ - -/* Convert ASCII string S to single precision float value Y. */ - -static void -asctoe24 (s, y) - const char *s; - UEMUSHORT *y; -{ - asctoeg (s, y, 24); -} - - -/* Convert ASCII string S to double precision value Y. */ - -static void -asctoe53 (s, y) - const char *s; - UEMUSHORT *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 -} + break; + case rvc_normal: + /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, + whereas the intermediate representation is 0.F x 2**exp. + Which means we're off by one. */ + if (denormal) + exp = 0; + else + exp = REAL_EXP (r) + 1023 - 1; + image_hi |= exp << 20; + image_hi |= sig_hi; + image_lo = sig_lo; + break; -/* Convert ASCII string S to double extended value Y. */ + default: + gcc_unreachable (); + } -static void -asctoe64 (s, y) - const char *s; - UEMUSHORT *y; -{ - asctoeg (s, y, 64); + if (FLOAT_WORDS_BIG_ENDIAN) + buf[0] = image_hi, buf[1] = image_lo; + else + buf[0] = image_lo, buf[1] = image_hi; } -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) -/* Convert ASCII string S to 128-bit long double Y. */ - static void -asctoe113 (s, y) - const char *s; - UEMUSHORT *y; +decode_ieee_double (const struct real_format *fmt, REAL_VALUE_TYPE *r, + const long *buf) { - asctoeg (s, y, 113); -} -#endif + unsigned long image_hi, image_lo; + bool sign; + int exp; -/* Convert ASCII string S to e type Y. */ - -static void -asctoe (s, y) - const char *s; - UEMUSHORT *y; -{ - asctoeg (s, y, NBITS); -} + if (FLOAT_WORDS_BIG_ENDIAN) + image_hi = buf[0], image_lo = buf[1]; + else + image_lo = buf[0], image_hi = buf[1]; + image_lo &= 0xffffffff; + image_hi &= 0xffffffff; -/* Convert ASCII string SS to e type Y, with a specified rounding precision - of OPREC bits. BASE is 16 for C99 hexadecimal floating constants. */ + sign = (image_hi >> 31) & 1; + exp = (image_hi >> 20) & 0x7ff; -static void -asctoeg (ss, y, oprec) - const char *ss; - UEMUSHORT *y; - int oprec; -{ - UEMUSHORT yy[NI], xt[NI], tt[NI]; - int esign, decflg, sgnflg, nexp, exp, prec, lost; - int i, k, trail, c, rndsav; - EMULONG lexp; - UEMUSHORT nsign; - char *sp, *s, *lstr; - int base = 10; - - /* Copy the input string. */ - lstr = (char *) alloca (strlen (ss) + 1); - - while (*ss == ' ') /* skip leading spaces */ - ++ss; - - sp = lstr; - while ((*sp++ = *ss++) != '\0') - ; - s = lstr; + memset (r, 0, sizeof (*r)); - if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) - { - base = 16; - s += 2; - } + image_hi <<= 32 - 21; + image_hi |= image_lo >> 21; + image_hi &= 0x7fffffff; + image_lo <<= 32 - 21; - rndsav = rndprc; - rndprc = NBITS; /* Set to full precision */ - lost = 0; - nsign = 0; - decflg = 0; - sgnflg = 0; - nexp = 0; - exp = 0; - prec = 0; - ecleaz (yy); - trail = 0; - - nxtcom: - k = hex_value (*s); - if ((k >= 0) && (k < base)) + if (exp == 0) { - /* Ignore leading zeros */ - if ((prec == 0) && (decflg == 0) && (k == 0)) - goto donchr; - /* Identify and strip trailing zeros after the decimal point. */ - if ((trail == 0) && (decflg != 0)) - { - sp = s; - while (ISDIGIT (*sp) || (base == 16 && ISXDIGIT (*sp))) - ++sp; - /* Check for syntax error */ - c = *sp & CHARMASK; - if ((base != 10 || ((c != 'e') && (c != 'E'))) - && (base != 16 || ((c != 'p') && (c != 'P'))) - && (c != '\0') - && (c != '\n') && (c != '\r') && (c != ' ') - && (c != ',')) - goto unexpected_char_error; - --sp; - while (*sp == '0') - *sp-- = 'z'; - trail = 1; - if (*s == 'z') - goto donchr; - } - - /* If enough digits were given to more than fill up the yy register, - continuing until overflow into the high guard word yy[2] - guarantees that there will be a roundoff bit at the top - of the low guard word after normalization. */ - - if (yy[2] == 0) + if ((image_hi || image_lo) && fmt->has_denorm) { - if (base == 16) + r->cl = rvc_normal; + r->sign = sign; + SET_REAL_EXP (r, -1022); + if (HOST_BITS_PER_LONG == 32) { - if (decflg) - nexp += 4; /* count digits after decimal point */ - - eshup1 (yy); /* multiply current number by 16 */ - eshup1 (yy); - eshup1 (yy); - eshup1 (yy); + image_hi = (image_hi << 1) | (image_lo >> 31); + image_lo <<= 1; + r->sig[SIGSZ-1] = image_hi; + r->sig[SIGSZ-2] = image_lo; } 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] = (UEMUSHORT) k; - eaddm (xt, yy); - } - else - { - /* Mark any lost non-zero digit. */ - lost |= k; - /* Count lost digits before the decimal point. */ - if (decflg == 0) - { - if (base == 10) - nexp -= 1; - else - nexp -= 4; + image_hi = (image_hi << 31 << 2) | (image_lo << 1); + r->sig[SIGSZ-1] = image_hi; } + normalize (r); } - prec += 1; - goto donchr; - } - - switch (*s) - { - case 'z': - break; - case 'E': - case 'e': - case 'P': - case 'p': - goto expnt; - case '.': /* decimal point */ - if (decflg) - goto unexpected_char_error; - ++decflg; - break; - case '-': - nsign = 0xffff; - if (sgnflg) - goto unexpected_char_error; - ++sgnflg; - break; - case '+': - if (sgnflg) - goto unexpected_char_error; - ++sgnflg; - break; - case ',': - case ' ': - case '\0': - case '\n': - case '\r': - goto daldone; - case 'i': - case 'I': - goto infinite; - default: - unexpected_char_error: -#ifdef NANS - einan (yy); -#else - mtherr ("asctoe", DOMAIN); - eclear (yy); -#endif - goto aexit; - } - donchr: - ++s; - goto nxtcom; - - /* Exponent interpretation */ - expnt: - /* 0.0eXXX is zero, regardless of XXX. Check for the 0.0. */ - for (k = 0; k < NI; k++) - { - if (yy[k] != 0) - goto read_expnt; - } - goto aexit; - -read_expnt: - esign = 1; - exp = 0; - ++s; - /* check for + or - */ - if (*s == '-') - { - esign = -1; - ++s; - } - if (*s == '+') - ++s; - while (ISDIGIT (*s)) - { - 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; /* infinity */ - goto aexit; - } - if ((exp < MINDECEXP) && (base == 10)) - { - zero: - ecleaz (yy); - goto aexit; + else if (fmt->has_signed_zero) + r->sign = sign; } - - daldone: - if (base == 16) + else if (exp == 2047 && (fmt->has_nans || fmt->has_inf)) { - /* 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) + if (image_hi || image_lo) { - if (lexp < -NBITS) - goto zero; - lost |= eshift (yy, lexp); - lexp = 0; + r->cl = rvc_nan; + r->sign = sign; + r->signalling = ((image_hi >> 30) & 1) ^ fmt->qnan_msb_set; + if (HOST_BITS_PER_LONG == 32) + { + r->sig[SIGSZ-1] = image_hi; + r->sig[SIGSZ-2] = image_lo; + } + else + r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo; } - 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)) - { - 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; - - /* Convert to external format: - - Multiply by 10**nexp. If precision is 64 bits, - the maximum relative error incurred in forming 10**n - for 0 <= n <= 324 is 8.2e-20, at 10**180. - For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947. - For 0 >= n >= -999, it is -1.55e-19 at 10**-435. */ - - lexp = yy[E]; - if (nexp == 0) - { - k = 0; - goto expdon; - } - esign = 1; - if (nexp < 0) - { - nexp = -nexp; - esign = -1; - if (nexp > 4096) + else { - /* Punt. Can't handle this without 2 divides. */ - emovi (etens[0], tt); - lexp -= tt[E]; - k = edivm (tt, yy); - lexp += EXONE; - nexp -= 4096; - } - } - emov (eone, xt); - exp = 1; - i = NTEN; - do - { - if (exp & nexp) - emul (etens[i], xt, xt); - i--; - exp = exp + exp; - } - while (exp <= MAXP); - - emovi (xt, tt); - if (esign < 0) - { - lexp -= tt[E]; - k = edivm (tt, yy); - lexp += EXONE; + r->cl = rvc_inf; + r->sign = sign; + } } else { - lexp += tt[E]; - k = emulm (tt, yy); - lexp -= EXONE - 1; + r->cl = rvc_normal; + r->sign = sign; + SET_REAL_EXP (r, exp - 1023 + 1); + if (HOST_BITS_PER_LONG == 32) + { + r->sig[SIGSZ-1] = image_hi | SIG_MSB; + r->sig[SIGSZ-2] = image_lo; + } + else + r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo | SIG_MSB; } - lost = k; - - expdon: - - /* Round and convert directly to the destination type */ - 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 /* IBM */ -#endif /* C4X */ -#ifdef DEC - else if (oprec == 56) - lexp -= EXONE - 0201; -#endif - rndprc = oprec; - emdnorm (yy, lost, 0, lexp, 64); +} + +const struct real_format ieee_double_format = + { + encode_ieee_double, + decode_ieee_double, + 2, + 53, + 53, + -1021, + 1024, + 63, + 63, + false, + true, + true, + true, + true, + true, + true, + false + }; + +const struct real_format mips_double_format = + { + encode_ieee_double, + decode_ieee_double, + 2, + 53, + 53, + -1021, + 1024, + 63, + 63, + false, + true, + true, + true, + true, + true, + false, + true + }; + +const struct real_format motorola_double_format = + { + encode_ieee_double, + decode_ieee_double, + 2, + 53, + 53, + -1021, + 1024, + 63, + 63, + false, + true, + true, + true, + true, + true, + true, + true + }; + +/* IEEE extended real format. This comes in three flavors: Intel's as + a 12 byte image, Intel's as a 16 byte image, and Motorola's. Intel + 12- and 16-byte images may be big- or little endian; Motorola's is + always big endian. */ + +/* Helper subroutine which converts from the internal format to the + 12-byte little-endian Intel format. Functions below adjust this + for the other possible formats. */ +static void +encode_ieee_extended (const struct real_format *fmt, long *buf, + const REAL_VALUE_TYPE *r) +{ + unsigned long image_hi, sig_hi, sig_lo; + bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; - aexit: + image_hi = r->sign << 15; + sig_hi = sig_lo = 0; - rndprc = rndsav; - yy[0] = nsign; - switch (oprec) + switch (r->cl) { -#ifdef DEC - case 56: - todec (yy, y); /* see etodec.c */ - break; -#endif -#ifdef IBM - case 56: - toibm (yy, y, DFmode); - break; -#endif -#ifdef C4X - case 32: - toc4x (yy, y, HFmode); + case rvc_zero: break; -#endif - case 53: - toe53 (yy, y); - break; - case 24: - toe24 (yy, y); - break; - case 64: - toe64 (yy, y); + case rvc_inf: + if (fmt->has_inf) + { + image_hi |= 32767; + + /* Intel requires the explicit integer bit to be set, otherwise + it considers the value a "pseudo-infinity". Motorola docs + say it doesn't care. */ + sig_hi = 0x80000000; + } + else + { + image_hi |= 32767; + sig_lo = sig_hi = 0xffffffff; + } break; -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) - case 113: - toe113 (yy, y); + + case rvc_nan: + if (fmt->has_nans) + { + image_hi |= 32767; + if (r->canonical) + { + if (fmt->canonical_nan_lsbs_set) + { + sig_hi = (1 << 30) - 1; + sig_lo = 0xffffffff; + } + } + else if (HOST_BITS_PER_LONG == 32) + { + sig_hi = r->sig[SIGSZ-1]; + sig_lo = r->sig[SIGSZ-2]; + } + else + { + sig_lo = r->sig[SIGSZ-1]; + sig_hi = sig_lo >> 31 >> 1; + sig_lo &= 0xffffffff; + } + if (r->signalling == fmt->qnan_msb_set) + sig_hi &= ~(1 << 30); + else + sig_hi |= 1 << 30; + if ((sig_hi & 0x7fffffff) == 0 && sig_lo == 0) + sig_hi = 1 << 29; + + /* Intel requires the explicit integer bit to be set, otherwise + it considers the value a "pseudo-nan". Motorola docs say it + doesn't care. */ + sig_hi |= 0x80000000; + } + else + { + image_hi |= 32767; + sig_lo = sig_hi = 0xffffffff; + } break; -#endif - case NBITS: - emovo (yy, y); + + case rvc_normal: + { + int exp = REAL_EXP (r); + + /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, + whereas the intermediate representation is 0.F x 2**exp. + Which means we're off by one. + + Except for Motorola, which consider exp=0 and explicit + integer bit set to continue to be normalized. In theory + this discrepancy has been taken care of by the difference + in fmt->emin in round_for_format. */ + + if (denormal) + exp = 0; + else + { + exp += 16383 - 1; + gcc_assert (exp >= 0); + } + image_hi |= exp; + + if (HOST_BITS_PER_LONG == 32) + { + sig_hi = r->sig[SIGSZ-1]; + sig_lo = r->sig[SIGSZ-2]; + } + else + { + sig_lo = r->sig[SIGSZ-1]; + sig_hi = sig_lo >> 31 >> 1; + sig_lo &= 0xffffffff; + } + } break; + + default: + gcc_unreachable (); } + + buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi; } +/* Convert from the internal format to the 12-byte Motorola format + for an IEEE extended real. */ +static void +encode_ieee_extended_motorola (const struct real_format *fmt, long *buf, + const REAL_VALUE_TYPE *r) +{ + long intermed[3]; + encode_ieee_extended (fmt, intermed, r); + /* Motorola chips are assumed always to be big-endian. Also, the + padding in a Motorola extended real goes between the exponent and + the mantissa. At this point the mantissa is entirely within + elements 0 and 1 of intermed, and the exponent entirely within + element 2, so all we have to do is swap the order around, and + shift element 2 left 16 bits. */ + buf[0] = intermed[2] << 16; + buf[1] = intermed[1]; + buf[2] = intermed[0]; +} -/* Return Y = largest integer not greater than X (truncated toward minus - infinity). */ +/* Convert from the internal format to the 12-byte Intel format for + an IEEE extended real. */ +static void +encode_ieee_extended_intel_96 (const struct real_format *fmt, long *buf, + const REAL_VALUE_TYPE *r) +{ + if (FLOAT_WORDS_BIG_ENDIAN) + { + /* All the padding in an Intel-format extended real goes at the high + end, which in this case is after the mantissa, not the exponent. + Therefore we must shift everything down 16 bits. */ + long intermed[3]; + encode_ieee_extended (fmt, intermed, r); + buf[0] = ((intermed[2] << 16) | ((unsigned long)(intermed[1] & 0xFFFF0000) >> 16)); + buf[1] = ((intermed[1] << 16) | ((unsigned long)(intermed[0] & 0xFFFF0000) >> 16)); + buf[2] = (intermed[0] << 16); + } + else + /* encode_ieee_extended produces what we want directly. */ + encode_ieee_extended (fmt, buf, r); +} -static const UEMUSHORT bmask[] = +/* Convert from the internal format to the 16-byte Intel format for + an IEEE extended real. */ +static void +encode_ieee_extended_intel_128 (const struct real_format *fmt, long *buf, + const REAL_VALUE_TYPE *r) { - 0xffff, - 0xfffe, - 0xfffc, - 0xfff8, - 0xfff0, - 0xffe0, - 0xffc0, - 0xff80, - 0xff00, - 0xfe00, - 0xfc00, - 0xf800, - 0xf000, - 0xe000, - 0xc000, - 0x8000, - 0x0000, -}; + /* All the padding in an Intel-format extended real goes at the high end. */ + encode_ieee_extended_intel_96 (fmt, buf, r); + buf[3] = 0; +} +/* As above, we have a helper function which converts from 12-byte + little-endian Intel format to internal format. Functions below + adjust for the other possible formats. */ static void -efloor (x, y) - const UEMUSHORT x[]; - UEMUSHORT y[]; +decode_ieee_extended (const struct real_format *fmt, REAL_VALUE_TYPE *r, + const long *buf) { - UEMUSHORT *p; - int e, expon, i; - UEMUSHORT f[NE]; - - emov (x, f); /* leave in external format */ - expon = (int) f[NE - 1]; - e = (expon & 0x7fff) - (EXONE - 1); - if (e <= 0) - { - eclear (y); - goto isitneg; - } - /* number of bits to clear out */ - e = NBITS - e; - emov (f, y); - if (e <= 0) - return; + unsigned long image_hi, sig_hi, sig_lo; + bool sign; + int exp; + + sig_lo = buf[0], sig_hi = buf[1], image_hi = buf[2]; + sig_lo &= 0xffffffff; + sig_hi &= 0xffffffff; + image_hi &= 0xffffffff; - p = &y[0]; - while (e >= 16) + sign = (image_hi >> 15) & 1; + exp = image_hi & 0x7fff; + + memset (r, 0, sizeof (*r)); + + if (exp == 0) { - *p++ = 0; - e -= 16; - } - /* clear the remaining bits */ - *p &= bmask[e]; - /* truncate negatives toward minus infinity */ - isitneg: + if ((sig_hi || sig_lo) && fmt->has_denorm) + { + r->cl = rvc_normal; + r->sign = sign; + + /* When the IEEE format contains a hidden bit, we know that + it's zero at this point, and so shift up the significand + and decrease the exponent to match. In this case, Motorola + defines the explicit integer bit to be valid, so we don't + know whether the msb is set or not. */ + SET_REAL_EXP (r, fmt->emin); + if (HOST_BITS_PER_LONG == 32) + { + r->sig[SIGSZ-1] = sig_hi; + r->sig[SIGSZ-2] = sig_lo; + } + else + r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo; - if ((UEMUSHORT) expon & (UEMUSHORT) 0x8000) + normalize (r); + } + else if (fmt->has_signed_zero) + r->sign = sign; + } + else if (exp == 32767 && (fmt->has_nans || fmt->has_inf)) { - for (i = 0; i < NE - 1; i++) + /* See above re "pseudo-infinities" and "pseudo-nans". + Short summary is that the MSB will likely always be + set, and that we don't care about it. */ + sig_hi &= 0x7fffffff; + + if (sig_hi || sig_lo) { - if (f[i] != y[i]) + r->cl = rvc_nan; + r->sign = sign; + r->signalling = ((sig_hi >> 30) & 1) ^ fmt->qnan_msb_set; + if (HOST_BITS_PER_LONG == 32) { - esub (eone, y, y); - break; + r->sig[SIGSZ-1] = sig_hi; + r->sig[SIGSZ-2] = sig_lo; } + else + r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo; + } + else + { + r->cl = rvc_inf; + r->sign = sign; + } + } + else + { + r->cl = rvc_normal; + r->sign = sign; + SET_REAL_EXP (r, exp - 16383 + 1); + if (HOST_BITS_PER_LONG == 32) + { + r->sig[SIGSZ-1] = sig_hi; + r->sig[SIGSZ-2] = sig_lo; } + else + r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo; } } +/* Convert from the internal format to the 12-byte Motorola format + for an IEEE extended real. */ +static void +decode_ieee_extended_motorola (const struct real_format *fmt, REAL_VALUE_TYPE *r, + const long *buf) +{ + long intermed[3]; + + /* Motorola chips are assumed always to be big-endian. Also, the + padding in a Motorola extended real goes between the exponent and + the mantissa; remove it. */ + intermed[0] = buf[2]; + intermed[1] = buf[1]; + intermed[2] = (unsigned long)buf[0] >> 16; -#if 0 -/* Return S and EXP such that S * 2^EXP = X and .5 <= S < 1. - For example, 1.1 = 0.55 * 2^1. */ + decode_ieee_extended (fmt, r, intermed); +} +/* Convert from the internal format to the 12-byte Intel format for + an IEEE extended real. */ static void -efrexp (x, exp, s) - const UEMUSHORT x[]; - int *exp; - UEMUSHORT s[]; +decode_ieee_extended_intel_96 (const struct real_format *fmt, REAL_VALUE_TYPE *r, + const long *buf) { - UEMUSHORT xi[NI]; - EMULONG li; + if (FLOAT_WORDS_BIG_ENDIAN) + { + /* All the padding in an Intel-format extended real goes at the high + end, which in this case is after the mantissa, not the exponent. + Therefore we must shift everything up 16 bits. */ + long intermed[3]; - emovi (x, xi); - /* Handle denormalized numbers properly using long integer exponent. */ - li = (EMULONG) ((EMUSHORT) xi[1]); + intermed[0] = (((unsigned long)buf[2] >> 16) | (buf[1] << 16)); + intermed[1] = (((unsigned long)buf[1] >> 16) | (buf[0] << 16)); + intermed[2] = ((unsigned long)buf[0] >> 16); - if (li == 0) - { - li -= enormlz (xi); + decode_ieee_extended (fmt, r, intermed); } - xi[1] = 0x3ffe; - emovo (xi, s); - *exp = (int) (li - 0x3ffe); + else + /* decode_ieee_extended produces what we want directly. */ + decode_ieee_extended (fmt, r, buf); } -#endif - -/* Return e type Y = X * 2^PWR2. */ +/* Convert from the internal format to the 16-byte Intel format for + an IEEE extended real. */ static void -eldexp (x, pwr2, y) - const UEMUSHORT x[]; - int pwr2; - UEMUSHORT y[]; +decode_ieee_extended_intel_128 (const struct real_format *fmt, REAL_VALUE_TYPE *r, + const long *buf) { - UEMUSHORT 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); + /* All the padding in an Intel-format extended real goes at the high end. */ + decode_ieee_extended_intel_96 (fmt, r, buf); } - -#if 0 -/* C = remainder after dividing B by A, all e type values. - Least significant integer quotient bits left in EQUOT. */ +const struct real_format ieee_extended_motorola_format = + { + encode_ieee_extended_motorola, + decode_ieee_extended_motorola, + 2, + 64, + 64, + -16382, + 16384, + 95, + 95, + false, + true, + true, + true, + true, + true, + true, + true + }; + +const struct real_format ieee_extended_intel_96_format = + { + encode_ieee_extended_intel_96, + decode_ieee_extended_intel_96, + 2, + 64, + 64, + -16381, + 16384, + 79, + 79, + false, + true, + true, + true, + true, + true, + true, + false + }; + +const struct real_format ieee_extended_intel_128_format = + { + encode_ieee_extended_intel_128, + decode_ieee_extended_intel_128, + 2, + 64, + 64, + -16381, + 16384, + 79, + 79, + false, + true, + true, + true, + true, + true, + true, + false + }; + +/* The following caters to i386 systems that set the rounding precision + to 53 bits instead of 64, e.g. FreeBSD. */ +const struct real_format ieee_extended_intel_96_round_53_format = + { + encode_ieee_extended_intel_96, + decode_ieee_extended_intel_96, + 2, + 53, + 53, + -16381, + 16384, + 79, + 79, + false, + true, + true, + true, + true, + true, + true, + false + }; + +/* IBM 128-bit extended precision format: a pair of IEEE double precision + numbers whose sum is equal to the extended precision value. The number + with greater magnitude is first. This format has the same magnitude + range as an IEEE double precision value, but effectively 106 bits of + significand precision. Infinity and NaN are represented by their IEEE + double precision value stored in the first number, the second number is + +0.0 or -0.0 for Infinity and don't-care for NaN. */ + +static void encode_ibm_extended (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_ibm_extended (const struct real_format *, + REAL_VALUE_TYPE *, const long *); static void -eremain (a, b, c) - const UEMUSHORT a[], b[]; - UEMUSHORT c[]; +encode_ibm_extended (const struct real_format *fmt, long *buf, + const REAL_VALUE_TYPE *r) { - UEMUSHORT den[NI], num[NI]; + REAL_VALUE_TYPE u, normr, v; + const struct real_format *base_fmt; + + base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format; + + /* Renormalize R before doing any arithmetic on it. */ + normr = *r; + if (normr.cl == rvc_normal) + normalize (&normr); -#ifdef NANS - if (eisinf (b) - || (ecmp (a, ezero) == 0) - || eisnan (a) - || eisnan (b)) + /* u = IEEE double precision portion of significand. */ + u = normr; + round_for_format (base_fmt, &u); + encode_ieee_double (base_fmt, &buf[0], &u); + + if (u.cl == rvc_normal) { - enan (c, 0); - return; + do_add (&v, &normr, &u, 1); + /* Call round_for_format since we might need to denormalize. */ + round_for_format (base_fmt, &v); + encode_ieee_double (base_fmt, &buf[2], &v); } -#endif - if (ecmp (a, ezero) == 0) + else { - mtherr ("eremain", SING); - eclear (c); - return; + /* Inf, NaN, 0 are all representable as doubles, so the + least-significant part can be 0.0. */ + buf[2] = 0; + buf[3] = 0; } - emovi (a, den); - emovi (b, num); - eiremain (den, num); - /* Sign of remainder = sign of quotient */ - if (a[0] == b[0]) - num[0] = 0; - else - num[0] = 0xffff; - emovo (num, c); } -#endif - -/* Return quotient of exploded e-types NUM / DEN in EQUOT, - remainder in NUM. */ static void -eiremain (den, num) - UEMUSHORT den[], num[]; +decode_ibm_extended (const struct real_format *fmt ATTRIBUTE_UNUSED, REAL_VALUE_TYPE *r, + const long *buf) { - EMULONG ld, ln; - UEMUSHORT j; - - ld = den[E]; - ld -= enormlz (den); - ln = num[E]; - ln -= enormlz (num); - ecleaz (equot); - while (ln >= ld) + REAL_VALUE_TYPE u, v; + const struct real_format *base_fmt; + + base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format; + decode_ieee_double (base_fmt, &u, &buf[0]); + + if (u.cl != rvc_zero && u.cl != rvc_inf && u.cl != rvc_nan) { - if (ecmpm (den, num) <= 0) - { - esubm (den, num); - j = 1; - } - else - j = 0; - eshup1 (equot); - equot[NI - 1] |= j; - eshup1 (num); - ln -= 1; + decode_ieee_double (base_fmt, &v, &buf[2]); + do_add (r, &u, &v, 0); } - emdnorm (num, 0, 0, ln, 0); + else + *r = u; } -/* Report an error condition CODE encountered in function NAME. - - Mnemonic Value Significance - - DOMAIN 1 argument domain error - SING 2 function singularity - OVERFLOW 3 overflow range error - UNDERFLOW 4 underflow range error - TLOSS 5 total loss of precision - PLOSS 6 partial loss of precision - INVALID 7 NaN - producing operation - EDOM 33 Unix domain error code - ERANGE 34 Unix range error code +const struct real_format ibm_extended_format = + { + encode_ibm_extended, + decode_ibm_extended, + 2, + 53 + 53, + 53, + -1021 + 53, + 1024, + 127, + -1, + false, + true, + true, + true, + true, + true, + true, + false + }; + +const struct real_format mips_extended_format = + { + encode_ibm_extended, + decode_ibm_extended, + 2, + 53 + 53, + 53, + -1021 + 53, + 1024, + 127, + -1, + false, + true, + true, + true, + true, + true, + false, + true + }; - The order of appearance of the following messages is bound to the - error codes defined above. */ + +/* IEEE quad precision format. */ -int merror = 0; -extern int merror; +static void encode_ieee_quad (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_ieee_quad (const struct real_format *, + REAL_VALUE_TYPE *, const long *); static void -mtherr (name, code) - const char *name; - int code; +encode_ieee_quad (const struct real_format *fmt, long *buf, + const REAL_VALUE_TYPE *r) { - /* 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 (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) + unsigned long image3, image2, image1, image0, exp; + bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0; + REAL_VALUE_TYPE u; + + image3 = r->sign << 31; + image2 = 0; + image1 = 0; + image0 = 0; + + rshift_significand (&u, r, SIGNIFICAND_BITS - 113); + + switch (r->cl) { - switch (code) + case rvc_zero: + break; + + case rvc_inf: + if (fmt->has_inf) + image3 |= 32767 << 16; + else { - 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 (); + image3 |= 0x7fffffff; + image2 = 0xffffffff; + image1 = 0xffffffff; + image0 = 0xffffffff; } - } - - /* Set global error message word */ - merror = code + 1; -} + break; -#ifdef DEC -/* Convert DEC double precision D to e type E. */ + case rvc_nan: + if (fmt->has_nans) + { + image3 |= 32767 << 16; -static void -dectoe (d, e) - const UEMUSHORT *d; - UEMUSHORT *e; -{ - UEMUSHORT y[NI]; - UEMUSHORT r, *p; - - ecleaz (y); /* start with a zero */ - p = y; /* point to our number */ - r = *d; /* get DEC exponent word */ - if (*d & (unsigned int) 0x8000) - *p = 0xffff; /* fill in our sign */ - ++p; /* bump pointer to our exponent word */ - r &= 0x7fff; /* strip the sign bit */ - if (r == 0) /* answer = 0 if high order DEC word = 0 */ - goto done; - - - r >>= 7; /* shift exponent word down 7 bits */ - r += EXONE - 0201; /* subtract DEC exponent offset */ - /* add our e type exponent offset */ - *p++ = r; /* to form our exponent */ - - r = *d++; /* now do the high order mantissa */ - r &= 0177; /* strip off the DEC exponent and sign bits */ - r |= 0200; /* the DEC understood high order mantissa bit */ - *p++ = r; /* put result in our high guard word */ - - *p++ = *d++; /* fill in the rest of our mantissa */ - *p++ = *d++; - *p = *d; - - eshdn8 (y); /* shift our mantissa down 8 bits */ - done: - emovo (y, e); -} + if (r->canonical) + { + if (fmt->canonical_nan_lsbs_set) + { + image3 |= 0x7fff; + image2 = image1 = image0 = 0xffffffff; + } + } + else if (HOST_BITS_PER_LONG == 32) + { + image0 = u.sig[0]; + image1 = u.sig[1]; + image2 = u.sig[2]; + image3 |= u.sig[3] & 0xffff; + } + else + { + image0 = u.sig[0]; + image1 = image0 >> 31 >> 1; + image2 = u.sig[1]; + image3 |= (image2 >> 31 >> 1) & 0xffff; + image0 &= 0xffffffff; + image2 &= 0xffffffff; + } + if (r->signalling == fmt->qnan_msb_set) + image3 &= ~0x8000; + else + image3 |= 0x8000; + if (((image3 & 0xffff) | image2 | image1 | image0) == 0) + image3 |= 0x4000; + } + else + { + image3 |= 0x7fffffff; + image2 = 0xffffffff; + image1 = 0xffffffff; + image0 = 0xffffffff; + } + break; -/* Convert e type X to DEC double precision D. */ + case rvc_normal: + /* Recall that IEEE numbers are interpreted as 1.F x 2**exp, + whereas the intermediate representation is 0.F x 2**exp. + Which means we're off by one. */ + if (denormal) + exp = 0; + else + exp = REAL_EXP (r) + 16383 - 1; + image3 |= exp << 16; -static void -etodec (x, d) - const UEMUSHORT *x; - UEMUSHORT *d; -{ - UEMUSHORT xi[NI]; - EMULONG exp; - int rndsav; - - emovi (x, xi); - /* Adjust exponent for offsets. */ - exp = (EMULONG) xi[E] - (EXONE - 0201); - /* Round off to nearest or even. */ - rndsav = rndprc; - rndprc = 56; - emdnorm (xi, 0, 0, exp, 64); - rndprc = rndsav; - todec (xi, d); -} + if (HOST_BITS_PER_LONG == 32) + { + image0 = u.sig[0]; + image1 = u.sig[1]; + image2 = u.sig[2]; + image3 |= u.sig[3] & 0xffff; + } + else + { + image0 = u.sig[0]; + image1 = image0 >> 31 >> 1; + image2 = u.sig[1]; + image3 |= (image2 >> 31 >> 1) & 0xffff; + image0 &= 0xffffffff; + image2 &= 0xffffffff; + } + break; -/* Convert exploded e-type X, that has already been rounded to - 56-bit precision, to DEC format double Y. */ + default: + gcc_unreachable (); + } -static void -todec (x, y) - UEMUSHORT *x, *y; -{ - UEMUSHORT i; - UEMUSHORT *p; - - p = x; - *y = 0; - if (*p++) - *y = 0100000; - i = *p++; - if (i == 0) + if (FLOAT_WORDS_BIG_ENDIAN) { - *y++ = 0; - *y++ = 0; - *y++ = 0; - *y++ = 0; - return; + buf[0] = image3; + buf[1] = image2; + buf[2] = image1; + buf[3] = image0; } - if (i > 0377) + else { - *y++ |= 077777; - *y++ = 0xffff; - *y++ = 0xffff; - *y++ = 0xffff; -#ifdef ERANGE - errno = ERANGE; -#endif - return; + buf[0] = image0; + buf[1] = image1; + buf[2] = image2; + buf[3] = image3; } - 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 /* DEC */ - -#ifdef IBM -/* Convert IBM single/double precision to e type. */ static void -ibmtoe (d, e, mode) - const UEMUSHORT *d; - UEMUSHORT *e; - enum machine_mode mode; +decode_ieee_quad (const struct real_format *fmt, REAL_VALUE_TYPE *r, + const long *buf) { - UEMUSHORT y[NI]; - UEMUSHORT r, *p; - - ecleaz (y); /* start with a zero */ - p = y; /* point to our number */ - r = *d; /* get IBM exponent word */ - if (*d & (unsigned int) 0x8000) - *p = 0xffff; /* fill in our sign */ - ++p; /* bump pointer to our exponent word */ - r &= 0x7f00; /* strip the sign bit */ - r >>= 6; /* shift exponent word down 6 bits */ - /* in fact shift by 8 right and 2 left */ - r += EXONE - (0x41 << 2); /* subtract IBM exponent offset */ - /* add our e type exponent offset */ - *p++ = r; /* to form our exponent */ - - *p++ = *d++ & 0xff; /* now do the high order mantissa */ - /* strip off the IBM exponent and sign bits */ - if (mode != SFmode) /* there are only 2 words in SFmode */ + unsigned long image3, image2, image1, image0; + bool sign; + int exp; + + if (FLOAT_WORDS_BIG_ENDIAN) { - *p++ = *d++; /* fill in the rest of our mantissa */ - *p++ = *d++; + image3 = buf[0]; + image2 = buf[1]; + image1 = buf[2]; + image0 = buf[3]; } - *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); /* now normalise the mantissa */ - /* handle change in RADIX */ - emovo (y, e); -} - - + { + image0 = buf[0]; + image1 = buf[1]; + image2 = buf[2]; + image3 = buf[3]; + } + image0 &= 0xffffffff; + image1 &= 0xffffffff; + image2 &= 0xffffffff; -/* Convert e type to IBM single/double precision. */ + sign = (image3 >> 31) & 1; + exp = (image3 >> 16) & 0x7fff; + image3 &= 0xffff; -static void -etoibm (x, d, mode) - const UEMUSHORT *x; - UEMUSHORT *d; - enum machine_mode mode; -{ - UEMUSHORT xi[NI]; - EMULONG exp; - int rndsav; - - emovi (x, xi); - exp = (EMULONG) xi[E] - (EXONE - (0x41 << 2)); /* adjust exponent for offsets */ - /* round off to nearest or even */ - rndsav = rndprc; - rndprc = 56; - emdnorm (xi, 0, 0, exp, 64); - rndprc = rndsav; - toibm (xi, d, mode); -} + memset (r, 0, sizeof (*r)); -static void -toibm (x, y, mode) - UEMUSHORT *x, *y; - enum machine_mode mode; -{ - UEMUSHORT i; - UEMUSHORT *p; - int r; - - p = x; - *y = 0; - if (*p++) - *y = 0x8000; - i = *p++; - if (i == 0) + if (exp == 0) { - *y++ = 0; - *y++ = 0; - if (mode != SFmode) + if ((image3 | image2 | image1 | image0) && fmt->has_denorm) { - *y++ = 0; - *y++ = 0; + r->cl = rvc_normal; + r->sign = sign; + + SET_REAL_EXP (r, -16382 + (SIGNIFICAND_BITS - 112)); + if (HOST_BITS_PER_LONG == 32) + { + r->sig[0] = image0; + r->sig[1] = image1; + r->sig[2] = image2; + r->sig[3] = image3; + } + else + { + r->sig[0] = (image1 << 31 << 1) | image0; + r->sig[1] = (image3 << 31 << 1) | image2; + } + + normalize (r); } - return; + else if (fmt->has_signed_zero) + r->sign = sign; } - r = i & 0x3; - i >>= 2; - if (i > 0x7f) + else if (exp == 32767 && (fmt->has_nans || fmt->has_inf)) { - *y++ |= 0x7fff; - *y++ = 0xffff; - if (mode != SFmode) + if (image3 | image2 | image1 | image0) + { + r->cl = rvc_nan; + r->sign = sign; + r->signalling = ((image3 >> 15) & 1) ^ fmt->qnan_msb_set; + + if (HOST_BITS_PER_LONG == 32) + { + r->sig[0] = image0; + r->sig[1] = image1; + r->sig[2] = image2; + r->sig[3] = image3; + } + else + { + r->sig[0] = (image1 << 31 << 1) | image0; + r->sig[1] = (image3 << 31 << 1) | image2; + } + lshift_significand (r, r, SIGNIFICAND_BITS - 113); + } + else { - *y++ = 0xffff; - *y++ = 0xffff; + r->cl = rvc_inf; + r->sign = sign; } -#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) + else { - *y++ = x[M + 2]; - *y++ = x[M + 3]; + r->cl = rvc_normal; + r->sign = sign; + SET_REAL_EXP (r, exp - 16383 + 1); + + if (HOST_BITS_PER_LONG == 32) + { + r->sig[0] = image0; + r->sig[1] = image1; + r->sig[2] = image2; + r->sig[3] = image3; + } + else + { + r->sig[0] = (image1 << 31 << 1) | image0; + r->sig[1] = (image3 << 31 << 1) | image2; + } + lshift_significand (r, r, SIGNIFICAND_BITS - 113); + r->sig[SIGSZ-1] |= SIG_MSB; } } -#endif /* IBM */ +const struct real_format ieee_quad_format = + { + encode_ieee_quad, + decode_ieee_quad, + 2, + 113, + 113, + -16381, + 16384, + 127, + 127, + false, + true, + true, + true, + true, + true, + true, + false + }; + +const struct real_format mips_quad_format = + { + encode_ieee_quad, + decode_ieee_quad, + 2, + 113, + 113, + -16381, + 16384, + 127, + 127, + false, + true, + true, + true, + true, + true, + false, + true + }; + +/* Descriptions of VAX floating point formats can be found beginning at -#ifdef C4X -/* Convert C4X single/double precision to e type. */ + http://h71000.www7.hp.com/doc/73FINAL/4515/4515pro_013.html#f_floating_point_format -static void -c4xtoe (d, e, mode) - const UEMUSHORT *d; - UEMUSHORT *e; - enum machine_mode mode; -{ - UEMUSHORT y[NI]; - UEMUSHORT dn[4]; - int r; - int isnegative; - int size; - int i; - int carry; + The thing to remember is that they're almost IEEE, except for word + order, exponent bias, and the lack of infinities, nans, and denormals. - dn[0] = d[0]; - dn[1] = d[1]; - if (mode != QFmode) - { - dn[2] = d[3] << 8; - dn[3] = 0; - } + We don't implement the H_floating format here, simply because neither + the VAX or Alpha ports use it. */ - /* Short-circuit the zero case. */ - if ((dn[0] == 0x8000) - && (dn[1] == 0x0000) - && ((mode == QFmode) || ((dn[2] == 0x0000) && (dn[3] == 0x0000)))) - { - e[0] = 0; - e[1] = 0; - e[2] = 0; - e[3] = 0; - e[4] = 0; - e[5] = 0; - return; - } +static void encode_vax_f (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_vax_f (const struct real_format *, + REAL_VALUE_TYPE *, const long *); +static void encode_vax_d (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_vax_d (const struct real_format *, + REAL_VALUE_TYPE *, const long *); +static void encode_vax_g (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_vax_g (const struct real_format *, + REAL_VALUE_TYPE *, const long *); - ecleaz (y); /* start with a zero */ - r = dn[0]; /* get sign/exponent part */ - if (r & (unsigned int) 0x0080) - { - y[0] = 0xffff; /* fill in our sign */ - isnegative = TRUE; - } - else - isnegative = FALSE; +static void +encode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, + const REAL_VALUE_TYPE *r) +{ + unsigned long sign, exp, sig, image; - r >>= 8; /* Shift exponent word down 8 bits. */ - if (r & 0x80) /* Make the exponent negative if it is. */ - r = r | (~0 & ~0xff); + sign = r->sign << 15; - if (isnegative) + switch (r->cl) { - /* 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] = dn[0] & 0x7f; - - y[M+1] = dn[1]; - if (mode != QFmode) /* There are only 2 words in QFmode. */ - { - y[M+2] = dn[2]; /* Fill in the rest of our mantissa. */ - y[M+3] = dn[3]; - size = 4; - } - else - size = 2; - eshift (y, -8); + case rvc_zero: + image = 0; + break; - /* Now do the two's complement on the data. */ + case rvc_inf: + case rvc_nan: + image = 0xffff7fff | sign; + break; - carry = 1; /* Initially add 1 for the two's complement. */ - for (i=size + M; i > M; i--) - { - if (carry && (y[i] == 0x0000)) - /* We overflowed into the next word, carry is the same. */ - y[i] = carry ? 0x0000 : 0xffff; - else - { - /* No overflow, just invert and add carry. */ - y[i] = ((~y[i]) + carry) & 0xffff; - carry = 0; - } - } + case rvc_normal: + sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff; + exp = REAL_EXP (r) + 128; - if (carry) - { - eshift (y, -1); - y[M+1] |= 0x8000; - r++; - } - y[1] = r + EXONE; - } - else - { - /* Add our e type exponent offset to form our exponent. */ - r += EXONE; - y[1] = r; - - /* Now do the high order mantissa strip off the exponent and sign - bits and add the high 1 bit. */ - y[M] = (dn[0] & 0x7f) | 0x80; - - y[M+1] = dn[1]; - if (mode != QFmode) /* There are only 2 words in QFmode. */ - { - y[M+2] = dn[2]; /* Fill in the rest of our mantissa. */ - y[M+3] = dn[3]; - } - eshift (y, -8); + image = (sig << 16) & 0xffff0000; + image |= sign; + image |= exp << 7; + image |= sig >> 16; + break; + + default: + gcc_unreachable (); } - emovo (y, e); + buf[0] = image; } +static void +decode_vax_f (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r, const long *buf) +{ + unsigned long image = buf[0] & 0xffffffff; + int exp = (image >> 7) & 0xff; + + memset (r, 0, sizeof (*r)); + + if (exp != 0) + { + r->cl = rvc_normal; + r->sign = (image >> 15) & 1; + SET_REAL_EXP (r, exp - 128); -/* Convert e type to C4X single/double precision. */ + image = ((image & 0x7f) << 16) | ((image >> 16) & 0xffff); + r->sig[SIGSZ-1] = (image << (HOST_BITS_PER_LONG - 24)) | SIG_MSB; + } +} static void -etoc4x (x, d, mode) - const UEMUSHORT *x; - UEMUSHORT *d; - enum machine_mode mode; +encode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, + const REAL_VALUE_TYPE *r) { - UEMUSHORT xi[NI]; - EMULONG exp; - int rndsav; + unsigned long image0, image1, sign = r->sign << 15; + + switch (r->cl) + { + case rvc_zero: + image0 = image1 = 0; + break; + + case rvc_inf: + case rvc_nan: + image0 = 0xffff7fff | sign; + image1 = 0xffffffff; + break; + + case rvc_normal: + /* Extract the significand into straight hi:lo. */ + if (HOST_BITS_PER_LONG == 64) + { + image0 = r->sig[SIGSZ-1]; + image1 = (image0 >> (64 - 56)) & 0xffffffff; + image0 = (image0 >> (64 - 56 + 1) >> 31) & 0x7fffff; + } + else + { + image0 = r->sig[SIGSZ-1]; + image1 = r->sig[SIGSZ-2]; + image1 = (image0 << 24) | (image1 >> 8); + image0 = (image0 >> 8) & 0xffffff; + } - emovi (x, xi); + /* Rearrange the half-words of the significand to match the + external format. */ + image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff007f; + image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff; - /* Adjust exponent for offsets. */ - exp = (EMULONG) xi[E] - (EXONE - 0x7f); + /* Add the sign and exponent. */ + image0 |= sign; + image0 |= (REAL_EXP (r) + 128) << 7; + break; + + default: + gcc_unreachable (); + } - /* Round off to nearest or even. */ - rndsav = rndprc; - rndprc = mode == QFmode ? 24 : 32; - emdnorm (xi, 0, 0, exp, 64); - rndprc = rndsav; - toc4x (xi, d, mode); + if (FLOAT_WORDS_BIG_ENDIAN) + buf[0] = image1, buf[1] = image0; + else + buf[0] = image0, buf[1] = image1; } static void -toc4x (x, y, mode) - UEMUSHORT *x, *y; - enum machine_mode mode; +decode_vax_d (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r, const long *buf) { - int i; - int v; - int carry; - - /* Short-circuit the zero case */ - if ((x[0] == 0) /* Zero exponent and sign */ - && (x[1] == 0) - && (x[M] == 0) /* The rest is for zero mantissa */ - && (x[M+1] == 0) - /* Only check for double if necessary */ - && ((mode == QFmode) || ((x[M+2] == 0) && (x[M+3] == 0)))) - { - /* We have a zero. Put it into the output and return. */ - *y++ = 0x8000; - *y++ = 0x0000; - if (mode != QFmode) - { - *y++ = 0x0000; - *y++ = 0x0000; - } - return; - } + unsigned long image0, image1; + int exp; - *y = 0; + if (FLOAT_WORDS_BIG_ENDIAN) + image1 = buf[0], image0 = buf[1]; + else + image0 = buf[0], image1 = buf[1]; + image0 &= 0xffffffff; + image1 &= 0xffffffff; - /* Negative number require a two's complement conversion of the - mantissa. */ - if (x[0]) - { - *y = 0x0080; + exp = (image0 >> 7) & 0xff; - i = ((int) x[1]) - 0x7f; + memset (r, 0, sizeof (*r)); - /* Now add 1 to the inverted data to do the two's complement. */ - 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 (exp != 0) + { + r->cl = rvc_normal; + r->sign = (image0 >> 15) & 1; + SET_REAL_EXP (r, exp - 128); - /* 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 - of it. This only occurs if the number is -1 x 2^m. */ - if (x[M+1] & 0x8000) + /* Rearrange the half-words of the external format into + proper ascending order. */ + image0 = ((image0 & 0x7f) << 16) | ((image0 >> 16) & 0xffff); + image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff); + + if (HOST_BITS_PER_LONG == 64) { - /* This is the case of -1 x 2^m, we have to rid ourselves of the - high sign bit and shift the exponent. */ - eshift (x, 1); - i--; + image0 = (image0 << 31 << 1) | image1; + image0 <<= 64 - 56; + image0 |= SIG_MSB; + r->sig[SIGSZ-1] = image0; } - } - else - i = ((int) x[1]) - 0x7f; - - if ((i < -128) || (i > 127)) - { - y[0] |= 0xff7f; - y[1] = 0xffff; - if (mode != QFmode) + else { - y[2] = 0xffff; - y[3] = 0xffff; - y[3] = (y[1] << 8) | ((y[2] >> 8) & 0xff); - y[2] = (y[0] << 8) | ((y[1] >> 8) & 0xff); + r->sig[SIGSZ-1] = image0; + r->sig[SIGSZ-2] = image1; + lshift_significand (r, r, 2*HOST_BITS_PER_LONG - 56); + r->sig[SIGSZ-1] |= SIG_MSB; } -#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]; - y[3] = (y[1] << 8) | ((y[2] >> 8) & 0xff); - y[2] = (y[0] << 8) | ((y[1] >> 8) & 0xff); } } -#endif /* C4X */ - -/* Output a binary NaN bit pattern in the target machine's format. */ - -/* If special NaN bit patterns are required, define them in tm.h - as arrays of unsigned 16-bit shorts. Otherwise, use the default - patterns here. */ -#ifdef TFMODE_NAN -TFMODE_NAN; -#else -#ifdef IEEE -static const UEMUSHORT TFbignan[8] = - {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; -static const UEMUSHORT TFlittlenan[8] = {0, 0, 0, 0, 0, 0, 0x8000, 0xffff}; -#endif -#endif - -#ifdef XFMODE_NAN -XFMODE_NAN; -#else -#ifdef IEEE -static const UEMUSHORT XFbignan[6] = - {0x7fff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}; -static const UEMUSHORT XFlittlenan[6] = {0, 0, 0, 0xc000, 0xffff, 0}; -#endif -#endif - -#ifdef DFMODE_NAN -DFMODE_NAN; -#else -#ifdef IEEE -static const UEMUSHORT DFbignan[4] = {0x7fff, 0xffff, 0xffff, 0xffff}; -static const UEMUSHORT DFlittlenan[4] = {0, 0, 0, 0xfff8}; -#endif -#endif - -#ifdef SFMODE_NAN -SFMODE_NAN; -#else -#ifdef IEEE -static const UEMUSHORT SFbignan[2] = {0x7fff, 0xffff}; -static const UEMUSHORT SFlittlenan[2] = {0, 0xffc0}; -#endif -#endif - -#ifdef NANS static void -make_nan (nan, sign, mode) - UEMUSHORT *nan; - int sign; - enum machine_mode mode; +encode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, + const REAL_VALUE_TYPE *r) { - int n; - const UEMUSHORT *p; + unsigned long image0, image1, sign = r->sign << 15; - switch (mode) + switch (r->cl) { -/* Possibly the `reserved operand' patterns on a VAX can be - used like NaN's, but probably not in the same way as IEEE. */ -#if !defined(DEC) && !defined(IBM) && !defined(C4X) - case TFmode: -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) - n = 8; - if (REAL_WORDS_BIG_ENDIAN) - p = TFbignan; - else - p = TFlittlenan; + case rvc_zero: + image0 = image1 = 0; break; -#endif - /* FALLTHRU */ - case XFmode: - n = 6; - if (REAL_WORDS_BIG_ENDIAN) - p = XFbignan; - else - p = XFlittlenan; + case rvc_inf: + case rvc_nan: + image0 = 0xffff7fff | sign; + image1 = 0xffffffff; break; - case DFmode: - n = 4; - if (REAL_WORDS_BIG_ENDIAN) - p = DFbignan; + case rvc_normal: + /* Extract the significand into straight hi:lo. */ + if (HOST_BITS_PER_LONG == 64) + { + image0 = r->sig[SIGSZ-1]; + image1 = (image0 >> (64 - 53)) & 0xffffffff; + image0 = (image0 >> (64 - 53 + 1) >> 31) & 0xfffff; + } else - p = DFlittlenan; - break; + { + image0 = r->sig[SIGSZ-1]; + image1 = r->sig[SIGSZ-2]; + image1 = (image0 << 21) | (image1 >> 11); + image0 = (image0 >> 11) & 0xfffff; + } - case SFmode: - case HFmode: - n = 2; - if (REAL_WORDS_BIG_ENDIAN) - p = SFbignan; - else - p = SFlittlenan; + /* Rearrange the half-words of the significand to match the + external format. */ + image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff000f; + image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff; + + /* Add the sign and exponent. */ + image0 |= sign; + image0 |= (REAL_EXP (r) + 1024) << 4; break; -#endif default: - abort (); + gcc_unreachable (); } - 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); -} -#endif /* NANS */ -/* This is the inverse of the function `etarsingle' invoked by - REAL_VALUE_TO_TARGET_SINGLE. */ + if (FLOAT_WORDS_BIG_ENDIAN) + buf[0] = image1, buf[1] = image0; + else + buf[0] = image0, buf[1] = image1; +} -REAL_VALUE_TYPE -ereal_unto_float (f) - long f; +static void +decode_vax_g (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r, const long *buf) { - REAL_VALUE_TYPE r; - UEMUSHORT s[2]; - UEMUSHORT e[NE]; + unsigned long image0, image1; + int exp; - /* Convert 32 bit integer to array of 16 bit pieces in target machine order. - This is the inverse operation to what the function `endian' does. */ - if (REAL_WORDS_BIG_ENDIAN) - { - s[0] = (UEMUSHORT) (f >> 16); - s[1] = (UEMUSHORT) f; - } + if (FLOAT_WORDS_BIG_ENDIAN) + image1 = buf[0], image0 = buf[1]; else - { - s[0] = (UEMUSHORT) f; - s[1] = (UEMUSHORT) (f >> 16); - } - /* Convert and promote the target float to E-type. */ - e24toe (s, e); - /* Output E-type to REAL_VALUE_TYPE. */ - PUT_REAL (e, &r); - return r; -} + image0 = buf[0], image1 = buf[1]; + image0 &= 0xffffffff; + image1 &= 0xffffffff; + exp = (image0 >> 4) & 0x7ff; -/* This is the inverse of the function `etardouble' invoked by - REAL_VALUE_TO_TARGET_DOUBLE. */ - -REAL_VALUE_TYPE -ereal_unto_double (d) - long d[]; -{ - REAL_VALUE_TYPE r; - UEMUSHORT s[4]; - UEMUSHORT e[NE]; + memset (r, 0, sizeof (*r)); - /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces. */ - if (REAL_WORDS_BIG_ENDIAN) - { - s[0] = (UEMUSHORT) (d[0] >> 16); - s[1] = (UEMUSHORT) d[0]; - s[2] = (UEMUSHORT) (d[1] >> 16); - s[3] = (UEMUSHORT) d[1]; - } - else + if (exp != 0) { - /* Target float words are little-endian. */ - s[0] = (UEMUSHORT) d[0]; - s[1] = (UEMUSHORT) (d[0] >> 16); - s[2] = (UEMUSHORT) d[1]; - s[3] = (UEMUSHORT) (d[1] >> 16); - } - /* Convert target double to E-type. */ - e53toe (s, e); - /* Output E-type to REAL_VALUE_TYPE. */ - PUT_REAL (e, &r); - return r; -} + r->cl = rvc_normal; + r->sign = (image0 >> 15) & 1; + SET_REAL_EXP (r, exp - 1024); + /* Rearrange the half-words of the external format into + proper ascending order. */ + image0 = ((image0 & 0xf) << 16) | ((image0 >> 16) & 0xffff); + image1 = ((image1 & 0xffff) << 16) | ((image1 >> 16) & 0xffff); -/* Convert an SFmode target `float' value to a REAL_VALUE_TYPE. - This is somewhat like ereal_unto_float, but the input types - for these are different. */ + if (HOST_BITS_PER_LONG == 64) + { + image0 = (image0 << 31 << 1) | image1; + image0 <<= 64 - 53; + image0 |= SIG_MSB; + r->sig[SIGSZ-1] = image0; + } + else + { + r->sig[SIGSZ-1] = image0; + r->sig[SIGSZ-2] = image1; + lshift_significand (r, r, 64 - 53); + r->sig[SIGSZ-1] |= SIG_MSB; + } + } +} -REAL_VALUE_TYPE -ereal_from_float (f) - HOST_WIDE_INT f; +const struct real_format vax_f_format = + { + encode_vax_f, + decode_vax_f, + 2, + 24, + 24, + -127, + 127, + 15, + 15, + false, + false, + false, + false, + false, + false, + false, + false + }; + +const struct real_format vax_d_format = + { + encode_vax_d, + decode_vax_d, + 2, + 56, + 56, + -127, + 127, + 15, + 15, + false, + false, + false, + false, + false, + false, + false, + false + }; + +const struct real_format vax_g_format = + { + encode_vax_g, + decode_vax_g, + 2, + 53, + 53, + -1023, + 1023, + 15, + 15, + false, + false, + false, + false, + false, + false, + false, + false + }; + +/* Encode real R into a single precision DFP value in BUF. */ +static void +encode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED, + long *buf ATTRIBUTE_UNUSED, + const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) { - REAL_VALUE_TYPE r; - UEMUSHORT s[2]; - UEMUSHORT e[NE]; - - /* Convert 32 bit integer to array of 16 bit pieces in target machine order. - This is the inverse operation to what the function `endian' does. */ - if (REAL_WORDS_BIG_ENDIAN) - { - s[0] = (UEMUSHORT) (f >> 16); - s[1] = (UEMUSHORT) f; - } - else - { - s[0] = (UEMUSHORT) f; - s[1] = (UEMUSHORT) (f >> 16); - } - /* Convert and promote the target float to E-type. */ - e24toe (s, e); - /* Output E-type to REAL_VALUE_TYPE. */ - PUT_REAL (e, &r); - return r; + encode_decimal32 (fmt, buf, r); } +/* Decode a single precision DFP value in BUF into a real R. */ +static void +decode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, + const long *buf ATTRIBUTE_UNUSED) +{ + decode_decimal32 (fmt, r, buf); +} -/* Convert a DFmode target `double' value to a REAL_VALUE_TYPE. - This is somewhat like ereal_unto_double, but the input types - for these are different. +/* Encode real R into a double precision DFP value in BUF. */ +static void +encode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED, + long *buf ATTRIBUTE_UNUSED, + const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) +{ + encode_decimal64 (fmt, buf, r); +} - The DFmode is stored as an array of HOST_WIDE_INT in the target's - data format, with no holes in the bit packing. The first element - of the input array holds the bits that would come first in the - target computer's memory. */ +/* Decode a double precision DFP value in BUF into a real R. */ +static void +decode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, + const long *buf ATTRIBUTE_UNUSED) +{ + decode_decimal64 (fmt, r, buf); +} -REAL_VALUE_TYPE -ereal_from_double (d) - HOST_WIDE_INT d[]; +/* Encode real R into a quad precision DFP value in BUF. */ +static void +encode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED, + long *buf ATTRIBUTE_UNUSED, + const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED) { - REAL_VALUE_TYPE r; - UEMUSHORT s[4]; - UEMUSHORT e[NE]; + encode_decimal128 (fmt, buf, r); +} - /* 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] = (UEMUSHORT) (d[0] >> 16); - s[1] = (UEMUSHORT) d[0]; - s[2] = (UEMUSHORT) (d[1] >> 16); - s[3] = (UEMUSHORT) 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[0] = (UEMUSHORT) (d[0] >> 48); - s[1] = (UEMUSHORT) (d[0] >> 32); - s[2] = (UEMUSHORT) (d[0] >> 16); - s[3] = (UEMUSHORT) d[0]; -#endif - } - else - { - /* Target float words are little-endian. */ - s[0] = (UEMUSHORT) d[0]; - s[1] = (UEMUSHORT) (d[0] >> 16); -#if HOST_BITS_PER_WIDE_INT == 32 - s[2] = (UEMUSHORT) d[1]; - s[3] = (UEMUSHORT) (d[1] >> 16); -#else - s[2] = (UEMUSHORT) (d[0] >> 32); - s[3] = (UEMUSHORT) (d[0] >> 48); -#endif - } - /* Convert target double to E-type. */ - e53toe (s, e); - /* Output E-type to REAL_VALUE_TYPE. */ - PUT_REAL (e, &r); - return r; +/* Decode a quad precision DFP value in BUF into a real R. */ +static void +decode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED, + const long *buf ATTRIBUTE_UNUSED) +{ + decode_decimal128 (fmt, r, buf); } +/* Single precision decimal floating point (IEEE 754). */ +const struct real_format decimal_single_format = + { + encode_decimal_single, + decode_decimal_single, + 10, + 7, + 7, + -94, + 97, + 31, + 31, + false, + true, + true, + true, + true, + true, + true, + false + }; + +/* Double precision decimal floating point (IEEE 754). */ +const struct real_format decimal_double_format = + { + encode_decimal_double, + decode_decimal_double, + 10, + 16, + 16, + -382, + 385, + 63, + 63, + false, + true, + true, + true, + true, + true, + true, + false + }; + +/* Quad precision decimal floating point (IEEE 754). */ +const struct real_format decimal_quad_format = + { + encode_decimal_quad, + decode_decimal_quad, + 10, + 34, + 34, + -6142, + 6145, + 127, + 127, + false, + true, + true, + true, + true, + true, + true, + false + }; + +/* A synthetic "format" for internal arithmetic. It's the size of the + internal significand minus the two bits needed for proper rounding. + The encode and decode routines exist only to satisfy our paranoia + harness. */ -#if 0 -/* Convert target computer unsigned 64-bit integer to e-type. - The endian-ness of DImode follows the convention for integers, - so we use WORDS_BIG_ENDIAN here, not REAL_WORDS_BIG_ENDIAN. */ +static void encode_internal (const struct real_format *fmt, + long *, const REAL_VALUE_TYPE *); +static void decode_internal (const struct real_format *, + REAL_VALUE_TYPE *, const long *); static void -uditoe (di, e) - const UEMUSHORT *di; /* Address of the 64-bit int. */ - UEMUSHORT *e; +encode_internal (const struct real_format *fmt ATTRIBUTE_UNUSED, long *buf, + const REAL_VALUE_TYPE *r) { - UEMUSHORT 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; /* exponent if normalize shift count were 0 */ - if ((k = enormlz (yi)) > NBITS)/* normalize the significand */ - ecleaz (yi); /* it was zero */ - else - yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */ - emovo (yi, e); + memcpy (buf, r, sizeof (*r)); } -/* Convert target computer signed 64-bit integer to e-type. */ - static void -ditoe (di, e) - const UEMUSHORT *di; /* Address of the 64-bit int. */ - UEMUSHORT *e; +decode_internal (const struct real_format *fmt ATTRIBUTE_UNUSED, + REAL_VALUE_TYPE *r, const long *buf) { - unsigned EMULONG acc; - UEMUSHORT yi[NI]; - UEMUSHORT 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++; - } - /* Take absolute value */ - 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; /* exponent if normalize shift count were 0 */ - if ((k = enormlz (yi)) > NBITS)/* normalize the significand */ - ecleaz (yi); /* it was zero */ - else - yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */ - emovo (yi, e); - if (sign) - eneg (e); + memcpy (r, buf, sizeof (*r)); } +const struct real_format real_internal_format = + { + encode_internal, + decode_internal, + 2, + SIGNIFICAND_BITS - 2, + SIGNIFICAND_BITS - 2, + -MAX_EXP, + MAX_EXP, + -1, + -1, + false, + false, + true, + true, + false, + true, + true, + false + }; + +/* Calculate the square root of X in mode MODE, and store the result + in R. Return TRUE if the operation does not raise an exception. + For details see "High Precision Division and Square Root", + Alan H. Karp and Peter Markstein, HP Lab Report 93-93-42, June + 1993. http://www.hpl.hp.com/techreports/93/HPL-93-42.pdf. */ -/* Convert e-type to unsigned 64-bit int. */ - -static void -etoudi (x, i) - const UEMUSHORT *x; - UEMUSHORT *i; +bool +real_sqrt (REAL_VALUE_TYPE *r, enum machine_mode mode, + const REAL_VALUE_TYPE *x) { - UEMUSHORT xi[NI]; - int j, k; + static REAL_VALUE_TYPE halfthree; + static bool init = false; + REAL_VALUE_TYPE h, t, i; + int iter, exp; - emovi (x, xi); - if (xi[0]) + /* sqrt(-0.0) is -0.0. */ + if (real_isnegzero (x)) { - xi[M] = 0; - goto noshift; + *r = *x; + return false; } - k = (int) xi[E] - (EXONE - 1); - if (k <= 0) + + /* Negative arguments return NaN. */ + if (real_isneg (x)) { - for (j = 0; j < 4; j++) - *i++ = 0; - return; + get_canonical_qnan (r, 0); + return false; } - if (k > 64) + + /* Infinity and NaN return themselves. */ + if (!real_isfinite (x)) { - for (j = 0; j < 4; j++) - *i++ = 0xffff; - if (extra_warnings) - warning ("overflow on truncation to integer"); - return; + *r = *x; + return false; } - if (k > 16) + + if (!init) { - /* Shift more than 16 bits: first shift up k-16 mod 16, - then shift up by 16's. */ - 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); + do_add (&halfthree, &dconst1, &dconsthalf, 0); + init = true; } - else + + /* Initial guess for reciprocal sqrt, i. */ + exp = real_exponent (x); + real_ldexp (&i, &dconst1, -exp/2); + + /* Newton's iteration for reciprocal sqrt, i. */ + for (iter = 0; iter < 16; iter++) { - /* shift not more than 16 bits */ - eshift (xi, k); + /* i(n+1) = i(n) * (1.5 - 0.5*i(n)*i(n)*x). */ + do_multiply (&t, x, &i); + do_multiply (&h, &t, &i); + do_multiply (&t, &h, &dconsthalf); + do_add (&h, &halfthree, &t, 1); + do_multiply (&t, &i, &h); -noshift: + /* Check for early convergence. */ + if (iter >= 6 && real_identical (&i, &t)) + break; - 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; - } + /* ??? Unroll loop to avoid copying. */ + i = t; } -} + /* Final iteration: r = i*x + 0.5*i*x*(1.0 - i*(i*x)). */ + do_multiply (&t, x, &i); + do_multiply (&h, &t, &i); + do_add (&i, &dconst1, &h, 1); + do_multiply (&h, &t, &i); + do_multiply (&i, &dconsthalf, &h); + do_add (&h, &t, &i, 0); -/* Convert e-type to signed 64-bit int. */ + /* ??? We need a Tuckerman test to get the last bit. */ -static void -etodi (x, i) - const UEMUSHORT *x; - UEMUSHORT *i; + real_convert (r, mode, &h); + return true; +} + +/* Calculate X raised to the integer exponent N in mode MODE and store + the result in R. Return true if the result may be inexact due to + loss of precision. The algorithm is the classic "left-to-right binary + method" described in section 4.6.3 of Donald Knuth's "Seminumerical + Algorithms", "The Art of Computer Programming", Volume 2. */ + +bool +real_powi (REAL_VALUE_TYPE *r, enum machine_mode mode, + const REAL_VALUE_TYPE *x, HOST_WIDE_INT n) { - unsigned EMULONG acc; - UEMUSHORT xi[NI]; - UEMUSHORT carry; - UEMUSHORT *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) + unsigned HOST_WIDE_INT bit; + REAL_VALUE_TYPE t; + bool inexact = false; + bool init = false; + bool neg; + int i; + + if (n == 0) { - for (j = 0; j < 4; j++) - *i++ = 0xffff; - if (extra_warnings) - warning ("overflow on truncation to integer"); - return; + *r = dconst1; + return false; } - isave = i; - if (k > 16) + else if (n < 0) { - /* Shift more than 16 bits: first shift up k-16 mod 16, - then shift up by 16's. */ - 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); + /* Don't worry about overflow, from now on n is unsigned. */ + neg = true; + n = -n; } else - { - /* shift not more than 16 bits */ - eshift (xi, k); + neg = false; - 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; - } - } - /* Negate if negative */ - if (xi[0]) + t = *x; + bit = (unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1); + for (i = 0; i < HOST_BITS_PER_WIDE_INT; i++) { - carry = 0; - if (WORDS_BIG_ENDIAN) - isave += 3; - for (k = 0; k < 4; k++) + if (init) { - acc = (unsigned EMULONG) (~(*isave) & 0xffff) + carry; - if (WORDS_BIG_ENDIAN) - *isave-- = acc; - else - *isave++ = acc; - carry = 0; - if (acc & 0x10000) - carry = 1; + inexact |= do_multiply (&t, &t, &t); + if (n & bit) + inexact |= do_multiply (&t, &t, x); } + else if (n & bit) + init = true; + bit >>= 1; } + + if (neg) + inexact |= do_divide (&t, &dconst1, &t); + + real_convert (r, mode, &t); + return inexact; } +/* Round X to the nearest integer not larger in absolute value, i.e. + towards zero, placing the result in R in mode MODE. */ -/* Longhand square root routine. */ +void +real_trunc (REAL_VALUE_TYPE *r, enum machine_mode mode, + const REAL_VALUE_TYPE *x) +{ + do_fix_trunc (r, x); + if (mode != VOIDmode) + real_convert (r, mode, r); +} +/* Round X to the largest integer not greater in value, i.e. round + down, placing the result in R in mode MODE. */ -static int esqinited = 0; -static unsigned short sqrndbit[NI]; +void +real_floor (REAL_VALUE_TYPE *r, enum machine_mode mode, + const REAL_VALUE_TYPE *x) +{ + REAL_VALUE_TYPE t; -static void -esqrt (x, y) - const UEMUSHORT *x; - UEMUSHORT *y; + do_fix_trunc (&t, x); + if (! real_identical (&t, x) && x->sign) + do_add (&t, &t, &dconstm1, 0); + if (mode != VOIDmode) + real_convert (r, mode, &t); + else + *r = t; +} + +/* Round X to the smallest integer not less then argument, i.e. round + up, placing the result in R in mode MODE. */ + +void +real_ceil (REAL_VALUE_TYPE *r, enum machine_mode mode, + const REAL_VALUE_TYPE *x) +{ + REAL_VALUE_TYPE t; + + do_fix_trunc (&t, x); + if (! real_identical (&t, x) && ! x->sign) + do_add (&t, &t, &dconst1, 0); + if (mode != VOIDmode) + real_convert (r, mode, &t); + else + *r = t; +} + +/* Round X to the nearest integer, but round halfway cases away from + zero. */ + +void +real_round (REAL_VALUE_TYPE *r, enum machine_mode mode, + const REAL_VALUE_TYPE *x) +{ + do_add (r, x, &dconsthalf, x->sign); + do_fix_trunc (r, r); + if (mode != VOIDmode) + real_convert (r, mode, r); +} + +/* Set the sign of R to the sign of X. */ + +void +real_copysign (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *x) +{ + r->sign = x->sign; +} + +/* Convert from REAL_VALUE_TYPE to MPFR. The caller is responsible + for initializing and clearing the MPFR parameter. */ + +void +mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mp_rnd_t rndmode) { - UEMUSHORT temp[NI], num[NI], sq[NI], xx[NI]; - EMULONG m, exp; - int i, j, k, n, nlups; + /* We use a string as an intermediate type. */ + char buf[128]; + int ret; - if (esqinited == 0) + /* Take care of Infinity and NaN. */ + if (r->cl == rvc_inf) { - ecleaz (sqrndbit); - sqrndbit[NI - 2] = 1; - esqinited = 1; + mpfr_set_inf (m, r->sign == 1 ? -1 : 1); + return; } - /* Check for arg <= 0 */ - i = ecmp (x, ezero); - if (i <= 0) + + if (r->cl == rvc_nan) { - if (i == -1) - { - mtherr ("esqrt", DOMAIN); - eclear (y); - } - else - emov (x, y); + mpfr_set_nan (m); return; } + + real_to_hexadecimal (buf, r, sizeof (buf), 0, 1); + /* mpfr_set_str() parses hexadecimal floats from strings in the same + format that GCC will output them. Nothing extra is needed. */ + ret = mpfr_set_str (m, buf, 16, rndmode); + gcc_assert (ret == 0); +} + +/* Convert from MPFR to REAL_VALUE_TYPE, for a given type TYPE and rounding + mode RNDMODE. TYPE is only relevant if M is a NaN. */ + +void +real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type, mp_rnd_t rndmode) +{ + /* We use a string as an intermediate type. */ + char buf[128], *rstr; + mp_exp_t exp; -#ifdef INFINITY - if (eisinf (x)) + /* Take care of Infinity and NaN. */ + if (mpfr_inf_p (m)) { - eclear (y); - einfin (y); + real_inf (r); + if (mpfr_sgn (m) < 0) + *r = REAL_VALUE_NEGATE (*r); return; } -#endif - /* Bring in the arg and renormalize if it is denormal. */ - emovi (x, xx); - m = (EMULONG) xx[1]; /* local long word exponent */ - if (m == 0) - m -= enormlz (xx); - - /* Divide exponent by 2 */ - m -= 0x3ffe; - exp = (unsigned short) ((m / 2) + 0x3ffe); - - /* Adjust if exponent odd */ - if ((m & 1) != 0) - { - if (m > 0) - exp += 1; - eshdn1 (xx); - } - ecleaz (sq); - ecleaz (num); - n = 8; /* get 8 bits of result per inner loop */ - nlups = rndprc; - j = 0; - - while (nlups > 0) + if (mpfr_nan_p (m)) { - /* bring in next word of arg */ - if (j < NE) - num[NI - 1] = xx[j + 3]; - /* Do additional bit on last outer loop, for roundoff. */ - if (nlups <= 8) - n = nlups + 1; - for (i = 0; i < n; i++) - { - /* Next 2 bits of arg */ - eshup1 (num); - eshup1 (num); - /* Shift up answer */ - eshup1 (sq); - /* Make trial divisor */ - for (k = 0; k < NI; k++) - temp[k] = sq[k]; - eshup1 (temp); - eaddm (sqrndbit, temp); - /* Subtract and insert answer bit if it goes in */ - if (ecmpm (temp, num) <= 0) - { - esubm (temp, num); - sq[NI - 2] |= 1; - } - } - nlups -= n; - j += 1; + real_nan (r, "", 1, TYPE_MODE (type)); + return; } - /* Adjust for extra, roundoff loop done. */ - exp += (NBITS - 1) - rndprc; + rstr = mpfr_get_str (NULL, &exp, 16, 0, m, rndmode); - /* Sticky bit = 1 if the remainder is nonzero. */ - k = 0; - for (i = 3; i < NI; i++) - k |= (int) num[i]; - - /* Renormalize and round off. */ - emdnorm (sq, k, 0, exp, 64); - emovo (sq, y); -} -#endif -#endif /* EMU_NON_COMPILE not defined */ - -/* Return the binary precision of the significand for a given - floating point mode. The mode can hold an integer value - that many bits wide, without losing any bits. */ + /* The additional 12 chars add space for the sprintf below. This + leaves 6 digits for the exponent which is supposedly enough. */ + gcc_assert (rstr != NULL && strlen (rstr) < sizeof (buf) - 12); -unsigned int -significand_size (mode) - enum machine_mode mode; -{ + /* REAL_VALUE_ATOF expects the exponent for mantissa * 2**exp, + mpfr_get_str returns the exponent for mantissa * 16**exp, adjust + for that. */ + exp *= 4; -/* Don't test the modes, but their sizes, lest this - code won't work for BITS_PER_UNIT != 8 . */ + if (rstr[0] == '-') + sprintf (buf, "-0x.%sp%d", &rstr[1], (int) exp); + else + sprintf (buf, "0x.%sp%d", rstr, (int) exp); -switch (GET_MODE_BITSIZE (mode)) - { - case 32: + mpfr_free_str (rstr); + + real_from_string (r, buf); +} -#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT - return 56; -#endif +/* Check whether the real constant value given is an integer. */ - 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 +bool +real_isinteger (const REAL_VALUE_TYPE *c, enum machine_mode mode) +{ + REAL_VALUE_TYPE cint; - case 96: - return 64; + real_trunc (&cint, mode, c); + return real_identical (c, &cint); +} - case 128: -#if (INTEL_EXTENDED_IEEE_FORMAT == 0) - return 113; -#else - return 64; -#endif +/* Write into BUF the maximum representable finite floating-point + number, (1 - b**-p) * b**emax for a given FP format FMT as a hex + float string. LEN is the size of BUF, and the buffer must be large + enough to contain the resulting string. */ - default: - abort (); - } +void +get_max_float (const struct real_format *fmt, char *buf, size_t len) +{ + int i, n; + char *p; + + strcpy (buf, "0x0."); + n = fmt->p; + for (i = 0, p = buf + 4; i + 3 < n; i += 4) + *p++ = 'f'; + if (i < n) + *p++ = "08ce"[n - i]; + sprintf (p, "p%d", fmt->emax); + if (fmt->pnan < fmt->p) + { + /* This is an IBM extended double format made up of two IEEE + doubles. The value of the long double is the sum of the + values of the two parts. The most significant part is + required to be the value of the long double rounded to the + nearest double. Rounding means we need a slightly smaller + value for LDBL_MAX. */ + buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4]; + } + + gcc_assert (strlen (buf) < len); }