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