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