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