OSDN Git Service

PR c/10175
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
index c88b24f..069aedb 100644 (file)
@@ -29,18 +29,30 @@ 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.  */
 
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
+   supposedly valid even though this is a "target" file.  */
+#include "auto-host.h"
+
 /* It is incorrect to include config.h here, because this file is being
    compiled for the target, and hence definitions concerning only the host
    do not apply.  */
-
 #include "tconfig.h"
 #include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
 
 /* Don't use `fancy_abort' here even if config.h says to use it.  */
 #ifdef abort
 #undef abort
 #endif
 
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
 #include "libgcc2.h"
 \f
 #ifdef DECLARE_LIBRARY_RENAMES
@@ -117,7 +129,7 @@ DWtype
 __subvdi3 (DWtype a, DWtype b)
 {
 #ifdef L_addvdi3
-  return (a, (-b));
+  return __addvdi3 (a, (-b));
 #else
   DWtype w;
 
@@ -232,7 +244,7 @@ __mulvdi3 (DWtype u, DWtype v)
 #endif
 \f
 
-/* Unless shift functions are defined whith full ANSI prototypes,
+/* Unless shift functions are defined with full ANSI prototypes,
    parameter b will be promoted to int if word_type is smaller than an int.  */
 #ifdef L_lshrdi3
 DWtype
@@ -328,9 +340,27 @@ __ashrdi3 (DWtype u, word_type b)
 }
 #endif
 \f
+#ifdef L_ffssi2
+#undef int
+extern int __ffsSI2 (UWtype u);
+int
+__ffsSI2 (UWtype u)
+{
+  UWtype count;
+
+  if (u == 0)
+    return 0;
+
+  count_trailing_zeros (count, u);
+  return count + 1;
+}
+#endif
+\f
 #ifdef L_ffsdi2
-DWtype
-__ffsdi2 (DWtype u)
+#undef int
+extern int __ffsDI2 (DWtype u);
+int
+__ffsDI2 (DWtype u)
 {
   DWunion uu;
   UWtype word, count, add;
@@ -366,8 +396,19 @@ __muldi3 (DWtype u, DWtype v)
 }
 #endif
 \f
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+     defined (L_umoddi3) || defined (L_moddi3))
+#if defined (sdiv_qrnnd)
+#define L_udiv_w_sdiv
+#endif
+#endif
+
 #ifdef L_udiv_w_sdiv
 #if defined (sdiv_qrnnd)
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+     defined (L_umoddi3) || defined (L_moddi3))
+static inline __attribute__ ((__always_inline__))
+#endif
 UWtype
 __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
 {
@@ -495,12 +536,181 @@ const UQItype __clz_tab[] =
   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
 };
 #endif
