137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* ===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------===
237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *                     The LLVM Compiler Infrastructure
437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
59ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * This file is dual licensed under the MIT and the University of Illinois Open
69ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * Source Licenses. See LICENSE.TXT for details.
737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * ===----------------------------------------------------------------------===
937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
1037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * This file implements __udivmoddi4 for the compiler_rt library.
1137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
1237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * ===----------------------------------------------------------------------===
1337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */
14b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
15b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar#include "int_lib.h"
16b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
1737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* Effects: if rem != 0, *rem = a % b
1837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * Returns: a / b
1937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */
20b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
2137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */
22b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
231c5f89b1dd741135a4007ab577723d422f421eecAnton KorobeynikovCOMPILER_RT_ABI du_int
24b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar__udivmoddi4(du_int a, du_int b, du_int* rem)
25b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar{
26b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
27b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
28b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    udwords n;
29b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    n.all = a;
30b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    udwords d;
31b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    d.all = b;
32b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    udwords q;
33b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    udwords r;
34b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    unsigned sr;
3537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan    /* special cases, X is unknown, K != 0 */
368bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan    if (n.s.high == 0)
37b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
388bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        if (d.s.high == 0)
39b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        {
4037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /* 0 X
4137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * ---
4237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * 0 X
4337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             */
44b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            if (rem)
458bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                *rem = n.s.low % d.s.low;
468bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan            return n.s.low / d.s.low;
47b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        }
4837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* 0 X
4937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         * ---
5037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         * K X
5137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         */
52b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        if (rem)
538bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan            *rem = n.s.low;
54b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        return 0;
55b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
568bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan    /* n.s.high != 0 */
578bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan    if (d.s.low == 0)
58b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
598bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        if (d.s.high == 0)
60b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        {
6137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /* K X
6237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * ---
6337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * 0 0
6437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             */
65b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            if (rem)
668bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                *rem = n.s.high % d.s.low;
678bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan            return n.s.high / d.s.low;
68b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        }
698bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        /* d.s.high != 0 */
708bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        if (n.s.low == 0)
71b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        {
7237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /* K 0
7337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * ---
7437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * K 0
7537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             */
76b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            if (rem)
77b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            {
788bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                r.s.high = n.s.high % d.s.high;
798bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                r.s.low = 0;
80b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar                *rem = r.all;
81b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            }
828bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan            return n.s.high / d.s.high;
83b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        }
8437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* K K
8537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         * ---
8637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         * K 0
8737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         */
888bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        if ((d.s.high & (d.s.high - 1)) == 0)     /* if d is a power of 2 */
89b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        {
90b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            if (rem)
91b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            {
928bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                r.s.low = n.s.low;
938bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                r.s.high = n.s.high & (d.s.high - 1);
94b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar                *rem = r.all;
95b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            }
968bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan            return n.s.high >> __builtin_ctz(d.s.high);
97b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        }
9837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* K K
9937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         * ---
10037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         * K 0
10137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         */
1028bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
10337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* 0 <= sr <= n_uword_bits - 2 or sr large */
104b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        if (sr > n_uword_bits - 2)
105b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        {
106b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar           if (rem)
107b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar                *rem = n.all;
108b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            return 0;
109b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        }
110b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        ++sr;
11137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* 1 <= sr <= n_uword_bits - 1 */
11237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* q.all = n.all << (n_udword_bits - sr); */
1138bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        q.s.low = 0;
1148bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        q.s.high = n.s.low << (n_uword_bits - sr);
11537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* r.all = n.all >> sr; */
1168bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        r.s.high = n.s.high >> sr;
1178bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
118b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
1198bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan    else  /* d.s.low != 0 */
120b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
1218bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        if (d.s.high == 0)
122b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        {
12337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /* K X
12437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * ---
12537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * 0 K
12637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             */
1278bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan            if ((d.s.low & (d.s.low - 1)) == 0)     /* if d is a power of 2 */
128b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            {
129b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar                if (rem)
1308bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                    *rem = n.s.low & (d.s.low - 1);
1318bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                if (d.s.low == 1)
132b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar                    return n.all;
133d426091fdf6a15db9a5db35d522fe69f5dee35afJoerg Sonnenberger                sr = __builtin_ctz(d.s.low);
1348bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                q.s.high = n.s.high >> sr;
1358bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan                q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
136b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar                return q.all;
137b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            }
13837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /* K X
13937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * ---
1402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines             * 0 K
14137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             */
1428bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan            sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high);
14337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /* 2 <= sr <= n_udword_bits - 1
14437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * q.all = n.all << (n_udword_bits - sr);
14537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * r.all = n.all >> sr;
14637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             */
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            if (sr == n_uword_bits)
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            {
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                q.s.low = 0;
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                q.s.high = n.s.low;
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.high = 0;
1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.low = n.s.high;
1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            }
1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            else if (sr < n_uword_bits)  // 2 <= sr <= n_uword_bits - 1
1552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            {
1562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                q.s.low = 0;
1572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                q.s.high = n.s.low << (n_uword_bits - sr);
1582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.high = n.s.high >> sr;
1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
1602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            }
1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            else              // n_uword_bits + 1 <= sr <= n_udword_bits - 1
1622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            {
1632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                q.s.low = n.s.low << (n_udword_bits - sr);
1642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                q.s.high = (n.s.high << (n_udword_bits - sr)) |
1652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                           (n.s.low >> (sr - n_uword_bits));
1662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.high = 0;
1672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.low = n.s.high >> (sr - n_uword_bits);
1682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            }
169b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        }
170b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        else
171b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        {
17237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /* K X
17337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * ---
17437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             * K K
17537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan             */
1768bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan            sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high);
17737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /* 0 <= sr <= n_uword_bits - 1 or sr large */
178b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            if (sr > n_uword_bits - 1)
179b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            {
1802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                if (rem)
181b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar                    *rem = n.all;
182b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar                return 0;
183b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            }
184b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            ++sr;
18537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /* 1 <= sr <= n_uword_bits */
18637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan            /*  q.all = n.all << (n_udword_bits - sr); */
1878bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan            q.s.low = 0;
1882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            if (sr == n_uword_bits)
1892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            {
1902d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                q.s.high = n.s.low;
1912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.high = 0;
1922d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.low = n.s.high;
1932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            }
1942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            else
1952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            {
1962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                q.s.high = n.s.low << (n_uword_bits - sr);
1972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.high = n.s.high >> sr;
1982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
1992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines            }
200b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        }
201b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
20237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan    /* Not a special case
20337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan     * q and r are initialized with:
20437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan     * q.all = n.all << (n_udword_bits - sr);
20537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan     * r.all = n.all >> sr;
20637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan     * 1 <= sr <= n_udword_bits - 1
20737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan     */
208b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    su_int carry = 0;
209b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    for (; sr > 0; --sr)
210b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
21137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* r:q = ((r:q)  << 1) | carry */
2128bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        r.s.high = (r.s.high << 1) | (r.s.low  >> (n_uword_bits - 1));
2138bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        r.s.low  = (r.s.low  << 1) | (q.s.high >> (n_uword_bits - 1));
2148bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        q.s.high = (q.s.high << 1) | (q.s.low  >> (n_uword_bits - 1));
2158bf1e094893cb24796137b47ee0d46d18d299996Edward O'Callaghan        q.s.low  = (q.s.low  << 1) | carry;
21637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* carry = 0;
21737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         * if (r.all >= d.all)
21837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         * {
21937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         *      r.all -= d.all;
22037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         *      carry = 1;
22137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         * }
22237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         */
223b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1);
224b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        carry = s & 1;
225b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        r.all -= d.all & s;
226b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
227b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    q.all = (q.all << 1) | carry;
228b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    if (rem)
229b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        *rem = r.all;
230b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    return q.all;
231b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar}
232