xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/builtins/udivsi3.c (revision d31434597b255f3fd7646698e04170d148f1de49)
1156cd587Sjoerg /* ===-- udivsi3.c - Implement __udivsi3 -----------------------------------===
2156cd587Sjoerg  *
3156cd587Sjoerg  *                     The LLVM Compiler Infrastructure
4156cd587Sjoerg  *
5156cd587Sjoerg  * This file is dual licensed under the MIT and the University of Illinois Open
6156cd587Sjoerg  * Source Licenses. See LICENSE.TXT for details.
7156cd587Sjoerg  *
8156cd587Sjoerg  * ===----------------------------------------------------------------------===
9156cd587Sjoerg  *
10156cd587Sjoerg  * This file implements __udivsi3 for the compiler_rt library.
11156cd587Sjoerg  *
12156cd587Sjoerg  * ===----------------------------------------------------------------------===
13156cd587Sjoerg  */
14156cd587Sjoerg 
15156cd587Sjoerg #include "int_lib.h"
16156cd587Sjoerg 
17156cd587Sjoerg /* Returns: a / b */
18156cd587Sjoerg 
19156cd587Sjoerg /* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */
20156cd587Sjoerg 
21156cd587Sjoerg /* This function should not call __divsi3! */
22156cd587Sjoerg COMPILER_RT_ABI su_int
__udivsi3(su_int n,su_int d)23156cd587Sjoerg __udivsi3(su_int n, su_int d)
24156cd587Sjoerg {
25156cd587Sjoerg     const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
26156cd587Sjoerg     su_int q;
27156cd587Sjoerg     su_int r;
28156cd587Sjoerg     unsigned sr;
29156cd587Sjoerg     /* special cases */
30156cd587Sjoerg     if (d == 0)
31156cd587Sjoerg         return 0; /* ?! */
32156cd587Sjoerg     if (n == 0)
33156cd587Sjoerg         return 0;
34156cd587Sjoerg     sr = __builtin_clz(d) - __builtin_clz(n);
35156cd587Sjoerg     /* 0 <= sr <= n_uword_bits - 1 or sr large */
36156cd587Sjoerg     if (sr > n_uword_bits - 1)  /* d > r */
37156cd587Sjoerg         return 0;
38156cd587Sjoerg     if (sr == n_uword_bits - 1)  /* d == 1 */
39156cd587Sjoerg         return n;
40156cd587Sjoerg     ++sr;
41156cd587Sjoerg     /* 1 <= sr <= n_uword_bits - 1 */
42156cd587Sjoerg     /* Not a special case */
43156cd587Sjoerg     q = n << (n_uword_bits - sr);
44156cd587Sjoerg     r = n >> sr;
45156cd587Sjoerg     su_int carry = 0;
46156cd587Sjoerg     for (; sr > 0; --sr)
47156cd587Sjoerg     {
48156cd587Sjoerg         /* r:q = ((r:q)  << 1) | carry */
49156cd587Sjoerg         r = (r << 1) | (q >> (n_uword_bits - 1));
50156cd587Sjoerg         q = (q << 1) | carry;
51156cd587Sjoerg         /* carry = 0;
52156cd587Sjoerg          * if (r.all >= d.all)
53156cd587Sjoerg          * {
54156cd587Sjoerg          *      r.all -= d.all;
55156cd587Sjoerg          *      carry = 1;
56156cd587Sjoerg          * }
57156cd587Sjoerg          */
58156cd587Sjoerg         const si_int s = (si_int)(d - r - 1) >> (n_uword_bits - 1);
59156cd587Sjoerg         carry = s & 1;
60156cd587Sjoerg         r -= d & s;
61156cd587Sjoerg     }
62156cd587Sjoerg     q = (q << 1) | carry;
63156cd587Sjoerg     return q;
64156cd587Sjoerg }
653044ee7eSrin 
663044ee7eSrin #if defined(__ARM_EABI__)
67*d3143459Srin AEABI_RTABI su_int __aeabi_uidiv(su_int n, su_int d) COMPILER_RT_ALIAS(__udivsi3);
683044ee7eSrin #endif
69