summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnu/lib/libiberty/Makefile.bsd-wrapper4
-rw-r--r--gnu/lib/libiberty/include/floatformat.h34
-rw-r--r--gnu/lib/libiberty/shlib_version4
-rw-r--r--gnu/lib/libiberty/src/floatformat.c302
4 files changed, 267 insertions, 77 deletions
diff --git a/gnu/lib/libiberty/Makefile.bsd-wrapper b/gnu/lib/libiberty/Makefile.bsd-wrapper
index 7a60990f9c6..42626d86780 100644
--- a/gnu/lib/libiberty/Makefile.bsd-wrapper
+++ b/gnu/lib/libiberty/Makefile.bsd-wrapper
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.bsd-wrapper,v 1.6 2003/12/28 20:11:50 espie Exp $
+# $OpenBSD: Makefile.bsd-wrapper,v 1.7 2004/05/17 10:00:37 kettenis Exp $
LIB= iberty
CPPFLAGS+= -DHAVE_CONFIG_H -I$(.CURDIR) -I$(.CURDIR)/include -I$(.OBJDIR)
@@ -13,7 +13,7 @@ SRCS= argv.c choose-temp.c concat.c cplus-dem.c cp-demangle.c \
hashtab.c hex.c fibheap.c partition.c \
floatformat.c make-temp-file.c make-relative-prefix.c \
objalloc.c obstack.c oldhashtab.c \
- pexecute.c safe-ctype.c spaces.c splay-tree.c \
+ pexecute.c regex.c safe-ctype.c spaces.c splay-tree.c \
strerror.c strsignal.c \
xatexit.c xexit.c xmalloc.c xmemdup xstrerror.c xstrdup.c \
physmem.c lbasename.c lrealpath.c \
diff --git a/gnu/lib/libiberty/include/floatformat.h b/gnu/lib/libiberty/include/floatformat.h
index 90daca21bcb..a8244ada5c7 100644
--- a/gnu/lib/libiberty/include/floatformat.h
+++ b/gnu/lib/libiberty/include/floatformat.h
@@ -1,5 +1,5 @@
/* IEEE floating point support declarations, for GDB, the GNU Debugger.
- Copyright (C) 1991 Free Software Foundation, Inc.
+ Copyright 1991, 1994, 1995, 1997, 2000, 2003 Free Software Foundation, Inc.
This file is part of GDB.
@@ -61,8 +61,12 @@ struct floatformat
unsigned int exp_start;
unsigned int exp_len;
- /* Amount added to "true" exponent. 0x3fff for many IEEE extendeds. */
- unsigned int exp_bias;
+ /* Bias added to a "true" exponent to form the biased exponent. It
+ is intentionally signed as, otherwize, -exp_bias can turn into a
+ very large number (e.g., given the exp_bias of 0x3fff and a 64
+ bit long, the equation (long)(1 - exp_bias) evaluates to
+ 4294950914) instead of -16382). */
+ int exp_bias;
/* Exponent value which indicates NaN. This is the actual value stored in
the float, not adjusted by the exp_bias. This usually consists of all
one bits. */
@@ -73,6 +77,12 @@ struct floatformat
/* Is the integer bit explicit or implicit? */
enum floatformat_intbit intbit;
+
+ /* Internal name for debugging. */
+ const char *name;
+
+ /* Validator method. */
+ int (*is_valid) PARAMS ((const struct floatformat *fmt, const char *from));
};
/* floatformats for IEEE single and double, big and little endian. */
@@ -92,20 +102,32 @@ extern const struct floatformat floatformat_i387_ext;
extern const struct floatformat floatformat_m68881_ext;
extern const struct floatformat floatformat_i960_ext;
extern const struct floatformat floatformat_m88110_ext;
-extern const struct floatformat floatformat_arm_ext;
+extern const struct floatformat floatformat_m88110_harris_ext;
+extern const struct floatformat floatformat_arm_ext_big;
+extern const struct floatformat floatformat_arm_ext_littlebyte_bigword;
+/* IA-64 Floating Point register spilt into memory. */
+extern const struct floatformat floatformat_ia64_spill_big;
+extern const struct floatformat floatformat_ia64_spill_little;
+extern const struct floatformat floatformat_ia64_quad_big;
+extern const struct floatformat floatformat_ia64_quad_little;
/* Convert from FMT to a double.
FROM is the address of the extended float.
Store the double in *TO. */
extern void
-floatformat_to_double PARAMS ((const struct floatformat *, char *, double *));
+floatformat_to_double PARAMS ((const struct floatformat *, const char *, double *));
/* The converse: convert the double *FROM to FMT
and store where TO points. */
extern void
floatformat_from_double PARAMS ((const struct floatformat *,
- double *, char *));
+ const double *, char *));
+
+/* Return non-zero iff the data at FROM is a valid number in format FMT. */
+
+extern int
+floatformat_is_valid PARAMS ((const struct floatformat *fmt, const char *from));
#endif /* defined (FLOATFORMAT_H) */
diff --git a/gnu/lib/libiberty/shlib_version b/gnu/lib/libiberty/shlib_version
index 1394f4e4035..5b844bbf422 100644
--- a/gnu/lib/libiberty/shlib_version
+++ b/gnu/lib/libiberty/shlib_version
@@ -1,2 +1,2 @@
-major=6
-minor=1
+major=7
+minor=0
diff --git a/gnu/lib/libiberty/src/floatformat.c b/gnu/lib/libiberty/src/floatformat.c
index d69024f7390..a0f65354e48 100644
--- a/gnu/lib/libiberty/src/floatformat.c
+++ b/gnu/lib/libiberty/src/floatformat.c
@@ -1,5 +1,5 @@
/* IEEE floating point support routines, for GDB, the GNU Debugger.
- Copyright (C) 1991, 1994, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1994, 1999, 2000, 2003 Free Software Foundation, Inc.
This file is part of GDB.
@@ -17,18 +17,51 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* This is needed to pick up the NAN macro on some systems. */
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
#include "ansidecl.h"
+#include "libiberty.h"
#include "floatformat.h"
-#include <math.h> /* ldexp */
-#ifdef ANSI_PROTOTYPES
-#include <stddef.h>
-extern void *memcpy (void *s1, const void *s2, size_t n);
-extern void *memset (void *s, int c, size_t n);
+
+#ifndef INFINITY
+#ifdef HUGE_VAL
+#define INFINITY HUGE_VAL
#else
-extern char *memcpy ();
-extern char *memset ();
+#define INFINITY (1.0 / 0.0)
+#endif
#endif
+#ifndef NAN
+#define NAN (0.0 / 0.0)
+#endif
+
+static unsigned long get_field PARAMS ((const unsigned char *,
+ enum floatformat_byteorders,
+ unsigned int,
+ unsigned int,
+ unsigned int));
+static int floatformat_always_valid PARAMS ((const struct floatformat *fmt,
+ const char *from));
+
+static int
+floatformat_always_valid (fmt, from)
+ const struct floatformat *fmt ATTRIBUTE_UNUSED;
+ const char *from ATTRIBUTE_UNUSED;
+{
+ return 1;
+}
+
/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
going to bother with trying to muck around with whether it is defined in
a system header, what we do if not, etc. */
@@ -39,25 +72,29 @@ const struct floatformat floatformat_ieee_single_big =
{
floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
floatformat_intbit_no,
- "floatformat_ieee_single_big"
+ "floatformat_ieee_single_big",
+ floatformat_always_valid
};
const struct floatformat floatformat_ieee_single_little =
{
floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
floatformat_intbit_no,
- "floatformat_ieee_single_little"
+ "floatformat_ieee_single_little",
+ floatformat_always_valid
};
const struct floatformat floatformat_ieee_double_big =
{
floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
floatformat_intbit_no,
- "floatformat_ieee_double_big"
+ "floatformat_ieee_double_big",
+ floatformat_always_valid
};
const struct floatformat floatformat_ieee_double_little =
{
floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
floatformat_intbit_no,
- "floatformat_ieee_double_little"
+ "floatformat_ieee_double_little",
+ floatformat_always_valid
};
/* floatformat for IEEE double, little endian byte order, with big endian word
@@ -67,34 +104,64 @@ const struct floatformat floatformat_ieee_double_littlebyte_bigword =
{
floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
floatformat_intbit_no,
- "floatformat_ieee_double_littlebyte_bigword"
+ "floatformat_ieee_double_littlebyte_bigword",
+ floatformat_always_valid
};
+static int floatformat_i387_ext_is_valid PARAMS ((const struct floatformat *fmt, const char *from));
+
+static int
+floatformat_i387_ext_is_valid (fmt, from)
+ const struct floatformat *fmt;
+ const char *from;
+{
+ /* In the i387 double-extended format, if the exponent is all ones,
+ then the integer bit must be set. If the exponent is neither 0
+ nor ~0, the intbit must also be set. Only if the exponent is
+ zero can it be zero, and then it must be zero. */
+ unsigned long exponent, int_bit;
+ const unsigned char *ufrom = (const unsigned char *) from;
+
+ exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
+ fmt->exp_start, fmt->exp_len);
+ int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
+ fmt->man_start, 1);
+
+ if ((exponent == 0) != (int_bit == 0))
+ return 0;
+ else
+ return 1;
+}
+
const struct floatformat floatformat_i387_ext =
{
floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
floatformat_intbit_yes,
- "floatformat_i387_ext"
+ "floatformat_i387_ext",
+ floatformat_i387_ext_is_valid
};
const struct floatformat floatformat_m68881_ext =
{
/* Note that the bits from 16 to 31 are unused. */
floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
floatformat_intbit_yes,
- "floatformat_m68881_ext"
+ "floatformat_m68881_ext",
+ floatformat_always_valid
};
const struct floatformat floatformat_i960_ext =
{
/* Note that the bits from 0 to 15 are unused. */
floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
floatformat_intbit_yes,
- "floatformat_i960_ext"
+ "floatformat_i960_ext",
+ floatformat_always_valid
};
const struct floatformat floatformat_m88110_ext =
{
floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
floatformat_intbit_yes,
- "floatformat_m88110_ext"
+ "floatformat_m88110_ext",
+ floatformat_always_valid
};
const struct floatformat floatformat_m88110_harris_ext =
{
@@ -102,58 +169,59 @@ const struct floatformat floatformat_m88110_harris_ext =
double, and the last 64 bits are wasted. */
floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52,
floatformat_intbit_no,
- "floatformat_m88110_ext_harris"
+ "floatformat_m88110_ext_harris",
+ floatformat_always_valid
};
const struct floatformat floatformat_arm_ext_big =
{
/* Bits 1 to 16 are unused. */
floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
floatformat_intbit_yes,
- "floatformat_arm_ext_big"
+ "floatformat_arm_ext_big",
+ floatformat_always_valid
};
const struct floatformat floatformat_arm_ext_littlebyte_bigword =
{
/* Bits 1 to 16 are unused. */
floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
floatformat_intbit_yes,
- "floatformat_arm_ext_littlebyte_bigword"
+ "floatformat_arm_ext_littlebyte_bigword",
+ floatformat_always_valid
};
const struct floatformat floatformat_ia64_spill_big =
{
floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
floatformat_intbit_yes,
- "floatformat_ia64_spill_big"
+ "floatformat_ia64_spill_big",
+ floatformat_always_valid
};
const struct floatformat floatformat_ia64_spill_little =
{
floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
floatformat_intbit_yes,
- "floatformat_ia64_spill_little"
+ "floatformat_ia64_spill_little",
+ floatformat_always_valid
};
const struct floatformat floatformat_ia64_quad_big =
{
floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
floatformat_intbit_no,
- "floatformat_ia64_quad_big"
+ "floatformat_ia64_quad_big",
+ floatformat_always_valid
};
const struct floatformat floatformat_ia64_quad_little =
{
floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
floatformat_intbit_no,
- "floatformat_ia64_quad_little"
+ "floatformat_ia64_quad_little",
+ floatformat_always_valid
};
-static unsigned long get_field PARAMS ((unsigned char *,
- enum floatformat_byteorders,
- unsigned int,
- unsigned int,
- unsigned int));
-
-/* Extract a field which starts at START and is LEN bytes long. DATA and
+/* Extract a field which starts at START and is LEN bits long. DATA and
TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
static unsigned long
get_field (data, order, total_len, start, len)
- unsigned char *data;
+ const unsigned char *data;
enum floatformat_byteorders order;
unsigned int total_len;
unsigned int start;
@@ -207,10 +275,10 @@ get_field (data, order, total_len, start, len)
void
floatformat_to_double (fmt, from, to)
const struct floatformat *fmt;
- char *from;
+ const char *from;
double *to;
{
- unsigned char *ufrom = (unsigned char *)from;
+ const unsigned char *ufrom = (const unsigned char *)from;
double dto;
long exponent;
unsigned long mant;
@@ -220,9 +288,45 @@ floatformat_to_double (fmt, from, to)
exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
fmt->exp_start, fmt->exp_len);
- /* Note that if exponent indicates a NaN, we can't really do anything useful
- (not knowing if the host has NaN's, or how to build one). So it will
- end up as an infinity or something close; that is OK. */
+
+ /* If the exponent indicates a NaN, we don't have information to
+ decide what to do. So we handle it like IEEE, except that we
+ don't try to preserve the type of NaN. FIXME. */
+ if ((unsigned long) exponent == fmt->exp_nan)
+ {
+ int nan;
+
+ mant_off = fmt->man_start;
+ mant_bits_left = fmt->man_len;
+ nan = 0;
+ while (mant_bits_left > 0)
+ {
+ mant_bits = min (mant_bits_left, 32);
+
+ if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
+ mant_off, mant_bits) != 0)
+ {
+ /* This is a NaN. */
+ nan = 1;
+ break;
+ }
+
+ mant_off += mant_bits;
+ mant_bits_left -= mant_bits;
+ }
+
+ if (nan)
+ dto = NAN;
+ else
+ dto = INFINITY;
+
+ if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
+ dto = -dto;
+
+ *to = dto;
+
+ return;
+ }
mant_bits_left = fmt->man_len;
mant_off = fmt->man_start;
@@ -255,8 +359,18 @@ floatformat_to_double (fmt, from, to)
mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
mant_off, mant_bits);
- dto += ldexp ((double)mant, exponent - mant_bits);
- exponent -= mant_bits;
+ /* Handle denormalized numbers. FIXME: What should we do for
+ non-IEEE formats? */
+ if (exponent == 0 && mant != 0)
+ dto += ldexp ((double)mant,
+ (- fmt->exp_bias
+ - mant_bits
+ - (mant_off - fmt->man_start)
+ + 1));
+ else
+ dto += ldexp ((double)mant, exponent - mant_bits);
+ if (exponent != 0)
+ exponent -= mant_bits;
mant_off += mant_bits;
mant_bits_left -= mant_bits;
}
@@ -273,7 +387,7 @@ static void put_field PARAMS ((unsigned char *, enum floatformat_byteorders,
unsigned int,
unsigned long));
-/* Set a field which starts at START and is LEN bytes long. DATA and
+/* Set a field which starts at START and is LEN bits long. DATA and
TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
static void
put_field (data, order, total_len, start, len, stuff_to_put)
@@ -331,7 +445,7 @@ put_field (data, order, total_len, start, len, stuff_to_put)
void
floatformat_from_double (fmt, from, to)
const struct floatformat *fmt;
- double *from;
+ const double *from;
char *to;
{
double dfrom;
@@ -341,33 +455,54 @@ floatformat_from_double (fmt, from, to)
int mant_bits_left;
unsigned char *uto = (unsigned char *)to;
- memcpy (&dfrom, from, sizeof (dfrom));
+ dfrom = *from;
memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
+
+ /* If negative, set the sign bit. */
+ if (dfrom < 0)
+ {
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
+ dfrom = -dfrom;
+ }
+
if (dfrom == 0)
- return; /* Result is zero */
+ {
+ /* 0.0. */
+ return;
+ }
+
if (dfrom != dfrom)
{
- /* From is NaN */
+ /* NaN. */
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
fmt->exp_len, fmt->exp_nan);
- /* Be sure it's not infinity, but NaN value is irrel */
+ /* Be sure it's not infinity, but NaN value is irrelevant. */
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
32, 1);
return;
}
- /* If negative, set the sign bit. */
- if (dfrom < 0)
+ if (dfrom + dfrom == dfrom)
{
- put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
- dfrom = -dfrom;
+ /* This can only happen for an infinite value (or zero, which we
+ already handled above). */
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
+ fmt->exp_len, fmt->exp_nan);
+ return;
}
- /* How to tell an infinity from an ordinary number? FIXME-someday */
-
mant = frexp (dfrom, &exponent);
- put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len,
- exponent + fmt->exp_bias - 1);
+ if (exponent + fmt->exp_bias - 1 > 0)
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
+ fmt->exp_len, exponent + fmt->exp_bias - 1);
+ else
+ {
+ /* Handle a denormalized number. FIXME: What should we do for
+ non-IEEE formats? */
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
+ fmt->exp_len, 0);
+ mant = ldexp (mant, exponent + fmt->exp_bias - 1);
+ }
mant_bits_left = fmt->man_len;
mant_off = fmt->man_start;
@@ -380,12 +515,11 @@ floatformat_from_double (fmt, from, to)
mant_long = (unsigned long)mant;
mant -= mant_long;
- /* If the integer bit is implicit, then we need to discard it.
- If we are discarding a zero, we should be (but are not) creating
- a denormalized number which means adjusting the exponent
- (I think). */
+ /* If the integer bit is implicit, and we are not creating a
+ denormalized number, then we need to discard it. */
if ((unsigned int) mant_bits_left == fmt->man_len
- && fmt->intbit == floatformat_intbit_no)
+ && fmt->intbit == floatformat_intbit_no
+ && exponent + fmt->exp_bias - 1 > 0)
{
mant_long &= 0x7fffffff;
mant_bits -= 1;
@@ -404,9 +538,21 @@ floatformat_from_double (fmt, from, to)
}
}
+/* Return non-zero iff the data at FROM is a valid number in format FMT. */
+
+int
+floatformat_is_valid (fmt, from)
+ const struct floatformat *fmt;
+ const char *from;
+{
+ return fmt->is_valid (fmt, from);
+}
+
#ifdef IEEE_DEBUG
+#include <stdio.h>
+
/* This is to be run on a host which uses IEEE floating point. */
void
@@ -414,19 +560,31 @@ ieee_test (n)
double n;
{
double result;
- char exten[16];
- floatformat_to_double (&floatformat_ieee_double_big, &n, &result);
- if (n != result)
+ floatformat_to_double (&floatformat_ieee_double_little, (char *) &n,
+ &result);
+ if ((n != result && (! isnan (n) || ! isnan (result)))
+ || (n < 0 && result >= 0)
+ || (n >= 0 && result < 0))
printf ("Differ(to): %.20g -> %.20g\n", n, result);
- floatformat_from_double (&floatformat_ieee_double_big, &n, &result);
- if (n != result)
+
+ floatformat_from_double (&floatformat_ieee_double_little, &n,
+ (char *) &result);
+ if ((n != result && (! isnan (n) || ! isnan (result)))
+ || (n < 0 && result >= 0)
+ || (n >= 0 && result < 0))
printf ("Differ(from): %.20g -> %.20g\n", n, result);
- floatformat_from_double (&floatformat_m68881_ext, &n, exten);
- floatformat_to_double (&floatformat_m68881_ext, exten, &result);
- if (n != result)
- printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
+#if 0
+ {
+ char exten[16];
+
+ floatformat_from_double (&floatformat_m68881_ext, &n, exten);
+ floatformat_to_double (&floatformat_m68881_ext, exten, &result);
+ if (n != result)
+ printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
+ }
+#endif
#if IEEE_DEBUG > 1
/* This is to be run on a host which uses 68881 format. */
@@ -441,12 +599,22 @@ ieee_test (n)
int
main ()
{
+ ieee_test (0.0);
ieee_test (0.5);
ieee_test (256.0);
ieee_test (0.12345);
ieee_test (234235.78907234);
ieee_test (-512.0);
ieee_test (-0.004321);
+ ieee_test (1.2E-70);
+ ieee_test (1.2E-316);
+ ieee_test (4.9406564584124654E-324);
+ ieee_test (- 4.9406564584124654E-324);
+ ieee_test (- 0.0);
+ ieee_test (- INFINITY);
+ ieee_test (- NAN);
+ ieee_test (INFINITY);
+ ieee_test (NAN);
return 0;
}
#endif