/* More subroutines needed by GCC output code on some machines. */
/* Compile this one with gcc. */
/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
__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
-Wtype
-__ffsdi2 (DWtype u)
+#undef int
+extern int __ffsDI2 (DWtype u);
+int
+__ffsDI2 (DWtype u)
{
DWunion uu;
UWtype word, count, add;
#endif
\f
#ifdef L_clzsi2
-Wtype
-__clzsi2 (USItype x)
+#undef int
+extern int __clzSI2 (UWtype x);
+int
+__clzSI2 (UWtype x)
{
- UWtype w = x;
Wtype ret;
- count_leading_zeros (ret, w);
- ret -= (sizeof(w) - sizeof(x)) * BITS_PER_UNIT;
+ count_leading_zeros (ret, x);
return ret;
}
#endif
\f
#ifdef L_clzdi2
-Wtype
-__clzdi2 (UDItype x)
+#undef int
+extern int __clzDI2 (UDWtype x);
+int
+__clzDI2 (UDWtype x)
{
+ DWunion uu;
UWtype word;
Wtype ret, add;
- if (sizeof(x) > sizeof(word))
- {
- DWunion uu;
-
- uu.ll = x;
- if (uu.s.high)
- word = uu.s.high, add = 0;
- else
- word = uu.s.low, add = W_TYPE_SIZE;
- }
+ uu.ll = x;
+ if (uu.s.high)
+ word = uu.s.high, add = 0;
else
- word = x, add = (Wtype)(sizeof(x) - sizeof(word)) * BITS_PER_UNIT;
+ word = uu.s.low, add = W_TYPE_SIZE;
count_leading_zeros (ret, word);
return ret + add;
#endif
\f
#ifdef L_ctzsi2
-Wtype
-__ctzsi2 (USItype x)
+#undef int
+extern int __ctzSI2 (UWtype x);
+int
+__ctzSI2 (UWtype x)
{
Wtype ret;
#endif
\f
#ifdef L_ctzdi2
-Wtype
-__ctzdi2 (UDItype x)
+#undef int
+extern int __ctzDI2 (UDWtype x);
+int
+__ctzDI2 (UDWtype x)
{
+ DWunion uu;
UWtype word;
Wtype ret, add;
- if (sizeof(x) > sizeof(word))
- {
- DWunion uu;
-
- uu.ll = x;
- if (uu.s.low)
- word = uu.s.low, add = 0;
- else
- word = uu.s.high, add = W_TYPE_SIZE;
- }
+ uu.ll = x;
+ if (uu.s.low)
+ word = uu.s.low, add = 0;
else
- word = x, add = 0;
+ word = uu.s.high, add = W_TYPE_SIZE;
count_trailing_zeros (ret, word);
return ret + add;
#endif
\f
#ifdef L_popcountsi2
-Wtype
-__popcountsi2 (USItype x)
+#undef int
+extern int __popcountSI2 (UWtype x);
+int
+__popcountSI2 (UWtype x)
{
- return __popcount_tab[(x >> 0) & 0xff]
- + __popcount_tab[(x >> 8) & 0xff]
- + __popcount_tab[(x >> 16) & 0xff]
- + __popcount_tab[(x >> 24) & 0xff];
+ 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
-Wtype
-__popcountdi2 (UDItype x)
+#undef int
+extern int __popcountDI2 (UDWtype x);
+int
+__popcountDI2 (UDWtype x)
{
- return __popcount_tab[(x >> 0) & 0xff]
- + __popcount_tab[(x >> 8) & 0xff]
- + __popcount_tab[(x >> 16) & 0xff]
- + __popcount_tab[(x >> 24) & 0xff]
- + __popcount_tab[(x >> 32) & 0xff]
- + __popcount_tab[(x >> 40) & 0xff]
- + __popcount_tab[(x >> 48) & 0xff]
- + __popcount_tab[(x >> 56) & 0xff];
+ 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
-Wtype
-__paritysi2 (USItype x)
+#undef int
+extern int __paritySI2 (UWtype x);
+int
+__paritySI2 (UWtype x)
{
- UWtype nx = x;
- nx ^= nx >> 16;
- nx ^= nx >> 8;
- nx ^= nx >> 4;
- nx ^= nx >> 2;
- nx ^= nx >> 1;
- return nx & 1;
+#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
-Wtype
-__paritydi2 (UDItype x)
+#undef int
+extern int __parityDI2 (UDWtype x);
+int
+__parityDI2 (UDWtype x)
{
- UWtype nx = x ^ (x >> 32);
+ 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 ^= nx >> 2;
- nx ^= nx >> 1;
- return nx & 1;
+ nx &= 0xf;
+ return (0x6996 >> nx) & 1;
}
#endif
#ifdef L_clear_cache
/* Clear part of an instruction cache. */
-#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
-
void
__clear_cache (char *beg __attribute__((__unused__)),
char *end __attribute__((__unused__)))
{
#ifdef CLEAR_INSN_CACHE
CLEAR_INSN_CACHE (beg, end);
-#else
-#ifdef INSN_CACHE_SIZE
- static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
- static int initialized;
- int offset;
- void *start_addr
- void *end_addr;
- typedef (*function_ptr) (void);
-
-#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
- /* It's cheaper to clear the whole cache.
- Put in a series of jump instructions so that calling the beginning
- of the cache will clear the whole thing. */
-
- if (! initialized)
- {
- int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH);
- int end_ptr = ptr + INSN_CACHE_SIZE;
-
- while (ptr < end_ptr)
- {
- *(INSTRUCTION_TYPE *)ptr
- = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
- ptr += INSN_CACHE_LINE_WIDTH;
- }
- *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
-
- initialized = 1;
- }
-
- /* Call the beginning of the sequence. */
- (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH))
- ());
-
-#else /* Cache is large. */
-
- if (! initialized)
- {
- int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH);
-
- while (ptr < (int) array + sizeof array)
- {
- *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
- ptr += INSN_CACHE_LINE_WIDTH;
- }
-
- initialized = 1;
- }
-
- /* Find the location in array that occupies the same cache line as BEG. */
-
- offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
- start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
- & -INSN_CACHE_PLANE_SIZE)
- + offset);
-
- /* Compute the cache alignment of the place to stop clearing. */
-#if 0 /* This is not needed for gcc's purposes. */
- /* If the block to clear is bigger than a cache plane,
- we clear the entire cache, and OFFSET is already correct. */
- if (end < beg + INSN_CACHE_PLANE_SIZE)
-#endif
- offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH)
- & (INSN_CACHE_PLANE_SIZE - 1));
-
-#if INSN_CACHE_DEPTH > 1
- end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
- if (end_addr <= start_addr)
- end_addr += INSN_CACHE_PLANE_SIZE;
-
- for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
- {
- int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
- int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
-
- while (addr != stop)
- {
- /* Call the return instruction at ADDR. */
- ((function_ptr) addr) ();
-
- addr += INSN_CACHE_LINE_WIDTH;
- }
- }
-#else /* just one plane */
- do
- {
- /* Call the return instruction at START_ADDR. */
- ((function_ptr) start_addr) ();
-
- start_addr += INSN_CACHE_LINE_WIDTH;
- }
- while ((start_addr % INSN_CACHE_SIZE) != offset);
-#endif /* just one plane */
-#endif /* Cache is large */
-#endif /* Cache exists */
#endif /* CLEAR_INSN_CACHE */
}
#ifdef TRANSFER_FROM_TRAMPOLINE
TRANSFER_FROM_TRAMPOLINE
#endif
-
-#ifdef __sysV68__
-
-#include <sys/signal.h>
-#include <errno.h>
-
-/* Motorola forgot to put memctl.o in the libp version of libc881.a,
- so define it here, because we need it in __clear_insn_cache below */
-/* On older versions of this OS, no memctl or MCT_TEXT are defined;
- hence we enable this stuff only if MCT_TEXT is #define'd. */
-
-#ifdef MCT_TEXT
-asm("\n\
- global memctl\n\
-memctl:\n\
- movq &75,%d0\n\
- trap &0\n\
- bcc.b noerror\n\
- jmp cerror%\n\
-noerror:\n\
- movq &0,%d0\n\
- rts");
-#endif
-
-/* Clear instruction cache so we can call trampolines on stack.
- This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
-
-void
-__clear_insn_cache (void)
-{
-#ifdef MCT_TEXT
- int save_errno;
-
- /* Preserve errno, because users would be surprised to have
- errno changing without explicitly calling any system-call. */
- save_errno = errno;
-
- /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
- No need to use an address derived from _start or %sp, as 0 works also. */
- memctl(0, 4096, MCT_TEXT);
- errno = save_errno;
-#endif
-}
-
-#endif /* __sysV68__ */
#endif /* L_trampoline */
\f
#ifndef __CYGWIN__
#endif
#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
#endif /* L_ctors */
-\f
-#ifdef L_exit
-
-#include "gbl-ctors.h"
-
-#ifdef NEED_ATEXIT
-
-#ifndef ON_EXIT
-
-# include <errno.h>
-
-static func_ptr *atexit_chain = 0;
-static long atexit_chain_length = 0;
-static volatile long last_atexit_chain_slot = -1;
-
-int
-atexit (func_ptr func)
-{
- if (++last_atexit_chain_slot == atexit_chain_length)
- {
- atexit_chain_length += 32;
- if (atexit_chain)
- atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
- * sizeof (func_ptr));
- else
- atexit_chain = (func_ptr *) malloc (atexit_chain_length
- * sizeof (func_ptr));
- if (! atexit_chain)
- {
- atexit_chain_length = 0;
- last_atexit_chain_slot = -1;
- errno = ENOMEM;
- return (-1);
- }
- }
- atexit_chain[last_atexit_chain_slot] = func;
- return (0);
-}
-
-extern void _cleanup (void);
-extern void _exit (int) __attribute__ ((__noreturn__));
-
-void
-exit (int status)
-{
- if (atexit_chain)
- {
- for ( ; last_atexit_chain_slot-- >= 0; )
- {
- (*atexit_chain[last_atexit_chain_slot + 1]) ();
- atexit_chain[last_atexit_chain_slot + 1] = 0;
- }
- free (atexit_chain);
- atexit_chain = 0;
- }
-#ifdef EXIT_BODY
- EXIT_BODY;
-#else
- _cleanup ();
-#endif
- _exit (status);
-}
-
-#else /* ON_EXIT */
-
-/* Simple; we just need a wrapper for ON_EXIT. */
-int
-atexit (func_ptr func)
-{
- return ON_EXIT (func);
-}
-
-#endif /* ON_EXIT */
-#endif /* NEED_ATEXIT */
-#endif /* L_exit */