github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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 = a->offset-tlsoffset; 699 r->xadd = r->add; 700 r->siz = 4; 701 r->type = D_TLS; 702 s = lookup("runtime.tlsgm", 0); 703 r->sym = s; 704 r->xsym = s; 705 v = 0; 706 } 707 708 put4(v); 709 return; 710 711 bad: 712 diag("asmand: bad address %D", a); 713 return; 714 } 715 716 #define E 0xff 717 uchar ymovtab[] = 718 { 719 /* push */ 720 APUSHL, Ycs, Ynone, 0, 0x0e,E,0,0, 721 APUSHL, Yss, Ynone, 0, 0x16,E,0,0, 722 APUSHL, Yds, Ynone, 0, 0x1e,E,0,0, 723 APUSHL, Yes, Ynone, 0, 0x06,E,0,0, 724 APUSHL, Yfs, Ynone, 0, 0x0f,0xa0,E,0, 725 APUSHL, Ygs, Ynone, 0, 0x0f,0xa8,E,0, 726 727 APUSHW, Ycs, Ynone, 0, Pe,0x0e,E,0, 728 APUSHW, Yss, Ynone, 0, Pe,0x16,E,0, 729 APUSHW, Yds, Ynone, 0, Pe,0x1e,E,0, 730 APUSHW, Yes, Ynone, 0, Pe,0x06,E,0, 731 APUSHW, Yfs, Ynone, 0, Pe,0x0f,0xa0,E, 732 APUSHW, Ygs, Ynone, 0, Pe,0x0f,0xa8,E, 733 734 /* pop */ 735 APOPL, Ynone, Yds, 0, 0x1f,E,0,0, 736 APOPL, Ynone, Yes, 0, 0x07,E,0,0, 737 APOPL, Ynone, Yss, 0, 0x17,E,0,0, 738 APOPL, Ynone, Yfs, 0, 0x0f,0xa1,E,0, 739 APOPL, Ynone, Ygs, 0, 0x0f,0xa9,E,0, 740 741 APOPW, Ynone, Yds, 0, Pe,0x1f,E,0, 742 APOPW, Ynone, Yes, 0, Pe,0x07,E,0, 743 APOPW, Ynone, Yss, 0, Pe,0x17,E,0, 744 APOPW, Ynone, Yfs, 0, Pe,0x0f,0xa1,E, 745 APOPW, Ynone, Ygs, 0, Pe,0x0f,0xa9,E, 746 747 /* mov seg */ 748 AMOVW, Yes, Yml, 1, 0x8c,0,0,0, 749 AMOVW, Ycs, Yml, 1, 0x8c,1,0,0, 750 AMOVW, Yss, Yml, 1, 0x8c,2,0,0, 751 AMOVW, Yds, Yml, 1, 0x8c,3,0,0, 752 AMOVW, Yfs, Yml, 1, 0x8c,4,0,0, 753 AMOVW, Ygs, Yml, 1, 0x8c,5,0,0, 754 755 AMOVW, Yml, Yes, 2, 0x8e,0,0,0, 756 AMOVW, Yml, Ycs, 2, 0x8e,1,0,0, 757 AMOVW, Yml, Yss, 2, 0x8e,2,0,0, 758 AMOVW, Yml, Yds, 2, 0x8e,3,0,0, 759 AMOVW, Yml, Yfs, 2, 0x8e,4,0,0, 760 AMOVW, Yml, Ygs, 2, 0x8e,5,0,0, 761 762 /* mov cr */ 763 AMOVL, Ycr0, Yml, 3, 0x0f,0x20,0,0, 764 AMOVL, Ycr2, Yml, 3, 0x0f,0x20,2,0, 765 AMOVL, Ycr3, Yml, 3, 0x0f,0x20,3,0, 766 AMOVL, Ycr4, Yml, 3, 0x0f,0x20,4,0, 767 768 AMOVL, Yml, Ycr0, 4, 0x0f,0x22,0,0, 769 AMOVL, Yml, Ycr2, 4, 0x0f,0x22,2,0, 770 AMOVL, Yml, Ycr3, 4, 0x0f,0x22,3,0, 771 AMOVL, Yml, Ycr4, 4, 0x0f,0x22,4,0, 772 773 /* mov dr */ 774 AMOVL, Ydr0, Yml, 3, 0x0f,0x21,0,0, 775 AMOVL, Ydr6, Yml, 3, 0x0f,0x21,6,0, 776 AMOVL, Ydr7, Yml, 3, 0x0f,0x21,7,0, 777 778 AMOVL, Yml, Ydr0, 4, 0x0f,0x23,0,0, 779 AMOVL, Yml, Ydr6, 4, 0x0f,0x23,6,0, 780 AMOVL, Yml, Ydr7, 4, 0x0f,0x23,7,0, 781 782 /* mov tr */ 783 AMOVL, Ytr6, Yml, 3, 0x0f,0x24,6,0, 784 AMOVL, Ytr7, Yml, 3, 0x0f,0x24,7,0, 785 786 AMOVL, Yml, Ytr6, 4, 0x0f,0x26,6,E, 787 AMOVL, Yml, Ytr7, 4, 0x0f,0x26,7,E, 788 789 /* lgdt, sgdt, lidt, sidt */ 790 AMOVL, Ym, Ygdtr, 4, 0x0f,0x01,2,0, 791 AMOVL, Ygdtr, Ym, 3, 0x0f,0x01,0,0, 792 AMOVL, Ym, Yidtr, 4, 0x0f,0x01,3,0, 793 AMOVL, Yidtr, Ym, 3, 0x0f,0x01,1,0, 794 795 /* lldt, sldt */ 796 AMOVW, Yml, Yldtr, 4, 0x0f,0x00,2,0, 797 AMOVW, Yldtr, Yml, 3, 0x0f,0x00,0,0, 798 799 /* lmsw, smsw */ 800 AMOVW, Yml, Ymsw, 4, 0x0f,0x01,6,0, 801 AMOVW, Ymsw, Yml, 3, 0x0f,0x01,4,0, 802 803 /* ltr, str */ 804 AMOVW, Yml, Ytask, 4, 0x0f,0x00,3,0, 805 AMOVW, Ytask, Yml, 3, 0x0f,0x00,1,0, 806 807 /* load full pointer */ 808 AMOVL, Yml, Ycol, 5, 0,0,0,0, 809 AMOVW, Yml, Ycol, 5, Pe,0,0,0, 810 811 /* double shift */ 812 ASHLL, Ycol, Yml, 6, 0xa4,0xa5,0,0, 813 ASHRL, Ycol, Yml, 6, 0xac,0xad,0,0, 814 815 /* extra imul */ 816 AIMULW, Yml, Yrl, 7, Pq,0xaf,0,0, 817 AIMULL, Yml, Yrl, 7, Pm,0xaf,0,0, 818 0 819 }; 820 821 // byteswapreg returns a byte-addressable register (AX, BX, CX, DX) 822 // which is not referenced in a->type. 823 // If a is empty, it returns BX to account for MULB-like instructions 824 // that might use DX and AX. 825 int 826 byteswapreg(Adr *a) 827 { 828 int cana, canb, canc, cand; 829 830 cana = canb = canc = cand = 1; 831 832 switch(a->type) { 833 case D_NONE: 834 cana = cand = 0; 835 break; 836 case D_AX: 837 case D_AL: 838 case D_AH: 839 case D_INDIR+D_AX: 840 cana = 0; 841 break; 842 case D_BX: 843 case D_BL: 844 case D_BH: 845 case D_INDIR+D_BX: 846 canb = 0; 847 break; 848 case D_CX: 849 case D_CL: 850 case D_CH: 851 case D_INDIR+D_CX: 852 canc = 0; 853 break; 854 case D_DX: 855 case D_DL: 856 case D_DH: 857 case D_INDIR+D_DX: 858 cand = 0; 859 break; 860 } 861 switch(a->index) { 862 case D_AX: 863 cana = 0; 864 break; 865 case D_BX: 866 canb = 0; 867 break; 868 case D_CX: 869 canc = 0; 870 break; 871 case D_DX: 872 cand = 0; 873 break; 874 } 875 if(cana) 876 return D_AX; 877 if(canb) 878 return D_BX; 879 if(canc) 880 return D_CX; 881 if(cand) 882 return D_DX; 883 884 diag("impossible byte register"); 885 errorexit(); 886 return 0; 887 } 888 889 void 890 subreg(Prog *p, int from, int to) 891 { 892 893 if(debug['Q']) 894 print("\n%P s/%R/%R/\n", p, from, to); 895 896 if(p->from.type == from) { 897 p->from.type = to; 898 p->ft = 0; 899 } 900 if(p->to.type == from) { 901 p->to.type = to; 902 p->tt = 0; 903 } 904 905 if(p->from.index == from) { 906 p->from.index = to; 907 p->ft = 0; 908 } 909 if(p->to.index == from) { 910 p->to.index = to; 911 p->tt = 0; 912 } 913 914 from += D_INDIR; 915 if(p->from.type == from) { 916 p->from.type = to+D_INDIR; 917 p->ft = 0; 918 } 919 if(p->to.type == from) { 920 p->to.type = to+D_INDIR; 921 p->tt = 0; 922 } 923 924 if(debug['Q']) 925 print("%P\n", p); 926 } 927 928 static int 929 mediaop(Optab *o, int op, int osize, int z) 930 { 931 switch(op){ 932 case Pm: 933 case Pe: 934 case Pf2: 935 case Pf3: 936 if(osize != 1){ 937 if(op != Pm) 938 *andptr++ = op; 939 *andptr++ = Pm; 940 op = o->op[++z]; 941 break; 942 } 943 default: 944 if(andptr == and || andptr[-1] != Pm) 945 *andptr++ = Pm; 946 break; 947 } 948 *andptr++ = op; 949 return z; 950 } 951 952 void 953 doasm(Prog *p) 954 { 955 Optab *o; 956 Prog *q, pp; 957 uchar *t; 958 int z, op, ft, tt, breg; 959 int32 v, pre; 960 Reloc rel, *r; 961 Adr *a; 962 963 curp = p; // TODO 964 965 pre = prefixof(&p->from); 966 if(pre) 967 *andptr++ = pre; 968 pre = prefixof(&p->to); 969 if(pre) 970 *andptr++ = pre; 971 972 if(p->ft == 0) 973 p->ft = oclass(&p->from); 974 if(p->tt == 0) 975 p->tt = oclass(&p->to); 976 977 ft = p->ft * Ymax; 978 tt = p->tt * Ymax; 979 o = &optab[p->as]; 980 t = o->ytab; 981 if(t == 0) { 982 diag("asmins: noproto %P", p); 983 return; 984 } 985 for(z=0; *t; z+=t[3],t+=4) 986 if(ycover[ft+t[0]]) 987 if(ycover[tt+t[1]]) 988 goto found; 989 goto domov; 990 991 found: 992 switch(o->prefix) { 993 case Pq: /* 16 bit escape and opcode escape */ 994 *andptr++ = Pe; 995 *andptr++ = Pm; 996 break; 997 998 case Pf2: /* xmm opcode escape */ 999 case Pf3: 1000 *andptr++ = o->prefix; 1001 *andptr++ = Pm; 1002 break; 1003 1004 case Pm: /* opcode escape */ 1005 *andptr++ = Pm; 1006 break; 1007 1008 case Pe: /* 16 bit escape */ 1009 *andptr++ = Pe; 1010 break; 1011 1012 case Pb: /* botch */ 1013 break; 1014 } 1015 1016 op = o->op[z]; 1017 switch(t[2]) { 1018 default: 1019 diag("asmins: unknown z %d %P", t[2], p); 1020 return; 1021 1022 case Zpseudo: 1023 break; 1024 1025 case Zlit: 1026 for(; op = o->op[z]; z++) 1027 *andptr++ = op; 1028 break; 1029 1030 case Zlitm_r: 1031 for(; op = o->op[z]; z++) 1032 *andptr++ = op; 1033 asmand(&p->from, reg[p->to.type]); 1034 break; 1035 1036 case Zm_r: 1037 *andptr++ = op; 1038 asmand(&p->from, reg[p->to.type]); 1039 break; 1040 1041 case Zm2_r: 1042 *andptr++ = op; 1043 *andptr++ = o->op[z+1]; 1044 asmand(&p->from, reg[p->to.type]); 1045 break; 1046 1047 case Zm_r_xm: 1048 mediaop(o, op, t[3], z); 1049 asmand(&p->from, reg[p->to.type]); 1050 break; 1051 1052 case Zm_r_i_xm: 1053 mediaop(o, op, t[3], z); 1054 asmand(&p->from, reg[p->to.type]); 1055 *andptr++ = p->to.offset; 1056 break; 1057 1058 case Zibm_r: 1059 while ((op = o->op[z++]) != 0) 1060 *andptr++ = op; 1061 asmand(&p->from, reg[p->to.type]); 1062 *andptr++ = p->to.offset; 1063 break; 1064 1065 case Zaut_r: 1066 *andptr++ = 0x8d; /* leal */ 1067 if(p->from.type != D_ADDR) 1068 diag("asmins: Zaut sb type ADDR"); 1069 p->from.type = p->from.index; 1070 p->from.index = D_NONE; 1071 p->ft = 0; 1072 asmand(&p->from, reg[p->to.type]); 1073 p->from.index = p->from.type; 1074 p->from.type = D_ADDR; 1075 p->ft = 0; 1076 break; 1077 1078 case Zm_o: 1079 *andptr++ = op; 1080 asmand(&p->from, o->op[z+1]); 1081 break; 1082 1083 case Zr_m: 1084 *andptr++ = op; 1085 asmand(&p->to, reg[p->from.type]); 1086 break; 1087 1088 case Zr_m_xm: 1089 mediaop(o, op, t[3], z); 1090 asmand(&p->to, reg[p->from.type]); 1091 break; 1092 1093 case Zr_m_i_xm: 1094 mediaop(o, op, t[3], z); 1095 asmand(&p->to, reg[p->from.type]); 1096 *andptr++ = p->from.offset; 1097 break; 1098 1099 case Zo_m: 1100 *andptr++ = op; 1101 asmand(&p->to, o->op[z+1]); 1102 break; 1103 1104 case Zm_ibo: 1105 *andptr++ = op; 1106 asmand(&p->from, o->op[z+1]); 1107 *andptr++ = vaddr(&p->to, nil); 1108 break; 1109 1110 case Zibo_m: 1111 *andptr++ = op; 1112 asmand(&p->to, o->op[z+1]); 1113 *andptr++ = vaddr(&p->from, nil); 1114 break; 1115 1116 case Z_ib: 1117 case Zib_: 1118 if(t[2] == Zib_) 1119 a = &p->from; 1120 else 1121 a = &p->to; 1122 v = vaddr(a, nil); 1123 *andptr++ = op; 1124 *andptr++ = v; 1125 break; 1126 1127 case Zib_rp: 1128 *andptr++ = op + reg[p->to.type]; 1129 *andptr++ = vaddr(&p->from, nil); 1130 break; 1131 1132 case Zil_rp: 1133 *andptr++ = op + reg[p->to.type]; 1134 if(o->prefix == Pe) { 1135 v = vaddr(&p->from, nil); 1136 *andptr++ = v; 1137 *andptr++ = v>>8; 1138 } 1139 else 1140 relput4(p, &p->from); 1141 break; 1142 1143 case Zib_rr: 1144 *andptr++ = op; 1145 asmand(&p->to, reg[p->to.type]); 1146 *andptr++ = vaddr(&p->from, nil); 1147 break; 1148 1149 case Z_il: 1150 case Zil_: 1151 if(t[2] == Zil_) 1152 a = &p->from; 1153 else 1154 a = &p->to; 1155 *andptr++ = op; 1156 if(o->prefix == Pe) { 1157 v = vaddr(a, nil); 1158 *andptr++ = v; 1159 *andptr++ = v>>8; 1160 } 1161 else 1162 relput4(p, a); 1163 break; 1164 1165 case Zm_ilo: 1166 case Zilo_m: 1167 *andptr++ = op; 1168 if(t[2] == Zilo_m) { 1169 a = &p->from; 1170 asmand(&p->to, o->op[z+1]); 1171 } else { 1172 a = &p->to; 1173 asmand(&p->from, o->op[z+1]); 1174 } 1175 if(o->prefix == Pe) { 1176 v = vaddr(a, nil); 1177 *andptr++ = v; 1178 *andptr++ = v>>8; 1179 } 1180 else 1181 relput4(p, a); 1182 break; 1183 1184 case Zil_rr: 1185 *andptr++ = op; 1186 asmand(&p->to, reg[p->to.type]); 1187 if(o->prefix == Pe) { 1188 v = vaddr(&p->from, nil); 1189 *andptr++ = v; 1190 *andptr++ = v>>8; 1191 } 1192 else 1193 relput4(p, &p->from); 1194 break; 1195 1196 case Z_rp: 1197 *andptr++ = op + reg[p->to.type]; 1198 break; 1199 1200 case Zrp_: 1201 *andptr++ = op + reg[p->from.type]; 1202 break; 1203 1204 case Zclr: 1205 *andptr++ = op; 1206 asmand(&p->to, reg[p->to.type]); 1207 break; 1208 1209 case Zcall: 1210 q = p->pcond; 1211 if(q == nil) { 1212 diag("call without target"); 1213 errorexit(); 1214 } 1215 if(q->as != ATEXT) { 1216 // Could handle this case by making D_PCREL 1217 // record the Prog* instead of the Sym*, but let's 1218 // wait until the need arises. 1219 diag("call of non-TEXT %P", q); 1220 errorexit(); 1221 } 1222 *andptr++ = op; 1223 r = addrel(cursym); 1224 r->off = p->pc + andptr - and; 1225 r->type = D_PCREL; 1226 r->siz = 4; 1227 r->sym = q->from.sym; 1228 put4(0); 1229 break; 1230 1231 case Zbr: 1232 case Zjmp: 1233 case Zloop: 1234 q = p->pcond; 1235 if(q == nil) { 1236 diag("jmp/branch/loop without target"); 1237 errorexit(); 1238 } 1239 if(q->as == ATEXT) { 1240 // jump out of function 1241 if(t[2] == Zbr) { 1242 diag("branch to ATEXT"); 1243 errorexit(); 1244 } 1245 *andptr++ = o->op[z+1]; 1246 r = addrel(cursym); 1247 r->off = p->pc + andptr - and; 1248 r->sym = q->from.sym; 1249 r->type = D_PCREL; 1250 r->siz = 4; 1251 put4(0); 1252 break; 1253 } 1254 1255 // Assumes q is in this function. 1256 // TODO: Check in input, preserve in brchain. 1257 1258 // Fill in backward jump now. 1259 if(p->back & 1) { 1260 v = q->pc - (p->pc + 2); 1261 if(v >= -128) { 1262 if(p->as == AJCXZW) 1263 *andptr++ = 0x67; 1264 *andptr++ = op; 1265 *andptr++ = v; 1266 } else if(t[2] == Zloop) { 1267 diag("loop too far: %P", p); 1268 } else { 1269 v -= 5-2; 1270 if(t[2] == Zbr) { 1271 *andptr++ = 0x0f; 1272 v--; 1273 } 1274 *andptr++ = o->op[z+1]; 1275 *andptr++ = v; 1276 *andptr++ = v>>8; 1277 *andptr++ = v>>16; 1278 *andptr++ = v>>24; 1279 } 1280 break; 1281 } 1282 1283 // Annotate target; will fill in later. 1284 p->forwd = q->comefrom; 1285 q->comefrom = p; 1286 if(p->back & 2) { // short 1287 if(p->as == AJCXZW) 1288 *andptr++ = 0x67; 1289 *andptr++ = op; 1290 *andptr++ = 0; 1291 } else if(t[2] == Zloop) { 1292 diag("loop too far: %P", p); 1293 } else { 1294 if(t[2] == Zbr) 1295 *andptr++ = 0x0f; 1296 *andptr++ = o->op[z+1]; 1297 *andptr++ = 0; 1298 *andptr++ = 0; 1299 *andptr++ = 0; 1300 *andptr++ = 0; 1301 } 1302 break; 1303 1304 case Zcallcon: 1305 case Zjmpcon: 1306 if(t[2] == Zcallcon) 1307 *andptr++ = op; 1308 else 1309 *andptr++ = o->op[z+1]; 1310 r = addrel(cursym); 1311 r->off = p->pc + andptr - and; 1312 r->type = D_PCREL; 1313 r->siz = 4; 1314 r->add = p->to.offset; 1315 put4(0); 1316 break; 1317 1318 case Zcallind: 1319 *andptr++ = op; 1320 *andptr++ = o->op[z+1]; 1321 r = addrel(cursym); 1322 r->off = p->pc + andptr - and; 1323 r->type = D_ADDR; 1324 r->siz = 4; 1325 r->add = p->to.offset; 1326 r->sym = p->to.sym; 1327 put4(0); 1328 break; 1329 1330 case Zbyte: 1331 v = vaddr(&p->from, &rel); 1332 if(rel.siz != 0) { 1333 rel.siz = op; 1334 r = addrel(cursym); 1335 *r = rel; 1336 r->off = p->pc + andptr - and; 1337 } 1338 *andptr++ = v; 1339 if(op > 1) { 1340 *andptr++ = v>>8; 1341 if(op > 2) { 1342 *andptr++ = v>>16; 1343 *andptr++ = v>>24; 1344 } 1345 } 1346 break; 1347 1348 case Zmov: 1349 goto domov; 1350 } 1351 return; 1352 1353 domov: 1354 for(t=ymovtab; *t; t+=8) 1355 if(p->as == t[0]) 1356 if(ycover[ft+t[1]]) 1357 if(ycover[tt+t[2]]) 1358 goto mfound; 1359 bad: 1360 /* 1361 * here, the assembly has failed. 1362 * if its a byte instruction that has 1363 * unaddressable registers, try to 1364 * exchange registers and reissue the 1365 * instruction with the operands renamed. 1366 */ 1367 pp = *p; 1368 z = p->from.type; 1369 if(z >= D_BP && z <= D_DI) { 1370 if((breg = byteswapreg(&p->to)) != D_AX) { 1371 *andptr++ = 0x87; /* xchg lhs,bx */ 1372 asmand(&p->from, reg[breg]); 1373 subreg(&pp, z, breg); 1374 doasm(&pp); 1375 *andptr++ = 0x87; /* xchg lhs,bx */ 1376 asmand(&p->from, reg[breg]); 1377 } else { 1378 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1379 subreg(&pp, z, D_AX); 1380 doasm(&pp); 1381 *andptr++ = 0x90 + reg[z]; /* xchg lsh,ax */ 1382 } 1383 return; 1384 } 1385 z = p->to.type; 1386 if(z >= D_BP && z <= D_DI) { 1387 if((breg = byteswapreg(&p->from)) != D_AX) { 1388 *andptr++ = 0x87; /* xchg rhs,bx */ 1389 asmand(&p->to, reg[breg]); 1390 subreg(&pp, z, breg); 1391 doasm(&pp); 1392 *andptr++ = 0x87; /* xchg rhs,bx */ 1393 asmand(&p->to, reg[breg]); 1394 } else { 1395 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1396 subreg(&pp, z, D_AX); 1397 doasm(&pp); 1398 *andptr++ = 0x90 + reg[z]; /* xchg rsh,ax */ 1399 } 1400 return; 1401 } 1402 diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p); 1403 return; 1404 1405 mfound: 1406 switch(t[3]) { 1407 default: 1408 diag("asmins: unknown mov %d %P", t[3], p); 1409 break; 1410 1411 case 0: /* lit */ 1412 for(z=4; t[z]!=E; z++) 1413 *andptr++ = t[z]; 1414 break; 1415 1416 case 1: /* r,m */ 1417 *andptr++ = t[4]; 1418 asmand(&p->to, t[5]); 1419 break; 1420 1421 case 2: /* m,r */ 1422 *andptr++ = t[4]; 1423 asmand(&p->from, t[5]); 1424 break; 1425 1426 case 3: /* r,m - 2op */ 1427 *andptr++ = t[4]; 1428 *andptr++ = t[5]; 1429 asmand(&p->to, t[6]); 1430 break; 1431 1432 case 4: /* m,r - 2op */ 1433 *andptr++ = t[4]; 1434 *andptr++ = t[5]; 1435 asmand(&p->from, t[6]); 1436 break; 1437 1438 case 5: /* load full pointer, trash heap */ 1439 if(t[4]) 1440 *andptr++ = t[4]; 1441 switch(p->to.index) { 1442 default: 1443 goto bad; 1444 case D_DS: 1445 *andptr++ = 0xc5; 1446 break; 1447 case D_SS: 1448 *andptr++ = 0x0f; 1449 *andptr++ = 0xb2; 1450 break; 1451 case D_ES: 1452 *andptr++ = 0xc4; 1453 break; 1454 case D_FS: 1455 *andptr++ = 0x0f; 1456 *andptr++ = 0xb4; 1457 break; 1458 case D_GS: 1459 *andptr++ = 0x0f; 1460 *andptr++ = 0xb5; 1461 break; 1462 } 1463 asmand(&p->from, reg[p->to.type]); 1464 break; 1465 1466 case 6: /* double shift */ 1467 z = p->from.type; 1468 switch(z) { 1469 default: 1470 goto bad; 1471 case D_CONST: 1472 *andptr++ = 0x0f; 1473 *andptr++ = t[4]; 1474 asmand(&p->to, reg[p->from.index]); 1475 *andptr++ = p->from.offset; 1476 break; 1477 case D_CL: 1478 case D_CX: 1479 *andptr++ = 0x0f; 1480 *andptr++ = t[5]; 1481 asmand(&p->to, reg[p->from.index]); 1482 break; 1483 } 1484 break; 1485 1486 case 7: /* imul rm,r */ 1487 if(t[4] == Pq) { 1488 *andptr++ = Pe; 1489 *andptr++ = Pm; 1490 } else 1491 *andptr++ = t[4]; 1492 *andptr++ = t[5]; 1493 asmand(&p->from, reg[p->to.type]); 1494 break; 1495 } 1496 } 1497 1498 void 1499 asmins(Prog *p) 1500 { 1501 andptr = and; 1502 doasm(p); 1503 if(andptr > and+sizeof and) { 1504 print("and[] is too short - %ld byte instruction\n", andptr - and); 1505 errorexit(); 1506 } 1507 }