Patchwork [libiberty] IBM long double little-endian

login
register
mail settings
Submitter Alan Modra
Date Aug. 20, 2013, 2:35 a.m.
Message ID <20130820023555.GB3430@bubble.grove.modra.org>
Download mbox | patch
Permalink /patch/268349/
State New
Headers show

Comments

Alan Modra - Aug. 20, 2013, 2:35 a.m.
On Mon, Aug 19, 2013 at 09:53:14AM -0600, Tom Tromey wrote:
> >>>>> "Alan" == Alan Modra <amodra@gmail.com> writes:
> 
> Alan> This teaches gdb about little-endian IBM long double.  Like big-endian
> Alan> IBM long double, the little-endian version is an array of two doubles.
> 
> Alan> The patch also deletes some unused code I found in doublest.c.  OK to
> Alan> apply?
> 
> The gdb bits look fine to me, but the libiberty bits will have to be
> sent to the GCC patch list for approval.

Repost to gcc.  As far as I know, the libiberty files I'm touching
below are only used by gdb.  OK to apply?

include/
	* floatformat.h (floatformat_ibm_long_double): Delete.
	(floatformat_ibm_long_double_big): Declare.
	(floatformat_ibm_long_double_little): Declare.

libiberty/
	* floatformat.c (floatformat_ibm_long_double): Rename to..
	(floatformat_ibm_long_double_big): ..this.
	(floatformat_ibm_long_double_little): New.

gdb/
	* doublest.c (convert_floatformat_to_doublest): Use fmt->split_half
	for IBM long double nan and inf.
	(floatformat_is_negative, floatformat_classify,
	floatformat_mantissa): Similarly.
	(floatformat_ieee_single, floatformat_ieee_double,
	floatformat_ieee_quad, floatformat_arm_ext,
	floatformat_ia64_spill): Delete unused vars.
	(_initialize_doublest): Delete unused function.
	* gdbtypes.c (floatformats_ibm_long_double): Use new big- and
	little-endian variants of floatformat_ibm_long_double.
DJ Delorie - Aug. 20, 2013, 3:06 a.m.
The libiberty parts are OK.  The only drawback I can imagine is if
someone outside our source trees has used these, and installed a
shared library, and replaced it with this new one... but that's not
our problem, since we don't support that.

> include/
> 	* floatformat.h (floatformat_ibm_long_double): Delete.
> 	(floatformat_ibm_long_double_big): Declare.
> 	(floatformat_ibm_long_double_little): Declare.
> 
> libiberty/
> 	* floatformat.c (floatformat_ibm_long_double): Rename to..
> 	(floatformat_ibm_long_double_big): ..this.
> 	(floatformat_ibm_long_double_little): New.

Patch

Index: include/floatformat.h
===================================================================
RCS file: /cvs/src/src/include/floatformat.h,v
retrieving revision 1.16
diff -u -p -r1.16 floatformat.h
--- include/floatformat.h	3 Jan 2011 21:05:50 -0000	1.16
+++ include/floatformat.h	16 Aug 2013 06:46:24 -0000
@@ -128,7 +128,8 @@  extern const struct floatformat floatfor
 extern const struct floatformat floatformat_ia64_quad_big;
 extern const struct floatformat floatformat_ia64_quad_little;
 /* IBM long double (double+double).  */
-extern const struct floatformat floatformat_ibm_long_double;
+extern const struct floatformat floatformat_ibm_long_double_big;
+extern const struct floatformat floatformat_ibm_long_double_little;
 
 /* Convert from FMT to a double.
    FROM is the address of the extended float.
Index: libiberty/floatformat.c
===================================================================
RCS file: /cvs/src/src/libiberty/floatformat.c,v
retrieving revision 1.28
diff -u -p -r1.28 floatformat.c
--- libiberty/floatformat.c	17 Aug 2012 21:59:31 -0000	1.28
+++ libiberty/floatformat.c	16 Aug 2013 06:46:25 -0000
@@ -371,14 +371,23 @@  floatformat_ibm_long_double_is_valid (co
     }
 }
 
-const struct floatformat floatformat_ibm_long_double =
+const struct floatformat floatformat_ibm_long_double_big =
 {
   floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
   floatformat_intbit_no,
-  "floatformat_ibm_long_double",
+  "floatformat_ibm_long_double_big",
   floatformat_ibm_long_double_is_valid,
   &floatformat_ieee_double_big
 };
+
+const struct floatformat floatformat_ibm_long_double_little =
+{
+  floatformat_little, 128, 0, 1, 11, 1023, 2047, 12, 52,
+  floatformat_intbit_no,
+  "floatformat_ibm_long_double_little",
+  floatformat_ibm_long_double_is_valid,
+  &floatformat_ieee_double_little
+};
 
 
 #ifndef min
Index: gdb/doublest.c
===================================================================
RCS file: /cvs/src/src/gdb/doublest.c,v
retrieving revision 1.54
diff -u -p -r1.54 doublest.c
--- gdb/doublest.c	21 Jun 2013 16:24:14 -0000	1.54
+++ gdb/doublest.c	16 Aug 2013 06:46:22 -0000
@@ -190,7 +190,8 @@  convert_floatformat_to_doublest (const s
     {
       double dto;
 
-      floatformat_to_double (fmt, from, &dto);
+      floatformat_to_double (fmt->split_half ? fmt->split_half : fmt,
+			     from, &dto);
       *to = (DOUBLEST) dto;
       return;
     }
@@ -514,6 +515,11 @@  floatformat_is_negative (const struct fl
   gdb_assert (fmt->totalsize
 	      <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
 
+  /* An IBM long double (a two element array of double) always takes the
+     sign of the first double.  */
+  if (fmt->split_half)
+    fmt = fmt->split_half;
+
   order = floatformat_normalize_byteorder (fmt, uval, newfrom);
 
   if (order != fmt->byteorder)
