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