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