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