-typedef int HItype __attribute__ ((mode (HI)));
-typedef int SItype __attribute__ ((mode (SI)));
-typedef unsigned int USItype __attribute__ ((mode (SI)));
+/* This file contains 16-bit versions of some of the functions found in
+ libgcc2.c. Really libgcc ought to be moved out of the gcc directory
+ and into its own top level directory, and then split up into multiple
+ files. On this glorious day maybe this code can be integrated into
+ it too. */
+
+/* Copyright (C) 2005, 2008, 2009 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3, or (at your option) any later
+ version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
+#ifndef MIN_UNITS_PER_WORD
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#endif
+
+#ifndef LIBGCC2_UNITS_PER_WORD
+# if MIN_UNITS_PER_WORD > 4
+# define LIBGCC2_UNITS_PER_WORD 8
+# elif (MIN_UNITS_PER_WORD > 2 \
+ || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32))
+# define LIBGCC2_UNITS_PER_WORD 4
+# else
+# define LIBGCC2_UNITS_PER_WORD MIN_UNITS_PER_WORD
+# endif
+#endif
+
+#define word_type Wtype
+
+#include "libgcc2.h"
+#undef int
+
+/* These prototypes would normally live in libgcc2.h, but this can
+ only happen once the code below is integrated into libgcc2.c. */
+
+extern USItype udivmodsi4 (USItype, USItype, word_type);
+extern SItype __divsi3 (SItype, SItype);
+extern SItype __modsi3 (SItype, SItype);
+extern SItype __udivsi3 (SItype, SItype);
+extern SItype __umodsi3 (SItype, SItype);
+extern SItype __ashlsi3 (SItype, SItype);
+extern SItype __ashrsi3 (SItype, SItype);
+extern USItype __lshrsi3 (USItype, USItype);
+extern int __popcounthi2 (UHWtype);
+extern int __parityhi2 (UHWtype);
+extern int __clzhi2 (UHWtype);
+extern int __ctzhi2 (UHWtype);
+
-typedef int word_type __attribute__ ((mode (__word__)));
USItype
-udivmodsi4(USItype num, USItype den, word_type modwanted)
+udivmodsi4 (USItype num, USItype den, word_type modwanted)
{
USItype bit = 1;
USItype res = 0;
- while (den < num && bit && !(den & (1L<<31)))
+ while (den < num && bit && !(den & (1L << 31)))
{
- den <<=1;
- bit <<=1;
+ den <<= 1;
+ bit <<= 1;
}
while (bit)
{
num -= den;
res |= bit;
}
- bit >>=1;
- den >>=1;
+ bit >>= 1;
+ den >>= 1;
}
- if (modwanted) return num;
+
+ if (modwanted)
+ return num;
return res;
}
-
-
SItype
__divsi3 (SItype a, SItype b)
{
return res;
}
-
-
SItype
__modsi3 (SItype a, SItype b)
{
return res;
}
-
-
-
SItype
__udivsi3 (SItype a, SItype b)
{
return udivmodsi4 (a, b, 0);
}
-
-
SItype
__umodsi3 (SItype a, SItype b)
{
a >>= 1;
return a;
}
+
+/* Returns the number of set bits in X.
+ FIXME: The return type really should be unsigned,
+ but this is not how the builtin is prototyped. */
+int
+__popcounthi2 (UHWtype x)
+{
+ int ret;
+
+ ret = __popcount_tab [x & 0xff];
+ ret += __popcount_tab [(x >> 8) & 0xff];
+
+ return ret;
+}
+
+/* Returns the number of set bits in X, modulo 2.
+ FIXME: The return type really should be unsigned,
+ but this is not how the builtin is prototyped. */
+
+int
+__parityhi2 (UHWtype x)
+{
+ x ^= x >> 8;
+ x ^= x >> 4;
+ x &= 0xf;
+ return (0x6996 >> x) & 1;
+}
+
+/* Returns the number of leading zero bits in X.
+ FIXME: The return type really should be unsigned,
+ but this is not how the builtin is prototyped. */
+
+int
+__clzhi2 (UHWtype x)
+{
+ if (x > 0xff)
+ return 8 - __clz_tab[x >> 8];
+ return 16 - __clz_tab[x];
+}
+
+/* Returns the number of trailing zero bits in X.
+ FIXME: The return type really should be unsigned,
+ but this is not how the builtin is prototyped. */
+
+int
+__ctzhi2 (UHWtype x)
+{
+ /* This is cunning. It converts X into a number with only the one bit
+ set, the bit was the least significant bit in X. From this we can
+ use the __clz_tab[] array to compute the number of trailing bits. */
+ x &= - x;
+
+ if (x > 0xff)
+ return __clz_tab[x >> 8] + 7;
+ return __clz_tab[x] - 1;
+}