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\n"); 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\n", 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\n", 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\n", file); 292 goto out; 293 } 294 if(strncmp(arhdr.name, symname, strlen(symname))) { 295 diag("%s: first entry not symbol header\n", 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\n", 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\n", 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(long line) 451 { 452 char name[MAXHIST*NAMELEN], comp[4*NAMELEN], *p; 453 int i; 454 455 USED(line); 456 if(histfrogp <= 0) 457 return; 458 459 if(histfrog[0]->name[1] == '/') { 460 sprint(name, ""); 461 i = 1; 462 } else 463 if(histfrog[0]->name[1] == '.') { 464 sprint(name, "."); 465 i = 0; 466 } else { 467 if(debug['9']) 468 sprint(name, "/%s/lib", thestring); 469 else 470 sprint(name, "/usr/%clib", thechar); 471 i = 0; 472 } 473 474 for(; i<histfrogp; i++) { 475 snprint(comp, 2*NAMELEN, histfrog[i]->name+1); 476 for(;;) { 477 p = strstr(comp, "$O"); 478 if(p == 0) 479 break; 480 memmove(p+1, p+2, strlen(p+2)+1); 481 p[0] = thechar; 482 } 483 for(;;) { 484 p = strstr(comp, "$M"); 485 if(p == 0) 486 break; 487 memmove(p+strlen(thestring), p+2, strlen(p+2)+1); 488 memmove(p, thestring, strlen(thestring)); 489 if(strlen(comp) > NAMELEN) { 490 diag("library component too long"); 491 return; 492 } 493 } 494 if(strlen(comp) > NAMELEN || strlen(name) + strlen(comp) + 3 >= sizeof(name)) { 495 diag("library component too long"); 496 return; 497 } 498 strcat(name, "/"); 499 strcat(name, comp); 500 } 501 for(i=0; i<libraryp; i++) 502 if(strcmp(name, library[i]) == 0) 503 return; 504 505 p = malloc(strlen(name) + 1); 506 strcpy(p, name); 507 library[libraryp] = p; 508 libraryp++; 509 } 510 511 void 512 addhist(long line, int type) 513 { 514 Auto *u; 515 Sym *s; 516 int i, j, k; 517 518 u = malloc(sizeof(Auto)); 519 s = malloc(sizeof(Sym)); 520 s->name = malloc(2*(histfrogp+1) + 1); 521 522 u->sym = s; 523 u->type = type; 524 u->offset = line; 525 u->link = curhist; 526 curhist = u; 527 528 j = 1; 529 for(i=0; i<histfrogp; i++) { 530 k = histfrog[i]->value; 531 s->name[j+0] = k>>8; 532 s->name[j+1] = k; 533 j += 2; 534 } 535 } 536 537 void 538 histtoauto(void) 539 { 540 Auto *l; 541 542 while(l = curhist) { 543 curhist = l->link; 544 l->link = curauto; 545 curauto = l; 546 } 547 } 548 549 void 550 collapsefrog(Sym *s) 551 { 552 int i; 553 554 /* 555 * bad encoding of path components only allows 556 * MAXHIST components. if there is an overflow, 557 * first try to collapse xxx/.. 558 */ 559 for(i=1; i<histfrogp; i++) 560 if(strcmp(histfrog[i]->name+1, "..") == 0) { 561 memmove(histfrog+i-1, histfrog+i+1, 562 (histfrogp-i-1)*sizeof(histfrog[0])); 563 histfrogp--; 564 goto out; 565 } 566 567 /* 568 * next try to collapse . 569 */ 570 for(i=0; i<histfrogp; i++) 571 if(strcmp(histfrog[i]->name+1, ".") == 0) { 572 memmove(histfrog+i, histfrog+i+1, 573 (histfrogp-i-1)*sizeof(histfrog[0])); 574 goto out; 575 } 576 577 /* 578 * last chance, just truncate from front 579 */ 580 memmove(histfrog+0, histfrog+1, 581 (histfrogp-1)*sizeof(histfrog[0])); 582 583 out: 584 histfrog[histfrogp-1] = s; 585 } 586 587 void 588 nopout(Prog *p) 589 { 590 p->as = ANOP; 591 p->from.type = D_NONE; 592 p->to.type = D_NONE; 593 } 594 595 uchar* 596 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max) 597 { 598 int n; 599 600 n = stop - good; 601 memmove(buf, good, stop - good); 602 stop = buf + n; 603 n = MAXIO - n; 604 if(n > max) 605 n = max; 606 n = read(f, stop, n); 607 if(n <= 0) 608 return 0; 609 return stop + n; 610 } 611 612 void 613 ldobj(int f, long c, char *pn) 614 { 615 Prog *p, *t; 616 Sym *h[NSYM], *s, *di; 617 int v, o, r, skip; 618 long ipc; 619 uchar *bloc, *bsize, *stop; 620 621 bsize = buf.xbuf; 622 bloc = buf.xbuf; 623 di = S; 624 625 newloop: 626 memset(h, 0, sizeof(h)); 627 histfrogp = 0; 628 version++; 629 ipc = pc; 630 skip = 0; 631 632 loop: 633 if(c <= 0) 634 goto eof; 635 r = bsize - bloc; 636 if(r < 100 && r < c) { /* enough for largest prog */ 637 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 638 if(bsize == 0) 639 goto eof; 640 bloc = buf.xbuf; 641 goto loop; 642 } 643 o = bloc[0]; /* as */ 644 if(o <= 0 || o >= ALAST) { 645 diag("%s: opcode out of range %d\n", pn, o); 646 print(" probably not a .q file\n"); 647 errorexit(); 648 } 649 if(o == ANAME) { 650 stop = memchr(&bloc[3], 0, bsize-&bloc[3]); 651 if(stop == 0){ 652 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 653 if(bsize == 0) 654 goto eof; 655 bloc = buf.xbuf; 656 stop = memchr(&bloc[3], 0, bsize-&bloc[3]); 657 if(stop == 0){ 658 fprint(2, "%s: name too long\n", pn); 659 errorexit(); 660 } 661 } 662 v = bloc[1]; /* type */ 663 o = bloc[2]; /* sym */ 664 bloc += 3; 665 c -= 3; 666 667 r = 0; 668 if(v == D_STATIC) 669 r = version; 670 s = lookup((char*)bloc, r); 671 c -= &stop[1] - bloc; 672 bloc = stop + 1; 673 674 if(debug['W']) 675 print(" ANAME %s\n", s->name); 676 h[o] = s; 677 if((v == D_EXTERN || v == D_STATIC) && s->type == 0) 678 s->type = SXREF; 679 if(v == D_FILE) { 680 if(s->type != SFILE) { 681 histgen++; 682 s->type = SFILE; 683 s->value = histgen; 684 } 685 if(histfrogp < MAXHIST) { 686 histfrog[histfrogp] = s; 687 histfrogp++; 688 } else 689 collapsefrog(s); 690 } 691 goto loop; 692 } 693 694 if(nhunk < sizeof(Prog)) 695 gethunk(); 696 p = (Prog*)hunk; 697 nhunk -= sizeof(Prog); 698 hunk += sizeof(Prog); 699 700 p->as = o; 701 p->reg = bloc[1] & 0x3f; 702 if(bloc[1] & 0x80) 703 p->mark = NOSCHED; 704 p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24); 705 r = zaddr(bloc+6, &p->from, h) + 6; 706 if(bloc[1] & 0x40) 707 r += zaddr(bloc+r, &p->from3, h); 708 else 709 p->from3 = zprg.from3; 710 r += zaddr(bloc+r, &p->to, h); 711 bloc += r; 712 c -= r; 713 714 if(p->reg < 0 || p->reg > NREG) 715 diag("register out of range %d\n", p->reg); 716 717 p->link = P; 718 p->cond = P; 719 720 if(debug['W']) 721 print("%P\n", p); 722 723 switch(o) { 724 case AHISTORY: 725 if(p->to.offset == -1) { 726 addlib(p->line); 727 histfrogp = 0; 728 goto loop; 729 } 730 addhist(p->line, D_FILE); /* 'z' */ 731 if(p->to.offset) 732 addhist(p->to.offset, D_FILE1); /* 'Z' */ 733 histfrogp = 0; 734 goto loop; 735 736 case AEND: 737 histtoauto(); 738 if(curtext != P) 739 curtext->to.autom = curauto; 740 curauto = 0; 741 curtext = P; 742 if(c) 743 goto newloop; 744 return; 745 746 case AGLOBL: 747 s = p->from.sym; 748 if(s == S) { 749 diag("GLOBL must have a name\n%P\n", p); 750 errorexit(); 751 } 752 if(s->type == 0 || s->type == SXREF) { 753 s->type = SBSS; 754 s->value = 0; 755 } 756 if(s->type != SBSS) { 757 diag("redefinition: %s\n%P\n", s->name, p); 758 s->type = SBSS; 759 s->value = 0; 760 } 761 if(p->to.offset > s->value) 762 s->value = p->to.offset; 763 break; 764 765 case ADYNT: 766 if(p->to.sym == S) { 767 diag("DYNT without a sym\n%P\n", p); 768 break; 769 } 770 di = p->to.sym; 771 p->reg = 4; 772 if(di->type == SXREF) { 773 if(debug['z']) 774 Bprint(&bso, "%P set to %d\n", p, dtype); 775 di->type = SCONST; 776 di->value = dtype; 777 dtype += 4; 778 } 779 if(p->from.sym == S) 780 break; 781 782 p->from.offset = di->value; 783 p->from.sym->type = SDATA; 784 if(curtext == P) { 785 diag("DYNT not in text: %P\n", p); 786 break; 787 } 788 p->to.sym = curtext->from.sym; 789 p->to.type = D_CONST; 790 p->link = datap; 791 datap = p; 792 break; 793 794 case AINIT: 795 if(p->from.sym == S) { 796 diag("INIT without a sym\n%P\n", p); 797 break; 798 } 799 if(di == S) { 800 diag("INIT without previous DYNT\n%P\n", p); 801 break; 802 } 803 p->from.offset = di->value; 804 p->from.sym->type = SDATA; 805 p->link = datap; 806 datap = p; 807 break; 808 809 case ADATA: 810 p->link = datap; 811 datap = p; 812 break; 813 814 case AGOK: 815 diag("unknown opcode\n%P\n", p); 816 p->pc = pc; 817 pc++; 818 break; 819 820 case ATEXT: 821 if(curtext != P) { 822 histtoauto(); 823 curtext->to.autom = curauto; 824 curauto = 0; 825 } 826 curtext = p; 827 autosize = (p->to.offset+3L) & ~3L; 828 p->to.offset = autosize; 829 autosize += 4; 830 s = p->from.sym; 831 if(s == S) { 832 diag("TEXT must have a name\n%P\n", p); 833 errorexit(); 834 } 835 if(s->type != 0 && s->type != SXREF) { 836 if(p->reg & DUPOK) { 837 skip = 1; 838 goto casedef; 839 } 840 diag("redefinition: %s\n%P\n", s->name, p); 841 } 842 s->type = STEXT; 843 s->value = pc; 844 if(textp != P) { 845 for(t = textp; t->cond != P; t = t->cond) 846 ; 847 t->cond = p; 848 } else 849 textp = p; 850 lastp->link = p; 851 lastp = p; 852 p->pc = pc; 853 pc++; 854 break; 855 856 case AFMOVS: 857 if(skip) 858 goto casedef; 859 860 if(p->from.type == D_FCONST) { 861 /* size sb 9 max */ 862 sprint(literal, "$%lux", ieeedtof(&p->from.ieee)); 863 s = lookup(literal, 0); 864 if(s->type == 0) { 865 s->type = SBSS; 866 s->value = 4; 867 t = prg(); 868 t->as = ADATA; 869 t->line = p->line; 870 t->from.type = D_OREG; 871 t->from.sym = s; 872 t->from.name = D_EXTERN; 873 t->reg = 4; 874 t->to = p->from; 875 t->link = datap; 876 datap = t; 877 } 878 p->from.type = D_OREG; 879 p->from.sym = s; 880 p->from.name = D_EXTERN; 881 p->from.offset = 0; 882 } 883 goto casedef; 884 885 case AFMOVD: 886 if(skip) 887 goto casedef; 888 if(p->from.type == D_FCONST) { 889 /* size sb 18 max */ 890 sprint(literal, "$%lux.%lux", 891 p->from.ieee.l, p->from.ieee.h); 892 s = lookup(literal, 0); 893 if(s->type == 0) { 894 s->type = SBSS; 895 s->value = 8; 896 t = prg(); 897 t->as = ADATA; 898 t->line = p->line; 899 t->from.type = D_OREG; 900 t->from.sym = s; 901 t->from.name = D_EXTERN; 902 t->reg = 8; 903 t->to = p->from; 904 t->link = datap; 905 datap = t; 906 } 907 p->from.type = D_OREG; 908 p->from.sym = s; 909 p->from.name = D_EXTERN; 910 p->from.offset = 0; 911 } 912 goto casedef; 913 914 case ASUBC: 915 if(p->from.type == D_CONST) { 916 p->from.offset = -p->from.offset; 917 p->as = AADDC; 918 } 919 goto casedef; 920 921 case ASUBCCC: 922 if(p->from.type == D_CONST) { 923 p->from.offset = -p->from.offset; 924 p->as = AADDCCC; 925 } 926 goto casedef; 927 928 case ASUB: 929 if(p->from.type == D_CONST) { 930 p->from.offset = -p->from.offset; 931 p->as = AADD; 932 } 933 goto casedef; 934 935 default: 936 casedef: 937 if(skip) 938 nopout(p); 939 940 if(p->to.type == D_BRANCH) 941 p->to.offset += ipc; 942 lastp->link = p; 943 lastp = p; 944 p->pc = pc; 945 pc++; 946 break; 947 } 948 goto loop; 949 950 eof: 951 diag("truncated object file: %s\n", pn); 952 } 953 954 Sym* 955 lookup(char *symb, int v) 956 { 957 Sym *s; 958 char *p; 959 long h; 960 int c, l; 961 962 h = v; 963 for(p=symb; c = *p; p++) 964 h = h+h+h + c; 965 l = (p - symb) + 1; 966 if(h < 0) 967 h = ~h; 968 h %= NHASH; 969 for(s = hash[h]; s != S; s = s->link) 970 if(s->version == v) 971 if(memcmp(s->name, symb, l) == 0) 972 return s; 973 974 while(nhunk < sizeof(Sym)) 975 gethunk(); 976 s = (Sym*)hunk; 977 nhunk -= sizeof(Sym); 978 hunk += sizeof(Sym); 979 980 s->name = malloc(l + 1); 981 memmove(s->name, symb, l); 982 983 s->link = hash[h]; 984 s->type = 0; 985 s->version = v; 986 s->value = 0; 987 hash[h] = s; 988 return s; 989 } 990 991 Prog* 992 prg(void) 993 { 994 Prog *p; 995 int n; 996 997 n = (sizeof(Prog) + 3) & ~3; 998 while(nhunk < n) 999 gethunk(); 1000 1001 p = (Prog*)hunk; 1002 nhunk -= n; 1003 hunk += n; 1004 1005 *p = zprg; 1006 return p; 1007 } 1008 1009 void 1010 gethunk(void) 1011 { 1012 char *h; 1013 1014 h = sbrk((int)NHUNK); 1015 if(h == (char *)-1) { 1016 diag("out of memory\n"); 1017 errorexit(); 1018 } 1019 1020 hunk = h; 1021 nhunk = NHUNK; 1022 tothunk += NHUNK; 1023 } 1024 1025 void 1026 doprof1(void) 1027 { 1028 Sym *s; 1029 long n; 1030 Prog *p, *q; 1031 1032 if(debug['v']) 1033 Bprint(&bso, "%5.2f profile 1\n", cputime()); 1034 Bflush(&bso); 1035 s = lookup("__mcount", 0); 1036 n = 1; 1037 for(p = firstp->link; p != P; p = p->link) { 1038 if(p->as == ATEXT) { 1039 q = prg(); 1040 q->line = p->line; 1041 q->link = datap; 1042 datap = q; 1043 q->as = ADATA; 1044 q->from.type = D_OREG; 1045 q->from.name = D_EXTERN; 1046 q->from.offset = n*4; 1047 q->from.sym = s; 1048 q->reg = 4; 1049 q->to = p->from; 1050 q->to.type = D_CONST; 1051 1052 q = prg(); 1053 q->line = p->line; 1054 q->pc = p->pc; 1055 q->link = p->link; 1056 p->link = q; 1057 p = q; 1058 p->as = AMOVW; 1059 p->from.type = D_OREG; 1060 p->from.name = D_EXTERN; 1061 p->from.sym = s; 1062 p->from.offset = n*4 + 4; 1063 p->to.type = D_REG; 1064 p->to.reg = REGTMP; 1065 1066 q = prg(); 1067 q->line = p->line; 1068 q->pc = p->pc; 1069 q->link = p->link; 1070 p->link = q; 1071 p = q; 1072 p->as = AADD; 1073 p->from.type = D_CONST; 1074 p->from.offset = 1; 1075 p->to.type = D_REG; 1076 p->to.reg = REGTMP; 1077 1078 q = prg(); 1079 q->line = p->line; 1080 q->pc = p->pc; 1081 q->link = p->link; 1082 p->link = q; 1083 p = q; 1084 p->as = AMOVW; 1085 p->from.type = D_REG; 1086 p->from.reg = REGTMP; 1087 p->to.type = D_OREG; 1088 p->to.name = D_EXTERN; 1089 p->to.sym = s; 1090 p->to.offset = n*4 + 4; 1091 1092 n += 2; 1093 continue; 1094 } 1095 } 1096 q = prg(); 1097 q->line = 0; 1098 q->link = datap; 1099 datap = q; 1100 1101 q->as = ADATA; 1102 q->from.type = D_OREG; 1103 q->from.name = D_EXTERN; 1104 q->from.sym = s; 1105 q->reg = 4; 1106 q->to.type = D_CONST; 1107 q->to.offset = n; 1108 1109 s->type = SBSS; 1110 s->value = n*4; 1111 } 1112 1113 void 1114 doprof2(void) 1115 { 1116 Sym *s2, *s4; 1117 Prog *p, *q, *ps2, *ps4; 1118 1119 if(debug['v']) 1120 Bprint(&bso, "%5.2f profile 2\n", cputime()); 1121 Bflush(&bso); 1122 1123 s2 = lookup("_profin", 0); 1124 s4 = lookup("_profout", 0); 1125 1126 ps2 = P; 1127 ps4 = P; 1128 for(p = firstp; p != P; p = p->link) { 1129 if(p->as == ATEXT) { 1130 if(p->from.sym == s2) { 1131 p->reg = 1; 1132 ps2 = p; 1133 } 1134 if(p->from.sym == s4) { 1135 p->reg = 1; 1136 ps4 = p; 1137 } 1138 } 1139 } 1140 for(p = firstp; p != P; p = p->link) { 1141 if(p->as == ATEXT) { 1142 curtext = p; 1143 1144 if(p->reg & NOPROF) { /* dont profile */ 1145 for(;;) { 1146 q = p->link; 1147 if(q == P) 1148 break; 1149 if(q->as == ATEXT) 1150 break; 1151 p = q; 1152 } 1153 continue; 1154 } 1155 1156 /* 1157 * BL profin 1158 */ 1159 q = prg(); 1160 q->line = p->line; 1161 q->pc = p->pc; 1162 q->link = p->link; 1163 p->link = q; 1164 p = q; 1165 p->as = ABL; 1166 p->to.type = D_BRANCH; 1167 p->cond = ps2; 1168 p->to.sym = s2; 1169 1170 continue; 1171 } 1172 if(p->as == ARETURN) { 1173 1174 /* 1175 * RETURN 1176 */ 1177 q = prg(); 1178 q->as = ARETURN; 1179 q->from = p->from; 1180 q->to = p->to; 1181 q->link = p->link; 1182 p->link = q; 1183 1184 /* 1185 * BL profout 1186 */ 1187 p->as = ABL; 1188 p->from = zprg.from; 1189 p->to = zprg.to; 1190 p->to.type = D_BRANCH; 1191 p->cond = ps4; 1192 p->to.sym = s4; 1193 1194 p = q; 1195 1196 continue; 1197 } 1198 } 1199 } 1200 1201 void 1202 nuxiinit(void) 1203 { 1204 int i, c; 1205 1206 for(i=0; i<4; i++) { 1207 c = find1(0x01020304L, i+1); 1208 if(i >= 2) 1209 inuxi2[i-2] = c; 1210 if(i >= 3) 1211 inuxi1[i-3] = c; 1212 inuxi4[i] = c; 1213 1214 fnuxi8[i] = c+4; 1215 fnuxi8[i+4] = c; 1216 } 1217 if(debug['v']) { 1218 Bprint(&bso, "inuxi = "); 1219 for(i=0; i<1; i++) 1220 Bprint(&bso, "%d", inuxi1[i]); 1221 Bprint(&bso, " "); 1222 for(i=0; i<2; i++) 1223 Bprint(&bso, "%d", inuxi2[i]); 1224 Bprint(&bso, " "); 1225 for(i=0; i<4; i++) 1226 Bprint(&bso, "%d", inuxi4[i]); 1227 Bprint(&bso, "\nfnuxi = "); 1228 for(i=0; i<8; i++) 1229 Bprint(&bso, "%d", fnuxi8[i]); 1230 Bprint(&bso, "\n"); 1231 } 1232 Bflush(&bso); 1233 } 1234 1235 int 1236 find1(long l, int c) 1237 { 1238 char *p; 1239 int i; 1240 1241 p = (char*)&l; 1242 for(i=0; i<4; i++) 1243 if(*p++ == c) 1244 return i; 1245 return 0; 1246 } 1247 1248 long 1249 ieeedtof(Ieee *ieee) 1250 { 1251 int exp; 1252 long v; 1253 1254 if(ieee->h == 0) 1255 return 0; 1256 exp = (ieee->h>>20) & ((1L<<11)-1L); 1257 exp -= (1L<<10) - 2L; 1258 v = (ieee->h & 0xfffffL) << 3; 1259 v |= (ieee->l >> 29) & 0x7L; 1260 if((ieee->l >> 28) & 1) { 1261 v++; 1262 if(v & 0x800000L) { 1263 v = (v & 0x7fffffL) >> 1; 1264 exp++; 1265 } 1266 } 1267 if(exp <= -126 || exp >= 130) 1268 diag("double fp to single fp overflow\n"); 1269 v |= ((exp + 126) & 0xffL) << 23; 1270 v |= ieee->h & 0x80000000L; 1271 return v; 1272 } 1273 1274 double 1275 ieeedtod(Ieee *ieee) 1276 { 1277 Ieee e; 1278 double fr; 1279 int exp; 1280 1281 if(ieee->h & (1L<<31)) { 1282 e.h = ieee->h & ~(1L<<31); 1283 e.l = ieee->l; 1284 return -ieeedtod(&e); 1285 } 1286 if(ieee->l == 0 && ieee->h == 0) 1287 return 0; 1288 fr = ieee->l & ((1L<<16)-1L); 1289 fr /= 1L<<16; 1290 fr += (ieee->l>>16) & ((1L<<16)-1L); 1291 fr /= 1L<<16; 1292 fr += (ieee->h & (1L<<20)-1L) | (1L<<20); 1293 fr /= 1L<<21; 1294 exp = (ieee->h>>20) & ((1L<<11)-1L); 1295 exp -= (1L<<10) - 2L; 1296 return ldexp(fr, exp); 1297 } 1298 1299 /* 1300 * fake malloc 1301 */ 1302 void* 1303 malloc(ulong n) 1304 { 1305 void *v; 1306 1307 n = (n + 7) & ~7; 1308 while(nhunk < n) 1309 gethunk(); 1310 1311 v = (void*)hunk; 1312 nhunk -= n; 1313 hunk += n; 1314 1315 memset(v, 0, n); 1316 return v; 1317 } 1318 1319 void 1320 free(void *p) 1321 { 1322 USED(p); 1323 } 1324 1325 void* 1326 calloc(ulong m, ulong n) 1327 { 1328 void *p; 1329 1330 n *= m; 1331 p = malloc(n); 1332 memset(p, 0, n); 1333 return p; 1334 } 1335 1336 void* 1337 realloc(void *p, ulong n) 1338 { 1339 USED(p, n); 1340 fprint(2, "realloc called\n"); 1341 abort(); 1342 return 0; 1343 } 1344