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