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