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