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