summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/real.c
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
committerkan <kan@FreeBSD.org>2003-07-11 03:40:53 +0000
commitb2a8872fbe1ec1c49094559ac7b78e6ea4ab7180 (patch)
treef6b0610f4a17fd26aa234354f050080f789861a4 /contrib/gcc/real.c
parent52e69d78eee5612ac195e0701a5cebe40d1ab0e1 (diff)
downloadFreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.zip
FreeBSD-src-b2a8872fbe1ec1c49094559ac7b78e6ea4ab7180.tar.gz
Gcc 3.3.1-pre as of 2003-07-11.
Diffstat (limited to 'contrib/gcc/real.c')
-rw-r--r--contrib/gcc/real.c9558
1 files changed, 3489 insertions, 6069 deletions
diff --git a/contrib/gcc/real.c b/contrib/gcc/real.c
index 7b8879b..61cbf2e 100644
--- a/contrib/gcc/real.c
+++ b/contrib/gcc/real.c
@@ -1,6995 +1,4415 @@
-/* real.c - implementation of REAL_ARITHMETIC, REAL_VALUE_ATOF,
- and support for XFmode IEEE extended real floating point arithmetic.
+/* real.c - software floating point emulation.
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
Contributed by Stephen L. Moshier (moshier@world.std.com).
+ Re-written by Richard Henderson <rth@redhat.com>
-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 2, 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 COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
#include "config.h"
#include "system.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. */
+/* The floating point model used internally is not exactly IEEE 754
+ compliant, and close to the description in the ISO C 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 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 29.
+
+ Note that the decimal string conversion routines are sensitive to
+ rounding error. 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.
+
+ Target floating point models that use base 16 instead of base 2
+ (i.e. IBM 370), are handled during round_for_format, in which we
+ canonicalize the exponent to be a multiple of 4 (log2(16)), and
+ adjust the significand to match. */
+
+
+/* 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 PARAMS ((REAL_VALUE_TYPE *, int));
+static void get_canonical_qnan PARAMS ((REAL_VALUE_TYPE *, int));
+static void get_canonical_snan PARAMS ((REAL_VALUE_TYPE *, int));
+static void get_inf PARAMS ((REAL_VALUE_TYPE *, int));
+static bool sticky_rshift_significand PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ unsigned int));
+static void rshift_significand PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ unsigned int));
+static void lshift_significand PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ unsigned int));
+static void lshift_significand_1 PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static bool add_significands PARAMS ((REAL_VALUE_TYPE *r,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static bool sub_significands PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int));
+static void neg_significand PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static int cmp_significands PARAMS ((const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static int cmp_significand_0 PARAMS ((const REAL_VALUE_TYPE *));
+static void set_significand_bit PARAMS ((REAL_VALUE_TYPE *, unsigned int));
+static void clear_significand_bit PARAMS ((REAL_VALUE_TYPE *, unsigned int));
+static bool test_significand_bit PARAMS ((REAL_VALUE_TYPE *, unsigned int));
+static void clear_significand_below PARAMS ((REAL_VALUE_TYPE *,
+ unsigned int));
+static bool div_significands PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static void normalize PARAMS ((REAL_VALUE_TYPE *));
+
+static void do_add PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int));
+static void do_multiply PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static void do_divide PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+static int do_compare PARAMS ((const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int));
+static void do_fix_trunc PARAMS ((REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *));
+
+static unsigned long rtd_divmod PARAMS ((REAL_VALUE_TYPE *,
+ REAL_VALUE_TYPE *));
+
+static const REAL_VALUE_TYPE * ten_to_ptwo PARAMS ((int));
+static const REAL_VALUE_TYPE * ten_to_mptwo PARAMS ((int));
+static const REAL_VALUE_TYPE * real_digit PARAMS ((int));
+static void times_pten PARAMS ((REAL_VALUE_TYPE *, int));
+
+static void round_for_format PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *));
-/* 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 <Richard.Earnshaw@cl.cam.ac.uk>,
- 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
-
-/* 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
+/* Initialize R with a positive zero. */
-/* 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
-
-#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 (r, sign)
+ 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 (r, sign)
+ REAL_VALUE_TYPE *r;
+ int sign;
+{
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_nan;
+ r->sign = sign;
+ r->sig[SIGSZ-1] = SIG_MSB >> 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 (r, sign)
+ REAL_VALUE_TYPE *r;
+ int sign;
+{
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_nan;
+ r->sign = sign;
+ r->sig[SIGSZ-1] = SIG_MSB >> 2;
+}
-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 (r, sign)
+ REAL_VALUE_TYPE *r;
+ int sign;
+{
+ memset (r, 0, sizeof (*r));
+ r->class = 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 (r, a, n)
+ 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 (REAL_WORDS_BIG_ENDIAN)
+ if (n >= HOST_BITS_PER_LONG)
{
- switch (mode)
- {
- 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;
+ for (i = 0, ofs = n / HOST_BITS_PER_LONG; i < ofs; ++i)
+ sticky |= a->sig[i];
+ n &= HOST_BITS_PER_LONG - 1;
+ }
- default:
- abort ();
+ if (n != 0)
+ {
+ sticky |= a->sig[ofs] & (((unsigned long)1 << n) - 1);
+ for (i = 0; i < SIGSZ; ++i)
+ {
+ 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 (r, a, n)
+ 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 (r, a, n)
+ 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 (r, a)
+ 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 (r, a, b)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *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 (r, a, b, carry)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *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;
-}
+ unsigned long ai = a->sig[i];
+ unsigned long ri = ai - b->sig[i];
-/* Round real toward zero to unsigned HOST_WIDE_INT
- implements REAL_VALUE_UNSIGNED_FIX (x).
- Negative input returns zero. */
-
-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 (r, a)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a;
{
- UEMUSHORT df[NE], dg[NE];
- HOST_WIDE_INT low, high;
- int sign;
-
- if (GET_MODE_CLASS (mode) != MODE_FLOAT)
- abort ();
- sign = 0;
- low = i;
- if ((high = j) < 0)
- {
- sign = 1;
- /* complement and add 1 */
- high = ~high;
- if (low)
- low = -low;
- else
- high += 1;
- }
- eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
- ultoe ((unsigned HOST_WIDE_INT *) &high, dg);
- emul (dg, df, dg);
- ultoe ((unsigned HOST_WIDE_INT *) &low, df);
- eadd (df, dg, dg);
- if (sign)
- eneg (dg);
+ bool carry = true;
+ int i;
- /* 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))
+ for (i = 0; i < SIGSZ; ++i)
{
- case 32:
- etoe24 (dg, df);
- e24toe (df, dg);
- break;
-
- case 64:
- etoe53 (dg, df);
- e53toe (df, dg);
- break;
+ unsigned long ri, ai = a->sig[i];
- 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;
-
- default:
- abort ();
- }
-
- PUT_REAL (dg, d);
-}
+ if (carry)
+ {
+ if (ai)
+ {
+ ri = -ai;
+ carry = false;
+ }
+ else
+ ri = ai;
+ }
+ else
+ ri = ~ai;
+ r->sig[i] = ri;
+ }
+}
-/* REAL_VALUE_FROM_UNSIGNED_INT macro. */
+/* Compare significands. Return tri-state vs zero. */
-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_significands (a, b)
+ const REAL_VALUE_TYPE *a, *b;
{
- UEMUSHORT df[NE], dg[NE];
- unsigned HOST_WIDE_INT low, high;
+ int i;
- 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))
+ for (i = SIGSZ - 1; i >= 0; --i)
{
- 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;
+ 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_TO_INT macro. */
-
-void
-ereal_to_int (low, high, rr)
- HOST_WIDE_INT *low, *high;
- REAL_VALUE_TYPE rr;
+static inline int
+cmp_significand_0 (a)
+ const REAL_VALUE_TYPE *a;
{
- 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;
- }
-}
-
-
-/* REAL_VALUE_LDEXP macro. */
+ int i;
-REAL_VALUE_TYPE
-ereal_ldexp (x, n)
- REAL_VALUE_TYPE x;
- int n;
-{
- UEMUSHORT e[NE], y[NE];
- REAL_VALUE_TYPE r;
+ for (i = SIGSZ - 1; i >= 0; --i)
+ if (a->sig[i])
+ return 1;
- GET_REAL (&x, e);
-#ifdef NANS
- if (eisnan (e))
- return (x);
-#endif
- eldexp (e, n, y);
- PUT_REAL (y, &r);
- return (r);
+ return 0;
}
-/* These routines are conditionally compiled because functions
- of the same names may be defined in fold-const.c. */
-
-#ifdef REAL_ARITHMETIC
-
-/* Check for infinity in a REAL_VALUE_TYPE. */
+/* Set bit N of the significand of R. */
-int
-target_isinf (x)
- REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
+static inline void
+set_significand_bit (r, n)
+ REAL_VALUE_TYPE *r;
+ unsigned int n;
{
-#ifdef INFINITY
- UEMUSHORT e[NE];
-
- GET_REAL (&x, e);
- return (eisinf (e));
-#else
- return 0;
-#endif
+ r->sig[n / HOST_BITS_PER_LONG]
+ |= (unsigned long)1 << (n % HOST_BITS_PER_LONG);
}
-/* Check whether a REAL_VALUE_TYPE item is a NaN. */
+/* Clear bit N of the significand of R. */
-int
-target_isnan (x)
- REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
+static inline void
+clear_significand_bit (r, n)
+ REAL_VALUE_TYPE *r;
+ unsigned int n;
{
-#ifdef NANS
- UEMUSHORT e[NE];
-
- GET_REAL (&x, e);
- return (eisnan (e));
-#else
- return (0);
-#endif
+ r->sig[n / HOST_BITS_PER_LONG]
+ &= ~((unsigned long)1 << (n % HOST_BITS_PER_LONG));
}
+/* Test bit N of the significand of R. */
-/* Check for a negative REAL_VALUE_TYPE number.
- This just checks the sign bit, so that -0 counts as negative. */
-
-int
-target_negative (x)
- REAL_VALUE_TYPE x;
+static inline bool
+test_significand_bit (r, n)
+ REAL_VALUE_TYPE *r;
+ unsigned int n;
{
- return ereal_isneg (x);
+ /* ??? 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;
}
-/* Expansion of REAL_VALUE_TRUNCATE.
- The result is in floating point, rounded to nearest or even. */
+/* Clear bits 0..N-1 of the significand of R. */
-REAL_VALUE_TYPE
-real_value_truncate (mode, arg)
- enum machine_mode mode;
- REAL_VALUE_TYPE arg;
+static void
+clear_significand_below (r, n)
+ REAL_VALUE_TYPE *r;
+ unsigned int n;
{
- UEMUSHORT e[NE], t[NE];
- REAL_VALUE_TYPE r;
+ int i, w = n / HOST_BITS_PER_LONG;
- 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 */
+ for (i = 0; i < w; ++i)
+ r->sig[i] = 0;
- case XFmode:
- etoe64 (e, t);
- e64toe (t, t);
- break;
+ r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1);
+}
- case DFmode:
- etoe53 (e, t);
- e53toe (t, t);
- break;
+/* Divide the significands of A and B, placing the result in R. Return
+ true if the division was inexact. */
- case SFmode:
-#ifndef C4X
- case HFmode:
-#endif
- etoe24 (e, t);
- e24toe (t, t);
- break;
+static inline bool
+div_significands (r, a, b)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
+{
+ REAL_VALUE_TYPE u;
+ int i, bit = SIGNIFICAND_BITS - 1;
+ unsigned long msb, inexact;
-#ifdef C4X
- case HFmode:
- case QFmode:
- etoe53 (e, t);
- e53toe (t, t);
- break;
-#endif
+ u = *a;
+ memset (r->sig, 0, sizeof (r->sig));
- case SImode:
- r = etrunci (arg);
- return (r);
+ 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);
- /* If an unsupported type was requested, presume that
- the machine files know something useful to do with
- the unmodified value. */
+ for (i = 0, inexact = 0; i < SIGSZ; i++)
+ inexact |= u.sig[i];
- default:
- return (arg);
- }
- PUT_REAL (t, &r);
- return (r);
+ return inexact != 0;
}
-/* Try to change R into its exact multiplicative inverse in machine mode
- MODE. Return nonzero function value if successful. */
+/* 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.) */
-int
-exact_real_inverse (mode, r)
- enum machine_mode mode;
+static void
+normalize (r)
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;
+ int shift = 0, exp;
+ int i, j;
- /* 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;
+ /* 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;
- for (i = 0; i < NE - 2; i++)
+ /* Zero significand flushes to zero. */
+ if (i < 0)
{
- if (e[i] != 0)
- return 0;
+ r->class = rvc_zero;
+ r->exp = 0;
+ return;
}
- /* 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);
-
- /* Check the bits again, because the truncation might have
- generated an arbitrary saturation value on overflow. */
- if (einv[NE - 2] != 0x8000)
- return 0;
+ /* 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;
+ shift += j;
- for (i = 0; i < NE - 2; i++)
+ if (shift > 0)
{
- if (einv[i] != 0)
- return 0;
+ exp = r->exp - shift;
+ if (exp > MAX_EXP)
+ get_inf (r, r->sign);
+ else if (exp < -MAX_EXP)
+ get_zero (r, r->sign);
+ else
+ {
+ r->exp = exp;
+ lshift_significand (r, r, shift);
+ }
}
-
- /* 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 */
-
-/* Used for debugging--print the value of R in human-readable format
- on stderr. */
-
-void
-debug_real (r)
- REAL_VALUE_TYPE r;
-{
- char dstr[30];
-
- REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr);
- fprintf (stderr, "%s", dstr);
-}
-
-/* The following routines convert REAL_VALUE_TYPE to the various floating
- point formats that are meaningful to supported computers.
+/* Return R = A + (SUBTRACT_P ? -B : B). */
- The results are returned in 32-bit pieces, each piece stored in a `long'.
- This is so they can be printed by statements like
-
- fprintf (file, "%lx, %lx", L[0], L[1]);
-
- that will work on both narrow- and wide-word host computers. */
-
-/* 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. */
-
-void
-etartdouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
+static void
+do_add (r, a, b, subtract_p)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
+ int subtract_p;
{
- UEMUSHORT e[NE];
+ int dexp, sign, exp;
+ REAL_VALUE_TYPE t;
+ bool inexact = false;
- GET_REAL (&r, e);
-#if INTEL_EXTENDED_IEEE_FORMAT == 0
- etoe113 (e, e);
-#else
- etoe64 (e, e);
-#endif
- endian (e, l, TFmode);
-}
+ /* Determine if we need to add or subtract. */
+ sign = a->sign;
+ subtract_p = (sign ^ b->sign) ^ subtract_p;
-/* 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. */
+ switch (CLASS2 (a->class, b->class))
+ {
+ case CLASS2 (rvc_zero, rvc_zero):
+ /* -0 + -0 = -0, -0 - +0 = -0; all other cases yield +0. */
+ get_zero (r, sign & !subtract_p);
+ return;
-void
-etarldouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
-{
- UEMUSHORT e[NE];
+ 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;
- GET_REAL (&r, e);
- etoe64 (e, e);
- endian (e, l, XFmode);
-}
+ 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;
-/* 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. */
+ case CLASS2 (rvc_inf, rvc_inf):
+ if (subtract_p)
+ /* Inf - Inf = NaN. */
+ get_canonical_qnan (r, 0);
+ else
+ /* Inf + Inf = Inf. */
+ *r = *a;
+ return;
-void
-etardouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
-{
- UEMUSHORT e[NE];
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
- GET_REAL (&r, e);
- etoe53 (e, e);
- endian (e, l, DFmode);
-}
+ default:
+ abort ();
+ }
-/* Convert R to a single precision float value stored in the least-significant
- bits of a `long'. */
+ /* Swap the arguments such that A has the larger exponent. */
+ dexp = a->exp - b->exp;
+ if (dexp < 0)
+ {
+ const REAL_VALUE_TYPE *t;
+ t = a, a = b, b = t;
+ dexp = -dexp;
+ sign ^= subtract_p;
+ }
+ exp = a->exp;
-long
-etarsingle (r)
- REAL_VALUE_TYPE r;
-{
- UEMUSHORT e[NE];
- long l;
+ /* 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;
+ }
- GET_REAL (&r, e);
- etoe24 (e, e);
- endian (e, &l, SFmode);
- return ((long) l);
-}
+ inexact |= sticky_rshift_significand (&t, b, dexp);
+ b = &t;
+ }
-/* 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. */
+ if (subtract_p)
+ {
+ 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;
+ }
+ }
+ }
-void
-ereal_to_decimal (x, s)
- REAL_VALUE_TYPE x;
- char *s;
-{
- UEMUSHORT e[NE];
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp;
- GET_REAL (&x, e);
- etoasc (e, s, 20);
+ /* Re-normalize the result. */
+ normalize (r);
+
+ /* Special case: if the subtraction results in zero, the result
+ is positive. */
+ if (r->class == rvc_zero)
+ r->sign = 0;
+ else
+ r->sig[0] |= inexact;
}
-/* Compare X and Y. Return 1 if X > Y, 0 if X == Y, -1 if X < Y,
- or -2 if either is a NaN. */
+/* Return R = A * B. */
-int
-ereal_cmp (x, y)
- REAL_VALUE_TYPE x, y;
+static void
+do_multiply (r, a, b)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
{
- UEMUSHORT ex[NE], ey[NE];
+ REAL_VALUE_TYPE u, t, *rr;
+ unsigned int i, j, k;
+ int sign = a->sign ^ b->sign;
- GET_REAL (&x, ex);
- GET_REAL (&y, ey);
- return (ecmp (ex, ey));
-}
+ switch (CLASS2 (a->class, b->class))
+ {
+ 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;
-/* Return 1 if the sign bit of X is set, else return 0. */
+ 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;
-int
-ereal_isneg (x)
- REAL_VALUE_TYPE x;
-{
- UEMUSHORT ex[NE];
+ 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;
- GET_REAL (&x, ex);
- return (eisneg (ex));
-}
+ case CLASS2 (rvc_zero, rvc_inf):
+ case CLASS2 (rvc_inf, rvc_zero):
+ /* 0 * Inf = NaN */
+ get_canonical_qnan (r, sign);
+ return;
-/* End of REAL_ARITHMETIC interface */
-
-/*
- Extended precision IEEE binary floating point arithmetic routines
+ case CLASS2 (rvc_inf, rvc_inf):
+ case CLASS2 (rvc_normal, rvc_inf):
+ case CLASS2 (rvc_inf, rvc_normal):
+ /* Inf * Inf = Inf, R * Inf = Inf */
+ overflow:
+ get_inf (r, sign);
+ return;
- Numbers are stored in C language as arrays of 16-bit unsigned
- short integers. The arguments of the routines are pointers to
- the arrays.
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
- External e type data structure, similar to Intel 8087 chip
- temporary real format but possibly with a larger significand:
+ default:
+ abort ();
+ }
- 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 (r == a || r == b)
+ rr = &t;
+ else
+ rr = r;
+ get_zero (rr, 0);
+ /* Collect all the partial products. Since we don't have sure access
+ to a widening multiply, we split each long into two half-words.
- Internal exploded e-type data structure of a number (a "word" is 16 bits):
+ Consider the long-hand form of a four half-word multiplication:
- 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)
+ A B C D
+ * E F G H
+ --------------
+ DE DF DG DH
+ CE CF CG CH
+ BE BF BG BH
+ AE AF AG AH
+ 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. */
+ 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;
- Routines for external format e-type numbers
+ if (ai == 0)
+ continue;
- 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
+ for (j = 0; j < 2; ++j)
+ {
+ int exp = (a->exp - (2*SIGSZ-1-i)*(HOST_BITS_PER_LONG/2)
+ + (b->exp - (1-j)*(HOST_BITS_PER_LONG/2)));
- 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
+ if (exp > MAX_EXP)
+ goto overflow;
+ if (exp < -MAX_EXP)
+ /* Would underflow to zero, which we shouldn't bother adding. */
+ continue;
-/* Control register for rounding precision.
- This can be set to 113 (if NE=10), 80 (if NE=6), 64, 56, 53, or 24 bits. */
+ u.class = rvc_normal;
+ u.sign = 0;
+ u.exp = exp;
-int rndprc = NBITS;
-extern int rndprc;
+ 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;
-/* Clear out entire e-type number X. */
+ u.sig[k / 2] = ai * bi;
+ }
-static void
-eclear (x)
- UEMUSHORT *x;
-{
- int i;
+ normalize (&u);
+ do_add (rr, rr, &u, 0);
+ }
+ }
- for (i = 0; i < NE; i++)
- *x++ = 0;
+ rr->sign = sign;
+ if (rr != r)
+ *r = t;
}
-/* Move e-type number from A to B. */
+/* Return R = A / B. */
static void
-emov (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
+do_divide (r, a, b)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a, *b;
{
- int i;
-
- for (i = 0; i < NE; i++)
- *b++ = *a++;
-}
+ int exp, sign = a->sign ^ b->sign;
+ REAL_VALUE_TYPE t, *rr;
+ bool inexact;
+ switch (CLASS2 (a->class, b->class))
+ {
+ case CLASS2 (rvc_zero, rvc_zero):
+ /* 0 / 0 = NaN. */
+ case CLASS2 (rvc_inf, rvc_inf):
+ /* Inf / Inf = NaN. */
+ get_canonical_qnan (r, sign);
+ return;
-#if 0
-/* Absolute value of e-type X. */
+ case CLASS2 (rvc_zero, rvc_normal):
+ case CLASS2 (rvc_zero, rvc_inf):
+ /* 0 / ANY = 0. */
+ case CLASS2 (rvc_normal, rvc_inf):
+ /* R / Inf = 0. */
+ underflow:
+ get_zero (r, sign);
+ return;
-static void
-eabs (x)
- UEMUSHORT x[];
-{
- /* sign is top bit of last word of external format */
- x[NE - 1] &= 0x7fff;
-}
-#endif /* 0 */
+ case CLASS2 (rvc_normal, rvc_zero):
+ /* R / 0 = Inf. */
+ case CLASS2 (rvc_inf, rvc_zero):
+ /* Inf / 0 = Inf. */
+ get_inf (r, sign);
+ return;
-/* Negate the e-type number X. */
+ 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;
-static void
-eneg (x)
- UEMUSHORT x[];
-{
+ 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;
- x[NE - 1] ^= 0x8000; /* Toggle the sign bit */
-}
+ case CLASS2 (rvc_inf, rvc_normal):
+ /* Inf / R = Inf. */
+ overflow:
+ get_inf (r, sign);
+ return;
-/* Return 1 if sign bit of e-type number X is nonzero, else zero. */
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
-static int
-eisneg (x)
- const UEMUSHORT x[];
-{
+ default:
+ abort ();
+ }
- if (x[NE - 1] & 0x8000)
- return (1);
+ if (r == a || r == b)
+ rr = &t;
else
- return (0);
-}
+ rr = r;
-/* Return 1 if e-type number X is infinity, else return zero. */
+ rr->class = rvc_normal;
+ rr->sign = sign;
-static int
-eisinf (x)
- const UEMUSHORT x[];
-{
+ exp = a->exp - b->exp + 1;
+ if (exp > MAX_EXP)
+ goto overflow;
+ if (exp < -MAX_EXP)
+ goto underflow;
+ rr->exp = exp;
-#ifdef NANS
- if (eisnan (x))
- return (0);
-#endif
- if ((x[NE - 1] & 0x7fff) == 0x7fff)
- return (1);
- else
- return (0);
+ inexact = div_significands (rr, a, b);
+
+ /* Re-normalize the result. */
+ normalize (rr);
+ rr->sig[0] |= inexact;
+
+ if (rr != r)
+ *r = t;
}
-/* 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 a tri-state comparison of A vs B. Return NAN_RESULT if
+ one of the two operands is a NaN. */
static int
-eisnan (x)
- const UEMUSHORT x[] ATTRIBUTE_UNUSED;
+do_compare (a, b, nan_result)
+ const REAL_VALUE_TYPE *a, *b;
+ int nan_result;
{
-#ifdef NANS
- int i;
+ int ret;
- /* 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 (CLASS2 (a->class, b->class))
{
- if (*x++ != 0)
- return (1);
- }
-#endif
+ case CLASS2 (rvc_zero, rvc_zero):
+ /* Sign of zero doesn't matter for compares. */
+ return 0;
- return (0);
-}
+ case CLASS2 (rvc_inf, rvc_zero):
+ case CLASS2 (rvc_inf, rvc_normal):
+ case CLASS2 (rvc_normal, rvc_zero):
+ return (a->sign ? -1 : 1);
-/* Fill e-type number X with infinity pattern (IEEE)
- or largest possible number (non-IEEE). */
+ case CLASS2 (rvc_inf, rvc_inf):
+ return -a->sign - -b->sign;
-static void
-einfin (x)
- UEMUSHORT *x;
-{
- int i;
+ case CLASS2 (rvc_zero, rvc_normal):
+ case CLASS2 (rvc_zero, rvc_inf):
+ case CLASS2 (rvc_normal, rvc_inf):
+ return (b->sign ? 1 : -1);
-#ifdef INFINITY
- for (i = 0; i < NE - 1; i++)
- *x++ = 0;
- *x |= 32767;
-#else
- for (i = 0; i < NE - 1; i++)
- *x++ = 0xffff;
- *x |= 32766;
- if (rndprc < NBITS)
- {
- if (rndprc == 113)
- {
- *(x - 9) = 0;
- *(x - 8) = 0;
- }
- if (rndprc == 64)
- {
- *(x - 5) = 0;
- }
- if (rndprc == 53)
- {
- *(x - 4) = 0xf800;
- }
- else
- {
- *(x - 4) = 0;
- *(x - 3) = 0;
- *(x - 2) = 0xff00;
- }
+ 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;
+
+ default:
+ abort ();
}
-#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. */
+ if (a->sign != b->sign)
+ return -a->sign - -b->sign;
-#ifdef NANS
-static void
-enan (x, sign)
- UEMUSHORT *x;
- int sign;
-{
- int i;
+ if (a->exp > b->exp)
+ ret = 1;
+ else if (a->exp < b->exp)
+ ret = -1;
+ else
+ ret = cmp_significands (a, b);
- for (i = 0; i < NE - 2; i++)
- *x++ = 0;
- *x++ = 0xc000;
- *x = (sign << 15) | 0x7fff;
+ return (a->sign ? -ret : ret);
}
-#endif /* NANS */
-/* Move in an e-type number A, converting it to exploded e-type B. */
+/* Return A truncated to an integral value toward zero. */
static void
-emovi (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
+do_fix_trunc (r, a)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *a;
{
- const UEMUSHORT *p;
- UEMUSHORT *q;
- int i;
+ *r = *a;
- 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)
+ switch (r->class)
{
-#ifdef NANS
- if (eisnan (a))
- {
- *q++ = 0;
- for (i = 3; i < NI; i++)
- *q++ = *p--;
- return;
- }
-#endif
+ case rvc_zero:
+ case rvc_inf:
+ case rvc_nan:
+ break;
- for (i = 2; i < NI; i++)
- *q++ = 0;
- return;
- }
-#endif
+ case rvc_normal:
+ if (r->exp <= 0)
+ get_zero (r, r->sign);
+ else if (r->exp < SIGNIFICAND_BITS)
+ clear_significand_below (r, SIGNIFICAND_BITS - r->exp);
+ break;
- /* 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;
+ default:
+ abort ();
+ }
}
-/* Move out exploded e-type number A, converting it to e type B. */
+/* Perform the binary or unary operation described by CODE.
+ For a unary operation, leave OP1 NULL. */
-static void
-emovo (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
+void
+real_arithmetic (r, icode, op0, op1)
+ REAL_VALUE_TYPE *r;
+ int icode;
+ const REAL_VALUE_TYPE *op0, *op1;
{
- 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)
+ enum tree_code code = icode;
+
+ switch (code)
{
-#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++;
-}
+ case PLUS_EXPR:
+ do_add (r, op0, op1, 0);
+ break;
-/* Clear out exploded e-type number XI. */
+ case MINUS_EXPR:
+ do_add (r, op0, op1, 1);
+ break;
-static void
-ecleaz (xi)
- UEMUSHORT *xi;
-{
- int i;
+ case MULT_EXPR:
+ do_multiply (r, op0, op1);
+ break;
- for (i = 0; i < NI; i++)
- *xi++ = 0;
-}
+ case RDIV_EXPR:
+ do_divide (r, op0, op1);
+ break;
-/* Clear out exploded e-type XI, but don't touch the sign. */
+ case MIN_EXPR:
+ if (op1->class == rvc_nan)
+ *r = *op1;
+ else if (do_compare (op0, op1, -1) < 0)
+ *r = *op0;
+ else
+ *r = *op1;
+ break;
-static void
-ecleazs (xi)
- UEMUSHORT *xi;
-{
- int i;
+ case MAX_EXPR:
+ if (op1->class == rvc_nan)
+ *r = *op1;
+ else if (do_compare (op0, op1, 1) < 0)
+ *r = *op1;
+ else
+ *r = *op0;
+ break;
- ++xi;
- for (i = 0; i < NI - 1; i++)
- *xi++ = 0;
-}
+ case NEGATE_EXPR:
+ *r = *op0;
+ r->sign ^= 1;
+ break;
-/* Move exploded e-type number from A to B. */
+ case ABS_EXPR:
+ *r = *op0;
+ r->sign = 0;
+ break;
-static void
-emovz (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
-{
- int i;
+ case FIX_TRUNC_EXPR:
+ do_fix_trunc (r, op0);
+ break;
- for (i = 0; i < NI - 1; i++)
- *b++ = *a++;
- /* clear low guard word */
- *b = 0;
+ default:
+ abort ();
+ }
}
-/* Generate exploded e-type NaN.
- The explicit pattern for this is maximum exponent and
- top two significant bits set. */
+/* Legacy. Similar, but return the result directly. */
-#ifdef NANS
-static void
-einan (x)
- UEMUSHORT x[];
+REAL_VALUE_TYPE
+real_arithmetic2 (icode, op0, op1)
+ int icode;
+ const REAL_VALUE_TYPE *op0, *op1;
{
-
- ecleaz (x);
- x[E] = 0x7fff;
- x[M + 1] = 0xc000;
+ REAL_VALUE_TYPE r;
+ real_arithmetic (&r, icode, op0, op1);
+ return r;
}
-#endif /* NANS */
-/* Return nonzero if exploded e-type X is a NaN. */
-
-#ifdef NANS
-static int
-eiisnan (x)
- const UEMUSHORT x[];
+bool
+real_compare (icode, op0, op1)
+ int icode;
+ const REAL_VALUE_TYPE *op0, *op1;
{
- int i;
+ enum tree_code code = icode;
- if ((x[E] & 0x7fff) == 0x7fff)
+ switch (code)
{
- for (i = M + 1; i < NI; i++)
- {
- if (x[i] != 0)
- return (1);
- }
+ 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->class == rvc_nan || op1->class == rvc_nan;
+ case ORDERED_EXPR:
+ return op0->class != rvc_nan && op1->class != 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;
+
+ default:
+ abort ();
}
- return (0);
}
-#endif /* NANS */
-/* Return nonzero if sign of exploded e-type X is nonzero. */
+/* Return floor log2(R). */
-#ifdef NANS
-static int
-eiisneg (x)
- const UEMUSHORT x[];
-{
-
- return x[0] != 0;
+int
+real_exponent (r)
+ const REAL_VALUE_TYPE *r;
+{
+ switch (r->class)
+ {
+ case rvc_zero:
+ return 0;
+ case rvc_inf:
+ case rvc_nan:
+ return (unsigned int)-1 >> 1;
+ case rvc_normal:
+ return r->exp;
+ default:
+ abort ();
+ }
}
-#endif /* NANS */
-#if 0
-/* Fill exploded e-type X with infinity pattern.
- This has maximum exponent and significand all zeros. */
+/* R = OP0 * 2**EXP. */
-static void
-eiinfin (x)
- UEMUSHORT x[];
+void
+real_ldexp (r, op0, exp)
+ REAL_VALUE_TYPE *r;
+ const REAL_VALUE_TYPE *op0;
+ int exp;
{
+ *r = *op0;
+ switch (r->class)
+ {
+ case rvc_zero:
+ case rvc_inf:
+ case rvc_nan:
+ break;
- ecleaz (x);
- x[E] = 0x7fff;
-}
-#endif /* 0 */
-
-/* Return nonzero if exploded e-type X is infinite. */
-
-#ifdef INFINITY
-static int
-eiisinf (x)
- const UEMUSHORT x[];
-{
+ case rvc_normal:
+ exp += op0->exp;
+ if (exp > MAX_EXP)
+ get_inf (r, r->sign);
+ else if (exp < -MAX_EXP)
+ get_zero (r, r->sign);
+ else
+ r->exp = exp;
+ break;
-#ifdef NANS
- if (eiisnan (x))
- return (0);
-#endif
- if ((x[E] & 0x7fff) == 0x7fff)
- return (1);
- return (0);
+ default:
+ abort ();
+ }
}
-#endif /* INFINITY */
-/* Compare significands of numbers in internal exploded e-type format.
- Guard words are included in the comparison.
+/* Determine whether a floating-point value X is infinite. */
- Returns +1 if a > b
- 0 if a == b
- -1 if a < b */
-
-static int
-ecmpm (a, b)
- const UEMUSHORT *a, *b;
+bool
+real_isinf (r)
+ const REAL_VALUE_TYPE *r;
{
- int i;
-
- a += M; /* skip up to significand area */
- b += M;
- for (i = M; i < NI; i++)
- {
- if (*a++ != *b++)
- goto difrnt;
- }
- return (0);
-
- difrnt:
- if (*(--a) > *(--b))
- return (1);
- else
- return (-1);
+ return (r->class == rvc_inf);
}
-/* Shift significand of exploded e-type X down by 1 bit. */
+/* Determine whether a floating-point value X is a NaN. */
-static void
-eshdn1 (x)
- UEMUSHORT *x;
+bool
+real_isnan (r)
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT bits;
- int i;
-
- x += M; /* point to significand area */
-
- bits = 0;
- for (i = M; i < NI; i++)
- {
- if (*x & 1)
- bits |= 1;
- *x >>= 1;
- if (bits & 2)
- *x |= 0x8000;
- bits <<= 1;
- ++x;
- }
+ return (r->class == rvc_nan);
}
-/* Shift significand of exploded e-type X up by 1 bit. */
+/* Determine whether a floating-point value X is negative. */
-static void
-eshup1 (x)
- UEMUSHORT *x;
+bool
+real_isneg (r)
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT bits;
- int i;
-
- x += NI - 1;
- bits = 0;
-
- for (i = M; i < NI; i++)
- {
- if (*x & 0x8000)
- bits |= 1;
- *x <<= 1;
- if (bits & 2)
- *x |= 1;
- bits <<= 1;
- --x;
- }
+ return r->sign;
}
+/* Determine whether a floating-point value X is minus zero. */
-/* Shift significand of exploded e-type X down by 8 bits. */
-
-static void
-eshdn8 (x)
- UEMUSHORT *x;
+bool
+real_isnegzero (r)
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT newbyt, oldbyt;
- int i;
-
- x += M;
- oldbyt = 0;
- for (i = M; i < NI; i++)
- {
- newbyt = *x << 8;
- *x >>= 8;
- *x |= oldbyt;
- oldbyt = newbyt;
- ++x;
- }
+ return r->sign && r->class == rvc_zero;
}
-/* Shift significand of exploded e-type X up by 8 bits. */
+/* Compare two floating-point objects for bitwise identity. */
-static void
-eshup8 (x)
- UEMUSHORT *x;
+extern bool
+real_identical (a, b)
+ const REAL_VALUE_TYPE *a, *b;
{
int i;
- UEMUSHORT newbyt, oldbyt;
- x += NI - 1;
- oldbyt = 0;
+ if (a->class != b->class)
+ return false;
+ if (a->sign != b->sign)
+ return false;
- for (i = M; i < NI; i++)
+ switch (a->class)
{
- newbyt = *x >> 8;
- *x <<= 8;
- *x |= oldbyt;
- oldbyt = newbyt;
- --x;
- }
-}
-
-/* Shift significand of exploded e-type X up by 16 bits. */
-
-static void
-eshup6 (x)
- UEMUSHORT *x;
-{
- int i;
- UEMUSHORT *p;
+ case rvc_zero:
+ case rvc_inf:
+ break;
- p = x + M;
- x += M + 1;
+ case rvc_normal:
+ if (a->exp != b->exp)
+ return false;
+ /* FALLTHRU */
+ case rvc_nan:
+ for (i = 0; i < SIGSZ; ++i)
+ if (a->sig[i] != b->sig[i])
+ return false;
+ break;
- for (i = M; i < NI - 1; i++)
- *p++ = *x++;
+ default:
+ abort ();
+ }
- *p = 0;
+ return true;
}
-/* Shift significand of exploded e-type X down by 16 bits. */
+/* Try to change R into its exact multiplicative inverse in machine
+ mode MODE. Return true if successful. */
-static void
-eshdn6 (x)
- UEMUSHORT *x;
+bool
+exact_real_inverse (mode, r)
+ enum machine_mode mode;
+ REAL_VALUE_TYPE *r;
{
+ const REAL_VALUE_TYPE *one = real_digit (1);
+ REAL_VALUE_TYPE u;
int i;
- UEMUSHORT *p;
-
- x += NI - 1;
- p = x + 1;
-
- for (i = M; i < NI - 1; i++)
- *(--p) = *(--x);
-
- *(--p) = 0;
+
+ if (r->class != 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.class != 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;
}
+
+/* Render R as an integer. */
-/* Add significands of exploded e-type X and Y. X + Y replaces Y. */
-
-static void
-eaddm (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
-{
- unsigned EMULONG a;
- int i;
- unsigned int carry;
-
- x += NI - 1;
- y += NI - 1;
- carry = 0;
- for (i = M; i < NI; i++)
- {
- a = (unsigned EMULONG) (*x) + (unsigned EMULONG) (*y) + carry;
- if (a & 0x10000)
- carry = 1;
+HOST_WIDE_INT
+real_to_integer (r)
+ const REAL_VALUE_TYPE *r;
+{
+ unsigned HOST_WIDE_INT i;
+
+ switch (r->class)
+ {
+ 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->exp <= 0)
+ goto underflow;
+ if (r->exp > HOST_BITS_PER_WIDE_INT)
+ goto overflow;
+
+ if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
+ i = r->sig[SIGSZ-1];
+ else if (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];
+ }
else
- carry = 0;
- *y = (UEMUSHORT) a;
- --x;
- --y;
- }
-}
+ abort ();
-/* Subtract significands of exploded e-type X and Y. Y - X replaces Y. */
+ i >>= HOST_BITS_PER_WIDE_INT - r->exp;
-static void
-esubm (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
-{
- unsigned EMULONG a;
- int i;
- unsigned int carry;
+ if (r->sign)
+ i = -i;
+ return i;
- x += NI - 1;
- y += NI - 1;
- carry = 0;
- for (i = M; i < NI; i++)
- {
- a = (unsigned EMULONG) (*y) - (unsigned EMULONG) (*x) - carry;
- if (a & 0x10000)
- carry = 1;
- else
- carry = 0;
- *y = (UEMUSHORT) a;
- --x;
- --y;
+ default:
+ abort ();
}
}
+/* Likewise, but to an integer pair, HI+LOW. */
-static UEMUSHORT equot[NI];
-
-
-#if 0
-/* Radix 2 shift-and-add versions of multiply and divide */
-
-
-/* Divide significands */
-
-int
-edivm (den, num)
- UEMUSHORT den[], num[];
+void
+real_to_integer2 (plow, phigh, r)
+ HOST_WIDE_INT *plow, *phigh;
+ const REAL_VALUE_TYPE *r;
{
- int i;
- UEMUSHORT *p, *q;
- UEMUSHORT j;
-
- p = &equot[0];
- *p++ = num[0];
- *p++ = num[1];
+ REAL_VALUE_TYPE t;
+ HOST_WIDE_INT low, high;
+ int exp;
- for (i = M; i < NI; i++)
+ switch (r->class)
{
- *p++ = 0;
- }
-
- /* Use faster compare and subtraction if denominator has only 15 bits of
- significance. */
+ case rvc_zero:
+ underflow:
+ low = high = 0;
+ break;
- p = &den[M + 2];
- if (*p++ == 0)
- {
- for (i = M + 3; i < NI; i++)
+ 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
{
- if (*p++ != 0)
- goto fulldiv;
+ high--;
+ low = -1;
}
- if ((den[M + 1] & 1) != 0)
- goto fulldiv;
- eshdn1 (num);
- eshdn1 (den);
+ break;
- p = &den[M + 1];
- q = &num[M + 1];
+ case rvc_normal:
+ exp = r->exp;
+ if (exp <= 0)
+ goto underflow;
+ if (exp > 2*HOST_BITS_PER_WIDE_INT)
+ goto overflow;
- for (i = 0; i < NBITS + 2; i++)
+ rshift_significand (&t, r, 2*HOST_BITS_PER_WIDE_INT - exp);
+ if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
{
- if (*p <= *q)
- {
- *q -= *p;
- j = 1;
- }
- else
- {
- j = 0;
- }
- eshup1 (equot);
- equot[NI - 2] |= j;
- eshup1 (num);
+ high = t.sig[SIGSZ-1];
+ low = t.sig[SIGSZ-2];
}
- goto divdon;
- }
-
- /* The number of quotient bits to calculate is NBITS + 1 scaling guard
- bit + 1 roundoff bit. */
-
- fulldiv:
-
- p = &equot[NI - 2];
- for (i = 0; i < NBITS + 2; i++)
- {
- if (ecmpm (den, num) <= 0)
+ else if (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG)
{
- esubm (den, num);
- j = 1; /* quotient bit = 1 */
+ 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];
}
else
- j = 0;
- eshup1 (equot);
- *p |= j;
- eshup1 (num);
- }
-
- divdon:
+ abort ();
- eshdn1 (equot);
- eshdn1 (equot);
+ if (r->sign)
+ {
+ if (low == 0)
+ high = -high;
+ else
+ low = -low, high = ~high;
+ }
+ break;
- /* test for nonzero remainder after roundoff bit */
- p = &num[M];
- j = 0;
- for (i = M; i < NI; i++)
- {
- j |= *p++;
+ default:
+ abort ();
}
- if (j)
- j = 1;
-
- for (i = 0; i < NI; i++)
- num[i] = equot[i];
- return ((int) j);
+ *plow = low;
+ *phigh = high;
}
+/* 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. */
-/* Multiply significands */
-
-int
-emulm (a, b)
- UEMUSHORT a[], b[];
+static unsigned long
+rtd_divmod (num, den)
+ REAL_VALUE_TYPE *num, *den;
{
- UEMUSHORT *p, *q;
- int i, j, k;
-
- equot[0] = b[0];
- equot[1] = b[1];
- for (i = M; i < NI; i++)
- equot[i] = 0;
+ unsigned long q, msb;
+ int expn = num->exp, expd = den->exp;
- 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;
- }
+ if (expn < expd)
+ return 0;
- q = &equot[NI - 1];
- j = 0;
- for (i = 0; i < k; i++)
+ q = msb = 0;
+ goto start;
+ do
{
- if (*p & 1)
- eaddm (b, equot);
- /* remember if there were any nonzero bits shifted out */
- if (*q & 1)
- j |= 1;
- eshdn1 (a);
- eshdn1 (equot);
+ 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;
+ }
}
+ while (--expn >= expd);
- for (i = 0; i < NI; i++)
- b[i] = equot[i];
+ num->exp = expd;
+ normalize (num);
- /* return flag for lost nonzero bits */
- return (j);
+ return q;
}
-#else
+/* 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. */
-/* Radix 65536 versions of multiply and divide. */
+#define M_LOG10_2 0.30102999566398119521
-/* Multiply significand of e-type number B
- by 16-bit quantity A, return e-type result to C. */
+void
+real_to_decimal (str, r_orig, buf_size, digits, crop_trailing_zeros)
+ char *str;
+ const REAL_VALUE_TYPE *r_orig;
+ size_t buf_size, digits;
+ int crop_trailing_zeros;
+{
+ 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;
+
+ r = *r_orig;
+ switch (r.class)
+ {
+ 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? */
+ strcpy (str, (r.sign ? "-NaN" : "+NaN"));
+ return;
+ default:
+ abort ();
+ }
-static void
-m16m (a, b, c)
- unsigned int a;
- const UEMUSHORT b[];
- UEMUSHORT c[];
-{
- UEMUSHORT *pp;
- unsigned EMULONG carry;
- const UEMUSHORT *ps;
- UEMUSHORT p[NI];
- unsigned EMULONG aa, m;
- int i;
+ /* 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;
- aa = a;
- pp = &p[NI-2];
- *pp++ = 0;
- *pp = 0;
- ps = &b[NI-1];
+ /* 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 = r.exp * M_LOG10_2;
+ for (max_digits = 1; dec_exp ; max_digits++)
+ dec_exp /= 10;
- for (i=M+1; i<NI; i++)
- {
- if (*ps == 0)
- {
- --ps;
- --pp;
- *(pp-1) = 0;
- }
- else
- {
- m = (unsigned EMULONG) aa * *ps--;
- carry = (m & 0xffff) + *pp;
- *pp-- = (UEMUSHORT) carry;
- carry = (carry >> 16) + (m >> 16) + *pp;
- *pp = (UEMUSHORT) carry;
- *(pp-1) = carry >> 16;
- }
- }
- for (i=M; i<NI; i++)
- c[i] = p[i];
-}
+ /* Bound the number of digits printed by the size of the output buffer. */
+ max_digits = buf_size - 1 - 1 - 2 - max_digits - 1;
+ if (max_digits > buf_size)
+ abort ();
+ if (digits > max_digits)
+ digits = max_digits;
-/* Divide significands of exploded e-types NUM / DEN. Neither the
- numerator NUM nor the denominator DEN is permitted to have its high guard
- word nonzero. */
+ one = real_digit (1);
+ ten = ten_to_ptwo (0);
-static int
-edivm (den, num)
- const UEMUSHORT den[];
- UEMUSHORT num[];
-{
- int i;
- UEMUSHORT *p;
- unsigned EMULONG tnum;
- UEMUSHORT j, tdenm, tquot;
- UEMUSHORT tprod[NI+1];
+ sign = r.sign;
+ r.sign = 0;
- p = &equot[0];
- *p++ = num[0];
- *p++ = num[1];
+ dec_exp = 0;
+ pten = *one;
- for (i=M; i<NI; i++)
- {
- *p++ = 0;
- }
- eshdn1 (num);
- tdenm = den[M+1];
- for (i=M; i<NI; i++)
+ cmp_one = do_compare (&r, one, 0);
+ if (cmp_one > 0)
{
- /* Find trial quotient digit (the radix is 65536). */
- tnum = (((unsigned EMULONG) num[M]) << 16) + num[M+1];
+ int m;
- /* Do not execute the divide instruction if it will overflow. */
- if ((tdenm * (unsigned long) 0xffff) < tnum)
- tquot = 0xffff;
- else
- tquot = tnum / tdenm;
- /* Multiply denominator by trial quotient digit. */
- m16m ((unsigned int) tquot, den, tprod);
- /* The quotient digit may have been overestimated. */
- if (ecmpm (tprod, num) > 0)
- {
- tquot -= 1;
- esubm (den, tprod);
- if (ecmpm (tprod, num) > 0)
- {
- tquot -= 1;
- esubm (den, tprod);
- }
- }
- esubm (tprod, num);
- equot[i] = tquot;
- eshup6 (num);
- }
- /* test for nonzero remainder after roundoff bit */
- p = &num[M];
- j = 0;
- for (i=M; i<NI; i++)
- {
- j |= *p++;
- }
- if (j)
- j = 1;
+ /* Number is greater than one. Convert significand to an integer
+ and strip trailing decimal zeros. */
- for (i=0; i<NI; i++)
- num[i] = equot[i];
+ u = r;
+ u.exp = SIGNIFICAND_BITS - 1;
- return ((int) j);
-}
+ /* Largest M, such that 10**2**M fits within SIGNIFICAND_BITS. */
+ m = floor_log2 (max_digits);
-/* Multiply significands of exploded e-type A and B, result in B. */
+ /* 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;
-static int
-emulm (a, b)
- const UEMUSHORT a[];
- UEMUSHORT b[];
-{
- const UEMUSHORT *p;
- UEMUSHORT *q;
- UEMUSHORT pprod[NI];
- UEMUSHORT j;
- int i;
+ 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);
- equot[0] = b[0];
- equot[1] = b[1];
- for (i=M; i<NI; i++)
- equot[i] = 0;
+ /* Revert the scaling to integer that we performed earlier. */
+ u.exp += r.exp - (SIGNIFICAND_BITS - 1);
+ r = u;
- j = 0;
- p = &a[NI-1];
- q = &equot[NI-1];
- for (i=M+1; i<NI; i++)
- {
- if (*p == 0)
+ /* 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 (r.exp > 0)
{
- --p;
+ m = floor_log2 ((int)(r.exp * 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
- {
- m16m ((unsigned int) *p--, b, pprod);
- eaddm (pprod, equot);
- }
- j |= *q;
- eshdn6 (equot);
+ /* 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)
+ {
+ int m;
- for (i=0; i<NI; i++)
- b[i] = equot[i];
+ /* Number is less than one. Pad significand with leading
+ decimal zeros. */
- /* return flag for lost nonzero bits */
- return ((int) j);
-}
-#endif
+ v = r;
+ while (1)
+ {
+ /* Stop if we'd shift bits off the bottom. */
+ if (v.sig[0] & 7)
+ break;
+ do_multiply (&u, &v, ten);
-/* Normalize and round off.
+ /* Stop if we're now >= 1. */
+ if (u.exp > 0)
+ break;
- 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.
+ v = u;
+ dec_exp -= 1;
+ }
+ r = v;
- 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.
+ /* 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)(-r.exp * M_LOG10_2)) + 1;
+ do
+ {
+ const REAL_VALUE_TYPE *ptentwo = ten_to_ptwo (m);
+ const REAL_VALUE_TYPE *ptenmtwo = ten_to_mptwo (m);
- 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.
+ if (do_compare (&v, ptenmtwo, 0) <= 0)
+ {
+ do_multiply (&v, &v, ptentwo);
+ do_multiply (&pten, &pten, ptentwo);
+ dec_exp -= 1 << m;
+ }
+ }
+ while (--m >= 0);
- Input RCNTRL is the rounding control. If it is nonzero, the
- returned value will be rounded to RNDPRC bits.
+ /* Invert the positive power of 10 that we've collected so far. */
+ do_divide (&pten, one, &pten);
+ }
- 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. */
+ p = str;
+ if (sign)
+ *p++ = '-';
+ first = p++;
-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];
+ /* At this point, PTEN should contain the nearest power of 10 smaller
+ than R, such that this division produces the first digit.
-static void
-emdnorm (s, lost, subflg, exp, rcntrl)
- UEMUSHORT s[];
- int lost;
- int subflg;
- EMULONG exp;
- int rcntrl;
-{
- int i, j;
- UEMUSHORT r;
+ 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. */
- /* Normalize */
- j = enormlz (s);
+ digit = rtd_divmod (&r, &pten);
- /* a blank significand could mean either zero or infinity. */
-#ifndef INFINITY
- if (j > NBITS)
+ /* Be prepared for error in that division via underflow ... */
+ if (digit == 0 && cmp_significand_0 (&r))
{
- ecleazs (s);
- return;
+ /* Multiply by 10 and try again. */
+ do_multiply (&r, &r, ten);
+ digit = rtd_divmod (&r, &pten);
+ dec_exp -= 1;
+ if (digit == 0)
+ abort ();
}
-#endif
- exp -= j;
-#ifndef INFINITY
- if (exp >= 32767L)
- goto overf;
-#else
- if ((j > NBITS) && (exp < 32767))
+
+ /* ... or overflow. */
+ if (digit == 10)
{
- ecleazs (s);
- return;
+ *p++ = '1';
+ if (--digits > 0)
+ *p++ = '0';
+ dec_exp += 1;
}
-#endif
- if (exp < 0L)
+ else if (digit > 10)
+ abort ();
+ else
+ *p++ = digit + '0';
+
+ /* Generate subsequent digits. */
+ while (--digits > 0)
{
- if (exp > (EMULONG) (-NBITS - 1))
- {
- j = (int) exp;
- i = eshift (s, j);
- if (i)
- lost = 1;
- }
- else
- {
- ecleazs (s);
- return;
- }
+ do_multiply (&r, &r, ten);
+ digit = rtd_divmod (&r, &pten);
+ *p++ = digit + '0';
}
- /* 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;
+ last = p;
- case 53:
- rw = 6;
- rmsk = 0x7ff;
- rmbit = 0x0400;
- rebit = 0x800;
- re = rw;
- break;
+ /* Generate one more digit with which to do rounding. */
+ do_multiply (&r, &r, ten);
+ digit = rtd_divmod (&r, &pten);
- /* 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)
+ /* Round the result. */
+ if (digit == 5)
{
- i = rw + 1;
- while (i < NI)
- {
- if (s[i])
- r |= 1;
- s[i] = 0;
- ++i;
- }
+ /* 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++;
}
- s[rw] &= ~rmsk;
- if ((r & rmbit) != 0)
+ if (digit > 5)
{
-#ifndef C4X
- if (r == rmbit)
+ while (p > first)
{
- if (lost == 0)
- { /* round to even */
- if ((s[re] & rebit) == 0)
- goto mddone;
- }
+ digit = *--p;
+ if (digit == '9')
+ *p = '0';
else
{
- if (subflg != 0)
- goto mddone;
+ *p = digit + 1;
+ break;
}
}
-#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))
+
+ /* 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)
{
- s[rw] &= ~rmsk;
- if (rndprc == 24)
- {
- s[5] = 0;
- s[6] = 0;
- }
+ first[1] = '1';
+ dec_exp++;
}
-#endif
- return;
}
- if (exp < 0)
- s[1] = 0;
- else
- s[1] = (UEMUSHORT) exp;
-}
+
+ /* Insert the decimal point. */
+ first[0] = first[1];
+ first[1] = '.';
-/* Subtract. C = B - A, all e type numbers. */
+ /* If requested, drop trailing zeros. Never crop past "1.0". */
+ if (crop_trailing_zeros)
+ while (last > first + 3 && last[-1] == '0')
+ last--;
-static int subflg = 0;
+ /* Append the exponent. */
+ sprintf (last, "e%+d", dec_exp);
+}
-static void
-esub (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
+/* 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. */
+
+void
+real_to_hexadecimal (str, r, buf_size, digits, crop_trailing_zeros)
+ char *str;
+ const REAL_VALUE_TYPE *r;
+ size_t buf_size, digits;
+ int crop_trailing_zeros;
{
+ int i, j, exp = r->exp;
+ char *p, *first;
+ char exp_buf[16];
+ size_t max_digits;
-#ifdef NANS
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
+ switch (r->class)
{
- emov (b, c);
+ case rvc_zero:
+ exp = 0;
+ break;
+ case rvc_normal:
+ break;
+ case rvc_inf:
+ strcpy (str, (r->sign ? "-Inf" : "+Inf"));
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);
+ case rvc_nan:
+ /* ??? Print the significand as well, if not canonical? */
+ strcpy (str, (r->sign ? "-NaN" : "+NaN"));
return;
+ default:
+ abort ();
}
-#endif
- subflg = 1;
- eadd1 (a, b, c);
-}
-/* Add. C = A + B, all e type. */
+ if (digits == 0)
+ digits = SIGNIFICAND_BITS / 4;
-static void
-eadd (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
-{
+ /* Bound the number of digits printed by the size of the output buffer. */
-#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);
+ sprintf (exp_buf, "p%+d", exp);
+ max_digits = buf_size - strlen (exp_buf) - r->sign - 4 - 1;
+ if (max_digits > buf_size)
+ abort ();
+ if (digits > max_digits)
+ digits = max_digits;
+
+ 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;
+ }
+
+ out:
+ if (crop_trailing_zeros)
+ while (p > first + 1 && p[-1] == '0')
+ p--;
+
+ sprintf (p, "p%+d", exp);
}
-/* Arithmetic common to both addition and subtraction. */
+/* Initialize R from a decimal or hexadecimal string. The string is
+ assumed to have been syntax checked already. */
-static void
-eadd1 (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
+void
+real_from_string (r, str)
+ REAL_VALUE_TYPE *r;
+ const char *str;
{
- UEMUSHORT ai[NI], bi[NI], ci[NI];
- int i, lost, j, k;
- EMULONG lt, lta, ltb;
+ int exp = 0;
+ bool sign = false;
-#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)
+ get_zero (r, 0);
+
+ if (*str == '-')
{
- if (lt < (EMULONG) (-NBITS - 1))
- goto done; /* answer same as larger addend */
- k = (int) lt;
- lost = eshift (ai, k); /* shift the smaller number down */
+ sign = true;
+ str++;
}
- else
+ else if (*str == '+')
+ str++;
+
+ if (str[0] == '0' && str[1] == 'x')
{
- /* 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])
+ /* 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)
{
- eclear (c);
- return;
+ r->sig[pos / HOST_BITS_PER_LONG]
+ |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
+ pos -= 4;
}
- /* if same sign, result is double */
- /* double denormalized tiny number */
- if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0))
+ exp += 4;
+ str++;
+ }
+ if (*str == '.')
+ {
+ str++;
+ if (pos == SIGNIFICAND_BITS - 4)
{
- eshup1 (bi);
- goto done;
+ while (*str == '0')
+ str++, exp -= 4;
}
- /* add 1 to exponent unless both are zero! */
- for (j = 1; j < NI - 1; j++)
+ while (1)
{
- if (bi[j] != 0)
+ d = hex_value (*str);
+ if (d == _hex_bad)
+ break;
+ if (pos >= 0)
{
- ltb += 1;
- if (ltb >= 0x7fff)
- {
- eclear (c);
- if (ai[0] != 0)
- eneg (c);
- einfin (c);
- return;
- }
- break;
+ r->sig[pos / HOST_BITS_PER_LONG]
+ |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
+ pos -= 4;
}
+ str++;
}
- 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);
+ if (*str == 'p' || *str == 'P')
+ {
+ bool exp_neg = false;
- done:
- emovo (bi, c);
-}
+ str++;
+ if (*str == '-')
+ {
+ exp_neg = true;
+ str++;
+ }
+ else if (*str == '+')
+ str++;
-/* Divide: C = B/A, all e type. */
+ 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;
-static void
-ediv (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
-{
- UEMUSHORT ai[NI], bi[NI];
- int i, sign;
- EMULONG lt, lta, ltb;
+ exp += d;
+ }
-/* 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);
+ r->class = rvc_normal;
+ r->exp = exp;
-#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;
+ normalize (r);
}
-#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))
+ else
{
- 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++)
+ /* Decimal floating point. */
+ const REAL_VALUE_TYPE *ten = ten_to_ptwo (0);
+ int d;
+
+ while (*str == '0')
+ str++;
+ while (ISDIGIT (*str))
{
- if (bi[i] != 0)
- {
- ltb -= enormlz (bi);
- goto dnzro1;
- }
+ d = *str++ - '0';
+ do_multiply (r, r, ten);
+ if (d)
+ do_add (r, r, real_digit (d), 0);
}
- eclear (c);
- goto divsign;
- }
- dnzro1:
-
- if (ai[E] == 0)
- { /* possible divide by zero */
- for (i = 1; i < NI - 1; i++)
+ if (*str == '.')
{
- if (ai[i] != 0)
+ str++;
+ if (r->class == rvc_zero)
{
- lta -= enormlz (ai);
- goto dnzro2;
+ 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--;
}
}
-/* 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 (*str == 'e' || *str == 'E')
{
- if (ai[i] != 0)
+ bool exp_neg = false;
+
+ str++;
+ if (*str == '-')
{
- lta -= enormlz (ai);
- goto mnzer1;
+ exp_neg = true;
+ str++;
}
- }
- eclear (c);
- goto mulsign;
- }
- mnzer1:
+ else if (*str == '+')
+ str++;
- if (bi[E] == 0)
- {
- for (i = 1; i < NI - 1; i++)
- {
- if (bi[i] != 0)
+ d = 0;
+ while (ISDIGIT (*str))
{
- ltb -= enormlz (bi);
- goto mnzer2;
+ 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;
}
- eclear (c);
- goto mulsign;
+
+ if (exp)
+ times_pten (r, exp);
}
- mnzer2:
- /* Multiply significands */
- j = emulm (ai, bi);
- /* calculate exponent */
- lt = lta + ltb - (EXONE - 1);
- emdnorm (bi, j, 0, lt, 64);
- emovo (bi, c);
+ r->sign = sign;
+ return;
- mulsign:
+ underflow:
+ get_zero (r, sign);
+ return;
- if (sign
-#ifndef IEEE
- && (ecmp (c, ezero) != 0)
-#endif
- )
- *(c+(NE-1)) |= 0x8000;
- else
- *(c+(NE-1)) &= ~0x8000;
+ overflow:
+ get_inf (r, sign);
+ return;
}
-/* Convert double precision PE to e-type Y. */
+/* Legacy. Similar, but return the result directly. */
-static void
-e53toe (pe, y)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
+REAL_VALUE_TYPE
+real_from_string2 (s, mode)
+ const char *s;
+ enum machine_mode mode;
{
-#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. */
+ REAL_VALUE_TYPE r;
- 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 */
+ real_from_string (&r, s);
+ if (mode != VOIDmode)
+ real_convert (&r, mode, &r);
+
+ return r;
}
-/* Convert double extended precision float PE to e type Y. */
+/* Initialize R from the integer pair HIGH+LOW. */
-static void
-e64toe (pe, y)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
+void
+real_from_integer (r, mode, low, high, unsigned_p)
+ REAL_VALUE_TYPE *r;
+ enum machine_mode mode;
+ unsigned HOST_WIDE_INT low;
+ HOST_WIDE_INT high;
+ int unsigned_p;
{
- 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)
+ if (low == 0 && high == 0)
+ get_zero (r, 0);
+ else
{
- for (i = 0; i < 5; i++)
- *p++ = *e++;
+ r->class = rvc_normal;
+ r->sign = high < 0 && !unsigned_p;
+ r->exp = 2 * HOST_BITS_PER_WIDE_INT;
- /* 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)
+ if (r->sign)
{
- UEMUSHORT temp[NI];
-
- emovi (yy, temp);
- eshup1 (temp);
- emovo (temp,y);
- return;
+ high = ~high;
+ if (low == 0)
+ high += 1;
+ else
+ low = -low;
}
- }
- 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)
+
+ if (HOST_BITS_PER_LONG == HOST_BITS_PER_WIDE_INT)
{
- 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;
- }
- }
+ r->sig[SIGSZ-1] = high;
+ r->sig[SIGSZ-2] = low;
+ memset (r->sig, 0, sizeof(long)*(SIGSZ-2));
}
- else
+ else if (HOST_BITS_PER_LONG*2 == HOST_BITS_PER_WIDE_INT)
{
-#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 */
+ 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;
+ if (SIGSZ > 4)
+ memset (r->sig, 0, sizeof(long)*(SIGSZ-4));
}
-#endif /* NANS */
- eclear (y);
- einfin (y);
- if (*p & 0x8000)
- eneg (y);
- return;
+ else
+ abort ();
+
+ normalize (r);
}
-#endif /* INFINITY */
- p = yy;
- q = y;
- for (i = 0; i < NE; i++)
- *q++ = *p++;
+
+ if (mode != VOIDmode)
+ real_convert (r, mode, r);
}
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* Convert 128-bit long double precision float PE to e type Y. */
+/* Returns 10**2**N. */
-static void
-e113toe (pe, y)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
+static const REAL_VALUE_TYPE *
+ten_to_ptwo (n)
+ int n;
{
- 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)
+ static REAL_VALUE_TYPE tens[EXP_BITS];
+
+ if (n < 0 || n >= EXP_BITS)
+ abort ();
+
+ if (tens[n].class == rvc_zero)
{
-#ifdef NANS
- if (! REAL_WORDS_BIG_ENDIAN)
+ if (n < (HOST_BITS_PER_WIDE_INT == 64 ? 5 : 4))
{
- for (i = 0; i < 7; i++)
- {
- if (pe[i] != 0)
- {
- enan (y, yy[0] != 0);
- return;
- }
- }
+ HOST_WIDE_INT t = 10;
+ int i;
+
+ for (i = 0; i < n; ++i)
+ t *= t;
+
+ real_from_integer (&tens[n], VOIDmode, t, 0, 1);
}
else
{
- for (i = 1; i < 8; i++)
- {
- if (pe[i] != 0)
- {
- enan (y, yy[0] != 0);
- return;
- }
- }
+ const REAL_VALUE_TYPE *t = ten_to_ptwo (n - 1);
+ do_multiply (&tens[n], t, t);
}
-#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);
+
+ return &tens[n];
}
-#endif
-/* Convert single precision float PE to e type Y. */
+/* Returns 10**(-2**N). */
-static void
-e24toe (pe, y)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
+static const REAL_VALUE_TYPE *
+ten_to_mptwo (n)
+ int n;
{
-#ifdef IBM
-
- ibmtoe (pe, y, SFmode);
-
-#else
+ static REAL_VALUE_TYPE tens[EXP_BITS];
-#ifdef C4X
-
- c4xtoe (pe, y, QFmode);
-
-#else
+ if (n < 0 || n >= EXP_BITS)
+ abort ();
- UEMUSHORT r;
- const UEMUSHORT *e;
- UEMUSHORT *p;
- UEMUSHORT yy[NI];
- int denorm, k;
+ if (tens[n].class == rvc_zero)
+ do_divide (&tens[n], real_digit (1), ten_to_ptwo (n));
- 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 */
+ return &tens[n];
}
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* Convert e-type X to IEEE 128-bit long double format E. */
+/* Returns N. */
-static void
-etoe113 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+static const REAL_VALUE_TYPE *
+real_digit (n)
+ int n;
{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
+ static REAL_VALUE_TYPE num[10];
-#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);
+ if (n < 0 || n > 9)
+ abort ();
+
+ if (n > 0 && num[n].class == rvc_zero)
+ real_from_integer (&num[n], VOIDmode, n, 0, 1);
+
+ return &num[n];
}
-/* Convert exploded e-type X, that has already been rounded to
- 113-bit precision, to IEEE 128-bit long double format Y. */
+/* Multiply R by 10**EXP. */
static void
-toe113 (a, b)
- UEMUSHORT *a, *b;
+times_pten (r, exp)
+ REAL_VALUE_TYPE *r;
+ int exp;
{
- UEMUSHORT *p, *q;
- UEMUSHORT i;
+ REAL_VALUE_TYPE pten, *rr;
+ bool negative = (exp < 0);
+ int i;
-#ifdef NANS
- if (eiisnan (a))
+ if (negative)
{
- make_nan (b, eiisneg (a), TFmode);
- return;
+ exp = -exp;
+ pten = *real_digit (1);
+ rr = &pten;
}
-#endif
- p = a;
- if (REAL_WORDS_BIG_ENDIAN)
- q = b;
else
- q = b + 7; /* point to output exponent */
+ rr = r;
- /* 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++;
- }
+ 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);
}
-#endif
-/* Convert e-type X to IEEE double extended format E. */
+/* Fills R with +Inf. */
-static void
-etoe64 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+void
+real_inf (r)
+ REAL_VALUE_TYPE *r;
{
- 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);
+ get_inf (r, 0);
}
-/* Convert exploded e-type X, that has already been rounded to
- 64-bit precision, to IEEE double extended format 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
-toe64 (a, b)
- UEMUSHORT *a, *b;
+bool
+real_nan (r, str, quiet, mode)
+ REAL_VALUE_TYPE *r;
+ const char *str;
+ int quiet;
+ enum machine_mode mode;
{
- UEMUSHORT *p, *q;
- UEMUSHORT i;
+ const struct real_format *fmt;
-#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
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
- /* 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)
+ if (*str == 0)
{
-#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;
+ if (quiet)
+ get_canonical_qnan (r, 0);
else
- *q++ = *p++;
- *q++ = 0;
-#endif
+ get_canonical_snan (r, 0);
}
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))
+ int base = 10, d;
+ bool neg = false;
+
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_nan;
+
+ /* Parse akin to strtol into the significand of R. */
+
+ while (ISSPACE (*str))
+ str++;
+ if (*str == '-')
+ str++, neg = true;
+ else if (*str == '+')
+ str++;
+ if (*str == '0')
{
- /* Intel long double infinity significand. */
- *q-- = 0x8000;
- *q-- = 0;
- *q-- = 0;
- *q = 0;
- return;
+ if (*++str == 'x')
+ str++, base = 16;
+ else
+ base = 8;
}
-#endif
- for (i = 0; i < 4; i++)
- *q-- = *p++;
- }
-#endif
-}
-/* e type to double precision. */
+ while ((d = hex_value (*str)) < base)
+ {
+ REAL_VALUE_TYPE u;
-#ifdef DEC
-/* Convert e-type X to DEC-format double E. */
+ 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:
+ abort ();
+ }
-static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etodec (x, e); /* see etodec.c */
-}
+ get_zero (&u, 0);
+ u.sig[0] = d;
+ add_significands (r, r, &u);
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit double precision, to DEC double Y. */
+ str++;
+ }
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- todec (x, y);
-}
+ /* Must have consumed the entire string for success. */
+ if (*str != 0)
+ return false;
-#else
-#ifdef IBM
-/* Convert e-type X to IBM 370-format double E. */
+ /* 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->p);
-static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoibm (x, e, DFmode);
-}
+ /* Our MSB is always unset for NaNs. */
+ r->sig[SIGSZ-1] &= ~SIG_MSB;
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit precision, to IBM 370 double Y. */
+ /* Force quiet or signalling NaN. */
+ if (quiet)
+ r->sig[SIGSZ-1] |= SIG_MSB >> 1;
+ else
+ r->sig[SIGSZ-1] &= ~(SIG_MSB >> 1);
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- toibm (x, y, DFmode);
-}
+ /* Force at least one bit of the significand set. */
+ for (d = 0; d < SIGSZ; ++d)
+ if (r->sig[d])
+ break;
+ if (d == SIGSZ)
+ r->sig[SIGSZ-1] |= SIG_MSB >> 2;
-#else /* it's neither DEC nor IBM */
-#ifdef C4X
-/* Convert e-type X to C4X-format long double E. */
+ /* Our intermediate format forces QNaNs to have MSB-1 set.
+ If the target format has QNaNs with the top bit unset,
+ mirror the output routines and invert the top two bits. */
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1) | (SIG_MSB >> 2);
+ }
-static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoc4x (x, e, HFmode);
+ return true;
}
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit precision, to IBM 370 double Y. */
+/* Fills R with 2**N. */
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
+void
+real_2expN (r, n)
+ REAL_VALUE_TYPE *r;
+ int n;
{
- toc4x (x, y, HFmode);
-}
+ memset (r, 0, sizeof (*r));
-#else /* it's neither DEC nor IBM nor C4X */
-
-/* Convert e-type X to IEEE double E. */
+ n++;
+ if (n > MAX_EXP)
+ r->class = rvc_inf;
+ else if (n < -MAX_EXP)
+ ;
+ else
+ {
+ r->class = rvc_normal;
+ r->exp = n;
+ r->sig[SIGSZ-1] = SIG_MSB;
+ }
+}
+
static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+round_for_format (fmt, r)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
+ int p2, np2, i, w;
+ unsigned long sticky;
+ bool guard, lsb;
+ int emin2m1, emax2;
-#ifdef NANS
- if (eisnan (x))
+ p2 = fmt->p * fmt->log2_b;
+ emin2m1 = (fmt->emin - 1) * fmt->log2_b;
+ emax2 = fmt->emax * fmt->log2_b;
+
+ np2 = SIGNIFICAND_BITS - p2;
+ switch (r->class)
{
- make_nan (e, eisneg (x), DFmode);
+ underflow:
+ get_zero (r, r->sign);
+ case rvc_zero:
+ if (!fmt->has_signed_zero)
+ r->sign = 0;
return;
- }
-#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);
-}
-/* Convert exploded e-type X, that has already been rounded to
- 53-bit precision, to IEEE double Y. */
+ overflow:
+ get_inf (r, r->sign);
+ case rvc_inf:
+ return;
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- UEMUSHORT i;
- UEMUSHORT *p;
+ case rvc_nan:
+ clear_significand_below (r, np2);
-#ifdef NANS
- if (eiisnan (x))
- {
- make_nan (y, eiisneg (x), DFmode);
+ /* If we've cleared the entire significand, we need one bit
+ set for this to continue to be a NaN. */
+ for (i = 0; i < SIGSZ; ++i)
+ if (r->sig[i])
+ break;
+ if (i == SIGSZ)
+ r->sig[SIGSZ-1] = SIG_MSB >> 2;
return;
+
+ case rvc_normal:
+ break;
+
+ default:
+ abort ();
}
-#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 */
- i = *p++;
- if (i >= (unsigned int) 2047)
+ /* If we're not base2, normalize the exponent to a multiple of
+ the true base. */
+ if (fmt->log2_b != 1)
{
- /* Saturate at largest number less than infinity. */
-#ifdef INFINITY
- *y |= 0x7ff0;
- if (! REAL_WORDS_BIG_ENDIAN)
- {
- *(--y) = 0;
- *(--y) = 0;
- *(--y) = 0;
- }
- else
+ int shift = r->exp & (fmt->log2_b - 1);
+ if (shift)
{
- ++y;
- *y++ = 0;
- *y++ = 0;
- *y++ = 0;
+ shift = fmt->log2_b - shift;
+ r->sig[0] |= sticky_rshift_significand (r, r, shift);
+ r->exp += shift;
}
-#else
- *y |= (UEMUSHORT) 0x7fef;
- if (! REAL_WORDS_BIG_ENDIAN)
+ }
+
+ /* Check the range of the exponent. If we're out of range,
+ either underflow or overflow. */
+ if (r->exp > emax2)
+ goto overflow;
+ else if (r->exp <= emin2m1)
+ {
+ int diff;
+
+ if (!fmt->has_denorm)
{
- *(--y) = 0xffff;
- *(--y) = 0xffff;
- *(--y) = 0xffff;
+ /* Don't underflow completely until we've had a chance to round. */
+ if (r->exp < emin2m1)
+ goto underflow;
}
else
{
- ++y;
- *y++ = 0xffff;
- *y++ = 0xffff;
- *y++ = 0xffff;
+ diff = emin2m1 - r->exp + 1;
+ if (diff > p2)
+ goto underflow;
+
+ /* De-normalize the significand. */
+ r->sig[0] |= sticky_rshift_significand (r, r, diff);
+ r->exp += diff;
}
-#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
- {
- ++y;
- *y++ = *p++;
- *y++ = *p++;
- *y++ = *p++;
- }
-}
-#endif /* not C4X */
-#endif /* not IBM */
-#endif /* not DEC */
+ /* 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. */
+ 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);
-/* e type to single precision. */
+ /* Round to even. */
+ if (guard && (sticky || lsb))
+ {
+ REAL_VALUE_TYPE u;
+ get_zero (&u, 0);
+ set_significand_bit (&u, np2);
-#ifdef IBM
-/* Convert e-type X to IBM 370 float E. */
+ if (add_significands (r, r, &u))
+ {
+ /* Overflow. Means the significand had been all ones, and
+ is now all zeros. Need to increase the exponent, and
+ possibly re-normalize it. */
+ if (++r->exp > emax2)
+ goto overflow;
+ r->sig[SIGSZ-1] = SIG_MSB;
+
+ if (fmt->log2_b != 1)
+ {
+ int shift = r->exp & (fmt->log2_b - 1);
+ if (shift)
+ {
+ shift = fmt->log2_b - shift;
+ rshift_significand (r, r, shift);
+ r->exp += shift;
+ if (r->exp > emax2)
+ goto overflow;
+ }
+ }
+ }
+ }
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoibm (x, e, SFmode);
+ /* Catch underflow that we deferred until after rounding. */
+ if (r->exp <= emin2m1)
+ goto underflow;
+
+ /* Clear out trailing garbage. */
+ clear_significand_below (r, np2);
}
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to IBM 370 float Y. */
+/* Extend or truncate to a new mode. */
-static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+void
+real_convert (r, mode, a)
+ REAL_VALUE_TYPE *r;
+ enum machine_mode mode;
+ const REAL_VALUE_TYPE *a;
{
- toibm (x, y, SFmode);
-}
+ const struct real_format *fmt;
-#else
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
-#ifdef C4X
-/* Convert e-type X to C4X float E. */
+ *r = *a;
+ round_for_format (fmt, r);
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+ /* round_for_format de-normalizes denormals. Undo just that part. */
+ if (r->class == rvc_normal)
+ normalize (r);
+}
+
+/* Legacy. Likewise, except return the struct directly. */
+
+REAL_VALUE_TYPE
+real_value_truncate (mode, a)
+ enum machine_mode mode;
+ REAL_VALUE_TYPE a;
{
- etoc4x (x, e, QFmode);
+ REAL_VALUE_TYPE r;
+ real_convert (&r, mode, &a);
+ return r;
}
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to IBM 370 float Y. */
+/* Return true if truncating to MODE is exact. */
-static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+bool
+exact_real_truncate (mode, a)
+ enum machine_mode mode;
+ const REAL_VALUE_TYPE *a;
{
- toc4x (x, y, QFmode);
+ REAL_VALUE_TYPE t;
+ real_convert (&t, mode, a);
+ return real_identical (&t, a);
}
-#else
+/* 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.
-/* Convert e-type X to IEEE float E. DEC float is the same as IEEE float. */
+ Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE. */
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+long
+real_to_target_fmt (buf, r_orig, fmt)
+ long *buf;
+ const REAL_VALUE_TYPE *r_orig;
+ const struct real_format *fmt;
{
- EMULONG exp;
- UEMUSHORT xi[NI];
- int rndsav;
+ REAL_VALUE_TYPE r;
+ long buf1;
-#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);
+ r = *r_orig;
+ round_for_format (fmt, &r);
+
+ if (!buf)
+ buf = &buf1;
+ (*fmt->encode) (fmt, buf, &r);
+
+ return *buf;
}
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to IEEE float Y. */
+/* Similar, but look up the format from MODE. */
-static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+long
+real_to_target (buf, r, mode)
+ long *buf;
+ const REAL_VALUE_TYPE *r;
+ 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_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
- i = *p++;
-/* Handle overflow cases. */
- if (i >= 255)
- {
-#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;
- 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);
- }
- 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
+ return real_to_target_fmt (buf, r, fmt);
}
-#endif /* not C4X */
-#endif /* not IBM */
-/* 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. */
+/* 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 int
-ecmp (a, b)
- const UEMUSHORT *a, *b;
+void
+real_from_target_fmt (r, buf, fmt)
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+ const struct real_format *fmt;
{
- UEMUSHORT ai[NI], bi[NI];
- UEMUSHORT *p, *q;
- int i;
- int msign;
+ (*fmt->decode) (fmt, r, buf);
+}
-#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++)
- {
- if (ai[i] != 0)
- goto nzro;
- if (bi[i] != 0)
- goto nzro;
- }
- 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++)
- {
- goto diff;
- }
- }
- while (--i > 0);
+/* Similar, but look up the format from MODE. */
- return (0); /* equality */
+void
+real_from_target (r, buf, mode)
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+ enum machine_mode mode;
+{
+ const struct real_format *fmt;
- diff:
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
- if (*(--p) > *(--q))
- return (msign); /* p is bigger */
- else
- return (-msign); /* p is littler */
-}
+ (*fmt->decode) (fmt, r, buf);
+}
-#if 0
-/* Find e-type nearest integer to X, as floor (X + 0.5). */
+/* Return the number of bits in the significand for MODE. */
+/* ??? Legacy. Should get access to real_format directly. */
-static void
-eround (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
+int
+significand_size (mode)
+ enum machine_mode mode;
{
- eadd (ehalf, x, y);
- efloor (y, y);
+ const struct real_format *fmt;
+
+ fmt = real_format_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ return 0;
+
+ return fmt->p * fmt->log2_b;
}
-#endif /* 0 */
-/* Convert HOST_WIDE_INT LP to e type Y. */
+/* 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. */
-static void
-ltoe (lp, y)
- const HOST_WIDE_INT *lp;
- UEMUSHORT *y;
+unsigned int
+real_hash (r)
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT yi[NI];
- unsigned HOST_WIDE_INT ll;
- int k;
+ unsigned int h;
+ size_t i;
- ecleaz (yi);
- if (*lp < 0)
+ h = r->class | (r->sign << 2);
+ switch (r->class)
{
- /* make it positive */
- ll = (unsigned HOST_WIDE_INT) (-(*lp));
- yi[0] = 0xffff; /* put correct sign in the e type number */
- }
- 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
+ case rvc_zero:
+ case rvc_inf:
+ break;
- 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 */
-}
+ case rvc_normal:
+ h |= r->exp << 3;
+ /* FALLTHRU */
-/* Convert unsigned HOST_WIDE_INT LP to e type Y. */
+ case rvc_nan:
+ 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];
+ break;
-static void
-ultoe (lp, y)
- const unsigned HOST_WIDE_INT *lp;
- UEMUSHORT *y;
-{
- 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
+ default:
+ abort ();
+ }
- 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 */
+ return h;
}
+
+/* IEEE single-precision format. */
-
-/* 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 encode_ieee_single PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ieee_single PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-eifrac (x, i, frac)
- const UEMUSHORT *x;
- HOST_WIDE_INT *i;
- UEMUSHORT *frac;
+encode_ieee_single (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT xi[NI];
- int j, k;
- unsigned HOST_WIDE_INT ll;
+ unsigned long image, sig, exp;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
- 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))
+ image = r->sign << 31;
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
+
+ switch (r->class)
{
- /* long integer overflow: output large integer
- and correct fraction */
- if (xi[0])
- *i = ((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1);
+ 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)
{
-#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;
- 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];
+ image |= 255 << 23;
+ image |= sig;
+ if (!fmt->qnan_msb_set)
+ image ^= 1 << 23 | 1 << 22;
}
- while ((k -= 16) > 0);
- *i = ll;
- if (xi[0])
- *i = -(*i);
- }
- 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;
+ else
+ image |= 0x7fffffff;
+ break;
- emovo (xi, frac);
-}
+ 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 = r->exp + 127 - 1;
+ image |= exp << 23;
+ image |= sig;
+ break;
+ default:
+ abort ();
+ }
-/* 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. */
+ buf[0] = image;
+}
static void
-euifrac (x, i, frac)
- const UEMUSHORT *x;
- unsigned HOST_WIDE_INT *i;
- UEMUSHORT *frac;
+decode_ieee_single (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- unsigned HOST_WIDE_INT ll;
- UEMUSHORT xi[NI];
- int j, k;
+ unsigned long image = buf[0] & 0xffffffff;
+ bool sign = (image >> 31) & 1;
+ int exp = (image >> 23) & 0xff;
- emovi (x, xi);
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- /* if exponent <= 0, integer = 0 and argument is fraction */
- *i = 0L;
- emovo (xi, frac);
- return;
- }
- if (k > HOST_BITS_PER_WIDE_INT)
+ memset (r, 0, sizeof (*r));
+ image <<= HOST_BITS_PER_LONG - 24;
+ image &= ~SIG_MSB;
+
+ if (exp == 0)
{
- /* 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");
+ if (image && fmt->has_denorm)
+ {
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = -126;
+ r->sig[SIGSZ-1] = image << 1;
+ normalize (r);
+ }
+ else if (fmt->has_signed_zero)
+ r->sign = sign;
}
- else if (k > 16)
+ else if (exp == 255 && (fmt->has_nans || fmt->has_inf))
{
- /* 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
+ if (image)
{
- eshup6 (xi);
- ll = (ll << 16) | xi[M];
+ r->class = rvc_nan;
+ r->sign = sign;
+ if (!fmt->qnan_msb_set)
+ image ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
+ r->sig[SIGSZ-1] = image;
+ }
+ else
+ {
+ r->class = rvc_inf;
+ r->sign = sign;
}
- while ((k -= 16) > 0);
- *i = ll;
}
else
{
- /* shift not more than 16 bits */
- eshift (xi, k);
- *i = (HOST_WIDE_INT) xi[M] & 0xffff;
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 127 + 1;
+ r->sig[SIGSZ-1] = image | SIG_MSB;
}
+}
- 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;
+const struct real_format ieee_single_format =
+ {
+ encode_ieee_single,
+ decode_ieee_single,
+ 2,
+ 1,
+ 24,
+ -125,
+ 128,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
- emovo (xi, frac);
-}
+
+/* IEEE double-precision format. */
-/* Shift the significand of exploded e-type X up or down by SC bits. */
+static void encode_ieee_double PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ieee_double PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
-static int
-eshift (x, sc)
- UEMUSHORT *x;
- int sc;
+static void
+encode_ieee_double (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT lost;
- UEMUSHORT *p;
+ unsigned long image_lo, image_hi, sig_lo, sig_hi, exp;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
- if (sc == 0)
- return (0);
+ image_hi = r->sign << 31;
+ image_lo = 0;
- lost = 0;
- p = x + NI - 1;
+ if (HOST_BITS_PER_LONG == 64)
+ {
+ sig_hi = r->sig[SIGSZ-1];
+ sig_lo = (sig_hi >> (64 - 53)) & 0xffffffff;
+ sig_hi = (sig_hi >> (64 - 53 + 1) >> 31) & 0xfffff;
+ }
+ else
+ {
+ 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;
+ }
- if (sc < 0)
+ switch (r->class)
{
- sc = -sc;
- while (sc >= 16)
- {
- lost |= *p; /* remember lost bits */
- eshdn6 (x);
- sc -= 16;
- }
+ case rvc_zero:
+ break;
- while (sc >= 8)
+ case rvc_inf:
+ if (fmt->has_inf)
+ image_hi |= 2047 << 20;
+ else
{
- lost |= *p & 0xff;
- eshdn8 (x);
- sc -= 8;
+ image_hi |= 0x7fffffff;
+ image_lo = 0xffffffff;
}
+ break;
- while (sc > 0)
+ case rvc_nan:
+ if (fmt->has_nans)
{
- lost |= *p & 1;
- eshdn1 (x);
- sc -= 1;
+ image_hi |= 2047 << 20;
+ image_hi |= sig_hi;
+ if (!fmt->qnan_msb_set)
+ image_hi ^= 1 << 19 | 1 << 18;
+ image_lo = sig_lo;
}
- }
- else
- {
- while (sc >= 16)
+ else
{
- eshup6 (x);
- sc -= 16;
+ image_hi |= 0x7fffffff;
+ image_lo = 0xffffffff;
}
+ break;
- while (sc >= 8)
- {
- eshup8 (x);
- sc -= 8;
- }
+ 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 = r->exp + 1023 - 1;
+ image_hi |= exp << 20;
+ image_hi |= sig_hi;
+ image_lo = sig_lo;
+ break;
- while (sc > 0)
- {
- eshup1 (x);
- sc -= 1;
- }
+ default:
+ abort ();
}
- if (lost)
- lost = 1;
- return ((int) lost);
-}
-/* Shift normalize the significand area of exploded e-type X.
- Return the shift count (up = positive). */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image_hi, buf[1] = image_lo;
+ else
+ buf[0] = image_lo, buf[1] = image_hi;
+}
-static int
-enormlz (x)
- UEMUSHORT x[];
+static void
+decode_ieee_double (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- 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;
+ unsigned long image_hi, image_lo;
+ bool sign;
+ int exp;
- /* 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)
+ 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;
+
+ sign = (image_hi >> 31) & 1;
+ exp = (image_hi >> 20) & 0x7ff;
+
+ memset (r, 0, sizeof (*r));
+
+ image_hi <<= 32 - 21;
+ image_hi |= image_lo >> 21;
+ image_hi &= 0x7fffffff;
+ image_lo <<= 32 - 21;
+
+ if (exp == 0)
{
- eshup1 (x);
- sc += 1;
- if (sc > NBITS)
+ if ((image_hi || image_lo) && fmt->has_denorm)
{
- mtherr ("enormlz", UNDERFLOW);
- return (sc);
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = -1022;
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ image_hi = (image_hi << 1) | (image_lo >> 31);
+ image_lo <<= 1;
+ r->sig[SIGSZ-1] = image_hi;
+ r->sig[SIGSZ-2] = image_lo;
+ }
+ else
+ {
+ image_hi = (image_hi << 31 << 2) | (image_lo << 1);
+ r->sig[SIGSZ-1] = image_hi;
+ }
+ normalize (r);
}
+ else if (fmt->has_signed_zero)
+ r->sign = sign;
}
- return (sc);
-
- /* Normalize by shifting down out of the high guard word
- of the significand */
- normdn:
-
- if (*p & 0xff00)
+ else if (exp == 2047 && (fmt->has_nans || fmt->has_inf))
{
- eshdn8 (x);
- sc -= 8;
+ if (image_hi || image_lo)
+ {
+ r->class = rvc_nan;
+ r->sign = sign;
+ 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;
+
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
+ }
+ else
+ {
+ r->class = rvc_inf;
+ r->sign = sign;
+ }
}
- while (*p != 0)
+ else
{
- eshdn1 (x);
- sc -= 1;
-
- if (sc < -NBITS)
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 1023 + 1;
+ if (HOST_BITS_PER_LONG == 32)
{
- mtherr ("enormlz", OVERFLOW);
- return (sc);
+ 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;
}
- return (sc);
}
-/* Powers of ten used in decimal <-> binary conversions. */
-
-#define NTEN 12
-#define MAXP 4096
-
-#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 */
-};
+const struct real_format ieee_double_format =
+ {
+ encode_ieee_double,
+ decode_ieee_double,
+ 2,
+ 1,
+ 53,
+ -1021,
+ 1024,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
-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] =
-{
- {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 */
-};
+
+/* IEEE extended double precision format. This comes in three
+ flavours: Intel's as a 12 byte image, Intel's as a 16 byte image,
+ and Motorola's. */
+
+static void encode_ieee_extended PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ieee_extended PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+
+static void encode_ieee_extended_128 PARAMS ((const struct real_format *fmt,
+ long *,
+ const REAL_VALUE_TYPE *));
+static void decode_ieee_extended_128 PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *,
+ const long *));
-static const UEMUSHORT emtens[NTEN + 1][NE] =
+static void
+encode_ieee_extended (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- {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
+ unsigned long image_hi, sig_hi, sig_lo;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
-#if 0
-/* Convert float value X to ASCII string STRING with NDIG digits after
- the decimal point. */
+ image_hi = r->sign << 15;
+ sig_hi = sig_lo = 0;
-static void
-e24toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
-{
- UEMUSHORT w[NI];
+ switch (r->class)
+ {
+ case rvc_zero:
+ break;
- e24toe (x, w);
- etoasc (w, string, ndigs);
-}
+ case rvc_inf:
+ if (fmt->has_inf)
+ {
+ image_hi |= 32767;
-/* Convert double value X to ASCII string STRING with NDIG digits after
- the decimal point. */
+ /* 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;
-static void
-e53toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
-{
- UEMUSHORT w[NI];
+ case rvc_nan:
+ if (fmt->has_nans)
+ {
+ image_hi |= 32767;
+ 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 (!fmt->qnan_msb_set)
+ sig_hi ^= 1 << 30 | 1 << 29;
- e53toe (x, w);
- etoasc (w, string, ndigs);
-}
+ /* 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;
-/* Convert double extended value X to ASCII string STRING with NDIG digits
- after the decimal point. */
+ case rvc_normal:
+ {
+ int exp = r->exp;
+
+ /* 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 descrepency has been taken care of by the difference
+ in fmt->emin in round_for_format. */
+
+ if (denormal)
+ exp = 0;
+ else
+ {
+ exp += 16383 - 1;
+ if (exp < 0)
+ abort ();
+ }
+ 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;
-static void
-e64toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
-{
- UEMUSHORT w[NI];
+ default:
+ abort ();
+ }
- e64toe (x, w);
- etoasc (w, string, ndigs);
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image_hi << 16, buf[1] = sig_hi, buf[2] = sig_lo;
+ else
+ buf[0] = sig_lo, buf[1] = sig_hi, buf[2] = image_hi;
}
-/* Convert 128-bit long double value X to ASCII string STRING with NDIG digits
- after the decimal point. */
-
static void
-e113toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
+encode_ieee_extended_128 (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT w[NI];
-
- e113toe (x, w);
- etoasc (w, string, ndigs);
+ buf[3 * !FLOAT_WORDS_BIG_ENDIAN] = 0;
+ encode_ieee_extended (fmt, buf+!!FLOAT_WORDS_BIG_ENDIAN, r);
}
-#endif /* 0 */
-
-/* Convert e-type X to ASCII string STRING with NDIGS digits after
- the decimal point. */
-
-static char wstring[80]; /* working storage for ASCII output */
static void
-etoasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
+decode_ieee_extended (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- 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))
- {
- sprintf (wstring, " NaN ");
- goto bxit;
- }
-#endif
- rndprc = NBITS; /* set to full precision */
- emov (x, y); /* retain external format */
- if (y[NE - 1] & 0x8000)
- {
- sign = 0xffff;
- y[NE - 1] &= 0x7fff;
- }
- else
- {
- 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++)
- {
- if (y[k] != 0)
- goto tnzro; /* denormalized number */
- }
- goto isone; /* valid all zeros */
- }
- tnzro:
-
- /* Test for infinity. */
- if (y[NE - 1] == 0x7fff)
- {
- if (sign)
- sprintf (wstring, " -Infinity ");
- else
- sprintf (wstring, " Infinity ");
- goto bxit;
- }
-
- /* 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;
- }
+ unsigned long image_hi, sig_hi, sig_lo;
+ bool sign;
+ int exp;
- /* Compare to 1.0 */
- i = ecmp (eone, y);
- if (i == 0)
- goto isone;
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image_hi = buf[0] >> 16, sig_hi = buf[1], sig_lo = buf[2];
+ else
+ sig_lo = buf[0], sig_hi = buf[1], image_hi = buf[2];
+ sig_lo &= 0xffffffff;
+ sig_hi &= 0xffffffff;
+ image_hi &= 0xffffffff;
- if (i == -2)
- abort ();
+ sign = (image_hi >> 15) & 1;
+ exp = image_hi & 0x7fff;
- 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));
- 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 ((sig_hi || sig_lo) && fmt->has_denorm)
{
- if (ecmp (p, u) <= 0)
+ r->class = 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. */
+ r->exp = fmt->emin;
+ if (HOST_BITS_PER_LONG == 32)
{
- ediv (p, u, u);
- emul (p, t, t);
- expon += (int) m;
+ r->sig[SIGSZ-1] = sig_hi;
+ r->sig[SIGSZ-2] = sig_lo;
}
- m >>= 1;
- if (m == 0)
- break;
- p += NE;
+ else
+ r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
+
+ 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 == 32767 && (fmt->has_nans || fmt->has_inf))
+ {
+ /* 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)
{
- while ((y[NE - 2] & 0x8000) == 0)
+ r->class = rvc_nan;
+ r->sign = sign;
+ if (HOST_BITS_PER_LONG == 32)
{
- emul (ten, y, y);
- expon -= 1;
+ r->sig[SIGSZ-1] = sig_hi;
+ r->sig[SIGSZ-2] = sig_lo;
}
+ else
+ r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
+
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
}
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);
+ r->class = rvc_inf;
+ r->sign = sign;
}
- k = -MAXP;
- p = &emtens[0][0];
- r = &etens[0][0];
- emov (y, w);
- emov (eone, t);
- while (ecmp (eone, w) > 0)
- {
- if (ecmp (p, w) >= 0)
- {
- emul (r, w, w);
- emul (r, t, t);
- expon += k;
- }
- k /= 2;
- if (k == 0)
- break;
- p += NE;
- r += NE;
- }
- ediv (t, eone, t);
}
- isone:
- /* 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;
- }
- else
- {
- *s++ = (char) digit + '0';
- *s++ = '.';
- }
- /* Generate digits after the decimal point. */
- for (k = 0; k <= ndigs; k++)
- {
- /* 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';
- }
- digit = equot[NI - 1];
- --s;
- ss = s;
- /* round off the ASCII string */
- if (digit > 4)
- {
- /* Test for critical rounding case in ASCII output. */
- if (digit == 5)
- {
- emovo (y, t);
- if (ecmp (t, ezero) != 0)
- goto roun; /* round to nearest */
-#ifndef C4X
- if ((*(s - 1) & 1) == 0)
- goto doexp; /* round to even */
-#endif
- }
- /* Round up and propagate carry-outs */
- roun:
- --s;
- k = *s & CHARMASK;
- /* Carry out to most significant digit? */
- if (k == '.')
- {
- --s;
- k = *s;
- k += 1;
- *s = (char) k;
- /* Most significant digit carries to 10? */
- if (k > '9')
- {
- expon += 1;
- *s = '1';
- }
- goto doexp;
- }
- /* Round up and carry out from less significant digits */
- k += 1;
- *s = (char) k;
- if (k > '9')
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 16383 + 1;
+ if (HOST_BITS_PER_LONG == 32)
{
- *s = '0';
- goto roun;
+ r->sig[SIGSZ-1] = sig_hi;
+ r->sig[SIGSZ-2] = sig_lo;
}
+ else
+ r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
}
- 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;
+decode_ieee_extended_128 (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- asctoeg (s, y, 24);
+ decode_ieee_extended (fmt, r, buf+!!FLOAT_WORDS_BIG_ENDIAN);
}
-
-/* Convert ASCII string S to double precision value Y. */
+const struct real_format ieee_extended_motorola_format =
+ {
+ encode_ieee_extended,
+ decode_ieee_extended,
+ 2,
+ 1,
+ 64,
+ -16382,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+const struct real_format ieee_extended_intel_96_format =
+ {
+ encode_ieee_extended,
+ decode_ieee_extended,
+ 2,
+ 1,
+ 64,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+const struct real_format ieee_extended_intel_128_format =
+ {
+ encode_ieee_extended_128,
+ decode_ieee_extended_128,
+ 2,
+ 1,
+ 64,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+/* 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,
+ decode_ieee_extended,
+ 2,
+ 1,
+ 53,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+/* 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
+ ignored. Zeroes, Infinities, and NaNs are set in both doubles
+ due to precedent. */
+
+static void encode_ibm_extended PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ibm_extended PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-asctoe53 (s, y)
- const char *s;
- UEMUSHORT *y;
+encode_ibm_extended (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
-#if defined(DEC) || defined(IBM)
- asctoeg (s, y, 56);
-#else
-#if defined(C4X)
- asctoeg (s, y, 32);
-#else
- asctoeg (s, y, 53);
-#endif
-#endif
-}
+ REAL_VALUE_TYPE u, v;
+ switch (r->class)
+ {
+ case rvc_zero:
+ /* Both doubles have sign bit set. */
+ buf[0] = FLOAT_WORDS_BIG_ENDIAN ? r->sign << 31 : 0;
+ buf[1] = FLOAT_WORDS_BIG_ENDIAN ? 0 : r->sign << 31;
+ buf[2] = buf[0];
+ buf[3] = buf[1];
+ break;
-/* Convert ASCII string S to double extended value Y. */
+ case rvc_inf:
+ case rvc_nan:
+ /* Both doubles set to Inf / NaN. */
+ encode_ieee_double (&ieee_double_format, &buf[0], r);
+ buf[2] = buf[0];
+ buf[3] = buf[1];
+ return;
+
+ case rvc_normal:
+ /* u = IEEE double precision portion of significand. */
+ u = *r;
+ clear_significand_below (&u, SIGNIFICAND_BITS - 53);
+
+ normalize (&u);
+ /* If the upper double is zero, we have a denormal double, so
+ move it to the first double and leave the second as zero. */
+ if (u.class == rvc_zero)
+ {
+ v = u;
+ u = *r;
+ normalize (&u);
+ }
+ else
+ {
+ /* v = remainder containing additional 53 bits of significand. */
+ do_add (&v, r, &u, 1);
+ round_for_format (&ieee_double_format, &v);
+ }
-static void
-asctoe64 (s, y)
- const char *s;
- UEMUSHORT *y;
-{
- asctoeg (s, y, 64);
-}
+ round_for_format (&ieee_double_format, &u);
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* Convert ASCII string S to 128-bit long double Y. */
+ encode_ieee_double (&ieee_double_format, &buf[0], &u);
+ encode_ieee_double (&ieee_double_format, &buf[2], &v);
+ break;
-static void
-asctoe113 (s, y)
- const char *s;
- UEMUSHORT *y;
-{
- asctoeg (s, y, 113);
+ default:
+ abort ();
+ }
}
-#endif
-
-/* Convert ASCII string S to e type Y. */
static void
-asctoe (s, y)
- const char *s;
- UEMUSHORT *y;
+decode_ibm_extended (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- asctoeg (s, y, NBITS);
+ REAL_VALUE_TYPE u, v;
+
+ decode_ieee_double (&ieee_double_format, &u, &buf[0]);
+
+ if (u.class != rvc_zero && u.class != rvc_inf && u.class != rvc_nan)
+ {
+ decode_ieee_double (&ieee_double_format, &v, &buf[2]);
+ do_add (r, &u, &v, 0);
+ }
+ else
+ *r = u;
}
-/* Convert ASCII string SS to e type Y, with a specified rounding precision
- of OPREC bits. BASE is 16 for C99 hexadecimal floating constants. */
+const struct real_format ibm_extended_format =
+ {
+ encode_ibm_extended,
+ decode_ibm_extended,
+ 2,
+ 1,
+ 53 + 53,
+ -1021 + 53,
+ 1024,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+
+/* IEEE quad precision format. */
+
+static void encode_ieee_quad PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_ieee_quad PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-asctoeg (ss, y, oprec)
- const char *ss;
- UEMUSHORT *y;
- int oprec;
+encode_ieee_quad (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- 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;
+ unsigned long image3, image2, image1, image0, exp;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
+ REAL_VALUE_TYPE u;
- if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
- {
- base = 16;
- s += 2;
- }
+ image3 = r->sign << 31;
+ image2 = 0;
+ image1 = 0;
+ image0 = 0;
- 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))
+ rshift_significand (&u, r, SIGNIFICAND_BITS - 113);
+
+ switch (r->class)
{
- /* 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))
+ case rvc_zero:
+ break;
+
+ case rvc_inf:
+ if (fmt->has_inf)
+ image3 |= 32767 << 16;
+ else
{
- 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;
+ image3 |= 0x7fffffff;
+ image2 = 0xffffffff;
+ image1 = 0xffffffff;
+ image0 = 0xffffffff;
}
+ break;
- /* 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)
+ case rvc_nan:
+ if (fmt->has_nans)
{
- if (base == 16)
- {
- if (decflg)
- nexp += 4; /* count digits after decimal point */
+ image3 |= 32767 << 16;
- eshup1 (yy); /* multiply current number by 16 */
- eshup1 (yy);
- eshup1 (yy);
- eshup1 (yy);
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ image0 = u.sig[0];
+ image1 = u.sig[1];
+ image2 = u.sig[2];
+ image3 |= u.sig[3] & 0xffff;
}
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);
+ image0 = u.sig[0];
+ image1 = image0 >> 31 >> 1;
+ image2 = u.sig[1];
+ image3 |= (image2 >> 31 >> 1) & 0xffff;
+ image0 &= 0xffffffff;
+ image2 &= 0xffffffff;
}
- /* Insert the current digit. */
- ecleaz (xt);
- xt[NI - 2] = (UEMUSHORT) k;
- eaddm (xt, yy);
+
+ if (!fmt->qnan_msb_set)
+ image3 ^= 1 << 15 | 1 << 14;
}
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;
- }
+ image3 |= 0x7fffffff;
+ image2 = 0xffffffff;
+ image1 = 0xffffffff;
+ image0 = 0xffffffff;
}
- 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;
- }
- daldone:
- if (base == 16)
- {
- /* Base 16 hexadecimal floating constant. */
- if ((k = enormlz (yy)) > NBITS)
+ 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 = r->exp + 16383 - 1;
+ image3 |= exp << 16;
+
+ if (HOST_BITS_PER_LONG == 32)
{
- ecleaz (yy);
- goto aexit;
+ image0 = u.sig[0];
+ image1 = u.sig[1];
+ image2 = u.sig[2];
+ image3 |= u.sig[3] & 0xffff;
}
- /* Adjust the exponent. NEXP is the number of hex digits,
- EXP is a power of 2. */
- lexp = (EXONE - 1 + NBITS) - k + yy[E] + exp - nexp;
- if (lexp > 0x7fff)
- goto infinite;
- if (lexp < 0)
- goto zero;
- yy[E] = lexp;
- goto expdon;
- }
+ else
+ {
+ image0 = u.sig[0];
+ image1 = image0 >> 31 >> 1;
+ image2 = u.sig[1];
+ image3 |= (image2 >> 31 >> 1) & 0xffff;
+ image0 &= 0xffffffff;
+ image2 &= 0xffffffff;
+ }
+ break;
- 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;
+ default:
+ abort ();
}
- 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)
+ if (FLOAT_WORDS_BIG_ENDIAN)
{
- nexp = -nexp;
- esign = -1;
- if (nexp > 4096)
- {
- /* Punt. Can't handle this without 2 divides. */
- emovi (etens[0], tt);
- lexp -= tt[E];
- k = edivm (tt, yy);
- lexp += EXONE;
- nexp -= 4096;
- }
+ buf[0] = image3;
+ buf[1] = image2;
+ buf[2] = image1;
+ buf[3] = image0;
}
- emov (eone, xt);
- exp = 1;
- i = NTEN;
- do
+ else
{
- if (exp & nexp)
- emul (etens[i], xt, xt);
- i--;
- exp = exp + exp;
+ buf[0] = image0;
+ buf[1] = image1;
+ buf[2] = image2;
+ buf[3] = image3;
}
- while (exp <= MAXP);
+}
- emovi (xt, tt);
- if (esign < 0)
+static void
+decode_ieee_quad (fmt, r, buf)
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+{
+ unsigned long image3, image2, image1, image0;
+ bool sign;
+ int exp;
+
+ if (FLOAT_WORDS_BIG_ENDIAN)
{
- lexp -= tt[E];
- k = edivm (tt, yy);
- lexp += EXONE;
+ image3 = buf[0];
+ image2 = buf[1];
+ image1 = buf[2];
+ image0 = buf[3];
}
else
{
- lexp += tt[E];
- k = emulm (tt, yy);
- lexp -= EXONE - 1;
+ image0 = buf[0];
+ image1 = buf[1];
+ image2 = buf[2];
+ image3 = buf[3];
}
- 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);
+ image0 &= 0xffffffff;
+ image1 &= 0xffffffff;
+ image2 &= 0xffffffff;
- aexit:
+ sign = (image3 >> 31) & 1;
+ exp = (image3 >> 16) & 0x7fff;
+ image3 &= 0xffff;
- rndprc = rndsav;
- yy[0] = nsign;
- switch (oprec)
- {
-#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);
- break;
-#endif
-
- case 53:
- toe53 (yy, y);
- break;
- case 24:
- toe24 (yy, y);
- break;
- case 64:
- toe64 (yy, y);
- break;
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- case 113:
- toe113 (yy, y);
- break;
-#endif
- case NBITS:
- emovo (yy, y);
- break;
- }
-}
+ memset (r, 0, sizeof (*r));
+ if (exp == 0)
+ {
+ if ((image3 | image2 | image1 | image0) && fmt->has_denorm)
+ {
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = -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;
+ }
-/* Return Y = largest integer not greater than X (truncated toward minus
- infinity). */
+ normalize (r);
+ }
+ else if (fmt->has_signed_zero)
+ r->sign = sign;
+ }
+ else if (exp == 32767 && (fmt->has_nans || fmt->has_inf))
+ {
+ if (image3 | image2 | image1 | image0)
+ {
+ r->class = rvc_nan;
+ r->sign = sign;
-static const UEMUSHORT bmask[] =
-{
- 0xffff,
- 0xfffe,
- 0xfffc,
- 0xfff8,
- 0xfff0,
- 0xffe0,
- 0xffc0,
- 0xff80,
- 0xff00,
- 0xfe00,
- 0xfc00,
- 0xf800,
- 0xf000,
- 0xe000,
- 0xc000,
- 0x8000,
- 0x0000,
-};
+ 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);
-static void
-efloor (x, y)
- const UEMUSHORT x[];
- UEMUSHORT y[];
-{
- 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;
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
+ }
+ else
+ {
+ r->class = rvc_inf;
+ r->sign = sign;
+ }
}
- /* number of bits to clear out */
- e = NBITS - e;
- emov (f, y);
- if (e <= 0)
- return;
-
- p = &y[0];
- while (e >= 16)
+ else
{
- *p++ = 0;
- e -= 16;
- }
- /* clear the remaining bits */
- *p &= bmask[e];
- /* truncate negatives toward minus infinity */
- isitneg:
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 16383 + 1;
- if ((UEMUSHORT) expon & (UEMUSHORT) 0x8000)
- {
- for (i = 0; i < NE - 1; i++)
+ if (HOST_BITS_PER_LONG == 32)
{
- if (f[i] != y[i])
- {
- esub (eone, y, y);
- break;
- }
+ 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;
}
}
-
-#if 0
-/* Return S and EXP such that S * 2^EXP = X and .5 <= S < 1.
- For example, 1.1 = 0.55 * 2^1. */
+const struct real_format ieee_quad_format =
+ {
+ encode_ieee_quad,
+ decode_ieee_quad,
+ 2,
+ 1,
+ 113,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+/* Descriptions of VAX floating point formats can be found beginning at
+
+ http://www.openvms.compaq.com:8000/73final/4515/4515pro_013.html#f_floating_point_format
+
+ The thing to remember is that they're almost IEEE, except for word
+ order, exponent bias, and the lack of infinities, nans, and denormals.
+
+ We don't implement the H_floating format here, simply because neither
+ the VAX or Alpha ports use it. */
+
+static void encode_vax_f PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_vax_f PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+static void encode_vax_d PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_vax_d PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+static void encode_vax_g PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_vax_g PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-efrexp (x, exp, s)
- const UEMUSHORT x[];
- int *exp;
- UEMUSHORT s[];
+encode_vax_f (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT xi[NI];
- EMULONG li;
+ unsigned long sign, exp, sig, image;
- emovi (x, xi);
- /* Handle denormalized numbers properly using long integer exponent. */
- li = (EMULONG) ((EMUSHORT) xi[1]);
+ sign = r->sign << 15;
- if (li == 0)
+ switch (r->class)
{
- li -= enormlz (xi);
- }
- xi[1] = 0x3ffe;
- emovo (xi, s);
- *exp = (int) (li - 0x3ffe);
-}
-#endif
+ case rvc_zero:
+ image = 0;
+ break;
-/* Return e type Y = X * 2^PWR2. */
+ case rvc_inf:
+ case rvc_nan:
+ image = 0xffff7fff | sign;
+ break;
-static void
-eldexp (x, pwr2, y)
- const UEMUSHORT x[];
- int pwr2;
- UEMUSHORT y[];
-{
- UEMUSHORT xi[NI];
- EMULONG li;
- int i;
+ case rvc_normal:
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
+ exp = r->exp + 128;
- emovi (x, xi);
- li = xi[1];
- li += pwr2;
- i = 0;
- emdnorm (xi, i, i, li, 64);
- emovo (xi, y);
-}
+ image = (sig << 16) & 0xffff0000;
+ image |= sign;
+ image |= exp << 7;
+ image |= sig >> 16;
+ break;
+ default:
+ abort ();
+ }
-#if 0
-/* C = remainder after dividing B by A, all e type values.
- Least significant integer quotient bits left in EQUOT. */
+ buf[0] = image;
+}
static void
-eremain (a, b, c)
- const UEMUSHORT a[], b[];
- UEMUSHORT c[];
+decode_vax_f (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT den[NI], num[NI];
+ unsigned long image = buf[0] & 0xffffffff;
+ int exp = (image >> 7) & 0xff;
-#ifdef NANS
- if (eisinf (b)
- || (ecmp (a, ezero) == 0)
- || eisnan (a)
- || eisnan (b))
- {
- enan (c, 0);
- return;
- }
-#endif
- if (ecmp (a, ezero) == 0)
+ memset (r, 0, sizeof (*r));
+
+ if (exp != 0)
{
- mtherr ("eremain", SING);
- eclear (c);
- return;
+ r->class = rvc_normal;
+ r->sign = (image >> 15) & 1;
+ r->exp = exp - 128;
+
+ image = ((image & 0x7f) << 16) | ((image >> 16) & 0xffff);
+ r->sig[SIGSZ-1] = (image << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
}
- 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[];
+encode_vax_d (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- EMULONG ld, ln;
- UEMUSHORT j;
-
- ld = den[E];
- ld -= enormlz (den);
- ln = num[E];
- ln -= enormlz (num);
- ecleaz (equot);
- while (ln >= ld)
+ unsigned long image0, image1, sign = r->sign << 15;
+
+ switch (r->class)
{
- if (ecmpm (den, num) <= 0)
+ 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)
{
- esubm (den, num);
- j = 1;
+ image0 = r->sig[SIGSZ-1];
+ image1 = (image0 >> (64 - 56)) & 0xffffffff;
+ image0 = (image0 >> (64 - 56 + 1) >> 31) & 0x7fffff;
}
else
- j = 0;
- eshup1 (equot);
- equot[NI - 1] |= j;
- eshup1 (num);
- ln -= 1;
- }
- emdnorm (num, 0, 0, ln, 0);
-}
-
-/* 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
-
- The order of appearance of the following messages is bound to the
- error codes defined above. */
-
-int merror = 0;
-extern int merror;
-
-static void
-mtherr (name, code)
- const char *name;
- int code;
-{
- /* 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)
- {
- switch (code)
{
- case DOMAIN: warning ("%s: argument domain error" , name); break;
- case SING: warning ("%s: function singularity" , name); break;
- case OVERFLOW: warning ("%s: overflow range error" , name); break;
- case UNDERFLOW: warning ("%s: underflow range error" , name); break;
- case TLOSS: warning ("%s: total loss of precision" , name); break;
- case PLOSS: warning ("%s: partial loss of precision", name); break;
- case INVALID: warning ("%s: NaN - producing operation", name); break;
- default: abort ();
+ image0 = r->sig[SIGSZ-1];
+ image1 = r->sig[SIGSZ-2];
+ image1 = (image0 << 24) | (image1 >> 8);
+ image0 = (image0 >> 8) & 0xffffff;
}
- }
-
- /* Set global error message word */
- merror = code + 1;
-}
-
-#ifdef DEC
-/* Convert DEC double precision D to e type E. */
-
-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);
-}
-
-/* Convert e type X to DEC double precision D. */
-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);
-}
+ /* Rearrange the half-words of the significand to match the
+ external format. */
+ image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff007f;
+ image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit precision, to DEC format double Y. */
+ /* Add the sign and exponent. */
+ image0 |= sign;
+ image0 |= (r->exp + 128) << 7;
+ break;
-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)
- {
- *y++ = 0;
- *y++ = 0;
- *y++ = 0;
- *y++ = 0;
- return;
- }
- if (i > 0377)
- {
- *y++ |= 077777;
- *y++ = 0xffff;
- *y++ = 0xffff;
- *y++ = 0xffff;
-#ifdef ERANGE
- errno = ERANGE;
-#endif
- return;
+ default:
+ abort ();
}
- 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. */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image1, buf[1] = image0;
+ else
+ buf[0] = image0, buf[1] = image1;
+}
static void
-ibmtoe (d, e, mode)
- const UEMUSHORT *d;
- UEMUSHORT *e;
- enum machine_mode mode;
+decode_vax_d (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ 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 */
- {
- *p++ = *d++; /* fill in the rest of our mantissa */
- *p++ = *d++;
- }
- *p = *d;
+ unsigned long image0, image1;
+ int exp;
- if (y[M] == 0 && y[M+1] == 0 && y[M+2] == 0 && y[M+3] == 0)
- y[0] = y[E] = 0;
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image1 = buf[0], image0 = buf[1];
else
- y[E] -= 5 + enormlz (y); /* now normalise the mantissa */
- /* handle change in RADIX */
- emovo (y, e);
-}
+ image0 = buf[0], image1 = buf[1];
+ image0 &= 0xffffffff;
+ image1 &= 0xffffffff;
+ exp = (image0 >> 7) & 0x7f;
+ memset (r, 0, sizeof (*r));
-/* Convert e type to IBM single/double precision. */
+ if (exp != 0)
+ {
+ r->class = rvc_normal;
+ r->sign = (image0 >> 15) & 1;
+ r->exp = exp - 128;
-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);
-}
+ /* 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);
-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)
- {
- *y++ = 0;
- *y++ = 0;
- if (mode != SFmode)
+ if (HOST_BITS_PER_LONG == 64)
{
- *y++ = 0;
- *y++ = 0;
+ image0 = (image0 << 31 << 1) | image1;
+ image0 <<= 64 - 56;
+ image0 |= SIG_MSB;
+ r->sig[SIGSZ-1] = image0;
}
- return;
- }
- r = i & 0x3;
- i >>= 2;
- if (i > 0x7f)
- {
- *y++ |= 0x7fff;
- *y++ = 0xffff;
- if (mode != SFmode)
+ else
{
- *y++ = 0xffff;
- *y++ = 0xffff;
+ 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;
- }
- i &= 0x7f;
- *y |= (i << 8);
- eshift (x, r + 5);
- *y++ |= x[M];
- *y++ = x[M + 1];
- if (mode != SFmode)
- {
- *y++ = x[M + 2];
- *y++ = x[M + 3];
}
}
-#endif /* IBM */
-
-
-#ifdef C4X
-/* Convert C4X single/double precision to e type. */
static void
-c4xtoe (d, e, mode)
- const UEMUSHORT *d;
- UEMUSHORT *e;
- enum machine_mode mode;
+encode_vax_g (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- UEMUSHORT y[NI];
- UEMUSHORT dn[4];
- int r;
- int isnegative;
- int size;
- int i;
- int carry;
+ unsigned long image0, image1, sign = r->sign << 15;
- dn[0] = d[0];
- dn[1] = d[1];
- if (mode != QFmode)
+ switch (r->class)
{
- dn[2] = d[3] << 8;
- dn[3] = 0;
- }
-
- /* 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;
- }
-
- 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;
+ case rvc_zero:
+ image0 = image1 = 0;
+ break;
- r >>= 8; /* Shift exponent word down 8 bits. */
- if (r & 0x80) /* Make the exponent negative if it is. */
- r = r | (~0 & ~0xff);
+ case rvc_inf:
+ case rvc_nan:
+ image0 = 0xffff7fff | sign;
+ image1 = 0xffffffff;
+ break;
- if (isnegative)
- {
- /* 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;
- }
+ 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
- size = 2;
- eshift (y, -8);
+ {
+ image0 = r->sig[SIGSZ-1];
+ image1 = r->sig[SIGSZ-2];
+ image1 = (image0 << 21) | (image1 >> 11);
+ image0 = (image0 >> 11) & 0xfffff;
+ }
- /* Now do the two's complement on the data. */
+ /* Rearrange the half-words of the significand to match the
+ external format. */
+ image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff000f;
+ image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
- 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;
- }
- }
+ /* Add the sign and exponent. */
+ image0 |= sign;
+ image0 |= (r->exp + 1024) << 4;
+ break;
- 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);
+ default:
+ abort ();
}
- emovo (y, e);
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image1, buf[1] = image0;
+ else
+ buf[0] = image0, buf[1] = image1;
}
-
-/* Convert e type to C4X single/double precision. */
-
static void
-etoc4x (x, d, mode)
- const UEMUSHORT *x;
- UEMUSHORT *d;
- enum machine_mode mode;
+decode_vax_g (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
-
- emovi (x, xi);
+ unsigned long image0, image1;
+ int exp;
- /* Adjust exponent for offsets. */
- exp = (EMULONG) xi[E] - (EXONE - 0x7f);
-
- /* 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)
+ image1 = buf[0], image0 = buf[1];
+ else
+ image0 = buf[0], image1 = buf[1];
+ image0 &= 0xffffffff;
+ image1 &= 0xffffffff;
-static void
-toc4x (x, y, mode)
- UEMUSHORT *x, *y;
- enum machine_mode mode;
-{
- 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;
- }
+ exp = (image0 >> 4) & 0x7ff;
- *y = 0;
+ memset (r, 0, sizeof (*r));
- /* Negative number require a two's complement conversion of the
- mantissa. */
- if (x[0])
+ if (exp != 0)
{
- *y = 0x0080;
+ r->class = rvc_normal;
+ r->sign = (image0 >> 15) & 1;
+ r->exp = exp - 1024;
- i = ((int) x[1]) - 0x7f;
+ /* 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);
- /* 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 (HOST_BITS_PER_LONG == 64)
{
- if (x[v] == 0x0000)
- x[v] = carry ? 0x0000 : 0xffff;
- else
- {
- x[v] = ((~x[v]) + carry) & 0xffff;
- carry = 0;
- }
- v--;
+ image0 = (image0 << 31 << 1) | image1;
+ image0 <<= 64 - 53;
+ image0 |= SIG_MSB;
+ r->sig[SIGSZ-1] = image0;
}
-
- /* 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)
+ else
{
- /* 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--;
+ r->sig[SIGSZ-1] = image0;
+ r->sig[SIGSZ-2] = image1;
+ lshift_significand (r, r, 64 - 53);
+ r->sig[SIGSZ-1] |= SIG_MSB;
}
}
- else
- i = ((int) x[1]) - 0x7f;
+}
- if ((i < -128) || (i > 127))
- {
- y[0] |= 0xff7f;
- y[1] = 0xffff;
- if (mode != QFmode)
- {
- y[2] = 0xffff;
- y[3] = 0xffff;
- y[3] = (y[1] << 8) | ((y[2] >> 8) & 0xff);
- y[2] = (y[0] << 8) | ((y[1] >> 8) & 0xff);
- }
-#ifdef ERANGE
- errno = ERANGE;
-#endif
- return;
- }
+const struct real_format vax_f_format =
+ {
+ encode_vax_f,
+ decode_vax_f,
+ 2,
+ 1,
+ 24,
+ -127,
+ 127,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+const struct real_format vax_d_format =
+ {
+ encode_vax_d,
+ decode_vax_d,
+ 2,
+ 1,
+ 56,
+ -127,
+ 127,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+const struct real_format vax_g_format =
+ {
+ encode_vax_g,
+ decode_vax_g,
+ 2,
+ 1,
+ 53,
+ -1023,
+ 1023,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+/* A good reference for these can be found in chapter 9 of
+ "ESA/390 Principles of Operation", IBM document number SA22-7201-01.
+ An on-line version can be found here:
+
+ http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/DZ9AR001/9.1?DT=19930923083613
+*/
+
+static void encode_i370_single PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_i370_single PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+static void encode_i370_double PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_i370_double PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
- y[0] |= ((i & 0xff) << 8);
+static void
+encode_i370_single (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
+{
+ unsigned long sign, exp, sig, image;
- eshift (x, 8);
+ sign = r->sign << 31;
- y[0] |= x[M] & 0x7f;
- y[1] = x[M + 1];
- if (mode != QFmode)
+ switch (r->class)
{
- 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);
+ case rvc_zero:
+ image = 0;
+ break;
+
+ case rvc_inf:
+ case rvc_nan:
+ image = 0x7fffffff | sign;
+ break;
+
+ case rvc_normal:
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0xffffff;
+ exp = ((r->exp / 4) + 64) << 24;
+ image = sign | exp | sig;
+ break;
+
+ default:
+ abort ();
}
+
+ buf[0] = image;
}
-#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
+static void
+decode_i370_single (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+{
+ unsigned long sign, sig, image = buf[0];
+ int exp;
-#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
+ sign = (image >> 31) & 1;
+ exp = (image >> 24) & 0x7f;
+ sig = image & 0xffffff;
-#ifdef SFMODE_NAN
-SFMODE_NAN;
-#else
-#ifdef IEEE
-static const UEMUSHORT SFbignan[2] = {0x7fff, 0xffff};
-static const UEMUSHORT SFlittlenan[2] = {0, 0xffc0};
-#endif
-#endif
+ memset (r, 0, sizeof (*r));
+ if (exp || sig)
+ {
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = (exp - 64) * 4;
+ r->sig[SIGSZ-1] = sig << (HOST_BITS_PER_LONG - 24);
+ normalize (r);
+ }
+}
-#ifdef NANS
static void
-make_nan (nan, sign, mode)
- UEMUSHORT *nan;
- int sign;
- enum machine_mode mode;
+encode_i370_double (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
- int n;
- const UEMUSHORT *p;
+ unsigned long sign, exp, image_hi, image_lo;
+
+ sign = r->sign << 31;
- switch (mode)
+ switch (r->class)
{
-/* 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:
+ image_hi = image_lo = 0;
break;
-#endif
- /* FALLTHRU */
- case XFmode:
- n = 6;
- if (REAL_WORDS_BIG_ENDIAN)
- p = XFbignan;
- else
- p = XFlittlenan;
+ case rvc_inf:
+ case rvc_nan:
+ image_hi = 0x7fffffff | sign;
+ image_lo = 0xffffffff;
break;
- case DFmode:
- n = 4;
- if (REAL_WORDS_BIG_ENDIAN)
- p = DFbignan;
+ case rvc_normal:
+ if (HOST_BITS_PER_LONG == 64)
+ {
+ image_hi = r->sig[SIGSZ-1];
+ image_lo = (image_hi >> (64 - 56)) & 0xffffffff;
+ image_hi = (image_hi >> (64 - 56 + 1) >> 31) & 0xffffff;
+ }
else
- p = DFlittlenan;
- break;
+ {
+ image_hi = r->sig[SIGSZ-1];
+ image_lo = r->sig[SIGSZ-2];
+ image_lo = (image_lo >> 8) | (image_hi << 24);
+ image_hi >>= 8;
+ }
- case SFmode:
- case HFmode:
- n = 2;
- if (REAL_WORDS_BIG_ENDIAN)
- p = SFbignan;
- else
- p = SFlittlenan;
+ exp = ((r->exp / 4) + 64) << 24;
+ image_hi |= sign | exp;
break;
-#endif
default:
abort ();
}
- if (REAL_WORDS_BIG_ENDIAN)
- *nan++ = (sign << 15) | (*p++ & 0x7fff);
- while (--n != 0)
- *nan++ = *p++;
- if (! REAL_WORDS_BIG_ENDIAN)
- *nan = (sign << 15) | (*p & 0x7fff);
-}
-#endif /* NANS */
-/* This is the inverse of the function `etarsingle' invoked by
- REAL_VALUE_TO_TARGET_SINGLE. */
-
-REAL_VALUE_TYPE
-ereal_unto_float (f)
- long f;
-{
- 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;
- }
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image_hi, buf[1] = image_lo;
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;
+ buf[0] = image_lo, buf[1] = image_hi;
}
-
-/* This is the inverse of the function `etardouble' invoked by
- REAL_VALUE_TO_TARGET_DOUBLE. */
-
-REAL_VALUE_TYPE
-ereal_unto_double (d)
- long d[];
+static void
+decode_i370_double (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[4];
- UEMUSHORT e[NE];
+ unsigned long sign, image_hi, image_lo;
+ int exp;
- /* 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];
- }
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image_hi = buf[0], image_lo = buf[1];
else
- {
- /* 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;
-}
-
+ image_lo = buf[0], image_hi = buf[1];
-/* 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. */
+ sign = (image_hi >> 31) & 1;
+ exp = (image_hi >> 24) & 0x7f;
+ image_hi &= 0xffffff;
+ image_lo &= 0xffffffff;
-REAL_VALUE_TYPE
-ereal_from_float (f)
- HOST_WIDE_INT f;
-{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[2];
- UEMUSHORT e[NE];
+ memset (r, 0, sizeof (*r));
- /* 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
+ if (exp || image_hi || image_lo)
{
- 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;
-}
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = (exp - 64) * 4 + (SIGNIFICAND_BITS - 56);
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ r->sig[0] = image_lo;
+ r->sig[1] = image_hi;
+ }
+ else
+ r->sig[0] = image_lo | (image_hi << 31 << 1);
-/* 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.
+ normalize (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. */
+const struct real_format i370_single_format =
+ {
+ encode_i370_single,
+ decode_i370_single,
+ 16,
+ 4,
+ 6,
+ -64,
+ 63,
+ false,
+ false,
+ false, /* ??? The encoding does allow for "unnormals". */
+ false, /* ??? The encoding does allow for "unnormals". */
+ false
+ };
+
+const struct real_format i370_double_format =
+ {
+ encode_i370_double,
+ decode_i370_double,
+ 16,
+ 4,
+ 14,
+ -64,
+ 63,
+ false,
+ false,
+ false, /* ??? The encoding does allow for "unnormals". */
+ false, /* ??? The encoding does allow for "unnormals". */
+ false
+ };
+
+/* The "twos-complement" c4x format is officially defined as
-REAL_VALUE_TYPE
-ereal_from_double (d)
- HOST_WIDE_INT d[];
-{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[4];
- UEMUSHORT e[NE];
+ x = s(~s).f * 2**e
- /* 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;
-}
+ This is rather misleading. One must remember that F is signed.
+ A better description would be
+ x = -1**s * ((s + 1 + .f) * 2**e
-#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. */
+ So if we have a (4 bit) fraction of .1000 with a sign bit of 1,
+ that's -1 * (1+1+(-.5)) == -1.5. I think.
-static void
-uditoe (di, e)
- const UEMUSHORT *di; /* Address of the 64-bit int. */
- UEMUSHORT *e;
-{
- UEMUSHORT yi[NI];
- int k;
+ The constructions here are taken from Tables 5-1 and 5-2 of the
+ TMS320C4x User's Guide wherein step-by-step instructions for
+ conversion from IEEE are presented. That's close enough to our
+ internal representation so as to make things easy.
- 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);
-}
+ See http://www-s.ti.com/sc/psheets/spru063c/spru063c.pdf */
-/* Convert target computer signed 64-bit integer to e-type. */
+static void encode_c4x_single PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_c4x_single PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+static void encode_c4x_extended PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_c4x_extended PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
static void
-ditoe (di, e)
- const UEMUSHORT *di; /* Address of the 64-bit int. */
- UEMUSHORT *e;
-{
- unsigned EMULONG acc;
- UEMUSHORT yi[NI];
- UEMUSHORT carry;
- int k, sign;
+encode_c4x_single (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
+{
+ unsigned long image, exp, sig;
+
+ switch (r->class)
+ {
+ case rvc_zero:
+ exp = -128;
+ sig = 0;
+ break;
- 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--)
+ case rvc_inf:
+ case rvc_nan:
+ exp = 127;
+ sig = 0x800000 - r->sign;
+ break;
+
+ case rvc_normal:
+ exp = r->exp - 1;
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
+ if (r->sign)
{
- acc = (unsigned EMULONG) (~yi[k] & 0xffff) + carry;
- yi[k] = acc;
- carry = 0;
- if (acc & 0x10000)
- carry = 1;
+ if (sig)
+ sig = -sig;
+ else
+ exp--;
+ sig |= 0x800000;
}
- }
- 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);
-}
+ break;
+ default:
+ abort ();
+ }
-/* Convert e-type to unsigned 64-bit int. */
+ image = ((exp & 0xff) << 24) | (sig & 0xffffff);
+ buf[0] = image;
+}
static void
-etoudi (x, i)
- const UEMUSHORT *x;
- UEMUSHORT *i;
+decode_c4x_single (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT xi[NI];
- int j, k;
+ unsigned long image = buf[0];
+ unsigned long sig;
+ int exp, sf;
- emovi (x, xi);
- if (xi[0])
- {
- xi[M] = 0;
- goto noshift;
- }
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0;
- return;
- }
- if (k > 64)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0xffff;
- if (extra_warnings)
- warning ("overflow on truncation to integer");
- return;
- }
- if (k > 16)
+ exp = (((image >> 24) & 0xff) ^ 0x80) - 0x80;
+ sf = ((image & 0xffffff) ^ 0x800000) - 0x800000;
+
+ memset (r, 0, sizeof (*r));
+
+ if (exp != -128)
{
- /* 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
+ r->class = rvc_normal;
+
+ sig = sf & 0x7fffff;
+ if (sf < 0)
{
- eshup6 (xi);
- if (WORDS_BIG_ENDIAN)
- *i++ = xi[M];
+ r->sign = 1;
+ if (sig)
+ sig = -sig;
else
- *i-- = xi[M];
+ exp++;
}
- while ((k -= 16) > 0);
- }
- else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
+ sig = (sig << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
-noshift:
-
- if (WORDS_BIG_ENDIAN)
- {
- i += 3;
- *i-- = xi[M];
- *i-- = 0;
- *i-- = 0;
- *i = 0;
- }
- else
- {
- *i++ = xi[M];
- *i++ = 0;
- *i++ = 0;
- *i = 0;
- }
+ r->exp = exp + 1;
+ r->sig[SIGSZ-1] = sig;
}
}
+static void
+encode_c4x_extended (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
+{
+ unsigned long exp, sig;
+
+ switch (r->class)
+ {
+ case rvc_zero:
+ exp = -128;
+ sig = 0;
+ break;
-/* Convert e-type to signed 64-bit int. */
+ case rvc_inf:
+ case rvc_nan:
+ exp = 127;
+ sig = 0x80000000 - r->sign;
+ break;
-static void
-etodi (x, i)
- const UEMUSHORT *x;
- UEMUSHORT *i;
-{
- 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)
- {
- for (j = 0; j < 4; j++)
- *i++ = 0xffff;
- if (extra_warnings)
- warning ("overflow on truncation to integer");
- return;
- }
- isave = i;
- 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);
- if (j == 0)
- j = 16;
- eshift (xi, j);
- if (WORDS_BIG_ENDIAN)
- *i++ = xi[M];
- else
- {
- i += 3;
- *i-- = xi[M];
- }
- k -= j;
- do
- {
- eshup6 (xi);
- if (WORDS_BIG_ENDIAN)
- *i++ = xi[M];
- else
- *i-- = xi[M];
- }
- while ((k -= 16) > 0);
- }
- else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
+ case rvc_normal:
+ exp = r->exp - 1;
- 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])
- {
- carry = 0;
- if (WORDS_BIG_ENDIAN)
- isave += 3;
- for (k = 0; k < 4; k++)
+ sig = r->sig[SIGSZ-1];
+ if (HOST_BITS_PER_LONG == 64)
+ sig = sig >> 1 >> 31;
+ sig &= 0x7fffffff;
+
+ if (r->sign)
{
- acc = (unsigned EMULONG) (~(*isave) & 0xffff) + carry;
- if (WORDS_BIG_ENDIAN)
- *isave-- = acc;
+ if (sig)
+ sig = -sig;
else
- *isave++ = acc;
- carry = 0;
- if (acc & 0x10000)
- carry = 1;
+ exp--;
+ sig |= 0x80000000;
}
- }
-}
-
+ break;
-/* Longhand square root routine. */
+ default:
+ abort ();
+ }
+ exp = (exp & 0xff) << 24;
+ sig &= 0xffffffff;
-static int esqinited = 0;
-static unsigned short sqrndbit[NI];
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = exp, buf[1] = sig;
+ else
+ buf[0] = sig, buf[0] = exp;
+}
static void
-esqrt (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
+decode_c4x_extended (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
{
- UEMUSHORT temp[NI], num[NI], sq[NI], xx[NI];
- EMULONG m, exp;
- int i, j, k, n, nlups;
+ unsigned long sig;
+ int exp, sf;
- if (esqinited == 0)
- {
- ecleaz (sqrndbit);
- sqrndbit[NI - 2] = 1;
- esqinited = 1;
- }
- /* Check for arg <= 0 */
- i = ecmp (x, ezero);
- if (i <= 0)
- {
- if (i == -1)
- {
- mtherr ("esqrt", DOMAIN);
- eclear (y);
- }
- else
- emov (x, y);
- return;
- }
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ exp = buf[0], sf = buf[1];
+ else
+ sf = buf[0], exp = buf[1];
-#ifdef INFINITY
- if (eisinf (x))
- {
- eclear (y);
- einfin (y);
- 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);
- }
+ exp = (((exp >> 24) & 0xff) & 0x80) - 0x80;
+ sf = ((sf & 0xffffffff) ^ 0x80000000) - 0x80000000;
- ecleaz (sq);
- ecleaz (num);
- n = 8; /* get 8 bits of result per inner loop */
- nlups = rndprc;
- j = 0;
+ memset (r, 0, sizeof (*r));
- while (nlups > 0)
+ if (exp != -128)
{
- /* 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++)
+ r->class = rvc_normal;
+
+ sig = sf & 0x7fffffff;
+ if (sf < 0)
{
- /* 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;
- }
+ r->sign = 1;
+ if (sig)
+ sig = -sig;
+ else
+ exp++;
}
- nlups -= n;
- j += 1;
- }
+ if (HOST_BITS_PER_LONG == 64)
+ sig = sig << 1 << 31;
+ sig |= SIG_MSB;
- /* Adjust for extra, roundoff loop done. */
- exp += (NBITS - 1) - rndprc;
+ r->exp = exp + 1;
+ r->sig[SIGSZ-1] = sig;
+ }
+}
- /* Sticky bit = 1 if the remainder is nonzero. */
- k = 0;
- for (i = 3; i < NI; i++)
- k |= (int) num[i];
+const struct real_format c4x_single_format =
+ {
+ encode_c4x_single,
+ decode_c4x_single,
+ 2,
+ 1,
+ 24,
+ -126,
+ 128,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+const struct real_format c4x_extended_format =
+ {
+ encode_c4x_extended,
+ decode_c4x_extended,
+ 2,
+ 1,
+ 32,
+ -126,
+ 128,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
- /* 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. */
+/* 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. */
-unsigned int
-significand_size (mode)
- enum machine_mode mode;
+static void encode_internal PARAMS ((const struct real_format *fmt,
+ long *, const REAL_VALUE_TYPE *));
+static void decode_internal PARAMS ((const struct real_format *,
+ REAL_VALUE_TYPE *, const long *));
+
+static void
+encode_internal (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const REAL_VALUE_TYPE *r;
{
+ memcpy (buf, r, sizeof (*r));
+}
-/* Don't test the modes, but their sizes, lest this
- code won't work for BITS_PER_UNIT != 8 . */
+static void
+decode_internal (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ REAL_VALUE_TYPE *r;
+ const long *buf;
+{
+ memcpy (r, buf, sizeof (*r));
+}
-switch (GET_MODE_BITSIZE (mode))
+const struct real_format real_internal_format =
{
- case 32:
-
-#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
- return 56;
-#endif
-
- return 24;
-
- case 64:
-#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
- return 53;
-#else
-#if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
- return 56;
-#else
-#if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
- return 56;
-#else
-#if TARGET_FLOAT_FORMAT == C4X_FLOAT_FORMAT
- return 56;
-#else
- abort ();
-#endif
-#endif
-#endif
-#endif
-
- case 96:
- return 64;
+ encode_internal,
+ decode_internal,
+ 2,
+ 1,
+ SIGNIFICAND_BITS - 2,
+ -MAX_EXP,
+ MAX_EXP,
+ true,
+ true,
+ false,
+ true,
+ true
+ };
+
+/* Set up default mode to format mapping for IEEE. Everyone else has
+ to set these values in OVERRIDE_OPTIONS. */
- case 128:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- return 113;
-#else
- return 64;
-#endif
+const struct real_format *real_format_for_mode[TFmode - QFmode + 1] =
+{
+ NULL, /* QFmode */
+ NULL, /* HFmode */
+ NULL, /* TQFmode */
+ &ieee_single_format, /* SFmode */
+ &ieee_double_format, /* DFmode */
- default:
- abort ();
- }
-}
+ /* We explicitly don't handle XFmode. There are two formats,
+ pretty much equally common. Choose one in OVERRIDE_OPTIONS. */
+ NULL, /* XFmode */
+ &ieee_quad_format /* TFmode */
+};
OpenPOWER on IntegriCloud