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