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"
#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
+#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;
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
#endif
#endif
-#ifdef L_gcov
-
-/* Gcov 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>
-#if defined (TARGET_HAS_F_SETLKW)
-#include <fcntl.h>
-#include <errno.h>
-#endif
-
-/* Chain of per-object gcov structures. */
-static struct gcov_info *gcov_list;
-
-/* A program checksum allows us to distinguish program data for an
- object file included in multiple programs. */
-static unsigned gcov_crc32;
-
-static void
-gcov_version_mismatch (struct gcov_info *ptr, unsigned version)
-{
- unsigned expected = GCOV_VERSION;
- unsigned ix;
- char e[4], v[4];
-
- for (ix = 4; ix--; expected >>= 8, version >>= 8)
- {
- e[ix] = expected;
- v[ix] = version;
- }
-
- fprintf (stderr,
- "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
- ptr->filename, e, v);
-}
-
-/* Dump the coverage counts. We merge with existing counts when
- possible, to avoid growing the .da files ad infinitum. We use this
- program's checksum to make sure we only accumulate whole program
- statistics to the correct summary. An object file might be embedded
- in two separate programs, and we must keep the two program
- summaries separate. */
-
-static void
-gcov_exit (void)
-{
- struct gcov_info *ptr;
- unsigned ix, jx;
- struct gcov_summary program;
- gcov_type program_max_one = 0;
- gcov_type program_max_sum = 0;
- gcov_type program_sum = 0;
- unsigned program_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
-
- memset (&program, 0, sizeof (program));
- program.checksum = gcov_crc32;
-
- for (ptr = gcov_list; ptr; ptr = ptr->next)
- {
- FILE *da_file;
- struct gcov_summary object;
- struct gcov_summary local_prg;
- int merging = 0;
- long base;
- const struct function_info *fn_info;
- gcov_type *count_ptr;
- gcov_type object_max_one = 0;
-
- ptr->wkspc = 0;
- if (!ptr->filename)
- continue;
-
- for (ix = ptr->n_arc_counts, count_ptr = ptr->arc_counts; ix--;)
- {
- gcov_type count = *count_ptr++;
-
- if (count > object_max_one)
- object_max_one = count;
- }
- if (object_max_one > program_max_one)
- program_max_one = object_max_one;
-
- memset (&local_prg, 0, sizeof (local_prg));
- memset (&object, 0, sizeof (object));
-
- /* Open for modification */
- if ((da_file = fopen (ptr->filename, "r+b")))
- merging = 1;
- else if ((da_file = fopen (ptr->filename, "w+b")))
- ;
- else
- {
- fprintf (stderr, "profiling:%s:Cannot open\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 simultaneously. So if we can, lock the file to
- avoid race conditions. */
- while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
- && errno == EINTR)
- continue;
-#endif
- if (merging)
- {
- /* Merge data from file. */
- unsigned tag, length;
-
- if (gcov_read_unsigned (da_file, &tag) || tag != GCOV_DATA_MAGIC)
- {
- fprintf (stderr, "profiling:%s:Not a gcov data file\n",
- ptr->filename);
- read_fatal:;
- fclose (da_file);
- ptr->filename = 0;
- continue;
- }
- if (gcov_read_unsigned (da_file, &length) || length != GCOV_VERSION)
- {
- gcov_version_mismatch (ptr, length);
- goto read_fatal;
- }
-
- /* Merge execution counts for each function. */
- count_ptr = ptr->arc_counts;
- for (ix = ptr->n_functions, fn_info = ptr->functions;
- ix--; fn_info++)
- {
- if (gcov_read_unsigned (da_file, &tag)
- || gcov_read_unsigned (da_file, &length))
- {
- read_error:;
- fprintf (stderr, "profiling:%s:Error merging\n",
- ptr->filename);
- goto read_fatal;
- }
-
- /* Check function */
- if (tag != GCOV_TAG_FUNCTION)
- {
- read_mismatch:;
- fprintf (stderr, "profiling:%s:Merge mismatch at %s\n",
- ptr->filename, fn_info->name);
- goto read_fatal;
- }
- {
- unsigned flength, checksum;
-
- if (gcov_read_unsigned (da_file, &flength)
- || gcov_skip_string (da_file, flength)
- || gcov_read_unsigned (da_file, &checksum))
- goto read_error;
- if (flength != strlen (fn_info->name)
- || checksum != fn_info->checksum)
- goto read_mismatch;
- }
- /* Check arc counts */
- if (gcov_read_unsigned (da_file, &tag)
- || gcov_read_unsigned (da_file, &length))
- goto read_error;
- if (tag != GCOV_TAG_ARC_COUNTS
- || length / 8 != fn_info->n_arc_counts)
- goto read_mismatch;
- {
- gcov_type count;
-
- for (jx = fn_info->n_arc_counts; jx--; count_ptr++)
- if (gcov_read_counter (da_file, &count))
- goto read_error;
- else
- *count_ptr += count;
- }
- }
-
- /* Check object summary */
- if (gcov_read_unsigned (da_file, &tag)
- || gcov_read_unsigned (da_file, &length))
- goto read_error;
- if (tag != GCOV_TAG_OBJECT_SUMMARY)
- goto read_mismatch;
- if (gcov_read_summary (da_file, &object))
- goto read_error;
-
- /* Check program summary */
- while (1)
- {
- long base = ftell (da_file);
-
- if (gcov_read_unsigned (da_file, &tag)
- || gcov_read_unsigned (da_file, &length))
- {
- if (feof (da_file))
- break;
- goto read_error;
- }
- if (tag != GCOV_TAG_PROGRAM_SUMMARY
- && tag != GCOV_TAG_PLACEHOLDER_SUMMARY
- && tag != GCOV_TAG_INCORRECT_SUMMARY)
- goto read_mismatch;
- if (gcov_read_summary (da_file, &local_prg))
- goto read_error;
- if (local_prg.checksum != program.checksum)
- continue;
- if (tag == GCOV_TAG_PLACEHOLDER_SUMMARY)
- {
- fprintf (stderr,
- "profiling:%s:Concurrent race detected\n",
- ptr->filename);
- goto read_fatal;
- }
- merging = -1;
- if (tag != GCOV_TAG_PROGRAM_SUMMARY)
- break;
-
- if (program.runs
- && memcmp (&program, &local_prg, sizeof (program)))
- {
- fprintf (stderr, "profiling:%s:Invocation mismatch\n",
- ptr->filename);
- local_prg.runs = 0;
- }
- else
- memcpy (&program, &local_prg, sizeof (program));
- ptr->wkspc = base;
- break;
- }
- fseek (da_file, 0, SEEK_SET);
- }
-
- object.runs++;
- object.arcs = ptr->n_arc_counts;
- object.arc_sum = 0;
- if (object.arc_max_one < object_max_one)
- object.arc_max_one = object_max_one;
- object.arc_sum_max += object_max_one;
-
- /* Write out the data. */
- if (/* magic */
- gcov_write_unsigned (da_file, GCOV_DATA_MAGIC)
- /* version number */
- || gcov_write_unsigned (da_file, GCOV_VERSION))
- {
- write_error:;
- fclose (da_file);
- fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
- ptr->filename = 0;
- continue;
- }
-
- /* Write execution counts for each function. */
- count_ptr = ptr->arc_counts;
- for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
- {
- /* Announce function. */
- if (gcov_write_unsigned (da_file, GCOV_TAG_FUNCTION)
- || !(base = gcov_reserve_length (da_file))
- /* function name */
- || gcov_write_string (da_file, fn_info->name,
- strlen (fn_info->name))
- /* function checksum */
- || gcov_write_unsigned (da_file, fn_info->checksum)
- || gcov_write_length (da_file, base))
- goto write_error;
-
- /* arc counts. */
- if (gcov_write_unsigned (da_file, GCOV_TAG_ARC_COUNTS)
- || !(base = gcov_reserve_length (da_file)))
- goto write_error;
-
- for (jx = fn_info->n_arc_counts; jx--;)
- {
- gcov_type count = *count_ptr++;
-
- object.arc_sum += count;
- if (object.arc_max_sum < count)
- object.arc_max_sum = count;
- if (gcov_write_counter (da_file, count))
- goto write_error; /* RIP Edsger Dijkstra */
- }
- if (gcov_write_length (da_file, base))
- goto write_error;
- }
-
- /* Object file summary. */
- if (gcov_write_summary (da_file, GCOV_TAG_OBJECT_SUMMARY, &object))
- goto write_error;
-
- if (merging >= 0)
- {
- if (fseek (da_file, 0, SEEK_END))
- goto write_error;
- ptr->wkspc = ftell (da_file);
- if (gcov_write_summary (da_file, GCOV_TAG_PLACEHOLDER_SUMMARY,
- &program))
- goto write_error;
- }
- else if (ptr->wkspc)
- {
- /* Zap trailing program summary */
- if (fseek (da_file, ptr->wkspc, SEEK_SET))
- goto write_error;
- if (!local_prg.runs)
- ptr->wkspc = 0;
- if (gcov_write_unsigned (da_file,
- local_prg.runs ? GCOV_TAG_PLACEHOLDER_SUMMARY
- : GCOV_TAG_INCORRECT_SUMMARY))
- goto write_error;
- }
- if (fflush (da_file))
- goto write_error;
-
- if (fclose (da_file))
- {
- fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
- ptr->filename = 0;
- }
- else
- {
- program_arcs += ptr->n_arc_counts;
- program_sum += object.arc_sum;
- if (program_max_sum < object.arc_max_sum)
- program_max_sum = object.arc_max_sum;
- }
- }
-
- /* Generate whole program statistics. */
- program.runs++;
- program.arcs = program_arcs;
- program.arc_sum = program_sum;
- if (program.arc_max_one < program_max_one)
- program.arc_max_one = program_max_one;
- if (program.arc_max_sum < program_max_sum)
- program.arc_max_sum = program_max_sum;
- program.arc_sum_max += program_max_one;
-
- /* Upate whole program statistics. */
- for (ptr = gcov_list; ptr; ptr = ptr->next)
- if (ptr->filename && ptr->wkspc)
- {
- FILE *da_file;
-
- da_file = fopen (ptr->filename, "r+b");
- if (!da_file)
- {
- fprintf (stderr, "profiling:%s:Cannot open\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, ptr->wkspc, SEEK_SET)
- || gcov_write_summary (da_file, GCOV_TAG_PROGRAM_SUMMARY, &program)
- || fflush (da_file))
- fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
- if (fclose (da_file))
- fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
- }
-}
-
-/* Add a new object file onto the bb chain. Invoked automatically
- when running an object file's global ctors. */
-
-void
-__gcov_init (struct gcov_info *info)
-{
- if (!info->version)
- return;
- if (info->version != GCOV_VERSION)
- gcov_version_mismatch (info, info->version);
- else
- {
- const char *ptr = info->filename;
- unsigned crc32 = gcov_crc32;
-
- do
- {
- unsigned ix;
- unsigned value = *ptr << 24;
-
- for (ix = 8; ix--; value <<= 1)
- {
- unsigned feedback;
-
- feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
- crc32 <<= 1;
- crc32 ^= feedback;
- }
- }
- while (*ptr++);
-
- gcov_crc32 = crc32;
-
- if (!gcov_list)
- atexit (gcov_exit);
-
- info->next = gcov_list;
- gcov_list = info;
- }
- info->version = 0;
-}
-
-/* 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
-__gcov_flush (void)
-{
- struct gcov_info *ptr;
-
- gcov_exit ();
- for (ptr = gcov_list; ptr; ptr = ptr->next)
- {
- unsigned i;
-
- for (i = ptr->n_arc_counts; i--;)
- ptr->arc_counts[i] = 0;
- }
-}
-
-#endif /* L_gcov */
\f
#ifdef L_clear_cache
/* Clear part of an instruction cache. */