Provide __P definition if not already defined.
[kopensolaris-gnu/glibc.git] / stdlib / longlong.h
index bbb92e3..397188e 100644 (file)
@@ -1,20 +1,21 @@
 /* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
+   Copyright (C) 1991,92,93,94,96,97,98,99 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
 
-Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
 
-This file is free software; you can redistribute it and/or modify
-it under the terms of the GNU Library General Public License as published by
-the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
 
-This 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 Library General Public
-License for more details.
-
-You should have received a copy of the GNU Library General Public License
-along with this file; see the file COPYING.LIB.  If not, write to
-the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  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:
 
@@ -35,6 +36,21 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 #define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
 #define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
 
+/* This is used to make sure no undesirable sharing between different libraries
+   that use this file takes place.  */
+#ifndef __MPN
+#define __MPN(x) __##x
+#endif
+
+#ifndef __P
+# if defined __GNUC__ || (defined (__STDC__) && __STDC__) \
+     || defined (__cplusplus)
+#  define __P(args)    args
+# else
+#  define __P(args)    ()
+# endif
+#endif
+
 /* Define auxiliary asm macros.
 
    1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
@@ -139,9 +155,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
     __asm__ ("clz %0,%1"                                               \
             : "=r" ((USItype)(count))                                  \
             : "r" ((USItype)(x)))
+#define COUNT_LEADING_ZEROS_0 32
 #endif /* __a29k__ */
 
-#if defined (__alpha__) && W_TYPE_SIZE == 64
+#if defined (__alpha) && W_TYPE_SIZE == 64
 #define umul_ppmm(ph, pl, m0, m1) \
   do {                                                                 \
     UDItype __m0 = (m0), __m1 = (m1);                                  \
@@ -158,10 +175,10 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
     (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));                                \
     (r) = __r;                                                         \
   } while (0)
-extern UDItype __udiv_qrnnd ();
+extern UDItype __udiv_qrnnd __P ((UDItype *, UDItype, UDItype, UDItype));
 #define UDIV_TIME 220
 #endif /* LONGLONG_STANDALONE */
-#endif /* __alpha__ */
+#endif /* __alpha */
 
 #if defined (__arm__) && W_TYPE_SIZE == 32
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
@@ -182,6 +199,7 @@ extern UDItype __udiv_qrnnd ();
             "rI" ((USItype)(bh)),                                      \
             "r" ((USItype)(al)),                                       \
             "rI" ((USItype)(bl)))
+#if 0
 #define umul_ppmm(xh, xl, a, b) \
   __asm__ ("%@ Inlined umul_ppmm
        mov     %|r0, %2, lsr #16
@@ -203,6 +221,7 @@ extern UDItype __udiv_qrnnd ();
           : "r0", "r1", "r2")
 #define UMUL_TIME 20
 #define UDIV_TIME 100
+#endif
 #endif /* __arm__ */
 
 #if defined (__clipper__) && W_TYPE_SIZE == 32
@@ -298,9 +317,9 @@ extern UDItype __udiv_qrnnd ();
           struct {USItype __h, __l;} __i;                              \
          } __xx;                                                       \
     __asm__ ("xmpyu %1,%2,%0"                                          \
-            : "=fx" (__xx.__ll)                                        \
-            : "fx" ((USItype)(u)),                                     \
-              "fx" ((USItype)(v)));                                    \
+            : "=*f" (__xx.__ll)                                        \
+            : "*f" ((USItype)(u)),                                     \
+              "*f" ((USItype)(v)));                                    \
     (wh) = __xx.__i.__h;                                               \
     (wl) = __xx.__i.__l;                                               \
   } while (0)
@@ -339,7 +358,7 @@ extern USItype __udiv_qrnnd ();
        sub             %0,%1,%0                ; Subtract it.
        " : "=r" (count), "=r" (__tmp) : "1" (x));                      \
   } while (0)
-#endif
+#endif /* hppa */
 
 #if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32
 #define umul_ppmm(xh, xl, m0, m1) \
@@ -431,7 +450,29 @@ extern USItype __udiv_qrnnd ();
 #endif
 #endif /* 80x86 */
 
