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 if(s2->type != STEXT || s4->type != STEXT) { 1126 diag("_profin/_profout not defined\n"); 1127 return; 1128 } 1129 1130 ps2 = P; 1131 ps4 = P; 1132 for(p = firstp; p != P; p = p->link) { 1133 if(p->as == ATEXT) { 1134 if(p->from.sym == s2) { 1135 p->reg = 1; 1136 ps2 = p; 1137 } 1138 if(p->from.sym == s4) { 1139 p->reg = 1; 1140 ps4 = p; 1141 } 1142 } 1143 } 1144 for(p = firstp; p != P; p = p->link) { 1145 if(p->as == ATEXT) { 1146 curtext = p; 1147 1148 if(p->reg & NOPROF) { /* dont profile */ 1149 for(;;) { 1150 q = p->link; 1151 if(q == P) 1152 break; 1153 if(q->as == ATEXT) 1154 break; 1155 p = q; 1156 } 1157 continue; 1158 } 1159 1160 /* 1161 * BL profin 1162 */ 1163 q = prg(); 1164 q->line = p->line; 1165 q->pc = p->pc; 1166 q->link = p->link; 1167 p->link = q; 1168 p = q; 1169 p->as = ABL; 1170 p->to.type = D_BRANCH; 1171 p->cond = ps2; 1172 p->to.sym = s2; 1173 1174 continue; 1175 } 1176 if(p->as == ARETURN) { 1177 1178 /* 1179 * RETURN 1180 */ 1181 q = prg(); 1182 q->as = ARETURN; 1183 q->from = p->from; 1184 q->to = p->to; 1185 q->link = p->link; 1186 p->link = q; 1187 1188 /* 1189 * BL profout 1190 */ 1191 p->as = ABL; 1192 p->from = zprg.from; 1193 p->to = zprg.to; 1194 p->to.type = D_BRANCH; 1195 p->cond = ps4; 1196 p->to.sym = s4; 1197 1198 p = q; 1199 1200 continue; 1201 } 1202 } 1203 } 1204 1205 void 1206 nuxiinit(void) 1207 { 1208 int i, c; 1209 1210 for(i=0; i<4; i++) { 1211 c = find1(0x01020304L, i+1); 1212 if(i >= 2) 1213 inuxi2[i-2] = c; 1214 if(i >= 3) 1215 inuxi1[i-3] = c; 1216 inuxi4[i] = c; 1217 1218 fnuxi8[i] = c+4; 1219 fnuxi8[i+4] = c; 1220 } 1221 if(debug['v']) { 1222 Bprint(&bso, "inuxi = "); 1223 for(i=0; i<1; i++) 1224 Bprint(&bso, "%d", inuxi1[i]); 1225 Bprint(&bso, " "); 1226 for(i=0; i<2; i++) 1227 Bprint(&bso, "%d", inuxi2[i]); 1228 Bprint(&bso, " "); 1229 for(i=0; i<4; i++) 1230 Bprint(&bso, "%d", inuxi4[i]); 1231 Bprint(&bso, "\nfnuxi = "); 1232 for(i=0; i<8; i++) 1233 Bprint(&bso, "%d", fnuxi8[i]); 1234 Bprint(&bso, "\n"); 1235 } 1236 Bflush(&bso); 1237 } 1238 1239 int 1240 find1(long l, int c) 1241 { 1242 char *p; 1243 int i; 1244 1245 p = (char*)&l; 1246 for(i=0; i<4; i++) 1247 if(*p++ == c) 1248 return i; 1249 return 0; 1250 } 1251 1252 long 1253 ieeedtof(Ieee *ieee) 1254 { 1255 int exp; 1256 long v; 1257 1258 if(ieee->h == 0) 1259 return 0; 1260 exp = (ieee->h>>20) & ((1L<<11)-1L); 1261 exp -= (1L<<10) - 2L; 1262 v = (ieee->h & 0xfffffL) << 3; 1263 v |= (ieee->l >> 29) & 0x7L; 1264 if((ieee->l >> 28) & 1) { 1265 v++; 1266 if(v & 0x800000L) { 1267 v = (v & 0x7fffffL) >> 1; 1268 exp++; 1269 } 1270 } 1271 if(exp <= -126 || exp >= 130) 1272 diag("double fp to single fp overflow\n"); 1273 v |= ((exp + 126) & 0xffL) << 23; 1274 v |= ieee->h & 0x80000000L; 1275 return v; 1276 } 1277 1278 double 1279 ieeedtod(Ieee *ieee) 1280 { 1281 Ieee e; 1282 double fr; 1283 int exp; 1284 1285 if(ieee->h & (1L<<31)) { 1286 e.h = ieee->h & ~(1L<<31); 1287 e.l = ieee->l; 1288 return -ieeedtod(&e); 1289 } 1290 if(ieee->l == 0 && ieee->h == 0) 1291 return 0; 1292 fr = ieee->l & ((1L<<16)-1L); 1293 fr /= 1L<<16; 1294 fr += (ieee->l>>16) & ((1L<<16)-1L); 1295 fr /= 1L<<16; 1296 fr += (ieee->h & (1L<<20)-1L) | (1L<<20); 1297 fr /= 1L<<21; 1298 exp = (ieee->h>>20) & ((1L<<11)-1L); 1299 exp -= (1L<<10) - 2L; 1300 return ldexp(fr, exp); 1301 } 1302 1303 /* 1304 * fake malloc 1305 */ 1306 void* 1307 malloc(ulong n) 1308 { 1309 void *v; 1310 1311 n = (n + 7) & ~7; 1312 while(nhunk < n) 1313 gethunk(); 1314 1315 v = (void*)hunk; 1316 nhunk -= n; 1317 hunk += n; 1318 1319 memset(v, 0, n); 1320 return v; 1321 } 1322 1323 void 1324 free(void *p) 1325 { 1326 USED(p); 1327 } 1328 1329 void* 1330 calloc(ulong m, ulong n) 1331 { 1332 void *p; 1333 1334 n *= m; 1335 p = malloc(n); 1336 memset(p, 0, n); 1337 return p; 1338 } 1339 1340 void* 1341 realloc(void *p, ulong n) 1342 { 1343 USED(p, n); 1344 fprint(2, "realloc called\n"); 1345 abort(); 1346 return 0; 1347 } 1348