xref: /openbmc/u-boot/arch/nios2/lib/libgcc.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
28d52ea6dSThomas Chou /*
38d52ea6dSThomas Chou  * This file is part of GNU CC.
48d52ea6dSThomas Chou  */
58d52ea6dSThomas Chou 
68d52ea6dSThomas Chou typedef unsigned int UWtype;
78d52ea6dSThomas Chou typedef unsigned int UHWtype;
88d52ea6dSThomas Chou typedef unsigned long long UDWtype;
98d52ea6dSThomas Chou #define W_TYPE_SIZE 32
108d52ea6dSThomas Chou 
118d52ea6dSThomas Chou typedef unsigned char UQItype;
128d52ea6dSThomas Chou typedef long SItype;
138d52ea6dSThomas Chou typedef unsigned long USItype;
148d52ea6dSThomas Chou typedef long long DItype;
158d52ea6dSThomas Chou typedef unsigned long long DSItype;
168d52ea6dSThomas Chou 
178d52ea6dSThomas Chou #include "longlong.h"
188d52ea6dSThomas Chou 
198d52ea6dSThomas Chou 
208d52ea6dSThomas Chou typedef int word_type;
218d52ea6dSThomas Chou typedef long Wtype;
228d52ea6dSThomas Chou typedef long long DWtype;
238d52ea6dSThomas Chou 
248d52ea6dSThomas Chou struct DWstruct { Wtype low, high;};
258d52ea6dSThomas Chou 
268d52ea6dSThomas Chou typedef union
278d52ea6dSThomas Chou {
288d52ea6dSThomas Chou   struct DWstruct s;
298d52ea6dSThomas Chou   DWtype ll;
308d52ea6dSThomas Chou } DWunion;
318d52ea6dSThomas Chou 
328d52ea6dSThomas Chou #define BITS_PER_UNIT 8
338d52ea6dSThomas Chou 
348d52ea6dSThomas Chou UDWtype
358d52ea6dSThomas Chou __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp);
368d52ea6dSThomas Chou 
378d52ea6dSThomas Chou const UQItype __clz_tab[256] =
388d52ea6dSThomas Chou {
398d52ea6dSThomas Chou   0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
408d52ea6dSThomas Chou   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
418d52ea6dSThomas Chou   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
428d52ea6dSThomas Chou   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
438d52ea6dSThomas Chou   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,
448d52ea6dSThomas Chou   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,
458d52ea6dSThomas Chou   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,
468d52ea6dSThomas Chou   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
478d52ea6dSThomas Chou };
488d52ea6dSThomas Chou 
498d52ea6dSThomas Chou 
508d52ea6dSThomas Chou DWtype
__ashldi3(DWtype u,word_type b)518d52ea6dSThomas Chou __ashldi3 (DWtype u, word_type b)
528d52ea6dSThomas Chou {
538d52ea6dSThomas Chou   if (b == 0)
548d52ea6dSThomas Chou     return u;
558d52ea6dSThomas Chou 
568d52ea6dSThomas Chou   const DWunion uu = {.ll = u};
578d52ea6dSThomas Chou   const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
588d52ea6dSThomas Chou   DWunion w;
598d52ea6dSThomas Chou 
608d52ea6dSThomas Chou   if (bm <= 0)
618d52ea6dSThomas Chou     {
628d52ea6dSThomas Chou       w.s.low = 0;
638d52ea6dSThomas Chou       w.s.high = (UWtype) uu.s.low << -bm;
648d52ea6dSThomas Chou     }
658d52ea6dSThomas Chou   else
668d52ea6dSThomas Chou     {
678d52ea6dSThomas Chou       const UWtype carries = (UWtype) uu.s.low >> bm;
688d52ea6dSThomas Chou 
698d52ea6dSThomas Chou       w.s.low = (UWtype) uu.s.low << b;
708d52ea6dSThomas Chou       w.s.high = ((UWtype) uu.s.high << b) | carries;
718d52ea6dSThomas Chou     }
728d52ea6dSThomas Chou 
738d52ea6dSThomas Chou   return w.ll;
748d52ea6dSThomas Chou }
758d52ea6dSThomas Chou 
768d52ea6dSThomas Chou DWtype
__ashrdi3(DWtype u,word_type b)778d52ea6dSThomas Chou __ashrdi3 (DWtype u, word_type b)
788d52ea6dSThomas Chou {
798d52ea6dSThomas Chou   if (b == 0)
808d52ea6dSThomas Chou     return u;
818d52ea6dSThomas Chou 
828d52ea6dSThomas Chou   const DWunion uu = {.ll = u};
838d52ea6dSThomas Chou   const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
848d52ea6dSThomas Chou   DWunion w;
858d52ea6dSThomas Chou 
868d52ea6dSThomas Chou   if (bm <= 0)
878d52ea6dSThomas Chou     {
888d52ea6dSThomas Chou       /* w.s.high = 1..1 or 0..0 */
898d52ea6dSThomas Chou       w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
908d52ea6dSThomas Chou       w.s.low = uu.s.high >> -bm;
918d52ea6dSThomas Chou     }
928d52ea6dSThomas Chou   else
938d52ea6dSThomas Chou     {
948d52ea6dSThomas Chou       const UWtype carries = (UWtype) uu.s.high << bm;
958d52ea6dSThomas Chou 
968d52ea6dSThomas Chou       w.s.high = uu.s.high >> b;
978d52ea6dSThomas Chou       w.s.low = ((UWtype) uu.s.low >> b) | carries;
988d52ea6dSThomas Chou     }
998d52ea6dSThomas Chou 
1008d52ea6dSThomas Chou   return w.ll;
1018d52ea6dSThomas Chou }
1028d52ea6dSThomas Chou 
1038d52ea6dSThomas Chou DWtype
__lshrdi3(DWtype u,word_type b)1048d52ea6dSThomas Chou __lshrdi3 (DWtype u, word_type b)
1058d52ea6dSThomas Chou {
1068d52ea6dSThomas Chou   if (b == 0)
1078d52ea6dSThomas Chou     return u;
1088d52ea6dSThomas Chou 
1098d52ea6dSThomas Chou   const DWunion uu = {.ll = u};
1108d52ea6dSThomas Chou   const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
1118d52ea6dSThomas Chou   DWunion w;
1128d52ea6dSThomas Chou 
1138d52ea6dSThomas Chou   if (bm <= 0)
1148d52ea6dSThomas Chou     {
1158d52ea6dSThomas Chou       w.s.high = 0;
1168d52ea6dSThomas Chou       w.s.low = (UWtype) uu.s.high >> -bm;
1178d52ea6dSThomas Chou     }
1188d52ea6dSThomas Chou   else
1198d52ea6dSThomas Chou     {
1208d52ea6dSThomas Chou       const UWtype carries = (UWtype) uu.s.high << bm;
1218d52ea6dSThomas Chou 
1228d52ea6dSThomas Chou       w.s.high = (UWtype) uu.s.high >> b;
1238d52ea6dSThomas Chou       w.s.low = ((UWtype) uu.s.low >> b) | carries;
1248d52ea6dSThomas Chou     }
1258d52ea6dSThomas Chou 
1268d52ea6dSThomas Chou   return w.ll;
1278d52ea6dSThomas Chou }
1288d52ea6dSThomas Chou 
1298d52ea6dSThomas Chou word_type
__cmpdi2(DWtype a,DWtype b)1308d52ea6dSThomas Chou __cmpdi2 (DWtype a, DWtype b)
1318d52ea6dSThomas Chou {
1328d52ea6dSThomas Chou   const DWunion au = {.ll = a};
1338d52ea6dSThomas Chou   const DWunion bu = {.ll = b};
1348d52ea6dSThomas Chou 
1358d52ea6dSThomas Chou   if (au.s.high < bu.s.high)
1368d52ea6dSThomas Chou     return 0;
1378d52ea6dSThomas Chou   else if (au.s.high > bu.s.high)
1388d52ea6dSThomas Chou     return 2;
1398d52ea6dSThomas Chou   if ((UWtype) au.s.low < (UWtype) bu.s.low)
1408d52ea6dSThomas Chou     return 0;
1418d52ea6dSThomas Chou   else if ((UWtype) au.s.low > (UWtype) bu.s.low)
1428d52ea6dSThomas Chou     return 2;
1438d52ea6dSThomas Chou   return 1;
1448d52ea6dSThomas Chou }
1458d52ea6dSThomas Chou 
1468d52ea6dSThomas Chou UDWtype
__udivmoddi4(UDWtype n,UDWtype d,UDWtype * rp)1478d52ea6dSThomas Chou __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
1488d52ea6dSThomas Chou {
1498d52ea6dSThomas Chou   const DWunion nn = {.ll = n};
1508d52ea6dSThomas Chou   const DWunion dd = {.ll = d};
1518d52ea6dSThomas Chou   DWunion rr;
1528d52ea6dSThomas Chou   UWtype d0, d1, n0, n1, n2;
1538d52ea6dSThomas Chou   UWtype q0, q1;
1548d52ea6dSThomas Chou   UWtype b, bm;
1558d52ea6dSThomas Chou 
1568d52ea6dSThomas Chou   d0 = dd.s.low;
1578d52ea6dSThomas Chou   d1 = dd.s.high;
1588d52ea6dSThomas Chou   n0 = nn.s.low;
1598d52ea6dSThomas Chou   n1 = nn.s.high;
1608d52ea6dSThomas Chou 
1618d52ea6dSThomas Chou #if !UDIV_NEEDS_NORMALIZATION
1628d52ea6dSThomas Chou   if (d1 == 0)
1638d52ea6dSThomas Chou     {
1648d52ea6dSThomas Chou       if (d0 > n1)
1658d52ea6dSThomas Chou 	{
1668d52ea6dSThomas Chou 	  /* 0q = nn / 0D */
1678d52ea6dSThomas Chou 
1688d52ea6dSThomas Chou 	  udiv_qrnnd (q0, n0, n1, n0, d0);
1698d52ea6dSThomas Chou 	  q1 = 0;
1708d52ea6dSThomas Chou 
1718d52ea6dSThomas Chou 	  /* Remainder in n0.  */
1728d52ea6dSThomas Chou 	}
1738d52ea6dSThomas Chou       else
1748d52ea6dSThomas Chou 	{
1758d52ea6dSThomas Chou 	  /* qq = NN / 0d */
1768d52ea6dSThomas Chou 
1778d52ea6dSThomas Chou 	  if (d0 == 0)
1788d52ea6dSThomas Chou 	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
1798d52ea6dSThomas Chou 
1808d52ea6dSThomas Chou 	  udiv_qrnnd (q1, n1, 0, n1, d0);
1818d52ea6dSThomas Chou 	  udiv_qrnnd (q0, n0, n1, n0, d0);
1828d52ea6dSThomas Chou 
1838d52ea6dSThomas Chou 	  /* Remainder in n0.  */
1848d52ea6dSThomas Chou 	}
1858d52ea6dSThomas Chou 
1868d52ea6dSThomas Chou       if (rp != 0)
1878d52ea6dSThomas Chou 	{
1888d52ea6dSThomas Chou 	  rr.s.low = n0;
1898d52ea6dSThomas Chou 	  rr.s.high = 0;
1908d52ea6dSThomas Chou 	  *rp = rr.ll;
1918d52ea6dSThomas Chou 	}
1928d52ea6dSThomas Chou     }
1938d52ea6dSThomas Chou 
1948d52ea6dSThomas Chou #else /* UDIV_NEEDS_NORMALIZATION */
1958d52ea6dSThomas Chou 
1968d52ea6dSThomas Chou   if (d1 == 0)
1978d52ea6dSThomas Chou     {
1988d52ea6dSThomas Chou       if (d0 > n1)
1998d52ea6dSThomas Chou 	{
2008d52ea6dSThomas Chou 	  /* 0q = nn / 0D */
2018d52ea6dSThomas Chou 
2028d52ea6dSThomas Chou 	  count_leading_zeros (bm, d0);
2038d52ea6dSThomas Chou 
2048d52ea6dSThomas Chou 	  if (bm != 0)
2058d52ea6dSThomas Chou 	    {
2068d52ea6dSThomas Chou 	      /* Normalize, i.e. make the most significant bit of the
2078d52ea6dSThomas Chou 		 denominator set.  */
2088d52ea6dSThomas Chou 
2098d52ea6dSThomas Chou 	      d0 = d0 << bm;
2108d52ea6dSThomas Chou 	      n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
2118d52ea6dSThomas Chou 	      n0 = n0 << bm;
2128d52ea6dSThomas Chou 	    }
2138d52ea6dSThomas Chou 
2148d52ea6dSThomas Chou 	  udiv_qrnnd (q0, n0, n1, n0, d0);
2158d52ea6dSThomas Chou 	  q1 = 0;
2168d52ea6dSThomas Chou 
2178d52ea6dSThomas Chou 	  /* Remainder in n0 >> bm.  */
2188d52ea6dSThomas Chou 	}
2198d52ea6dSThomas Chou       else
2208d52ea6dSThomas Chou 	{
2218d52ea6dSThomas Chou 	  /* qq = NN / 0d */
2228d52ea6dSThomas Chou 
2238d52ea6dSThomas Chou 	  if (d0 == 0)
2248d52ea6dSThomas Chou 	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
2258d52ea6dSThomas Chou 
2268d52ea6dSThomas Chou 	  count_leading_zeros (bm, d0);
2278d52ea6dSThomas Chou 
2288d52ea6dSThomas Chou 	  if (bm == 0)
2298d52ea6dSThomas Chou 	    {
2308d52ea6dSThomas Chou 	      /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
2318d52ea6dSThomas Chou 		 conclude (the most significant bit of n1 is set) /\ (the
2328d52ea6dSThomas Chou 		 leading quotient digit q1 = 1).
2338d52ea6dSThomas Chou 
2348d52ea6dSThomas Chou 		 This special case is necessary, not an optimization.
2358d52ea6dSThomas Chou 		 (Shifts counts of W_TYPE_SIZE are undefined.)  */
2368d52ea6dSThomas Chou 
2378d52ea6dSThomas Chou 	      n1 -= d0;
2388d52ea6dSThomas Chou 	      q1 = 1;
2398d52ea6dSThomas Chou 	    }
2408d52ea6dSThomas Chou 	  else
2418d52ea6dSThomas Chou 	    {
2428d52ea6dSThomas Chou 	      /* Normalize.  */
2438d52ea6dSThomas Chou 
2448d52ea6dSThomas Chou 	      b = W_TYPE_SIZE - bm;
2458d52ea6dSThomas Chou 
2468d52ea6dSThomas Chou 	      d0 = d0 << bm;
2478d52ea6dSThomas Chou 	      n2 = n1 >> b;
2488d52ea6dSThomas Chou 	      n1 = (n1 << bm) | (n0 >> b);
2498d52ea6dSThomas Chou 	      n0 = n0 << bm;
2508d52ea6dSThomas Chou 
2518d52ea6dSThomas Chou 	      udiv_qrnnd (q1, n1, n2, n1, d0);
2528d52ea6dSThomas Chou 	    }
2538d52ea6dSThomas Chou 
2548d52ea6dSThomas Chou 	  /* n1 != d0...  */
2558d52ea6dSThomas Chou 
2568d52ea6dSThomas Chou 	  udiv_qrnnd (q0, n0, n1, n0, d0);
2578d52ea6dSThomas Chou 
2588d52ea6dSThomas Chou 	  /* Remainder in n0 >> bm.  */
2598d52ea6dSThomas Chou 	}
2608d52ea6dSThomas Chou 
2618d52ea6dSThomas Chou       if (rp != 0)
2628d52ea6dSThomas Chou 	{
2638d52ea6dSThomas Chou 	  rr.s.low = n0 >> bm;
2648d52ea6dSThomas Chou 	  rr.s.high = 0;
2658d52ea6dSThomas Chou 	  *rp = rr.ll;
2668d52ea6dSThomas Chou 	}
2678d52ea6dSThomas Chou     }
2688d52ea6dSThomas Chou #endif /* UDIV_NEEDS_NORMALIZATION */
2698d52ea6dSThomas Chou 
2708d52ea6dSThomas Chou   else
2718d52ea6dSThomas Chou     {
2728d52ea6dSThomas Chou       if (d1 > n1)
2738d52ea6dSThomas Chou 	{
2748d52ea6dSThomas Chou 	  /* 00 = nn / DD */
2758d52ea6dSThomas Chou 
2768d52ea6dSThomas Chou 	  q0 = 0;
2778d52ea6dSThomas Chou 	  q1 = 0;
2788d52ea6dSThomas Chou 
2798d52ea6dSThomas Chou 	  /* Remainder in n1n0.  */
2808d52ea6dSThomas Chou 	  if (rp != 0)
2818d52ea6dSThomas Chou 	    {
2828d52ea6dSThomas Chou 	      rr.s.low = n0;
2838d52ea6dSThomas Chou 	      rr.s.high = n1;
2848d52ea6dSThomas Chou 	      *rp = rr.ll;
2858d52ea6dSThomas Chou 	    }
2868d52ea6dSThomas Chou 	}
2878d52ea6dSThomas Chou       else
2888d52ea6dSThomas Chou 	{
2898d52ea6dSThomas Chou 	  /* 0q = NN / dd */
2908d52ea6dSThomas Chou 
2918d52ea6dSThomas Chou 	  count_leading_zeros (bm, d1);
2928d52ea6dSThomas Chou 	  if (bm == 0)
2938d52ea6dSThomas Chou 	    {
2948d52ea6dSThomas Chou 	      /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
2958d52ea6dSThomas Chou 		 conclude (the most significant bit of n1 is set) /\ (the
2968d52ea6dSThomas Chou 		 quotient digit q0 = 0 or 1).
2978d52ea6dSThomas Chou 
2988d52ea6dSThomas Chou 		 This special case is necessary, not an optimization.  */
2998d52ea6dSThomas Chou 
3008d52ea6dSThomas Chou 	      /* The condition on the next line takes advantage of that
3018d52ea6dSThomas Chou 		 n1 >= d1 (true due to program flow).  */
3028d52ea6dSThomas Chou 	      if (n1 > d1 || n0 >= d0)
3038d52ea6dSThomas Chou 		{
3048d52ea6dSThomas Chou 		  q0 = 1;
3058d52ea6dSThomas Chou 		  sub_ddmmss (n1, n0, n1, n0, d1, d0);
3068d52ea6dSThomas Chou 		}
3078d52ea6dSThomas Chou 	      else
3088d52ea6dSThomas Chou 		q0 = 0;
3098d52ea6dSThomas Chou 
3108d52ea6dSThomas Chou 	      q1 = 0;
3118d52ea6dSThomas Chou 
3128d52ea6dSThomas Chou 	      if (rp != 0)
3138d52ea6dSThomas Chou 		{
3148d52ea6dSThomas Chou 		  rr.s.low = n0;
3158d52ea6dSThomas Chou 		  rr.s.high = n1;
3168d52ea6dSThomas Chou 		  *rp = rr.ll;
3178d52ea6dSThomas Chou 		}
3188d52ea6dSThomas Chou 	    }
3198d52ea6dSThomas Chou 	  else
3208d52ea6dSThomas Chou 	    {
3218d52ea6dSThomas Chou 	      UWtype m1, m0;
3228d52ea6dSThomas Chou 	      /* Normalize.  */
3238d52ea6dSThomas Chou 
3248d52ea6dSThomas Chou 	      b = W_TYPE_SIZE - bm;
3258d52ea6dSThomas Chou 
3268d52ea6dSThomas Chou 	      d1 = (d1 << bm) | (d0 >> b);
3278d52ea6dSThomas Chou 	      d0 = d0 << bm;
3288d52ea6dSThomas Chou 	      n2 = n1 >> b;
3298d52ea6dSThomas Chou 	      n1 = (n1 << bm) | (n0 >> b);
3308d52ea6dSThomas Chou 	      n0 = n0 << bm;
3318d52ea6dSThomas Chou 
3328d52ea6dSThomas Chou 	      udiv_qrnnd (q0, n1, n2, n1, d1);
3338d52ea6dSThomas Chou 	      umul_ppmm (m1, m0, q0, d0);
3348d52ea6dSThomas Chou 
3358d52ea6dSThomas Chou 	      if (m1 > n1 || (m1 == n1 && m0 > n0))
3368d52ea6dSThomas Chou 		{
3378d52ea6dSThomas Chou 		  q0--;
3388d52ea6dSThomas Chou 		  sub_ddmmss (m1, m0, m1, m0, d1, d0);
3398d52ea6dSThomas Chou 		}
3408d52ea6dSThomas Chou 
3418d52ea6dSThomas Chou 	      q1 = 0;
3428d52ea6dSThomas Chou 
3438d52ea6dSThomas Chou 	      /* Remainder in (n1n0 - m1m0) >> bm.  */
3448d52ea6dSThomas Chou 	      if (rp != 0)
3458d52ea6dSThomas Chou 		{
3468d52ea6dSThomas Chou 		  sub_ddmmss (n1, n0, n1, n0, m1, m0);
3478d52ea6dSThomas Chou 		  rr.s.low = (n1 << b) | (n0 >> bm);
3488d52ea6dSThomas Chou 		  rr.s.high = n1 >> bm;
3498d52ea6dSThomas Chou 		  *rp = rr.ll;
3508d52ea6dSThomas Chou 		}
3518d52ea6dSThomas Chou 	    }
3528d52ea6dSThomas Chou 	}
3538d52ea6dSThomas Chou     }
3548d52ea6dSThomas Chou 
3558d52ea6dSThomas Chou   const DWunion ww = {{.low = q0, .high = q1}};
3568d52ea6dSThomas Chou   return ww.ll;
3578d52ea6dSThomas Chou }
3588d52ea6dSThomas Chou 
3598d52ea6dSThomas Chou DWtype
__divdi3(DWtype u,DWtype v)3608d52ea6dSThomas Chou __divdi3 (DWtype u, DWtype v)
3618d52ea6dSThomas Chou {
3628d52ea6dSThomas Chou   word_type c = 0;
3638d52ea6dSThomas Chou   DWunion uu = {.ll = u};
3648d52ea6dSThomas Chou   DWunion vv = {.ll = v};
3658d52ea6dSThomas Chou   DWtype w;
3668d52ea6dSThomas Chou 
3678d52ea6dSThomas Chou   if (uu.s.high < 0)
3688d52ea6dSThomas Chou     c = ~c,
3698d52ea6dSThomas Chou     uu.ll = -uu.ll;
3708d52ea6dSThomas Chou   if (vv.s.high < 0)
3718d52ea6dSThomas Chou     c = ~c,
3728d52ea6dSThomas Chou     vv.ll = -vv.ll;
3738d52ea6dSThomas Chou 
3748d52ea6dSThomas Chou   w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
3758d52ea6dSThomas Chou   if (c)
3768d52ea6dSThomas Chou     w = -w;
3778d52ea6dSThomas Chou 
3788d52ea6dSThomas Chou   return w;
3798d52ea6dSThomas Chou }
3808d52ea6dSThomas Chou 
3818d52ea6dSThomas Chou DWtype
__negdi2(DWtype u)3828d52ea6dSThomas Chou __negdi2 (DWtype u)
3838d52ea6dSThomas Chou {
3848d52ea6dSThomas Chou   const DWunion uu = {.ll = u};
3858d52ea6dSThomas Chou   const DWunion w = { {.low = -uu.s.low,
3868d52ea6dSThomas Chou 		       .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } };
3878d52ea6dSThomas Chou 
3888d52ea6dSThomas Chou   return w.ll;
3898d52ea6dSThomas Chou }
3908d52ea6dSThomas Chou 
3918d52ea6dSThomas Chou 
3928d52ea6dSThomas Chou DWtype
__muldi3(DWtype u,DWtype v)3938d52ea6dSThomas Chou __muldi3 (DWtype u, DWtype v)
3948d52ea6dSThomas Chou {
3958d52ea6dSThomas Chou   const DWunion uu = {.ll = u};
3968d52ea6dSThomas Chou   const DWunion vv = {.ll = v};
3978d52ea6dSThomas Chou   DWunion  w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)};
3988d52ea6dSThomas Chou 
3998d52ea6dSThomas Chou   w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
4008d52ea6dSThomas Chou   + (UWtype) uu.s.high * (UWtype) vv.s.low);
4018d52ea6dSThomas Chou 
4028d52ea6dSThomas Chou   return w.ll;
4038d52ea6dSThomas Chou }
4048d52ea6dSThomas Chou 
4058d52ea6dSThomas Chou DWtype
__moddi3(DWtype u,DWtype v)4068d52ea6dSThomas Chou __moddi3 (DWtype u, DWtype v)
4078d52ea6dSThomas Chou {
4088d52ea6dSThomas Chou   word_type c = 0;
4098d52ea6dSThomas Chou   DWunion uu = {.ll = u};
4108d52ea6dSThomas Chou   DWunion vv = {.ll = v};
4118d52ea6dSThomas Chou   DWtype w;
4128d52ea6dSThomas Chou 
4138d52ea6dSThomas Chou   if (uu.s.high < 0)
4148d52ea6dSThomas Chou     c = ~c,
4158d52ea6dSThomas Chou     uu.ll = -uu.ll;
4168d52ea6dSThomas Chou   if (vv.s.high < 0)
4178d52ea6dSThomas Chou     vv.ll = -vv.ll;
4188d52ea6dSThomas Chou 
4198d52ea6dSThomas Chou   (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
4208d52ea6dSThomas Chou   if (c)
4218d52ea6dSThomas Chou     w = -w;
4228d52ea6dSThomas Chou 
4238d52ea6dSThomas Chou   return w;
4248d52ea6dSThomas Chou }
4258d52ea6dSThomas Chou 
4268d52ea6dSThomas Chou word_type
__ucmpdi2(DWtype a,DWtype b)4278d52ea6dSThomas Chou __ucmpdi2 (DWtype a, DWtype b)
4288d52ea6dSThomas Chou {
4298d52ea6dSThomas Chou   const DWunion au = {.ll = a};
4308d52ea6dSThomas Chou   const DWunion bu = {.ll = b};
4318d52ea6dSThomas Chou 
4328d52ea6dSThomas Chou   if ((UWtype) au.s.high < (UWtype) bu.s.high)
4338d52ea6dSThomas Chou     return 0;
4348d52ea6dSThomas Chou   else if ((UWtype) au.s.high > (UWtype) bu.s.high)
4358d52ea6dSThomas Chou     return 2;
4368d52ea6dSThomas Chou   if ((UWtype) au.s.low < (UWtype) bu.s.low)
4378d52ea6dSThomas Chou     return 0;
4388d52ea6dSThomas Chou   else if ((UWtype) au.s.low > (UWtype) bu.s.low)
4398d52ea6dSThomas Chou     return 2;
4408d52ea6dSThomas Chou   return 1;
4418d52ea6dSThomas Chou }
4428d52ea6dSThomas Chou 
4438d52ea6dSThomas Chou 
4448d52ea6dSThomas Chou UDWtype
__udivdi3(UDWtype n,UDWtype d)4458d52ea6dSThomas Chou __udivdi3 (UDWtype n, UDWtype d)
4468d52ea6dSThomas Chou {
4478d52ea6dSThomas Chou   return __udivmoddi4 (n, d, (UDWtype *) 0);
4488d52ea6dSThomas Chou }
4498d52ea6dSThomas Chou 
4508d52ea6dSThomas Chou UDWtype
__umoddi3(UDWtype u,UDWtype v)4518d52ea6dSThomas Chou __umoddi3 (UDWtype u, UDWtype v)
4528d52ea6dSThomas Chou {
4538d52ea6dSThomas Chou   UDWtype w;
4548d52ea6dSThomas Chou   (void) __udivmoddi4 (u, v, &w);
4558d52ea6dSThomas Chou 
4568d52ea6dSThomas Chou   return w;
4578d52ea6dSThomas Chou }
4588d52ea6dSThomas Chou 
4598d52ea6dSThomas Chou static USItype
udivmodsi4(USItype num,USItype den,word_type modwanted)4608d52ea6dSThomas Chou udivmodsi4(USItype num, USItype den, word_type modwanted)
4618d52ea6dSThomas Chou {
4628d52ea6dSThomas Chou   USItype bit = 1;
4638d52ea6dSThomas Chou   USItype res = 0;
4648d52ea6dSThomas Chou 
4658d52ea6dSThomas Chou   while (den < num && bit && !(den & (1L<<31)))
4668d52ea6dSThomas Chou     {
4678d52ea6dSThomas Chou       den <<=1;
4688d52ea6dSThomas Chou       bit <<=1;
4698d52ea6dSThomas Chou     }
4708d52ea6dSThomas Chou   while (bit)
4718d52ea6dSThomas Chou     {
4728d52ea6dSThomas Chou       if (num >= den)
4738d52ea6dSThomas Chou 	{
4748d52ea6dSThomas Chou 	  num -= den;
4758d52ea6dSThomas Chou 	  res |= bit;
4768d52ea6dSThomas Chou 	}
4778d52ea6dSThomas Chou       bit >>=1;
4788d52ea6dSThomas Chou       den >>=1;
4798d52ea6dSThomas Chou     }
4808d52ea6dSThomas Chou   if (modwanted) return num;
4818d52ea6dSThomas Chou   return res;
4828d52ea6dSThomas Chou }
4838d52ea6dSThomas Chou 
4848d52ea6dSThomas Chou SItype
__divsi3(SItype a,SItype b)4858d52ea6dSThomas Chou __divsi3 (SItype a, SItype b)
4868d52ea6dSThomas Chou {
4878d52ea6dSThomas Chou   word_type neg = 0;
4888d52ea6dSThomas Chou   SItype res;
4898d52ea6dSThomas Chou 
4908d52ea6dSThomas Chou   if (a < 0)
4918d52ea6dSThomas Chou     {
4928d52ea6dSThomas Chou       a = -a;
4938d52ea6dSThomas Chou       neg = !neg;
4948d52ea6dSThomas Chou     }
4958d52ea6dSThomas Chou 
4968d52ea6dSThomas Chou   if (b < 0)
4978d52ea6dSThomas Chou     {
4988d52ea6dSThomas Chou       b = -b;
4998d52ea6dSThomas Chou       neg = !neg;
5008d52ea6dSThomas Chou     }
5018d52ea6dSThomas Chou 
5028d52ea6dSThomas Chou   res = udivmodsi4 (a, b, 0);
5038d52ea6dSThomas Chou 
5048d52ea6dSThomas Chou   if (neg)
5058d52ea6dSThomas Chou     res = -res;
5068d52ea6dSThomas Chou 
5078d52ea6dSThomas Chou   return res;
5088d52ea6dSThomas Chou }
5098d52ea6dSThomas Chou 
5108d52ea6dSThomas Chou 
5118d52ea6dSThomas Chou SItype
__udivsi3(SItype a,SItype b)5128d52ea6dSThomas Chou __udivsi3 (SItype a, SItype b)
5138d52ea6dSThomas Chou {
5148d52ea6dSThomas Chou   return udivmodsi4 (a, b, 0);
5158d52ea6dSThomas Chou }
5168d52ea6dSThomas Chou 
5178d52ea6dSThomas Chou 
5188d52ea6dSThomas Chou SItype
__modsi3(SItype a,SItype b)5198d52ea6dSThomas Chou __modsi3 (SItype a, SItype b)
5208d52ea6dSThomas Chou {
5218d52ea6dSThomas Chou   word_type neg = 0;
5228d52ea6dSThomas Chou   SItype res;
5238d52ea6dSThomas Chou 
5248d52ea6dSThomas Chou   if (a < 0)
5258d52ea6dSThomas Chou     {
5268d52ea6dSThomas Chou       a = -a;
5278d52ea6dSThomas Chou       neg = 1;
5288d52ea6dSThomas Chou     }
5298d52ea6dSThomas Chou 
5308d52ea6dSThomas Chou   if (b < 0)
5318d52ea6dSThomas Chou     b = -b;
5328d52ea6dSThomas Chou 
5338d52ea6dSThomas Chou   res = udivmodsi4 (a, b, 1);
5348d52ea6dSThomas Chou 
5358d52ea6dSThomas Chou   if (neg)
5368d52ea6dSThomas Chou     res = -res;
5378d52ea6dSThomas Chou 
5388d52ea6dSThomas Chou   return res;
5398d52ea6dSThomas Chou }
5408d52ea6dSThomas Chou 
5418d52ea6dSThomas Chou SItype
__mulsi3(SItype a,SItype b)5428d52ea6dSThomas Chou __mulsi3 (SItype a, SItype b)
5438d52ea6dSThomas Chou {
5448d52ea6dSThomas Chou   SItype res = 0;
5458d52ea6dSThomas Chou   USItype cnt = a;
5468d52ea6dSThomas Chou 
5478d52ea6dSThomas Chou   while (cnt)
5488d52ea6dSThomas Chou     {
5498d52ea6dSThomas Chou       if (cnt & 1)
5508d52ea6dSThomas Chou 	{
5518d52ea6dSThomas Chou 	  res += b;
5528d52ea6dSThomas Chou 	}
5538d52ea6dSThomas Chou       b <<= 1;
5548d52ea6dSThomas Chou       cnt >>= 1;
5558d52ea6dSThomas Chou     }
5568d52ea6dSThomas Chou 
5578d52ea6dSThomas Chou   return res;
5588d52ea6dSThomas Chou }
5598d52ea6dSThomas Chou 
5608d52ea6dSThomas Chou SItype
__umodsi3(SItype a,SItype b)5618d52ea6dSThomas Chou __umodsi3 (SItype a, SItype b)
5628d52ea6dSThomas Chou 
5638d52ea6dSThomas Chou {
5648d52ea6dSThomas Chou   return udivmodsi4 (a, b, 1);
5658d52ea6dSThomas Chou }
5668d52ea6dSThomas Chou 
5678d52ea6dSThomas Chou int
__gcc_bcmp(const unsigned char * s1,const unsigned char * s2,unsigned long size)5688d52ea6dSThomas Chou __gcc_bcmp (const unsigned char *s1, const unsigned char *s2, unsigned long size)
5698d52ea6dSThomas Chou {
5708d52ea6dSThomas Chou   while (size > 0)
5718d52ea6dSThomas Chou     {
5728d52ea6dSThomas Chou       const unsigned char c1 = *s1++, c2 = *s2++;
5738d52ea6dSThomas Chou       if (c1 != c2)
5748d52ea6dSThomas Chou 	return c1 - c2;
5758d52ea6dSThomas Chou       size--;
5768d52ea6dSThomas Chou     }
5778d52ea6dSThomas Chou   return 0;
5788d52ea6dSThomas Chou }
579