github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/5c/mul.c (about) 1 // Inferno utils/5c/mul.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/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 32 #include "gc.h" 33 34 /* 35 * code sequences for multiply by constant. 36 * [a-l][0-3] 37 * lsl $(A-'a'),r0,r1 38 * [+][0-7] 39 * add r0,r1,r2 40 * [-][0-7] 41 * sub r0,r1,r2 42 */ 43 44 static int maxmulops = 3; /* max # of ops to replace mul with */ 45 static int multabp; 46 static int32 mulval; 47 static char* mulcp; 48 static int32 valmax; 49 static int shmax; 50 51 static int docode(char *hp, char *cp, int r0, int r1); 52 static int gen1(int len); 53 static int gen2(int len, int32 r1); 54 static int gen3(int len, int32 r0, int32 r1, int flag); 55 enum 56 { 57 SR1 = 1<<0, /* r1 has been shifted */ 58 SR0 = 1<<1, /* r0 has been shifted */ 59 UR1 = 1<<2, /* r1 has not been used */ 60 UR0 = 1<<3, /* r0 has not been used */ 61 }; 62 63 Multab* 64 mulcon0(int32 v) 65 { 66 int a1, a2, g; 67 Multab *m, *m1; 68 char hint[10]; 69 70 if(v < 0) 71 v = -v; 72 73 /* 74 * look in cache 75 */ 76 m = multab; 77 for(g=0; g<nelem(multab); g++) { 78 if(m->val == v) { 79 if(m->code[0] == 0) 80 return 0; 81 return m; 82 } 83 m++; 84 } 85 86 /* 87 * select a spot in cache to overwrite 88 */ 89 multabp++; 90 if(multabp < 0 || multabp >= nelem(multab)) 91 multabp = 0; 92 m = multab+multabp; 93 m->val = v; 94 mulval = v; 95 96 /* 97 * look in execption hint table 98 */ 99 a1 = 0; 100 a2 = hintabsize; 101 for(;;) { 102 if(a1 >= a2) 103 goto no; 104 g = (a2 + a1)/2; 105 if(v < hintab[g].val) { 106 a2 = g; 107 continue; 108 } 109 if(v > hintab[g].val) { 110 a1 = g+1; 111 continue; 112 } 113 break; 114 } 115 116 if(docode(hintab[g].hint, m->code, 1, 0)) 117 return m; 118 print("multiply table failure %d\n", v); 119 m->code[0] = 0; 120 return 0; 121 122 no: 123 /* 124 * try to search 125 */ 126 hint[0] = 0; 127 for(g=1; g<=maxmulops; g++) { 128 if(g >= maxmulops && v >= 65535) 129 break; 130 mulcp = hint+g; 131 *mulcp = 0; 132 if(gen1(g)) { 133 if(docode(hint, m->code, 1, 0)) 134 return m; 135 print("multiply table failure %d\n", v); 136 break; 137 } 138 } 139 140 /* 141 * try a recur followed by a shift 142 */ 143 g = 0; 144 while(!(v & 1)) { 145 g++; 146 v >>= 1; 147 } 148 if(g) { 149 m1 = mulcon0(v); 150 if(m1) { 151 strcpy(m->code, m1->code); 152 sprint(strchr(m->code, 0), "%c0", g+'a'); 153 return m; 154 } 155 } 156 m->code[0] = 0; 157 return 0; 158 } 159 160 static int 161 docode(char *hp, char *cp, int r0, int r1) 162 { 163 int c, i; 164 165 c = *hp++; 166 *cp = c; 167 cp += 2; 168 switch(c) { 169 default: 170 c -= 'a'; 171 if(c < 1 || c >= 30) 172 break; 173 for(i=0; i<4; i++) { 174 switch(i) { 175 case 0: 176 if(docode(hp, cp, r0<<c, r1)) 177 goto out; 178 break; 179 case 1: 180 if(docode(hp, cp, r1<<c, r1)) 181 goto out; 182 break; 183 case 2: 184 if(docode(hp, cp, r0, r0<<c)) 185 goto out; 186 break; 187 case 3: 188 if(docode(hp, cp, r0, r1<<c)) 189 goto out; 190 break; 191 } 192 } 193 break; 194 195 case '+': 196 for(i=0; i<8; i++) { 197 cp[-1] = i+'0'; 198 switch(i) { 199 case 1: 200 if(docode(hp, cp, r0+r1, r1)) 201 goto out; 202 break; 203 case 5: 204 if(docode(hp, cp, r0, r0+r1)) 205 goto out; 206 break; 207 } 208 } 209 break; 210 211 case '-': 212 for(i=0; i<8; i++) { 213 cp[-1] = i+'0'; 214 switch(i) { 215 case 1: 216 if(docode(hp, cp, r0-r1, r1)) 217 goto out; 218 break; 219 case 2: 220 if(docode(hp, cp, r1-r0, r1)) 221 goto out; 222 break; 223 case 5: 224 if(docode(hp, cp, r0, r0-r1)) 225 goto out; 226 break; 227 case 6: 228 if(docode(hp, cp, r0, r1-r0)) 229 goto out; 230 break; 231 } 232 } 233 break; 234 235 case 0: 236 if(r0 == mulval) 237 return 1; 238 } 239 return 0; 240 241 out: 242 cp[-1] = i+'0'; 243 return 1; 244 } 245 246 static int 247 gen1(int len) 248 { 249 int i; 250 251 for(shmax=1; shmax<30; shmax++) { 252 valmax = 1<<shmax; 253 if(valmax >= mulval) 254 break; 255 } 256 if(mulval == 1) 257 return 1; 258 259 len--; 260 for(i=1; i<=shmax; i++) 261 if(gen2(len, 1<<i)) { 262 *--mulcp = 'a'+i; 263 return 1; 264 } 265 return 0; 266 } 267 268 static int 269 gen2(int len, int32 r1) 270 { 271 int i; 272 273 if(len <= 0) { 274 if(r1 == mulval) 275 return 1; 276 return 0; 277 } 278 279 len--; 280 if(len == 0) 281 goto calcr0; 282 283 if(gen3(len, r1, r1+1, UR1)) { 284 i = '+'; 285 goto out; 286 } 287 if(gen3(len, r1-1, r1, UR0)) { 288 i = '-'; 289 goto out; 290 } 291 if(gen3(len, 1, r1+1, UR1)) { 292 i = '+'; 293 goto out; 294 } 295 if(gen3(len, 1, r1-1, UR1)) { 296 i = '-'; 297 goto out; 298 } 299 300 return 0; 301 302 calcr0: 303 if(mulval == r1+1) { 304 i = '+'; 305 goto out; 306 } 307 if(mulval == r1-1) { 308 i = '-'; 309 goto out; 310 } 311 return 0; 312 313 out: 314 *--mulcp = i; 315 return 1; 316 } 317 318 static int 319 gen3(int len, int32 r0, int32 r1, int flag) 320 { 321 int i, f1, f2; 322 int32 x; 323 324 if(r0 <= 0 || 325 r0 >= r1 || 326 r1 > valmax) 327 return 0; 328 329 len--; 330 if(len == 0) 331 goto calcr0; 332 333 if(!(flag & UR1)) { 334 f1 = UR1|SR1; 335 for(i=1; i<=shmax; i++) { 336 x = r0<<i; 337 if(x > valmax) 338 break; 339 if(gen3(len, r0, x, f1)) { 340 i += 'a'; 341 goto out; 342 } 343 } 344 } 345 346 if(!(flag & UR0)) { 347 f1 = UR1|SR1; 348 for(i=1; i<=shmax; i++) { 349 x = r1<<i; 350 if(x > valmax) 351 break; 352 if(gen3(len, r1, x, f1)) { 353 i += 'a'; 354 goto out; 355 } 356 } 357 } 358 359 if(!(flag & SR1)) { 360 f1 = UR1|SR1|(flag&UR0); 361 for(i=1; i<=shmax; i++) { 362 x = r1<<i; 363 if(x > valmax) 364 break; 365 if(gen3(len, r0, x, f1)) { 366 i += 'a'; 367 goto out; 368 } 369 } 370 } 371 372 if(!(flag & SR0)) { 373 f1 = UR0|SR0|(flag&(SR1|UR1)); 374 375 f2 = UR1|SR1; 376 if(flag & UR1) 377 f2 |= UR0; 378 if(flag & SR1) 379 f2 |= SR0; 380 381 for(i=1; i<=shmax; i++) { 382 x = r0<<i; 383 if(x > valmax) 384 break; 385 if(x > r1) { 386 if(gen3(len, r1, x, f2)) { 387 i += 'a'; 388 goto out; 389 } 390 } else 391 if(gen3(len, x, r1, f1)) { 392 i += 'a'; 393 goto out; 394 } 395 } 396 } 397 398 x = r1+r0; 399 if(gen3(len, r0, x, UR1)) { 400 i = '+'; 401 goto out; 402 } 403 404 if(gen3(len, r1, x, UR1)) { 405 i = '+'; 406 goto out; 407 } 408 409 x = r1-r0; 410 if(gen3(len, x, r1, UR0)) { 411 i = '-'; 412 goto out; 413 } 414 415 if(x > r0) { 416 if(gen3(len, r0, x, UR1)) { 417 i = '-'; 418 goto out; 419 } 420 } else 421 if(gen3(len, x, r0, UR0)) { 422 i = '-'; 423 goto out; 424 } 425 426 return 0; 427 428 calcr0: 429 f1 = flag & (UR0|UR1); 430 if(f1 == UR1) { 431 for(i=1; i<=shmax; i++) { 432 x = r1<<i; 433 if(x >= mulval) { 434 if(x == mulval) { 435 i += 'a'; 436 goto out; 437 } 438 break; 439 } 440 } 441 } 442 443 if(mulval == r1+r0) { 444 i = '+'; 445 goto out; 446 } 447 if(mulval == r1-r0) { 448 i = '-'; 449 goto out; 450 } 451 452 return 0; 453 454 out: 455 *--mulcp = i; 456 return 1; 457 } 458 459 /* 460 * hint table has numbers that 461 * the search algorithm fails on. 462 * <1000: 463 * all numbers 464 * <5000: 465 * ÷ by 5 466 * <10000: 467 * ÷ by 50 468 * <65536: 469 * ÷ by 250 470 */ 471 Hintab hintab[] = 472 { 473 683, "b++d+e+", 474 687, "b+e++e-", 475 691, "b++d+e+", 476 731, "b++d+e+", 477 811, "b++d+i+", 478 821, "b++e+e+", 479 843, "b+d++e+", 480 851, "b+f-+e-", 481 853, "b++e+e+", 482 877, "c++++g-", 483 933, "b+c++g-", 484 981, "c-+e-d+", 485 1375, "b+c+b+h-", 486 1675, "d+b++h+", 487 2425, "c++f-e+", 488 2675, "c+d++f-", 489 2750, "b+d-b+h-", 490 2775, "c-+g-e-", 491 3125, "b++e+g+", 492 3275, "b+c+g+e+", 493 3350, "c++++i+", 494 3475, "c-+e-f-", 495 3525, "c-+d+g-", 496 3625, "c-+e-j+", 497 3675, "b+d+d+e+", 498 3725, "b+d-+h+", 499 3925, "b+d+f-d-", 500 4275, "b+g++e+", 501 4325, "b+h-+d+", 502 4425, "b+b+g-j-", 503 4525, "b+d-d+f+", 504 4675, "c++d-g+", 505 4775, "b+d+b+g-", 506 4825, "c+c-+i-", 507 4850, "c++++i-", 508 4925, "b++e-g-", 509 4975, "c+f++e-", 510 5500, "b+g-c+d+", 511 6700, "d+b++i+", 512 9700, "d++++j-", 513 11000, "b+f-c-h-", 514 11750, "b+d+g+j-", 515 12500, "b+c+e-k+", 516 13250, "b+d+e-f+", 517 13750, "b+h-c-d+", 518 14250, "b+g-c+e-", 519 14500, "c+f+j-d-", 520 14750, "d-g--f+", 521 16750, "b+e-d-n+", 522 17750, "c+h-b+e+", 523 18250, "d+b+h-d+", 524 18750, "b+g-++f+", 525 19250, "b+e+b+h+", 526 19750, "b++h--f-", 527 20250, "b+e-l-c+", 528 20750, "c++bi+e-", 529 21250, "b+i+l+c+", 530 22000, "b+e+d-g-", 531 22250, "b+d-h+k-", 532 22750, "b+d-e-g+", 533 23250, "b+c+h+e-", 534 23500, "b+g-c-g-", 535 23750, "b+g-b+h-", 536 24250, "c++g+m-", 537 24750, "b+e+e+j-", 538 25000, "b++dh+g+", 539 25250, "b+e+d-g-", 540 25750, "b+e+b+j+", 541 26250, "b+h+c+e+", 542 26500, "b+h+c+g+", 543 26750, "b+d+e+g-", 544 27250, "b+e+e+f+", 545 27500, "c-i-c-d+", 546 27750, "b+bd++j+", 547 28250, "d-d-++i-", 548 28500, "c+c-h-e-", 549 29000, "b+g-d-f+", 550 29500, "c+h+++e-", 551 29750, "b+g+f-c+", 552 30250, "b+f-g-c+", 553 33500, "c-f-d-n+", 554 33750, "b+d-b+j-", 555 34250, "c+e+++i+", 556 35250, "e+b+d+k+", 557 35500, "c+e+d-g-", 558 35750, "c+i-++e+", 559 36250, "b+bh-d+e+", 560 36500, "c+c-h-e-", 561 36750, "d+e--i+", 562 37250, "b+g+g+b+", 563 37500, "b+h-b+f+", 564 37750, "c+be++j-", 565 38500, "b+e+b+i+", 566 38750, "d+i-b+d+", 567 39250, "b+g-l-+d+", 568 39500, "b+g-c+g-", 569 39750, "b+bh-c+f-", 570 40250, "b+bf+d+g-", 571 40500, "b+g-c+g+", 572 40750, "c+b+i-e+", 573 41250, "d++bf+h+", 574 41500, "b+j+c+d-", 575 41750, "c+f+b+h-", 576 42500, "c+h++g+", 577 42750, "b+g+d-f-", 578 43250, "b+l-e+d-", 579 43750, "c+bd+h+f-", 580 44000, "b+f+g-d-", 581 44250, "b+d-g--f+", 582 44500, "c+e+c+h+", 583 44750, "b+e+d-h-", 584 45250, "b++g+j-g+", 585 45500, "c+d+e-g+", 586 45750, "b+d-h-e-", 587 46250, "c+bd++j+", 588 46500, "b+d-c-j-", 589 46750, "e-e-b+g-", 590 47000, "b+c+d-j-", 591 47250, "b+e+e-g-", 592 47500, "b+g-c-h-", 593 47750, "b+f-c+h-", 594 48250, "d--h+n-", 595 48500, "b+c-g+m-", 596 48750, "b+e+e-g+", 597 49500, "c-f+e+j-", 598 49750, "c+c+g++f-", 599 50000, "b+e+e+k+", 600 50250, "b++i++g+", 601 50500, "c+g+f-i+", 602 50750, "b+e+d+k-", 603 51500, "b+i+c-f+", 604 51750, "b+bd+g-e-", 605 52250, "b+d+g-j+", 606 52500, "c+c+f+g+", 607 52750, "b+c+e+i+", 608 53000, "b+i+c+g+", 609 53500, "c+g+g-n+", 610 53750, "b+j+d-c+", 611 54250, "b+d-g-j-", 612 54500, "c-f+e+f+", 613 54750, "b+f-+c+g+", 614 55000, "b+g-d-g-", 615 55250, "b+e+e+g+", 616 55500, "b+cd++j+", 617 55750, "b+bh-d-f-", 618 56250, "c+d-b+j-", 619 56500, "c+d+c+i+", 620 56750, "b+e+d++h-", 621 57000, "b+d+g-f+", 622 57250, "b+f-m+d-", 623 57750, "b+i+c+e-", 624 58000, "b+e+d+h+", 625 58250, "c+b+g+g+", 626 58750, "d-e-j--e+", 627 59000, "d-i-+e+", 628 59250, "e--h-m+", 629 59500, "c+c-h+f-", 630 59750, "b+bh-e+i-", 631 60250, "b+bh-e-e-", 632 60500, "c+c-g-g-", 633 60750, "b+e-l-e-", 634 61250, "b+g-g-c+", 635 61750, "b+g-c+g+", 636 62250, "f--+c-i-", 637 62750, "e+f--+g+", 638 64750, "b+f+d+p-", 639 }; 640 int hintabsize = nelem(hintab);