Patchwork [libiberty,gdb] IEEE 754 half floating-point format

login
register
mail settings
Submitter Ken Werner
Date July 2, 2010, 5:11 p.m.
Message ID <201007021911.31134.ken@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/57696/
State New
Headers show

Comments

Ken Werner - July 2, 2010, 5:11 p.m.
On Friday, July 02, 2010 06:59:05 pm Ken Werner wrote:
> Hi,
> 
> The attached patch adds the half precision floating-point format as
> described in IEEE 754-2008 as binary16. Languages such as OpenCL and
> architectures like ARM support this representation.
> Any suggestions are welcome.
> 
> Regards
> -ken

Whoops, I intended to crosspost this patch on gcc-patches as well because it 
touches files within the libiberty and include directory.
Sorry.

Regards
-ken
DJ Delorie - July 2, 2010, 6:47 p.m.
The libiberty parts are OK.  At least, they shouldn't break anything,
I have no idea if the *values* are correct.

Patch

include/ChangeLog:

2010-07-02  Ken Werner  <ken.werner@de.ibm.com>

	* gfloatformat.h (floatformat_ieee_half_big): Add declaration.
	(floatformat_ieee_half_little): Likewise.

libiberty/ChangeLog:

2010-07-02  Ken Werner  <ken.werner@de.ibm.com>

	* floatformat.c (floatformat_ieee_half_big): New variable.
	(floatformat_ieee_half_little): Likewise.

ChangeLog:

2010-07-02  Ken Werner  <ken.werner@de.ibm.com>

	* gdbtypes.h (floatformats_ieee_half): Add declaration.
	* gdbtypes.c (floatformats_ieee_half): New variable.
	* doublest.c (floatformat_from_length): Set format to
	gdbarch_half_format if length matches.
	* gdbarch.sh (half_bit): New architecture method.
	(half_format): Likewise.
	* gdbarch.h: Regenerate.
	* gdbarch.c: Likewise.


Index: include/floatformat.h
===================================================================
RCS file: /cvs/src/src/include/floatformat.h,v
retrieving revision 1.14
diff -u -p -r1.14 floatformat.h
--- include/floatformat.h	8 Nov 2007 00:08:48 -0000	1.14
+++ include/floatformat.h	2 Jul 2010 15:35:08 -0000
@@ -96,6 +96,8 @@  struct floatformat
 
 /* floatformats for IEEE single and double, big and little endian.  */
 
+extern const struct floatformat floatformat_ieee_half_big;
+extern const struct floatformat floatformat_ieee_half_little;
 extern const struct floatformat floatformat_ieee_single_big;
 extern const struct floatformat floatformat_ieee_single_little;
 extern const struct floatformat floatformat_ieee_double_big;
