Home | History | Annotate | Line # | Download | only in sparc64
sparc64.h revision 1.1
      1  1.1  mrg /* UltraSPARC 64 support macros.
      2  1.1  mrg 
      3  1.1  mrg    THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY.  THEY'RE ALMOST
      4  1.1  mrg    CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
      5  1.1  mrg    FUTURE GNU MP RELEASES.
      6  1.1  mrg 
      7  1.1  mrg Copyright 2003 Free Software Foundation, Inc.
      8  1.1  mrg 
      9  1.1  mrg This file is part of the GNU MP Library.
     10  1.1  mrg 
     11  1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
     12  1.1  mrg it under the terms of the GNU Lesser General Public License as published by
     13  1.1  mrg the Free Software Foundation; either version 3 of the License, or (at your
     14  1.1  mrg option) any later version.
     15  1.1  mrg 
     16  1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     17  1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     18  1.1  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     19  1.1  mrg License for more details.
     20  1.1  mrg 
     21  1.1  mrg You should have received a copy of the GNU Lesser General Public License
     22  1.1  mrg along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
     23  1.1  mrg 
     24  1.1  mrg 
     25  1.1  mrg #define LOW32(x)   ((x) & 0xFFFFFFFF)
     26  1.1  mrg #define HIGH32(x)  ((x) >> 32)
     27  1.1  mrg 
     28  1.1  mrg 
     29  1.1  mrg /* Halfword number i in src is accessed as src[i+HALF_ENDIAN_ADJ(i)].
     30  1.1  mrg    Plain src[i] would be incorrect in big endian, HALF_ENDIAN_ADJ has the
     31  1.1  mrg    effect of swapping the two halves in this case.  */
     32  1.1  mrg #if HAVE_LIMB_BIG_ENDIAN
     33  1.1  mrg #define HALF_ENDIAN_ADJ(i)  (1 - (((i) & 1) << 1))   /* +1 even, -1 odd */
     34  1.1  mrg #endif
     35  1.1  mrg #if HAVE_LIMB_LITTLE_ENDIAN
     36  1.1  mrg #define HALF_ENDIAN_ADJ(i)  0                        /* no adjust */
     37  1.1  mrg #endif
     38  1.1  mrg #ifndef HALF_ENDIAN_ADJ
     39  1.1  mrg Error, error, unknown limb endianness;
     40  1.1  mrg #endif
     41  1.1  mrg 
     42  1.1  mrg 
     43  1.1  mrg /* umul_ppmm_lowequal sets h to the high limb of q*d, assuming the low limb
     44  1.1  mrg    of that product is equal to l.  dh and dl are the 32-bit halves of d.
     45  1.1  mrg 
     46  1.1  mrg    |-----high----||----low-----|
     47  1.1  mrg    +------+------+
     48  1.1  mrg    |             |                 ph = qh * dh
     49  1.1  mrg    +------+------+
     50  1.1  mrg           +------+------+
     51  1.1  mrg           |             |          pm1 = ql * dh
     52  1.1  mrg           +------+------+
     53  1.1  mrg           +------+------+
     54  1.1  mrg           |             |          pm2 = qh * dl
     55  1.1  mrg           +------+------+
     56  1.1  mrg                  +------+------+
     57  1.1  mrg                  |             |   pl = ql * dl (not calculated)
     58  1.1  mrg                  +------+------+
     59  1.1  mrg 
     60  1.1  mrg    Knowing that the low 64 bits is equal to l means that LOW(pm1) + LOW(pm2)
     61  1.1  mrg    + HIGH(pl) == HIGH(l).  The only thing we need from those product parts
     62  1.1  mrg    is whether they produce a carry into the high.
     63  1.1  mrg 
     64  1.1  mrg    pm_l = LOW(pm1)+LOW(pm2) is done to contribute its carry, then the only
     65  1.1  mrg    time there's a further carry from LOW(pm_l)+HIGH(pl) is if LOW(pm_l) >
     66  1.1  mrg    HIGH(l).  pl is never actually calculated.  */
     67  1.1  mrg 
     68  1.1  mrg #define umul_ppmm_lowequal(h, q, d, dh, dl, l)  \
     69  1.1  mrg   do {                                          \
     70  1.1  mrg     mp_limb_t  ql, qh, ph, pm1, pm2, pm_l;      \
     71  1.1  mrg     ASSERT (dh == HIGH32(d));                   \
     72  1.1  mrg     ASSERT (dl == LOW32(d));                    \
     73  1.1  mrg     ASSERT (q*d == l);                          \
     74  1.1  mrg                                                 \
     75  1.1  mrg     ql = LOW32 (q);                             \
     76  1.1  mrg     qh = HIGH32 (q);                            \
     77  1.1  mrg                                                 \
     78  1.1  mrg     pm1 = ql * dh;                              \
     79  1.1  mrg     pm2 = qh * dl;                              \
     80  1.1  mrg     ph  = qh * dh;                              \
     81  1.1  mrg                                                 \
     82  1.1  mrg     pm_l = LOW32 (pm1) + LOW32 (pm2);           \
     83  1.1  mrg                                                 \
     84  1.1  mrg     (h) = ph + HIGH32 (pm1) + HIGH32 (pm2)      \
     85  1.1  mrg       + HIGH32 (pm_l) + ((pm_l << 32) > l);     \
     86  1.1  mrg                                                 \
     87  1.1  mrg     ASSERT_HIGH_PRODUCT (h, q, d);              \
     88  1.1  mrg   } while (0)
     89  1.1  mrg 
     90  1.1  mrg 
     91  1.1  mrg /* Set h to the high of q*d, assuming the low limb of that product is equal
     92  1.1  mrg    to l, and that d fits in 32-bits.
     93  1.1  mrg 
     94  1.1  mrg    |-----high----||----low-----|
     95  1.1  mrg           +------+------+
     96  1.1  mrg           |             |          pm = qh * dl
     97  1.1  mrg           +------+------+
     98  1.1  mrg                  +------+------+
     99  1.1  mrg                  |             |   pl = ql * dl (not calculated)
    100  1.1  mrg                  +------+------+
    101  1.1  mrg 
    102  1.1  mrg    Knowing that LOW(pm) + HIGH(pl) == HIGH(l) (mod 2^32) means that the only
    103  1.1  mrg    time there's a carry from that sum is when LOW(pm) > HIGH(l).  There's no
    104  1.1  mrg    need to calculate pl to determine this.  */
    105  1.1  mrg 
    106  1.1  mrg #define umul_ppmm_half_lowequal(h, q, d, l)     \
    107  1.1  mrg   do {                                          \
    108  1.1  mrg     mp_limb_t pm;                               \
    109  1.1  mrg     ASSERT (q*d == l);                          \
    110  1.1  mrg     ASSERT (HIGH32(d) == 0);                    \
    111  1.1  mrg                                                 \
    112  1.1  mrg     pm = HIGH32(q) * d;                         \
    113  1.1  mrg     (h) = HIGH32(pm) + ((pm << 32) > l);        \
    114  1.1  mrg     ASSERT_HIGH_PRODUCT (h, q, d);              \
    115  1.1  mrg   } while (0)
    116  1.1  mrg 
    117  1.1  mrg 
    118  1.1  mrg /* check that h is the high limb of x*y */
    119  1.1  mrg #if WANT_ASSERT
    120  1.1  mrg #define ASSERT_HIGH_PRODUCT(h, x, y)    \
    121  1.1  mrg   do {                                  \
    122  1.1  mrg     mp_limb_t  want_h, dummy;           \
    123  1.1  mrg     umul_ppmm (want_h, dummy, x, y);    \
    124  1.1  mrg     ASSERT (h == want_h);               \
    125  1.1  mrg   } while (0)
    126  1.1  mrg #else
    127  1.1  mrg #define ASSERT_HIGH_PRODUCT(h, q, d)    \
    128  1.1  mrg   do { } while (0)
    129  1.1  mrg #endif
    130  1.1  mrg 
    131  1.1  mrg 
    132  1.1  mrg /* Count the leading zeros on a limb, but assuming it fits in 32 bits.
    133  1.1  mrg    The count returned will be in the range 32 to 63.
    134  1.1  mrg    This is the 32-bit generic C count_leading_zeros from longlong.h. */
    135  1.1  mrg #define count_leading_zeros_32(count, x)                                      \
    136  1.1  mrg   do {                                                                        \
    137  1.1  mrg     mp_limb_t  __xr = (x);                                                    \
    138  1.1  mrg     unsigned   __a;                                                           \
    139  1.1  mrg     ASSERT ((x) != 0);                                                        \
    140  1.1  mrg     ASSERT ((x) <= CNST_LIMB(0xFFFFFFFF));                                    \
    141  1.1  mrg     __a = __xr < ((UWtype) 1 << 16) ? (__xr < ((UWtype) 1 << 8) ? 1 : 8 + 1)  \
    142  1.1  mrg       : (__xr < ((UWtype) 1 << 24)  ? 16 + 1 : 24 + 1);                       \
    143  1.1  mrg                                                                               \
    144  1.1  mrg     (count) = W_TYPE_SIZE + 1 - __a - __clz_tab[__xr >> __a];                 \
    145  1.1  mrg   } while (0)
    146  1.1  mrg 
    147  1.1  mrg 
    148  1.1  mrg /* Set inv to a 32-bit inverse floor((b*(b-d)-1) / d), knowing that d fits
    149  1.1  mrg    32 bits and is normalized (high bit set).  */
    150  1.1  mrg #define invert_half_limb(inv, d)                \
    151  1.1  mrg   do {                                          \
    152  1.1  mrg     mp_limb_t  _n;                              \
    153  1.1  mrg     ASSERT ((d) <= 0xFFFFFFFF);                 \
    154  1.1  mrg     ASSERT ((d) & 0x80000000);                  \
    155  1.1  mrg     _n = (((mp_limb_t) -(d)) << 32) - 1;        \
    156  1.1  mrg     (inv) = (mp_limb_t) (unsigned) (_n / (d));  \
    157  1.1  mrg   } while (0)
    158  1.1  mrg 
    159  1.1  mrg 
    160  1.1  mrg /* Divide nh:nl by d, setting q to the quotient and r to the remainder.
    161  1.1  mrg    q, r, nh and nl are 32-bits each, d_limb is 32-bits but in an mp_limb_t,
    162  1.1  mrg    dinv_limb is similarly a 32-bit inverse but in an mp_limb_t.  */
    163  1.1  mrg 
    164  1.1  mrg #define udiv_qrnnd_half_preinv(q, r, nh, nl, d_limb, dinv_limb)         \
    165  1.1  mrg   do {                                                                  \
    166  1.1  mrg     unsigned   _n2, _n10, _n1, _nadj, _q11n, _xh, _r, _q;               \
    167  1.1  mrg     mp_limb_t  _n, _x;                                                  \
    168  1.1  mrg     ASSERT (d_limb <= 0xFFFFFFFF);                                      \
    169  1.1  mrg     ASSERT (dinv_limb <= 0xFFFFFFFF);                                   \
    170  1.1  mrg     ASSERT (d_limb & 0x80000000);                                       \
    171  1.1  mrg     ASSERT (nh < d_limb);                                               \
    172  1.1  mrg     _n10 = (nl);                                                        \
    173  1.1  mrg     _n2 = (nh);                                                         \
    174  1.1  mrg     _n1 = (int) _n10 >> 31;                                             \
    175  1.1  mrg     _nadj = _n10 + (_n1 & d_limb);                                      \
    176  1.1  mrg     _x = dinv_limb * (_n2 - _n1) + _nadj;                               \
    177  1.1  mrg     _q11n = ~(_n2 + HIGH32 (_x));             /* -q1-1 */               \
    178  1.1  mrg     _n = ((mp_limb_t) _n2 << 32) + _n10;                                \
    179  1.1  mrg     _x = _n + d_limb * _q11n;                 /* n-q1*d-d */            \
    180  1.1  mrg     _xh = HIGH32 (_x) - d_limb;               /* high(n-q1*d-d) */      \
    181  1.1  mrg     ASSERT (_xh == 0 || _xh == ~0);                                     \
    182  1.1  mrg     _r = _x + (d_limb & _xh);                 /* addback */             \
    183  1.1  mrg     _q = _xh - _q11n;                         /* q1+1-addback */        \
    184  1.1  mrg     ASSERT (_r < d_limb);                                               \
    185  1.1  mrg     ASSERT (d_limb * _q + _r == _n);                                    \
    186  1.1  mrg     (r) = _r;                                                           \
    187  1.1  mrg     (q) = _q;                                                           \
    188  1.1  mrg   } while (0)
    189  1.1  mrg 
    190  1.1  mrg 
    191