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