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