375 lines
7.8 KiB
C
375 lines
7.8 KiB
C
/* 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-2021 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"
|
|
#include "libgcc_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);
|
|
|
|
|
|
#ifdef XSTORMY16_UDIVMODSI4
|
|
USItype
|
|
udivmodsi4 (USItype num, USItype den, word_type modwanted)
|
|
{
|
|
USItype bit = 1;
|
|
USItype res = 0;
|
|
|
|
while (den < num && bit && !(den & (1L << 31)))
|
|
{
|
|
den <<= 1;
|
|
bit <<= 1;
|
|
}
|
|
while (bit)
|
|
{
|
|
if (num >= den)
|
|
{
|
|
num -= den;
|
|
res |= bit;
|
|
}
|
|
bit >>= 1;
|
|
den >>= 1;
|
|
}
|
|
|
|
if (modwanted)
|
|
return num;
|
|
return res;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_DIVSI3
|
|
SItype
|
|
__divsi3 (SItype a, SItype b)
|
|
{
|
|
word_type neg = 0;
|
|
SItype res;
|
|
|
|
if (a < 0)
|
|
{
|
|
a = -a;
|
|
neg = !neg;
|
|
}
|
|
|
|
if (b < 0)
|
|
{
|
|
b = -b;
|
|
neg = !neg;
|
|
}
|
|
|
|
res = udivmodsi4 (a, b, 0);
|
|
|
|
if (neg)
|
|
res = -res;
|
|
|
|
return res;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_MODSI3
|
|
SItype
|
|
__modsi3 (SItype a, SItype b)
|
|
{
|
|
word_type neg = 0;
|
|
SItype res;
|
|
|
|
if (a < 0)
|
|
{
|
|
a = -a;
|
|
neg = 1;
|
|
}
|
|
|
|
if (b < 0)
|
|
b = -b;
|
|
|
|
res = udivmodsi4 (a, b, 1);
|
|
|
|
if (neg)
|
|
res = -res;
|
|
|
|
return res;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_UDIVSI3
|
|
SItype
|
|
__udivsi3 (SItype a, SItype b)
|
|
{
|
|
return udivmodsi4 (a, b, 0);
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_UMODSI3
|
|
SItype
|
|
__umodsi3 (SItype a, SItype b)
|
|
{
|
|
return udivmodsi4 (a, b, 1);
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_ASHLSI3
|
|
SItype
|
|
__ashlsi3 (SItype a, SItype b)
|
|
{
|
|
word_type i;
|
|
|
|
if (b & 16)
|
|
a <<= 16;
|
|
if (b & 8)
|
|
a <<= 8;
|
|
for (i = (b & 0x7); i > 0; --i)
|
|
a <<= 1;
|
|
return a;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_ASHRSI3
|
|
SItype
|
|
__ashrsi3 (SItype a, SItype b)
|
|
{
|
|
word_type i;
|
|
|
|
if (b & 16)
|
|
a >>= 16;
|
|
if (b & 8)
|
|
a >>= 8;
|
|
for (i = (b & 0x7); i > 0; --i)
|
|
a >>= 1;
|
|
return a;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_LSHRSI3
|
|
USItype
|
|
__lshrsi3 (USItype a, USItype b)
|
|
{
|
|
word_type i;
|
|
|
|
if (b & 16)
|
|
a >>= 16;
|
|
if (b & 8)
|
|
a >>= 8;
|
|
for (i = (b & 0x7); i > 0; --i)
|
|
a >>= 1;
|
|
return a;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_POPCOUNTHI2
|
|
/* Returns the number of set bits in X.
|
|
FIXME: The return type really should be "unsigned int"
|
|
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;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_PARITYHI2
|
|
/* Returns the number of set bits in X, modulo 2.
|
|
FIXME: The return type really should be "unsigned int"
|
|
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;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_CLZHI2
|
|
/* Returns the number of zero-bits from the most significant bit to the
|
|
first nonzero bit in X. Returns 16 for X == 0. Implemented as a
|
|
simple for loop in order to save space by removing the need for
|
|
the __clz_tab array.
|
|
FIXME: The return type really should be "unsigned int" but this is
|
|
not how the builtin is prototyped. */
|
|
#undef unsigned
|
|
int
|
|
__clzhi2 (UHWtype x)
|
|
{
|
|
unsigned int i;
|
|
unsigned int c;
|
|
unsigned int value = x;
|
|
|
|
for (c = 0, i = 1 << 15; i; i >>= 1, c++)
|
|
if (i & value)
|
|
break;
|
|
return c;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_CTZHI2
|
|
/* Returns the number of trailing zero bits in X.
|
|
FIXME: The return type really should be "signed int" since
|
|
ctz(0) returns -1, 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 that was the least significant bit in X. From this we
|
|
can use the count_leading_zeros to compute the number of trailing
|
|
bits. */
|
|
x &= - x;
|
|
|
|
return 15 - __builtin_clz (x);
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_FFSHI2
|
|
/* Returns one plus the index of the least significant 1-bit of X,
|
|
or if X is zero, returns zero. FIXME: The return type really
|
|
should be "unsigned int" but this is not how the builtin is
|
|
prototyped. */
|
|
|
|
int
|
|
__ffshi2 (UHWtype u)
|
|
{
|
|
UHWtype count;
|
|
|
|
if (u == 0)
|
|
return 0;
|
|
|
|
return 16 - __builtin_clz (u & - u);
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_CLRSBHI2
|
|
/* Returns the number of leading redundant sign bits in X.
|
|
I.e. the number of bits following the most significant bit which are
|
|
identical to it. There are no special cases for 0 or other values. */
|
|
|
|
int
|
|
__clrsbhi2 (HWtype x)
|
|
{
|
|
if (x < 0)
|
|
x = ~x;
|
|
if (x == 0)
|
|
return 15;
|
|
return __builtin_clz (x) - 1;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_UCMPSI2
|
|
/* Performs an unsigned comparison of two 32-bit values: A and B.
|
|
If A is less than B, then 0 is returned. If A is greater than B,
|
|
then 2 is returned. Otherwise A and B are equal and 1 is returned. */
|
|
|
|
word_type
|
|
__ucmpsi2 (USItype a, USItype b)
|
|
{
|
|
word_type hi_a = (a >> 16);
|
|
word_type hi_b = (b >> 16);
|
|
|
|
if (hi_a == hi_b)
|
|
{
|
|
word_type low_a = (a & 0xffff);
|
|
word_type low_b = (b & 0xffff);
|
|
|
|
return low_a < low_b ? 0 : (low_a > low_b ? 2 : 1);
|
|
}
|
|
|
|
return hi_a < hi_b ? 0 : 2;
|
|
}
|
|
#endif
|
|
|
|
#ifdef XSTORMY16_CMPSI2
|
|
/* Performs an signed comparison of two 32-bit values: A and B.
|
|
If A is less than B, then 0 is returned. If A is greater than B,
|
|
then 2 is returned. Otherwise A and B are equal and 1 is returned. */
|
|
|
|
word_type
|
|
__cmpsi2 (SItype a, SItype b)
|
|
{
|
|
word_type hi_a = (a >> 16);
|
|
word_type hi_b = (b >> 16);
|
|
|
|
if (hi_a == hi_b)
|
|
{
|
|
word_type low_a = (a & 0xffff);
|
|
word_type low_b = (b & 0xffff);
|
|
|
|
return low_a < low_b ? 0 : (low_a > low_b ? 2 : 1);
|
|
}
|
|
|
|
return hi_a < hi_b ? 0 : 2;
|
|
}
|
|
#endif
|