1156cd587Sjoerg /* ===-- udivmodti4.c - Implement __udivmodti4 -----------------------------=== 2156cd587Sjoerg * 3156cd587Sjoerg * The LLVM Compiler Infrastructure 4156cd587Sjoerg * 5156cd587Sjoerg * This file is dual licensed under the MIT and the University of Illinois Open 6156cd587Sjoerg * Source Licenses. See LICENSE.TXT for details. 7156cd587Sjoerg * 8156cd587Sjoerg * ===----------------------------------------------------------------------=== 9156cd587Sjoerg * 10156cd587Sjoerg * This file implements __udivmodti4 for the compiler_rt library. 11156cd587Sjoerg * 12156cd587Sjoerg * ===----------------------------------------------------------------------=== 13156cd587Sjoerg */ 14156cd587Sjoerg 15156cd587Sjoerg #include "int_lib.h" 16156cd587Sjoerg 17156cd587Sjoerg #ifdef CRT_HAS_128BIT 18156cd587Sjoerg 19156cd587Sjoerg /* Effects: if rem != 0, *rem = a % b 20156cd587Sjoerg * Returns: a / b 21156cd587Sjoerg */ 22156cd587Sjoerg 23156cd587Sjoerg /* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */ 24156cd587Sjoerg 25*f7f78b33Sjoerg COMPILER_RT_ABI tu_int __udivmodti4(tu_int a,tu_int b,tu_int * rem)26156cd587Sjoerg__udivmodti4(tu_int a, tu_int b, tu_int* rem) 27156cd587Sjoerg { 28156cd587Sjoerg const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; 29156cd587Sjoerg const unsigned n_utword_bits = sizeof(tu_int) * CHAR_BIT; 30156cd587Sjoerg utwords n; 31156cd587Sjoerg n.all = a; 32156cd587Sjoerg utwords d; 33156cd587Sjoerg d.all = b; 34156cd587Sjoerg utwords q; 35156cd587Sjoerg utwords r; 36156cd587Sjoerg unsigned sr; 37156cd587Sjoerg /* special cases, X is unknown, K != 0 */ 38156cd587Sjoerg if (n.s.high == 0) 39156cd587Sjoerg { 40156cd587Sjoerg if (d.s.high == 0) 41156cd587Sjoerg { 42156cd587Sjoerg /* 0 X 43156cd587Sjoerg * --- 44156cd587Sjoerg * 0 X 45156cd587Sjoerg */ 46156cd587Sjoerg if (rem) 47156cd587Sjoerg *rem = n.s.low % d.s.low; 48156cd587Sjoerg return n.s.low / d.s.low; 49156cd587Sjoerg } 50156cd587Sjoerg /* 0 X 51156cd587Sjoerg * --- 52156cd587Sjoerg * K X 53156cd587Sjoerg */ 54156cd587Sjoerg if (rem) 55156cd587Sjoerg *rem = n.s.low; 56156cd587Sjoerg return 0; 57156cd587Sjoerg } 58156cd587Sjoerg /* n.s.high != 0 */ 59156cd587Sjoerg if (d.s.low == 0) 60156cd587Sjoerg { 61156cd587Sjoerg if (d.s.high == 0) 62156cd587Sjoerg { 63156cd587Sjoerg /* K X 64156cd587Sjoerg * --- 65156cd587Sjoerg * 0 0 66156cd587Sjoerg */ 67156cd587Sjoerg if (rem) 68156cd587Sjoerg *rem = n.s.high % d.s.low; 69156cd587Sjoerg return n.s.high / d.s.low; 70156cd587Sjoerg } 71156cd587Sjoerg /* d.s.high != 0 */ 72156cd587Sjoerg if (n.s.low == 0) 73156cd587Sjoerg { 74156cd587Sjoerg /* K 0 75156cd587Sjoerg * --- 76156cd587Sjoerg * K 0 77156cd587Sjoerg */ 78156cd587Sjoerg if (rem) 79156cd587Sjoerg { 80156cd587Sjoerg r.s.high = n.s.high % d.s.high; 81156cd587Sjoerg r.s.low = 0; 82156cd587Sjoerg *rem = r.all; 83156cd587Sjoerg } 84156cd587Sjoerg return n.s.high / d.s.high; 85156cd587Sjoerg } 86156cd587Sjoerg /* K K 87156cd587Sjoerg * --- 88156cd587Sjoerg * K 0 89156cd587Sjoerg */ 90156cd587Sjoerg if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ 91156cd587Sjoerg { 92156cd587Sjoerg if (rem) 93156cd587Sjoerg { 94156cd587Sjoerg r.s.low = n.s.low; 95156cd587Sjoerg r.s.high = n.s.high & (d.s.high - 1); 96156cd587Sjoerg *rem = r.all; 97156cd587Sjoerg } 98156cd587Sjoerg return n.s.high >> __builtin_ctzll(d.s.high); 99156cd587Sjoerg } 100156cd587Sjoerg /* K K 101156cd587Sjoerg * --- 102156cd587Sjoerg * K 0 103156cd587Sjoerg */ 104156cd587Sjoerg sr = __builtin_clzll(d.s.high) - __builtin_clzll(n.s.high); 105156cd587Sjoerg /* 0 <= sr <= n_udword_bits - 2 or sr large */ 106156cd587Sjoerg if (sr > n_udword_bits - 2) 107156cd587Sjoerg { 108156cd587Sjoerg if (rem) 109156cd587Sjoerg *rem = n.all; 110156cd587Sjoerg return 0; 111156cd587Sjoerg } 112156cd587Sjoerg ++sr; 113156cd587Sjoerg /* 1 <= sr <= n_udword_bits - 1 */ 114156cd587Sjoerg /* q.all = n.all << (n_utword_bits - sr); */ 115156cd587Sjoerg q.s.low = 0; 116156cd587Sjoerg q.s.high = n.s.low << (n_udword_bits - sr); 117156cd587Sjoerg /* r.all = n.all >> sr; */ 118156cd587Sjoerg r.s.high = n.s.high >> sr; 119156cd587Sjoerg r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 120156cd587Sjoerg } 121156cd587Sjoerg else /* d.s.low != 0 */ 122156cd587Sjoerg { 123156cd587Sjoerg if (d.s.high == 0) 124156cd587Sjoerg { 125156cd587Sjoerg /* K X 126156cd587Sjoerg * --- 127156cd587Sjoerg * 0 K 128156cd587Sjoerg */ 129156cd587Sjoerg if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ 130156cd587Sjoerg { 131156cd587Sjoerg if (rem) 132156cd587Sjoerg *rem = n.s.low & (d.s.low - 1); 133156cd587Sjoerg if (d.s.low == 1) 134156cd587Sjoerg return n.all; 135156cd587Sjoerg sr = __builtin_ctzll(d.s.low); 136156cd587Sjoerg q.s.high = n.s.high >> sr; 137156cd587Sjoerg q.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 138156cd587Sjoerg return q.all; 139156cd587Sjoerg } 140156cd587Sjoerg /* K X 141156cd587Sjoerg * --- 142156cd587Sjoerg * 0 K 143156cd587Sjoerg */ 144156cd587Sjoerg sr = 1 + n_udword_bits + __builtin_clzll(d.s.low) 145156cd587Sjoerg - __builtin_clzll(n.s.high); 146156cd587Sjoerg /* 2 <= sr <= n_utword_bits - 1 147156cd587Sjoerg * q.all = n.all << (n_utword_bits - sr); 148156cd587Sjoerg * r.all = n.all >> sr; 149156cd587Sjoerg */ 150*f7f78b33Sjoerg if (sr == n_udword_bits) 151*f7f78b33Sjoerg { 152*f7f78b33Sjoerg q.s.low = 0; 153*f7f78b33Sjoerg q.s.high = n.s.low; 154*f7f78b33Sjoerg r.s.high = 0; 155*f7f78b33Sjoerg r.s.low = n.s.high; 156*f7f78b33Sjoerg } 157*f7f78b33Sjoerg else if (sr < n_udword_bits) // 2 <= sr <= n_udword_bits - 1 158*f7f78b33Sjoerg { 159*f7f78b33Sjoerg q.s.low = 0; 160*f7f78b33Sjoerg q.s.high = n.s.low << (n_udword_bits - sr); 161*f7f78b33Sjoerg r.s.high = n.s.high >> sr; 162*f7f78b33Sjoerg r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 163*f7f78b33Sjoerg } 164*f7f78b33Sjoerg else // n_udword_bits + 1 <= sr <= n_utword_bits - 1 165*f7f78b33Sjoerg { 166*f7f78b33Sjoerg q.s.low = n.s.low << (n_utword_bits - sr); 167*f7f78b33Sjoerg q.s.high = (n.s.high << (n_utword_bits - sr)) | 168*f7f78b33Sjoerg (n.s.low >> (sr - n_udword_bits)); 169*f7f78b33Sjoerg r.s.high = 0; 170*f7f78b33Sjoerg r.s.low = n.s.high >> (sr - n_udword_bits); 171*f7f78b33Sjoerg } 172156cd587Sjoerg } 173156cd587Sjoerg else 174156cd587Sjoerg { 175156cd587Sjoerg /* K X 176156cd587Sjoerg * --- 177156cd587Sjoerg * K K 178156cd587Sjoerg */ 179156cd587Sjoerg sr = __builtin_clzll(d.s.high) - __builtin_clzll(n.s.high); 180156cd587Sjoerg /*0 <= sr <= n_udword_bits - 1 or sr large */ 181156cd587Sjoerg if (sr > n_udword_bits - 1) 182156cd587Sjoerg { 183156cd587Sjoerg if (rem) 184156cd587Sjoerg *rem = n.all; 185156cd587Sjoerg return 0; 186156cd587Sjoerg } 187156cd587Sjoerg ++sr; 188*f7f78b33Sjoerg /* 1 <= sr <= n_udword_bits 189*f7f78b33Sjoerg * q.all = n.all << (n_utword_bits - sr); 190*f7f78b33Sjoerg * r.all = n.all >> sr; 191156cd587Sjoerg */ 192*f7f78b33Sjoerg q.s.low = 0; 193*f7f78b33Sjoerg if (sr == n_udword_bits) 194*f7f78b33Sjoerg { 195*f7f78b33Sjoerg q.s.high = n.s.low; 196*f7f78b33Sjoerg r.s.high = 0; 197*f7f78b33Sjoerg r.s.low = n.s.high; 198*f7f78b33Sjoerg } 199*f7f78b33Sjoerg else 200*f7f78b33Sjoerg { 201*f7f78b33Sjoerg r.s.high = n.s.high >> sr; 202*f7f78b33Sjoerg r.s.low = (n.s.high << (n_udword_bits - sr)) | (n.s.low >> sr); 203*f7f78b33Sjoerg q.s.high = n.s.low << (n_udword_bits - sr); 204*f7f78b33Sjoerg } 205156cd587Sjoerg } 206156cd587Sjoerg } 207156cd587Sjoerg /* Not a special case 208156cd587Sjoerg * q and r are initialized with: 209156cd587Sjoerg * q.all = n.all << (n_utword_bits - sr); 210156cd587Sjoerg * r.all = n.all >> sr; 211156cd587Sjoerg * 1 <= sr <= n_utword_bits - 1 212156cd587Sjoerg */ 213156cd587Sjoerg su_int carry = 0; 214156cd587Sjoerg for (; sr > 0; --sr) 215156cd587Sjoerg { 216156cd587Sjoerg /* r:q = ((r:q) << 1) | carry */ 217156cd587Sjoerg r.s.high = (r.s.high << 1) | (r.s.low >> (n_udword_bits - 1)); 218156cd587Sjoerg r.s.low = (r.s.low << 1) | (q.s.high >> (n_udword_bits - 1)); 219156cd587Sjoerg q.s.high = (q.s.high << 1) | (q.s.low >> (n_udword_bits - 1)); 220156cd587Sjoerg q.s.low = (q.s.low << 1) | carry; 221156cd587Sjoerg /* carry = 0; 222156cd587Sjoerg * if (r.all >= d.all) 223156cd587Sjoerg * { 224156cd587Sjoerg * r.all -= d.all; 225156cd587Sjoerg * carry = 1; 226156cd587Sjoerg * } 227156cd587Sjoerg */ 228156cd587Sjoerg const ti_int s = (ti_int)(d.all - r.all - 1) >> (n_utword_bits - 1); 229156cd587Sjoerg carry = s & 1; 230156cd587Sjoerg r.all -= d.all & s; 231156cd587Sjoerg } 232156cd587Sjoerg q.all = (q.all << 1) | carry; 233156cd587Sjoerg if (rem) 234156cd587Sjoerg *rem = r.all; 235156cd587Sjoerg return q.all; 236156cd587Sjoerg } 237156cd587Sjoerg 238156cd587Sjoerg #endif /* CRT_HAS_128BIT */ 239