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