1 #include "l.h" 2 3 void 4 span(void) 5 { 6 Prog *p, *q; 7 long v, 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 if(p->to.type == D_BRANCH) 17 if(p->pcond == P) 18 p->pcond = p; 19 if((q = p->pcond) != P) 20 if(q->back != 2) 21 n = 1; 22 p->back = n; 23 if(p->as == AADJSP) { 24 p->to.type = D_SP; 25 v = -p->from.offset; 26 p->from.offset = v; 27 p->as = AADDL; 28 if(v < 0) { 29 p->as = ASUBL; 30 v = -v; 31 p->from.offset = v; 32 } 33 if(v == 0) 34 p->as = ANOP; 35 } 36 } 37 n = 0; 38 39 start: 40 if(debug['v']) 41 Bprint(&bso, "%5.2f span\n", cputime()); 42 Bflush(&bso); 43 c = INITTEXT; 44 for(p = firstp; p != P; p = p->link) { 45 if(p->as == ATEXT) 46 curtext = p; 47 if(p->to.type == D_BRANCH) 48 if(p->back) 49 p->pc = c; 50 asmins(p); 51 p->pc = c; 52 m = andptr-and; 53 p->mark = m; 54 c += m; 55 } 56 57 loop: 58 n++; 59 if(debug['v']) 60 Bprint(&bso, "%5.2f span %d\n", cputime(), n); 61 Bflush(&bso); 62 if(n > 50) { 63 print("span must be looping\n"); 64 errorexit(); 65 } 66 again = 0; 67 c = INITTEXT; 68 for(p = firstp; p != P; p = p->link) { 69 if(p->as == ATEXT) 70 curtext = p; 71 if(p->to.type == D_BRANCH) { 72 if(p->back) 73 p->pc = c; 74 asmins(p); 75 m = andptr-and; 76 if(m != p->mark) { 77 p->mark = m; 78 again++; 79 } 80 } 81 p->pc = c; 82 c += p->mark; 83 } 84 if(again) { 85 textsize = c; 86 goto loop; 87 } 88 if(INITRND) { 89 INITDAT = rnd(c, INITRND); 90 if(INITDAT != idat) { 91 idat = INITDAT; 92 goto start; 93 } 94 } 95 xdefine("etext", STEXT, c); 96 if(debug['v']) 97 Bprint(&bso, "etext = %lux\n", c); 98 Bflush(&bso); 99 for(p = textp; p != P; p = p->pcond) 100 p->from.sym->value = p->pc; 101 textsize = c - INITTEXT; 102 } 103 104 void 105 xdefine(char *p, int t, long v) 106 { 107 Sym *s; 108 109 s = lookup(p, 0); 110 if(s->type == 0 || s->type == SXREF) { 111 s->type = t; 112 s->value = v; 113 } 114 if(s->type == STEXT && s->value == 0) 115 s->value = v; 116 } 117 118 void 119 putsymb(char *s, int t, long v, int ver) 120 { 121 int i, f; 122 123 if(t == 'f') 124 s++; 125 lput(v); 126 if(ver) 127 t += 'a' - 'A'; 128 cput(t+0x80); /* 0x80 is variable length */ 129 130 if(t == 'Z' || t == 'z') { 131 cput(s[0]); 132 for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) { 133 cput(s[i]); 134 cput(s[i+1]); 135 } 136 cput(0); 137 cput(0); 138 i++; 139 } 140 else { 141 for(i=0; s[i]; i++) 142 cput(s[i]); 143 cput(0); 144 } 145 symsize += 4 + 1 + i + 1; 146 147 if(debug['n']) { 148 if(t == 'z' || t == 'Z') { 149 Bprint(&bso, "%c %.8lux ", t, v); 150 for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) { 151 f = ((s[i]&0xff) << 8) | (s[i+1]&0xff); 152 Bprint(&bso, "/%x", f); 153 } 154 Bprint(&bso, "\n"); 155 return; 156 } 157 if(ver) 158 Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver); 159 else 160 Bprint(&bso, "%c %.8lux %s\n", t, v, s); 161 } 162 } 163 164 void 165 asmsym(void) 166 { 167 Prog *p; 168 Auto *a; 169 Sym *s; 170 int h; 171 Relocsym *rs; 172 Reloc *r; 173 174 for(rs = relocs; rs != nil; rs = rs->link) { 175 if(rs->s != nil) 176 putsymb(rs->s->name, 'U', 0, 0); 177 for(r = rs->reloc; r != nil; r = r->link) 178 putsymb("", r->type, r->pc-INITTEXT, 0); 179 } 180 181 s = lookup("etext", 0); 182 if(s->type == STEXT) 183 putsymb(s->name, 'T', s->value, s->version); 184 185 for(h=0; h<NHASH; h++) 186 for(s=hash[h]; s!=S; s=s->link) 187 switch(s->type) { 188 case SCONST: 189 putsymb(s->name, 'D', s->value, s->version); 190 continue; 191 192 case SDATA: 193 putsymb(s->name, 'D', s->value+INITDAT, s->version); 194 continue; 195 196 case SBSS: 197 putsymb(s->name, 'B', s->value+INITDAT, s->version); 198 continue; 199 200 case SFILE: 201 putsymb(s->name, 'f', s->value, s->version); 202 continue; 203 } 204 205 for(p=textp; p!=P; p=p->pcond) { 206 s = p->from.sym; 207 if(s->type != STEXT) 208 continue; 209 210 /* filenames first */ 211 for(a=p->to.autom; a; a=a->link) 212 if(a->type == D_FILE) 213 putsymb(a->asym->name, 'z', a->aoffset, 0); 214 else 215 if(a->type == D_FILE1) 216 putsymb(a->asym->name, 'Z', a->aoffset, 0); 217 218 putsymb(s->name, 'T', s->value, s->version); 219 220 /* frame, auto and param after */ 221 putsymb(".frame", 'm', p->to.offset+4, 0); 222 223 for(a=p->to.autom; a; a=a->link) 224 if(a->type == D_AUTO) 225 putsymb(a->asym->name, 'a', -a->aoffset, 0); 226 else 227 if(a->type == D_PARAM) 228 putsymb(a->asym->name, 'p', a->aoffset, 0); 229 } 230 if(debug['v'] || debug['n']) 231 Bprint(&bso, "symsize = %lud\n", symsize); 232 Bflush(&bso); 233 } 234 235 void 236 asmlc(void) 237 { 238 long oldpc, oldlc; 239 Prog *p; 240 long v, s; 241 242 oldpc = INITTEXT; 243 oldlc = 0; 244 for(p = firstp; p != P; p = p->link) { 245 if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) { 246 if(p->as == ATEXT) 247 curtext = p; 248 if(debug['L']) 249 Bprint(&bso, "%6lux %P\n", 250 p->pc, p); 251 continue; 252 } 253 if(debug['L']) 254 Bprint(&bso, "\t\t%6ld", lcsize); 255 v = (p->pc - oldpc) / MINLC; 256 while(v) { 257 s = 127; 258 if(v < 127) 259 s = v; 260 cput(s+128); /* 129-255 +pc */ 261 if(debug['L']) 262 Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128); 263 v -= s; 264 lcsize++; 265 } 266 s = p->line - oldlc; 267 oldlc = p->line; 268 oldpc = p->pc + MINLC; 269 if(s > 64 || s < -64) { 270 cput(0); /* 0 vv +lc */ 271 cput(s>>24); 272 cput(s>>16); 273 cput(s>>8); 274 cput(s); 275 if(debug['L']) { 276 if(s > 0) 277 Bprint(&bso, " lc+%ld(%d,%ld)\n", 278 s, 0, s); 279 else 280 Bprint(&bso, " lc%ld(%d,%ld)\n", 281 s, 0, s); 282 Bprint(&bso, "%6lux %P\n", 283 p->pc, p); 284 } 285 lcsize += 5; 286 continue; 287 } 288 if(s > 0) { 289 cput(0+s); /* 1-64 +lc */ 290 if(debug['L']) { 291 Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s); 292 Bprint(&bso, "%6lux %P\n", 293 p->pc, p); 294 } 295 } else { 296 cput(64-s); /* 65-128 -lc */ 297 if(debug['L']) { 298 Bprint(&bso, " lc%ld(%ld)\n", s, 64-s); 299 Bprint(&bso, "%6lux %P\n", 300 p->pc, p); 301 } 302 } 303 lcsize++; 304 } 305 while(lcsize & 1) { 306 s = 129; 307 cput(s); 308 lcsize++; 309 } 310 if(debug['v'] || debug['L']) 311 Bprint(&bso, "lcsize = %ld\n", lcsize); 312 Bflush(&bso); 313 } 314 315 int 316 oclass(Adr *a) 317 { 318 long v; 319 320 if(a->type >= D_INDIR || a->index != D_NONE) { 321 if(a->index != D_NONE && a->scale == 0) { 322 if(a->type == D_ADDR) { 323 switch(a->index) { 324 case D_EXTERN: 325 case D_STATIC: 326 return Yi32; 327 case D_AUTO: 328 case D_PARAM: 329 return Yiauto; 330 } 331 return Yxxx; 332 } 333 return Ycol; 334 } 335 return Ym; 336 } 337 switch(a->type) 338 { 339 case D_AL: 340 return Yal; 341 342 case D_AX: 343 return Yax; 344 345 case D_CL: 346 case D_DL: 347 case D_BL: 348 case D_AH: 349 case D_CH: 350 case D_DH: 351 case D_BH: 352 return Yrb; 353 354 case D_CX: 355 return Ycx; 356 357 case D_DX: 358 case D_BX: 359 return Yrx; 360 361 case D_SP: 362 case D_BP: 363 case D_SI: 364 case D_DI: 365 return Yrl; 366 367 case D_F0+0: 368 return Yf0; 369 370 case D_F0+1: 371 case D_F0+2: 372 case D_F0+3: 373 case D_F0+4: 374 case D_F0+5: 375 case D_F0+6: 376 case D_F0+7: 377 return Yrf; 378 379 case D_NONE: 380 return Ynone; 381 382 case D_CS: return Ycs; 383 case D_SS: return Yss; 384 case D_DS: return Yds; 385 case D_ES: return Yes; 386 case D_FS: return Yfs; 387 case D_GS: return Ygs; 388 389 case D_GDTR: return Ygdtr; 390 case D_IDTR: return Yidtr; 391 case D_LDTR: return Yldtr; 392 case D_MSW: return Ymsw; 393 case D_TASK: return Ytask; 394 395 case D_CR+0: return Ycr0; 396 case D_CR+1: return Ycr1; 397 case D_CR+2: return Ycr2; 398 case D_CR+3: return Ycr3; 399 case D_CR+4: return Ycr4; 400 case D_CR+5: return Ycr5; 401 case D_CR+6: return Ycr6; 402 case D_CR+7: return Ycr7; 403 404 case D_DR+0: return Ydr0; 405 case D_DR+1: return Ydr1; 406 case D_DR+2: return Ydr2; 407 case D_DR+3: return Ydr3; 408 case D_DR+4: return Ydr4; 409 case D_DR+5: return Ydr5; 410 case D_DR+6: return Ydr6; 411 case D_DR+7: return Ydr7; 412 413 case D_TR+0: return Ytr0; 414 case D_TR+1: return Ytr1; 415 case D_TR+2: return Ytr2; 416 case D_TR+3: return Ytr3; 417 case D_TR+4: return Ytr4; 418 case D_TR+5: return Ytr5; 419 case D_TR+6: return Ytr6; 420 case D_TR+7: return Ytr7; 421 422 case D_EXTERN: 423 case D_STATIC: 424 case D_AUTO: 425 case D_PARAM: 426 return Ym; 427 428 case D_CONST: 429 case D_ADDR: 430 if(a->sym == S) { 431 v = a->offset; 432 if(v == 0) 433 return Yi0; 434 if(v == 1) 435 return Yi1; 436 if(v >= -128 && v <= 127) 437 return Yi8; 438 } 439 return Yi32; 440 441 case D_BRANCH: 442 return Ybr; 443 } 444 return Yxxx; 445 } 446 447 void 448 asmidx(Adr *a, int base) 449 { 450 int i; 451 452 switch(a->index) { 453 default: 454 goto bad; 455 456 case D_NONE: 457 i = 4 << 3; 458 goto bas; 459 460 case D_AX: 461 case D_CX: 462 case D_DX: 463 case D_BX: 464 case D_BP: 465 case D_SI: 466 case D_DI: 467 i = reg[a->index] << 3; 468 break; 469 } 470 switch(a->scale) { 471 default: 472 goto bad; 473 case 1: 474 break; 475 case 2: 476 i |= (1<<6); 477 break; 478 case 4: 479 i |= (2<<6); 480 break; 481 case 8: 482 i |= (3<<6); 483 break; 484 } 485 bas: 486 switch(base) { 487 default: 488 goto bad; 489 case D_NONE: /* must be mod=00 */ 490 i |= 5; 491 break; 492 case D_AX: 493 case D_CX: 494 case D_DX: 495 case D_BX: 496 case D_SP: 497 case D_SI: 498 case D_DI: 499 i |= reg[base]; 500 break; 501 } 502 *andptr++ = i; 503 return; 504 bad: 505 diag("asmidx: bad address %D", a); 506 *andptr++ = 0; 507 return; 508 } 509 510 static Relocsym * 511 genrelocsym(Sym *s, Relocsym**l) 512 { 513 Relocsym *r; 514 515 *l = r = malloc(sizeof(Relocsym)); 516 r->s = s; 517 r->reloc = nil; 518 r->link = nil; 519 return r; 520 } 521 522 static void 523 genreloc(Sym *s, long pc, int type) 524 { 525 Reloc *r; 526 Relocsym *rs, **l; 527 528 if(relocs == nil) 529 genrelocsym(nil, &relocs); 530 l = &relocs; 531 for(rs = *l; rs != nil; rs = *l) { 532 l = &rs->link; 533 if(rs->s == s) 534 break; 535 } 536 if(rs == nil) 537 rs = genrelocsym(s, l); 538 r = malloc(sizeof(Reloc)); 539 r->type = type; 540 r->pc = pc; 541 r->link = rs->reloc; 542 rs->reloc = r; 543 } 544 545 void 546 wreloc(Sym *s, long pc) 547 { 548 switch(s->type) { 549 case SCONST: 550 break; 551 case SUNDEF: 552 genreloc(s, pc, 'R'); 553 break; 554 default: 555 genreloc(nil, pc, 'R'); 556 break; 557 } 558 } 559 560 static void 561 put4(long v) 562 { 563 if(reloca) { 564 if(curp != P) 565 wreloc(reloca->sym, curp->pc + andptr - &and[0]); 566 reloca = nil; 567 } 568 andptr[0] = v; 569 andptr[1] = v>>8; 570 andptr[2] = v>>16; 571 andptr[3] = v>>24; 572 andptr += 4; 573 } 574 575 long 576 vaddr(Adr *a) 577 { 578 int t; 579 long v; 580 Sym *s; 581 582 t = a->type; 583 v = a->offset; 584 if(t == D_ADDR) 585 t = a->index; 586 switch(t) { 587 case D_STATIC: 588 case D_EXTERN: 589 s = a->sym; 590 if(s != nil) { 591 if(reloc) 592 reloca = a; 593 switch(s->type) { 594 case SUNDEF: 595 break; 596 case STEXT: 597 case SCONST: 598 v += s->value; 599 break; 600 default: 601 v += INITDAT + s->value; 602 } 603 } 604 } 605 return v; 606 } 607 608 void 609 asmand(Adr *a, int r) 610 { 611 long v; 612 int t; 613 Adr aa; 614 615 v = a->offset; 616 t = a->type; 617 if(a->index != D_NONE) { 618 if(t >= D_INDIR) { 619 t -= D_INDIR; 620 if(t == D_NONE) { 621 *andptr++ = (0 << 6) | (4 << 0) | (r << 3); 622 asmidx(a, t); 623 put4(v); 624 return; 625 } 626 if(v == 0) { 627 *andptr++ = (0 << 6) | (4 << 0) | (r << 3); 628 asmidx(a, t); 629 return; 630 } 631 if(v >= -128 && v < 128) { 632 *andptr++ = (1 << 6) | (4 << 0) | (r << 3); 633 asmidx(a, t); 634 *andptr++ = v; 635 return; 636 } 637 *andptr++ = (2 << 6) | (4 << 0) | (r << 3); 638 asmidx(a, t); 639 put4(v); 640 return; 641 } 642 switch(t) { 643 default: 644 goto bad; 645 case D_STATIC: 646 case D_EXTERN: 647 aa.type = D_NONE+D_INDIR; 648 break; 649 case D_AUTO: 650 case D_PARAM: 651 aa.type = D_SP+D_INDIR; 652 break; 653 } 654 aa.offset = vaddr(a); 655 aa.index = a->index; 656 aa.scale = a->scale; 657 asmand(&aa, r); 658 return; 659 } 660 if(t >= D_AL && t <= D_F0+7) { 661 if(v) 662 goto bad; 663 *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3); 664 return; 665 } 666 if(t >= D_INDIR) { 667 t -= D_INDIR; 668 if(t == D_NONE) { 669 *andptr++ = (0 << 6) | (5 << 0) | (r << 3); 670 put4(v); 671 return; 672 } 673 if(t == D_SP) { 674 if(v == 0) { 675 *andptr++ = (0 << 6) | (4 << 0) | (r << 3); 676 asmidx(a, D_SP); 677 return; 678 } 679 if(v >= -128 && v < 128) { 680 *andptr++ = (1 << 6) | (4 << 0) | (r << 3); 681 asmidx(a, D_SP); 682 *andptr++ = v; 683 return; 684 } 685 *andptr++ = (2 << 6) | (4 << 0) | (r << 3); 686 asmidx(a, D_SP); 687 put4(v); 688 return; 689 } 690 if(t >= D_AX && t <= D_DI) { 691 if(v == 0 && t != D_BP) { 692 *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); 693 return; 694 } 695 if(v >= -128 && v < 128) { 696 andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); 697 andptr[1] = v; 698 andptr += 2; 699 return; 700 } 701 *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); 702 put4(v); 703 return; 704 } 705 goto bad; 706 } 707 switch(a->type) { 708 default: 709 goto bad; 710 case D_STATIC: 711 case D_EXTERN: 712 aa.type = D_NONE+D_INDIR; 713 break; 714 case D_AUTO: 715 case D_PARAM: 716 aa.type = D_SP+D_INDIR; 717 break; 718 } 719 aa.index = D_NONE; 720 aa.scale = 1; 721 aa.offset = vaddr(a); 722 asmand(&aa, r); 723 return; 724 bad: 725 diag("asmand: bad address %D", a); 726 return; 727 } 728 729 #define E 0xff 730 uchar ymovtab[] = 731 { 732 /* push */ 733 APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0, 734 APUSHL, Yss, Ynone, 0, 0x16,E,0,0, 735 APUSHL, Yds, Ynone, 0, 0x1e,E,0,0, 736 APUSHL, Yes, Ynone, 0, 0x06,E,0,0, 737 APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0, 738 APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0, 739 740 APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0, 741 APUSHW, Yss, Ynone, 0, Pe,0x16,E,0, 742 APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0, 743 APUSHW, Yes, Ynone, 0, Pe,0x06,E,0, 744 APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E, 745 APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E, 746 747 /* pop */ 748 APOPL, Ynone, Yds, 0, 0x1f,E,0,0, 749 APOPL, Ynone, Yes, 0, 0x07,E,0,0, 750 APOPL, Ynone, Yss, 0, 0x17,E,0,0, 751 APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0, 752 APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0, 753 754 APOPW, Ynone, Yds, 0, Pe,0x1f,E,0, 755 APOPW, Ynone, Yes, 0, Pe,0x07,E,0, 756 APOPW, Ynone, Yss, 0, Pe,0x17,E,0, 757 APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E, 758 APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E, 759 760 /* mov seg */ 761 AMOVW, Yes, Yml, 1, 0x8c,0,0,0, 762 AMOVW, Ycs, Yml, 1, 0x8c,1,0,0, 763 AMOVW, Yss, Yml, 1, 0x8c,2,0,0, 764 AMOVW, Yds, Yml, 1, 0x8c,3,0,0, 765 AMOVW, Yfs, Yml, 1, 0x8c,4,0,0, 766 AMOVW, Ygs, Yml, 1, 0x8c,5,0,0, 767 768 AMOVW, Yml, Yes, 2, 0x8e,0,0,0, 769 AMOVW, Yml, Ycs, 2, 0x8e,1,0,0, 770 AMOVW, Yml, Yss, 2, 0x8e,2,0,0, 771 AMOVW, Yml, Yds, 2, 0x8e,3,0,0, 772 AMOVW, Yml, Yfs, 2, 0x8e,4,0,0, 773 AMOVW, Yml, Ygs, 2, 0x8e,5,0,0, 774 775 /* mov cr */ 776 AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0, 777 AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0, 778 AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0, 779 AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0, 780 781 AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0, 782 AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0, 783 AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0, 784 AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0, 785 786 /* mov dr */ 787 AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0, 788 AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0, 789 AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0, 790 791 AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0, 792 AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0, 793 AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0, 794 795 /* mov tr */ 796 AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0, 797 AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0, 798 799 AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E, 800 AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E, 801 802 /* lgdt, sgdt, lidt, sidt */ 803 AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0, 804 AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0, 805 AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0, 806 AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0, 807 808 /* lldt, sldt */ 809 AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0, 810 AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0, 811 812 /* lmsw, smsw */ 813 AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0, 814 AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0, 815 816 /* ltr, str */ 817 AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0, 818 AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0, 819 820 /* load full pointer */ 821 AMOVL, Yml, Ycol, 5, 0,0,0,0, 822 AMOVW, Yml, Ycol, 5, Pe,0,0,0, 823 824 /* double shift */ 825 ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0, 826 ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0, 827 828 /* extra imul */ 829 AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0, 830 0 831 }; 832 833 int 834 isax(Adr *a) 835 { 836 837 switch(a->type) { 838 case D_AX: 839 case D_AL: 840 case D_AH: 841 case D_INDIR+D_AX: 842 return 1; 843 } 844 if(a->index == D_AX) 845 return 1; 846 return 0; 847 } 848 849 void 850 subreg(Prog *p, int from, int to) 851 { 852 853 if(debug['Q']) 854 print("\n%P s/%R/%R/\n", p, from, to); 855 856 if(p->from.type == from) 857 p->from.type = to; 858 if(p->to.type == from) 859 p->to.type = to; 860 861 if(p->from.index == from) 862 p->from.index = to; 863 if(p->to.index == from) 864 p->to.index = to; 865 866 from += D_INDIR; 867 if(p->from.type == from) 868 p->from.type = to+D_INDIR; 869 if(p->to.type == from) 870 p->to.type = to+D_INDIR; 871 872 if(debug['Q']) 873 print("%P\n", p); 874 } 875 876 void 877 doasm(Prog *p) 878 { 879 Optab *o; 880 Prog *q, pp; 881 uchar *t; 882 int z, op, ft, tt; 883 long v; 884 885 o = &optab[p->as]; 886 ft = oclass(&p->from) * Ymax; 887 tt = oclass(&p->to) * Ymax; 888 t = o->ytab; 889 if(t == 0) { 890 diag("asmins: noproto %P", p); 891 return; 892 } 893 for(z=0; *t; z+=t[3],t+=4) 894 if(ycover[ft+t[0]]) 895 if(ycover[tt+t[1]]) 896 goto found; 897 goto domov; 898 899 found: 900 switch(o->prefix) { 901 case Pq: /* 16 bit escape and opcode escape */ 902 *andptr++ = Pe; 903 *andptr++ = Pm; 904 break; 905 906 case Pm: /* opcode escape */ 907 *andptr++ = Pm; 908 break; 909 910 case Pe: /* 16 bit escape */ 911 *andptr++ = Pe; 912 break; 913 914 case Pb: /* botch */ 915 break; 916 } 917 v = vaddr(&p->from); 918 op = o->op[z]; 919 switch(t[2]) { 920 default: 921 diag("asmins: unknown z %d %P", t[2], p); 922 return; 923 924 case Zpseudo: 925 break; 926 927 case Zlit: 928 for(; op = o->op[z]; z++) 929 *andptr++ = op; 930 break; 931 932 case Zm_r: 933 *andptr++ = op; 934 asmand(&p->from, reg[p->to.type]); 935 break; 936 937 case Zaut_r: 938 *andptr++ = 0x8d; /* leal */ 939 if(p->from.type != D_ADDR) 940 diag("asmins: Zaut sb type ADDR"); 941 p->from.type = p->from.index; 942 p->from.index = D_NONE; 943 asmand(&p->from, reg[p->to.type]); 944 p->from.index = p->from.type; 945 p->from.type = D_ADDR; 946 break; 947 948 case Zm_o: 949 *andptr++ = op; 950 asmand(&p->from, o->op[z+1]); 951 break; 952 953 case Zr_m: 954 *andptr++ = op; 955 asmand(&p->to, reg[p->from.type]); 956 break; 957 958 case Zo_m: 959 *andptr++ = op; 960 asmand(&p->to, o->op[z+1]); 961 break; 962 963 case Zm_ibo: 964 v = vaddr(&p->to); 965 *andptr++ = op; 966 asmand(&p->from, o->op[z+1]); 967 *andptr++ = v; 968 break; 969 970 case Zibo_m: 971 *andptr++ = op; 972 asmand(&p->to, o->op[z+1]); 973 *andptr++ = v; 974 break; 975 976 case Z_ib: 977 v = vaddr(&p->to); 978 case Zib_: 979 *andptr++ = op; 980 *andptr++ = v; 981 break; 982 983 case Zib_rp: 984 *andptr++ = op + reg[p->to.type]; 985 *andptr++ = v; 986 break; 987 988 case Zil_rp: 989 *andptr++ = op + reg[p->to.type]; 990 if(o->prefix == Pe) { 991 *andptr++ = v; 992 *andptr++ = v>>8; 993 } 994 else 995 put4(v); 996 break; 997 998 case Zib_rr: 999 *andptr++ = op; 1000 asmand(&p->to, reg[p->to.type]); 1001 *andptr++ = v; 1002 break; 1003 1004 case Z_il: 1005 v = vaddr(&p->to); 1006 case Zil_: 1007 *andptr++ = op; 1008 if(o->prefix == Pe) { 1009 *andptr++ = v; 1010 *andptr++ = v>>8; 1011 } 1012 else 1013 put4(v); 1014 break; 1015 1016 case Zm_ilo: 1017 v = vaddr(&p->to); 1018 *andptr++ = op; 1019 asmand(&p->from, o->op[z+1]); 1020 if(o->prefix == Pe) { 1021 *andptr++ = v; 1022 *andptr++ = v>>8; 1023 } 1024 else 1025 put4(v); 1026 break; 1027 1028 case Zilo_m: 1029 *andptr++ = op; 1030 asmand(&p->to, o->op[z+1]); 1031 if(o->prefix == Pe) { 1032 *andptr++ = v; 1033 *andptr++ = v>>8; 1034 } 1035 else 1036 put4(v); 1037 break; 1038 1039 case Zil_rr: 1040 *andptr++ = op; 1041 asmand(&p->to, reg[p->to.type]); 1042 if(o->prefix == Pe) { 1043 *andptr++ = v; 1044 *andptr++ = v>>8; 1045 } 1046 else 1047 put4(v); 1048 break; 1049 1050 case Z_rp: 1051 *andptr++ = op + reg[p->to.type]; 1052 break; 1053 1054 case Zrp_: 1055 *andptr++ = op + reg[p->from.type]; 1056 break; 1057 1058 case Zclr: 1059 *andptr++ = op; 1060 asmand(&p->to, reg[p->to.type]); 1061 break; 1062 1063 case Zbr: 1064 q = p->pcond; 1065 if(q) { 1066 v = q->pc - p->pc - 2; 1067 if(v >= -128 && v <= 127) { 1068 *andptr++ = op; 1069 *andptr++ = v; 1070 } else { 1071 v -= 6-2; 1072 *andptr++ = 0x0f; 1073 *andptr++ = o->op[z+1]; 1074 *andptr++ = v; 1075 *andptr++ = v>>8; 1076 *andptr++ = v>>16; 1077 *andptr++ = v>>24; 1078 } 1079 } 1080 break; 1081 1082 case Zcall: 1083 q = p->pcond; 1084 if(q) { 1085 v = q->pc - p->pc - 5; 1086 if(reloc && curp != P) { 1087 switch(p->to.sym->type) { 1088 case SUNDEF: 1089 v = 0; 1090 genreloc(p->to.sym, p->pc, 'P'); 1091 break; 1092 case SCONST: 1093 diag("Zcall: %P", curp); 1094 break; 1095 } 1096 } 1097 *andptr++ = op; 1098 *andptr++ = v; 1099 *andptr++ = v>>8; 1100 *andptr++ = v>>16; 1101 *andptr++ = v>>24; 1102 } 1103 break; 1104 1105 case Zjmp: 1106 q = p->pcond; 1107 if(q) { 1108 v = q->pc - p->pc - 2; 1109 if(v >= -128 && v <= 127) { 1110 *andptr++ = op; 1111 *andptr++ = v; 1112 } else { 1113 v -= 5-2; 1114 *andptr++ = o->op[z+1]; 1115 *andptr++ = v; 1116 *andptr++ = v>>8; 1117 *andptr++ = v>>16; 1118 *andptr++ = v>>24; 1119 } 1120 } 1121 break; 1122 1123 case Zloop: 1124 q = p->pcond; 1125 if(q) { 1126 v = q->pc - p->pc - 2; 1127 if(v < -128 && v > 127) 1128 diag("loop too far: %P", p); 1129 *andptr++ = op; 1130 *andptr++ = v; 1131 } 1132 break; 1133 1134 case Zbyte: 1135 *andptr++ = v; 1136 if(op > 1) { 1137 *andptr++ = v>>8; 1138 if(op > 2) { 1139 *andptr++ = v>>16; 1140 *andptr++ = v>>24; 1141 } 1142 } 1143 break; 1144 1145 case Zmov: 1146 goto domov; 1147 } 1148 return; 1149 1150 domov: 1151 for(t=ymovtab; *t; t+=8) 1152 if(p->as == t[0]) 1153 if(ycover[ft+t[1]]) 1154 if(ycover[tt+t[2]]) 1155 goto mfound; 1156 bad: 1157 /* 1158 * here, the assembly has failed. 1159 * if its a byte instruction that has 1160 * unaddressable registers, try to 1161 * exchange registers and reissue the 1162 * instruction with the operands renamed. 1163 */ 1164 pp = *p; 1165 z = p->from.type; 1166 if(z >= D_BP && z <= D_DI) { 1167 if(isax(&p->to)) { 1168 *andptr++ = 0x87; /* xchg lhs,bx */ 1169 asmand(&p->from, reg[D_BX]); 1170 subreg(&pp, z, D_BX); 1171 doasm(&pp); 1172 *andptr++ = 0x87; /* xchg lhs,bx */ 1173 asmand(&p->from, reg[D_BX]); 1174 } else { 1175 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1176 subreg(&pp, z, D_AX); 1177 doasm(&pp); 1178 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1179 } 1180 return; 1181 } 1182 z = p->to.type; 1183 if(z >= D_BP && z <= D_DI) { 1184 if(isax(&p->from)) { 1185 *andptr++ = 0x87; /* xchg rhs,bx */ 1186 asmand(&p->to, reg[D_BX]); 1187 subreg(&pp, z, D_BX); 1188 doasm(&pp); 1189 *andptr++ = 0x87; /* xchg rhs,bx */ 1190 asmand(&p->to, reg[D_BX]); 1191 } else { 1192 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1193 subreg(&pp, z, D_AX); 1194 doasm(&pp); 1195 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1196 } 1197 return; 1198 } 1199 diag("doasm: notfound t2=%lux from=%lux to=%lux %P", t[2], p->from.type, p->to.type, p); 1200 return; 1201 1202 mfound: 1203 switch(t[3]) { 1204 default: 1205 diag("asmins: unknown mov %d %P", t[3], p); 1206 break; 1207 1208 case 0: /* lit */ 1209 for(z=4; t[z]!=E; z++) 1210 *andptr++ = t[z]; 1211 break; 1212 1213 case 1: /* r,m */ 1214 *andptr++ = t[4]; 1215 asmand(&p->to, t[5]); 1216 break; 1217 1218 case 2: /* m,r */ 1219 *andptr++ = t[4]; 1220 asmand(&p->from, t[5]); 1221 break; 1222 1223 case 3: /* r,m - 2op */ 1224 *andptr++ = t[4]; 1225 *andptr++ = t[5]; 1226 asmand(&p->to, t[6]); 1227 break; 1228 1229 case 4: /* m,r - 2op */ 1230 *andptr++ = t[4]; 1231 *andptr++ = t[5]; 1232 asmand(&p->from, t[6]); 1233 break; 1234 1235 case 5: /* load full pointer, trash heap */ 1236 if(t[4]) 1237 *andptr++ = t[4]; 1238 switch(p->to.index) { 1239 default: 1240 goto bad; 1241 case D_DS: 1242 *andptr++ = 0xc5; 1243 break; 1244 case D_SS: 1245 *andptr++ = 0x0f; 1246 *andptr++ = 0xb2; 1247 break; 1248 case D_ES: 1249 *andptr++ = 0xc4; 1250 break; 1251 case D_FS: 1252 *andptr++ = 0x0f; 1253 *andptr++ = 0xb4; 1254 break; 1255 case D_GS: 1256 *andptr++ = 0x0f; 1257 *andptr++ = 0xb5; 1258 break; 1259 } 1260 asmand(&p->from, reg[p->to.type]); 1261 break; 1262 1263 case 6: /* double shift */ 1264 z = p->from.type; 1265 switch(z) { 1266 default: 1267 goto bad; 1268 case D_CONST: 1269 *andptr++ = 0x0f; 1270 *andptr++ = t[4]; 1271 asmand(&p->to, reg[p->from.index]); 1272 *andptr++ = p->from.offset; 1273 break; 1274 case D_CL: 1275 case D_CX: 1276 *andptr++ = 0x0f; 1277 *andptr++ = t[5]; 1278 asmand(&p->to, reg[p->from.index]); 1279 break; 1280 } 1281 break; 1282 1283 case 7: /* imul rm,r */ 1284 *andptr++ = t[4]; 1285 *andptr++ = t[5]; 1286 asmand(&p->from, reg[p->to.type]); 1287 break; 1288 } 1289 } 1290 1291 void 1292 asmins(Prog *p) 1293 { 1294 1295 andptr = and; 1296 doasm(p); 1297 } 1298