+\f
+#ifdef L_clzsi2
+#undef int
+extern int __clzSI2 (UWtype x);
+int
+__clzSI2 (UWtype x)
+{
+  Wtype ret;
+
+  count_leading_zeros (ret, x);
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_clzdi2
+#undef int
+extern int __clzDI2 (UDWtype x);
+int
+__clzDI2 (UDWtype x)
+{
+  DWunion uu;
+  UWtype word;
+  Wtype ret, add;
+
+  uu.ll = x;
+  if (uu.s.high)
+    word = uu.s.high, add = 0;
+  else
+    word = uu.s.low, add = W_TYPE_SIZE;
+
+  count_leading_zeros (ret, word);
+  return ret + add;
+}
+#endif
+\f
+#ifdef L_ctzsi2
+#undef int
+extern int __ctzSI2 (UWtype x);
+int
+__ctzSI2 (UWtype x)
+{
+  Wtype ret;
+
+  count_trailing_zeros (ret, x);
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_ctzdi2
+#undef int
+extern int __ctzDI2 (UDWtype x);
+int
+__ctzDI2 (UDWtype x)
+{
+  DWunion uu;
+  UWtype word;
+  Wtype ret, add;
+
+  uu.ll = x;
+  if (uu.s.low)
+    word = uu.s.low, add = 0;
+  else
+    word = uu.s.high, add = W_TYPE_SIZE;
+
+  count_trailing_zeros (ret, word);
+  return ret + add;
+}
+#endif
+
+#if (defined (L_popcountsi2) || defined (L_popcountdi2)        \
+     || defined (L_popcount_tab))
+extern const UQItype __popcount_tab[] ATTRIBUTE_HIDDEN;
+#endif
+
+#ifdef L_popcount_tab
+const UQItype __popcount_tab[] =
+{
+    0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
+};
+#endif
+\f
+#ifdef L_popcountsi2
+#undef int
+extern int __popcountSI2 (UWtype x);
+int
+__popcountSI2 (UWtype x)
+{
+  UWtype i, ret = 0;
+
+  for (i = 0; i < W_TYPE_SIZE; i += 8)
+    ret += __popcount_tab[(x >> i) & 0xff];
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_popcountdi2
+#undef int
+extern int __popcountDI2 (UDWtype x);
+int
+__popcountDI2 (UDWtype x)
+{
+  UWtype i, ret = 0;
+
+  for (i = 0; i < 2*W_TYPE_SIZE; i += 8)
+    ret += __popcount_tab[(x >> i) & 0xff];
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_paritysi2
+#undef int
+extern int __paritySI2 (UWtype x);
+int
+__paritySI2 (UWtype x)
+{
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+  x ^= x >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+  x ^= x >> 16;
+#endif
+  x ^= x >> 8;
+  x ^= x >> 4;
+  x &= 0xf;
+  return (0x6996 >> x) & 1;
+}
+#endif
+\f
+#ifdef L_paritydi2
+#undef int
+extern int __parityDI2 (UDWtype x);
+int
+__parityDI2 (UDWtype x)
+{
+  DWunion uu;
+  UWtype nx;
+
+  uu.ll = x;
+  nx = uu.s.low ^ uu.s.high;
+
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+  nx ^= nx >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+  nx ^= nx >> 16;
+#endif
+  nx ^= nx >> 8;
+  nx ^= nx >> 4;
+  nx &= 0xf;
+  return (0x6996 >> nx) & 1;
+}
+#endif
 
 #ifdef L_udivmoddi4
 
 #if (defined (L_udivdi3) || defined (L_divdi3) || \
      defined (L_umoddi3) || defined (L_moddi3))
-static inline
+static inline __attribute__ ((__always_inline__))
 #endif
 UDWtype
 __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
@@ -922,28 +1132,20 @@ __fixxfdi (XFtype a)
 DWtype
 __fixunsdfDI (DFtype a)
 {
-  DFtype b;
-  UDWtype v;
+  UWtype hi, lo;
 
-  if (a < 0)
-    return 0;
+  /* Get high part of result.  The division here will just moves the radix
+     point and will not cause any rounding.  Then the conversion to integral
+     type chops result as desired.  */
+  hi = a / HIGH_WORD_COEFF;
 
-  /* Compute high word of result, as a flonum.  */
-  b = (a / HIGH_WORD_COEFF);
-  /* Convert that to fixed (but not to DWtype!),
-     and shift it into the high word.  */
-  v = (UWtype) b;
-  v <<= WORD_SIZE;
-  /* Remove high part from the DFtype, leaving the low part as flonum.  */
-  a -= (DFtype)v;
-  /* Convert that to fixed (but not to DWtype!) and add it in.
-     Sometimes A comes out negative.  This is significant, since
-     A has more bits than a long int does.  */
-  if (a < 0)
-    v -= (UWtype) (- a);
-  else
-    v += (UWtype) a;
-  return v;
+  /* Get low part of result.  Convert `hi' to floating type and scale it back,
+     then subtract this from the number being converted.  This leaves the low
+     part.  Convert that to integral type.  */
+  lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
+
+  /* Assemble result from the two parts.  */
+  return ((UDWtype) hi << WORD_SIZE) | lo;
 }
 #endif
 
@@ -968,28 +1170,20 @@ __fixunssfDI (SFtype original_a)
      to lose any bits.  Some day someone else can write a faster version
      that avoids converting to DFtype, and verify it really works right.  */
   DFtype a = original_a;
-  DFtype b;
-  UDWtype v;
+  UWtype hi, lo;
 
-  if (a < 0)
-    return 0;
+  /* Get high part of result.  The division here will just moves the radix
+     point and will not cause any rounding.  Then the conversion to integral
+     type chops result as desired.  */
+  hi = a / HIGH_WORD_COEFF;
 
-  /* Compute high word of result, as a flonum.  */
-  b = (a / HIGH_WORD_COEFF);
-  /* Convert that to fixed (but not to DWtype!),
-     and shift it into the high word.  */
-  v = (UWtype) b;
-  v <<= WORD_SIZE;
-  /* Remove high part from the DFtype, leaving the low part as flonum.  */
-  a -= (DFtype) v;
-  /* Convert that to fixed (but not to DWtype!) and add it in.
-     Sometimes A comes out negative.  This is significant, since
-     A has more bits than a long int does.  */
-  if (a < 0)
-    v -= (UWtype) (- a);
-  else
-    v += (UWtype) a;
-  return v;
+  /* Get low part of result.  Convert `hi' to floating type and scale it back,
+     then subtract this from the number being converted.  This leaves the low
+     part.  Convert that to integral type.  */
+  lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
+
+  /* Assemble result from the two parts.  */
+  return ((UDWtype) hi << WORD_SIZE) | lo;
 }
 #endif
 
@@ -1091,7 +1285,10 @@ __floatdisf (DWtype u)
             && u < ((DWtype) 1 << DF_SIZE)))
        {
          if ((UDWtype) u & (REP_BIT - 1))
-           u |= REP_BIT;
+           {
+             u &= ~ (REP_BIT - 1);
+             u |= REP_BIT;
+           }
        }
     }
   f = (Wtype) (u >> WORD_SIZE);
