1 #ifndef __ASM_ARM_DIV64 2 #define __ASM_ARM_DIV64 3 4 #include <linux/types.h> 5 #include <asm/compiler.h> 6 7 /* 8 * The semantics of do_div() are: 9 * 10 * uint32_t do_div(uint64_t *n, uint32_t base) 11 * { 12 * uint32_t remainder = *n % base; 13 * *n = *n / base; 14 * return remainder; 15 * } 16 * 17 * In other words, a 64-bit dividend with a 32-bit divisor producing 18 * a 64-bit result and a 32-bit remainder. To accomplish this optimally 19 * we call a special __do_div64 helper with completely non standard 20 * calling convention for arguments and results (beware). 21 */ 22 23 #ifdef __ARMEB__ 24 #define __xh "r0" 25 #define __xl "r1" 26 #else 27 #define __xl "r0" 28 #define __xh "r1" 29 #endif 30 31 #define __do_div_asm(n, base) \ 32 ({ \ 33 register unsigned int __base asm("r4") = base; \ 34 register unsigned long long __n asm("r0") = n; \ 35 register unsigned long long __res asm("r2"); \ 36 register unsigned int __rem asm(__xh); \ 37 asm( __asmeq("%0", __xh) \ 38 __asmeq("%1", "r2") \ 39 __asmeq("%2", "r0") \ 40 __asmeq("%3", "r4") \ 41 "bl __do_div64" \ 42 : "=r" (__rem), "=r" (__res) \ 43 : "r" (__n), "r" (__base) \ 44 : "ip", "lr", "cc"); \ 45 n = __res; \ 46 __rem; \ 47 }) 48 49 #if __GNUC__ < 4 50 51 /* 52 * gcc versions earlier than 4.0 are simply too problematic for the 53 * optimized implementation below. First there is gcc PR 15089 that 54 * tend to trig on more complex constructs, spurious .global __udivsi3 55 * are inserted even if none of those symbols are referenced in the 56 * generated code, and those gcc versions are not able to do constant 57 * propagation on long long values anyway. 58 */ 59 #define do_div(n, base) __do_div_asm(n, base) 60 61 #elif __GNUC__ >= 4 62 63 #include <asm/bug.h> 64 65 /* 66 * If the divisor happens to be constant, we determine the appropriate 67 * inverse at compile time to turn the division into a few inline 68 * multiplications instead which is much faster. And yet only if compiling 69 * for ARMv4 or higher (we need umull/umlal) and if the gcc version is 70 * sufficiently recent to perform proper long long constant propagation. 71 * (It is unfortunate that gcc doesn't perform all this internally.) 72 */ 73 #define do_div(n, base) \ 74 ({ \ 75 unsigned int __r, __b = (base); \ 76 if (!__builtin_constant_p(__b) || __b == 0 || \ 77 (__LINUX_ARM_ARCH__ < 4 && (__b & (__b - 1)) != 0)) { \ 78 /* non-constant divisor (or zero): slow path */ \ 79 __r = __do_div_asm(n, __b); \ 80 } else if ((__b & (__b - 1)) == 0) { \ 81 /* Trivial: __b is constant and a power of 2 */ \ 82 /* gcc does the right thing with this code. */ \ 83 __r = n; \ 84 __r &= (__b - 1); \ 85 n /= __b; \ 86 } else { \ 87 /* Multiply by inverse of __b: n/b = n*(p/b)/p */ \ 88 /* We rely on the fact that most of this code gets */ \ 89 /* optimized away at compile time due to constant */ \ 90 /* propagation and only a couple inline assembly */ \ 91 /* instructions should remain. Better avoid any */ \ 92 /* code construct that might prevent that. */ \ 93 unsigned long long __res, __x, __t, __m, __n = n; \ 94 unsigned int __c, __p, __z = 0; \ 95 /* preserve low part of n for reminder computation */ \ 96 __r = __n; \ 97 /* determine number of bits to represent __b */ \ 98 __p = 1 << __div64_fls(__b); \ 99 /* compute __m = ((__p << 64) + __b - 1) / __b */ \ 100 __m = (~0ULL / __b) * __p; \ 101 __m += (((~0ULL % __b + 1) * __p) + __b - 1) / __b; \ 102 /* compute __res = __m*(~0ULL/__b*__b-1)/(__p << 64) */ \ 103 __x = ~0ULL / __b * __b - 1; \ 104 __res = (__m & 0xffffffff) * (__x & 0xffffffff); \ 105 __res >>= 32; \ 106 __res += (__m & 0xffffffff) * (__x >> 32); \ 107 __t = __res; \ 108 __res += (__x & 0xffffffff) * (__m >> 32); \ 109 __t = (__res < __t) ? (1ULL << 32) : 0; \ 110 __res = (__res >> 32) + __t; \ 111 __res += (__m >> 32) * (__x >> 32); \ 112 __res /= __p; \ 113 /* Now sanitize and optimize what we've got. */ \ 114 if (~0ULL % (__b / (__b & -__b)) == 0) { \ 115 /* those cases can be simplified with: */ \ 116 __n /= (__b & -__b); \ 117 __m = ~0ULL / (__b / (__b & -__b)); \ 118 __p = 1; \ 119 __c = 1; \ 120 } else if (__res != __x / __b) { \ 121 /* We can't get away without a correction */ \ 122 /* to compensate for bit truncation errors. */ \ 123 /* To avoid it we'd need an additional bit */ \ 124 /* to represent __m which would overflow it. */ \ 125 /* Instead we do m=p/b and n/b=(n*m+m)/p. */ \ 126 __c = 1; \ 127 /* Compute __m = (__p << 64) / __b */ \ 128 __m = (~0ULL / __b) * __p; \ 129 __m += ((~0ULL % __b + 1) * __p) / __b; \ 130 } else { \ 131 /* Reduce __m/__p, and try to clear bit 31 */ \ 132 /* of __m when possible otherwise that'll */ \ 133 /* need extra overflow handling later. */ \ 134 unsigned int __bits = -(__m & -__m); \ 135 __bits |= __m >> 32; \ 136 __bits = (~__bits) << 1; \ 137 /* If __bits == 0 then setting bit 31 is */ \ 138 /* unavoidable. Simply apply the maximum */ \ 139 /* possible reduction in that case. */ \ 140 /* Otherwise the MSB of __bits indicates the */ \ 141 /* best reduction we should apply. */ \ 142 if (!__bits) { \ 143 __p /= (__m & -__m); \ 144 __m /= (__m & -__m); \ 145 } else { \ 146 __p >>= __div64_fls(__bits); \ 147 __m >>= __div64_fls(__bits); \ 148 } \ 149 /* No correction needed. */ \ 150 __c = 0; \ 151 } \ 152 /* Now we have a combination of 2 conditions: */ \ 153 /* 1) whether or not we need a correction (__c), and */ \ 154 /* 2) whether or not there might be an overflow in */ \ 155 /* the cross product (__m & ((1<<63) | (1<<31))) */ \ 156 /* Select the best insn combination to perform the */ \ 157 /* actual __m * __n / (__p << 64) operation. */ \ 158 if (!__c) { \ 159 asm ( "umull %Q0, %R0, %1, %Q2\n\t" \ 160 "mov %Q0, #0" \ 161 : "=&r" (__res) \ 162 : "r" (__m), "r" (__n) \ 163 : "cc" ); \ 164 } else if (!(__m & ((1ULL << 63) | (1ULL << 31)))) { \ 165 __res = __m; \ 166 asm ( "umlal %Q0, %R0, %Q1, %Q2\n\t" \ 167 "mov %Q0, #0" \ 168 : "+&r" (__res) \ 169 : "r" (__m), "r" (__n) \ 170 : "cc" ); \ 171 } else { \ 172 asm ( "umull %Q0, %R0, %Q1, %Q2\n\t" \ 173 "cmn %Q0, %Q1\n\t" \ 174 "adcs %R0, %R0, %R1\n\t" \ 175 "adc %Q0, %3, #0" \ 176 : "=&r" (__res) \ 177 : "r" (__m), "r" (__n), "r" (__z) \ 178 : "cc" ); \ 179 } \ 180 if (!(__m & ((1ULL << 63) | (1ULL << 31)))) { \ 181 asm ( "umlal %R0, %Q0, %R1, %Q2\n\t" \ 182 "umlal %R0, %Q0, %Q1, %R2\n\t" \ 183 "mov %R0, #0\n\t" \ 184 "umlal %Q0, %R0, %R1, %R2" \ 185 : "+&r" (__res) \ 186 : "r" (__m), "r" (__n) \ 187 : "cc" ); \ 188 } else { \ 189 asm ( "umlal %R0, %Q0, %R2, %Q3\n\t" \ 190 "umlal %R0, %1, %Q2, %R3\n\t" \ 191 "mov %R0, #0\n\t" \ 192 "adds %Q0, %1, %Q0\n\t" \ 193 "adc %R0, %R0, #0\n\t" \ 194 "umlal %Q0, %R0, %R2, %R3" \ 195 : "+&r" (__res), "+&r" (__z) \ 196 : "r" (__m), "r" (__n) \ 197 : "cc" ); \ 198 } \ 199 __res /= __p; \ 200 /* The reminder can be computed with 32-bit regs */ \ 201 /* only, and gcc is good at that. */ \ 202 { \ 203 unsigned int __res0 = __res; \ 204 unsigned int __b0 = __b; \ 205 __r -= __res0 * __b0; \ 206 } \ 207 /* BUG_ON(__r >= __b || __res * __b + __r != n); */ \ 208 n = __res; \ 209 } \ 210 __r; \ 211 }) 212 213 /* our own fls implementation to make sure constant propagation is fine */ 214 #define __div64_fls(bits) \ 215 ({ \ 216 unsigned int __left = (bits), __nr = 0; \ 217 if (__left & 0xffff0000) __nr += 16, __left >>= 16; \ 218 if (__left & 0x0000ff00) __nr += 8, __left >>= 8; \ 219 if (__left & 0x000000f0) __nr += 4, __left >>= 4; \ 220 if (__left & 0x0000000c) __nr += 2, __left >>= 2; \ 221 if (__left & 0x00000002) __nr += 1; \ 222 __nr; \ 223 }) 224 225 #endif 226 227 #endif 228