1 /* ===-- udivmodti4.c - Implement __udivmodti4 -----------------------------=== 2 * 3 * The LLVM Compiler Infrastructure 4 * 5 * This file is dual licensed under the MIT and the University of Illinois Open 6 * Source Licenses. See LICENSE.TXT for details. 7 * 8 * ===----------------------------------------------------------------------=== 9 * 10 * This file implements __udivmodti4 for the compiler_rt library. 11 * 12 * ===----------------------------------------------------------------------=== 13 */ 14 15 #include "int_lib.h" 16 17 #ifdef CRT_HAS_128BIT 18 19 /* Effects: if rem != 0, *rem = a % b 20 * Returns: a / b 21 */ 22 23 /* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */ 24 25 COMPILER_RT_ABI tu_int 26 __udivmodti4(tu_int a, tu_int b, tu_int* rem) 27 { 28 const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; 29 const unsigned n_utword_bits = sizeof(tu_int) * CHAR_BIT; 30 utwords n; 31 n.all = a; 32 utwords d; 33 d.all = b; 34 utwords q; 35 utwords r; 36 unsigned sr; 37 /* special cases, X is unknown, K != 0 */ 38 if (n.s.high == 0) 39 { 40 if (d.s.high == 0) 41 { 42 /* 0 X 43 * --- 44 * 0 X 45 */ 46 if (rem) 47 *rem = n.s.low % d.s.low; 48 return n.s.low / d.s.low; 49 } 50 /* 0 X 51 * --- 52 * K X 53 */ 54 if (rem) 55 *rem = n.s.low; 56 return 0; 57 } 58 /* n.s.high != 0 */ 59 if (d.s.low == 0) 60 { 61 if (d.s.high == 0) 62 { 63 /* K X 64 * --- 65 * 0 0 66 */ 67 if (rem) 68 *rem = n.s.high % d.s.low; 69 return n.s.high / d.s.low; 70 } 71 /* d.s.high != 0 */ 72 if (n.s.low == 0) 73 { 74 /* K 0 75 * --- 76 * K 0 77 */ 78 if (rem) 79 { 80 r.s.high = n.s.high % d.s.high; 81 r.s.low = 0; 82 *rem = r.all; 83 } 84 return n.s.high / d.s.high; 85 } 86 /* K K 87 * --- 88 * K 0 89 */ 90 if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ 91 { 92 if (rem) 93 { 94 r.s.low = n.s.low; 95 r.s.high = n.s.high & (d.s.high - 1); 96 *rem = r.all; 97 } 98 return n.s.high >> __builtin_ctzll(d.s.high); 99 } 100 /* K K 101 * --- 102 * K 0 103 */ 104 sr = __builtin_clzll(d.s.high) - __builtin_clzll(n.s.high); 105 /* 0 <= sr <= n_udword_bits - 2 or sr large */ 106 if (sr > n_udword_bits - 2) 107 { 108 if (rem) 109 *rem = n.all; 110 return 0; 111 } 112 ++sr; 113 /* 1 <= sr <= n_udword_bits - 1 */ 114 /* q.all = n.all << (n_utword_bits - sr); */ 115 q.s.low = 0; 116 q.s.high = n.s.low << (n_udword_bits - sr); 117 /* r.all = n.all >> sr; */ 118 r.s.high = n.s.high >> sr; 119 r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 120 } 121 else /* d.s.low != 0 */ 122 { 123 if (d.s.high == 0) 124 { 125 /* K X 126 * --- 127 * 0 K 128 */ 129 if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ 130 { 131 if (rem) 132 *rem = n.s.low & (d.s.low - 1); 133 if (d.s.low == 1) 134 return n.all; 135 sr = __builtin_ctzll(d.s.low); 136 q.s.high = n.s.high >> sr; 137 q.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 138 return q.all; 139 } 140 /* K X 141 * --- 142 * 0 K 143 */ 144 sr = 1 + n_udword_bits + __builtin_clzll(d.s.low) 145 - __builtin_clzll(n.s.high); 146 /* 2 <= sr <= n_utword_bits - 1 147 * q.all = n.all << (n_utword_bits - sr); 148 * r.all = n.all >> sr; 149 */ 150 if (sr == n_udword_bits) 151 { 152 q.s.low = 0; 153 q.s.high = n.s.low; 154 r.s.high = 0; 155 r.s.low = n.s.high; 156 } 157 else if (sr < n_udword_bits) // 2 <= sr <= n_udword_bits - 1 158 { 159 q.s.low = 0; 160 q.s.high = n.s.low << (n_udword_bits - sr); 161 r.s.high = n.s.high >> sr; 162 r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 163 } 164 else // n_udword_bits + 1 <= sr <= n_utword_bits - 1 165 { 166 q.s.low = n.s.low << (n_utword_bits - sr); 167 q.s.high = (n.s.high << (n_utword_bits - sr)) | 168 (n.s.low >> (sr - n_udword_bits)); 169 r.s.high = 0; 170 r.s.low = n.s.high >> (sr - n_udword_bits); 171 } 172 } 173 else 174 { 175 /* K X 176 * --- 177 * K K 178 */ 179 sr = __builtin_clzll(d.s.high) - __builtin_clzll(n.s.high); 180 /*0 <= sr <= n_udword_bits - 1 or sr large */ 181 if (sr > n_udword_bits - 1) 182 { 183 if (rem) 184 *rem = n.all; 185 return 0; 186 } 187 ++sr; 188 /* 1 <= sr <= n_udword_bits 189 * q.all = n.all << (n_utword_bits - sr); 190 * r.all = n.all >> sr; 191 */ 192 q.s.low = 0; 193 if (sr == n_udword_bits) 194 { 195 q.s.high = n.s.low; 196 r.s.high = 0; 197 r.s.low = n.s.high; 198 } 199 else 200 { 201 r.s.high = n.s.high >> sr; 202 r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 203 q.s.high = n.s.low << (n_udword_bits - sr); 204 } 205 } 206 } 207 /* Not a special case 208 * q and r are initialized with: 209 * q.all = n.all << (n_utword_bits - sr); 210 * r.all = n.all >> sr; 211 * 1 <= sr <= n_utword_bits - 1 212 */ 213 su_int carry = 0; 214 for (; sr > 0; --sr) 215 { 216 /* r:q = ((r:q) << 1) | carry */ 217 r.s.high = (r.s.high << 1) | (r.s.low >> (n_udword_bits - 1)); 218 r.s.low = (r.s.low << 1) | (q.s.high >> (n_udword_bits - 1)); 219 q.s.high = (q.s.high << 1) | (q.s.low >> (n_udword_bits - 1)); 220 q.s.low = (q.s.low << 1) | carry; 221 /* carry = 0; 222 * if (r.all >= d.all) 223 * { 224 * r.all -= d.all; 225 * carry = 1; 226 * } 227 */ 228 const ti_int s = (ti_int)(d.all - r.all - 1) >> (n_utword_bits - 1); 229 carry = s & 1; 230 r.all -= d.all & s; 231 } 232 q.all = (q.all << 1) | carry; 233 if (rem) 234 *rem = r.all; 235 return q.all; 236 } 237 238 #endif /* CRT_HAS_128BIT */ 239