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 = '6'; 11 char *thestring = "960"; 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 msdos boot 18 * -H4 -T0x8000 -R4 is Intel 960 coff 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 = "6.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: 6l [-options] objects"); 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: /* msdos boot */ 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: /* is 960 coff */ 130 HEADR = 0x8CL; 131 if(INITTEXT == -1) 132 INITTEXT = 0x8000; 133 if(INITDAT == -1) 134 INITDAT = 0; 135 if(INITRND == -1) 136 INITRND = 4; 137 break; 138 } 139 if(INITDAT != 0 && INITRND != 0) 140 print("warning: -D0x%lux is ignored because of -R0x%lux\n", 141 INITDAT, INITRND); 142 if(debug['v']) 143 Bprint(&bso, "HEADER = -H0x%ld -T0x%lux -D0x%lux -R0x%lux\n", 144 HEADTYPE, INITTEXT, INITDAT, INITRND); 145 Bflush(&bso); 146 for(i=1; optab[i].as; i++) 147 if(i != optab[i].as) { 148 diag("phase error in optab: %d", i); 149 errorexit(); 150 } 151 maxop = i; 152 153 for(i=0; i<Ymax; i++) 154 ycover[i*Ymax + i] = 1; 155 156 ycover[Yi5*Ymax + Yri5] = 1; 157 ycover[Yr*Ymax + Yri5] = 1; 158 159 ycover[Yi5*Ymax + Ynri5] = 1; 160 ycover[Yr*Ymax + Ynri5] = 1; 161 ycover[Ynone*Ymax + Ynri5] = 1; 162 163 ycover[Yi5*Ymax + Yi32] = 1; 164 165 zprg.link = P; 166 zprg.cond = P; 167 zprg.back = 2; 168 zprg.as = AGOK; 169 zprg.type = D_NONE; 170 zprg.offset = 0; 171 zprg.from.type = D_NONE; 172 zprg.from.index = D_NONE; 173 zprg.from.scale = 1; 174 zprg.to = zprg.from; 175 176 pcstr = "%.6lux "; 177 nuxiinit(); 178 histgen = 0; 179 textp = P; 180 datap = P; 181 edatap = P; 182 pc = 0; 183 cout = create(outfile, 1, 0775); 184 if(cout < 0) { 185 diag("cannot create %s", outfile); 186 errorexit(); 187 } 188 version = 0; 189 cbp = buf.cbuf; 190 cbc = sizeof(buf.cbuf); 191 firstp = prg(); 192 lastp = firstp; 193 194 if(INITENTRY == 0) { 195 INITENTRY = "_main"; 196 if(debug['p']) 197 INITENTRY = "_mainp"; 198 if(!debug['l']) 199 lookup(INITENTRY, 0)->type = SXREF; 200 } else 201 lookup(INITENTRY, 0)->type = SXREF; 202 203 while(*argv) 204 objfile(*argv++); 205 if(!debug['l']) 206 loadlib(0, libraryp); 207 firstp = firstp->link; 208 if(firstp == P) 209 errorexit(); 210 patch(); 211 if(debug['p']) 212 doprof2(); 213 dodata(); 214 follow(); 215 noops(); 216 span(); 217 doinit(); 218 asmb(); 219 undef(); 220 if(debug['v']) { 221 Bprint(&bso, "%5.2f cpu time\n", cputime()); 222 Bprint(&bso, "%ld symbols\n", nsymbol); 223 Bprint(&bso, "%ld memory used\n", thunk); 224 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); 225 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); 226 } 227 Bflush(&bso); 228 229 errorexit(); 230 } 231 232 void 233 loadlib(int beg, int end) 234 { 235 int i, t; 236 237 for(i=end-1; i>=beg; i--) { 238 t = libraryp; 239 if(debug['v']) 240 Bprint(&bso, "%5.2f autolib: %s\n", cputime(), library[i]); 241 objfile(library[i]); 242 if(t != libraryp) 243 loadlib(t, libraryp); 244 } 245 } 246 247 void 248 errorexit(void) 249 { 250 251 if(nerrors) { 252 if(cout >= 0) 253 remove(outfile); 254 exits("error"); 255 } 256 exits(0); 257 } 258 259 void 260 objfile(char *file) 261 { 262 long off, esym, cnt, l; 263 int f, work; 264 Sym *s; 265 char magbuf[SARMAG]; 266 char name[100], pname[150]; 267 struct ar_hdr arhdr; 268 char *e, *start, *stop; 269 270 if(file[0] == '-' && file[1] == 'l') { 271 if(debug['9']) 272 sprint(name, "/%s/lib/lib", thestring); 273 else 274 sprint(name, "/usr/%clib/lib", thechar); 275 strcat(name, file+2); 276 strcat(name, ".a"); 277 file = name; 278 } 279 if(debug['v']) 280 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file); 281 Bflush(&bso); 282 f = open(file, 0); 283 if(f < 0) { 284 diag("cannot open file: %s", file); 285 errorexit(); 286 } 287 l = read(f, magbuf, SARMAG); 288 if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){ 289 /* load it as a regular file */ 290 l = seek(f, 0L, 2); 291 seek(f, 0L, 0); 292 ldobj(f, l, file); 293 close(f); 294 return; 295 } 296 297 if(debug['v']) 298 Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file); 299 l = read(f, &arhdr, SAR_HDR); 300 if(l != SAR_HDR) { 301 diag("%s: short read on archive file symbol header", file); 302 goto out; 303 } 304 if(strncmp(arhdr.name, symname, strlen(symname))) { 305 diag("%s: first entry not symbol header", file); 306 goto out; 307 } 308 309 esym = SARMAG + SAR_HDR + atolwhex(arhdr.size); 310 off = SARMAG + SAR_HDR; 311 312 /* 313 * just bang the whole symbol file into memory 314 */ 315 seek(f, off, 0); 316 cnt = esym - off; 317 start = malloc(cnt + 10); 318 cnt = read(f, start, cnt); 319 if(cnt <= 0){ 320 close(f); 321 return; 322 } 323 stop = &start[cnt]; 324 memset(stop, 0, 10); 325 326 work = 1; 327 while(work){ 328 if(debug['v']) 329 Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file); 330 Bflush(&bso); 331 work = 0; 332 for(e = start; e < stop; e = strchr(e+5, 0) + 1) { 333 s = lookup(e+5, 0); 334 if(s->type != SXREF) 335 continue; 336 sprint(pname, "%s(%s)", file, s->name); 337 if(debug['v']) 338 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname); 339 Bflush(&bso); 340 l = e[1] & 0xff; 341 l |= (e[2] & 0xff) << 8; 342 l |= (e[3] & 0xff) << 16; 343 l |= (e[4] & 0xff) << 24; 344 seek(f, l, 0); 345 l = read(f, &arhdr, SAR_HDR); 346 if(l != SAR_HDR) 347 goto bad; 348 if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag))) 349 goto bad; 350 l = atolwhex(arhdr.size); 351 ldobj(f, l, pname); 352 if(s->type == SXREF) { 353 diag("%s: failed to load: %s", file, s->name); 354 errorexit(); 355 } 356 work = 1; 357 } 358 } 359 return; 360 361 bad: 362 diag("%s: bad or out of date archive", file); 363 out: 364 close(f); 365 } 366 367 int 368 zaddr(uchar *p, Adr *a, Sym *h[]) 369 { 370 int c, t, i; 371 long l; 372 Sym *s; 373 Auto *u; 374 375 t = p[0]; 376 377 c = 1; 378 if(t & T_INDEX) { 379 a->index = p[c]; 380 a->scale = p[c+1]; 381 c += 2; 382 } else { 383 a->index = D_NONE; 384 a->scale = 0; 385 } 386 a->offset = 0; 387 if(t & T_OFFSET) { 388 a->offset = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); 389 c += 4; 390 } 391 a->sym = S; 392 if(t & T_SYM) { 393 a->sym = h[p[c]]; 394 c++; 395 } 396 a->type = D_NONE; 397 if(t & T_FCONST) { 398 a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24); 399 a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24); 400 c += 8; 401 a->type = D_FCONST; 402 } else 403 if(t & T_SCONST) { 404 for(i=0; i<NSNAME; i++) 405 a->scon[i] = p[c+i]; 406 c += NSNAME; 407 a->type = D_SCONST; 408 } 409 if(t & T_TYPE) { 410 a->type = p[c]; 411 c++; 412 } 413 s = a->sym; 414 if(s == S) 415 return c; 416 417 418 t = a->type; 419 if(t != D_AUTO && t != D_PARAM) 420 return c; 421 l = a->offset; 422 for(u=curauto; u; u=u->link) { 423 if(u->sym == s) 424 if(u->type == t) { 425 if(u->offset > l) 426 u->offset = l; 427 return c; 428 } 429 } 430 431 while(nhunk < sizeof(Auto)) 432 gethunk(); 433 u = (Auto*)hunk; 434 nhunk -= sizeof(Auto); 435 hunk += sizeof(Auto); 436 437 u->link = curauto; 438 curauto = u; 439 u->sym = s; 440 u->offset = l; 441 u->type = t; 442 return c; 443 } 444 445 void 446 addlib(char *obj) 447 { 448 char name[1024], comp[256], *p; 449 int i; 450 451 if(histfrogp <= 0) 452 return; 453 454 if(histfrog[0]->name[1] == '/') { 455 sprint(name, ""); 456 i = 1; 457 } else 458 if(histfrog[0]->name[1] == '.') { 459 sprint(name, "."); 460 i = 0; 461 } else { 462 if(debug['9']) 463 sprint(name, "/%s/lib", thestring); 464 else 465 sprint(name, "/usr/%clib", thechar); 466 i = 0; 467 } 468 469 for(; i<histfrogp; i++) { 470 snprint(comp, sizeof comp, histfrog[i]->name+1); 471 for(;;) { 472 p = strstr(comp, "$O"); 473 if(p == 0) 474 break; 475 memmove(p+1, p+2, strlen(p+2)+1); 476 p[0] = thechar; 477 } 478 for(;;) { 479 p = strstr(comp, "$M"); 480 if(p == 0) 481 break; 482 if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) { 483 diag("library component too long"); 484 return; 485 } 486 memmove(p+strlen(thestring), p+2, strlen(p+2)+1); 487 memmove(p, thestring, strlen(thestring)); 488 } 489 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) { 490 diag("library component too long"); 491 return; 492 } 493 strcat(name, "/"); 494 strcat(name, comp); 495 } 496 for(i=0; i<libraryp; i++) 497 if(strcmp(name, library[i]) == 0) 498 return; 499 if(libraryp == nelem(library)){ 500 diag("too many autolibs; skipping %s", name); 501 return; 502 } 503 504 p = malloc(strlen(name) + 1); 505 strcpy(p, name); 506 library[libraryp] = p; 507 p = malloc(strlen(obj) + 1); 508 strcpy(p, obj); 509 libraryobj[libraryp] = p; 510 libraryp++; 511 } 512 513 void 514 addhist(long line, int type) 515 { 516 Auto *u; 517 Sym *s; 518 int i, j, k; 519 520 u = malloc(sizeof(Auto)); 521 s = malloc(sizeof(Sym)); 522 s->name = malloc(2*(histfrogp+1) + 1); 523 524 u->sym = s; 525 u->type = type; 526 u->offset = line; 527 u->link = curhist; 528 curhist = u; 529 530 j = 1; 531 for(i=0; i<histfrogp; i++) { 532 k = histfrog[i]->value; 533 s->name[j+0] = k>>8; 534 s->name[j+1] = k; 535 j += 2; 536 } 537 } 538 539 void 540 histtoauto(void) 541 { 542 Auto *l; 543 544 while(l = curhist) { 545 curhist = l->link; 546 l->link = curauto; 547 curauto = l; 548 } 549 } 550 551 void 552 collapsefrog(Sym *s) 553 { 554 int i; 555 556 /* 557 * bad encoding of path components only allows 558 * MAXHIST components. if there is an overflow, 559 * first try to collapse xxx/.. 560 */ 561 for(i=1; i<histfrogp; i++) 562 if(strcmp(histfrog[i]->name+1, "..") == 0) { 563 memmove(histfrog+i-1, histfrog+i+1, 564 (histfrogp-i-1)*sizeof(histfrog[0])); 565 histfrogp--; 566 goto out; 567 } 568 569 /* 570 * next try to collapse . 571 */ 572 for(i=0; i<histfrogp; i++) 573 if(strcmp(histfrog[i]->name+1, ".") == 0) { 574 memmove(histfrog+i, histfrog+i+1, 575 (histfrogp-i-1)*sizeof(histfrog[0])); 576 goto out; 577 } 578 579 /* 580 * last chance, just truncate from front 581 */ 582 memmove(histfrog+0, histfrog+1, 583 (histfrogp-1)*sizeof(histfrog[0])); 584 585 out: 586 histfrog[histfrogp-1] = s; 587 } 588 589 uchar* 590 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max) 591 { 592 int n; 593 594 n = stop - good; 595 memmove(buf, good, stop - good); 596 stop = buf + n; 597 n = MAXIO - n; 598 if(n > max) 599 n = max; 600 n = read(f, stop, n); 601 if(n <= 0) 602 return 0; 603 return stop + n; 604 } 605 606 void 607 ldobj(int f, long c, char *pn) 608 { 609 Prog *p; 610 Sym *h[NSYM], *s; 611 int v, o, r; 612 long ipc; 613 uchar *bloc, *bsize, *stop; 614 615 bsize = buf.xbuf; 616 bloc = buf.xbuf; 617 618 newloop: 619 memset(h, 0, sizeof(h)); 620 version++; 621 histfrogp = 0; 622 ipc = pc; 623 624 loop: 625 if(c <= 0) 626 goto eof; 627 r = bsize - bloc; 628 if(r < 100 && r < c) { /* enough for largest prog */ 629 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 630 if(bsize == 0) 631 goto eof; 632 bloc = buf.xbuf; 633 goto loop; 634 } 635 o = bloc[0]; 636 if(o <= 0 || o >= maxop) { 637 if(o < 0) 638 goto eof; 639 diag("%s: opcode out of range %d", pn, o); 640 print(" probably not a .8 file\n"); 641 errorexit(); 642 } 643 644 if(o == ANAME) { 645 stop = memchr(&bloc[3], 0, bsize-&bloc[3]); 646 if(stop == 0){ 647 bsize = readsome(f, buf.xbuf, bloc, bsize, c); 648 if(bsize == 0) 649 goto eof; 650 bloc = buf.xbuf; 651 stop = memchr(&bloc[3], 0, bsize-&bloc[3]); 652 if(stop == 0){ 653 fprint(2, "%s: name too long\n", pn); 654 errorexit(); 655 } 656 } 657 v = bloc[1]; /* type */ 658 o = bloc[2]; /* sym */ 659 bloc += 3; 660 c -= 3; 661 662 r = 0; 663 if(v == D_STATIC) 664 r = version; 665 s = lookup((char*)bloc, r); 666 c -= &stop[1] - bloc; 667 bloc = stop + 1; 668 669 if(debug['W']) 670 print(" ANAME %s\n", s->name); 671 h[o] = s; 672 if((v == D_EXTERN || v == D_STATIC) && s->type == 0) 673 s->type = SXREF; 674 if(v == D_FILE) { 675 if(s->type != SFILE) { 676 histgen++; 677 s->type = SFILE; 678 s->value = histgen; 679 } 680 if(histfrogp < MAXHIST) { 681 histfrog[histfrogp] = s; 682 histfrogp++; 683 } else 684 collapsefrog(s); 685 } 686 goto loop; 687 } 688 689 while(nhunk < sizeof(Prog)) 690 gethunk(); 691 p = (Prog*)hunk; 692 nhunk -= sizeof(Prog); 693 hunk += sizeof(Prog); 694 695 p->as = o; 696 p->line = bloc[1] | (bloc[2] << 8) | (bloc[3] << 16) | (bloc[4] << 24); 697 p->back = 2; 698 r = bloc[5]; 699 p->type = D_NONE; 700 p->offset = 0; 701 if(r > 0) { 702 if(r >= 33) { 703 p->type = D_CONST; 704 p->offset = r - 33; 705 } else 706 p->type = D_R0 + (r - 1); 707 } 708 r = zaddr(bloc+6, &p->from, h) + 6; 709 r += zaddr(bloc+r, &p->to, h); 710 bloc += r; 711 c -= r; 712 713 if(debug['W']) 714 print("%P\n", p); 715 716 switch(p->as) { 717 case AHISTORY: 718 if(p->to.offset == -1) { 719 addlib(pn); 720 histfrogp = 0; 721 goto loop; 722 } 723 addhist(p->line, D_FILE); 724 if(p->to.offset) 725 addhist(p->to.offset, D_FILE1); 726 histfrogp = 0; 727 goto loop; 728 729 case AEND: 730 histtoauto(); 731 if(curtext != P) 732 curtext->to.autom = curauto; 733 curauto = 0; 734 curtext = P; 735 if(c) 736 goto newloop; 737 return; 738 739 case AGLOBL: 740 s = p->from.sym; 741 if(s->type == 0 || s->type == SXREF) { 742 s->type = SBSS; 743 s->value = 0; 744 } 745 if(s->type != SBSS) { 746 diag("%s: redefinition: %s in %s", 747 pn, s->name, TNAME); 748 s->type = SBSS; 749 s->value = 0; 750 } 751 if(p->to.offset > s->value) 752 s->value = p->to.offset; 753 goto loop; 754 755 case ADATA: 756 if(edatap == P) 757 datap = p; 758 else 759 edatap->link = p; 760 edatap = p; 761 p->link = P; 762 goto loop; 763 764 case AGOK: 765 diag("%s: GOK opcode in %s", pn, TNAME); 766 pc++; 767 goto loop; 768 769 case ATEXT: 770 if(curtext != P) { 771 histtoauto(); 772 curtext->to.autom = curauto; 773 curauto = 0; 774 } 775 curtext = p; 776 lastp->link = p; 777 lastp = p; 778 p->pc = pc; 779 s = p->from.sym; 780 if(s == S) { 781 diag("%s: no TEXT symbol: %P", pn, p); 782 errorexit(); 783 } 784 if(s->type != 0 && s->type != SXREF) 785 diag("%s: redefinition: %s", pn, s->name); 786 s->type = STEXT; 787 s->value = p->pc; 788 pc++; 789 p->cond = P; 790 if(textp == P) { 791 textp = p; 792 etextp = p; 793 goto loop; 794 } 795 etextp->cond = p; 796 etextp = p; 797 goto loop; 798 799 case AADDO: 800 if(p->from.type == D_CONST) 801 if(p->from.offset < 0) { 802 p->as = ASUBO; 803 p->from.offset = -p->from.offset; 804 } 805 goto casdef; 806 807 case AADDI: 808 if(p->from.type == D_CONST) 809 if(p->from.offset < 0) { 810 p->as = ASUBI; 811 p->from.offset = -p->from.offset; 812 } 813 goto casdef; 814 815 case ASUBO: 816 if(p->from.type == D_CONST) 817 if(p->from.offset < 0) { 818 p->as = AADDO; 819 p->from.offset = -p->from.offset; 820 } 821 goto casdef; 822 823 case ASUBI: 824 if(p->from.type == D_CONST) 825 if(p->from.offset < 0) { 826 p->as = AADDI; 827 p->from.offset = -p->from.offset; 828 } 829 goto casdef; 830 831 casdef: 832 default: 833 if(p->to.type == D_BRANCH) 834 p->to.offset += ipc; 835 lastp->link = p; 836 lastp = p; 837 p->pc = pc; 838 pc++; 839 goto loop; 840 } 841 goto loop; 842 843 eof: 844 diag("truncated object file: %s", pn); 845 } 846 847 Sym* 848 lookup(char *symb, int v) 849 { 850 Sym *s; 851 char *p; 852 long h; 853 int c, l; 854 855 h = v; 856 for(p=symb; c = *p; p++) 857 h = h+h+h + c; 858 l = (p - symb) + 1; 859 if(h < 0) 860 h = ~h; 861 h %= NHASH; 862 for(s = hash[h]; s != S; s = s->link) 863 if(s->version == v) 864 if(memcmp(s->name, symb, l) == 0) 865 return s; 866 867 while(nhunk < sizeof(Sym)) 868 gethunk(); 869 s = (Sym*)hunk; 870 nhunk -= sizeof(Sym); 871 hunk += sizeof(Sym); 872 873 s->name = malloc(l); 874 memmove(s->name, symb, l); 875 876 s->link = hash[h]; 877 s->type = 0; 878 s->version = v; 879 s->value = 0; 880 hash[h] = s; 881 nsymbol++; 882 return s; 883 } 884 885 Prog* 886 prg(void) 887 { 888 Prog *p; 889 890 while(nhunk < sizeof(Prog)) 891 gethunk(); 892 p = (Prog*)hunk; 893 nhunk -= sizeof(Prog); 894 hunk += sizeof(Prog); 895 896 *p = zprg; 897 return p; 898 } 899 900 Prog* 901 copyp(Prog *q) 902 { 903 Prog *p; 904 905 p = prg(); 906 *p = *q; 907 return p; 908 } 909 910 Prog* 911 appendp(Prog *q) 912 { 913 Prog *p; 914 915 p = prg(); 916 p->link = q->link; 917 q->link = p; 918 p->line = q->line; 919 return p; 920 } 921 922 void 923 gethunk(void) 924 { 925 char *h; 926 long nh; 927 928 nh = NHUNK; 929 if(thunk >= 5L*NHUNK) { 930 nh = 5L*NHUNK; 931 if(thunk >= 25L*NHUNK) 932 nh = 25L*NHUNK; 933 } 934 h = sbrk(nh); 935 if(h == (char*)-1) { 936 diag("out of memory"); 937 errorexit(); 938 } 939 hunk = h; 940 nhunk = nh; 941 thunk += nh; 942 } 943 944 void 945 doprof1(void) 946 {} 947 948 void 949 doprof2(void) 950 {} 951 952 void 953 nuxiinit(void) 954 { 955 int i, c; 956 957 for(i=0; i<4; i++) { 958 c = find1(0x04030201L, i+1); 959 if(i < 2) 960 inuxi2[i] = c; 961 if(i < 1) 962 inuxi1[i] = c; 963 inuxi4[i] = c; 964 fnuxi4[i] = c; 965 fnuxi8[i] = c; 966 fnuxi8[i+4] = c+4; 967 } 968 if(debug['v']) { 969 Bprint(&bso, "inuxi = "); 970 for(i=0; i<1; i++) 971 Bprint(&bso, "%d", inuxi1[i]); 972 Bprint(&bso, " "); 973 for(i=0; i<2; i++) 974 Bprint(&bso, "%d", inuxi2[i]); 975 Bprint(&bso, " "); 976 for(i=0; i<4; i++) 977 Bprint(&bso, "%d", inuxi4[i]); 978 Bprint(&bso, "\nfnuxi = "); 979 for(i=0; i<4; i++) 980 Bprint(&bso, "%d", fnuxi4[i]); 981 Bprint(&bso, " "); 982 for(i=0; i<8; i++) 983 Bprint(&bso, "%d", fnuxi8[i]); 984 Bprint(&bso, "\n"); 985 } 986 Bflush(&bso); 987 } 988 989 int 990 find1(long l, int c) 991 { 992 char *p; 993 int i; 994 995 p = (char*)&l; 996 for(i=0; i<4; i++) 997 if(*p++ == c) 998 return i; 999 return 0; 1000 } 1001 1002 int 1003 find2(long l, int c) 1004 { 1005 short *p; 1006 int i; 1007 1008 p = (short*)&l; 1009 for(i=0; i<4; i+=2) { 1010 if(((*p >> 8) & 0xff) == c) 1011 return i; 1012 if((*p++ & 0xff) == c) 1013 return i+1; 1014 } 1015 return 0; 1016 } 1017 1018 long 1019 ieeedtof(Ieee *e) 1020 { 1021 int exp; 1022 long v; 1023 1024 if(e->h == 0) 1025 return 0; 1026 exp = (e->h>>20) & ((1L<<11)-1L); 1027 exp -= (1L<<10) - 2L; 1028 v = (e->h & 0xfffffL) << 3; 1029 v |= (e->l >> 29) & 0x7L; 1030 if((e->l >> 28) & 1) { 1031 v++; 1032 if(v & 0x800000L) { 1033 v = (v & 0x7fffffL) >> 1; 1034 exp++; 1035 } 1036 } 1037 if(exp <= -126 || exp >= 130) 1038 diag("double fp to single fp overflow"); 1039 v |= ((exp + 126) & 0xffL) << 23; 1040 v |= e->h & 0x80000000L; 1041 return v; 1042 } 1043 1044 double 1045 ieeedtod(Ieee *ieee) 1046 { 1047 Ieee e; 1048 double fr; 1049 int exp; 1050 1051 if(ieee->h & (1L<<31)) { 1052 e.h = ieee->h & ~(1L<<31); 1053 e.l = ieee->l; 1054 return -ieeedtod(&e); 1055 } 1056 if(ieee->l == 0 && ieee->h == 0) 1057 return 0; 1058 fr = ieee->l & ((1L<<16)-1L); 1059 fr /= 1L<<16; 1060 fr += (ieee->l>>16) & ((1L<<16)-1L); 1061 fr /= 1L<<16; 1062 fr += (ieee->h & (1L<<20)-1L) | (1L<<20); 1063 fr /= 1L<<21; 1064 exp = (ieee->h>>20) & ((1L<<11)-1L); 1065 exp -= (1L<<10) - 2L; 1066 return ldexp(fr, exp); 1067 } 1068 1069 /* 1070 * fake malloc 1071 */ 1072 void* 1073 malloc(ulong n) 1074 { 1075 void *p; 1076 1077 while(n & 7) 1078 n++; 1079 while(nhunk < n) 1080 gethunk(); 1081 p = hunk; 1082 nhunk -= n; 1083 hunk += n; 1084 return p; 1085 } 1086 1087 void 1088 free(void *p) 1089 { 1090 USED(p); 1091 } 1092 1093 void* 1094 calloc(ulong m, ulong n) 1095 { 1096 void *p; 1097 1098 n *= m; 1099 p = malloc(n); 1100 memset(p, 0, n); 1101 return p; 1102 } 1103 1104 void* 1105 realloc(void *p, ulong n) 1106 { 1107 1108 fprint(2, "realloc(0x%p %ld) called\n", p, n); 1109 abort(); 1110 return 0; 1111 } 1112