Changeset 790
- Timestamp:
- 12/07/10 10:39:21 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cg87.c (modified) (4 diffs)
- branches/dmd-1.x/src/backend/cgen.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cod1.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/el.c (modified) (1 diff)
- branches/dmd-1.x/src/interpret.c (modified) (1 diff)
- branches/dmd-1.x/src/tocsym.c (modified) (1 diff)
- trunk/src/backend/cg87.c (modified) (4 diffs)
- trunk/src/backend/cgen.c (modified) (1 diff)
- trunk/src/backend/cod1.c (modified) (1 diff)
- trunk/src/backend/el.c (modified) (1 diff)
- trunk/src/interpret.c (modified) (1 diff)
- trunk/src/tocsym.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cg87.c
r772 r790 443 443 //elem_print(e); 444 444 break; 445 445 } 446 446 if (_8087elems[i].e == e && 447 447 _8087elems[i].offset == offset) 448 448 { //printf("cse found %d\n",i); 449 449 //elem_print(e); 450 450 break; 451 451 } 452 452 } 453 453 return i; 454 454 } 455 455 456 456 /************************************* 457 457 * Reload common subexpression. 458 458 */ 459 459 460 460 code *comsub87(elem *e,regm_t *pretregs) 461 461 { code *c; 462 462 463 //printf("comsub87(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 463 464 // Look on 8087 stack 464 465 int i = cse_get(e, 0); 465 466 466 467 if (tycomplex(e->Ety)) 467 468 { 468 469 unsigned sz = tysize(e->Ety); 469 470 int j = cse_get(e, sz / 2); 470 471 if (i >= 0 && j >= 0) 471 472 { 472 473 c = push87(); 473 474 c = cat(c, push87()); 474 475 c = genf2(c,0xD9,0xC0 + i); // FLD ST(i) 475 476 c = genf2(c,0xD9,0xC0 + j + 1); // FLD ST(j + 1) 476 477 c = cat(c,fixresult_complex87(e,mST01,pretregs)); 477 478 } 478 479 else 479 480 // Reload 480 481 c = loaddata(e,pretregs); 481 482 } 482 483 else 483 484 { 484 485 if (i >= 0) 485 486 { 486 487 c = push87(); 487 488 c = genf2(c,0xD9,0xC0 + i); // FLD ST(i) 488 c = cat(c,fixresult(e,mST0,pretregs)); 489 if (*pretregs & XMMREGS) 490 c = cat(c,fixresult87(e,mST0,pretregs)); 491 else 492 c = cat(c,fixresult(e,mST0,pretregs)); 489 493 } 490 494 else 491 495 // Reload 492 496 c = loaddata(e,pretregs); 493 497 } 494 498 495 499 freenode(e); 496 500 return c; 497 501 } 498 502 499 503 500 504 /************************** 501 505 * Generate code to deal with floatreg. 502 506 */ 503 507 504 508 code * genfltreg(code *c,unsigned opcode,unsigned reg,targ_size_t offset) 505 509 { 506 510 floatreg = TRUE; 507 511 reflocal = TRUE; 508 512 if ((opcode & ~7) == 0xD8) … … 1535 1539 1536 1540 /************************* 1537 1541 * If op == -1, load expression e into ST0. 1538 1542 * else compute (eleft op e), eleft is in ST0. 1539 1543 * Must follow same logic as cmporder87(); 1540 1544 */ 1541 1545 1542 1546 code *load87(elem *e,unsigned eoffset,regm_t *pretregs,elem *eleft,int op) 1543 1547 { 1544 1548 elem *e1; 1545 1549 code *ccomma,*c,*c2,*cpush; 1546 1550 code cs; 1547 1551 regm_t retregs; 1548 1552 unsigned reg,mf,mf1; 1549 1553 int opr; 1550 1554 unsigned char ldop; 1551 1555 tym_t ty; 1552 1556 int i; 1553 1557 1554 1558 #if NDPP 1555 printf("+load87(e=%p, eoffset=%d, *pretregs= x%x, eleft=%p, op=%d, stackused = %d)\n",e,eoffset,*pretregs,eleft,op,stackused);1559 printf("+load87(e=%p, eoffset=%d, *pretregs=%s, eleft=%p, op=%d, stackused = %d)\n",e,eoffset,regm_str(*pretregs),eleft,op,stackused); 1556 1560 #endif 1557 1561 elem_debug(e); 1558 1562 ccomma = NULL; 1559 1563 cpush = NULL; 1560 1564 if (ADDFWAIT()) 1561 1565 cs.Iflags = CFwait; 1562 1566 else 1563 1567 cs.Iflags = 0; 1564 1568 cs.Irex = 0; 1565 1569 opr = oprev[op + 1]; 1566 1570 ty = tybasic(e->Ety); 1567 1571 if ((ty == TYldouble || ty == TYildouble) && 1568 1572 op != -1 && e->Eoper != OPd_ld) 1569 1573 goto Ldefault; 1570 1574 mf = (ty == TYfloat || ty == TYifloat || ty == TYcfloat) ? MFfloat : MFdouble; 1571 1575 L5: 1572 1576 switch (e->Eoper) 1573 1577 { 1574 1578 case OPcomma: 1575 1579 ccomma = docommas(&e); … … 1806 1810 pop87(); 1807 1811 if (op == 4 || op == 6) // sub or div 1808 1812 { code *cl; 1809 1813 1810 1814 cl = code_last(c); 1811 1815 if (cl && cl->Iop == 0xD9 && cl->Irm == 0xC9) // FXCH ST(1) 1812 1816 { cl->Iop = NOP; 1813 1817 opr = op; // reverse operands 1814 1818 } 1815 1819 } 1816 1820 c = genf2(c,0xDE,modregrm(3,opr,1)); // FopRP 1817 1821 } 1818 1822 break; 1819 1823 } 1820 1824 if (op == 3) // FCOMP 1821 1825 { pop87(); // extra pop was done 1822 1826 cg87_87topsw(c); 1823 1827 } 1824 1828 c2 = fixresult87(e,((op == 3) ? mPSW : mST0),pretregs); 1825 1829 #if NDPP 1826 printf("-load87(e=%p, eoffset=%d, *pretregs= x%x, eleft=%p, op=%d, stackused = %d)\n",e,eoffset,*pretregs,eleft,op,stackused);1830 printf("-load87(e=%p, eoffset=%d, *pretregs=%s, eleft=%p, op=%d, stackused = %d)\n",e,eoffset,regm_str(*pretregs),eleft,op,stackused); 1827 1831 #endif 1828 1832 return cat4(ccomma,cpush,c,c2); 1829 1833 } 1830 1834 1831 1835 /******************************** 1832 1836 * Determine if a compare is to be done forwards (return 0) 1833 1837 * or backwards (return 1). 1834 1838 * Must follow same logic as load87(). 1835 1839 */ 1836 1840 1837 1841 int cmporder87(elem *e) 1838 1842 { 1839 1843 //printf("cmporder87(%p)\n",e); 1840 1844 L1: 1841 1845 switch (e->Eoper) 1842 1846 { 1843 1847 case OPcomma: 1844 1848 e = e->E2; 1845 1849 goto L1; 1846 1850 … … 1878 1882 goto ret1; 1879 1883 } 1880 1884 1881 1885 ret1: return 1; 1882 1886 ret0: return 0; 1883 1887 } 1884 1888 1885 1889 /******************************* 1886 1890 * Perform an assignment to a long double/double/float. 1887 1891 */ 1888 1892 1889 1893 code *eq87(elem *e,regm_t *pretregs) 1890 1894 { 1891 1895 regm_t retregs; 1892 1896 code *c1,*c2; 1893 1897 code cs; 1894 1898 unsigned op1; 1895 1899 unsigned op2; 1896 1900 tym_t ty1; 1897 1901 1898 //printf("+eq87(e = %p, *pretregs = x%x)\n", e, *pretregs);1902 //printf("+eq87(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 1899 1903 assert(e->Eoper == OPeq); 1900 1904 retregs = mST0 | (*pretregs & mPSW); 1901 1905 c1 = codelem(e->E2,&retregs,FALSE); 1902 1906 ty1 = tybasic(e->E1->Ety); 1903 1907 switch (ty1) 1904 1908 { case TYdouble_alias: 1905 1909 case TYidouble: 1906 1910 case TYdouble: op1 = ESC(MFdouble,1); op2 = 3; break; 1907 1911 case TYifloat: 1908 1912 case TYfloat: op1 = ESC(MFfloat,1); op2 = 3; break; 1909 1913 case TYildouble: 1910 1914 case TYldouble: op1 = 0xDB; op2 = 7; break; 1911 1915 default: 1912 1916 assert(0); 1913 1917 } 1914 if (*pretregs & (mST0 | ALLREGS | mBP )) // if want result on stack too1918 if (*pretregs & (mST0 | ALLREGS | mBP | XMMREGS)) // if want result on stack too 1915 1919 { 1916 1920 if (ty1 == TYldouble || ty1 == TYildouble) 1917 1921 { 1918 1922 c1 = cat(c1,push87()); 1919 1923 c1 = genf2(c1,0xD9,0xC0); // FLD ST(0) 1920 1924 pop87(); 1921 1925 } 1922 1926 else 1923 1927 op2 = 2; // FST e->E1 1924 1928 } 1925 1929 else 1926 1930 { // FSTP e->E1 1927 1931 pop87(); 1928 1932 } 1929 1933 #if 0 1930 1934 // Doesn't work if ST(0) gets saved to the stack by getlvalue() 1931 1935 c2 = loadea(e->E1,&cs,op1,op2,0,0,0); 1932 1936 #else 1933 1937 cs.Irex = 0; 1934 1938 cs.Iflags = 0; branches/dmd-1.x/src/backend/cgen.c
r772 r790 552 552 * set flags based on result 553 553 * Else if flags & 8 554 554 * do not disturb flags 555 555 * Else 556 556 * don't care about flags 557 557 * If flags & 1 then byte move 558 558 * If flags & 2 then short move (for I32 and I64) 559 559 * If flags & 4 then don't disturb unused portion of register 560 560 * If flags & 16 then reg is a byte register AL..BH 561 561 * If flags & 64 then 64 bit move (I64 only) 562 562 * Returns: 563 563 * code (if any) generated 564 564 */ 565 565 566 566 code *movregconst(code *c,unsigned reg,targ_size_t value,regm_t flags) 567 567 { unsigned r; 568 568 regm_t regm; 569 569 regm_t mreg; 570 570 targ_size_t regv; 571 571 572 //printf("movregconst(%ll x)\n", value);572 //printf("movregconst(%lld (%llx))\n", value, value); 573 573 #define genclrreg(a,r) genregs(a,0x31,r,r) 574 574 575 575 regm = regcon.immed.mval & mask[reg]; 576 576 regv = regcon.immed.value[reg]; 577 577 578 578 if (flags & 1) // 8 bits 579 579 { unsigned msk; 580 580 581 581 value &= 0xFF; 582 582 regm &= BYTEREGS; 583 583 584 584 // If we already have the right value in the right register 585 585 if (regm && (regv & 0xFF) == value) 586 586 goto L2; 587 587 588 588 if (flags & 16 && reg & 4 && // if an H byte register 589 589 regcon.immed.mval & mask[reg & 3] && 590 590 (((regv = regcon.immed.value[reg & 3]) >> 8) & 0xFF) == value) 591 591 goto L2; 592 592 branches/dmd-1.x/src/backend/cod1.c
r772 r790 3786 3786 } 3787 3787 else if (sz == tysize[TYldouble]) // TYldouble 3788 3788 return load87(e,0,pretregs,NULL,-1); 3789 3789 else 3790 3790 { 3791 3791 #ifdef DEBUG 3792 3792 elem_print(e); 3793 3793 #endif 3794 3794 assert(0); 3795 3795 } 3796 3796 return c; 3797 3797 } 3798 3798 /* not for flags only */ 3799 3799 flags = *pretregs & mPSW; /* save original */ 3800 3800 forregs = *pretregs & (mBP | ALLREGS | mES | XMMREGS); 3801 3801 if (*pretregs & mSTACK) 3802 3802 forregs |= DOUBLEREGS; 3803 3803 if (e->Eoper == OPconst) 3804 3804 { regm_t save; 3805 3805 3806 if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,®)) 3806 targ_size_t value = e->EV.Vint; 3807 if (sz == 8) 3808 value = e->EV.Vullong; 3809 3810 if (sz == REGSIZE && reghasvalue(forregs,value,®)) 3807 3811 forregs = mask[reg]; 3808 3812 3809 3813 save = regcon.immed.mval; 3810 3814 c = allocreg(&forregs,®,tym); /* allocate registers */ 3811 3815 regcon.immed.mval = save; // KLUDGE! 3812 3816 if (sz <= REGSIZE) 3813 3817 { 3814 3818 if (sz == 1) 3815 3819 flags |= 1; 3816 3820 else if (!I16 && sz == SHORTSIZE && 3817 3821 !(mask[reg] & regcon.mvar) && 3818 3822 !(config.flags4 & CFG4speed) 3819 3823 ) 3820 3824 flags |= 2; 3821 3825 if (sz == 8) 3822 3826 flags |= 64; 3823 3827 if (reg >= XMM0) 3824 3828 { /* This comes about because 0, 1, pi, etc., constants don't get stored 3825 3829 * in the data segment, because they are x87 opcodes. 3826 3830 * Not so efficient. We should at least do a PXOR for 0. 3827 3831 */ 3828 3832 unsigned r; 3829 3833 targ_size_t value = e->EV.Vuns; 3830 3834 if (sz == 8) 3831 3835 value = e->EV.Vullong; 3832 3836 ce = regwithvalue(CNIL,ALLREGS,value,&r,flags); 3833 3837 flags = 0; // flags are already set 3834 3838 ce = genfltreg(ce,0x89,r,0); // MOV floatreg,r 3835 3839 if (sz == 8) 3836 3840 code_orrex(ce, REX_W); 3837 3841 assert(sz == 4 || sz == 8); // float or double 3838 3842 unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; 3839 3843 ce = genfltreg(ce,op,reg - XMM0,0); // MOVSS/MOVSD XMMreg,floatreg 3840 3844 } 3841 3845 else 3842 { ce = movregconst(CNIL,reg, e->EV.Vint,flags);3846 { ce = movregconst(CNIL,reg,value,flags); 3843 3847 flags = 0; // flags are already set 3844 3848 } 3845 3849 } 3846 3850 else if (sz < 8) // far pointers, longs for 16 bit targets 3847 3851 { 3848 3852 targ_int msw,lsw; 3849 3853 regm_t mswflags; 3850 3854 3851 3855 msw = I32 ? e->EV.Vfp.Vseg 3852 3856 : (e->EV.Vulong >> 16); 3853 3857 lsw = e->EV.Vfp.Voff; 3854 3858 mswflags = 0; 3855 3859 if (forregs & mES) 3856 3860 { 3857 3861 ce = movregconst(CNIL,reg,msw,0); // MOV reg,segment 3858 3862 genregs(ce,0x8E,0,reg); // MOV ES,reg 3859 3863 msw = lsw; // MOV reg,offset 3860 3864 } 3861 3865 else 3862 3866 { branches/dmd-1.x/src/backend/el.c
r773 r790 3022 3022 assert(0); 3023 3023 } 3024 3024 if (bit == -1) 3025 3025 value++; 3026 3026 else if (bit == 1) 3027 3027 value--; 3028 3028 return value == 0; 3029 3029 } 3030 3030 3031 3031 /****************************** 3032 3032 * Extract long double value from constant elem. 3033 3033 * Silently ignore types which are not floating point values. 3034 3034 */ 3035 3035 3036 3036 targ_ldouble el_toldouble(elem *e) 3037 3037 { targ_ldouble result; 3038 3038 3039 3039 elem_debug(e); 3040 3040 assert(cnst(e)); 3041 3041 #if TX86 3042 switch (tysize(typemask(e))) 3043 { 3044 case FLOATSIZE: // TYfloat 3042 switch (tybasic(typemask(e))) 3043 { 3044 case TYfloat: 3045 case TYifloat: 3045 3046 result = e->EV.Vfloat; 3046 3047 break; 3047 case DOUBLESIZE: // TYdouble 3048 case TYdouble: 3049 case TYidouble: 3050 case TYdouble_alias: 3048 3051 result = e->EV.Vdouble; 3049 3052 break; 3050 case LNGDBLSIZE: // TYldouble 3053 case TYldouble: 3054 case TYildouble: 3051 3055 result = e->EV.Vldouble; 3052 3056 break; 3053 3057 } 3054 3058 #else 3055 3059 #if !DDRT 3056 3060 switch (tysize[tybasic(typemask(e))]) 3057 3061 { 3058 3062 case FLOATSIZE: // TYfloat 3059 3063 result = e->EV.Vfloat; 3060 3064 break; 3061 3065 case DOUBLESIZE: // TYdouble 3062 3066 result = e->EV.Vdouble; 3063 3067 break; 3064 3068 #if DOUBLESIZE != LNGDBLSIZE 3065 3069 case LNGDBLSIZE: // TYldouble 3066 3070 #ifdef LNGHDBLSIZE 3067 3071 case LNGHDBLSIZE: 3068 3072 #endif 3069 3073 #if (TARGET_POWERPC) 3070 3074 if (config.flags & CFGldblisdbl) branches/dmd-1.x/src/interpret.c
r752 r790 1328 1328 Dsymbol *s = v->toAlias(); 1329 1329 if (s == v && !v->isStatic() && v->init) 1330 1330 { 1331 1331 ExpInitializer *ie = v->init->isExpInitializer(); 1332 1332 if (ie) 1333 1333 e = ie->exp->interpret(istate); 1334 1334 else if (v->init->isVoidInitializer()) 1335 1335 e = NULL; 1336 1336 } 1337 1337 #if DMDV2 1338 1338 else if (s == v && (v->isConst() || v->isImmutable()) && v->init) 1339 1339 #else 1340 1340 else if (s == v && v->isConst() && v->init) 1341 1341 #endif 1342 1342 { e = v->init->toExpression(); 1343 1343 if (!e) 1344 1344 e = EXP_CANT_INTERPRET; 1345 1345 else if (!e->type) 1346 1346 e->type = v->type; 1347 1347 } 1348 #if 0 // currently fails test interpret3.d 1349 else 1350 { 1351 error("%s cannot be interpreted at compile time"); 1352 e = EXP_CANT_INTERPRET; 1353 } 1354 #endif 1348 1355 } 1349 1356 else if (declaration->isAttribDeclaration() || 1350 1357 declaration->isTemplateMixin() || 1351 1358 declaration->isTupleDeclaration()) 1352 1359 { // These can be made to work, too lazy now 1353 1360 error("Declaration %s is not yet implemented in CTFE", toChars()); 1354 1361 1355 1362 e = EXP_CANT_INTERPRET; 1356 1363 } 1357 1364 else 1358 1365 { // Others should not contain executable code, so are trivial to evaluate 1359 1366 e = NULL; 1360 1367 } 1361 1368 #if LOG 1362 1369 printf("-DeclarationExp::interpret(%s): %p\n", toChars(), e); 1363 1370 #endif 1364 1371 return e; 1365 1372 } 1366 1373 1367 1374 Expression *TupleExp::interpret(InterState *istate) branches/dmd-1.x/src/tocsym.c
r557 r790 218 218 if (nestedref) 219 219 { 220 220 /* Symbol is accessed by a nested function. Make sure 221 221 * it is not put in a register, and that the optimizer 222 222 * assumes it is modified across function calls and pointer 223 223 * dereferences. 224 224 */ 225 225 //printf("\tnested ref, not register\n"); 226 226 type_setcv(&t, t->Tty | mTYvolatile); 227 227 } 228 228 } 229 229 if (storage_class & STCconst) 230 230 { 231 231 // Insert const modifiers 232 232 tym_t tym = 0; 233 233 234 234 if (storage_class & STCconst) 235 235 tym |= mTYconst; 236 236 type_setcv(&t, tym); 237 237 } 238 239 if (ident == Id::va_argsave) 240 /* __va_argsave is set outside of the realm of the optimizer, 241 * so we tell the optimizer to leave it alone 242 */ 243 type_setcv(&t, t->Tty | mTYvolatile); 244 238 245 switch (linkage) 239 246 { 240 247 case LINKwindows: 241 248 m = mTYman_std; 242 249 break; 243 250 244 251 case LINKpascal: 245 252 m = mTYman_pas; 246 253 break; 247 254 248 255 case LINKc: 249 256 m = mTYman_c; 250 257 break; 251 258 252 259 case LINKd: 253 260 m = mTYman_d; 254 261 break; 255 262 256 263 case LINKcpp: 257 264 m = mTYman_cpp; trunk/src/backend/cg87.c
r772 r790 443 443 //elem_print(e); 444 444 break; 445 445 } 446 446 if (_8087elems[i].e == e && 447 447 _8087elems[i].offset == offset) 448 448 { //printf("cse found %d\n",i); 449 449 //elem_print(e); 450 450 break; 451 451 } 452 452 } 453 453 return i; 454 454 } 455 455 456 456 /************************************* 457 457 * Reload common subexpression. 458 458 */ 459 459 460 460 code *comsub87(elem *e,regm_t *pretregs) 461 461 { code *c; 462 462 463 //printf("comsub87(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 463 464 // Look on 8087 stack 464 465 int i = cse_get(e, 0); 465 466 466 467 if (tycomplex(e->Ety)) 467 468 { 468 469 unsigned sz = tysize(e->Ety); 469 470 int j = cse_get(e, sz / 2); 470 471 if (i >= 0 && j >= 0) 471 472 { 472 473 c = push87(); 473 474 c = cat(c, push87()); 474 475 c = genf2(c,0xD9,0xC0 + i); // FLD ST(i) 475 476 c = genf2(c,0xD9,0xC0 + j + 1); // FLD ST(j + 1) 476 477 c = cat(c,fixresult_complex87(e,mST01,pretregs)); 477 478 } 478 479 else 479 480 // Reload 480 481 c = loaddata(e,pretregs); 481 482 } 482 483 else 483 484 { 484 485 if (i >= 0) 485 486 { 486 487 c = push87(); 487 488 c = genf2(c,0xD9,0xC0 + i); // FLD ST(i) 488 c = cat(c,fixresult(e,mST0,pretregs)); 489 if (*pretregs & XMMREGS) 490 c = cat(c,fixresult87(e,mST0,pretregs)); 491 else 492 c = cat(c,fixresult(e,mST0,pretregs)); 489 493 } 490 494 else 491 495 // Reload 492 496 c = loaddata(e,pretregs); 493 497 } 494 498 495 499 freenode(e); 496 500 return c; 497 501 } 498 502 499 503 500 504 /************************** 501 505 * Generate code to deal with floatreg. 502 506 */ 503 507 504 508 code * genfltreg(code *c,unsigned opcode,unsigned reg,targ_size_t offset) 505 509 { 506 510 floatreg = TRUE; 507 511 reflocal = TRUE; 508 512 if ((opcode & ~7) == 0xD8) … … 1535 1539 1536 1540 /************************* 1537 1541 * If op == -1, load expression e into ST0. 1538 1542 * else compute (eleft op e), eleft is in ST0. 1539 1543 * Must follow same logic as cmporder87(); 1540 1544 */ 1541 1545 1542 1546 code *load87(elem *e,unsigned eoffset,regm_t *pretregs,elem *eleft,int op) 1543 1547 { 1544 1548 elem *e1; 1545 1549 code *ccomma,*c,*c2,*cpush; 1546 1550 code cs; 1547 1551 regm_t retregs; 1548 1552 unsigned reg,mf,mf1; 1549 1553 int opr; 1550 1554 unsigned char ldop; 1551 1555 tym_t ty; 1552 1556 int i; 1553 1557 1554 1558 #if NDPP 1555 printf("+load87(e=%p, eoffset=%d, *pretregs= x%x, eleft=%p, op=%d, stackused = %d)\n",e,eoffset,*pretregs,eleft,op,stackused);1559 printf("+load87(e=%p, eoffset=%d, *pretregs=%s, eleft=%p, op=%d, stackused = %d)\n",e,eoffset,regm_str(*pretregs),eleft,op,stackused); 1556 1560 #endif 1557 1561 elem_debug(e); 1558 1562 ccomma = NULL; 1559 1563 cpush = NULL; 1560 1564 if (ADDFWAIT()) 1561 1565 cs.Iflags = CFwait; 1562 1566 else 1563 1567 cs.Iflags = 0; 1564 1568 cs.Irex = 0; 1565 1569 opr = oprev[op + 1]; 1566 1570 ty = tybasic(e->Ety); 1567 1571 if ((ty == TYldouble || ty == TYildouble) && 1568 1572 op != -1 && e->Eoper != OPd_ld) 1569 1573 goto Ldefault; 1570 1574 mf = (ty == TYfloat || ty == TYifloat || ty == TYcfloat) ? MFfloat : MFdouble; 1571 1575 L5: 1572 1576 switch (e->Eoper) 1573 1577 { 1574 1578 case OPcomma: 1575 1579 ccomma = docommas(&e); … … 1806 1810 pop87(); 1807 1811 if (op == 4 || op == 6) // sub or div 1808 1812 { code *cl; 1809 1813 1810 1814 cl = code_last(c); 1811 1815 if (cl && cl->Iop == 0xD9 && cl->Irm == 0xC9) // FXCH ST(1) 1812 1816 { cl->Iop = NOP; 1813 1817 opr = op; // reverse operands 1814 1818 } 1815 1819 } 1816 1820 c = genf2(c,0xDE,modregrm(3,opr,1)); // FopRP 1817 1821 } 1818 1822 break; 1819 1823 } 1820 1824 if (op == 3) // FCOMP 1821 1825 { pop87(); // extra pop was done 1822 1826 cg87_87topsw(c); 1823 1827 } 1824 1828 c2 = fixresult87(e,((op == 3) ? mPSW : mST0),pretregs); 1825 1829 #if NDPP 1826 printf("-load87(e=%p, eoffset=%d, *pretregs= x%x, eleft=%p, op=%d, stackused = %d)\n",e,eoffset,*pretregs,eleft,op,stackused);1830 printf("-load87(e=%p, eoffset=%d, *pretregs=%s, eleft=%p, op=%d, stackused = %d)\n",e,eoffset,regm_str(*pretregs),eleft,op,stackused); 1827 1831 #endif 1828 1832 return cat4(ccomma,cpush,c,c2); 1829 1833 } 1830 1834 1831 1835 /******************************** 1832 1836 * Determine if a compare is to be done forwards (return 0) 1833 1837 * or backwards (return 1). 1834 1838 * Must follow same logic as load87(). 1835 1839 */ 1836 1840 1837 1841 int cmporder87(elem *e) 1838 1842 { 1839 1843 //printf("cmporder87(%p)\n",e); 1840 1844 L1: 1841 1845 switch (e->Eoper) 1842 1846 { 1843 1847 case OPcomma: 1844 1848 e = e->E2; 1845 1849 goto L1; 1846 1850 … … 1878 1882 goto ret1; 1879 1883 } 1880 1884 1881 1885 ret1: return 1; 1882 1886 ret0: return 0; 1883 1887 } 1884 1888 1885 1889 /******************************* 1886 1890 * Perform an assignment to a long double/double/float. 1887 1891 */ 1888 1892 1889 1893 code *eq87(elem *e,regm_t *pretregs) 1890 1894 { 1891 1895 regm_t retregs; 1892 1896 code *c1,*c2; 1893 1897 code cs; 1894 1898 unsigned op1; 1895 1899 unsigned op2; 1896 1900 tym_t ty1; 1897 1901 1898 //printf("+eq87(e = %p, *pretregs = x%x)\n", e, *pretregs);1902 //printf("+eq87(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 1899 1903 assert(e->Eoper == OPeq); 1900 1904 retregs = mST0 | (*pretregs & mPSW); 1901 1905 c1 = codelem(e->E2,&retregs,FALSE); 1902 1906 ty1 = tybasic(e->E1->Ety); 1903 1907 switch (ty1) 1904 1908 { case TYdouble_alias: 1905 1909 case TYidouble: 1906 1910 case TYdouble: op1 = ESC(MFdouble,1); op2 = 3; break; 1907 1911 case TYifloat: 1908 1912 case TYfloat: op1 = ESC(MFfloat,1); op2 = 3; break; 1909 1913 case TYildouble: 1910 1914 case TYldouble: op1 = 0xDB; op2 = 7; break; 1911 1915 default: 1912 1916 assert(0); 1913 1917 } 1914 if (*pretregs & (mST0 | ALLREGS | mBP )) // if want result on stack too1918 if (*pretregs & (mST0 | ALLREGS | mBP | XMMREGS)) // if want result on stack too 1915 1919 { 1916 1920 if (ty1 == TYldouble || ty1 == TYildouble) 1917 1921 { 1918 1922 c1 = cat(c1,push87()); 1919 1923 c1 = genf2(c1,0xD9,0xC0); // FLD ST(0) 1920 1924 pop87(); 1921 1925 } 1922 1926 else 1923 1927 op2 = 2; // FST e->E1 1924 1928 } 1925 1929 else 1926 1930 { // FSTP e->E1 1927 1931 pop87(); 1928 1932 } 1929 1933 #if 0 1930 1934 // Doesn't work if ST(0) gets saved to the stack by getlvalue() 1931 1935 c2 = loadea(e->E1,&cs,op1,op2,0,0,0); 1932 1936 #else 1933 1937 cs.Irex = 0; 1934 1938 cs.Iflags = 0; trunk/src/backend/cgen.c
r772 r790 552 552 * set flags based on result 553 553 * Else if flags & 8 554 554 * do not disturb flags 555 555 * Else 556 556 * don't care about flags 557 557 * If flags & 1 then byte move 558 558 * If flags & 2 then short move (for I32 and I64) 559 559 * If flags & 4 then don't disturb unused portion of register 560 560 * If flags & 16 then reg is a byte register AL..BH 561 561 * If flags & 64 then 64 bit move (I64 only) 562 562 * Returns: 563 563 * code (if any) generated 564 564 */ 565 565 566 566 code *movregconst(code *c,unsigned reg,targ_size_t value,regm_t flags) 567 567 { unsigned r; 568 568 regm_t regm; 569 569 regm_t mreg; 570 570 targ_size_t regv; 571 571 572 //printf("movregconst(%ll x)\n", value);572 //printf("movregconst(%lld (%llx))\n", value, value); 573 573 #define genclrreg(a,r) genregs(a,0x31,r,r) 574 574 575 575 regm = regcon.immed.mval & mask[reg]; 576 576 regv = regcon.immed.value[reg]; 577 577 578 578 if (flags & 1) // 8 bits 579 579 { unsigned msk; 580 580 581 581 value &= 0xFF; 582 582 regm &= BYTEREGS; 583 583 584 584 // If we already have the right value in the right register 585 585 if (regm && (regv & 0xFF) == value) 586 586 goto L2; 587 587 588 588 if (flags & 16 && reg & 4 && // if an H byte register 589 589 regcon.immed.mval & mask[reg & 3] && 590 590 (((regv = regcon.immed.value[reg & 3]) >> 8) & 0xFF) == value) 591 591 goto L2; 592 592 trunk/src/backend/cod1.c
r772 r790 3786 3786 } 3787 3787 else if (sz == tysize[TYldouble]) // TYldouble 3788 3788 return load87(e,0,pretregs,NULL,-1); 3789 3789 else 3790 3790 { 3791 3791 #ifdef DEBUG 3792 3792 elem_print(e); 3793 3793 #endif 3794 3794 assert(0); 3795 3795 } 3796 3796 return c; 3797 3797 } 3798 3798 /* not for flags only */ 3799 3799 flags = *pretregs & mPSW; /* save original */ 3800 3800 forregs = *pretregs & (mBP | ALLREGS | mES | XMMREGS); 3801 3801 if (*pretregs & mSTACK) 3802 3802 forregs |= DOUBLEREGS; 3803 3803 if (e->Eoper == OPconst) 3804 3804 { regm_t save; 3805 3805 3806 if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,®)) 3806 targ_size_t value = e->EV.Vint; 3807 if (sz == 8) 3808 value = e->EV.Vullong; 3809 3810 if (sz == REGSIZE && reghasvalue(forregs,value,®)) 3807 3811 forregs = mask[reg]; 3808 3812 3809 3813 save = regcon.immed.mval; 3810 3814 c = allocreg(&forregs,®,tym); /* allocate registers */ 3811 3815 regcon.immed.mval = save; // KLUDGE! 3812 3816 if (sz <= REGSIZE) 3813 3817 { 3814 3818 if (sz == 1) 3815 3819 flags |= 1; 3816 3820 else if (!I16 && sz == SHORTSIZE && 3817 3821 !(mask[reg] & regcon.mvar) && 3818 3822 !(config.flags4 & CFG4speed) 3819 3823 ) 3820 3824 flags |= 2; 3821 3825 if (sz == 8) 3822 3826 flags |= 64; 3823 3827 if (reg >= XMM0) 3824 3828 { /* This comes about because 0, 1, pi, etc., constants don't get stored 3825 3829 * in the data segment, because they are x87 opcodes. 3826 3830 * Not so efficient. We should at least do a PXOR for 0. 3827 3831 */ 3828 3832 unsigned r; 3829 3833 targ_size_t value = e->EV.Vuns; 3830 3834 if (sz == 8) 3831 3835 value = e->EV.Vullong; 3832 3836 ce = regwithvalue(CNIL,ALLREGS,value,&r,flags); 3833 3837 flags = 0; // flags are already set 3834 3838 ce = genfltreg(ce,0x89,r,0); // MOV floatreg,r 3835 3839 if (sz == 8) 3836 3840 code_orrex(ce, REX_W); 3837 3841 assert(sz == 4 || sz == 8); // float or double 3838 3842 unsigned op = (sz == 4) ? 0xF30F10 : 0xF20F10; 3839 3843 ce = genfltreg(ce,op,reg - XMM0,0); // MOVSS/MOVSD XMMreg,floatreg 3840 3844 } 3841 3845 else 3842 { ce = movregconst(CNIL,reg, e->EV.Vint,flags);3846 { ce = movregconst(CNIL,reg,value,flags); 3843 3847 flags = 0; // flags are already set 3844 3848 } 3845 3849 } 3846 3850 else if (sz < 8) // far pointers, longs for 16 bit targets 3847 3851 { 3848 3852 targ_int msw,lsw; 3849 3853 regm_t mswflags; 3850 3854 3851 3855 msw = I32 ? e->EV.Vfp.Vseg 3852 3856 : (e->EV.Vulong >> 16); 3853 3857 lsw = e->EV.Vfp.Voff; 3854 3858 mswflags = 0; 3855 3859 if (forregs & mES) 3856 3860 { 3857 3861 ce = movregconst(CNIL,reg,msw,0); // MOV reg,segment 3858 3862 genregs(ce,0x8E,0,reg); // MOV ES,reg 3859 3863 msw = lsw; // MOV reg,offset 3860 3864 } 3861 3865 else 3862 3866 { trunk/src/backend/el.c
r773 r790 3022 3022 assert(0); 3023 3023 } 3024 3024 if (bit == -1) 3025 3025 value++; 3026 3026 else if (bit == 1) 3027 3027 value--; 3028 3028 return value == 0; 3029 3029 } 3030 3030 3031 3031 /****************************** 3032 3032 * Extract long double value from constant elem. 3033 3033 * Silently ignore types which are not floating point values. 3034 3034 */ 3035 3035 3036 3036 targ_ldouble el_toldouble(elem *e) 3037 3037 { targ_ldouble result; 3038 3038 3039 3039 elem_debug(e); 3040 3040 assert(cnst(e)); 3041 3041 #if TX86 3042 switch (tysize(typemask(e))) 3043 { 3044 case FLOATSIZE: // TYfloat 3042 switch (tybasic(typemask(e))) 3043 { 3044 case TYfloat: 3045 case TYifloat: 3045 3046 result = e->EV.Vfloat; 3046 3047 break; 3047 case DOUBLESIZE: // TYdouble 3048 case TYdouble: 3049 case TYidouble: 3050 case TYdouble_alias: 3048 3051 result = e->EV.Vdouble; 3049 3052 break; 3050 case LNGDBLSIZE: // TYldouble 3053 case TYldouble: 3054 case TYildouble: 3051 3055 result = e->EV.Vldouble; 3052 3056 break; 3053 3057 } 3054 3058 #else 3055 3059 #if !DDRT 3056 3060 switch (tysize[tybasic(typemask(e))]) 3057 3061 { 3058 3062 case FLOATSIZE: // TYfloat 3059 3063 result = e->EV.Vfloat; 3060 3064 break; 3061 3065 case DOUBLESIZE: // TYdouble 3062 3066 result = e->EV.Vdouble; 3063 3067 break; 3064 3068 #if DOUBLESIZE != LNGDBLSIZE 3065 3069 case LNGDBLSIZE: // TYldouble 3066 3070 #ifdef LNGHDBLSIZE 3067 3071 case LNGHDBLSIZE: 3068 3072 #endif 3069 3073 #if (TARGET_POWERPC) 3070 3074 if (config.flags & CFGldblisdbl) trunk/src/interpret.c
r752 r790 1328 1328 Dsymbol *s = v->toAlias(); 1329 1329 if (s == v && !v->isStatic() && v->init) 1330 1330 { 1331 1331 ExpInitializer *ie = v->init->isExpInitializer(); 1332 1332 if (ie) 1333 1333 e = ie->exp->interpret(istate); 1334 1334 else if (v->init->isVoidInitializer()) 1335 1335 e = NULL; 1336 1336 } 1337 1337 #if DMDV2 1338 1338 else if (s == v && (v->isConst() || v->isImmutable()) && v->init) 1339 1339 #else 1340 1340 else if (s == v && v->isConst() && v->init) 1341 1341 #endif 1342 1342 { e = v->init->toExpression(); 1343 1343 if (!e) 1344 1344 e = EXP_CANT_INTERPRET; 1345 1345 else if (!e->type) 1346 1346 e->type = v->type; 1347 1347 } 1348 #if 0 // currently fails test interpret3.d 1349 else 1350 { 1351 error("%s cannot be interpreted at compile time"); 1352 e = EXP_CANT_INTERPRET; 1353 } 1354 #endif 1348 1355 } 1349 1356 else if (declaration->isAttribDeclaration() || 1350 1357 declaration->isTemplateMixin() || 1351 1358 declaration->isTupleDeclaration()) 1352 1359 { // These can be made to work, too lazy now 1353 1360 error("Declaration %s is not yet implemented in CTFE", toChars()); 1354 1361 1355 1362 e = EXP_CANT_INTERPRET; 1356 1363 } 1357 1364 else 1358 1365 { // Others should not contain executable code, so are trivial to evaluate 1359 1366 e = NULL; 1360 1367 } 1361 1368 #if LOG 1362 1369 printf("-DeclarationExp::interpret(%s): %p\n", toChars(), e); 1363 1370 #endif 1364 1371 return e; 1365 1372 } 1366 1373 1367 1374 Expression *TupleExp::interpret(InterState *istate) trunk/src/tocsym.c
r557 r790 219 219 s->Sclass = SCextern; 220 220 s->Sfl = FLextern; 221 221 slist_add(s); 222 222 } 223 223 else 224 224 { 225 225 s->Sclass = SCauto; 226 226 s->Sfl = FLauto; 227 227 228 228 if (nestedrefs.dim) 229 229 { 230 230 /* Symbol is accessed by a nested function. Make sure 231 231 * it is not put in a register, and that the optimizer 232 232 * assumes it is modified across function calls and pointer 233 233 * dereferences. 234 234 */ 235 235 //printf("\tnested ref, not register\n"); 236 236 type_setcv(&t, t->Tty | mTYvolatile); 237 237 } 238 238 } 239 240 if (ident == Id::va_argsave) 241 /* __va_argsave is set outside of the realm of the optimizer, 242 * so we tell the optimizer to leave it alone 243 */ 244 type_setcv(&t, t->Tty | mTYvolatile); 239 245 240 246 mangle_t m = 0; 241 247 switch (linkage) 242 248 { 243 249 case LINKwindows: 244 250 m = mTYman_std; 245 251 break; 246 252 247 253 case LINKpascal: 248 254 m = mTYman_pas; 249 255 break; 250 256 251 257 case LINKc: 252 258 m = mTYman_c; 253 259 break; 254 260 255 261 case LINKd: 256 262 m = mTYman_d; 257 263 break; 258 264
