1 #include "lib9.h" 2 #include "isa.h" 3 #include "interp.h" 4 #include "raise.h" 5 6 #define DOT ((ulong)code) 7 8 #define RESCHED 1 /* check for interpreter reschedule */ 9 10 enum 11 { 12 RAX = 0, 13 RAH = 4, 14 RCX = 1, 15 RDX = 2, 16 RBX = 3, 17 RSP = 4, 18 RBP = 5, 19 RSI = 6, 20 RDI = 7, 21 22 RFP = RSI, 23 RMP = RDI, 24 RTA = RDX, 25 RTMP = RBX, 26 27 Omovzxb = 0xb6, 28 Omovzxw = 0xb7, 29 Osal = 0xd1, 30 Oaddf = 0xdc, 31 Ocall = 0xe8, 32 Ocallrm = 0xff, 33 Ocdq = 0x99, 34 Ocld = 0xfc, 35 Ocmpb = 0x38, 36 Ocmpw = 0x39, 37 Ocmpi = 0x83, 38 Odecrm = 0xff, 39 Oincr = 0x40, 40 Oincrm = 0xff, 41 Ojccl = 0x83, 42 Ojcsl = 0x82, 43 Ojeqb = 0x74, 44 Ojeql = 0x84, 45 Ojgel = 0x8d, 46 Ojgtl = 0x8f, 47 Ojhil = 0x87, 48 Ojlel = 0x8e, 49 Ojlsl = 0x86, 50 Ojltl = 0x8c, 51 Ojol = 0x80, 52 Ojnol = 0x81, 53 Ojbl = 0x82, 54 Ojael = 0x83, 55 Ojal = 0x87, 56 Ojnel = 0x85, 57 Ojbel = 0x86, 58 Ojneb = 0x75, 59 Ojgtb = 0x7f, 60 Ojgeb = 0x7d, 61 Ojleb = 0x7e, 62 Ojltb = 0x7c, 63 Ojmp = 0xe9, 64 Ojmpb = 0xeb, 65 Ojmprm = 0xff, 66 Oldb = 0x8a, 67 Olds = 0x89, 68 Oldw = 0x8b, 69 Olea = 0x8d, 70 Otestib = 0xf6, 71 Oshld = 0xa5, 72 Oshrd = 0xad, 73 Osar = 0xd3, 74 Osarimm = 0xc1, 75 Omov = 0xc7, 76 Omovf = 0xdd, 77 Omovimm = 0xb8, 78 Omovsb = 0xa4, 79 Orep = 0xf3, 80 Oret = 0xc3, 81 Oshl = 0xd3, 82 Oshr = 0xd1, 83 Ostb = 0x88, 84 Ostw = 0x89, 85 Osubf = 0xdc, 86 Oxchg = 0x87, 87 OxchgAX = 0x90, 88 Oxor = 0x31, 89 Opopl = 0x58, 90 Opushl = 0x50, 91 Opushrm = 0xff, 92 Oneg = 0xf7, 93 94 SRCOP = (1<<0), 95 DSTOP = (1<<1), 96 WRTPC = (1<<2), 97 TCHECK = (1<<3), 98 NEWPC = (1<<4), 99 DBRAN = (1<<5), 100 THREOP = (1<<6), 101 102 ANDAND = 1, 103 OROR = 2, 104 EQAND = 3, 105 106 MacFRP = 0, 107 MacRET = 1, 108 MacCASE = 2, 109 MacCOLR = 3, 110 MacMCAL = 4, 111 MacFRAM = 5, 112 MacMFRA = 6, 113 MacRELQ = 7, 114 NMACRO 115 }; 116 117 static uchar* code; 118 static uchar* base; 119 static ulong* patch; 120 static int pass; 121 static Module* mod; 122 static uchar* tinit; 123 static ulong* litpool; 124 static int nlit; 125 static void macfrp(void); 126 static void macret(void); 127 static void maccase(void); 128 static void maccolr(void); 129 static void macmcal(void); 130 static void macfram(void); 131 static void macmfra(void); 132 static void macrelq(void); 133 static ulong macro[NMACRO]; 134 void (*comvec)(void); 135 extern void das(uchar*, int); 136 137 #define T(r) *((void**)(R.r)) 138 139 struct 140 { 141 int idx; 142 void (*gen)(void); 143 } mactab[] = 144 { 145 MacFRP, macfrp, /* decrement and free pointer */ 146 MacRET, macret, /* return instruction */ 147 MacCASE, maccase, /* case instruction */ 148 MacCOLR, maccolr, /* increment and color pointer */ 149 MacMCAL, macmcal, /* mcall bottom half */ 150 MacFRAM, macfram, /* frame instruction */ 151 MacMFRA, macmfra, /* punt mframe because t->initialize==0 */ 152 MacRELQ, macrelq, /* reschedule */ 153 }; 154 155 static void 156 bounds(void) 157 { 158 error(exBounds); 159 } 160 161 static void 162 rdestroy(void) 163 { 164 destroy(R.s); 165 } 166 167 static void 168 rmcall(void) 169 { 170 Prog *p; 171 Frame *f; 172 173 if((void*)R.dt == H) 174 error(exModule); 175 176 f = (Frame*)R.FP; 177 if(f == H) 178 error(exModule); 179 180 f->mr = nil; 181 ((void(*)(Frame*))R.dt)(f); 182 R.SP = (uchar*)f; 183 R.FP = f->fp; 184 if(f->t == nil) 185 unextend(f); 186 else 187 freeptrs(f, f->t); 188 p = currun(); 189 if(p->kill != nil) 190 error(p->kill); 191 } 192 193 static void 194 rmfram(void) 195 { 196 Type *t; 197 Frame *f; 198 uchar *nsp; 199 200 t = (Type*)R.s; 201 if(t == H) 202 error(exModule); 203 204 nsp = R.SP + t->size; 205 if(nsp >= R.TS) { 206 R.s = t; 207 extend(); 208 T(d) = R.s; 209 return; 210 } 211 f = (Frame*)R.SP; 212 R.SP = nsp; 213 f->t = t; 214 f->mr = nil; 215 initmem(t, f); 216 T(d) = f; 217 } 218 219 static int 220 bc(int o) 221 { 222 if(o < 127 && o > -128) 223 return 1; 224 return 0; 225 } 226 227 static void 228 urk(void) 229 { 230 error(exCompile); 231 } 232 233 static void 234 genb(uchar o) 235 { 236 *code++ = o; 237 } 238 239 static void 240 gen2(uchar o1, uchar o2) 241 { 242 code[0] = o1; 243 code[1] = o2; 244 code += 2; 245 } 246 247 static void 248 genw(ulong o) 249 { 250 *(ulong*)code = o; 251 code += 4; 252 } 253 254 static void 255 modrm(int inst, ulong disp, int rm, int r) 256 { 257 *code++ = inst; 258 if(disp == 0) { 259 *code++ = (0<<6)|(r<<3)|rm; 260 return; 261 } 262 if(bc(disp)) { 263 code[0] = (1<<6)|(r<<3)|rm; 264 code[1] = disp; 265 code += 2; 266 return; 267 } 268 *code++ = (2<<6)|(r<<3)|rm; 269 *(ulong*)code = disp; 270 code += 4; 271 } 272 273 static void 274 con(ulong o, int r) 275 { 276 if(o == 0) { 277 gen2(Oxor, (3<<6)|(r<<3)|r); 278 return; 279 } 280 genb(Omovimm+r); 281 genw(o); 282 } 283 284 static void 285 opwld(Inst *i, int mi, int r) 286 { 287 int ir, rta; 288 289 switch(UXSRC(i->add)) { 290 default: 291 print("%D\n", i); 292 urk(); 293 case SRC(AFP): 294 modrm(mi, i->s.ind, RFP, r); 295 return; 296 case SRC(AMP): 297 modrm(mi, i->s.ind, RMP, r); 298 return; 299 case SRC(AIMM): 300 con(i->s.imm, r); 301 return; 302 case SRC(AIND|AFP): 303 ir = RFP; 304 break; 305 case SRC(AIND|AMP): 306 ir = RMP; 307 break; 308 } 309 rta = RTA; 310 if(mi == Olea) 311 rta = r; 312 modrm(Oldw, i->s.i.f, ir, rta); 313 modrm(mi, i->s.i.s, rta, r); 314 } 315 316 static void 317 opwst(Inst *i, int mi, int r) 318 { 319 int ir, rta; 320 321 switch(UXDST(i->add)) { 322 default: 323 print("%D\n", i); 324 urk(); 325 case DST(AIMM): 326 con(i->d.imm, r); 327 return; 328 case DST(AFP): 329 modrm(mi, i->d.ind, RFP, r); 330 return; 331 case DST(AMP): 332 modrm(mi, i->d.ind, RMP, r); 333 return; 334 case DST(AIND|AFP): 335 ir = RFP; 336 break; 337 case DST(AIND|AMP): 338 ir = RMP; 339 break; 340 } 341 rta = RTA; 342 if(mi == Olea) 343 rta = r; 344 modrm(Oldw, i->d.i.f, ir, rta); 345 modrm(mi, i->d.i.s, rta, r); 346 } 347 348 static void 349 bra(ulong dst, int op) 350 { 351 dst -= (DOT+5); 352 genb(op); 353 genw(dst); 354 } 355 356 static void 357 rbra(ulong dst, int op) 358 { 359 dst += (ulong)base; 360 dst -= DOT+5; 361 genb(op); 362 genw(dst); 363 } 364 365 static void 366 literal(ulong imm, int roff) 367 { 368 nlit++; 369 370 genb(Omovimm+RAX); 371 genw((ulong)litpool); 372 modrm(Ostw, roff, RTMP, RAX); 373 374 if(pass == 0) 375 return; 376 377 *litpool = imm; 378 litpool++; 379 } 380 381 static void 382 punt(Inst *i, int m, void (*fn)(void)) 383 { 384 ulong pc; 385 386 con((ulong)&R, RTMP); 387 388 if(m & SRCOP) { 389 if(UXSRC(i->add) == SRC(AIMM)) 390 literal(i->s.imm, O(REG, s)); 391 else { 392 opwld(i, Olea, RAX); 393 modrm(Ostw, O(REG, s), RTMP, RAX); 394 } 395 } 396 397 if(m & DSTOP) { 398 opwst(i, Olea, 0); 399 modrm(Ostw, O(REG, d), RTMP, RAX); 400 } 401 if(m & WRTPC) { 402 modrm(Omov, O(REG, PC), RTMP, 0); 403 pc = patch[i-mod->prog+1]; 404 genw((ulong)base + pc); 405 } 406 if(m & DBRAN) { 407 pc = patch[(Inst*)i->d.imm-mod->prog]; 408 literal((ulong)base+pc, O(REG, d)); 409 } 410 411 switch(i->add&ARM) { 412 case AXNON: 413 if(m & THREOP) { 414 modrm(Oldw, O(REG, d), RTMP, RAX); 415 modrm(Ostw, O(REG, m), RTMP, RAX); 416 } 417 break; 418 case AXIMM: 419 literal((short)i->reg, O(REG, m)); 420 break; 421 case AXINF: 422 modrm(Olea, i->reg, RFP, RAX); 423 modrm(Ostw, O(REG, m), RTMP, RAX); 424 break; 425 case AXINM: 426 modrm(Olea, i->reg, RMP, RAX); 427 modrm(Ostw, O(REG, m), RTMP, RAX); 428 break; 429 } 430 modrm(Ostw, O(REG, FP), RTMP, RFP); 431 432 bra((ulong)fn, Ocall); 433 434 con((ulong)&R, RTMP); 435 if(m & TCHECK) { 436 modrm(Ocmpi, O(REG, t), RTMP, 7);// CMPL $0, R.t 437 genb(0x00); 438 gen2(Ojeqb, 0x06); // JEQ .+6 439 genb(Opopl+RDI); 440 genb(Opopl+RSI); 441 genb(Opopl+RDX); 442 genb(Opopl+RCX); 443 genb(Opopl+RBX); 444 genb(Oret); 445 } 446 447 modrm(Oldw, O(REG, FP), RTMP, RFP); 448 modrm(Oldw, O(REG, MP), RTMP, RMP); 449 450 if(m & NEWPC) { 451 modrm(Oldw, O(REG, PC), RTMP, RAX); 452 gen2(Ojmprm, (3<<6)|(4<<3)|RAX); 453 } 454 } 455 456 static void 457 mid(Inst *i, uchar mi, int r) 458 { 459 int ir; 460 461 switch(i->add&ARM) { 462 default: 463 opwst(i, mi, r); 464 return; 465 case AXIMM: 466 con((short)i->reg, r); 467 return; 468 case AXINF: 469 ir = RFP; 470 break; 471 case AXINM: 472 ir = RMP; 473 break; 474 } 475 modrm(mi, i->reg, ir, r); 476 } 477 478 static void 479 arith(Inst *i, int op2, int rm) 480 { 481 if(UXSRC(i->add) != SRC(AIMM)) { 482 if(i->add&ARM) { 483 mid(i, Oldw, RAX); 484 opwld(i, op2|2, 0); 485 opwst(i, Ostw, 0); 486 return; 487 } 488 opwld(i, Oldw, RAX); 489 opwst(i, op2, 0); 490 return; 491 } 492 if(i->add&ARM) { 493 mid(i, Oldw, RAX); 494 if(bc(i->s.imm)) { 495 gen2(0x83, (3<<6)|(rm<<3)|RAX); 496 genb(i->s.imm); 497 } 498 else { 499 gen2(0x81, (3<<6)|(rm<<3)|RAX); 500 genw(i->s.imm); 501 } 502 opwst(i, Ostw, RAX); 503 return; 504 } 505 if(bc(i->s.imm)) { 506 opwst(i, 0x83, rm); 507 genb(i->s.imm); 508 return; 509 } 510 opwst(i, 0x81, rm); 511 genw(i->s.imm); 512 } 513 514 static void 515 arithb(Inst *i, int op2) 516 { 517 if(UXSRC(i->add) == SRC(AIMM)) 518 urk(); 519 520 if(i->add&ARM) { 521 mid(i, Oldb, RAX); 522 opwld(i, op2|2, 0); 523 opwst(i, Ostb, 0); 524 return; 525 } 526 opwld(i, Oldb, RAX); 527 opwst(i, op2, RAX); 528 } 529 530 static void 531 shift(Inst *i, int ld, int st, int op, int r) 532 { 533 mid(i, ld, RAX); 534 opwld(i, Oldw, RCX); 535 gen2(op, (3<<6)|(r<<3)|RAX); 536 opwst(i, st, RAX); 537 } 538 539 static void 540 arithf(Inst *i, int op) 541 { 542 opwld(i, Omovf, 0); 543 mid(i, 0xdc, op); 544 opwst(i, Omovf, 3); 545 } 546 547 static void 548 cmpl(int r, ulong v) 549 { 550 if(bc(v)) { 551 gen2(0x83, (3<<6)|(7<<3)|r); 552 genb(v); 553 return; 554 } 555 gen2(0x81, (3<<6)|(7<<3)|r); 556 genw(v); 557 } 558 559 static int 560 swapbraop(int b) 561 { 562 switch(b) { 563 case Ojgel: 564 return Ojlel; 565 case Ojlel: 566 return Ojgel; 567 case Ojgtl: 568 return Ojltl; 569 case Ojltl: 570 return Ojgtl; 571 } 572 return b; 573 } 574 575 static void 576 schedcheck(Inst *i) 577 { 578 if(RESCHED && i->d.ins <= i){ 579 con((ulong)&R, RTMP); 580 /* sub $1, R.IC */ 581 modrm(0x83, O(REG, IC), RTMP, 5); 582 genb(1); 583 gen2(Ojgtb, 5); 584 rbra(macro[MacRELQ], Ocall); 585 } 586 } 587 588 static void 589 cbra(Inst *i, int jmp) 590 { 591 if(RESCHED) 592 schedcheck(i); 593 mid(i, Oldw, RAX); 594 if(UXSRC(i->add) == SRC(AIMM)) { 595 cmpl(RAX, i->s.imm); 596 jmp = swapbraop(jmp); 597 } 598 else 599 opwld(i, Ocmpw, RAX); 600 genb(0x0f); 601 rbra(patch[i->d.ins-mod->prog], jmp); 602 } 603 604 static void 605 cbral(Inst *i, int jmsw, int jlsw, int mode) 606 { 607 ulong dst; 608 uchar *label; 609 610 if(RESCHED) 611 schedcheck(i); 612 opwld(i, Olea, RTMP); 613 mid(i, Olea, RTA); 614 modrm(Oldw, 4, RTA, RAX); 615 modrm(Ocmpw, 4, RTMP, RAX); 616 label = 0; 617 dst = patch[i->d.ins-mod->prog]; 618 switch(mode) { 619 case ANDAND: 620 gen2(Ojneb, 0); 621 label = code-1; 622 break; 623 case OROR: 624 genb(0x0f); 625 rbra(dst, jmsw); 626 break; 627 case EQAND: 628 genb(0x0f); 629 rbra(dst, jmsw); 630 gen2(Ojneb, 0); 631 label = code-1; 632 break; 633 } 634 modrm(Oldw, 0, RTA, RAX); 635 modrm(Ocmpw, 0, RTMP, RAX); 636 genb(0x0f); 637 rbra(dst, jlsw); 638 if(label != nil) 639 *label = code-label-1; 640 } 641 642 static void 643 cbrab(Inst *i, int jmp) 644 { 645 if(RESCHED) 646 schedcheck(i); 647 mid(i, Oldb, RAX); 648 if(UXSRC(i->add) == SRC(AIMM)) 649 urk(); 650 651 opwld(i, Ocmpb, RAX); 652 genb(0x0f); 653 rbra(patch[i->d.ins-mod->prog], jmp); 654 } 655 656 static void 657 cbraf(Inst *i, int jmp) 658 { 659 if(RESCHED) 660 schedcheck(i); 661 opwld(i, Omovf, 0); 662 mid(i, 0xdc, 3); // FCOMP 663 genb(0x9b); // FWAIT 664 gen2(0xdf, 0xe0); // FSTSW AX 665 genb(0x9e); // SAHF 666 667 genb(0x0f); 668 rbra(patch[i->d.ins-mod->prog], jmp); 669 } 670 671 static void 672 comcase(Inst *i, int w) 673 { 674 int l; 675 WORD *t, *e; 676 677 if(w != 0) { 678 opwld(i, Oldw, RAX); // v 679 genb(Opushl+RSI); 680 opwst(i, Olea, RSI); // table 681 rbra(macro[MacCASE], Ojmp); 682 } 683 684 t = (WORD*)(mod->origmp+i->d.ind+4); 685 l = t[-1]; 686 687 /* have to take care not to relocate the same table twice - 688 * the limbo compiler can duplicate a case instruction 689 * during its folding phase 690 */ 691 692 if(pass == 0) { 693 if(l >= 0) 694 t[-1] = -l-1; /* Mark it not done */ 695 return; 696 } 697 if(l >= 0) /* Check pass 2 done */ 698 return; 699 t[-1] = -l-1; /* Set real count */ 700 e = t + t[-1]*3; 701 while(t < e) { 702 t[2] = (ulong)base + patch[t[2]]; 703 t += 3; 704 } 705 t[0] = (ulong)base + patch[t[0]]; 706 } 707 708 static void 709 comcasel(Inst *i) 710 { 711 int l; 712 WORD *t, *e; 713 714 t = (WORD*)(mod->origmp+i->d.ind+8); 715 l = t[-2]; 716 if(pass == 0) { 717 if(l >= 0) 718 t[-2] = -l-1; /* Mark it not done */ 719 return; 720 } 721 if(l >= 0) /* Check pass 2 done */ 722 return; 723 t[-2] = -l-1; /* Set real count */ 724 e = t + t[-2]*6; 725 while(t < e) { 726 t[4] = (ulong)base + patch[t[4]]; 727 t += 6; 728 } 729 t[0] = (ulong)base + patch[t[0]]; 730 } 731 732 static void 733 commframe(Inst *i) 734 { 735 int o; 736 uchar *punt, *mlnil; 737 738 opwld(i, Oldw, RAX); 739 cmpl(RAX, (ulong)H); 740 gen2(Ojeqb, 0); 741 mlnil = code - 1; 742 if((i->add&ARM) == AXIMM) { 743 o = OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, frame); 744 modrm(Oldw, o, RAX, RTA); 745 } else { 746 gen2(Oldw, (3<<6)|(RTMP<<3)|RAX); // MOVL AX, RTMP 747 mid(i, Oldw, RCX); // index 748 gen2(Olea, (0<<6)|(0<<3)|4); // lea (AX)(RCX*8) 749 genb((3<<6)|(RCX<<3)|RAX); // assumes sizeof(Modl) == 8 hence 3 750 o = OA(Modlink, links)+O(Modl, frame); 751 modrm(Oldw, o, RAX, RTA); // frame 752 genb(OxchgAX+RTMP); // get old AX back 753 } 754 modrm(0x83, O(Type, initialize), RTA, 7); 755 genb(0); 756 gen2(Ojneb, 0); 757 punt = code - 1; 758 genb(OxchgAX+RTA); 759 opwst(i, Olea, RTA); 760 *mlnil = code-mlnil-1; 761 rbra(macro[MacMFRA], Ocall); 762 rbra(patch[i-mod->prog+1], Ojmp); 763 764 *punt = code-punt-1; 765 rbra(macro[MacFRAM], Ocall); 766 opwst(i, Ostw, RCX); 767 } 768 769 static void 770 commcall(Inst *i) 771 { 772 uchar *mlnil; 773 774 con((ulong)&R, RTMP); // MOVL $R, RTMP 775 opwld(i, Oldw, RCX); 776 modrm(Omov, O(Frame, lr), RCX, 0); // MOVL $.+1, lr(CX) f->lr = R.PC 777 genw((ulong)base+patch[i-mod->prog+1]); 778 modrm(Ostw, O(Frame, fp), RCX, RFP); // MOVL RFP, fp(CX) f->fp = R.FP 779 modrm(Oldw, O(REG, M), RTMP, RTA); // MOVL R.M, RTA 780 modrm(Ostw, O(Frame, mr), RCX, RTA); // MOVL RTA, mr(CX) f->mr = R.M 781 opwst(i, Oldw, RTA); // MOVL ml, RTA 782 cmpl(RTA, (ulong)H); 783 gen2(Ojeqb, 0); 784 mlnil = code - 1; 785 if((i->add&ARM) == AXIMM) 786 modrm(Oldw, OA(Modlink, links)+i->reg*sizeof(Modl)+O(Modl, u.pc), RTA, RAX); 787 else { 788 genb(Opushl+RCX); 789 mid(i, Oldw, RCX); // index 790 gen2(Olea, (0<<6)|(0<<3)|4); // lea (RTA)(RCX*8) 791 genb((3<<6)|(RCX<<3)|RTA); // assumes sizeof(Modl) == 8 hence 3 792 modrm(Oldw, OA(Modlink, links)+O(Modl, u.pc), RAX, RAX); 793 genb(Opopl+RCX); 794 } 795 *mlnil = code-mlnil-1; 796 rbra(macro[MacMCAL], Ocall); 797 } 798 799 static void 800 larith(Inst *i, int op, int opc) 801 { 802 opwld(i, Olea, RTMP); 803 mid(i, Olea, RTA); 804 modrm(Oldw, 0, RTA, RAX); // MOVL 0(RTA), AX 805 modrm(op, 0, RTMP, RAX); // ADDL 0(RTMP), AX 806 modrm(Oldw, 4, RTA, RCX); // MOVL 4(RTA), CX 807 modrm(opc, 4, RTMP, RCX); // ADCL 4(RTMP), CX 808 if((i->add&ARM) != AXNON) 809 opwst(i, Olea, RTA); 810 modrm(Ostw, 0, RTA, RAX); 811 modrm(Ostw, 4, RTA, RCX); 812 } 813 814 static void 815 shll(Inst *i) 816 { 817 uchar *label, *label1; 818 819 opwld(i, Oldw, RCX); 820 mid(i, Olea, RTA); 821 gen2(Otestib, (3<<6)|(0<<3)|RCX); 822 genb(0x20); 823 gen2(Ojneb, 0); 824 label = code-1; 825 modrm(Oldw, 0, RTA, RAX); 826 modrm(Oldw, 4, RTA, RBX); 827 genb(0x0f); 828 gen2(Oshld, (3<<6)|(RAX<<3)|RBX); 829 gen2(Oshl, (3<<6)|(4<<3)|RAX); 830 gen2(Ojmpb, 0); 831 label1 = code-1; 832 *label = code-label-1; 833 modrm(Oldw, 0, RTA, RBX); 834 con(0, RAX); 835 gen2(Oshl, (3<<6)|(4<<3)|RBX); 836 *label1 = code-label1-1; 837 opwst(i, Olea, RTA); 838 modrm(Ostw, 0, RTA, RAX); 839 modrm(Ostw, 4, RTA, RBX); 840 } 841 842 static void 843 shrl(Inst *i) 844 { 845 uchar *label, *label1; 846 847 opwld(i, Oldw, RCX); 848 mid(i, Olea, RTA); 849 gen2(Otestib, (3<<6)|(0<<3)|RCX); 850 genb(0x20); 851 gen2(Ojneb, 0); 852 label = code-1; 853 modrm(Oldw, 0, RTA, RAX); 854 modrm(Oldw, 4, RTA, RBX); 855 genb(0x0f); 856 gen2(Oshrd, (3<<6)|(RBX<<3)|RAX); 857 gen2(Osar, (3<<6)|(7<<3)|RBX); 858 gen2(Ojmpb, 0); 859 label1 = code-1; 860 *label = code-label-1; 861 modrm(Oldw, 4, RTA, RBX); 862 gen2(Oldw, (3<<6)|(RAX<<3)|RBX); 863 gen2(Osarimm, (3<<6)|(7<<3)|RBX); 864 genb(0x1f); 865 gen2(Osar, (3<<6)|(7<<3)|RAX); 866 *label1 = code-label1-1; 867 opwst(i, Olea, RTA); 868 modrm(Ostw, 0, RTA, RAX); 869 modrm(Ostw, 4, RTA, RBX); 870 } 871 872 static 873 void 874 compdbg(void) 875 { 876 print("%s:%lud@%.8lux\n", R.M->m->name, *(ulong*)R.m, *(ulong*)R.s); 877 } 878 879 static void 880 comp(Inst *i) 881 { 882 int r; 883 WORD *t, *e; 884 char buf[64]; 885 886 if(0) { 887 Inst xx; 888 xx.add = AXIMM|SRC(AIMM); 889 xx.s.imm = (ulong)code; 890 xx.reg = i-mod->prog; 891 punt(&xx, SRCOP, compdbg); 892 } 893 894 switch(i->op) { 895 default: 896 snprint(buf, sizeof buf, "%s compile, no '%D'", mod->name, i); 897 error(buf); 898 break; 899 case IMCALL: 900 if((i->add&ARM) == AXIMM) 901 commcall(i); 902 else 903 punt(i, SRCOP|DSTOP|THREOP|WRTPC|NEWPC, optab[i->op]); 904 break; 905 case ISEND: 906 case IRECV: 907 case IALT: 908 punt(i, SRCOP|DSTOP|TCHECK|WRTPC, optab[i->op]); 909 break; 910 case ISPAWN: 911 punt(i, SRCOP|DBRAN, optab[i->op]); 912 break; 913 case IBNEC: 914 case IBEQC: 915 case IBLTC: 916 case IBLEC: 917 case IBGTC: 918 case IBGEC: 919 punt(i, SRCOP|DBRAN|NEWPC|WRTPC, optab[i->op]); 920 break; 921 case ICASEC: 922 comcase(i, 0); 923 punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]); 924 break; 925 case ICASEL: 926 comcasel(i); 927 punt(i, SRCOP|DSTOP|NEWPC, optab[i->op]); 928 break; 929 case IADDC: 930 case IMULL: 931 case IDIVL: 932 case IMODL: 933 case IMNEWZ: 934 case ILSRW: 935 case ILSRL: 936 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 937 break; 938 case ILOAD: 939 case INEWA: 940 case INEWAZ: 941 case INEW: 942 case INEWZ: 943 case ISLICEA: 944 case ISLICELA: 945 case ICONSB: 946 case ICONSW: 947 case ICONSL: 948 case ICONSF: 949 case ICONSM: 950 case ICONSMP: 951 case ICONSP: 952 case IMOVMP: 953 case IHEADMP: 954 case IHEADL: 955 case IINSC: 956 case ICVTAC: 957 case ICVTCW: 958 case ICVTWC: 959 case ICVTLC: 960 case ICVTCL: 961 case ICVTFC: 962 case ICVTCF: 963 case ICVTRF: 964 case ICVTFR: 965 case ICVTWS: 966 case ICVTSW: 967 case IMSPAWN: 968 case ICVTCA: 969 case ISLICEC: 970 case INBALT: 971 punt(i, SRCOP|DSTOP, optab[i->op]); 972 break; 973 case INEWCM: 974 case INEWCMP: 975 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 976 break; 977 case IMFRAME: 978 if((i->add&ARM) == AXIMM) 979 commframe(i); 980 else 981 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 982 break; 983 case INEWCB: 984 case INEWCW: 985 case INEWCF: 986 case INEWCP: 987 case INEWCL: 988 punt(i, DSTOP|THREOP, optab[i->op]); 989 break; 990 case IEXIT: 991 punt(i, 0, optab[i->op]); 992 break; 993 case ICVTBW: 994 opwld(i, Oldb, RAX); 995 genb(0x0f); 996 gen2(0xb6, (3<<6)|(RAX<<3)|RAX); 997 opwst(i, Ostw, RAX); 998 break; 999 case ICVTWB: 1000 opwld(i, Oldw, RAX); 1001 opwst(i, Ostb, RAX); 1002 break; 1003 case ICVTFW: 1004 if(1){ 1005 punt(i, SRCOP|DSTOP, optab[i->op]); 1006 break; 1007 } 1008 opwld(i, Omovf, 0); 1009 opwst(i, 0xdb, 3); 1010 break; 1011 case ICVTWF: 1012 if(1){ 1013 punt(i, SRCOP|DSTOP, optab[i->op]); 1014 break; 1015 } 1016 opwld(i, 0xdb, 0); 1017 opwst(i, Omovf, 3); 1018 break; 1019 case ICVTLF: 1020 if(1){ 1021 punt(i, SRCOP|DSTOP, optab[i->op]); 1022 break; 1023 } 1024 opwld(i, 0xdf, 5); 1025 opwst(i, Omovf, 3); 1026 break; 1027 case ICVTFL: 1028 if(1){ 1029 punt(i, SRCOP|DSTOP, optab[i->op]); 1030 break; 1031 } 1032 opwld(i, Omovf, 0); 1033 opwst(i, 0xdf, 7); 1034 break; 1035 case IHEADM: 1036 opwld(i, Oldw, RAX); 1037 modrm(Olea, OA(List, data), RAX, RAX); 1038 goto movm; 1039 case IMOVM: 1040 opwld(i, Olea, RAX); 1041 movm: 1042 opwst(i, Olea, RBX); 1043 mid(i, Oldw, RCX); 1044 genb(OxchgAX+RSI); 1045 gen2(Oxchg, (3<<6)|(RDI<<3)|RBX); 1046 genb(Ocld); 1047 gen2(Orep, Omovsb); 1048 genb(OxchgAX+RSI); 1049 gen2(Oxchg, (3<<6)|(RDI<<3)|RBX); 1050 break; 1051 case IRET: 1052 rbra(macro[MacRET], Ojmp); 1053 break; 1054 case IFRAME: 1055 if(UXSRC(i->add) != SRC(AIMM)) { 1056 punt(i, SRCOP|DSTOP, optab[i->op]); 1057 break; 1058 } 1059 tinit[i->s.imm] = 1; 1060 con((ulong)mod->type[i->s.imm], RTA); 1061 rbra(macro[MacFRAM], Ocall); 1062 opwst(i, Ostw, RCX); 1063 break; 1064 case ILEA: 1065 if(UXSRC(i->add) == SRC(AIMM)) { 1066 gen2(Ojmpb, 4); 1067 genw(i->s.imm); 1068 con((ulong)(code-4), RAX); 1069 } 1070 else 1071 opwld(i, Olea, RAX); 1072 opwst(i, Ostw, RAX); 1073 break; 1074 case IHEADW: 1075 opwld(i, Oldw, RAX); 1076 modrm(Oldw, OA(List, data), RAX, RAX); 1077 opwst(i, Ostw, RAX); 1078 break; 1079 case IHEADF: 1080 opwld(i, Oldw, RAX); 1081 modrm(Omovf, OA(List, data), RAX, 0); 1082 opwst(i, Omovf, 3); 1083 break; 1084 case IHEADB: 1085 opwld(i, Oldw, RAX); 1086 modrm(Oldb, OA(List, data), RAX, RAX); 1087 opwst(i, Ostb, RAX); 1088 break; 1089 case ITAIL: 1090 opwld(i, Oldw, RAX); 1091 modrm(Oldw, O(List, tail), RAX, RBX); 1092 goto movp; 1093 case IMOVP: 1094 case IHEADP: 1095 opwld(i, Oldw, RBX); 1096 if(i->op == IHEADP) 1097 modrm(Oldw, OA(List, data), RBX, RBX); 1098 movp: 1099 cmpl(RBX, (ulong)H); 1100 gen2(Ojeqb, 0x05); 1101 rbra(macro[MacCOLR], Ocall); 1102 opwst(i, Oldw, RAX); 1103 opwst(i, Ostw, RBX); 1104 rbra(macro[MacFRP], Ocall); 1105 break; 1106 case ILENA: 1107 opwld(i, Oldw, RBX); 1108 con(0, RAX); 1109 cmpl(RBX, (ulong)H); 1110 gen2(Ojeqb, 0x02); 1111 modrm(Oldw, O(Array, len), RBX, RAX); 1112 opwst(i, Ostw, RAX); 1113 break; 1114 case ILENC: 1115 opwld(i, Oldw, RBX); 1116 con(0, RAX); 1117 cmpl(RBX, (ulong)H); 1118 gen2(Ojeqb, 0x09); 1119 modrm(Oldw, O(String, len), RBX, RAX); 1120 cmpl(RAX, 0); 1121 gen2(Ojgeb, 0x02); 1122 gen2(Oneg, (3<<6)|(3<<3)|RAX); 1123 opwst(i, Ostw, RAX); 1124 break; 1125 case ILENL: 1126 con(0, RAX); 1127 opwld(i, Oldw, RBX); 1128 cmpl(RBX, (ulong)H); 1129 gen2(Ojeqb, 0x05); 1130 modrm(Oldw, O(List, tail), RBX, RBX); 1131 genb(Oincr+RAX); 1132 gen2(Ojmpb, 0xf6); 1133 opwst(i, Ostw, RAX); 1134 break; 1135 case IBEQF: 1136 cbraf(i, Ojeql); 1137 break; 1138 case IBNEF: 1139 cbraf(i, Ojnel); 1140 break; 1141 case IBLEF: 1142 cbraf(i, Ojlsl); 1143 break; 1144 case IBLTF: 1145 cbraf(i, Ojcsl); 1146 break; 1147 case IBGEF: 1148 cbraf(i, Ojccl); 1149 break; 1150 case IBGTF: 1151 cbraf(i, Ojhil); 1152 break; 1153 case IBEQW: 1154 cbra(i, Ojeql); 1155 break; 1156 case IBLEW: 1157 cbra(i, Ojlel); 1158 break; 1159 case IBNEW: 1160 cbra(i, Ojnel); 1161 break; 1162 case IBGTW: 1163 cbra(i, Ojgtl); 1164 break; 1165 case IBLTW: 1166 cbra(i, Ojltl); 1167 break; 1168 case IBGEW: 1169 cbra(i, Ojgel); 1170 break; 1171 case IBEQB: 1172 cbrab(i, Ojeql); 1173 break; 1174 case IBLEB: 1175 cbrab(i, Ojlsl); 1176 break; 1177 case IBNEB: 1178 cbrab(i, Ojnel); 1179 break; 1180 case IBGTB: 1181 cbrab(i, Ojhil); 1182 break; 1183 case IBLTB: 1184 cbrab(i, Ojbl); 1185 break; 1186 case IBGEB: 1187 cbrab(i, Ojael); 1188 break; 1189 case ISUBW: 1190 arith(i, 0x29, 5); 1191 break; 1192 case ISUBB: 1193 arithb(i, 0x28); 1194 break; 1195 case ISUBF: 1196 arithf(i, 5); 1197 break; 1198 case IADDW: 1199 arith(i, 0x01, 0); 1200 break; 1201 case IADDB: 1202 arithb(i, 0x00); 1203 break; 1204 case IADDF: 1205 arithf(i, 0); 1206 break; 1207 case IORW: 1208 arith(i, 0x09, 1); 1209 break; 1210 case IORB: 1211 arithb(i, 0x08); 1212 break; 1213 case IANDW: 1214 arith(i, 0x21, 4); 1215 break; 1216 case IANDB: 1217 arithb(i, 0x20); 1218 break; 1219 case IXORW: 1220 arith(i, Oxor, 6); 1221 break; 1222 case IXORB: 1223 arithb(i, 0x30); 1224 break; 1225 case ISHLW: 1226 shift(i, Oldw, Ostw, 0xd3, 4); 1227 break; 1228 case ISHLB: 1229 shift(i, Oldb, Ostb, 0xd2, 4); 1230 break; 1231 case ISHRW: 1232 shift(i, Oldw, Ostw, 0xd3, 7); 1233 break; 1234 case ISHRB: 1235 shift(i, Oldb, Ostb, 0xd2, 5); 1236 break; 1237 case IMOVF: 1238 opwld(i, Omovf, 0); 1239 opwst(i, Omovf, 3); 1240 break; 1241 case INEGF: 1242 opwld(i, Omovf, 0); 1243 genb(0xd9); 1244 genb(0xe0); 1245 opwst(i, Omovf, 3); 1246 break; 1247 case IMOVB: 1248 opwld(i, Oldb, RAX); 1249 opwst(i, Ostb, RAX); 1250 break; 1251 case IMOVW: 1252 case ICVTLW: // Little endian 1253 if(UXSRC(i->add) == SRC(AIMM)) { 1254 opwst(i, Omov, RAX); 1255 genw(i->s.imm); 1256 break; 1257 } 1258 opwld(i, Oldw, RAX); 1259 opwst(i, Ostw, RAX); 1260 break; 1261 case ICVTWL: 1262 opwst(i, Olea, RTMP); 1263 opwld(i, Oldw, RAX); 1264 modrm(Ostw, 0, RTMP, RAX); 1265 genb(0x99); 1266 modrm(Ostw, 4, RTMP, RDX); 1267 break; 1268 case ICALL: 1269 if(UXDST(i->add) != DST(AIMM)) 1270 opwst(i, Oldw, RTA); 1271 opwld(i, Oldw, RAX); 1272 modrm(Omov, O(Frame, lr), RAX, 0); // MOVL $.+1, lr(AX) 1273 genw((ulong)base+patch[i-mod->prog+1]); 1274 modrm(Ostw, O(Frame, fp), RAX, RFP); // MOVL RFP, fp(AX) 1275 gen2(Oldw, (3<<6)|(RFP<<3)|RAX); // MOVL AX,RFP 1276 if(UXDST(i->add) != DST(AIMM)){ 1277 gen2(Ojmprm, (3<<6)|(4<<3)|RTA); 1278 break; 1279 } 1280 /* no break */ 1281 case IJMP: 1282 if(RESCHED) 1283 schedcheck(i); 1284 rbra(patch[i->d.ins-mod->prog], Ojmp); 1285 break; 1286 case IMOVPC: 1287 opwst(i, Omov, RAX); 1288 genw(patch[i->s.imm]+(ulong)base); 1289 break; 1290 case IGOTO: 1291 opwst(i, Olea, RBX); 1292 opwld(i, Oldw, RAX); 1293 gen2(Ojmprm, (0<<6)|(4<<3)|4); 1294 genb((2<<6)|(RAX<<3)|RBX); 1295 1296 if(pass == 0) 1297 break; 1298 1299 t = (WORD*)(mod->origmp+i->d.ind); 1300 e = t + t[-1]; 1301 t[-1] = 0; 1302 while(t < e) { 1303 t[0] = (ulong)base + patch[t[0]]; 1304 t++; 1305 } 1306 break; 1307 case IMULF: 1308 arithf(i, 1); 1309 break; 1310 case IDIVF: 1311 arithf(i, 7); 1312 break; 1313 case IMODW: 1314 case IDIVW: 1315 case IMULW: 1316 mid(i, Oldw, RAX); 1317 opwld(i, Oldw, RTMP); 1318 if(i->op == IMULW) 1319 gen2(0xf7, (3<<6)|(4<<3)|RTMP); 1320 else { 1321 genb(Ocdq); 1322 gen2(0xf7, (3<<6)|(7<<3)|RTMP); // IDIV AX, RTMP 1323 if(i->op == IMODW) 1324 genb(0x90+RDX); // XCHG AX, DX 1325 } 1326 opwst(i, Ostw, RAX); 1327 break; 1328 case IMODB: 1329 case IDIVB: 1330 case IMULB: 1331 mid(i, Oldb, RAX); 1332 opwld(i, Oldb, RTMP); 1333 if(i->op == IMULB) 1334 gen2(0xf6, (3<<6)|(4<<3)|RTMP); 1335 else { 1336 genb(Ocdq); 1337 gen2(0xf6, (3<<6)|(7<<3)|RTMP); // IDIV AX, RTMP 1338 if(i->op == IMODB) 1339 genb(0x90+RDX); // XCHG AX, DX 1340 } 1341 opwst(i, Ostb, RAX); 1342 break; 1343 case IINDX: 1344 opwld(i, Oldw, RTMP); // MOVW xx(s), BX 1345 1346 if(bflag){ 1347 opwst(i, Oldw, RAX); 1348 modrm(0x3b, O(Array, len), RTMP, RAX); /* CMP index, len */ 1349 gen2(0x72, 5); /* JB */ 1350 bra((ulong)bounds, Ocall); 1351 modrm(Oldw, O(Array, t), RTMP, RTA); 1352 modrm(0xf7, O(Type, size), RTA, 5); /* IMULL AX, xx(t) */ 1353 } 1354 else{ 1355 modrm(Oldw, O(Array, t), RTMP, RAX); // MOVW t(BX), AX 1356 modrm(Oldw, O(Type, size), RAX, RAX); // MOVW size(AX), AX 1357 if(UXDST(i->add) == DST(AIMM)) { 1358 gen2(0x69, (3<<6)|(RAX<<3)|0); 1359 genw(i->d.imm); 1360 } 1361 else 1362 opwst(i, 0xf7, 5); // IMULL AX,xx(d) 1363 } 1364 1365 modrm(0x03, O(Array, data), RBX, RAX); // ADDL data(BX), AX 1366 r = RMP; 1367 if((i->add&ARM) == AXINF) 1368 r = RFP; 1369 modrm(Ostw, i->reg, r, RAX); 1370 break; 1371 case IINDB: 1372 r = 0; 1373 goto idx; 1374 case IINDF: 1375 case IINDL: 1376 r = 3; 1377 goto idx; 1378 case IINDW: 1379 r = 2; 1380 idx: 1381 opwld(i, Oldw, RAX); 1382 opwst(i, Oldw, RTMP); 1383 if(bflag){ 1384 modrm(0x3b, O(Array, len), RAX, RTMP); /* CMP index, len */ 1385 gen2(0x72, 5); /* JB */ 1386 bra((ulong)bounds, Ocall); 1387 } 1388 modrm(Oldw, O(Array, data), RAX, RAX); 1389 gen2(Olea, (0<<6)|(0<<3)|4); /* lea (AX)(RTMP*r) */ 1390 genb((r<<6)|(RTMP<<3)|RAX); 1391 r = RMP; 1392 if((i->add&ARM) == AXINF) 1393 r = RFP; 1394 modrm(Ostw, i->reg, r, RAX); 1395 break; 1396 case IINDC: 1397 opwld(i, Oldw, RAX); // string 1398 mid(i, Oldw, RBX); // index 1399 if(bflag){ 1400 modrm(Oldw, O(String, len), RAX, RTA); 1401 cmpl(RTA, 0); 1402 gen2(Ojltb, 16); 1403 gen2(0x3b, (3<<6)|(RBX<<3)|RTA); /* cmp index, len */ 1404 gen2(0x72, 5); /* JB */ 1405 bra((ulong)bounds, Ocall); 1406 genb(0x0f); 1407 gen2(Omovzxb, (1<<6)|(0<<3)|4); 1408 gen2((0<<6)|(RBX<<3)|RAX, O(String, data)); 1409 gen2(Ojmpb, sizeof(Rune)==4? 10: 11); 1410 gen2(Oneg, (3<<6)|(3<<3)|RTA); 1411 gen2(0x3b, (3<<6)|(RBX<<3)|RTA); /* cmp index, len */ 1412 gen2(0x73, 0xee); /* JNB */ 1413 if(sizeof(Rune) == 4){ 1414 gen2(Oldw, (1<<6)|(0<<3)|4); 1415 gen2((2<<6)|(RBX<<3)|RAX, O(String, data)); 1416 }else{ 1417 genb(0x0f); 1418 gen2(Omovzxw, (1<<6)|(0<<3)|4); 1419 gen2((1<<6)|(RBX<<3)|RAX, O(String, data)); 1420 } 1421 opwst(i, Ostw, RAX); 1422 break; 1423 } 1424 modrm(Ocmpi, O(String, len), RAX, 7); 1425 genb(0); 1426 gen2(Ojltb, 7); 1427 genb(0x0f); 1428 gen2(Omovzxb, (1<<6)|(0<<3)|4); /* movzbx 12(AX)(RBX*1), RAX */ 1429 gen2((0<<6)|(RBX<<3)|RAX, O(String, data)); 1430 if(sizeof(Rune) == 4){ 1431 gen2(Ojmpb, 4); 1432 gen2(Oldw, (1<<6)|(0<<3)|4); /* movl 12(AX)(RBX*4), RAX */ 1433 gen2((2<<6)|(RBX<<3)|RAX, O(String, data)); 1434 }else{ 1435 gen2(Ojmpb, 5); 1436 genb(0x0f); 1437 gen2(Omovzxw, (1<<6)|(0<<3)|4); /* movzwx 12(AX)(RBX*2), RAX */ 1438 gen2((1<<6)|(RBX<<3)|RAX, O(String, data)); 1439 } 1440 opwst(i, Ostw, RAX); 1441 break; 1442 case ICASE: 1443 comcase(i, 1); 1444 break; 1445 case IMOVL: 1446 opwld(i, Olea, RTA); 1447 opwst(i, Olea, RTMP); 1448 modrm(Oldw, 0, RTA, RAX); 1449 modrm(Ostw, 0, RTMP, RAX); 1450 modrm(Oldw, 4, RTA, RAX); 1451 modrm(Ostw, 4, RTMP, RAX); 1452 break; 1453 case IADDL: 1454 larith(i, 0x03, 0x13); 1455 break; 1456 case ISUBL: 1457 larith(i, 0x2b, 0x1b); 1458 break; 1459 case IORL: 1460 larith(i, 0x0b, 0x0b); 1461 break; 1462 case IANDL: 1463 larith(i, 0x23, 0x23); 1464 break; 1465 case IXORL: 1466 larith(i, 0x33, 0x33); 1467 break; 1468 case IBEQL: 1469 cbral(i, Ojnel, Ojeql, ANDAND); 1470 break; 1471 case IBNEL: 1472 cbral(i, Ojnel, Ojnel, OROR); 1473 break; 1474 case IBLEL: 1475 cbral(i, Ojltl, Ojbel, EQAND); 1476 break; 1477 case IBGTL: 1478 cbral(i, Ojgtl, Ojal, EQAND); 1479 break; 1480 case IBLTL: 1481 cbral(i, Ojltl, Ojbl, EQAND); 1482 break; 1483 case IBGEL: 1484 cbral(i, Ojgtl, Ojael, EQAND); 1485 break; 1486 case ISHLL: 1487 shll(i); 1488 break; 1489 case ISHRL: 1490 shrl(i); 1491 break; 1492 case IRAISE: 1493 punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]); 1494 break; 1495 case IMULX: 1496 case IDIVX: 1497 case ICVTXX: 1498 case IMULX0: 1499 case IDIVX0: 1500 case ICVTXX0: 1501 case IMULX1: 1502 case IDIVX1: 1503 case ICVTXX1: 1504 case ICVTFX: 1505 case ICVTXF: 1506 case IEXPW: 1507 case IEXPL: 1508 case IEXPF: 1509 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1510 break; 1511 case ISELF: 1512 punt(i, DSTOP, optab[i->op]); 1513 break; 1514 } 1515 } 1516 1517 static void 1518 preamble(void) 1519 { 1520 if(comvec) 1521 return; 1522 1523 comvec = malloc(32); 1524 if(comvec == nil) 1525 error(exNomem); 1526 code = (uchar*)comvec; 1527 1528 genb(Opushl+RBX); 1529 genb(Opushl+RCX); 1530 genb(Opushl+RDX); 1531 genb(Opushl+RSI); 1532 genb(Opushl+RDI); 1533 con((ulong)&R, RTMP); 1534 modrm(Oldw, O(REG, FP), RTMP, RFP); 1535 modrm(Oldw, O(REG, MP), RTMP, RMP); 1536 modrm(Ojmprm, O(REG, PC), RTMP, 4); 1537 1538 segflush(comvec, 32); 1539 } 1540 1541 static void 1542 maccase(void) 1543 { 1544 uchar *loop, *def, *lab1; 1545 1546 modrm(Oldw, 0, RSI, RDX); // n = t[0] 1547 modrm(Olea, 4, RSI, RSI); // t = &t[1] 1548 gen2(Oldw, (3<<6)|(RBX<<3)|RDX); // MOVL DX, BX 1549 gen2(Oshr, (3<<6)|(4<<3)|RBX); // SHL BX,1 1550 gen2(0x01, (3<<6)|(RDX<<3)|RBX); // ADDL DX, BX BX = n*3 1551 gen2(Opushrm, (0<<6)|(6<<3)|4); 1552 genb((2<<6)|(RBX<<3)|RSI); // PUSHL 0(SI)(BX*4) 1553 loop = code; 1554 cmpl(RDX, 0); 1555 gen2(Ojleb, 0); 1556 def = code-1; 1557 gen2(Oldw, (3<<6)|(RCX<<3)|RDX); // MOVL DX, CX n2 = n 1558 gen2(Oshr, (3<<6)|(5<<3)|RCX); // SHR CX,1 n2 = n2>>1 1559 gen2(Oldw, (3<<6)|(RBX<<3)|RCX); // MOVL CX, BX 1560 gen2(Oshr, (3<<6)|(4<<3)|RBX); // SHL BX,1 1561 gen2(0x01, (3<<6)|(RCX<<3)|RBX); // ADDL CX, BX BX = n2*3 1562 gen2(0x3b, (0<<6)|(RAX<<3)|4); 1563 genb((2<<6)|(RBX<<3)|RSI); // CMPL AX, 0(SI)(BX*4) 1564 gen2(Ojgeb, 0); // JGE lab1 1565 lab1 = code-1; 1566 gen2(Oldw, (3<<6)|(RDX<<3)|RCX); 1567 gen2(Ojmpb, loop-code-2); 1568 *lab1 = code-lab1-1; // lab1: 1569 gen2(0x3b, (1<<6)|(RAX<<3)|4); 1570 gen2((2<<6)|(RBX<<3)|RSI, 4); // CMPL AX, 4(SI)(BX*4) 1571 gen2(Ojltb, 0); 1572 lab1 = code-1; 1573 gen2(Olea, (1<<6)|(RSI<<3)|4); 1574 gen2((2<<6)|(RBX<<3)|RSI, 12); // LEA 12(SI)(RBX*4), RSI 1575 gen2(0x2b, (3<<6)|(RDX<<3)|RCX); // SUBL CX, DX n -= n2 1576 gen2(Odecrm, (3<<6)|(1<<3)|RDX); // DECL DX n -= 1 1577 gen2(Ojmpb, loop-code-2); 1578 *lab1 = code-lab1-1; // lab1: 1579 gen2(Oldw, (1<<6)|(RAX<<3)|4); 1580 gen2((2<<6)|(RBX<<3)|RSI, 8); // MOVL 8(SI)(BX*4), AX 1581 genb(Opopl+RSI); // ditch default 1582 genb(Opopl+RSI); 1583 gen2(Ojmprm, (3<<6)|(4<<3)|RAX); // JMP*L AX 1584 *def = code-def-1; // def: 1585 genb(Opopl+RAX); // ditch default 1586 genb(Opopl+RSI); 1587 gen2(Ojmprm, (3<<6)|(4<<3)|RAX); 1588 } 1589 1590 static void 1591 macfrp(void) 1592 { 1593 cmpl(RAX, (ulong)H); // CMPL AX, $H 1594 gen2(Ojneb, 0x01); // JNE .+1 1595 genb(Oret); // RET 1596 modrm(0x83, O(Heap, ref)-sizeof(Heap), RAX, 7); 1597 genb(0x01); // CMP AX.ref, $1 1598 gen2(Ojeqb, 0x04); // JNE .+4 1599 modrm(Odecrm, O(Heap, ref)-sizeof(Heap), RAX, 1); 1600 genb(Oret); // DEC AX.ref 1601 // RET 1602 con((ulong)&R, RTMP); // MOV $R, RTMP 1603 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP 1604 modrm(Ostw, O(REG, s), RTMP, RAX); // MOVL RAX, R.s 1605 bra((ulong)rdestroy, Ocall); // CALL rdestroy 1606 con((ulong)&R, RTMP); // MOVL $R, RTMP 1607 modrm(Oldw, O(REG, FP), RTMP, RFP); // MOVL R.MP, RMP 1608 modrm(Oldw, O(REG, MP), RTMP, RMP); // MOVL R.FP, RFP 1609 genb(Oret); 1610 } 1611 1612 static void 1613 macret(void) 1614 { 1615 Inst i; 1616 uchar *s; 1617 static ulong lpunt, lnomr, lfrmr, linterp; 1618 1619 s = code; 1620 1621 lpunt -= 2; 1622 lnomr -= 2; 1623 lfrmr -= 2; 1624 linterp -= 2; 1625 1626 con(0, RBX); // MOVL $0, RBX 1627 modrm(Oldw, O(Frame, t), RFP, RAX); // MOVL t(FP), RAX 1628 gen2(Ocmpw, (3<<6)|(RAX<<3)|RBX); // CMPL RAX, RBX 1629 gen2(Ojeqb, lpunt-(code-s)); // JEQ lpunt 1630 modrm(Oldw, O(Type, destroy), RAX, RAX);// MOVL destroy(RAX), RAX 1631 gen2(Ocmpw, (3<<6)|(RAX<<3)|RBX); // CMPL RAX, RBX 1632 gen2(Ojeqb, lpunt-(code-s)); // JEQ lpunt 1633 modrm(Ocmpw, O(Frame, fp), RFP, RBX); // CMPL fp(FP), RBX 1634 gen2(Ojeqb, lpunt-(code-s)); // JEQ lpunt 1635 modrm(Ocmpw, O(Frame, mr), RFP, RBX); // CMPL mr(FP), RBX 1636 gen2(Ojeqb, lnomr-(code-s)); // JEQ lnomr 1637 con((ulong)&R, RTMP); // MOVL $R, RTMP 1638 modrm(Oldw, O(REG, M), RTMP, RTA); // MOVL R.M, RTA 1639 modrm(Odecrm, O(Heap, ref)-sizeof(Heap), RTA, 1); 1640 gen2(Ojneb, lfrmr-(code-s)); // JNE lfrmr 1641 modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RTA, 0); 1642 gen2(Ojmpb, lpunt-(code-s)); // JMP lpunt 1643 lfrmr = code - s; 1644 modrm(Oldw, O(Frame, mr), RFP, RTA); // MOVL mr(FP), RTA 1645 modrm(Ostw, O(REG, M), RTMP, RTA); // MOVL RTA, R.M 1646 modrm(Oldw, O(Modlink, MP), RTA, RMP); // MOVL MP(RTA), RMP 1647 modrm(Ostw, O(REG, MP), RTMP, RMP); // MOVL RMP, R.MP 1648 modrm(Ocmpi, O(Modlink, compiled), RTA, 7);// CMPL $0, M.compiled 1649 genb(0x00); 1650 gen2(Ojeqb, linterp-(code-s)); // JEQ linterp 1651 lnomr = code - s; 1652 gen2(Ocallrm, (3<<6)|(2<<3)|RAX); // CALL* AX 1653 con((ulong)&R, RTMP); // MOVL $R, RTMP 1654 modrm(Ostw, O(REG, SP), RTMP, RFP); // MOVL RFP, R.SP 1655 modrm(Oldw, O(Frame, lr), RFP, RAX); // MOVL lr(RFP), RAX 1656 modrm(Oldw, O(Frame, fp), RFP, RFP); // MOVL fp(RFP), RFP 1657 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP 1658 gen2(Ojmprm, (3<<6)|(4<<3)|RAX); // JMP*L AX 1659 1660 linterp = code - s; // return to uncompiled code 1661 gen2(Ocallrm, (3<<6)|(2<<3)|RAX); // CALL* AX 1662 con((ulong)&R, RTMP); // MOVL $R, RTMP 1663 modrm(Ostw, O(REG, SP), RTMP, RFP); // MOVL RFP, R.SP 1664 modrm(Oldw, O(Frame, lr), RFP, RAX); // MOVL lr(RFP), RAX 1665 modrm(Ostw, O(REG, PC), RTMP, RAX); // MOVL RAX, R.PC 1666 modrm(Oldw, O(Frame, fp), RFP, RFP); // MOVL fp(RFP), RFP 1667 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP 1668 genb(Opopl+RDI); // return to uncompiled code 1669 genb(Opopl+RSI); 1670 genb(Opopl+RDX); 1671 genb(Opopl+RCX); 1672 genb(Opopl+RBX); 1673 genb(Oret); 1674 // label: 1675 lpunt = code - s; 1676 1677 i.add = AXNON; 1678 punt(&i, TCHECK|NEWPC, optab[IRET]); 1679 } 1680 1681 static void 1682 maccolr(void) 1683 { 1684 modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RBX, 0); 1685 gen2(Oldw, (0<<6)|(RAX<<3)|5); // INCL ref(BX) 1686 genw((ulong)&mutator); // MOVL mutator, RAX 1687 modrm(Ocmpw, O(Heap, color)-sizeof(Heap), RBX, RAX); 1688 gen2(Ojneb, 0x01); // CMPL color(BX), RAX 1689 genb(Oret); // MOVL $propagator,RTMP 1690 con(propagator, RAX); // MOVL RTMP, color(BX) 1691 modrm(Ostw, O(Heap, color)-sizeof(Heap), RBX, RAX); 1692 gen2(Ostw, (0<<6)|(RAX<<3)|5); // can be any !0 value 1693 genw((ulong)&nprop); // MOVL RBX, nprop 1694 genb(Oret); 1695 } 1696 1697 static void 1698 macmcal(void) 1699 { 1700 uchar *label, *mlnil, *interp; 1701 1702 cmpl(RAX, (ulong)H); 1703 gen2(Ojeqb, 0); 1704 mlnil = code - 1; 1705 modrm(0x83, O(Modlink, prog), RTA, 7); // CMPL $0, ml->prog 1706 genb(0x00); 1707 gen2(Ojneb, 0); // JNE patch 1708 label = code-1; 1709 *mlnil = code-mlnil-1; 1710 modrm(Ostw, O(REG, FP), RTMP, RCX); 1711 modrm(Ostw, O(REG, dt), RTMP, RAX); 1712 bra((ulong)rmcall, Ocall); // CALL rmcall 1713 con((ulong)&R, RTMP); // MOVL $R, RTMP 1714 modrm(Oldw, O(REG, FP), RTMP, RFP); 1715 modrm(Oldw, O(REG, MP), RTMP, RMP); 1716 genb(Oret); // RET 1717 *label = code-label-1; // patch: 1718 gen2(Oldw, (3<<6)|(RFP<<3)|RCX); // MOVL CX, RFP R.FP = f 1719 modrm(Ostw, O(REG, M), RTMP, RTA); // MOVL RTA, R.M 1720 modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RTA, 0); 1721 modrm(Oldw, O(Modlink, MP), RTA, RMP); // MOVL R.M->mp, RMP 1722 modrm(Ostw, O(REG, MP), RTMP, RMP); // MOVL RMP, R.MP R.MP = ml->MP 1723 modrm(Ocmpi, O(Modlink, compiled), RTA, 7);// CMPL $0, M.compiled 1724 genb(0x00); 1725 genb(Opopl+RTA); // balance call 1726 gen2(Ojeqb, 0); // JEQ interp 1727 interp = code-1; 1728 gen2(Ojmprm, (3<<6)|(4<<3)|RAX); // JMP*L AX 1729 *interp = code-interp-1; // interp: 1730 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL FP, R.FP 1731 modrm(Ostw, O(REG, PC), RTMP, RAX); // MOVL PC, R.PC 1732 genb(Opopl+RDI); // call to uncompiled code 1733 genb(Opopl+RSI); 1734 genb(Opopl+RDX); 1735 genb(Opopl+RCX); 1736 genb(Opopl+RBX); 1737 genb(Oret); 1738 } 1739 1740 static void 1741 macfram(void) 1742 { 1743 uchar *label; 1744 1745 con((ulong)&R, RTMP); // MOVL $R, RTMP 1746 modrm(Oldw, O(REG, SP), RTMP, RAX); // MOVL R.SP, AX 1747 modrm(0x03, O(Type, size), RTA, RAX); // ADDL size(RCX), RAX 1748 modrm(0x3b, O(REG, TS), RTMP, RAX); // CMPL AX, R.TS 1749 gen2(0x7c, 0x00); // JL .+(patch) 1750 label = code-1; 1751 1752 modrm(Ostw, O(REG, s), RTMP, RTA); 1753 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP 1754 bra((ulong)extend, Ocall); // CALL extend 1755 con((ulong)&R, RTMP); 1756 modrm(Oldw, O(REG, FP), RTMP, RFP); // MOVL R.MP, RMP 1757 modrm(Oldw, O(REG, MP), RTMP, RMP); // MOVL R.FP, RFP 1758 modrm(Oldw, O(REG, s), RTMP, RCX); // MOVL R.s, *R.d 1759 genb(Oret); // RET 1760 *label = code-label-1; 1761 modrm(Oldw, O(REG, SP), RTMP, RCX); // MOVL R.SP, CX 1762 modrm(Ostw, O(REG, SP), RTMP, RAX); // MOVL AX, R.SP 1763 1764 modrm(Ostw, O(Frame, t), RCX, RTA); // MOVL RTA, t(CX) f->t = t 1765 modrm(Omov, REGMOD*4, RCX, 0); // MOVL $0, mr(CX) f->mr 1766 genw(0); 1767 modrm(Oldw, O(Type, initialize), RTA, RTA); 1768 gen2(Ojmprm, (3<<6)|(4<<3)|RTA); // JMP*L RTA 1769 genb(Oret); // RET 1770 } 1771 1772 static void 1773 macmfra(void) 1774 { 1775 con((ulong)&R, RTMP); // MOVL $R, RTMP 1776 modrm(Ostw, O(REG, FP), RTMP, RFP); 1777 modrm(Ostw, O(REG, s), RTMP, RAX); // Save type 1778 modrm(Ostw, O(REG, d), RTMP, RTA); // Save destination 1779 bra((ulong)rmfram, Ocall); // CALL rmfram 1780 con((ulong)&R, RTMP); // MOVL $R, RTMP 1781 modrm(Oldw, O(REG, FP), RTMP, RFP); 1782 modrm(Oldw, O(REG, MP), RTMP, RMP); 1783 genb(Oret); // RET 1784 } 1785 1786 static void 1787 macrelq(void) 1788 { 1789 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL FP, R.FP 1790 genb(Opopl+RAX); 1791 modrm(Ostw, O(REG, PC), RTMP, RAX); // MOVL PC, R.PC 1792 genb(Opopl+RDI); 1793 genb(Opopl+RSI); 1794 genb(Opopl+RDX); 1795 genb(Opopl+RCX); 1796 genb(Opopl+RBX); 1797 genb(Oret); 1798 } 1799 1800 void 1801 comd(Type *t) 1802 { 1803 int i, j, m, c; 1804 1805 for(i = 0; i < t->np; i++) { 1806 c = t->map[i]; 1807 j = i<<5; 1808 for(m = 0x80; m != 0; m >>= 1) { 1809 if(c & m) { 1810 modrm(Oldw, j, RFP, RAX); 1811 rbra(macro[MacFRP], Ocall); 1812 } 1813 j += sizeof(WORD*); 1814 } 1815 } 1816 genb(Oret); 1817 } 1818 1819 void 1820 comi(Type *t) 1821 { 1822 int i, j, m, c; 1823 1824 con((ulong)H, RAX); 1825 for(i = 0; i < t->np; i++) { 1826 c = t->map[i]; 1827 j = i<<5; 1828 for(m = 0x80; m != 0; m >>= 1) { 1829 if(c & m) 1830 modrm(Ostw, j, RCX, RAX); 1831 j += sizeof(WORD*); 1832 } 1833 } 1834 genb(Oret); 1835 } 1836 1837 void 1838 typecom(Type *t) 1839 { 1840 int n; 1841 uchar *tmp; 1842 1843 if(t == nil || t->initialize != 0) 1844 return; 1845 1846 tmp = mallocz(4096*sizeof(uchar), 0); 1847 if(tmp == nil) 1848 error(exNomem); 1849 1850 code = tmp; 1851 comi(t); 1852 n = code - tmp; 1853 code = tmp; 1854 comd(t); 1855 n += code - tmp; 1856 free(tmp); 1857 1858 code = mallocz(n, 0); 1859 if(code == nil) 1860 return; 1861 1862 t->initialize = code; 1863 comi(t); 1864 t->destroy = code; 1865 comd(t); 1866 1867 if(cflag > 3) 1868 print("typ= %.8lux %4d i %.8lux d %.8lux asm=%d\n", 1869 (ulong)t, t->size, (ulong)t->initialize, (ulong)t->destroy, n); 1870 1871 segflush(t->initialize, n); 1872 } 1873 1874 static void 1875 patchex(Module *m, ulong *p) 1876 { 1877 Handler *h; 1878 Except *e; 1879 1880 if((h = m->htab) == nil) 1881 return; 1882 for( ; h->etab != nil; h++){ 1883 h->pc1 = p[h->pc1]; 1884 h->pc2 = p[h->pc2]; 1885 for(e = h->etab; e->s != nil; e++) 1886 e->pc = p[e->pc]; 1887 if(e->pc != -1) 1888 e->pc = p[e->pc]; 1889 } 1890 } 1891 1892 int 1893 compile(Module *m, int size, Modlink *ml) 1894 { 1895 ulong v; 1896 Modl *e; 1897 Link *l; 1898 int i, n; 1899 uchar *s, *tmp; 1900 1901 base = nil; 1902 patch = mallocz(size*sizeof(*patch), 0); 1903 tinit = malloc(m->ntype*sizeof(*tinit)); 1904 tmp = mallocz(4096*sizeof(uchar),0); 1905 if(tinit == nil || patch == nil || tmp == nil) 1906 goto bad; 1907 1908 preamble(); 1909 1910 mod = m; 1911 n = 0; 1912 pass = 0; 1913 nlit = 0; 1914 1915 for(i = 0; i < size; i++) { 1916 code = tmp; 1917 comp(&m->prog[i]); 1918 patch[i] = n; 1919 n += code - tmp; 1920 } 1921 1922 for(i = 0; i < nelem(mactab); i++) { 1923 code = tmp; 1924 mactab[i].gen(); 1925 macro[mactab[i].idx] = n; 1926 n += code - tmp; 1927 } 1928 1929 n = (n+3)&~3; 1930 1931 nlit *= sizeof(ulong); 1932 base = mallocz(n + nlit, 0); 1933 if(base == nil) 1934 goto bad; 1935 1936 if(cflag > 3) 1937 print("dis=%5d %5d 386=%5d asm=%.8lux lit=%d: %s\n", 1938 size, size*sizeof(Inst), n, (ulong)base, nlit, m->name); 1939 1940 pass++; 1941 nlit = 0; 1942 litpool = (ulong*)(base+n); 1943 code = base; 1944 1945 for(i = 0; i < size; i++) { 1946 s = code; 1947 comp(&m->prog[i]); 1948 if(cflag > 4) { 1949 print("%D\n", &m->prog[i]); 1950 das(s, code-s); 1951 } 1952 } 1953 1954 for(i = 0; i < nelem(mactab); i++) 1955 mactab[i].gen(); 1956 1957 v = (ulong)base; 1958 for(l = m->ext; l->name; l++) { 1959 l->u.pc = (Inst*)(v+patch[l->u.pc-m->prog]); 1960 typecom(l->frame); 1961 } 1962 if(ml != nil) { 1963 e = &ml->links[0]; 1964 for(i = 0; i < ml->nlinks; i++) { 1965 e->u.pc = (Inst*)(v+patch[e->u.pc-m->prog]); 1966 typecom(e->frame); 1967 e++; 1968 } 1969 } 1970 for(i = 0; i < m->ntype; i++) { 1971 if(tinit[i] != 0) 1972 typecom(m->type[i]); 1973 } 1974 patchex(m, patch); 1975 m->entry = (Inst*)(v+patch[mod->entry-mod->prog]); 1976 free(patch); 1977 free(tinit); 1978 free(tmp); 1979 free(m->prog); 1980 m->prog = (Inst*)base; 1981 m->compiled = 1; 1982 segflush(base, n*sizeof(base)); 1983 return 1; 1984 bad: 1985 free(patch); 1986 free(tinit); 1987 free(tmp); 1988 free(base); 1989 return 0; 1990 } 1991 1992