Changeset 772
- Timestamp:
- 12/03/10 23:52:08 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cg87.c (modified) (3 diffs)
- branches/dmd-1.x/src/backend/cgen.c (modified) (2 diffs)
- branches/dmd-1.x/src/backend/cod1.c (modified) (2 diffs)
- branches/dmd-1.x/src/backend/cod2.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cod3.c (modified) (2 diffs)
- branches/dmd-1.x/src/backend/cod4.c (modified) (1 diff)
- branches/dmd-1.x/src/glue.c (modified) (1 diff)
- trunk/src/backend/cg87.c (modified) (3 diffs)
- trunk/src/backend/cgen.c (modified) (2 diffs)
- trunk/src/backend/cod1.c (modified) (2 diffs)
- trunk/src/backend/cod2.c (modified) (1 diff)
- trunk/src/backend/cod3.c (modified) (2 diffs)
- trunk/src/backend/cod4.c (modified) (1 diff)
- trunk/src/glue.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cg87.c
r768 r772 53 53 54 54 int stackused = 0; /* number of items on the 8087 stack */ 55 55 56 56 /********************************* 57 57 */ 58 58 59 59 struct Dconst 60 60 { 61 61 int round; 62 62 symbol *roundto0; 63 63 symbol *roundtonearest; 64 64 }; 65 65 66 66 static Dconst oldd; 67 67 68 68 #define NDPP 0 // print out debugging info 69 69 70 70 code *loadComplex(elem *e); 71 71 code *opmod_complex87(elem *e,regm_t *pretregs); 72 72 code *opass_complex87(elem *e,regm_t *pretregs); 73 STATICcode * genf2(code *c,unsigned op,unsigned rm);73 code * genf2(code *c,unsigned op,unsigned rm); 74 74 75 75 #define CW_roundto0 0xFBF 76 76 #define CW_roundtonearest 0x3BF 77 77 78 78 STATIC code *genrnd(code *c, short cw); 79 79 80 80 /********************************** 81 81 * When we need to temporarilly save 8087 registers, we record information 82 82 * about the save into an array of NDP structs: 83 83 */ 84 84 85 85 NDP *NDP::save = NULL; 86 86 int NDP::savemax = 0; /* # of entries in NDP::save[] */ 87 87 int NDP::savetop = 0; /* # of entries used in NDP::save[] */ 88 88 89 89 #ifdef DEBUG 90 90 #define NDPSAVEINC 2 /* flush reallocation bugs */ 91 91 #else 92 92 #define NDPSAVEINC 8 /* allocation chunk sizes */ 93 93 #endif … … 508 508 if ((opcode & ~7) == 0xD8) 509 509 c = genfwait(c); 510 510 return genc1(c,opcode,modregxrm(2,reg,BPRM),FLfltreg,offset); 511 511 } 512 512 513 513 /******************************* 514 514 * Decide if we need to gen an FWAIT. 515 515 */ 516 516 517 517 code *genfwait(code *c) 518 518 { 519 519 if (ADDFWAIT()) 520 520 c = gen1(c,FWAIT); 521 521 return c; 522 522 } 523 523 524 524 /*************************************** 525 525 * Generate floating point instruction. 526 526 */ 527 527 528 STATICcode * genf2(code *c,unsigned op,unsigned rm)528 code * genf2(code *c,unsigned op,unsigned rm) 529 529 { 530 530 return gen2(genfwait(c),op,rm); 531 531 } 532 532 533 533 /*************************** 534 534 * Put the 8087 flags into the CPU flags. 535 535 */ 536 536 537 537 STATIC code * cg87_87topsw(code *c) 538 538 { 539 539 c = cat(c,getregs(mAX)); 540 540 if (config.target_cpu >= TARGET_80286) 541 541 c = genf2(c,0xDF,0xE0); // FSTSW AX 542 542 else 543 543 { c = genfltreg(c,0xD8+5,7,0); /* FSTSW floatreg[BP] */ 544 544 genfwait(c); /* FWAIT */ 545 545 genfltreg(c,0x8A,4,1); /* MOV AH,floatreg+1[BP] */ 546 546 } 547 547 gen1(c,0x9E); // SAHF 548 548 code_orflag(c,CFpsw); … … 1672 1672 break; 1673 1673 1674 1674 case OPs64_d: 1675 1675 if (e->E1->Eoper == OPvar || 1676 1676 (e->E1->Eoper == OPind && e->E1->Ecount == 0)) 1677 1677 { 1678 1678 c = getlvalue(&cs,e->E1,0); 1679 1679 cs.Iop = 0xDF; 1680 1680 if (ADDFWAIT()) 1681 1681 cs.Iflags |= CFwait; 1682 1682 if (!I16) 1683 1683 cs.Iflags &= ~CFopsize; 1684 1684 c = cat(c,push87()); 1685 1685 cs.Irm |= modregrm(0,5,0); 1686 1686 c = gen(c,&cs); // FILD m64 1687 1687 // Variable cannot be put into a register anymore 1688 1688 if (e->E1->Eoper == OPvar) 1689 1689 notreg(e->E1); 1690 1690 freenode(e->E1); 1691 1691 } 1692 else if (I64) 1693 { 1694 retregs = ALLREGS; 1695 c = codelem(e->E1,&retregs,FALSE); 1696 reg = findreg(retregs); 1697 c = genfltreg(c,0x89,reg,0); // MOV floatreg,reg 1698 code_orrex(c, REX_W); 1699 c = cat(c,push87()); 1700 c = genfltreg(c,0xDF,5,0); // FILD long long ptr floatreg 1701 } 1692 1702 else 1693 1703 { 1694 1704 retregs = ALLREGS; 1695 1705 c = codelem(e->E1,&retregs,FALSE); 1696 1706 reg = findreglsw(retregs); 1697 1707 c = genfltreg(c,0x89,reg,0); // MOV floatreg,reglsw 1698 1708 reg = findregmsw(retregs); 1699 1709 c = genfltreg(c,0x89,reg,4); // MOV floatreg+4,regmsw 1700 1710 c = cat(c,push87()); 1701 1711 c = genfltreg(c,0xDF,5,0); // FILD long long ptr floatreg 1702 1712 } 1703 1713 if (op != -1) 1704 1714 { c = cat(c,makesure87(eleft,eoffset,1,0)); 1705 1715 c = genf2(c,0xDE,modregrm(3,opr,1)); // FopRP 1706 1716 pop87(); 1707 1717 } 1708 1718 break; 1709 1719 1710 1720 case OPconst: 1711 1721 ldop = loadconst(e, 0); branches/dmd-1.x/src/backend/cgen.c
r770 r772 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 17 #include <time.h> 18 18 #include "cc.h" 19 19 #include "el.h" 20 20 #include "oper.h" 21 21 #include "code.h" 22 22 #include "type.h" 23 23 #include "global.h" 24 24 25 25 static char __file__[] = __FILE__; /* for tassert.h */ 26 26 #include "tassert.h" 27 27 28 28 /************************************* 29 29 * Handy function to answer the question: who the heck is generating this piece of code? 30 30 */ 31 31 inline void ccheck(code *cs) 32 32 { 33 33 // if (cs->Iop == LEA && (cs->Irm & 0x3F) == 0x34 && cs->Isib == 7) *(char*)0=0; 34 // if (cs->Iop == 0x31) *(char*)0=0; 34 35 } 35 36 36 37 /***************************** 37 38 * Find last code in list. 38 39 */ 39 40 40 41 code *code_last(code *c) 41 42 { 42 43 if (c) 43 44 { while (c->next) 44 45 c = c->next; 45 46 } 46 47 return c; 47 48 } 48 49 49 50 /***************************** 50 51 * Set flag bits on last code in list. 51 52 */ 52 53 53 54 void code_orflag(code *c,unsigned flag) … … 587 588 if (flags & 16 && reg & 4 && // if an H byte register 588 589 regcon.immed.mval & mask[reg & 3] && 589 590 (((regv = regcon.immed.value[reg & 3]) >> 8) & 0xFF) == value) 590 591 goto L2; 591 592 592 593 /* Avoid byte register loads on Pentium Pro and Pentium II 593 594 * to avoid dependency stalls. 594 595 */ 595 596 if (config.flags4 & CFG4speed && 596 597 config.target_cpu >= TARGET_PentiumPro && !(flags & 4)) 597 598 goto L3; 598 599 599 600 // See if another register has the right value 600 601 r = 0; 601 602 for (mreg = (regcon.immed.mval & BYTEREGS); mreg; mreg >>= 1) 602 603 { 603 604 if (mreg & 1) 604 605 { 605 606 if ((regcon.immed.value[r] & 0xFF) == value) 606 607 { c = genregs(c,0x8A,reg,r); // MOV regL,rL 608 if (I64 && r >= 4) 609 code_orrex(c, REX); 607 610 goto L2; 608 611 } 609 612 if (r < 4 && ((regcon.immed.value[r] >> 8) & 0xFF) == value) 610 613 { c = genregs(c,0x8A,reg,r | 4); // MOV regL,rH 611 614 goto L2; 612 615 } 613 616 } 614 617 r++; 615 618 } 616 619 617 620 if (value == 0 && !(flags & 8)) 618 621 { 619 622 if (!(flags & 4) && // if we can set the whole register 620 623 !(flags & 16 && reg & 4)) // and reg is not an H register 621 624 { c = genregs(c,0x31,reg,reg); // XOR reg,reg 622 625 regimmed_set(reg,value); 623 626 regv = 0; 624 627 } 625 628 else 626 629 c = genregs(c,0x30,reg,reg); // XOR regL,regL branches/dmd-1.x/src/backend/cod1.c
r771 r772 8 8 * only. The license is in /dmd/src/dmd/backendlicense.txt 9 9 * or /dm/src/dmd/backendlicense.txt 10 10 * For any other uses, please contact Digital Mars. 11 11 */ 12 12 13 13 #if !SPP 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 17 #include <stdlib.h> 18 18 #include <time.h> 19 19 #include "cc.h" 20 20 #include "el.h" 21 21 #include "oper.h" 22 22 #include "code.h" 23 23 #include "global.h" 24 24 #include "type.h" 25 25 26 26 static char __file__[] = __FILE__; /* for tassert.h */ 27 27 #include "tassert.h" 28 29 /* Generate the appropriate ESC instruction */ 30 #define ESC(MF,b) (0xD8 + ((MF) << 1) + (b)) 31 enum MF 32 { // Values for MF 33 MFfloat = 0, 34 MFlong = 1, 35 MFdouble = 2, 36 MFword = 3 37 }; 38 code * genf2(code *c,unsigned op,unsigned rm); 28 39 29 40 targ_size_t paramsize(elem *e,unsigned stackalign); 30 41 STATIC code * funccall (elem *,unsigned,unsigned,regm_t *,regm_t); 31 42 32 43 /* array to convert from index register to r/m field */ 33 44 /* AX CX DX BX SP BP SI DI */ 34 45 static const signed char regtorm32[8] = { 0, 1, 2, 3,-1, 5, 6, 7 }; 35 46 signed char regtorm [8] = { -1,-1,-1, 7,-1, 6, 4, 5 }; 36 47 37 48 /************************** 38 49 * Determine if e is a 32 bit scaled index addressing mode. 39 50 * Returns: 40 51 * 0 not a scaled index addressing mode 41 52 * !=0 the value for ss in the SIB byte 42 53 */ 43 54 44 55 int isscaledindex(elem *e) 45 56 { targ_uns ss; 46 57 47 58 assert(!I16); … … 3792 3803 if (e->Eoper == OPconst) 3793 3804 { regm_t save; 3794 3805 3795 3806 if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,®)) 3796 3807 forregs = mask[reg]; 3797 3808 3798 3809 save = regcon.immed.mval; 3799 3810 c = allocreg(&forregs,®,tym); /* allocate registers */ 3800 3811 regcon.immed.mval = save; // KLUDGE! 3801 3812 if (sz <= REGSIZE) 3802 3813 { 3803 3814 if (sz == 1) 3804 3815 flags |= 1; 3805 3816 else if (!I16 && sz == SHORTSIZE && 3806 3817 !(mask[reg] & regcon.mvar) && 3807 3818 !(config.flags4 & CFG4speed) 3808 3819 ) 3809 3820 flags |= 2; 3810 3821 if (sz == 8) 3811 3822 flags |= 64; 3812 ce = movregconst(CNIL,reg,e->EV.Vint,flags); 3813 flags = 0; // flags are already set 3823 if (reg >= XMM0) 3824 { /* This comes about because 0, 1, pi, etc., constants don't get stored 3825 * in the data segment, because they are x87 opcodes. 3826 * Not so efficient. We should at least do a PXOR for 0. 3827 */ 3828 unsigned r; 3829 targ_size_t value = e->EV.Vuns; 3830 if (sz == 8) 3831 value = e->EV.Vullong; 3832 ce = regwithvalue(CNIL,ALLREGS,value,&r,flags); 3833 flags = 0; // flags are already set 3834 ce = genfltreg(ce,0x89,r,0); // MOV floatreg,r 3835 if (sz == 8) 3836 code_orrex(ce, REX_W); 3837 assert(sz == 4 || sz == 8); // float or double 3838 unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; 3839 ce = genfltreg(ce,op,reg - XMM0,0); // MOVSS/MOVSD XMMreg,floatreg 3840 } 3841 else 3842 { ce = movregconst(CNIL,reg,e->EV.Vint,flags); 3843 flags = 0; // flags are already set 3844 } 3814 3845 } 3815 3846 else if (sz < 8) // far pointers, longs for 16 bit targets 3816 3847 { 3817 3848 targ_int msw,lsw; 3818 3849 regm_t mswflags; 3819 3850 3820 3851 msw = I32 ? e->EV.Vfp.Vseg 3821 3852 : (e->EV.Vulong >> 16); 3822 3853 lsw = e->EV.Vfp.Voff; 3823 3854 mswflags = 0; 3824 3855 if (forregs & mES) 3825 3856 { 3826 3857 ce = movregconst(CNIL,reg,msw,0); // MOV reg,segment 3827 3858 genregs(ce,0x8E,0,reg); // MOV ES,reg 3828 3859 msw = lsw; // MOV reg,offset 3829 3860 } 3830 3861 else 3831 3862 { 3832 3863 sreg = findreglsw(forregs); 3833 3864 ce = movregconst(CNIL,sreg,lsw,0); branches/dmd-1.x/src/backend/cod2.c
r771 r772 1571 1571 code *cc,*c,*c1,*cnop1,*c2,*cnop2; 1572 1572 con_t regconold,regconsave; 1573 1573 unsigned stackpushold,stackpushsave; 1574 1574 int ehindexold,ehindexsave; 1575 1575 unsigned jop; 1576 1576 unsigned op1; 1577 1577 unsigned sz1; 1578 1578 unsigned sz2; 1579 1579 elem *e1; 1580 1580 elem *e2; 1581 1581 elem *e21; 1582 1582 elem *e22; 1583 1583 1584 1584 /* vars to save state of 8087 */ 1585 1585 int stackusedold,stackusedsave; 1586 1586 NDP _8087old[arraysize(_8087elems)]; 1587 1587 NDP _8087save[arraysize(_8087elems)]; 1588 1588 1589 1589 _chkstack(); 1590 1590 1591 // dbg_printf("cdcond(e = %p, *pretregs = x%x)\n",e,*pretregs);1591 //printf("cdcond(e = %p, *pretregs = %s)\n",e,regm_str(*pretregs)); 1592 1592 e1 = e->E1; 1593 1593 e2 = e->E2; 1594 1594 e21 = e2->E1; 1595 1595 e22 = e2->E2; 1596 1596 cc = docommas(&e1); 1597 1597 cgstate.stackclean++; 1598 1598 psw = *pretregs & mPSW; /* save PSW bit */ 1599 1599 op1 = e1->Eoper; 1600 1600 sz1 = tysize(e1->Ety); 1601 1601 unsigned rex = (I64 && sz1 == 8) ? REX_W : 0; 1602 1602 unsigned grex = rex << 16; 1603 1603 jop = jmpopcode(e1); 1604 1604 1605 1605 if (!OTrel(op1) && e1 == e21 && 1606 1606 sz1 <= REGSIZE && !tyfloating(e1->Ety)) 1607 1607 { // Recognize (e ? e : f) 1608 1608 regm_t retregs; 1609 1609 1610 1610 cnop1 = gennop(CNIL); 1611 1611 retregs = *pretregs | mPSW; branches/dmd-1.x/src/backend/cod3.c
r771 r772 1266 1266 for (regm_t x = topush; x; x >>= 1) 1267 1267 npush += x & 1; 1268 1268 1269 1269 // Keep the stack aligned by 8 for any subsequent function calls 1270 1270 if (!I16 && calledafunc && 1271 1271 (STACKALIGN == 16 || config.flags4 & CFG4stackalign)) 1272 1272 { 1273 1273 //printf("npush = %d Poff = x%x needframe = %d localsize = x%x\n", npush, Poff, needframe, localsize); 1274 1274 1275 1275 int sz = Poff + (needframe ? 0 : -REGSIZE) + localsize + npush * REGSIZE; 1276 1276 if (STACKALIGN == 16) 1277 1277 { 1278 1278 if (sz & (8|4)) 1279 1279 localsize += STACKALIGN - (sz & (8|4)); 1280 1280 } 1281 1281 else if (sz & 4) 1282 1282 localsize += 4; 1283 1283 } 1284 1284 1285 1285 //printf("Foff x%02x Aoff x%02x Toff x%02x NDPoff x%02x CSoff x%02x Poff x%02x localsize x%02x\n", 1286 // Foff,Aoff,Toff,NDPoff,CSoff,Poff,localsize);1286 //(int)Foff,(int)Aoff,(int)Toff,(int)NDPoff,(int)CSoff,(int)Poff,(int)localsize); 1287 1287 1288 1288 xlocalsize = localsize; 1289 1289 1290 1290 if (tyf & mTYnaked) // if no prolog/epilog for function 1291 1291 { 1292 1292 hasframe = 1; 1293 1293 return NULL; 1294 1294 } 1295 1295 1296 1296 if (tym == TYifunc) 1297 1297 { static unsigned char ops2[] = { 0x60,0x1E,0x06,0 }; 1298 1298 static unsigned char ops0[] = { 0x50,0x51,0x52,0x53, 1299 1299 0x54,0x55,0x56,0x57, 1300 1300 0x1E,0x06,0 }; 1301 1301 1302 1302 unsigned char *p; 1303 1303 1304 1304 p = (config.target_cpu >= TARGET_80286) ? ops2 : ops0; 1305 1305 do 1306 1306 c = gen1(c,*p); … … 1838 1838 } 1839 1839 } 1840 1840 } 1841 1841 1842 1842 /* Load arguments passed in registers into the varargs save area 1843 1843 * so they can be accessed by va_arg(). 1844 1844 */ 1845 1845 if (I64 && variadic(funcsym_p->Stype)) 1846 1846 { 1847 1847 /* Look for __va_argsave 1848 1848 */ 1849 1849 symbol *sv = NULL; 1850 1850 for (SYMIDX si = 0; si < globsym.top; si++) 1851 1851 { symbol *s = globsym.tab[si]; 1852 1852 if (s->Sident[0] == '_' && strcmp(s->Sident, "__va_argsave") == 0) 1853 1853 { sv = s; 1854 1854 break; 1855 1855 } 1856 1856 } 1857 1857 1858 if (sv )1858 if (sv && !(sv->Sflags & SFLdead)) 1859 1859 { 1860 1860 /* Generate code to move any arguments passed in registers into 1861 1861 * the stack variable __va_argsave, 1862 1862 * so we can reference it via pointers through va_arg(). 1863 1863 * struct __va_argsave_t { 1864 1864 * size_t[6] regs; 1865 1865 * real[8] fpregs; 1866 1866 * uint offset_regs; 1867 1867 * uint offset_fpregs; 1868 1868 * void* stack_args; 1869 1869 * void* reg_args; 1870 1870 * } 1871 1871 * The MOVAPS instructions seg fault if data is not aligned on 1872 1872 * 16 bytes, so this gives us a nice check to ensure no mistakes. 1873 1873 MOV voff+0*8[RBP],EDI 1874 1874 MOV voff+1*8[RBP],ESI 1875 1875 MOV voff+2*8[RBP],RDX 1876 1876 MOV voff+3*8[RBP],RCX 1877 1877 MOV voff+4*8[RBP],R8 1878 1878 MOV voff+5*8[RBP],R9 branches/dmd-1.x/src/backend/cod4.c
r771 r772 2462 2462 goto Lcomplex; 2463 2463 /* FALL-THROUGH */ 2464 2464 case OPs64_d: 2465 2465 case OPs32_d: 2466 2466 case OPs16_d: 2467 2467 case OPu16_d: 2468 2468 return load87(e,0,pretregs,NULL,-1); 2469 2469 case OPu32_d: 2470 2470 if (!I16) 2471 2471 { 2472 2472 unsigned retregs = ALLREGS; 2473 2473 c1 = codelem(e->E1, &retregs, FALSE); 2474 2474 unsigned reg = findreg(retregs); 2475 2475 c1 = genfltreg(c1, 0x89, reg, 0); 2476 2476 regwithvalue(c1,ALLREGS,0,®,0); 2477 2477 genfltreg(c1, 0x89, reg, REGSIZE); 2478 2478 2479 2479 cat(c1, push87()); 2480 2480 genfltreg(c1,0xDF,5,0); // FILD m64int 2481 2481 2482 retregs = mST0 | (*pretregs & mPSW);2482 retregs = mST0 /*| (*pretregs & mPSW)*/; 2483 2483 c2 = fixresult87(e, retregs, pretregs); 2484 2484 return cat(c1, c2); 2485 2485 } 2486 2486 break; 2487 2487 case OPd_s16: 2488 2488 case OPd_s32: 2489 2489 case OPd_u16: 2490 2490 case OPd_s64: 2491 2491 return cnvt87(e,pretregs); 2492 2492 case OPd_u32: // use subroutine, not 8087 2493 2493 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 2494 2494 retregs = mST0; 2495 2495 #else 2496 2496 retregs = DOUBLEREGS; 2497 2497 #endif 2498 2498 goto L1; 2499 2499 2500 2500 case OPd_u64: 2501 2501 retregs = DOUBLEREGS; 2502 2502 goto L1; branches/dmd-1.x/src/glue.c
r705 r772 1135 1135 } 1136 1136 1137 1137 unsigned TypeFunction::totym() 1138 1138 { 1139 1139 tym_t tyf; 1140 1140 1141 1141 //printf("TypeFunction::totym(), linkage = %d\n", linkage); 1142 1142 switch (linkage) 1143 1143 { 1144 1144 case LINKwindows: 1145 1145 tyf = (varargs == 1) ? TYnfunc : TYnsfunc; 1146 1146 break; 1147 1147 1148 1148 case LINKpascal: 1149 1149 tyf = (varargs == 1) ? TYnfunc : TYnpfunc; 1150 1150 break; 1151 1151 1152 1152 case LINKc: 1153 1153 tyf = TYnfunc; 1154 1154 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 1155 if ( retStyle() == RETstack)1155 if (I32 && retStyle() == RETstack) 1156 1156 tyf = TYhfunc; 1157 1157 #endif 1158 1158 break; 1159 1159 1160 1160 case LINKd: 1161 1161 tyf = (varargs == 1) ? TYnfunc : TYjfunc; 1162 1162 break; 1163 1163 1164 1164 case LINKcpp: 1165 1165 tyf = TYnfunc; 1166 1166 break; 1167 1167 1168 1168 default: 1169 1169 printf("linkage = %d\n", linkage); 1170 1170 assert(0); 1171 1171 } 1172 1172 #if DMDV2 1173 1173 if (isnothrow) 1174 1174 tyf |= mTYnothrow; 1175 1175 #endif trunk/src/backend/cg87.c
r768 r772 53 53 54 54 int stackused = 0; /* number of items on the 8087 stack */ 55 55 56 56 /********************************* 57 57 */ 58 58 59 59 struct Dconst 60 60 { 61 61 int round; 62 62 symbol *roundto0; 63 63 symbol *roundtonearest; 64 64 }; 65 65 66 66 static Dconst oldd; 67 67 68 68 #define NDPP 0 // print out debugging info 69 69 70 70 code *loadComplex(elem *e); 71 71 code *opmod_complex87(elem *e,regm_t *pretregs); 72 72 code *opass_complex87(elem *e,regm_t *pretregs); 73 STATICcode * genf2(code *c,unsigned op,unsigned rm);73 code * genf2(code *c,unsigned op,unsigned rm); 74 74 75 75 #define CW_roundto0 0xFBF 76 76 #define CW_roundtonearest 0x3BF 77 77 78 78 STATIC code *genrnd(code *c, short cw); 79 79 80 80 /********************************** 81 81 * When we need to temporarilly save 8087 registers, we record information 82 82 * about the save into an array of NDP structs: 83 83 */ 84 84 85 85 NDP *NDP::save = NULL; 86 86 int NDP::savemax = 0; /* # of entries in NDP::save[] */ 87 87 int NDP::savetop = 0; /* # of entries used in NDP::save[] */ 88 88 89 89 #ifdef DEBUG 90 90 #define NDPSAVEINC 2 /* flush reallocation bugs */ 91 91 #else 92 92 #define NDPSAVEINC 8 /* allocation chunk sizes */ 93 93 #endif … … 508 508 if ((opcode & ~7) == 0xD8) 509 509 c = genfwait(c); 510 510 return genc1(c,opcode,modregxrm(2,reg,BPRM),FLfltreg,offset); 511 511 } 512 512 513 513 /******************************* 514 514 * Decide if we need to gen an FWAIT. 515 515 */ 516 516 517 517 code *genfwait(code *c) 518 518 { 519 519 if (ADDFWAIT()) 520 520 c = gen1(c,FWAIT); 521 521 return c; 522 522 } 523 523 524 524 /*************************************** 525 525 * Generate floating point instruction. 526 526 */ 527 527 528 STATICcode * genf2(code *c,unsigned op,unsigned rm)528 code * genf2(code *c,unsigned op,unsigned rm) 529 529 { 530 530 return gen2(genfwait(c),op,rm); 531 531 } 532 532 533 533 /*************************** 534 534 * Put the 8087 flags into the CPU flags. 535 535 */ 536 536 537 537 STATIC code * cg87_87topsw(code *c) 538 538 { 539 539 c = cat(c,getregs(mAX)); 540 540 if (config.target_cpu >= TARGET_80286) 541 541 c = genf2(c,0xDF,0xE0); // FSTSW AX 542 542 else 543 543 { c = genfltreg(c,0xD8+5,7,0); /* FSTSW floatreg[BP] */ 544 544 genfwait(c); /* FWAIT */ 545 545 genfltreg(c,0x8A,4,1); /* MOV AH,floatreg+1[BP] */ 546 546 } 547 547 gen1(c,0x9E); // SAHF 548 548 code_orflag(c,CFpsw); … … 1672 1672 break; 1673 1673 1674 1674 case OPs64_d: 1675 1675 if (e->E1->Eoper == OPvar || 1676 1676 (e->E1->Eoper == OPind && e->E1->Ecount == 0)) 1677 1677 { 1678 1678 c = getlvalue(&cs,e->E1,0); 1679 1679 cs.Iop = 0xDF; 1680 1680 if (ADDFWAIT()) 1681 1681 cs.Iflags |= CFwait; 1682 1682 if (!I16) 1683 1683 cs.Iflags &= ~CFopsize; 1684 1684 c = cat(c,push87()); 1685 1685 cs.Irm |= modregrm(0,5,0); 1686 1686 c = gen(c,&cs); // FILD m64 1687 1687 // Variable cannot be put into a register anymore 1688 1688 if (e->E1->Eoper == OPvar) 1689 1689 notreg(e->E1); 1690 1690 freenode(e->E1); 1691 1691 } 1692 else if (I64) 1693 { 1694 retregs = ALLREGS; 1695 c = codelem(e->E1,&retregs,FALSE); 1696 reg = findreg(retregs); 1697 c = genfltreg(c,0x89,reg,0); // MOV floatreg,reg 1698 code_orrex(c, REX_W); 1699 c = cat(c,push87()); 1700 c = genfltreg(c,0xDF,5,0); // FILD long long ptr floatreg 1701 } 1692 1702 else 1693 1703 { 1694 1704 retregs = ALLREGS; 1695 1705 c = codelem(e->E1,&retregs,FALSE); 1696 1706 reg = findreglsw(retregs); 1697 1707 c = genfltreg(c,0x89,reg,0); // MOV floatreg,reglsw 1698 1708 reg = findregmsw(retregs); 1699 1709 c = genfltreg(c,0x89,reg,4); // MOV floatreg+4,regmsw 1700 1710 c = cat(c,push87()); 1701 1711 c = genfltreg(c,0xDF,5,0); // FILD long long ptr floatreg 1702 1712 } 1703 1713 if (op != -1) 1704 1714 { c = cat(c,makesure87(eleft,eoffset,1,0)); 1705 1715 c = genf2(c,0xDE,modregrm(3,opr,1)); // FopRP 1706 1716 pop87(); 1707 1717 } 1708 1718 break; 1709 1719 1710 1720 case OPconst: 1711 1721 ldop = loadconst(e, 0); trunk/src/backend/cgen.c
r769 r772 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 17 #include <time.h> 18 18 #include "cc.h" 19 19 #include "el.h" 20 20 #include "oper.h" 21 21 #include "code.h" 22 22 #include "type.h" 23 23 #include "global.h" 24 24 25 25 static char __file__[] = __FILE__; /* for tassert.h */ 26 26 #include "tassert.h" 27 27 28 28 /************************************* 29 29 * Handy function to answer the question: who the heck is generating this piece of code? 30 30 */ 31 31 inline void ccheck(code *cs) 32 32 { 33 33 // if (cs->Iop == LEA && (cs->Irm & 0x3F) == 0x34 && cs->Isib == 7) *(char*)0=0; 34 // if (cs->Iop == 0x31) *(char*)0=0; 34 35 } 35 36 36 37 /***************************** 37 38 * Find last code in list. 38 39 */ 39 40 40 41 code *code_last(code *c) 41 42 { 42 43 if (c) 43 44 { while (c->next) 44 45 c = c->next; 45 46 } 46 47 return c; 47 48 } 48 49 49 50 /***************************** 50 51 * Set flag bits on last code in list. 51 52 */ 52 53 53 54 void code_orflag(code *c,unsigned flag) … … 587 588 if (flags & 16 && reg & 4 && // if an H byte register 588 589 regcon.immed.mval & mask[reg & 3] && 589 590 (((regv = regcon.immed.value[reg & 3]) >> 8) & 0xFF) == value) 590 591 goto L2; 591 592 592 593 /* Avoid byte register loads on Pentium Pro and Pentium II 593 594 * to avoid dependency stalls. 594 595 */ 595 596 if (config.flags4 & CFG4speed && 596 597 config.target_cpu >= TARGET_PentiumPro && !(flags & 4)) 597 598 goto L3; 598 599 599 600 // See if another register has the right value 600 601 r = 0; 601 602 for (mreg = (regcon.immed.mval & BYTEREGS); mreg; mreg >>= 1) 602 603 { 603 604 if (mreg & 1) 604 605 { 605 606 if ((regcon.immed.value[r] & 0xFF) == value) 606 607 { c = genregs(c,0x8A,reg,r); // MOV regL,rL 608 if (I64 && r >= 4) 609 code_orrex(c, REX); 607 610 goto L2; 608 611 } 609 612 if (r < 4 && ((regcon.immed.value[r] >> 8) & 0xFF) == value) 610 613 { c = genregs(c,0x8A,reg,r | 4); // MOV regL,rH 611 614 goto L2; 612 615 } 613 616 } 614 617 r++; 615 618 } 616 619 617 620 if (value == 0 && !(flags & 8)) 618 621 { 619 622 if (!(flags & 4) && // if we can set the whole register 620 623 !(flags & 16 && reg & 4)) // and reg is not an H register 621 624 { c = genregs(c,0x31,reg,reg); // XOR reg,reg 622 625 regimmed_set(reg,value); 623 626 regv = 0; 624 627 } 625 628 else 626 629 c = genregs(c,0x30,reg,reg); // XOR regL,regL trunk/src/backend/cod1.c
r771 r772 8 8 * only. The license is in /dmd/src/dmd/backendlicense.txt 9 9 * or /dm/src/dmd/backendlicense.txt 10 10 * For any other uses, please contact Digital Mars. 11 11 */ 12 12 13 13 #if !SPP 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 17 #include <stdlib.h> 18 18 #include <time.h> 19 19 #include "cc.h" 20 20 #include "el.h" 21 21 #include "oper.h" 22 22 #include "code.h" 23 23 #include "global.h" 24 24 #include "type.h" 25 25 26 26 static char __file__[] = __FILE__; /* for tassert.h */ 27 27 #include "tassert.h" 28 29 /* Generate the appropriate ESC instruction */ 30 #define ESC(MF,b) (0xD8 + ((MF) << 1) + (b)) 31 enum MF 32 { // Values for MF 33 MFfloat = 0, 34 MFlong = 1, 35 MFdouble = 2, 36 MFword = 3 37 }; 38 code * genf2(code *c,unsigned op,unsigned rm); 28 39 29 40 targ_size_t paramsize(elem *e,unsigned stackalign); 30 41 STATIC code * funccall (elem *,unsigned,unsigned,regm_t *,regm_t); 31 42 32 43 /* array to convert from index register to r/m field */ 33 44 /* AX CX DX BX SP BP SI DI */ 34 45 static const signed char regtorm32[8] = { 0, 1, 2, 3,-1, 5, 6, 7 }; 35 46 signed char regtorm [8] = { -1,-1,-1, 7,-1, 6, 4, 5 }; 36 47 37 48 /************************** 38 49 * Determine if e is a 32 bit scaled index addressing mode. 39 50 * Returns: 40 51 * 0 not a scaled index addressing mode 41 52 * !=0 the value for ss in the SIB byte 42 53 */ 43 54 44 55 int isscaledindex(elem *e) 45 56 { targ_uns ss; 46 57 47 58 assert(!I16); … … 3792 3803 if (e->Eoper == OPconst) 3793 3804 { regm_t save; 3794 3805 3795 3806 if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,®)) 3796 3807 forregs = mask[reg]; 3797 3808 3798 3809 save = regcon.immed.mval; 3799 3810 c = allocreg(&forregs,®,tym); /* allocate registers */ 3800 3811 regcon.immed.mval = save; // KLUDGE! 3801 3812 if (sz <= REGSIZE) 3802 3813 { 3803 3814 if (sz == 1) 3804 3815 flags |= 1; 3805 3816 else if (!I16 && sz == SHORTSIZE && 3806 3817 !(mask[reg] & regcon.mvar) && 3807 3818 !(config.flags4 & CFG4speed) 3808 3819 ) 3809 3820 flags |= 2; 3810 3821 if (sz == 8) 3811 3822 flags |= 64; 3812 ce = movregconst(CNIL,reg,e->EV.Vint,flags); 3813 flags = 0; // flags are already set 3823 if (reg >= XMM0) 3824 { /* This comes about because 0, 1, pi, etc., constants don't get stored 3825 * in the data segment, because they are x87 opcodes. 3826 * Not so efficient. We should at least do a PXOR for 0. 3827 */ 3828 unsigned r; 3829 targ_size_t value = e->EV.Vuns; 3830 if (sz == 8) 3831 value = e->EV.Vullong; 3832 ce = regwithvalue(CNIL,ALLREGS,value,&r,flags); 3833 flags = 0; // flags are already set 3834 ce = genfltreg(ce,0x89,r,0); // MOV floatreg,r 3835 if (sz == 8) 3836 code_orrex(ce, REX_W); 3837 assert(sz == 4 || sz == 8); // float or double 3838 unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; 3839 ce = genfltreg(ce,op,reg - XMM0,0); // MOVSS/MOVSD XMMreg,floatreg 3840 } 3841 else 3842 { ce = movregconst(CNIL,reg,e->EV.Vint,flags); 3843 flags = 0; // flags are already set 3844 } 3814 3845 } 3815 3846 else if (sz < 8) // far pointers, longs for 16 bit targets 3816 3847 { 3817 3848 targ_int msw,lsw; 3818 3849 regm_t mswflags; 3819 3850 3820 3851 msw = I32 ? e->EV.Vfp.Vseg 3821 3852 : (e->EV.Vulong >> 16); 3822 3853 lsw = e->EV.Vfp.Voff; 3823 3854 mswflags = 0; 3824 3855 if (forregs & mES) 3825 3856 { 3826 3857 ce = movregconst(CNIL,reg,msw,0); // MOV reg,segment 3827 3858 genregs(ce,0x8E,0,reg); // MOV ES,reg 3828 3859 msw = lsw; // MOV reg,offset 3829 3860 } 3830 3861 else 3831 3862 { 3832 3863 sreg = findreglsw(forregs); 3833 3864 ce = movregconst(CNIL,sreg,lsw,0); trunk/src/backend/cod2.c
r771 r772 1571 1571 code *cc,*c,*c1,*cnop1,*c2,*cnop2; 1572 1572 con_t regconold,regconsave; 1573 1573 unsigned stackpushold,stackpushsave; 1574 1574 int ehindexold,ehindexsave; 1575 1575 unsigned jop; 1576 1576 unsigned op1; 1577 1577 unsigned sz1; 1578 1578 unsigned sz2; 1579 1579 elem *e1; 1580 1580 elem *e2; 1581 1581 elem *e21; 1582 1582 elem *e22; 1583 1583 1584 1584 /* vars to save state of 8087 */ 1585 1585 int stackusedold,stackusedsave; 1586 1586 NDP _8087old[arraysize(_8087elems)]; 1587 1587 NDP _8087save[arraysize(_8087elems)]; 1588 1588 1589 1589 _chkstack(); 1590 1590 1591 // dbg_printf("cdcond(e = %p, *pretregs = x%x)\n",e,*pretregs);1591 //printf("cdcond(e = %p, *pretregs = %s)\n",e,regm_str(*pretregs)); 1592 1592 e1 = e->E1; 1593 1593 e2 = e->E2; 1594 1594 e21 = e2->E1; 1595 1595 e22 = e2->E2; 1596 1596 cc = docommas(&e1); 1597 1597 cgstate.stackclean++; 1598 1598 psw = *pretregs & mPSW; /* save PSW bit */ 1599 1599 op1 = e1->Eoper; 1600 1600 sz1 = tysize(e1->Ety); 1601 1601 unsigned rex = (I64 && sz1 == 8) ? REX_W : 0; 1602 1602 unsigned grex = rex << 16; 1603 1603 jop = jmpopcode(e1); 1604 1604 1605 1605 if (!OTrel(op1) && e1 == e21 && 1606 1606 sz1 <= REGSIZE && !tyfloating(e1->Ety)) 1607 1607 { // Recognize (e ? e : f) 1608 1608 regm_t retregs; 1609 1609 1610 1610 cnop1 = gennop(CNIL); 1611 1611 retregs = *pretregs | mPSW; trunk/src/backend/cod3.c
r771 r772 1266 1266 for (regm_t x = topush; x; x >>= 1) 1267 1267 npush += x & 1; 1268 1268 1269 1269 // Keep the stack aligned by 8 for any subsequent function calls 1270 1270 if (!I16 && calledafunc && 1271 1271 (STACKALIGN == 16 || config.flags4 & CFG4stackalign)) 1272 1272 { 1273 1273 //printf("npush = %d Poff = x%x needframe = %d localsize = x%x\n", npush, Poff, needframe, localsize); 1274 1274 1275 1275 int sz = Poff + (needframe ? 0 : -REGSIZE) + localsize + npush * REGSIZE; 1276 1276 if (STACKALIGN == 16) 1277 1277 { 1278 1278 if (sz & (8|4)) 1279 1279 localsize += STACKALIGN - (sz & (8|4)); 1280 1280 } 1281 1281 else if (sz & 4) 1282 1282 localsize += 4; 1283 1283 } 1284 1284 1285 1285 //printf("Foff x%02x Aoff x%02x Toff x%02x NDPoff x%02x CSoff x%02x Poff x%02x localsize x%02x\n", 1286 // Foff,Aoff,Toff,NDPoff,CSoff,Poff,localsize);1286 //(int)Foff,(int)Aoff,(int)Toff,(int)NDPoff,(int)CSoff,(int)Poff,(int)localsize); 1287 1287 1288 1288 xlocalsize = localsize; 1289 1289 1290 1290 if (tyf & mTYnaked) // if no prolog/epilog for function 1291 1291 { 1292 1292 hasframe = 1; 1293 1293 return NULL; 1294 1294 } 1295 1295 1296 1296 if (tym == TYifunc) 1297 1297 { static unsigned char ops2[] = { 0x60,0x1E,0x06,0 }; 1298 1298 static unsigned char ops0[] = { 0x50,0x51,0x52,0x53, 1299 1299 0x54,0x55,0x56,0x57, 1300 1300 0x1E,0x06,0 }; 1301 1301 1302 1302 unsigned char *p; 1303 1303 1304 1304 p = (config.target_cpu >= TARGET_80286) ? ops2 : ops0; 1305 1305 do 1306 1306 c = gen1(c,*p); … … 1838 1838 } 1839 1839 } 1840 1840 } 1841 1841 1842 1842 /* Load arguments passed in registers into the varargs save area 1843 1843 * so they can be accessed by va_arg(). 1844 1844 */ 1845 1845 if (I64 && variadic(funcsym_p->Stype)) 1846 1846 { 1847 1847 /* Look for __va_argsave 1848 1848 */ 1849 1849 symbol *sv = NULL; 1850 1850 for (SYMIDX si = 0; si < globsym.top; si++) 1851 1851 { symbol *s = globsym.tab[si]; 1852 1852 if (s->Sident[0] == '_' && strcmp(s->Sident, "__va_argsave") == 0) 1853 1853 { sv = s; 1854 1854 break; 1855 1855 } 1856 1856 } 1857 1857 1858 if (sv )1858 if (sv && !(sv->Sflags & SFLdead)) 1859 1859 { 1860 1860 /* Generate code to move any arguments passed in registers into 1861 1861 * the stack variable __va_argsave, 1862 1862 * so we can reference it via pointers through va_arg(). 1863 1863 * struct __va_argsave_t { 1864 1864 * size_t[6] regs; 1865 1865 * real[8] fpregs; 1866 1866 * uint offset_regs; 1867 1867 * uint offset_fpregs; 1868 1868 * void* stack_args; 1869 1869 * void* reg_args; 1870 1870 * } 1871 1871 * The MOVAPS instructions seg fault if data is not aligned on 1872 1872 * 16 bytes, so this gives us a nice check to ensure no mistakes. 1873 1873 MOV voff+0*8[RBP],EDI 1874 1874 MOV voff+1*8[RBP],ESI 1875 1875 MOV voff+2*8[RBP],RDX 1876 1876 MOV voff+3*8[RBP],RCX 1877 1877 MOV voff+4*8[RBP],R8 1878 1878 MOV voff+5*8[RBP],R9 trunk/src/backend/cod4.c
r771 r772 2462 2462 goto Lcomplex; 2463 2463 /* FALL-THROUGH */ 2464 2464 case OPs64_d: 2465 2465 case OPs32_d: 2466 2466 case OPs16_d: 2467 2467 case OPu16_d: 2468 2468 return load87(e,0,pretregs,NULL,-1); 2469 2469 case OPu32_d: 2470 2470 if (!I16) 2471 2471 { 2472 2472 unsigned retregs = ALLREGS; 2473 2473 c1 = codelem(e->E1, &retregs, FALSE); 2474 2474 unsigned reg = findreg(retregs); 2475 2475 c1 = genfltreg(c1, 0x89, reg, 0); 2476 2476 regwithvalue(c1,ALLREGS,0,®,0); 2477 2477 genfltreg(c1, 0x89, reg, REGSIZE); 2478 2478 2479 2479 cat(c1, push87()); 2480 2480 genfltreg(c1,0xDF,5,0); // FILD m64int 2481 2481 2482 retregs = mST0 | (*pretregs & mPSW);2482 retregs = mST0 /*| (*pretregs & mPSW)*/; 2483 2483 c2 = fixresult87(e, retregs, pretregs); 2484 2484 return cat(c1, c2); 2485 2485 } 2486 2486 break; 2487 2487 case OPd_s16: 2488 2488 case OPd_s32: 2489 2489 case OPd_u16: 2490 2490 case OPd_s64: 2491 2491 return cnvt87(e,pretregs); 2492 2492 case OPd_u32: // use subroutine, not 8087 2493 2493 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 2494 2494 retregs = mST0; 2495 2495 #else 2496 2496 retregs = DOUBLEREGS; 2497 2497 #endif 2498 2498 goto L1; 2499 2499 2500 2500 case OPd_u64: 2501 2501 retregs = DOUBLEREGS; 2502 2502 goto L1; trunk/src/glue.c
r705 r772 1132 1132 } 1133 1133 1134 1134 unsigned TypeFunction::totym() 1135 1135 { 1136 1136 tym_t tyf; 1137 1137 1138 1138 //printf("TypeFunction::totym(), linkage = %d\n", linkage); 1139 1139 switch (linkage) 1140 1140 { 1141 1141 case LINKwindows: 1142 1142 tyf = (varargs == 1) ? TYnfunc : TYnsfunc; 1143 1143 break; 1144 1144 1145 1145 case LINKpascal: 1146 1146 tyf = (varargs == 1) ? TYnfunc : TYnpfunc; 1147 1147 break; 1148 1148 1149 1149 case LINKc: 1150 1150 tyf = TYnfunc; 1151 1151 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 1152 if ( retStyle() == RETstack)1152 if (I32 && retStyle() == RETstack) 1153 1153 tyf = TYhfunc; 1154 1154 #endif 1155 1155 break; 1156 1156 1157 1157 case LINKd: 1158 1158 tyf = (varargs == 1) ? TYnfunc : TYjfunc; 1159 1159 break; 1160 1160 1161 1161 case LINKcpp: 1162 1162 tyf = TYnfunc; 1163 1163 break; 1164 1164 1165 1165 default: 1166 1166 printf("linkage = %d\n", linkage); 1167 1167 assert(0); 1168 1168 } 1169 1169 #if DMDV2 1170 1170 if (isnothrow) 1171 1171 tyf |= mTYnothrow; 1172 1172 #endif
