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
__subvdi3 (DWtype a, DWtype b)
{
#ifdef L_addvdi3
- return (a, (-b));
+ return __addvdi3 (a, (-b));
#else
DWtype w;
#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
}
#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;
}
#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)
{
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)
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
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
&& 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);
#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. */