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