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