github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/8l/span.c (about) 1 // Inferno utils/8l/span.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8l/span.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 // Instruction layout. 32 33 #include "l.h" 34 #include "../ld/lib.h" 35 #include "../ld/elf.h" 36 37 static int32 vaddr(Adr*, Reloc*); 38 39 void 40 span1(Sym *s) 41 { 42 Prog *p, *q; 43 int32 c, v, loop; 44 uchar *bp; 45 int n, m, i; 46 47 cursym = s; 48 49 for(p = s->text; p != P; p = p->link) { 50 p->back = 2; // use short branches first time through 51 if((q = p->pcond) != P && (q->back & 2)) 52 p->back |= 1; // backward jump 53 54 if(p->as == AADJSP) { 55 p->to.type = D_SP; 56 v = -p->from.offset; 57 p->from.offset = v; 58 p->as = AADDL; 59 if(v < 0) { 60 p->as = ASUBL; 61 v = -v; 62 p->from.offset = v; 63 } 64 if(v == 0) 65 p->as = ANOP; 66 } 67 } 68 69 n = 0; 70 do { 71 loop = 0; 72 memset(s->r, 0, s->nr*sizeof s->r[0]); 73 s->nr = 0; 74 s->np = 0; 75 c = 0; 76 for(p = s->text; p != P; p = p->link) { 77 p->pc = c; 78 79 // process forward jumps to p 80 for(q = p->comefrom; q != P; q = q->forwd) { 81 v = p->pc - (q->pc + q->mark); 82 if(q->back & 2) { // short 83 if(v > 127) { 84 loop++; 85 q->back ^= 2; 86 } 87 if(q->as == AJCXZW) 88 s->p[q->pc+2] = v; 89 else 90 s->p[q->pc+1] = v; 91 } else { 92 bp = s->p + q->pc + q->mark - 4; 93 *bp++ = v; 94 *bp++ = v>>8; 95 *bp++ = v>>16; 96 *bp = v>>24; 97 } 98 } 99 p->comefrom = P; 100 101 asmins(p); 102 p->pc = c; 103 m = andptr-and; 104 symgrow(s, p->pc+m); 105 memmove(s->p+p->pc, and, m); 106 p->mark = m; 107 c += m; 108 } 109 if(++n > 20) { 110 diag("span must be looping"); 111 errorexit(); 112 } 113 } while(loop); 114 s->size = c; 115 116 if(debug['a'] > 1) { 117 print("span1 %s %d (%d tries)\n %.6ux", s->name, s->size, n, 0); 118 for(i=0; i<s->np; i++) { 119 print(" %.2ux", s->p[i]); 120 if(i%16 == 15) 121 print("\n %.6ux", i+1); 122 } 123 if(i%16) 124 print("\n"); 125 126 for(i=0; i<s->nr; i++) { 127 Reloc *r; 128 129 r = &s->r[i]; 130 print(" rel %#.4ux/%d %s%+d\n", r->off, r->siz, r->sym->name, r->add); 131 } 132 } 133 } 134 135 void 136 span(void) 137 { 138 Prog *p, *q; 139 int32 v; 140 int n; 141 142 if(debug['v']) 143 Bprint(&bso, "%5.2f span\n", cputime()); 144 145 // NOTE(rsc): If we get rid of the globals we should 146 // be able to parallelize these iterations. 147 for(cursym = textp; cursym != nil; cursym = cursym->next) { 148 if(cursym->text == nil || cursym->text->link == nil) 149 continue; 150 151 // TODO: move into span1 152 for(p = cursym->text; p != P; p = p->link) { 153 n = 0; 154 if(p->to.type == D_BRANCH) 155 if(p->pcond == P) 156 p->pcond = p; 157 if((q = p->pcond) != P) 158 if(q->back != 2) 159 n = 1; 160 p->back = n; 161 if(p->as == AADJSP) { 162 p->to.type = D_SP; 163 v = -p->from.offset; 164 p->from.offset = v; 165 p->as = AADDL; 166 if(v < 0) { 167 p->as = ASUBL; 168 v = -v; 169 p->from.offset = v; 170 } 171 if(v == 0) 172 p->as = ANOP; 173 } 174 } 175 span1(cursym); 176 } 177 } 178 179 void 180 xdefine(char *p, int t, int32 v) 181 { 182 Sym *s; 183 184 s = lookup(p, 0); 185 s->type = t; 186 s->value = v; 187 s->reachable = 1; 188 s->special = 1; 189 } 190 191 void 192 instinit(void) 193 { 194 int i; 195 196 for(i=1; optab[i].as; i++) 197 if(i != optab[i].as) { 198 diag("phase error in optab: at %A found %A", i, optab[i].as); 199 errorexit(); 200 } 201 maxop = i; 202 203 for(i=0; i<Ymax; i++) 204 ycover[i*Ymax + i] = 1; 205 206 ycover[Yi0*Ymax + Yi8] = 1; 207 ycover[Yi1*Ymax + Yi8] = 1; 208 209 ycover[Yi0*Ymax + Yi32] = 1; 210 ycover[Yi1*Ymax + Yi32] = 1; 211 ycover[Yi8*Ymax + Yi32] = 1; 212 213 ycover[Yal*Ymax + Yrb] = 1; 214 ycover[Ycl*Ymax + Yrb] = 1; 215 ycover[Yax*Ymax + Yrb] = 1; 216 ycover[Ycx*Ymax + Yrb] = 1; 217 ycover[Yrx*Ymax + Yrb] = 1; 218 219 ycover[Yax*Ymax + Yrx] = 1; 220 ycover[Ycx*Ymax + Yrx] = 1; 221 222 ycover[Yax*Ymax + Yrl] = 1; 223 ycover[Ycx*Ymax + Yrl] = 1; 224 ycover[Yrx*Ymax + Yrl] = 1; 225 226 ycover[Yf0*Ymax + Yrf] = 1; 227 228 ycover[Yal*Ymax + Ymb] = 1; 229 ycover[Ycl*Ymax + Ymb] = 1; 230 ycover[Yax*Ymax + Ymb] = 1; 231 ycover[Ycx*Ymax + Ymb] = 1; 232 ycover[Yrx*Ymax + Ymb] = 1; 233 ycover[Yrb*Ymax + Ymb] = 1; 234 ycover[Ym*Ymax + Ymb] = 1; 235 236 ycover[Yax*Ymax + Yml] = 1; 237 ycover[Ycx*Ymax + Yml] = 1; 238 ycover[Yrx*Ymax + Yml] = 1; 239 ycover[Yrl*Ymax + Yml] = 1; 240 ycover[Ym*Ymax + Yml] = 1; 241 242 ycover[Yax*Ymax + Ymm] = 1; 243 ycover[Ycx*Ymax + Ymm] = 1; 244 ycover[Yrx*Ymax + Ymm] = 1; 245 ycover[Yrl*Ymax + Ymm] = 1; 246 ycover[Ym*Ymax + Ymm] = 1; 247 ycover[Ymr*Ymax + Ymm] = 1; 248 249 ycover[Ym*Ymax + Yxm] = 1; 250 ycover[Yxr*Ymax + Yxm] = 1; 251 252 for(i=0; i<D_NONE; i++) { 253 reg[i] = -1; 254 if(i >= D_AL && i <= D_BH) 255 reg[i] = (i-D_AL) & 7; 256 if(i >= D_AX && i <= D_DI) 257 reg[i] = (i-D_AX) & 7; 258 if(i >= D_F0 && i <= D_F0+7) 259 reg[i] = (i-D_F0) & 7; 260 if(i >= D_X0 && i <= D_X0+7) 261 reg[i] = (i-D_X0) & 7; 262 } 263 } 264 265 int 266 prefixof(Adr *a) 267 { 268 switch(a->type) { 269 case D_INDIR+D_CS: 270 return 0x2e; 271 case D_INDIR+D_DS: 272 return 0x3e; 273 case D_INDIR+D_ES: 274 return 0x26; 275 case D_INDIR+D_FS: 276 return 0x64; 277 case D_INDIR+D_GS: 278 return 0x65; 279 } 280 return 0; 281 } 282 283 int 284 oclass(Adr *a) 285 { 286 int32 v; 287 288 if((a->type >= D_INDIR && a->type < 2*D_INDIR) || a->index != D_NONE) { 289 if(a->index != D_NONE && a->scale == 0) { 290 if(a->type == D_ADDR) { 291 switch(a->index) { 292 case D_EXTERN: 293 case D_STATIC: 294 return Yi32; 295 case D_AUTO: 296 case D_PARAM: 297 return Yiauto; 298 } 299 return Yxxx; 300 } 301 //if(a->type == D_INDIR+D_ADDR) 302 // print("*Ycol\n"); 303 return Ycol; 304 } 305 return Ym; 306 } 307 switch(a->type) 308 { 309 case D_AL: 310 return Yal; 311 312 case D_AX: 313 return Yax; 314 315 case D_CL: 316 case D_DL: 317 case D_BL: 318 case D_AH: 319 case D_CH: 320 case D_DH: 321 case D_BH: 322 return Yrb; 323 324 case D_CX: 325 return Ycx; 326 327 case D_DX: 328 case D_BX: 329 return Yrx; 330 331 case D_SP: 332 case D_BP: 333 case D_SI: 334 case D_DI: 335 return Yrl; 336 337 case D_F0+0: 338 return Yf0; 339 340 case D_F0+1: 341 case D_F0+2: 342 case D_F0+3: 343 case D_F0+4: 344 case D_F0+5: 345 case D_F0+6: 346 case D_F0+7: 347 return Yrf; 348 349 case D_X0+0: 350 case D_X0+1: 351 case D_X0+2: 352 case D_X0+3: 353 case D_X0+4: 354 case D_X0+5: 355 case D_X0+6: 356 case D_X0+7: 357 return Yxr; 358 359 case D_NONE: 360 return Ynone; 361 362 case D_CS: return Ycs; 363 case D_SS: return Yss; 364 case D_DS: return Yds; 365 case D_ES: return Yes; 366 case D_FS: return Yfs; 367 case D_GS: return Ygs; 368 369 case D_GDTR: return Ygdtr; 370 case D_IDTR: return Yidtr; 371 case D_LDTR: return Yldtr; 372 case D_MSW: return Ymsw; 373 case D_TASK: return Ytask; 374 375 case D_CR+0: return Ycr0; 376 case D_CR+1: return Ycr1; 377 case D_CR+2: return Ycr2; 378 case D_CR+3: return Ycr3; 379 case D_CR+4: return Ycr4; 380 case D_CR+5: return Ycr5; 381 case D_CR+6: return Ycr6; 382 case D_CR+7: return Ycr7; 383 384 case D_DR+0: return Ydr0; 385 case D_DR+1: return Ydr1; 386 case D_DR+2: return Ydr2; 387 case D_DR+3: return Ydr3; 388 case D_DR+4: return Ydr4; 389 case D_DR+5: return Ydr5; 390 case D_DR+6: return Ydr6; 391 case D_DR+7: return Ydr7; 392 393 case D_TR+0: return Ytr0; 394 case D_TR+1: return Ytr1; 395 case D_TR+2: return Ytr2; 396 case D_TR+3: return Ytr3; 397 case D_TR+4: return Ytr4; 398 case D_TR+5: return Ytr5; 399 case D_TR+6: return Ytr6; 400 case D_TR+7: return Ytr7; 401 402 case D_EXTERN: 403 case D_STATIC: 404 case D_AUTO: 405 case D_PARAM: 406 return Ym; 407 408 case D_CONST: 409 case D_CONST2: 410 case D_ADDR: 411 if(a->sym == S) { 412 v = a->offset; 413 if(v == 0) 414 return Yi0; 415 if(v == 1) 416 return Yi1; 417 if(v >= -128 && v <= 127) 418 return Yi8; 419 } 420 return Yi32; 421 422 case D_BRANCH: 423 return Ybr; 424 } 425 return Yxxx; 426 } 427 428 void 429 asmidx(int scale, int index, int base) 430 { 431 int i; 432 433 switch(index) { 434 default: 435 goto bad; 436 437 case D_NONE: 438 i = 4 << 3; 439 goto bas; 440 441 case D_AX: 442 case D_CX: 443 case D_DX: 444 case D_BX: 445 case D_BP: 446 case D_SI: 447 case D_DI: 448 i = reg[index] << 3; 449 break; 450 } 451 switch(scale) { 452 default: 453 goto bad; 454 case 1: 455 break; 456 case 2: 457 i |= (1<<6); 458 break; 459 case 4: 460 i |= (2<<6); 461 break; 462 case 8: 463 i |= (3<<6); 464 break; 465 } 466 bas: 467 switch(base) { 468 default: 469 goto bad; 470 case D_NONE: /* must be mod=00 */ 471 i |= 5; 472 break; 473 case D_AX: 474 case D_CX: 475 case D_DX: 476 case D_BX: 477 case D_SP: 478 case D_BP: 479 case D_SI: 480 case D_DI: 481 i |= reg[base]; 482 break; 483 } 484 *andptr++ = i; 485 return; 486 bad: 487 diag("asmidx: bad address %d,%d,%d", scale, index, base); 488 *andptr++ = 0; 489 return; 490 } 491 492 static void 493 put4(int32 v) 494 { 495 andptr[0] = v; 496 andptr[1] = v>>8; 497 andptr[2] = v>>16; 498 andptr[3] = v>>24; 499 andptr += 4; 500 } 501 502 static void 503 relput4(Prog *p, Adr *a) 504 { 505 vlong v; 506 Reloc rel, *r; 507 508 v = vaddr(a, &rel); 509 if(rel.siz != 0) { 510 if(rel.siz != 4) 511 diag("bad reloc"); 512 r = addrel(cursym); 513 *r = rel; 514 r->off = p->pc + andptr - and; 515 } 516 put4(v); 517 } 518 519 int32 520 symaddr(Sym *s) 521 { 522 if(!s->reachable) 523 diag("unreachable symbol in symaddr - %s", s->name); 524 return s->value; 525 } 526 527 static int32 528 vaddr(Adr *a, Reloc *r) 529 { 530 int t; 531 int32 v; 532 Sym *s; 533 534 if(r != nil) 535 memset(r, 0, sizeof *r); 536 537 t = a->type; 538 v = a->offset; 539 if(t == D_ADDR) 540 t = a->index; 541 switch(t) { 542 case D_STATIC: 543 case D_EXTERN: 544 s = a->sym; 545 if(s != nil) { 546 if(!s->reachable) 547 sysfatal("unreachable symbol in vaddr - %s", s->name); 548 if(r == nil) { 549 diag("need reloc for %D", a); 550 errorexit(); 551 } 552 r->type = D_ADDR; 553 r->siz = 4; 554 r->off = -1; 555 r->sym = s; 556 r->add = v; 557 v = 0; 558 } 559 } 560 return v; 561 } 562 563 static int 564 istls(Adr *a) 565 { 566 if(HEADTYPE == Hlinux) 567 return a->index == D_GS; 568 return a->type == D_INDIR+D_GS; 569 } 570 571 void 572 asmand(Adr *a, int r) 573 { 574 int32 v; 575 int t, scale; 576 Reloc rel; 577 578 v = a->offset; 579 t = a->type; 580 rel.siz = 0; 581 if(a->index != D_NONE && a->index != D_FS && a->index != D_GS) { 582 if(t < D_INDIR || t >= 2*D_INDIR) { 583 switch(t) { 584 default: 585 goto bad; 586 case D_STATIC: 587 case D_EXTERN: 588 t = D_NONE; 589 v = vaddr(a, &rel); 590 break; 591 case D_AUTO: 592 case D_PARAM: 593 t = D_SP; 594 break; 595 } 596 } else 597 t -= D_INDIR; 598 599 if(t == D_NONE) { 600 *andptr++ = (0 << 6) | (4 << 0) | (r << 3); 601 asmidx(a->scale, a->index, t); 602 goto putrelv; 603 } 604 if(v == 0 && rel.siz == 0 && t != D_BP) { 605 *andptr++ = (0 << 6) | (4 << 0) | (r << 3); 606 asmidx(a->scale, a->index, t); 607 return; 608 } 609 if(v >= -128 && v < 128 && rel.siz == 0) { 610 *andptr++ = (1 << 6) | (4 << 0) | (r << 3); 611 asmidx(a->scale, a->index, t); 612 *andptr++ = v; 613 return; 614 } 615 *andptr++ = (2 << 6) | (4 << 0) | (r << 3); 616 asmidx(a->scale, a->index, t); 617 goto putrelv; 618 } 619 if(t >= D_AL && t <= D_F7 || t >= D_X0 && t <= D_X7) { 620 if(v) 621 goto bad; 622 *andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3); 623 return; 624 } 625 626 scale = a->scale; 627 if(t < D_INDIR || t >= 2*D_INDIR) { 628 switch(a->type) { 629 default: 630 goto bad; 631 case D_STATIC: 632 case D_EXTERN: 633 t = D_NONE; 634 v = vaddr(a, &rel); 635 break; 636 case D_AUTO: 637 case D_PARAM: 638 t = D_SP; 639 break; 640 } 641 scale = 1; 642 } else 643 t -= D_INDIR; 644 645 if(t == D_NONE || (D_CS <= t && t <= D_GS)) { 646 *andptr++ = (0 << 6) | (5 << 0) | (r << 3); 647 goto putrelv; 648 } 649 if(t == D_SP) { 650 if(v == 0 && rel.siz == 0) { 651 *andptr++ = (0 << 6) | (4 << 0) | (r << 3); 652 asmidx(scale, D_NONE, t); 653 return; 654 } 655 if(v >= -128 && v < 128 && rel.siz == 0) { 656 *andptr++ = (1 << 6) | (4 << 0) | (r << 3); 657 asmidx(scale, D_NONE, t); 658 *andptr++ = v; 659 return; 660 } 661 *andptr++ = (2 << 6) | (4 << 0) | (r << 3); 662 asmidx(scale, D_NONE, t); 663 goto putrelv; 664 } 665 if(t >= D_AX && t <= D_DI) { 666 if(v == 0 && rel.siz == 0 && t != D_BP) { 667 *andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3); 668 return; 669 } 670 if(v >= -128 && v < 128 && rel.siz == 0 && a->index != D_FS && a->index != D_GS) { 671 andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3); 672 andptr[1] = v; 673 andptr += 2; 674 return; 675 } 676 *andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3); 677 goto putrelv; 678 } 679 goto bad; 680 681 putrelv: 682 if(rel.siz != 0) { 683 Reloc *r; 684 685 if(rel.siz != 4) { 686 diag("bad rel"); 687 goto bad; 688 } 689 r = addrel(cursym); 690 *r = rel; 691 r->off = curp->pc + andptr - and; 692 } else if(iself && linkmode == LinkExternal && istls(a) && HEADTYPE != Hopenbsd) { 693 Reloc *r; 694 Sym *s; 695 696 r = addrel(cursym); 697 r->off = curp->pc + andptr - and; 698 r->add = 0; 699 r->xadd = 0; 700 r->siz = 4; 701 r->type = D_TLS; 702 if(a->offset == tlsoffset+0) 703 s = lookup("runtime.g", 0); 704 else 705 s = lookup("runtime.m", 0); 706 s->type = STLSBSS; 707 s->reachable = 1; 708 s->hide = 1; 709 s->size = PtrSize; 710 r->sym = s; 711 r->xsym = s; 712 v = 0; 713 } 714 715 put4(v); 716 return; 717 718 bad: 719 diag("asmand: bad address %D", a); 720 return; 721 } 722 723 #define E 0xff 724 uchar ymovtab[] = 725 { 726 /* push */ 727 APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0, 728 APUSHL, Yss, Ynone, 0, 0x16,E,0,0, 729 APUSHL, Yds, Ynone, 0, 0x1e,E,0,0, 730 APUSHL, Yes, Ynone, 0, 0x06,E,0,0, 731 APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0, 732 APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0, 733 734 APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0, 735 APUSHW, Yss, Ynone, 0, Pe,0x16,E,0, 736 APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0, 737 APUSHW, Yes, Ynone, 0, Pe,0x06,E,0, 738 APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E, 739 APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E, 740 741 /* pop */ 742 APOPL, Ynone, Yds, 0, 0x1f,E,0,0, 743 APOPL, Ynone, Yes, 0, 0x07,E,0,0, 744 APOPL, Ynone, Yss, 0, 0x17,E,0,0, 745 APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0, 746 APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0, 747 748 APOPW, Ynone, Yds, 0, Pe,0x1f,E,0, 749 APOPW, Ynone, Yes, 0, Pe,0x07,E,0, 750 APOPW, Ynone, Yss, 0, Pe,0x17,E,0, 751 APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E, 752 APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E, 753 754 /* mov seg */ 755 AMOVW, Yes, Yml, 1, 0x8c,0,0,0, 756 AMOVW, Ycs, Yml, 1, 0x8c,1,0,0, 757 AMOVW, Yss, Yml, 1, 0x8c,2,0,0, 758 AMOVW, Yds, Yml, 1, 0x8c,3,0,0, 759 AMOVW, Yfs, Yml, 1, 0x8c,4,0,0, 760 AMOVW, Ygs, Yml, 1, 0x8c,5,0,0, 761 762 AMOVW, Yml, Yes, 2, 0x8e,0,0,0, 763 AMOVW, Yml, Ycs, 2, 0x8e,1,0,0, 764 AMOVW, Yml, Yss, 2, 0x8e,2,0,0, 765 AMOVW, Yml, Yds, 2, 0x8e,3,0,0, 766 AMOVW, Yml, Yfs, 2, 0x8e,4,0,0, 767 AMOVW, Yml, Ygs, 2, 0x8e,5,0,0, 768 769 /* mov cr */ 770 AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0, 771 AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0, 772 AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0, 773 AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0, 774 775 AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0, 776 AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0, 777 AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0, 778 AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0, 779 780 /* mov dr */ 781 AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0, 782 AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0, 783 AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0, 784 785 AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0, 786 AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0, 787 AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0, 788 789 /* mov tr */ 790 AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0, 791 AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0, 792 793 AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E, 794 AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E, 795 796 /* lgdt, sgdt, lidt, sidt */ 797 AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0, 798 AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0, 799 AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0, 800 AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0, 801 802 /* lldt, sldt */ 803 AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0, 804 AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0, 805 806 /* lmsw, smsw */ 807 AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0, 808 AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0, 809 810 /* ltr, str */ 811 AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0, 812 AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0, 813 814 /* load full pointer */ 815 AMOVL, Yml, Ycol, 5, 0,0,0,0, 816 AMOVW, Yml, Ycol, 5, Pe,0,0,0, 817 818 /* double shift */ 819 ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0, 820 ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0, 821 822 /* extra imul */ 823 AIMULW, Yml, Yrl, 7, Pq,0xaf,0,0, 824 AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0, 825 0 826 }; 827 828 // byteswapreg returns a byte-addressable register (AX, BX, CX, DX) 829 // which is not referenced in a->type. 830 // If a is empty, it returns BX to account for MULB-like instructions 831 // that might use DX and AX. 832 int 833 byteswapreg(Adr *a) 834 { 835 int cana, canb, canc, cand; 836 837 cana = canb = canc = cand = 1; 838 839 switch(a->type) { 840 case D_NONE: 841 cana = cand = 0; 842 break; 843 case D_AX: 844 case D_AL: 845 case D_AH: 846 case D_INDIR+D_AX: 847 cana = 0; 848 break; 849 case D_BX: 850 case D_BL: 851 case D_BH: 852 case D_INDIR+D_BX: 853 canb = 0; 854 break; 855 case D_CX: 856 case D_CL: 857 case D_CH: 858 case D_INDIR+D_CX: 859 canc = 0; 860 break; 861 case D_DX: 862 case D_DL: 863 case D_DH: 864 case D_INDIR+D_DX: 865 cand = 0; 866 break; 867 } 868 switch(a->index) { 869 case D_AX: 870 cana = 0; 871 break; 872 case D_BX: 873 canb = 0; 874 break; 875 case D_CX: 876 canc = 0; 877 break; 878 case D_DX: 879 cand = 0; 880 break; 881 } 882 if(cana) 883 return D_AX; 884 if(canb) 885 return D_BX; 886 if(canc) 887 return D_CX; 888 if(cand) 889 return D_DX; 890 891 diag("impossible byte register"); 892 errorexit(); 893 return 0; 894 } 895 896 void 897 subreg(Prog *p, int from, int to) 898 { 899 900 if(debug['Q']) 901 print("\n%P s/%R/%R/\n", p, from, to); 902 903 if(p->from.type == from) { 904 p->from.type = to; 905 p->ft = 0; 906 } 907 if(p->to.type == from) { 908 p->to.type = to; 909 p->tt = 0; 910 } 911 912 if(p->from.index == from) { 913 p->from.index = to; 914 p->ft = 0; 915 } 916 if(p->to.index == from) { 917 p->to.index = to; 918 p->tt = 0; 919 } 920 921 from += D_INDIR; 922 if(p->from.type == from) { 923 p->from.type = to+D_INDIR; 924 p->ft = 0; 925 } 926 if(p->to.type == from) { 927 p->to.type = to+D_INDIR; 928 p->tt = 0; 929 } 930 931 if(debug['Q']) 932 print("%P\n", p); 933 } 934 935 static int 936 mediaop(Optab *o, int op, int osize, int z) 937 { 938 switch(op){ 939 case Pm: 940 case Pe: 941 case Pf2: 942 case Pf3: 943 if(osize != 1){ 944 if(op != Pm) 945 *andptr++ = op; 946 *andptr++ = Pm; 947 op = o->op[++z]; 948 break; 949 } 950 default: 951 if(andptr == and || andptr[-1] != Pm) 952 *andptr++ = Pm; 953 break; 954 } 955 *andptr++ = op; 956 return z; 957 } 958 959 void 960 doasm(Prog *p) 961 { 962 Optab *o; 963 Prog *q, pp; 964 uchar *t; 965 int z, op, ft, tt, breg; 966 int32 v, pre; 967 Reloc rel, *r; 968 Adr *a; 969 970 curp = p; // TODO 971 972 pre = prefixof(&p->from); 973 if(pre) 974 *andptr++ = pre; 975 pre = prefixof(&p->to); 976 if(pre) 977 *andptr++ = pre; 978 979 if(p->ft == 0) 980 p->ft = oclass(&p->from); 981 if(p->tt == 0) 982 p->tt = oclass(&p->to); 983 984 ft = p->ft * Ymax; 985 tt = p->tt * Ymax; 986 o = &optab[p->as]; 987 t = o->ytab; 988 if(t == 0) { 989 diag("asmins: noproto %P", p); 990 return; 991 } 992 for(z=0; *t; z+=t[3],t+=4) 993 if(ycover[ft+t[0]]) 994 if(ycover[tt+t[1]]) 995 goto found; 996 goto domov; 997 998 found: 999 switch(o->prefix) { 1000 case Pq: /* 16 bit escape and opcode escape */ 1001 *andptr++ = Pe; 1002 *andptr++ = Pm; 1003 break; 1004 1005 case Pf2: /* xmm opcode escape */ 1006 case Pf3: 1007 *andptr++ = o->prefix; 1008 *andptr++ = Pm; 1009 break; 1010 1011 case Pm: /* opcode escape */ 1012 *andptr++ = Pm; 1013 break; 1014 1015 case Pe: /* 16 bit escape */ 1016 *andptr++ = Pe; 1017 break; 1018 1019 case Pb: /* botch */ 1020 break; 1021 } 1022 1023 op = o->op[z]; 1024 switch(t[2]) { 1025 default: 1026 diag("asmins: unknown z %d %P", t[2], p); 1027 return; 1028 1029 case Zpseudo: 1030 break; 1031 1032 case Zlit: 1033 for(; op = o->op[z]; z++) 1034 *andptr++ = op; 1035 break; 1036 1037 case Zlitm_r: 1038 for(; op = o->op[z]; z++) 1039 *andptr++ = op; 1040 asmand(&p->from, reg[p->to.type]); 1041 break; 1042 1043 case Zm_r: 1044 *andptr++ = op; 1045 asmand(&p->from, reg[p->to.type]); 1046 break; 1047 1048 case Zm2_r: 1049 *andptr++ = op; 1050 *andptr++ = o->op[z+1]; 1051 asmand(&p->from, reg[p->to.type]); 1052 break; 1053 1054 case Zm_r_xm: 1055 mediaop(o, op, t[3], z); 1056 asmand(&p->from, reg[p->to.type]); 1057 break; 1058 1059 case Zm_r_i_xm: 1060 mediaop(o, op, t[3], z); 1061 asmand(&p->from, reg[p->to.type]); 1062 *andptr++ = p->to.offset; 1063 break; 1064 1065 case Zibm_r: 1066 while ((op = o->op[z++]) != 0) 1067 *andptr++ = op; 1068 asmand(&p->from, reg[p->to.type]); 1069 *andptr++ = p->to.offset; 1070 break; 1071 1072 case Zaut_r: 1073 *andptr++ = 0x8d; /* leal */ 1074 if(p->from.type != D_ADDR) 1075 diag("asmins: Zaut sb type ADDR"); 1076 p->from.type = p->from.index; 1077 p->from.index = D_NONE; 1078 p->ft = 0; 1079 asmand(&p->from, reg[p->to.type]); 1080 p->from.index = p->from.type; 1081 p->from.type = D_ADDR; 1082 p->ft = 0; 1083 break; 1084 1085 case Zm_o: 1086 *andptr++ = op; 1087 asmand(&p->from, o->op[z+1]); 1088 break; 1089 1090 case Zr_m: 1091 *andptr++ = op; 1092 asmand(&p->to, reg[p->from.type]); 1093 break; 1094 1095 case Zr_m_xm: 1096 mediaop(o, op, t[3], z); 1097 asmand(&p->to, reg[p->from.type]); 1098 break; 1099 1100 case Zr_m_i_xm: 1101 mediaop(o, op, t[3], z); 1102 asmand(&p->to, reg[p->from.type]); 1103 *andptr++ = p->from.offset; 1104 break; 1105 1106 case Zo_m: 1107 *andptr++ = op; 1108 asmand(&p->to, o->op[z+1]); 1109 break; 1110 1111 case Zm_ibo: 1112 *andptr++ = op; 1113 asmand(&p->from, o->op[z+1]); 1114 *andptr++ = vaddr(&p->to, nil); 1115 break; 1116 1117 case Zibo_m: 1118 *andptr++ = op; 1119 asmand(&p->to, o->op[z+1]); 1120 *andptr++ = vaddr(&p->from, nil); 1121 break; 1122 1123 case Z_ib: 1124 case Zib_: 1125 if(t[2] == Zib_) 1126 a = &p->from; 1127 else 1128 a = &p->to; 1129 v = vaddr(a, nil); 1130 *andptr++ = op; 1131 *andptr++ = v; 1132 break; 1133 1134 case Zib_rp: 1135 *andptr++ = op + reg[p->to.type]; 1136 *andptr++ = vaddr(&p->from, nil); 1137 break; 1138 1139 case Zil_rp: 1140 *andptr++ = op + reg[p->to.type]; 1141 if(o->prefix == Pe) { 1142 v = vaddr(&p->from, nil); 1143 *andptr++ = v; 1144 *andptr++ = v>>8; 1145 } 1146 else 1147 relput4(p, &p->from); 1148 break; 1149 1150 case Zib_rr: 1151 *andptr++ = op; 1152 asmand(&p->to, reg[p->to.type]); 1153 *andptr++ = vaddr(&p->from, nil); 1154 break; 1155 1156 case Z_il: 1157 case Zil_: 1158 if(t[2] == Zil_) 1159 a = &p->from; 1160 else 1161 a = &p->to; 1162 *andptr++ = op; 1163 if(o->prefix == Pe) { 1164 v = vaddr(a, nil); 1165 *andptr++ = v; 1166 *andptr++ = v>>8; 1167 } 1168 else 1169 relput4(p, a); 1170 break; 1171 1172 case Zm_ilo: 1173 case Zilo_m: 1174 *andptr++ = op; 1175 if(t[2] == Zilo_m) { 1176 a = &p->from; 1177 asmand(&p->to, o->op[z+1]); 1178 } else { 1179 a = &p->to; 1180 asmand(&p->from, o->op[z+1]); 1181 } 1182 if(o->prefix == Pe) { 1183 v = vaddr(a, nil); 1184 *andptr++ = v; 1185 *andptr++ = v>>8; 1186 } 1187 else 1188 relput4(p, a); 1189 break; 1190 1191 case Zil_rr: 1192 *andptr++ = op; 1193 asmand(&p->to, reg[p->to.type]); 1194 if(o->prefix == Pe) { 1195 v = vaddr(&p->from, nil); 1196 *andptr++ = v; 1197 *andptr++ = v>>8; 1198 } 1199 else 1200 relput4(p, &p->from); 1201 break; 1202 1203 case Z_rp: 1204 *andptr++ = op + reg[p->to.type]; 1205 break; 1206 1207 case Zrp_: 1208 *andptr++ = op + reg[p->from.type]; 1209 break; 1210 1211 case Zclr: 1212 *andptr++ = op; 1213 asmand(&p->to, reg[p->to.type]); 1214 break; 1215 1216 case Zcall: 1217 q = p->pcond; 1218 if(q == nil) { 1219 diag("call without target"); 1220 errorexit(); 1221 } 1222 if(q->as != ATEXT) { 1223 // Could handle this case by making D_PCREL 1224 // record the Prog* instead of the Sym*, but let's 1225 // wait until the need arises. 1226 diag("call of non-TEXT %P", q); 1227 errorexit(); 1228 } 1229 *andptr++ = op; 1230 r = addrel(cursym); 1231 r->off = p->pc + andptr - and; 1232 r->type = D_PCREL; 1233 r->siz = 4; 1234 r->sym = q->from.sym; 1235 put4(0); 1236 break; 1237 1238 case Zbr: 1239 case Zjmp: 1240 case Zloop: 1241 q = p->pcond; 1242 if(q == nil) { 1243 diag("jmp/branch/loop without target"); 1244 errorexit(); 1245 } 1246 if(q->as == ATEXT) { 1247 // jump out of function 1248 if(t[2] == Zbr) { 1249 diag("branch to ATEXT"); 1250 errorexit(); 1251 } 1252 *andptr++ = o->op[z+1]; 1253 r = addrel(cursym); 1254 r->off = p->pc + andptr - and; 1255 r->sym = q->from.sym; 1256 r->type = D_PCREL; 1257 r->siz = 4; 1258 put4(0); 1259 break; 1260 } 1261 1262 // Assumes q is in this function. 1263 // TODO: Check in input, preserve in brchain. 1264 1265 // Fill in backward jump now. 1266 if(p->back & 1) { 1267 v = q->pc - (p->pc + 2); 1268 if(v >= -128) { 1269 if(p->as == AJCXZW) 1270 *andptr++ = 0x67; 1271 *andptr++ = op; 1272 *andptr++ = v; 1273 } else if(t[2] == Zloop) { 1274 diag("loop too far: %P", p); 1275 } else { 1276 v -= 5-2; 1277 if(t[2] == Zbr) { 1278 *andptr++ = 0x0f; 1279 v--; 1280 } 1281 *andptr++ = o->op[z+1]; 1282 *andptr++ = v; 1283 *andptr++ = v>>8; 1284 *andptr++ = v>>16; 1285 *andptr++ = v>>24; 1286 } 1287 break; 1288 } 1289 1290 // Annotate target; will fill in later. 1291 p->forwd = q->comefrom; 1292 q->comefrom = p; 1293 if(p->back & 2) { // short 1294 if(p->as == AJCXZW) 1295 *andptr++ = 0x67; 1296 *andptr++ = op; 1297 *andptr++ = 0; 1298 } else if(t[2] == Zloop) { 1299 diag("loop too far: %P", p); 1300 } else { 1301 if(t[2] == Zbr) 1302 *andptr++ = 0x0f; 1303 *andptr++ = o->op[z+1]; 1304 *andptr++ = 0; 1305 *andptr++ = 0; 1306 *andptr++ = 0; 1307 *andptr++ = 0; 1308 } 1309 break; 1310 1311 case Zcallcon: 1312 case Zjmpcon: 1313 if(t[2] == Zcallcon) 1314 *andptr++ = op; 1315 else 1316 *andptr++ = o->op[z+1]; 1317 r = addrel(cursym); 1318 r->off = p->pc + andptr - and; 1319 r->type = D_PCREL; 1320 r->siz = 4; 1321 r->add = p->to.offset; 1322 put4(0); 1323 break; 1324 1325 case Zcallind: 1326 *andptr++ = op; 1327 *andptr++ = o->op[z+1]; 1328 r = addrel(cursym); 1329 r->off = p->pc + andptr - and; 1330 r->type = D_ADDR; 1331 r->siz = 4; 1332 r->add = p->to.offset; 1333 r->sym = p->to.sym; 1334 put4(0); 1335 break; 1336 1337 case Zbyte: 1338 v = vaddr(&p->from, &rel); 1339 if(rel.siz != 0) { 1340 rel.siz = op; 1341 r = addrel(cursym); 1342 *r = rel; 1343 r->off = p->pc + andptr - and; 1344 } 1345 *andptr++ = v; 1346 if(op > 1) { 1347 *andptr++ = v>>8; 1348 if(op > 2) { 1349 *andptr++ = v>>16; 1350 *andptr++ = v>>24; 1351 } 1352 } 1353 break; 1354 1355 case Zmov: 1356 goto domov; 1357 } 1358 return; 1359 1360 domov: 1361 for(t=ymovtab; *t; t+=8) 1362 if(p->as == t[0]) 1363 if(ycover[ft+t[1]]) 1364 if(ycover[tt+t[2]]) 1365 goto mfound; 1366 bad: 1367 /* 1368 * here, the assembly has failed. 1369 * if its a byte instruction that has 1370 * unaddressable registers, try to 1371 * exchange registers and reissue the 1372 * instruction with the operands renamed. 1373 */ 1374 pp = *p; 1375 z = p->from.type; 1376 if(z >= D_BP && z <= D_DI) { 1377 if((breg = byteswapreg(&p->to)) != D_AX) { 1378 *andptr++ = 0x87; /* xchg lhs,bx */ 1379 asmand(&p->from, reg[breg]); 1380 subreg(&pp, z, breg); 1381 doasm(&pp); 1382 *andptr++ = 0x87; /* xchg lhs,bx */ 1383 asmand(&p->from, reg[breg]); 1384 } else { 1385 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1386 subreg(&pp, z, D_AX); 1387 doasm(&pp); 1388 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1389 } 1390 return; 1391 } 1392 z = p->to.type; 1393 if(z >= D_BP && z <= D_DI) { 1394 if((breg = byteswapreg(&p->from)) != D_AX) { 1395 *andptr++ = 0x87; /* xchg rhs,bx */ 1396 asmand(&p->to, reg[breg]); 1397 subreg(&pp, z, breg); 1398 doasm(&pp); 1399 *andptr++ = 0x87; /* xchg rhs,bx */ 1400 asmand(&p->to, reg[breg]); 1401 } else { 1402 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1403 subreg(&pp, z, D_AX); 1404 doasm(&pp); 1405 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1406 } 1407 return; 1408 } 1409 diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p); 1410 return; 1411 1412 mfound: 1413 switch(t[3]) { 1414 default: 1415 diag("asmins: unknown mov %d %P", t[3], p); 1416 break; 1417 1418 case 0: /* lit */ 1419 for(z=4; t[z]!=E; z++) 1420 *andptr++ = t[z]; 1421 break; 1422 1423 case 1: /* r,m */ 1424 *andptr++ = t[4]; 1425 asmand(&p->to, t[5]); 1426 break; 1427 1428 case 2: /* m,r */ 1429 *andptr++ = t[4]; 1430 asmand(&p->from, t[5]); 1431 break; 1432 1433 case 3: /* r,m - 2op */ 1434 *andptr++ = t[4]; 1435 *andptr++ = t[5]; 1436 asmand(&p->to, t[6]); 1437 break; 1438 1439 case 4: /* m,r - 2op */ 1440 *andptr++ = t[4]; 1441 *andptr++ = t[5]; 1442 asmand(&p->from, t[6]); 1443 break; 1444 1445 case 5: /* load full pointer, trash heap */ 1446 if(t[4]) 1447 *andptr++ = t[4]; 1448 switch(p->to.index) { 1449 default: 1450 goto bad; 1451 case D_DS: 1452 *andptr++ = 0xc5; 1453 break; 1454 case D_SS: 1455 *andptr++ = 0x0f; 1456 *andptr++ = 0xb2; 1457 break; 1458 case D_ES: 1459 *andptr++ = 0xc4; 1460 break; 1461 case D_FS: 1462 *andptr++ = 0x0f; 1463 *andptr++ = 0xb4; 1464 break; 1465 case D_GS: 1466 *andptr++ = 0x0f; 1467 *andptr++ = 0xb5; 1468 break; 1469 } 1470 asmand(&p->from, reg[p->to.type]); 1471 break; 1472 1473 case 6: /* double shift */ 1474 z = p->from.type; 1475 switch(z) { 1476 default: 1477 goto bad; 1478 case D_CONST: 1479 *andptr++ = 0x0f; 1480 *andptr++ = t[4]; 1481 asmand(&p->to, reg[p->from.index]); 1482 *andptr++ = p->from.offset; 1483 break; 1484 case D_CL: 1485 case D_CX: 1486 *andptr++ = 0x0f; 1487 *andptr++ = t[5]; 1488 asmand(&p->to, reg[p->from.index]); 1489 break; 1490 } 1491 break; 1492 1493 case 7: /* imul rm,r */ 1494 if(t[4] == Pq) { 1495 *andptr++ = Pe; 1496 *andptr++ = Pm; 1497 } else 1498 *andptr++ = t[4]; 1499 *andptr++ = t[5]; 1500 asmand(&p->from, reg[p->to.type]); 1501 break; 1502 } 1503 } 1504 1505 void 1506 asmins(Prog *p) 1507 { 1508 andptr = and; 1509 doasm(p); 1510 if(andptr > and+sizeof and) { 1511 print("and[] is too short - %ld byte instruction\n", andptr - and); 1512 errorexit(); 1513 } 1514 }