+#if defined (__i860__) && W_TYPE_SIZE == 32
+#define rshift_rhlc(r,h,l,c) \
+  __asm__ ("shr %3,r0,r0\;shrd %1,%2,%0"                               \
+          "=r" (r) : "r" (h), "r" (l), "rn" (c))
+#endif /* i860 */
+
 #if defined (__i960__) && W_TYPE_SIZE == 32
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  __asm__ ("cmpo 1,0\;addc %5,%4,%1\;addc %3,%2,%0"                    \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "%dI" ((USItype)(ah)),                                     \
+            "dI" ((USItype)(bh)),                                      \
+            "%dI" ((USItype)(al)),                                     \
+            "dI" ((USItype)(bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  __asm__ ("cmpo 0,0\;subc %5,%4,%1\;subc %3,%2,%0"                    \
+          : "=r" ((USItype)(sh)),                                      \
+            "=&r" ((USItype)(sl))                                      \
+          : "dI" ((USItype)(ah)),                                      \
+            "dI" ((USItype)(bh)),                                      \
+            "dI" ((USItype)(al)),                                      \
+            "dI" ((USItype)(bl)))
 #define umul_ppmm(w1, w0, u, v) \
   ({union {UDItype __ll;                                               \
           struct {USItype __l, __h;} __i;                              \
@@ -447,8 +488,40 @@ extern USItype __udiv_qrnnd ();
             : "=d" (__w)                                               \
             : "%dI" ((USItype)(u)),                                    \
               "dI" ((USItype)(v)));                                    \
-    __w; })  
-#endif /* __i960__ */
+    __w; })
+#define udiv_qrnnd(q, r, nh, nl, d) \
+  do {                                                                 \
+    union {UDItype __ll;                                               \
+          struct {USItype __l, __h;} __i;                              \
+         } __nn;                                                       \
+    __nn.__i.__h = (nh); __nn.__i.__l = (nl);                          \
+    __asm__ ("ediv %d,%n,%0"                                           \
+          : "=d" (__rq.__ll)                                           \
+          : "dI" (__nn.__ll),                                          \
+            "dI" ((USItype)(d)));                                      \
+    (r) = __rq.__i.__l; (q) = __rq.__i.__h;                            \
+  } while (0)
+#define count_leading_zeros(count, x) \
+  do {                                                                 \
+    USItype __cbtmp;                                                   \
+    __asm__ ("scanbit %1,%0"                                           \
+            : "=r" (__cbtmp)                                           \
+            : "r" ((USItype)(x)));                                     \
+    (count) = __cbtmp ^ 31;                                            \
+  } while (0)
+#define COUNT_LEADING_ZEROS_0 (-32) /* sic */
+#if defined (__i960mx)         /* what is the proper symbol to test??? */
+#define rshift_rhlc(r,h,l,c) \
+  do {                                                                 \
+    union {UDItype __ll;                                               \
+          struct {USItype __l, __h;} __i;                              \
+         } __nn;                                                       \
+    __nn.__i.__h = (h); __nn.__i.__l = (l);                            \
+    __asm__ ("shre %2,%1,%0"                                           \
+            : "=d" (r) : "dI" (__nn.__ll), "dI" (c));                  \
+  }
+#endif /* i960mx */
+#endif /* i960 */
 
 #if (defined (__mc68000__) || defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
@@ -469,7 +542,7 @@ extern USItype __udiv_qrnnd ();
             "d" ((USItype)(bh)),                                       \
             "1" ((USItype)(al)),                                       \
             "g" ((USItype)(bl)))
