Home | History | Annotate | Line # | Download | only in builtins
      1      1.1  joerg /* ===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------===
      2      1.1  joerg  *
      3      1.1  joerg  *                     The LLVM Compiler Infrastructure
      4      1.1  joerg  *
      5      1.1  joerg  * This file is dual licensed under the MIT and the University of Illinois Open
      6      1.1  joerg  * Source Licenses. See LICENSE.TXT for details.
      7      1.1  joerg  *
      8      1.1  joerg  * ===----------------------------------------------------------------------===
      9      1.1  joerg  *
     10      1.1  joerg  * This file implements __udivmoddi4 for the compiler_rt library.
     11      1.1  joerg  *
     12      1.1  joerg  * ===----------------------------------------------------------------------===
     13      1.1  joerg  */
     14      1.1  joerg 
     15      1.1  joerg #include "int_lib.h"
     16      1.1  joerg 
     17      1.1  joerg /* Effects: if rem != 0, *rem = a % b
     18      1.1  joerg  * Returns: a / b
     19      1.1  joerg  */
     20      1.1  joerg 
     21      1.1  joerg /* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */
     22      1.1  joerg 
     23      1.1  joerg COMPILER_RT_ABI du_int
     24      1.1  joerg __udivmoddi4(du_int a, du_int b, du_int* rem)
     25      1.1  joerg {
     26      1.1  joerg     const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
     27      1.1  joerg     const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
     28      1.1  joerg     udwords n;
     29      1.1  joerg     n.all = a;
     30      1.1  joerg     udwords d;
     31      1.1  joerg     d.all = b;
     32      1.1  joerg     udwords q;
     33      1.1  joerg     udwords r;
     34      1.1  joerg     unsigned sr;
     35      1.1  joerg     /* special cases, X is unknown, K != 0 */
     36      1.1  joerg     if (n.s.high == 0)
     37      1.1  joerg     {
     38      1.1  joerg         if (d.s.high == 0)
     39      1.1  joerg         {
     40      1.1  joerg             /* 0 X
     41      1.1  joerg              * ---
     42      1.1  joerg              * 0 X
     43      1.1  joerg              */
     44      1.1  joerg             if (rem)
     45      1.1  joerg                 *rem = n.s.low % d.s.low;
     46      1.1  joerg             return n.s.low / d.s.low;
     47      1.1  joerg         }
     48      1.1  joerg         /* 0 X
     49      1.1  joerg          * ---
     50      1.1  joerg          * K X
     51      1.1  joerg          */
     52      1.1  joerg         if (rem)
     53      1.1  joerg             *rem = n.s.low;
     54      1.1  joerg         return 0;
     55      1.1  joerg     }
     56      1.1  joerg     /* n.s.high != 0 */
     57      1.1  joerg     if (d.s.low == 0)
     58      1.1  joerg     {
     59      1.1  joerg         if (d.s.high == 0)
     60      1.1  joerg         {
     61      1.1  joerg             /* K X
     62      1.1  joerg              * ---
     63      1.1  joerg              * 0 0
     64      1.1  joerg              */
     65      1.1  joerg             if (rem)
     66      1.1  joerg                 *rem = n.s.high % d.s.low;
     67      1.1  joerg             return n.s.high / d.s.low;
     68      1.1  joerg         }
     69      1.1  joerg         /* d.s.high != 0 */
     70      1.1  joerg         if (n.s.low == 0)
     71      1.1  joerg         {
     72      1.1  joerg             /* K 0
     73      1.1  joerg              * ---
     74      1.1  joerg              * K 0
     75      1.1  joerg              */
     76      1.1  joerg             if (rem)
     77      1.1  joerg             {
     78      1.1  joerg                 r.s.high = n.s.high % d.s.high;
     79      1.1  joerg                 r.s.low = 0;
     80      1.1  joerg                 *rem = r.all;
     81      1.1  joerg             }
     82      1.1  joerg             return n.s.high / d.s.high;
     83      1.1  joerg         }
     84      1.1  joerg         /* K K
     85      1.1  joerg          * ---
     86      1.1  joerg          * K 0
     87      1.1  joerg          */
     88      1.1  joerg         if ((d.s.high & (d.s.high - 1)) == 0)     /* if d is a power of 2 */
     89      1.1  joerg         {
     90      1.1  joerg             if (rem)
     91      1.1  joerg             {
     92      1.1  joerg                 r.s.low = n.s.low;
     93      1.1  joerg                 r.s.high = n.s.high & (d.s.high - 1);
     94      1.1  joerg                 *rem = r.all;
     95      1.1  joerg             }
     96      1.1  joerg             return n.s.high >> __builtin_ctz(d.s.high);
     97      1.1  joerg         }
     98      1.1  joerg         /* K K
     99      1.1  joerg          * ---
    100      1.1  joerg          * K 0
    101      1.1  joerg          */
    102      1.1  joerg         sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
    103      1.1  joerg         /* 0 <= sr <= n_uword_bits - 2 or sr large */
    104      1.1  joerg         if (sr > n_uword_bits - 2)
    105      1.1  joerg         {
    106      1.1  joerg            if (rem)
    107      1.1  joerg                 *rem = n.all;
    108      1.1  joerg             return 0;
    109      1.1  joerg         }
    110      1.1  joerg         ++sr;
    111      1.1  joerg         /* 1 <= sr <= n_uword_bits - 1 */
    112      1.1  joerg         /* q.all = n.all << (n_udword_bits - sr); */
    113      1.1  joerg         q.s.low = 0;
    114      1.1  joerg         q.s.high = n.s.low << (n_uword_bits - sr);
    115      1.1  joerg         /* r.all = n.all >> sr; */
    116      1.1  joerg         r.s.high = n.s.high >> sr;
    117      1.1  joerg         r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
    118      1.1  joerg     }
    119      1.1  joerg     else  /* d.s.low != 0 */
    120      1.1  joerg     {
    121      1.1  joerg         if (d.s.high == 0)
    122      1.1  joerg         {
    123      1.1  joerg             /* K X
    124      1.1  joerg              * ---
    125      1.1  joerg              * 0 K
    126      1.1  joerg              */
    127      1.1  joerg             if ((d.s.low & (d.s.low - 1)) == 0)     /* if d is a power of 2 */
    128      1.1  joerg             {
    129      1.1  joerg                 if (rem)
    130      1.1  joerg                     *rem = n.s.low & (d.s.low - 1);
    131      1.1  joerg                 if (d.s.low == 1)
    132      1.1  joerg                     return n.all;
    133      1.1  joerg                 sr = __builtin_ctz(d.s.low);
    134      1.1  joerg                 q.s.high = n.s.high >> sr;
    135      1.1  joerg                 q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
    136      1.1  joerg                 return q.all;
    137      1.1  joerg             }
    138      1.1  joerg             /* K X
    139      1.1  joerg              * ---
    140  1.1.1.2  joerg              * 0 K
    141      1.1  joerg              */
    142      1.1  joerg             sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high);
    143      1.1  joerg             /* 2 <= sr <= n_udword_bits - 1
    144      1.1  joerg              * q.all = n.all << (n_udword_bits - sr);
    145      1.1  joerg              * r.all = n.all >> sr;
    146      1.1  joerg              */
    147  1.1.1.2  joerg             if (sr == n_uword_bits)
    148  1.1.1.2  joerg             {
    149  1.1.1.2  joerg                 q.s.low = 0;
    150  1.1.1.2  joerg                 q.s.high = n.s.low;
    151  1.1.1.2  joerg                 r.s.high = 0;
    152  1.1.1.2  joerg                 r.s.low = n.s.high;
    153  1.1.1.2  joerg             }
    154  1.1.1.2  joerg             else if (sr < n_uword_bits)  // 2 <= sr <= n_uword_bits - 1
    155  1.1.1.2  joerg             {
    156  1.1.1.2  joerg                 q.s.low = 0;
    157  1.1.1.2  joerg                 q.s.high = n.s.low << (n_uword_bits - sr);
    158  1.1.1.2  joerg                 r.s.high = n.s.high >> sr;
    159  1.1.1.2  joerg                 r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
    160  1.1.1.2  joerg             }
    161  1.1.1.2  joerg             else              // n_uword_bits + 1 <= sr <= n_udword_bits - 1
    162  1.1.1.2  joerg             {
    163  1.1.1.2  joerg                 q.s.low = n.s.low << (n_udword_bits - sr);
    164  1.1.1.2  joerg                 q.s.high = (n.s.high << (n_udword_bits - sr)) |
    165  1.1.1.2  joerg                            (n.s.low >> (sr - n_uword_bits));
    166  1.1.1.2  joerg                 r.s.high = 0;
    167  1.1.1.2  joerg                 r.s.low = n.s.high >> (sr - n_uword_bits);
    168  1.1.1.2  joerg             }
    169      1.1  joerg         }
    170      1.1  joerg         else
    171      1.1  joerg         {
    172      1.1  joerg             /* K X
    173      1.1  joerg              * ---
    174      1.1  joerg              * K K
    175      1.1  joerg              */
    176      1.1  joerg             sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
    177      1.1  joerg             /* 0 <= sr <= n_uword_bits - 1 or sr large */
    178      1.1  joerg             if (sr > n_uword_bits - 1)
    179      1.1  joerg             {
    180  1.1.1.2  joerg                 if (rem)
    181      1.1  joerg                     *rem = n.all;
    182      1.1  joerg                 return 0;
    183      1.1  joerg             }
    184      1.1  joerg             ++sr;
    185      1.1  joerg             /* 1 <= sr <= n_uword_bits */
    186      1.1  joerg             /*  q.all = n.all << (n_udword_bits - sr); */
    187      1.1  joerg             q.s.low = 0;
    188  1.1.1.2  joerg             if (sr == n_uword_bits)
    189  1.1.1.2  joerg             {
    190  1.1.1.2  joerg                 q.s.high = n.s.low;
    191  1.1.1.2  joerg                 r.s.high = 0;
    192  1.1.1.2  joerg                 r.s.low = n.s.high;
    193  1.1.1.2  joerg             }
    194  1.1.1.2  joerg             else
    195  1.1.1.2  joerg             {
    196  1.1.1.2  joerg                 q.s.high = n.s.low << (n_uword_bits - sr);
    197  1.1.1.2  joerg                 r.s.high = n.s.high >> sr;
    198  1.1.1.2  joerg                 r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
    199  1.1.1.2  joerg             }
    200      1.1  joerg         }
    201      1.1  joerg     }
    202      1.1  joerg     /* Not a special case
    203      1.1  joerg      * q and r are initialized with:
    204      1.1  joerg      * q.all = n.all << (n_udword_bits - sr);
    205      1.1  joerg      * r.all = n.all >> sr;
    206      1.1  joerg      * 1 <= sr <= n_udword_bits - 1
    207      1.1  joerg      */
    208      1.1  joerg     su_int carry = 0;
    209      1.1  joerg     for (; sr > 0; --sr)
    210      1.1  joerg     {
    211      1.1  joerg         /* r:q = ((r:q)  << 1) | carry */
    212      1.1  joerg         r.s.high = (r.s.high << 1) | (r.s.low  >> (n_uword_bits - 1));
    213      1.1  joerg         r.s.low  = (r.s.low  << 1) | (q.s.high >> (n_uword_bits - 1));
    214      1.1  joerg         q.s.high = (q.s.high << 1) | (q.s.low  >> (n_uword_bits - 1));
    215      1.1  joerg         q.s.low  = (q.s.low  << 1) | carry;
    216      1.1  joerg         /* carry = 0;
    217      1.1  joerg          * if (r.all >= d.all)
    218      1.1  joerg          * {
    219      1.1  joerg          *      r.all -= d.all;
    220      1.1  joerg          *      carry = 1;
    221      1.1  joerg          * }
    222      1.1  joerg          */
    223      1.1  joerg         const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1);
    224      1.1  joerg         carry = s & 1;
    225      1.1  joerg         r.all -= d.all & s;
    226      1.1  joerg     }
    227      1.1  joerg     q.all = (q.all << 1) | carry;
    228      1.1  joerg     if (rem)
    229      1.1  joerg         *rem = r.all;
    230      1.1  joerg     return q.all;
    231      1.1  joerg }
    232