github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/8c/mul.c (about) 1 // Inferno utils/8c/mul.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/mul.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 typedef struct Malg Malg; 34 typedef struct Mparam Mparam; 35 36 struct Malg 37 { 38 schar vals[10]; 39 }; 40 41 struct Mparam 42 { 43 uint32 value; 44 schar alg; 45 char neg; 46 char shift; 47 char arg; 48 schar off; 49 }; 50 51 static Mparam multab[32]; 52 static int mulptr; 53 54 static Malg malgs[] = 55 { 56 {0, 100}, 57 {-1, 1, 100}, 58 {-9, -5, -3, 3, 5, 9, 100}, 59 {6, 10, 12, 18, 20, 24, 36, 40, 72, 100}, 60 {-8, -4, -2, 2, 4, 8, 100}, 61 }; 62 63 /* 64 * return position of lowest 1 65 */ 66 int 67 lowbit(uint32 v) 68 { 69 int s, i; 70 uint32 m; 71 72 s = 0; 73 m = 0xFFFFFFFFUL; 74 for(i = 16; i > 0; i >>= 1) { 75 m >>= i; 76 if((v & m) == 0) { 77 v >>= i; 78 s += i; 79 } 80 } 81 return s; 82 } 83 84 void 85 genmuladd(Node *d, Node *s, int m, Node *a) 86 { 87 Node nod; 88 89 nod.op = OINDEX; 90 nod.left = a; 91 nod.right = s; 92 nod.scale = m; 93 nod.type = types[TIND]; 94 nod.xoffset = 0; 95 xcom(&nod); 96 gopcode(OADDR, d->type, &nod, d); 97 } 98 99 void 100 mulparam(uint32 m, Mparam *mp) 101 { 102 int c, i, j, n, o, q, s; 103 int bc, bi, bn, bo, bq, bs, bt; 104 schar *p; 105 int32 u; 106 uint32 t; 107 108 bc = bq = 10; 109 bi = bn = bo = bs = bt = 0; 110 for(i = 0; i < nelem(malgs); i++) { 111 for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++) 112 for(s = 0; s < 2; s++) { 113 c = 10; 114 q = 10; 115 u = m - o; 116 if(u == 0) 117 continue; 118 if(s) { 119 o = -o; 120 if(o > 0) 121 continue; 122 u = -u; 123 } 124 n = lowbit(u); 125 t = (uint32)u >> n; 126 switch(i) { 127 case 0: 128 if(t == 1) { 129 c = s + 1; 130 q = 0; 131 break; 132 } 133 switch(t) { 134 case 3: 135 case 5: 136 case 9: 137 c = s + 1; 138 if(n) 139 c++; 140 q = 0; 141 break; 142 } 143 if(s) 144 break; 145 switch(t) { 146 case 15: 147 case 25: 148 case 27: 149 case 45: 150 case 81: 151 c = 2; 152 if(n) 153 c++; 154 q = 1; 155 break; 156 } 157 break; 158 case 1: 159 if(t == 1) { 160 c = 3; 161 q = 3; 162 break; 163 } 164 switch(t) { 165 case 3: 166 case 5: 167 case 9: 168 c = 3; 169 q = 2; 170 break; 171 } 172 break; 173 case 2: 174 if(t == 1) { 175 c = 3; 176 q = 2; 177 break; 178 } 179 break; 180 case 3: 181 if(s) 182 break; 183 if(t == 1) { 184 c = 3; 185 q = 1; 186 break; 187 } 188 break; 189 case 4: 190 if(t == 1) { 191 c = 3; 192 q = 0; 193 break; 194 } 195 break; 196 } 197 if(c < bc || (c == bc && q > bq)) { 198 bc = c; 199 bi = i; 200 bn = n; 201 bo = o; 202 bq = q; 203 bs = s; 204 bt = t; 205 } 206 } 207 } 208 mp->value = m; 209 if(bc <= 3) { 210 mp->alg = bi; 211 mp->shift = bn; 212 mp->off = bo; 213 mp->neg = bs; 214 mp->arg = bt; 215 } 216 else 217 mp->alg = -1; 218 } 219 220 int 221 m0(int a) 222 { 223 switch(a) { 224 case -2: 225 case 2: 226 return 2; 227 case -3: 228 case 3: 229 return 2; 230 case -4: 231 case 4: 232 return 4; 233 case -5: 234 case 5: 235 return 4; 236 case 6: 237 return 2; 238 case -8: 239 case 8: 240 return 8; 241 case -9: 242 case 9: 243 return 8; 244 case 10: 245 return 4; 246 case 12: 247 return 2; 248 case 15: 249 return 2; 250 case 18: 251 return 8; 252 case 20: 253 return 4; 254 case 24: 255 return 2; 256 case 25: 257 return 4; 258 case 27: 259 return 2; 260 case 36: 261 return 8; 262 case 40: 263 return 4; 264 case 45: 265 return 4; 266 case 72: 267 return 8; 268 case 81: 269 return 8; 270 } 271 diag(Z, "bad m0"); 272 return 0; 273 } 274 275 int 276 m1(int a) 277 { 278 switch(a) { 279 case 15: 280 return 4; 281 case 25: 282 return 4; 283 case 27: 284 return 8; 285 case 45: 286 return 8; 287 case 81: 288 return 8; 289 } 290 diag(Z, "bad m1"); 291 return 0; 292 } 293 294 int 295 m2(int a) 296 { 297 switch(a) { 298 case 6: 299 return 2; 300 case 10: 301 return 2; 302 case 12: 303 return 4; 304 case 18: 305 return 2; 306 case 20: 307 return 4; 308 case 24: 309 return 8; 310 case 36: 311 return 4; 312 case 40: 313 return 8; 314 case 72: 315 return 8; 316 } 317 diag(Z, "bad m2"); 318 return 0; 319 } 320 321 void 322 shiftit(Type *t, Node *s, Node *d) 323 { 324 int32 c; 325 326 c = (int32)s->vconst & 31; 327 switch(c) { 328 case 0: 329 break; 330 case 1: 331 gopcode(OADD, t, d, d); 332 break; 333 default: 334 gopcode(OASHL, t, s, d); 335 } 336 } 337 338 static int 339 mulgen1(uint32 v, Node *n) 340 { 341 int i, o; 342 Mparam *p; 343 Node nod, nods; 344 345 for(i = 0; i < nelem(multab); i++) { 346 p = &multab[i]; 347 if(p->value == v) 348 goto found; 349 } 350 351 p = &multab[mulptr]; 352 if(++mulptr == nelem(multab)) 353 mulptr = 0; 354 355 mulparam(v, p); 356 357 found: 358 // print("v=%.x a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off); 359 if(p->alg < 0) 360 return 0; 361 362 nods = *nodconst(p->shift); 363 364 o = OADD; 365 if(p->alg > 0) { 366 regalloc(&nod, n, Z); 367 if(p->off < 0) 368 o = OSUB; 369 } 370 371 switch(p->alg) { 372 case 0: 373 switch(p->arg) { 374 case 1: 375 shiftit(n->type, &nods, n); 376 break; 377 case 15: 378 case 25: 379 case 27: 380 case 45: 381 case 81: 382 genmuladd(n, n, m1(p->arg), n); 383 /* fall thru */ 384 case 3: 385 case 5: 386 case 9: 387 genmuladd(n, n, m0(p->arg), n); 388 shiftit(n->type, &nods, n); 389 break; 390 default: 391 goto bad; 392 } 393 if(p->neg == 1) 394 gins(ANEGL, Z, n); 395 break; 396 case 1: 397 switch(p->arg) { 398 case 1: 399 gmove(n, &nod); 400 shiftit(n->type, &nods, &nod); 401 break; 402 case 3: 403 case 5: 404 case 9: 405 genmuladd(&nod, n, m0(p->arg), n); 406 shiftit(n->type, &nods, &nod); 407 break; 408 default: 409 goto bad; 410 } 411 if(p->neg) 412 gopcode(o, n->type, &nod, n); 413 else { 414 gopcode(o, n->type, n, &nod); 415 gmove(&nod, n); 416 } 417 break; 418 case 2: 419 genmuladd(&nod, n, m0(p->off), n); 420 shiftit(n->type, &nods, n); 421 goto comop; 422 case 3: 423 genmuladd(&nod, n, m0(p->off), n); 424 shiftit(n->type, &nods, n); 425 genmuladd(n, &nod, m2(p->off), n); 426 break; 427 case 4: 428 genmuladd(&nod, n, m0(p->off), nodconst(0)); 429 shiftit(n->type, &nods, n); 430 goto comop; 431 default: 432 diag(Z, "bad mul alg"); 433 break; 434 comop: 435 if(p->neg) { 436 gopcode(o, n->type, n, &nod); 437 gmove(&nod, n); 438 } 439 else 440 gopcode(o, n->type, &nod, n); 441 } 442 443 if(p->alg > 0) 444 regfree(&nod); 445 446 return 1; 447 448 bad: 449 diag(Z, "mulgen botch"); 450 return 1; 451 } 452 453 void 454 mulgen(Type *t, Node *r, Node *n) 455 { 456 if(!mulgen1(r->vconst, n)) 457 gopcode(OMUL, t, r, n); 458 }