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