summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/ChangeLog4
-rw-r--r--contrib/paranoia.cc2698
-rw-r--r--gcc/ChangeLog31
-rw-r--r--gcc/Makefile.in11
-rw-r--r--gcc/builtins.c5
-rw-r--r--gcc/c-common.c6
-rw-r--r--gcc/c-lex.c9
-rw-r--r--gcc/config/alpha/alpha.c77
-rw-r--r--gcc/config/alpha/alpha.h5
-rw-r--r--gcc/config/ia64/ia64.md20
-rw-r--r--gcc/config/m68hc11/m68hc11.h5
-rw-r--r--gcc/config/m88k/m88k.h8
-rw-r--r--gcc/config/vax/vax.c69
-rw-r--r--gcc/config/vax/vax.h26
-rw-r--r--gcc/cse.c23
-rw-r--r--gcc/defaults.h11
-rw-r--r--gcc/doc/tm.texi23
-rw-r--r--gcc/emit-rtl.c16
-rw-r--r--gcc/f/ChangeLog8
-rw-r--r--gcc/f/target.c16
-rw-r--r--gcc/f/target.h50
-rw-r--r--gcc/fold-const.c11
-rw-r--r--gcc/java/ChangeLog7
-rw-r--r--gcc/java/jcf-parse.c75
-rw-r--r--gcc/java/jcf-write.c23
-rw-r--r--gcc/java/lex.c2
-rw-r--r--gcc/loop.c11
-rw-r--r--gcc/optabs.c8
-rw-r--r--gcc/real.c8916
-rw-r--r--gcc/real.h363
-rw-r--r--gcc/simplify-rtx.c4
-rw-r--r--gcc/toplev.c4
-rw-r--r--gcc/tree.c7
33 files changed, 6099 insertions, 6453 deletions
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index a4bf4316263..27ad70c2e09 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,7 @@
+2002-09-16 Richard Henderson <rth@redhat.com>
+
+ * paranoia.cc: New file.
+
2002-09-04 Richard Henderson <rth@redhat.com>
* enquire.c: Remove.
diff --git a/contrib/paranoia.cc b/contrib/paranoia.cc
new file mode 100644
index 00000000000..0b87da9d690
--- /dev/null
+++ b/contrib/paranoia.cc
@@ -0,0 +1,2698 @@
+/* A C version of Kahan's Floating Point Test "Paranoia"
+
+Thos Sumner, UCSF, Feb. 1985
+David Gay, BTL, Jan. 1986
+
+This is a rewrite from the Pascal version by
+
+B. A. Wichmann, 18 Jan. 1985
+
+(and does NOT exhibit good C programming style).
+
+Adjusted to use Standard C headers 19 Jan. 1992 (dmg);
+
+(C) Apr 19 1983 in BASIC version by:
+Professor W. M. Kahan,
+567 Evans Hall
+Electrical Engineering & Computer Science Dept.
+University of California
+Berkeley, California 94720
+USA
+
+converted to Pascal by:
+B. A. Wichmann
+National Physical Laboratory
+Teddington Middx
+TW11 OLW
+UK
+
+converted to C by:
+
+David M. Gay and Thos Sumner
+AT&T Bell Labs Computer Center, Rm. U-76
+600 Mountain Avenue University of California
+Murray Hill, NJ 07974 San Francisco, CA 94143
+USA USA
+
+with simultaneous corrections to the Pascal source (reflected
+in the Pascal source available over netlib).
+[A couple of bug fixes from dgh = sun!dhough incorporated 31 July 1986.]
+
+Reports of results on various systems from all the versions
+of Paranoia are being collected by Richard Karpinski at the
+same address as Thos Sumner. This includes sample outputs,
+bug reports, and criticisms.
+
+You may copy this program freely if you acknowledge its source.
+Comments on the Pascal version to NPL, please.
+
+The following is from the introductory commentary from Wichmann's work:
+
+The BASIC program of Kahan is written in Microsoft BASIC using many
+facilities which have no exact analogy in Pascal. The Pascal
+version below cannot therefore be exactly the same. Rather than be
+a minimal transcription of the BASIC program, the Pascal coding
+follows the conventional style of block-structured languages. Hence
+the Pascal version could be useful in producing versions in other
+structured languages.
+
+Rather than use identifiers of minimal length (which therefore have
+little mnemonic significance), the Pascal version uses meaningful
+identifiers as follows [Note: A few changes have been made for C]:
+
+
+BASIC C BASIC C BASIC C
+
+A J S StickyBit
+A1 AInverse J0 NoErrors T
+B Radix [Failure] T0 Underflow
+B1 BInverse J1 NoErrors T2 ThirtyTwo
+B2 RadixD2 [SeriousDefect] T5 OneAndHalf
+B9 BMinusU2 J2 NoErrors T7 TwentySeven
+C [Defect] T8 TwoForty
+C1 CInverse J3 NoErrors U OneUlp
+D [Flaw] U0 UnderflowThreshold
+D4 FourD K PageNo U1
+E0 L Milestone U2
+E1 M V
+E2 Exp2 N V0
+E3 N1 V8
+E5 MinSqEr O Zero V9
+E6 SqEr O1 One W
+E7 MaxSqEr O2 Two X
+E8 O3 Three X1
+E9 O4 Four X8
+F1 MinusOne O5 Five X9 Random1
+F2 Half O8 Eight Y
+F3 Third O9 Nine Y1
+F6 P Precision Y2
+F9 Q Y9 Random2
+G1 GMult Q8 Z
+G2 GDiv Q9 Z0 PseudoZero
+G3 GAddSub R Z1
+H R1 RMult Z2
+H1 HInverse R2 RDiv Z9
+I R3 RAddSub
+IO NoTrials R4 RSqrt
+I3 IEEE R9 Random9
+
+SqRWrng
+
+All the variables in BASIC are true variables and in consequence,
+the program is more difficult to follow since the "constants" must
+be determined (the glossary is very helpful). The Pascal version
+uses Real constants, but checks are added to ensure that the values
+are correctly converted by the compiler.
+
+The major textual change to the Pascal version apart from the
+identifiersis that named procedures are used, inserting parameters
+wherehelpful. New procedures are also introduced. The
+correspondence is as follows:
+
+
+BASIC Pascal
+lines
+
+90- 140 Pause
+170- 250 Instructions
+380- 460 Heading
+480- 670 Characteristics
+690- 870 History
+2940-2950 Random
+3710-3740 NewD
+4040-4080 DoesYequalX
+4090-4110 PrintIfNPositive
+4640-4850 TestPartialUnderflow
+
+*/
+
+ /* This version of paranoia has been modified to work with GCC's internal
+ software floating point emulation library, as a sanity check of same.
+
+ I'm doing this in C++ so that I can do operator overloading and not
+ have to modify so damned much of the existing code. */
+
+ extern "C" {
+#include <stdio.h>
+#include <stddef.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+#include <float.h>
+
+ /* This part is made all the more awful because many gcc headers are
+ not prepared at all to be parsed as C++. The biggest stickler
+ here is const structure members. So we include exactly the pieces
+ that we need. */
+
+#define GTY(x)
+
+#include "ansidecl.h"
+#include "auto-host.h"
+#include "hwint.h"
+
+#undef EXTRA_MODES_FILE
+
+ struct rtx_def;
+ typedef struct rtx_def *rtx;
+ struct rtvec_def;
+ typedef struct rtvec_def *rtvec;
+ union tree_node;
+ typedef union tree_node *tree;
+
+#define DEFTREECODE(SYM, STRING, TYPE, NARGS) SYM,
+ enum tree_code {
+#include "tree.def"
+ LAST_AND_UNUSED_TREE_CODE
+ };
+#undef DEFTREECODE
+
+#include "real.h"
+ }
+
+/* We never produce signals from the library. Thus setjmp need do nothing. */
+#undef setjmp
+#define setjmp(x) (0)
+
+static bool verbose = false;
+static int verbose_index = 0;
+
+/* ====================================================================== */
+/* The implementation of the abstract floating point class based on gcc's
+ real.c. I.e. the object of this excersize. Templated so that we can
+ all fp sizes. */
+
+template<int SIZE, enum machine_mode MODE>
+class real_c_float
+{
+ private:
+ long image[SIZE / 32];
+
+ void from_long(long);
+ void from_str(const char *);
+ void binop(int code, const real_c_float&);
+ void unop(int code);
+ bool cmp(int code, const real_c_float&) const;
+
+ public:
+ real_c_float()
+ { }
+ real_c_float(long l)
+ { from_long(l); }
+ real_c_float(const char *s)
+ { from_str(s); }
+ real_c_float(const real_c_float &b)
+ { memcpy(image, b.image, sizeof(image)); }
+
+ const real_c_float& operator= (long l)
+ { from_long(l); return *this; }
+ const real_c_float& operator= (const char *s)
+ { from_str(s); return *this; }
+ const real_c_float& operator= (const real_c_float &b)
+ { memcpy(image, b.image, sizeof(image)); return *this; }
+
+ const real_c_float& operator+= (const real_c_float &b)
+ { binop(PLUS_EXPR, b); return *this; }
+ const real_c_float& operator-= (const real_c_float &b)
+ { binop(MINUS_EXPR, b); return *this; }
+ const real_c_float& operator*= (const real_c_float &b)
+ { binop(MULT_EXPR, b); return *this; }
+ const real_c_float& operator/= (const real_c_float &b)
+ { binop(RDIV_EXPR, b); return *this; }
+
+ real_c_float operator- () const
+ { real_c_float r(*this); r.unop(NEGATE_EXPR); return r; }
+ real_c_float abs () const
+ { real_c_float r(*this); r.unop(ABS_EXPR); return r; }
+
+ bool operator < (const real_c_float &b) const { return cmp(LT_EXPR, b); }
+ bool operator <= (const real_c_float &b) const { return cmp(LE_EXPR, b); }
+ bool operator == (const real_c_float &b) const { return cmp(EQ_EXPR, b); }
+ bool operator != (const real_c_float &b) const { return cmp(NE_EXPR, b); }
+ bool operator >= (const real_c_float &b) const { return cmp(GE_EXPR, b); }
+ bool operator > (const real_c_float &b) const { return cmp(GT_EXPR, b); }
+
+ const char * str () const;
+ const char * hex () const;
+ long integer () const;
+ int exp () const;
+ void ldexp (int);
+};
+
+template<int SIZE, enum machine_mode MODE>
+void
+real_c_float<SIZE, MODE>::from_long (long l)
+{
+ REAL_VALUE_TYPE f;
+
+ real_from_integer (&f, MODE, l, l < 0 ? -1 : 0, 0);
+ real_to_target (image, &f, MODE);
+}
+
+template<int SIZE, enum machine_mode MODE>
+void
+real_c_float<SIZE, MODE>::from_str (const char *s)
+{
+ REAL_VALUE_TYPE f;
+ char *p = s;
+
+ if (*p == '-' || *p == '+')
+ p++;
+ if (strcasecmp(p, "inf") == 0)
+ {
+ real_inf (&f);
+ if (*s == '-')
+ real_arithmetic (&f, NEGATE_EXPR, &f, NULL);
+ }
+ else if (strcasecmp(p, "nan") == 0)
+ real_nan (&f, "", 1, MODE);
+ else
+ real_from_string (&f, s);
+
+ real_to_target (image, &f, MODE);
+}
+
+template<int SIZE, enum machine_mode MODE>
+void
+real_c_float<SIZE, MODE>::binop (int code, const real_c_float &b)
+{
+ REAL_VALUE_TYPE ai, bi, ri;
+
+ real_from_target (&ai, image, MODE);
+ real_from_target (&bi, b.image, MODE);
+ real_arithmetic (&ri, code, &ai, &bi);
+ real_to_target (image, &ri, MODE);
+
+ if (verbose)
+ {
+ char ab[64], bb[64], rb[64];
+ const int digits = int(SIZE / 4);
+ char symbol_for_code;
+
+ real_from_target (&ri, image, MODE);
+ real_to_hexadecimal (ab, &ai, digits);
+ real_to_hexadecimal (bb, &bi, digits);
+ real_to_hexadecimal (rb, &ri, digits);
+
+ switch (code)
+ {
+ case PLUS_EXPR:
+ symbol_for_code = '+';
+ break;
+ case MINUS_EXPR:
+ symbol_for_code = '-';
+ break;
+ case MULT_EXPR:
+ symbol_for_code = '*';
+ break;
+ case RDIV_EXPR:
+ symbol_for_code = '/';
+ break;
+ default:
+ abort ();
+ }
+
+ fprintf (stderr, "%6d: %s %c %s = %s\n", verbose_index++,
+ ab, symbol_for_code, bb, rb);
+ }
+}
+
+template<int SIZE, enum machine_mode MODE>
+void
+real_c_float<SIZE, MODE>::unop (int code)
+{
+ REAL_VALUE_TYPE ai, ri;
+
+ real_from_target (&ai, image, MODE);
+ real_arithmetic (&ri, code, &ai, NULL);
+ real_to_target (image, &ri, MODE);
+
+ if (verbose)
+ {
+ char ab[64], rb[64];
+ const int digits = int(SIZE / 4);
+ const char *symbol_for_code;
+
+ real_from_target (&ri, image, MODE);
+ real_to_hexadecimal (ab, &ai, digits);
+ real_to_hexadecimal (rb, &ri, digits);
+
+ switch (code)
+ {
+ case NEGATE_EXPR:
+ symbol_for_code = "-";
+ break;
+ case ABS_EXPR:
+ symbol_for_code = "abs ";
+ break;
+ default:
+ abort ();
+ }
+
+ fprintf (stderr, "%6d: %s%s = %s\n", verbose_index++,
+ symbol_for_code, ab, rb);
+ }
+}
+
+template<int SIZE, enum machine_mode MODE>
+bool
+real_c_float<SIZE, MODE>::cmp (int code, const real_c_float &b) const
+{
+ REAL_VALUE_TYPE ai, bi;
+ bool ret;
+
+ real_from_target (&ai, image, MODE);
+ real_from_target (&bi, b.image, MODE);
+ ret = real_compare (code, &ai, &bi);
+
+ if (verbose)
+ {
+ char ab[64], bb[64];
+ const int digits = int(SIZE / 4);
+ const char *symbol_for_code;
+
+ real_to_hexadecimal (ab, &ai, digits);
+ real_to_hexadecimal (bb, &bi, digits);
+
+ switch (code)
+ {
+ case LT_EXPR:
+ symbol_for_code = "<";
+ break;
+ case LE_EXPR:
+ symbol_for_code = "<=";
+ break;
+ case EQ_EXPR:
+ symbol_for_code = "==";
+ break;
+ case NE_EXPR:
+ symbol_for_code = "!=";
+ break;
+ case GE_EXPR:
+ symbol_for_code = ">=";
+ break;
+ case GT_EXPR:
+ symbol_for_code = ">";
+ break;
+ default:
+ abort ();
+ }
+
+ fprintf (stderr, "%6d: %s %s %s = %s\n", verbose_index++,
+ ab, symbol_for_code, bb, (ret ? "true" : "false"));
+ }
+
+ return ret;
+}
+
+template<int SIZE, enum machine_mode MODE>
+const char *
+real_c_float<SIZE, MODE>::str() const
+{
+ REAL_VALUE_TYPE f;
+ const int digits = int(SIZE * .30102999566398119521 + 1);
+
+ real_from_target (&f, image, MODE);
+ char *buf = new char[digits + 10];
+ real_to_decimal (buf, &f, digits);
+
+ return buf;
+}
+
+template<int SIZE, enum machine_mode MODE>
+const char *
+real_c_float<SIZE, MODE>::hex() const
+{
+ REAL_VALUE_TYPE f;
+ const int digits = int(SIZE / 4);
+
+ real_from_target (&f, image, MODE);
+ char *buf = new char[digits + 10];
+ real_to_hexadecimal (buf, &f, digits);
+
+ return buf;
+}
+
+template<int SIZE, enum machine_mode MODE>
+long
+real_c_float<SIZE, MODE>::integer() const
+{
+ REAL_VALUE_TYPE f;
+ real_from_target (&f, image, MODE);
+ return real_to_integer (&f);
+}
+
+template<int SIZE, enum machine_mode MODE>
+int
+real_c_float<SIZE, MODE>::exp() const
+{
+ REAL_VALUE_TYPE f;
+ real_from_target (&f, image, MODE);
+ return real_exponent (&f);
+}
+
+template<int SIZE, enum machine_mode MODE>
+void
+real_c_float<SIZE, MODE>::ldexp (int exp)
+{
+ REAL_VALUE_TYPE ai;
+
+ real_from_target (&ai, image, MODE);
+ real_ldexp (&ai, &ai, exp);
+ real_to_target (image, &ai, MODE);
+}
+
+/* ====================================================================== */
+/* An implementation of the abstract floating point class that uses native
+ arithmetic. Exists for reference and debugging. */
+
+template<typename T>
+class native_float
+{
+ private:
+ // Force intermediate results back to memory.
+ volatile T image;
+
+ static T from_str (const char *);
+ static T do_abs (T);
+ static T verbose_binop (T, char, T, T);
+ static T verbose_unop (const char *, T, T);
+ static bool verbose_cmp (T, const char *, T, bool);
+
+ public:
+ native_float()
+ { }
+ native_float(long l)
+ { image = l; }
+ native_float(const char *s)
+ { image = from_str(s); }
+ native_float(const native_float &b)
+ { image = b.image; }
+
+ const native_float& operator= (long l)
+ { image = l; return *this; }
+ const native_float& operator= (const char *s)
+ { image = from_str(s); return *this; }
+ const native_float& operator= (const native_float &b)
+ { image = b.image; return *this; }
+
+ const native_float& operator+= (const native_float &b)
+ {
+ image = verbose_binop(image, '+', b.image, image + b.image);
+ return *this;
+ }
+ const native_float& operator-= (const native_float &b)
+ {
+ image = verbose_binop(image, '-', b.image, image - b.image);
+ return *this;
+ }
+ const native_float& operator*= (const native_float &b)
+ {
+ image = verbose_binop(image, '*', b.image, image * b.image);
+ return *this;
+ }
+ const native_float& operator/= (const native_float &b)
+ {
+ image = verbose_binop(image, '/', b.image, image / b.image);
+ return *this;
+ }
+
+ native_float operator- () const
+ {
+ native_float r;
+ r.image = verbose_unop("-", image, -image);
+ return r;
+ }
+ native_float abs () const
+ {
+ native_float r;
+ r.image = verbose_unop("abs ", image, do_abs(image));
+ return r;
+ }
+
+ bool operator < (const native_float &b) const
+ { return verbose_cmp(image, "<", b.image, image < b.image); }
+ bool operator <= (const native_float &b) const
+ { return verbose_cmp(image, "<=", b.image, image <= b.image); }
+ bool operator == (const native_float &b) const
+ { return verbose_cmp(image, "==", b.image, image == b.image); }
+ bool operator != (const native_float &b) const
+ { return verbose_cmp(image, "!=", b.image, image != b.image); }
+ bool operator >= (const native_float &b) const
+ { return verbose_cmp(image, ">=", b.image, image >= b.image); }
+ bool operator > (const native_float &b) const
+ { return verbose_cmp(image, ">", b.image, image > b.image); }
+
+ const char * str () const;
+ const char * hex () const;
+ long integer () const
+ { return long(image); }
+ int exp () const;
+ void ldexp (int);
+};
+
+template<typename T>
+inline T
+native_float<T>::from_str (const char *s)
+{
+ return strtold (s, NULL);
+}
+
+template<>
+inline float
+native_float<float>::from_str (const char *s)
+{
+ return strtof (s, NULL);
+}
+
+template<>
+inline double
+native_float<double>::from_str (const char *s)
+{
+ return strtod (s, NULL);
+}
+
+template<typename T>
+inline T
+native_float<T>::do_abs (T image)
+{
+ return fabsl (image);
+}
+
+template<>
+inline float
+native_float<float>::do_abs (float image)
+{
+ return fabsf (image);
+}
+
+template<>
+inline double
+native_float<double>::do_abs (double image)
+{
+ return fabs (image);
+}
+
+template<typename T>
+T
+native_float<T>::verbose_binop (T a, char symbol, T b, T r)
+{
+ if (verbose)
+ {
+ const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
+#ifdef NO_LONG_DOUBLE
+ fprintf (stderr, "%6d: %.*a %c %.*a = %.*a\n", verbose_index++,
+ digits, (double)a, symbol,
+ digits, (double)b, digits, (double)r);
+#else
+ fprintf (stderr, "%6d: %.*La %c %.*La = %.*La\n", verbose_index++,
+ digits, (long double)a, symbol,
+ digits, (long double)b, digits, (long double)r);
+#endif
+ }
+ return r;
+}
+
+template<typename T>
+T
+native_float<T>::verbose_unop (const char *symbol, T a, T r)
+{
+ if (verbose)
+ {
+ const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
+#ifdef NO_LONG_DOUBLE
+ fprintf (stderr, "%6d: %s%.*a = %.*a\n", verbose_index++,
+ symbol, digits, (double)a, digits, (double)r);
+#else
+ fprintf (stderr, "%6d: %s%.*La = %.*La\n", verbose_index++,
+ symbol, digits, (long double)a, digits, (long double)r);
+#endif
+ }
+ return r;
+}
+
+template<typename T>
+bool
+native_float<T>::verbose_cmp (T a, const char *symbol, T b, bool r)
+{
+ if (verbose)
+ {
+ const int digits = int(sizeof(T) * CHAR_BIT / 4) - 1;
+#ifndef NO_LONG_DOUBLE
+ fprintf (stderr, "%6d: %.*a %s %.*a = %s\n", verbose_index++,
+ digits, (double)a, symbol,
+ digits, (double)b, (r ? "true" : "false"));
+#else
+ fprintf (stderr, "%6d: %.*La %s %.*La = %s\n", verbose_index++,
+ digits, (long double)a, symbol,
+ digits, (long double)b, (r ? "true" : "false"));
+#endif
+ }
+ return r;
+}
+
+template<typename T>
+const char *
+native_float<T>::str() const
+{
+ char *buf = new char[50];
+ const int digits = int(sizeof(T) * CHAR_BIT * .30102999566398119521 + 1);
+#ifndef NO_LONG_DOUBLE
+ sprintf (buf, "%.*e", digits - 1, (double) image);
+#else
+ sprintf (buf, "%.*Le", digits - 1, (long double) image);
+#endif
+ return buf;
+}
+
+template<typename T>
+const char *
+native_float<T>::hex() const
+{
+ char *buf = new char[50];
+ const int digits = int(sizeof(T) * CHAR_BIT / 4);
+#ifndef NO_LONG_DOUBLE
+ sprintf (buf, "%.*a", digits - 1, (double) image);
+#else
+ sprintf (buf, "%.*La", digits - 1, (long double) image);
+#endif
+ return buf;
+}
+
+template<typename T>
+int
+native_float<T>::exp() const
+{
+ int e;
+ frexp (image, &e);
+ return e;
+}
+
+template<typename T>
+void
+native_float<T>::ldexp (int exp)
+{
+ image = ldexpl (image, exp);
+}
+
+template<>
+void
+native_float<float>::ldexp (int exp)
+{
+ image = ldexpf (image, exp);
+}
+
+template<>
+void
+native_float<double>::ldexp (int exp)
+{
+ image = ::ldexp (image, exp);
+}
+
+/* ====================================================================== */
+/* Some libm routines that Paranoia expects to be available. */
+
+template<typename FLOAT>
+inline FLOAT
+FABS (const FLOAT &f)
+{
+ return f.abs();
+}
+
+template<typename FLOAT, typename RHS>
+inline FLOAT
+operator+ (const FLOAT &a, const RHS &b)
+{
+ return FLOAT(a) += FLOAT(b);
+}
+
+template<typename FLOAT, typename RHS>
+inline FLOAT
+operator- (const FLOAT &a, const RHS &b)
+{
+ return FLOAT(a) -= FLOAT(b);
+}
+
+template<typename FLOAT, typename RHS>
+inline FLOAT
+operator* (const FLOAT &a, const RHS &b)
+{
+ return FLOAT(a) *= FLOAT(b);
+}
+
+template<typename FLOAT, typename RHS>
+inline FLOAT
+operator/ (const FLOAT &a, const RHS &b)
+{
+ return FLOAT(a) /= FLOAT(b);
+}
+
+template<typename FLOAT>
+FLOAT
+FLOOR (const FLOAT &f)
+{
+ /* ??? This is only correct when F is representable as an integer. */
+ long i = f.integer();
+ FLOAT r;
+
+ r = i;
+ if (i < 0 && f != r)
+ r = i - 1;
+
+ return r;
+}
+
+template<typename FLOAT>
+FLOAT
+SQRT (const FLOAT &f)
+{
+#if 0
+ FLOAT zero = long(0);
+ FLOAT two = 2;
+ FLOAT one = 1;
+ FLOAT diff, diff2;
+ FLOAT z, t;
+
+ if (f == zero)
+ return zero;
+ if (f < zero)
+ return zero / zero;
+ if (f == one)
+ return f;
+
+ z = f;
+ z.ldexp (-f.exp() / 2);
+
+ diff2 = FABS (z * z - f);
+ if (diff2 > zero)
+ while (1)
+ {
+ t = (f / (two * z)) + (z / two);
+ diff = FABS (t * t - f);
+ if (diff >= diff2)
+ break;
+ z = t;
+ diff2 = diff;
+ }
+
+ return z;
+#elif defined(NO_LONG_DOUBLE)
+ double d;
+ char buf[64];
+
+ d = strtod (f.hex(), NULL);
+ d = sqrt (d);
+ sprintf(buf, "%.35a", d);
+
+ return FLOAT(buf);
+#else
+ long double ld;
+ char buf[64];
+
+ ld = strtold (f.hex(), NULL);
+ ld = sqrtl (ld);
+ sprintf(buf, "%.35La", ld);
+
+ return FLOAT(buf);
+#endif
+}
+
+template<typename FLOAT>
+FLOAT
+LOG (FLOAT x)
+{
+#if 0
+ FLOAT zero = long(0);
+ FLOAT one = 1;
+
+ if (x <= zero)
+ return zero / zero;
+ if (x == one)
+ return zero;
+
+ int exp = x.exp() - 1;
+ x.ldexp(-exp);
+
+ FLOAT xm1 = x - one;
+ FLOAT y = xm1;
+ long n = 2;
+
+ FLOAT sum = xm1;
+ while (1)
+ {
+ y *= xm1;
+ FLOAT term = y / FLOAT (n);
+ FLOAT next = sum + term;
+ if (next == sum)
+ break;
+ sum = next;
+ if (++n == 1000)
+ break;
+ }
+
+ if (exp)
+ sum += FLOAT (exp) * FLOAT(".69314718055994530941");
+
+ return sum;
+#elif defined (NO_LONG_DOUBLE)
+ double d;
+ char buf[64];
+
+ d = strtod (x.hex(), NULL);
+ d = log (d);
+ sprintf(buf, "%.35a", d);
+
+ return FLOAT(buf);
+#else
+ long double ld;
+ char buf[64];
+
+ ld = strtold (x.hex(), NULL);
+ ld = logl (ld);
+ sprintf(buf, "%.35La", ld);
+
+ return FLOAT(buf);
+#endif
+}
+
+template<typename FLOAT>
+FLOAT
+EXP (const FLOAT &x)
+{
+ /* Cheat. */
+#ifdef NO_LONG_DOUBLE
+ double d;
+ char buf[64];
+
+ d = strtod (x.hex(), NULL);
+ d = exp (d);
+ sprintf(buf, "%.35a", d);
+
+ return FLOAT(buf);
+#else
+ long double ld;
+ char buf[64];
+
+ ld = strtold (x.hex(), NULL);
+ ld = expl (ld);
+ sprintf(buf, "%.35La", ld);
+
+ return FLOAT(buf);
+#endif
+}
+
+template<typename FLOAT>
+FLOAT
+POW (const FLOAT &base, const FLOAT &exp)
+{
+ /* Cheat. */
+#ifdef NO_LONG_DOUBLE
+ double d1, d2;
+ char buf[64];
+
+ d1 = strtod (base.hex(), NULL);
+ d2 = strtod (exp.hex(), NULL);
+ d1 = pow (d1, d2);
+ sprintf(buf, "%.35a", d1);
+
+ return FLOAT(buf);
+#else
+ long double ld1, ld2;
+ char buf[64];
+
+ ld1 = strtold (base.hex(), NULL);
+ ld2 = strtold (exp.hex(), NULL);
+ ld1 = powl (ld1, ld2);
+ sprintf(buf, "%.35La", ld1);
+
+ return FLOAT(buf);
+#endif
+}
+
+/* ====================================================================== */
+/* Real Paranoia begins again here. We wrap the thing in a template so
+ that we can instantiate it for each floating point type we care for. */
+
+int NoTrials = 20; /*Number of tests for commutativity. */
+bool do_pause = false;
+
+enum Guard { No, Yes };
+enum Rounding { Other, Rounded, Chopped };
+enum Class { Failure, Serious, Defect, Flaw };
+
+template<typename FLOAT>
+struct Paranoia
+{
+ FLOAT Radix, BInvrse, RadixD2, BMinusU2;
+
+ /* Small floating point constants. */
+ FLOAT Zero;
+ FLOAT Half;
+ FLOAT One;
+ FLOAT Two;
+ FLOAT Three;
+ FLOAT Four;
+ FLOAT Five;
+ FLOAT Eight;
+ FLOAT Nine;
+ FLOAT TwentySeven;
+ FLOAT ThirtyTwo;
+ FLOAT TwoForty;
+ FLOAT MinusOne;
+ FLOAT OneAndHalf;
+
+ /* Declarations of Variables. */
+ int Indx;
+ char ch[8];
+ FLOAT AInvrse, A1;
+ FLOAT C, CInvrse;
+ FLOAT D, FourD;
+ FLOAT E0, E1, Exp2, E3, MinSqEr;
+ FLOAT SqEr, MaxSqEr, E9;
+ FLOAT Third;
+ FLOAT F6, F9;
+ FLOAT H, HInvrse;
+ int I;
+ FLOAT StickyBit, J;
+ FLOAT MyZero;
+ FLOAT Precision;
+ FLOAT Q, Q9;
+ FLOAT R, Random9;
+ FLOAT T, Underflow, S;
+ FLOAT OneUlp, UfThold, U1, U2;
+ FLOAT V, V0, V9;
+ FLOAT W;
+ FLOAT X, X1, X2, X8, Random1;
+ FLOAT Y, Y1, Y2, Random2;
+ FLOAT Z, PseudoZero, Z1, Z2, Z9;
+ int ErrCnt[4];
+ int Milestone;
+ int PageNo;
+ int M, N, N1;
+ Guard GMult, GDiv, GAddSub;
+ Rounding RMult, RDiv, RAddSub, RSqrt;
+ int Break, Done, NotMonot, Monot, Anomaly, IEEE, SqRWrng, UfNGrad;
+
+ /* Computed constants. */
+ /*U1 gap below 1.0, i.e, 1.0-U1 is next number below 1.0 */
+ /*U2 gap above 1.0, i.e, 1.0+U2 is next number above 1.0 */
+
+ int main ();
+
+ FLOAT Sign (FLOAT);
+ FLOAT Random ();
+ void Pause ();
+ void BadCond (int, const char *);
+ void SqXMinX (int);
+ void TstCond (int, int, const char *);
+ void notify (const char *);
+ void IsYeqX ();
+ void NewD ();
+ void PrintIfNPositive ();
+ void SR3750 ();
+ void TstPtUf ();
+
+ // Pretend we're bss.
+ Paranoia() { memset(this, 0, sizeof (*this)); }
+};
+
+template<typename FLOAT>
+int
+Paranoia<FLOAT>::main()
+{
+ /* First two assignments use integer right-hand sides. */
+ Zero = long(0);
+ One = long(1);
+ Two = long(2);
+ Three = long(3);
+ Four = long(4);
+ Five = long(5);
+ Eight = long(8);
+ Nine = long(9);
+ TwentySeven = long(27);
+ ThirtyTwo = long(32);
+ TwoForty = long(240);
+ MinusOne = long(-1);
+ Half = "0x1p-1";
+ OneAndHalf = "0x3p-1";
+ ErrCnt[Failure] = 0;
+ ErrCnt[Serious] = 0;
+ ErrCnt[Defect] = 0;
+ ErrCnt[Flaw] = 0;
+ PageNo = 1;
+ /*=============================================*/
+ Milestone = 7;
+ /*=============================================*/
+ printf ("Program is now RUNNING tests on small integers:\n");
+
+ TstCond (Failure, (Zero + Zero == Zero), "0+0 != 0");
+ TstCond (Failure, (One - One == Zero), "1-1 != 0");
+ TstCond (Failure, (One > Zero), "1 <= 0");
+ TstCond (Failure, (One + One == Two), "1+1 != 2");
+
+ Z = -Zero;
+ if (Z != Zero)
+ {
+ ErrCnt[Failure] = ErrCnt[Failure] + 1;
+ printf ("Comparison alleges that -0.0 is Non-zero!\n");
+ U2 = "0.001";
+ Radix = 1;
+ TstPtUf ();
+ }
+
+ TstCond (Failure, (Three == Two + One), "3 != 2+1");
+ TstCond (Failure, (Four == Three + One), "4 != 3+1");
+ TstCond (Failure, (Four + Two * (-Two) == Zero), "4 + 2*(-2) != 0");
+ TstCond (Failure, (Four - Three - One == Zero), "4-3-1 != 0");
+
+ TstCond (Failure, (MinusOne == (Zero - One)), "-1 != 0-1");
+ TstCond (Failure, (MinusOne + One == Zero), "-1+1 != 0");
+ TstCond (Failure, (One + MinusOne == Zero), "1+(-1) != 0");
+ TstCond (Failure, (MinusOne + FABS (One) == Zero), "-1+abs(1) != 0");
+ TstCond (Failure, (MinusOne + MinusOne * MinusOne == Zero),
+ "-1+(-1)*(-1) != 0");
+
+ TstCond (Failure, Half + MinusOne + Half == Zero, "1/2 + (-1) + 1/2 != 0");
+
+ /*=============================================*/
+ Milestone = 10;
+ /*=============================================*/
+
+ TstCond (Failure, (Nine == Three * Three), "9 != 3*3");
+ TstCond (Failure, (TwentySeven == Nine * Three), "27 != 9*3");
+ TstCond (Failure, (Eight == Four + Four), "8 != 4+4");
+ TstCond (Failure, (ThirtyTwo == Eight * Four), "32 != 8*4");
+ TstCond (Failure, (ThirtyTwo - TwentySeven - Four - One == Zero),
+ "32-27-4-1 != 0");
+
+ TstCond (Failure, Five == Four + One, "5 != 4+1");
+ TstCond (Failure, TwoForty == Four * Five * Three * Four, "240 != 4*5*3*4");
+ TstCond (Failure, TwoForty / Three - Four * Four * Five == Zero,
+ "240/3 - 4*4*5 != 0");
+ TstCond (Failure, TwoForty / Four - Five * Three * Four == Zero,
+ "240/4 - 5*3*4 != 0");
+ TstCond (Failure, TwoForty / Five - Four * Three * Four == Zero,
+ "240/5 - 4*3*4 != 0");
+
+ if (ErrCnt[Failure] == 0)
+ {
+ printf ("-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K.\n");
+ printf ("\n");
+ }
+ printf ("Searching for Radix and Precision.\n");
+ W = One;
+ do
+ {
+ W = W + W;
+ Y = W + One;
+ Z = Y - W;
+ Y = Z - One;
+ }
+ while (MinusOne + FABS (Y) < Zero);
+ /*.. now W is just big enough that |((W+1)-W)-1| >= 1 ... */
+ Precision = Zero;
+ Y = One;
+ do
+ {
+ Radix = W + Y;
+ Y = Y + Y;
+ Radix = Radix - W;
+ }
+ while (Radix == Zero);
+ if (Radix < Two)
+ Radix = One;
+ printf ("Radix = %s .\n", Radix.str());
+ if (Radix != One)
+ {
+ W = One;
+ do
+ {
+ Precision = Precision + One;
+ W = W * Radix;
+ Y = W + One;
+ }
+ while ((Y - W) == One);
+ }
+ /*... now W == Radix^Precision is barely too big to satisfy (W+1)-W == 1
+ ... */
+ U1 = One / W;
+ U2 = Radix * U1;
+ printf ("Closest relative separation found is U1 = %s .\n\n", U1.str());
+ printf ("Recalculating radix and precision\n ");
+
+ /*save old values */
+ E0 = Radix;
+ E1 = U1;
+ E9 = U2;
+ E3 = Precision;
+
+ X = Four / Three;
+ Third = X - One;
+ F6 = Half - Third;
+ X = F6 + F6;
+ X = FABS (X - Third);
+ if (X < U2)
+ X = U2;
+
+ /*... now X = (unknown no.) ulps of 1+... */
+ do
+ {
+ U2 = X;
+ Y = Half * U2 + ThirtyTwo * U2 * U2;
+ Y = One + Y;
+ X = Y - One;
+ }
+ while (!((U2 <= X) || (X <= Zero)));
+
+ /*... now U2 == 1 ulp of 1 + ... */
+ X = Two / Three;
+ F6 = X - Half;
+ Third = F6 + F6;
+ X = Third - Half;
+ X = FABS (X + F6);
+ if (X < U1)
+ X = U1;
+
+ /*... now X == (unknown no.) ulps of 1 -... */
+ do
+ {
+ U1 = X;
+ Y = Half * U1 + ThirtyTwo * U1 * U1;
+ Y = Half - Y;
+ X = Half + Y;
+ Y = Half - X;
+ X = Half + Y;
+ }
+ while (!((U1 <= X) || (X <= Zero)));
+ /*... now U1 == 1 ulp of 1 - ... */
+ if (U1 == E1)
+ printf ("confirms closest relative separation U1 .\n");
+ else
+ printf ("gets better closest relative separation U1 = %s .\n", U1.str());
+ W = One / U1;
+ F9 = (Half - U1) + Half;
+
+ Radix = FLOOR (FLOAT ("0.01") + U2 / U1);
+ if (Radix == E0)
+ printf ("Radix confirmed.\n");
+ else
+ printf ("MYSTERY: recalculated Radix = %s .\n", Radix.str());
+ TstCond (Defect, Radix <= Eight + Eight,
+ "Radix is too big: roundoff problems");
+ TstCond (Flaw, (Radix == Two) || (Radix == 10)
+ || (Radix == One), "Radix is not as good as 2 or 10");
+ /*=============================================*/
+ Milestone = 20;
+ /*=============================================*/
+ TstCond (Failure, F9 - Half < Half,
+ "(1-U1)-1/2 < 1/2 is FALSE, prog. fails?");
+ X = F9;
+ I = 1;
+ Y = X - Half;
+ Z = Y - Half;
+ TstCond (Failure, (X != One)
+ || (Z == Zero), "Comparison is fuzzy,X=1 but X-1/2-1/2 != 0");
+ X = One + U2;
+ I = 0;
+ /*=============================================*/
+ Milestone = 25;
+ /*=============================================*/
+ /*... BMinusU2 = nextafter(Radix, 0) */
+ BMinusU2 = Radix - One;
+ BMinusU2 = (BMinusU2 - U2) + One;
+ /* Purify Integers */
+ if (Radix != One)
+ {
+ X = -TwoForty * LOG (U1) / LOG (Radix);
+ Y = FLOOR (Half + X);
+ if (FABS (X - Y) * Four < One)
+ X = Y;
+ Precision = X / TwoForty;
+ Y = FLOOR (Half + Precision);
+ if (FABS (Precision - Y) * TwoForty < Half)
+ Precision = Y;
+ }
+ if ((Precision != FLOOR (Precision)) || (Radix == One))
+ {
+ printf ("Precision cannot be characterized by an Integer number\n");
+ printf
+ ("of significant digits but, by itself, this is a minor flaw.\n");
+ }
+ if (Radix == One)
+ printf
+ ("logarithmic encoding has precision characterized solely by U1.\n");
+ else
+ printf ("The number of significant digits of the Radix is %s .\n",
+ Precision.str());
+ TstCond (Serious, U2 * Nine * Nine * TwoForty < One,
+ "Precision worse than 5 decimal figures ");
+ /*=============================================*/
+ Milestone = 30;
+ /*=============================================*/
+ /* Test for extra-precise subexpressions */
+ X = FABS (((Four / Three - One) - One / Four) * Three - One / Four);
+ do
+ {
+ Z2 = X;
+ X = (One + (Half * Z2 + ThirtyTwo * Z2 * Z2)) - One;
+ }
+ while (!((Z2 <= X) || (X <= Zero)));
+ X = Y = Z = FABS ((Three / Four - Two / Three) * Three - One / Four);
+ do
+ {
+ Z1 = Z;
+ Z = (One / Two - ((One / Two - (Half * Z1 + ThirtyTwo * Z1 * Z1))
+ + One / Two)) + One / Two;
+ }
+ while (!((Z1 <= Z) || (Z <= Zero)));
+ do
+ {
+ do
+ {
+ Y1 = Y;
+ Y =
+ (Half - ((Half - (Half * Y1 + ThirtyTwo * Y1 * Y1)) + Half)) +
+ Half;
+ }
+ while (!((Y1 <= Y) || (Y <= Zero)));
+ X1 = X;
+ X = ((Half * X1 + ThirtyTwo * X1 * X1) - F9) + F9;
+ }
+ while (!((X1 <= X) || (X <= Zero)));
+ if ((X1 != Y1) || (X1 != Z1))
+ {
+ BadCond (Serious, "Disagreements among the values X1, Y1, Z1,\n");
+ printf ("respectively %s, %s, %s,\n", X1.str(), Y1.str(), Z1.str());
+ printf ("are symptoms of inconsistencies introduced\n");
+ printf ("by extra-precise evaluation of arithmetic subexpressions.\n");
+ notify ("Possibly some part of this");
+ if ((X1 == U1) || (Y1 == U1) || (Z1 == U1))
+ printf ("That feature is not tested further by this program.\n");
+ }
+ else
+ {
+ if ((Z1 != U1) || (Z2 != U2))
+ {
+ if ((Z1 >= U1) || (Z2 >= U2))
+ {
+ BadCond (Failure, "");
+ notify ("Precision");
+ printf ("\tU1 = %s, Z1 - U1 = %s\n", U1.str(), (Z1 - U1).str());
+ printf ("\tU2 = %s, Z2 - U2 = %s\n", U2.str(), (Z2 - U2).str());
+ }
+ else
+ {
+ if ((Z1 <= Zero) || (Z2 <= Zero))
+ {
+ printf ("Because of unusual Radix = %s", Radix.str());
+ printf (", or exact rational arithmetic a result\n");
+ printf ("Z1 = %s, or Z2 = %s ", Z1.str(), Z2.str());
+ notify ("of an\nextra-precision");
+ }
+ if (Z1 != Z2 || Z1 > Zero)
+ {
+ X = Z1 / U1;
+ Y = Z2 / U2;
+ if (Y > X)
+ X = Y;
+ Q = -LOG (X);
+ printf ("Some subexpressions appear to be calculated "
+ "extra precisely\n");
+ printf ("with about %s extra B-digits, i.e.\n",
+ (Q / LOG (Radix)).str());
+ printf ("roughly %s extra significant decimals.\n",
+ (Q / LOG (FLOAT (10))).str());
+ }
+ printf
+ ("That feature is not tested further by this program.\n");
+ }
+ }
+ }
+ Pause ();
+ /*=============================================*/
+ Milestone = 35;
+ /*=============================================*/
+ if (Radix >= Two)
+ {
+ X = W / (Radix * Radix);
+ Y = X + One;
+ Z = Y - X;
+ T = Z + U2;
+ X = T - Z;
+ TstCond (Failure, X == U2,
+ "Subtraction is not normalized X=Y,X+Z != Y+Z!");
+ if (X == U2)
+ printf ("Subtraction appears to be normalized, as it should be.");
+ }
+ printf ("\nChecking for guard digit in *, /, and -.\n");
+ Y = F9 * One;
+ Z = One * F9;
+ X = F9 - Half;
+ Y = (Y - Half) - X;
+ Z = (Z - Half) - X;
+ X = One + U2;
+ T = X * Radix;
+ R = Radix * X;
+ X = T - Radix;
+ X = X - Radix * U2;
+ T = R - Radix;
+ T = T - Radix * U2;
+ X = X * (Radix - One);
+ T = T * (Radix - One);
+ if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero))
+ GMult = Yes;
+ else
+ {
+ GMult = No;
+ TstCond (Serious, false, "* lacks a Guard Digit, so 1*X != X");
+ }
+ Z = Radix * U2;
+ X = One + Z;
+ Y = FABS ((X + Z) - X * X) - U2;
+ X = One - U2;
+ Z = FABS ((X - U2) - X * X) - U1;
+ TstCond (Failure, (Y <= Zero)
+ && (Z <= Zero), "* gets too many final digits wrong.\n");
+ Y = One - U2;
+ X = One + U2;
+ Z = One / Y;
+ Y = Z - X;
+ X = One / Three;
+ Z = Three / Nine;
+ X = X - Z;
+ T = Nine / TwentySeven;
+ Z = Z - T;
+ TstCond (Defect, X == Zero && Y == Zero && Z == Zero,
+ "Division lacks a Guard Digit, so error can exceed 1 ulp\n"
+ "or 1/3 and 3/9 and 9/27 may disagree");
+ Y = F9 / One;
+ X = F9 - Half;
+ Y = (Y - Half) - X;
+ X = One + U2;
+ T = X / One;
+ X = T - X;
+ if ((X == Zero) && (Y == Zero) && (Z == Zero))
+ GDiv = Yes;
+ else
+ {
+ GDiv = No;
+ TstCond (Serious, false, "Division lacks a Guard Digit, so X/1 != X");
+ }
+ X = One / (One + U2);
+ Y = X - Half - Half;
+ TstCond (Serious, Y < Zero, "Computed value of 1/1.000..1 >= 1");
+ X = One - U2;
+ Y = One + Radix * U2;
+ Z = X * Radix;
+ T = Y * Radix;
+ R = Z / Radix;
+ StickyBit = T / Radix;
+ X = R - X;
+ Y = StickyBit - Y;
+ TstCond (Failure, X == Zero && Y == Zero,
+ "* and/or / gets too many last digits wrong");
+ Y = One - U1;
+ X = One - F9;
+ Y = One - Y;
+ T = Radix - U2;
+ Z = Radix - BMinusU2;
+ T = Radix - T;
+ if ((X == U1) && (Y == U1) && (Z == U2) && (T == U2))
+ GAddSub = Yes;
+ else
+ {
+ GAddSub = No;
+ TstCond (Serious, false,
+ "- lacks Guard Digit, so cancellation is obscured");
+ }
+ if (F9 != One && F9 - One >= Zero)
+ {
+ BadCond (Serious, "comparison alleges (1-U1) < 1 although\n");
+ printf (" subtraction yields (1-U1) - 1 = 0 , thereby vitiating\n");
+ printf (" such precautions against division by zero as\n");
+ printf (" ... if (X == 1.0) {.....} else {.../(X-1.0)...}\n");
+ }
+ if (GMult == Yes && GDiv == Yes && GAddSub == Yes)
+ printf
+ (" *, /, and - appear to have guard digits, as they should.\n");
+ /*=============================================*/
+ Milestone = 40;
+ /*=============================================*/
+ Pause ();
+ printf ("Checking rounding on multiply, divide and add/subtract.\n");
+ RMult = Other;
+ RDiv = Other;
+ RAddSub = Other;
+ RadixD2 = Radix / Two;
+ A1 = Two;
+ Done = false;
+ do
+ {
+ AInvrse = Radix;
+ do
+ {
+ X = AInvrse;
+ AInvrse = AInvrse / A1;
+ }
+ while (!(FLOOR (AInvrse) != AInvrse));
+ Done = (X == One) || (A1 > Three);
+ if (!Done)
+ A1 = Nine + One;
+ }
+ while (!(Done));
+ if (X == One)
+ A1 = Radix;
+ AInvrse = One / A1;
+ X = A1;
+ Y = AInvrse;
+ Done = false;
+ do
+ {
+ Z = X * Y - Half;
+ TstCond (Failure, Z == Half, "X * (1/X) differs from 1");
+ Done = X == Radix;
+ X = Radix;
+ Y = One / X;
+ }
+ while (!(Done));
+ Y2 = One + U2;
+ Y1 = One - U2;
+ X = OneAndHalf - U2;
+ Y = OneAndHalf + U2;
+ Z = (X - U2) * Y2;
+ T = Y * Y1;
+ Z = Z - X;
+ T = T - X;
+ X = X * Y2;
+ Y = (Y + U2) * Y1;
+ X = X - OneAndHalf;
+ Y = Y - OneAndHalf;
+ if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T <= Zero))
+ {
+ X = (OneAndHalf + U2) * Y2;
+ Y = OneAndHalf - U2 - U2;
+ Z = OneAndHalf + U2 + U2;
+ T = (OneAndHalf - U2) * Y1;
+ X = X - (Z + U2);
+ StickyBit = Y * Y1;
+ S = Z * Y2;
+ T = T - Y;
+ Y = (U2 - Y) + StickyBit;
+ Z = S - (Z + U2 + U2);
+ StickyBit = (Y2 + U2) * Y1;
+ Y1 = Y2 * Y1;
+ StickyBit = StickyBit - Y2;
+ Y1 = Y1 - Half;
+ if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
+ && (StickyBit == Zero) && (Y1 == Half))
+ {
+ RMult = Rounded;
+ printf ("Multiplication appears to round correctly.\n");
+ }
+ else if ((X + U2 == Zero) && (Y < Zero) && (Z + U2 == Zero)
+ && (T < Zero) && (StickyBit + U2 == Zero) && (Y1 < Half))
+ {
+ RMult = Chopped;
+ printf ("Multiplication appears to chop.\n");
+ }
+ else
+ printf ("* is neither chopped nor correctly rounded.\n");
+ if ((RMult == Rounded) && (GMult == No))
+ notify ("Multiplication");
+ }
+ else
+ printf ("* is neither chopped nor correctly rounded.\n");
+ /*=============================================*/
+ Milestone = 45;
+ /*=============================================*/
+ Y2 = One + U2;
+ Y1 = One - U2;
+ Z = OneAndHalf + U2 + U2;
+ X = Z / Y2;
+ T = OneAndHalf - U2 - U2;
+ Y = (T - U2) / Y1;
+ Z = (Z + U2) / Y2;
+ X = X - OneAndHalf;
+ Y = Y - T;
+ T = T / Y1;
+ Z = Z - (OneAndHalf + U2);
+ T = (U2 - OneAndHalf) + T;
+ if (!((X > Zero) || (Y > Zero) || (Z > Zero) || (T > Zero)))
+ {
+ X = OneAndHalf / Y2;
+ Y = OneAndHalf - U2;
+ Z = OneAndHalf + U2;
+ X = X - Y;
+ T = OneAndHalf / Y1;
+ Y = Y / Y1;
+ T = T - (Z + U2);
+ Y = Y - Z;
+ Z = Z / Y2;
+ Y1 = (Y2 + U2) / Y2;
+ Z = Z - OneAndHalf;
+ Y2 = Y1 - Y2;
+ Y1 = (F9 - U1) / F9;
+ if ((X == Zero) && (Y == Zero) && (Z == Zero) && (T == Zero)
+ && (Y2 == Zero) && (Y2 == Zero) && (Y1 - Half == F9 - Half))
+ {
+ RDiv = Rounded;
+ printf ("Division appears to round correctly.\n");
+ if (GDiv == No)
+ notify ("Division");
+ }
+ else if ((X < Zero) && (Y < Zero) && (Z < Zero) && (T < Zero)
+ && (Y2 < Zero) && (Y1 - Half < F9 - Half))
+ {
+ RDiv = Chopped;
+ printf ("Division appears to chop.\n");
+ }
+ }
+ if (RDiv == Other)
+ printf ("/ is neither chopped nor correctly rounded.\n");
+ BInvrse = One / Radix;
+ TstCond (Failure, (BInvrse * Radix - Half == Half),
+ "Radix * ( 1 / Radix ) differs from 1");
+ /*=============================================*/
+ Milestone = 50;
+ /*=============================================*/
+ TstCond (Failure, ((F9 + U1) - Half == Half)
+ && ((BMinusU2 + U2) - One == Radix - One),
+ "Incomplete carry-propagation in Addition");
+ X = One - U1 * U1;
+ Y = One + U2 * (One - U2);
+ Z = F9 - Half;
+ X = (X - Half) - Z;
+ Y = Y - One;
+ if ((X == Zero) && (Y == Zero))
+ {
+ RAddSub = Chopped;
+ printf ("Add/Subtract appears to be chopped.\n");
+ }
+ if (GAddSub == Yes)
+ {
+ X = (Half + U2) * U2;
+ Y = (Half - U2) * U2;
+ X = One + X;
+ Y = One + Y;
+ X = (One + U2) - X;
+ Y = One - Y;
+ if ((X == Zero) && (Y == Zero))
+ {
+ X = (Half + U2) * U1;
+ Y = (Half - U2) * U1;
+ X = One - X;
+ Y = One - Y;
+ X = F9 - X;
+ Y = One - Y;
+ if ((X == Zero) && (Y == Zero))
+ {
+ RAddSub = Rounded;
+ printf ("Addition/Subtraction appears to round correctly.\n");
+ if (GAddSub == No)
+ notify ("Add/Subtract");
+ }
+ else
+ printf ("Addition/Subtraction neither rounds nor chops.\n");
+ }
+ else
+ printf ("Addition/Subtraction neither rounds nor chops.\n");
+ }
+ else
+ printf ("Addition/Subtraction neither rounds nor chops.\n");
+ S = One;
+ X = One + Half * (One + Half);
+ Y = (One + U2) * Half;
+ Z = X - Y;
+ T = Y - X;
+ StickyBit = Z + T;
+ if (StickyBit != Zero)
+ {
+ S = Zero;
+ BadCond (Flaw, "(X - Y) + (Y - X) is non zero!\n");
+ }
+ StickyBit = Zero;
+ if ((GMult == Yes) && (GDiv == Yes) && (GAddSub == Yes)
+ && (RMult == Rounded) && (RDiv == Rounded)
+ && (RAddSub == Rounded) && (FLOOR (RadixD2) == RadixD2))
+ {
+ printf ("Checking for sticky bit.\n");
+ X = (Half + U1) * U2;
+ Y = Half * U2;
+ Z = One + Y;
+ T = One + X;
+ if ((Z - One <= Zero) && (T - One >= U2))
+ {
+ Z = T + Y;
+ Y = Z - X;
+ if ((Z - T >= U2) && (Y - T == Zero))
+ {
+ X = (Half + U1) * U1;
+ Y = Half * U1;
+ Z = One - Y;
+ T = One - X;
+ if ((Z - One == Zero) && (T - F9 == Zero))
+ {
+ Z = (Half - U1) * U1;
+ T = F9 - Z;
+ Q = F9 - Y;
+ if ((T - F9 == Zero) && (F9 - U1 - Q == Zero))
+ {
+ Z = (One + U2) * OneAndHalf;
+ T = (OneAndHalf + U2) - Z + U2;
+ X = One + Half / Radix;
+ Y = One + Radix * U2;
+ Z = X * Y;
+ if (T == Zero && X + Radix * U2 - Z == Zero)
+ {
+ if (Radix != Two)
+ {
+ X = Two + U2;
+ Y = X / Two;
+ if ((Y - One == Zero))
+ StickyBit = S;
+ }
+ else
+ StickyBit = S;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (StickyBit == One)
+ printf ("Sticky bit apparently used correctly.\n");
+ else
+ printf ("Sticky bit used incorrectly or not at all.\n");
+ TstCond (Flaw, !(GMult == No || GDiv == No || GAddSub == No ||
+ RMult == Other || RDiv == Other || RAddSub == Other),
+ "lack(s) of guard digits or failure(s) to correctly round or chop\n\
+(noted above) count as one flaw in the final tally below");
+ /*=============================================*/
+ Milestone = 60;
+ /*=============================================*/
+ printf ("\n");
+ printf ("Does Multiplication commute? ");
+ printf ("Testing on %d random pairs.\n", NoTrials);
+ Random9 = SQRT (FLOAT (3));
+ Random1 = Third;
+ I = 1;
+ do
+ {
+ X = Random ();
+ Y = Random ();
+ Z9 = Y * X;
+ Z = X * Y;
+ Z9 = Z - Z9;
+ I = I + 1;
+ }
+ while (!((I > NoTrials) || (Z9 != Zero)));
+ if (I == NoTrials)
+ {
+ Random1 = One + Half / Three;
+ Random2 = (U2 + U1) + One;
+ Z = Random1 * Random2;
+ Y = Random2 * Random1;
+ Z9 = (One + Half / Three) * ((U2 + U1) + One) - (One + Half /
+ Three) * ((U2 + U1) +
+ One);
+ }
+ if (!((I == NoTrials) || (Z9 == Zero)))
+ BadCond (Defect, "X * Y == Y * X trial fails.\n");
+ else
+ printf (" No failures found in %d integer pairs.\n", NoTrials);
+ /*=============================================*/
+ Milestone = 70;
+ /*=============================================*/
+ printf ("\nRunning test of square root(x).\n");
+ TstCond (Failure, (Zero == SQRT (Zero))
+ && (-Zero == SQRT (-Zero))
+ && (One == SQRT (One)), "Square root of 0.0, -0.0 or 1.0 wrong");
+ MinSqEr = Zero;
+ MaxSqEr = Zero;
+ J = Zero;
+ X = Radix;
+ OneUlp = U2;
+ SqXMinX (Serious);
+ X = BInvrse;
+ OneUlp = BInvrse * U1;
+ SqXMinX (Serious);
+ X = U1;
+ OneUlp = U1 * U1;
+ SqXMinX (Serious);
+ if (J != Zero)
+ Pause ();
+ printf ("Testing if sqrt(X * X) == X for %d Integers X.\n", NoTrials);
+ J = Zero;
+ X = Two;
+ Y = Radix;
+ if ((Radix != One))
+ do
+ {
+ X = Y;
+ Y = Radix * Y;
+ }
+ while (!((Y - X >= NoTrials)));
+ OneUlp = X * U2;
+ I = 1;
+ while (I <= NoTrials)
+ {
+ X = X + One;
+ SqXMinX (Defect);
+ if (J > Zero)
+ break;
+ I = I + 1;
+ }
+ printf ("Test for sqrt monotonicity.\n");
+ I = -1;
+ X = BMinusU2;
+ Y = Radix;
+ Z = Radix + Radix * U2;
+ NotMonot = false;
+ Monot = false;
+ while (!(NotMonot || Monot))
+ {
+ I = I + 1;
+ X = SQRT (X);
+ Q = SQRT (Y);
+ Z = SQRT (Z);
+ if ((X > Q) || (Q > Z))
+ NotMonot = true;
+ else
+ {
+ Q = FLOOR (Q + Half);
+ if (!(I > 0 || Radix == Q * Q))
+ Monot = true;
+ else if (I > 0)
+ {
+ if (I > 1)
+ Monot = true;
+ else
+ {
+ Y = Y * BInvrse;
+ X = Y - U1;
+ Z = Y + U1;
+ }
+ }
+ else
+ {
+ Y = Q;
+ X = Y - U2;
+ Z = Y + U2;
+ }
+ }
+ }
+ if (Monot)
+ printf ("sqrt has passed a test for Monotonicity.\n");
+ else
+ {
+ BadCond (Defect, "");
+ printf ("sqrt(X) is non-monotonic for X near %s .\n", Y.str());
+ }
+ /*=============================================*/
+ Milestone = 110;
+ /*=============================================*/
+ printf ("Seeking Underflow thresholds UfThold and E0.\n");
+ D = U1;
+ if (Precision != FLOOR (Precision))
+ {
+ D = BInvrse;
+ X = Precision;
+ do
+ {
+ D = D * BInvrse;
+ X = X - One;
+ }
+ while (X > Zero);
+ }
+ Y = One;
+ Z = D;
+ /* ... D is power of 1/Radix < 1. */
+ do
+ {
+ C = Y;
+ Y = Z;
+ Z = Y * Y;
+ }
+ while ((Y > Z) && (Z + Z > Z));
+ Y = C;
+ Z = Y * D;
+ do
+ {
+ C = Y;
+ Y = Z;
+ Z = Y * D;
+ }
+ while ((Y > Z) && (Z + Z > Z));
+ if (Radix < Two)
+ HInvrse = Two;
+ else
+ HInvrse = Radix;
+ H = One / HInvrse;
+ /* ... 1/HInvrse == H == Min(1/Radix, 1/2) */
+ CInvrse = One / C;
+ E0 = C;
+ Z = E0 * H;
+ /* ...1/Radix^(BIG Integer) << 1 << CInvrse == 1/C */
+ do
+ {
+ Y = E0;
+ E0 = Z;
+ Z = E0 * H;
+ }
+ while ((E0 > Z) && (Z + Z > Z));
+ UfThold = E0;
+ E1 = Zero;
+ Q = Zero;
+ E9 = U2;
+ S = One + E9;
+ D = C * S;
+ if (D <= C)
+ {
+ E9 = Radix * U2;
+ S = One + E9;
+ D = C * S;
+ if (D <= C)
+ {
+ BadCond (Failure,
+ "multiplication gets too many last digits wrong.\n");
+ Underflow = E0;
+ Y1 = Zero;
+ PseudoZero = Z;
+ Pause ();
+ }
+ }
+ else
+ {
+ Underflow = D;
+ PseudoZero = Underflow * H;
+ UfThold = Zero;
+ do
+ {
+ Y1 = Underflow;
+ Underflow = PseudoZero;
+ if (E1 + E1 <= E1)
+ {
+ Y2 = Underflow * HInvrse;
+ E1 = FABS (Y1 - Y2);
+ Q = Y1;
+ if ((UfThold == Zero) && (Y1 != Y2))
+ UfThold = Y1;
+ }
+ PseudoZero = PseudoZero * H;
+ }
+ while ((Underflow > PseudoZero)
+ && (PseudoZero + PseudoZero > PseudoZero));
+ }
+ /* Comment line 4530 .. 4560 */
+ if (PseudoZero != Zero)
+ {
+ printf ("\n");
+ Z = PseudoZero;
+ /* ... Test PseudoZero for "phoney- zero" violates */
+ /* ... PseudoZero < Underflow or PseudoZero < PseudoZero + PseudoZero
+ ... */
+ if (PseudoZero <= Zero)
+ {
+ BadCond (Failure, "Positive expressions can underflow to an\n");
+ printf ("allegedly negative value\n");
+ printf ("PseudoZero that prints out as: %s .\n", PseudoZero.str());
+ X = -PseudoZero;
+ if (X <= Zero)
+ {
+ printf ("But -PseudoZero, which should be\n");
+ printf ("positive, isn't; it prints out as %s .\n", X.str());
+ }
+ }
+ else
+ {
+ BadCond (Flaw, "Underflow can stick at an allegedly positive\n");
+ printf ("value PseudoZero that prints out as %s .\n",
+ PseudoZero.str());
+ }
+ TstPtUf ();
+ }
+ /*=============================================*/
+ Milestone = 120;
+ /*=============================================*/
+ if (CInvrse * Y > CInvrse * Y1)
+ {
+ S = H * S;
+ E0 = Underflow;
+ }
+ if (!((E1 == Zero) || (E1 == E0)))
+ {
+ BadCond (Defect, "");
+ if (E1 < E0)
+ {
+ printf ("Products underflow at a higher");
+ printf (" threshold than differences.\n");
+ if (PseudoZero == Zero)
+ E0 = E1;
+ }
+ else
+ {
+ printf ("Difference underflows at a higher");
+ printf (" threshold than products.\n");
+ }
+ }
+ printf ("Smallest strictly positive number found is E0 = %s .\n", E0.str());
+ Z = E0;
+ TstPtUf ();
+ Underflow = E0;
+ if (N == 1)
+ Underflow = Y;
+ I = 4;
+ if (E1 == Zero)
+ I = 3;
+ if (UfThold == Zero)
+ I = I - 2;
+ UfNGrad = true;
+ switch (I)
+ {
+ case 1:
+ UfThold = Underflow;
+ if ((CInvrse * Q) != ((CInvrse * Y) * S))
+ {
+ UfThold = Y;
+ BadCond (Failure, "Either accuracy deteriorates as numbers\n");
+ printf ("approach a threshold = %s\n", UfThold.str());
+ printf (" coming down from %s\n", C.str());
+ printf
+ (" or else multiplication gets too many last digits wrong.\n");
+ }
+ Pause ();
+ break;
+
+ case 2:
+ BadCond (Failure,
+ "Underflow confuses Comparison, which alleges that\n");
+ printf ("Q == Y while denying that |Q - Y| == 0; these values\n");
+ printf ("print out as Q = %s, Y = %s .\n", Q.str(), Y2.str());
+ printf ("|Q - Y| = %s .\n", FABS (Q - Y2).str());
+ UfThold = Q;
+ break;
+
+ case 3:
+ X = X;
+ break;
+
+ case 4:
+ if ((Q == UfThold) && (E1 == E0) && (FABS (UfThold - E1 / E9) <= E1))
+ {
+ UfNGrad = false;
+ printf ("Underflow is gradual; it incurs Absolute Error =\n");
+ printf ("(roundoff in UfThold) < E0.\n");
+ Y = E0 * CInvrse;
+ Y = Y * (OneAndHalf + U2);
+ X = CInvrse * (One + U2);
+ Y = Y / X;
+ IEEE = (Y == E0);
+ }
+ }
+ if (UfNGrad)
+ {
+ printf ("\n");
+ if (setjmp (ovfl_buf))
+ {
+ printf ("Underflow / UfThold failed!\n");
+ R = H + H;
+ }
+ else
+ R = SQRT (Underflow / UfThold);
+ if (R <= H)
+ {
+ Z = R * UfThold;
+ X = Z * (One + R * H * (One + H));
+ }
+ else
+ {
+ Z = UfThold;
+ X = Z * (One + H * H * (One + H));
+ }
+ if (!((X == Z) || (X - Z != Zero)))
+ {
+ BadCond (Flaw, "");
+ printf ("X = %s\n\tis not equal to Z = %s .\n", X.str(), Z.str());
+ Z9 = X - Z;
+ printf ("yet X - Z yields %s .\n", Z9.str());
+ printf (" Should this NOT signal Underflow, ");
+ printf ("this is a SERIOUS DEFECT\nthat causes ");
+ printf ("confusion when innocent statements like\n");;
+ printf (" if (X == Z) ... else");
+ printf (" ... (f(X) - f(Z)) / (X - Z) ...\n");
+ printf ("encounter Division by Zero although actually\n");
+ if (setjmp (ovfl_buf))
+ printf ("X / Z fails!\n");
+ else
+ printf ("X / Z = 1 + %s .\n", ((X / Z - Half) - Half).str());
+ }
+ }
+ printf ("The Underflow threshold is %s, below which\n", UfThold.str());
+ printf ("calculation may suffer larger Relative error than ");
+ printf ("merely roundoff.\n");
+ Y2 = U1 * U1;
+ Y = Y2 * Y2;
+ Y2 = Y * U1;
+ if (Y2 <= UfThold)
+ {
+ if (Y > E0)
+ {
+ BadCond (Defect, "");
+ I = 5;
+ }
+ else
+ {
+ BadCond (Serious, "");
+ I = 4;
+ }
+ printf ("Range is too narrow; U1^%d Underflows.\n", I);
+ }
+ /*=============================================*/
+ Milestone = 130;
+ /*=============================================*/
+ Y = -FLOOR (Half - TwoForty * LOG (UfThold) / LOG (HInvrse)) / TwoForty;
+ Y2 = Y + Y;
+ printf ("Since underflow occurs below the threshold\n");
+ printf ("UfThold = (%s) ^ (%s)\nonly underflow ", HInvrse.str(), Y.str());
+ printf ("should afflict the expression\n\t(%s) ^ (%s);\n",
+ HInvrse.str(), Y2.str());
+ printf ("actually calculating yields:");
+ if (setjmp (ovfl_buf))
+ {
+ BadCond (Serious, "trap on underflow.\n");
+ }
+ else
+ {
+ V9 = POW (HInvrse, Y2);
+ printf (" %s .\n", V9.str());
+ if (!((V9 >= Zero) && (V9 <= (Radix + Radix + E9) * UfThold)))
+ {
+ BadCond (Serious, "this is not between 0 and underflow\n");
+ printf (" threshold = %s .\n", UfThold.str());
+ }
+ else if (!(V9 > UfThold * (One + E9)))
+ printf ("This computed value is O.K.\n");
+ else
+ {
+ BadCond (Defect, "this is not between 0 and underflow\n");
+ printf (" threshold = %s .\n", UfThold.str());
+ }
+ }
+ /*=============================================*/
+ Milestone = 160;
+ /*=============================================*/
+ Pause ();
+ printf ("Searching for Overflow threshold:\n");
+ printf ("This may generate an error.\n");
+ Y = -CInvrse;
+ V9 = HInvrse * Y;
+ if (setjmp (ovfl_buf))
+ {
+ I = 0;
+ V9 = Y;
+ goto overflow;
+ }
+ do
+ {
+ V = Y;
+ Y = V9;
+ V9 = HInvrse * Y;
+ }
+ while (V9 < Y);
+ I = 1;
+overflow:
+ Z = V9;
+ printf ("Can `Z = -Y' overflow?\n");
+ printf ("Trying it on Y = %s .\n", Y.str());
+ V9 = -Y;
+ V0 = V9;
+ if (V - Y == V + V0)
+ printf ("Seems O.K.\n");
+ else
+ {
+ printf ("finds a ");
+ BadCond (Flaw, "-(-Y) differs from Y.\n");
+ }
+ if (Z != Y)
+ {
+ BadCond (Serious, "");
+ printf ("overflow past %s\n\tshrinks to %s .\n", Y.str(), Z.str());
+ }
+ if (I)
+ {
+ Y = V * (HInvrse * U2 - HInvrse);
+ Z = Y + ((One - HInvrse) * U2) * V;
+ if (Z < V0)
+ Y = Z;
+ if (Y < V0)
+ V = Y;
+ if (V0 - V < V0)
+ V = V0;
+ }
+ else
+ {
+ V = Y * (HInvrse * U2 - HInvrse);
+ V = V + ((One - HInvrse) * U2) * Y;
+ }
+ printf ("Overflow threshold is V = %s .\n", V.str());
+ if (I)
+ printf ("Overflow saturates at V0 = %s .\n", V0.str());
+ else
+ printf ("There is no saturation value because "
+ "the system traps on overflow.\n");
+ V9 = V * One;
+ printf ("No Overflow should be signaled for V * 1 = %s\n", V9.str());
+ V9 = V / One;
+ printf (" nor for V / 1 = %s.\n", V9.str());
+ printf ("Any overflow signal separating this * from the one\n");
+ printf ("above is a DEFECT.\n");
+ /*=============================================*/
+ Milestone = 170;
+ /*=============================================*/
+ if (!(-V < V && -V0 < V0 && -UfThold < V && UfThold < V))
+ {
+ BadCond (Failure, "Comparisons involving ");
+ printf ("+-%s, +-%s\nand +-%s are confused by Overflow.",
+ V.str(), V0.str(), UfThold.str());
+ }
+ /*=============================================*/
+ Milestone = 175;
+ /*=============================================*/
+ printf ("\n");
+ for (Indx = 1; Indx <= 3; ++Indx)
+ {
+ switch (Indx)
+ {
+ case 1:
+ Z = UfThold;
+ break;
+ case 2:
+ Z = E0;
+ break;
+ case 3:
+ Z = PseudoZero;
+ break;
+ }
+ if (Z != Zero)
+ {
+ V9 = SQRT (Z);
+ Y = V9 * V9;
+ if (Y / (One - Radix * E9) < Z || Y > (One + Radix * E9) * Z)
+ { /* dgh: + E9 --> * E9 */
+ if (V9 > U1)
+ BadCond (Serious, "");
+ else
+ BadCond (Defect, "");
+ printf ("Comparison alleges that what prints as Z = %s\n",
+ Z.str());
+ printf (" is too far from sqrt(Z) ^ 2 = %s .\n", Y.str());
+ }
+ }
+ }
+ /*=============================================*/
+ Milestone = 180;
+ /*=============================================*/
+ for (Indx = 1; Indx <= 2; ++Indx)
+ {
+ if (Indx == 1)
+ Z = V;
+ else
+ Z = V0;
+ V9 = SQRT (Z);
+ X = (One - Radix * E9) * V9;
+ V9 = V9 * X;
+ if (((V9 < (One - Two * Radix * E9) * Z) || (V9 > Z)))
+ {
+ Y = V9;
+ if (X < W)
+ BadCond (Serious, "");
+ else
+ BadCond (Defect, "");
+ printf ("Comparison alleges that Z = %s\n", Z.str());
+ printf (" is too far from sqrt(Z) ^ 2 (%s) .\n", Y.str());
+ }
+ }
+ /*=============================================*/
+ Milestone = 190;
+ /*=============================================*/
+ Pause ();
+ X = UfThold * V;
+ Y = Radix * Radix;
+ if (X * Y < One || X > Y)
+ {
+ if (X * Y < U1 || X > Y / U1)
+ BadCond (Defect, "Badly");
+ else
+ BadCond (Flaw, "");
+
+ printf (" unbalanced range; UfThold * V = %s\n\t%s\n",
+ X.str(), "is too far from 1.\n");
+ }
+ /*=============================================*/
+ Milestone = 200;
+ /*=============================================*/
+ for (Indx = 1; Indx <= 5; ++Indx)
+ {
+ X = F9;
+ switch (Indx)
+ {
+ case 2:
+ X = One + U2;
+ break;
+ case 3:
+ X = V;
+ break;
+ case 4:
+ X = UfThold;
+ break;
+ case 5:
+ X = Radix;
+ }
+ Y = X;
+ if (setjmp (ovfl_buf))
+ printf (" X / X traps when X = %s\n", X.str());
+ else
+ {
+ V9 = (Y / X - Half) - Half;
+ if (V9 == Zero)
+ continue;
+ if (V9 == -U1 && Indx < 5)
+ BadCond (Flaw, "");
+ else
+ BadCond (Serious, "");
+ printf (" X / X differs from 1 when X = %s\n", X.str());
+ printf (" instead, X / X - 1/2 - 1/2 = %s .\n", V9.str());
+ }
+ }
+ /*=============================================*/
+ Milestone = 210;
+ /*=============================================*/
+ MyZero = Zero;
+ printf ("\n");
+ printf ("What message and/or values does Division by Zero produce?\n");
+ printf (" Trying to compute 1 / 0 produces ...");
+ if (!setjmp (ovfl_buf))
+ printf (" %s .\n", (One / MyZero).str());
+ printf ("\n Trying to compute 0 / 0 produces ...");
+ if (!setjmp (ovfl_buf))
+ printf (" %s .\n", (Zero / MyZero).str());
+ /*=============================================*/
+ Milestone = 220;
+ /*=============================================*/
+ Pause ();
+ printf ("\n");
+ {
+ static const char *msg[] = {
+ "FAILUREs encountered =",
+ "SERIOUS DEFECTs discovered =",
+ "DEFECTs discovered =",
+ "FLAWs discovered ="
+ };
+ int i;
+ for (i = 0; i < 4; i++)
+ if (ErrCnt[i])
+ printf ("The number of %-29s %d.\n", msg[i], ErrCnt[i]);
+ }
+ printf ("\n");
+ if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] + ErrCnt[Flaw]) > 0)
+ {
+ if ((ErrCnt[Failure] + ErrCnt[Serious] + ErrCnt[Defect] == 0)
+ && (ErrCnt[Flaw] > 0))
+ {
+ printf ("The arithmetic diagnosed seems ");
+ printf ("Satisfactory though flawed.\n");
+ }
+ if ((ErrCnt[Failure] + ErrCnt[Serious] == 0) && (ErrCnt[Defect] > 0))
+ {
+ printf ("The arithmetic diagnosed may be Acceptable\n");
+ printf ("despite inconvenient Defects.\n");
+ }
+ if ((ErrCnt[Failure] + ErrCnt[Serious]) > 0)
+ {
+ printf ("The arithmetic diagnosed has ");
+ printf ("unacceptable Serious Defects.\n");
+ }
+ if (ErrCnt[Failure] > 0)
+ {
+ printf ("Potentially fatal FAILURE may have spoiled this");
+ printf (" program's subsequent diagnoses.\n");
+ }
+ }
+ else
+ {
+ printf ("No failures, defects nor flaws have been discovered.\n");
+ if (!((RMult == Rounded) && (RDiv == Rounded)
+ && (RAddSub == Rounded) && (RSqrt == Rounded)))
+ printf ("The arithmetic diagnosed seems Satisfactory.\n");
+ else
+ {
+ if (StickyBit >= One &&
+ (Radix - Two) * (Radix - Nine - One) == Zero)
+ {
+ printf ("Rounding appears to conform to ");
+ printf ("the proposed IEEE standard P");
+ if ((Radix == Two) &&
+ ((Precision - Four * Three * Two) *
+ (Precision - TwentySeven - TwentySeven + One) == Zero))
+ printf ("754");
+ else
+ printf ("854");
+ if (IEEE)
+ printf (".\n");
+ else
+ {
+ printf (",\nexcept for possibly Double Rounding");
+ printf (" during Gradual Underflow.\n");
+ }
+ }
+ printf ("The arithmetic diagnosed appears to be Excellent!\n");
+ }
+ }
+ printf ("END OF TEST.\n");
+ return 0;
+}
+
+template<typename FLOAT>
+FLOAT
+Paranoia<FLOAT>::Sign (FLOAT X)
+{
+ return X >= FLOAT (long (0)) ? 1 : -1;
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::Pause ()
+{
+ if (do_pause)
+ {
+ fputs ("Press return...", stdout);
+ fflush (stdout);
+ getchar();
+ }
+ printf ("\nDiagnosis resumes after milestone Number %d", Milestone);
+ printf (" Page: %d\n\n", PageNo);
+ ++Milestone;
+ ++PageNo;
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::TstCond (int K, int Valid, const char *T)
+{
+ if (!Valid)
+ {
+ BadCond (K, T);
+ printf (".\n");
+ }
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::BadCond (int K, const char *T)
+{
+ static const char *msg[] = { "FAILURE", "SERIOUS DEFECT", "DEFECT", "FLAW" };
+
+ ErrCnt[K] = ErrCnt[K] + 1;
+ printf ("%s: %s", msg[K], T);
+}
+
+/* Random computes
+ X = (Random1 + Random9)^5
+ Random1 = X - FLOOR(X) + 0.000005 * X;
+ and returns the new value of Random1. */
+
+template<typename FLOAT>
+FLOAT
+Paranoia<FLOAT>::Random ()
+{
+ FLOAT X, Y;
+
+ X = Random1 + Random9;
+ Y = X * X;
+ Y = Y * Y;
+ X = X * Y;
+ Y = X - FLOOR (X);
+ Random1 = Y + X * FLOAT ("0.000005");
+ return (Random1);
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::SqXMinX (int ErrKind)
+{
+ FLOAT XA, XB;
+
+ XB = X * BInvrse;
+ XA = X - XB;
+ SqEr = ((SQRT (X * X) - XB) - XA) / OneUlp;
+ if (SqEr != Zero)
+ {
+ if (SqEr < MinSqEr)
+ MinSqEr = SqEr;
+ if (SqEr > MaxSqEr)
+ MaxSqEr = SqEr;
+ J = J + 1;
+ BadCond (ErrKind, "\n");
+ printf ("sqrt(%s) - %s = %s\n", (X * X).str(), X.str(),
+ (OneUlp * SqEr).str());
+ printf ("\tinstead of correct value 0 .\n");
+ }
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::NewD ()
+{
+ X = Z1 * Q;
+ X = FLOOR (Half - X / Radix) * Radix + X;
+ Q = (Q - X * Z) / Radix + X * X * (D / Radix);
+ Z = Z - Two * X * D;
+ if (Z <= Zero)
+ {
+ Z = -Z;
+ Z1 = -Z1;
+ }
+ D = Radix * D;
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::SR3750 ()
+{
+ if (!((X - Radix < Z2 - Radix) || (X - Z2 > W - Z2)))
+ {
+ I = I + 1;
+ X2 = SQRT (X * D);
+ Y2 = (X2 - Z2) - (Y - Z2);
+ X2 = X8 / (Y - Half);
+ X2 = X2 - Half * X2 * X2;
+ SqEr = (Y2 + Half) + (Half - X2);
+ if (SqEr < MinSqEr)
+ MinSqEr = SqEr;
+ SqEr = Y2 - X2;
+ if (SqEr > MaxSqEr)
+ MaxSqEr = SqEr;
+ }
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::IsYeqX ()
+{
+ if (Y != X)
+ {
+ if (N <= 0)
+ {
+ if (Z == Zero && Q <= Zero)
+ printf ("WARNING: computing\n");
+ else
+ BadCond (Defect, "computing\n");
+ printf ("\t(%s) ^ (%s)\n", Z.str(), Q.str());
+ printf ("\tyielded %s;\n", Y.str());
+ printf ("\twhich compared unequal to correct %s ;\n", X.str());
+ printf ("\t\tthey differ by %s .\n", (Y - X).str());
+ }
+ N = N + 1; /* ... count discrepancies. */
+ }
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::PrintIfNPositive ()
+{
+ if (N > 0)
+ printf ("Similar discrepancies have occurred %d times.\n", N);
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::TstPtUf ()
+{
+ N = 0;
+ if (Z != Zero)
+ {
+ printf ("Since comparison denies Z = 0, evaluating ");
+ printf ("(Z + Z) / Z should be safe.\n");
+ if (setjmp (ovfl_buf))
+ goto very_serious;
+ Q9 = (Z + Z) / Z;
+ printf ("What the machine gets for (Z + Z) / Z is %s .\n", Q9.str());
+ if (FABS (Q9 - Two) < Radix * U2)
+ {
+ printf ("This is O.K., provided Over/Underflow");
+ printf (" has NOT just been signaled.\n");
+ }
+ else
+ {
+ if ((Q9 < One) || (Q9 > Two))
+ {
+ very_serious:
+ N = 1;
+ ErrCnt[Serious] = ErrCnt[Serious] + 1;
+ printf ("This is a VERY SERIOUS DEFECT!\n");
+ }
+ else
+ {
+ N = 1;
+ ErrCnt[Defect] = ErrCnt[Defect] + 1;
+ printf ("This is a DEFECT!\n");
+ }
+ }
+ V9 = Z * One;
+ Random1 = V9;
+ V9 = One * Z;
+ Random2 = V9;
+ V9 = Z / One;
+ if ((Z == Random1) && (Z == Random2) && (Z == V9))
+ {
+ if (N > 0)
+ Pause ();
+ }
+ else
+ {
+ N = 1;
+ BadCond (Defect, "What prints as Z = ");
+ printf ("%s\n\tcompares different from ", Z.str());
+ if (Z != Random1)
+ printf ("Z * 1 = %s ", Random1.str());
+ if (!((Z == Random2) || (Random2 == Random1)))
+ printf ("1 * Z == %s\n", Random2.str());
+ if (!(Z == V9))
+ printf ("Z / 1 = %s\n", V9.str());
+ if (Random2 != Random1)
+ {
+ ErrCnt[Defect] = ErrCnt[Defect] + 1;
+ BadCond (Defect, "Multiplication does not commute!\n");
+ printf ("\tComparison alleges that 1 * Z = %s\n", Random2.str());
+ printf ("\tdiffers from Z * 1 = %s\n", Random1.str());
+ }
+ Pause ();
+ }
+ }
+}
+
+template<typename FLOAT>
+void
+Paranoia<FLOAT>::notify (const char *s)
+{
+ printf ("%s test appears to be inconsistent...\n", s);
+ printf (" PLEASE NOTIFY KARPINKSI!\n");
+}
+
+/* ====================================================================== */
+
+int main(int ac, char **av)
+{
+ init_real_once ();
+
+ while (1)
+ switch (getopt (ac, av, "pvg:fdl"))
+ {
+ case -1:
+ return 0;
+ case 'p':
+ do_pause = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'g':
+ {
+ int size = strtol (optarg, 0, 0);
+
+ switch (size)
+ {
+ case 32:
+ Paranoia< real_c_float<32, SFmode> >().main();
+ break;
+
+ case 64:
+ Paranoia< real_c_float<64, DFmode> >().main();
+ break;
+
+ case 96:
+ Paranoia< real_c_float<96, XFmode> >().main();
+ break;
+
+ case 128:
+ Paranoia< real_c_float<128, TFmode> >().main();
+ break;
+
+ default:
+ puts ("Invalid gcc implementation size.");
+ return 1;
+ }
+ break;
+ }
+
+ case 'f':
+ Paranoia < native_float<float> >().main();
+ break;
+ case 'd':
+ Paranoia < native_float<double> >().main();
+ break;
+ case 'l':
+#ifndef NO_LONG_DOUBLE
+ Paranoia < native_float<long double> >().main();
+#endif
+ break;
+
+ case '?':
+ puts ("-p\tpause between pages");
+ puts ("-g<N>\treal.c implementation size N");
+ puts ("-f\tnative float");
+ puts ("-d\tnative double");
+ puts ("-l\tnative long double");
+ return 0;
+ }
+}
+
+/* GCC stuff referenced by real.o. */
+
+extern "C" void
+fancy_abort ()
+{
+ abort ();
+}
+
+int target_flags = 0;
+
+extern "C"
+enum machine_mode
+mode_for_size (unsigned int size, enum mode_class, int)
+{
+ switch (size)
+ {
+ case 32:
+ return SFmode;
+ case 64:
+ return DFmode;
+ case 96:
+ return XFmode;
+ case 128:
+ return TFmode;
+ }
+ abort ();
+}
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b9611076c32..a54214ca7ae 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,34 @@
+2002-09-16 Richard Henderson <rth@redhat.com>
+
+ * real.c, real.h: Rewrite from scratch.
+
+ * Makefile.in (simplify-rtx.o): Depend on TREE_H.
+ (paranoia): New target.
+ * builtins.c (fold_builtin_inf): Use new real.h interface.
+ * c-common.c (builtin_define_with_hex_fp_value): Likewise.
+ * c-lex.c (interpret_float): Likewise.
+ * emit-rtl.c (gen_lowpart_common): Likewise.
+ * optabs.c (expand_float): Use real_2expN.
+ * config/ia64/ia64.md (divsi3, udivsi3): Likewise.
+ * defaults.h (INTEL_EXTENDED_IEEE_FORMAT): New.
+ (FLOAT_WORDS_BIG_ENDIAN): New.
+ * cse.c (find_comparison_args): Don't pass FLOAT_STORE_FLAG_VALUE
+ directly to REAL_VALUE_NEGATIVE.
+ * loop.c (canonicalize_condition): Likewise.
+ * simplify-rtx.c: Include tree.h.
+ (simplify_unary_operation): Don't handle FIX and UNSIGNED_FIX
+ with floating-point result modes.
+ * toplev.c (backend_init): Call init_real_once.
+
+ * fold-const.c (force_fit_type): Don't call CHECK_FLOAT_VALUE.
+ * tree.c (build_real): Likewise.
+ * config/alpha/alpha.c, config/vax/vax.c (float_strings,
+ float_values, inited_float_values, check_float_value): Remove.
+ * config/alpha/alpha.h, config/m68hc11/m68hc11.h,
+ config/m88k/m88k.h, config/vax/vax.h (CHECK_FLOAT_VALUE): Remove.
+ * doc/tm.texi (CHECK_FLOAT_VALUE): Remove.
+ (VAX_HALFWORD_ORDER): Remove.
+
2002-09-16 Ulrich Weigand <uweigand@de.ibm.com>
* config/s390/s390.c: (legitimize_la_operand): Remove, replace by ...
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index ad51e9fc86f..df9ba312cc3 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1473,7 +1473,7 @@ jump.o : jump.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) flags.h hard-reg-set.h $(REGS_H
simplify-rtx.o : simplify-rtx.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
- output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H)
+ output.h function.h $(GGC_H) $(OBSTACK_H) $(TM_P_H) $(TREE_H)
cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
output.h function.h cselib.h $(GGC_H) $(TM_P_H) gt-cselib.h
@@ -3260,6 +3260,15 @@ ${QMTEST_DIR}/gpp-expected.qmr: ${QMTEST_DIR}/context
.PHONY: qmtest-g++
+# Run Paranoia on real.c.
+
+paranoia.o: $(srcdir)/../contrib/paranoia.cc $(CONFIG_H) $(SYSTEM_H) \
+ real.h $(TREE_H)
+ g++ -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+
+paranoia: paranoia.o real.o $(LIBIBERTY)
+ g++ -o $@ paranoia.o real.o $(LIBIBERTY)
+
# These exist for maintenance purposes.
# Update the tags table.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 7b2841bcae9..2e7cd53323b 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -4140,10 +4140,13 @@ fold_builtin_inf (type, warn)
tree type;
int warn;
{
+ REAL_VALUE_TYPE real;
+
if (!MODE_HAS_INFINITIES (TYPE_MODE (type)) && warn)
warning ("target format does not support infinity");
- return build_real (type, ereal_inf (TYPE_MODE (type)));
+ real_inf (&real);
+ return build_real (type, real);
}
/* Used by constant folding to eliminate some builtin calls early. EXP is
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 7feabee95a2..34941e008ae 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -5266,7 +5266,7 @@ builtin_define_with_int_value (macro, value)
static void
builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix)
const char *macro;
- tree type;
+ tree type ATTRIBUTE_UNUSED;
int digits;
const char *hex_str;
const char *fp_suffix;
@@ -5284,8 +5284,8 @@ builtin_define_with_hex_fp_value (macro, type, digits, hex_str, fp_suffix)
it's easy to get the exact correct value), parse it as a real,
then print it back out as decimal. */
- real = REAL_VALUE_HTOF (hex_str, TYPE_MODE (type));
- REAL_VALUE_TO_DECIMAL (real, dec_str, digits);
+ real_from_string (&real, hex_str);
+ real_to_decimal (dec_str, &real, digits);
sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
cpp_define (parse_in, buf);
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index 2d1ad3415a9..f2e9d5d1629 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -925,13 +925,8 @@ interpret_float (token, flags)
memcpy (copy, token->val.str.text, copylen);
copy[copylen] = '\0';
- /* The second argument, machine_mode, of REAL_VALUE_ATOF tells the
- desired precision of the binary result of decimal-to-binary
- conversion. */
- if (flags & CPP_N_HEX)
- real = REAL_VALUE_HTOF (copy, TYPE_MODE (type));
- else
- real = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+ real_from_string (&real, copy);
+ real_convert (&real, TYPE_MODE (type), &real);
/* A diagnostic is required for "soft" overflow by some ISO C
testsuites. This is not pedwarn, because some people don't want
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index d5b8099718e..dcd377f63e4 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -8880,83 +8880,6 @@ alpha_reorg (insns)
}
}
-/* Check a floating-point value for validity for a particular machine mode. */
-
-static const char * const float_strings[] =
-{
- /* These are for FLOAT_VAX. */
- "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
- "-1.70141173319264430e+38",
- "2.93873587705571877e-39", /* 2^-128 */
- "-2.93873587705571877e-39",
- /* These are for the default broken IEEE mode, which traps
- on infinity or denormal numbers. */
- "3.402823466385288598117e+38", /* 2^128 (1 - 2^-24) */
- "-3.402823466385288598117e+38",
- "1.1754943508222875079687e-38", /* 2^-126 */
- "-1.1754943508222875079687e-38",
-};
-
-static REAL_VALUE_TYPE float_values[8];
-static int inited_float_values = 0;
-
-int
-check_float_value (mode, d, overflow)
- enum machine_mode mode;
- REAL_VALUE_TYPE *d;
- int overflow ATTRIBUTE_UNUSED;
-{
-
- if (TARGET_IEEE || TARGET_IEEE_CONFORMANT || TARGET_IEEE_WITH_INEXACT)
- return 0;
-
- if (inited_float_values == 0)
- {
- int i;
- for (i = 0; i < 8; i++)
- float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
-
- inited_float_values = 1;
- }
-
- if (mode == SFmode)
- {
- REAL_VALUE_TYPE r;
- REAL_VALUE_TYPE *fvptr;
-
- if (TARGET_FLOAT_VAX)
- fvptr = &float_values[0];
- else
- fvptr = &float_values[4];
-
- memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
- if (REAL_VALUES_LESS (fvptr[0], r))
- {
- memcpy (d, &fvptr[0], sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- else if (REAL_VALUES_LESS (r, fvptr[1]))
- {
- memcpy (d, &fvptr[1], sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- else if (REAL_VALUES_LESS (dconst0, r)
- && REAL_VALUES_LESS (r, fvptr[2]))
- {
- memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- else if (REAL_VALUES_LESS (r, dconst0)
- && REAL_VALUES_LESS (fvptr[3], r))
- {
- memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- }
-
- return 0;
-}
-
#ifdef OBJECT_FORMAT_ELF
/* Switch to the section to which we should output X. The only thing
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index c3bce2ee9f6..4d1d1f4c5c3 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -1779,11 +1779,6 @@ do { \
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf ((LABEL), "*$%s%ld", (PREFIX), (long)(NUM))
-/* Check a floating-point value for validity for a particular machine mode. */
-
-#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
- ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW))
-
/* We use the default ASCII-output routine, except that we don't write more
than 50 characters since the assembler doesn't support very long lines. */
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index 1275acdc17e..b5896521597 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -1990,6 +1990,7 @@
"INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
{
rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
+ REAL_VALUE_TYPE twon34_r;
op0_tf = gen_reg_rtx (TFmode);
op0_di = gen_reg_rtx (DImode);
@@ -2005,14 +2006,9 @@
expand_float (op2_tf, operands[2], 0);
/* 2^-34 */
-#if 0
- twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
- (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
+ real_2expN (&twon34_r, -34);
+ twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, TFmode);
twon34 = force_reg (TFmode, twon34);
-#else
- twon34 = gen_reg_rtx (TFmode);
- convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
-#endif
emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));
@@ -2051,6 +2047,7 @@
"INTEL_EXTENDED_IEEE_FORMAT && TARGET_INLINE_DIV"
{
rtx op1_tf, op2_tf, op0_tf, op0_di, twon34;
+ REAL_VALUE_TYPE twon34_r;
op0_tf = gen_reg_rtx (TFmode);
op0_di = gen_reg_rtx (DImode);
@@ -2066,14 +2063,9 @@
expand_float (op2_tf, operands[2], 1);
/* 2^-34 */
-#if 0
- twon34 = (CONST_DOUBLE_FROM_REAL_VALUE
- (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), TFmode));
+ real_2expN (&twon34_r, -34);
+ twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, TFmode);
twon34 = force_reg (TFmode, twon34);
-#else
- twon34 = gen_reg_rtx (TFmode);
- convert_move (twon34, force_const_mem (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_FROM_TARGET_SINGLE (0x2e800000), SFmode)), 0);
-#endif
emit_insn (gen_divsi3_internal (op0_tf, op1_tf, op2_tf, twon34));
diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h
index d42dab13e12..bdd3fe198f9 100644
--- a/gcc/config/m68hc11/m68hc11.h
+++ b/gcc/config/m68hc11/m68hc11.h
@@ -303,11 +303,6 @@ extern const struct processor_costs *m68hc11_cost;
this size or smaller can be used for structures and unions with the
appropriate sizes. */
#define MAX_FIXED_MODE_SIZE 64
-
-/* Floats are checked in a generic way. */
-/* #define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) */
-
-
/* target machine storage layout */
diff --git a/gcc/config/m88k/m88k.h b/gcc/config/m88k/m88k.h
index bdd323b031a..4cd5075832c 100644
--- a/gcc/config/m88k/m88k.h
+++ b/gcc/config/m88k/m88k.h
@@ -389,14 +389,6 @@ extern int flag_pic; /* -fpic */
/* Maximum size (in bits) to use for the largest integral type that
replaces a BLKmode type. */
/* #define MAX_FIXED_MODE_SIZE 0 */
-
-/* Check a `double' value for validity for a particular machine mode.
- This is defined to avoid crashes outputting certain constants.
- Since we output the number in hex, the assembler won't choke on it. */
-/* #define CHECK_FLOAT_VALUE(MODE,VALUE) */
-
-/* A code distinguishing the floating point format of the target machine. */
-/* #define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT */
/*** Register Usage ***/
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index ded7570f32d..705818fde0f 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -696,75 +696,6 @@ vax_rtx_cost (x)
}
return c;
}
-
-/* Check a `double' value for validity for a particular machine mode. */
-
-static const char *const float_strings[] =
-{
- "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
- "-1.70141173319264430e+38",
- "2.93873587705571877e-39", /* 2^-128 */
- "-2.93873587705571877e-39"
-};
-
-static REAL_VALUE_TYPE float_values[4];
-
-static int inited_float_values = 0;
-
-
-int
-check_float_value (mode, d, overflow)
- enum machine_mode mode;
- REAL_VALUE_TYPE *d;
- int overflow;
-{
- if (inited_float_values == 0)
- {
- int i;
- for (i = 0; i < 4; i++)
- {
- float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
- }
-
- inited_float_values = 1;
- }
-
- if (overflow)
- {
- memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
- return 1;
- }
-
- if ((mode) == SFmode)
- {
- REAL_VALUE_TYPE r;
- memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
- if (REAL_VALUES_LESS (float_values[0], r))
- {
- memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- else if (REAL_VALUES_LESS (r, float_values[1]))
- {
- memcpy (d, &float_values[1], sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- else if (REAL_VALUES_LESS (dconst0, r)
- && REAL_VALUES_LESS (r, float_values[2]))
- {
- memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- else if (REAL_VALUES_LESS (r, dconst0)
- && REAL_VALUES_LESS (float_values[3], r))
- {
- memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
- return 1;
- }
- }
-
- return 0;
-}
#if VMS_TARGET
/* Additional support code for VMS target. */
diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
index 3d9767847b3..fed8ac4fa12 100644
--- a/gcc/config/vax/vax.h
+++ b/gcc/config/vax/vax.h
@@ -885,32 +885,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
#define UDIVSI3_LIBCALL "*udiv"
#define UMODSI3_LIBCALL "*urem"
-
-/* Check a `double' value for validity for a particular machine mode. */
-
-/* note that it is very hard to accidentally create a number that fits in a
- double but not in a float, since their ranges are almost the same */
-
-#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
- ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW))
-
-/* For future reference:
- D Float: 9 bit, sign magnitude, excess 128 binary exponent
- normalized 56 bit fraction, redundant bit not represented
- approximately 16 decimal digits of precision
-
- The values to use if we trust decimal to binary conversions:
-#define MAX_D_FLOAT 1.7014118346046923e+38
-#define MIN_D_FLOAT .29387358770557188e-38
-
- G float: 12 bit, sign magnitude, excess 1024 binary exponent
- normalized 53 bit fraction, redundant bit not represented
- approximately 15 decimal digits precision
-
- The values to use if we trust decimal to binary conversions:
-#define MAX_G_FLOAT .898846567431157e+308
-#define MIN_G_FLOAT .556268464626800e-308
-*/
/* Tell final.c how to eliminate redundant test instructions. */
diff --git a/gcc/cse.c b/gcc/cse.c
index 0096e206d21..adaf20d32b4 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -3147,13 +3147,17 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
else if (GET_RTX_CLASS (GET_CODE (arg1)) == '<')
{
+#ifdef FLOAT_STORE_FLAG_VALUE
+ REAL_VALUE_TYPE fsfv;
+#endif
+
if (code == NE
|| (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_INT
&& code == LT && STORE_FLAG_VALUE == -1)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
x = arg1;
@@ -3162,8 +3166,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
&& code == GE && STORE_FLAG_VALUE == -1)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
x = arg1, reverse_code = 1;
@@ -3199,6 +3203,9 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
for (; p; p = p->next_same_value)
{
enum machine_mode inner_mode = GET_MODE (p->exp);
+#ifdef FLOAT_STORE_FLAG_VALUE
+ REAL_VALUE_TYPE fsfv;
+#endif
/* If the entry isn't valid, skip it. */
if (! exp_equiv_p (p->exp, p->exp, 1, 0))
@@ -3223,8 +3230,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == LT
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
&& GET_RTX_CLASS (GET_CODE (p->exp)) == '<'))
@@ -3243,8 +3250,8 @@ find_comparison_args (code, parg1, parg2, pmode1, pmode2)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == GE
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
)
&& GET_RTX_CLASS (GET_CODE (p->exp)) == '<')
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 371f17d7248..17b8bf9a29e 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -564,6 +564,17 @@ You Lose! You must define PREFERRED_DEBUGGING_TYPE!
&& !ROUND_TOWARDS_ZERO)
#endif
+#ifndef INTEL_EXTENDED_IEEE_FORMAT
+#define INTEL_EXTENDED_IEEE_FORMAT 0
+#endif
+
+/* If FLOAT_WORDS_BIG_ENDIAN and HOST_FLOAT_WORDS_BIG_ENDIAN are not defined
+ in the header files, then this implies the word-endianness is the same as
+ for integers. */
+#ifndef FLOAT_WORDS_BIG_ENDIAN
+#define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
#ifndef TARGET_FLT_EVAL_METHOD
#define TARGET_FLT_EVAL_METHOD 0
#endif
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 6977f5646c4..4629a12ca31 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1291,22 +1291,6 @@ You need not define this macro if it always returns @code{word_mode}.
You would most commonly define this macro if the @code{allocate_stack}
pattern needs to support both a 32- and a 64-bit mode.
-@findex CHECK_FLOAT_VALUE
-@item CHECK_FLOAT_VALUE (@var{mode}, @var{value}, @var{overflow})
-A C statement to validate the value @var{value} (of type
-@code{double}) for mode @var{mode}. This means that you check whether
-@var{value} fits within the possible range of values for mode
-@var{mode} on this target machine. The mode @var{mode} is always
-a mode of class @code{MODE_FLOAT}. @var{overflow} is nonzero if
-the value is already known to be out of range.
-
-If @var{value} is not valid or if @var{overflow} is nonzero, you should
-set @var{overflow} to 1 and then assign some valid value to @var{value}.
-Allowing an invalid value to go through the compiler can produce
-incorrect assembler code which may even cause Unix assemblers to crash.
-
-This macro need not be defined if there is no work for it to do.
-
@findex TARGET_FLOAT_FORMAT
@item TARGET_FLOAT_FORMAT
A code distinguishing the floating point format of the target machine.
@@ -1343,13 +1327,6 @@ defined for them.
The ordering of the component words of floating point values stored in
memory is controlled by @code{FLOAT_WORDS_BIG_ENDIAN}.
-@findex VAX_HALFWORD_ORDER
-@item VAX_HALFWORD_ORDER
-This macro is only used if @code{TARGET_FLOAT_FORMAT} is
-@code{VAX_FLOAT_FORMAT}. If defaulted or defined as 1, the halfwords of
-the generated floating point data are in the order used by the VAX. If
-defined as 0, they are reversed, which is used by the PDP-11 target.
-
@findex MODE_HAS_NANS
@item MODE_HAS_NANS (@var{mode})
When defined, this macro should be true if @var{mode} has a NaN
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index b8297a8808c..70a1228450e 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1042,10 +1042,9 @@ gen_lowpart_common (mode, x)
&& GET_CODE (x) == CONST_INT)
{
REAL_VALUE_TYPE r;
- HOST_WIDE_INT i;
+ long i = INTVAL (x);
- i = INTVAL (x);
- r = REAL_VALUE_FROM_TARGET_SINGLE (i);
+ real_from_target (&r, &i, mode);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
else if (GET_MODE_CLASS (mode) == MODE_FLOAT
@@ -1054,8 +1053,8 @@ gen_lowpart_common (mode, x)
&& GET_MODE (x) == VOIDmode)
{
REAL_VALUE_TYPE r;
- HOST_WIDE_INT i[2];
HOST_WIDE_INT low, high;
+ long i[2];
if (GET_CODE (x) == CONST_INT)
{
@@ -1068,18 +1067,17 @@ gen_lowpart_common (mode, x)
high = CONST_DOUBLE_HIGH (x);
}
-#if HOST_BITS_PER_WIDE_INT == 32
+ if (HOST_BITS_PER_WIDE_INT > 32)
+ high = low >> 31 >> 1;
+
/* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the
target machine. */
if (WORDS_BIG_ENDIAN)
i[0] = high, i[1] = low;
else
i[0] = low, i[1] = high;
-#else
- i[0] = low;
-#endif
- r = REAL_VALUE_FROM_TARGET_DOUBLE (i);
+ real_from_target (&r, i, mode);
return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
}
else if ((GET_MODE_CLASS (mode) == MODE_INT
diff --git a/gcc/f/ChangeLog b/gcc/f/ChangeLog
index 50c32fecf90..658babde4cb 100644
--- a/gcc/f/ChangeLog
+++ b/gcc/f/ChangeLog
@@ -1,3 +1,11 @@
+2002-09-16 Richard Henderson <rth@redhat.com>
+
+ * target.c (ffetarget_real1): Don't pass FFETARGET_ATOF_
+ directly to ffetarget_make_real1.
+ (ffetarget_real2): Similarly.
+ * target.h (ffetarget_cvt_r1_to_rv_, ffetarget_cvt_rv_to_r2_,
+ ffetarget_cvt_r2_to_rv_): Use new real.h interface and simplify.
+
2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
* intdoc.texi: Regenerate.
diff --git a/gcc/f/target.c b/gcc/f/target.c
index 1ea4fa2ec88..82ae955ebec 100644
--- a/gcc/f/target.c
+++ b/gcc/f/target.c
@@ -2277,9 +2277,11 @@ ffetarget_real1 (ffetargetReal1 *value, ffelexToken integer,
*p = '\0';
- ffetarget_make_real1 (value,
- FFETARGET_ATOF_ (ptr,
- SFmode));
+ {
+ REAL_VALUE_TYPE rv;
+ rv = FFETARGET_ATOF_ (ptr, SFmode);
+ ffetarget_make_real1 (value, rv);
+ }
if (sz > ARRAY_SIZE (ffetarget_string_))
malloc_kill_ks (malloc_pool_image (), ptr, sz);
@@ -2363,9 +2365,11 @@ ffetarget_real2 (ffetargetReal2 *value, ffelexToken integer,
*p = '\0';
- ffetarget_make_real2 (value,
- FFETARGET_ATOF_ (ptr,
- DFmode));
+ {
+ REAL_VALUE_TYPE rv;
+ rv = FFETARGET_ATOF_ (ptr, DFmode);
+ ffetarget_make_real2 (value, rv);
+ }
if (sz > ARRAY_SIZE (ffetarget_string_))
malloc_kill_ks (malloc_pool_image (), ptr, sz);
diff --git a/gcc/f/target.h b/gcc/f/target.h
index 0601c4a468b..2716a7b559f 100644
--- a/gcc/f/target.h
+++ b/gcc/f/target.h
@@ -331,54 +331,30 @@ typedef ? ffetargetLogical8;
?
#endif
#if FFETARGET_okREAL1
-#ifdef FFETARGET_32bit_longs
-typedef long int ffetargetReal1;
-#define ffetargetReal1_f "l"
-#define ffetarget_cvt_r1_to_rv_ REAL_VALUE_UNTO_TARGET_SINGLE
-#define ffetarget_cvt_rv_to_r1_ REAL_VALUE_TO_TARGET_SINGLE
-#else
typedef int ffetargetReal1;
#define ffetargetReal1_f ""
-#define ffetarget_cvt_r1_to_rv_(in) \
- ({ REAL_VALUE_TYPE _rv; \
- _rv = REAL_VALUE_UNTO_TARGET_SINGLE ((long) (in)); \
+#define ffetarget_cvt_r1_to_rv_(in) \
+ ({ REAL_VALUE_TYPE _rv; \
+ long _in = (in); \
+ real_from_target (&_rv, &_in, mode_for_size (32, MODE_FLOAT, 0)); \
_rv; })
#define ffetarget_cvt_rv_to_r1_(in, out) \
({ long _tmp; \
REAL_VALUE_TO_TARGET_SINGLE ((in), _tmp); \
(out) = (ffetargetReal1) _tmp; })
#endif
-#endif
#if FFETARGET_okREAL2
-#ifdef FFETARGET_32bit_longs
-typedef struct
- {
- long int v[2];
- }
-ffetargetReal2;
-#define ffetargetReal2_f "l"
-#define ffetarget_cvt_r2_to_rv_ REAL_VALUE_UNTO_TARGET_DOUBLE
-#define ffetarget_cvt_rv_to_r2_ REAL_VALUE_TO_TARGET_DOUBLE
-#else
-typedef struct
- {
- int v[2];
- }
-ffetargetReal2;
+typedef struct { int v[2]; } ffetargetReal2;
#define ffetargetReal2_f ""
-#define ffetarget_cvt_r2_to_rv_(in) \
- ({ REAL_VALUE_TYPE _rv; \
- long _tmp[2]; \
- _tmp[0] = (in)[0]; \
- _tmp[1] = (in)[1]; \
- _rv = REAL_VALUE_UNTO_TARGET_DOUBLE (_tmp); \
+#define ffetarget_cvt_r2_to_rv_(in) \
+ ({ REAL_VALUE_TYPE _rv; long _tmp[2]; \
+ _tmp[0] = (in)[0]; _tmp[1] = (in)[1]; \
+ real_from_target (&_rv, _tmp, mode_for_size (64, MODE_FLOAT, 0)); \
_rv; })
-#define ffetarget_cvt_rv_to_r2_(in, out) \
- ({ long _tmp[2]; \
- REAL_VALUE_TO_TARGET_DOUBLE ((in), _tmp); \
- (out)[0] = (int) (_tmp[0]); \
- (out)[1] = (int) (_tmp[1]); })
-#endif
+#define ffetarget_cvt_rv_to_r2_(in, out) \
+ ({ long _tmp[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE ((in), _tmp); \
+ (out)[0] = (int)_tmp[0]; (out)[1] = (int)_tmp[1]; })
#endif
#if FFETARGET_okREAL3
typedef long ffetargetReal3[?];
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 1b2124a737e..c1ea09d7a5a 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -178,10 +178,7 @@ decode (words, low, hi)
Return 1 if a signed overflow occurs, 0 otherwise. If OVERFLOW is
nonzero, a signed overflow has already occurred in calculating T, so
- propagate it.
-
- Make the real constant T valid for its type by calling CHECK_FLOAT_VALUE,
- if it exists. */
+ propagate it. */
int
force_fit_type (t, overflow)
@@ -194,10 +191,8 @@ force_fit_type (t, overflow)
if (TREE_CODE (t) == REAL_CST)
{
-#ifdef CHECK_FLOAT_VALUE
- CHECK_FLOAT_VALUE (TYPE_MODE (TREE_TYPE (t)), TREE_REAL_CST (t),
- overflow);
-#endif
+ /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
+ Consider doing it via real_convert now. */
return overflow;
}
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index c8b4e8c521c..ac1b565950f 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,10 @@
+2002-09-16 Richard Henderson <rth@redhat.com>
+
+ * jcf-parse.c (get_constant): Runtime check for IEEE format;
+ use new real.h interface.
+ * jcf-write.c (find_constant_index): Use new real.h interface.
+ * lex.c (IS_ZERO): Use REAL_VALUES_EQUAL.
+
2002-09-15 Kazu Hirata <kazu@cs.umass.edu>
* lang.c: Follow spelling conventions.
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index fc755f0ce71..29ccf6328df 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -290,47 +290,44 @@ get_constant (jcf, index)
force_fit_type (value, 0);
break;
}
-#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
+
case CONSTANT_Float:
- {
- jint num = JPOOL_INT(jcf, index);
- REAL_VALUE_TYPE d;
- d = REAL_VALUE_FROM_TARGET_SINGLE (num);
- value = build_real (float_type_node, d);
- break;
- }
+ /* ??? Even more ideal would be to import the number using the
+ IEEE decode routines, then use whatever format the target
+ actually uses. This would enable Java on VAX to kind work. */
+ if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+ {
+ jint num = JPOOL_INT(jcf, index);
+ long buf = num;
+ REAL_VALUE_TYPE d;
+ real_from_target (&d, &buf, SFmode);
+ value = build_real (float_type_node, d);
+ break;
+ }
+ else
+ goto bad;
+
case CONSTANT_Double:
- {
- HOST_WIDE_INT num[2];
- REAL_VALUE_TYPE d;
- HOST_WIDE_INT lo, hi;
- num[0] = JPOOL_UINT (jcf, index);
- lshift_double (num[0], 0, 32, 64, &lo, &hi, 0);
- num[0] = JPOOL_UINT (jcf, index+1);
- add_double (lo, hi, num[0], 0, &lo, &hi);
-
- /* Since ereal_from_double expects an array of HOST_WIDE_INT
- in the target's format, we swap the elements for big endian
- targets, unless HOST_WIDE_INT is sufficiently large to
- contain a target double, in which case the 2nd element
- is ignored.
-
- FIXME: Is this always right for cross targets? */
- if (FLOAT_WORDS_BIG_ENDIAN && sizeof(num[0]) < 8)
- {
- num[0] = hi;
- num[1] = lo;
- }
- else
- {
- num[0] = lo;
- num[1] = hi;
- }
- d = REAL_VALUE_FROM_TARGET_DOUBLE (num);
- value = build_real (double_type_node, d);
- break;
- }
-#endif /* TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT */
+ if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT)
+ {
+ long buf[2], lo, hi;
+ REAL_VALUE_TYPE d;
+
+ hi = JPOOL_UINT (jcf, index);
+ lo = JPOOL_UINT (jcf, index+1);
+
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = hi, buf[1] = lo;
+ else
+ buf[0] = lo, buf[1] = hi;
+
+ real_from_target (&d, buf, DFmode);
+ value = build_real (double_type_node, d);
+ break;
+ }
+ else
+ goto bad;
+
case CONSTANT_String:
{
tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c
index 076912505e5..1a9f1075e23 100644
--- a/gcc/java/jcf-write.c
+++ b/gcc/java/jcf-write.c
@@ -826,21 +826,18 @@ find_constant_index (value, state)
else if (TREE_CODE (value) == REAL_CST)
{
long words[2];
+
+ real_to_target (words, &TREE_REAL_CST (value),
+ TYPE_MODE (TREE_TYPE (value)));
+ words[0] &= 0xffffffff;
+ words[1] &= 0xffffffff;
+
if (TYPE_PRECISION (TREE_TYPE (value)) == 32)
- {
- words[0] = etarsingle (TREE_REAL_CST (value)) & 0xFFFFFFFF;
- return find_constant1 (&state->cpool, CONSTANT_Float,
- (jword)words[0]);
- }
+ return find_constant1 (&state->cpool, CONSTANT_Float, (jword)words[0]);
else
- {
- etardouble (TREE_REAL_CST (value), words);
- return find_constant2 (&state->cpool, CONSTANT_Double,
- (jword)(words[1-FLOAT_WORDS_BIG_ENDIAN] &
- 0xFFFFFFFF),
- (jword)(words[FLOAT_WORDS_BIG_ENDIAN] &
- 0xFFFFFFFF));
- }
+ return find_constant2 (&state->cpool, CONSTANT_Double,
+ (jword)words[1-FLOAT_WORDS_BIG_ENDIAN],
+ (jword)words[FLOAT_WORDS_BIG_ENDIAN]);
}
else if (TREE_CODE (value) == STRING_CST)
return find_string_constant (&state->cpool, value);
diff --git a/gcc/java/lex.c b/gcc/java/lex.c
index 5659ed2a1f5..026d3cacbd6 100644
--- a/gcc/java/lex.c
+++ b/gcc/java/lex.c
@@ -834,7 +834,7 @@ java_parse_escape_sequence ()
}
#ifndef JC1_LITE
-#define IS_ZERO(X) (ereal_cmp (X, dconst0) == 0)
+#define IS_ZERO(X) REAL_VALUES_EQUAL (X, dconst0)
/* Subroutine of java_lex: converts floating-point literals to tree
nodes. LITERAL_TOKEN is the input literal, JAVA_LVAL is where to
diff --git a/gcc/loop.c b/gcc/loop.c
index 0c634e7eeda..1e2709f8aae 100644
--- a/gcc/loop.c
+++ b/gcc/loop.c
@@ -9292,6 +9292,9 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
if (set)
{
enum machine_mode inner_mode = GET_MODE (SET_DEST (set));
+#ifdef FLOAT_STORE_FLAG_VALUE
+ REAL_VALUE_TYPE fsfv;
+#endif
/* ??? We may not combine comparisons done in a CCmode with
comparisons not done in a CCmode. This is to aid targets
@@ -9319,8 +9322,8 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == LT
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (inner_mode))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
))
&& GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'))
@@ -9339,8 +9342,8 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
#ifdef FLOAT_STORE_FLAG_VALUE
|| (code == GE
&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
- && (REAL_VALUE_NEGATIVE
- (FLOAT_STORE_FLAG_VALUE (inner_mode))))
+ && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
+ REAL_VALUE_NEGATIVE (fsfv)))
#endif
))
&& GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'
diff --git a/gcc/optabs.c b/gcc/optabs.c
index f098aa6a092..01121714692 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -4626,10 +4626,8 @@ expand_float (to, from, unsignedp)
emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
0, label);
- /* On SCO 3.2.1, ldexp rejects values outside [0.5, 1).
- Rather than setting up a dconst_dot_5, let's hope SCO
- fixes the bug. */
- offset = REAL_VALUE_LDEXP (dconst1, GET_MODE_BITSIZE (GET_MODE (from)));
+
+ real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)));
temp = expand_binop (fmode, add_optab, target,
CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
target, 0, OPTAB_LIB_WIDEN);
@@ -4812,7 +4810,7 @@ expand_fix (to, from, unsignedp)
rtx limit, lab1, lab2, insn;
bitsize = GET_MODE_BITSIZE (GET_MODE (to));
- offset = REAL_VALUE_LDEXP (dconst1, bitsize - 1);
+ real_2expN (&offset, bitsize - 1);
limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
lab1 = gen_label_rtx ();
lab2 = gen_label_rtx ();
diff --git a/gcc/real.c b/gcc/real.c
index fc0f57a1eed..61ab02ce6a9 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -1,6776 +1,3924 @@
-/* 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.
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 "real.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).
-
-Machine files (tm.h etc) 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 first part of this file interfaces gcc to a floating point
-arithmetic suite that was not written with gcc in mind. Avoid
-changing the low-level arithmetic routines unless you have suitable
-test programs available. A special version of the PARANOIA floating
-point arithmetic tester, modified for this purpose, can be found on
-usc.edu: /pub/C-numanal/ieeetest.zoo. Other tests, and libraries of
-XFmode and TFmode transcendental functions, can be obtained by ftp from
-netlib.att.com: netlib/cephes. */
-
-/* Type of computer arithmetic.
- Only one of DEC, IBM, IEEE, C4X, or UNK should get defined.
-
- `IEEE', when REAL_WORDS_BIG_ENDIAN is non-zero, refers generically
- to big-endian IEEE floating-point data structure. This definition
- should work in SFmode `float' type and DFmode `double' type on
- virtually all big-endian IEEE machines. If LONG_DOUBLE_TYPE_SIZE
- has been defined to be 96, then IEEE also invokes the particular
- XFmode (`long double' type) data structure used by the Motorola
- 680x0 series processors.
-
- `IEEE', when REAL_WORDS_BIG_ENDIAN is zero, refers generally to
- little-endian IEEE machines. In this case, if LONG_DOUBLE_TYPE_SIZE
- has been defined to be 96, then IEEE also invokes the particular
- XFmode `long double' data structure used by the Intel 80x86 series
- processors.
-
- `DEC' refers specifically to the Digital Equipment Corp PDP-11
- and VAX floating point data structure. This model currently
- supports no type wider than DFmode.
-
- `IBM' refers specifically to the IBM System/370 and compatible
- floating point data structure. This model currently supports
- no type wider than DFmode. The IBM conversions were contributed by
- frank@atom.ansto.gov.au (Frank Crawford).
-
- `C4X' refers specifically to the floating point format used on
- Texas Instruments TMS320C3x and TMS320C4x digital signal
- processors. This supports QFmode (32-bit float, double) and HFmode
- (40-bit long double) where BITS_PER_BYTE is 32. Unlike IEEE
- floats, C4x floats are not rounded to be even. The C4x conversions
- were contributed by m.hayes@elec.canterbury.ac.nz (Michael Hayes) and
- Haj.Ten.Brugge@net.HCC.nl (Herman ten Brugge).
-
- If LONG_DOUBLE_TYPE_SIZE = 64 (the default, unless tm.h defines it)
- then `long double' and `double' are both implemented, but they
- both mean DFmode.
-
- 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. */
-
-#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
-
-/* Make sure that the endianness is correct for IBM and DEC. */
-#if defined(DEC)
-#undef LARGEST_EXPONENT_IS_NORMAL
-#define LARGEST_EXPONENT_IS_NORMAL(x) 1
-#undef REAL_WORDS_BIG_ENDIAN
-/* Strangely enough, DEC float most closely resembles big endian IEEE */
-#define REAL_WORDS_BIG_ENDIAN 1
-/* ... but the halfwords are reversed from IEEE big endian. */
-#ifndef VAX_HALFWORD_ORDER
-#define VAX_HALFWORD_ORDER 1
-#endif
-#else
-#if defined(IBM)
-#if !REAL_WORDS_BIG_ENDIAN
- #error "Little-endian representations are not supported for IBM."
-#endif
-#endif
-#endif
+/* 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.
-#if defined(DEC) && !defined (TARGET_G_FLOAT)
-#define TARGET_G_FLOAT 0
-#endif
+ Specifically
-#ifndef VAX_HALFWORD_ORDER
-#define VAX_HALFWORD_ORDER 0
-#endif
+ x = s * b^e * \sum_{k=1}^p f_k * b^{-k}
-/* 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
+ 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.
-/* 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
- #error "You will have to modify this program to have a smaller unit size."
-#endif
-#endif
-#endif
-#endif
+ We differ from typical IEEE 754 encodings in that the entire
+ significand is fractional. Normalized significands are in the
+ range [0.5, 1.0).
-/* 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
+ 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.
-#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
- #error "You will have to modify this program to have a smaller unit size."
-#endif
-#endif
-#endif
-#endif
+ Both of these requirements are easily satisfied. The largest
+ target significand is 113 bits; we store 128. The smallest
+ denormal number fits in 17 exponent bits; we store 29.
-#if EMUSHORT_SIZE != 16
- #error "The host interface doesn't work if no 16-bit size exists."
-#endif
+ 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. */
-/* Calculate the size of the generic "e" type. This always has
- identical in-memory size to REAL_VALUE_TYPE. The sizes are supposed
- to be the same as well, but when REAL_VALUE_TYPE_SIZE is not evenly
- divisible by HOST_BITS_PER_WIDE_INT we have some padding in
- REAL_VALUE_TYPE.
- There are only two supported sizes: ten and six 16-bit words (160
- or 96 bits). */
-
-#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !INTEL_EXTENDED_IEEE_FORMAT
-/* TFmode */
-# define NE 10
-# define MAXDECEXP 4932
-# define MINDECEXP -4977
-#else
-# define NE 6
-# define MAXDECEXP 4932
-# define MINDECEXP -4956
-#endif
-/* Fail compilation if 2*NE is not the appropriate size.
- If HOST_BITS_PER_WIDE_INT is 64, we're going to have padding
- at the end of the array, because neither 96 nor 160 is
- evenly divisible by 64. */
-struct compile_test_dummy {
- char twice_NE_must_equal_sizeof_REAL_VALUE_TYPE
- [(sizeof (REAL_VALUE_TYPE) >= 2*NE) ? 1 : -1];
+/* Enumerate the special cases of numbers that we encounter. */
+enum real_value_class {
+ rvc_zero,
+ rvc_normal,
+ rvc_inf,
+ rvc_nan
};
-/* 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. */
-#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)
-
-/* 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
+/* Used to classify two numbers simultaneously. */
+#define CLASS2(A, B) ((A) << 2 | (B))
+
+/* An expanded form of the represented number. */
+
+#define SIGNIFICAND_BITS 128
+#define EXP_BITS (32 - 3)
+#define MAX_EXP ((1 << (EXP_BITS - 1)) - 1)
+#define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
+#define SIG_MSB ((unsigned long)1 << (HOST_BITS_PER_LONG - 1))
+
+#if HOST_BITS_PER_LONG != 64 && HOST_BITS_PER_LONG != 32
+ #error "Some constant folding done by hand to avoid shift count warnings"
#endif
-/* Information about the various IEEE precisions. At the moment, we only
- support exponents of 15 bits or less. */
-struct ieee_format
+struct real_value
{
- /* Precision. */
- int precision;
+ enum real_value_class class : 2;
+ unsigned int sign : 1;
+ int exp : EXP_BITS;
+ unsigned long sig[SIGSZ];
+};
- /* Size of the exponent in bits. */
- int expbits;
+/* Describes the properties of the specific target format in use. */
+struct real_format
+{
+ /* Move to and from the target bytes. */
+ void (*encode) (const struct real_format *, long *,
+ const struct real_value *);
+ void (*decode) (const struct real_format *, struct real_value *,
+ const long *);
- /* Overall size of the value in bits. */
- int bits;
+ /* The radix of the exponent and digits of the significand. */
+ int b;
- /* Mode used for representing the value. */
- enum machine_mode mode;
+ /* log2(b). */
+ int log2_b;
- /* Exponent adjustment for offsets. */
- EMULONG adjustment;
-};
+ /* Size of the significand in digits of radix B. */
+ int p;
-#ifdef IEEE
-/* IEEE float (24 bits). */
-static const struct ieee_format ieee_24 =
-{
- 24,
- 8,
- 32,
- SFmode,
- EXONE - 0x7f
-};
+ /* The minimum negative integer, x, such that b**(x-1) is normalized. */
+ int emin;
-/* IEEE double (53 bits). */
-static const struct ieee_format ieee_53 =
-{
- 53,
- 11,
- 64,
- DFmode,
- EXONE - 0x3ff
+ /* The maximum integer, x, such that b**(x-1) is representable. */
+ int emax;
+
+ /* Properties of the format. */
+ bool has_nans;
+ bool has_inf;
+ bool has_denorm;
+ bool has_signed_zero;
+ bool qnan_msb_set;
};
-#endif /* IEEE */
-/* IEEE extended double (64 bits). */
-static const struct ieee_format ieee_64 =
-{
- 64,
- 15,
- 80,
- XFmode,
- 0
-};
+static const struct real_format *fmt_for_mode[TFmode - QFmode + 1];
+
+
+static void get_zero PARAMS ((struct real_value *, int));
+static void get_canonical_qnan PARAMS ((struct real_value *, int));
+static void get_canonical_snan PARAMS ((struct real_value *, int));
+static void get_inf PARAMS ((struct real_value *, int));
+static void sticky_rshift_significand PARAMS ((struct real_value *,
+ const struct real_value *,
+ unsigned int));
+static void rshift_significand PARAMS ((struct real_value *,
+ const struct real_value *,
+ unsigned int));
+static void lshift_significand PARAMS ((struct real_value *,
+ const struct real_value *,
+ unsigned int));
+static void lshift_significand_1 PARAMS ((struct real_value *,
+ const struct real_value *));
+static bool add_significands PARAMS ((struct real_value *r,
+ const struct real_value *,
+ const struct real_value *));
+static bool sub_significands PARAMS ((struct real_value *,
+ const struct real_value *,
+ const struct real_value *));
+static void neg_significand PARAMS ((struct real_value *,
+ const struct real_value *));
+static int cmp_significands PARAMS ((const struct real_value *,
+ const struct real_value *));
+static void set_significand_bit PARAMS ((struct real_value *, unsigned int));
+static void clear_significand_bit PARAMS ((struct real_value *, unsigned int));
+static bool test_significand_bit PARAMS ((struct real_value *, unsigned int));
+static void clear_significand_below PARAMS ((struct real_value *,
+ unsigned int));
+static bool div_significands PARAMS ((struct real_value *,
+ const struct real_value *,
+ const struct real_value *));
+static void normalize PARAMS ((struct real_value *));
+
+static void do_add PARAMS ((struct real_value *, const struct real_value *,
+ const struct real_value *, int));
+static void do_multiply PARAMS ((struct real_value *,
+ const struct real_value *,
+ const struct real_value *));
+static void do_divide PARAMS ((struct real_value *, const struct real_value *,
+ const struct real_value *));
+static int do_compare PARAMS ((const struct real_value *,
+ const struct real_value *, int));
+
+static const struct real_value * ten_to_ptwo PARAMS ((int));
+static const struct real_value * real_digit PARAMS ((int));
+
+static void round_for_format PARAMS ((const struct real_format *,
+ struct real_value *));
+
+/* Initialize R with a positive zero. */
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* IEEE long double (113 bits). */
-static const struct ieee_format ieee_113 =
+static inline void
+get_zero (r, sign)
+ struct real_value *r;
+ int sign;
{
- 113,
- 15,
- 128,
- TFmode,
- 0
-};
-#endif /* INTEL_EXTENDED_IEEE_FORMAT == 0 */
+ memset (r, 0, sizeof (*r));
+ r->sign = sign;
+}
-#ifdef DEC
-/* DEC F float (24 bits). */
-static const struct ieee_format dec_f =
-{
- 24,
- 8,
- 32,
- SFmode,
- EXONE - 0201
-};
+/* Initialize R with the canonical quiet NaN. */
-/* DEC D float (56 bits). */
-static const struct ieee_format dec_d =
+static inline void
+get_canonical_qnan (r, sign)
+ struct real_value *r;
+ int sign;
{
- 56,
- 8,
- 64,
- DFmode,
- EXONE - 0201
-};
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_nan;
+ r->sign = sign;
+ r->sig[SIGSZ-1] = SIG_MSB >> 1;
+}
-/* DEC G float (53 bits). */
-static const struct ieee_format dec_g =
+static inline void
+get_canonical_snan (r, sign)
+ struct real_value *r;
+ int sign;
{
- 53,
- 11,
- 64,
- DFmode,
- EXONE - 1025
-};
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_nan;
+ r->sign = sign;
+ r->sig[SIGSZ-1] = SIG_MSB >> 2;
+}
-#if 0
-/* DEC H float (113 bits). (not yet used) */
-static const struct ieee_format dec_h =
+static inline void
+get_inf (r, sign)
+ struct real_value *r;
+ int sign;
{
- 113,
- 15,
- 128,
- TFmode,
- EXONE - 16385
-};
-#endif
-#endif /* DEC */
-
-extern int extra_warnings;
-extern const UEMUSHORT ezero[NE], ehalf[NE], eone[NE], etwo[NE];
-extern const UEMUSHORT elog2[NE], esqrt2[NE];
-
-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 void make_nan PARAMS ((UEMUSHORT *, int, enum machine_mode));
-#endif
-static int eiisneg PARAMS ((const UEMUSHORT *));
-static void saturate PARAMS ((UEMUSHORT *, int, int, int));
-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 void ieeetoe PARAMS ((const UEMUSHORT *, UEMUSHORT *,
- const struct ieee_format *));
-static void etoieee PARAMS ((const UEMUSHORT *, UEMUSHORT *,
- const struct ieee_format *));
-static void toieee PARAMS ((UEMUSHORT *, UEMUSHORT *,
- const struct ieee_format *));
-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
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_inf;
+ r->sign = sign;
+}
+
-/* 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, set the least
+ significant bit of R. */
static void
-endian (e, x, mode)
- const UEMUSHORT e[];
- long x[];
- enum machine_mode mode;
+sticky_rshift_significand (r, a, n)
+ struct real_value *r;
+ const struct real_value *a;
+ unsigned int n;
{
- unsigned long th, t;
+ bool sticky = false;
+ unsigned int i, ofs = 0;
- if (REAL_WORDS_BIG_ENDIAN && !VAX_HALFWORD_ORDER)
+ 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 -= ofs * HOST_BITS_PER_LONG;
+ }
- 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;
}
-}
+ r->sig[0] |= sticky;
+}
-/* 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)
+ struct real_value *r;
+ const struct real_value *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))
+ unsigned int i, ofs = n / HOST_BITS_PER_LONG;
+
+ n -= ofs * HOST_BITS_PER_LONG;
+ if (n != 0)
{
- PUT_REAL (d2, value);
- return;
+ 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)));
+ }
}
-#endif
- code = (enum tree_code) icode;
- switch (code)
+ else
{
- case PLUS_EXPR:
- eadd (d2, d1, v);
- break;
-
- case MINUS_EXPR:
- esub (d2, d1, v); /* d1 - d2 */
- break;
-
- case MULT_EXPR:
- emul (d2, d1, v);
- break;
-
- case RDIV_EXPR:
-#ifndef INFINITY
- if (ecmp (d2, ezero) == 0)
- abort ();
-#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;
+ for (i = 0; ofs + i < SIGSZ; ++i)
+ r->sig[i] = a->sig[ofs + i];
+ for (; i < SIGSZ; ++i)
+ r->sig[i] = 0;
}
-PUT_REAL (v, value);
}
+/* 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)
+ struct real_value *r;
+ const struct real_value *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 -= ofs * HOST_BITS_PER_LONG;
+ 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)
+ struct real_value *r;
+ const struct real_value *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)
+ struct real_value *r;
+ const struct real_value *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;
+ unsigned long ai = a->sig[i];
+ unsigned long ri = ai + b->sig[i];
- 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 */
-
- 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.
+ Return true if there was carry 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)
+ struct real_value *r;
+ const struct real_value *a, *b;
{
- UEMUSHORT f[NE], g[NE];
- HOST_WIDE_INT l;
+ bool carry = false;
+ int i;
- GET_REAL (&x, f);
-#ifdef NANS
- if (eisnan (f))
+ for (i = 0; i < SIGSZ; ++i)
{
- warning ("conversion from NaN to int");
- return (-1);
- }
-#endif
- eifrac (f, &l, g);
- return l;
-}
-
-/* Round real toward zero to unsigned HOST_WIDE_INT
- implements REAL_VALUE_UNSIGNED_FIX (x).
- Negative input returns zero. */
+ unsigned long ai = a->sig[i];
+ unsigned long ri = ai - b->sig[i];
-unsigned HOST_WIDE_INT
-efixui (x)
- REAL_VALUE_TYPE x;
-{
- UEMUSHORT f[NE], g[NE];
- unsigned HOST_WIDE_INT l;
+ if (carry)
+ {
+ carry = ri > ai;
+ carry |= ~--ri == 0;
+ }
+ else
+ carry = ri > ai;
- GET_REAL (&x, f);
-#ifdef NANS
- if (eisnan (f))
- {
- warning ("conversion from NaN to unsigned int");
- return (-1);
+ r->sig[i] = ri;
}
-#endif
- euifrac (f, &l, g);
- return l;
-}
+ return carry;
+}
-/* REAL_VALUE_FROM_INT macro. */
+/* Negate the significand A, placing the result in R. */
-void
-ereal_from_int (d, i, j, mode)
- REAL_VALUE_TYPE *d;
- HOST_WIDE_INT i, j;
- enum machine_mode mode;
+static inline void
+neg_significand (r, a)
+ struct real_value *r;
+ const struct real_value *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 struct real_value *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;
+ unsigned long ai = a->sig[i];
+ unsigned long bi = b->sig[i];
- case 96:
- etoe64 (dg, df);
- e64toe (df, dg);
- break;
+ if (ai > bi)
+ return 1;
+ if (ai < bi)
+ return -1;
+ }
- case 128:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- etoe113 (dg, df);
- e113toe (df, dg);
-#else
- etoe64 (dg, df);
- e64toe (df, dg);
-#endif
- break;
+ return 0;
+}
- default:
- abort ();
- }
+/* Set bit N of the significand of R. */
- PUT_REAL (dg, d);
+static inline void
+set_significand_bit (r, n)
+ struct real_value *r;
+ unsigned int n;
+{
+ r->sig[n / HOST_BITS_PER_LONG]
+ |= (unsigned long)1 << (n % HOST_BITS_PER_LONG);
}
+/* Clear bit N of the significand of R. */
-/* REAL_VALUE_TO_INT macro. */
-
-void
-ereal_to_int (low, high, rr)
- HOST_WIDE_INT *low, *high;
- REAL_VALUE_TYPE rr;
+static inline void
+clear_significand_bit (r, n)
+ struct real_value *r;
+ unsigned int n;
{
- UEMUSHORT d[NE], df[NE], dg[NE], dh[NE];
- int s;
-
- GET_REAL (&rr, d);
-#ifdef NANS
- if (eisnan (d))
- {
- warning ("conversion from NaN to int");
- *low = -1;
- *high = -1;
- return;
- }
-#endif
- /* convert positive value */
- s = 0;
- if (eisneg (d))
- {
- eneg (d);
- s = 1;
- }
- eldexp (eone, HOST_BITS_PER_WIDE_INT, df);
- ediv (df, d, dg); /* dg = d / 2^32 is the high word */
- euifrac (dg, (unsigned HOST_WIDE_INT *) high, dh);
- emul (df, dh, dg); /* fractional part is the low word */
- euifrac (dg, (unsigned HOST_WIDE_INT *) low, dh);
- if (s)
- {
- /* complement and add 1 */
- *high = ~(*high);
- if (*low)
- *low = -(*low);
- else
- *high += 1;
- }
+ r->sig[n / HOST_BITS_PER_LONG]
+ &= ~((unsigned long)1 << (n % HOST_BITS_PER_LONG));
}
+/* Test bit N of the significand of R. */
-/* REAL_VALUE_LDEXP macro. */
-
-REAL_VALUE_TYPE
-ereal_ldexp (x, n)
- REAL_VALUE_TYPE x;
- int n;
+static inline bool
+test_significand_bit (r, n)
+ struct real_value *r;
+ unsigned int n;
{
- UEMUSHORT e[NE], y[NE];
- REAL_VALUE_TYPE r;
-
- GET_REAL (&x, e);
-#ifdef NANS
- if (eisnan (e))
- return (x);
-#endif
- eldexp (e, n, y);
- PUT_REAL (y, &r);
- return (r);
+ /* ??? Compiler bug here if we return this expression directly.
+ The conversion to bool strips the "&1" and we wind up testing
+ e.g. 2 != 0 -> true. Seen in gcc version 3.2 20020520. */
+ int t = (r->sig[n / HOST_BITS_PER_LONG] >> (n % HOST_BITS_PER_LONG)) & 1;
+ return t;
}
-/* Check for infinity in a REAL_VALUE_TYPE. */
+/* Clear bits 0..N-1 of the significand of R. */
-int
-target_isinf (x)
- REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
+static void
+clear_significand_below (r, n)
+ struct real_value *r;
+ unsigned int n;
{
-#ifdef INFINITY
- UEMUSHORT e[NE];
+ int i, w = n / HOST_BITS_PER_LONG;
- GET_REAL (&x, e);
- return (eisinf (e));
-#else
- return 0;
-#endif
+ for (i = 0; i < w; ++i)
+ r->sig[i] = 0;
+
+ r->sig[w] &= ~(((unsigned long)1 << (n % HOST_BITS_PER_LONG)) - 1);
}
-/* Check whether a REAL_VALUE_TYPE item is a NaN. */
+/* Divide the significands of A and B, placing the result in R. Return
+ true if the division was inexact. */
-int
-target_isnan (x)
- REAL_VALUE_TYPE x ATTRIBUTE_UNUSED;
+static inline bool
+div_significands (r, a, b)
+ struct real_value *r;
+ const struct real_value *a, *b;
{
-#ifdef NANS
- UEMUSHORT e[NE];
+ struct real_value u;
+ int bit = SIGNIFICAND_BITS - 1;
+ int i;
+ long inexact;
- GET_REAL (&x, e);
- return (eisnan (e));
-#else
- return (0);
-#endif
-}
+ u = *a;
+ memset (r->sig, 0, sizeof (r->sig));
+ goto start;
+ do
+ {
+ if ((u.sig[SIGSZ-1] & SIG_MSB) == 0)
+ {
+ lshift_significand_1 (&u, &u);
+ start:
+ if (cmp_significands (&u, b) >= 0)
+ {
+ sub_significands (&u, &u, b);
+ set_significand_bit (r, bit);
+ }
+ }
+ else
+ {
+ /* We lose a bit here, and thus know the next quotient bit
+ will be one. */
+ lshift_significand_1 (&u, &u);
+ sub_significands (&u, &u, b);
+ set_significand_bit (r, bit);
+ }
+ }
+ while (--bit >= 0);
-/* Check for a negative REAL_VALUE_TYPE number.
- This just checks the sign bit, so that -0 counts as negative. */
+ for (i = 0, inexact = 0; i < SIGSZ; i++)
+ inexact |= u.sig[i];
-int
-target_negative (x)
- REAL_VALUE_TYPE x;
-{
- return ereal_isneg (x);
+ return inexact != 0;
}
-/* Expansion of REAL_VALUE_TRUNCATE.
- The result is in floating point, rounded to nearest or even. */
+/* Adjust the exponent and significand of R such that the most
+ significant bit is set. We underflow to zero and overflow to
+ infinity here, without denormals. (The intermediate representation
+ exponent is large enough to handle target denormals normalized.) */
-REAL_VALUE_TYPE
-real_value_truncate (mode, arg)
- enum machine_mode mode;
- REAL_VALUE_TYPE arg;
+static void
+normalize (r)
+ struct real_value *r;
{
- UEMUSHORT e[NE], t[NE];
- REAL_VALUE_TYPE r;
-
- GET_REAL (&arg, e);
-#ifdef NANS
- if (eisnan (e))
- return (arg);
-#endif
- eclear (t);
- switch (mode)
- {
- case TFmode:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- etoe113 (e, t);
- e113toe (t, t);
- break;
-#endif
- /* FALLTHRU */
-
- case XFmode:
- etoe64 (e, t);
- e64toe (t, t);
- break;
+ int shift = 0, exp;
+ int i, j;
- case DFmode:
- etoe53 (e, t);
- e53toe (t, t);
+ /* Find the first word that is non-zero. */
+ for (i = SIGSZ - 1; i >= 0; i--)
+ if (r->sig[i] == 0)
+ shift += HOST_BITS_PER_LONG;
+ else
break;
- case SFmode:
-#ifndef C4X
- case HFmode:
-#endif
- etoe24 (e, t);
- e24toe (t, t);
- break;
+ /* Zero significand flushes to zero. */
+ if (i < 0)
+ {
+ r->class = rvc_zero;
+ r->exp = 0;
+ return;
+ }
-#ifdef C4X
- case HFmode:
- case QFmode:
- etoe53 (e, t);
- e53toe (t, t);
+ /* Find the first bit that is non-zero. */
+ for (j = 0; ; j++)
+ if (r->sig[i] & ((unsigned long)1 << (HOST_BITS_PER_LONG - 1 - j)))
break;
-#endif
-
- case SImode:
- r = etrunci (arg);
- return (r);
+ shift += j;
- /* If an unsupported type was requested, presume that
- the machine files know something useful to do with
- the unmodified value. */
-
- default:
- return (arg);
+ if (shift > 0)
+ {
+ exp = 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);
+ }
}
- PUT_REAL (t, &r);
- return (r);
}
+
+/* Return R = A + (SUBTRACT_P ? -B : B). */
-/* Return true if ARG can be represented exactly in MODE. */
-
-bool
-exact_real_truncate (mode, arg)
- enum machine_mode mode;
- REAL_VALUE_TYPE *arg;
+static void
+do_add (r, a, b, subtract_p)
+ struct real_value *r;
+ const struct real_value *a, *b;
+ int subtract_p;
{
- REAL_VALUE_TYPE trunc;
+ int dexp, sign, exp;
+ struct real_value t;
- if (target_isnan (*arg))
- return false;
+ /* Determine if we need to add or subtract. */
+ sign = a->sign;
+ subtract_p = (sign ^ b->sign) ^ subtract_p;
- trunc = real_value_truncate (mode, *arg);
- return ereal_cmp (*arg, trunc) == 0;
-}
+ switch (CLASS2 (a->class, b->class))
+ {
+ case CLASS2 (rvc_zero, rvc_zero):
+ /* +-0 +/- +-0 = +0. */
+ get_zero (r, 0);
+ return;
-/* Try to change R into its exact multiplicative inverse in machine mode
- MODE. Return nonzero function value if successful. */
+ 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;
-int
-exact_real_inverse (mode, r)
- enum machine_mode mode;
- REAL_VALUE_TYPE *r;
-{
- UEMUSHORT e[NE], einv[NE];
- REAL_VALUE_TYPE rinv;
- int i;
+ 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;
- GET_REAL (r, e);
+ case CLASS2 (rvc_inf, rvc_inf):
+ if (subtract_p)
+ /* Inf - Inf = NaN. */
+ get_canonical_qnan (r, 0);
+ else
+ /* Inf + Inf = Inf. */
+ *r = *a;
+ return;
- /* Test for input in range. Don't transform IEEE special values. */
- if (eisinf (e) || eisnan (e) || (ecmp (e, ezero) == 0))
- return 0;
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
- /* Test for a power of 2: all significand bits zero except the MSB.
- We are assuming the target has binary (or hex) arithmetic. */
- if (e[NE - 2] != 0x8000)
- return 0;
+ default:
+ abort ();
+ }
- for (i = 0; i < NE - 2; i++)
+ /* Swap the arguments such that A has the larger exponent. */
+ dexp = a->exp - b->exp;
+ if (dexp < 0)
{
- if (e[i] != 0)
- return 0;
+ const struct real_value *t;
+ t = a, a = b, b = t;
+ dexp = -dexp;
+ sign ^= subtract_p;
}
+ exp = a->exp;
- /* Compute the inverse and truncate it to the required mode. */
- ediv (e, eone, einv);
- PUT_REAL (einv, &rinv);
- rinv = real_value_truncate (mode, rinv);
-
-#ifdef CHECK_FLOAT_VALUE
- /* This check is not redundant. It may, for example, flush
- a supposedly IEEE denormal value to zero. */
- i = 0;
- if (CHECK_FLOAT_VALUE (mode, rinv, i))
- return 0;
-#endif
- GET_REAL (&rinv, einv);
+ /* If the exponents are not identical, we need to shift the
+ significand of B down. */
+ if (dexp > 0)
+ {
+ /* If the exponents are too far apart, the significands
+ do not overlap, which makes the subtraction a noop. */
+ if (dexp >= SIGNIFICAND_BITS)
+ {
+ *r = *a;
+ r->sign = sign;
+ return;
+ }
- /* Check the bits again, because the truncation might have
- generated an arbitrary saturation value on overflow. */
- if (einv[NE - 2] != 0x8000)
- return 0;
+ sticky_rshift_significand (&t, b, dexp);
+ b = &t;
+ }
- for (i = 0; i < NE - 2; i++)
+ if (subtract_p)
{
- if (einv[i] != 0)
- return 0;
+ if (sub_significands (r, a, b))
+ {
+ /* 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. */
+ sticky_rshift_significand (r, r, 1);
+ r->sig[SIGSZ-1] |= SIG_MSB;
+ if (++exp > MAX_EXP)
+ {
+ get_inf (r, sign);
+ return;
+ }
+ }
}
- /* 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;
-}
-
-/* Used for debugging--print the value of R in human-readable format
- on stderr. */
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp;
-void
-debug_real (r)
- REAL_VALUE_TYPE r;
-{
- char dstr[30];
+ /* Re-normalize the result. */
+ normalize (r);
- REAL_VALUE_TO_DECIMAL (r, dstr, -1);
- fprintf (stderr, "%s", dstr);
+ /* Special case: if the subtraction results in zero, the result
+ is positive. */
+ if (r->class == rvc_zero)
+ r->sign = 0;
}
-
-/* The following routines convert REAL_VALUE_TYPE to the various floating
- point formats that are meaningful to supported computers.
+/* Return R = A * 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_multiply (r, a, b)
+ struct real_value *r;
+ const struct real_value *a, *b;
{
- UEMUSHORT e[NE];
+ struct real_value u, t, *rr;
+ unsigned int i, j, k;
+ int sign = a->sign ^ b->sign;
- GET_REAL (&r, e);
-#if INTEL_EXTENDED_IEEE_FORMAT == 0
- etoe113 (e, e);
-#else
- etoe64 (e, e);
-#endif
- endian (e, l, TFmode);
-}
+ 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;
-/* 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. */
+ 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;
-void
-etarldouble (r, l)
- REAL_VALUE_TYPE r;
- long l[];
-{
- UEMUSHORT e[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 (&r, e);
- etoe64 (e, e);
- endian (e, l, XFmode);
-}
+ case CLASS2 (rvc_zero, rvc_inf):
+ case CLASS2 (rvc_inf, rvc_zero):
+ /* 0 * Inf = NaN */
+ get_canonical_qnan (r, sign);
+ 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):
+ case CLASS2 (rvc_normal, rvc_inf):
+ case CLASS2 (rvc_inf, rvc_normal):
+ /* Inf * Inf = Inf, R * Inf = Inf */
+ overflow:
+ get_inf (r, sign);
+ 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'. */
+ if (r == a || r == b)
+ rr = &t;
+ else
+ rr = r;
+ get_zero (rr, 0);
-long
-etarsingle (r)
- REAL_VALUE_TYPE r;
-{
- UEMUSHORT e[NE];
- long l;
+ u.class = rvc_normal;
+ u.sign = 0;
- GET_REAL (&r, e);
- etoe24 (e, e);
- endian (e, &l, SFmode);
- return ((long) l);
-}
+ /* Collect all the partial products. Since we don't have sure access
+ to a widening multiply, we split each long into two half-words.
-/* 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.
+ Consider the long-hand form of a four half-word multiplication:
- The argument DIGITS is the number of decimal digits to print,
- or -1 to indicate "enough", i.e. DECIMAL_DIG for for the target. */
+ A B C D
+ * E F G H
+ --------------
+ DE DF DG DH
+ CE CF CG CH
+ BE BF BG BH
+ AE AF AG AH
-void
-ereal_to_decimal (x, s, digits)
- REAL_VALUE_TYPE x;
- char *s;
- int digits;
-{
- UEMUSHORT e[NE];
- GET_REAL (&x, e);
+ 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. */
- /* Find DECIMAL_DIG for the target. */
- if (digits < 0)
- switch (TARGET_FLOAT_FORMAT)
- {
- case IEEE_FLOAT_FORMAT:
- switch (LONG_DOUBLE_TYPE_SIZE)
- {
- case 32:
- digits = 9;
- break;
- case 64:
- digits = 17;
- break;
- case 128:
- if (!INTEL_EXTENDED_IEEE_FORMAT)
- {
- digits = 36;
- break;
- }
- /* FALLTHRU */
- case 96:
- digits = 21;
- break;
+ 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;
- default:
- abort ();
- }
- break;
+ if (ai == 0)
+ continue;
- case VAX_FLOAT_FORMAT:
- digits = 18; /* D_FLOAT */
- break;
+ 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)));
- case IBM_FLOAT_FORMAT:
- digits = 18;
- break;
+ if (exp > MAX_EXP)
+ goto overflow;
+ if (exp < -MAX_EXP)
+ /* Would underflow to zero, which we shouldn't bother adding. */
+ continue;
- case C4X_FLOAT_FORMAT:
- digits = 11;
- break;
+ u.exp = exp;
- default:
- abort ();
- }
-
- /* etoasc interprets digits as places after the decimal point.
- We interpret digits as total decimal digits, which IMO is
- more useful. Since the output will have one digit before
- the point, subtract one. */
- etoasc (e, s, digits - 1);
-}
+ 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;
-/* Compare X and Y. Return 1 if X > Y, 0 if X == Y, -1 if X < Y,
- or -2 if either is a NaN. */
+ u.sig[k / 2] = ai * bi;
+ }
-int
-ereal_cmp (x, y)
- REAL_VALUE_TYPE x, y;
-{
- UEMUSHORT ex[NE], ey[NE];
+ do_add (rr, rr, &u, 0);
+ }
+ }
- GET_REAL (&x, ex);
- GET_REAL (&y, ey);
- return (ecmp (ex, ey));
+ rr->sign = sign;
+ if (rr != r)
+ *r = t;
}
-/* Return 1 if the sign bit of X is set, else return 0. */
+/* Return R = A / B. */
-int
-ereal_isneg (x)
- REAL_VALUE_TYPE x;
+static void
+do_divide (r, a, b)
+ struct real_value *r;
+ const struct real_value *a, *b;
{
- UEMUSHORT ex[NE];
-
- GET_REAL (&x, ex);
- return (eisneg (ex));
-}
-
-
-/*
- Extended precision IEEE binary floating point arithmetic routines
-
- Numbers are stored in C language as arrays of 16-bit unsigned
- short integers. The arguments of the routines are pointers to
- the arrays.
+ int exp, sign = a->sign ^ b->sign;
+ struct real_value t, *rr;
+ bool inexact;
- External e type data structure, similar to Intel 8087 chip
- temporary real format but possibly with a larger significand:
-
- 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)
+ switch (CLASS2 (a->class, b->class))
+ {
+ case CLASS2 (rvc_zero, rvc_zero):
+ /* 0 / 0 = NaN. */
+ case CLASS2 (rvc_inf, rvc_zero):
+ /* Inf / 0 = NaN. */
+ case CLASS2 (rvc_inf, rvc_inf):
+ /* Inf / Inf = NaN. */
+ get_canonical_qnan (r, sign);
+ return;
+ 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;
- Internal exploded e-type data structure of a number (a "word" is 16 bits):
+ case CLASS2 (rvc_normal, rvc_zero):
+ /* R / 0 = Inf. */
+ get_inf (r, sign);
+ return;
- 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)
+ 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;
+ 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;
+ case CLASS2 (rvc_inf, rvc_normal):
+ /* Inf / R = Inf. */
+ overflow:
+ get_inf (r, sign);
+ return;
- Routines for external format e-type numbers
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
- 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
+ default:
+ abort ();
+ }
- 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 (r == a || r == b)
+ rr = &t;
+ else
+ rr = r;
-/* Control register for rounding precision.
- This can be set to 113 (if NE=10), 80 (if NE=6), 64, 56, 53, or 24 bits. */
+ rr->class = rvc_normal;
+ rr->sign = sign;
-int rndprc = NBITS;
-extern int rndprc;
+ exp = a->exp - b->exp + 1;
+ if (exp > MAX_EXP)
+ goto overflow;
+ if (exp < -MAX_EXP)
+ goto underflow;
+ rr->exp = exp;
-/* Clear out entire e-type number X. */
+ inexact = div_significands (rr, a, b);
+ rr->sig[0] |= inexact;
-static void
-eclear (x)
- UEMUSHORT *x;
-{
- int i;
+ /* Re-normalize the result. */
+ normalize (rr);
- for (i = 0; i < NE; i++)
- *x++ = 0;
+ if (rr != r)
+ *r = t;
}
-/* Move e-type number from A to B. */
+/* Return a tri-state comparison of A vs B. Return NAN_RESULT if
+ one of the two operands is a NaN. */
-static void
-emov (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
+static int
+do_compare (a, b, nan_result)
+ const struct real_value *a, *b;
+ int nan_result;
{
- int i;
+ int ret;
- for (i = 0; i < NE; i++)
- *b++ = *a++;
-}
+ switch (CLASS2 (a->class, b->class))
+ {
+ case CLASS2 (rvc_zero, rvc_zero):
+ /* Sign of zero doesn't matter for compares. */
+ 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);
-#if 0
-/* Absolute value of e-type X. */
+ case CLASS2 (rvc_inf, rvc_inf):
+ return -a->sign - -b->sign;
-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_zero, rvc_normal):
+ case CLASS2 (rvc_zero, rvc_inf):
+ case CLASS2 (rvc_normal, rvc_inf):
+ return (b->sign ? 1 : -1);
-/* 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):
+ case CLASS2 (rvc_nan, rvc_zero):
+ case CLASS2 (rvc_nan, rvc_normal):
+ case CLASS2 (rvc_nan, rvc_inf):
+ return nan_result;
-static void
-eneg (x)
- UEMUSHORT x[];
-{
+ case CLASS2 (rvc_normal, rvc_normal):
+ break;
- x[NE - 1] ^= 0x8000; /* Toggle the sign bit */
-}
+ default:
+ abort ();
+ }
-/* Return 1 if sign bit of e-type number X is nonzero, else zero. */
+ if (a->sign != b->sign)
+ return -a->sign - -b->sign;
-static int
-eisneg (x)
- const UEMUSHORT x[];
-{
-
- if (x[NE - 1] & 0x8000)
- return (1);
+ if (a->exp > b->exp)
+ ret = 1;
+ else if (a->exp < b->exp)
+ ret = -1;
else
- return (0);
-}
-
-/* Return 1 if e-type number X is infinity, else return zero. */
-
-static int
-eisinf (x)
- const UEMUSHORT x[];
-{
+ ret = cmp_significands (a, b);
-#ifdef NANS
- if (eisnan (x))
- return (0);
-#endif
- if ((x[NE - 1] & 0x7fff) == 0x7fff)
- return (1);
- else
- return (0);
+ return (a->sign ? -ret : ret);
}
-/* 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. */
+/* Perform the binary or unary operation described by CODE.
+ For a unary operation, leave OP1 NULL. */
-static int
-eisnan (x)
- const UEMUSHORT x[] ATTRIBUTE_UNUSED;
+void
+real_arithmetic (tr, icode, top0, top1)
+ REAL_VALUE_TYPE *tr;
+ int icode;
+ const REAL_VALUE_TYPE *top0, *top1;
{
-#ifdef NANS
- int i;
+ struct real_value *r = (struct real_value *) tr;
+ const struct real_value *op0 = (const struct real_value *) top0;
+ const struct real_value *op1 = (const struct real_value *) top1;
+ enum tree_code code = icode;
- /* 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 (code)
{
- if (*x++ != 0)
- return (1);
- }
-#endif
+ case PLUS_EXPR:
+ do_add (r, op0, op1, 0);
+ break;
- return (0);
-}
+ case MINUS_EXPR:
+ do_add (r, op0, op1, 1);
+ break;
-/* Fill e-type number X with infinity pattern (IEEE)
- or largest possible number (non-IEEE). */
+ case MULT_EXPR:
+ do_multiply (r, op0, op1);
+ break;
-static void
-einfin (x)
- UEMUSHORT *x;
-{
- int i;
+ case RDIV_EXPR:
+ do_divide (r, op0, op1);
+ break;
-#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;
- }
+ case MIN_EXPR:
+ if (op1->class == rvc_nan)
+ *r = *op1;
+ else if (do_compare (op0, op1, -1) < 0)
+ *r = *op0;
else
- {
- *(x - 4) = 0;
- *(x - 3) = 0;
- *(x - 2) = 0xff00;
- }
- }
-#endif
-}
-
-/* Similar, except return it as a REAL_VALUE_TYPE. */
-
-REAL_VALUE_TYPE
-ereal_inf (mode)
- enum machine_mode mode;
-{
- REAL_VALUE_TYPE r;
- UEMUSHORT e[NE];
- int prec, rndsav;
+ *r = *op1;
+ break;
- switch (mode)
- {
- case QFmode:
- case SFmode:
- prec = 24;
+ case MAX_EXPR:
+ if (op1->class == rvc_nan)
+ *r = *op1;
+ else if (do_compare (op0, op1, 1) < 0)
+ *r = *op1;
+ else
+ *r = *op0;
break;
- case HFmode:
- case DFmode:
- prec = 53;
+
+ case NEGATE_EXPR:
+ *r = *op0;
+ r->sign ^= 1;
break;
- case TFmode:
- if (!INTEL_EXTENDED_IEEE_FORMAT)
- {
- prec = 113;
- break;
- }
- /* FALLTHRU */
- case XFmode:
- prec = 64;
+
+ case ABS_EXPR:
+ *r = *op0;
+ r->sign = 0;
break;
+
default:
abort ();
}
-
- rndsav = rndprc;
- rndprc = prec;
- eclear (e);
- einfin (e);
- rndprc = rndsav;
-
- PUT_REAL (e, &r);
- return r;
}
-/* 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. */
+/* Legacy. Similar, but return the result directly. */
-#ifdef NANS
-static void
-enan (x, sign)
- UEMUSHORT *x;
- int sign;
+REAL_VALUE_TYPE
+real_arithmetic2 (icode, top0, top1)
+ int icode;
+ const REAL_VALUE_TYPE *top0, *top1;
{
- int i;
-
- for (i = 0; i < NE - 2; i++)
- *x++ = 0;
- *x++ = 0xc000;
- *x = (sign << 15) | 0x7fff;
+ REAL_VALUE_TYPE r;
+ real_arithmetic (&r, icode, top0, top1);
+ return r;
}
-#endif /* NANS */
-
-/* Move in an e-type number A, converting it to exploded e-type B. */
-static void
-emovi (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
+bool
+real_compare (icode, top0, top1)
+ int icode;
+ const REAL_VALUE_TYPE *top0, *top1;
{
- const UEMUSHORT *p;
- UEMUSHORT *q;
- int i;
+ enum tree_code code = icode;
+ const struct real_value *op0 = (const struct real_value *) top0;
+ const struct real_value *op1 = (const struct real_value *) top1;
- 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 (code)
{
-#ifdef NANS
- if (eisnan (a))
- {
- *q++ = 0;
- for (i = 3; i < NI; i++)
- *q++ = *p--;
- return;
- }
-#endif
+ 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;
- for (i = 2; i < NI; i++)
- *q++ = 0;
- return;
+ default:
+ abort ();
}
-#endif
-
- /* 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;
}
-/* Move out exploded e-type number A, converting it to e type B. */
+/* Return floor log2(R). */
-static void
-emovo (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
+int
+real_exponent (tr)
+ const REAL_VALUE_TYPE *tr;
{
- 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)
+ const struct real_value *r = (const struct real_value *) tr;
+
+ switch (r->class)
{
-#ifdef NANS
- if (eiisnan (a))
- {
- enan (b, eiisneg (a));
- return;
- }
-#endif
- einfin (b);
- return;
+ 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
- /* skip over guard word */
- ++p;
- /* move the significand */
- for (j = 0; j < NE - 1; j++)
- *q-- = *p++;
-}
-
-/* Clear out exploded e-type number XI. */
-
-static void
-ecleaz (xi)
- UEMUSHORT *xi;
-{
- int i;
-
- for (i = 0; i < NI; i++)
- *xi++ = 0;
}
-/* Clear out exploded e-type XI, but don't touch the sign. */
-static void
-ecleazs (xi)
- UEMUSHORT *xi;
-{
- int i;
-
- ++xi;
- for (i = 0; i < NI - 1; i++)
- *xi++ = 0;
-}
-
-/* Move exploded e-type number from A to B. */
+/* R = OP0 * 2**EXP. */
-static void
-emovz (a, b)
- const UEMUSHORT *a;
- UEMUSHORT *b;
-{
- int i;
-
- for (i = 0; i < NI - 1; i++)
- *b++ = *a++;
- /* clear low guard word */
- *b = 0;
-}
-
-/* Generate exploded e-type NaN.
- The explicit pattern for this is maximum exponent and
- top two significant bits set. */
-
-#ifdef NANS
-static void
-einan (x)
- UEMUSHORT x[];
-{
-
- ecleaz (x);
- x[E] = 0x7fff;
- x[M + 1] = 0xc000;
-}
-#endif /* NANS */
-
-/* Return nonzero if exploded e-type X is a NaN. */
-
-#ifdef NANS
-static int
-eiisnan (x)
- const UEMUSHORT x[];
+void
+real_ldexp (tr, top0, exp)
+ REAL_VALUE_TYPE *tr;
+ const REAL_VALUE_TYPE *top0;
+ int exp;
{
- int i;
+ struct real_value *r = (struct real_value *) tr;
+ const struct real_value *op0 = (const struct real_value *) top0;
- if ((x[E] & 0x7fff) == 0x7fff)
+ *r = *op0;
+ switch (r->class)
{
- for (i = M + 1; i < NI; i++)
- {
- if (x[i] != 0)
- return (1);
- }
- }
- return (0);
-}
-#endif /* NANS */
-
-/* Return nonzero if sign of exploded e-type X is nonzero. */
+ case rvc_zero:
+ case rvc_inf:
+ case rvc_nan:
+ break;
-static int
-eiisneg (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;
- return x[0] != 0;
+ default:
+ abort ();
+ }
}
-#if 0
-/* Fill exploded e-type X with infinity pattern.
- This has maximum exponent and significand all zeros. */
+/* Determine whether a floating-point value X is infinite. */
-static void
-eiinfin (x)
- UEMUSHORT x[];
+bool
+real_isinf (tr)
+ const REAL_VALUE_TYPE *tr;
{
-
- ecleaz (x);
- x[E] = 0x7fff;
+ const struct real_value *r = (const struct real_value *) tr;
+ return (r->class == rvc_inf);
}
-#endif /* 0 */
-/* Return nonzero if exploded e-type X is infinite. */
+/* Determine whether a floating-point value X is a NaN. */
-#ifdef INFINITY
-static int
-eiisinf (x)
- const UEMUSHORT x[];
+bool
+real_isnan (tr)
+ const REAL_VALUE_TYPE *tr;
{
-
-#ifdef NANS
- if (eiisnan (x))
- return (0);
-#endif
- if ((x[E] & 0x7fff) == 0x7fff)
- return (1);
- return (0);
+ const struct real_value *r = (const struct real_value *) tr;
+ return (r->class == rvc_nan);
}
-#endif /* INFINITY */
-
-/* Compare significands of numbers in internal exploded e-type format.
- Guard words are included in the comparison.
- Returns +1 if a > b
- 0 if a == b
- -1 if a < b */
+/* Determine whether a floating-point value X is negative. */
-static int
-ecmpm (a, b)
- const UEMUSHORT *a, *b;
+bool
+real_isneg (tr)
+ const REAL_VALUE_TYPE *tr;
{
- 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);
+ const struct real_value *r = (const struct real_value *) tr;
+ return r->sign;
}
-/* Shift significand of exploded e-type X down by 1 bit. */
+/* Determine whether a floating-point value X is minus zero. */
-static void
-eshdn1 (x)
- UEMUSHORT *x;
+bool
+real_isnegzero (tr)
+ const REAL_VALUE_TYPE *tr;
{
- 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;
- }
+ const struct real_value *r = (const struct real_value *) tr;
+ return r->sign && r->class == rvc_zero;
}
-/* Shift significand of exploded e-type X up by 1 bit. */
+/* Compare two floating-point objects for bitwise identity. */
-static void
-eshup1 (x)
- UEMUSHORT *x;
+extern bool
+real_identical (ta, tb)
+ const REAL_VALUE_TYPE *ta, *tb;
{
- UEMUSHORT bits;
+ const struct real_value *a = (const struct real_value *) ta;
+ const struct real_value *b = (const struct real_value *) tb;
int i;
- x += NI - 1;
- bits = 0;
+ if (a->class != b->class)
+ return false;
+ if (a->sign != b->sign)
+ return false;
- for (i = M; i < NI; i++)
+ switch (a->class)
{
- if (*x & 0x8000)
- bits |= 1;
- *x <<= 1;
- if (bits & 2)
- *x |= 1;
- bits <<= 1;
- --x;
- }
-}
-
-
-/* Shift significand of exploded e-type X down by 8 bits. */
+ case rvc_zero:
+ case rvc_inf:
+ break;
-static void
-eshdn8 (x)
- UEMUSHORT *x;
-{
- UEMUSHORT newbyt, oldbyt;
- int i;
+ 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;
- x += M;
- oldbyt = 0;
- for (i = M; i < NI; i++)
- {
- newbyt = *x << 8;
- *x >>= 8;
- *x |= oldbyt;
- oldbyt = newbyt;
- ++x;
+ default:
+ abort ();
}
-}
-
-/* Shift significand of exploded e-type X up by 8 bits. */
-static void
-eshup8 (x)
- UEMUSHORT *x;
-{
- int i;
- UEMUSHORT newbyt, oldbyt;
-
- x += NI - 1;
- oldbyt = 0;
-
- for (i = M; i < NI; i++)
- {
- newbyt = *x >> 8;
- *x <<= 8;
- *x |= oldbyt;
- oldbyt = newbyt;
- --x;
- }
+ return true;
}
-/* Shift significand of exploded e-type X up by 16 bits. */
+/* Try to change R into its exact multiplicative inverse in machine
+ mode MODE. Return true if successful. */
-static void
-eshup6 (x)
- UEMUSHORT *x;
+bool
+exact_real_inverse (mode, tr)
+ enum machine_mode mode;
+ REAL_VALUE_TYPE *tr;
{
+ const struct real_value *one = real_digit (1);
+ struct real_value *r = (struct real_value *) tr;
+ struct real_value u;
int i;
- UEMUSHORT *p;
+
+ if (r->class != rvc_normal)
+ return false;
- p = x + M;
- x += M + 1;
+ /* 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;
- for (i = M; i < NI - 1; i++)
- *p++ = *x++;
+ /* Find the inverse and truncate to the required mode. */
+ do_divide (&u, one, r);
+ real_convert ((REAL_VALUE_TYPE *)&u, mode, (REAL_VALUE_TYPE *)&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;
- *p = 0;
+ *r = u;
+ return true;
}
+
+/* Render R as an integer. */
-/* Shift significand of exploded e-type X down by 16 bits. */
-
-static void
-eshdn6 (x)
- UEMUSHORT *x;
+HOST_WIDE_INT
+real_to_integer (tr)
+ const REAL_VALUE_TYPE *tr;
{
- int i;
- UEMUSHORT *p;
+ const struct real_value *r = (const struct real_value *) tr;
+ unsigned HOST_WIDE_INT i;
- x += NI - 1;
- p = x + 1;
-
- for (i = M; i < NI - 1; i++)
- *(--p) = *(--x);
+ switch (r->class)
+ {
+ case rvc_zero:
+ underflow:
+ return 0;
- *(--p) = 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;
-/* Add significands of exploded e-type X and Y. X + Y replaces Y. */
+ case rvc_normal:
+ if (r->exp <= 0)
+ goto underflow;
+ if (r->exp > HOST_BITS_PER_WIDE_INT)
+ goto overflow;
-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;
+ 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, tr)
+ HOST_WIDE_INT *plow, *phigh;
+ const REAL_VALUE_TYPE *tr;
{
- int i;
- UEMUSHORT *p, *q;
- UEMUSHORT j;
-
- p = &equot[0];
- *p++ = num[0];
- *p++ = num[1];
+ struct real_value r;
+ HOST_WIDE_INT low, high;
+ int exp;
- for (i = M; i < NI; i++)
+ r = *(const struct real_value *) tr;
+ 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 (&r, &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 = r.sig[SIGSZ-1];
+ low = r.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 = r.sig[SIGSZ-1];
+ high = high << (HOST_BITS_PER_LONG - 1) << 1;
+ high |= r.sig[SIGSZ-2];
+
+ low = r.sig[SIGSZ-3];
+ low = low << (HOST_BITS_PER_LONG - 1) << 1;
+ low |= r.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;
}
+/* Render R as a decimal floating point constant. Emit DIGITS
+ significant digits in the result. If DIGITS <= 0, choose the
+ maximum for the representation. */
-/* Multiply significands */
+#define M_LOG10_2 0.30102999566398119521
-int
-emulm (a, b)
- UEMUSHORT a[], b[];
+void
+real_to_decimal (str, r_orig, digits)
+ char *str;
+ const REAL_VALUE_TYPE *r_orig;
+ int digits;
{
- UEMUSHORT *p, *q;
- int i, j, k;
-
- equot[0] = b[0];
- equot[1] = b[1];
- for (i = M; i < NI; i++)
- equot[i] = 0;
+ struct real_value r;
+ const struct real_value *one, *ten;
+ int dec_exp, max_digits, d, cmp_half;
+ char *p, *first, *last;
+ bool sign;
- p = &a[NI - 2];
- k = NBITS;
- while (*p == 0) /* significand is not supposed to be zero */
+ r = *(const struct real_value *)r_orig;
+ switch (r.class)
{
- eshdn6 (a);
- k -= 16;
- }
- if ((*p & 0xff) == 0)
- {
- eshdn8 (a);
- k -= 8;
- }
-
- q = &equot[NI - 1];
- j = 0;
- for (i = 0; i < k; i++)
- {
- if (*p & 1)
- eaddm (b, equot);
- /* remember if there were any nonzero bits shifted out */
- if (*q & 1)
- j |= 1;
- eshdn1 (a);
- eshdn1 (equot);
+ 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 ();
}
- for (i = 0; i < NI; i++)
- b[i] = equot[i];
+ max_digits = SIGNIFICAND_BITS * M_LOG10_2;
+ if (digits <= 0 || digits > max_digits)
+ digits = max_digits;
- /* return flag for lost nonzero bits */
- return (j);
-}
-
-#else
-
-/* Radix 65536 versions of multiply and divide. */
-
-/* Multiply significand of e-type number B
- by 16-bit quantity A, return e-type result to C. */
-
-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;
+ one = real_digit (1);
+ ten = ten_to_ptwo (0);
- aa = a;
- pp = &p[NI-2];
- *pp++ = 0;
- *pp = 0;
- ps = &b[NI-1];
+ sign = r.sign;
+ r.sign = 0;
- for (i=M+1; i<NI; i++)
+ /* Estimate the decimal exponent. */
+ dec_exp = r.exp * M_LOG10_2;
+
+ /* Scale the number such that it is in [1, 10). */
+ if (dec_exp > 0)
{
- 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;
- }
+ int i;
+ for (i = EXP_BITS - 1; i >= 0; --i)
+ if (dec_exp & (1 << i))
+ do_divide (&r, &r, ten_to_ptwo (i));
}
- for (i=M; i<NI; i++)
- c[i] = p[i];
-}
-
-/* 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. */
-
-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];
-
- p = &equot[0];
- *p++ = num[0];
- *p++ = num[1];
-
- for (i=M; i<NI; i++)
+ else if (dec_exp < 0)
{
- *p++ = 0;
+ int i, pos_exp = -(--dec_exp);
+
+ for (i = EXP_BITS - 1; i >= 0; --i)
+ if (pos_exp & (1 << i))
+ do_multiply (&r, &r, ten_to_ptwo (i));
}
- eshdn1 (num);
- tdenm = den[M+1];
- for (i=M; i<NI; i++)
- {
- /* Find trial quotient digit (the radix is 65536). */
- tnum = (((unsigned EMULONG) num[M]) << 16) + num[M+1];
- /* 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);
+ /* Assert that the number is in the proper range. Round-off can
+ prevent the above from working exactly. */
+ if (do_compare (&r, one, -1) < 0)
+ {
+ do_multiply (&r, &r, ten);
+ dec_exp--;
}
- /* test for nonzero remainder after roundoff bit */
- p = &num[M];
- j = 0;
- for (i=M; i<NI; i++)
+ else if (do_compare (&r, ten, 1) >= 0)
{
- j |= *p++;
+ do_divide (&r, &r, ten);
+ dec_exp++;
}
- if (j)
- j = 1;
-
- for (i=0; i<NI; i++)
- num[i] = equot[i];
- return ((int) j);
-}
-
-/* Multiply significands of exploded e-type A and B, result in B. */
-
-static int
-emulm (a, b)
- const UEMUSHORT a[];
- UEMUSHORT b[];
-{
- const UEMUSHORT *p;
- UEMUSHORT *q;
- UEMUSHORT pprod[NI];
- UEMUSHORT j;
- int i;
+ p = str;
+ if (sign)
+ *p++ = '-';
+ first = p++;
+ while (1)
+ {
+ d = real_to_integer ((const REAL_VALUE_TYPE *) &r);
+ do_add (&r, &r, real_digit (d), 1);
- equot[0] = b[0];
- equot[1] = b[1];
- for (i=M; i<NI; i++)
- equot[i] = 0;
+ *p++ = d + '0';
+ if (--digits == 0)
+ break;
+ do_multiply (&r, &r, ten);
+ }
+ last = p;
- j = 0;
- p = &a[NI-1];
- q = &equot[NI-1];
- for (i=M+1; i<NI; i++)
+ /* Round the result. Compare R vs 0.5 by doing R*2 vs 1.0. */
+ r.exp += 1;
+ cmp_half = do_compare (&r, one, -1);
+ if (cmp_half == 0)
+ /* Round to even. */
+ cmp_half += d & 1;
+ if (cmp_half > 0)
{
- if (*p == 0)
+ while (p > first)
{
- --p;
+ d = *--p;
+ if (d == '9')
+ *p = '0';
+ else
+ {
+ *p = d + 1;
+ break;
+ }
}
- else
+
+ if (p == first)
{
- m16m ((unsigned int) *p--, b, pprod);
- eaddm (pprod, equot);
+ first[1] = '1';
+ dec_exp++;
}
- j |= *q;
- eshdn6 (equot);
}
+
+ first[0] = first[1];
+ first[1] = '.';
- for (i=0; i<NI; i++)
- b[i] = equot[i];
-
- /* return flag for lost nonzero bits */
- return ((int) j);
+ sprintf (last, "e%+d", dec_exp);
}
-#endif
-
-
-/* Normalize and round off.
-
- The internal format number to be rounded is S.
- Input LOST is 0 if the value is exact. This is the so-called sticky bit.
-
- Input SUBFLG indicates whether the number was obtained
- by a subtraction operation. In that case if LOST is nonzero
- then the number is slightly smaller than indicated.
- Input EXP is the biased exponent, which may be negative.
- the exponent field of S is ignored but is replaced by
- EXP as adjusted by normalization and rounding.
+/* Render R as a hexadecimal floating point constant. Emit DIGITS
+ significant digits in the result. If DIGITS <= 0, choose the maximum
+ for the representation. */
- Input RCNTRL is the rounding control. If it is nonzero, the
- returned value will be rounded to RNDPRC bits.
-
- 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. */
-
-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];
-
-static void
-emdnorm (s, lost, subflg, exp, rcntrl)
- UEMUSHORT s[];
- int lost;
- int subflg ATTRIBUTE_UNUSED;
- EMULONG exp;
- int rcntrl;
+void
+real_to_hexadecimal (str, tr, digits)
+ char *str;
+ const REAL_VALUE_TYPE *tr;
+ int digits;
{
+ struct real_value r;
int i, j;
- UEMUSHORT r;
+ char *p;
- /* Normalize */
- j = enormlz (s);
+ r = *(const struct real_value *) tr;
- /* a blank significand could mean either zero or infinity. */
-#ifndef INFINITY
- if (j > NBITS)
+ switch (r.class)
{
- ecleazs (s);
+ case rvc_zero:
+ r.exp = 0;
+ break;
+ case rvc_normal:
+ break;
+ case rvc_inf:
+ strcpy (str, (r.sign ? "+Inf" : "-Inf"));
return;
- }
-#endif
- exp -= j;
-#ifndef INFINITY
- if (exp >= 32767L)
- goto overf;
-#else
- if ((j > NBITS) && (exp < 32767))
- {
- ecleazs (s);
+ case rvc_nan:
+ /* ??? Print the significand as well, if not canonical? */
+ strcpy (str, (r.sign ? "+NaN" : "-NaN"));
return;
+ default:
+ abort ();
}
-#endif
- if (exp < 0L)
- {
- if (exp > (EMULONG) (-NBITS - 1))
- {
- j = (int) exp;
- i = eshift (s, j);
- if (i)
- lost = 1;
- }
- else
- {
- ecleazs (s);
- return;
- }
- }
- /* Round off, unless told not to by rcntrl. */
- if (rcntrl == 0)
- goto mdfin;
- /* Set up rounding parameters if the control register changed. */
- if (rndprc != rlast)
- {
- ecleaz (rbit);
- switch (rndprc)
- {
- default:
- case NBITS:
- rw = NI - 1; /* low guard word */
- rmsk = 0xffff;
- rmbit = 0x8000;
- re = rw - 1;
- rebit = 1;
- break;
- case 113:
- rw = 10;
- rmsk = 0x7fff;
- rmbit = 0x4000;
- rebit = 0x8000;
- re = rw;
- break;
+ if (digits <= 0)
+ digits = SIGNIFICAND_BITS / 4;
- case 64:
- rw = 7;
- rmsk = 0xffff;
- rmbit = 0x8000;
- re = rw - 1;
- rebit = 1;
- break;
+ p = str;
+ if (r.sign)
+ *p++ = '-';
+ *p++ = '0';
+ *p++ = 'x';
+ *p++ = '0';
+ *p++ = '.';
- /* For DEC or IBM arithmetic */
- case 56:
- rw = 6;
- rmsk = 0xff;
- rmbit = 0x80;
- rebit = 0x100;
- re = rw;
- break;
+ 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:
+ sprintf (p, "p%+d", r.exp);
+}
- case 53:
- rw = 6;
- rmsk = 0x7ff;
- rmbit = 0x0400;
- rebit = 0x800;
- re = rw;
- break;
+/* Initialize R from a decimal or hexadecimal string. The string is
+ assumed to have been syntax checked already. */
- /* For C4x arithmetic */
- case 32:
- rw = 5;
- rmsk = 0xffff;
- rmbit = 0x8000;
- rebit = 1;
- re = rw - 1;
- break;
+void
+real_from_string (tr, str)
+ REAL_VALUE_TYPE *tr;
+ const char *str;
+{
+ struct real_value *r = (struct real_value *) tr;
+ int exp = 0;
- case 24:
- rw = 4;
- rmsk = 0xff;
- rmbit = 0x80;
- rebit = 0x100;
- re = rw;
- break;
- }
- rbit[re] = rebit;
- rlast = rndprc;
- }
+ get_zero (r, 0);
- /* 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)))
+ if (*str == '-')
{
- lost |= s[NI - 1] & 1;
- eshdn1 (s);
+ r->sign = 1;
+ str++;
}
- /* Clear out all bits below the rounding bit,
- remembering in r if any were nonzero. */
- r = s[rw] & rmsk;
- if (rndprc < NBITS)
- {
- i = rw + 1;
- while (i < NI)
- {
- if (s[i])
- r |= 1;
- s[i] = 0;
- ++i;
- }
- }
- s[rw] &= ~rmsk;
- if ((r & rmbit) != 0)
+ else if (*str == '+')
+ str++;
+
+ if (str[0] == '0' && str[1] == 'x')
{
-#ifndef C4X
- if (r == rmbit)
+ /* Hexadecimal floating point. */
+ int pos = SIGNIFICAND_BITS - 4, d;
+
+ str += 2;
+
+ while (*str == '0')
+ str++;
+ while (1)
{
- if (lost == 0)
- { /* round to even */
- if ((s[re] & rebit) == 0)
- goto mddone;
- }
- else
+ d = hex_value (*str);
+ if (d == _hex_bad)
+ break;
+ if (pos >= 0)
{
- if (subflg != 0)
- goto mddone;
+ r->sig[pos / HOST_BITS_PER_LONG]
+ |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
+ pos -= 4;
}
+ exp += 4;
+ str++;
}
-#endif
- eaddm (rbit, s);
- }
-#ifndef C4X
- mddone:
-#endif
-/* 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))
+ if (*str == '.')
{
- s[rw] &= ~rmsk;
- if (rndprc == 24)
+ str++;
+ while (1)
{
- s[5] = 0;
- s[6] = 0;
+ d = hex_value (*str);
+ if (d == _hex_bad)
+ break;
+ if (pos >= 0)
+ {
+ r->sig[pos / HOST_BITS_PER_LONG]
+ |= (unsigned long) d << (pos % HOST_BITS_PER_LONG);
+ pos -= 4;
+ }
+ str++;
}
}
-#endif
- return;
- }
- if (exp < 0)
- s[1] = 0;
- else
- s[1] = (UEMUSHORT) exp;
-}
-
-/* Subtract. C = B - A, all e type numbers. */
-
-static int subflg = 0;
-
-static void
-esub (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
-{
-
-#ifdef NANS
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
-/* Infinity minus infinity is a NaN.
- Test for subtracting infinities of the same sign. */
- if (eisinf (a) && eisinf (b)
- && ((eisneg (a) ^ eisneg (b)) == 0))
- {
- mtherr ("esub", INVALID);
- enan (c, 0);
- return;
- }
-#endif
- subflg = 1;
- eadd1 (a, b, c);
-}
-
-/* Add. C = A + B, all e type. */
-
-static void
-eadd (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
-{
-
-#ifdef NANS
-/* NaN plus anything is a NaN. */
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
-/* Infinity minus infinity is a NaN.
- Test for adding infinities of opposite signs. */
- if (eisinf (a) && eisinf (b)
- && ((eisneg (a) ^ eisneg (b)) != 0))
- {
- mtherr ("esub", INVALID);
- enan (c, 0);
- return;
- }
-#endif
- subflg = 0;
- eadd1 (a, b, c);
-}
-
-/* Arithmetic common to both addition and subtraction. */
-
-static void
-eadd1 (a, b, c)
- const UEMUSHORT *a, *b;
- UEMUSHORT *c;
-{
- UEMUSHORT ai[NI], bi[NI], ci[NI];
- int i, lost, j, k;
- EMULONG lt, lta, ltb;
+ if (*str == 'p' || *str == 'P')
+ {
+ int exp_neg = 0;
-#ifdef INFINITY
- if (eisinf (a))
- {
- emov (a, c);
- if (subflg)
- eneg (c);
- return;
- }
- if (eisinf (b))
- {
- emov (b, c);
- return;
- }
-#endif
- emovi (a, ai);
- emovi (b, bi);
- if (subflg)
- ai[0] = ~ai[0];
-
- /* compare exponents */
- lta = ai[E];
- ltb = bi[E];
- lt = lta - ltb;
- if (lt > 0L)
- { /* put the larger number in bi */
- emovz (bi, ci);
- emovz (ai, bi);
- emovz (ci, ai);
- ltb = bi[E];
- lt = -lt;
- }
- lost = 0;
- if (lt != 0L)
- {
- if (lt < (EMULONG) (-NBITS - 1))
- goto done; /* answer same as larger addend */
- k = (int) lt;
- lost = eshift (ai, k); /* shift the smaller number down */
- }
- else
- {
- /* exponents were the same, so must compare significands */
- i = ecmpm (ai, bi);
- if (i == 0)
- { /* the numbers are identical in magnitude */
- /* if different signs, result is zero */
- if (ai[0] != bi[0])
- {
- eclear (c);
- return;
- }
- /* if same sign, result is double */
- /* double denormalized tiny number */
- if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0))
+ str++;
+ if (*str == '-')
{
- eshup1 (bi);
- goto done;
+ exp_neg = 1;
+ str++;
}
- /* add 1 to exponent unless both are zero! */
- for (j = 1; j < NI - 1; j++)
+ else if (*str == '+')
+ str++;
+
+ d = 0;
+ while (ISDIGIT (*str))
{
- if (bi[j] != 0)
+ int t = d;
+ d *= 10;
+ d += *str - '0';
+ if (d < t)
{
- ltb += 1;
- if (ltb >= 0x7fff)
- {
- eclear (c);
- if (ai[0] != 0)
- eneg (c);
- einfin (c);
- return;
- }
- break;
+ /* Overflowed the exponent. */
+ if (exp_neg)
+ goto underflow;
+ else
+ goto overflow;
}
+ str++;
}
- bi[E] = (UEMUSHORT) ltb;
- goto done;
+ if (exp_neg)
+ d = -d;
+
+ exp += d;
}
- if (i > 0)
- { /* put the larger number in bi */
- emovz (bi, ci);
- emovz (ai, bi);
- emovz (ci, ai);
+
+ r->class = rvc_normal;
+ r->exp = exp;
+ if (r->exp != exp)
+ {
+ if (exp < 0)
+ goto underflow;
+ else
+ goto overflow;
}
- }
- if (ai[0] == bi[0])
- {
- eaddm (ai, bi);
- subflg = 0;
+
+ normalize (r);
}
else
{
- esubm (ai, bi);
- subflg = 1;
- }
- emdnorm (bi, lost, subflg, ltb, !ROUND_TOWARDS_ZERO);
-
- done:
- emovo (bi, c);
-}
-
-/* Divide: C = B/A, all e type. */
+ /* Decimal floating point. */
+ const struct real_value *ten = ten_to_ptwo (0);
+ int 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;
-
-/* IEEE says if result is not a NaN, the sign is "-" if and only if
- operands have opposite signs -- but flush -0 to 0 later if not IEEE. */
- sign = eisneg (a) ^ eisneg (b);
-
-#ifdef NANS
-/* Return any NaN input. */
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
-/* Zero over zero, or infinity over infinity, is a NaN. */
- if (((ecmp (a, ezero) == 0) && (ecmp (b, ezero) == 0))
- || (eisinf (a) && eisinf (b)))
- {
- mtherr ("ediv", INVALID);
- enan (c, sign);
- return;
- }
-#endif
-/* Infinity over anything else is infinity. */
-#ifdef INFINITY
- if (eisinf (b))
- {
- einfin (c);
- goto divsign;
- }
-/* Anything else over infinity is zero. */
- if (eisinf (a))
- {
- eclear (c);
- goto divsign;
- }
-#endif
- emovi (a, ai);
- emovi (b, bi);
- lta = ai[E];
- ltb = bi[E];
- if (bi[E] == 0)
- { /* See if numerator is zero. */
- for (i = 1; i < NI - 1; i++)
+ 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++;
+ while (ISDIGIT (*str))
{
- lta -= enormlz (ai);
- goto dnzro2;
+ 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, !ROUND_TOWARDS_ZERO);
- 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;
+ if (*str == 'e' || *str == 'E')
+ {
+ int exp_neg = 0;
-/* 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);
+ str++;
+ if (*str == '-')
+ {
+ exp_neg = 1;
+ str++;
+ }
+ else if (*str == '+')
+ str++;
-#ifdef NANS
-/* NaN times anything is the same NaN. */
- if (eisnan (a))
- {
- emov (a, c);
- return;
- }
- if (eisnan (b))
- {
- emov (b, c);
- return;
- }
-/* Zero times infinity is a NaN. */
- if ((eisinf (a) && (ecmp (b, ezero) == 0))
- || (eisinf (b) && (ecmp (a, ezero) == 0)))
- {
- mtherr ("emul", INVALID);
- enan (c, sign);
- return;
- }
-#endif
-/* Infinity times anything else is infinity. */
-#ifdef INFINITY
- if (eisinf (a) || eisinf (b))
- {
- einfin (c);
- goto mulsign;
- }
-#endif
- emovi (a, ai);
- emovi (b, bi);
- lta = ai[E];
- ltb = bi[E];
- if (ai[E] == 0)
- {
- for (i = 1; i < NI - 1; i++)
- {
- if (ai[i] != 0)
+ d = 0;
+ while (ISDIGIT (*str))
{
- lta -= enormlz (ai);
- goto mnzer1;
+ int t = d;
+ d *= 10;
+ d += *str - '0';
+ if (d < t)
+ {
+ /* Overflowed the exponent. */
+ if (exp_neg)
+ goto underflow;
+ else
+ goto overflow;
+ }
+ str++;
}
+ if (exp_neg)
+ d = -d;
+ exp += d;
}
- eclear (c);
- goto mulsign;
- }
- mnzer1:
- if (bi[E] == 0)
- {
- for (i = 1; i < NI - 1; i++)
+ if (exp < 0)
{
- if (bi[i] != 0)
- {
- ltb -= enormlz (bi);
- goto mnzer2;
- }
+ exp = -exp;
+ for (d = 0; d < EXP_BITS; ++d)
+ if (exp & (1 << d))
+ do_divide (r, r, ten_to_ptwo (d));
+ }
+ else if (exp > 0)
+ {
+ for (d = 0; d < EXP_BITS; ++d)
+ if (exp & (1 << d))
+ do_multiply (r, r, ten_to_ptwo (d));
}
- eclear (c);
- goto mulsign;
}
- mnzer2:
- /* Multiply significands */
- j = emulm (ai, bi);
- /* calculate exponent */
- lt = lta + ltb - (EXONE - 1);
- emdnorm (bi, j, 0, lt, !ROUND_TOWARDS_ZERO);
- emovo (bi, c);
+ return;
- mulsign:
+ underflow:
+ get_zero (r, 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, 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);
+ REAL_VALUE_TYPE r;
-#else
+ real_from_string (&r, s);
+ if (mode != VOIDmode)
+ real_convert (&r, mode, &r);
- ieeetoe (pe, y, &ieee_53);
-
-#endif /* not C4X */
-#endif /* not IBM */
-#endif /* not DEC */
+ 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 (tr, mode, low, high, unsigned_p)
+ REAL_VALUE_TYPE *tr;
+ 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;
+ struct real_value *r = (struct real_value *) tr;
- e = pe;
- p = yy;
- for (i = 0; i < NE - 5; i++)
- *p++ = 0;
-#ifndef C4X
- /* REAL_WORDS_BIG_ENDIAN is always 0 for DEC and 1 for IBM.
- This precision is not ordinarily supported on DEC or IBM. */
- if (! REAL_WORDS_BIG_ENDIAN)
+ if (low == 0 && high == 0)
+ get_zero (r, 0);
+ else
{
- for (i = 0; i < 5; i++)
- *p++ = *e++;
-
-#ifdef IEEE
- /* 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)
+ r->class = rvc_normal;
+ r->sign = high < 0 && !unsigned_p;
+ r->exp = 2 * HOST_BITS_PER_WIDE_INT;
+
+ if (r->sign)
{
- UEMUSHORT temp[NI];
+ high = ~high;
+ if (low == 0)
+ high += 1;
+ else
+ low = -low;
+ }
- emovi (yy, temp);
- eshup1 (temp);
- emovo (temp,y);
- return;
+ if (HOST_BITS_PER_LONG == HOST_BITS_PER_WIDE_INT)
+ {
+ r->sig[SIGSZ-1] = high;
+ r->sig[SIGSZ-2] = low;
+ memset (r->sig, 0, sizeof(long)*(SIGSZ-2));
}
-#endif /* IEEE */
- }
- else
- {
- p = &yy[0] + (NE - 1);
- *p-- = *e++;
- ++e;
- for (i = 0; i < 4; i++)
- *p-- = *e++;
- }
-#endif /* not C4X */
-#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)
+ else if (HOST_BITS_PER_LONG*2 == 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 >> (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));
}
else
- {
- /* 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;
+ abort ();
- for (i = 3; i <= 5; i++)
- {
- if (pe[i] != 0)
- {
-bigend_nan:
- enan (y, (*p & 0x8000) != 0);
- return;
- }
- }
- }
-#endif /* NANS */
- eclear (y);
- einfin (y);
- if (*p & 0x8000)
- eneg (y);
- return;
+ normalize (r);
}
-#endif /* INFINITY */
- p = yy;
- q = y;
- for (i = 0; i < NE; i++)
- *q++ = *p++;
-}
-
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* Convert 128-bit long double precision float PE to e type Y. */
-static void
-e113toe (pe, y)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
-{
- ieeetoe (pe, y, &ieee_113);
+ if (mode != VOIDmode)
+ real_convert (tr, mode, tr);
}
-#endif /* INTEL_EXTENDED_IEEE_FORMAT == 0 */
-/* 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 struct real_value *
+ten_to_ptwo (n)
+ int n;
{
-#ifdef IBM
-
- ibmtoe (pe, y, SFmode);
-
-#else
-
-#ifdef C4X
-
- c4xtoe (pe, y, QFmode);
-
-#else
-#ifdef DEC
-
- ieeetoe (pe, y, &dec_f);
-
-#else
+ static struct real_value tens[EXP_BITS];
- ieeetoe (pe, y, &ieee_24);
-
-#endif /* not DEC */
-#endif /* not C4X */
-#endif /* not IBM */
-}
-
-/* Convert machine format float of specified format PE to e type Y. */
+ if (n < 0 || n >= EXP_BITS)
+ abort ();
-static void
-ieeetoe (pe, y, fmt)
- const UEMUSHORT *pe;
- UEMUSHORT *y;
- const struct ieee_format *fmt;
-{
- UEMUSHORT r;
- const UEMUSHORT *e;
- UEMUSHORT *p;
- UEMUSHORT yy[NI];
- int denorm, i, k;
- int shortsm1 = fmt->bits / 16 - 1;
-#ifdef INFINITY
- int expmask = (1 << fmt->expbits) - 1;
-#endif
-int expshift = (fmt->precision - 1) & 0x0f;
- int highbit = 1 << expshift;
-
- e = pe;
- denorm = 0;
- ecleaz (yy);
- if (! REAL_WORDS_BIG_ENDIAN)
- e += shortsm1;
- r = *e;
- yy[0] = 0;
- if (r & 0x8000)
- yy[0] = 0xffff;
- yy[M] = (r & (highbit - 1)) | highbit;
- r = (r & 0x7fff) >> expshift;
-#ifdef INFINITY
- if (!LARGEST_EXPONENT_IS_NORMAL (fmt->precision) && r == expmask)
+ if (tens[n].class == rvc_zero)
{
-#ifdef NANS
- /* First check the word where high order mantissa and exponent live */
- if ((*e & (highbit - 1)) != 0)
+ if (n < (HOST_BITS_PER_WIDE_INT == 64 ? 5 : 4))
{
- enan (y, yy[0] != 0);
- return;
- }
- if (! REAL_WORDS_BIG_ENDIAN)
- {
- for (i = 0; i < shortsm1; 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 ((REAL_VALUE_TYPE *) &tens[n], VOIDmode, t, 0, 1);
}
else
{
- for (i = 1; i < shortsm1 + 1; i++)
- {
- if (pe[i] != 0)
- {
- enan (y, yy[0] != 0);
- return;
- }
- }
- }
-#endif /* NANS */
- eclear (y);
- einfin (y);
- if (yy[0])
- eneg (y);
- return;
- }
-#endif /* INFINITY */
- /* If zero exponent, then the significand is denormalized.
- So take back the understood high significand bit. */
- if (r == 0)
- {
- denorm = 1;
- yy[M] &= ~highbit;
- }
- r += fmt->adjustment;
- yy[E] = r;
- p = &yy[M + 1];
- if (! REAL_WORDS_BIG_ENDIAN)
- {
- for (i = 0; i < shortsm1; i++)
- *p++ = *(--e);
- }
- else
- {
- ++e;
- for (i = 0; i < shortsm1; i++)
- *p++ = *e++;
- }
- if (fmt->precision == 113)
- {
- /* denorm is left alone in 113 bit format */
- if (!denorm)
- eshift (yy, -1);
- }
- else
- {
- eshift (yy, -(expshift + 1));
- if (denorm)
- { /* if zero exponent, then normalize the significand */
- if ((k = enormlz (yy)) > NBITS)
- ecleazs (yy);
- else
- yy[E] -= (UEMUSHORT) (k - 1);
+ const struct real_value *t = ten_to_ptwo (n - 1);
+ do_multiply (&tens[n], t, t);
}
}
- emovo (yy, y);
+
+ 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 struct real_value *
+real_digit (n)
+ int n;
{
- etoieee (x, e, &ieee_113);
+ static struct real_value num[10];
+
+ if (n < 0 || n > 9)
+ abort ();
+
+ if (n > 0 && num[n].class == rvc_zero)
+ real_from_integer ((REAL_VALUE_TYPE *) &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. */
+/* Fills R with +Inf. */
-static void
-toe113 (x, y)
- UEMUSHORT *x, *y;
+void
+real_inf (tr)
+ REAL_VALUE_TYPE *tr;
{
- toieee (x, y, &ieee_113);
+ get_inf ((struct real_value *)tr, 0);
}
-#endif /* INTEL_EXTENDED_IEEE_FORMAT == 0 */
+/* 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. */
-/* Convert e-type X to IEEE double extended format E. */
-
-static void
-etoe64 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+void
+real_nan (tr, str, quiet, mode)
+ REAL_VALUE_TYPE *tr;
+ const char *str;
+ int quiet;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
{
- etoieee (x, e, &ieee_64);
+ struct real_value *r = (struct real_value *) tr;
+
+ if (*str == 0)
+ {
+ if (quiet)
+ get_canonical_qnan (r, 0);
+ else
+ get_canonical_snan (r, 0);
+ }
+ else
+ /* FIXME */
+ abort ();
}
-/* Convert exploded e-type X, that has already been rounded to
- 64-bit precision, to IEEE double extended format Y. */
+/* Fills R with 2**N. */
-static void
-toe64 (x, y)
- UEMUSHORT *x, *y;
+void
+real_2expN (tr, n)
+ REAL_VALUE_TYPE *tr;
+ int n;
{
- toieee (x, y, &ieee_64);
-}
+ struct real_value *r = (struct real_value *) tr;
-/* e type to double precision. */
+ memset (r, 0, sizeof (*r));
-#ifdef DEC
-/* Convert e-type X to DEC-format 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;
+ struct real_value *r;
{
- etodec (x, e);
-}
+ int p2, np2, i, w;
+ bool sticky, guard, lsb;
+ int emin2m1, emax2;
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit double precision, to DEC double Y. */
+ p2 = fmt->p * fmt->log2_b;
+ emin2m1 = (fmt->emin - 1) * fmt->log2_b;
+ emax2 = fmt->emax * fmt->log2_b;
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- todec (x, y);
-}
+ np2 = SIGNIFICAND_BITS - p2;
+ switch (r->class)
+ {
+ underflow:
+ get_zero (r, r->sign);
+ case rvc_zero:
+ if (!fmt->has_signed_zero)
+ r->sign = 0;
+ return;
-#else
-#ifdef IBM
-/* Convert e-type X to IBM 370-format double E. */
+ overflow:
+ get_inf (r, r->sign);
+ case rvc_inf:
+ return;
-static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoibm (x, e, DFmode);
-}
+ case rvc_nan:
+ clear_significand_below (r, np2 + 1);
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit precision, to IBM 370 double Y. */
+ /* 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 >> 1;
+ return;
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- toibm (x, y, DFmode);
-}
+ case rvc_normal:
+ break;
-#else /* it's neither DEC nor IBM */
-#ifdef C4X
-/* Convert e-type X to C4X-format long double E. */
+ default:
+ abort ();
+ }
-static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoc4x (x, e, HFmode);
-}
+ /* If we're not base2, normalize the exponent to a multiple of
+ the true base. */
+ if (fmt->log2_b != 1)
+ {
+ int shift = r->exp & (fmt->log2_b - 1);
+ if (shift)
+ {
+ shift = fmt->log2_b - shift;
+ sticky_rshift_significand (r, r, shift);
+ r->exp += shift;
+ }
+ }
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit precision, to IBM 370 double Y. */
+ /* 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;
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- toc4x (x, y, HFmode);
-}
+ if (!fmt->has_denorm)
+ {
+ /* Don't underflow completely until we've had a chance to round. */
+ if (r->exp < emin2m1)
+ goto underflow;
+ }
+ else
+ {
+ diff = emin2m1 - r->exp + 1;
+ if (diff > p2)
+ goto underflow;
-#else /* it's neither DEC nor IBM nor C4X */
+ /* De-normalize the significand. */
+ sticky_rshift_significand (r, r, diff);
+ r->exp += diff;
+ }
+ }
-/* Convert e-type X to IEEE double E. */
+ /* There are P2 true significand bits, followed by one guard bit,
+ followed by one sticky bit, followed by stuff. Fold non-zero
+ stuff into the sticky bit. */
-static void
-etoe53 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoieee (x, e, &ieee_53);
-}
+ sticky = 0;
+ for (i = 0, w = (np2 - 1) / HOST_BITS_PER_LONG; i < w; ++i)
+ if (r->sig[i])
+ sticky = 1;
+ sticky |=
+ r->sig[w] & (((unsigned long)1 << ((np2 - 1) % HOST_BITS_PER_LONG)) - 1);
-/* Convert exploded e-type X, that has already been rounded to
- 53-bit precision, to IEEE double Y. */
+ guard = test_significand_bit (r, np2 - 1);
+ lsb = test_significand_bit (r, np2);
-static void
-toe53 (x, y)
- UEMUSHORT *x, *y;
-{
- toieee (x, y, &ieee_53);
-}
+ /* Round to even. */
+ if (guard && (sticky || lsb))
+ {
+ struct real_value u;
+ get_zero (&u, 0);
+ set_significand_bit (&u, np2);
-#endif /* not C4X */
-#endif /* not IBM */
-#endif /* not DEC */
+ 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;
+ sticky_rshift_significand (r, r, shift);
+ r->exp += shift;
+ if (r->exp > emax2)
+ goto overflow;
+ }
+ }
+ }
+ }
+ /* Catch underflow that we deferred until after rounding. */
+ if (r->exp <= emin2m1)
+ goto underflow;
-/* e type to single precision. */
+ /* Clear out trailing garbage. */
+ clear_significand_below (r, np2);
+}
-#ifdef IBM
-/* Convert e-type X to IBM 370 float E. */
+/* Extend or truncate to a new mode. */
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+void
+real_convert (tr, mode, ta)
+ REAL_VALUE_TYPE *tr;
+ enum machine_mode mode;
+ const REAL_VALUE_TYPE *ta;
{
- etoibm (x, e, SFmode);
+ struct real_value *r = (struct real_value *)tr;
+ const struct real_value *a = (const struct real_value *)ta;
+ const struct real_format *fmt;
+
+ fmt = fmt_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
+
+ *r = *a;
+ round_for_format (fmt, r);
+
+ /* round_for_format de-normalizes denormals. Undo just that part. */
+ if (r->class == rvc_normal)
+ normalize (r);
}
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to IBM 370 float Y. */
+/* Legacy. Likewise, except return the struct directly. */
-static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+REAL_VALUE_TYPE
+real_value_truncate (mode, a)
+ enum machine_mode mode;
+ REAL_VALUE_TYPE a;
{
- toibm (x, y, SFmode);
+ REAL_VALUE_TYPE r;
+ real_convert (&r, mode, &a);
+ return r;
}
-#else /* it's not IBM */
+/* Return true if truncating to MODE is exact. */
-#ifdef C4X
-/* Convert e-type X to C4X float E. */
-
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+bool
+exact_real_truncate (mode, ta)
+ enum machine_mode mode;
+ const REAL_VALUE_TYPE *ta;
{
- etoc4x (x, e, QFmode);
+ REAL_VALUE_TYPE t;
+ real_convert (&t, mode, ta);
+ return real_identical (&t, ta);
}
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to IBM 370 float Y. */
+/* Write R to the target format of MODE. Place the words of the
+ result in target word order in BUF. There are always 32 bits
+ in each long, no matter the size of the host long.
-static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+ Legacy: return word 0 for implementing REAL_VALUE_TO_TARGET_SINGLE. */
+
+long
+real_to_target (buf, tr, mode)
+ long *buf;
+ const REAL_VALUE_TYPE *tr;
+ enum machine_mode mode;
{
- toc4x (x, y, QFmode);
-}
+ struct real_value r;
+ const struct real_format *fmt;
+ long buf1;
-#else /* it's neither IBM nor C4X */
+ r = *(const struct real_value *) tr;
-#ifdef DEC
+ fmt = fmt_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
-/* Convert e-type X to DEC F-float E. */
+ round_for_format (fmt, &r);
+ if (!buf)
+ buf = &buf1;
+ (*fmt->encode) (fmt, buf, &r);
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
-{
- etoieee (x, e, &dec_f);
+ return *buf;
}
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to DEC F-float Y. */
+/* Read R from the target format of MODE. Read the words of the
+ result in target word order in BUF. There are always 32 bits
+ in each long, no matter the size of the host long. */
-static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+void
+real_from_target (tr, buf, mode)
+ REAL_VALUE_TYPE *tr;
+ const long *buf;
+ enum machine_mode mode;
{
- toieee (x, y, &dec_f);
-}
+ struct real_value *r = (struct real_value *) tr;
+ const struct real_format *fmt;
-#else
+ fmt = fmt_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
-/* Convert e-type X to IEEE float E. */
+ (*fmt->decode) (fmt, r, buf);
+}
-static void
-etoe24 (x, e)
- const UEMUSHORT *x;
- UEMUSHORT *e;
+/* Return the number of bits in the significand for MODE. */
+/* ??? Legacy. Should get access to real_format directly. */
+
+int
+significand_size (mode)
+ enum machine_mode mode;
{
- etoieee (x, e, &ieee_24);
+ const struct real_format *fmt;
+
+ fmt = fmt_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ return 0;
+
+ return fmt->p * fmt->log2_b;
}
+
+/* IEEE single-precision format. */
-/* Convert exploded e-type X, that has already been rounded to
- float precision, to IEEE float Y. */
+static void encode_ieee_single PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_ieee_single PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
static void
-toe24 (x, y)
- UEMUSHORT *x, *y;
+encode_ieee_single (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const struct real_value *r;
{
- toieee (x, y, &ieee_24);
-}
+ unsigned long image, sig, exp;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
-#endif /* not DEC */
-#endif /* not C4X */
-#endif /* not IBM */
+ image = r->sign << 31;
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
+ switch (r->class)
+ {
+ case rvc_zero:
+ break;
-/* Convert e-type X to the IEEE format described by FMT. */
+ case rvc_inf:
+ if (fmt->has_inf)
+ image |= 255 << 23;
+ else
+ image |= 0x7fffffff;
+ break;
-static void
-etoieee (x, e, fmt)
- const UEMUSHORT *x;
- UEMUSHORT *e;
- const struct ieee_format *fmt;
-{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
+ case rvc_nan:
+ if (fmt->has_nans)
+ {
+ image |= 255 << 23;
+ image |= sig;
+ if (!fmt->qnan_msb_set)
+ image ^= 1 << 23 | 1 << 22;
+ }
+ else
+ image |= 0x7fffffff;
+ break;
-#ifdef NANS
- if (eisnan (x))
- {
- make_nan (e, eisneg (x), fmt->mode);
- return;
+ 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;
}
-#endif
-
- emovi (x, xi);
-#ifdef INFINITY
- if (eisinf (x))
- goto nonorm;
-#endif
- /* Adjust exponent for offset. */
- exp = (EMULONG) xi[E] - fmt->adjustment;
-
- /* Round off to nearest or even. */
- rndsav = rndprc;
- rndprc = fmt->precision;
- emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
- rndprc = rndsav;
-#ifdef INFINITY
- nonorm:
-#endif
- toieee (xi, e, fmt);
+ buf[0] = image;
}
-/* Convert exploded e-type X, that has already been rounded to
- the necessary precision, to the IEEE format described by FMT. */
-
static void
-toieee (x, y, fmt)
- UEMUSHORT *x, *y;
- const struct ieee_format *fmt;
+decode_ieee_single (fmt, r, buf)
+ const struct real_format *fmt;
+ struct real_value *r;
+ const long *buf;
{
- UEMUSHORT maxexp;
- UEMUSHORT *q;
- int words;
- int i;
+ unsigned long image = buf[0] & 0xffffffff;
+ bool sign = (image >> 31) & 1;
+ int exp = (image >> 23) & 0xff;
- maxexp = (1 << fmt->expbits) - 1;
- words = (fmt->bits - fmt->expbits) / EMUSHORT_SIZE;
-
-#ifdef NANS
- if (eiisnan (x))
- {
- make_nan (y, eiisneg (x), fmt->mode);
- return;
- }
-#endif
+ memset (r, 0, sizeof (*r));
+ image <<= HOST_BITS_PER_LONG - 24;
+ image &= ~SIG_MSB;
- if (fmt->expbits < 15
- && LARGEST_EXPONENT_IS_NORMAL (fmt->bits)
- && x[E] > maxexp)
+ if (exp == 0)
{
- saturate (y, eiisneg (x), fmt->bits, 1);
- return;
+ 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;
}
-
- /* Point to the exponent. */
- if (REAL_WORDS_BIG_ENDIAN)
- q = y;
- else
- q = y + words;
-
- /* Copy the sign. */
- if (x[0])
- *q = 0x8000;
- else
- *q = 0;
-
- if (fmt->expbits < 15
- && !LARGEST_EXPONENT_IS_NORMAL (fmt->bits)
- && x[E] >= maxexp)
+ else if (exp == 255 && (fmt->has_nans || fmt->has_inf))
{
- /* Saturate at largest number less that infinity. */
- UEMUSHORT fill;
-#ifdef INFINITY
- *q |= maxexp << (15 - fmt->expbits);
- fill = 0;
-#else
- *q |= (maxexp << (15 - fmt->expbits)) - 1;
- fill = 0xffff;
-#endif
-
- if (!REAL_WORDS_BIG_ENDIAN)
+ if (image)
{
- for (i = 0; i < words; i++)
- *(--q) = fill;
+ 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
{
- for (i = 0; i < words; i++)
- *(++q) = fill;
+ r->class = rvc_inf;
+ r->sign = sign;
}
-#if defined(INFINITY) && defined(ERANGE)
- errno = ERANGE;
-#endif
- return;
}
-
- /* If denormal and DEC float, return zero (DEC has no denormals) */
-#ifdef DEC
- if (x[E] == 0)
- {
- for (i = 0; i < fmt->bits / EMUSHORT_SIZE ; i++)
- q[i] = 0;
- return;
- }
-#endif /* DEC */
-
- /* Delete the implied bit unless denormal, except for
- 64-bit precision. */
- if (fmt->precision != 64 && x[E] != 0)
+ else
{
- eshup1 (x);
- }
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 127 + 1;
+ r->sig[SIGSZ-1] = image | SIG_MSB;
+ }
+}
+
+const struct real_format ieee_single =
+ {
+ encode_ieee_single,
+ decode_ieee_single,
+ 2,
+ 1,
+ 24,
+ -125,
+ 128,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
- /* Shift denormal double extended Intel format significand down
- one bit. */
- if (fmt->precision == 64 && x[E] == 0 && ! REAL_WORDS_BIG_ENDIAN)
- eshdn1 (x);
+
+/* IEEE double-precision format. */
- if (fmt->expbits < 15)
- {
- /* Shift the significand. */
- eshift (x, 15 - fmt->expbits);
+static void encode_ieee_double PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_ieee_double PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
- /* Combine the exponent and upper bits of the significand. */
- *q |= x[E] << (15 - fmt->expbits);
- *q |= x[M] & (UEMUSHORT) ~((maxexp << (15 - fmt->expbits)) | 0x8000);
- }
- else
- {
- /* Copy the exponent. */
- *q |= x[E];
- }
-
- /* Add padding after the exponent. At the moment, this is only necessary for
- 64-bit precision; in this case, the padding is 16 bits. */
- if (fmt->precision == 64)
- {
- *(q + 1) = 0;
+static void
+encode_ieee_double (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const struct real_value *r;
+{
+ unsigned long image_lo, image_hi, sig_lo, sig_hi, exp;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
- /* Skip padding. */
- if (REAL_WORDS_BIG_ENDIAN)
- ++q;
- }
+ image_hi = r->sign << 31;
+ image_lo = 0;
- /* Copy the significand. */
- if (REAL_WORDS_BIG_ENDIAN)
+ if (HOST_BITS_PER_LONG == 64)
{
- for (i = 0; i < words; i++)
- *(++q) = x[i + M + 1];
+ sig_hi = r->sig[SIGSZ-1];
+ sig_lo = (sig_hi >> (64 - 53)) & 0xffffffff;
+ sig_hi = (sig_hi >> (64 - 53 + 1) >> 31) & 0xfffff;
}
-#ifdef INFINITY
- else if (fmt->precision == 64 && eiisinf (x))
- {
- /* Intel double extended infinity significand. */
- *(--q) = 0x8000;
- *(--q) = 0;
- *(--q) = 0;
- *(--q) = 0;
- }
-#endif
else
{
- for (i = 0; i < words; i++)
- *(--q) = x[i + M + 1];
+ 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;
}
-}
+ switch (r->class)
+ {
+ case rvc_zero:
+ break;
-/* Compare two e type numbers.
- Return +1 if a > b
- 0 if a == b
- -1 if a < b
- -2 if either a or b is a NaN. */
-
-static int
-ecmp (a, b)
- const UEMUSHORT *a, *b;
-{
- UEMUSHORT ai[NI], bi[NI];
- UEMUSHORT *p, *q;
- int i;
- int msign;
+ case rvc_inf:
+ if (fmt->has_inf)
+ image_hi |= 2047 << 20;
+ else
+ {
+ image_hi |= 0x7fffffff;
+ image_lo = 0xffffffff;
+ }
+ break;
-#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++)
+ case rvc_nan:
+ if (fmt->has_nans)
{
- if (ai[i] != 0)
- goto nzro;
- if (bi[i] != 0)
- goto nzro;
+ image_hi |= 2047 << 20;
+ image_hi |= sig_hi;
+ if (!fmt->qnan_msb_set)
+ image_hi ^= 1 << 19 | 1 << 18;
+ image_lo = sig_lo;
}
- 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;
+ image_hi |= 0x7fffffff;
+ image_lo = 0xffffffff;
}
- }
- while (--i > 0);
-
- return (0); /* equality */
-
- diff:
-
- if (*(--p) > *(--q))
- return (msign); /* p is bigger */
- else
- return (-msign); /* p is littler */
-}
-
-#if 0
-/* Find e-type nearest integer to X, as floor (X + 0.5). */
-
-static void
-eround (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
-{
- eadd (ehalf, x, y);
- efloor (y, y);
-}
-#endif /* 0 */
-
-/* Convert HOST_WIDE_INT LP to e type Y. */
-
-static void
-ltoe (lp, y)
- const HOST_WIDE_INT *lp;
- UEMUSHORT *y;
-{
- UEMUSHORT yi[NI];
- unsigned HOST_WIDE_INT ll;
- int k;
+ break;
- ecleaz (yi);
- if (*lp < 0)
- {
- /* make it positive */
- ll = (unsigned HOST_WIDE_INT) (-(*lp));
- yi[0] = 0xffff; /* put correct sign in the e type number */
- }
- else
- {
- ll = (unsigned HOST_WIDE_INT) (*lp);
+ 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;
}
- /* 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
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image_hi, buf[1] = image_lo;
else
- yi[E] -= (UEMUSHORT) k;/* subtract shift count from exponent */
- emovo (yi, y); /* output the answer */
+ buf[0] = image_lo, buf[1] = image_hi;
}
-/* Convert unsigned HOST_WIDE_INT LP to e type Y. */
-
static void
-ultoe (lp, y)
- const unsigned HOST_WIDE_INT *lp;
- UEMUSHORT *y;
+decode_ieee_double (fmt, r, buf)
+ const struct real_format *fmt;
+ struct real_value *r;
+ const long *buf;
{
- 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
+ unsigned long image_hi, image_lo;
+ bool sign;
+ int exp;
- if ((k = enormlz (yi)) > NBITS)/* normalize the significand */
- ecleaz (yi); /* it was zero */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image_hi = buf[0], image_lo = buf[1];
else
- yi[E] -= (UEMUSHORT) k; /* subtract shift count from exponent */
- emovo (yi, y); /* output the answer */
-}
+ image_lo = buf[0], image_hi = buf[1];
+ image_lo &= 0xffffffff;
+ image_hi &= 0xffffffff;
+ sign = (image_hi >> 31) & 1;
+ exp = (image_hi >> 20) & 0x7ff;
-/* 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). */
+ memset (r, 0, sizeof (*r));
-static void
-eifrac (x, i, frac)
- const UEMUSHORT *x;
- HOST_WIDE_INT *i;
- UEMUSHORT *frac;
-{
- UEMUSHORT xi[NI];
- int j, k;
- unsigned HOST_WIDE_INT ll;
+ image_hi <<= 32 - 21;
+ image_hi |= image_lo >> 21;
+ image_hi &= 0x7fffffff;
+ image_lo <<= 32 - 21;
- emovi (x, xi);
- k = (int) xi[E] - (EXONE - 1);
- if (k <= 0)
+ if (exp == 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))
- {
- /* long integer overflow: output large integer
- and correct fraction */
- if (xi[0])
- *i = ((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1);
- else
+ if ((image_hi || image_lo) && fmt->has_denorm)
{
-#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
+ 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);
}
- eshift (xi, k);
- if (extra_warnings)
- warning ("overflow on truncation to integer");
+ else if (fmt->has_signed_zero)
+ r->sign = sign;
}
- else if (k > 16)
+ else if (exp == 2047 && (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_hi || image_lo)
{
- eshup6 (xi);
- ll = (ll << 16) | xi[M];
- }
- 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;
-
- emovo (xi, frac);
-}
-
-
-/* Find unsigned HOST_WIDE_INT integer I and floating point fractional part
- FRAC of e-type X. A negative input yields integer output = 0 but
- correct fraction. */
-
-static void
-euifrac (x, i, frac)
- const UEMUSHORT *x;
- unsigned HOST_WIDE_INT *i;
- UEMUSHORT *frac;
-{
- unsigned HOST_WIDE_INT ll;
- UEMUSHORT xi[NI];
- int j, k;
+ 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;
- 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)
- {
- /* Long integer overflow: output large integer
- and correct fraction.
- Note, the BSD MicroVAX compiler says that ~(0UL)
- is a syntax error. */
- *i = ~(0L);
- eshift (xi, k);
- if (extra_warnings)
- warning ("overflow on truncation to unsigned integer");
- }
- else if (k > 16)
- {
- /* Shift more than 16 bits: first shift up k-16 mod 16,
- then shift up by 16's. */
- j = k - ((k >> 4) << 4);
- eshift (xi, j);
- ll = xi[M];
- k -= j;
- do
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
+ }
+ else
{
- eshup6 (xi);
- ll = (ll << 16) | xi[M];
+ 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;
- }
-
- if (xi[0]) /* A negative value yields unsigned integer 0. */
- *i = 0L;
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 1023 + 1;
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ r->sig[SIGSZ-1] = image_hi | SIG_MSB;
+ r->sig[SIGSZ-2] = image_lo;
+ }
+ else
+ r->sig[SIGSZ-1] = (image_hi << 31 << 1) | image_lo | SIG_MSB;
+ }
+}
+
+const struct real_format ieee_double =
+ {
+ encode_ieee_double,
+ decode_ieee_double,
+ 2,
+ 1,
+ 53,
+ -1021,
+ 1024,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
- xi[0] = 0;
- xi[E] = EXONE - 1;
- xi[M] = 0;
- if ((k = enormlz (xi)) > NBITS)
- ecleaz (xi);
- else
- xi[E] -= (UEMUSHORT) k;
+
+/* 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. */
- emovo (xi, frac);
-}
+static void encode_ieee_extended PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_ieee_extended PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
-/* Shift the significand of exploded e-type X up or down by SC bits. */
+static void encode_ieee_extended_128 PARAMS ((const struct real_format *fmt,
+ long *,
+ const struct real_value *));
+static void decode_ieee_extended_128 PARAMS ((const struct real_format *,
+ struct real_value *,
+ const long *));
-static int
-eshift (x, sc)
- UEMUSHORT *x;
- int sc;
+static void
+encode_ieee_extended (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const struct real_value *r;
{
- UEMUSHORT lost;
- UEMUSHORT *p;
-
- if (sc == 0)
- return (0);
+ unsigned long image_hi, sig_hi, sig_lo;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
- lost = 0;
- p = x + NI - 1;
+ image_hi = r->sign << 15;
+ sig_hi = sig_lo = 0;
- 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)
{
- lost |= *p & 0xff;
- eshdn8 (x);
- sc -= 8;
- }
+ image_hi |= 32767;
- while (sc > 0)
- {
- lost |= *p & 1;
- eshdn1 (x);
- sc -= 1;
- }
- }
- else
- {
- while (sc >= 16)
- {
- eshup6 (x);
- sc -= 16;
+ /* 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;
}
-
- while (sc >= 8)
+ else
{
- eshup8 (x);
- sc -= 8;
+ image_hi |= 32767;
+ sig_lo = sig_hi = 0xffffffff;
}
+ break;
- while (sc > 0)
+ case rvc_nan:
+ if (fmt->has_nans)
{
- eshup1 (x);
- sc -= 1;
- }
- }
- if (lost)
- lost = 1;
- return ((int) lost);
-}
-
-/* Shift normalize the significand area of exploded e-type X.
- Return the shift count (up = positive). */
-
-static int
-enormlz (x)
- UEMUSHORT x[];
-{
- UEMUSHORT *p;
- int sc;
-
- sc = 0;
- p = &x[M];
- if (*p != 0)
- goto normdn;
- ++p;
- if (*p & 0x8000)
- return (0); /* already normalized */
- while (*p == 0)
- {
- eshup6 (x);
- sc += 16;
+ 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;
- /* With guard word, there are NBITS+16 bits available.
- Return true if all are zero. */
- if (sc > NBITS)
- return (sc);
- }
- /* see if high byte is zero */
- while ((*p & 0xff00) == 0)
- {
- eshup8 (x);
- sc += 8;
- }
- /* now shift 1 bit at a time */
- while ((*p & 0x8000) == 0)
- {
- eshup1 (x);
- sc += 1;
- if (sc > NBITS)
- {
- mtherr ("enormlz", UNDERFLOW);
- return (sc);
+ /* 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;
}
- }
- return (sc);
-
- /* Normalize by shifting down out of the high guard word
- of the significand */
- normdn:
-
- if (*p & 0xff00)
- {
- eshdn8 (x);
- sc -= 8;
- }
- while (*p != 0)
- {
- eshdn1 (x);
- sc -= 1;
-
- if (sc < -NBITS)
+ else
{
- mtherr ("enormlz", OVERFLOW);
- return (sc);
+ image_hi |= 32767;
+ sig_lo = sig_hi = 0xffffffff;
}
- }
- 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 */
-};
-
-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 */
-};
-
-static const UEMUSHORT emtens[NTEN + 1][NE] =
-{
- {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
+ break;
-#if 0
-/* Convert float value X to ASCII string STRING with NDIG digits after
- the decimal point. */
+ case rvc_normal:
+ {
+ int exp = r->exp;
-static void
-e24toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
-{
- UEMUSHORT w[NI];
+ /* 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.
- e24toe (x, w);
- etoasc (w, string, ndigs);
-}
+ 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. */
-/* Convert double value X to ASCII string STRING with NDIG digits after
- the decimal point. */
+ if (denormal)
+ exp = 0;
+ else
+ {
+ exp += 16383 - 1;
+ if (exp < 0)
+ abort ();
+ }
+ image_hi |= exp;
-static void
-e53toasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
-{
- UEMUSHORT w[NI];
+ 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;
+ }
- e53toe (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 double extended value X to ASCII string STRING with NDIG digits
- after the decimal point. */
-
static void
-e64toasc (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 struct real_value *r;
{
- UEMUSHORT w[NI];
-
- e64toe (x, w);
- etoasc (w, string, ndigs);
+ buf[3 * !FLOAT_WORDS_BIG_ENDIAN] = 0;
+ encode_ieee_extended (fmt, buf+!!FLOAT_WORDS_BIG_ENDIAN, r);
}
-/* 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;
+decode_ieee_extended (fmt, r, buf)
+ const struct real_format *fmt;
+ struct real_value *r;
+ const long *buf;
{
- UEMUSHORT w[NI];
+ unsigned long image_hi, sig_hi, sig_lo;
+ bool sign;
+ int exp;
- e113toe (x, w);
- etoasc (w, string, ndigs);
-}
-#endif /* 0 */
+ 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;
-/* Convert e-type X to ASCII string STRING with NDIGS digits after
- the decimal point. */
+ sign = (image_hi >> 15) & 1;
+ exp = image_hi & 0x7fff;
-static char wstring[80]; /* working storage for ASCII output */
+ memset (r, 0, sizeof (*r));
-static void
-etoasc (x, string, ndigs)
- const UEMUSHORT x[];
- char *string;
- int ndigs;
-{
- 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)
+ if (exp == 0)
{
- 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 ((sig_hi || sig_lo) && fmt->has_denorm)
{
- 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;
- }
+ r->class = rvc_normal;
+ r->sign = sign;
- /* 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;
- }
-
- /* Compare to 1.0 */
- i = ecmp (eone, y);
- if (i == 0)
- goto isone;
-
- if (i == -2)
- abort ();
-
- 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;
-
- p = &etens[NTEN - 4][0];
- m = 16;
- do
- {
- ediv (p, u, t);
- efloor (t, w);
- for (j = 0; j < NE - 1; j++)
+ /* 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)
{
- if (t[j] != w[j])
- goto noint;
+ r->sig[SIGSZ-1] = sig_hi;
+ r->sig[SIGSZ-2] = sig_lo;
}
- 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 (ecmp (p, u) <= 0)
- {
- ediv (p, u, u);
- emul (p, t, t);
- expon += (int) m;
- }
- 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)
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 16383 + 1;
+ if (HOST_BITS_PER_LONG == 32)
{
- 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
+ r->sig[SIGSZ-1] = sig_hi;
+ r->sig[SIGSZ-2] = sig_lo;
}
- /* 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')
- {
- *s = '0';
- goto roun;
- }
- }
- doexp:
- /* Strip trailing zeros, but leave at least one. */
- while (ss[-1] == '0' && ss[-2] != '.')
- --ss;
- sprintf (ss, "e%d", expon);
- bxit:
- rndprc = rndsav;
- /* copy out the working string */
- s = string;
- ss = wstring;
- while (*ss == ' ') /* strip possible leading space */
- ++ss;
- while ((*s++ = *ss++) != '\0')
- ;
-}
-
-
-/* Convert ASCII string to floating point.
-
- Numeric input is a free format decimal number of any length, with
- or without decimal point. Entering E after the number followed by an
- integer number causes the second number to be interpreted as a power of
- 10 to be multiplied by the first number (i.e., "scientific" notation). */
-
-/* Convert ASCII string S to single precision float value Y. */
-
-static void
-asctoe24 (s, y)
- const char *s;
- UEMUSHORT *y;
-{
- asctoeg (s, y, 24);
-}
-
-
-/* Convert ASCII string S to double precision value Y. */
-
-static void
-asctoe53 (s, y)
- const char *s;
- UEMUSHORT *y;
-{
-#if defined(DEC) || defined(IBM)
- asctoeg (s, y, 56);
-#else
-#if defined(C4X)
- asctoeg (s, y, 32);
-#else
- asctoeg (s, y, 53);
-#endif
-#endif
-}
-
-
-/* Convert ASCII string S to double extended value Y. */
-
-static void
-asctoe64 (s, y)
- const char *s;
- UEMUSHORT *y;
-{
- asctoeg (s, y, 64);
-}
-
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
-/* Convert ASCII string S to 128-bit long double Y. */
+ else
+ r->sig[SIGSZ-1] = (sig_hi << 31 << 1) | sig_lo;
+ }
+}
+
+static void
+decode_ieee_extended_128 (fmt, r, buf)
+ const struct real_format *fmt;
+ struct real_value *r;
+ const long *buf;
+{
+ decode_ieee_extended (fmt, r, buf+!!FLOAT_WORDS_BIG_ENDIAN);
+}
+
+const struct real_format ieee_extended_motorola =
+ {
+ encode_ieee_extended,
+ decode_ieee_extended,
+ 2,
+ 1,
+ 64,
+ -16382,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+const struct real_format ieee_extended_intel_96 =
+ {
+ encode_ieee_extended,
+ decode_ieee_extended,
+ 2,
+ 1,
+ 64,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+const struct real_format ieee_extended_intel_128 =
+ {
+ encode_ieee_extended_128,
+ decode_ieee_extended_128,
+ 2,
+ 1,
+ 64,
+ -16381,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
-static void
-asctoe113 (s, y)
- const char *s;
- UEMUSHORT *y;
-{
- asctoeg (s, y, 113);
-}
-#endif
+
+/* IEEE quad precision format. */
-/* Convert ASCII string S to e type Y. */
+static void encode_ieee_quad PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_ieee_quad PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
static void
-asctoe (s, y)
- const char *s;
- UEMUSHORT *y;
+encode_ieee_quad (fmt, buf, r)
+ const struct real_format *fmt;
+ long *buf;
+ const struct real_value *r;
{
- asctoeg (s, y, NBITS);
-}
+ unsigned long image3, image2, image1, image0, exp;
+ bool denormal = (r->sig[SIGSZ-1] & SIG_MSB) == 0;
+ struct real_value 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. */
+ image3 = r->sign << 31;
+ image2 = 0;
+ image1 = 0;
+ image0 = 0;
-static void
-asctoeg (ss, y, oprec)
- const char *ss;
- UEMUSHORT *y;
- int oprec;
-{
- UEMUSHORT yy[NI], xt[NI], tt[NI];
- int esign, decflg, sgnflg, nexp, exp, prec, lost;
- int i, k, trail, c, rndsav;
- EMULONG lexp;
- UEMUSHORT nsign;
- char *sp, *s, *lstr;
- int base = 10;
-
- /* Copy the input string. */
- lstr = (char *) alloca (strlen (ss) + 1);
-
- while (*ss == ' ') /* skip leading spaces */
- ++ss;
-
- sp = lstr;
- while ((*sp++ = *ss++) != '\0')
- ;
- s = lstr;
+ rshift_significand (&u, r, SIGNIFICAND_BITS - 113);
- if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+ switch (r->class)
{
- base = 16;
- s += 2;
- }
+ case rvc_zero:
+ break;
- 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))
- {
- /* 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_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;
+
+ 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)
+ {
+ image0 = u.sig[0];
+ image1 = u.sig[1];
+ image2 = u.sig[2];
+ image3 |= u.sig[3] & 0xffff;
+ }
+ else
+ {
+ image0 = u.sig[0];
+ image1 = image0 >> 31 >> 1;
+ image2 = u.sig[1];
+ image3 |= (image2 >> 31 >> 1) & 0xffff;
+ image0 &= 0xffffffff;
+ image2 &= 0xffffffff;
+ }
break;
- 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))
+
+ if (FLOAT_WORDS_BIG_ENDIAN)
{
- infinite:
- ecleaz (yy);
- yy[E] = 0x7fff; /* infinity */
- goto aexit;
+ buf[0] = image3;
+ buf[1] = image2;
+ buf[2] = image1;
+ buf[3] = image0;
}
- if ((exp < MINDECEXP) && (base == 10))
+ else
{
- zero:
- ecleaz (yy);
- goto aexit;
+ buf[0] = image0;
+ buf[1] = image1;
+ buf[2] = image2;
+ buf[3] = image3;
}
+}
- daldone:
- if (base == 16)
- {
- /* Base 16 hexadecimal floating constant. */
- if ((k = enormlz (yy)) > NBITS)
- {
- ecleaz (yy);
- goto aexit;
- }
- /* Adjust the exponent. NEXP is the number of hex digits,
- EXP is a power of 2. */
- lexp = (EXONE - 1 + NBITS) - k + yy[E] + exp - nexp;
- if (lexp > 0x7fff)
- goto infinite;
- if (lexp < 0)
- goto zero;
- yy[E] = lexp;
- goto expdon;
- }
+static void
+decode_ieee_quad (fmt, r, buf)
+ const struct real_format *fmt;
+ struct real_value *r;
+ const long *buf;
+{
+ unsigned long image3, image2, image1, image0;
+ bool sign;
+ int exp;
- nexp = exp - nexp;
- /* Pad trailing zeros to minimize power of 10, per IEEE spec. */
- while ((nexp > 0) && (yy[2] == 0))
+ if (FLOAT_WORDS_BIG_ENDIAN)
{
- emovz (yy, xt);
- eshup1 (xt);
- eshup1 (xt);
- eaddm (yy, xt);
- eshup1 (xt);
- if (xt[2] != 0)
- break;
- nexp -= 1;
- emovz (xt, yy);
+ image3 = buf[0];
+ image2 = buf[1];
+ image1 = buf[2];
+ image0 = buf[3];
}
- if ((k = enormlz (yy)) > NBITS)
+ else
{
- ecleaz (yy);
- goto aexit;
+ image0 = buf[0];
+ image1 = buf[1];
+ image2 = buf[2];
+ image3 = buf[3];
}
- lexp = (EXONE - 1 + NBITS) - k;
- emdnorm (yy, lost, 0, lexp, 64);
- lost = 0;
+ image0 &= 0xffffffff;
+ image1 &= 0xffffffff;
+ image2 &= 0xffffffff;
- /* Convert to external format:
+ sign = (image3 >> 31) & 1;
+ exp = (image3 >> 16) & 0x7fff;
+ image3 &= 0xffff;
- 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. */
+ memset (r, 0, sizeof (*r));
- lexp = yy[E];
- if (nexp == 0)
- {
- k = 0;
- goto expdon;
- }
- esign = 1;
- if (nexp < 0)
+ if (exp == 0)
{
- nexp = -nexp;
- esign = -1;
- if (nexp > 4096)
+ if ((image3 | image2 | image1 | image0) && fmt->has_denorm)
{
- /* Punt. Can't handle this without 2 divides. */
- emovi (etens[0], tt);
- lexp -= tt[E];
- k = edivm (tt, yy);
- lexp += EXONE;
- nexp -= 4096;
+ 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;
+ }
+
+ normalize (r);
}
+ else if (fmt->has_signed_zero)
+ r->sign = sign;
}
- emov (eone, xt);
- exp = 1;
- i = NTEN;
- do
+ else if (exp == 32767 && (fmt->has_nans || fmt->has_inf))
{
- if (exp & nexp)
- emul (etens[i], xt, xt);
- i--;
- exp = exp + exp;
- }
- while (exp <= MAXP);
+ if (image3 | image2 | image1 | image0)
+ {
+ r->class = rvc_nan;
+ r->sign = sign;
- emovi (xt, tt);
- if (esign < 0)
- {
- lexp -= tt[E];
- k = edivm (tt, yy);
- lexp += EXONE;
- }
- else
- {
- lexp += tt[E];
- k = emulm (tt, yy);
- lexp -= EXONE - 1;
- }
- lost = k;
-
- expdon:
-
- /* 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
-#ifdef DEC
- else if (oprec == 24)
- lexp -= dec_f.adjustment;
- else if (oprec == 56)
- {
- if (TARGET_G_FLOAT)
- lexp -= dec_g.adjustment;
+ 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);
+
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1 | SIG_MSB >> 2);
+ }
else
- lexp -= dec_d.adjustment;
+ {
+ r->class = rvc_inf;
+ r->sign = sign;
+ }
}
-#else
-else if (oprec == 24)
- lexp -= EXONE - 0177;
-#endif /* DEC */
-#endif /* IBM */
-#endif /* C4X */
- rndprc = oprec;
- emdnorm (yy, lost, 0, lexp, 64);
-
- aexit:
-
- rndprc = rndsav;
- yy[0] = nsign;
- switch (oprec)
+ else
{
-#ifdef DEC
- case 56:
- todec (yy, y);
- break;
-#endif
-#ifdef IBM
- case 56:
- toibm (yy, y, DFmode);
- break;
-#endif
-#ifdef C4X
- case 32:
- toc4x (yy, y, HFmode);
- break;
-#endif
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = exp - 16383 + 1;
- 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;
+ if (HOST_BITS_PER_LONG == 32)
+ {
+ r->sig[0] = image0;
+ r->sig[1] = image1;
+ r->sig[2] = image2;
+ r->sig[3] = image3;
+ }
+ else
+ {
+ r->sig[0] = (image1 << 31 << 1) | image0;
+ r->sig[1] = (image3 << 31 << 1) | image2;
+ }
+ lshift_significand (r, r, SIGNIFICAND_BITS - 113);
+ r->sig[SIGSZ-1] |= SIG_MSB;
}
}
+const struct real_format ieee_quad =
+ {
+ encode_ieee_quad,
+ decode_ieee_quad,
+ 2,
+ 1,
+ 113,
+ -16382,
+ 16384,
+ true,
+ true,
+ true,
+ true,
+ true
+ };
+
+/* The VAX floating point formats. */
-/* Return Y = largest integer not greater than X (truncated toward minus
- infinity). */
-
-static const UEMUSHORT bmask[] =
-{
- 0xffff,
- 0xfffe,
- 0xfffc,
- 0xfff8,
- 0xfff0,
- 0xffe0,
- 0xffc0,
- 0xff80,
- 0xff00,
- 0xfe00,
- 0xfc00,
- 0xf800,
- 0xf000,
- 0xe000,
- 0xc000,
- 0x8000,
- 0x0000,
-};
+static void encode_vax_f PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_vax_f PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
+static void encode_vax_d PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_vax_d PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
+static void encode_vax_g PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_vax_g PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
static void
-efloor (x, y)
- const UEMUSHORT x[];
- UEMUSHORT y[];
+encode_vax_f (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const struct real_value *r;
{
- UEMUSHORT *p;
- int e, expon, i;
- UEMUSHORT f[NE];
-
- emov (x, f); /* leave in external format */
- expon = (int) f[NE - 1];
- e = (expon & 0x7fff) - (EXONE - 1);
- if (e <= 0)
- {
- eclear (y);
- goto isitneg;
- }
- /* number of bits to clear out */
- e = NBITS - e;
- emov (f, y);
- if (e <= 0)
- return;
-
- p = &y[0];
- while (e >= 16)
- {
- *p++ = 0;
- e -= 16;
- }
- /* clear the remaining bits */
- *p &= bmask[e];
- /* truncate negatives toward minus infinity */
- isitneg:
-
- if ((UEMUSHORT) expon & (UEMUSHORT) 0x8000)
- {
- for (i = 0; i < NE - 1; i++)
- {
- if (f[i] != y[i])
- {
- esub (eone, y, y);
- break;
- }
- }
- }
-}
+ unsigned long sign, exp, sig, image;
+ sign = r->sign << 15;
-#if 0
-/* Return S and EXP such that S * 2^EXP = X and .5 <= S < 1.
- For example, 1.1 = 0.55 * 2^1. */
+ switch (r->class)
+ {
+ case rvc_zero:
+ image = 0;
+ break;
-static void
-efrexp (x, exp, s)
- const UEMUSHORT x[];
- int *exp;
- UEMUSHORT s[];
-{
- UEMUSHORT xi[NI];
- EMULONG li;
+ case rvc_inf:
+ case rvc_nan:
+ image = 0xffff7fff | sign;
+ break;
- emovi (x, xi);
- /* Handle denormalized numbers properly using long integer exponent. */
- li = (EMULONG) ((EMUSHORT) xi[1]);
+ case rvc_normal:
+ sig = (r->sig[SIGSZ-1] >> (HOST_BITS_PER_LONG - 24)) & 0x7fffff;
+ exp = r->exp + 128;
- if (li == 0)
- {
- li -= enormlz (xi);
+ image = (sig << 16) & 0xffff0000;
+ image |= sign;
+ image |= exp << 7;
+ image |= sig >> 16;
+ break;
}
- xi[1] = 0x3ffe;
- emovo (xi, s);
- *exp = (int) (li - 0x3ffe);
-}
-#endif
-/* Return e type Y = X * 2^PWR2. */
+ buf[0] = image;
+}
static void
-eldexp (x, pwr2, y)
- const UEMUSHORT x[];
- int pwr2;
- UEMUSHORT y[];
+decode_vax_f (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ struct real_value *r;
+ const long *buf;
{
- UEMUSHORT xi[NI];
- EMULONG li;
- int i;
+ unsigned long image = buf[0] & 0xffffffff;
+ int exp = (image >> 7) & 0xff;
- emovi (x, xi);
- li = xi[1];
- li += pwr2;
- i = 0;
- emdnorm (xi, i, i, li, !ROUND_TOWARDS_ZERO);
- emovo (xi, y);
-}
+ memset (r, 0, sizeof (*r));
+ if (exp != 0)
+ {
+ r->class = rvc_normal;
+ r->sign = (image >> 15) & 1;
+ r->exp = exp - 128;
-#if 0
-/* C = remainder after dividing B by A, all e type values.
- Least significant integer quotient bits left in EQUOT. */
+ image = ((image & 0x7f) << 16) | ((image >> 16) & 0xffff);
+ r->sig[SIGSZ-1] = (image << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
+ }
+}
static void
-eremain (a, b, c)
- const UEMUSHORT a[], b[];
- UEMUSHORT c[];
+encode_vax_d (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const struct real_value *r;
{
- UEMUSHORT den[NI], num[NI];
+ unsigned long image0, image1, sign = r->sign << 15;
-#ifdef NANS
- if (eisinf (b)
- || (ecmp (a, ezero) == 0)
- || eisnan (a)
- || eisnan (b))
+ switch (r->class)
{
- enan (c, 0);
- return;
- }
-#endif
- if (ecmp (a, ezero) == 0)
- {
- mtherr ("eremain", SING);
- eclear (c);
- return;
- }
- emovi (a, den);
- emovi (b, num);
- eiremain (den, num);
- /* Sign of remainder = sign of quotient */
- if (a[0] == b[0])
- num[0] = 0;
- else
- num[0] = 0xffff;
- emovo (num, c);
-}
-#endif
+ case rvc_zero:
+ image0 = image1 = 0;
+ break;
-/* Return quotient of exploded e-types NUM / DEN in EQUOT,
- remainder in NUM. */
+ case rvc_inf:
+ case rvc_nan:
+ image0 = 0xffff7fff | sign;
+ image1 = 0xffffffff;
+ break;
-static void
-eiremain (den, num)
- UEMUSHORT den[], num[];
-{
- EMULONG ld, ln;
- UEMUSHORT j;
-
- ld = den[E];
- ld -= enormlz (den);
- ln = num[E];
- ln -= enormlz (num);
- ecleaz (equot);
- while (ln >= ld)
- {
- if (ecmpm (den, num) <= 0)
+ 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;
-}
+ /* Rearrange the half-words of the significand to match the
+ external format. */
+ image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff007f;
+ image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
-#ifdef DEC
-/* Convert DEC double precision D to e type E. */
+ /* Add the sign and exponent. */
+ image0 |= sign;
+ image0 |= (r->exp + 128) << 7;
+ break;
+ }
-static void
-dectoe (d, e)
- const UEMUSHORT *d;
- UEMUSHORT *e;
-{
- if (TARGET_G_FLOAT)
- ieeetoe (d, e, &dec_g);
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = image1, buf[1] = image0;
else
- ieeetoe (d, e, &dec_d);
+ buf[0] = image0, buf[1] = image1;
}
-/* Convert e type X to DEC double precision D. */
-
static void
-etodec (x, d)
- const UEMUSHORT *x;
- UEMUSHORT *d;
+decode_vax_d (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ struct real_value *r;
+ const long *buf;
{
- UEMUSHORT xi[NI];
- EMULONG exp;
- int rndsav;
- const struct ieee_format *fmt;
+ unsigned long image0, image1;
+ int exp;
- if (TARGET_G_FLOAT)
- fmt = &dec_g;
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image1 = buf[0], image0 = buf[1];
else
- fmt = &dec_d;
-
- emovi (x, xi);
- /* Adjust exponent for offsets. */
- exp = (EMULONG) xi[E] - fmt->adjustment;
- /* Round off to nearest or even. */
- rndsav = rndprc;
- rndprc = fmt->precision;
- emdnorm (xi, 0, 0, exp, !ROUND_TOWARDS_ZERO);
- rndprc = rndsav;
- todec (xi, d);
-}
+ image0 = buf[0], image1 = buf[1];
+ image0 &= 0xffffffff;
+ image1 &= 0xffffffff;
-/* Convert exploded e-type X, that has already been rounded to
- 56-bit precision, to DEC format double Y. */
+ exp = (image0 >> 7) & 0x7f;
-static void
-todec (x, y)
- UEMUSHORT *x, *y;
-{
- if (TARGET_G_FLOAT)
- toieee (x, y, &dec_g);
- else
- toieee (x, y, &dec_d);
-}
-#endif /* DEC */
+ memset (r, 0, sizeof (*r));
-#ifdef IBM
-/* Convert IBM single/double precision to e type. */
-
-static void
-ibmtoe (d, e, mode)
- const UEMUSHORT *d;
- UEMUSHORT *e;
- enum machine_mode mode;
-{
- 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 */
+ if (exp != 0)
{
- *p++ = *d++; /* fill in the rest of our mantissa */
- *p++ = *d++;
- }
- *p = *d;
-
- if (y[M] == 0 && y[M+1] == 0 && y[M+2] == 0 && y[M+3] == 0)
- y[0] = y[E] = 0;
- else
- y[E] -= 5 + enormlz (y); /* now normalize the mantissa */
- /* handle change in RADIX */
- emovo (y, e);
-}
+ r->class = rvc_normal;
+ r->sign = (image0 >> 15) & 1;
+ r->exp = exp - 128;
+ /* 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);
-
-/* Convert e type to IBM single/double precision. */
-
-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, !ROUND_TOWARDS_ZERO);
- rndprc = rndsav;
- toibm (xi, d, mode);
-}
-
-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 struct real_value *r;
{
- UEMUSHORT y[NI];
- UEMUSHORT dn[4];
- int r;
- int isnegative;
- int size;
- int i;
- int carry;
-
- dn[0] = d[0];
- dn[1] = d[1];
- if (mode != QFmode)
- {
- 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;
- }
+ unsigned long image0, image1, sign = r->sign << 15;
- ecleaz (y); /* start with a zero */
- r = dn[0]; /* get sign/exponent part */
- if (r & (unsigned int) 0x0080)
+ switch (r->class)
{
- y[0] = 0xffff; /* fill in our sign */
- isnegative = TRUE;
- }
- else
- isnegative = FALSE;
-
- r >>= 8; /* Shift exponent word down 8 bits. */
- if (r & 0x80) /* Make the exponent negative if it is. */
- r = r | (~0 & ~0xff);
+ case rvc_zero:
+ image0 = image1 = 0;
+ 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;
+ case rvc_inf:
+ case rvc_nan:
+ image0 = 0xffff7fff | sign;
+ image1 = 0xffffffff;
+ break;
- y[M+1] = dn[1];
- if (mode != QFmode) /* There are only 2 words in QFmode. */
+ case rvc_normal:
+ /* Extract the significand into straight hi:lo. */
+ if (HOST_BITS_PER_LONG == 64)
{
- y[M+2] = dn[2]; /* Fill in the rest of our mantissa. */
- y[M+3] = dn[3];
- size = 4;
+ image0 = r->sig[SIGSZ-1];
+ image1 = (image0 >> (64 - 53)) & 0xffffffff;
+ image0 = (image0 >> (64 - 53 + 1) >> 31) & 0xfffff;
}
else
- size = 2;
- eshift (y, -8);
-
- /* Now do the two's complement on the data. */
-
- 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;
- }
+ image0 = r->sig[SIGSZ-1];
+ image1 = r->sig[SIGSZ-2];
+ image1 = (image0 << 21) | (image1 >> 11);
+ image0 = (image0 >> 11) & 0xfffff;
}
- 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);
+ /* Rearrange the half-words of the significand to match the
+ external format. */
+ image0 = ((image0 << 16) | (image0 >> 16)) & 0xffff000f;
+ image1 = ((image1 << 16) | (image1 >> 16)) & 0xffffffff;
+
+ /* Add the sign and exponent. */
+ image0 |= sign;
+ image0 |= (r->exp + 1024) << 4;
+ break;
}
- 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;
+ struct real_value *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, !ROUND_TOWARDS_ZERO);
- 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;
-
- i = ((int) x[1]) - 0x7f;
+ r->class = rvc_normal;
+ r->sign = (image0 >> 15) & 1;
+ r->exp = exp - 1024;
- /* Now add 1 to the inverted data to do the two's complement. */
- if (mode != QFmode)
- v = 4 + M;
- else
- v = 2 + M;
- carry = 1;
- while (v > M)
- {
- if (x[v] == 0x0000)
- x[v] = carry ? 0x0000 : 0xffff;
- else
- {
- x[v] = ((~x[v]) + carry) & 0xffff;
- carry = 0;
- }
- v--;
- }
+ /* 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);
- /* 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)
+ if (HOST_BITS_PER_LONG == 64)
{
- /* This is the case of -1 x 2^m, we have to rid ourselves of the
- high sign bit and shift the exponent. */
- eshift (x, 1);
- i--;
+ image0 = (image0 << 31 << 1) | image1;
+ image0 <<= 64 - 53;
+ image0 |= SIG_MSB;
+ r->sig[SIGSZ-1] = image0;
}
- }
- else
- i = ((int) x[1]) - 0x7f;
-
- if ((i < -128) || (i > 127))
- {
- y[0] |= 0xff7f;
- y[1] = 0xffff;
- if (mode != QFmode)
+ else
{
- y[2] = 0xffff;
- y[3] = 0xffff;
- y[3] = (y[1] << 8) | ((y[2] >> 8) & 0xff);
- y[2] = (y[0] << 8) | ((y[1] >> 8) & 0xff);
- }
-#ifdef ERANGE
- errno = ERANGE;
-#endif
- return;
- }
-
- y[0] |= ((i & 0xff) << 8);
-
- eshift (x, 8);
+ r->sig[SIGSZ-1] = image0;
+ r->sig[SIGSZ-2] = image1;
+ lshift_significand (r, r, 64 - 53);
+ r->sig[SIGSZ-1] |= SIG_MSB;
+ }
+ }
+}
+
+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
+ };
- y[0] |= x[M] & 0x7f;
- y[1] = x[M + 1];
- if (mode != QFmode)
- {
- y[2] = x[M + 2];
- y[3] = x[M + 3];
- y[3] = (y[1] << 8) | ((y[2] >> 8) & 0xff);
- y[2] = (y[0] << 8) | ((y[1] >> 8) & 0xff);
- }
-}
-#endif /* C4X */
-
-/* Output a binary NaN bit pattern in the target machine's format. */
-
-/* If special NaN bit patterns are required, define them in tm.h
- as arrays of unsigned 16-bit shorts. Otherwise, use the default
- patterns here. */
-#ifdef TFMODE_NAN
-TFMODE_NAN;
-#else
-#if defined (IEEE) && (INTEL_EXTENDED_IEEE_FORMAT == 0)
-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
+
+/* The IBM S/390 floating point formats. 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:
-#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
+ http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/DZ9AR001/9.1?DT=19930923083613
+*/
-#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
+static void encode_i370_single PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_i370_single PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
+static void encode_i370_double PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_i370_double PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
-#ifdef SFMODE_NAN
-SFMODE_NAN;
-#else
-#ifdef IEEE
-static const UEMUSHORT SFbignan[2] = {0x7fff, 0xffff};
-static const UEMUSHORT SFlittlenan[2] = {0, 0xffc0};
-#endif
-#endif
-
-
-#ifdef NANS
static void
-make_nan (nan, sign, mode)
- UEMUSHORT *nan;
- int sign;
- enum machine_mode mode;
+encode_i370_single (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const struct real_value *r;
{
- int n;
- const UEMUSHORT *p;
- int size;
+ unsigned long sign, exp, sig, image;
- size = GET_MODE_BITSIZE (mode);
- if (LARGEST_EXPONENT_IS_NORMAL (size))
- {
- warning ("%d-bit floats cannot hold NaNs", size);
- saturate (nan, sign, size, 0);
- return;
- }
- switch (mode)
- {
-/* 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;
- break;
-#endif
- /* FALLTHRU */
+ sign = r->sign << 31;
- case XFmode:
- n = 6;
- if (REAL_WORDS_BIG_ENDIAN)
- p = XFbignan;
- else
- p = XFlittlenan;
+ switch (r->class)
+ {
+ case rvc_zero:
+ image = 0;
break;
- case DFmode:
- n = 4;
- if (REAL_WORDS_BIG_ENDIAN)
- p = DFbignan;
- else
- p = DFlittlenan;
+ case rvc_inf:
+ case rvc_nan:
+ image = 0x7fffffff | sign;
break;
- case SFmode:
- case HFmode:
- n = 2;
- if (REAL_WORDS_BIG_ENDIAN)
- p = SFbignan;
- else
- p = SFlittlenan;
+ 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;
-#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 */
-
-
-/* Create a saturation value for a SIZE-bit float, assuming that
- LARGEST_EXPONENT_IS_NORMAL (SIZE).
- If SIGN is true, fill X with the most negative value, otherwise fill
- it with the most positive value. WARN is true if the function should
- warn about overflow. */
+ buf[0] = image;
+}
static void
-saturate (x, sign, size, warn)
- UEMUSHORT *x;
- int sign, size, warn;
+decode_i370_single (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ struct real_value *r;
+ const long *buf;
{
- int i;
-
- if (warn && extra_warnings)
- warning ("value exceeds the range of a %d-bit float", size);
-
- /* Create the most negative value. */
- for (i = 0; i < size / EMUSHORT_SIZE; i++)
- x[i] = 0xffff;
-
- /* Make it positive, if necessary. */
- if (!sign)
- x[REAL_WORDS_BIG_ENDIAN? 0 : i - 1] = 0x7fff;
-}
+ unsigned long sign, sig, image = buf[0];
+ int exp;
+ sign = (image >> 31) & 1;
+ exp = (image >> 24) & 0x7f;
+ sig = image & 0xffffff;
-/* This is the inverse of the function `etarsingle' invoked by
- REAL_VALUE_TO_TARGET_SINGLE. */
+ memset (r, 0, sizeof (*r));
-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;
- }
- else
+ if (exp || sig)
{
- s[0] = (UEMUSHORT) f;
- s[1] = (UEMUSHORT) (f >> 16);
+ r->class = rvc_normal;
+ r->sign = sign;
+ r->exp = (exp - 64) * 4;
+ r->sig[SIGSZ-1] = sig << (HOST_BITS_PER_LONG - 24);
+ normalize (r);
}
- /* 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;
}
-
-/* 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
+encode_i370_double (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const struct real_value *r;
{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[4];
- UEMUSHORT e[NE];
+ unsigned long sign, exp, image_hi, image_lo;
- /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces. */
- if (REAL_WORDS_BIG_ENDIAN)
- {
- s[0] = (UEMUSHORT) (d[0] >> 16);
- s[1] = (UEMUSHORT) d[0];
- s[2] = (UEMUSHORT) (d[1] >> 16);
- s[3] = (UEMUSHORT) d[1];
- }
- else
- {
- /* 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;
-}
+ sign = r->sign << 31;
+ switch (r->class)
+ {
+ case rvc_zero:
+ image_hi = image_lo = 0;
+ break;
-/* 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. */
+ case rvc_inf:
+ case rvc_nan:
+ image_hi = 0x7fffffff | sign;
+ image_lo = 0xffffffff;
+ break;
-REAL_VALUE_TYPE
-ereal_from_float (f)
- HOST_WIDE_INT f;
-{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[2];
- UEMUSHORT e[NE];
+ 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
+ {
+ image_hi = r->sig[SIGSZ-1];
+ image_lo = r->sig[SIGSZ-2];
+ image_lo = (image_lo >> 8) | (image_hi << 24);
+ image_hi >>= 8;
+ }
- /* 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;
+ exp = ((r->exp / 4) + 64) << 24;
+ image_hi |= sign | exp;
+ break;
}
+
+ 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;
}
+static void
+decode_i370_double (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ struct real_value *r;
+ const long *buf;
+{
+ unsigned long sign, image_hi, image_lo;
+ int exp;
-/* 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.
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ image_hi = buf[0], image_lo = buf[1];
+ else
+ image_lo = buf[0], image_hi = buf[1];
- 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. */
+ sign = (image_hi >> 31) & 1;
+ exp = (image_hi >> 24) & 0x7f;
+ image_hi &= 0xffffff;
+ image_lo &= 0xffffffff;
-REAL_VALUE_TYPE
-ereal_from_double (d)
- HOST_WIDE_INT d[];
-{
- REAL_VALUE_TYPE r;
- UEMUSHORT s[4];
- UEMUSHORT e[NE];
+ memset (r, 0, sizeof (*r));
- /* Convert array of HOST_WIDE_INT to equivalent array of 16-bit pieces. */
- if (REAL_WORDS_BIG_ENDIAN)
+ if (exp || image_hi || image_lo)
{
-#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;
-}
+ 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);
+
+ normalize (r);
+ }
+}
+
+const struct real_format i370_single =
+ {
+ 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 =
+ {
+ 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
+ };
+
+/* TMS320C[34]x twos complement floating point format. */
-#if 0
-/* Convert target computer unsigned 64-bit integer to e-type.
- The endian-ness of DImode follows the convention for integers,
- so we use WORDS_BIG_ENDIAN here, not REAL_WORDS_BIG_ENDIAN. */
+static void encode_c4x_single PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_c4x_single PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
+static void encode_c4x_extended PARAMS ((const struct real_format *fmt,
+ long *, const struct real_value *));
+static void decode_c4x_extended PARAMS ((const struct real_format *,
+ struct real_value *, const long *));
static void
-uditoe (di, e)
- const UEMUSHORT *di; /* Address of the 64-bit int. */
- UEMUSHORT *e;
+encode_c4x_single (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const struct real_value *r;
{
- UEMUSHORT yi[NI];
- int k;
-
- ecleaz (yi);
- if (WORDS_BIG_ENDIAN)
- {
- for (k = M; k < M + 4; k++)
- yi[k] = *di++;
- }
- else
+ unsigned long image, exp, sig;
+
+ switch (r->class)
{
- 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);
-}
-
-/* Convert target computer signed 64-bit integer to e-type. */
+ case rvc_zero:
+ exp = -128;
+ sig = 0;
+ break;
-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;
+ case rvc_inf:
+ case rvc_nan:
+ exp = 127;
+ sig = 0x800000 - r->sign;
+ 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_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;
}
+ break;
}
- 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);
-}
-
-/* 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;
+ struct real_value *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);
+ sig = (sig << (HOST_BITS_PER_LONG - 24)) | SIG_MSB;
+
+ r->exp = exp + 1;
+ r->sig[SIGSZ-1] = sig;
}
- else
+}
+
+static void
+encode_c4x_extended (fmt, buf, r)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ long *buf;
+ const struct real_value *r;
+{
+ unsigned long exp, sig;
+
+ switch (r->class)
{
- /* shift not more than 16 bits */
- eshift (xi, k);
+ case rvc_zero:
+ exp = -128;
+ sig = 0;
+ break;
-noshift:
+ case rvc_inf:
+ case rvc_nan:
+ exp = 127;
+ sig = 0x80000000 - r->sign;
+ break;
- if (WORDS_BIG_ENDIAN)
- {
- i += 3;
- *i-- = xi[M];
- *i-- = 0;
- *i-- = 0;
- *i = 0;
- }
- else
+ case rvc_normal:
+ exp = r->exp - 1;
+
+ sig = r->sig[SIGSZ-1];
+ if (HOST_BITS_PER_LONG == 64)
+ sig = sig >> 1 >> 31;
+ sig &= 0x7fffffff;
+
+ if (r->sign)
{
- *i++ = xi[M];
- *i++ = 0;
- *i++ = 0;
- *i = 0;
+ if (sig)
+ sig = -sig;
+ else
+ exp--;
+ sig |= 0x80000000;
}
+ break;
}
-}
+ exp = (exp & 0xff) << 24;
+ sig &= 0xffffffff;
-/* Convert e-type to signed 64-bit int. */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf[0] = exp, buf[1] = sig;
+ else
+ buf[0] = sig, buf[0] = exp;
+}
static void
-etodi (x, i)
- const UEMUSHORT *x;
- UEMUSHORT *i;
+decode_c4x_extended (fmt, r, buf)
+ const struct real_format *fmt ATTRIBUTE_UNUSED;
+ struct real_value *r;
+ const long *buf;
{
- 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);
- }
+ unsigned long sig;
+ int exp, sf;
+
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ exp = buf[0], sf = buf[1];
else
- {
- /* shift not more than 16 bits */
- eshift (xi, k);
+ sf = buf[0], exp = buf[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])
+ exp = (((exp >> 24) & 0xff) & 0x80) - 0x80;
+ sf = ((sf & 0xffffffff) ^ 0x80000000) - 0x80000000;
+
+ memset (r, 0, sizeof (*r));
+
+ if (exp != -128)
{
- carry = 0;
- if (WORDS_BIG_ENDIAN)
- isave += 3;
- for (k = 0; k < 4; k++)
+ r->class = rvc_normal;
+
+ sig = sf & 0x7fffffff;
+ if (sf < 0)
{
- acc = (unsigned EMULONG) (~(*isave) & 0xffff) + carry;
- if (WORDS_BIG_ENDIAN)
- *isave-- = acc;
+ r->sign = 1;
+ if (sig)
+ sig = -sig;
else
- *isave++ = acc;
- carry = 0;
- if (acc & 0x10000)
- carry = 1;
- }
- }
-}
-
-
-/* Longhand square root routine. */
+ exp++;
+ }
+ if (HOST_BITS_PER_LONG == 64)
+ sig = sig << 1 << 31;
+ sig |= SIG_MSB;
+
+ r->exp = exp + 1;
+ r->sig[SIGSZ-1] = sig;
+ }
+}
+
+const struct real_format c4x_single =
+ {
+ encode_c4x_single,
+ decode_c4x_single,
+ 2,
+ 1,
+ 24,
+ -126,
+ 128,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+const struct real_format c4x_extended =
+ {
+ encode_c4x_extended,
+ decode_c4x_extended,
+ 2,
+ 1,
+ 32,
+ -126,
+ 128,
+ false,
+ false,
+ false,
+ false,
+ false
+ };
+
+/* Initialize things at start of compilation. */
-static int esqinited = 0;
-static unsigned short sqrndbit[NI];
+static const struct real_format * format_for_size PARAMS ((int));
-static void
-esqrt (x, y)
- const UEMUSHORT *x;
- UEMUSHORT *y;
+static const struct real_format *
+format_for_size (size)
+ int size;
{
- UEMUSHORT temp[NI], num[NI], sq[NI], xx[NI];
- EMULONG m, exp;
- int i, j, k, n, nlups;
+#ifndef TARGET_G_FORMAT
+#define TARGET_G_FORMAT 0
+#endif
- if (esqinited == 0)
- {
- ecleaz (sqrndbit);
- sqrndbit[NI - 2] = 1;
- esqinited = 1;
- }
- /* Check for arg <= 0 */
- i = ecmp (x, ezero);
- if (i <= 0)
+ switch (TARGET_FLOAT_FORMAT)
{
- if (i == -1)
+ case IEEE_FLOAT_FORMAT:
+ switch (size)
{
- mtherr ("esqrt", DOMAIN);
- eclear (y);
- }
- else
- emov (x, y);
- return;
- }
+ case 32:
+ return &ieee_single;
-#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);
- }
+ case 64:
+ return &ieee_double;
- ecleaz (sq);
- ecleaz (num);
- n = 8; /* get 8 bits of result per inner loop */
- nlups = rndprc;
- j = 0;
+ case 96:
+ if (!INTEL_EXTENDED_IEEE_FORMAT)
+ return &ieee_extended_motorola;
+ else
+ return &ieee_extended_intel_96;
- while (nlups > 0)
- {
- /* 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++)
+ case 128:
+ if (!INTEL_EXTENDED_IEEE_FORMAT)
+ return &ieee_quad;
+ else
+ return &ieee_extended_intel_128;
+ }
+ break;
+
+ case VAX_FLOAT_FORMAT:
+ switch (size)
{
- /* 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;
- }
+ case 32:
+ return &vax_f_format;
+
+ case 64:
+ if (TARGET_G_FORMAT)
+ return &vax_g_format;
+ else
+ return &vax_d_format;
}
- nlups -= n;
- j += 1;
- }
+ break;
- /* Adjust for extra, roundoff loop done. */
- exp += (NBITS - 1) - rndprc;
+ case IBM_FLOAT_FORMAT:
+ switch (size)
+ {
+ case 32:
+ return &i370_single;
+ case 64:
+ return &i370_double;
+ }
+ break;
- /* Sticky bit = 1 if the remainder is nonzero. */
- k = 0;
- for (i = 3; i < NI; i++)
- k |= (int) num[i];
+ case C4X_FLOAT_FORMAT:
+ switch (size)
+ {
+ case 32:
+ return &c4x_single;
+ case 64:
+ return &c4x_extended;
+ }
+ break;
+ }
- /* Renormalize and round off. */
- emdnorm (sq, k, 0, exp, !ROUND_TOWARDS_ZERO);
- emovo (sq, y);
+ abort ();
}
-#endif
-
-/* 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. */
-unsigned int
-significand_size (mode)
- enum machine_mode mode;
+void
+init_real_once ()
{
+ int i;
- /* Don't test the modes, but their sizes, lest this
- code won't work for BITS_PER_UNIT != 8 . */
-
- switch (GET_MODE_BITSIZE (mode))
+ /* Set up the mode->format table. */
+ for (i = 0; i < 3; ++i)
{
- case 32:
+ enum machine_mode mode;
+ int size;
-#ifdef C4X
- return 56;
-#else
- return 24;
-#endif
-
- case 64:
-#ifdef IEEE
- return 53;
-#else
- return 56;
-#endif
-
- case 96:
- return 64;
+ if (i == 0)
+ size = FLOAT_TYPE_SIZE;
+ else if (i == 1)
+ size = DOUBLE_TYPE_SIZE;
+ else
+ size = LONG_DOUBLE_TYPE_SIZE;
- case 128:
-#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
- return 113;
-#else
- return 64;
-#endif
+ mode = mode_for_size (size, MODE_FLOAT, 0);
+ if (mode == BLKmode)
+ abort ();
- default:
- abort ();
+ fmt_for_mode[mode - QFmode] = format_for_size (size);
}
}
diff --git a/gcc/real.h b/gcc/real.h
index f4265826ce9..31fa56140a9 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -2,96 +2,44 @@
Copyright (C) 1989, 1991, 1994, 1996, 1997, 1998,
1999, 2000, 2002 Free Software Foundation, Inc.
-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. */
#ifndef GCC_REAL_H
#define GCC_REAL_H
#include "machmode.h"
-/* Define codes for all the float formats that we know of. */
-#define UNKNOWN_FLOAT_FORMAT 0
-#define IEEE_FLOAT_FORMAT 1
-#define VAX_FLOAT_FORMAT 2
-#define IBM_FLOAT_FORMAT 3
-#define C4X_FLOAT_FORMAT 4
-
-/* Default to IEEE float if not specified. Nearly all machines use it. */
-
-#ifndef TARGET_FLOAT_FORMAT
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-#endif
-
-#ifndef HOST_FLOAT_FORMAT
-#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-#endif
-
-#ifndef INTEL_EXTENDED_IEEE_FORMAT
-#define INTEL_EXTENDED_IEEE_FORMAT 0
-#endif
-
-/* If FLOAT_WORDS_BIG_ENDIAN and HOST_FLOAT_WORDS_BIG_ENDIAN are not defined
- in the header files, then this implies the word-endianness is the same as
- for integers. */
-
-/* This is defined 0 or 1, like WORDS_BIG_ENDIAN. */
-#ifndef FLOAT_WORDS_BIG_ENDIAN
-#define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
-
-/* This is defined 0 or 1, unlike HOST_WORDS_BIG_ENDIAN. */
-#ifndef HOST_FLOAT_WORDS_BIG_ENDIAN
-#ifdef HOST_WORDS_BIG_ENDIAN
-#define HOST_FLOAT_WORDS_BIG_ENDIAN 1
-#else
-#define HOST_FLOAT_WORDS_BIG_ENDIAN 0
-#endif
-#endif
-
-#ifndef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE 64
-#endif
-/* MAX_LONG_DOUBLE_TYPE_SIZE is a constant tested by #if.
- LONG_DOUBLE_TYPE_SIZE can vary at compiler run time.
- So long as macros like REAL_VALUE_TO_TARGET_LONG_DOUBLE cannot
- vary too, however, then XFmode and TFmode long double
- cannot both be supported at the same time. */
-#ifndef MAX_LONG_DOUBLE_TYPE_SIZE
-#define MAX_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
-#endif
+/* REAL_VALUE_TYPE is an array of the minimum number of HOST_WIDE_INTs
+ required to hold a 128-bit floating point type. This is true even
+ if the maximum precision floating point type on the target is smaller.
-/* **** Start of software floating point emulator interface macros **** */
+ The extra 32 bits are for storing the mode of the float. Ideally
+ we'd keep this elsewhere, but that's too drastic a change all at once. */
-/* REAL_VALUE_TYPE is an array of the minimum number of HOST_WIDE_INTs
- required to hold either a 96- or 160-bit extended precision floating
- point type. This is true even if the maximum precision floating
- point type on the target is smaller. */
-#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !INTEL_EXTENDED_IEEE_FORMAT
-#define REAL_VALUE_TYPE_SIZE 160
-#else
-#define REAL_VALUE_TYPE_SIZE 96
-#endif
+#define REAL_VALUE_TYPE_SIZE (128 + 32)
#define REAL_WIDTH \
(REAL_VALUE_TYPE_SIZE/HOST_BITS_PER_WIDE_INT \
+ (REAL_VALUE_TYPE_SIZE%HOST_BITS_PER_WIDE_INT ? 1 : 0)) /* round up */
+
struct realvaluetype GTY(()) {
HOST_WIDE_INT r[REAL_WIDTH];
};
+
/* Various headers condition prototypes on #ifdef REAL_VALUE_TYPE, so it needs
to be a macro. realvaluetype cannot be a typedef as this interferes with
other headers declaring opaque pointers to it. */
@@ -99,7 +47,7 @@ struct realvaluetype GTY(()) {
/* Calculate the format for CONST_DOUBLE. We need as many slots as
are necessary to overlay a REAL_VALUE_TYPE on them. This could be
- as many as five (32-bit HOST_WIDE_INT, 160-bit REAL_VALUE_TYPE).
+ as many as four (32-bit HOST_WIDE_INT, 128-bit REAL_VALUE_TYPE).
A number of places assume that there are always at least two 'w'
slots in a CONST_DOUBLE, so we provide them even if one would suffice. */
@@ -126,134 +74,177 @@ struct realvaluetype GTY(()) {
# endif
#endif
-extern unsigned int significand_size PARAMS ((enum machine_mode));
+/* Declare functions in real.c. */
-#define REAL_ARITHMETIC(value, code, d1, d2) \
- earith (&(value), (code), &(d1), &(d2))
+/* Initialize the emulator. */
+extern void init_real_once PARAMS ((void));
-/* Declare functions in real.c. */
-extern void earith PARAMS ((REAL_VALUE_TYPE *, int,
- REAL_VALUE_TYPE *, REAL_VALUE_TYPE *));
-extern REAL_VALUE_TYPE etrunci PARAMS ((REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE etruncui PARAMS ((REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE ereal_negate PARAMS ((REAL_VALUE_TYPE));
-extern HOST_WIDE_INT efixi PARAMS ((REAL_VALUE_TYPE));
-extern unsigned HOST_WIDE_INT efixui PARAMS ((REAL_VALUE_TYPE));
-extern void ereal_from_int PARAMS ((REAL_VALUE_TYPE *,
- HOST_WIDE_INT, HOST_WIDE_INT,
- enum machine_mode));
-extern void ereal_from_uint PARAMS ((REAL_VALUE_TYPE *,
- unsigned HOST_WIDE_INT,
- unsigned HOST_WIDE_INT,
- enum machine_mode));
-extern void ereal_to_int PARAMS ((HOST_WIDE_INT *, HOST_WIDE_INT *,
- REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE ereal_ldexp PARAMS ((REAL_VALUE_TYPE, int));
-
-extern void etartdouble PARAMS ((REAL_VALUE_TYPE, long *));
-extern void etarldouble PARAMS ((REAL_VALUE_TYPE, long *));
-extern void etardouble PARAMS ((REAL_VALUE_TYPE, long *));
-extern long etarsingle PARAMS ((REAL_VALUE_TYPE));
-extern void ereal_to_decimal PARAMS ((REAL_VALUE_TYPE, char *, int));
-extern int ereal_cmp PARAMS ((REAL_VALUE_TYPE, REAL_VALUE_TYPE));
-extern int ereal_isneg PARAMS ((REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE ereal_unto_float PARAMS ((long));
-extern REAL_VALUE_TYPE ereal_unto_double PARAMS ((long *));
-extern REAL_VALUE_TYPE ereal_from_float PARAMS ((HOST_WIDE_INT));
-extern REAL_VALUE_TYPE ereal_from_double PARAMS ((HOST_WIDE_INT *));
-
-#define REAL_VALUES_EQUAL(x, y) (ereal_cmp ((x), (y)) == 0)
-/* true if x < y : */
-#define REAL_VALUES_LESS(x, y) (ereal_cmp ((x), (y)) == -1)
-#define REAL_VALUE_LDEXP(x, n) ereal_ldexp (x, n)
-
-/* Compare two floating-point objects for bitwise identity.
- This is not the same as comparing for equality on IEEE hosts:
- -0.0 equals 0.0 but they are not identical, and conversely
- two NaNs might be identical but they cannot be equal. */
-#define REAL_VALUES_IDENTICAL(x, y) \
- (!memcmp ((char *) &(x), (char *) &(y), sizeof (REAL_VALUE_TYPE)))
-
-/* These return REAL_VALUE_TYPE: */
-#define REAL_VALUE_RNDZINT(x) (etrunci (x))
-#define REAL_VALUE_UNSIGNED_RNDZINT(x) (etruncui (x))
-
-/* Truncate the floating-point value X to mode MODE. */
-#define REAL_VALUE_TRUNCATE(mode, x) real_value_truncate (mode, x)
-extern REAL_VALUE_TYPE real_value_truncate PARAMS ((enum machine_mode,
- REAL_VALUE_TYPE));
+/* Binary or unary arithmetic on tree_code. */
+extern void real_arithmetic PARAMS ((REAL_VALUE_TYPE *, int,
+ const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+
+/* Compare reals by tree_code. */
+extern bool real_compare PARAMS ((int, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+
+/* Determine whether a floating-point value X is infinite. */
+extern bool real_isinf PARAMS ((const REAL_VALUE_TYPE *));
+
+/* Determine whether a floating-point value X is a NaN. */
+extern bool real_isnan PARAMS ((const REAL_VALUE_TYPE *));
+
+/* Determine whether a floating-point value X is negative. */
+extern bool real_isneg PARAMS ((const REAL_VALUE_TYPE *));
+
+/* Determine whether a floating-point value X is minus zero. */
+extern bool real_isnegzero PARAMS ((const REAL_VALUE_TYPE *));
+
+/* Compare two floating-point objects for bitwise identity. */
+extern bool real_identical PARAMS ((const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
-/* Expansion of REAL_VALUE_TRUNCATE.
- The result is in floating point, rounded to nearest or even. */
+/* Extend or truncate to a new mode. */
+extern void real_convert PARAMS ((REAL_VALUE_TYPE *,
+ enum machine_mode,
+ const REAL_VALUE_TYPE *));
+
+/* Return true if truncating to NEW is exact. */
extern bool exact_real_truncate PARAMS ((enum machine_mode,
- REAL_VALUE_TYPE *));
+ const REAL_VALUE_TYPE *));
+
+/* Render R as a decimal floating point constant. */
+extern void real_to_decimal PARAMS ((char *, const REAL_VALUE_TYPE *,
+ int));
+
+/* Render R as a hexadecimal floating point constant. */
+extern void real_to_hexadecimal PARAMS ((char *, const REAL_VALUE_TYPE *,
+ int));
+
+/* Render R as an integer. */
+extern HOST_WIDE_INT real_to_integer PARAMS ((const REAL_VALUE_TYPE *));
+extern void real_to_integer2 PARAMS ((HOST_WIDE_INT *, HOST_WIDE_INT *,
+ const REAL_VALUE_TYPE *));
+
+/* Initialize R from a decimal or hexadecimal string. */
+extern void real_from_string PARAMS ((REAL_VALUE_TYPE *, const char *));
+
+/* Initialize R from an integer pair HIGH/LOW. */
+extern void real_from_integer PARAMS ((REAL_VALUE_TYPE *,
+ enum machine_mode,
+ unsigned HOST_WIDE_INT,
+ HOST_WIDE_INT, int));
-/* These return HOST_WIDE_INT: */
-/* Convert a floating-point value to integer, rounding toward zero. */
-#define REAL_VALUE_FIX(x) (efixi (x))
-/* Convert a floating-point value to unsigned integer, rounding
- toward zero. */
-#define REAL_VALUE_UNSIGNED_FIX(x) (efixui (x))
+extern long real_to_target PARAMS ((long *, const REAL_VALUE_TYPE *,
+ enum machine_mode));
-/* Convert ASCII string S to floating point in mode M.
- Decimal input uses ATOF. Hexadecimal uses HTOF. */
-#define REAL_VALUE_ATOF(s,m) ereal_atof(s,m)
-#define REAL_VALUE_HTOF(s,m) ereal_atof(s,m)
+extern void real_from_target PARAMS ((REAL_VALUE_TYPE *, const long *,
+ enum machine_mode));
-#define REAL_VALUE_NEGATE ereal_negate
+extern void real_inf PARAMS ((REAL_VALUE_TYPE *));
-/* Compute the absolute value of a floating-point value X. */
-#define REAL_VALUE_ABS(x) \
- (REAL_VALUE_NEGATIVE (x) ? REAL_VALUE_NEGATE (x) : (x))
+extern void real_nan PARAMS ((REAL_VALUE_TYPE *, const char *,
+ int, enum machine_mode));
+
+extern void real_2expN PARAMS ((REAL_VALUE_TYPE *, int));
+
+/* ====================================================================== */
+/* Crap. */
+
+/* Define codes for all the float formats that we know of. */
+#define UNKNOWN_FLOAT_FORMAT 0
+#define IEEE_FLOAT_FORMAT 1
+#define VAX_FLOAT_FORMAT 2
+#define IBM_FLOAT_FORMAT 3
+#define C4X_FLOAT_FORMAT 4
+
+/* Default to IEEE float if not specified. Nearly all machines use it. */
+
+#ifndef TARGET_FLOAT_FORMAT
+#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
+#endif
+
+#define REAL_ARITHMETIC(value, code, d1, d2) \
+ real_arithmetic (&(value), code, &(d1), &(d2))
+
+#define REAL_VALUES_IDENTICAL(x, y) real_identical (&(x), &(y))
+#define REAL_VALUES_EQUAL(x, y) real_compare (EQ_EXPR, &(x), &(y))
+#define REAL_VALUES_LESS(x, y) real_compare (LT_EXPR, &(x), &(y))
/* Determine whether a floating-point value X is infinite. */
-#define REAL_VALUE_ISINF(x) (target_isinf (x))
+#define REAL_VALUE_ISINF(x) real_isinf (&(x))
/* Determine whether a floating-point value X is a NaN. */
-#define REAL_VALUE_ISNAN(x) (target_isnan (x))
+#define REAL_VALUE_ISNAN(x) real_isnan (&(x))
/* Determine whether a floating-point value X is negative. */
-#define REAL_VALUE_NEGATIVE(x) (target_negative (x))
+#define REAL_VALUE_NEGATIVE(x) real_isneg (&(x))
/* Determine whether a floating-point value X is minus zero. */
-#define REAL_VALUE_MINUS_ZERO(x) \
- ((ereal_cmp (x, dconst0) == 0) && (ereal_isneg (x) != 0 ))
+#define REAL_VALUE_MINUS_ZERO(x) real_isnegzero (&(x))
+
+/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
+#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
+ real_to_target (OUT, &(IN), \
+ mode_for_size (LONG_DOUBLE_TYPE_SIZE, MODE_FLOAT, 0))
-#define REAL_VALUE_TO_INT ereal_to_int
+#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
+ real_to_target (OUT, &(IN), mode_for_size (64, MODE_FLOAT, 0))
-/* Here the cast to HOST_WIDE_INT sign-extends arguments such as ~0. */
-#define REAL_VALUE_FROM_INT(d, lo, hi, mode) \
- ereal_from_int (&d, (HOST_WIDE_INT) (lo), (HOST_WIDE_INT) (hi), mode)
+/* IN is a REAL_VALUE_TYPE. OUT is a long. */
+#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) \
+ ((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_FLOAT, 0)))
-#define REAL_VALUE_FROM_UNSIGNED_INT(d, lo, hi, mode) \
- ereal_from_uint (&d, lo, hi, mode)
+#define REAL_VALUE_TO_DECIMAL(r, s, dig) \
+ real_to_decimal (s, &(r), dig)
-/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
-#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
- (LONG_DOUBLE_TYPE_SIZE == 64 ? etardouble ((IN), (OUT)) \
- : LONG_DOUBLE_TYPE_SIZE == 96 ? etarldouble ((IN), (OUT)) \
- : LONG_DOUBLE_TYPE_SIZE == 128 ? etartdouble ((IN), (OUT)) \
- : abort ())
-#define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) (etardouble ((IN), (OUT)))
+#define REAL_VALUE_FROM_INT(r, lo, hi, mode) \
+ real_from_integer (&(r), mode, lo, hi, 0)
-/* IN is a REAL_VALUE_TYPE. OUT is a long. */
-#define REAL_VALUE_TO_TARGET_SINGLE(IN, OUT) ((OUT) = etarsingle ((IN)))
+#define REAL_VALUE_FROM_UNSIGNED_INT(r, lo, hi, mode) \
+ real_from_integer (&(r), mode, lo, hi, 1)
+
+extern REAL_VALUE_TYPE real_value_truncate PARAMS ((enum machine_mode,
+ REAL_VALUE_TYPE));
+
+#define REAL_VALUE_TO_INT(plow, phigh, r) \
+ real_to_integer2 (plow, phigh, &(r))
+
+extern REAL_VALUE_TYPE real_arithmetic2 PARAMS ((int, const REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *));
+
+#define REAL_VALUE_NEGATE(X) \
+ real_arithmetic2 (NEGATE_EXPR, &(X), NULL)
-/* Inverse of REAL_VALUE_TO_TARGET_DOUBLE. */
-#define REAL_VALUE_UNTO_TARGET_DOUBLE(d) (ereal_unto_double (d))
+#define REAL_VALUE_ABS(X) \
+ real_arithmetic2 (ABS_EXPR, &(X), NULL)
-/* Inverse of REAL_VALUE_TO_TARGET_SINGLE. */
-#define REAL_VALUE_UNTO_TARGET_SINGLE(f) (ereal_unto_float (f))
+extern int significand_size PARAMS ((enum machine_mode));
-/* d is an array of HOST_WIDE_INT that holds a double precision
- value in the target computer's floating point format. */
-#define REAL_VALUE_FROM_TARGET_DOUBLE(d) (ereal_from_double (d))
+extern REAL_VALUE_TYPE real_from_string2 PARAMS ((const char *,
+ enum machine_mode));
-/* f is a HOST_WIDE_INT containing a single precision target float value. */
-#define REAL_VALUE_FROM_TARGET_SINGLE(f) (ereal_from_float (f))
+#define REAL_VALUE_ATOF(s, m) \
+ real_from_string2 (s, m)
-/* Conversions to decimal ASCII string. */
-#define REAL_VALUE_TO_DECIMAL(r, s, dig) (ereal_to_decimal (r, s, dig))
+#define CONST_DOUBLE_ATOF(s, m) \
+ CONST_DOUBLE_FROM_REAL_VALUE (real_from_string2 (s, m), m)
+
+#define REAL_VALUE_FIX(r) \
+ real_to_integer (&(r))
+
+/* ??? Not quite right. */
+#define REAL_VALUE_UNSIGNED_FIX(r) \
+ real_to_integer (&(r))
+
+/* ??? These were added for Paranoia support. */
+
+/* Return floor log2(R). */
+extern int real_exponent PARAMS ((const REAL_VALUE_TYPE *));
+
+/* R = A * 2**EXP. */
+extern void real_ldexp PARAMS ((REAL_VALUE_TYPE *,
+ const REAL_VALUE_TYPE *, int));
/* **** End of software floating point emulator interface macros **** */
@@ -264,35 +255,23 @@ extern REAL_VALUE_TYPE dconst1;
extern REAL_VALUE_TYPE dconst2;
extern REAL_VALUE_TYPE dconstm1;
-/* Given a CONST_DOUBLE in FROM, store into TO the value it represents. */
/* Function to return a real value (not a tree node)
from a given integer constant. */
-union tree_node;
REAL_VALUE_TYPE real_value_from_int_cst PARAMS ((union tree_node *,
- union tree_node *));
+ union tree_node *));
-#define REAL_VALUE_FROM_CONST_DOUBLE(to, from) \
+/* Given a CONST_DOUBLE in FROM, store into TO the value it represents. */
+#define REAL_VALUE_FROM_CONST_DOUBLE(to, from) \
memcpy (&(to), &CONST_DOUBLE_LOW ((from)), sizeof (REAL_VALUE_TYPE))
/* Return a CONST_DOUBLE with value R and mode M. */
-
#define CONST_DOUBLE_FROM_REAL_VALUE(r, m) \
const_double_from_real_value (r, m)
extern rtx const_double_from_real_value PARAMS ((REAL_VALUE_TYPE,
enum machine_mode));
-/* Shorthand; can be handy in machine descriptions. */
-#define CONST_DOUBLE_ATOF(s, m) \
- CONST_DOUBLE_FROM_REAL_VALUE (REAL_VALUE_ATOF (s, m), m)
-
/* Replace R by 1/R in the given machine mode, if the result is exact. */
-extern int exact_real_inverse PARAMS ((enum machine_mode, REAL_VALUE_TYPE *));
-extern int target_isnan PARAMS ((REAL_VALUE_TYPE));
-extern int target_isinf PARAMS ((REAL_VALUE_TYPE));
-extern int target_negative PARAMS ((REAL_VALUE_TYPE));
-extern void debug_real PARAMS ((REAL_VALUE_TYPE));
-extern REAL_VALUE_TYPE ereal_atof PARAMS ((const char *, enum machine_mode));
-extern REAL_VALUE_TYPE ereal_inf PARAMS ((enum machine_mode));
+extern bool exact_real_inverse PARAMS ((enum machine_mode, REAL_VALUE_TYPE *));
/* In tree.c: wrap up a REAL_VALUE_TYPE in a tree node. */
extern tree build_real PARAMS ((tree, REAL_VALUE_TYPE));
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 5d58bdae5d5..555646cccd5 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -22,8 +22,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
-
#include "rtl.h"
+#include "tree.h"
#include "tm_p.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -603,8 +603,6 @@ simplify_unary_operation (code, mode, op, op_mode)
case NEG: d = REAL_VALUE_NEGATE (d); break;
case FLOAT_TRUNCATE: d = real_value_truncate (mode, d); break;
case FLOAT_EXTEND: /* All this does is change the mode. */ break;
- case FIX: d = REAL_VALUE_RNDZINT (d); break;
- case UNSIGNED_FIX: d = REAL_VALUE_UNSIGNED_RNDZINT (d); break;
default:
abort ();
}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 0f7e6a5644b..595eefc624a 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -66,6 +66,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "reload.h"
#include "dwarf2asm.h"
#include "integrate.h"
+#include "real.h"
#include "debug.h"
#include "target.h"
#include "langhooks.h"
@@ -5155,6 +5156,9 @@ backend_init ()
/* init_emit_once uses reg_raw_mode and therefore must be called
after init_regs which initialized reg_raw_mode. */
init_regs ();
+ /* Similarly, init_emit_once uses floating point numbers, and
+ thus must follow init_real_once. */
+ init_real_once ();
init_emit_once (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
#ifdef VMS_DEBUGGING_INFO
diff --git a/gcc/tree.c b/gcc/tree.c
index 1a5910e985d..1d0da06aa5a 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -474,11 +474,8 @@ build_real (type, d)
REAL_VALUE_TYPE *dp;
int overflow = 0;
- /* Check for valid float value for this type on this target machine;
- if not, can print error message and store a valid value in D. */
-#ifdef CHECK_FLOAT_VALUE
- CHECK_FLOAT_VALUE (TYPE_MODE (type), d, overflow);
-#endif
+ /* ??? Used to check for overflow here via CHECK_FLOAT_TYPE.
+ Consider doing it via real_convert now. */
v = make_node (REAL_CST);
dp = ggc_alloc (sizeof (REAL_VALUE_TYPE));