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 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->pcond) { 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->asym->name, 'z', a->aoffset, 0); 205 else 206 if(a->type == D_FILE1) 207 putsymb(a->asym->name, 'Z', a->aoffset, 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->asym->name, 'a', -a->aoffset, 0); 217 else 218 if(a->type == D_PARAM) 219 putsymb(a->asym->name, 'p', a->aoffset, 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_BP: 489 case D_SI: 490 case D_DI: 491 i |= reg[base]; 492 break; 493 } 494 *andptr++ = i; 495 return; 496 bad: 497 diag("asmidx: bad address %D", a); 498 *andptr++ = 0; 499 return; 500 } 501 502 static void 503 put4(long v) 504 { 505 if(dlm && curp != P && reloca != nil){ 506 dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1); 507 reloca = nil; 508 } 509 andptr[0] = v; 510 andptr[1] = v>>8; 511 andptr[2] = v>>16; 512 andptr[3] = v>>24; 513 andptr += 4; 514 } 515 516 long 517 vaddr(Adr *a) 518 { 519 int t; 520 long v; 521 Sym *s; 522 523 t = a->type; 524 v = a->offset; 525 if(t == D_ADDR) 526 t = a->index; 527 switch(t) { 528 case D_STATIC: 529 case D_EXTERN: 530 s = a->sym; 531 if(s != nil) { 532 if(dlm && curp != P) 533 reloca = a; 534 switch(s->type) { 535 case SUNDEF: 536 ckoff(s, v); 537 case STEXT: 538 case SCONST: 539 v += s->value; 540 break; 541 default: 542 v += INITDAT + s->value; 543 } 544 } 545 } 546 return v; 547 } 548 549 void 550 asmand(Adr *a, int r) 551 { 552 long v; 553 int t; 554 Adr aa; 555 556 v = a->offset; 557 t = a->type; 558 if(a->index != D_NONE) { 559 if(t >= D_INDIR) { 560 t -= D_INDIR; 561 if(t == D_NONE) { 562 *andptr++ = (0 << 6) | (4 << 0) | (r << 3); 563 asmidx(a, t); 564 put4(v); 565 return; 566 } 567 if(v == 0 && t != D_BP) { 568 *andptr++ = (0 << 6) | (4 << 0) | (r << 3); 569 asmidx(a, t); 570 return; 571 } 572 if(v >= -128 && v < 128) { 573 *andptr++ = (1 << 6) | (4 << 0) | (r << 3); 574 asmidx(a, t); 575 *andptr++ = v; 576 return; 577 } 578 *andptr++ = (2 << 6) | (4 << 0) | (r << 3); 579 asmidx(a, t); 580 put4(v); 581 return; 582 } 583 switch(t) { 584 default: 585 goto bad; 586 case D_STATIC: 587 case D_EXTERN: 588 aa.type = D_NONE+D_INDIR; 589 break; 590 case D_AUTO: 591 case D_PARAM: 592 aa.type = D_SP+D_INDIR; 593 break; 594 } 595 aa.offset = vaddr(a); 596 aa.index = a->index; 597 aa.scale = a->scale; 598 asmand(&aa, r); 599 return; 600 } 601 if(t >= D_AL && t <= D_F0+7) { 602 if(v) 603 goto bad; 604 *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3); 605 return; 606 } 607 if(t >= D_INDIR) { 608 t -= D_INDIR; 609 if(t == D_NONE) { 610 *andptr++ = (0 << 6) | (5 << 0) | (r << 3); 611 put4(v); 612 return; 613 } 614 if(t == D_SP) { 615 if(v == 0) { 616 *andptr++ = (0 << 6) | (4 << 0) | (r << 3); 617 asmidx(a, D_SP); 618 return; 619 } 620 if(v >= -128 && v < 128) { 621 *andptr++ = (1 << 6) | (4 << 0) | (r << 3); 622 asmidx(a, D_SP); 623 *andptr++ = v; 624 return; 625 } 626 *andptr++ = (2 << 6) | (4 << 0) | (r << 3); 627 asmidx(a, D_SP); 628 put4(v); 629 return; 630 } 631 if(t >= D_AX && t <= D_DI) { 632 if(v == 0 && t != D_BP) { 633 *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); 634 return; 635 } 636 if(v >= -128 && v < 128) { 637 andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); 638 andptr[1] = v; 639 andptr += 2; 640 return; 641 } 642 *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); 643 put4(v); 644 return; 645 } 646 goto bad; 647 } 648 switch(a->type) { 649 default: 650 goto bad; 651 case D_STATIC: 652 case D_EXTERN: 653 aa.type = D_NONE+D_INDIR; 654 break; 655 case D_AUTO: 656 case D_PARAM: 657 aa.type = D_SP+D_INDIR; 658 break; 659 } 660 aa.index = D_NONE; 661 aa.scale = 1; 662 aa.offset = vaddr(a); 663 asmand(&aa, r); 664 return; 665 bad: 666 diag("asmand: bad address %D", a); 667 return; 668 } 669 670 #define E 0xff 671 uchar ymovtab[] = 672 { 673 /* push */ 674 APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0, 675 APUSHL, Yss, Ynone, 0, 0x16,E,0,0, 676 APUSHL, Yds, Ynone, 0, 0x1e,E,0,0, 677 APUSHL, Yes, Ynone, 0, 0x06,E,0,0, 678 APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0, 679 APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0, 680 681 APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0, 682 APUSHW, Yss, Ynone, 0, Pe,0x16,E,0, 683 APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0, 684 APUSHW, Yes, Ynone, 0, Pe,0x06,E,0, 685 APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E, 686 APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E, 687 688 /* pop */ 689 APOPL, Ynone, Yds, 0, 0x1f,E,0,0, 690 APOPL, Ynone, Yes, 0, 0x07,E,0,0, 691 APOPL, Ynone, Yss, 0, 0x17,E,0,0, 692 APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0, 693 APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0, 694 695 APOPW, Ynone, Yds, 0, Pe,0x1f,E,0, 696 APOPW, Ynone, Yes, 0, Pe,0x07,E,0, 697 APOPW, Ynone, Yss, 0, Pe,0x17,E,0, 698 APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E, 699 APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E, 700 701 /* mov seg */ 702 AMOVW, Yes, Yml, 1, 0x8c,0,0,0, 703 AMOVW, Ycs, Yml, 1, 0x8c,1,0,0, 704 AMOVW, Yss, Yml, 1, 0x8c,2,0,0, 705 AMOVW, Yds, Yml, 1, 0x8c,3,0,0, 706 AMOVW, Yfs, Yml, 1, 0x8c,4,0,0, 707 AMOVW, Ygs, Yml, 1, 0x8c,5,0,0, 708 709 AMOVW, Yml, Yes, 2, 0x8e,0,0,0, 710 AMOVW, Yml, Ycs, 2, 0x8e,1,0,0, 711 AMOVW, Yml, Yss, 2, 0x8e,2,0,0, 712 AMOVW, Yml, Yds, 2, 0x8e,3,0,0, 713 AMOVW, Yml, Yfs, 2, 0x8e,4,0,0, 714 AMOVW, Yml, Ygs, 2, 0x8e,5,0,0, 715 716 /* mov cr */ 717 AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0, 718 AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0, 719 AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0, 720 AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0, 721 722 AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0, 723 AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0, 724 AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0, 725 AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0, 726 727 /* mov dr */ 728 AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0, 729 AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0, 730 AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0, 731 732 AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0, 733 AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0, 734 AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0, 735 736 /* mov tr */ 737 AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0, 738 AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0, 739 740 AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E, 741 AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E, 742 743 /* lgdt, sgdt, lidt, sidt */ 744 AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0, 745 AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0, 746 AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0, 747 AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0, 748 749 /* lldt, sldt */ 750 AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0, 751 AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0, 752 753 /* lmsw, smsw */ 754 AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0, 755 AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0, 756 757 /* ltr, str */ 758 AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0, 759 AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0, 760 761 /* load full pointer */ 762 AMOVL, Yml, Ycol, 5, 0,0,0,0, 763 AMOVW, Yml, Ycol, 5, Pe,0,0,0, 764 765 /* double shift */ 766 ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0, 767 ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0, 768 769 /* extra imul */ 770 AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0, 771 0 772 }; 773 774 int 775 isax(Adr *a) 776 { 777 778 switch(a->type) { 779 case D_AX: 780 case D_AL: 781 case D_AH: 782 case D_INDIR+D_AX: 783 return 1; 784 } 785 if(a->index == D_AX) 786 return 1; 787 return 0; 788 } 789 790 void 791 subreg(Prog *p, int from, int to) 792 { 793 794 if(debug['Q']) 795 print("\n%P s/%R/%R/\n", p, from, to); 796 797 if(p->from.type == from) 798 p->from.type = to; 799 if(p->to.type == from) 800 p->to.type = to; 801 802 if(p->from.index == from) 803 p->from.index = to; 804 if(p->to.index == from) 805 p->to.index = to; 806 807 from += D_INDIR; 808 if(p->from.type == from) 809 p->from.type = to+D_INDIR; 810 if(p->to.type == from) 811 p->to.type = to+D_INDIR; 812 813 if(debug['Q']) 814 print("%P\n", p); 815 } 816 817 void 818 doasm(Prog *p) 819 { 820 Optab *o; 821 Prog *q, pp; 822 uchar *t; 823 int z, op, ft, tt; 824 long v; 825 826 o = &optab[p->as]; 827 ft = oclass(&p->from) * Ymax; 828 tt = oclass(&p->to) * Ymax; 829 t = o->ytab; 830 if(t == 0) { 831 diag("asmins: noproto %P", p); 832 return; 833 } 834 for(z=0; *t; z+=t[3],t+=4) 835 if(ycover[ft+t[0]]) 836 if(ycover[tt+t[1]]) 837 goto found; 838 goto domov; 839 840 found: 841 switch(o->prefix) { 842 case Pq: /* 16 bit escape and opcode escape */ 843 *andptr++ = Pe; 844 *andptr++ = Pm; 845 break; 846 847 case Pm: /* opcode escape */ 848 *andptr++ = Pm; 849 break; 850 851 case Pe: /* 16 bit escape */ 852 *andptr++ = Pe; 853 break; 854 855 case Pb: /* botch */ 856 break; 857 } 858 v = vaddr(&p->from); 859 op = o->op[z]; 860 switch(t[2]) { 861 default: 862 diag("asmins: unknown z %d %P", t[2], p); 863 return; 864 865 case Zpseudo: 866 break; 867 868 case Zlit: 869 for(; op = o->op[z]; z++) 870 *andptr++ = op; 871 break; 872 873 case Zm_r: 874 *andptr++ = op; 875 asmand(&p->from, reg[p->to.type]); 876 break; 877 878 case Zaut_r: 879 *andptr++ = 0x8d; /* leal */ 880 if(p->from.type != D_ADDR) 881 diag("asmins: Zaut sb type ADDR"); 882 p->from.type = p->from.index; 883 p->from.index = D_NONE; 884 asmand(&p->from, reg[p->to.type]); 885 p->from.index = p->from.type; 886 p->from.type = D_ADDR; 887 break; 888 889 case Zm_o: 890 *andptr++ = op; 891 asmand(&p->from, o->op[z+1]); 892 break; 893 894 case Zr_m: 895 *andptr++ = op; 896 asmand(&p->to, reg[p->from.type]); 897 break; 898 899 case Zo_m: 900 *andptr++ = op; 901 asmand(&p->to, o->op[z+1]); 902 break; 903 904 case Zm_ibo: 905 v = vaddr(&p->to); 906 *andptr++ = op; 907 asmand(&p->from, o->op[z+1]); 908 *andptr++ = v; 909 break; 910 911 case Zibo_m: 912 *andptr++ = op; 913 asmand(&p->to, o->op[z+1]); 914 *andptr++ = v; 915 break; 916 917 case Z_ib: 918 v = vaddr(&p->to); 919 case Zib_: 920 *andptr++ = op; 921 *andptr++ = v; 922 break; 923 924 case Zib_rp: 925 *andptr++ = op + reg[p->to.type]; 926 *andptr++ = v; 927 break; 928 929 case Zil_rp: 930 *andptr++ = op + reg[p->to.type]; 931 if(o->prefix == Pe) { 932 *andptr++ = v; 933 *andptr++ = v>>8; 934 } 935 else 936 put4(v); 937 break; 938 939 case Zib_rr: 940 *andptr++ = op; 941 asmand(&p->to, reg[p->to.type]); 942 *andptr++ = v; 943 break; 944 945 case Z_il: 946 v = vaddr(&p->to); 947 case Zil_: 948 *andptr++ = op; 949 if(o->prefix == Pe) { 950 *andptr++ = v; 951 *andptr++ = v>>8; 952 } 953 else 954 put4(v); 955 break; 956 957 case Zm_ilo: 958 v = vaddr(&p->to); 959 *andptr++ = op; 960 asmand(&p->from, o->op[z+1]); 961 if(o->prefix == Pe) { 962 *andptr++ = v; 963 *andptr++ = v>>8; 964 } 965 else 966 put4(v); 967 break; 968 969 case Zilo_m: 970 *andptr++ = op; 971 asmand(&p->to, o->op[z+1]); 972 if(o->prefix == Pe) { 973 *andptr++ = v; 974 *andptr++ = v>>8; 975 } 976 else 977 put4(v); 978 break; 979 980 case Zil_rr: 981 *andptr++ = op; 982 asmand(&p->to, reg[p->to.type]); 983 if(o->prefix == Pe) { 984 *andptr++ = v; 985 *andptr++ = v>>8; 986 } 987 else 988 put4(v); 989 break; 990 991 case Z_rp: 992 *andptr++ = op + reg[p->to.type]; 993 break; 994 995 case Zrp_: 996 *andptr++ = op + reg[p->from.type]; 997 break; 998 999 case Zclr: 1000 *andptr++ = op; 1001 asmand(&p->to, reg[p->to.type]); 1002 break; 1003 1004 case Zbr: 1005 q = p->pcond; 1006 if(q) { 1007 v = q->pc - p->pc - 2; 1008 if(v >= -128 && v <= 127) { 1009 *andptr++ = op; 1010 *andptr++ = v; 1011 } else { 1012 v -= 6-2; 1013 *andptr++ = 0x0f; 1014 *andptr++ = o->op[z+1]; 1015 *andptr++ = v; 1016 *andptr++ = v>>8; 1017 *andptr++ = v>>16; 1018 *andptr++ = v>>24; 1019 } 1020 } 1021 break; 1022 1023 case Zcall: 1024 q = p->pcond; 1025 if(q) { 1026 v = q->pc - p->pc - 5; 1027 if(dlm && curp != P && p->to.sym->type == SUNDEF){ 1028 /* v = 0 - p->pc - 5; */ 1029 v = 0; 1030 ckoff(p->to.sym, v); 1031 v += p->to.sym->value; 1032 dynreloc(p->to.sym, p->pc+1, 0); 1033 } 1034 *andptr++ = op; 1035 *andptr++ = v; 1036 *andptr++ = v>>8; 1037 *andptr++ = v>>16; 1038 *andptr++ = v>>24; 1039 } 1040 break; 1041 1042 case Zjmp: 1043 q = p->pcond; 1044 if(q) { 1045 v = q->pc - p->pc - 2; 1046 if(v >= -128 && v <= 127) { 1047 *andptr++ = op; 1048 *andptr++ = v; 1049 } else { 1050 v -= 5-2; 1051 *andptr++ = o->op[z+1]; 1052 *andptr++ = v; 1053 *andptr++ = v>>8; 1054 *andptr++ = v>>16; 1055 *andptr++ = v>>24; 1056 } 1057 } 1058 break; 1059 1060 case Zloop: 1061 q = p->pcond; 1062 if(q) { 1063 v = q->pc - p->pc - 2; 1064 if(v < -128 && v > 127) 1065 diag("loop too far: %P", p); 1066 *andptr++ = op; 1067 *andptr++ = v; 1068 } 1069 break; 1070 1071 case Zbyte: 1072 *andptr++ = v; 1073 if(op > 1) { 1074 *andptr++ = v>>8; 1075 if(op > 2) { 1076 *andptr++ = v>>16; 1077 *andptr++ = v>>24; 1078 } 1079 } 1080 break; 1081 1082 case Zmov: 1083 goto domov; 1084 } 1085 return; 1086 1087 domov: 1088 for(t=ymovtab; *t; t+=8) 1089 if(p->as == t[0]) 1090 if(ycover[ft+t[1]]) 1091 if(ycover[tt+t[2]]) 1092 goto mfound; 1093 bad: 1094 /* 1095 * here, the assembly has failed. 1096 * if its a byte instruction that has 1097 * unaddressable registers, try to 1098 * exchange registers and reissue the 1099 * instruction with the operands renamed. 1100 */ 1101 pp = *p; 1102 z = p->from.type; 1103 if(z >= D_BP && z <= D_DI) { 1104 if(isax(&p->to)) { 1105 *andptr++ = 0x87; /* xchg lhs,bx */ 1106 asmand(&p->from, reg[D_BX]); 1107 subreg(&pp, z, D_BX); 1108 doasm(&pp); 1109 *andptr++ = 0x87; /* xchg lhs,bx */ 1110 asmand(&p->from, reg[D_BX]); 1111 } else { 1112 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1113 subreg(&pp, z, D_AX); 1114 doasm(&pp); 1115 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1116 } 1117 return; 1118 } 1119 z = p->to.type; 1120 if(z >= D_BP && z <= D_DI) { 1121 if(isax(&p->from)) { 1122 *andptr++ = 0x87; /* xchg rhs,bx */ 1123 asmand(&p->to, reg[D_BX]); 1124 subreg(&pp, z, D_BX); 1125 doasm(&pp); 1126 *andptr++ = 0x87; /* xchg rhs,bx */ 1127 asmand(&p->to, reg[D_BX]); 1128 } else { 1129 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1130 subreg(&pp, z, D_AX); 1131 doasm(&pp); 1132 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1133 } 1134 return; 1135 } 1136 diag("doasm: notfound t2=%lux from=%lux to=%lux %P", t[2], p->from.type, p->to.type, p); 1137 return; 1138 1139 mfound: 1140 switch(t[3]) { 1141 default: 1142 diag("asmins: unknown mov %d %P", t[3], p); 1143 break; 1144 1145 case 0: /* lit */ 1146 for(z=4; t[z]!=E; z++) 1147 *andptr++ = t[z]; 1148 break; 1149 1150 case 1: /* r,m */ 1151 *andptr++ = t[4]; 1152 asmand(&p->to, t[5]); 1153 break; 1154 1155 case 2: /* m,r */ 1156 *andptr++ = t[4]; 1157 asmand(&p->from, t[5]); 1158 break; 1159 1160 case 3: /* r,m - 2op */ 1161 *andptr++ = t[4]; 1162 *andptr++ = t[5]; 1163 asmand(&p->to, t[6]); 1164 break; 1165 1166 case 4: /* m,r - 2op */ 1167 *andptr++ = t[4]; 1168 *andptr++ = t[5]; 1169 asmand(&p->from, t[6]); 1170 break; 1171 1172 case 5: /* load full pointer, trash heap */ 1173 if(t[4]) 1174 *andptr++ = t[4]; 1175 switch(p->to.index) { 1176 default: 1177 goto bad; 1178 case D_DS: 1179 *andptr++ = 0xc5; 1180 break; 1181 case D_SS: 1182 *andptr++ = 0x0f; 1183 *andptr++ = 0xb2; 1184 break; 1185 case D_ES: 1186 *andptr++ = 0xc4; 1187 break; 1188 case D_FS: 1189 *andptr++ = 0x0f; 1190 *andptr++ = 0xb4; 1191 break; 1192 case D_GS: 1193 *andptr++ = 0x0f; 1194 *andptr++ = 0xb5; 1195 break; 1196 } 1197 asmand(&p->from, reg[p->to.type]); 1198 break; 1199 1200 case 6: /* double shift */ 1201 z = p->from.type; 1202 switch(z) { 1203 default: 1204 goto bad; 1205 case D_CONST: 1206 *andptr++ = 0x0f; 1207 *andptr++ = t[4]; 1208 asmand(&p->to, reg[p->from.index]); 1209 *andptr++ = p->from.offset; 1210 break; 1211 case D_CL: 1212 case D_CX: 1213 *andptr++ = 0x0f; 1214 *andptr++ = t[5]; 1215 asmand(&p->to, reg[p->from.index]); 1216 break; 1217 } 1218 break; 1219 1220 case 7: /* imul rm,r */ 1221 *andptr++ = t[4]; 1222 *andptr++ = t[5]; 1223 asmand(&p->from, reg[p->to.type]); 1224 break; 1225 } 1226 } 1227 1228 void 1229 asmins(Prog *p) 1230 { 1231 1232 andptr = and; 1233 doasm(p); 1234 } 1235 1236 enum{ 1237 ABSD = 0, 1238 ABSU = 1, 1239 RELD = 2, 1240 RELU = 3, 1241 }; 1242 1243 int modemap[4] = { 0, 1, -1, 2, }; 1244 1245 typedef struct Reloc Reloc; 1246 1247 struct Reloc 1248 { 1249 int n; 1250 int t; 1251 uchar *m; 1252 ulong *a; 1253 }; 1254 1255 Reloc rels; 1256 1257 static void 1258 grow(Reloc *r) 1259 { 1260 int t; 1261 uchar *m, *nm; 1262 ulong *a, *na; 1263 1264 t = r->t; 1265 r->t += 64; 1266 m = r->m; 1267 a = r->a; 1268 r->m = nm = malloc(r->t*sizeof(uchar)); 1269 r->a = na = malloc(r->t*sizeof(ulong)); 1270 memmove(nm, m, t*sizeof(uchar)); 1271 memmove(na, a, t*sizeof(ulong)); 1272 free(m); 1273 free(a); 1274 } 1275 1276 void 1277 dynreloc(Sym *s, ulong v, int abs) 1278 { 1279 int i, k, n; 1280 uchar *m; 1281 ulong *a; 1282 Reloc *r; 1283 1284 if(s->type == SUNDEF) 1285 k = abs ? ABSU : RELU; 1286 else 1287 k = abs ? ABSD : RELD; 1288 /* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */ 1289 k = modemap[k]; 1290 r = &rels; 1291 n = r->n; 1292 if(n >= r->t) 1293 grow(r); 1294 m = r->m; 1295 a = r->a; 1296 for(i = n; i > 0; i--){ 1297 if(v < a[i-1]){ /* happens occasionally for data */ 1298 m[i] = m[i-1]; 1299 a[i] = a[i-1]; 1300 } 1301 else 1302 break; 1303 } 1304 m[i] = k; 1305 a[i] = v; 1306 r->n++; 1307 } 1308 1309 static int 1310 sput(char *s) 1311 { 1312 char *p; 1313 1314 p = s; 1315 while(*s) 1316 cput(*s++); 1317 cput(0); 1318 return s-p+1; 1319 } 1320 1321 void 1322 asmdyn() 1323 { 1324 int i, n, t, c; 1325 Sym *s; 1326 ulong la, ra, *a; 1327 vlong off; 1328 uchar *m; 1329 Reloc *r; 1330 1331 cflush(); 1332 off = seek(cout, 0, 1); 1333 lput(0); 1334 t = 0; 1335 lput(imports); 1336 t += 4; 1337 for(i = 0; i < NHASH; i++) 1338 for(s = hash[i]; s != S; s = s->link) 1339 if(s->type == SUNDEF){ 1340 lput(s->sig); 1341 t += 4; 1342 t += sput(s->name); 1343 } 1344 1345 la = 0; 1346 r = &rels; 1347 n = r->n; 1348 m = r->m; 1349 a = r->a; 1350 lput(n); 1351 t += 4; 1352 for(i = 0; i < n; i++){ 1353 ra = *a-la; 1354 if(*a < la) 1355 diag("bad relocation order"); 1356 if(ra < 256) 1357 c = 0; 1358 else if(ra < 65536) 1359 c = 1; 1360 else 1361 c = 2; 1362 cput((c<<6)|*m++); 1363 t++; 1364 if(c == 0){ 1365 cput(ra); 1366 t++; 1367 } 1368 else if(c == 1){ 1369 wputb(ra); 1370 t += 2; 1371 } 1372 else{ 1373 lput(ra); 1374 t += 4; 1375 } 1376 la = *a++; 1377 } 1378 1379 cflush(); 1380 seek(cout, off, 0); 1381 lput(t); 1382 1383 if(debug['v']){ 1384 Bprint(&bso, "import table entries = %d\n", imports); 1385 Bprint(&bso, "export table entries = %d\n", exports); 1386 } 1387 } 1388