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\n", 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\n", 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 0 829 }; 830 831 int 832 isax(Adr *a) 833 { 834 835 switch(a->type) { 836 case D_AX: 837 case D_AL: 838 case D_AH: 839 case D_INDIR+D_AX: 840 return 1; 841 } 842 if(a->index == D_AX) 843 return 1; 844 return 0; 845 } 846 847 void 848 subreg(Prog *p, int from, int to) 849 { 850 851 if(debug['Q']) 852 print("\n%P s/%R/%R/\n", p, from, to); 853 854 if(p->from.type == from) 855 p->from.type = to; 856 if(p->to.type == from) 857 p->to.type = to; 858 859 if(p->from.index == from) 860 p->from.index = to; 861 if(p->to.index == from) 862 p->to.index = to; 863 864 from += D_INDIR; 865 if(p->from.type == from) 866 p->from.type = to+D_INDIR; 867 if(p->to.type == from) 868 p->to.type = to+D_INDIR; 869 870 if(debug['Q']) 871 print("%P\n", p); 872 } 873 874 void 875 doasm(Prog *p) 876 { 877 Optab *o; 878 Prog *q, pp; 879 uchar *t; 880 int z, op, ft, tt; 881 long v; 882 883 o = &optab[p->as]; 884 ft = oclass(&p->from) * Ymax; 885 tt = oclass(&p->to) * Ymax; 886 t = o->ytab; 887 if(t == 0) { 888 diag("asmins: noproto %P\n", p); 889 return; 890 } 891 for(z=0; *t; z+=t[3],t+=4) 892 if(ycover[ft+t[0]]) 893 if(ycover[tt+t[1]]) 894 goto found; 895 goto domov; 896 897 found: 898 switch(o->prefix) { 899 case Pq: /* 16 bit escape and opcode escape */ 900 *andptr++ = Pe; 901 *andptr++ = Pm; 902 break; 903 904 case Pm: /* opcode escape */ 905 *andptr++ = Pm; 906 break; 907 908 case Pe: /* 16 bit escape */ 909 *andptr++ = Pe; 910 break; 911 912 case Pb: /* botch */ 913 break; 914 } 915 v = vaddr(&p->from); 916 op = o->op[z]; 917 switch(t[2]) { 918 default: 919 diag("asmins: unknown z %d %P\n", t[2], p); 920 return; 921 922 case Zpseudo: 923 break; 924 925 case Zlit: 926 for(; op = o->op[z]; z++) 927 *andptr++ = op; 928 break; 929 930 case Zm_r: 931 *andptr++ = op; 932 asmand(&p->from, reg[p->to.type]); 933 break; 934 935 case Zaut_r: 936 *andptr++ = 0x8d; /* leal */ 937 if(p->from.type != D_ADDR) 938 diag("asmins: Zaut sb type ADDR"); 939 p->from.type = p->from.index; 940 p->from.index = D_NONE; 941 asmand(&p->from, reg[p->to.type]); 942 p->from.index = p->from.type; 943 p->from.type = D_ADDR; 944 break; 945 946 case Zm_o: 947 *andptr++ = op; 948 asmand(&p->from, o->op[z+1]); 949 break; 950 951 case Zr_m: 952 *andptr++ = op; 953 asmand(&p->to, reg[p->from.type]); 954 break; 955 956 case Zo_m: 957 *andptr++ = op; 958 asmand(&p->to, o->op[z+1]); 959 break; 960 961 case Zm_ibo: 962 v = vaddr(&p->to); 963 *andptr++ = op; 964 asmand(&p->from, o->op[z+1]); 965 *andptr++ = v; 966 break; 967 968 case Zibo_m: 969 *andptr++ = op; 970 asmand(&p->to, o->op[z+1]); 971 *andptr++ = v; 972 break; 973 974 case Z_ib: 975 v = vaddr(&p->to); 976 case Zib_: 977 *andptr++ = op; 978 *andptr++ = v; 979 break; 980 981 case Zib_rp: 982 *andptr++ = op + reg[p->to.type]; 983 *andptr++ = v; 984 break; 985 986 case Zil_rp: 987 *andptr++ = op + reg[p->to.type]; 988 if(o->prefix == Pe) { 989 *andptr++ = v; 990 *andptr++ = v>>8; 991 } 992 else 993 put4(v); 994 break; 995 996 case Zib_rr: 997 *andptr++ = op; 998 asmand(&p->to, reg[p->to.type]); 999 *andptr++ = v; 1000 break; 1001 1002 case Z_il: 1003 v = vaddr(&p->to); 1004 case Zil_: 1005 *andptr++ = op; 1006 if(o->prefix == Pe) { 1007 *andptr++ = v; 1008 *andptr++ = v>>8; 1009 } 1010 else 1011 put4(v); 1012 break; 1013 1014 case Zm_ilo: 1015 v = vaddr(&p->to); 1016 *andptr++ = op; 1017 asmand(&p->from, o->op[z+1]); 1018 if(o->prefix == Pe) { 1019 *andptr++ = v; 1020 *andptr++ = v>>8; 1021 } 1022 else 1023 put4(v); 1024 break; 1025 1026 case Zilo_m: 1027 *andptr++ = op; 1028 asmand(&p->to, o->op[z+1]); 1029 if(o->prefix == Pe) { 1030 *andptr++ = v; 1031 *andptr++ = v>>8; 1032 } 1033 else 1034 put4(v); 1035 break; 1036 1037 case Zil_rr: 1038 *andptr++ = op; 1039 asmand(&p->to, reg[p->to.type]); 1040 if(o->prefix == Pe) { 1041 *andptr++ = v; 1042 *andptr++ = v>>8; 1043 } 1044 else 1045 put4(v); 1046 break; 1047 1048 case Z_rp: 1049 *andptr++ = op + reg[p->to.type]; 1050 break; 1051 1052 case Zrp_: 1053 *andptr++ = op + reg[p->from.type]; 1054 break; 1055 1056 case Zclr: 1057 *andptr++ = op; 1058 asmand(&p->to, reg[p->to.type]); 1059 break; 1060 1061 case Zbr: 1062 q = p->pcond; 1063 if(q) { 1064 v = q->pc - p->pc - 2; 1065 if(v >= -128 && v <= 127) { 1066 *andptr++ = op; 1067 *andptr++ = v; 1068 } else { 1069 v -= 6-2; 1070 *andptr++ = 0x0f; 1071 *andptr++ = o->op[z+1]; 1072 *andptr++ = v; 1073 *andptr++ = v>>8; 1074 *andptr++ = v>>16; 1075 *andptr++ = v>>24; 1076 } 1077 } 1078 break; 1079 1080 case Zcall: 1081 q = p->pcond; 1082 if(q) { 1083 v = q->pc - p->pc - 5; 1084 if(reloc && curp != P) { 1085 switch(p->to.sym->type) { 1086 case SUNDEF: 1087 v = 0; 1088 genreloc(p->to.sym, p->pc, 'P'); 1089 break; 1090 case SCONST: 1091 diag("Zcall: %P", curp); 1092 break; 1093 } 1094 } 1095 *andptr++ = op; 1096 *andptr++ = v; 1097 *andptr++ = v>>8; 1098 *andptr++ = v>>16; 1099 *andptr++ = v>>24; 1100 } 1101 break; 1102 1103 case Zjmp: 1104 q = p->pcond; 1105 if(q) { 1106 v = q->pc - p->pc - 2; 1107 if(v >= -128 && v <= 127) { 1108 *andptr++ = op; 1109 *andptr++ = v; 1110 } else { 1111 v -= 5-2; 1112 *andptr++ = o->op[z+1]; 1113 *andptr++ = v; 1114 *andptr++ = v>>8; 1115 *andptr++ = v>>16; 1116 *andptr++ = v>>24; 1117 } 1118 } 1119 break; 1120 1121 case Zloop: 1122 q = p->pcond; 1123 if(q) { 1124 v = q->pc - p->pc - 2; 1125 if(v < -128 && v > 127) 1126 diag("loop too far: %P\n", p); 1127 *andptr++ = op; 1128 *andptr++ = v; 1129 } 1130 break; 1131 1132 case Zbyte: 1133 *andptr++ = v; 1134 if(op > 1) { 1135 *andptr++ = v>>8; 1136 if(op > 2) { 1137 *andptr++ = v>>16; 1138 *andptr++ = v>>24; 1139 } 1140 } 1141 break; 1142 1143 case Zmov: 1144 goto domov; 1145 } 1146 return; 1147 1148 domov: 1149 for(t=ymovtab; *t; t+=8) 1150 if(p->as == t[0]) 1151 if(ycover[ft+t[1]]) 1152 if(ycover[tt+t[2]]) 1153 goto mfound; 1154 bad: 1155 /* 1156 * here, the assembly has failed. 1157 * if its a byte instruction that has 1158 * unaddressable registers, try to 1159 * exchange registers and reissue the 1160 * instruction with the operands renamed. 1161 */ 1162 pp = *p; 1163 z = p->from.type; 1164 if(z >= D_BP && z <= D_DI) { 1165 if(isax(&p->to)) { 1166 *andptr++ = 0x87; /* xchg lhs,bx */ 1167 asmand(&p->from, reg[D_BX]); 1168 subreg(&pp, z, D_BX); 1169 doasm(&pp); 1170 *andptr++ = 0x87; /* xchg lhs,bx */ 1171 asmand(&p->from, reg[D_BX]); 1172 } else { 1173 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1174 subreg(&pp, z, D_AX); 1175 doasm(&pp); 1176 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1177 } 1178 return; 1179 } 1180 z = p->to.type; 1181 if(z >= D_BP && z <= D_DI) { 1182 if(isax(&p->from)) { 1183 *andptr++ = 0x87; /* xchg rhs,bx */ 1184 asmand(&p->to, reg[D_BX]); 1185 subreg(&pp, z, D_BX); 1186 doasm(&pp); 1187 *andptr++ = 0x87; /* xchg rhs,bx */ 1188 asmand(&p->to, reg[D_BX]); 1189 } else { 1190 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1191 subreg(&pp, z, D_AX); 1192 doasm(&pp); 1193 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1194 } 1195 return; 1196 } 1197 diag("doasm: notfound t2=%lux from=%lux to=%lux %P\n", t[2], p->from.type, p->to.type, p); 1198 return; 1199 1200 mfound: 1201 switch(t[3]) { 1202 default: 1203 diag("asmins: unknown mov %d %P\n", t[3], p); 1204 break; 1205 1206 case 0: /* lit */ 1207 for(z=4; t[z]!=E; z++) 1208 *andptr++ = t[z]; 1209 break; 1210 1211 case 1: /* r,m */ 1212 *andptr++ = t[4]; 1213 asmand(&p->to, t[5]); 1214 break; 1215 1216 case 2: /* m,r */ 1217 *andptr++ = t[4]; 1218 asmand(&p->from, t[5]); 1219 break; 1220 1221 case 3: /* r,m - 2op */ 1222 *andptr++ = t[4]; 1223 *andptr++ = t[5]; 1224 asmand(&p->to, t[6]); 1225 break; 1226 1227 case 4: /* m,r - 2op */ 1228 *andptr++ = t[4]; 1229 *andptr++ = t[5]; 1230 asmand(&p->from, t[6]); 1231 break; 1232 1233 case 5: /* load full pointer, trash heap */ 1234 if(t[4]) 1235 *andptr++ = t[4]; 1236 switch(p->to.index) { 1237 default: 1238 goto bad; 1239 case D_DS: 1240 *andptr++ = 0xc5; 1241 break; 1242 case D_SS: 1243 *andptr++ = 0x0f; 1244 *andptr++ = 0xb2; 1245 break; 1246 case D_ES: 1247 *andptr++ = 0xc4; 1248 break; 1249 case D_FS: 1250 *andptr++ = 0x0f; 1251 *andptr++ = 0xb4; 1252 break; 1253 case D_GS: 1254 *andptr++ = 0x0f; 1255 *andptr++ = 0xb5; 1256 break; 1257 } 1258 asmand(&p->from, reg[p->to.type]); 1259 break; 1260 1261 case 6: /* double shift */ 1262 z = p->from.type; 1263 switch(z) { 1264 default: 1265 goto bad; 1266 case D_CONST: 1267 *andptr++ = 0x0f; 1268 *andptr++ = t[4]; 1269 asmand(&p->to, reg[p->from.index]); 1270 *andptr++ = p->from.offset; 1271 break; 1272 case D_CL: 1273 case D_CX: 1274 *andptr++ = 0x0f; 1275 *andptr++ = t[5]; 1276 asmand(&p->to, reg[p->from.index]); 1277 break; 1278 } 1279 break; 1280 } 1281 } 1282 1283 void 1284 asmins(Prog *p) 1285 { 1286 1287 andptr = and; 1288 doasm(p); 1289 } 1290