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 lput(0L); /* offset to first shdr */ 303 lput(0L); /* flags = PPC */ 304 lput((52L<<16)|32L); /* Ehdr & Phdr sizes*/ 305 lput((3L<<16)|0L); /* # Phdrs & Shdr size */ 306 lput((0L<<16)|0L); /* # Shdrs & shdr string size */ 307 308 lput(1L); /* text - type = PT_LOAD */ 309 lput(HEADR); /* file offset */ 310 lput(INITTEXT & ~KMASK); /* vaddr */ 311 lput(INITTEXT); /* paddr */ 312 lput(textsize); /* file size */ 313 lput(textsize); /* memory size */ 314 lput(0x05L); /* protections = RX */ 315 lput(0x10000L); /* alignment */ 316 317 lput(1L); /* data - type = PT_LOAD */ 318 lput(HEADR+textsize); /* file offset */ 319 lput(INITDAT & ~KMASK); /* vaddr */ 320 lput(INITDAT); /* paddr */ 321 lput(datsize); /* file size */ 322 lput(datsize); /* memory size */ 323 lput(0x07L); /* protections = RWX */ 324 lput(0x10000L); /* alignment */ 325 326 lput(0L); /* data - type = PT_NULL */ 327 lput(HEADR+textsize+datsize); /* file offset */ 328 lput(0L); 329 lput(0L); 330 lput(symsize); /* symbol table size */ 331 lput(lcsize); /* line number size */ 332 lput(0x04L); /* protections = R */ 333 lput(0x04L); /* alignment code?? */ 334 break; 335 } 336 cflush(); 337 } 338 339 void 340 strnput(char *s, int n) 341 { 342 for(; *s; s++){ 343 CPUT(*s); 344 n--; 345 } 346 for(; n > 0; n--) 347 CPUT(0); 348 } 349 350 void 351 cput(long l) 352 { 353 CPUT(l); 354 } 355 356 void 357 wput(long l) 358 { 359 cbp[0] = l>>8; 360 cbp[1] = l; 361 cbp += 2; 362 cbc -= 2; 363 if(cbc <= 0) 364 cflush(); 365 } 366 367 void 368 lput(long l) 369 { 370 371 LPUT(l); 372 } 373 374 void 375 cflush(void) 376 { 377 int n; 378 379 n = sizeof(buf.cbuf) - cbc; 380 if(n) 381 write(cout, buf.cbuf, n); 382 cbp = buf.cbuf; 383 cbc = sizeof(buf.cbuf); 384 } 385 386 void 387 asmsym(void) 388 { 389 Prog *p; 390 Auto *a; 391 Sym *s; 392 int h; 393 394 s = lookup("etext", 0); 395 if(s->type == STEXT) 396 putsymb(s->name, 'T', s->value, s->version); 397 398 for(h=0; h<NHASH; h++) 399 for(s=hash[h]; s!=S; s=s->link) 400 switch(s->type) { 401 case SCONST: 402 putsymb(s->name, 'D', s->value, s->version); 403 continue; 404 405 case SDATA: 406 putsymb(s->name, 'D', s->value+INITDAT, s->version); 407 continue; 408 409 case SBSS: 410 putsymb(s->name, 'B', s->value+INITDAT, s->version); 411 continue; 412 413 case SFILE: 414 putsymb(s->name, 'f', s->value, s->version); 415 continue; 416 } 417 418 for(p=textp; p!=P; p=p->cond) { 419 s = p->from.sym; 420 if(s->type != STEXT && s->type != SLEAF) 421 continue; 422 423 /* filenames first */ 424 for(a=p->to.autom; a; a=a->link) 425 if(a->type == D_FILE) 426 putsymb(a->sym->name, 'z', a->aoffset, 0); 427 else 428 if(a->type == D_FILE1) 429 putsymb(a->sym->name, 'Z', a->aoffset, 0); 430 431 if(s->type == STEXT) 432 putsymb(s->name, 'T', s->value, s->version); 433 else 434 putsymb(s->name, 'L', s->value, s->version); 435 436 /* frame, auto and param after */ 437 putsymb(".frame", 'm', p->to.offset+4, 0); 438 for(a=p->to.autom; a; a=a->link) 439 if(a->type == D_AUTO) 440 putsymb(a->sym->name, 'a', -a->aoffset, 0); 441 else 442 if(a->type == D_PARAM) 443 putsymb(a->sym->name, 'p', a->aoffset, 0); 444 } 445 if(debug['v'] || debug['n']) 446 Bprint(&bso, "symsize = %lud\n", symsize); 447 Bflush(&bso); 448 } 449 450 void 451 putsymb(char *s, int t, long v, int ver) 452 { 453 int i, f; 454 455 if(t == 'f') 456 s++; 457 LPUT(v); 458 if(ver) 459 t += 'a' - 'A'; 460 CPUT(t+0x80); /* 0x80 is variable length */ 461 462 if(t == 'Z' || t == 'z') { 463 CPUT(s[0]); 464 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 465 CPUT(s[i]); 466 CPUT(s[i+1]); 467 } 468 CPUT(0); 469 CPUT(0); 470 i++; 471 } 472 else { 473 for(i=0; s[i]; i++) 474 CPUT(s[i]); 475 CPUT(0); 476 } 477 symsize += 4 + 1 + i + 1; 478 479 if(debug['n']) { 480 if(t == 'z' || t == 'Z') { 481 Bprint(&bso, "%c %.8lux ", t, v); 482 for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) { 483 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff); 484 Bprint(&bso, "/%x", f); 485 } 486 Bprint(&bso, "\n"); 487 return; 488 } 489 if(ver) 490 Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver); 491 else 492 Bprint(&bso, "%c %.8lux %s\n", t, v, s); 493 } 494 } 495 496 #define MINLC 4 497 void 498 asmlc(void) 499 { 500 long oldpc, oldlc; 501 Prog *p; 502 long v, s; 503 504 oldpc = INITTEXT; 505 oldlc = 0; 506 for(p = firstp; p != P; p = p->link) { 507 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) { 508 if(p->as == ATEXT) 509 curtext = p; 510 if(debug['L']) 511 Bprint(&bso, "%6lux %P\n", 512 p->pc, p); 513 continue; 514 } 515 if(debug['L']) 516 Bprint(&bso, "\t\t%6ld", lcsize); 517 v = (p->pc - oldpc) / MINLC; 518 while(v) { 519 s = 127; 520 if(v < 127) 521 s = v; 522 CPUT(s+128); /* 129-255 +pc */ 523 if(debug['L']) 524 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128); 525 v -= s; 526 lcsize++; 527 } 528 s = p->line - oldlc; 529 oldlc = p->line; 530 oldpc = p->pc + MINLC; 531 if(s > 64 || s < -64) { 532 CPUT(0); /* 0 vv +lc */ 533 CPUT(s>>24); 534 CPUT(s>>16); 535 CPUT(s>>8); 536 CPUT(s); 537 if(debug['L']) { 538 if(s > 0) 539 Bprint(&bso, " lc+%ld(%d,%ld)\n", 540 s, 0, s); 541 else 542 Bprint(&bso, " lc%ld(%d,%ld)\n", 543 s, 0, s); 544 Bprint(&bso, "%6lux %P\n", 545 p->pc, p); 546 } 547 lcsize += 5; 548 continue; 549 } 550 if(s > 0) { 551 CPUT(0+s); /* 1-64 +lc */ 552 if(debug['L']) { 553 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s); 554 Bprint(&bso, "%6lux %P\n", 555 p->pc, p); 556 } 557 } else { 558 CPUT(64-s); /* 65-128 -lc */ 559 if(debug['L']) { 560 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s); 561 Bprint(&bso, "%6lux %P\n", 562 p->pc, p); 563 } 564 } 565 lcsize++; 566 } 567 while(lcsize & 1) { 568 s = 129; 569 CPUT(s); 570 lcsize++; 571 } 572 if(debug['v'] || debug['L']) 573 Bprint(&bso, "lcsize = %ld\n", lcsize); 574 Bflush(&bso); 575 } 576 577 void 578 datblk(long s, long n) 579 { 580 Prog *p; 581 char *cast; 582 long l, fl, j, d; 583 int i, c; 584 585 memset(buf.dbuf, 0, n+100); 586 for(p = datap; p != P; p = p->link) { 587 curp = p; 588 l = p->from.sym->value + p->from.offset - s; 589 c = p->reg; 590 i = 0; 591 if(l < 0) { 592 if(l+c <= 0) 593 continue; 594 while(l < 0) { 595 l++; 596 i++; 597 } 598 } 599 if(l >= n) 600 continue; 601 if(p->as != AINIT && p->as != ADYNT) { 602 for(j=l+(c-i)-1; j>=l; j--) 603 if(buf.dbuf[j]) { 604 print("%P\n", p); 605 diag("multiple initialization"); 606 break; 607 } 608 } 609 switch(p->to.type) { 610 default: 611 diag("unknown mode in initialization\n%P", p); 612 break; 613 614 case D_FCONST: 615 switch(c) { 616 default: 617 case 4: 618 fl = ieeedtof(&p->to.ieee); 619 cast = (char*)&fl; 620 for(; i<c; i++) { 621 buf.dbuf[l] = cast[fnuxi8[i+4]]; 622 l++; 623 } 624 break; 625 case 8: 626 cast = (char*)&p->to.ieee; 627 for(; i<c; i++) { 628 buf.dbuf[l] = cast[fnuxi8[i]]; 629 l++; 630 } 631 break; 632 } 633 break; 634 635 case D_SCONST: 636 for(; i<c; i++) { 637 buf.dbuf[l] = p->to.sval[i]; 638 l++; 639 } 640 break; 641 642 case D_CONST: 643 d = p->to.offset; 644 if(p->to.sym) { 645 if(p->to.sym->type == SUNDEF){ 646 ckoff(p->to.sym, d); 647 d += p->to.sym->value; 648 } 649 if(p->to.sym->type == STEXT || 650 p->to.sym->type == SLEAF) 651 d += p->to.sym->value; 652 if(p->to.sym->type == SDATA) 653 d += p->to.sym->value + INITDAT; 654 if(p->to.sym->type == SBSS) 655 d += p->to.sym->value + INITDAT; 656 if(dlm) 657 dynreloc(p->to.sym, l+s+INITDAT, 1, 0, 0); 658 } 659 cast = (char*)&d; 660 switch(c) { 661 default: 662 diag("bad nuxi %d %d\n%P", c, i, curp); 663 break; 664 case 1: 665 for(; i<c; i++) { 666 buf.dbuf[l] = cast[inuxi1[i]]; 667 l++; 668 } 669 break; 670 case 2: 671 for(; i<c; i++) { 672 buf.dbuf[l] = cast[inuxi2[i]]; 673 l++; 674 } 675 break; 676 case 4: 677 for(; i<c; i++) { 678 buf.dbuf[l] = cast[inuxi4[i]]; 679 l++; 680 } 681 break; 682 } 683 break; 684 } 685 } 686 write(cout, buf.dbuf, n); 687 } 688