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