@@ -1235,337 +1432,6 @@ __eprintf (const char *string, const char *expression,
 #endif
 #endif
 
-#ifdef L_bb
-
-struct bb_function_info {
-  long checksum;
-  int arc_count;
-  const char *name;
-};
-
-/* Structure emitted by --profile-arcs  */
-struct bb
-{
-  long zero_word;
-  const char *filename;
-  gcov_type *counts;
-  long ncounts;
-  struct bb *next;
-
-  /* Older GCC's did not emit these fields.  */
-  long sizeof_bb;
-  struct bb_function_info *function_infos;
-};
-
-#ifndef inhibit_libc
-
-/* Arc profile dumper. Requires atexit and stdio.  */
-
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
-#include <stdio.h>
-
-#include "gcov-io.h"
-#include <string.h>
-#ifdef TARGET_HAS_F_SETLKW
-#include <fcntl.h>
-#include <errno.h>
-#endif
-
-/* Chain of per-object file bb structures. */
-static struct bb *bb_head;
-
-/* Dump the coverage counts. We merge with existing counts when
-   possible, to avoid growing the .da files ad infinitum.  */
-
-void
-__bb_exit_func (void)
-{
-  struct bb *ptr;
-  int i;
-  gcov_type program_sum = 0;
-  gcov_type program_max = 0;
-  long program_arcs = 0;
-  gcov_type merged_sum = 0;
-  gcov_type merged_max = 0;
-  long merged_arcs = 0;
-  
-#if defined (TARGET_HAS_F_SETLKW)
-  struct flock s_flock;
-
-  s_flock.l_type = F_WRLCK;
-  s_flock.l_whence = SEEK_SET;
-  s_flock.l_start = 0;
-  s_flock.l_len = 0; /* Until EOF. */
-  s_flock.l_pid = getpid ();
-#endif
-
-  /* Non-merged stats for this program.  */
-  for (ptr = bb_head; ptr; ptr = ptr->next)
-    {
-      for (i = 0; i < ptr->ncounts; i++)
-       {
-         program_sum += ptr->counts[i];
-
-         if (ptr->counts[i] > program_max)
-           program_max = ptr->counts[i];
-       }
-      program_arcs += ptr->ncounts;
-    }
-  
-  for (ptr = bb_head; ptr; ptr = ptr->next)
-    {
-      FILE *da_file;
-      gcov_type object_max = 0;
-      gcov_type object_sum = 0;
-      long object_functions = 0;
-      int merging = 0;
-      int error = 0;
-      struct bb_function_info *fn_info;
-      gcov_type *count_ptr;
-      
-      /* Open for modification */
-      da_file = fopen (ptr->filename, "r+b");
-      
-      if (da_file)
-       merging = 1;
-      else
-       {
-         /* Try for appending */
-         da_file = fopen (ptr->filename, "ab");
-         /* Some old systems might not allow the 'b' mode modifier.
-             Therefore, try to open without it.  This can lead to a
-             race condition so that when you delete and re-create the
-             file, the file might be opened in text mode, but then,
-             you shouldn't delete the file in the first place.  */
-         if (!da_file)
-           da_file = fopen (ptr->filename, "a");
-       }
-      
-      if (!da_file)
-       {
-         fprintf (stderr, "arc profiling: Can't open output file %s.\n",
-                  ptr->filename);
-         ptr->filename = 0;
-         continue;
-       }
-
-#if defined (TARGET_HAS_F_SETLKW)
-      /* After a fork, another process might try to read and/or write
-         the same file simultanously.  So if we can, lock the file to
-         avoid race conditions.  */
-      while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
-            && errno == EINTR)
-       continue;
-#endif
-      for (fn_info = ptr->function_infos; fn_info->arc_count != -1; fn_info++)
-       object_functions++;
-
-      if (merging)
-       {
-         /* Merge data from file.  */
-         long tmp_long;
-         gcov_type tmp_gcov;
-         
-         if (/* magic */
-             (__read_long (&tmp_long, da_file, 4) || tmp_long != -123l)
-             /* functions in object file.  */
-             || (__read_long (&tmp_long, da_file, 4)
-                 || tmp_long != object_functions)
-             /* extension block, skipped */
-             || (__read_long (&tmp_long, da_file, 4)
-                 || fseek (da_file, tmp_long, SEEK_CUR)))
-           {
-           read_error:;
-             fprintf (stderr, "arc profiling: Error merging output file %s.\n",
-                      ptr->filename);
-             clearerr (da_file);
-           }
-         else
-           {
-             /* Merge execution counts for each function.  */
-             count_ptr = ptr->counts;
-             
-             for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
-                  fn_info++)
-               {
-                 if (/* function name delim */
-                     (__read_long (&tmp_long, da_file, 4)
-                      || tmp_long != -1)
-                     /* function name length */
-                     || (__read_long (&tmp_long, da_file, 4)
-                         || tmp_long != (long) strlen (fn_info->name))
-                     /* skip string */
-                     || fseek (da_file, ((tmp_long + 1) + 3) & ~3, SEEK_CUR)
-                     /* function name delim */
-                     || (__read_long (&tmp_long, da_file, 4)
-                         || tmp_long != -1))
-                   goto read_error;
-
-                 if (/* function checksum */
-                     (__read_long (&tmp_long, da_file, 4)
-                      || tmp_long != fn_info->checksum)
-                     /* arc count */
-                     || (__read_long (&tmp_long, da_file, 4)
-                         || tmp_long != fn_info->arc_count))
-                   goto read_error;
-                 
-                 for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
-                   if (__read_gcov_type (&tmp_gcov, da_file, 8))
-                     goto read_error;
-                   else
-                     *count_ptr += tmp_gcov;
-               }
-           }
-         fseek (da_file, 0, SEEK_SET);
-       }
-      
-      /* Calculate the per-object statistics.  */
-      for (i = 0; i < ptr->ncounts; i++)
-       {
-         object_sum += ptr->counts[i];
-
-         if (ptr->counts[i] > object_max)
-           object_max = ptr->counts[i];
-       }
-      merged_sum += object_sum;
-      if (merged_max < object_max)
-       merged_max = object_max;
-      merged_arcs += ptr->ncounts;
-      
-      /* Write out the data. */
-      if (/* magic */
-         __write_long (-123, da_file, 4)
-         /* number of functions in object file.  */
-         || __write_long (object_functions, da_file, 4)
-         /* length of extra data in bytes.  */
-         || __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4)
-
-         /* whole program statistics. If merging write per-object
-            now, rewrite later */
-         /* number of instrumented arcs.  */
-         || __write_long (merging ? ptr->ncounts : program_arcs, da_file, 4)
-         /* sum of counters.  */
-         || __write_gcov_type (merging ? object_sum : program_sum, da_file, 8)
-         /* maximal counter.  */
-         || __write_gcov_type (merging ? object_max : program_max, da_file, 8)
-
-         /* per-object statistics.  */
-         /* number of counters.  */
-         || __write_long (ptr->ncounts, da_file, 4)
-         /* sum of counters.  */
-         || __write_gcov_type (object_sum, da_file, 8)
-         /* maximal counter.  */
-         || __write_gcov_type (object_max, da_file, 8))
-       {
-       write_error:;
-         fprintf (stderr, "arc profiling: Error writing output file %s.\n",
-                  ptr->filename);
-         error = 1;
-       }
-      else
-       {
-         /* Write execution counts for each function.  */
-         count_ptr = ptr->counts;
-
-         for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
-              fn_info++)
-           {
-             if (__write_gcov_string (fn_info->name,
-                                      strlen (fn_info->name), da_file, -1)
-                 || __write_long (fn_info->checksum, da_file, 4)
-                 || __write_long (fn_info->arc_count, da_file, 4))
-               goto write_error;
-             
-             for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
-               if (__write_gcov_type (*count_ptr, da_file, 8))
-                 goto write_error; /* RIP Edsger Dijkstra */
-           }
-       }
-
-      if (fclose (da_file))
-       {
-         fprintf (stderr, "arc profiling: Error closing output file %s.\n",
-                  ptr->filename);
-         error = 1;
-       }
-      if (error || !merging)
-       ptr->filename = 0;
-    }
-
-  /* Upate whole program statistics.  */
-  for (ptr = bb_head; ptr; ptr = ptr->next)
-    if (ptr->filename)
-      {
-       FILE *da_file;
-       
-       da_file = fopen (ptr->filename, "r+b");
-       if (!da_file)
-         {
-           fprintf (stderr, "arc profiling: Cannot reopen %s.\n",
-                    ptr->filename);
-           continue;
-         }
-       
-#if defined (TARGET_HAS_F_SETLKW)
-       while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
-              && errno == EINTR)
-         continue;
-#endif
-       
-       if (fseek (da_file, 4 * 3, SEEK_SET)
-           /* number of instrumented arcs.  */
-           || __write_long (program_arcs, da_file, 4)
-           /* sum of counters.  */
-           || __write_gcov_type (program_sum, da_file, 8)
-           /* maximal counter.  */
-           || __write_gcov_type (program_max, da_file, 8))
-         fprintf (stderr, "arc profiling: Error updating program header %s.\n",
-                  ptr->filename);
-       if (fclose (da_file))
-         fprintf (stderr, "arc profiling: Error reclosing %s\n",
-                  ptr->filename);
-      }
-}
-
-/* Add a new object file onto the bb chain.  Invoked automatically
-   when running an object file's global ctors.  */
-
-void
-__bb_init_func (struct bb *blocks)
-{
-  if (blocks->zero_word)
-    return;
-
-  /* Initialize destructor and per-thread data.  */
-  if (!bb_head)
-    atexit (__bb_exit_func);
-
-  /* Set up linked list.  */
-  blocks->zero_word = 1;
-  blocks->next = bb_head;
-  bb_head = blocks;
-}
-
-/* Called before fork or exec - write out profile information gathered so
-   far and reset it to zero.  This avoids duplication or loss of the
-   profile information gathered so far.  */
-
-void
-__bb_fork_func (void)
-{
-  struct bb *ptr;
-
-  __bb_exit_func ();
-  for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
-    {
-      long i;
-      for (i = ptr->ncounts - 1; i >= 0; i--)
-       ptr->counts[i] = 0;
-    }
-}
-
-#endif /* not inhibit_libc */
-#endif /* L_bb */
 \f
 #ifdef L_clear_cache
 /* Clear part of an instruction cache.  */