1 #include "l.h" 2 3 void 4 span(void) 5 { 6 Prog *p, *q; 7 long c, idat; 8 int m, n, again; 9 10 xdefine("etext", STEXT, 0L); 11 idat = INITDAT; 12 for(p = firstp; p != P; p = p->link) { 13 if(p->as == ATEXT) 14 curtext = p; 15 n = 0; 16 q = p->cond; 17 if(q != P) 18 if(q->back != 2) 19 n = 1; 20 p->back = n; 21 } 22 n = 0; 23 24 start: 25 if(debug['v']) 26 Bprint(&bso, "%5.2f span\n", cputime()); 27 Bflush(&bso); 28 c = INITTEXT; 29 for(p = firstp; p != P; p = p->link) { 30 if(p->as == ATEXT) { 31 curtext = p; 32 autosize = p->to.offset + 4; 33 if(p->from.sym != S) 34 p->from.sym->value = c; 35 } 36 p->pc = c; 37 if(p->to.type == D_BRANCH) { 38 if(p->cond == P) 39 p->cond = p; 40 } 41 asmins(p); 42 m = (char*)andptr - (char*)and; 43 p->mark = m; 44 c += m; 45 } 46 47 loop: 48 n++; 49 if(debug['v']) 50 Bprint(&bso, "%5.2f span %d\n", cputime(), n); 51 Bflush(&bso); 52 if(n > 60) { 53 print("span must be looping\n"); 54 errorexit(); 55 } 56 again = 0; 57 c = INITTEXT; 58 for(p = firstp; p != P; p = p->link) { 59 if(p->as == ATEXT) { 60 curtext = p; 61 autosize = p->to.offset + 4; 62 } 63 if(p->to.type == D_BRANCH) { 64 asmins(p); 65 if(!p->back) 66 p->pc = c; 67 m = (char*)andptr - (char*)and; 68 if(m != p->mark) { 69 p->mark = m; 70 again++; 71 } 72 } 73 p->pc = c; 74 c += p->mark; 75 } 76 if(again) { 77 textsize = c; 78 goto loop; 79 } 80 INITDAT = c; 81 if(INITRND) { 82 INITDAT = rnd(c, INITRND); 83 if(INITDAT != idat) { 84 idat = INITDAT; 85 goto start; 86 } 87 } 88 xdefine("etext", STEXT, c); 89 if(debug['v']) 90 Bprint(&bso, "etext = %lux\n", c); 91 Bflush(&bso); 92 for(p = textp; p != P; p = p->cond) 93 p->from.sym->value = p->pc; 94 textsize = c - INITTEXT; 95 } 96 97 void 98 xdefine(char *p, int t, long v) 99 { 100 Sym *s; 101 102 s = lookup(p, 0); 103 if(s->type == 0 || s->type == SXREF) { 104 s->type = t; 105 s->value = v; 106 } 107 if(s->type == STEXT || s->type == SLEAF) 108 if(s->value == 0) 109 s->value = v; 110 } 111 112 void 113 putsymb(char *s, int t, long v, int ver) 114 { 115 int i, f; 116 117 if(t == 'f') 118 s++; 119 lput(v); 120 if(ver) 121 t += 'a' - 'A'; 122 CPUT(t+0x80); /* 0x80 is variable length */ 123 124 if(t == 'Z' || t == 'z') { 125 CPUT(s[0]); 126 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 127 CPUT(s[i]); 128 CPUT(s[i+1]); 129 } 130 CPUT(0); 131 CPUT(0); 132 i++; 133 } 134 else { 135 for(i=0; s[i]; i++) 136 CPUT(s[i]); 137 CPUT(0); 138 } 139 symsize += 4 + 1 + i + 1; 140 141 if(debug['n']) { 142 if(t == 'z' || t == 'Z') { 143 Bprint(&bso, "%c %.8lux ", t, v); 144 for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) { 145 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff); 146 Bprint(&bso, "/%x", f); 147 } 148 Bprint(&bso, "\n"); 149 return; 150 } 151 if(ver) 152 Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver); 153 else 154 Bprint(&bso, "%c %.8lux %s\n", t, v, s); 155 } 156 } 157 158 void 159 asmsym(void) 160 { 161 Prog *p; 162 Auto *a; 163 Sym *s; 164 int h; 165 166 s = lookup("etext", 0); 167 if(s->type == STEXT) 168 putsymb(s->name, 'T', s->value, s->version); 169 170 for(h=0; h<NHASH; h++) 171 for(s=hash[h]; s!=S; s=s->link) 172 switch(s->type) { 173 case SDATA: 174 putsymb(s->name, 'D', s->value+INITDAT, s->version); 175 continue; 176 177 case SBSS: 178 putsymb(s->name, 'B', s->value+INITDAT, s->version); 179 continue; 180 181 case SFILE: 182 putsymb(s->name, 'f', s->value, s->version); 183 continue; 184 } 185 186 for(p=textp; p!=P; p=p->cond) { 187 s = p->from.sym; 188 if(s->type != STEXT && s->type != SLEAF) 189 continue; 190 191 /* filenames first */ 192 for(a=p->to.autom; a; a=a->link) 193 if(a->type == D_FILE) 194 putsymb(a->sym->name, 'z', a->offset, 0); 195 else 196 if(a->type == D_FILE1) 197 putsymb(a->sym->name, 'Z', a->offset, 0); 198 199 if(s->type == STEXT) 200 putsymb(s->name, 'T', s->value, s->version); 201 else 202 putsymb(s->name, 'L', s->value, s->version); 203 204 /* frame, auto and param after */ 205 putsymb(".frame", 'm', p->to.offset+4, 0); 206 for(a=p->to.autom; a; a=a->link) 207 if(a->type == D_AUTO) 208 putsymb(a->sym->name, 'a', -a->offset, 0); 209 else 210 if(a->type == D_PARAM) 211 putsymb(a->sym->name, 'p', a->offset, 0); 212 } 213 if(debug['v'] || debug['n']) 214 Bprint(&bso, "symsize = %lud\n", symsize); 215 Bflush(&bso); 216 } 217 218 void 219 asmlc(void) 220 { 221 long oldpc, oldlc; 222 Prog *p; 223 long v, s; 224 225 oldpc = INITTEXT; 226 oldlc = 0; 227 for(p = firstp; p != P; p = p->link) { 228 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) { 229 if(p->as == ATEXT) 230 curtext = p; 231 if(debug['L']) 232 Bprint(&bso, "%6lux %P\n", 233 p->pc, p); 234 continue; 235 } 236 if(debug['L']) 237 Bprint(&bso, "\t\t%6ld", lcsize); 238 v = (p->pc - oldpc) / MINLC; 239 while(v) { 240 s = 127; 241 if(v < 127) 242 s = v; 243 CPUT(s+128); /* 129-255 +pc */ 244 if(debug['L']) 245 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128); 246 v -= s; 247 lcsize++; 248 } 249 s = p->line - oldlc; 250 oldlc = p->line; 251 oldpc = p->pc + MINLC; 252 if(s > 64 || s < -64) { 253 CPUT(0); /* 0 vv +lc */ 254 CPUT(s>>24); 255 CPUT(s>>16); 256 CPUT(s>>8); 257 CPUT(s); 258 if(debug['L']) { 259 if(s > 0) 260 Bprint(&bso, " lc+%ld(%d,%ld)\n", 261 s, 0, s); 262 else 263 Bprint(&bso, " lc%ld(%d,%ld)\n", 264 s, 0, s); 265 Bprint(&bso, "%6lux %P\n", 266 p->pc, p); 267 } 268 lcsize += 5; 269 continue; 270 } 271 if(s > 0) { 272 CPUT(0+s); /* 1-64 +lc */ 273 if(debug['L']) { 274 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s); 275 Bprint(&bso, "%6lux %P\n", 276 p->pc, p); 277 } 278 } else { 279 CPUT(64-s); /* 65-128 -lc */ 280 if(debug['L']) { 281 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s); 282 Bprint(&bso, "%6lux %P\n", 283 p->pc, p); 284 } 285 } 286 lcsize++; 287 } 288 while(lcsize & 1) { 289 s = 129; 290 CPUT(s); 291 lcsize++; 292 } 293 if(debug['v'] || debug['L']) 294 Bprint(&bso, "lcsize = %ld\n", lcsize); 295 Bflush(&bso); 296 } 297 298 int 299 oclass1(Prog *p) 300 { 301 int t; 302 303 t = p->type; 304 if(t == D_NONE) 305 return Ynone; 306 if(t >= D_R0 && t < D_R0+32) 307 return Yr; 308 if(t == D_CONST) 309 return Yi5; 310 return Yxxx; 311 } 312 313 int 314 oclass(Adr *a) 315 { 316 long v; 317 318 if(a->type >= D_INDIR || a->index != D_NONE) { 319 if(a->index != D_NONE && a->scale == 0) { 320 if(a->type >= D_ADDR) 321 return Yi32; 322 return Ycol; 323 } 324 return Ym; 325 } 326 switch(a->type) 327 { 328 default: 329 if(a->type >= D_R0 && a->type < D_R0+32) 330 return Yr; 331 case D_NONE: 332 return Ynone; 333 334 case D_EXTERN: 335 case D_STATIC: 336 case D_AUTO: 337 case D_PARAM: 338 return Ym; 339 340 case D_CONST: 341 case D_ADDR: 342 if(a->sym == S) { 343 v = a->offset; 344 if(v >= 0 && v < 32) 345 return Yi5; 346 } 347 return Yi32; 348 349 case D_BRANCH: 350 return Ybr; 351 } 352 return Yxxx; 353 } 354 355 void 356 dob(int o, long dpc) 357 { 358 long i; 359 360 i = (o & 0xff) << 24; 361 if(dpc >= -(1<<23) || dpc < (1<<23)) { 362 i |= dpc & 0xfffffc; /* tandi seems to keep low bits on */ 363 *andptr++ = i; 364 return; 365 } 366 diag("branch 23 too far"); 367 } 368 369 void 370 dorrb(int o, int r, int m, long dpc) 371 { 372 long i; 373 374 i = (o & 0xff) << 24; 375 i |= (r & 0x1f) << 19; 376 if(r & 32) 377 i |= 1<<13; /* m1 */ 378 i |= (m & 0x1f) << 14; 379 if(r & 32) 380 i |= 1<<13; /* m1 */ 381 /* bug?? */ 382 if(dpc >= -((1<<12)) || dpc < ((1<<12))) { 383 i |= dpc & 0xffc; 384 *andptr++ = i; 385 return; 386 } 387 diag("branch 12 too far"); 388 } 389 390 void 391 dormem(int o, int r, Adr *a) 392 { 393 long i, v; 394 int t, abase, index, scale; 395 396 397 abase = D_NONE; 398 index = a->index; 399 scale = a->scale; 400 v = a->offset; 401 402 t = a->type; 403 if(t >= D_INDIR) { 404 t -= D_INDIR; 405 if(t < D_R0 || t >= D_R0+32) 406 if(t != D_NONE) 407 diag("dormem 1 %D %d", a, a->type); 408 abase = t; 409 goto asm; 410 } 411 switch(t) { 412 default: 413 diag("dormem 2 %D", a); 414 break; 415 416 case D_STATIC: 417 case D_EXTERN: 418 t = a->sym->type; 419 if(t == 0 || t == SXREF) { 420 diag("undefined external: %s in %s\n", 421 a->sym->name, TNAME); 422 a->sym->type = SDATA; 423 } 424 v += a->sym->value; 425 abase = REGSB; 426 if(a->sym == symSB) { 427 v = INITDAT; 428 abase = D_NONE; 429 } 430 break; 431 432 case D_PARAM: 433 v += 4L; 434 435 case D_AUTO: 436 v += autosize; 437 abase = REGSP; 438 break; 439 } 440 441 asm: 442 t = 0; 443 if(v == 0) 444 t |= Anooffset; 445 else 446 if(v < 0 || v >= 4096) 447 t |= Abigoffset; 448 if(index != D_NONE) { 449 t |= Aindex; 450 switch(scale) { 451 default: 452 diag("bad scale %A", a); 453 case 1: 454 scale = 0; 455 break; 456 case 2: 457 scale = 1; 458 break; 459 case 4: 460 scale = 2; 461 break; 462 case 8: 463 scale = 3; 464 break; 465 case 16: 466 scale = 4; 467 break; 468 } 469 } 470 if(abase != D_NONE) 471 t |= Abase; 472 473 i = (o & 0xff) << 24; 474 i |= (r & 0x1f) << 19; 475 switch(t) { 476 default: 477 diag("dormem mode %lux %D\n", t, a); 478 break; 479 480 case 0: 481 case Anooffset: 482 /* 483 * mema mode 0 484 */ 485 i |= v; 486 *andptr++ = i; 487 break; 488 489 case Abase: 490 /* 491 * mema mode 1 492 */ 493 i |= 1 << 13; 494 i |= ((abase-D_R0) & 0x1f) << 14; 495 i |= v; 496 *andptr++ = i; 497 break; 498 499 case Abase|Anooffset: 500 /* 501 * memb mode 4 502 */ 503 i |= 0x4 << 10; 504 i |= ((abase-D_R0) & 0x1f) << 14; 505 *andptr++ = i; 506 break; 507 508 case Abase|Aindex|Anooffset: 509 /* 510 * memb mode 7 511 */ 512 i |= 0x7 << 10; 513 i |= ((abase-D_R0) & 0x1f) << 14; 514 i |= ((index-D_R0) & 0x1f) << 0; 515 i |= (scale & 0x7) << 7; 516 *andptr++ = i; 517 break; 518 519 case Abigoffset: 520 /* 521 * memb mode c 522 */ 523 i |= 0xc << 10; 524 *andptr++ = i; 525 *andptr++ = v; 526 break; 527 528 case Abase|Abigoffset: 529 /* 530 * memb mode d 531 */ 532 i |= 0xd << 10; 533 i |= ((abase-D_R0) & 0x1f) << 14; 534 *andptr++ = i; 535 *andptr++ = v; 536 break; 537 538 case Aindex: 539 case Aindex|Abigoffset: 540 case Aindex|Anooffset: 541 /* 542 * memb mode e 543 */ 544 i |= 0xe << 10; 545 i |= ((index-D_R0) & 0x1f) << 0; 546 i |= (scale & 0x7) << 7; 547 *andptr++ = i; 548 *andptr++ = v; 549 break; 550 551 case Abase|Aindex: 552 case Abase|Aindex|Abigoffset: 553 /* 554 * memb mode f 555 */ 556 i |= 0xf << 10; 557 i |= ((abase-D_R0) & 0x1f) << 14; 558 i |= ((index-D_R0) & 0x1f) << 0; 559 i |= (scale & 0x7) << 7; 560 *andptr++ = i; 561 *andptr++ = v; 562 break; 563 } 564 565 } 566 567 void 568 dorrr(int op, int src1, int src2, int dst) 569 { 570 ulong i; 571 572 i = (op & 0xfL) << 7; 573 i |= (op & 0xff0L) << 20; 574 i |= (src1 & 31) << 0; /* src1 */ 575 if(src1 & 32) 576 i |= 1<<11; /* m1 */ 577 i |= (src2 & 31) << 14; /* src2 */ 578 if(src2 & 32) 579 i |= 1<<12; /* m2 */ 580 i |= (dst & 31) << 19; /* dst */ 581 *andptr++ = i; 582 } 583 584 void 585 doir(Adr *a, int dst) 586 { 587 long c; 588 int t; 589 590 c = a->offset; 591 if(a->type == D_ADDR) { 592 switch(a->index) { 593 default: 594 diag("type in doir/D_ADDR"); 595 break; 596 case D_EXTERN: 597 case D_STATIC: 598 if(!a->sym) 599 break; 600 t = a->sym->type; 601 if(t == 0 || t == SXREF) { 602 diag("undefined external: %s in %s\n", 603 a->sym->name, TNAME); 604 a->sym->type = SDATA; 605 } 606 c += a->sym->value; 607 if(a->sym == symSB) 608 c = INITDAT; 609 } 610 } else 611 if(a->type != D_CONST) 612 diag("type in doir"); 613 614 if(c >= 0 && c < 4096) { 615 *andptr++ = (0x8c<<24) | (dst<<19) | (c<<0); /* mova $c,dst */ 616 return; 617 } 618 if(c >= -31 && c < 0) { 619 dorrr(0x592, 32-c, 32+0, dst); /* subo $c,$0,dst */ 620 return; 621 } 622 for(t=10; t<32-5; t++) 623 if((c & ~(31<<t)) == 0) { /* shlo $c1,$c2,dst */ 624 dorrr(0x59c, 32+t, 32+((c>>t)&31), dst); 625 return; 626 } 627 *andptr++ = (0x8c<<24) | (dst<<19) | (0xc<<10); /* mova $bigc,dst */ 628 *andptr++ = c; 629 } 630 631 void 632 doasm(Prog *p) 633 { 634 Optab *o; 635 uchar *t; 636 int z, ft, tt, mt; 637 638 o = &optab[p->as]; 639 ft = oclass(&p->from) * Ymax; 640 mt = oclass1(p) * Ymax; 641 tt = oclass(&p->to) * Ymax; 642 t = o->ytab; 643 if(t == 0) { 644 diag("asmins: noproto %P\n", p); 645 return; 646 } 647 for(z=0; *t; z+=t[4], t+=5) 648 if(ycover[ft+t[0]]) 649 if(ycover[mt+t[1]]) 650 if(ycover[tt+t[2]]) 651 goto found; 652 653 diag("asmins: notfound <%d,%d,%d> %P\n", 654 ft/Ymax, mt/Ymax, tt/Ymax, p); 655 return; 656 657 found: 658 switch(t[3]) { 659 default: 660 diag("asmins: unknown z %d %P\n", t[3], p); 661 return; 662 663 case Zpseudo: 664 break; 665 666 case Zbr: 667 dob(o->op[z], p->cond->pc - p->pc); 668 break; 669 670 case Zrxr: /* Yri5, Ynone, Yr5 */ 671 if(ft == Yr*Ymax) 672 ft = p->from.type - D_R0; 673 else 674 ft = p->from.offset | 32; 675 676 dorrr(o->op[z], ft, 0, p->to.type-D_R0); 677 break; 678 679 case Zrrx: /* Yri5, Ynone, Yri5 */ 680 if(ft == Yr*Ymax) 681 ft = p->from.type - D_R0; 682 else 683 ft = p->from.offset | 32; 684 if(tt == Yr*Ymax) 685 tt = p->to.type - D_R0; 686 else 687 tt = p->to.offset | 32; 688 689 dorrr(o->op[z], ft, tt, 0); 690 break; 691 692 case Zirx: /* Yi32, Ynone, Yri5 */ 693 if(tt == Yr*Ymax) 694 tt = p->to.type - D_R0; 695 else 696 tt = p->to.offset | 32; 697 698 doir(&p->from, REGTMP-D_R0); 699 dorrr(o->op[z], REGTMP-D_R0, tt, 0); 700 break; 701 702 case Zrrr: /* Yri5, Ynri5, Yr */ 703 if(ft == Yr*Ymax) 704 ft = p->from.type - D_R0; 705 else 706 ft = p->from.offset | 32; 707 708 if(mt == Ynone*Ymax) 709 mt = p->to.type - D_R0; 710 else 711 if(mt == Yr*Ymax) 712 mt = p->type - D_R0; 713 else 714 mt = p->offset | 32; 715 716 dorrr(o->op[z], ft, mt, p->to.type-D_R0); 717 break; 718 719 case Zir: /* Yi32, Yr */ 720 doir(&p->from, p->to.type-D_R0); 721 break; 722 723 case Zirr: /* Yi32, Ynri5, Yr */ 724 if(mt == Ynone*Ymax) 725 mt = p->to.type - D_R0; 726 else 727 if(mt == Yr*Ymax) 728 mt = p->type - D_R0; 729 else 730 mt = p->offset | 32; 731 732 doir(&p->from, REGTMP-D_R0); 733 dorrr(o->op[z], REGTMP-D_R0, mt, p->to.type-D_R0); 734 break; 735 736 case Zmbr: 737 dormem(o->op[z], REGLINK-D_R0, &p->to); 738 break; 739 740 case Zmr: 741 dormem(o->op[z], p->to.type-D_R0, &p->from); 742 break; 743 744 case Zrm: 745 dormem(o->op[z], p->from.type-D_R0, &p->to); 746 break; 747 748 case Zim: 749 if(p->from.offset != 0) { 750 doir(&p->from, REGTMP-D_R0); 751 dormem(o->op[z], REGTMP-D_R0, &p->to); 752 } else 753 dormem(o->op[z], REGZERO-D_R0, &p->to); 754 break; 755 756 case Zlong: 757 *andptr++ = p->from.offset; 758 break; 759 760 case Znone: 761 dorrr(o->op[z], 0, 0, 0); 762 break; 763 } 764 } 765 766 void 767 asmins(Prog *p) 768 { 769 770 andptr = and; 771 doasm(p); 772 } 773