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, 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 genb(0x0f); 1414 gen2(Omovzxw, (1<<6)|(0<<3)|4); 1415 gen2((1<<6)|(RBX<<3)|RAX, O(String, data)); 1416 opwst(i, Ostw, RAX); 1417 break; 1418 } 1419 modrm(Ocmpi, O(String, len), RAX, 7); 1420 genb(0); 1421 gen2(Ojltb, 7); 1422 genb(0x0f); 1423 gen2(Omovzxb, (1<<6)|(0<<3)|4); /* movzbx 12(AX)(RBX*1), RAX */ 1424 gen2((0<<6)|(RBX<<3)|RAX, O(String, data)); 1425 gen2(Ojmpb, 5); 1426 genb(0x0f); 1427 gen2(Omovzxw, (1<<6)|(0<<3)|4); /* movzwx 12(AX)(RBX*4), RAX */ 1428 gen2((1<<6)|(RBX<<3)|RAX, O(String, data)); 1429 opwst(i, Ostw, RAX); 1430 break; 1431 case ICASE: 1432 comcase(i, 1); 1433 break; 1434 case IMOVL: 1435 opwld(i, Olea, RTA); 1436 opwst(i, Olea, RTMP); 1437 modrm(Oldw, 0, RTA, RAX); 1438 modrm(Ostw, 0, RTMP, RAX); 1439 modrm(Oldw, 4, RTA, RAX); 1440 modrm(Ostw, 4, RTMP, RAX); 1441 break; 1442 case IADDL: 1443 larith(i, 0x03, 0x13); 1444 break; 1445 case ISUBL: 1446 larith(i, 0x2b, 0x1b); 1447 break; 1448 case IORL: 1449 larith(i, 0x0b, 0x0b); 1450 break; 1451 case IANDL: 1452 larith(i, 0x23, 0x23); 1453 break; 1454 case IXORL: 1455 larith(i, 0x33, 0x33); 1456 break; 1457 case IBEQL: 1458 cbral(i, Ojnel, Ojeql, ANDAND); 1459 break; 1460 case IBNEL: 1461 cbral(i, Ojnel, Ojnel, OROR); 1462 break; 1463 case IBLEL: 1464 cbral(i, Ojltl, Ojbel, EQAND); 1465 break; 1466 case IBGTL: 1467 cbral(i, Ojgtl, Ojal, EQAND); 1468 break; 1469 case IBLTL: 1470 cbral(i, Ojltl, Ojbl, EQAND); 1471 break; 1472 case IBGEL: 1473 cbral(i, Ojgtl, Ojael, EQAND); 1474 break; 1475 case ISHLL: 1476 shll(i); 1477 break; 1478 case ISHRL: 1479 shrl(i); 1480 break; 1481 case IRAISE: 1482 punt(i, SRCOP|WRTPC|NEWPC, optab[i->op]); 1483 break; 1484 case IMULX: 1485 case IDIVX: 1486 case ICVTXX: 1487 case IMULX0: 1488 case IDIVX0: 1489 case ICVTXX0: 1490 case IMULX1: 1491 case IDIVX1: 1492 case ICVTXX1: 1493 case ICVTFX: 1494 case ICVTXF: 1495 case IEXPW: 1496 case IEXPL: 1497 case IEXPF: 1498 punt(i, SRCOP|DSTOP|THREOP, optab[i->op]); 1499 break; 1500 case ISELF: 1501 punt(i, DSTOP, optab[i->op]); 1502 break; 1503 } 1504 } 1505 1506 static void 1507 preamble(void) 1508 { 1509 if(comvec) 1510 return; 1511 1512 comvec = malloc(32); 1513 if(comvec == nil) 1514 error(exNomem); 1515 code = (uchar*)comvec; 1516 1517 genb(Opushl+RBX); 1518 genb(Opushl+RCX); 1519 genb(Opushl+RDX); 1520 genb(Opushl+RSI); 1521 genb(Opushl+RDI); 1522 con((ulong)&R, RTMP); 1523 modrm(Oldw, O(REG, FP), RTMP, RFP); 1524 modrm(Oldw, O(REG, MP), RTMP, RMP); 1525 modrm(Ojmprm, O(REG, PC), RTMP, 4); 1526 1527 segflush(comvec, 32); 1528 } 1529 1530 static void 1531 maccase(void) 1532 { 1533 uchar *loop, *def, *lab1; 1534 1535 modrm(Oldw, 0, RSI, RDX); // n = t[0] 1536 modrm(Olea, 4, RSI, RSI); // t = &t[1] 1537 gen2(Oldw, (3<<6)|(RBX<<3)|RDX); // MOVL DX, BX 1538 gen2(Oshr, (3<<6)|(4<<3)|RBX); // SHL BX,1 1539 gen2(0x01, (3<<6)|(RDX<<3)|RBX); // ADDL DX, BX BX = n*3 1540 gen2(Opushrm, (0<<6)|(6<<3)|4); 1541 genb((2<<6)|(RBX<<3)|RSI); // PUSHL 0(SI)(BX*4) 1542 loop = code; 1543 cmpl(RDX, 0); 1544 gen2(Ojleb, 0); 1545 def = code-1; 1546 gen2(Oldw, (3<<6)|(RCX<<3)|RDX); // MOVL DX, CX n2 = n 1547 gen2(Oshr, (3<<6)|(5<<3)|RCX); // SHR CX,1 n2 = n2>>1 1548 gen2(Oldw, (3<<6)|(RBX<<3)|RCX); // MOVL CX, BX 1549 gen2(Oshr, (3<<6)|(4<<3)|RBX); // SHL BX,1 1550 gen2(0x01, (3<<6)|(RCX<<3)|RBX); // ADDL CX, BX BX = n2*3 1551 gen2(0x3b, (0<<6)|(RAX<<3)|4); 1552 genb((2<<6)|(RBX<<3)|RSI); // CMPL AX, 0(SI)(BX*4) 1553 gen2(Ojgeb, 0); // JGE lab1 1554 lab1 = code-1; 1555 gen2(Oldw, (3<<6)|(RDX<<3)|RCX); 1556 gen2(Ojmpb, loop-code-2); 1557 *lab1 = code-lab1-1; // lab1: 1558 gen2(0x3b, (1<<6)|(RAX<<3)|4); 1559 gen2((2<<6)|(RBX<<3)|RSI, 4); // CMPL AX, 4(SI)(BX*4) 1560 gen2(Ojltb, 0); 1561 lab1 = code-1; 1562 gen2(Olea, (1<<6)|(RSI<<3)|4); 1563 gen2((2<<6)|(RBX<<3)|RSI, 12); // LEA 12(SI)(RBX*4), RSI 1564 gen2(0x2b, (3<<6)|(RDX<<3)|RCX); // SUBL CX, DX n -= n2 1565 gen2(Odecrm, (3<<6)|(1<<3)|RDX); // DECL DX n -= 1 1566 gen2(Ojmpb, loop-code-2); 1567 *lab1 = code-lab1-1; // lab1: 1568 gen2(Oldw, (1<<6)|(RAX<<3)|4); 1569 gen2((2<<6)|(RBX<<3)|RSI, 8); // MOVL 8(SI)(BX*4), AX 1570 genb(Opopl+RSI); // ditch default 1571 genb(Opopl+RSI); 1572 gen2(Ojmprm, (3<<6)|(4<<3)|RAX); // JMP*L AX 1573 *def = code-def-1; // def: 1574 genb(Opopl+RAX); // ditch default 1575 genb(Opopl+RSI); 1576 gen2(Ojmprm, (3<<6)|(4<<3)|RAX); 1577 } 1578 1579 static void 1580 macfrp(void) 1581 { 1582 cmpl(RAX, (ulong)H); // CMPL AX, $H 1583 gen2(Ojneb, 0x01); // JNE .+1 1584 genb(Oret); // RET 1585 modrm(0x83, O(Heap, ref)-sizeof(Heap), RAX, 7); 1586 genb(0x01); // CMP AX.ref, $1 1587 gen2(Ojeqb, 0x04); // JNE .+4 1588 modrm(Odecrm, O(Heap, ref)-sizeof(Heap), RAX, 1); 1589 genb(Oret); // DEC AX.ref 1590 // RET 1591 con((ulong)&R, RTMP); // MOV $R, RTMP 1592 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP 1593 modrm(Ostw, O(REG, s), RTMP, RAX); // MOVL RAX, R.s 1594 bra((ulong)rdestroy, Ocall); // CALL rdestroy 1595 con((ulong)&R, RTMP); // MOVL $R, RTMP 1596 modrm(Oldw, O(REG, FP), RTMP, RFP); // MOVL R.MP, RMP 1597 modrm(Oldw, O(REG, MP), RTMP, RMP); // MOVL R.FP, RFP 1598 genb(Oret); 1599 } 1600 1601 static void 1602 macret(void) 1603 { 1604 Inst i; 1605 uchar *s; 1606 static ulong lpunt, lnomr, lfrmr, linterp; 1607 1608 s = code; 1609 1610 lpunt -= 2; 1611 lnomr -= 2; 1612 lfrmr -= 2; 1613 linterp -= 2; 1614 1615 con(0, RBX); // MOVL $0, RBX 1616 modrm(Oldw, O(Frame, t), RFP, RAX); // MOVL t(FP), RAX 1617 gen2(Ocmpw, (3<<6)|(RAX<<3)|RBX); // CMPL RAX, RBX 1618 gen2(Ojeqb, lpunt-(code-s)); // JEQ lpunt 1619 modrm(Oldw, O(Type, destroy), RAX, RAX);// MOVL destroy(RAX), RAX 1620 gen2(Ocmpw, (3<<6)|(RAX<<3)|RBX); // CMPL RAX, RBX 1621 gen2(Ojeqb, lpunt-(code-s)); // JEQ lpunt 1622 modrm(Ocmpw, O(Frame, fp), RFP, RBX); // CMPL fp(FP), RBX 1623 gen2(Ojeqb, lpunt-(code-s)); // JEQ lpunt 1624 modrm(Ocmpw, O(Frame, mr), RFP, RBX); // CMPL mr(FP), RBX 1625 gen2(Ojeqb, lnomr-(code-s)); // JEQ lnomr 1626 con((ulong)&R, RTMP); // MOVL $R, RTMP 1627 modrm(Oldw, O(REG, M), RTMP, RTA); // MOVL R.M, RTA 1628 modrm(Odecrm, O(Heap, ref)-sizeof(Heap), RTA, 1); 1629 gen2(Ojneb, lfrmr-(code-s)); // JNE lfrmr 1630 modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RTA, 0); 1631 gen2(Ojmpb, lpunt-(code-s)); // JMP lpunt 1632 lfrmr = code - s; 1633 modrm(Oldw, O(Frame, mr), RFP, RTA); // MOVL mr(FP), RTA 1634 modrm(Ostw, O(REG, M), RTMP, RTA); // MOVL RTA, R.M 1635 modrm(Oldw, O(Modlink, MP), RTA, RMP); // MOVL MP(RTA), RMP 1636 modrm(Ostw, O(REG, MP), RTMP, RMP); // MOVL RMP, R.MP 1637 modrm(Ocmpi, O(Modlink, compiled), RTA, 7);// CMPL $0, M.compiled 1638 genb(0x00); 1639 gen2(Ojeqb, linterp-(code-s)); // JEQ linterp 1640 lnomr = code - s; 1641 gen2(Ocallrm, (3<<6)|(2<<3)|RAX); // CALL* AX 1642 con((ulong)&R, RTMP); // MOVL $R, RTMP 1643 modrm(Ostw, O(REG, SP), RTMP, RFP); // MOVL RFP, R.SP 1644 modrm(Oldw, O(Frame, lr), RFP, RAX); // MOVL lr(RFP), RAX 1645 modrm(Oldw, O(Frame, fp), RFP, RFP); // MOVL fp(RFP), RFP 1646 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP 1647 gen2(Ojmprm, (3<<6)|(4<<3)|RAX); // JMP*L AX 1648 1649 linterp = code - s; // return to uncompiled code 1650 gen2(Ocallrm, (3<<6)|(2<<3)|RAX); // CALL* AX 1651 con((ulong)&R, RTMP); // MOVL $R, RTMP 1652 modrm(Ostw, O(REG, SP), RTMP, RFP); // MOVL RFP, R.SP 1653 modrm(Oldw, O(Frame, lr), RFP, RAX); // MOVL lr(RFP), RAX 1654 modrm(Ostw, O(REG, PC), RTMP, RAX); // MOVL RAX, R.PC 1655 modrm(Oldw, O(Frame, fp), RFP, RFP); // MOVL fp(RFP), RFP 1656 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP 1657 genb(Opopl+RDI); // return to uncompiled code 1658 genb(Opopl+RSI); 1659 genb(Opopl+RDX); 1660 genb(Opopl+RCX); 1661 genb(Opopl+RBX); 1662 genb(Oret); 1663 // label: 1664 lpunt = code - s; 1665 1666 i.add = AXNON; 1667 punt(&i, TCHECK|NEWPC, optab[IRET]); 1668 } 1669 1670 static void 1671 maccolr(void) 1672 { 1673 modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RBX, 0); 1674 gen2(Oldw, (0<<6)|(RAX<<3)|5); // INCL ref(BX) 1675 genw((ulong)&mutator); // MOVL mutator, RAX 1676 modrm(Ocmpw, O(Heap, color)-sizeof(Heap), RBX, RAX); 1677 gen2(Ojneb, 0x01); // CMPL color(BX), RAX 1678 genb(Oret); // MOVL $propagator,RTMP 1679 con(propagator, RAX); // MOVL RTMP, color(BX) 1680 modrm(Ostw, O(Heap, color)-sizeof(Heap), RBX, RAX); 1681 gen2(Ostw, (0<<6)|(RAX<<3)|5); // can be any !0 value 1682 genw((ulong)&nprop); // MOVL RBX, nprop 1683 genb(Oret); 1684 } 1685 1686 static void 1687 macmcal(void) 1688 { 1689 uchar *label, *mlnil, *interp; 1690 1691 cmpl(RAX, (ulong)H); 1692 gen2(Ojeqb, 0); 1693 mlnil = code - 1; 1694 modrm(0x83, O(Modlink, prog), RTA, 7); // CMPL $0, ml->prog 1695 genb(0x00); 1696 gen2(Ojneb, 0); // JNE patch 1697 label = code-1; 1698 *mlnil = code-mlnil-1; 1699 modrm(Ostw, O(REG, FP), RTMP, RCX); 1700 modrm(Ostw, O(REG, dt), RTMP, RAX); 1701 bra((ulong)rmcall, Ocall); // CALL rmcall 1702 con((ulong)&R, RTMP); // MOVL $R, RTMP 1703 modrm(Oldw, O(REG, FP), RTMP, RFP); 1704 modrm(Oldw, O(REG, MP), RTMP, RMP); 1705 genb(Oret); // RET 1706 *label = code-label-1; // patch: 1707 gen2(Oldw, (3<<6)|(RFP<<3)|RCX); // MOVL CX, RFP R.FP = f 1708 modrm(Ostw, O(REG, M), RTMP, RTA); // MOVL RTA, R.M 1709 modrm(Oincrm, O(Heap, ref)-sizeof(Heap), RTA, 0); 1710 modrm(Oldw, O(Modlink, MP), RTA, RMP); // MOVL R.M->mp, RMP 1711 modrm(Ostw, O(REG, MP), RTMP, RMP); // MOVL RMP, R.MP R.MP = ml->MP 1712 modrm(Ocmpi, O(Modlink, compiled), RTA, 7);// CMPL $0, M.compiled 1713 genb(0x00); 1714 genb(Opopl+RTA); // balance call 1715 gen2(Ojeqb, 0); // JEQ interp 1716 interp = code-1; 1717 gen2(Ojmprm, (3<<6)|(4<<3)|RAX); // JMP*L AX 1718 *interp = code-interp-1; // interp: 1719 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL FP, R.FP 1720 modrm(Ostw, O(REG, PC), RTMP, RAX); // MOVL PC, R.PC 1721 genb(Opopl+RDI); // call to uncompiled code 1722 genb(Opopl+RSI); 1723 genb(Opopl+RDX); 1724 genb(Opopl+RCX); 1725 genb(Opopl+RBX); 1726 genb(Oret); 1727 } 1728 1729 static void 1730 macfram(void) 1731 { 1732 uchar *label; 1733 1734 con((ulong)&R, RTMP); // MOVL $R, RTMP 1735 modrm(Oldw, O(REG, SP), RTMP, RAX); // MOVL R.SP, AX 1736 modrm(0x03, O(Type, size), RTA, RAX); // ADDL size(RCX), RAX 1737 modrm(0x3b, O(REG, TS), RTMP, RAX); // CMPL AX, R.TS 1738 gen2(0x7c, 0x00); // JL .+(patch) 1739 label = code-1; 1740 1741 modrm(Ostw, O(REG, s), RTMP, RTA); 1742 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL RFP, R.FP 1743 bra((ulong)extend, Ocall); // CALL extend 1744 con((ulong)&R, RTMP); 1745 modrm(Oldw, O(REG, FP), RTMP, RFP); // MOVL R.MP, RMP 1746 modrm(Oldw, O(REG, MP), RTMP, RMP); // MOVL R.FP, RFP 1747 modrm(Oldw, O(REG, s), RTMP, RCX); // MOVL R.s, *R.d 1748 genb(Oret); // RET 1749 *label = code-label-1; 1750 modrm(Oldw, O(REG, SP), RTMP, RCX); // MOVL R.SP, CX 1751 modrm(Ostw, O(REG, SP), RTMP, RAX); // MOVL AX, R.SP 1752 1753 modrm(Ostw, O(Frame, t), RCX, RTA); // MOVL RTA, t(CX) f->t = t 1754 modrm(Omov, REGMOD*4, RCX, 0); // MOVL $0, mr(CX) f->mr 1755 genw(0); 1756 modrm(Oldw, O(Type, initialize), RTA, RTA); 1757 gen2(Ojmprm, (3<<6)|(4<<3)|RTA); // JMP*L RTA 1758 genb(Oret); // RET 1759 } 1760 1761 static void 1762 macmfra(void) 1763 { 1764 con((ulong)&R, RTMP); // MOVL $R, RTMP 1765 modrm(Ostw, O(REG, FP), RTMP, RFP); 1766 modrm(Ostw, O(REG, s), RTMP, RAX); // Save type 1767 modrm(Ostw, O(REG, d), RTMP, RTA); // Save destination 1768 bra((ulong)rmfram, Ocall); // CALL rmfram 1769 con((ulong)&R, RTMP); // MOVL $R, RTMP 1770 modrm(Oldw, O(REG, FP), RTMP, RFP); 1771 modrm(Oldw, O(REG, MP), RTMP, RMP); 1772 genb(Oret); // RET 1773 } 1774 1775 static void 1776 macrelq(void) 1777 { 1778 modrm(Ostw, O(REG, FP), RTMP, RFP); // MOVL FP, R.FP 1779 genb(Opopl+RAX); 1780 modrm(Ostw, O(REG, PC), RTMP, RAX); // MOVL PC, R.PC 1781 genb(Opopl+RDI); 1782 genb(Opopl+RSI); 1783 genb(Opopl+RDX); 1784 genb(Opopl+RCX); 1785 genb(Opopl+RBX); 1786 genb(Oret); 1787 } 1788 1789 void 1790 comd(Type *t) 1791 { 1792 int i, j, m, c; 1793 1794 for(i = 0; i < t->np; i++) { 1795 c = t->map[i]; 1796 j = i<<5; 1797 for(m = 0x80; m != 0; m >>= 1) { 1798 if(c & m) { 1799 modrm(Oldw, j, RFP, RAX); 1800 rbra(macro[MacFRP], Ocall); 1801 } 1802 j += sizeof(WORD*); 1803 } 1804 } 1805 genb(Oret); 1806 } 1807 1808 void 1809 comi(Type *t) 1810 { 1811 int i, j, m, c; 1812 1813 con((ulong)H, RAX); 1814 for(i = 0; i < t->np; i++) { 1815 c = t->map[i]; 1816 j = i<<5; 1817 for(m = 0x80; m != 0; m >>= 1) { 1818 if(c & m) 1819 modrm(Ostw, j, RCX, RAX); 1820 j += sizeof(WORD*); 1821 } 1822 } 1823 genb(Oret); 1824 } 1825 1826 void 1827 typecom(Type *t) 1828 { 1829 int n; 1830 uchar *tmp; 1831 1832 if(t == nil || t->initialize != 0) 1833 return; 1834 1835 tmp = mallocz(4096*sizeof(uchar), 0); 1836 if(tmp == nil) 1837 error(exNomem); 1838 1839 code = tmp; 1840 comi(t); 1841 n = code - tmp; 1842 code = tmp; 1843 comd(t); 1844 n += code - tmp; 1845 free(tmp); 1846 1847 code = mallocz(n, 0); 1848 if(code == nil) 1849 return; 1850 1851 t->initialize = code; 1852 comi(t); 1853 t->destroy = code; 1854 comd(t); 1855 1856 if(cflag > 3) 1857 print("typ= %.8lux %4d i %.8lux d %.8lux asm=%d\n", 1858 (ulong)t, t->size, (ulong)t->initialize, (ulong)t->destroy, n); 1859 1860 segflush(t->initialize, n); 1861 } 1862 1863 static void 1864 patchex(Module *m, ulong *p) 1865 { 1866 Handler *h; 1867 Except *e; 1868 1869 if((h = m->htab) == nil) 1870 return; 1871 for( ; h->etab != nil; h++){ 1872 h->pc1 = p[h->pc1]; 1873 h->pc2 = p[h->pc2]; 1874 for(e = h->etab; e->s != nil; e++) 1875 e->pc = p[e->pc]; 1876 if(e->pc != -1) 1877 e->pc = p[e->pc]; 1878 } 1879 } 1880 1881 int 1882 compile(Module *m, int size, Modlink *ml) 1883 { 1884 ulong v; 1885 Modl *e; 1886 Link *l; 1887 int i, n; 1888 uchar *s, *tmp; 1889 1890 base = nil; 1891 patch = mallocz(size*sizeof(*patch), 0); 1892 tinit = malloc(m->ntype*sizeof(*tinit)); 1893 tmp = mallocz(4096*sizeof(uchar),0); 1894 if(tinit == nil || patch == nil || tmp == nil) 1895 goto bad; 1896 1897 preamble(); 1898 1899 mod = m; 1900 n = 0; 1901 pass = 0; 1902 nlit = 0; 1903 1904 for(i = 0; i < size; i++) { 1905 code = tmp; 1906 comp(&m->prog[i]); 1907 patch[i] = n; 1908 n += code - tmp; 1909 } 1910 1911 for(i = 0; i < nelem(mactab); i++) { 1912 code = tmp; 1913 mactab[i].gen(); 1914 macro[mactab[i].idx] = n; 1915 n += code - tmp; 1916 } 1917 1918 n = (n+3)&~3; 1919 1920 nlit *= sizeof(ulong); 1921 base = mallocz(n + nlit, 0); 1922 if(base == nil) 1923 goto bad; 1924 1925 if(cflag > 3) 1926 print("dis=%5d %5d 386=%5d asm=%.8lux lit=%d: %s\n", 1927 size, size*sizeof(Inst), n, (ulong)base, nlit, m->name); 1928 1929 pass++; 1930 nlit = 0; 1931 litpool = (ulong*)(base+n); 1932 code = base; 1933 1934 for(i = 0; i < size; i++) { 1935 s = code; 1936 comp(&m->prog[i]); 1937 if(cflag > 4) { 1938 print("%D\n", &m->prog[i]); 1939 das(s, code-s); 1940 } 1941 } 1942 1943 for(i = 0; i < nelem(mactab); i++) 1944 mactab[i].gen(); 1945 1946 v = (ulong)base; 1947 for(l = m->ext; l->name; l++) { 1948 l->u.pc = (Inst*)(v+patch[l->u.pc-m->prog]); 1949 typecom(l->frame); 1950 } 1951 if(ml != nil) { 1952 e = &ml->links[0]; 1953 for(i = 0; i < ml->nlinks; i++) { 1954 e->u.pc = (Inst*)(v+patch[e->u.pc-m->prog]); 1955 typecom(e->frame); 1956 e++; 1957 } 1958 } 1959 for(i = 0; i < m->ntype; i++) { 1960 if(tinit[i] != 0) 1961 typecom(m->type[i]); 1962 } 1963 patchex(m, patch); 1964 m->entry = (Inst*)(v+patch[mod->entry-mod->prog]); 1965 free(patch); 1966 free(tinit); 1967 free(tmp); 1968 free(m->prog); 1969 m->prog = (Inst*)base; 1970 m->compiled = 1; 1971 segflush(base, n*sizeof(base)); 1972 return 1; 1973 bad: 1974 free(patch); 1975 free(tinit); 1976 free(tmp); 1977 free(base); 1978 return 0; 1979 } 1980 1981