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