xref: /rk3399_rockchip-uboot/arch/nios2/lib/longlong.h (revision c4a7ece02046f647019cc0aaddf530833a8db29c)
18d52ea6dSThomas Chou /* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
28d52ea6dSThomas Chou    Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2004,
38d52ea6dSThomas Chou    2005  Free Software Foundation, Inc.
48d52ea6dSThomas Chou 
51a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
6*1a05b5f9SThomas Chou  */
78d52ea6dSThomas Chou 
88d52ea6dSThomas Chou /* You have to define the following before including this file:
98d52ea6dSThomas Chou 
108d52ea6dSThomas Chou    UWtype -- An unsigned type, default type for operations (typically a "word")
118d52ea6dSThomas Chou    UHWtype -- An unsigned type, at least half the size of UWtype.
128d52ea6dSThomas Chou    UDWtype -- An unsigned type, at least twice as large a UWtype
138d52ea6dSThomas Chou    W_TYPE_SIZE -- size in bits of UWtype
148d52ea6dSThomas Chou 
158d52ea6dSThomas Chou    UQItype -- Unsigned 8 bit type.
168d52ea6dSThomas Chou    SItype, USItype -- Signed and unsigned 32 bit types.
178d52ea6dSThomas Chou    DItype, UDItype -- Signed and unsigned 64 bit types.
188d52ea6dSThomas Chou 
198d52ea6dSThomas Chou    On a 32 bit machine UWtype should typically be USItype;
208d52ea6dSThomas Chou    on a 64 bit machine, UWtype should typically be UDItype.  */
218d52ea6dSThomas Chou 
228d52ea6dSThomas Chou #define __BITS4 (W_TYPE_SIZE / 4)
238d52ea6dSThomas Chou #define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
248d52ea6dSThomas Chou #define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
258d52ea6dSThomas Chou #define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
268d52ea6dSThomas Chou 
278d52ea6dSThomas Chou #ifndef W_TYPE_SIZE
288d52ea6dSThomas Chou #define W_TYPE_SIZE	32
298d52ea6dSThomas Chou #define UWtype		USItype
308d52ea6dSThomas Chou #define UHWtype		USItype
318d52ea6dSThomas Chou #define UDWtype		UDItype
328d52ea6dSThomas Chou #endif
338d52ea6dSThomas Chou 
348d52ea6dSThomas Chou extern const UQItype __clz_tab[256];
358d52ea6dSThomas Chou 
368d52ea6dSThomas Chou /* Define auxiliary asm macros.
378d52ea6dSThomas Chou 
388d52ea6dSThomas Chou    1) umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two
398d52ea6dSThomas Chou    UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype
408d52ea6dSThomas Chou    word product in HIGH_PROD and LOW_PROD.
418d52ea6dSThomas Chou 
428d52ea6dSThomas Chou    2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a
438d52ea6dSThomas Chou    UDWtype product.  This is just a variant of umul_ppmm.
448d52ea6dSThomas Chou 
458d52ea6dSThomas Chou    3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
468d52ea6dSThomas Chou    denominator) divides a UDWtype, composed by the UWtype integers
478d52ea6dSThomas Chou    HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
488d52ea6dSThomas Chou    in QUOTIENT and the remainder in REMAINDER.  HIGH_NUMERATOR must be less
498d52ea6dSThomas Chou    than DENOMINATOR for correct operation.  If, in addition, the most
508d52ea6dSThomas Chou    significant bit of DENOMINATOR must be 1, then the pre-processor symbol
518d52ea6dSThomas Chou    UDIV_NEEDS_NORMALIZATION is defined to 1.
528d52ea6dSThomas Chou 
538d52ea6dSThomas Chou    4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
548d52ea6dSThomas Chou    denominator).  Like udiv_qrnnd but the numbers are signed.  The quotient
558d52ea6dSThomas Chou    is rounded towards 0.
568d52ea6dSThomas Chou 
578d52ea6dSThomas Chou    5) count_leading_zeros(count, x) counts the number of zero-bits from the
588d52ea6dSThomas Chou    msb to the first nonzero bit in the UWtype X.  This is the number of
598d52ea6dSThomas Chou    steps X needs to be shifted left to set the msb.  Undefined for X == 0,
608d52ea6dSThomas Chou    unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value.
618d52ea6dSThomas Chou 
628d52ea6dSThomas Chou    6) count_trailing_zeros(count, x) like count_leading_zeros, but counts
638d52ea6dSThomas Chou    from the least significant end.
648d52ea6dSThomas Chou 
658d52ea6dSThomas Chou    7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
668d52ea6dSThomas Chou    high_addend_2, low_addend_2) adds two UWtype integers, composed by
678d52ea6dSThomas Chou    HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
688d52ea6dSThomas Chou    respectively.  The result is placed in HIGH_SUM and LOW_SUM.  Overflow
698d52ea6dSThomas Chou    (i.e. carry out) is not stored anywhere, and is lost.
708d52ea6dSThomas Chou 
718d52ea6dSThomas Chou    8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
728d52ea6dSThomas Chou    high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
738d52ea6dSThomas Chou    composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
748d52ea6dSThomas Chou    LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
758d52ea6dSThomas Chou    and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
768d52ea6dSThomas Chou    and is lost.
778d52ea6dSThomas Chou 
788d52ea6dSThomas Chou    If any of these macros are left undefined for a particular CPU,
798d52ea6dSThomas Chou    C macros are used.  */
808d52ea6dSThomas Chou 
818d52ea6dSThomas Chou /* The CPUs come in alphabetical order below.
828d52ea6dSThomas Chou 
838d52ea6dSThomas Chou    Please add support for more CPUs here, or improve the current support
848d52ea6dSThomas Chou    for the CPUs below!
858d52ea6dSThomas Chou    (E.g. WE32100, IBM360.)  */
868d52ea6dSThomas Chou 
878d52ea6dSThomas Chou /* Snipped per CPU support */
888d52ea6dSThomas Chou 
898d52ea6dSThomas Chou /* If this machine has no inline assembler, use C macros.  */
908d52ea6dSThomas Chou 
918d52ea6dSThomas Chou #if !defined (add_ssaaaa)
928d52ea6dSThomas Chou #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
938d52ea6dSThomas Chou   do {									\
948d52ea6dSThomas Chou     UWtype __x;								\
958d52ea6dSThomas Chou     __x = (al) + (bl);							\
968d52ea6dSThomas Chou     (sh) = (ah) + (bh) + (__x < (al));					\
978d52ea6dSThomas Chou     (sl) = __x;								\
988d52ea6dSThomas Chou   } while (0)
998d52ea6dSThomas Chou #endif
1008d52ea6dSThomas Chou 
1018d52ea6dSThomas Chou #if !defined (sub_ddmmss)
1028d52ea6dSThomas Chou #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
1038d52ea6dSThomas Chou   do {									\
1048d52ea6dSThomas Chou     UWtype __x;								\
1058d52ea6dSThomas Chou     __x = (al) - (bl);							\
1068d52ea6dSThomas Chou     (sh) = (ah) - (bh) - (__x > (al));					\
1078d52ea6dSThomas Chou     (sl) = __x;								\
1088d52ea6dSThomas Chou   } while (0)
1098d52ea6dSThomas Chou #endif
1108d52ea6dSThomas Chou 
1118d52ea6dSThomas Chou /* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of
1128d52ea6dSThomas Chou    smul_ppmm.  */
1138d52ea6dSThomas Chou #if !defined (umul_ppmm) && defined (smul_ppmm)
1148d52ea6dSThomas Chou #define umul_ppmm(w1, w0, u, v)						\
1158d52ea6dSThomas Chou   do {									\
1168d52ea6dSThomas Chou     UWtype __w1;							\
1178d52ea6dSThomas Chou     UWtype __xm0 = (u), __xm1 = (v);					\
1188d52ea6dSThomas Chou     smul_ppmm (__w1, w0, __xm0, __xm1);					\
1198d52ea6dSThomas Chou     (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1)		\
1208d52ea6dSThomas Chou 		+ (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0);		\
1218d52ea6dSThomas Chou   } while (0)
1228d52ea6dSThomas Chou #endif
1238d52ea6dSThomas Chou 
1248d52ea6dSThomas Chou /* If we still don't have umul_ppmm, define it using plain C.  */
1258d52ea6dSThomas Chou #if !defined (umul_ppmm)
1268d52ea6dSThomas Chou #define umul_ppmm(w1, w0, u, v)						\
1278d52ea6dSThomas Chou   do {									\
1288d52ea6dSThomas Chou     UWtype __x0, __x1, __x2, __x3;					\
1298d52ea6dSThomas Chou     UHWtype __ul, __vl, __uh, __vh;					\
1308d52ea6dSThomas Chou 									\
1318d52ea6dSThomas Chou     __ul = __ll_lowpart (u);						\
1328d52ea6dSThomas Chou     __uh = __ll_highpart (u);						\
1338d52ea6dSThomas Chou     __vl = __ll_lowpart (v);						\
1348d52ea6dSThomas Chou     __vh = __ll_highpart (v);						\
1358d52ea6dSThomas Chou 									\
1368d52ea6dSThomas Chou     __x0 = (UWtype) __ul * __vl;					\
1378d52ea6dSThomas Chou     __x1 = (UWtype) __ul * __vh;					\
1388d52ea6dSThomas Chou     __x2 = (UWtype) __uh * __vl;					\
1398d52ea6dSThomas Chou     __x3 = (UWtype) __uh * __vh;					\
1408d52ea6dSThomas Chou 									\
1418d52ea6dSThomas Chou     __x1 += __ll_highpart (__x0);/* this can't give carry */		\
1428d52ea6dSThomas Chou     __x1 += __x2;		/* but this indeed can */		\
1438d52ea6dSThomas Chou     if (__x1 < __x2)		/* did we get it? */			\
1448d52ea6dSThomas Chou       __x3 += __ll_B;		/* yes, add it in the proper pos.  */	\
1458d52ea6dSThomas Chou 									\
1468d52ea6dSThomas Chou     (w1) = __x3 + __ll_highpart (__x1);					\
1478d52ea6dSThomas Chou     (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);		\
1488d52ea6dSThomas Chou   } while (0)
1498d52ea6dSThomas Chou #endif
1508d52ea6dSThomas Chou 
1518d52ea6dSThomas Chou #if !defined (__umulsidi3)
1528d52ea6dSThomas Chou #define __umulsidi3(u, v) \
1538d52ea6dSThomas Chou   ({DWunion __w;							\
1548d52ea6dSThomas Chou     umul_ppmm (__w.s.high, __w.s.low, u, v);				\
1558d52ea6dSThomas Chou     __w.ll; })
1568d52ea6dSThomas Chou #endif
1578d52ea6dSThomas Chou 
1588d52ea6dSThomas Chou /* Define this unconditionally, so it can be used for debugging.  */
1598d52ea6dSThomas Chou #define __udiv_qrnnd_c(q, r, n1, n0, d) \
1608d52ea6dSThomas Chou   do {									\
1618d52ea6dSThomas Chou     UWtype __d1, __d0, __q1, __q0;					\
1628d52ea6dSThomas Chou     UWtype __r1, __r0, __m;						\
1638d52ea6dSThomas Chou     __d1 = __ll_highpart (d);						\
1648d52ea6dSThomas Chou     __d0 = __ll_lowpart (d);						\
1658d52ea6dSThomas Chou 									\
1668d52ea6dSThomas Chou     __r1 = (n1) % __d1;							\
1678d52ea6dSThomas Chou     __q1 = (n1) / __d1;							\
1688d52ea6dSThomas Chou     __m = (UWtype) __q1 * __d0;						\
1698d52ea6dSThomas Chou     __r1 = __r1 * __ll_B | __ll_highpart (n0);				\
1708d52ea6dSThomas Chou     if (__r1 < __m)							\
1718d52ea6dSThomas Chou       {									\
1728d52ea6dSThomas Chou 	__q1--, __r1 += (d);						\
1738d52ea6dSThomas Chou 	if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
1748d52ea6dSThomas Chou 	  if (__r1 < __m)						\
1758d52ea6dSThomas Chou 	    __q1--, __r1 += (d);					\
1768d52ea6dSThomas Chou       }									\
1778d52ea6dSThomas Chou     __r1 -= __m;							\
1788d52ea6dSThomas Chou 									\
1798d52ea6dSThomas Chou     __r0 = __r1 % __d1;							\
1808d52ea6dSThomas Chou     __q0 = __r1 / __d1;							\
1818d52ea6dSThomas Chou     __m = (UWtype) __q0 * __d0;						\
1828d52ea6dSThomas Chou     __r0 = __r0 * __ll_B | __ll_lowpart (n0);				\
1838d52ea6dSThomas Chou     if (__r0 < __m)							\
1848d52ea6dSThomas Chou       {									\
1858d52ea6dSThomas Chou 	__q0--, __r0 += (d);						\
1868d52ea6dSThomas Chou 	if (__r0 >= (d))						\
1878d52ea6dSThomas Chou 	  if (__r0 < __m)						\
1888d52ea6dSThomas Chou 	    __q0--, __r0 += (d);					\
1898d52ea6dSThomas Chou       }									\
1908d52ea6dSThomas Chou     __r0 -= __m;							\
1918d52ea6dSThomas Chou 									\
1928d52ea6dSThomas Chou     (q) = (UWtype) __q1 * __ll_B | __q0;				\
1938d52ea6dSThomas Chou     (r) = __r0;								\
1948d52ea6dSThomas Chou   } while (0)
1958d52ea6dSThomas Chou 
1968d52ea6dSThomas Chou /* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through
1978d52ea6dSThomas Chou    __udiv_w_sdiv (defined in libgcc or elsewhere).  */
1988d52ea6dSThomas Chou #if !defined (udiv_qrnnd) && defined (sdiv_qrnnd)
1998d52ea6dSThomas Chou #define udiv_qrnnd(q, r, nh, nl, d) \
2008d52ea6dSThomas Chou   do {									\
2018d52ea6dSThomas Chou     USItype __r;							\
2028d52ea6dSThomas Chou     (q) = __udiv_w_sdiv (&__r, nh, nl, d);				\
2038d52ea6dSThomas Chou     (r) = __r;								\
2048d52ea6dSThomas Chou   } while (0)
2058d52ea6dSThomas Chou #endif
2068d52ea6dSThomas Chou 
2078d52ea6dSThomas Chou /* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c.  */
2088d52ea6dSThomas Chou #if !defined (udiv_qrnnd)
2098d52ea6dSThomas Chou #define UDIV_NEEDS_NORMALIZATION 1
2108d52ea6dSThomas Chou #define udiv_qrnnd __udiv_qrnnd_c
2118d52ea6dSThomas Chou #endif
2128d52ea6dSThomas Chou 
2138d52ea6dSThomas Chou #if !defined (count_leading_zeros)
2148d52ea6dSThomas Chou #define count_leading_zeros(count, x) \
2158d52ea6dSThomas Chou   do {									\
2168d52ea6dSThomas Chou     UWtype __xr = (x);							\
2178d52ea6dSThomas Chou     UWtype __a;								\
2188d52ea6dSThomas Chou 									\
2198d52ea6dSThomas Chou     if (W_TYPE_SIZE <= 32)						\
2208d52ea6dSThomas Chou       {									\
2218d52ea6dSThomas Chou 	__a = __xr < ((UWtype)1<<2*__BITS4)				\
2228d52ea6dSThomas Chou 	  ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4)			\
2238d52ea6dSThomas Chou 	  : (__xr < ((UWtype)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);	\
2248d52ea6dSThomas Chou       }									\
2258d52ea6dSThomas Chou     else								\
2268d52ea6dSThomas Chou       {									\
2278d52ea6dSThomas Chou 	for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8)			\
2288d52ea6dSThomas Chou 	  if (((__xr >> __a) & 0xff) != 0)				\
2298d52ea6dSThomas Chou 	    break;							\
2308d52ea6dSThomas Chou       }									\
2318d52ea6dSThomas Chou 									\
2328d52ea6dSThomas Chou     (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a);		\
2338d52ea6dSThomas Chou   } while (0)
2348d52ea6dSThomas Chou #define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE
2358d52ea6dSThomas Chou #endif
2368d52ea6dSThomas Chou 
2378d52ea6dSThomas Chou #if !defined (count_trailing_zeros)
2388d52ea6dSThomas Chou /* Define count_trailing_zeros using count_leading_zeros.  The latter might be
2398d52ea6dSThomas Chou    defined in asm, but if it is not, the C version above is good enough.  */
2408d52ea6dSThomas Chou #define count_trailing_zeros(count, x) \
2418d52ea6dSThomas Chou   do {									\
2428d52ea6dSThomas Chou     UWtype __ctz_x = (x);						\
2438d52ea6dSThomas Chou     UWtype __ctz_c;							\
2448d52ea6dSThomas Chou     count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x);			\
2458d52ea6dSThomas Chou     (count) = W_TYPE_SIZE - 1 - __ctz_c;				\
2468d52ea6dSThomas Chou   } while (0)
2478d52ea6dSThomas Chou #endif
2488d52ea6dSThomas Chou 
2498d52ea6dSThomas Chou #ifndef UDIV_NEEDS_NORMALIZATION
2508d52ea6dSThomas Chou #define UDIV_NEEDS_NORMALIZATION 0
2518d52ea6dSThomas Chou #endif
252