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