1 #include "l.h" 2 3 static struct { 4 ulong start; 5 ulong size; 6 ulong extra; 7 } pool; 8 9 int checkpool(Prog*, int); 10 int flushpool(Prog*, int, int); 11 12 int 13 isbranch(Prog *p) 14 { 15 int as = p->as; 16 return (as >= ABEQ && as <= ABLE) || as == AB || as == ABL || as == ABX; 17 } 18 19 static int 20 ispad(Prog *p) 21 { 22 if(p->as != AMOVW) 23 return 0; 24 if(p->from.type != D_REG || p->from.reg != REGSB) 25 return 0; 26 if(p->to.type != D_REG || p->to.reg != REGSB) 27 return 0; 28 return 1; 29 } 30 31 int 32 fninc(Sym *s) 33 { 34 if(thumb){ 35 if(s->thumb){ 36 if(s->foreign) 37 return 8; 38 else 39 return 0; 40 } 41 else{ 42 if(s->foreign) 43 return 0; 44 else 45 diag("T A !foreign in fninc"); 46 } 47 } 48 else{ 49 if(s->thumb){ 50 if(s->foreign) 51 return 0; 52 else 53 diag("A T !foreign in fninc"); 54 } 55 else{ 56 if(s->foreign) 57 return 4; 58 else 59 return 0; 60 } 61 } 62 return 0; 63 } 64 65 int 66 fnpinc(Sym *s) 67 { 68 if(!s->fnptr){ // a simplified case BX O(R) -> BL O(R) 69 if(!debug['f']) 70 diag("fnptr == 0 in fnpinc"); 71 if(s->foreign) 72 diag("bad usage in fnpinc %s %d %d %d", s->name, s->used, s->foreign, s->thumb); 73 return 0; 74 } 75 /* 0, 1, 2, 3 squared */ 76 if(s->thumb) 77 return s->foreign ? 9 : 1; 78 else 79 return s->foreign ? 4 : 0; 80 } 81 82 static Prog * 83 pad(Prog *p, int pc) 84 { 85 Prog *q; 86 87 q = prg(); 88 q->as = AMOVW; 89 q->line = p->line; 90 q->from.type = D_REG; 91 q->from.reg = REGSB; 92 q->to.type = D_REG; 93 q->to.reg = REGSB; 94 q->pc = pc; 95 q->link = p->link; 96 return q; 97 } 98 99 static int 100 scan(Prog *op, Prog *p, int c) 101 { 102 Prog *q; 103 104 for(q = op->link; q != p; q = q->link){ 105 q->pc = c; 106 c += oplook(q)->size; 107 nocache(q); 108 } 109 return c; 110 } 111 112 /* size of a case statement including jump table */ 113 static long 114 casesz(Prog *p) 115 { 116 int jt = 0; 117 long n = 0; 118 Optab *o; 119 120 for( ; p != P; p = p->link){ 121 if(p->as == ABCASE) 122 jt = 1; 123 else if(jt) 124 break; 125 o = oplook(p); 126 n += o->size; 127 } 128 return n; 129 } 130 131 void 132 span(void) 133 { 134 Prog *p, *op; 135 Sym *setext, *s; 136 Optab *o; 137 int m, bflag, i; 138 long c, otxt, v; 139 int lastthumb = -1; 140 141 if(debug['v']) 142 Bprint(&bso, "%5.2f span\n", cputime()); 143 Bflush(&bso); 144 145 bflag = 0; 146 c = INITTEXT; 147 op = nil; 148 otxt = c; 149 for(p = firstp; p != P; op = p, p = p->link) { 150 setarch(p); 151 p->pc = c; 152 o = oplook(p); 153 m = o->size; 154 // must check literal pool here in case p generates many instructions 155 if(blitrl){ 156 if(thumb && isbranch(p)) 157 pool.extra += brextra(p); 158 if(checkpool(op, p->as == ACASE ? casesz(p) : m)) 159 c = p->pc = scan(op, p, c); 160 } 161 if(m == 0) { 162 if(p->as == ATEXT) { 163 if(blitrl && lastthumb != -1 && lastthumb != thumb){ // flush literal pool 164 if(flushpool(op, 0, 1)) 165 c = p->pc = scan(op, p, c); 166 } 167 lastthumb = thumb; 168 curtext = p; 169 autosize = p->to.offset + 4; 170 if(p->from.sym != S) 171 p->from.sym->value = c; 172 /* need passes to resolve branches */ 173 if(c-otxt >= 1L<<17) 174 bflag = 1; 175 otxt = c; 176 if(thumb && blitrl) 177 pool.extra += brextra(p); 178 continue; 179 } 180 diag("zero-width instruction\n%P", p); 181 continue; 182 } 183 switch(o->flag & (LFROM|LTO|LPOOL)) { 184 case LFROM: 185 addpool(p, &p->from); 186 break; 187 case LTO: 188 addpool(p, &p->to); 189 break; 190 case LPOOL: 191 if ((p->scond&C_SCOND) == 14) 192 flushpool(p, 0, 0); 193 break; 194 } 195 if(p->as==AMOVW && p->to.type==D_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == 14) 196 flushpool(p, 0, 0); 197 c += m; 198 if(blitrl && p->link == P){ 199 if(thumb && isbranch(p)) 200 pool.extra += brextra(p); 201 checkpool(p, 0); 202 } 203 } 204 205 /* 206 * if any procedure is large enough to 207 * generate a large SBRA branch, then 208 * generate extra passes putting branches 209 * around jmps to fix. this is rare. 210 */ 211 while(bflag) { 212 if(debug['v']) 213 Bprint(&bso, "%5.2f span1\n", cputime()); 214 bflag = 0; 215 c = INITTEXT; 216 for(p = firstp; p != P; p = p->link) { 217 setarch(p); 218 p->pc = c; 219 if(thumb && isbranch(p)) 220 nocache(p); 221 o = oplook(p); 222 /* very larg branches 223 if(o->type == 6 && p->cond) { 224 otxt = p->cond->pc - c; 225 if(otxt < 0) 226 otxt = -otxt; 227 if(otxt >= (1L<<17) - 10) { 228 q = prg(); 229 q->link = p->link; 230 p->link = q; 231 q->as = AB; 232 q->to.type = D_BRANCH; 233 q->cond = p->cond; 234 p->cond = q; 235 q = prg(); 236 q->link = p->link; 237 p->link = q; 238 q->as = AB; 239 q->to.type = D_BRANCH; 240 q->cond = q->link->link; 241 bflag = 1; 242 } 243 } 244 */ 245 m = o->size; 246 if(m == 0) { 247 if(p->as == ATEXT) { 248 curtext = p; 249 autosize = p->to.offset + 4; 250 if(p->from.sym != S) 251 p->from.sym->value = c; 252 continue; 253 } 254 diag("zero-width instruction\n%P", p); 255 continue; 256 } 257 c += m; 258 } 259 } 260 261 if(seenthumb){ // branch resolution 262 int passes = 0; 263 int lastc = 0; 264 int again; 265 Prog *oop; 266 267 loop: 268 passes++; 269 if(passes > 150){ 270 diag("span looping !"); 271 errorexit(); 272 } 273 c = INITTEXT; 274 oop = op = nil; 275 again = 0; 276 for(p = firstp; p != P; oop = op, op = p, p = p->link){ 277 setarch(p); 278 if(p->pc != c) 279 again = 1; 280 p->pc = c; 281 if(thumb && isbranch(p)) 282 nocache(p); 283 o = oplook(p); 284 m = o->size; 285 if(passes == 1 && thumb && isbranch(p)){ // start conservative so unneeded alignment is not added 286 if(p->as == ABL) 287 m = 4; 288 else 289 m = 2; 290 p->align = 0; 291 } 292 if(p->align){ 293 if((p->align == 4 && (c&3)) || (p->align == 2 && !(c&3))){ 294 if(ispad(op)){ 295 oop->link = p; 296 op = oop; 297 c -= 2; 298 p->pc = c; 299 } 300 else{ 301 op->link = pad(op, c); 302 op = op->link; 303 c += 2; 304 p->pc = c; 305 } 306 again = 1; 307 } 308 } 309 if(m == 0) { 310 if(p->as == ATEXT) { 311 curtext = p; 312 autosize = p->to.offset + 4; 313 if(p->from.sym != S) 314 p->from.sym->value = c; 315 continue; 316 } 317 } 318 c += m; 319 } 320 if(c != lastc || again){ 321 lastc = c; 322 goto loop; 323 } 324 } 325 326 if(0 && seenthumb){ // rm redundant padding - obsolete 327 int d; 328 329 op = nil; 330 d = 0; 331 for(p = firstp; p != P; op = p, p = p->link){ 332 p->pc -= d; 333 if(p->as == ATEXT){ 334 if(p->from.sym != S) 335 p->from.sym->value -= d; 336 // if(p->from.sym != S) print("%s %ux %d %d %d\n", p->from.sym->name ? p->from.sym->name : "?", p->from.sym->value, p->from.sym->thumb, p->from.sym->foreign, p->from.sym->fnptr); 337 } 338 if(ispad(p) && p->link != P && ispad(p->link)){ 339 op->link = p->link->link; 340 d += 4; 341 p = op; 342 } 343 } 344 // print("%d bytes removed (padding)\n", d); 345 c -= d; 346 } 347 348 if(debug['t']) { 349 /* 350 * add strings to text segment 351 */ 352 c = rnd(c, 8); 353 for(i=0; i<NHASH; i++) 354 for(s = hash[i]; s != S; s = s->link) { 355 if(s->type != SSTRING) 356 continue; 357 v = s->value; 358 while(v & 3) 359 v++; 360 s->value = c; 361 c += v; 362 } 363 } 364 365 c = rnd(c, 8); 366 367 setext = lookup("etext", 0); 368 if(setext != S) { 369 setext->value = c; 370 textsize = c - INITTEXT; 371 } 372 if(INITRND) 373 INITDAT = rnd(c, INITRND); 374 if(debug['v']) 375 Bprint(&bso, "tsize = %lux\n", textsize); 376 Bflush(&bso); 377 } 378 379 /* 380 * when the first reference to the literal pool threatens 381 * to go out of range of a 12-bit PC-relative offset, 382 * drop the pool now, and branch round it. 383 * this happens only in extended basic blocks that exceed 4k. 384 */ 385 int 386 checkpool(Prog *p, int sz) 387 { 388 if(thumb){ 389 if(pool.size >= 0x3fc || (p->pc+sz+pool.extra+2+2)+(pool.size-4)-pool.start-4 >= 0x3fc) 390 return flushpool(p, 1, 0); 391 else if(p->link == P) 392 return flushpool(p, 2, 0); 393 return 0; 394 } 395 if(pool.size >= 0xffc || immaddr((p->pc+sz+4)+4+pool.size - pool.start+8) == 0) 396 return flushpool(p, 1, 0); 397 else if(p->link == P) 398 return flushpool(p, 2, 0); 399 return 0; 400 } 401 402 int 403 flushpool(Prog *p, int skip, int force) 404 { 405 Prog *q; 406 407 if(blitrl) { 408 if(skip){ 409 if(0 && skip==1)print("note: flush literal pool at %lux: len=%lud ref=%lux\n", p->pc+4, pool.size, pool.start); 410 q = prg(); 411 q->as = AB; 412 q->to.type = D_BRANCH; 413 q->cond = p->link; 414 q->link = blitrl; 415 blitrl = q; 416 } 417 else if(!force && (p->pc+pool.size-pool.start < (thumb ? 0x3fc+4-pool.extra : 2048))) 418 return 0; 419 elitrl->link = p->link; 420 p->link = blitrl; 421 blitrl = 0; /* BUG: should refer back to values until out-of-range */ 422 elitrl = 0; 423 pool.size = 0; 424 pool.start = 0; 425 pool.extra = 0; 426 return 1; 427 } 428 return 0; 429 } 430 431 void 432 addpool(Prog *p, Adr *a) 433 { 434 Prog *q, t; 435 int c; 436 437 if(thumb) 438 c = thumbaclass(a, p); 439 else 440 c = aclass(a); 441 442 t = zprg; 443 t.as = AWORD; 444 445 switch(c) { 446 default: 447 t.to = *a; 448 break; 449 450 case C_SROREG: 451 case C_LOREG: 452 case C_ROREG: 453 case C_FOREG: 454 case C_SOREG: 455 case C_HOREG: 456 case C_GOREG: 457 case C_FAUTO: 458 case C_SAUTO: 459 case C_LAUTO: 460 case C_LACON: 461 case C_GACON: 462 t.to.type = D_CONST; 463 t.to.offset = instoffset; 464 break; 465 } 466 467 for(q = blitrl; q != P; q = q->link) /* could hash on t.t0.offset */ 468 if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) { 469 p->cond = q; 470 return; 471 } 472 473 q = prg(); 474 *q = t; 475 q->pc = pool.size; 476 477 if(blitrl == P) { 478 blitrl = q; 479 pool.start = p->pc; 480 q->align = 4; 481 } else 482 elitrl->link = q; 483 elitrl = q; 484 pool.size += 4; 485 486 p->cond = q; 487 } 488 489 void 490 xdefine(char *p, int t, long v) 491 { 492 Sym *s; 493 494 s = lookup(p, 0); 495 if(s->type == 0 || s->type == SXREF) { 496 s->type = t; 497 s->value = v; 498 } 499 } 500 501 long 502 regoff(Adr *a) 503 { 504 505 instoffset = 0; 506 aclass(a); 507 return instoffset; 508 } 509 510 long 511 immrot(ulong v) 512 { 513 int i; 514 515 for(i=0; i<16; i++) { 516 if((v & ~0xff) == 0) 517 return (i<<8) | v | (1<<25); 518 v = (v<<2) | (v>>30); 519 } 520 return 0; 521 } 522 523 long 524 immaddr(long v) 525 { 526 if(v >= 0 && v <= 0xfff) 527 return (v & 0xfff) | 528 (1<<24) | /* pre indexing */ 529 (1<<23); /* pre indexing, up */ 530 if(v >= -0xfff && v < 0) 531 return (-v & 0xfff) | 532 (1<<24); /* pre indexing */ 533 return 0; 534 } 535 536 int 537 immfloat(long v) 538 { 539 return (v & 0xC03) == 0; /* offset will fit in floating-point load/store */ 540 } 541 542 int 543 immhalf(long v) 544 { 545 if(v >= 0 && v <= 0xff) 546 return v| 547 (1<<24)| /* pre indexing */ 548 (1<<23); /* pre indexing, up */ 549 if(v >= -0xff && v < 0) 550 return (-v & 0xff)| 551 (1<<24); /* pre indexing */ 552 return 0; 553 } 554 555 int 556 aclass(Adr *a) 557 { 558 Sym *s; 559 int t; 560 561 switch(a->type) { 562 case D_NONE: 563 return C_NONE; 564 565 case D_REG: 566 return C_REG; 567 568 case D_REGREG: 569 return C_REGREG; 570 571 case D_SHIFT: 572 return C_SHIFT; 573 574 case D_FREG: 575 return C_FREG; 576 577 case D_FPCR: 578 return C_FCR; 579 580 case D_OREG: 581 switch(a->name) { 582 case D_EXTERN: 583 case D_STATIC: 584 if(a->sym == 0 || a->sym->name == 0) { 585 print("null sym external\n"); 586 print("%D\n", a); 587 return C_GOK; 588 } 589 s = a->sym; 590 t = s->type; 591 if(t == 0 || t == SXREF) { 592 diag("undefined external: %s in %s", 593 s->name, TNAME); 594 s->type = SDATA; 595 } 596 if(dlm) { 597 switch(t) { 598 default: 599 instoffset = s->value + a->offset + INITDAT; 600 break; 601 case SUNDEF: 602 case STEXT: 603 case SCONST: 604 case SLEAF: 605 case SSTRING: 606 instoffset = s->value + a->offset; 607 break; 608 } 609 return C_ADDR; 610 } 611 instoffset = s->value + a->offset - BIG; 612 t = immaddr(instoffset); 613 if(t) { 614 if(immhalf(instoffset)) 615 return immfloat(t) ? C_HFEXT : C_HEXT; 616 if(immfloat(t)) 617 return C_FEXT; 618 return C_SEXT; 619 } 620 return C_LEXT; 621 case D_AUTO: 622 instoffset = autosize + a->offset; 623 t = immaddr(instoffset); 624 if(t){ 625 if(immhalf(instoffset)) 626 return immfloat(t) ? C_HFAUTO : C_HAUTO; 627 if(immfloat(t)) 628 return C_FAUTO; 629 return C_SAUTO; 630 } 631 return C_LAUTO; 632 633 case D_PARAM: 634 instoffset = autosize + a->offset + 4L; 635 t = immaddr(instoffset); 636 if(t){ 637 if(immhalf(instoffset)) 638 return immfloat(t) ? C_HFAUTO : C_HAUTO; 639 if(immfloat(t)) 640 return C_FAUTO; 641 return C_SAUTO; 642 } 643 return C_LAUTO; 644 case D_NONE: 645 instoffset = a->offset; 646 t = immaddr(instoffset); 647 if(t) { 648 if(immhalf(instoffset)) /* n.b. that it will also satisfy immrot */ 649 return immfloat(t) ? C_HFOREG : C_HOREG; 650 if(immfloat(t)) 651 return C_FOREG; /* n.b. that it will also satisfy immrot */ 652 t = immrot(instoffset); 653 if(t) 654 return C_SROREG; 655 if(immhalf(instoffset)) 656 return C_HOREG; 657 return C_SOREG; 658 } 659 t = immrot(instoffset); 660 if(t) 661 return C_ROREG; 662 return C_LOREG; 663 } 664 return C_GOK; 665 666 case D_PSR: 667 return C_PSR; 668 669 case D_OCONST: 670 switch(a->name) { 671 case D_EXTERN: 672 case D_STATIC: 673 s = a->sym; 674 t = s->type; 675 if(t == 0 || t == SXREF) { 676 diag("undefined external: %s in %s", 677 s->name, TNAME); 678 s->type = SDATA; 679 } 680 instoffset = s->value + a->offset + INITDAT; 681 if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF) { 682 instoffset = s->value + a->offset; 683 #ifdef CALLEEBX 684 instoffset += fnpinc(s); 685 #else 686 if(s->thumb) 687 instoffset++; // T bit 688 #endif 689 return C_LCON; 690 } 691 return C_LCON; 692 } 693 return C_GOK; 694 695 case D_FCONST: 696 return C_FCON; 697 698 case D_CONST: 699 switch(a->name) { 700 701 case D_NONE: 702 instoffset = a->offset; 703 if(a->reg != NREG) 704 goto aconsize; 705 706 t = immrot(instoffset); 707 if(t) 708 return C_RCON; 709 t = immrot(~instoffset); 710 if(t) 711 return C_NCON; 712 return C_LCON; 713 714 case D_EXTERN: 715 case D_STATIC: 716 s = a->sym; 717 if(s == S) 718 break; 719 t = s->type; 720 switch(t) { 721 case 0: 722 case SXREF: 723 diag("undefined external: %s in %s", 724 s->name, TNAME); 725 s->type = SDATA; 726 break; 727 case SUNDEF: 728 case STEXT: 729 case SSTRING: 730 case SCONST: 731 case SLEAF: 732 instoffset = s->value + a->offset; 733 #ifdef CALLEEBX 734 instoffset += fnpinc(s); 735 #else 736 if(s->thumb) 737 instoffset++; // T bit 738 #endif 739 return C_LCON; 740 } 741 if(!dlm) { 742 instoffset = s->value + a->offset - BIG; 743 t = immrot(instoffset); 744 if(t && instoffset != 0) 745 return C_RECON; 746 } 747 instoffset = s->value + a->offset + INITDAT; 748 return C_LCON; 749 750 case D_AUTO: 751 instoffset = autosize + a->offset; 752 goto aconsize; 753 754 case D_PARAM: 755 instoffset = autosize + a->offset + 4L; 756 aconsize: 757 t = immrot(instoffset); 758 if(t) 759 return C_RACON; 760 return C_LACON; 761 } 762 return C_GOK; 763 764 case D_BRANCH: 765 return C_SBRA; 766 } 767 return C_GOK; 768 } 769 770 Optab* 771 oplook(Prog *p) 772 { 773 int a1, a2, a3, r; 774 char *c1, *c3; 775 Optab *o, *e; 776 Optab *otab; 777 Oprang *orange; 778 779 if(thumb){ 780 otab = thumboptab; 781 orange = thumboprange; 782 } 783 else{ 784 otab = optab; 785 orange = oprange; 786 } 787 a1 = p->optab; 788 if(a1) 789 return otab+(a1-1); 790 a1 = p->from.class; 791 if(a1 == 0) { 792 if(thumb) 793 a1 = thumbaclass(&p->from, p) + 1; 794 else 795 a1 = aclass(&p->from) + 1; 796 p->from.class = a1; 797 } 798 a1--; 799 a3 = p->to.class; 800 if(a3 == 0) { 801 if(thumb) 802 a3 = thumbaclass(&p->to, p) + 1; 803 else 804 a3 = aclass(&p->to) + 1; 805 p->to.class = a3; 806 } 807 a3--; 808 a2 = C_NONE; 809 if(p->reg != NREG) 810 a2 = C_REG; 811 r = p->as; 812 o = orange[r].start; 813 if(o == 0) { 814 a1 = opcross[repop[r]][a1][a2][a3]; 815 if(a1) { 816 p->optab = a1+1; 817 return otab+a1; 818 } 819 o = orange[r].stop; /* just generate an error */ 820 } 821 if(0) { 822 print("oplook %A %d %d %d\n", 823 (int)p->as, a1, a2, a3); 824 print(" %d %d\n", p->from.type, p->to.type); 825 } 826 e = orange[r].stop; 827 c1 = xcmp[a1]; 828 c3 = xcmp[a3]; 829 for(; o<e; o++) 830 if(o->a2 == a2) 831 if(c1[o->a1]) 832 if(c3[o->a3]) { 833 p->optab = (o-otab)+1; 834 return o; 835 } 836 diag("illegal combination %A %d %d %d", 837 p->as, a1, a2, a3); 838 prasm(p); 839 if(o == 0) 840 o = otab; 841 return o; 842 } 843 844 int 845 cmp(int a, int b) 846 { 847 848 if(a == b) 849 return 1; 850 switch(a) { 851 case C_LCON: 852 if(b == C_RCON || b == C_NCON) 853 return 1; 854 break; 855 case C_LACON: 856 if(b == C_RACON) 857 return 1; 858 break; 859 case C_LECON: 860 if(b == C_RECON) 861 return 1; 862 break; 863 864 case C_HFEXT: 865 return b == C_HEXT || b == C_FEXT; 866 case C_FEXT: 867 case C_HEXT: 868 return b == C_HFEXT; 869 case C_SEXT: 870 return cmp(C_HFEXT, b); 871 case C_LEXT: 872 return cmp(C_SEXT, b); 873 874 case C_HFAUTO: 875 return b == C_HAUTO || b == C_FAUTO; 876 case C_FAUTO: 877 case C_HAUTO: 878 return b == C_HFAUTO; 879 case C_SAUTO: 880 return cmp(C_HFAUTO, b); 881 case C_LAUTO: 882 return cmp(C_SAUTO, b); 883 884 case C_HFOREG: 885 return b == C_HOREG || b == C_FOREG; 886 case C_FOREG: 887 case C_HOREG: 888 return b == C_HFOREG; 889 case C_SROREG: 890 return cmp(C_SOREG, b) || cmp(C_ROREG, b); 891 case C_SOREG: 892 case C_ROREG: 893 return b == C_SROREG || cmp(C_HFOREG, b); 894 case C_LOREG: 895 return cmp(C_SROREG, b); 896 897 case C_LBRA: 898 if(b == C_SBRA) 899 return 1; 900 break; 901 case C_GBRA: 902 if(b == C_SBRA || b == C_LBRA) 903 return 1; 904 905 case C_HREG: 906 return cmp(C_SP, b) || cmp(C_PC, b); 907 908 } 909 return 0; 910 } 911 912 int 913 ocmp(void *a1, void *a2) 914 { 915 Optab *p1, *p2; 916 int n; 917 918 p1 = (Optab*)a1; 919 p2 = (Optab*)a2; 920 n = p1->as - p2->as; 921 if(n) 922 return n; 923 n = (p2->flag&V4) - (p1->flag&V4); /* architecture version */ 924 if(n) 925 return n; 926 n = p1->a1 - p2->a1; 927 if(n) 928 return n; 929 n = p1->a2 - p2->a2; 930 if(n) 931 return n; 932 n = p1->a3 - p2->a3; 933 if(n) 934 return n; 935 return 0; 936 } 937 938 void 939 buildop(void) 940 { 941 int i, n, r; 942 943 armv4 = !debug['h']; 944 for(i=0; i<C_GOK; i++) 945 for(n=0; n<C_GOK; n++) 946 xcmp[i][n] = cmp(n, i); 947 for(n=0; optab[n].as != AXXX; n++) 948 if((optab[n].flag & V4) && !armv4) { 949 optab[n].as = AXXX; 950 break; 951 } 952 qsort(optab, n, sizeof(optab[0]), ocmp); 953 for(i=0; i<n; i++) { 954 r = optab[i].as; 955 oprange[r].start = optab+i; 956 while(optab[i].as == r) 957 i++; 958 oprange[r].stop = optab+i; 959 i--; 960 961 switch(r) 962 { 963 default: 964 diag("unknown op in build: %A", r); 965 errorexit(); 966 case AADD: 967 oprange[AAND] = oprange[r]; 968 oprange[AEOR] = oprange[r]; 969 oprange[ASUB] = oprange[r]; 970 oprange[ARSB] = oprange[r]; 971 oprange[AADC] = oprange[r]; 972 oprange[ASBC] = oprange[r]; 973 oprange[ARSC] = oprange[r]; 974 oprange[AORR] = oprange[r]; 975 oprange[ABIC] = oprange[r]; 976 break; 977 case ACMP: 978 oprange[ATST] = oprange[r]; 979 oprange[ATEQ] = oprange[r]; 980 oprange[ACMN] = oprange[r]; 981 break; 982 case AMVN: 983 break; 984 case ABEQ: 985 oprange[ABNE] = oprange[r]; 986 oprange[ABCS] = oprange[r]; 987 oprange[ABHS] = oprange[r]; 988 oprange[ABCC] = oprange[r]; 989 oprange[ABLO] = oprange[r]; 990 oprange[ABMI] = oprange[r]; 991 oprange[ABPL] = oprange[r]; 992 oprange[ABVS] = oprange[r]; 993 oprange[ABVC] = oprange[r]; 994 oprange[ABHI] = oprange[r]; 995 oprange[ABLS] = oprange[r]; 996 oprange[ABGE] = oprange[r]; 997 oprange[ABLT] = oprange[r]; 998 oprange[ABGT] = oprange[r]; 999 oprange[ABLE] = oprange[r]; 1000 break; 1001 case ASLL: 1002 oprange[ASRL] = oprange[r]; 1003 oprange[ASRA] = oprange[r]; 1004 break; 1005 case AMUL: 1006 oprange[AMULU] = oprange[r]; 1007 break; 1008 case ADIV: 1009 oprange[AMOD] = oprange[r]; 1010 oprange[AMODU] = oprange[r]; 1011 oprange[ADIVU] = oprange[r]; 1012 break; 1013 case AMOVW: 1014 case AMOVB: 1015 case AMOVBU: 1016 case AMOVH: 1017 case AMOVHU: 1018 break; 1019 case ASWPW: 1020 oprange[ASWPBU] = oprange[r]; 1021 break; 1022 case AB: 1023 case ABL: 1024 case ABX: 1025 case ABXRET: 1026 case ASWI: 1027 case AWORD: 1028 case AMOVM: 1029 case ARFE: 1030 case ATEXT: 1031 case ACASE: 1032 case ABCASE: 1033 break; 1034 case AADDF: 1035 oprange[AADDD] = oprange[r]; 1036 oprange[ASUBF] = oprange[r]; 1037 oprange[ASUBD] = oprange[r]; 1038 oprange[AMULF] = oprange[r]; 1039 oprange[AMULD] = oprange[r]; 1040 oprange[ADIVF] = oprange[r]; 1041 oprange[ADIVD] = oprange[r]; 1042 oprange[AMOVFD] = oprange[r]; 1043 oprange[AMOVDF] = oprange[r]; 1044 break; 1045 1046 case ACMPF: 1047 oprange[ACMPD] = oprange[r]; 1048 break; 1049 1050 case AMOVF: 1051 oprange[AMOVD] = oprange[r]; 1052 break; 1053 1054 case AMOVFW: 1055 oprange[AMOVWF] = oprange[r]; 1056 oprange[AMOVWD] = oprange[r]; 1057 oprange[AMOVDW] = oprange[r]; 1058 break; 1059 1060 case AMULL: 1061 oprange[AMULA] = oprange[r]; 1062 oprange[AMULAL] = oprange[r]; 1063 oprange[AMULLU] = oprange[r]; 1064 oprange[AMULALU] = oprange[r]; 1065 break; 1066 } 1067 } 1068 } 1069 1070 /* 1071 void 1072 buildrep(int x, int as) 1073 { 1074 Opcross *p; 1075 Optab *e, *s, *o; 1076 int a1, a2, a3, n; 1077 1078 if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) { 1079 diag("assumptions fail in buildrep"); 1080 errorexit(); 1081 } 1082 repop[as] = x; 1083 p = (opcross + x); 1084 s = oprange[as].start; 1085 e = oprange[as].stop; 1086 for(o=e-1; o>=s; o--) { 1087 n = o-optab; 1088 for(a2=0; a2<2; a2++) { 1089 if(a2) { 1090 if(o->a2 == C_NONE) 1091 continue; 1092 } else 1093 if(o->a2 != C_NONE) 1094 continue; 1095 for(a1=0; a1<32; a1++) { 1096 if(!xcmp[a1][o->a1]) 1097 continue; 1098 for(a3=0; a3<32; a3++) 1099 if(xcmp[a3][o->a3]) 1100 (*p)[a1][a2][a3] = n; 1101 } 1102 } 1103 } 1104 oprange[as].start = 0; 1105 } 1106 */ 1107 1108 enum{ 1109 ABSD = 0, 1110 ABSU = 1, 1111 RELD = 2, 1112 RELU = 3, 1113 }; 1114 1115 int modemap[4] = { 0, 1, -1, 2, }; 1116 1117 typedef struct Reloc Reloc; 1118 1119 struct Reloc 1120 { 1121 int n; 1122 int t; 1123 uchar *m; 1124 ulong *a; 1125 }; 1126 1127 Reloc rels; 1128 1129 static void 1130 grow(Reloc *r) 1131 { 1132 int t; 1133 uchar *m, *nm; 1134 ulong *a, *na; 1135 1136 t = r->t; 1137 r->t += 64; 1138 m = r->m; 1139 a = r->a; 1140 r->m = nm = malloc(r->t*sizeof(uchar)); 1141 r->a = na = malloc(r->t*sizeof(ulong)); 1142 memmove(nm, m, t*sizeof(uchar)); 1143 memmove(na, a, t*sizeof(ulong)); 1144 free(m); 1145 free(a); 1146 } 1147 1148 void 1149 dynreloc(Sym *s, long v, int abs) 1150 { 1151 int i, k, n; 1152 uchar *m; 1153 ulong *a; 1154 Reloc *r; 1155 1156 if(v&3) 1157 diag("bad relocation address"); 1158 v >>= 2; 1159 if(s != S && s->type == SUNDEF) 1160 k = abs ? ABSU : RELU; 1161 else 1162 k = abs ? ABSD : RELD; 1163 /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */ 1164 k = modemap[k]; 1165 r = &rels; 1166 n = r->n; 1167 if(n >= r->t) 1168 grow(r); 1169 m = r->m; 1170 a = r->a; 1171 for(i = n; i > 0; i--){ 1172 if(v < a[i-1]){ /* happens occasionally for data */ 1173 m[i] = m[i-1]; 1174 a[i] = a[i-1]; 1175 } 1176 else 1177 break; 1178 } 1179 m[i] = k; 1180 a[i] = v; 1181 r->n++; 1182 } 1183 1184 static int 1185 sput(char *s) 1186 { 1187 char *p; 1188 1189 p = s; 1190 while(*s) 1191 cput(*s++); 1192 cput(0); 1193 return s-p+1; 1194 } 1195 1196 void 1197 asmdyn() 1198 { 1199 int i, n, t, c; 1200 Sym *s; 1201 ulong la, ra, *a; 1202 vlong off; 1203 uchar *m; 1204 Reloc *r; 1205 1206 cflush(); 1207 off = seek(cout, 0, 1); 1208 lput(0); 1209 t = 0; 1210 lput(imports); 1211 t += 4; 1212 for(i = 0; i < NHASH; i++) 1213 for(s = hash[i]; s != S; s = s->link) 1214 if(s->type == SUNDEF){ 1215 lput(s->sig); 1216 t += 4; 1217 t += sput(s->name); 1218 } 1219 1220 la = 0; 1221 r = &rels; 1222 n = r->n; 1223 m = r->m; 1224 a = r->a; 1225 lput(n); 1226 t += 4; 1227 for(i = 0; i < n; i++){ 1228 ra = *a-la; 1229 if(*a < la) 1230 diag("bad relocation order"); 1231 if(ra < 256) 1232 c = 0; 1233 else if(ra < 65536) 1234 c = 1; 1235 else 1236 c = 2; 1237 cput((c<<6)|*m++); 1238 t++; 1239 if(c == 0){ 1240 cput(ra); 1241 t++; 1242 } 1243 else if(c == 1){ 1244 wput(ra); 1245 t += 2; 1246 } 1247 else{ 1248 lput(ra); 1249 t += 4; 1250 } 1251 la = *a++; 1252 } 1253 1254 cflush(); 1255 seek(cout, off, 0); 1256 lput(t); 1257 1258 if(debug['v']){ 1259 Bprint(&bso, "import table entries = %d\n", imports); 1260 Bprint(&bso, "export table entries = %d\n", exports); 1261 } 1262 } 1263