|
29 | 29 |
|
30 | 30 | extern "C" { |
31 | 31 |
|
| 32 | +typedef signed long long DItype __attribute__((mode (DI))); |
| 33 | +typedef unsigned long long UDItype __attribute__((mode (DI))); |
| 34 | +typedef unsigned int USItype __attribute__((mode (SI))); |
| 35 | + |
| 36 | +extern int __builtin_clzll(unsigned long long); |
| 37 | + |
| 38 | +#define DWtype DItype |
| 39 | +#define UDWtype UDItype |
| 40 | +#define UWtype USItype |
| 41 | + |
| 42 | +UDWtype __udivdi3 (UDWtype n, UDWtype d); |
| 43 | +UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp); |
| 44 | +UDWtype __umoddi3 (UDWtype u, UDWtype v); |
| 45 | + |
| 46 | +UDWtype __udivdi3 (UDWtype n, UDWtype d) |
| 47 | +{ |
| 48 | + return __udivmoddi4 (n, d, (UDWtype *) 0); |
| 49 | +} |
| 50 | + |
| 51 | +UDWtype __umoddi3 (UDWtype u, UDWtype v) |
| 52 | +{ |
| 53 | + UDWtype w; |
| 54 | + |
| 55 | + (void) __udivmoddi4 (u, v, &w); |
| 56 | + |
| 57 | + return w; |
| 58 | +} |
| 59 | + |
| 60 | +UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) |
| 61 | +{ |
| 62 | + UDWtype q = 0, r = n, y = d; |
| 63 | + UWtype lz1, lz2, i, k; |
| 64 | + |
| 65 | + // Implements align divisor shift dividend method. This algorithm |
| 66 | + // aligns the divisor under the dividend and then perform number of |
| 67 | + // test-subtract iterations which shift the dividend left. Number of |
| 68 | + // iterations is k + 1 where k is the number of bit positions the |
| 69 | + // divisor must be shifted left to align it under the dividend. |
| 70 | + // quotient bits can be saved in the rightmost positions of the dividend |
| 71 | + // as it shifts left on each test-subtract iteration. |
| 72 | + |
| 73 | + if (y <= r) |
| 74 | + { |
| 75 | + lz1 = static_cast<USItype>(__builtin_clzll(static_cast<unsigned long long>(d))); |
| 76 | + lz2 = static_cast<USItype>(__builtin_clzll(static_cast<unsigned long long>(n))); |
| 77 | + |
| 78 | + k = lz1 - lz2; |
| 79 | + y = (y << k); |
| 80 | + |
| 81 | + // Dividend can exceed 2 ^ (width - 1) - 1 but still be less than the |
| 82 | + // aligned divisor. Normal iteration can drops the high order bit |
| 83 | + // of the dividend. Therefore, first test-subtract iteration is a |
| 84 | + // special case, saving its quotient bit in a separate location and |
| 85 | + // not shifting the dividend. |
| 86 | + |
| 87 | + if (r >= y) |
| 88 | + { |
| 89 | + r = r - y; |
| 90 | + q = (1ULL << k); |
| 91 | + } |
| 92 | + |
| 93 | + if (k > 0) |
| 94 | + { |
| 95 | + y = y >> 1; |
| 96 | + |
| 97 | + // k additional iterations where k regular test subtract shift |
| 98 | + // dividend iterations are done. |
| 99 | + |
| 100 | + i = k; |
| 101 | + |
| 102 | + do |
| 103 | + { |
| 104 | + if (r >= y) |
| 105 | + { |
| 106 | + r = ((r - y) << 1) + 1; |
| 107 | + } |
| 108 | + else |
| 109 | + { |
| 110 | + r = (r << 1); |
| 111 | + } |
| 112 | + |
| 113 | + i = i - 1; |
| 114 | + } |
| 115 | + while (i != 0); |
| 116 | + |
| 117 | + // First quotient bit is combined with the quotient bits resulting |
| 118 | + // from the k regular iterations. |
| 119 | + |
| 120 | + q = q + r; |
| 121 | + r = r >> k; |
| 122 | + q = q - (r << k); |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + if (rp) |
| 127 | + { |
| 128 | + *rp = r; |
| 129 | + } |
| 130 | + |
| 131 | + return q; |
| 132 | +} |
| 133 | + |
32 | 134 | #if defined(__GNUC__) |
33 | 135 | #pragma GCC diagnostic push |
34 | 136 | #pragma GCC diagnostic ignored "-Wcast-align" |
|
0 commit comments