-#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)) && W_TYPE_SIZE == 32
+#if (defined (__mc68020__) || defined (__NeXT__) || defined(mc68020))
 #define umul_ppmm(w1, w0, u, v) \
   __asm__ ("mulu%.l %3,%1:%0"                                          \
           : "=d" ((USItype)(w0)),                                      \
@@ -496,8 +569,9 @@ extern USItype __udiv_qrnnd ();
   __asm__ ("bfffo %1{%b2:%b2},%0"                                      \
           : "=d" ((USItype)(count))                                    \
           : "od" ((USItype)(x)), "n" (0))
+#define COUNT_LEADING_ZEROS_0 32
 #else /* not mc68020 */
-#define umul_ppmmxx(xh, xl, a, b) \
+#define umul_ppmm(xh, xl, a, b) \
   do { USItype __umul_tmp1, __umul_tmp2;                               \
        __asm__ ("| Inlined umul_ppmm
        move%.l %5,%3
@@ -522,7 +596,7 @@ extern USItype __udiv_qrnnd ();
        addx%.l %2,%0
        | End inlined umul_ppmm"                                        \
              : "=&d" ((USItype)(xh)), "=&d" ((USItype)(xl)),           \
-               "=d" (__umul_tmp1), "=&d" (__umul_tmp2)                 \
+               "=d" (__umul_tmp1), "=&d" (__umul_tmp2)                 \
              : "%2" ((USItype)(a)), "d" ((USItype)(b)));               \
   } while (0)
 #define UMUL_TIME 100
@@ -557,6 +631,7 @@ extern USItype __udiv_qrnnd ();
             : "r" ((USItype)(x)));                                     \
     (count) = __cbtmp ^ 31;                                            \
   } while (0)
+#define COUNT_LEADING_ZEROS_0 63 /* sic */
 #if defined (__m88110__)
 #define umul_ppmm(wh, wl, u, v) \
   do {                                                                 \
@@ -738,6 +813,7 @@ extern USItype __udiv_qrnnd ();
   __asm__ ("{cntlz|cntlzw} %0,%1"                                      \
           : "=r" ((USItype)(count))                                    \
           : "r" ((USItype)(x)))
+#define COUNT_LEADING_ZEROS_0 32
 #if defined (_ARCH_PPC)
 #define umul_ppmm(ph, pl, m0, m1) \
   do {                                                                 \
@@ -887,7 +963,7 @@ extern USItype __udiv_qrnnd ();
        (count) += 16;                                                  \
       }                                                                        \
   } while (0)
-#endif
+#endif /* RT/ROMP */
 
 #if defined (__sh2__) && W_TYPE_SIZE == 32
 #define umul_ppmm(w1, w0, u, v) \
@@ -1012,6 +1088,9 @@ extern USItype __udiv_qrnnd ();
   __asm__ ("scan %1,0,%0"                                              \
           : "=r" ((USItype)(x))                                        \
           : "r" ((USItype)(count)))
+/* Early sparclites return 63 for an argument of 0, but they warn that future
+   implementations might change this.  Therefore, leave COUNT_LEADING_ZEROS_0
+   undefined.  */
 #endif /* __sparclite__ */
 #endif /* __sparc_v8__ */
 /* Default to sparc v7 versions of umul_ppmm and udiv_qrnnd.  */
@@ -1065,18 +1144,111 @@ extern USItype __udiv_qrnnd ();
 #define UMUL_TIME 39           /* 39 instructions */
 #endif
 #ifndef udiv_qrnnd
-#ifndef LONGLONG_STANDALONE
+/* It's quite necessary to add this much assembler for the sparc.
+   The default udiv_qrnnd (in C) is more than 10 times slower!  */
 #define udiv_qrnnd(q, r, n1, n0, d) \
-  do { USItype __r;                                                    \
-    (q) = __udiv_qrnnd (&__r, (n1), (n0), (d));                                \
-    (r) = __r;                                                         \
-  } while (0)
-extern USItype __udiv_qrnnd ();
+  __asm__ ("! Inlined udiv_qrnnd
+       mov     32,%%g1
+       subcc   %1,%2,%%g0
+1:     bcs     5f
+        addxcc %0,%0,%0        ! shift n1n0 and a q-bit in lsb
+       sub     %1,%2,%1        ! this kills msb of n
+       addx    %1,%1,%1        ! so this can't give carry
+       subcc   %%g1,1,%%g1
+2:     bne     1b
+        subcc  %1,%2,%%g0
+       bcs     3f
+        addxcc %0,%0,%0        ! shift n1n0 and a q-bit in lsb
+       b       3f
+        sub    %1,%2,%1        ! this kills msb of n
+4:     sub     %1,%2,%1
+5:     addxcc  %1,%1,%1
+       bcc     2b
+        subcc  %%g1,1,%%g1
+! Got carry from n.  Subtract next step to cancel this carry.
+       bne     4b
+        addcc  %0,%0,%0        ! shift n1n0 and a 0-bit in lsb
+       sub     %1,%2,%1
+3:     xnor    %0,0,%0
+       ! End of inline udiv_qrnnd"                                     \
+          : "=&r" ((USItype)(q)),                                      \
+            "=&r" ((USItype)(r))                                       \
+          : "r" ((USItype)(d)),                                        \
+            "1" ((USItype)(n1)),                                       \
+            "0" ((USItype)(n0)) : "%g1" __AND_CLOBBER_CC)
+#define UDIV_TIME (3+7*32)     /* 7 instructions/iteration. 32 iterations. */
+#else
+extern USItype __udiv_qrnnd __P ((USItype *, USItype, USItype, USItype));
 #define UDIV_TIME 140
-#endif /* LONGLONG_STANDALONE */
 #endif /* udiv_qrnnd */
 #endif /* __sparc__ */
 
+#if (defined (__sparc_v9__) || (defined (__sparc__) && defined (__arch64__)) \
+    || defined (__sparcv9)) && W_TYPE_SIZE == 64
+#define add_ssaaaa(sh, sl, ah, al, bh, bl)                             \
+  __asm__ ("addcc %4,%5,%1
+           add %2,%3,%0
+           bcs,a,pn %%xcc, 1f
+           add %0, 1, %0
+           1:"                                                         \
+          : "=r" ((UDItype)(sh)),                                      \
+            "=&r" ((UDItype)(sl))                                      \
+          : "r" ((UDItype)(ah)),                                       \
+            "r" ((UDItype)(bh)),                                       \
+            "r" ((UDItype)(al)),                                       \
+            "r" ((UDItype)(bl))                                        \
+          : "cc")
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl)                             \
+  __asm__ ("subcc %4,%5,%1
+           sub %2,%3,%0
+           bcs,a,pn %%xcc, 1f
+           sub %0, 1, %0
+           1:"                                                         \
+          : "=r" ((UDItype)(sh)),                                      \
+            "=&r" ((UDItype)(sl))                                      \
+          : "r" ((UDItype)(ah)),                                       \
+            "r" ((UDItype)(bh)),                                       \
+            "r" ((UDItype)(al)),                                       \
+            "r" ((UDItype)(bl))                                        \
+          : "cc")
+
+#define umul_ppmm(wh, wl, u, v)                                                \
+  do {                                                                 \
+         UDItype tmp1, tmp2, tmp3, tmp4;                               \
+         __asm__ __volatile__ (                                        \
+                  "srl %7,0,%3
+                   mulx %3,%6,%1
+                   srlx %6,32,%2
+                   mulx %2,%3,%4
+                   sllx %4,32,%5
+                   srl %6,0,%3
+                   sub %1,%5,%5
+                   srlx %5,32,%5
+                   addcc %4,%5,%4
+                   srlx %7,32,%5
+                   mulx %3,%5,%3
+                   mulx %2,%5,%5
+                   sethi %%hi(0x80000000),%2
+                   addcc %4,%3,%4
+                   srlx %4,32,%4
+                   add %2,%2,%2
+                   movcc %%xcc,%%g0,%2
+                   addcc %5,%4,%5
+                   sllx %3,32,%3
+                   add %1,%3,%1
+                   add %5,%2,%0"                                       \
+          : "=r" ((UDItype)(wh)),                                      \
+            "=&r" ((UDItype)(wl)),                                     \
+            "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4)     \
+          : "r" ((UDItype)(u)),                                        \
+            "r" ((UDItype)(v))                                         \
+          : "cc");                                                     \
+  } while (0)
+#define UMUL_TIME 96
+#define UDIV_TIME 230
+#endif /* __sparc_v9__ */
+
 #if defined (__vax__) && W_TYPE_SIZE == 32
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
   __asm__ ("addl2 %5,%1
@@ -1154,20 +1326,6 @@ extern USItype __udiv_qrnnd ();
     (xh) += ((((signed int) __m0 >> 15) & __m1)                                \
             + (((signed int) __m1 >> 15) & __m0));                     \
   } while (0)
-#define umul_ppmm_off(xh, xl, m0, m1) \
-  do {                                                                 \
-    union {long int __ll;                                              \
-          struct {unsigned int __h, __l;} __i;                         \
-         } __xx;                                                       \
-    __asm__ ("mult     %S0,%H3"                                        \
-            : "=r" (__xx.__i.__h),                                     \
-              "=r" (__xx.__i.__l)                                      \
-            : "%1" (m0),                                               \
-              "rQR" (m1));                                             \
-    (xh) = __xx.__i.__h + ((((signed int) m0 >> 15) & m1)              \
-                          + (((signed int) m1 >> 15) & m0));           \
-    (xl) = __xx.__i.__l;                                               \
-  } while (0)
 #endif /* __z8000__ */
 
 #endif /* __GNUC__ */
@@ -1292,7 +1450,7 @@ extern USItype __udiv_qrnnd ();
 #define udiv_qrnnd(q, r, nh, nl, d) \
   do {                                                                 \
     UWtype __r;                                                                \
-    (q) = __udiv_w_sdiv (&__r, nh, nl, d);                             \
+    (q) = __MPN(udiv_w_sdiv) (&__r, nh, nl, d);                                \
     (r) = __r;                                                         \
   } while (0)
 #endif