github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/src/cmd/8c/div.c (about) 1 // Inferno utils/8c/div.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/div.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 #include "gc.h" 32 33 /* 34 * Based on: Granlund, T.; Montgomery, P.L. 35 * "Division by Invariant Integers using Multiplication". 36 * SIGPLAN Notices, Vol. 29, June 1994, page 61. 37 */ 38 39 #define TN(n) ((uvlong)1 << (n)) 40 #define T31 TN(31) 41 #define T32 TN(32) 42 43 int 44 multiplier(uint32 d, int p, uvlong *mp) 45 { 46 int l; 47 uvlong mlo, mhi, tlo, thi; 48 49 l = topbit(d - 1) + 1; 50 mlo = (((TN(l) - d) << 32) / d) + T32; 51 if(l + p == 64) 52 mhi = (((TN(l) + 1 - d) << 32) / d) + T32; 53 else 54 mhi = (TN(32 + l) + TN(32 + l - p)) / d; 55 /*assert(mlo < mhi);*/ 56 while(l > 0) { 57 tlo = mlo >> 1; 58 thi = mhi >> 1; 59 if(tlo == thi) 60 break; 61 mlo = tlo; 62 mhi = thi; 63 l--; 64 } 65 *mp = mhi; 66 return l; 67 } 68 69 int 70 sdiv(uint32 d, uint32 *mp, int *sp) 71 { 72 int s; 73 uvlong m; 74 75 s = multiplier(d, 32 - 1, &m); 76 *mp = m; 77 *sp = s; 78 if(m >= T31) 79 return 1; 80 else 81 return 0; 82 } 83 84 int 85 udiv(uint32 d, uint32 *mp, int *sp, int *pp) 86 { 87 int p, s; 88 uvlong m; 89 90 s = multiplier(d, 32, &m); 91 p = 0; 92 if(m >= T32) { 93 while((d & 1) == 0) { 94 d >>= 1; 95 p++; 96 } 97 s = multiplier(d, 32 - p, &m); 98 } 99 *mp = m; 100 *pp = p; 101 if(m >= T32) { 102 /*assert(p == 0);*/ 103 *sp = s - 1; 104 return 1; 105 } 106 else { 107 *sp = s; 108 return 0; 109 } 110 } 111 112 void 113 sdivgen(Node *l, Node *r, Node *ax, Node *dx) 114 { 115 int a, s; 116 uint32 m; 117 vlong c; 118 119 c = r->vconst; 120 if(c < 0) 121 c = -c; 122 a = sdiv(c, &m, &s); 123 //print("a=%d i=%d s=%d m=%ux\n", a, (int32)r->vconst, s, m); 124 gins(AMOVL, nodconst(m), ax); 125 gins(AIMULL, l, Z); 126 gins(AMOVL, l, ax); 127 if(a) 128 gins(AADDL, ax, dx); 129 gins(ASHRL, nodconst(31), ax); 130 gins(ASARL, nodconst(s), dx); 131 gins(AADDL, ax, dx); 132 if(r->vconst < 0) 133 gins(ANEGL, Z, dx); 134 } 135 136 void 137 udivgen(Node *l, Node *r, Node *ax, Node *dx) 138 { 139 int a, s, t; 140 uint32 m; 141 Node nod; 142 143 a = udiv(r->vconst, &m, &s, &t); 144 //print("a=%ud i=%d p=%d s=%d m=%ux\n", a, (int32)r->vconst, t, s, m); 145 if(t != 0) { 146 gins(AMOVL, l, ax); 147 gins(ASHRL, nodconst(t), ax); 148 gins(AMOVL, nodconst(m), dx); 149 gins(AMULL, dx, Z); 150 } 151 else if(a) { 152 if(l->op != OREGISTER) { 153 regalloc(&nod, l, Z); 154 gins(AMOVL, l, &nod); 155 l = &nod; 156 } 157 gins(AMOVL, nodconst(m), ax); 158 gins(AMULL, l, Z); 159 gins(AADDL, l, dx); 160 gins(ARCRL, nodconst(1), dx); 161 if(l == &nod) 162 regfree(l); 163 } 164 else { 165 gins(AMOVL, nodconst(m), ax); 166 gins(AMULL, l, Z); 167 } 168 if(s != 0) 169 gins(ASHRL, nodconst(s), dx); 170 } 171 172 void 173 sext(Node *d, Node *s, Node *l) 174 { 175 if(s->reg == D_AX && !nodreg(d, Z, D_DX)) { 176 reg[D_DX]++; 177 gins(ACDQ, Z, Z); 178 } 179 else { 180 regalloc(d, l, Z); 181 gins(AMOVL, s, d); 182 gins(ASARL, nodconst(31), d); 183 } 184 } 185 186 void 187 sdiv2(int32 c, int v, Node *l, Node *n) 188 { 189 Node nod; 190 191 if(v > 0) { 192 if(v > 1) { 193 sext(&nod, n, l); 194 gins(AANDL, nodconst((1 << v) - 1), &nod); 195 gins(AADDL, &nod, n); 196 regfree(&nod); 197 } 198 else { 199 gins(ACMPL, n, nodconst(0x80000000)); 200 gins(ASBBL, nodconst(-1), n); 201 } 202 gins(ASARL, nodconst(v), n); 203 } 204 if(c < 0) 205 gins(ANEGL, Z, n); 206 } 207 208 void 209 smod2(int32 c, int v, Node *l, Node *n) 210 { 211 Node nod; 212 213 if(c == 1) { 214 zeroregm(n); 215 return; 216 } 217 218 sext(&nod, n, l); 219 if(v == 0) { 220 zeroregm(n); 221 gins(AXORL, &nod, n); 222 gins(ASUBL, &nod, n); 223 } 224 else if(v > 1) { 225 gins(AANDL, nodconst((1 << v) - 1), &nod); 226 gins(AADDL, &nod, n); 227 gins(AANDL, nodconst((1 << v) - 1), n); 228 gins(ASUBL, &nod, n); 229 } 230 else { 231 gins(AANDL, nodconst(1), n); 232 gins(AXORL, &nod, n); 233 gins(ASUBL, &nod, n); 234 } 235 regfree(&nod); 236 }