1 #include "l.h" 2 3 #define KMASK 0xF0000000 4 5 #define LPUT(c)\ 6 {\ 7 cbp[0] = (c)>>24;\ 8 cbp[1] = (c)>>16;\ 9 cbp[2] = (c)>>8;\ 10 cbp[3] = (c);\ 11 cbp += 4;\ 12 cbc -= 4;\ 13 if(cbc <= 0)\ 14 cflush();\ 15 } 16 17 #define CPUT(c)\ 18 {\ 19 cbp[0] = (c);\ 20 cbp++;\ 21 cbc--;\ 22 if(cbc <= 0)\ 23 cflush();\ 24 } 25 26 void strnput(char*, int); 27 28 long 29 entryvalue(void) 30 { 31 char *a; 32 Sym *s; 33 34 a = INITENTRY; 35 if(*a >= '0' && *a <= '9') 36 return atolwhex(a); 37 s = lookup(a, 0); 38 if(s->type == 0) 39 return INITTEXT; 40 if(dlm && s->type == SDATA) 41 return s->value+INITDAT; 42 if(s->type != STEXT && s->type != SLEAF) 43 diag("entry not text: %s", s->name); 44 return s->value; 45 } 46 47 void 48 asmb(void) 49 { 50 Prog *p; 51 long t; 52 Optab *o; 53 54 if(debug['v']) 55 Bprint(&bso, "%5.2f asm\n", cputime()); 56 Bflush(&bso); 57 seek(cout, HEADR, 0); 58 pc = INITTEXT; 59 for(p = firstp; p != P; p = p->link) { 60 if(p->as == ATEXT) { 61 curtext = p; 62 autosize = p->to.offset + 4; 63 if(p->from3.type == D_CONST) { 64 for(; pc < p->pc; pc++) 65 CPUT(0); 66 } 67 } 68 if(p->pc != pc) { 69 diag("phase error %lux sb %lux", 70 p->pc, pc); 71 if(!debug['a']) 72 prasm(curp); 73 pc = p->pc; 74 } 75 curp = p; 76 o = oplook(p); /* could probably avoid this call */ 77 if(asmout(p, o, 0)) { 78 p = p->link; 79 pc += 4; 80 } 81 pc += o->size; 82 } 83 if(debug['a']) 84 Bprint(&bso, "\n"); 85 Bflush(&bso); 86 cflush(); 87 88 curtext = P; 89 switch(HEADTYPE) { 90 case 0: 91 case 1: 92 case 2: 93 case 5: 94 seek(cout, HEADR+textsize, 0); 95 break; 96 case 3: 97 seek(cout, rnd(HEADR+textsize, 4), 0); 98 break; 99 case 4: 100 seek(cout, rnd(HEADR+textsize, 4096), 0); 101 break; 102 } 103 104 if(dlm){ 105 char buf[8]; 106 107 write(cout, buf, INITDAT-textsize); 108 textsize = INITDAT; 109 } 110 111 for(t = 0; t < datsize; t += sizeof(buf)-100) { 112 if(datsize-t > sizeof(buf)-100) 113 datblk(t, sizeof(buf)-100); 114 else 115 datblk(t, datsize-t); 116 } 117 118 symsize = 0; 119 lcsize = 0; 120 if(!debug['s']) { 121 if(debug['v']) 122 Bprint(&bso, "%5.2f sym\n", cputime()); 123 Bflush(&bso); 124 switch(HEADTYPE) { 125 case 0: 126 case 1: 127 case 2: 128 case 5: 129 seek(cout, HEADR+textsize+datsize, 0); 130 break; 131 case 3: 132 seek(cout, rnd(HEADR+textsize, 4)+datsize, 0); 133 break; 134 case 4: 135 seek(cout, rnd(HEADR+textsize, 4096)+datsize, 0); 136 break; 137 } 138 if(!debug['s']) 139 asmsym(); 140 if(debug['v']) 141 Bprint(&bso, "%5.2f sp\n", cputime()); 142 Bflush(&bso); 143 if(!debug['s']) 144 asmlc(); 145 if(dlm) 146 asmdyn(); 147 if(HEADTYPE == 0 || HEADTYPE == 1) /* round up file length for boot image */ 148 if((symsize+lcsize) & 1) 149 CPUT(0); 150 cflush(); 151 } 152 else if(dlm){ 153 asmdyn(); 154 cflush(); 155 } 156 157 seek(cout, 0L, 0); 158 switch(HEADTYPE) { 159 case 0: 160 lput(0x1030107); /* magic and sections */ 161 lput(textsize); /* sizes */ 162 lput(datsize); 163 lput(bsssize); 164 lput(symsize); /* nsyms */ 165 lput(entryvalue()); /* va of entry */ 166 lput(0L); 167 lput(lcsize); 168 break; 169 case 1: 170 lput(0x4a6f7921); /* Joy! */ 171 lput(0x70656666); /* peff */ 172 lput(0x70777063); /* pwpc */ 173 lput(1); 174 lput(0); 175 lput(0); 176 lput(0); 177 lput(0); 178 lput(0x30002); /*YY*/ 179 lput(0); 180 lput(~0); 181 lput(0); 182 lput(textsize+datsize); 183 lput(textsize+datsize); 184 lput(textsize+datsize); 185 lput(0xd0); /* header size */ 186 lput(0x10400); 187 lput(~0); 188 lput(0); 189 lput(0xc); 190 lput(0xc); 191 lput(0xc); 192 lput(0xc0); 193 lput(0x01010400); 194 lput(~0); 195 lput(0); 196 lput(0x38); 197 lput(0x38); 198 lput(0x38); 199 lput(0x80); 200 lput(0x04040400); 201 lput(0); 202 lput(1); 203 lput(0); 204 lput(~0); 205 lput(0); 206 lput(~0); 207 lput(0); 208 lput(0); 209 lput(0); 210 lput(0); 211 lput(0); 212 lput(0); 213 lput(0); 214 lput(0); 215 lput(0); 216 lput(0); 217 lput(0); 218 lput(0x3100); /* load address */ 219 lput(0); 220 lput(0); 221 lput(0); /* whew! */ 222 break; 223 case 2: 224 if(dlm) 225 lput(0x80000000 | (4*21*21+7)); /* magic */ 226 else 227 lput(4*21*21+7); /* magic */ 228 lput(textsize); /* sizes */ 229 lput(datsize); 230 lput(bsssize); 231 lput(symsize); /* nsyms */ 232 lput(entryvalue()); /* va of entry */ 233 lput(0L); 234 lput(lcsize); 235 break; 236 case 3: 237 break; 238 case 4: 239 lput((0x1DFL<<16)|3L); /* magic and sections */ 240 lput(time(0)); /* time and date */ 241 lput(rnd(HEADR+textsize, 4096)+datsize); 242 lput(symsize); /* nsyms */ 243 lput((0x48L<<16)|15L); /* size of optional hdr and flags */ 244 245 lput((0413<<16)|01L); /* magic and version */ 246 lput(textsize); /* sizes */ 247 lput(datsize); 248 lput(bsssize); 249 lput(entryvalue()); /* va of entry */ 250 lput(INITTEXT); /* va of base of text */ 251 lput(INITDAT); /* va of base of data */ 252 lput(INITDAT); /* address of TOC */ 253 lput((1L<<16)|1); /* sn(entry) | sn(text) */ 254 lput((2L<<16)|1); /* sn(data) | sn(toc) */ 255 lput((0L<<16)|3); /* sn(loader) | sn(bss) */ 256 lput((3L<<16)|3); /* maxalign(text) | maxalign(data) */ 257 lput(('1'<<24)|('L'<<16)|0); /* type field, and reserved */ 258 lput(0); /* max stack allowed */ 259 lput(0); /* max data allowed */ 260 lput(0); lput(0); lput(0); /* reserved */ 261 262 strnput(".text", 8); /* text segment */ 263 lput(INITTEXT); /* address */ 264 lput(INITTEXT); 265 lput(textsize); 266 lput(HEADR); 267 lput(0L); 268 lput(HEADR+textsize+datsize+symsize); 269 lput(lcsize); /* line number size */ 270 lput(0x20L); /* flags */ 271 272 strnput(".data", 8); /* data segment */ 273 lput(INITDAT); /* address */ 274 lput(INITDAT); 275 lput(datsize); 276 lput(rnd(HEADR+textsize, 4096));/* sizes */ 277 lput(0L); 278 lput(0L); 279 lput(0L); 280 lput(0x40L); /* flags */ 281 282 strnput(".bss", 8); /* bss segment */ 283 lput(INITDAT+datsize); /* address */ 284 lput(INITDAT+datsize); 285 lput(bsssize); 286 lput(0L); 287 lput(0L); 288 lput(0L); 289 lput(0L); 290 lput(0x80L); /* flags */ 291 break; 292 case 5: 293 strnput("\177ELF", 4); /* e_ident */ 294 CPUT(1); /* class = 32 bit */ 295 CPUT(2); /* data = MSB */ 296 CPUT(1); /* version = CURRENT */ 297 strnput("", 9); 298 lput((2L<<16)|20L); /* type = EXEC; machine = PowerPC */ 299 lput(1L); /* version = CURRENT */ 300 lput(entryvalue() & ~KMASK); /* entry vaddr */ 301 lput(52L); /* offset to first phdr */ 302 303 if(debug['S']){ 304 lput(HEADR+textsize+datsize+symsize); /* offset to first shdr */ 305 lput(0L); /* flags = PPC */ 306 lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ 307 lput((3L<<16)|40L); /* # Phdrs & Shdr size */ 308 lput((3L<<16)|2L); /* # Shdrs & shdr string size */ 309 } 310 else{ 311 lput(0L); 312 lput(0L); /* flags = PPC */ 313 lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ 314 lput((3L<<16)|0L); /* # Phdrs & Shdr size */ 315 lput((3L<<16)|0L); /* # Shdrs & shdr string size */ 316 } 317 318 lput(1L); /* text - type = PT_LOAD */ 319 lput(HEADR); /* file offset */ 320 lput(INITTEXT & ~KMASK); /* vaddr */ 321 lput(INITTEXT); /* paddr */ 322 lput(textsize); /* file size */ 323 lput(textsize); /* memory size */ 324 lput(0x05L); /* protections = RX */ 325 lput(0x10000L); /* alignment */ 326 327 lput(1L); /* data - type = PT_LOAD */ 328 lput(HEADR+textsize); /* file offset */ 329 lput(INITDAT & ~KMASK); /* vaddr */ 330 lput(INITDAT); /* paddr */ 331 lput(datsize); /* file size */ 332 lput(datsize); /* memory size */ 333 lput(0x07L); /* protections = RWX */ 334 lput(0x10000L); /* alignment */ 335 336 lput(0L); /* data - type = PT_NULL */ 337 lput(HEADR+textsize+datsize); /* file offset */ 338 lput(0L); 339 lput(0L); 340 lput(symsize); /* symbol table size */ 341 lput(lcsize); /* line number size */ 342 lput(0x04L); /* protections = R */ 343 lput(0x04L); /* alignment code?? */ 344 cflush(); 345 346 if(!debug['S']) 347 break; 348 349 seek(cout, HEADR+textsize+datsize+symsize, 0); 350 lput(1); /* Section name (string tbl index) */ 351 lput(1); /* Section type */ 352 lput(2|4); /* Section flags */ 353 lput(INITTEXT & ~KMASK); /* Section virtual addr at execution */ 354 lput(HEADR); /* Section file offset */ 355 lput(textsize); /* Section size in bytes */ 356 lput(0); /* Link to another section */ 357 lput(0); /* Additional section information */ 358 lput(0x10000L); /* Section alignment */ 359 lput(0); /* Entry size if section holds table */ 360 361 lput(7); /* Section name (string tbl index) */ 362 lput(1); /* Section type */ 363 lput(2|1); /* Section flags */ 364 lput(INITDAT & ~KMASK); /* Section virtual addr at execution */ 365 lput(HEADR+textsize); /* Section file offset */ 366 lput(datsize); /* Section size in bytes */ 367 lput(0); /* Link to another section */ 368 lput(0); /* Additional section information */ 369 lput(0x10000L); /* Section alignment */ 370 lput(0); /* Entry size if section holds table */ 371 372 /* string section header */ 373 lput(12); /* Section name (string tbl index) */ 374 lput(3); /* Section type */ 375 lput(1 << 5); /* Section flags */ 376 lput(0); /* Section virtual addr at execution */ 377 lput(HEADR+textsize+datsize+symsize+3*40); /* Section file offset */ 378 lput(14); /* Section size in bytes */ 379 lput(0); /* Link to another section */ 380 lput(0); /* Additional section information */ 381 lput(1); /* Section alignment */ 382 lput(0); /* Entry size if section holds table */ 383 384 /* string table */ 385 cput(0); 386 strnput(".text", 5); 387 cput(0); 388 strnput(".data", 5); 389 cput(0); 390 strnput(".strtab", 7); 391 cput(0); 392 cput(0); 393 394 break; 395 } 396 cflush(); 397 } 398 399 void 400 strnput(char *s, int n) 401 { 402 for(; *s; s++){ 403 CPUT(*s); 404 n--; 405 } 406 for(; n > 0; n--) 407 CPUT(0); 408 } 409 410 void 411 cput(long l) 412 { 413 CPUT(l); 414 } 415 416 void 417 wput(long l) 418 { 419 cbp[0] = l>>8; 420 cbp[1] = l; 421 cbp += 2; 422 cbc -= 2; 423 if(cbc <= 0) 424 cflush(); 425 } 426 427 void 428 lput(long l) 429 { 430 431 LPUT(l); 432 } 433 434 void 435 cflush(void) 436 { 437 int n; 438 439 n = sizeof(buf.cbuf) - cbc; 440 if(n) 441 write(cout, buf.cbuf, n); 442 cbp = buf.cbuf; 443 cbc = sizeof(buf.cbuf); 444 } 445 446 void 447 asmsym(void) 448 { 449 Prog *p; 450 Auto *a; 451 Sym *s; 452 int h; 453 454 s = lookup("etext", 0); 455 if(s->type == STEXT) 456 putsymb(s->name, 'T', s->value, s->version); 457 458 for(h=0; h<NHASH; h++) 459 for(s=hash[h]; s!=S; s=s->link) 460 switch(s->type) { 461 case SCONST: 462 putsymb(s->name, 'D', s->value, s->version); 463 continue; 464 465 case SDATA: 466 putsymb(s->name, 'D', s->value+INITDAT, s->version); 467 continue; 468 469 case SBSS: 470 putsymb(s->name, 'B', s->value+INITDAT, s->version); 471 continue; 472 473 case SFILE: 474 putsymb(s->name, 'f', s->value, s->version); 475 continue; 476 } 477 478 for(p=textp; p!=P; p=p->cond) { 479 s = p->from.sym; 480 if(s->type != STEXT && s->type != SLEAF) 481 continue; 482 483 /* filenames first */ 484 for(a=p->to.autom; a; a=a->link) 485 if(a->type == D_FILE) 486 putsymb(a->sym->name, 'z', a->aoffset, 0); 487 else 488 if(a->type == D_FILE1) 489 putsymb(a->sym->name, 'Z', a->aoffset, 0); 490 491 if(s->type == STEXT) 492 putsymb(s->name, 'T', s->value, s->version); 493 else 494 putsymb(s->name, 'L', s->value, s->version); 495 496 /* frame, auto and param after */ 497 putsymb(".frame", 'm', p->to.offset+4, 0); 498 for(a=p->to.autom; a; a=a->link) 499 if(a->type == D_AUTO) 500 putsymb(a->sym->name, 'a', -a->aoffset, 0); 501 else 502 if(a->type == D_PARAM) 503 putsymb(a->sym->name, 'p', a->aoffset, 0); 504 } 505 if(debug['v'] || debug['n']) 506 Bprint(&bso, "symsize = %lud\n", symsize); 507 Bflush(&bso); 508 } 509 510 void 511 putsymb(char *s, int t, long v, int ver) 512 { 513 int i, f; 514 515 if(t == 'f') 516 s++; 517 LPUT(v); 518 if(ver) 519 t += 'a' - 'A'; 520 CPUT(t+0x80); /* 0x80 is variable length */ 521 522 if(t == 'Z' || t == 'z') { 523 CPUT(s[0]); 524 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 525 CPUT(s[i]); 526 CPUT(s[i+1]); 527 } 528 CPUT(0); 529 CPUT(0); 530 i++; 531 } 532 else { 533 for(i=0; s[i]; i++) 534 CPUT(s[i]); 535 CPUT(0); 536 } 537 symsize += 4 + 1 + i + 1; 538 539 if(debug['n']) { 540 if(t == 'z' || t == 'Z') { 541 Bprint(&bso, "%c %.8lux ", t, v); 542 for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) { 543 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff); 544 Bprint(&bso, "/%x", f); 545 } 546 Bprint(&bso, "\n"); 547 return; 548 } 549 if(ver) 550 Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver); 551 else 552 Bprint(&bso, "%c %.8lux %s\n", t, v, s); 553 } 554 } 555 556 #define MINLC 4 557 void 558 asmlc(void) 559 { 560 long oldpc, oldlc; 561 Prog *p; 562 long v, s; 563 564 oldpc = INITTEXT; 565 oldlc = 0; 566 for(p = firstp; p != P; p = p->link) { 567 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) { 568 if(p->as == ATEXT) 569 curtext = p; 570 if(debug['L']) 571 Bprint(&bso, "%6lux %P\n", 572 p->pc, p); 573 continue; 574 } 575 if(debug['L']) 576 Bprint(&bso, "\t\t%6ld", lcsize); 577 v = (p->pc - oldpc) / MINLC; 578 while(v) { 579 s = 127; 580 if(v < 127) 581 s = v; 582 CPUT(s+128); /* 129-255 +pc */ 583 if(debug['L']) 584 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128); 585 v -= s; 586 lcsize++; 587 } 588 s = p->line - oldlc; 589 oldlc = p->line; 590 oldpc = p->pc + MINLC; 591 if(s > 64 || s < -64) { 592 CPUT(0); /* 0 vv +lc */ 593 CPUT(s>>24); 594 CPUT(s>>16); 595 CPUT(s>>8); 596 CPUT(s); 597 if(debug['L']) { 598 if(s > 0) 599 Bprint(&bso, " lc+%ld(%d,%ld)\n", 600 s, 0, s); 601 else 602 Bprint(&bso, " lc%ld(%d,%ld)\n", 603 s, 0, s); 604 Bprint(&bso, "%6lux %P\n", 605 p->pc, p); 606 } 607 lcsize += 5; 608 continue; 609 } 610 if(s > 0) { 611 CPUT(0+s); /* 1-64 +lc */ 612 if(debug['L']) { 613 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s); 614 Bprint(&bso, "%6lux %P\n", 615 p->pc, p); 616 } 617 } else { 618 CPUT(64-s); /* 65-128 -lc */ 619 if(debug['L']) { 620 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s); 621 Bprint(&bso, "%6lux %P\n", 622 p->pc, p); 623 } 624 } 625 lcsize++; 626 } 627 while(lcsize & 1) { 628 s = 129; 629 CPUT(s); 630 lcsize++; 631 } 632 if(debug['v'] || debug['L']) 633 Bprint(&bso, "lcsize = %ld\n", lcsize); 634 Bflush(&bso); 635 } 636 637 void 638 datblk(long s, long n) 639 { 640 Prog *p; 641 char *cast; 642 long l, fl, j, d; 643 int i, c; 644 645 memset(buf.dbuf, 0, n+100); 646 for(p = datap; p != P; p = p->link) { 647 curp = p; 648 l = p->from.sym->value + p->from.offset - s; 649 c = p->reg; 650 i = 0; 651 if(l < 0) { 652 if(l+c <= 0) 653 continue; 654 while(l < 0) { 655 l++; 656 i++; 657 } 658 } 659 if(l >= n) 660 continue; 661 if(p->as != AINIT && p->as != ADYNT) { 662 for(j=l+(c-i)-1; j>=l; j--) 663 if(buf.dbuf[j]) { 664 print("%P\n", p); 665 diag("multiple initialization"); 666 break; 667 } 668 } 669 switch(p->to.type) { 670 default: 671 diag("unknown mode in initialization\n%P", p); 672 break; 673 674 case D_FCONST: 675 switch(c) { 676 default: 677 case 4: 678 fl = ieeedtof(&p->to.ieee); 679 cast = (char*)&fl; 680 for(; i<c; i++) { 681 buf.dbuf[l] = cast[fnuxi8[i+4]]; 682 l++; 683 } 684 break; 685 case 8: 686 cast = (char*)&p->to.ieee; 687 for(; i<c; i++) { 688 buf.dbuf[l] = cast[fnuxi8[i]]; 689 l++; 690 } 691 break; 692 } 693 break; 694 695 case D_SCONST: 696 for(; i<c; i++) { 697 buf.dbuf[l] = p->to.sval[i]; 698 l++; 699 } 700 break; 701 702 case D_CONST: 703 d = p->to.offset; 704 if(p->to.sym) { 705 if(p->to.sym->type == SUNDEF){ 706 ckoff(p->to.sym, d); 707 d += p->to.sym->value; 708 } 709 if(p->to.sym->type == STEXT || 710 p->to.sym->type == SLEAF) 711 d += p->to.sym->value; 712 if(p->to.sym->type == SDATA) 713 d += p->to.sym->value + INITDAT; 714 if(p->to.sym->type == SBSS) 715 d += p->to.sym->value + INITDAT; 716 if(dlm) 717 dynreloc(p->to.sym, l+s+INITDAT, 1, 0, 0); 718 } 719 cast = (char*)&d; 720 switch(c) { 721 default: 722 diag("bad nuxi %d %d\n%P", c, i, curp); 723 break; 724 case 1: 725 for(; i<c; i++) { 726 buf.dbuf[l] = cast[inuxi1[i]]; 727 l++; 728 } 729 break; 730 case 2: 731 for(; i<c; i++) { 732 buf.dbuf[l] = cast[inuxi2[i]]; 733 l++; 734 } 735 break; 736 case 4: 737 for(; i<c; i++) { 738 buf.dbuf[l] = cast[inuxi4[i]]; 739 l++; 740 } 741 break; 742 } 743 break; 744 } 745 } 746 write(cout, buf.dbuf, n); 747 } 748