1 #define EXTERN 2 #include "l.h" 3 #include <ar.h> 4 5 #ifndef DEFAULT 6 #define DEFAULT '9' 7 #endif 8 9 char *noname = "<none>"; 10 char symname[] = SYMDEF; 11 char thechar = 'v'; 12 char *thestring = "mips"; 13 14 /* 15 * -H0 -T0x40004C -D0x10000000 is abbrev unix 16 * -H1 -T0x80020000 -R4 is bootp() format for 3k 17 * -H2 -T4128 -R4096 is plan9 format 18 * -H3 -T0x80020000 -R8 is bootp() format for 4k 19 * -H4 -T0x400000 -R4 is sgi unix coff executable 20 * -H5 -T0x4000A0 -R4 is sgi unix elf executable 21 * -H6 is headerless 22 */ 23 24 int little; 25 26 void 27 main(int argc, char *argv[]) 28 { 29 int c; 30 char *a; 31 32 Binit(&bso, 1, OWRITE); 33 cout = -1; 34 listinit(); 35 outfile = 0; 36 nerrors = 0; 37 curtext = P; 38 HEADTYPE = -1; 39 INITTEXT = -1; 40 INITDAT = -1; 41 INITRND = -1; 42 INITENTRY = 0; 43 44 ARGBEGIN { 45 default: 46 c = ARGC(); 47 if(c >= 0 && c < sizeof(debug)) 48 debug[c]++; 49 break; 50 case 'o': 51 outfile = ARGF(); 52 break; 53 case 'E': 54 a = ARGF(); 55 if(a) 56 INITENTRY = a; 57 break; 58 case 'L': /* for little-endian mips */ 59 thechar = '0'; 60 thestring = "spim"; 61 little = 1; 62 break; 63 case 'T': 64 a = ARGF(); 65 if(a) 66 INITTEXT = atolwhex(a); 67 break; 68 case 'D': 69 a = ARGF(); 70 if(a) 71 INITDAT = atolwhex(a); 72 break; 73 case 'R': 74 a = ARGF(); 75 if(a) 76 INITRND = atolwhex(a); 77 break; 78 case 'H': 79 a = ARGF(); 80 if(a) 81 HEADTYPE = atolwhex(a); 82 /* do something about setting INITTEXT */ 83 break; 84 } ARGEND 85 86 USED(argc); 87 88 if(*argv == 0) { 89 diag("usage: %cl [-options] objects", thechar); 90 errorexit(); 91 } 92 if(!debug['9'] && !debug['U'] && !debug['B']) 93 debug[DEFAULT] = 1; 94 if(HEADTYPE == -1) { 95 if(debug['U']) 96 HEADTYPE = 0; 97 if(debug['B']) 98 HEADTYPE = 1; 99 if(debug['9']) 100 HEADTYPE = 2; 101 } 102 switch(HEADTYPE) { 103 default: 104 diag("unknown -H option"); 105 errorexit(); 106 107 case 0: /* unix simple */ 108 HEADR = 20L+56L; 109 if(INITTEXT == -1) 110 INITTEXT = 0x40004CL; 111 if(INITDAT == -1) 112 INITDAT = 0x10000000L; 113 if(INITRND == -1) 114 INITRND = 0; 115 break; 116 case 1: /* boot for 3k */ 117 HEADR = 20L+60L; 118 if(INITTEXT == -1) 119 INITTEXT = 0x80020000L; 120 if(INITDAT == -1) 121 INITDAT = 0; 122 if(INITRND == -1) 123 INITRND = 4; 124 break; 125 case 2: /* plan 9 */ 126 HEADR = 32L; 127 if(INITTEXT == -1) 128 INITTEXT = 4128; 129 if(INITDAT == -1) 130 INITDAT = 0; 131 if(INITRND == -1) 132 INITRND = 4096; 133 break; 134 case 3: /* boot for 4k */ 135 HEADR = 20L+56L+3*40L; 136 if(INITTEXT == -1) 137 INITTEXT = 0x80020000L; 138 if(INITDAT == -1) 139 INITDAT = 0; 140 if(INITRND == -1) 141 INITRND = 8; 142 break; 143 case 4: /* sgi unix coff executable */ 144 HEADR = 20L+56L+3*40L; 145 if(INITTEXT == -1) 146 INITTEXT = 0x00400000L+HEADR; 147 if(INITDAT == -1) 148 INITDAT = 0x10000000; 149 if(INITRND == -1) 150 INITRND = 0; 151 break; 152 case 5: /* sgi unix elf executable */ 153 HEADR = rnd(52L+3*32L, 16); 154 if(INITTEXT == -1) 155 INITTEXT = 0x00400000L+HEADR; 156 if(INITDAT == -1) 157 INITDAT = 0x10000000; 158 if(INITRND == -1) 159 INITRND = 0; 160 break; 161 case 6: /* headerless */ 162 HEADR = 0; 163 if(INITTEXT == -1) 164 INITTEXT = 0x80000000L+HEADR; 165 if(INITDAT == -1) 166 INITDAT = 0; 167 if(INITRND == -1) 168 INITRND = 4096; 169 break; 170 } 171 if(INITDAT != 0 && INITRND != 0) 172 print("warning: -D0x%lux is ignored because of -R0x%lux\n", 173 INITDAT, INITRND); 174 if(debug['v']) 175 Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n", 176 HEADTYPE, INITTEXT, INITDAT, INITRND); 177 Bflush(&bso); 178 zprg.as = AGOK; 179 zprg.reg = NREG; 180 zprg.from.name = D_NONE; 181 zprg.from.type = D_NONE; 182 zprg.from.reg = NREG; 183 zprg.to = zprg.from; 184 buildop(); 185 histgen = 0; 186 textp = P; 187 datap = P; 188 pc = 0; 189 dtype = 4; 190 if(outfile == 0) { 191 static char name[20]; 192 193 snprint(name, sizeof name, "%c.out", thechar); 194 outfile = name; 195 } 196 cout = create(outfile, 1, 0775); 197 if(cout < 0) { 198 diag("%s: cannot create", outfile); 199 errorexit(); 200 } 201 nuxiinit(); 202 203 version = 0; 204 cbp = buf.cbuf; 205 cbc = sizeof(buf.cbuf); 206 firstp = prg(); 207 lastp = firstp; 208 209 if(INITENTRY == 0) { 210 INITENTRY = "_main"; 211 if(debug['p']) 212 INITENTRY = "_mainp"; 213 if(!debug['l']) 214 lookup(INITENTRY, 0)->type = SXREF; 215 } else 216 lookup(INITENTRY, 0)->type = SXREF; 217 218 while(*argv) 219 objfile(*argv++); 220 if(!debug['l']) 221 loadlib(); 222 firstp = firstp->link; 223 if(firstp == P) 224 goto out; 225 patch(); 226 if(debug['p']) 227 if(debug['1']) 228 doprof1(); 229 else 230 doprof2(); 231 dodata(); 232 follow(); 233 if(firstp == P) 234 goto out; 235 noops(); 236 span(); 237 asmb(); 238 undef(); 239 240 out: 241 if(debug['v']) { 242 Bprint(&bso, "%5.2f cpu time\n", cputime()); 243 Bprint(&bso, "%ld memory used\n", thunk); 244 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); 245 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); 246 } 247 Bflush(&bso); 248 errorexit(); 249 } 250 251 void 252 loadlib(void) 253 { 254 int i; 255 long h; 256 Sym *s; 257 258 loop: 259 xrefresolv = 0; 260 for(i=0; i<libraryp; i++) { 261 if(debug['v']) 262 Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]); 263 objfile(library[i]); 264 } 265 if(xrefresolv) 266 for(h=0; h<nelem(hash); h++) 267 for(s = hash[h]; s != S; s = s->link) 268 if(s->type == SXREF) 269 goto loop; 270 } 271 272 void 273 errorexit(void) 274 { 275 276 if(nerrors) { 277 if(cout >= 0) 278 remove(outfile); 279 exits("error"); 280 } 281 exits(0); 282 } 283 284 void 285 objfile(char *file) 286 { 287 long off, esym, cnt, l; 288 int f, work; 289 Sym *s; 290 char magbuf[SARMAG]; 291 char name[100], pname[150]; 292 struct ar_hdr arhdr; 293 char *e, *start, *stop; 294 295 if(file[0] == '-' && file[1] == 'l') { 296 if(debug['9']) 297 sprint(name, "/%s/lib/lib", thestring); 298 else 299 sprint(name, "/usr/%clib/lib", thechar); 300 strcat(name, file+2); 301 strcat(name, ".a"); 302 file = name; 303 } 304 if(debug['v']) 305 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file); 306 Bflush(&bso); 307 f = open(file, 0); 308 if(f < 0) { 309 diag("cannot open file: %s", file); 310 errorexit(); 311 } 312 l = read(f, magbuf, SARMAG); 313 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){ 314 /* load it as a regular file */ 315 l = seek(f, 0L, 2); 316 seek(f, 0L, 0); 317 ldobj(f, l, file); 318 close(f); 319 return; 320 } 321 322 if(debug['v']) 323 Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file); 324 l = read(f, &arhdr, SAR_HDR); 325 if(l != SAR_HDR) { 326 diag("%s: short read on archive file symbol header", file); 327 goto out; 328 } 329 if(strncmp(arhdr.name, symname, strlen(symname))) { 330 diag("%s: first entry not symbol header", file); 331 goto out; 332 } 333 334 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size); 335 off = SARMAG + SAR_HDR; 336 337 /* 338 * just bang the whole symbol file into memory 339 */ 340 seek(f, off, 0); 341 cnt = esym - off; 342 start = malloc(cnt + 10); 343 cnt = read(f, start, cnt); 344 if(cnt <= 0){ 345 close(f); 346 return; 347 } 348 stop = &start[cnt]; 349 memset(stop, 0, 10); 350 351 work = 1; 352 while(work){ 353 if(debug['v']) 354 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file); 355 Bflush(&bso); 356 work = 0; 357 for(e = start; e < stop; e = strchr(e+5, 0) + 1) { 358 s = lookup(e+5, 0); 359 if(s->type != SXREF) 360 continue; 361 sprint(pname, "%s(%s)", file, s->name); 362 if(debug['v']) 363 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname); 364 Bflush(&bso); 365 l = e[1] & 0xff; 366 l |= (e[2] & 0xff) << 8; 367 l |= (e[3] & 0xff) << 16; 368 l |= (e[4] & 0xff) << 24; 369 seek(f, l, 0); 370 l = read(f, &arhdr, SAR_HDR); 371 if(l != SAR_HDR) 372 goto bad; 373 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag))) 374 goto bad; 375 l = atolwhex(arhdr.size); 376 ldobj(f, l, pname); 377 if(s->type == SXREF) { 378 diag("%s: failed to load: %s", file, s->name); 379 errorexit(); 380 } 381 work = 1; 382 xrefresolv = 1; 383 } 384 } 385 return; 386 387 bad: 388 diag("%s: bad or out of date archive", file); 389 out: 390 close(f); 391 } 392 393 int 394 zaddr(uchar *p, Adr *a, Sym *h[]) 395 { 396 int i, c; 397 long l; 398 Sym *s; 399 Auto *u; 400 401 c = p[2]; 402 if(c < 0 || c > NSYM){ 403 print("sym out of range: %d\n", c); 404 p[0] = ALAST+1; 405 return 0; 406 } 407 a->type = p[0]; 408 a->reg = p[1]; 409 a->sym = h[c]; 410 a->name = p[3]; 411 c = 4; 412 413 if(a->reg < 0 || a->reg > NREG) { 414 print("register out of range %d\n", a->reg); 415 p[0] = ALAST+1; 416 return 0; /* force real diagnostic */ 417 } 418 419 switch(a->type) { 420 default: 421 print("unknown type %d\n", a->type); 422 p[0] = ALAST+1; 423 return 0; /* force real diagnostic */ 424 425 case D_NONE: 426 case D_REG: 427 case D_FREG: 428 case D_MREG: 429 case D_FCREG: 430 case D_LO: 431 case D_HI: 432 break; 433 434 case D_BRANCH: 435 case D_OREG: 436 case D_CONST: 437 case D_OCONST: 438 a->offset = p[4] | (p[5]<<8) | 439 (p[6]<<16) | (p[7]<<24); 440 c += 4; 441 break; 442 443 case D_SCONST: 444 while(nhunk < NSNAME) 445 gethunk(); 446 a->sval = (char*)hunk; 447 nhunk -= NSNAME; 448 hunk += NSNAME; 449 450 memmove(a->sval, p+4, NSNAME); 451 c += NSNAME; 452 break; 453 454 case D_FCONST: 455 while(nhunk < sizeof(Ieee)) 456 gethunk(); 457 a->ieee = (Ieee*)hunk; 458 nhunk -= NSNAME; 459 hunk += NSNAME; 460 461 a->ieee->l = p[4] | (p[5]<<8) | 462 (p[6]<<16) | (p[7]<<24); 463 a->ieee->h = p[8] | (p[9]<<8) | 464 (p[10]<<16) | (p[11]<<24); 465 c += 8; 466 break; 467 } 468 s = a->sym; 469 if(s == S) 470 return c; 471 i = a->name; 472 if(i != D_AUTO && i != D_PARAM) 473 return c; 474 475 l = a->offset; 476 for(u=curauto; u; u=u->link) 477 if(u->asym == s) 478 if(u->type == i) { 479 if(u->aoffset > l) 480 u->aoffset = l; 481 return c; 482 } 483 484 while(nhunk < sizeof(Auto)) 485 gethunk(); 486 u = (Auto*)hunk; 487 nhunk -= sizeof(Auto); 488 hunk += sizeof(Auto); 489 490 u->link = curauto; 491 curauto = u; 492 u->asym = s; 493 u->aoffset = l; 494 u->type = i; 495 return c; 496 } 497 498 void 499 addlib(char *obj) 500 { 501 char name[1024], comp[256], *p; 502 int i; 503 504 if(histfrogp <= 0) 505 return; 506 507 if(histfrog[0]->name[1] == '/') { 508 sprint(name, ""); 509 i = 1; 510 } else 511 if(histfrog[0]->name[1] == '.') { 512 sprint(name, "."); 513 i = 0; 514 } else { 515 if(debug['9']) 516 sprint(name, "/%s/lib", thestring); 517 else 518 sprint(name, "/usr/%clib", thechar); 519 i = 0; 520 } 521 522 for(; i<histfrogp; i++) { 523 snprint(comp, sizeof comp, histfrog[i]->name+1); 524 for(;;) { 525 p = strstr(comp, "$O"); 526 if(p == 0) 527 break; 528 memmove(p+1, p+2, strlen(p+2)+1); 529 p[0] = thechar; 530 } 531 for(;;) { 532 p = strstr(comp, "$M"); 533 if(p == 0) 534 break; 535 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) { 536 diag("library component too long"); 537 return; 538 } 539 memmove(p+strlen(thestring), p+2, strlen(p+2)+1); 540 memmove(p, thestring, strlen(thestring)); 541 } 542 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) { 543 diag("library component too long"); 544 return; 545 } 546 strcat(name, "/"); 547 strcat(name, comp); 548 } 549 for(i=0; i<libraryp; i++) 550 if(strcmp(name, library[i]) == 0) 551 return; 552 if(libraryp == nelem(library)){ 553 diag("too many autolibs; skipping %s", name); 554 return; 555 } 556 557 p = malloc(strlen(name) + 1); 558 strcpy(p, name); 559 library[libraryp] = p; 560 p = malloc(strlen(obj) + 1); 561 strcpy(p, obj); 562 libraryobj[libraryp] = p; 563 libraryp++; 564 } 565 566 void 567 addhist(long line, int type) 568 { 569 Auto *u; 570 Sym *s; 571 int i, j, k; 572 573 u = malloc(sizeof(Auto)); 574 s = malloc(sizeof(Sym)); 575 s->name = malloc(2*(histfrogp+1) + 1); 576 577 u->asym = s; 578 u->type = type; 579 u->aoffset = line; 580 u->link = curhist; 581 curhist = u; 582 583 j = 1; 584 for(i=0; i<histfrogp; i++) { 585 k = histfrog[i]->value; 586 s->name[j+0] = k>>8; 587 s->name[j+1] = k; 588 j += 2; 589 } 590 } 591 592 void 593 histtoauto(void) 594 { 595 Auto *l; 596 597 while(l = curhist) { 598 curhist = l->link; 599 l->link = curauto; 600 curauto = l; 601 } 602 } 603 604 void 605 collapsefrog(Sym *s) 606 { 607 int i; 608 609 /* 610 * bad encoding of path components only allows 611 * MAXHIST components. if there is an overflow, 612 * first try to collapse xxx/.. 613 */ 614 for(i=1; i<histfrogp; i++) 615 if(strcmp(histfrog[i]->name+1, "..") == 0) { 616 memmove(histfrog+i-1, histfrog+i+1, 617 (histfrogp-i-1)*sizeof(histfrog[0])); 618 histfrogp--; 619 goto out; 620 } 621 622 /* 623 * next try to collapse . 624 */ 625 for(i=0; i<histfrogp; i++) 626 if(strcmp(histfrog[i]->name+1, ".") == 0) { 627 memmove(histfrog+i, histfrog+i+1, 628 (histfrogp-i-1)*sizeof(histfrog[0])); 629 goto out; 630 } 631 632 /* 633 * last chance, just truncate from front 634 */ 635 memmove(histfrog+0, histfrog+1, 636 (histfrogp-1)*sizeof(histfrog[0])); 637 638 out: 639 histfrog[histfrogp-1] = s; 640 } 641 642 void 643 nopout(Prog *p) 644 { 645 p->as = ANOP; 646 p->from.type = D_NONE; 647 p->to.type = D_NONE; 648 } 649 650 uchar* 651 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max) 652 { 653 int n; 654 655 n = stop - good; 656 memmove(buf, good, stop - good); 657 stop = buf + n; 658 n = MAXIO - n; 659 if(n > max) 660 n = max; 661 n = read(f, stop, n); 662 if(n <= 0) 663 return 0; 664 return stop + n; 665 } 666 667 void 668 ldobj(int f, long c, char *pn) 669 { 670 long ipc; 671 Prog *p, *t; 672 uchar *bloc, *bsize, *stop; 673 Sym *h[NSYM], *s, *di; 674 int v, o, r, skip; 675 676 bsize = buf.xbuf; 677 bloc = buf.xbuf; 678 di = S; 679 680 newloop: 681 memset(h, 0, sizeof(h)); 682 version++; 683 histfrogp = 0; 684 ipc = pc; 685 skip = 0; 686 687 loop: 688 if(c <= 0) 689 goto eof; 690 r = bsize - bloc; 691 if(r < 100 && r < c) { /* enough for largest prog */ 692 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 693 if(bsize == 0) 694 goto eof; 695 bloc = buf.xbuf; 696 goto loop; 697 } 698 o = bloc[0]; /* as */ 699 if(o <= AXXX || o >= ALAST) { 700 diag("%s: line %ld: opcode out of range %d", pn, pc-ipc, o); 701 print(" probably not a .%c file\n", thechar); 702 errorexit(); 703 } 704 if(o == ANAME || o == ASIGNAME) { 705 if(o == ASIGNAME) { 706 bloc += 4; 707 c -= 4; 708 } 709 stop = memchr(&bloc[3], 0, bsize-&bloc[3]); 710 if(stop == 0){ 711 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 712 if(bsize == 0) 713 goto eof; 714 bloc = buf.xbuf; 715 stop = memchr(&bloc[3], 0, bsize-&bloc[3]); 716 if(stop == 0){ 717 fprint(2, "%s: name too long\n", pn); 718 errorexit(); 719 } 720 } 721 v = bloc[1]; /* type */ 722 o = bloc[2]; /* sym */ 723 bloc += 3; 724 c -= 3; 725 726 r = 0; 727 if(v == D_STATIC) 728 r = version; 729 s = lookup((char*)bloc, r); 730 c -= &stop[1] - bloc; 731 bloc = stop + 1; 732 733 if(debug['W']) 734 print(" ANAME %s\n", s->name); 735 h[o] = s; 736 if((v == D_EXTERN || v == D_STATIC) && s->type == 0) 737 s->type = SXREF; 738 if(v == D_FILE) { 739 if(s->type != SFILE) { 740 histgen++; 741 s->type = SFILE; 742 s->value = histgen; 743 } 744 if(histfrogp < MAXHIST) { 745 histfrog[histfrogp] = s; 746 histfrogp++; 747 } else 748 collapsefrog(s); 749 } 750 goto loop; 751 } 752 753 if(nhunk < sizeof(Prog)) 754 gethunk(); 755 p = (Prog*)hunk; 756 nhunk -= sizeof(Prog); 757 hunk += sizeof(Prog); 758 759 p->as = o; 760 p->reg = bloc[1] & 0x7f; 761 if(bloc[1] & 0x80) 762 p->mark = NOSCHED; 763 p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24); 764 765 r = zaddr(bloc+6, &p->from, h) + 6; 766 r += zaddr(bloc+r, &p->to, h); 767 bloc += r; 768 c -= r; 769 770 if(p->reg < 0 || p->reg > NREG) 771 diag("register out of range %d", p->reg); 772 773 p->link = P; 774 p->cond = P; 775 776 if(debug['W']) 777 print("%P\n", p); 778 779 switch(o) { 780 case AHISTORY: 781 if(p->to.offset == -1) { 782 addlib(pn); 783 histfrogp = 0; 784 goto loop; 785 } 786 addhist(p->line, D_FILE); /* 'z' */ 787 if(p->to.offset) 788 addhist(p->to.offset, D_FILE1); /* 'Z' */ 789 histfrogp = 0; 790 goto loop; 791 792 case AEND: 793 histtoauto(); 794 if(curtext != P) 795 curtext->to.autom = curauto; 796 curauto = 0; 797 curtext = P; 798 if(c) 799 goto newloop; 800 return; 801 802 case AGLOBL: 803 s = p->from.sym; 804 if(s == S) { 805 diag("GLOBL must have a name\n%P", p); 806 errorexit(); 807 } 808 if(s->type == 0 || s->type == SXREF) { 809 s->type = SBSS; 810 s->value = 0; 811 } 812 if(s->type != SBSS) { 813 diag("redefinition: %s\n%P", s->name, p); 814 s->type = SBSS; 815 s->value = 0; 816 } 817 if(p->to.offset > s->value) 818 s->value = p->to.offset; 819 break; 820 821 case ADYNT: 822 if(p->to.sym == S) { 823 diag("DYNT without a sym\n%P", p); 824 break; 825 } 826 di = p->to.sym; 827 p->reg = 4; 828 if(di->type == SXREF) { 829 if(debug['z']) 830 Bprint(&bso, "%P set to %d\n", p, dtype); 831 di->type = SCONST; 832 di->value = dtype; 833 dtype += 4; 834 } 835 if(p->from.sym == S) 836 break; 837 838 p->from.offset = di->value; 839 p->from.sym->type = SDATA; 840 if(curtext == P) { 841 diag("DYNT not in text: %P", p); 842 break; 843 } 844 p->to.sym = curtext->from.sym; 845 p->to.type = D_CONST; 846 p->link = datap; 847 datap = p; 848 break; 849 850 case AINIT: 851 if(p->from.sym == S) { 852 diag("INIT without a sym\n%P", p); 853 break; 854 } 855 if(di == S) { 856 diag("INIT without previous DYNT\n%P", p); 857 break; 858 } 859 p->from.offset = di->value; 860 p->from.sym->type = SDATA; 861 p->link = datap; 862 datap = p; 863 break; 864 865 case ADATA: 866 if(p->from.sym == S) { 867 diag("DATA without a sym\n%P", p); 868 break; 869 } 870 p->link = datap; 871 datap = p; 872 break; 873 874 case AGOK: 875 diag("unknown opcode\n%P", p); 876 p->pc = pc; 877 pc++; 878 break; 879 880 case ATEXT: 881 if(curtext != P) { 882 histtoauto(); 883 curtext->to.autom = curauto; 884 curauto = 0; 885 } 886 skip = 0; 887 curtext = p; 888 autosize = (p->to.offset+3L) & ~3L; 889 p->to.offset = autosize; 890 autosize += 4; 891 s = p->from.sym; 892 if(s == S) { 893 diag("TEXT must have a name\n%P", p); 894 errorexit(); 895 } 896 if(s->type != 0 && s->type != SXREF) { 897 if(p->reg & DUPOK) { 898 skip = 1; 899 goto casedef; 900 } 901 diag("redefinition: %s\n%P", s->name, p); 902 } 903 s->type = STEXT; 904 s->value = pc; 905 lastp->link = p; 906 lastp = p; 907 p->pc = pc; 908 pc++; 909 if(textp == P) { 910 textp = p; 911 etextp = p; 912 goto loop; 913 } 914 etextp->cond = p; 915 etextp = p; 916 break; 917 918 case ASUB: 919 case ASUBU: 920 if(p->from.type == D_CONST) 921 if(p->from.name == D_NONE) { 922 p->from.offset = -p->from.offset; 923 if(p->as == ASUB) 924 p->as = AADD; 925 else 926 p->as = AADDU; 927 } 928 goto casedef; 929 930 case AMOVF: 931 if(skip) 932 goto casedef; 933 934 if(p->from.type == D_FCONST) { 935 /* size sb 9 max */ 936 sprint(literal, "$%lux", ieeedtof(p->from.ieee)); 937 s = lookup(literal, 0); 938 if(s->type == 0) { 939 s->type = SBSS; 940 s->value = 4; 941 t = prg(); 942 t->as = ADATA; 943 t->line = p->line; 944 t->from.type = D_OREG; 945 t->from.sym = s; 946 t->from.name = D_EXTERN; 947 t->reg = 4; 948 t->to = p->from; 949 t->link = datap; 950 datap = t; 951 } 952 p->from.type = D_OREG; 953 p->from.sym = s; 954 p->from.name = D_EXTERN; 955 p->from.offset = 0; 956 } 957 goto casedef; 958 959 case AMOVD: 960 if(skip) 961 goto casedef; 962 963 if(p->from.type == D_FCONST) { 964 /* size sb 18 max */ 965 sprint(literal, "$%lux.%lux", 966 p->from.ieee->l, p->from.ieee->h); 967 s = lookup(literal, 0); 968 if(s->type == 0) { 969 s->type = SBSS; 970 s->value = 8; 971 t = prg(); 972 t->as = ADATA; 973 t->line = p->line; 974 t->from.type = D_OREG; 975 t->from.sym = s; 976 t->from.name = D_EXTERN; 977 t->reg = 8; 978 t->to = p->from; 979 t->link = datap; 980 datap = t; 981 } 982 p->from.type = D_OREG; 983 p->from.sym = s; 984 p->from.name = D_EXTERN; 985 p->from.offset = 0; 986 } 987 goto casedef; 988 989 default: 990 casedef: 991 if(skip) 992 nopout(p); 993 994 if(p->to.type == D_BRANCH) 995 p->to.offset += ipc; 996 lastp->link = p; 997 lastp = p; 998 p->pc = pc; 999 pc++; 1000 break; 1001 } 1002 goto loop; 1003 1004 eof: 1005 diag("truncated object file: %s", pn); 1006 } 1007 1008 Sym* 1009 lookup(char *symb, int v) 1010 { 1011 Sym *s; 1012 char *p; 1013 long h; 1014 int c, l; 1015 1016 h = v; 1017 for(p=symb; c = *p; p++) 1018 h = h+h+h + c; 1019 l = (p - symb) + 1; 1020 if(h < 0) 1021 h = ~h; 1022 h %= NHASH; 1023 for(s = hash[h]; s != S; s = s->link) 1024 if(s->version == v) 1025 if(memcmp(s->name, symb, l) == 0) 1026 return s; 1027 1028 while(nhunk < sizeof(Sym)) 1029 gethunk(); 1030 s = (Sym*)hunk; 1031 nhunk -= sizeof(Sym); 1032 hunk += sizeof(Sym); 1033 1034 s->name = malloc(l); 1035 memmove(s->name, symb, l); 1036 1037 s->link = hash[h]; 1038 s->type = 0; 1039 s->version = v; 1040 s->value = 0; 1041 hash[h] = s; 1042 return s; 1043 } 1044 1045 Prog* 1046 prg(void) 1047 { 1048 Prog *p; 1049 1050 while(nhunk < sizeof(Prog)) 1051 gethunk(); 1052 p = (Prog*)hunk; 1053 nhunk -= sizeof(Prog); 1054 hunk += sizeof(Prog); 1055 1056 *p = zprg; 1057 return p; 1058 } 1059 1060 void 1061 gethunk(void) 1062 { 1063 char *h; 1064 long nh; 1065 1066 nh = NHUNK; 1067 if(thunk >= 5L*NHUNK) { 1068 nh = 5L*NHUNK; 1069 if(thunk >= 25L*NHUNK) 1070 nh = 25L*NHUNK; 1071 } 1072 h = mysbrk(nh); 1073 if(h == (char*)-1) { 1074 diag("out of memory"); 1075 errorexit(); 1076 } 1077 hunk = h; 1078 nhunk = nh; 1079 thunk += nh; 1080 } 1081 1082 void 1083 doprof1(void) 1084 { 1085 Sym *s; 1086 long n; 1087 Prog *p, *q; 1088 1089 if(debug['v']) 1090 Bprint(&bso, "%5.2f profile 1\n", cputime()); 1091 Bflush(&bso); 1092 s = lookup("__mcount", 0); 1093 n = 1; 1094 for(p = firstp->link; p != P; p = p->link) { 1095 if(p->as == ATEXT) { 1096 q = prg(); 1097 q->line = p->line; 1098 q->link = datap; 1099 datap = q; 1100 q->as = ADATA; 1101 q->from.type = D_OREG; 1102 q->from.name = D_EXTERN; 1103 q->from.offset = n*4; 1104 q->from.sym = s; 1105 q->reg = 4; 1106 q->to = p->from; 1107 q->to.type = D_CONST; 1108 1109 q = prg(); 1110 q->line = p->line; 1111 q->pc = p->pc; 1112 q->link = p->link; 1113 p->link = q; 1114 p = q; 1115 p->as = AMOVW; 1116 p->from.type = D_OREG; 1117 p->from.name = D_EXTERN; 1118 p->from.sym = s; 1119 p->from.offset = n*4 + 4; 1120 p->to.type = D_REG; 1121 p->to.reg = REGTMP; 1122 1123 q = prg(); 1124 q->line = p->line; 1125 q->pc = p->pc; 1126 q->link = p->link; 1127 p->link = q; 1128 p = q; 1129 p->as = AADDU; 1130 p->from.type = D_CONST; 1131 p->from.offset = 1; 1132 p->to.type = D_REG; 1133 p->to.reg = REGTMP; 1134 1135 q = prg(); 1136 q->line = p->line; 1137 q->pc = p->pc; 1138 q->link = p->link; 1139 p->link = q; 1140 p = q; 1141 p->as = AMOVW; 1142 p->from.type = D_REG; 1143 p->from.reg = REGTMP; 1144 p->to.type = D_OREG; 1145 p->to.name = D_EXTERN; 1146 p->to.sym = s; 1147 p->to.offset = n*4 + 4; 1148 1149 n += 2; 1150 continue; 1151 } 1152 } 1153 q = prg(); 1154 q->line = 0; 1155 q->link = datap; 1156 datap = q; 1157 1158 q->as = ADATA; 1159 q->from.type = D_OREG; 1160 q->from.name = D_EXTERN; 1161 q->from.sym = s; 1162 q->reg = 4; 1163 q->to.type = D_CONST; 1164 q->to.offset = n; 1165 1166 s->type = SBSS; 1167 s->value = n*4; 1168 } 1169 1170 void 1171 doprof2(void) 1172 { 1173 Sym *s2, *s4; 1174 Prog *p, *q, *q2, *ps2, *ps4; 1175 1176 if(debug['v']) 1177 Bprint(&bso, "%5.2f profile 2\n", cputime()); 1178 Bflush(&bso); 1179 1180 if(debug['e']){ 1181 s2 = lookup("_tracein", 0); 1182 s4 = lookup("_traceout", 0); 1183 }else{ 1184 s2 = lookup("_profin", 0); 1185 s4 = lookup("_profout", 0); 1186 } 1187 if(s2->type != STEXT || s4->type != STEXT) { 1188 if(debug['e']) 1189 diag("_tracein/_traceout not defined %d %d", s2->type, s4->type); 1190 else 1191 diag("_profin/_profout not defined"); 1192 return; 1193 } 1194 1195 ps2 = P; 1196 ps4 = P; 1197 for(p = firstp; p != P; p = p->link) { 1198 if(p->as == ATEXT) { 1199 if(p->from.sym == s2) { 1200 ps2 = p; 1201 p->reg = 1; 1202 } 1203 if(p->from.sym == s4) { 1204 ps4 = p; 1205 p->reg = 1; 1206 } 1207 } 1208 } 1209 for(p = firstp; p != P; p = p->link) { 1210 if(p->as == ATEXT) { 1211 if(p->reg & NOPROF) { 1212 for(;;) { 1213 q = p->link; 1214 if(q == P) 1215 break; 1216 if(q->as == ATEXT) 1217 break; 1218 p = q; 1219 } 1220 continue; 1221 } 1222 1223 /* 1224 * JAL profin, R2 1225 */ 1226 q = prg(); 1227 q->line = p->line; 1228 q->pc = p->pc; 1229 q->link = p->link; 1230 if(debug['e']){ /* embedded tracing */ 1231 q2 = prg(); 1232 p->link = q2; 1233 q2->link = q; 1234 1235 q2->line = p->line; 1236 q2->pc = p->pc; 1237 1238 q2->as = AJMP; 1239 q2->to.type = D_BRANCH; 1240 q2->to.sym = p->to.sym; 1241 q2->cond = q->link; 1242 }else 1243 p->link = q; 1244 p = q; 1245 p->as = AJAL; 1246 p->to.type = D_BRANCH; 1247 p->cond = ps2; 1248 p->to.sym = s2; 1249 1250 continue; 1251 } 1252 if(p->as == ARET) { 1253 /* 1254 * RET (default) 1255 */ 1256 if(debug['e']){ /* embedded tracing */ 1257 q = prg(); 1258 q->line = p->line; 1259 q->pc = p->pc; 1260 q->link = p->link; 1261 p->link = q; 1262 p = q; 1263 } 1264 /* 1265 * RET 1266 */ 1267 q = prg(); 1268 q->as = ARET; 1269 q->from = p->from; 1270 q->to = p->to; 1271 q->link = p->link; 1272 p->link = q; 1273 1274 /* 1275 * JAL profout 1276 */ 1277 p->as = AJAL; 1278 p->from = zprg.from; 1279 p->to = zprg.to; 1280 p->to.type = D_BRANCH; 1281 p->cond = ps4; 1282 p->to.sym = s4; 1283 1284 p = q; 1285 1286 continue; 1287 } 1288 } 1289 } 1290 1291 void 1292 nuxiinit(void) 1293 { 1294 int i, c; 1295 1296 for(i=0; i<4; i++) 1297 if (!little) { /* normal big-endian case */ 1298 c = find1(0x01020304L, i+1); 1299 if(i >= 2) 1300 inuxi2[i-2] = c; 1301 if(i >= 3) 1302 inuxi1[i-3] = c; 1303 inuxi4[i] = c; 1304 fnuxi8[i] = c+4; 1305 fnuxi8[i+4] = c; 1306 } else { /* oddball little-endian case */ 1307 c = find1(0x04030201L, i+1); 1308 if(i < 2) 1309 inuxi2[i] = c; 1310 if(i < 1) 1311 inuxi1[i] = c; 1312 inuxi4[i] = c; 1313 fnuxi4[i] = c; 1314 fnuxi8[i] = c; 1315 fnuxi8[i+4] = c+4; 1316 } 1317 if(debug['v']) { 1318 Bprint(&bso, "inuxi = "); 1319 for(i=0; i<1; i++) 1320 Bprint(&bso, "%d", inuxi1[i]); 1321 Bprint(&bso, " "); 1322 for(i=0; i<2; i++) 1323 Bprint(&bso, "%d", inuxi2[i]); 1324 Bprint(&bso, " "); 1325 for(i=0; i<4; i++) 1326 Bprint(&bso, "%d", inuxi4[i]); 1327 Bprint(&bso, "\nfnuxi = "); 1328 for(i=0; i<8; i++) 1329 Bprint(&bso, "%d", fnuxi8[i]); 1330 Bprint(&bso, "\n"); 1331 } 1332 Bflush(&bso); 1333 } 1334 1335 find1(long l, int c) 1336 { 1337 char *p; 1338 int i; 1339 1340 p = (char*)&l; 1341 for(i=0; i<4; i++) 1342 if(*p++ == c) 1343 return i; 1344 return 0; 1345 } 1346 1347 long 1348 ieeedtof(Ieee *ieeep) 1349 { 1350 int exp; 1351 long v; 1352 1353 if(ieeep->h == 0) 1354 return 0; 1355 exp = (ieeep->h>>20) & ((1L<<11)-1L); 1356 exp -= (1L<<10) - 2L; 1357 v = (ieeep->h & 0xfffffL) << 3; 1358 v |= (ieeep->l >> 29) & 0x7L; 1359 if((ieeep->l >> 28) & 1) { 1360 v++; 1361 if(v & 0x800000L) { 1362 v = (v & 0x7fffffL) >> 1; 1363 exp++; 1364 } 1365 } 1366 if(exp <= -126 || exp >= 130) 1367 diag("double fp to single fp overflow"); 1368 v |= ((exp + 126) & 0xffL) << 23; 1369 v |= ieeep->h & 0x80000000L; 1370 return v; 1371 } 1372 1373 double 1374 ieeedtod(Ieee *ieeep) 1375 { 1376 Ieee e; 1377 double fr; 1378 int exp; 1379 1380 if(ieeep->h & (1L<<31)) { 1381 e.h = ieeep->h & ~(1L<<31); 1382 e.l = ieeep->l; 1383 return -ieeedtod(&e); 1384 } 1385 if(ieeep->l == 0 && ieeep->h == 0) 1386 return 0; 1387 fr = ieeep->l & ((1L<<16)-1L); 1388 fr /= 1L<<16; 1389 fr += (ieeep->l>>16) & ((1L<<16)-1L); 1390 fr /= 1L<<16; 1391 fr += (ieeep->h & (1L<<20)-1L) | (1L<<20); 1392 fr /= 1L<<21; 1393 exp = (ieeep->h>>20) & ((1L<<11)-1L); 1394 exp -= (1L<<10) - 2L; 1395 return ldexp(fr, exp); 1396 } 1397