| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * Copyright (C) 1989-2013 Free Software Foundation, Inc. |
| */ |
| |
| #include "libgcc2.h" |
| |
| DWtype |
| __ashldi3(DWtype u, shift_count_type b) |
| { |
| if (b == 0) |
| return u; |
| |
| const DWunion uu = {.ll = u}; |
| const shift_count_type bm = W_TYPE_SIZE - b; |
| DWunion w; |
| |
| if (bm <= 0) { |
| w.s.low = 0; |
| w.s.high = (UWtype)uu.s.low << -bm; |
| } else { |
| const UWtype carries = (UWtype) uu.s.low >> bm; |
| |
| w.s.low = (UWtype)uu.s.low << b; |
| w.s.high = ((UWtype)uu.s.high << b) | carries; |
| } |
| |
| return w.ll; |
| } |
| |
| DWtype |
| __ashrdi3(DWtype u, shift_count_type b) |
| { |
| if (b == 0) |
| return u; |
| |
| const DWunion uu = {.ll = u}; |
| const shift_count_type bm = W_TYPE_SIZE - b; |
| DWunion w; |
| |
| if (bm <= 0) { |
| /* w.s.high = 1..1 or 0..0 */ |
| w.s.high = uu.s.high >> (W_TYPE_SIZE - 1); |
| w.s.low = uu.s.high >> -bm; |
| } else { |
| const UWtype carries = (UWtype) uu.s.high << bm; |
| |
| w.s.high = uu.s.high >> b; |
| w.s.low = ((UWtype)uu.s.low >> b) | carries; |
| } |
| |
| return w.ll; |
| } |
| |
| DWtype |
| __lshrdi3(DWtype u, shift_count_type b) |
| { |
| if (b == 0) |
| return u; |
| |
| const DWunion uu = {.ll = u}; |
| const shift_count_type bm = W_TYPE_SIZE - b; |
| DWunion w; |
| |
| if (bm <= 0) { |
| w.s.high = 0; |
| w.s.low = (UWtype)uu.s.high >> -bm; |
| } else { |
| const UWtype carries = (UWtype)uu.s.high << bm; |
| |
| w.s.high = (UWtype)uu.s.high >> b; |
| w.s.low = ((UWtype)uu.s.low >> b) | carries; |
| } |
| |
| return w.ll; |
| } |
| |
| unsigned long |
| udivmodsi4(unsigned long num, unsigned long den, int modwanted) |
| { |
| unsigned long bit = 1; |
| unsigned long res = 0; |
| |
| while (den < num && bit && !(den & (1L<<31))) { |
| den <<= 1; |
| bit <<= 1; |
| } |
| |
| while (bit) { |
| if (num >= den) { |
| num -= den; |
| res |= bit; |
| } |
| bit >>= 1; |
| den >>= 1; |
| } |
| |
| if (modwanted) |
| return num; |
| |
| return res; |
| } |
| |
| long |
| __divsi3(long a, long b) |
| { |
| int neg = 0; |
| long res; |
| |
| if (a < 0) { |
| a = -a; |
| neg = !neg; |
| } |
| |
| if (b < 0) { |
| b = -b; |
| neg = !neg; |
| } |
| |
| res = udivmodsi4(a, b, 0); |
| |
| if (neg) |
| res = -res; |
| |
| return res; |
| } |
| |
| long |
| __modsi3(long a, long b) |
| { |
| int neg = 0; |
| long res; |
| |
| if (a < 0) { |
| a = -a; |
| neg = 1; |
| } |
| |
| if (b < 0) |
| b = -b; |
| |
| res = udivmodsi4(a, b, 1); |
| |
| if (neg) |
| res = -res; |
| |
| return res; |
| } |
| |
| long |
| __udivsi3(long a, long b) |
| { |
| return udivmodsi4(a, b, 0); |
| } |
| |
| long |
| __umodsi3(long a, long b) |
| { |
| return udivmodsi4(a, b, 1); |
| } |
| |
| UDWtype |
| __udivmoddi4(UDWtype n, UDWtype d, UDWtype *rp) |
| { |
| UDWtype q = 0, r = n, y = d; |
| UWtype lz1, lz2, i, k; |
| |
| /* |
| * Implements align divisor shift dividend method. This algorithm |
| * aligns the divisor under the dividend and then perform number of |
| * test-subtract iterations which shift the dividend left. Number of |
| * iterations is k + 1 where k is the number of bit positions the |
| * divisor must be shifted left to align it under the dividend. |
| * quotient bits can be saved in the rightmost positions of the |
| * dividend as it shifts left on each test-subtract iteration. |
| */ |
| |
| if (y <= r) { |
| lz1 = __builtin_clzll(d); |
| lz2 = __builtin_clzll(n); |
| |
| k = lz1 - lz2; |
| y = (y << k); |
| |
| /* |
| * Dividend can exceed 2 ^ (width - 1) - 1 but still be less |
| * than the aligned divisor. Normal iteration can drops the |
| * high order bit of the dividend. Therefore, first |
| * test-subtract iteration is a special case, saving its |
| * quotient bit in a separate location and not shifting |
| * the dividend. |
| */ |
| |
| if (r >= y) { |
| r = r - y; |
| q = (1ULL << k); |
| } |
| |
| if (k > 0) { |
| y = y >> 1; |
| |
| /* |
| * k additional iterations where k regular test |
| * subtract shift dividend iterations are done. |
| */ |
| i = k; |
| do { |
| if (r >= y) |
| r = ((r - y) << 1) + 1; |
| else |
| r = (r << 1); |
| i = i - 1; |
| } while (i != 0); |
| |
| /* |
| * First quotient bit is combined with the quotient |
| * bits resulting from the k regular iterations. |
| */ |
| q = q + r; |
| r = r >> k; |
| q = q - (r << k); |
| } |
| } |
| |
| if (rp) |
| *rp = r; |
| |
| return q; |
| } |
| |
| UDWtype |
| __udivdi3(UDWtype n, UDWtype d) |
| { |
| return __udivmoddi4(n, d, (UDWtype *)0); |
| } |