home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 5
/
FreshFish_July-August1994.bin
/
bbs
/
gnu
/
gmp-1.3.2-src.lha
/
src
/
amiga
/
gmp-1.3.2
/
longlong.h
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-07
|
33KB
|
1,028 lines
/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
This definition file is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2, or (at your option) any later version.
This definition file 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef LONG_TYPE_SIZE
#ifdef BITS_PER_LONGINT
#define LONG_TYPE_SIZE BITS_PER_LONGINT
#else
#define LONG_TYPE_SIZE 32
#endif
#endif
#define __BITS4 (LONG_TYPE_SIZE / 4)
#define __ll_B (1L << (LONG_TYPE_SIZE / 2))
#define __ll_lowpart(t) ((unsigned long int) (t) % __ll_B)
#define __ll_highpart(t) ((unsigned long int) (t) / __ll_B)
/* Define auxiliary asm macros.
1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
multiplies two unsigned long integers MULTIPLER and MULTIPLICAND,
and generates a two unsigned word product in HIGH_PROD and
LOW_PROD.
2) __umulsidi3(a,b) multiplies two unsigned long integers A and B,
and returns a long long product. This is just a variant of umul_ppmm.
3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
denominator) divides a two-word unsigned integer, composed by the
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 non-zero bit. This is the number of steps X
needs to be shifted left to set the msb. Undefined for X == 0.
6) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
high_addend_2, low_addend_2) adds two two-word unsigned 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.
7) sub_ddmmss(high_difference, low_difference, high_minuend,
low_minuend, high_subtrahend, low_subtrahend) subtracts two
two-word unsigned 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! */
#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 (__a29k__) || defined (___AM29K__)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("add %1,%4,%5
addc %0,%2,%3" \
: "=r" ((unsigned long int)(sh)), \
"=&r" ((unsigned long int)(sl)) \
: "%r" ((unsigned long int)(ah)), \
"rI" ((unsigned long int)(bh)), \
"%r" ((unsigned long int)(al)), \
"rI" ((unsigned long int)(bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("sub %1,%4,%5
subc %0,%2,%3" \
: "=r" ((unsigned long int)(sh)), \
"=&r" ((unsigned long int)(sl)) \
: "r" ((unsigned long int)(ah)), \
"rI" ((unsigned long int)(bh)), \
"r" ((unsigned long int)(al)), \
"rI" ((unsigned long int)(bl)))
#define umul_ppmm(xh, xl, m0, m1) \
do { \
unsigned long int __m0 = (m0), __m1 = (m1); \
__asm__ ("multiplu %0,%1,%2" \
: "=r" ((unsigned long int)(xl)) \
: "r" (__m0), \
"r" (__m1)); \
__asm__ ("multmu %0,%1,%2" \
: "=r" ((unsigned long int)(xh)) \
: "r" (__m0), \
"r" (__m1)); \
} while (0)
#define udiv_qrnnd(q, r, n1, n0, d) \
__asm__ ("dividu %0,%3,%4" \
: "=r" ((unsigned long int)(q)), \
"=q" ((unsigned long int)(r)) \
: "1" ((unsigned long int)(n1)), \
"r" ((unsigned long int)(n0)), \
"r" ((unsigned long int)(d)))
#define count_leading_zeros(count, x) \
__asm__ ("clz %0,%1" \
: "=r" ((unsigned long int)(count)) \
: "r" ((unsigned long int)(x)))
#endif /* __a29k__ */
#if defined (__alpha__)
#define umul_ppmm(ph, pl, m0, m1) \
do { \
unsigned long int __m0 = (m0), __m1 = (m1); \
__asm__ ("umulh %r1,%2,%0" \
: "=r" ((unsigned long int) ph) \
: "%rJ" (__m0), \
"rI" (__m1)); \
(pl) = (unsigned long int) (__m0) * (unsigned long int) (__m1); \
} while (0)
#define UMUL_TIME 46
#define UDIV_TIME 500
#endif
#if defined (__arm__)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("adds %1,%4,%5
adc %0,%2,%3" \
: "=r" ((unsigned long int)(sh)), \
"=&r" ((unsigned long int)(sl)) \
: "%r" ((unsigned long int)(ah)), \
"rI" ((unsigned long int)(bh)), \
"%r" ((unsigned long int)(al)), \
"rI" ((unsigned long int)(bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subs %1,%4,%5
sbc %0,%2,%3" \
: "=r" ((unsigned long int)(sh)), \
"=&r" ((unsigned long int)(sl)) \
: "r" ((unsigned long int)(ah)), \
"rI" ((unsigned long int)(bh)), \
"r" ((unsigned long int)(al)), \
"rI" ((unsigned long int)(bl)))
#endif /* __arm__ */
#if defined (__gmicro__)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("add.w %5,%1
addx %3,%0" \
: "=g" ((unsigned long int)(sh)), \
"=&g" ((unsigned long int)(sl)) \
: "%0" ((unsigned long int)(ah)), \
"g" ((unsigned long int)(bh)), \
"%1" ((unsigned long int)(al)), \
"g" ((unsigned long int)(bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("sub.w %5,%1
subx %3,%0" \
: "=g" ((unsigned long int)(sh)), \
"=&g" ((unsigned long int)(sl)) \
: "0" ((unsigned long int)(ah)), \
"g" ((unsigned long int)(bh)), \
"1" ((unsigned long int)(al)), \
"g" ((unsigned long int)(bl)))
#define umul_ppmm(ph, pl, m0, m1) \
__asm__ ("mulx %3,%0,%1" \
: "=g" ((unsigned long int)(ph)), \
"=r" ((unsigned long int)(pl)) \
: "%0" ((unsigned long int)(m0)), \
"g" ((unsigned long int)(m1)))
#define udiv_qrnnd(q, r, nh, nl, d) \
__asm__ ("divx %4,%0,%1" \
: "=g" ((unsigned long int)(q)), \
"=r" ((unsigned long int)(r)) \
: "1" ((unsigned long int)(nh)), \
"0" ((unsigned long int)(nl)), \
"g" ((unsigned long int)(d)))
#define count_leading_zeros(count, x) \
__asm__ ("bsch/1 %1,%0" \
: "=g" (count) \
: "g" ((unsigned long int)(x)), \
"0" (0UL))
#endif
#if defined (__hppa)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("add %4,%5,%1
addc %2,%3,%0" \
: "=r" ((unsigned long int)(sh)), \
"=&r" ((unsigned long int)(sl)) \
: "%rM" ((unsigned long int)(ah)), \
"rM" ((unsigned long int)(bh)), \
"%rM" ((unsigned lo