OSDN Git Service

Declare __fixunsxfdi.
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
index fd27c95..4dd2843 100644 (file)
@@ -55,17 +55,27 @@ typedef              int DItype     __attribute__ ((mode (DI)));
 typedef unsigned int UDItype   __attribute__ ((mode (DI)));
 typedef        float SFtype    __attribute__ ((mode (SF)));
 typedef                float DFtype    __attribute__ ((mode (DF)));
-#if 0
+#if LONG_DOUBLE_TYPE_SIZE == 96
 typedef                float XFtype    __attribute__ ((mode (XF)));
 #endif
 #if LONG_DOUBLE_TYPE_SIZE == 128
 typedef                float TFtype    __attribute__ ((mode (TF)));
 #endif
 
-/* Make sure that we don't accidentaly use any normal C language built-in
+#if BITS_PER_WORD==16
+typedef int word_type __attribute__ ((mode (HI)));
+#endif
+#if BITS_PER_WORD==32
+typedef int word_type __attribute__ ((mode (SI)));
+#endif
+#if BITS_PER_WORD==64
+typedef int word_type __attribute__ ((mode (DI)));
+#endif
+
+/* Make sure that we don't accidentally use any normal C language built-in
    type names in the first part of this file.  Instead we want to use *only*
    the type names defined above.  The following macro definitions insure
-   that if we *do* accidently use soem normal C language built-in type name,
+   that if we *do* accidentally use some normal C language built-in type name,
    we will get a syntax error.  */
 
 #define char bogus_type
@@ -105,6 +115,7 @@ typedef union
 
 extern DItype __fixunssfdi (SFtype a);
 extern DItype __fixunsdfdi (DFtype a);
+extern DItype __fixunsxfdi (XFtype a);
 \f
 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
 #if defined (L_divdi3) || defined (L_moddi3)
@@ -255,6 +266,27 @@ __ashrdi3 (u, b)
 }
 #endif
 \f
+#ifdef L_ffsdi2
+DItype
+__ffsdi2 (u)
+     DItype u;
+{
+  DIunion uu, w;
+  uu.ll = u;
+  w.s.high = 0;
+  w.s.low = ffs (uu.s.low);
+  if (w.s.low != 0)
+    return w.ll;
+  w.s.low = ffs (uu.s.high);
+  if (w.s.low != 0)
+    {
+      w.s.low += BITS_PER_UNIT * sizeof (SItype);
+      return w.ll;
+    }
+  return w.ll;
+}
+#endif
+\f
 #ifdef L_muldi3
 DItype
 __muldi3 (u, v)
@@ -284,7 +316,7 @@ __udiv_w_sdiv (rp, a1, a0, d)
 
   if ((SItype) d >= 0)
     {
-      if (a1 < d - a1 - (a0 >> 31))
+      if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
        {
          /* dividend, divisor, and quotient are nonnegative */
          sdiv_qrnnd (q, r, a1, a0, d);
@@ -292,18 +324,18 @@ __udiv_w_sdiv (rp, a1, a0, d)
       else
        {
          /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
-         sub_ddmmss (c1, c0, a1, a0, d >> 1, d << 31);
+         sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
          /* Divide (c1*2^32 + c0) by d */
          sdiv_qrnnd (q, r, c1, c0, d);
          /* Add 2^31 to quotient */
-         q += 1 << 31;
+         q += (USItype) 1 << (SI_TYPE_SIZE - 1);
        }
     }
   else
     {
       b1 = d >> 1;                     /* d/2, between 2^30 and 2^31 - 1 */
       c1 = a1 >> 1;                    /* A/2 */
-      c0 = (a1 << 31) + (a0 >> 1);
+      c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
 
       if (a1 < b1)                     /* A < 2^32*b1, so A/2 < 2^31*b1 */
        {
@@ -609,6 +641,7 @@ __udivmoddi4 (n, d, rp)
 
 #ifdef L_divdi3
 UDItype __udivmoddi4 ();
+
 DItype
 __divdi3 (u, v)
      DItype u, v;
@@ -687,7 +720,7 @@ __udivdi3 (n, d)
 #endif
 \f
 #ifdef L_cmpdi2
-SItype
+word_type
 __cmpdi2 (a, b)
      DItype a, b;
 {
@@ -708,7 +741,7 @@ __cmpdi2 (a, b)
 #endif
 
 #ifdef L_ucmpdi2
-SItype
+word_type
 __ucmpdi2 (a, b)
      DItype a, b;
 {
@@ -772,6 +805,50 @@ __fixtfdi (a)
 }
 #endif
 
+#if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
+#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+
+DItype
+__fixunsxfdi (a)
+     XFtype a;
+{
+  XFtype b;
+  UDItype v;
+
+  if (a < 0)
+    return 0;
+
+  /* Compute high word of result, as a flonum.  */
+  b = (a / HIGH_WORD_COEFF);
+  /* Convert that to fixed (but not to DItype!),
+     and shift it into the high word.  */
+  v = (USItype) b;
+  v <<= WORD_SIZE;
+  /* Remove high part from the XFtype, leaving the low part as flonum.  */
+  a -= (XFtype)v;
+  /* Convert that to fixed (but not to DItype!) 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 -= (USItype) (- a);
+  else
+    v += (USItype) a;
+  return v;
+}
+#endif
+
+#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
+DItype
+__fixxfdi (a)
+     XFtype a;
+{
+  if (a < 0)
+    return - __fixunsxfdi (-a);
+  return __fixunsxfdi (a);
+}
+#endif
+
 #ifdef L_fixunsdfdi
 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
@@ -862,6 +939,30 @@ __fixsfdi (SFtype a)
 }
 #endif
 
+#if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
+#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
+#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+
+XFtype
+__floatdixf (u)
+     DItype u;
+{
+  XFtype d;
+  SItype negate = 0;
+
+  if (u < 0)
+    u = -u, negate = 1;
+
+  d = (USItype) (u >> WORD_SIZE);
+  d *= HIGH_HALFWORD_COEFF;
+  d *= HIGH_HALFWORD_COEFF;
+  d += (USItype) (u & (HIGH_WORD_COEFF - 1));
+
+  return (negate ? -d : d);
+}
+#endif
+
 #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
@@ -919,7 +1020,10 @@ SFtype
 __floatdisf (u)
      DItype u;
 {
-  SFtype f;
+  /* Do the calculation in DFmode
+     so that we don't lose any of the precision of the high word
+     while multiplying it.  */
+  DFtype f;
   SItype negate = 0;
 
   if (u < 0)
@@ -930,7 +1034,20 @@ __floatdisf (u)
   f *= HIGH_HALFWORD_COEFF;
   f += (USItype) (u & (HIGH_WORD_COEFF - 1));
 
-  return (negate ? -f : f);
+  return (SFtype) (negate ? -f : f);
+}
+#endif
+
+#if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
+#include "glimits.h"
+
+USItype
+__fixunsxfsi (a)
+     XFtype a;
+{
+  if (a >= - (DFtype) LONG_MIN)
+    return (SItype) (a + LONG_MIN) - LONG_MIN;
+  return (SItype) a;
 }
 #endif
 
@@ -1066,7 +1183,7 @@ asm ("___builtin_saveregs:");
        asm ("  bri     %r1");          /* delayed return */
        asm ("  st.l    %r28,12(%r16)"); /* pointer to overflow args */
 
-#else /* not __SVR4__ */
+#else /* not __svr4__ */
        asm ("  .text");
        asm ("  .align  4");
 
@@ -1104,7 +1221,7 @@ asm ("___builtin_saveregs:");
        asm ("  mov     r30,sp");
                                /* recover stack and pass address to start 
                                   of data.  */
-#endif /* not __SVR4__ */
+#endif /* not __svr4__ */
 #else /* not __i860__ */
 #ifdef __sparc__
        asm (".global __builtin_saveregs");
@@ -1149,7 +1266,7 @@ __builtin_saveregs ()
 #endif
 \f
 #ifdef L_eprintf
-#ifndef inhibit_eprintf
+#ifndef inhibit_libc
 
 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
 #include <stdio.h>
@@ -1170,46 +1287,210 @@ __eprintf (string, expression, line, filename)
 #endif
 
 #ifdef L_bb
-/* Avoid warning from ranlib about empty object file.  */
-void
-__bb_avoid_warning ()
-{}
 
-#if defined (__sun__) && defined (__mc68000__)
+/* Structure emitted by -a  */
 struct bb
 {
-  int initialized;
-  char *filename;
-  int *counts;
-  int ncounts;
-  int zero_word;
-  int *addresses;
+  long zero_word;
+  const char *filename;
+  long *counts;
+  long ncounts;
+  struct bb *next;
+  const unsigned long *addresses;
+
+  /* Older GCC's did not emit these fields.  */
+  long nwords;
+  const char **functions;
+  const long *line_nums;
+  const char **filenames;
 };
 
-extern int ___tcov_init;
+#ifdef BLOCK_PROFILER_CODE
+BLOCK_PROFILER_CODE
+#else
+
+/* Simple minded basic block profiling output dumper for
+   systems that don't provde tcov support.  At present,
+   it requires atexit and stdio.  */
 
-__bb_init_func (blocks)
-       struct bb *blocks;
+#include <stdio.h>
+
+#ifdef HAVE_ATEXIT
+extern void atexit (void (*) (void));
+#define ON_EXIT(FUNC,ARG) atexit ((FUNC))
+#else
+#ifdef sun
+extern void on_exit (void*, void*);
+#define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
+#endif
+#endif
+
+static struct bb *bb_head = (struct bb *)0;
+
+/* Return the number of digits needed to print a value */
+/* __inline__ */ static int num_digits (long value, int base)
 {
-  if (! ___tcov_init)
-    ___tcov_init_func ();
+  int minus = (value < 0 && base != 16);
+  unsigned long v = (minus) ? -value : value;
+  int ret = minus;
 
-  ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
+  do
+    {
+      v /= base;
+      ret++;
+    }
+  while (v);
+
+  return ret;
 }
 
+void
+__bb_exit_func (void)
+{
+  FILE *file = fopen ("bb.out", "a");
+  long time_value;
+
+  if (!file)
+    perror ("bb.out");
+
+  else
+    {
+      struct bb *ptr;
+
+      /* This is somewhat type incorrect, but it avoids worrying about
+        exactly where time.h is included from.  It should be ok unless
+        a void * differs from other pointer formats, or if sizeof(long)
+        is < sizeof (time_t).  It would be nice if we could assume the
+        use of rationale standards here.  */
+
+      time((void *) &time_value);
+      fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
+
+      /* We check the length field explicitly in order to allow compatibility
+        with older GCC's which did not provide it.  */
+
+      for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
+       {
+         int i;
+         int func_p    = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
+         int line_p    = (func_p && ptr->line_nums);
+         int file_p    = (func_p && ptr->filenames);
+         long ncounts  = ptr->ncounts;
+         long cnt_max  = 0;
+         long line_max = 0;
+         long addr_max = 0;
+         int file_len  = 0;
+         int func_len  = 0;
+         int blk_len   = num_digits (ncounts, 10);
+         int cnt_len;
+         int line_len;
+         int addr_len;
+
+         fprintf (file, "File %s, %ld basic blocks \n\n",
+                  ptr->filename, ncounts);
+
+         /* Get max values for each field.  */
+         for (i = 0; i < ncounts; i++)
+           {
+             const char *p;
+             int len;
+
+             if (cnt_max < ptr->counts[i])
+               cnt_max = ptr->counts[i];
+
+             if (addr_max < ptr->addresses[i])
+               addr_max = ptr->addresses[i];
+
+             if (line_p && line_max < ptr->line_nums[i])
+               line_max = ptr->line_nums[i];
+
+             if (func_p)
+               {
+                 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
+                 len = strlen (p);
+                 if (func_len < len)
+                   func_len = len;
+               }
+
+             if (file_p)
+               {
+                 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
+                 len = strlen (p);
+                 if (file_len < len)
+                   file_len = len;
+               }
+           }
+
+         addr_len = num_digits (addr_max, 16);
+         cnt_len  = num_digits (cnt_max, 10);
+         line_len = num_digits (line_max, 10);
+
+         /* Now print out the basic block information.  */
+         for (i = 0; i < ncounts; i++)
+           {
+             fprintf (file,
+                      "    Block #%*d: executed %*ld time(s) address= 0x%.*lx",
+                      blk_len, i+1,
+                      cnt_len, ptr->counts[i],
+                      addr_len, ptr->addresses[i]);
+
+             if (func_p)
+               fprintf (file, " function= %-*s", func_len,
+                        (ptr->functions[i]) ? ptr->functions[i] : "<none>");
+
+             if (line_p)
+               fprintf (file, " line= %*d", line_len, ptr->line_nums[i]);
+
+             if (file_p)
+               fprintf (file, " file= %s",
+                        (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
+
+             fprintf (file, "\n");
+           }
+
+         fprintf (file, "\n");
+         fflush (file);
+       }
+
+      fprintf (file, "\n\n");
+      fclose (file);
+    }
+}
+
+void
+__bb_init_func (struct bb *blocks)
+{
+  /* User is supposed to check whether the first word is non-0,
+     but just in case.... */
+
+  if (blocks->zero_word)
+    return;
+
+#ifdef ON_EXIT
+  /* Initialize destructor.  */
+  if (!bb_head)
+    ON_EXIT (__bb_exit_func, 0);
 #endif
-#endif
+
+  /* Set up linked list.  */
+  blocks->zero_word = 1;
+  blocks->next = bb_head;
+  bb_head = blocks;
+}
+
+#endif /* !BLOCK_PROFILER_CODE */
+#endif /* L_bb */
 \f
 /* frills for C++ */
 
-#ifdef L_builtin_new
+#ifdef L_op_new
 typedef void (*vfp)(void);
 
 extern vfp __new_handler;
 
+/* void * operator new (size_t sz) */
 void *
-__builtin_new (sz)
-     size_t sz;
+__builtin_new (size_t sz)
 {
   void *p;
 
@@ -1221,18 +1502,21 @@ __builtin_new (sz)
     (*__new_handler) ();
   return p;
 }
-#endif
+#endif /* L_op_new */
 
-#ifdef L_caps_New
+#ifdef L_new_handler
 
+#ifndef inhibit_libc
 /* This gets us __GNU_LIBRARY__.  */
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
 #include <stdio.h>
 
 #ifdef __GNU_LIBRARY__
   /* Avoid forcing the library's meaning of `write' on the user program
-     by using the "internal" name (for use within the library)
+     by using the "internal" name (for use within the library)  */
 #define write(fd, buf, n)      __write((fd), (buf), (n))
 #endif
+#endif /* inhibit_libc */
 
 typedef void (*vfp)(void);
 
@@ -1241,31 +1525,6 @@ static void default_new_handler (void);
 
 vfp __new_handler = default_new_handler;
 
-void *
-__builtin_vec_new (p, maxindex, size, ctor)
-     void *p;
-     size_t maxindex;
-     size_t size;
-     void (*ctor)(void *);
-{
-  size_t i;
-  size_t nelts = maxindex + 1;
-  void *rval;
-
-  if (p == 0)
-    p = __builtin_new (nelts * size);
-
-  rval = p;
-
-  for (i = 0; i < nelts; i++)
-    {
-      (*ctor) (p);
-      p += size;
-    }
-
-  return rval;
-}
-
 vfp
 __set_new_handler (handler)
      vfp handler;
@@ -1299,44 +1558,17 @@ default_new_handler ()
   _exit (-1);
 }
 #endif
-\f
-#ifdef L_builtin_del
-typedef void (*vfp)(void);
 
+#ifdef L_op_delete
+/* void operator delete (void *ptr) */
 void
-__builtin_delete (ptr)
-     void *ptr;
+__builtin_delete (void *ptr)
 {
   if (ptr)
     free (ptr);
 }
-
-void
-__builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
-     void *ptr;
-     size_t maxindex;
-     size_t size;
-     void (*dtor)(void *, int);
-     int auto_delete;
-{
-  size_t i;
-  size_t nelts = maxindex + 1;
-  void *p = ptr;
-
-  ptr += nelts * size;
-
-  for (i = 0; i < nelts; i++)
-    {
-      ptr -= size;
-      (*dtor) (ptr, auto_delete);
-    }
-
-  if (auto_delete_vec)
-    __builtin_delete (p);
-}
-
 #endif
-
+\f
 #ifdef L_shtab
 unsigned int __shtab[] = {
     0x00000001, 0x00000002, 0x00000004, 0x00000008,
@@ -1499,6 +1731,7 @@ __enable_execute_stack ()
 
 #ifdef __pyr__
 
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
 #include <stdio.h>
 #include <sys/mman.h>
 #include <sys/types.h>
@@ -1526,6 +1759,14 @@ __enable_execute_stack ()
 #ifdef L__main
 
 #include "gbl-ctors.h"
+/* Some systems use __main in a way incompatible with its use in gcc, in these
+   cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
+   give the same symbol without quotes for an alternative entry point.  You
+   must define both, or niether. */
+#ifndef NAME__MAIN
+#define NAME__MAIN "__main"
+#define SYMBOL__MAIN __main
+#endif
 
 /* Run all the global destructors on exit from the program.  */
 
@@ -1585,7 +1826,7 @@ __do_global_ctors ()
    to run __do_global_ctors, so we need not do anything here.  */
 
 void
-__main ()
+SYMBOL__MAIN ()
 {
   /* Support recursive calls to `main': run initializers just once.  */
   static int initialized = 0;