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