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