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