@@ -540,6 +546,13 @@  floatformat_classify (const struct float
   gdb_assert (fmt->totalsize
 	      <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
 
+  /* An IBM long double (a two element array of double) can be classified
+     by looking at the first double.  inf and nan are specified as
+     ignoring the second double.  zero and subnormal will always have
+     the second double 0.0 if the long double is correctly rounded.  */
+  if (fmt->split_half)
+    fmt = fmt->split_half;
+
   order = floatformat_normalize_byteorder (fmt, uval, newfrom);
 
   if (order != fmt->byteorder)
@@ -622,6 +635,16 @@  floatformat_mantissa (const struct float
   gdb_assert (fmt->totalsize
 	      <= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
 
+  /* For IBM long double (a two element array of double), return the
+     mantissa of the first double.  The problem with returning the
+     actual mantissa from both doubles is that there can be an
+     arbitrary number of implied 0's or 1's between the mantissas
+     of the first and second double.  In any case, this function
+     is only used for dumping out nans, and a nan is specified to
+     ignore the value in the second double.  */
+  if (fmt->split_half)
+    fmt = fmt->split_half;
+
   order = floatformat_normalize_byteorder (fmt, uval, newfrom);
 
   if (order != fmt->byteorder)
@@ -879,27 +902,3 @@  convert_typed_floating (const void *from
       floatformat_from_doublest (to_fmt, &d, to);
     }
 }
-
-const struct floatformat *floatformat_ieee_single[BFD_ENDIAN_UNKNOWN];
-const struct floatformat *floatformat_ieee_double[BFD_ENDIAN_UNKNOWN];
-const struct floatformat *floatformat_ieee_quad[BFD_ENDIAN_UNKNOWN];
-const struct floatformat *floatformat_arm_ext[BFD_ENDIAN_UNKNOWN];
-const struct floatformat *floatformat_ia64_spill[BFD_ENDIAN_UNKNOWN];
-
-extern void _initialize_doublest (void);
-
-extern void
-_initialize_doublest (void)
-{
-  floatformat_ieee_single[BFD_ENDIAN_LITTLE] = &floatformat_ieee_single_little;
-  floatformat_ieee_single[BFD_ENDIAN_BIG] = &floatformat_ieee_single_big;
-  floatformat_ieee_double[BFD_ENDIAN_LITTLE] = &floatformat_ieee_double_little;
-  floatformat_ieee_double[BFD_ENDIAN_BIG] = &floatformat_ieee_double_big;
-  floatformat_arm_ext[BFD_ENDIAN_LITTLE]
-    = &floatformat_arm_ext_littlebyte_bigword;
-  floatformat_arm_ext[BFD_ENDIAN_BIG] = &floatformat_arm_ext_big;
-  floatformat_ia64_spill[BFD_ENDIAN_LITTLE] = &floatformat_ia64_spill_little;
-  floatformat_ia64_spill[BFD_ENDIAN_BIG] = &floatformat_ia64_spill_big;
-  floatformat_ieee_quad[BFD_ENDIAN_LITTLE] = &floatformat_ia64_quad_little;
-  floatformat_ieee_quad[BFD_ENDIAN_BIG] = &floatformat_ia64_quad_big;
-}
Index: gdb/gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.251
diff -u -p -r1.251 gdbtypes.c
--- gdb/gdbtypes.c	15 Apr 2013 17:30:36 -0000	1.251
+++ gdb/gdbtypes.c	16 Aug 2013 06:46:22 -0000
@@ -108,8 +108,8 @@  const struct floatformat *floatformats_v
   &floatformat_vax_d
 };
 const struct floatformat *floatformats_ibm_long_double[BFD_ENDIAN_UNKNOWN] = {
-  &floatformat_ibm_long_double,
-  &floatformat_ibm_long_double
+  &floatformat_ibm_long_double_big,
+  &floatformat_ibm_long_double_little
 };
 
 /* Should opaque types be resolved?  */