Index: libiberty/floatformat.c
===================================================================
RCS file: /cvs/src/src/libiberty/floatformat.c,v
retrieving revision 1.25
diff -u -p -r1.25 floatformat.c
--- libiberty/floatformat.c	13 Nov 2007 15:12:42 -0000	1.25
+++ libiberty/floatformat.c	2 Jul 2010 15:35:08 -0000
@@ -77,7 +77,23 @@  floatformat_always_valid (const struct f
    a system header, what we do if not, etc.  */
 #define FLOATFORMAT_CHAR_BIT 8
 
-/* floatformats for IEEE single and double, big and little endian.  */
+/* floatformats for IEEE half, single and double, big and little endian.  */
+const struct floatformat floatformat_ieee_half_big =
+{
+  floatformat_big, 16, 0, 1, 5, 15, 31, 6, 10,
+  floatformat_intbit_no,
+  "floatformat_ieee_half_big",
+  floatformat_always_valid,
+  NULL
+};
+const struct floatformat floatformat_ieee_half_little =
+{
+  floatformat_little, 16, 0, 1, 5, 15, 31, 6, 10,
+  floatformat_intbit_no,
+  "floatformat_ieee_half_little",
+  floatformat_always_valid,
+  NULL
+};
 const struct floatformat floatformat_ieee_single_big =
 {
   floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
Index: gdb/gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.132
diff -u -p -r1.132 gdbtypes.h
--- gdb/gdbtypes.h	29 Jun 2010 16:17:58 -0000	1.132
+++ gdb/gdbtypes.h	2 Jul 2010 15:35:08 -0000
@@ -1191,6 +1191,7 @@  extern const struct objfile_type *objfil
 
  
 /* Explicit floating-point formats.  See "floatformat.h".  */
+extern const struct floatformat *floatformats_ieee_half[BFD_ENDIAN_UNKNOWN];
 extern const struct floatformat *floatformats_ieee_single[BFD_ENDIAN_UNKNOWN];
 extern const struct floatformat *floatformats_ieee_double[BFD_ENDIAN_UNKNOWN];
 extern const struct floatformat *floatformats_ieee_double_littlebyte_bigword[BFD_ENDIAN_UNKNOWN];
Index: gdb/gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.194
diff -u -p -r1.194 gdbtypes.c
--- gdb/gdbtypes.c	29 Jun 2010 16:53:09 -0000	1.194
+++ gdb/gdbtypes.c	2 Jul 2010 15:35:07 -0000
@@ -42,6 +42,10 @@ 
 
 
 /* Floatformat pairs.  */
+const struct floatformat *floatformats_ieee_half[BFD_ENDIAN_UNKNOWN] = {
+  &floatformat_ieee_half_big,
+  &floatformat_ieee_half_little
+};
 const struct floatformat *floatformats_ieee_single[BFD_ENDIAN_UNKNOWN] = {
   &floatformat_ieee_single_big,
   &floatformat_ieee_single_little
Index: gdb/doublest.c
===================================================================
RCS file: /cvs/src/src/gdb/doublest.c,v
retrieving revision 1.44
diff -u -p -r1.44 doublest.c
--- gdb/doublest.c	14 May 2010 17:53:16 -0000	1.44
+++ gdb/doublest.c	2 Jul 2010 15:35:05 -0000
@@ -777,7 +777,10 @@  floatformat_from_length (struct gdbarch 
 {
   const struct floatformat *format;
 
-  if (len * TARGET_CHAR_BIT == gdbarch_float_bit (gdbarch))
+  if (len * TARGET_CHAR_BIT == gdbarch_half_bit (gdbarch))
+    format = gdbarch_half_format (gdbarch)
+	       [gdbarch_byte_order (gdbarch)];
+  else if (len * TARGET_CHAR_BIT == gdbarch_float_bit (gdbarch))
     format = gdbarch_float_format (gdbarch)
 	       [gdbarch_byte_order (gdbarch)];
   else if (len * TARGET_CHAR_BIT == gdbarch_double_bit (gdbarch))
Index: gdb/gdbarch.sh
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.sh,v
retrieving revision 1.512
diff -u -p -r1.512 gdbarch.sh
--- gdb/gdbarch.sh	26 May 2010 18:19:27 -0000	1.512
+++ gdb/gdbarch.sh	2 Jul 2010 15:35:07 -0000
@@ -363,12 +363,14 @@  v:int:long_bit:::8 * sizeof (long):4*TAR
 # machine.
 v:int:long_long_bit:::8 * sizeof (LONGEST):2*gdbarch->long_bit::0
 
-# The ABI default bit-size and format for "float", "double", and "long
-# double".  These bit/format pairs should eventually be combined into
-# a single object.  For the moment, just initialize them as a pair.
+# The ABI default bit-size and format for "half", "float", "double", and
+# "long double".  These bit/format pairs should eventually be combined
+# into a single object.  For the moment, just initialize them as a pair.
 # Each format describes both the big and little endian layouts (if
 # useful).
 
+v:int:half_bit:::16:2*TARGET_CHAR_BIT::0
+v:const struct floatformat **:half_format:::::floatformats_ieee_half::pformat (gdbarch->half_format)
 v:int:float_bit:::8 * sizeof (float):4*TARGET_CHAR_BIT::0
 v:const struct floatformat **:float_format:::::floatformats_ieee_single::pformat (gdbarch->float_format)
 v:int:double_bit:::8 * sizeof (double):8*TARGET_CHAR_BIT::0
Index: gdb/gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.416
diff -u -p -r1.416 gdbarch.h
--- gdb/gdbarch.h	26 May 2010 18:19:26 -0000	1.416
+++ gdb/gdbarch.h	2 Jul 2010 15:35:06 -0000
@@ -118,12 +118,18 @@  extern void set_gdbarch_long_bit (struct
 extern int gdbarch_long_long_bit (struct gdbarch *gdbarch);
 extern void set_gdbarch_long_long_bit (struct gdbarch *gdbarch, int long_long_bit);
 
-/* The ABI default bit-size and format for "float", "double", and "long
-   double".  These bit/format pairs should eventually be combined into
-   a single object.  For the moment, just initialize them as a pair.
+/* The ABI default bit-size and format for "half", "float", "double", and
+   "long double".  These bit/format pairs should eventually be combined
+   into a single object.  For the moment, just initialize them as a pair.
    Each format describes both the big and little endian layouts (if
    useful). */
 
+extern int gdbarch_half_bit (struct gdbarch *gdbarch);
+extern void set_gdbarch_half_bit (struct gdbarch *gdbarch, int half_bit);
+
+extern const struct floatformat ** gdbarch_half_format (struct gdbarch *gdbarch);
+extern void set_gdbarch_half_format (struct gdbarch *gdbarch, const struct floatformat ** half_format);
+
 extern int gdbarch_float_bit (struct gdbarch *gdbarch);
 extern void set_gdbarch_float_bit (struct gdbarch *gdbarch, int float_bit);
 
Index: gdb/gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.468
diff -u -p -r1.468 gdbarch.c
--- gdb/gdbarch.c	26 May 2010 18:19:27 -0000	1.468
+++ gdb/gdbarch.c	2 Jul 2010 15:35:06 -0000
@@ -145,6 +145,8 @@  struct gdbarch
   int int_bit;
   int long_bit;
   int long_long_bit;
+  int half_bit;
+  const struct floatformat ** half_format;
   int float_bit;
   const struct floatformat ** float_format;
   int double_bit;
@@ -293,6 +295,8 @@  struct gdbarch startup_gdbarch =
   8 * sizeof (int),  /* int_bit */
   8 * sizeof (long),  /* long_bit */
   8 * sizeof (LONGEST),  /* long_long_bit */
+  16,  /* half_bit */
+  0,  /* half_format */
   8 * sizeof (float),  /* float_bit */
   0,  /* float_format */
   8 * sizeof (double),  /* double_bit */
@@ -451,6 +455,7 @@  gdbarch_alloc (const struct gdbarch_info
   gdbarch->int_bit = 4*TARGET_CHAR_BIT;
   gdbarch->long_bit = 4*TARGET_CHAR_BIT;
   gdbarch->long_long_bit = 2*gdbarch->long_bit;
+  gdbarch->half_bit = 2*TARGET_CHAR_BIT;
   gdbarch->float_bit = 4*TARGET_CHAR_BIT;
   gdbarch->double_bit = 8*TARGET_CHAR_BIT;
   gdbarch->long_double_bit = 8*TARGET_CHAR_BIT;
@@ -562,6 +567,9 @@  verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of int_bit, invalid_p == 0 */
   /* Skip verify of long_bit, invalid_p == 0 */
   /* Skip verify of long_long_bit, invalid_p == 0 */
+  /* Skip verify of half_bit, invalid_p == 0 */
+  if (gdbarch->half_format == 0)
+    gdbarch->half_format = floatformats_ieee_half;
   /* Skip verify of float_bit, invalid_p == 0 */
   if (gdbarch->float_format == 0)
     gdbarch->float_format = floatformats_ieee_single;
@@ -935,6 +943,12 @@  gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: get_syscall_number = <%s>\n",
                       host_address_to_string (gdbarch->get_syscall_number));
   fprintf_unfiltered (file,
+                      "gdbarch_dump: half_bit = %s\n",
+                      plongest (gdbarch->half_bit));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: half_format = %s\n",
+                      pformat (gdbarch->half_format));
+  fprintf_unfiltered (file,
                       "gdbarch_dump: has_dos_based_file_system = %s\n",
                       plongest (gdbarch->has_dos_based_file_system));
   fprintf_unfiltered (file,
@@ -1375,6 +1389,39 @@  set_gdbarch_long_long_bit (struct gdbarc
 }
 
 int
+gdbarch_half_bit (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  /* Skip verify of half_bit, invalid_p == 0 */
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_half_bit called\n");
+  return gdbarch->half_bit;
+}
+
+void
+set_gdbarch_half_bit (struct gdbarch *gdbarch,
+                      int half_bit)
+{
+  gdbarch->half_bit = half_bit;
+}
+
+const struct floatformat **
+gdbarch_half_format (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_half_format called\n");
+  return gdbarch->half_format;
+}
+
+void
+set_gdbarch_half_format (struct gdbarch *gdbarch,
+                         const struct floatformat ** half_format)
+{
+  gdbarch->half_format = half_format;
+}
+
+int
 gdbarch_float_bit (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);