udivsi3.c revision 214152
1214152Sed/* ===-- udivsi3.c - Implement __udivsi3 -----------------------------------===
2214152Sed *
3214152Sed *                     The LLVM Compiler Infrastructure
4214152Sed *
5214152Sed * This file is distributed under the University of Illinois Open Source
6214152Sed * License. See LICENSE.TXT for details.
7214152Sed *
8214152Sed * ===----------------------------------------------------------------------===
9214152Sed *
10214152Sed * This file implements __udivsi3 for the compiler_rt library.
11214152Sed *
12214152Sed * ===----------------------------------------------------------------------===
13214152Sed */
14214152Sed
15214152Sed#include "int_lib.h"
16214152Sed
17214152Sed/* Returns: a / b */
18214152Sed
19214152Sed/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */
20214152Sed
21214152Sedsu_int
22214152Sed__udivsi3(su_int n, su_int d)
23214152Sed{
24214152Sed    const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
25214152Sed    su_int q;
26214152Sed    su_int r;
27214152Sed    unsigned sr;
28214152Sed    /* special cases */
29214152Sed    if (d == 0)
30214152Sed        return 0; /* ?! */
31214152Sed    if (n == 0)
32214152Sed        return 0;
33214152Sed    sr = __builtin_clz(d) - __builtin_clz(n);
34214152Sed    /* 0 <= sr <= n_uword_bits - 1 or sr large */
35214152Sed    if (sr > n_uword_bits - 1)  /* d > r */
36214152Sed        return 0;
37214152Sed    if (sr == n_uword_bits - 1)  /* d == 1 */
38214152Sed        return n;
39214152Sed    ++sr;
40214152Sed    /* 1 <= sr <= n_uword_bits - 1 */
41214152Sed    /* Not a special case */
42214152Sed    q = n << (n_uword_bits - sr);
43214152Sed    r = n >> sr;
44214152Sed    su_int carry = 0;
45214152Sed    for (; sr > 0; --sr)
46214152Sed    {
47214152Sed        /* r:q = ((r:q)  << 1) | carry */
48214152Sed        r = (r << 1) | (q >> (n_uword_bits - 1));
49214152Sed        q = (q << 1) | carry;
50214152Sed        /* carry = 0;
51214152Sed         * if (r.all >= d.all)
52214152Sed         * {
53214152Sed         *      r.all -= d.all;
54214152Sed         *      carry = 1;
55214152Sed         * }
56214152Sed         */
57214152Sed        const si_int s = (si_int)(d - r - 1) >> (n_uword_bits - 1);
58214152Sed        carry = s & 1;
59214152Sed        r -= d & s;
60214152Sed    }
61214152Sed    q = (q << 1) | carry;
62214152Sed    return q;
63214152Sed}
64