blob: 30b846179c01175c4db93336bf7bb80f2fe6b188 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Thomas Chou38f1d982010-05-15 06:00:05 +08002/*
3 * This file is part of GNU CC.
Thomas Chou38f1d982010-05-15 06:00:05 +08004 */
5
6typedef unsigned int UWtype;
7typedef unsigned int UHWtype;
8typedef unsigned long long UDWtype;
9#define W_TYPE_SIZE 32
10
11typedef unsigned char UQItype;
12typedef long SItype;
13typedef unsigned long USItype;
14typedef long long DItype;
15typedef unsigned long long DSItype;
16
17#include "longlong.h"
18
Thomas Chou38f1d982010-05-15 06:00:05 +080019typedef int word_type;
20typedef long Wtype;
21typedef long long DWtype;
22
23struct DWstruct { Wtype low, high;};
24
25typedef union
26{
27 struct DWstruct s;
28 DWtype ll;
29} DWunion;
30
31#define BITS_PER_UNIT 8
32
33UDWtype
34__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp);
35
36const UQItype __clz_tab[256] =
37{
38 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
39 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
40 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
41 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
42 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
43 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
44 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
45 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
46};
47
Thomas Chou38f1d982010-05-15 06:00:05 +080048DWtype
49__ashldi3 (DWtype u, word_type b)
50{
51 if (b == 0)
52 return u;
53
54 const DWunion uu = {.ll = u};
55 const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
56 DWunion w;
57
58 if (bm <= 0)
59 {
60 w.s.low = 0;
61 w.s.high = (UWtype) uu.s.low << -bm;
62 }
63 else
64 {
65 const UWtype carries = (UWtype) uu.s.low >> bm;
66
67 w.s.low = (UWtype) uu.s.low << b;
68 w.s.high = ((UWtype) uu.s.high << b) | carries;
69 }
70
71 return w.ll;
72}
73
74DWtype
75__ashrdi3 (DWtype u, word_type b)
76{
77 if (b == 0)
78 return u;
79
80 const DWunion uu = {.ll = u};
81 const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
82 DWunion w;
83
84 if (bm <= 0)
85 {
86 /* w.s.high = 1..1 or 0..0 */
87 w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
88 w.s.low = uu.s.high >> -bm;
89 }
90 else
91 {
92 const UWtype carries = (UWtype) uu.s.high << bm;
93
94 w.s.high = uu.s.high >> b;
95 w.s.low = ((UWtype) uu.s.low >> b) | carries;
96 }
97
98 return w.ll;
99}
100
101DWtype
102__lshrdi3 (DWtype u, word_type b)
103{
104 if (b == 0)
105 return u;
106
107 const DWunion uu = {.ll = u};
108 const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
109 DWunion w;
110
111 if (bm <= 0)
112 {
113 w.s.high = 0;
114 w.s.low = (UWtype) uu.s.high >> -bm;
115 }
116 else
117 {
118 const UWtype carries = (UWtype) uu.s.high << bm;
119
120 w.s.high = (UWtype) uu.s.high >> b;
121 w.s.low = ((UWtype) uu.s.low >> b) | carries;
122 }
123
124 return w.ll;
125}
126
127word_type
128__cmpdi2 (DWtype a, DWtype b)
129{
130 const DWunion au = {.ll = a};
131 const DWunion bu = {.ll = b};
132
133 if (au.s.high < bu.s.high)
134 return 0;
135 else if (au.s.high > bu.s.high)
136 return 2;
137 if ((UWtype) au.s.low < (UWtype) bu.s.low)
138 return 0;
139 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
140 return 2;
141 return 1;
142}
143
144UDWtype
145__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
146{
147 const DWunion nn = {.ll = n};
148 const DWunion dd = {.ll = d};
149 DWunion rr;
150 UWtype d0, d1, n0, n1, n2;
151 UWtype q0, q1;
152 UWtype b, bm;
153
154 d0 = dd.s.low;
155 d1 = dd.s.high;
156 n0 = nn.s.low;
157 n1 = nn.s.high;
158
159#if !UDIV_NEEDS_NORMALIZATION
160 if (d1 == 0)
161 {
162 if (d0 > n1)
163 {
164 /* 0q = nn / 0D */
165
166 udiv_qrnnd (q0, n0, n1, n0, d0);
167 q1 = 0;
168
169 /* Remainder in n0. */
170 }
171 else
172 {
173 /* qq = NN / 0d */
174
175 if (d0 == 0)
176 d0 = 1 / d0; /* Divide intentionally by zero. */
177
178 udiv_qrnnd (q1, n1, 0, n1, d0);
179 udiv_qrnnd (q0, n0, n1, n0, d0);
180
181 /* Remainder in n0. */
182 }
183
184 if (rp != 0)
185 {
186 rr.s.low = n0;
187 rr.s.high = 0;
188 *rp = rr.ll;
189 }
190 }
191
192#else /* UDIV_NEEDS_NORMALIZATION */
193
194 if (d1 == 0)
195 {
196 if (d0 > n1)
197 {
198 /* 0q = nn / 0D */
199
200 count_leading_zeros (bm, d0);
201
202 if (bm != 0)
203 {
204 /* Normalize, i.e. make the most significant bit of the
205 denominator set. */
206
207 d0 = d0 << bm;
208 n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
209 n0 = n0 << bm;
210 }
211
212 udiv_qrnnd (q0, n0, n1, n0, d0);
213 q1 = 0;
214
215 /* Remainder in n0 >> bm. */
216 }
217 else
218 {
219 /* qq = NN / 0d */
220
221 if (d0 == 0)
222 d0 = 1 / d0; /* Divide intentionally by zero. */
223
224 count_leading_zeros (bm, d0);
225
226 if (bm == 0)
227 {
228 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
229 conclude (the most significant bit of n1 is set) /\ (the
230 leading quotient digit q1 = 1).
231
232 This special case is necessary, not an optimization.
233 (Shifts counts of W_TYPE_SIZE are undefined.) */
234
235 n1 -= d0;
236 q1 = 1;
237 }
238 else
239 {
240 /* Normalize. */
241
242 b = W_TYPE_SIZE - bm;
243
244 d0 = d0 << bm;
245 n2 = n1 >> b;
246 n1 = (n1 << bm) | (n0 >> b);
247 n0 = n0 << bm;
248
249 udiv_qrnnd (q1, n1, n2, n1, d0);
250 }
251
252 /* n1 != d0... */
253
254 udiv_qrnnd (q0, n0, n1, n0, d0);
255
256 /* Remainder in n0 >> bm. */
257 }
258
259 if (rp != 0)
260 {
261 rr.s.low = n0 >> bm;
262 rr.s.high = 0;
263 *rp = rr.ll;
264 }
265 }
266#endif /* UDIV_NEEDS_NORMALIZATION */
267
268 else
269 {
270 if (d1 > n1)
271 {
272 /* 00 = nn / DD */
273
274 q0 = 0;
275 q1 = 0;
276
277 /* Remainder in n1n0. */
278 if (rp != 0)
279 {
280 rr.s.low = n0;
281 rr.s.high = n1;
282 *rp = rr.ll;
283 }
284 }
285 else
286 {
287 /* 0q = NN / dd */
288
289 count_leading_zeros (bm, d1);
290 if (bm == 0)
291 {
292 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
293 conclude (the most significant bit of n1 is set) /\ (the
294 quotient digit q0 = 0 or 1).
295
296 This special case is necessary, not an optimization. */
297
298 /* The condition on the next line takes advantage of that
299 n1 >= d1 (true due to program flow). */
300 if (n1 > d1 || n0 >= d0)
301 {
302 q0 = 1;
303 sub_ddmmss (n1, n0, n1, n0, d1, d0);
304 }
305 else
306 q0 = 0;
307
308 q1 = 0;
309
310 if (rp != 0)
311 {
312 rr.s.low = n0;
313 rr.s.high = n1;
314 *rp = rr.ll;
315 }
316 }
317 else
318 {
319 UWtype m1, m0;
320 /* Normalize. */
321
322 b = W_TYPE_SIZE - bm;
323
324 d1 = (d1 << bm) | (d0 >> b);
325 d0 = d0 << bm;
326 n2 = n1 >> b;
327 n1 = (n1 << bm) | (n0 >> b);
328 n0 = n0 << bm;
329
330 udiv_qrnnd (q0, n1, n2, n1, d1);
331 umul_ppmm (m1, m0, q0, d0);
332
333 if (m1 > n1 || (m1 == n1 && m0 > n0))
334 {
335 q0--;
336 sub_ddmmss (m1, m0, m1, m0, d1, d0);
337 }
338
339 q1 = 0;
340
341 /* Remainder in (n1n0 - m1m0) >> bm. */
342 if (rp != 0)
343 {
344 sub_ddmmss (n1, n0, n1, n0, m1, m0);
345 rr.s.low = (n1 << b) | (n0 >> bm);
346 rr.s.high = n1 >> bm;
347 *rp = rr.ll;
348 }
349 }
350 }
351 }
352
353 const DWunion ww = {{.low = q0, .high = q1}};
354 return ww.ll;
355}
356
357DWtype
358__divdi3 (DWtype u, DWtype v)
359{
360 word_type c = 0;
361 DWunion uu = {.ll = u};
362 DWunion vv = {.ll = v};
363 DWtype w;
364
365 if (uu.s.high < 0)
366 c = ~c,
367 uu.ll = -uu.ll;
368 if (vv.s.high < 0)
369 c = ~c,
370 vv.ll = -vv.ll;
371
372 w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
373 if (c)
374 w = -w;
375
376 return w;
377}
378
379DWtype
380__negdi2 (DWtype u)
381{
382 const DWunion uu = {.ll = u};
383 const DWunion w = { {.low = -uu.s.low,
384 .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } };
385
386 return w.ll;
387}
388
Thomas Chou38f1d982010-05-15 06:00:05 +0800389DWtype
390__muldi3 (DWtype u, DWtype v)
391{
392 const DWunion uu = {.ll = u};
393 const DWunion vv = {.ll = v};
394 DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)};
395
396 w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
397 + (UWtype) uu.s.high * (UWtype) vv.s.low);
398
399 return w.ll;
400}
401
402DWtype
403__moddi3 (DWtype u, DWtype v)
404{
405 word_type c = 0;
406 DWunion uu = {.ll = u};
407 DWunion vv = {.ll = v};
408 DWtype w;
409
410 if (uu.s.high < 0)
411 c = ~c,
412 uu.ll = -uu.ll;
413 if (vv.s.high < 0)
414 vv.ll = -vv.ll;
415
416 (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
417 if (c)
418 w = -w;
419
420 return w;
421}
422
423word_type
424__ucmpdi2 (DWtype a, DWtype b)
425{
426 const DWunion au = {.ll = a};
427 const DWunion bu = {.ll = b};
428
429 if ((UWtype) au.s.high < (UWtype) bu.s.high)
430 return 0;
431 else if ((UWtype) au.s.high > (UWtype) bu.s.high)
432 return 2;
433 if ((UWtype) au.s.low < (UWtype) bu.s.low)
434 return 0;
435 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
436 return 2;
437 return 1;
438}
439
Thomas Chou38f1d982010-05-15 06:00:05 +0800440UDWtype
441__udivdi3 (UDWtype n, UDWtype d)
442{
443 return __udivmoddi4 (n, d, (UDWtype *) 0);
444}
445
446UDWtype
447__umoddi3 (UDWtype u, UDWtype v)
448{
449 UDWtype w;
450 (void) __udivmoddi4 (u, v, &w);
451
452 return w;
453}
454
455static USItype
456udivmodsi4(USItype num, USItype den, word_type modwanted)
457{
458 USItype bit = 1;
459 USItype res = 0;
460
461 while (den < num && bit && !(den & (1L<<31)))
462 {
463 den <<=1;
464 bit <<=1;
465 }
466 while (bit)
467 {
468 if (num >= den)
469 {
470 num -= den;
471 res |= bit;
472 }
473 bit >>=1;
474 den >>=1;
475 }
476 if (modwanted) return num;
477 return res;
478}
479
480SItype
481__divsi3 (SItype a, SItype b)
482{
483 word_type neg = 0;
484 SItype res;
485
486 if (a < 0)
487 {
488 a = -a;
489 neg = !neg;
490 }
491
492 if (b < 0)
493 {
494 b = -b;
495 neg = !neg;
496 }
497
498 res = udivmodsi4 (a, b, 0);
499
500 if (neg)
501 res = -res;
502
503 return res;
504}
505
Thomas Chou38f1d982010-05-15 06:00:05 +0800506SItype
507__udivsi3 (SItype a, SItype b)
508{
509 return udivmodsi4 (a, b, 0);
510}
511
Thomas Chou38f1d982010-05-15 06:00:05 +0800512SItype
513__modsi3 (SItype a, SItype b)
514{
515 word_type neg = 0;
516 SItype res;
517
518 if (a < 0)
519 {
520 a = -a;
521 neg = 1;
522 }
523
524 if (b < 0)
525 b = -b;
526
527 res = udivmodsi4 (a, b, 1);
528
529 if (neg)
530 res = -res;
531
532 return res;
533}
534
535SItype
536__mulsi3 (SItype a, SItype b)
537{
538 SItype res = 0;
539 USItype cnt = a;
540
541 while (cnt)
542 {
543 if (cnt & 1)
Wolfgang Denkec7fbf52013-10-04 17:43:24 +0200544 {
Thomas Chou38f1d982010-05-15 06:00:05 +0800545 res += b;
546 }
547 b <<= 1;
548 cnt >>= 1;
549 }
550
551 return res;
552}
553
554SItype
555__umodsi3 (SItype a, SItype b)
556
557{
558 return udivmodsi4 (a, b, 1);
559}
560
561int
562__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, unsigned long size)
563{
564 while (size > 0)
565 {
566 const unsigned char c1 = *s1++, c2 = *s2++;
567 if (c1 != c2)
568 return c1 - c2;
569 size--;
570 }
571 return 0;
572}