Changeset 595
- Timestamp:
- 08/03/10 08:49:16 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cgcod.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cgen.c (modified) (2 diffs)
- branches/dmd-1.x/src/backend/cod1.c (modified) (4 diffs)
- branches/dmd-1.x/src/backend/cod3.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/code.h (modified) (2 diffs)
- trunk/src/backend/cgcod.c (modified) (1 diff)
- trunk/src/backend/cgen.c (modified) (2 diffs)
- trunk/src/backend/cod1.c (modified) (4 diffs)
- trunk/src/backend/cod3.c (modified) (1 diff)
- trunk/src/backend/code.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cgcod.c
r579 r595 1782 1782 #define allocreg(a,b,c) allocreg((a),(b),(c),__LINE__,__FILE__) 1783 1783 #endif 1784 1784 { regm_t r,s; 1785 1785 regm_t retregs; 1786 1786 unsigned reg; 1787 1787 unsigned msreg,lsreg; 1788 1788 int count; 1789 1789 unsigned size; 1790 1790 1791 1791 #if 0 1792 1792 // if (pass == PASSfinal) 1793 1793 { dbg_printf("allocreg %s,%d: regcon.mvar %s regcon.cse.mval %s msavereg %s *pretregs %s tym ", 1794 1794 file,line,regm_str(regcon.mvar),regm_str(regcon.cse.mval), 1795 1795 regm_str(msavereg),regm_str(*pretregs)); 1796 1796 WRTYxx(tym); 1797 1797 dbg_printf("\n"); 1798 1798 } 1799 1799 #endif 1800 1800 tym = tybasic(tym); 1801 1801 size = tysize[tym]; 1802 *pretregs &= mES | allregs ;1802 *pretregs &= mES | allregs | XMMREGS; 1803 1803 retregs = *pretregs; 1804 1804 if ((retregs & regcon.mvar) == retregs) // if exactly in reg vars 1805 1805 { 1806 1806 if (size <= REGSIZE) 1807 1807 { *preg = findreg(retregs); 1808 1808 assert(retregs == mask[*preg]); /* no more bits are set */ 1809 1809 } 1810 1810 else if (size <= 2 * REGSIZE) 1811 1811 { *preg = findregmsw(retregs); 1812 1812 assert(retregs & mLSW); 1813 1813 } 1814 1814 else 1815 1815 assert(0); 1816 1816 return getregs(retregs); 1817 1817 } 1818 1818 count = 0; 1819 1819 L1: 1820 1820 //printf("L1: allregs = x%x, *pretregs = x%x\n", allregs, *pretregs); 1821 1821 assert(++count < 10); /* fail instead of hanging if blocked */ 1822 1822 s = retregs & mES; branches/dmd-1.x/src/backend/cgen.c
r577 r595 45 45 void code_orflag(code *c,unsigned flag) 46 46 { 47 47 if (flag && c) 48 48 { while (c->next) 49 49 c = c->next; 50 50 c->Iflags |= flag; 51 51 } 52 52 } 53 53 54 54 /***************************** 55 55 * Set rex bits on last code in list. 56 56 */ 57 57 58 58 void code_orrex(code *c,unsigned rex) 59 59 { 60 60 if (rex && c) 61 61 { while (c->next) 62 62 c = c->next; 63 63 c->Irex |= rex; 64 64 } 65 } 66 67 /************************************** 68 * Set the opcode fields in cs. 69 * This is ridiculously complex, cs.Iop should 70 * just be an unsigned. 71 */ 72 code *setOpcode(code *c, code *cs, unsigned op) 73 { 74 cs->Iflags = 0; 75 if (op > 0xFF) 76 { 77 switch (op & 0xFF0000) 78 { 79 case 0: 80 break; 81 case 0x660000: 82 cs->Iflags = CFopsize; 83 break; 84 case 0xF20000: // REPNE 85 case 0xF30000: // REP/REPE 86 c = gen1(c, op >> 16); 87 break; 88 } 89 cs->Iop = op >> 8; 90 cs->Iop2 = op & 0xFF; 91 } 92 else 93 cs->Iop = op; 94 return c; 65 95 } 66 96 67 97 /***************************** 68 98 * Concatenate two code lists together. Return pointer to result. 69 99 */ 70 100 71 101 #if TX86 && __INTSIZE == 4 && __SC__ 72 102 __declspec(naked) code * __pascal cat(code *c1,code *c2) 73 103 { 74 104 _asm 75 105 { 76 106 mov EAX,c1-4[ESP] 77 107 mov ECX,c2-4[ESP] 78 108 test EAX,EAX 79 109 jne L6D 80 110 mov EAX,ECX 81 111 ret 8 82 112 83 113 L6D: mov EDX,EAX 84 114 cmp dword ptr [EAX],0 … … 364 394 { cs.Iop = op >> 8; 365 395 cs.Iop2 = op & 0xFF; 366 396 } 367 397 else 368 398 cs.Iop = op; 369 399 cs.Iea = ea; 370 400 cs.Iflags = CFoff; 371 401 cs.IFL2 = FLconst; 372 402 cs.IEV2.Vsize_t = EV2; 373 403 return gen(c,&cs); 374 404 } 375 405 376 406 /***************** 377 407 * Generate code. 378 408 */ 379 409 380 410 code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 381 411 { code cs; 382 412 383 413 assert(FL1 < FLMAX); 384 assert(op < 256); 385 cs.Iop = op; 414 if (op > 0xFF) 415 { 416 c = setOpcode(c, &cs, op); 417 cs.Iflags |= CFoff; 418 } 419 else 420 { cs.Iop = op; 421 cs.Iflags = CFoff; 422 } 386 423 cs.Iea = ea; 387 cs.Iflags = CFoff;388 424 cs.IFL1 = FL1; 389 425 cs.IEV1.Vsize_t = EV1; 390 426 return gen(c,&cs); 391 427 } 392 428 393 429 /***************** 394 430 * Generate code. 395 431 */ 396 432 397 433 code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 398 434 { code cs; 399 435 400 436 assert(FL1 < FLMAX); 401 437 assert(op < 256); 402 438 cs.Iop = op; 403 439 cs.Iea = ea; 404 440 cs.Iflags = CFoff; 405 441 cs.IFL1 = FL1; 406 442 cs.IEV1.Vsize_t = EV1; 407 443 assert(FL2 < FLMAX); branches/dmd-1.x/src/backend/cod1.c
r592 r595 538 538 539 539 /****************************** 540 540 * Routine to aid in setting things up for gen(). 541 541 * Look for common subexpression. 542 542 * Can handle indirection operators, but not if they're common subs. 543 543 * Input: 544 544 * e -> elem where we get some of the data from 545 545 * cs -> partially filled code to add 546 546 * op = opcode 547 547 * reg = reg field of (mod reg r/m) 548 548 * offset = data to be added to Voffset field 549 549 * keepmsk = mask of registers we must not destroy 550 550 * desmsk = mask of registers destroyed by executing the instruction 551 551 * Returns: 552 552 * pointer to code generated 553 553 */ 554 554 555 555 code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 556 556 regm_t keepmsk,regm_t desmsk) 557 557 { 558 code *c,*cg,*cd ;558 code *c,*cg,*cd,*cprefix; 559 559 560 560 #ifdef DEBUG 561 561 if (debugw) 562 562 printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%lld keepmsk=x%x desmsk=x%x\n", 563 563 e,cs,op,reg,(unsigned long long)offset,keepmsk,desmsk); 564 564 #endif 565 565 566 566 assert(e); 567 567 cs->Iflags = 0; 568 568 cs->Irex = 0; 569 c s->Iop = op;570 if ( !I16 && op >= 0x100) // if 2 byte opcode571 { cs->Iop = op >> 8;572 cs->Iop2 = op;573 }569 cprefix = NULL; 570 if (op > 0xFF) // if 2 byte opcode 571 cprefix = setOpcode(NULL, cs, op); 572 else 573 cs->Iop = op; 574 574 tym_t tym = e->Ety; 575 575 int sz = tysize(tym); 576 576 577 577 /* Determine if location we want to get is in a register. If so, */ 578 578 /* substitute the register for the EA. */ 579 579 /* Note that operators don't go through this. CSE'd operators are */ 580 580 /* picked up by comsub(). */ 581 581 if (e->Ecount && /* if cse */ 582 582 e->Ecount != e->Ecomsub && /* and cse was generated */ 583 583 op != 0x8D && op != 0xC4 && /* and not an LEA or LES */ 584 584 (op != 0xFF || reg != 3) && /* and not CALLF MEM16 */ 585 585 (op & 0xFFF8) != 0xD8) // and not 8087 opcode 586 586 { 587 587 assert(!EOP(e)); /* can't handle this */ 588 588 regm_t rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; // possible regs 589 589 if (sz > REGSIZE) // value is in 2 or 4 registers 590 590 { 591 591 if (I16 && sz == 8) // value is in 4 registers 592 592 { static regm_t rmask[4] = { mDX,mCX,mBX,mAX }; 593 593 rm &= rmask[offset >> 1]; … … 658 658 code_orrex(cd, REX_W); 659 659 } 660 660 else if (reg == 6) // if DIV 661 661 { cd = genregs(cd,0x33,DX,DX); // XOR DX,DX 662 662 if (I64 && sz == 8) 663 663 code_orrex(cd, REX_W); 664 664 } 665 665 } 666 666 667 667 // Eliminate MOV reg,reg 668 668 if ((cs->Iop & 0xFC) == 0x88 && 669 669 (cs->Irm & 0xC7) == modregrm(3,0,reg & 7)) 670 670 { 671 671 unsigned r = cs->Irm & 7; 672 672 if (cs->Irex & REX_B) 673 673 r |= 8; 674 674 if (r == reg) 675 675 cs->Iop = NOP; 676 676 } 677 677 678 return cat4(c,cg,cd,gen( CNIL,cs));678 return cat4(c,cg,cd,gen(cprefix,cs)); 679 679 } 680 680 681 681 /************************** 682 682 * Get addressing mode. 683 683 */ 684 684 685 685 unsigned getaddrmode(regm_t idxregs) 686 686 { 687 687 unsigned mode; 688 688 689 689 if (I16) 690 690 { 691 691 mode = (idxregs & mBX) ? modregrm(2,0,7) : /* [BX] */ 692 692 (idxregs & mDI) ? modregrm(2,0,5): /* [DI] */ 693 693 (idxregs & mSI) ? modregrm(2,0,4): /* [SI] */ 694 694 (assert(0),1); 695 695 } 696 696 else 697 697 { unsigned reg = findreg(idxregs & (ALLREGS | mBP)); 698 698 mode = modregrmx(2,0,reg); … … 3626 3626 if (tyfloating(tym)) // TYdouble or TYdouble_alias 3627 3627 gen2(ce,0xD1,modregrm(3,4,reg)); // SHL reg,1 3628 3628 c = cat(c,ce); 3629 3629 3630 3630 while ((i -= REGSIZE) >= 0) 3631 3631 { 3632 3632 c1 = loadea(e,&cs,0x0B,reg,i,regm,0); // OR reg,data+i 3633 3633 if (i == 0) 3634 3634 c1->Iflags |= CFpsw; // need the flags on last OR 3635 3635 c = cat(c,c1); 3636 3636 } 3637 3637 } 3638 3638 else if (sz == LNGDBLSIZE) // TYldouble 3639 3639 return load87(e,0,pretregs,NULL,-1); 3640 3640 else 3641 3641 assert(0); 3642 3642 return c; 3643 3643 } 3644 3644 /* not for flags only */ 3645 3645 flags = *pretregs & mPSW; /* save original */ 3646 forregs = *pretregs & (mBP | ALLREGS | mES );3646 forregs = *pretregs & (mBP | ALLREGS | mES | XMMREGS); 3647 3647 if (*pretregs & mSTACK) 3648 3648 forregs |= DOUBLEREGS; 3649 3649 if (e->Eoper == OPconst) 3650 3650 { regm_t save; 3651 3651 3652 3652 if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,®)) 3653 3653 forregs = mask[reg]; 3654 3654 3655 3655 save = regcon.immed.mval; 3656 3656 c = allocreg(&forregs,®,tym); /* allocate registers */ 3657 3657 regcon.immed.mval = save; // KLUDGE! 3658 3658 if (sz <= REGSIZE) 3659 3659 { 3660 3660 if (sz == 1) 3661 3661 flags |= 1; 3662 3662 else if (!I16 && sz == SHORTSIZE && 3663 3663 !(mask[reg] & regcon.mvar) && 3664 3664 !(config.flags4 & CFG4speed) 3665 3665 ) 3666 3666 flags |= 2; … … 3744 3744 printf("forregs = x%x\n",forregs); 3745 3745 } 3746 3746 #endif 3747 3747 assert(forregs & BYTEREGS); 3748 3748 if (!I16) 3749 3749 c = cat(c,loadea(e,&cs,0x8A,reg,0,0,0)); // MOV regL,data 3750 3750 else 3751 3751 { nregm = tyuns(tym) ? BYTEREGS : mAX; 3752 3752 if (*pretregs & nregm) 3753 3753 nreg = reg; /* already allocated */ 3754 3754 else 3755 3755 c = cat(c,allocreg(&nregm,&nreg,tym)); 3756 3756 ce = loadea(e,&cs,0x8A,nreg,0,0,0); /* MOV nregL,data */ 3757 3757 c = cat(c,ce); 3758 3758 if (reg != nreg) 3759 3759 { genmovreg(c,reg,nreg); /* MOV reg,nreg */ 3760 3760 cssave(e,mask[nreg],FALSE); 3761 3761 } 3762 3762 } 3763 3763 } 3764 else if (forregs & XMMREGS) 3765 { 3766 assert(sz == 4 || sz == 8); // float or double 3767 unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; 3768 ce = loadea(e,&cs,op,reg,0,RMload,0); // MOVSS/MOVSD reg,data 3769 c = cat(c,ce); 3770 } 3764 3771 else if (sz <= REGSIZE) 3765 3772 { 3766 3773 ce = loadea(e,&cs,0x8B,reg,0,RMload,0); // MOV reg,data 3767 3774 c = cat(c,ce); 3768 3775 } 3769 3776 else if (sz <= 2 * REGSIZE && forregs & mES) 3770 3777 { 3771 3778 ce = loadea(e,&cs,0xC4,reg,0,0,mES); /* LES data */ 3772 3779 c = cat(c,ce); 3773 3780 } 3774 3781 else if (sz <= 2 * REGSIZE) 3775 3782 { 3776 3783 if (I32 && sz == 8 && 3777 3784 (*pretregs & (mSTACK | mPSW)) == mSTACK) 3778 3785 { int i; 3779 3786 3780 3787 assert(0); 3781 3788 /* Note that we allocreg(DOUBLEREGS) needlessly */ 3782 3789 stackchanged = 1; 3783 3790 i = DOUBLESIZE - REGSIZE; branches/dmd-1.x/src/backend/cod3.c
r589 r595 1747 1747 } 1748 1748 c = cat(c,c2); 1749 1749 } 1750 1750 else if (s->Sclass == SCfastpar) 1751 1751 { unsigned preg = s->Spreg; 1752 1752 1753 1753 if (s->Sfl == FLreg) 1754 1754 { // MOV reg,preg 1755 1755 c = genmovreg(c,s->Sreglsw,preg); 1756 1756 if (I64 && sz == 8) 1757 1757 code_orrex(c, REX_W); 1758 1758 } 1759 1759 else if (s->Sflags & SFLdead || 1760 1760 (!anyiasm && !(s->Sflags & SFLread) && s->Sflags & SFLunambig && 1761 1761 #if MARS 1762 1762 // This variable has been reference by a nested function 1763 1763 !(s->Stype->Tty & mTYvolatile) && 1764 1764 #endif 1765 1765 (config.flags4 & CFG4optimized || !config.fulltypes))) 1766 1766 { 1767 // Ignore it, as it is never referenced 1767 1768 ; 1768 1769 } 1769 1770 else 1770 1771 { 1771 1772 targ_size_t offset = Aoff + BPoff + s->Soffset; 1773 int op = 0x89; // MOV x[EBP],preg 1774 if (preg >= XMM0 && preg <= XMM15) 1775 { 1776 if (sz == 8) 1777 op = 0xF20F11; // MOVSD x[EBP],preg 1778 else 1779 { 1780 assert(sz == 4); 1781 op = 0xF30F11; // MOVSS x[EBP],preg 1782 } 1783 } 1772 1784 if (hasframe) 1773 1785 { 1774 1786 if (!(pushalloc && preg == pushallocreg)) 1775 { // MOV x[EBP],preg 1776 c2 = genc1(CNIL,0x89, 1787 { 1788 // MOV x[EBP],preg 1789 c2 = genc1(CNIL,op, 1777 1790 modregxrm(2,preg,BPRM),FLconst, offset); 1791 if (preg >= XMM0 && preg <= XMM15) 1792 { 1793 } 1794 else 1795 { 1778 1796 //printf("%s Aoff = %d, BPoff = %d, Soffset = %d\n", s->Sident, Aoff, BPoff, s->Soffset); 1779 // if (offset & 2) 1780 // c2->Iflags |= CFopsize; 1781 if (I64 && sz == 8) 1782 code_orrex(c2, REX_W); 1797 // if (offset & 2) 1798 // c2->Iflags |= CFopsize; 1799 if (I64 && sz == 8) 1800 code_orrex(c2, REX_W); 1801 } 1783 1802 c = cat(c, c2); 1784 1803 } 1785 1804 } 1786 1805 else 1787 1806 { 1788 code *clast;1789 1790 1807 offset += EBPtoESP; 1791 #if 11792 1808 if (!(pushalloc && preg == pushallocreg)) 1793 #else1794 if (offset == 0 && (clast = code_last(c)) != NULL &&1795 (clast->Iop & 0xF8) == 0x50)1796 1809 { 1797 clast->Iop = 0x50 + preg; 1798 } 1799 else 1800 #endif 1801 { // MOV offset[ESP],preg 1810 // MOV offset[ESP],preg 1802 1811 // BUG: byte size? 1803 c2 = genc1(CNIL,0x89,modregxrm(2,preg,4),FLconst,offset); 1804 c2->Isib = modregrm(0,4,SP); 1805 if (I64 && sz == 8) 1806 c2->Irex |= REX_W; 1807 // if (offset & 2) 1808 // c2->Iflags |= CFopsize; 1812 c2 = genc1(CNIL,op, 1813 (modregrm(0,4,SP) << 8) | 1814 modregxrm(2,preg,4),FLconst,offset); 1815 if (preg >= XMM0 && preg <= XMM15) 1816 { 1817 } 1818 else 1819 { 1820 if (I64 && sz == 8) 1821 c2->Irex |= REX_W; 1822 // if (offset & 2) 1823 // c2->Iflags |= CFopsize; 1824 } 1809 1825 c = cat(c,c2); 1810 1826 } 1811 1827 } 1812 1828 } 1813 1829 } 1814 1830 } 1815 1831 1816 1832 #if 0 && TARGET_LINUX 1817 1833 if (gotref) 1818 1834 { // position independent reference 1819 1835 c = cat(c, cod3_load_got()); 1820 1836 } 1821 1837 #endif 1822 1838 1823 1839 return c; 1824 1840 } 1825 1841 1826 1842 /******************************* 1827 1843 * Generate and return function epilog. 1828 1844 * Output: branches/dmd-1.x/src/backend/code.h
r581 r595 32 32 #define SI 6 33 33 #define DI 7 34 34 35 35 #define R8 8 36 36 #define R9 9 37 37 #define R10 10 38 38 #define R11 11 39 39 #define R12 12 40 40 #define R13 13 41 41 #define R14 14 42 42 #define R15 15 43 43 44 44 #define XMM0 16 45 45 #define XMM1 17 46 46 #define XMM2 18 47 47 #define XMM3 19 48 48 #define XMM4 20 49 49 #define XMM5 21 50 50 #define XMM6 22 51 51 #define XMM7 23 52 53 /* There are also XMM8..XMM15 */ 52 /* There are also XMM8..XMM14 */ 53 #define XMM15 31 54 54 55 55 56 #define ES 24 56 57 #define PSW 25 57 58 #define STACK 26 // top of stack 58 59 #define ST0 27 // 8087 top of stack register 59 60 #define ST01 28 // top two 8087 registers; for complex types 60 61 61 62 #define NOREG 29 // no register 62 63 63 64 #define AL 0 64 65 #define CL 1 65 66 #define DL 2 66 67 #define BL 3 67 68 #define AH 4 68 69 #define CH 5 69 70 #define DH 6 70 71 #define BH 7 71 72 72 73 #define mAX 1 73 74 #define mCX 2 … … 794 795 void iasm_term( void ); 795 796 regm_t iasm_regs( block *bp ); 796 797 797 798 // nteh.c 798 799 code *nteh_prolog(void); 799 800 code *nteh_epilog(void); 800 801 void nteh_usevars(void); 801 802 void nteh_gentables(void); 802 803 code *nteh_setsp(int op); 803 804 code *nteh_filter(block *b); 804 805 void nteh_framehandler(symbol *); 805 806 code *nteh_gensindex(int); 806 807 #define GENSINDEXSIZE 7 807 808 code *nteh_monitor_prolog(Symbol *shandle); 808 809 code *nteh_monitor_epilog(regm_t retregs); 809 810 810 811 // cgen.c 811 812 code *code_last(code *c); 812 813 void code_orflag(code *c,unsigned flag); 813 814 void code_orrex(code *c,unsigned rex); 815 code *setOpcode(code *c, code *cs, unsigned op); 814 816 code * __pascal cat (code *c1 , code *c2 ); 815 817 code * cat3 (code *c1 , code *c2 , code *c3 ); 816 818 code * cat4 (code *c1 , code *c2 , code *c3 , code *c4 ); 817 819 code * cat6 (code *c1 , code *c2 , code *c3 , code *c4 , code *c5 , code *c6 ); 818 820 code *gen (code *c , code *cs ); 819 821 code *gen1 (code *c , unsigned op ); 820 822 code *gen2 (code *c , unsigned op , unsigned rm ); 821 823 code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib); 822 824 code *genregs (code *c , unsigned op , unsigned dstreg , unsigned srcreg ); 823 825 code *genpush (code *c , unsigned reg ); 824 826 code *genpop (code *c , unsigned reg ); 825 827 code *gentstreg (code *c , unsigned reg ); 826 828 code *genasm (code *c , char *s , unsigned slen ); 827 829 code *genmovreg (code *c , unsigned to , unsigned from ); 828 830 code *genjmp (code *c , unsigned op , unsigned fltarg , block *targ ); 829 831 code *gencsi (code *c , unsigned op , unsigned rm , unsigned FL2 , SYMIDX si ); 830 832 code *gencs (code *c , unsigned op , unsigned rm , unsigned FL2 , symbol *s ); 831 833 code *genc2 (code *c , unsigned op , unsigned rm , targ_size_t EV2 ); 832 834 code *genc1 (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 ); 833 835 code *genc (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 , unsigned FL2 , targ_size_t EV2 ); trunk/src/backend/cgcod.c
r579 r595 1782 1782 #define allocreg(a,b,c) allocreg((a),(b),(c),__LINE__,__FILE__) 1783 1783 #endif 1784 1784 { regm_t r,s; 1785 1785 regm_t retregs; 1786 1786 unsigned reg; 1787 1787 unsigned msreg,lsreg; 1788 1788 int count; 1789 1789 unsigned size; 1790 1790 1791 1791 #if 0 1792 1792 // if (pass == PASSfinal) 1793 1793 { dbg_printf("allocreg %s,%d: regcon.mvar %s regcon.cse.mval %s msavereg %s *pretregs %s tym ", 1794 1794 file,line,regm_str(regcon.mvar),regm_str(regcon.cse.mval), 1795 1795 regm_str(msavereg),regm_str(*pretregs)); 1796 1796 WRTYxx(tym); 1797 1797 dbg_printf("\n"); 1798 1798 } 1799 1799 #endif 1800 1800 tym = tybasic(tym); 1801 1801 size = tysize[tym]; 1802 *pretregs &= mES | allregs ;1802 *pretregs &= mES | allregs | XMMREGS; 1803 1803 retregs = *pretregs; 1804 1804 if ((retregs & regcon.mvar) == retregs) // if exactly in reg vars 1805 1805 { 1806 1806 if (size <= REGSIZE) 1807 1807 { *preg = findreg(retregs); 1808 1808 assert(retregs == mask[*preg]); /* no more bits are set */ 1809 1809 } 1810 1810 else if (size <= 2 * REGSIZE) 1811 1811 { *preg = findregmsw(retregs); 1812 1812 assert(retregs & mLSW); 1813 1813 } 1814 1814 else 1815 1815 assert(0); 1816 1816 return getregs(retregs); 1817 1817 } 1818 1818 count = 0; 1819 1819 L1: 1820 1820 //printf("L1: allregs = x%x, *pretregs = x%x\n", allregs, *pretregs); 1821 1821 assert(++count < 10); /* fail instead of hanging if blocked */ 1822 1822 s = retregs & mES; trunk/src/backend/cgen.c
r577 r595 45 45 void code_orflag(code *c,unsigned flag) 46 46 { 47 47 if (flag && c) 48 48 { while (c->next) 49 49 c = c->next; 50 50 c->Iflags |= flag; 51 51 } 52 52 } 53 53 54 54 /***************************** 55 55 * Set rex bits on last code in list. 56 56 */ 57 57 58 58 void code_orrex(code *c,unsigned rex) 59 59 { 60 60 if (rex && c) 61 61 { while (c->next) 62 62 c = c->next; 63 63 c->Irex |= rex; 64 64 } 65 } 66 67 /************************************** 68 * Set the opcode fields in cs. 69 * This is ridiculously complex, cs.Iop should 70 * just be an unsigned. 71 */ 72 code *setOpcode(code *c, code *cs, unsigned op) 73 { 74 cs->Iflags = 0; 75 if (op > 0xFF) 76 { 77 switch (op & 0xFF0000) 78 { 79 case 0: 80 break; 81 case 0x660000: 82 cs->Iflags = CFopsize; 83 break; 84 case 0xF20000: // REPNE 85 case 0xF30000: // REP/REPE 86 c = gen1(c, op >> 16); 87 break; 88 } 89 cs->Iop = op >> 8; 90 cs->Iop2 = op & 0xFF; 91 } 92 else 93 cs->Iop = op; 94 return c; 65 95 } 66 96 67 97 /***************************** 68 98 * Concatenate two code lists together. Return pointer to result. 69 99 */ 70 100 71 101 #if TX86 && __INTSIZE == 4 && __SC__ 72 102 __declspec(naked) code * __pascal cat(code *c1,code *c2) 73 103 { 74 104 _asm 75 105 { 76 106 mov EAX,c1-4[ESP] 77 107 mov ECX,c2-4[ESP] 78 108 test EAX,EAX 79 109 jne L6D 80 110 mov EAX,ECX 81 111 ret 8 82 112 83 113 L6D: mov EDX,EAX 84 114 cmp dword ptr [EAX],0 … … 364 394 { cs.Iop = op >> 8; 365 395 cs.Iop2 = op & 0xFF; 366 396 } 367 397 else 368 398 cs.Iop = op; 369 399 cs.Iea = ea; 370 400 cs.Iflags = CFoff; 371 401 cs.IFL2 = FLconst; 372 402 cs.IEV2.Vsize_t = EV2; 373 403 return gen(c,&cs); 374 404 } 375 405 376 406 /***************** 377 407 * Generate code. 378 408 */ 379 409 380 410 code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 381 411 { code cs; 382 412 383 413 assert(FL1 < FLMAX); 384 assert(op < 256); 385 cs.Iop = op; 414 if (op > 0xFF) 415 { 416 c = setOpcode(c, &cs, op); 417 cs.Iflags |= CFoff; 418 } 419 else 420 { cs.Iop = op; 421 cs.Iflags = CFoff; 422 } 386 423 cs.Iea = ea; 387 cs.Iflags = CFoff;388 424 cs.IFL1 = FL1; 389 425 cs.IEV1.Vsize_t = EV1; 390 426 return gen(c,&cs); 391 427 } 392 428 393 429 /***************** 394 430 * Generate code. 395 431 */ 396 432 397 433 code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 398 434 { code cs; 399 435 400 436 assert(FL1 < FLMAX); 401 437 assert(op < 256); 402 438 cs.Iop = op; 403 439 cs.Iea = ea; 404 440 cs.Iflags = CFoff; 405 441 cs.IFL1 = FL1; 406 442 cs.IEV1.Vsize_t = EV1; 407 443 assert(FL2 < FLMAX); trunk/src/backend/cod1.c
r592 r595 538 538 539 539 /****************************** 540 540 * Routine to aid in setting things up for gen(). 541 541 * Look for common subexpression. 542 542 * Can handle indirection operators, but not if they're common subs. 543 543 * Input: 544 544 * e -> elem where we get some of the data from 545 545 * cs -> partially filled code to add 546 546 * op = opcode 547 547 * reg = reg field of (mod reg r/m) 548 548 * offset = data to be added to Voffset field 549 549 * keepmsk = mask of registers we must not destroy 550 550 * desmsk = mask of registers destroyed by executing the instruction 551 551 * Returns: 552 552 * pointer to code generated 553 553 */ 554 554 555 555 code *loadea(elem *e,code *cs,unsigned op,unsigned reg,targ_size_t offset, 556 556 regm_t keepmsk,regm_t desmsk) 557 557 { 558 code *c,*cg,*cd ;558 code *c,*cg,*cd,*cprefix; 559 559 560 560 #ifdef DEBUG 561 561 if (debugw) 562 562 printf("loadea: e=%p cs=%p op=x%x reg=%d offset=%lld keepmsk=x%x desmsk=x%x\n", 563 563 e,cs,op,reg,(unsigned long long)offset,keepmsk,desmsk); 564 564 #endif 565 565 566 566 assert(e); 567 567 cs->Iflags = 0; 568 568 cs->Irex = 0; 569 c s->Iop = op;570 if ( !I16 && op >= 0x100) // if 2 byte opcode571 { cs->Iop = op >> 8;572 cs->Iop2 = op;573 }569 cprefix = NULL; 570 if (op > 0xFF) // if 2 byte opcode 571 cprefix = setOpcode(NULL, cs, op); 572 else 573 cs->Iop = op; 574 574 tym_t tym = e->Ety; 575 575 int sz = tysize(tym); 576 576 577 577 /* Determine if location we want to get is in a register. If so, */ 578 578 /* substitute the register for the EA. */ 579 579 /* Note that operators don't go through this. CSE'd operators are */ 580 580 /* picked up by comsub(). */ 581 581 if (e->Ecount && /* if cse */ 582 582 e->Ecount != e->Ecomsub && /* and cse was generated */ 583 583 op != 0x8D && op != 0xC4 && /* and not an LEA or LES */ 584 584 (op != 0xFF || reg != 3) && /* and not CALLF MEM16 */ 585 585 (op & 0xFFF8) != 0xD8) // and not 8087 opcode 586 586 { 587 587 assert(!EOP(e)); /* can't handle this */ 588 588 regm_t rm = regcon.cse.mval & ~regcon.cse.mops & ~regcon.mvar; // possible regs 589 589 if (sz > REGSIZE) // value is in 2 or 4 registers 590 590 { 591 591 if (I16 && sz == 8) // value is in 4 registers 592 592 { static regm_t rmask[4] = { mDX,mCX,mBX,mAX }; 593 593 rm &= rmask[offset >> 1]; … … 658 658 code_orrex(cd, REX_W); 659 659 } 660 660 else if (reg == 6) // if DIV 661 661 { cd = genregs(cd,0x33,DX,DX); // XOR DX,DX 662 662 if (I64 && sz == 8) 663 663 code_orrex(cd, REX_W); 664 664 } 665 665 } 666 666 667 667 // Eliminate MOV reg,reg 668 668 if ((cs->Iop & 0xFC) == 0x88 && 669 669 (cs->Irm & 0xC7) == modregrm(3,0,reg & 7)) 670 670 { 671 671 unsigned r = cs->Irm & 7; 672 672 if (cs->Irex & REX_B) 673 673 r |= 8; 674 674 if (r == reg) 675 675 cs->Iop = NOP; 676 676 } 677 677 678 return cat4(c,cg,cd,gen( CNIL,cs));678 return cat4(c,cg,cd,gen(cprefix,cs)); 679 679 } 680 680 681 681 /************************** 682 682 * Get addressing mode. 683 683 */ 684 684 685 685 unsigned getaddrmode(regm_t idxregs) 686 686 { 687 687 unsigned mode; 688 688 689 689 if (I16) 690 690 { 691 691 mode = (idxregs & mBX) ? modregrm(2,0,7) : /* [BX] */ 692 692 (idxregs & mDI) ? modregrm(2,0,5): /* [DI] */ 693 693 (idxregs & mSI) ? modregrm(2,0,4): /* [SI] */ 694 694 (assert(0),1); 695 695 } 696 696 else 697 697 { unsigned reg = findreg(idxregs & (ALLREGS | mBP)); 698 698 mode = modregrmx(2,0,reg); … … 3626 3626 if (tyfloating(tym)) // TYdouble or TYdouble_alias 3627 3627 gen2(ce,0xD1,modregrm(3,4,reg)); // SHL reg,1 3628 3628 c = cat(c,ce); 3629 3629 3630 3630 while ((i -= REGSIZE) >= 0) 3631 3631 { 3632 3632 c1 = loadea(e,&cs,0x0B,reg,i,regm,0); // OR reg,data+i 3633 3633 if (i == 0) 3634 3634 c1->Iflags |= CFpsw; // need the flags on last OR 3635 3635 c = cat(c,c1); 3636 3636 } 3637 3637 } 3638 3638 else if (sz == LNGDBLSIZE) // TYldouble 3639 3639 return load87(e,0,pretregs,NULL,-1); 3640 3640 else 3641 3641 assert(0); 3642 3642 return c; 3643 3643 } 3644 3644 /* not for flags only */ 3645 3645 flags = *pretregs & mPSW; /* save original */ 3646 forregs = *pretregs & (mBP | ALLREGS | mES );3646 forregs = *pretregs & (mBP | ALLREGS | mES | XMMREGS); 3647 3647 if (*pretregs & mSTACK) 3648 3648 forregs |= DOUBLEREGS; 3649 3649 if (e->Eoper == OPconst) 3650 3650 { regm_t save; 3651 3651 3652 3652 if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,®)) 3653 3653 forregs = mask[reg]; 3654 3654 3655 3655 save = regcon.immed.mval; 3656 3656 c = allocreg(&forregs,®,tym); /* allocate registers */ 3657 3657 regcon.immed.mval = save; // KLUDGE! 3658 3658 if (sz <= REGSIZE) 3659 3659 { 3660 3660 if (sz == 1) 3661 3661 flags |= 1; 3662 3662 else if (!I16 && sz == SHORTSIZE && 3663 3663 !(mask[reg] & regcon.mvar) && 3664 3664 !(config.flags4 & CFG4speed) 3665 3665 ) 3666 3666 flags |= 2; … … 3744 3744 printf("forregs = x%x\n",forregs); 3745 3745 } 3746 3746 #endif 3747 3747 assert(forregs & BYTEREGS); 3748 3748 if (!I16) 3749 3749 c = cat(c,loadea(e,&cs,0x8A,reg,0,0,0)); // MOV regL,data 3750 3750 else 3751 3751 { nregm = tyuns(tym) ? BYTEREGS : mAX; 3752 3752 if (*pretregs & nregm) 3753 3753 nreg = reg; /* already allocated */ 3754 3754 else 3755 3755 c = cat(c,allocreg(&nregm,&nreg,tym)); 3756 3756 ce = loadea(e,&cs,0x8A,nreg,0,0,0); /* MOV nregL,data */ 3757 3757 c = cat(c,ce); 3758 3758 if (reg != nreg) 3759 3759 { genmovreg(c,reg,nreg); /* MOV reg,nreg */ 3760 3760 cssave(e,mask[nreg],FALSE); 3761 3761 } 3762 3762 } 3763 3763 } 3764 else if (forregs & XMMREGS) 3765 { 3766 assert(sz == 4 || sz == 8); // float or double 3767 unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; 3768 ce = loadea(e,&cs,op,reg,0,RMload,0); // MOVSS/MOVSD reg,data 3769 c = cat(c,ce); 3770 } 3764 3771 else if (sz <= REGSIZE) 3765 3772 { 3766 3773 ce = loadea(e,&cs,0x8B,reg,0,RMload,0); // MOV reg,data 3767 3774 c = cat(c,ce); 3768 3775 } 3769 3776 else if (sz <= 2 * REGSIZE && forregs & mES) 3770 3777 { 3771 3778 ce = loadea(e,&cs,0xC4,reg,0,0,mES); /* LES data */ 3772 3779 c = cat(c,ce); 3773 3780 } 3774 3781 else if (sz <= 2 * REGSIZE) 3775 3782 { 3776 3783 if (I32 && sz == 8 && 3777 3784 (*pretregs & (mSTACK | mPSW)) == mSTACK) 3778 3785 { int i; 3779 3786 3780 3787 assert(0); 3781 3788 /* Note that we allocreg(DOUBLEREGS) needlessly */ 3782 3789 stackchanged = 1; 3783 3790 i = DOUBLESIZE - REGSIZE; trunk/src/backend/cod3.c
r589 r595 1747 1747 } 1748 1748 c = cat(c,c2); 1749 1749 } 1750 1750 else if (s->Sclass == SCfastpar) 1751 1751 { unsigned preg = s->Spreg; 1752 1752 1753 1753 if (s->Sfl == FLreg) 1754 1754 { // MOV reg,preg 1755 1755 c = genmovreg(c,s->Sreglsw,preg); 1756 1756 if (I64 && sz == 8) 1757 1757 code_orrex(c, REX_W); 1758 1758 } 1759 1759 else if (s->Sflags & SFLdead || 1760 1760 (!anyiasm && !(s->Sflags & SFLread) && s->Sflags & SFLunambig && 1761 1761 #if MARS 1762 1762 // This variable has been reference by a nested function 1763 1763 !(s->Stype->Tty & mTYvolatile) && 1764 1764 #endif 1765 1765 (config.flags4 & CFG4optimized || !config.fulltypes))) 1766 1766 { 1767 // Ignore it, as it is never referenced 1767 1768 ; 1768 1769 } 1769 1770 else 1770 1771 { 1771 1772 targ_size_t offset = Aoff + BPoff + s->Soffset; 1773 int op = 0x89; // MOV x[EBP],preg 1774 if (preg >= XMM0 && preg <= XMM15) 1775 { 1776 if (sz == 8) 1777 op = 0xF20F11; // MOVSD x[EBP],preg 1778 else 1779 { 1780 assert(sz == 4); 1781 op = 0xF30F11; // MOVSS x[EBP],preg 1782 } 1783 } 1772 1784 if (hasframe) 1773 1785 { 1774 1786 if (!(pushalloc && preg == pushallocreg)) 1775 { // MOV x[EBP],preg 1776 c2 = genc1(CNIL,0x89, 1787 { 1788 // MOV x[EBP],preg 1789 c2 = genc1(CNIL,op, 1777 1790 modregxrm(2,preg,BPRM),FLconst, offset); 1791 if (preg >= XMM0 && preg <= XMM15) 1792 { 1793 } 1794 else 1795 { 1778 1796 //printf("%s Aoff = %d, BPoff = %d, Soffset = %d\n", s->Sident, Aoff, BPoff, s->Soffset); 1779 // if (offset & 2) 1780 // c2->Iflags |= CFopsize; 1781 if (I64 && sz == 8) 1782 code_orrex(c2, REX_W); 1797 // if (offset & 2) 1798 // c2->Iflags |= CFopsize; 1799 if (I64 && sz == 8) 1800 code_orrex(c2, REX_W); 1801 } 1783 1802 c = cat(c, c2); 1784 1803 } 1785 1804 } 1786 1805 else 1787 1806 { 1788 code *clast;1789 1790 1807 offset += EBPtoESP; 1791 #if 11792 1808 if (!(pushalloc && preg == pushallocreg)) 1793 #else1794 if (offset == 0 && (clast = code_last(c)) != NULL &&1795 (clast->Iop & 0xF8) == 0x50)1796 1809 { 1797 clast->Iop = 0x50 + preg; 1798 } 1799 else 1800 #endif 1801 { // MOV offset[ESP],preg 1810 // MOV offset[ESP],preg 1802 1811 // BUG: byte size? 1803 c2 = genc1(CNIL,0x89,modregxrm(2,preg,4),FLconst,offset); 1804 c2->Isib = modregrm(0,4,SP); 1805 if (I64 && sz == 8) 1806 c2->Irex |= REX_W; 1807 // if (offset & 2) 1808 // c2->Iflags |= CFopsize; 1812 c2 = genc1(CNIL,op, 1813 (modregrm(0,4,SP) << 8) | 1814 modregxrm(2,preg,4),FLconst,offset); 1815 if (preg >= XMM0 && preg <= XMM15) 1816 { 1817 } 1818 else 1819 { 1820 if (I64 && sz == 8) 1821 c2->Irex |= REX_W; 1822 // if (offset & 2) 1823 // c2->Iflags |= CFopsize; 1824 } 1809 1825 c = cat(c,c2); 1810 1826 } 1811 1827 } 1812 1828 } 1813 1829 } 1814 1830 } 1815 1831 1816 1832 #if 0 && TARGET_LINUX 1817 1833 if (gotref) 1818 1834 { // position independent reference 1819 1835 c = cat(c, cod3_load_got()); 1820 1836 } 1821 1837 #endif 1822 1838 1823 1839 return c; 1824 1840 } 1825 1841 1826 1842 /******************************* 1827 1843 * Generate and return function epilog. 1828 1844 * Output: trunk/src/backend/code.h
r581 r595 32 32 #define SI 6 33 33 #define DI 7 34 34 35 35 #define R8 8 36 36 #define R9 9 37 37 #define R10 10 38 38 #define R11 11 39 39 #define R12 12 40 40 #define R13 13 41 41 #define R14 14 42 42 #define R15 15 43 43 44 44 #define XMM0 16 45 45 #define XMM1 17 46 46 #define XMM2 18 47 47 #define XMM3 19 48 48 #define XMM4 20 49 49 #define XMM5 21 50 50 #define XMM6 22 51 51 #define XMM7 23 52 53 /* There are also XMM8..XMM15 */ 52 /* There are also XMM8..XMM14 */ 53 #define XMM15 31 54 54 55 55 56 #define ES 24 56 57 #define PSW 25 57 58 #define STACK 26 // top of stack 58 59 #define ST0 27 // 8087 top of stack register 59 60 #define ST01 28 // top two 8087 registers; for complex types 60 61 61 62 #define NOREG 29 // no register 62 63 63 64 #define AL 0 64 65 #define CL 1 65 66 #define DL 2 66 67 #define BL 3 67 68 #define AH 4 68 69 #define CH 5 69 70 #define DH 6 70 71 #define BH 7 71 72 72 73 #define mAX 1 73 74 #define mCX 2 … … 794 795 void iasm_term( void ); 795 796 regm_t iasm_regs( block *bp ); 796 797 797 798 // nteh.c 798 799 code *nteh_prolog(void); 799 800 code *nteh_epilog(void); 800 801 void nteh_usevars(void); 801 802 void nteh_gentables(void); 802 803 code *nteh_setsp(int op); 803 804 code *nteh_filter(block *b); 804 805 void nteh_framehandler(symbol *); 805 806 code *nteh_gensindex(int); 806 807 #define GENSINDEXSIZE 7 807 808 code *nteh_monitor_prolog(Symbol *shandle); 808 809 code *nteh_monitor_epilog(regm_t retregs); 809 810 810 811 // cgen.c 811 812 code *code_last(code *c); 812 813 void code_orflag(code *c,unsigned flag); 813 814 void code_orrex(code *c,unsigned rex); 815 code *setOpcode(code *c, code *cs, unsigned op); 814 816 code * __pascal cat (code *c1 , code *c2 ); 815 817 code * cat3 (code *c1 , code *c2 , code *c3 ); 816 818 code * cat4 (code *c1 , code *c2 , code *c3 , code *c4 ); 817 819 code * cat6 (code *c1 , code *c2 , code *c3 , code *c4 , code *c5 , code *c6 ); 818 820 code *gen (code *c , code *cs ); 819 821 code *gen1 (code *c , unsigned op ); 820 822 code *gen2 (code *c , unsigned op , unsigned rm ); 821 823 code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib); 822 824 code *genregs (code *c , unsigned op , unsigned dstreg , unsigned srcreg ); 823 825 code *genpush (code *c , unsigned reg ); 824 826 code *genpop (code *c , unsigned reg ); 825 827 code *gentstreg (code *c , unsigned reg ); 826 828 code *genasm (code *c , char *s , unsigned slen ); 827 829 code *genmovreg (code *c , unsigned to , unsigned from ); 828 830 code *genjmp (code *c , unsigned op , unsigned fltarg , block *targ ); 829 831 code *gencsi (code *c , unsigned op , unsigned rm , unsigned FL2 , SYMIDX si ); 830 832 code *gencs (code *c , unsigned op , unsigned rm , unsigned FL2 , symbol *s ); 831 833 code *genc2 (code *c , unsigned op , unsigned rm , targ_size_t EV2 ); 832 834 code *genc1 (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 ); 833 835 code *genc (code *c , unsigned op , unsigned rm , unsigned FL1 , targ_size_t EV1 , unsigned FL2 , targ_size_t EV2 );
