github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5l/span.c (about) 1 // Inferno utils/5l/span.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/span.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 // Instruction layout. 32 33 #include "l.h" 34 #include "../ld/lib.h" 35 36 static struct { 37 uint32 start; 38 uint32 size; 39 uint32 extra; 40 } pool; 41 42 int checkpool(Prog*, int); 43 int flushpool(Prog*, int, int); 44 45 int 46 isbranch(Prog *p) 47 { 48 int as = p->as; 49 return (as >= ABEQ && as <= ABLE) || as == AB || as == ABL || as == ABX; 50 } 51 52 static int 53 scan(Prog *op, Prog *p, int c) 54 { 55 Prog *q; 56 57 for(q = op->link; q != p && q != P; q = q->link){ 58 q->pc = c; 59 c += oplook(q)->size; 60 nocache(q); 61 } 62 return c; 63 } 64 65 /* size of a case statement including jump table */ 66 static int32 67 casesz(Prog *p) 68 { 69 int jt = 0; 70 int32 n = 0; 71 Optab *o; 72 73 for( ; p != P; p = p->link){ 74 if(p->as == ABCASE) 75 jt = 1; 76 else if(jt) 77 break; 78 o = oplook(p); 79 n += o->size; 80 } 81 return n; 82 } 83 84 void 85 span(void) 86 { 87 Prog *p, *op; 88 Optab *o; 89 int m, bflag, i, v; 90 int32 c, otxt, out[6]; 91 Section *sect; 92 uchar *bp; 93 Sym *sub; 94 95 if(debug['v']) 96 Bprint(&bso, "%5.2f span\n", cputime()); 97 Bflush(&bso); 98 99 sect = addsection(&segtext, ".text", 05); 100 lookup("text", 0)->sect = sect; 101 lookup("etext", 0)->sect = sect; 102 103 bflag = 0; 104 c = INITTEXT; 105 otxt = c; 106 for(cursym = textp; cursym != nil; cursym = cursym->next) { 107 cursym->sect = sect; 108 p = cursym->text; 109 if(p == P || p->link == P) { // handle external functions and ELF section symbols 110 if(cursym->type & SSUB) 111 continue; 112 if(cursym->align != 0) 113 c = rnd(c, cursym->align); 114 cursym->value = 0; 115 for(sub = cursym; sub != S; sub = sub->sub) { 116 sub->value += c; 117 for(p = sub->text; p != P; p = p->link) 118 p->pc += sub->value; 119 } 120 c += cursym->size; 121 continue; 122 } 123 p->pc = c; 124 cursym->value = c; 125 126 autosize = p->to.offset + 4; 127 if(p->from.sym != S) 128 p->from.sym->value = c; 129 /* need passes to resolve branches */ 130 if(c-otxt >= 1L<<17) 131 bflag = 1; 132 otxt = c; 133 134 for(op = p, p = p->link; p != P; op = p, p = p->link) { 135 curp = p; 136 p->pc = c; 137 o = oplook(p); 138 m = o->size; 139 // must check literal pool here in case p generates many instructions 140 if(blitrl){ 141 if(checkpool(op, p->as == ACASE ? casesz(p) : m)) 142 c = p->pc = scan(op, p, c); 143 } 144 if(m == 0) { 145 diag("zero-width instruction\n%P", p); 146 continue; 147 } 148 switch(o->flag & (LFROM|LTO|LPOOL)) { 149 case LFROM: 150 addpool(p, &p->from); 151 break; 152 case LTO: 153 addpool(p, &p->to); 154 break; 155 case LPOOL: 156 if ((p->scond&C_SCOND) == 14) 157 flushpool(p, 0, 0); 158 break; 159 } 160 if(p->as==AMOVW && p->to.type==D_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == 14) 161 flushpool(p, 0, 0); 162 c += m; 163 } 164 if(blitrl){ 165 if(checkpool(op, 0)) 166 c = scan(op, P, c); 167 } 168 cursym->size = c - cursym->value; 169 } 170 171 /* 172 * if any procedure is large enough to 173 * generate a large SBRA branch, then 174 * generate extra passes putting branches 175 * around jmps to fix. this is rare. 176 */ 177 while(bflag) { 178 if(debug['v']) 179 Bprint(&bso, "%5.2f span1\n", cputime()); 180 bflag = 0; 181 c = INITTEXT; 182 for(cursym = textp; cursym != nil; cursym = cursym->next) { 183 if(!cursym->text || !cursym->text->link) 184 continue; 185 cursym->value = c; 186 for(p = cursym->text; p != P; p = p->link) { 187 curp = p; 188 p->pc = c; 189 o = oplook(p); 190 /* very large branches 191 if(o->type == 6 && p->cond) { 192 otxt = p->cond->pc - c; 193 if(otxt < 0) 194 otxt = -otxt; 195 if(otxt >= (1L<<17) - 10) { 196 q = prg(); 197 q->link = p->link; 198 p->link = q; 199 q->as = AB; 200 q->to.type = D_BRANCH; 201 q->cond = p->cond; 202 p->cond = q; 203 q = prg(); 204 q->link = p->link; 205 p->link = q; 206 q->as = AB; 207 q->to.type = D_BRANCH; 208 q->cond = q->link->link; 209 bflag = 1; 210 } 211 } 212 */ 213 m = o->size; 214 if(m == 0) { 215 if(p->as == ATEXT) { 216 autosize = p->to.offset + 4; 217 if(p->from.sym != S) 218 p->from.sym->value = c; 219 continue; 220 } 221 diag("zero-width instruction\n%P", p); 222 continue; 223 } 224 c += m; 225 } 226 cursym->size = c - cursym->value; 227 } 228 } 229 230 c = rnd(c, 8); 231 232 /* 233 * lay out the code. all the pc-relative code references, 234 * even cross-function, are resolved now; 235 * only data references need to be relocated. 236 * with more work we could leave cross-function 237 * code references to be relocated too, and then 238 * perhaps we'd be able to parallelize the span loop above. 239 */ 240 for(cursym = textp; cursym != nil; cursym = cursym->next) { 241 p = cursym->text; 242 if(p == P || p->link == P) 243 continue; 244 autosize = p->to.offset + 4; 245 symgrow(cursym, cursym->size); 246 247 bp = cursym->p; 248 for(p = p->link; p != P; p = p->link) { 249 pc = p->pc; 250 curp = p; 251 o = oplook(p); 252 asmout(p, o, out); 253 for(i=0; i<o->size/4; i++) { 254 v = out[i]; 255 *bp++ = v; 256 *bp++ = v>>8; 257 *bp++ = v>>16; 258 *bp++ = v>>24; 259 } 260 } 261 } 262 sect->vaddr = INITTEXT; 263 sect->len = c - INITTEXT; 264 } 265 266 /* 267 * when the first reference to the literal pool threatens 268 * to go out of range of a 12-bit PC-relative offset, 269 * drop the pool now, and branch round it. 270 * this happens only in extended basic blocks that exceed 4k. 271 */ 272 int 273 checkpool(Prog *p, int sz) 274 { 275 if(pool.size >= 0xffc || immaddr((p->pc+sz+4)+4+pool.size - pool.start+8) == 0) 276 return flushpool(p, 1, 0); 277 else if(p->link == P) 278 return flushpool(p, 2, 0); 279 return 0; 280 } 281 282 int 283 flushpool(Prog *p, int skip, int force) 284 { 285 Prog *q; 286 287 if(blitrl) { 288 if(skip){ 289 if(0 && skip==1)print("note: flush literal pool at %ux: len=%ud ref=%ux\n", p->pc+4, pool.size, pool.start); 290 q = prg(); 291 q->as = AB; 292 q->to.type = D_BRANCH; 293 q->cond = p->link; 294 q->link = blitrl; 295 q->line = p->line; 296 blitrl = q; 297 } 298 else if(!force && (p->pc+pool.size-pool.start < 2048)) 299 return 0; 300 elitrl->link = p->link; 301 p->link = blitrl; 302 // BUG(minux): how to correctly handle line number for constant pool entries? 303 // for now, we set line number to the last instruction preceding them at least 304 // this won't bloat the .debug_line tables 305 while(blitrl) { 306 blitrl->line = p->line; 307 blitrl = blitrl->link; 308 } 309 blitrl = 0; /* BUG: should refer back to values until out-of-range */ 310 elitrl = 0; 311 pool.size = 0; 312 pool.start = 0; 313 pool.extra = 0; 314 return 1; 315 } 316 return 0; 317 } 318 319 void 320 addpool(Prog *p, Adr *a) 321 { 322 Prog *q, t; 323 int c; 324 325 c = aclass(a); 326 327 t = zprg; 328 t.as = AWORD; 329 330 switch(c) { 331 default: 332 t.to = *a; 333 if(flag_shared && t.to.sym != S) 334 t.pcrel = p; 335 break; 336 337 case C_SROREG: 338 case C_LOREG: 339 case C_ROREG: 340 case C_FOREG: 341 case C_SOREG: 342 case C_HOREG: 343 case C_FAUTO: 344 case C_SAUTO: 345 case C_LAUTO: 346 case C_LACON: 347 t.to.type = D_CONST; 348 t.to.offset = instoffset; 349 break; 350 } 351 352 if(t.pcrel == P) { 353 for(q = blitrl; q != P; q = q->link) /* could hash on t.t0.offset */ 354 if(q->pcrel == P && memcmp(&q->to, &t.to, sizeof(t.to)) == 0) { 355 p->cond = q; 356 return; 357 } 358 } 359 360 q = prg(); 361 *q = t; 362 q->pc = pool.size; 363 364 if(blitrl == P) { 365 blitrl = q; 366 pool.start = p->pc; 367 q->align = 4; 368 } else 369 elitrl->link = q; 370 elitrl = q; 371 pool.size += 4; 372 373 p->cond = q; 374 } 375 376 void 377 xdefine(char *p, int t, int32 v) 378 { 379 Sym *s; 380 381 s = lookup(p, 0); 382 s->type = t; 383 s->value = v; 384 s->reachable = 1; 385 s->special = 1; 386 } 387 388 int32 389 regoff(Adr *a) 390 { 391 392 instoffset = 0; 393 aclass(a); 394 return instoffset; 395 } 396 397 int32 398 immrot(uint32 v) 399 { 400 int i; 401 402 for(i=0; i<16; i++) { 403 if((v & ~0xff) == 0) 404 return (i<<8) | v | (1<<25); 405 v = (v<<2) | (v>>30); 406 } 407 return 0; 408 } 409 410 int32 411 immaddr(int32 v) 412 { 413 if(v >= 0 && v <= 0xfff) 414 return (v & 0xfff) | 415 (1<<24) | /* pre indexing */ 416 (1<<23); /* pre indexing, up */ 417 if(v >= -0xfff && v < 0) 418 return (-v & 0xfff) | 419 (1<<24); /* pre indexing */ 420 return 0; 421 } 422 423 int 424 immfloat(int32 v) 425 { 426 return (v & 0xC03) == 0; /* offset will fit in floating-point load/store */ 427 } 428 429 int 430 immhalf(int32 v) 431 { 432 if(v >= 0 && v <= 0xff) 433 return v| 434 (1<<24)| /* pre indexing */ 435 (1<<23); /* pre indexing, up */ 436 if(v >= -0xff && v < 0) 437 return (-v & 0xff)| 438 (1<<24); /* pre indexing */ 439 return 0; 440 } 441 442 int32 443 symaddr(Sym *s) 444 { 445 if(!s->reachable) 446 diag("unreachable symbol in symaddr - %s", s->name); 447 return s->value; 448 } 449 450 int 451 aclass(Adr *a) 452 { 453 Sym *s; 454 int t; 455 456 switch(a->type) { 457 case D_NONE: 458 return C_NONE; 459 460 case D_REG: 461 return C_REG; 462 463 case D_REGREG: 464 return C_REGREG; 465 466 case D_REGREG2: 467 return C_REGREG2; 468 469 case D_SHIFT: 470 return C_SHIFT; 471 472 case D_FREG: 473 return C_FREG; 474 475 case D_FPCR: 476 return C_FCR; 477 478 case D_OREG: 479 switch(a->name) { 480 case D_EXTERN: 481 case D_STATIC: 482 if(a->sym == 0 || a->sym->name == 0) { 483 print("null sym external\n"); 484 print("%D\n", a); 485 return C_GOK; 486 } 487 instoffset = 0; // s.b. unused but just in case 488 return C_ADDR; 489 490 case D_AUTO: 491 instoffset = autosize + a->offset; 492 t = immaddr(instoffset); 493 if(t){ 494 if(immhalf(instoffset)) 495 return immfloat(t) ? C_HFAUTO : C_HAUTO; 496 if(immfloat(t)) 497 return C_FAUTO; 498 return C_SAUTO; 499 } 500 return C_LAUTO; 501 502 case D_PARAM: 503 instoffset = autosize + a->offset + 4L; 504 t = immaddr(instoffset); 505 if(t){ 506 if(immhalf(instoffset)) 507 return immfloat(t) ? C_HFAUTO : C_HAUTO; 508 if(immfloat(t)) 509 return C_FAUTO; 510 return C_SAUTO; 511 } 512 return C_LAUTO; 513 case D_NONE: 514 instoffset = a->offset; 515 t = immaddr(instoffset); 516 if(t) { 517 if(immhalf(instoffset)) /* n.b. that it will also satisfy immrot */ 518 return immfloat(t) ? C_HFOREG : C_HOREG; 519 if(immfloat(t)) 520 return C_FOREG; /* n.b. that it will also satisfy immrot */ 521 t = immrot(instoffset); 522 if(t) 523 return C_SROREG; 524 if(immhalf(instoffset)) 525 return C_HOREG; 526 return C_SOREG; 527 } 528 t = immrot(instoffset); 529 if(t) 530 return C_ROREG; 531 return C_LOREG; 532 } 533 return C_GOK; 534 535 case D_PSR: 536 return C_PSR; 537 538 case D_OCONST: 539 switch(a->name) { 540 case D_EXTERN: 541 case D_STATIC: 542 instoffset = 0; // s.b. unused but just in case 543 return C_ADDR; 544 } 545 return C_GOK; 546 547 case D_FCONST: 548 if(chipzero(&a->ieee) >= 0) 549 return C_ZFCON; 550 if(chipfloat(&a->ieee) >= 0) 551 return C_SFCON; 552 return C_LFCON; 553 554 case D_CONST: 555 case D_CONST2: 556 switch(a->name) { 557 558 case D_NONE: 559 instoffset = a->offset; 560 if(a->reg != NREG) 561 goto aconsize; 562 563 t = immrot(instoffset); 564 if(t) 565 return C_RCON; 566 t = immrot(~instoffset); 567 if(t) 568 return C_NCON; 569 return C_LCON; 570 571 case D_EXTERN: 572 case D_STATIC: 573 s = a->sym; 574 if(s == S) 575 break; 576 instoffset = 0; // s.b. unused but just in case 577 if(flag_shared) 578 return C_LCONADDR; 579 else 580 return C_LCON; 581 582 case D_AUTO: 583 instoffset = autosize + a->offset; 584 goto aconsize; 585 586 case D_PARAM: 587 instoffset = autosize + a->offset + 4L; 588 aconsize: 589 t = immrot(instoffset); 590 if(t) 591 return C_RACON; 592 return C_LACON; 593 } 594 return C_GOK; 595 596 case D_BRANCH: 597 return C_SBRA; 598 } 599 return C_GOK; 600 } 601 602 Optab* 603 oplook(Prog *p) 604 { 605 int a1, a2, a3, r; 606 char *c1, *c3; 607 Optab *o, *e; 608 609 a1 = p->optab; 610 if(a1) 611 return optab+(a1-1); 612 a1 = p->from.class; 613 if(a1 == 0) { 614 a1 = aclass(&p->from) + 1; 615 p->from.class = a1; 616 } 617 a1--; 618 a3 = p->to.class; 619 if(a3 == 0) { 620 a3 = aclass(&p->to) + 1; 621 p->to.class = a3; 622 } 623 a3--; 624 a2 = C_NONE; 625 if(p->reg != NREG) 626 a2 = C_REG; 627 r = p->as; 628 o = oprange[r].start; 629 if(o == 0) { 630 a1 = opcross[repop[r]][a1][a2][a3]; 631 if(a1) { 632 p->optab = a1+1; 633 return optab+a1; 634 } 635 o = oprange[r].stop; /* just generate an error */ 636 } 637 if(debug['O']) { 638 print("oplook %A %O %O %O\n", 639 (int)p->as, a1, a2, a3); 640 print(" %d %d\n", p->from.type, p->to.type); 641 } 642 e = oprange[r].stop; 643 c1 = xcmp[a1]; 644 c3 = xcmp[a3]; 645 for(; o<e; o++) 646 if(o->a2 == a2) 647 if(c1[o->a1]) 648 if(c3[o->a3]) { 649 p->optab = (o-optab)+1; 650 return o; 651 } 652 diag("illegal combination %A %O %O %O, %d %d", 653 p->as, a1, a2, a3, p->from.type, p->to.type); 654 prasm(p); 655 if(o == 0) 656 o = optab; 657 return o; 658 } 659 660 int 661 cmp(int a, int b) 662 { 663 664 if(a == b) 665 return 1; 666 switch(a) { 667 case C_LCON: 668 if(b == C_RCON || b == C_NCON) 669 return 1; 670 break; 671 case C_LACON: 672 if(b == C_RACON) 673 return 1; 674 break; 675 case C_LFCON: 676 if(b == C_ZFCON || b == C_SFCON) 677 return 1; 678 break; 679 680 case C_HFAUTO: 681 return b == C_HAUTO || b == C_FAUTO; 682 case C_FAUTO: 683 case C_HAUTO: 684 return b == C_HFAUTO; 685 case C_SAUTO: 686 return cmp(C_HFAUTO, b); 687 case C_LAUTO: 688 return cmp(C_SAUTO, b); 689 690 case C_HFOREG: 691 return b == C_HOREG || b == C_FOREG; 692 case C_FOREG: 693 case C_HOREG: 694 return b == C_HFOREG; 695 case C_SROREG: 696 return cmp(C_SOREG, b) || cmp(C_ROREG, b); 697 case C_SOREG: 698 case C_ROREG: 699 return b == C_SROREG || cmp(C_HFOREG, b); 700 case C_LOREG: 701 return cmp(C_SROREG, b); 702 703 case C_LBRA: 704 if(b == C_SBRA) 705 return 1; 706 break; 707 708 case C_HREG: 709 return cmp(C_SP, b) || cmp(C_PC, b); 710 711 } 712 return 0; 713 } 714 715 int 716 ocmp(const void *a1, const void *a2) 717 { 718 Optab *p1, *p2; 719 int n; 720 721 p1 = (Optab*)a1; 722 p2 = (Optab*)a2; 723 n = p1->as - p2->as; 724 if(n) 725 return n; 726 n = p1->a1 - p2->a1; 727 if(n) 728 return n; 729 n = p1->a2 - p2->a2; 730 if(n) 731 return n; 732 n = p1->a3 - p2->a3; 733 if(n) 734 return n; 735 return 0; 736 } 737 738 void 739 buildop(void) 740 { 741 int i, n, r; 742 743 for(i=0; i<C_GOK; i++) 744 for(n=0; n<C_GOK; n++) 745 xcmp[i][n] = cmp(n, i); 746 for(n=0; optab[n].as != AXXX; n++) { 747 if((optab[n].flag & LPCREL) != 0) { 748 if(flag_shared) 749 optab[n].size += optab[n].pcrelsiz; 750 else 751 optab[n].flag &= ~LPCREL; 752 } 753 } 754 qsort(optab, n, sizeof(optab[0]), ocmp); 755 for(i=0; i<n; i++) { 756 r = optab[i].as; 757 oprange[r].start = optab+i; 758 while(optab[i].as == r) 759 i++; 760 oprange[r].stop = optab+i; 761 i--; 762 763 switch(r) 764 { 765 default: 766 diag("unknown op in build: %A", r); 767 errorexit(); 768 case AADD: 769 oprange[AAND] = oprange[r]; 770 oprange[AEOR] = oprange[r]; 771 oprange[ASUB] = oprange[r]; 772 oprange[ARSB] = oprange[r]; 773 oprange[AADC] = oprange[r]; 774 oprange[ASBC] = oprange[r]; 775 oprange[ARSC] = oprange[r]; 776 oprange[AORR] = oprange[r]; 777 oprange[ABIC] = oprange[r]; 778 break; 779 case ACMP: 780 oprange[ATEQ] = oprange[r]; 781 oprange[ACMN] = oprange[r]; 782 break; 783 case AMVN: 784 break; 785 case ABEQ: 786 oprange[ABNE] = oprange[r]; 787 oprange[ABCS] = oprange[r]; 788 oprange[ABHS] = oprange[r]; 789 oprange[ABCC] = oprange[r]; 790 oprange[ABLO] = oprange[r]; 791 oprange[ABMI] = oprange[r]; 792 oprange[ABPL] = oprange[r]; 793 oprange[ABVS] = oprange[r]; 794 oprange[ABVC] = oprange[r]; 795 oprange[ABHI] = oprange[r]; 796 oprange[ABLS] = oprange[r]; 797 oprange[ABGE] = oprange[r]; 798 oprange[ABLT] = oprange[r]; 799 oprange[ABGT] = oprange[r]; 800 oprange[ABLE] = oprange[r]; 801 break; 802 case ASLL: 803 oprange[ASRL] = oprange[r]; 804 oprange[ASRA] = oprange[r]; 805 break; 806 case AMUL: 807 oprange[AMULU] = oprange[r]; 808 break; 809 case ADIV: 810 oprange[AMOD] = oprange[r]; 811 oprange[AMODU] = oprange[r]; 812 oprange[ADIVU] = oprange[r]; 813 break; 814 case AMOVW: 815 case AMOVB: 816 case AMOVBU: 817 case AMOVH: 818 case AMOVHU: 819 break; 820 case ASWPW: 821 oprange[ASWPBU] = oprange[r]; 822 break; 823 case AB: 824 case ABL: 825 case ABX: 826 case ABXRET: 827 case ASWI: 828 case AWORD: 829 case AMOVM: 830 case ARFE: 831 case ATEXT: 832 case AUSEFIELD: 833 case ALOCALS: 834 case ACASE: 835 case ABCASE: 836 case ATYPE: 837 break; 838 case AADDF: 839 oprange[AADDD] = oprange[r]; 840 oprange[ASUBF] = oprange[r]; 841 oprange[ASUBD] = oprange[r]; 842 oprange[AMULF] = oprange[r]; 843 oprange[AMULD] = oprange[r]; 844 oprange[ADIVF] = oprange[r]; 845 oprange[ADIVD] = oprange[r]; 846 oprange[ASQRTF] = oprange[r]; 847 oprange[ASQRTD] = oprange[r]; 848 oprange[AMOVFD] = oprange[r]; 849 oprange[AMOVDF] = oprange[r]; 850 oprange[AABSF] = oprange[r]; 851 oprange[AABSD] = oprange[r]; 852 break; 853 854 case ACMPF: 855 oprange[ACMPD] = oprange[r]; 856 break; 857 858 case AMOVF: 859 oprange[AMOVD] = oprange[r]; 860 break; 861 862 case AMOVFW: 863 oprange[AMOVDW] = oprange[r]; 864 break; 865 866 case AMOVWF: 867 oprange[AMOVWD] = oprange[r]; 868 break; 869 870 case AMULL: 871 oprange[AMULAL] = oprange[r]; 872 oprange[AMULLU] = oprange[r]; 873 oprange[AMULALU] = oprange[r]; 874 break; 875 876 case AMULWT: 877 oprange[AMULWB] = oprange[r]; 878 break; 879 880 case AMULAWT: 881 oprange[AMULAWB] = oprange[r]; 882 break; 883 884 case AMULA: 885 case ALDREX: 886 case ASTREX: 887 case ALDREXD: 888 case ASTREXD: 889 case ATST: 890 case APLD: 891 case AUNDEF: 892 case ACLZ: 893 break; 894 } 895 } 896 } 897 898 /* 899 void 900 buildrep(int x, int as) 901 { 902 Opcross *p; 903 Optab *e, *s, *o; 904 int a1, a2, a3, n; 905 906 if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) { 907 diag("assumptions fail in buildrep"); 908 errorexit(); 909 } 910 repop[as] = x; 911 p = (opcross + x); 912 s = oprange[as].start; 913 e = oprange[as].stop; 914 for(o=e-1; o>=s; o--) { 915 n = o-optab; 916 for(a2=0; a2<2; a2++) { 917 if(a2) { 918 if(o->a2 == C_NONE) 919 continue; 920 } else 921 if(o->a2 != C_NONE) 922 continue; 923 for(a1=0; a1<32; a1++) { 924 if(!xcmp[a1][o->a1]) 925 continue; 926 for(a3=0; a3<32; a3++) 927 if(xcmp[a3][o->a3]) 928 (*p)[a1][a2][a3] = n; 929 } 930 } 931 } 932 oprange[as].start = 0; 933 } 934 */