📄 longlong.h
字号:
/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *//* You have to define the following before including this file: UWtype -- An unsigned type, default type for operations (typically a "word") UHWtype -- An unsigned type, at least half the size of UWtype. UDWtype -- An unsigned type, at least twice as large a UWtype W_TYPE_SIZE -- size in bits of UWtype UQItype -- Unsigned 8 bit type. SItype, USItype -- Signed and unsigned 32 bit types. DItype, UDItype -- Signed and unsigned 64 bit types. On a 32 bit machine UWtype should typically be USItype; on a 64 bit machine, UWtype should typically be UDItype.*/#define __BITS4 (W_TYPE_SIZE / 4)#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))#ifndef W_TYPE_SIZE#define W_TYPE_SIZE 32#define UWtype USItype#define UHWtype USItype#define UDWtype UDItype#endif/* Define auxiliary asm macros. 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype word product in HIGH_PROD and LOW_PROD. 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a UDWtype product. This is just a variant of umul_ppmm. 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, denominator) divides a UDWtype, composed by the UWtype integers HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less than DENOMINATOR for correct operation. If, in addition, the most significant bit of DENOMINATOR must be 1, then the pre-processor symbol UDIV_NEEDS_NORMALIZATION is defined to 1. 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, denominator). Like udiv_qrnnd but the numbers are signed. The quotient is rounded towards 0. 5) count_leading_zeros(count, x) counts the number of zero-bits from the msb to the first nonzero bit in the UWtype X. This is the number of steps X needs to be shifted left to set the msb. Undefined for X == 0, unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts from the least significant end. 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, high_addend_2, low_addend_2) adds two UWtype integers, composed by HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow (i.e. carry out) is not stored anywhere, and is lost. 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, and is lost. If any of these macros are left undefined for a particular CPU, C macros are used. *//* The CPUs come in alphabetical order below. Please add support for more CPUs here, or improve the current support for the CPUs below! (E.g. WE32100, IBM360.) */#if defined (__GNUC__) && !defined (NO_ASM)/* We sometimes need to clobber "cc" with gcc2, but that would not be understood by gcc1. Use cpp to avoid major code duplication. */#if __GNUC__ < 2#define __CLOBBER_CC#define __AND_CLOBBER_CC#else /* __GNUC__ >= 2 */#define __CLOBBER_CC : "cc"#define __AND_CLOBBER_CC , "cc"#endif /* __GNUC__ < 2 */#if defined (__alpha) && W_TYPE_SIZE == 64#define umul_ppmm(ph, pl, m0, m1) \ do { \ UDItype __m0 = (m0), __m1 = (m1); \ __asm__ ("umulh %r1,%2,%0" \ : "=r" ((UDItype) ph) \ : "%rJ" (__m0), \ "rI" (__m1)); \ (pl) = __m0 * __m1; \ } while (0)#define UMUL_TIME 46#ifndef LONGLONG_STANDALONE#define udiv_qrnnd(q, r, n1, n0, d) \ do { UDItype __r; \ (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ (r) = __r; \ } while (0)extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype);#define UDIV_TIME 220#endif /* LONGLONG_STANDALONE */#ifdef __alpha_cix__#define count_leading_zeros(COUNT,X) \ __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X))#define count_trailing_zeros(COUNT,X) \ __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X))#define COUNT_LEADING_ZEROS_0 64#elseextern const UQItype __clz_tab[];#define count_leading_zeros(COUNT,X) \ do { \ UDItype __xr = (X), __t, __a; \ __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \ __a = __clz_tab[__t ^ 0xff] - 1; \ __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \ (COUNT) = 64 - (__clz_tab[__t] + __a*8); \ } while (0)#define count_trailing_zeros(COUNT,X) \ do { \ UDItype __xr = (X), __t, __a; \ __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \ __t = ~__t & -~__t; \ __a = ((__t & 0xCC) != 0) * 2; \ __a += ((__t & 0xF0) != 0) * 4; \ __a += ((__t & 0xAA) != 0); \ __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \ __a <<= 3; \ __t &= -__t; \ __a += ((__t & 0xCC) != 0) * 2; \ __a += ((__t & 0xF0) != 0) * 4; \ __a += ((__t & 0xAA) != 0); \ (COUNT) = __a; \ } while (0)#endif /* __alpha_cix__ */#endif /* __alpha */#if defined (__arc__) && W_TYPE_SIZE == 32#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ : "%r" ((USItype) (ah)), \ "rIJ" ((USItype) (bh)), \ "%r" ((USItype) (al)), \ "rIJ" ((USItype) (bl)))#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ : "r" ((USItype) (ah)), \ "rIJ" ((USItype) (bh)), \ "r" ((USItype) (al)), \ "rIJ" ((USItype) (bl)))/* Call libgcc routine. */#define umul_ppmm(w1, w0, u, v) \do { \ DWunion __w; \ __w.ll = __umulsidi3 (u, v); \ w1 = __w.s.high; \ w0 = __w.s.low; \} while (0)#define __umulsidi3 __umulsidi3UDItype __umulsidi3 (USItype, USItype);#endif#if defined (__arm__) && W_TYPE_SIZE == 32#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ : "%r" ((USItype) (ah)), \ "rI" ((USItype) (bh)), \ "%r" ((USItype) (al)), \ "rI" ((USItype) (bl)))#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ : "r" ((USItype) (ah)), \ "rI" ((USItype) (bh)), \ "r" ((USItype) (al)), \ "rI" ((USItype) (bl)))#define umul_ppmm(xh, xl, a, b) \{register USItype __t0, __t1, __t2; \ __asm__ ("%@ Inlined umul_ppmm\n" \ " mov %2, %5, lsr #16\n" \ " mov %0, %6, lsr #16\n" \ " bic %3, %5, %2, lsl #16\n" \ " bic %4, %6, %0, lsl #16\n" \ " mul %1, %3, %4\n" \ " mul %4, %2, %4\n" \ " mul %3, %0, %3\n" \ " mul %0, %2, %0\n" \ " adds %3, %4, %3\n" \ " addcs %0, %0, #65536\n" \ " adds %1, %1, %3, lsl #16\n" \ " adc %0, %0, %3, lsr #16" \ : "=&r" ((USItype) (xh)), \ "=r" ((USItype) (xl)), \ "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ : "r" ((USItype) (a)), \ "r" ((USItype) (b)));}#define UMUL_TIME 20#define UDIV_TIME 100#endif /* __arm__ */#if defined (__hppa) && W_TYPE_SIZE == 32#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ : "%rM" ((USItype) (ah)), \ "rM" ((USItype) (bh)), \ "%rM" ((USItype) (al)), \ "rM" ((USItype) (bl)))#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \ : "=r" ((USItype) (sh)), \ "=&r" ((USItype) (sl)) \ : "rM" ((USItype) (ah)), \ "rM" ((USItype) (bh)), \ "rM" ((USItype) (al)), \ "rM" ((USItype) (bl)))#if defined (_PA_RISC1_1)#define umul_ppmm(w1, w0, u, v) \ do { \ union \ { \ UDItype __f; \ struct {USItype __w1, __w0;} __w1w0; \ } __t; \ __asm__ ("xmpyu %1,%2,%0" \ : "=x" (__t.__f) \ : "x" ((USItype) (u)), \ "x" ((USItype) (v))); \ (w1) = __t.__w1w0.__w1; \ (w0) = __t.__w1w0.__w0; \ } while (0)#define UMUL_TIME 8#else#define UMUL_TIME 30#endif#define UDIV_TIME 40#define count_leading_zeros(count, x) \ do { \ USItype __tmp; \ __asm__ ( \ "ldi 1,%0\n" \" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n"\" ldo 16(%0),%0 ; Yes. Perform add.\n" \" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n"\" ldo 8(%0),%0 ; Yes. Perform add.\n" \" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n"\" ldo 4(%0),%0 ; Yes. Perform add.\n" \" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n"\" ldo 2(%0),%0 ; Yes. Perform add.\n" \" extru %1,30,1,%1 ; Extract bit 1.\n" \" sub %0,%1,%0 ; Subtract it.\n" \ : "=r" (count), "=r" (__tmp) : "1" (x)); \ } while (0)#endif#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32#define umul_ppmm(xh, xl, m0, m1) \ do { \ union {UDItype __ll; \ struct {USItype __h, __l;} __i; \ } __xx; \ USItype __m0 = (m0), __m1 = (m1); \ __asm__ ("mr %0,%3" \ : "=r" (__xx.__i.__h), \ "=r" (__xx.__i.__l) \ : "%1" (__m0), \ "r" (__m1)); \ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ (xh) += ((((SItype) __m0 >> 31) & __m1) \ + (((SItype) __m1 >> 31) & __m0)); \ } while (0)#define smul_ppmm(xh, xl, m0, m1) \ do { \ union {DItype __ll; \ struct {USItype __h, __l;} __i; \ } __xx; \ __asm__ ("mr %0,%3" \ : "=r" (__xx.__i.__h), \ "=r" (__xx.__i.__l) \ : "%1" (m0), \ "r" (m1)); \ (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ } while (0)#define sdiv_qrnnd(q, r, n1, n0, d) \ do { \ union {DItype __ll; \ struct {USItype __h, __l;} __i; \ } __xx; \ __xx.__i.__h = n1; __xx.__i.__l = n0; \ __asm__ ("dr %0,%2" \ : "=r" (__xx.__ll) \ : "0" (__xx.__ll), "r" (d)); \ (q) = __xx.__i.__l; (r) = __xx.__i.__h; \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -