Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "prlong.h" |
michael@0 | 7 | |
michael@0 | 8 | static PRInt64 ll_zero = LL_INIT( 0x00000000,0x00000000 ); |
michael@0 | 9 | static PRInt64 ll_maxint = LL_INIT( 0x7fffffff, 0xffffffff ); |
michael@0 | 10 | static PRInt64 ll_minint = LL_INIT( 0x80000000, 0x00000000 ); |
michael@0 | 11 | static PRUint64 ll_maxuint = LL_INIT( 0xffffffff, 0xffffffff ); |
michael@0 | 12 | |
michael@0 | 13 | PR_IMPLEMENT(PRInt64) LL_Zero(void) { return ll_zero; } |
michael@0 | 14 | PR_IMPLEMENT(PRInt64) LL_MaxInt(void) { return ll_maxint; } |
michael@0 | 15 | PR_IMPLEMENT(PRInt64) LL_MinInt(void) { return ll_minint; } |
michael@0 | 16 | PR_IMPLEMENT(PRUint64) LL_MaxUint(void) { return ll_maxuint; } |
michael@0 | 17 | |
michael@0 | 18 | #ifndef HAVE_LONG_LONG |
michael@0 | 19 | /* |
michael@0 | 20 | ** Divide 64-bit a by 32-bit b, which must be normalized so its high bit is 1. |
michael@0 | 21 | */ |
michael@0 | 22 | static void norm_udivmod32(PRUint32 *qp, PRUint32 *rp, PRUint64 a, PRUint32 b) |
michael@0 | 23 | { |
michael@0 | 24 | PRUint32 d1, d0, q1, q0; |
michael@0 | 25 | PRUint32 r1, r0, m; |
michael@0 | 26 | |
michael@0 | 27 | d1 = _hi16(b); |
michael@0 | 28 | d0 = _lo16(b); |
michael@0 | 29 | r1 = a.hi % d1; |
michael@0 | 30 | q1 = a.hi / d1; |
michael@0 | 31 | m = q1 * d0; |
michael@0 | 32 | r1 = (r1 << 16) | _hi16(a.lo); |
michael@0 | 33 | if (r1 < m) { |
michael@0 | 34 | q1--, r1 += b; |
michael@0 | 35 | if (r1 >= b /* i.e., we didn't get a carry when adding to r1 */ |
michael@0 | 36 | && r1 < m) { |
michael@0 | 37 | q1--, r1 += b; |
michael@0 | 38 | } |
michael@0 | 39 | } |
michael@0 | 40 | r1 -= m; |
michael@0 | 41 | r0 = r1 % d1; |
michael@0 | 42 | q0 = r1 / d1; |
michael@0 | 43 | m = q0 * d0; |
michael@0 | 44 | r0 = (r0 << 16) | _lo16(a.lo); |
michael@0 | 45 | if (r0 < m) { |
michael@0 | 46 | q0--, r0 += b; |
michael@0 | 47 | if (r0 >= b |
michael@0 | 48 | && r0 < m) { |
michael@0 | 49 | q0--, r0 += b; |
michael@0 | 50 | } |
michael@0 | 51 | } |
michael@0 | 52 | *qp = (q1 << 16) | q0; |
michael@0 | 53 | *rp = r0 - m; |
michael@0 | 54 | } |
michael@0 | 55 | |
michael@0 | 56 | static PRUint32 CountLeadingZeros(PRUint32 a) |
michael@0 | 57 | { |
michael@0 | 58 | PRUint32 t; |
michael@0 | 59 | PRUint32 r = 32; |
michael@0 | 60 | |
michael@0 | 61 | if ((t = a >> 16) != 0) |
michael@0 | 62 | r -= 16, a = t; |
michael@0 | 63 | if ((t = a >> 8) != 0) |
michael@0 | 64 | r -= 8, a = t; |
michael@0 | 65 | if ((t = a >> 4) != 0) |
michael@0 | 66 | r -= 4, a = t; |
michael@0 | 67 | if ((t = a >> 2) != 0) |
michael@0 | 68 | r -= 2, a = t; |
michael@0 | 69 | if ((t = a >> 1) != 0) |
michael@0 | 70 | r -= 1, a = t; |
michael@0 | 71 | if (a & 1) |
michael@0 | 72 | r--; |
michael@0 | 73 | return r; |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | PR_IMPLEMENT(void) ll_udivmod(PRUint64 *qp, PRUint64 *rp, PRUint64 a, PRUint64 b) |
michael@0 | 77 | { |
michael@0 | 78 | PRUint32 n0, n1, n2; |
michael@0 | 79 | PRUint32 q0, q1; |
michael@0 | 80 | PRUint32 rsh, lsh; |
michael@0 | 81 | |
michael@0 | 82 | n0 = a.lo; |
michael@0 | 83 | n1 = a.hi; |
michael@0 | 84 | |
michael@0 | 85 | if (b.hi == 0) { |
michael@0 | 86 | if (b.lo > n1) { |
michael@0 | 87 | /* (0 q0) = (n1 n0) / (0 D0) */ |
michael@0 | 88 | |
michael@0 | 89 | lsh = CountLeadingZeros(b.lo); |
michael@0 | 90 | |
michael@0 | 91 | if (lsh) { |
michael@0 | 92 | /* |
michael@0 | 93 | * Normalize, i.e. make the most significant bit of the |
michael@0 | 94 | * denominator be set. |
michael@0 | 95 | */ |
michael@0 | 96 | b.lo = b.lo << lsh; |
michael@0 | 97 | n1 = (n1 << lsh) | (n0 >> (32 - lsh)); |
michael@0 | 98 | n0 = n0 << lsh; |
michael@0 | 99 | } |
michael@0 | 100 | |
michael@0 | 101 | a.lo = n0, a.hi = n1; |
michael@0 | 102 | norm_udivmod32(&q0, &n0, a, b.lo); |
michael@0 | 103 | q1 = 0; |
michael@0 | 104 | |
michael@0 | 105 | /* remainder is in n0 >> lsh */ |
michael@0 | 106 | } else { |
michael@0 | 107 | /* (q1 q0) = (n1 n0) / (0 d0) */ |
michael@0 | 108 | |
michael@0 | 109 | if (b.lo == 0) /* user wants to divide by zero! */ |
michael@0 | 110 | b.lo = 1 / b.lo; /* so go ahead and crash */ |
michael@0 | 111 | |
michael@0 | 112 | lsh = CountLeadingZeros(b.lo); |
michael@0 | 113 | |
michael@0 | 114 | if (lsh == 0) { |
michael@0 | 115 | /* |
michael@0 | 116 | * From (n1 >= b.lo) |
michael@0 | 117 | * && (the most significant bit of b.lo is set), |
michael@0 | 118 | * conclude that |
michael@0 | 119 | * (the most significant bit of n1 is set) |
michael@0 | 120 | * && (the leading quotient digit q1 = 1). |
michael@0 | 121 | * |
michael@0 | 122 | * This special case is necessary, not an optimization |
michael@0 | 123 | * (Shifts counts of 32 are undefined). |
michael@0 | 124 | */ |
michael@0 | 125 | n1 -= b.lo; |
michael@0 | 126 | q1 = 1; |
michael@0 | 127 | } else { |
michael@0 | 128 | /* |
michael@0 | 129 | * Normalize. |
michael@0 | 130 | */ |
michael@0 | 131 | rsh = 32 - lsh; |
michael@0 | 132 | |
michael@0 | 133 | b.lo = b.lo << lsh; |
michael@0 | 134 | n2 = n1 >> rsh; |
michael@0 | 135 | n1 = (n1 << lsh) | (n0 >> rsh); |
michael@0 | 136 | n0 = n0 << lsh; |
michael@0 | 137 | |
michael@0 | 138 | a.lo = n1, a.hi = n2; |
michael@0 | 139 | norm_udivmod32(&q1, &n1, a, b.lo); |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | /* n1 != b.lo... */ |
michael@0 | 143 | |
michael@0 | 144 | a.lo = n0, a.hi = n1; |
michael@0 | 145 | norm_udivmod32(&q0, &n0, a, b.lo); |
michael@0 | 146 | |
michael@0 | 147 | /* remainder in n0 >> lsh */ |
michael@0 | 148 | } |
michael@0 | 149 | |
michael@0 | 150 | if (rp) { |
michael@0 | 151 | rp->lo = n0 >> lsh; |
michael@0 | 152 | rp->hi = 0; |
michael@0 | 153 | } |
michael@0 | 154 | } else { |
michael@0 | 155 | if (b.hi > n1) { |
michael@0 | 156 | /* (0 0) = (n1 n0) / (D1 d0) */ |
michael@0 | 157 | |
michael@0 | 158 | q0 = 0; |
michael@0 | 159 | q1 = 0; |
michael@0 | 160 | |
michael@0 | 161 | /* remainder in (n1 n0) */ |
michael@0 | 162 | if (rp) { |
michael@0 | 163 | rp->lo = n0; |
michael@0 | 164 | rp->hi = n1; |
michael@0 | 165 | } |
michael@0 | 166 | } else { |
michael@0 | 167 | /* (0 q0) = (n1 n0) / (d1 d0) */ |
michael@0 | 168 | |
michael@0 | 169 | lsh = CountLeadingZeros(b.hi); |
michael@0 | 170 | if (lsh == 0) { |
michael@0 | 171 | /* |
michael@0 | 172 | * From (n1 >= b.hi) |
michael@0 | 173 | * && (the most significant bit of b.hi is set), |
michael@0 | 174 | * conclude that |
michael@0 | 175 | * (the most significant bit of n1 is set) |
michael@0 | 176 | * && (the quotient digit q0 = 0 or 1). |
michael@0 | 177 | * |
michael@0 | 178 | * This special case is necessary, not an optimization. |
michael@0 | 179 | */ |
michael@0 | 180 | |
michael@0 | 181 | /* |
michael@0 | 182 | * The condition on the next line takes advantage of that |
michael@0 | 183 | * n1 >= b.hi (true due to control flow). |
michael@0 | 184 | */ |
michael@0 | 185 | if (n1 > b.hi || n0 >= b.lo) { |
michael@0 | 186 | q0 = 1; |
michael@0 | 187 | a.lo = n0, a.hi = n1; |
michael@0 | 188 | LL_SUB(a, a, b); |
michael@0 | 189 | } else { |
michael@0 | 190 | q0 = 0; |
michael@0 | 191 | } |
michael@0 | 192 | q1 = 0; |
michael@0 | 193 | |
michael@0 | 194 | if (rp) { |
michael@0 | 195 | rp->lo = n0; |
michael@0 | 196 | rp->hi = n1; |
michael@0 | 197 | } |
michael@0 | 198 | } else { |
michael@0 | 199 | PRInt64 m; |
michael@0 | 200 | |
michael@0 | 201 | /* |
michael@0 | 202 | * Normalize. |
michael@0 | 203 | */ |
michael@0 | 204 | rsh = 32 - lsh; |
michael@0 | 205 | |
michael@0 | 206 | b.hi = (b.hi << lsh) | (b.lo >> rsh); |
michael@0 | 207 | b.lo = b.lo << lsh; |
michael@0 | 208 | n2 = n1 >> rsh; |
michael@0 | 209 | n1 = (n1 << lsh) | (n0 >> rsh); |
michael@0 | 210 | n0 = n0 << lsh; |
michael@0 | 211 | |
michael@0 | 212 | a.lo = n1, a.hi = n2; |
michael@0 | 213 | norm_udivmod32(&q0, &n1, a, b.hi); |
michael@0 | 214 | LL_MUL32(m, q0, b.lo); |
michael@0 | 215 | |
michael@0 | 216 | if ((m.hi > n1) || ((m.hi == n1) && (m.lo > n0))) { |
michael@0 | 217 | q0--; |
michael@0 | 218 | LL_SUB(m, m, b); |
michael@0 | 219 | } |
michael@0 | 220 | |
michael@0 | 221 | q1 = 0; |
michael@0 | 222 | |
michael@0 | 223 | /* Remainder is ((n1 n0) - (m1 m0)) >> lsh */ |
michael@0 | 224 | if (rp) { |
michael@0 | 225 | a.lo = n0, a.hi = n1; |
michael@0 | 226 | LL_SUB(a, a, m); |
michael@0 | 227 | rp->lo = (a.hi << rsh) | (a.lo >> lsh); |
michael@0 | 228 | rp->hi = a.hi >> lsh; |
michael@0 | 229 | } |
michael@0 | 230 | } |
michael@0 | 231 | } |
michael@0 | 232 | } |
michael@0 | 233 | |
michael@0 | 234 | if (qp) { |
michael@0 | 235 | qp->lo = q0; |
michael@0 | 236 | qp->hi = q1; |
michael@0 | 237 | } |
michael@0 | 238 | } |
michael@0 | 239 | #endif /* !HAVE_LONG_LONG */ |