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