Changeset 627
- Timestamp:
- 08/25/10 21:37:50 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cg87.c (modified) (6 diffs)
- branches/dmd-1.x/src/backend/cgcod.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cgelem.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cgen.c (modified) (2 diffs)
- branches/dmd-1.x/src/backend/cod1.c (modified) (5 diffs)
- branches/dmd-1.x/src/backend/cod2.c (modified) (6 diffs)
- 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/backend/debug.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/el.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/evalu8.c (modified) (1 diff)
- branches/dmd-1.x/src/todt.c (modified) (5 diffs)
- trunk/src/backend/cg87.c (modified) (6 diffs)
- trunk/src/backend/cgcod.c (modified) (1 diff)
- trunk/src/backend/cgelem.c (modified) (1 diff)
- trunk/src/backend/cgen.c (modified) (2 diffs)
- trunk/src/backend/cod1.c (modified) (5 diffs)
- trunk/src/backend/cod2.c (modified) (6 diffs)
- trunk/src/backend/cod3.c (modified) (2 diffs)
- trunk/src/backend/cod4.c (modified) (1 diff)
- trunk/src/backend/debug.c (modified) (1 diff)
- trunk/src/backend/el.c (modified) (1 diff)
- trunk/src/backend/evalu8.c (modified) (1 diff)
- trunk/src/todt.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cg87.c
r622 r627 193 193 #endif 194 194 { 195 195 int i; 196 196 197 197 #if NDPP 198 198 dbg_printf("pop87(%s(%d): stackused=%d)\n", file, line, stackused); 199 199 #endif 200 200 --stackused; 201 201 assert(stackused >= 0); 202 202 for (i = 0; i < arraysize(_8087elems) - 1; i++) 203 203 _8087elems[i] = _8087elems[i + 1]; 204 204 /* end of stack is nothing */ 205 205 _8087elems[arraysize(_8087elems) - 1] = ndp_zero; 206 206 } 207 207 208 208 /******************************* 209 209 * Push 8087 stack. Generate and return any code 210 210 * necessary to preserve anything that might run off the end of the stack. 211 211 */ 212 212 213 code *push87() 213 #undef push87 214 215 #ifdef DEBUG 216 code *push87(int line, const char *file); 217 code *push87() { return push87(__LINE__,__FILE__); } 218 #endif 219 220 code *push87( 221 #ifdef DEBUG 222 int line, const char *file 223 #endif 224 ) 225 #ifdef DEBUG 226 #define push87() push87(__LINE__,__FILE__) 227 #endif 214 228 { 215 229 code *c; 216 230 int i; 217 231 218 232 c = CNIL; 219 233 // if we would lose the top register off of the stack 220 234 if (_8087elems[7].e != NULL) 221 235 { 222 236 i = getemptyslot(); 223 237 NDP::save[i] = _8087elems[7]; 224 238 c = genf2(c,0xD9,0xF6); // FDECSTP 225 239 c = genfwait(c); 226 240 c = ndp_fstp(c, i, _8087elems[7].e->Ety); // FSTP i[BP] 227 241 assert(stackused == 8); 228 242 if (NDPP) dbg_printf("push87() : overflow\n"); 229 243 } 230 244 else 231 245 { 232 if (NDPP) dbg_printf("push87(%d)\n",stackused); 246 #ifdef DEBUG 247 if (NDPP) dbg_printf("push87(%s(%d): %d)\n", file, line, stackused); 248 #endif 233 249 stackused++; 234 250 assert(stackused <= 8); 235 251 } 236 252 // Shift the stack up 237 253 for (i = 7; i > 0; i--) 238 254 _8087elems[i] = _8087elems[i - 1]; 239 255 _8087elems[0] = ndp_zero; 240 256 return c; 241 257 } 242 258 243 259 /***************************** 244 260 * Note elem e as being in ST(i) as being a value we want to keep. 245 261 */ 246 262 247 263 #ifdef DEBUG 248 264 void note87(elem *e, unsigned offset, int i, int linnum); 249 265 void note87(elem *e, unsigned offset, int i) 250 266 { 251 267 return note87(e, offset, i, 0); 252 268 } … … 472 488 c = cat(c,fixresult(e,mST0,pretregs)); 473 489 } 474 490 else 475 491 // Reload 476 492 c = loaddata(e,pretregs); 477 493 } 478 494 479 495 freenode(e); 480 496 return c; 481 497 } 482 498 483 499 484 500 /************************** 485 501 * Generate code to deal with floatreg. 486 502 */ 487 503 488 504 code * genfltreg(code *c,unsigned opcode,unsigned reg,targ_size_t offset) 489 505 { 490 506 floatreg = TRUE; 491 507 reflocal = TRUE; 492 if ((opcode & 0xF8) == 0xD8)508 if ((opcode & ~7) == 0xD8) 493 509 c = genfwait(c); 494 unsigned grex = I64 ? (REX_W << 16) : 0; 495 return genc1(c,opcode,grex | modregxrm(2,reg,BPRM),FLfltreg,offset); 510 return genc1(c,opcode,modregxrm(2,reg,BPRM),FLfltreg,offset); 496 511 } 497 512 498 513 /******************************* 499 514 * Decide if we need to gen an FWAIT. 500 515 */ 501 516 502 517 code *genfwait(code *c) 503 518 { 504 519 if (ADDFWAIT()) 505 520 c = gen1(c,FWAIT); 506 521 return c; 507 522 } 508 523 509 524 /*************************************** 510 525 * Generate floating point instruction. 511 526 */ 512 527 513 528 STATIC code * genf2(code *c,unsigned op,unsigned rm) 514 529 { 515 530 return gen2(genfwait(c),op,rm); … … 824 839 else 825 840 { c2 = genfltreg(c2,0x8B,AX,6); 826 841 genfltreg(c2,0x8B,BX,4); 827 842 genfltreg(c2,0x8B,CX,2); 828 843 genfltreg(c2,0x8B,DX,0); 829 844 } 830 845 } 831 846 } 832 847 else if (*pretregs == 0 && retregs == mST0) 833 848 { 834 849 c1 = genf2(c1,0xDD,modregrm(3,3,0)); // FPOP 835 850 pop87(); 836 851 } 837 852 else 838 853 { if (*pretregs & mPSW) 839 854 { if (!(retregs & mPSW)) 840 855 { assert(retregs & mST0); 841 856 c1 = genftst(c1,e,!(*pretregs & mST0)); // FTST 842 857 } 843 858 } 844 assert(!(*pretregs & mST0) || (retregs & mST0)); 859 if (*pretregs & mST0 && retregs & XMMREGS) 860 { 861 assert(sz <= DOUBLESIZE); 862 unsigned mf = (sz == FLOATSIZE) ? MFfloat : MFdouble; 863 // MOVD floatreg,XMM? 864 unsigned reg = findreg(retregs); 865 c1 = genfltreg(c1,0xF20F11,reg - XMM0,0); 866 c2 = push87(); 867 c2 = genfltreg(c2,ESC(mf,1),0,0); // FLD float/double ptr fltreg 868 } 869 else if (retregs & mST0 && *pretregs & XMMREGS) 870 { 871 assert(sz <= DOUBLESIZE); 872 unsigned mf = (sz == FLOATSIZE) ? MFfloat : MFdouble; 873 // FSTP floatreg 874 pop87(); 875 c1 = genfltreg(c1,ESC(mf,1),3,0); 876 genfwait(c1); 877 // MOVD XMM?,floatreg 878 unsigned reg; 879 c2 = allocreg(pretregs,®,(sz == FLOATSIZE) ? TYfloat : TYdouble); 880 c2 = genfltreg(c2,0xF20F10,reg -XMM0,0); 881 } 882 else 883 assert(!(*pretregs & mST0) || (retregs & mST0)); 845 884 } 846 885 if (*pretregs & mST0) 847 886 note87(e,0,0); 848 887 return cat(c1,c2); 849 888 } 850 889 851 890 /******************************** 852 891 * Generate in-line 8087 code for the following operators: 853 892 * add 854 893 * min 855 894 * mul 856 895 * div 857 896 * cmp 858 897 */ 859 898 860 899 // Reverse the order that the op is done in 861 900 static const char oprev[9] = { -1,0,1,2,3,5,4,7,6 }; 862 901 863 902 code *orth87(elem *e,regm_t *pretregs) 864 903 { … … 1699 1738 c = regwithvalue(c,ALLREGS & mMSW,0,®,0); // 0-extend 1700 1739 retregs |= mask[reg]; 1701 1740 mf1 = MFlong; 1702 1741 goto L3; 1703 1742 } 1704 1743 case OPs16_d: mf1 = MFword; goto L6; 1705 1744 case OPs32_d: mf1 = MFlong; goto L6; 1706 1745 L6: 1707 1746 if (op != -1) 1708 1747 note87(eleft,eoffset,0); // don't trash this value 1709 1748 if (e->E1->Eoper == OPvar || 1710 1749 (e->E1->Eoper == OPind && e->E1->Ecount == 0)) 1711 1750 { 1712 1751 goto L4; 1713 1752 } 1714 1753 else 1715 1754 { 1716 1755 retregs = ALLREGS; 1717 1756 c = codelem(e->E1,&retregs,FALSE); 1718 1757 L3: 1719 if ( !I32&& e->Eoper != OPs16_d)1758 if (I16 && e->Eoper != OPs16_d) 1720 1759 { 1721 1760 /* MOV floatreg+2,reg */ 1722 1761 reg = findregmsw(retregs); 1723 1762 c = genfltreg(c,0x89,reg,REGSIZE); 1724 1763 retregs &= mLSW; 1725 1764 } 1726 1765 reg = findreg(retregs); 1727 1766 c = genfltreg(c,0x89,reg,0); /* MOV floatreg,reg */ 1728 1767 if (op != -1) 1729 1768 { c = cat(c,makesure87(eleft,eoffset,0,0)); 1730 1769 genfltreg(c,ESC(mf1,0),op,0); /* Fop floatreg */ 1731 1770 } 1732 1771 else 1733 1772 { 1734 1773 /* FLD long ptr floatreg */ 1735 1774 c = cat(c,push87()); 1736 1775 c = genfltreg(c,ESC(mf1,1),0,0); 1737 1776 } 1738 1777 } 1739 1778 break; … … 3304 3343 c2 = genfltreg(c2, 0x8B, DX, 0); // MOV EDX,floatreg 3305 3344 3306 3345 pop87(); 3307 3346 c2 = genfltreg(c2, ESC(MFfloat,1),3,0); // FSTP floatreg 3308 3347 genfwait(c2); 3309 3348 c2 = genfltreg(c2, 0x8B, AX, 0); // MOV EAX,floatreg 3310 3349 } 3311 3350 else if (tym == TYcfloat && retregs & (mAX|mDX) && *pretregs & mST01) 3312 3351 { 3313 3352 c1 = push87(); 3314 3353 c1 = genfltreg(c1, 0x89, AX, 0); // MOV floatreg, EAX 3315 3354 genfltreg(c1, 0xD9, 0, 0); // FLD float ptr floatreg 3316 3355 3317 3356 c2 = push87(); 3318 3357 c2 = genfltreg(c2, 0x89, DX, 0); // MOV floatreg, EDX 3319 3358 genfltreg(c2, 0xD9, 0, 0); // FLD float ptr floatreg 3320 3359 3321 3360 if (*pretregs & mPSW) 3322 3361 c2 = genctst(c2,e,0); // FTST 3323 3362 } 3363 else if ((tym == TYcfloat || tym == TYcdouble) && 3364 *pretregs & (mXMM0|mXMM1) && retregs & mST01) 3365 { 3366 if (*pretregs & mPSW && !(retregs & mPSW)) 3367 c1 = genctst(c1,e,0); // FTST 3368 pop87(); 3369 c1 = genfltreg(c1, ESC(MFdouble,1),3,0); // FSTP floatreg 3370 genfwait(c1); 3371 c2 = getregs(mXMM0|mXMM1); 3372 c2 = genfltreg(c2, 0xF20F10, XMM1 - XMM0, 0); // MOVD XMM1,floatreg 3373 3374 pop87(); 3375 c2 = genfltreg(c2, ESC(MFdouble,1),3,0); // FSTP floatreg 3376 genfwait(c2); 3377 c2 = genfltreg(c2, 0xF20F10, XMM0 - XMM0, 0); // MOVD XMM0,floatreg 3378 } 3379 else if ((tym == TYcfloat || tym == TYcdouble) && 3380 retregs & (mXMM0|mXMM1) && *pretregs & mST01) 3381 { 3382 c1 = push87(); 3383 c1 = genfltreg(c1, 0xF20F11, XMM0-XMM0, 0); // MOVD floatreg, XMM0 3384 genfltreg(c1, 0xDD, 0, 0); // FLD double ptr floatreg 3385 3386 c2 = push87(); 3387 c2 = genfltreg(c2, 0xF20F11, XMM1-XMM0, 0); // MOV floatreg, XMM1 3388 genfltreg(c2, 0xDD, 0, 0); // FLD double ptr floatreg 3389 3390 if (*pretregs & mPSW) 3391 c2 = genctst(c2,e,0); // FTST 3392 } 3324 3393 else 3325 3394 { if (*pretregs & mPSW) 3326 3395 { if (!(retregs & mPSW)) 3327 3396 { assert(retregs & mST01); 3328 3397 c1 = genctst(c1,e,!(*pretregs & mST01)); // FTST 3329 3398 } 3330 3399 } 3331 3400 assert(!(*pretregs & mST01) || (retregs & mST01)); 3332 3401 } 3333 3402 if (*pretregs & mST01) 3334 3403 { note87(e,0,1); 3335 3404 note87(e,sz/2,0); 3336 3405 } 3337 3406 return cat(c1,c2); 3338 3407 } 3339 3408 3340 3409 /***************************************** 3341 3410 * Operators OPc_r and OPc_i 3342 3411 */ 3343 3412 … … 3381 3450 assert(*pretregs & (mST01 | mPSW)); 3382 3451 assert(!(*pretregs & ~(mST01 | mPSW))); 3383 3452 } 3384 3453 __out (result) 3385 3454 { 3386 3455 } 3387 3456 __body 3388 3457 #endif 3389 3458 { 3390 3459 tym_t ty = tybasic(e->Ety); 3391 3460 code *c = NULL; 3392 3461 code *cpush = NULL; 3393 3462 code cs; 3394 3463 unsigned mf; 3395 3464 unsigned sz; 3396 3465 unsigned char ldop; 3397 3466 regm_t retregs; 3398 3467 symbol *s; 3399 3468 int i; 3400 3469 3470 //printf("cload87(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 3401 3471 sz = tysize[ty] / 2; 3402 3472 memset(&cs, 0, sizeof(cs)); 3403 3473 if (ADDFWAIT()) 3404 3474 cs.Iflags = CFwait; 3405 3475 switch (ty) 3406 3476 { 3407 3477 case TYcfloat: mf = MFfloat; break; 3408 3478 case TYcdouble: mf = MFdouble; break; 3409 3479 case TYcldouble: break; 3410 3480 default: assert(0); 3411 3481 } 3412 3482 switch (e->Eoper) 3413 3483 { 3414 3484 case OPvar: 3415 3485 notreg(e); // never enregister this variable 3416 3486 case OPind: 3417 3487 cpush = cat(push87(), push87()); 3418 3488 switch (ty) 3419 3489 { 3420 3490 case TYcfloat: branches/dmd-1.x/src/backend/cgcod.c
r619 r627 377 377 i = branch(b,0); // see if jmp => jmp short 378 378 if (i) /* if any bytes saved */ 379 379 { targ_size_t offset; 380 380 381 381 b->Bsize -= i; 382 382 offset = b->Boffset + b->Bsize; 383 383 for (bn = b->Bnext; bn; bn = bn->Bnext) 384 384 { 385 385 if (bn->Balign) 386 386 { targ_size_t u = bn->Balign - 1; 387 387 388 388 offset = (offset + u) & ~u; 389 389 } 390 390 bn->Boffset = offset; 391 391 offset += bn->Bsize; 392 392 } 393 393 coffset = offset; 394 394 flag = TRUE; 395 395 } 396 396 } 397 if ( I32&& !(config.flags4 & CFG4optimized))397 if (!I16 && !(config.flags4 & CFG4optimized)) 398 398 break; // use the long conditional jmps 399 399 } while (flag); // loop till no more bytes saved 400 400 #ifdef DEBUG 401 401 debugw && printf("code jump optimization complete\n"); 402 402 #endif 403 403 404 404 // Compute starting offset for switch tables 405 405 #if ELFOBJ || MACHOBJ 406 406 swoffset = (config.flags & CFGromable) ? coffset : CDoffset; 407 407 #else 408 408 swoffset = (config.flags & CFGromable) ? coffset : Doffset; 409 409 #endif 410 410 swoffset = align(0,swoffset); 411 411 412 412 // Emit the generated code 413 413 if (eecontext.EEcompile == 1) 414 414 { 415 415 codout(eecontext.EEcode); 416 416 code_free(eecontext.EEcode); 417 417 #if SCPP branches/dmd-1.x/src/backend/cgelem.c
r618 r627 2066 2066 return optelem(e,TRUE); 2067 2067 } 2068 2068 #else 2069 2069 { 2070 2070 e->Eoper = OPeq; 2071 2071 el_free(e->E2); 2072 2072 e->E2 = el_copytree(e1); 2073 2073 e->E2 = el_una(OPneg,tym,e->E2); 2074 2074 return optelem(e,TRUE); 2075 2075 } 2076 2076 #endif 2077 2077 #endif 2078 2078 } 2079 2079 2080 2080 if (OPTIMIZER) 2081 2081 { 2082 2082 if (tyintegral(tym) && (e->Eoper == OPdiv || e->Eoper == OPmod)) 2083 2083 { int sz = tysize(tym); 2084 2084 2085 2085 // See if we can replace with OPremquo 2086 if (sz == intsize)2086 if (sz == REGSIZE && !I64) // need cent and ucent working for I64 to work 2087 2087 { 2088 2088 // Don't do it if there are special code sequences in the 2089 2089 // code generator (see cdmul()) 2090 2090 int pow2; 2091 2091 if (e->E2->Eoper == OPconst && 2092 2092 sz == REGSIZE && !uns && 2093 2093 (pow2 = ispow2(el_tolong(e->E2))) != -1 && 2094 2094 !(config.target_cpu < TARGET_80286 && pow2 != 1 && e->Eoper == OPdiv) 2095 2095 ) 2096 2096 ; 2097 2097 else 2098 2098 { 2099 2099 assert(sz == 2 || sz == 4); 2100 2100 int op = OPmsw; 2101 2101 if (e->Eoper == OPdiv) 2102 2102 { 2103 2103 op = (sz == 2) ? OP32_16 : OP64_32; 2104 2104 } 2105 2105 e->Eoper = OPremquo; 2106 2106 e = el_una(op, tym, e); branches/dmd-1.x/src/backend/cgen.c
r606 r627 144 144 * Add code to end of linked list. 145 145 * Note that unused operands are garbage. 146 146 * gen1() and gen2() are shortcut routines. 147 147 * Input: 148 148 * c -> linked list that code is to be added to end of 149 149 * cs -> data for the code 150 150 * Returns: 151 151 * pointer to start of code list 152 152 */ 153 153 154 154 code *gen(code *c,code *cs) 155 155 { code *ce,*cstart; 156 156 unsigned reg; 157 157 158 158 #ifdef DEBUG /* this is a high usage routine */ 159 159 assert(cs); 160 160 #endif 161 161 assert(I64 || cs->Irex == 0); 162 162 ce = code_calloc(); 163 163 *ce = *cs; 164 //printf("ce = %p %02x\n", ce, ce->Iop); 165 if (ce->Iop == LEA && ce->Irm == 4 && ce->Isib == 0x6D && ce->IFL1 == FLunde) *(char*)0=0; 164 166 if (config.flags4 & CFG4optimized && 165 167 ce->IFL2 == FLconst && 166 168 (ce->Iop == 0x81 || ce->Iop == 0x80) && 167 169 reghasvalue((ce->Iop == 0x80) ? BYTEREGS : ALLREGS,ce->IEV2.Vlong,®) && 168 170 !(ce->Iflags & CFopsize && I16) 169 171 ) 170 172 { // See if we can replace immediate instruction with register instruction 171 173 static unsigned char regop[8] = 172 174 { 0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38 }; 173 175 174 176 //printf("replacing 0x%02x, val = x%lx\n",ce->Iop,ce->IEV2.Vlong); 175 177 ce->Iop = regop[(ce->Irm & modregrm(0,7,0)) >> 3] | (ce->Iop & 1); 176 178 code_newreg(ce, reg); 177 179 } 178 180 code_next(ce) = CNIL; 179 181 if (c) 180 182 { cstart = c; 181 183 while (code_next(c)) c = code_next(c); /* find end of list */ 182 184 code_next(c) = ce; /* link into list */ 183 185 return cstart; 184 186 } 185 187 return ce; 186 188 } 187 189 188 190 code *gen1(code *c,unsigned op) 189 191 { code *ce,*cstart; 190 192 191 193 ce = code_calloc(); 192 194 ce->Iop = op; 195 assert(op != LEA); 193 196 if (c) 194 197 { cstart = c; 195 198 while (code_next(c)) c = code_next(c); /* find end of list */ 196 199 code_next(c) = ce; /* link into list */ 197 200 return cstart; 198 201 } 199 202 return ce; 200 203 } 201 204 202 205 code *gen2(code *c,unsigned op,unsigned rm) 203 206 { code *ce,*cstart; 204 207 205 208 cstart = ce = code_calloc(); 206 209 /*cxcalloc++;*/ 207 210 ce->Iop = op; 208 211 ce->Iea = rm; 209 212 if (c) 210 213 { cstart = c; 211 214 while (code_next(c)) c = code_next(c); /* find end of list */ 212 215 code_next(c) = ce; /* link into list */ 213 216 } 214 217 return cstart; 215 218 } 216 219 217 220 code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib) 218 221 { code *ce,*cstart; 219 222 220 223 cstart = ce = code_calloc(); 221 224 /*cxcalloc++;*/ 225 if (op == LEA && (rm & 0xFF) == 4 && (sib & 0xFF) == 0x6D) *(char*)0=0; 222 226 ce->Iop = op; 223 227 ce->Irm = rm; 224 228 ce->Isib = sib; 225 229 ce->Irex = (rm | (sib & (REX_B << 16))) >> 16; 226 230 if (sib & (REX_R << 16)) 227 231 ce->Irex |= REX_X; 228 232 if (c) 229 233 { cstart = c; 230 234 while (code_next(c)) c = code_next(c); /* find end of list */ 231 235 code_next(c) = ce; /* link into list */ 232 236 } 233 237 return cstart; 234 238 } 235 239 236 240 code *genregs(code *c,unsigned op,unsigned dstreg,unsigned srcreg) 237 241 { return gen2(c,op,modregxrmx(3,dstreg,srcreg)); } 238 242 239 243 code *gentstreg(code *c,unsigned t) 240 244 { 241 245 c = gen2(c,0x85,modregxrmx(3,t,t)); // TEST t,t … … 370 374 cs.Iea = ea; 371 375 cs.Iflags = CFoff; 372 376 cs.IFL2 = FLconst; 373 377 cs.IEV2.Vsize_t = EV2; 374 378 return gen(c,&cs); 375 379 } 376 380 377 381 /***************** 378 382 * Generate code. 379 383 */ 380 384 381 385 code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 382 386 { code cs; 383 387 384 388 assert(FL1 < FLMAX); 385 389 cs.Iop = op; 386 390 cs.Iflags = CFoff; 387 391 cs.Iea = ea; 388 392 cs.IFL1 = FL1; 389 393 cs.IEV1.Vsize_t = EV1; 394 if (cs.Iop == LEA && cs.IFL1 == FLunde) *(char*)0=0; 390 395 return gen(c,&cs); 391 396 } 392 397 393 398 /***************** 394 399 * Generate code. 395 400 */ 396 401 397 402 code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 398 403 { code cs; 399 404 400 405 assert(FL1 < FLMAX); 401 406 cs.Iop = op; 402 407 cs.Iea = ea; 403 408 cs.Iflags = CFoff; 404 409 cs.IFL1 = FL1; 405 410 cs.IEV1.Vsize_t = EV1; 406 411 assert(FL2 < FLMAX); 407 412 cs.IFL2 = FL2; 408 413 cs.IEV2.Vsize_t = EV2; 409 414 return gen(c,&cs); branches/dmd-1.x/src/backend/cod1.c
r621 r627 1855 1855 c = getregs(forregs); 1856 1856 ce = gen1(ce,0x58 + DX); 1857 1857 gen1(ce,0x58 + CX); 1858 1858 gen1(ce,0x58 + BX); 1859 1859 gen1(ce,0x58 + AX); 1860 1860 stackpush -= DOUBLESIZE; 1861 1861 retregs = DOUBLEREGS_16; /* for tstresult() below */ 1862 1862 } 1863 1863 else 1864 1864 #ifdef DEBUG 1865 1865 printf("retregs = x%x, forregs = x%x\n",retregs,forregs), 1866 1866 #endif 1867 1867 assert(0); 1868 1868 if (EOP(e)) 1869 1869 opsflag = TRUE; 1870 1870 } 1871 1871 else 1872 1872 { 1873 1873 c = allocreg(pretregs,&rreg,tym); /* allocate return regs */ 1874 1874 if (sz > REGSIZE) 1875 { unsigned msreg,lsreg; 1876 unsigned msrreg,lsrreg; 1877 1878 msreg = findregmsw(retregs); 1879 lsreg = findreglsw(retregs); 1880 msrreg = findregmsw(*pretregs); 1881 lsrreg = findreglsw(*pretregs); 1875 { 1876 unsigned msreg = findregmsw(retregs); 1877 unsigned lsreg = findreglsw(retregs); 1878 unsigned msrreg = findregmsw(*pretregs); 1879 unsigned lsrreg = findreglsw(*pretregs); 1882 1880 1883 1881 ce = genmovreg(ce,msrreg,msreg); /* MOV msrreg,msreg */ 1884 1882 ce = genmovreg(ce,lsrreg,lsreg); /* MOV lsrreg,lsreg */ 1885 1883 } 1884 else if (retregs & XMMREGS) 1885 { 1886 reg = findreg(retregs & XMMREGS); 1887 // MOVD floatreg, XMM? 1888 ce = genfltreg(ce,0xF20F11,reg - XMM0,0); 1889 // MOV rreg,floatreg 1890 ce = genfltreg(ce,0x8B,rreg,0); 1891 if (sz == 8) 1892 code_orrex(ce,REX_W); 1893 } 1886 1894 else 1887 { reg = findreg(retregs & (mBP | ALLREGS)); 1895 { 1896 reg = findreg(retregs & (mBP | ALLREGS)); 1888 1897 ce = genmovreg(ce,rreg,reg); /* MOV rreg,reg */ 1889 1898 } 1890 1899 } 1891 1900 c = cat(c,ce); 1892 1901 cssave(e,retregs | *pretregs,opsflag); 1893 1902 forregs = 0; /* don't care about result in reg */ 1894 1903 /* cuz we have real result in rreg */ 1895 1904 retregs = *pretregs & ~mPSW; 1896 1905 } 1897 1906 if (forccs) /* if return result in flags */ 1898 1907 c = cat(c,tstresult(retregs,tym,forregs)); 1899 1908 return c; 1900 1909 } 1901 1910 1902 1911 1903 1912 /******************************** 1904 1913 * Generate code sequence to call C runtime library support routine. 1905 1914 * clib = CLIBxxxx 1906 1915 * keepmask = mask of registers not to destroy. Currently can 1907 1916 * handle only 1. Should use a temporary rather than 1908 1917 * push/pop for speed. 1909 1918 */ 1910 1919 1911 1920 int clib_inited = 0; // != 0 if initialized 1912 1921 1913 1922 code *callclib(elem *e,unsigned clib,regm_t *pretregs,regm_t keepmask) 1914 1923 { 1924 //printf("callclib(e = %p, clib = %d, *pretregs = %s, keepmask = %s\n", e, clib, regm_str(*pretregs), regm_str(keepmask)); 1925 //elem_print(e); 1915 1926 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 1916 1927 static symbol lib[] = 1917 1928 { 1918 1929 /* Convert destroyed regs into saved regs */ 1919 1930 #define Z(desregs) (~(desregs) & (mBP| mES | ALLREGS)) 1920 1931 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 1921 1932 #define N(name) "_" name 1922 1933 #else 1923 1934 #define N(name) name 1924 1935 #endif 1925 1936 1926 1937 /* Shorthand to map onto SYMBOLY() */ 1927 1938 #define Y(desregs,name) SYMBOLY(FLfunc,Z(desregs),N(name),0) 1928 1939 1929 1940 Y(0,"_LCMP__"), // CLIBlcmp 1930 1941 Y(mAX|mCX|mDX,"_LMUL__"), // CLIBlmul 1931 1942 #if 1 1932 1943 Y(mAX|mBX|mCX|mDX,"_LDIV__"), // CLIBldiv 1933 1944 Y(mAX|mBX|mCX|mDX,"_LDIV__"), // CLIBlmod 1934 1945 Y(mAX|mBX|mCX|mDX,"_ULDIV__"), // CLIBuldiv … … 2081 2092 2082 2093 // NOTE: desregs is wrong for 16 bit code, mBX should be included 2083 2094 Y(mST0|mST01,"_Cmul"), // CLIBcmul 2084 2095 Y(mAX|mCX|mDX|mST0|mST01,"_Cdiv"), // CLIBcdiv 2085 2096 Y(mAX|mST0|mST01,"_Ccmp"), // CLIBccmp 2086 2097 2087 2098 Y(mST0,"_U64_LDBL"), // CLIBu64_ldbl 2088 2099 Y(mST0|mAX|mDX,"__LDBLULLNG"), // CLIBld_u64 2089 2100 }; 2090 2101 #endif 2091 2102 2092 2103 static struct 2093 2104 { 2094 2105 regm_t retregs16; /* registers that 16 bit result is returned in */ 2095 2106 regm_t retregs32; /* registers that 32 bit result is returned in */ 2096 2107 char pop; /* # of bytes popped off of stack upon return */ 2097 2108 char flags; 2098 2109 #define INF32 1 // if 32 bit only 2099 2110 #define INFfloat 2 // if this is floating point 2100 2111 #define INFwkdone 4 // if weak extern is already done 2112 #define INF64 8 // if 64 bit only 2101 2113 char push87; // # of pushes onto the 8087 stack 2102 2114 char pop87; // # of pops off of the 8087 stack 2103 2115 } info[CLIBMAX] = 2104 2116 { 2105 2117 {0,0,0,0}, /* _LCMP@ lcmp */ 2106 2118 {mDX|mAX,mDX|mAX,0,0}, // _LMUL@ lmul 2107 2119 {mDX|mAX,mDX|mAX,0,0}, // _LDIV@ ldiv 2108 2120 {mCX|mBX,mCX|mBX,0,0}, /* _LDIV@ lmod */ 2109 2121 {mDX|mAX,mDX|mAX,0,0}, /* _ULDIV@ uldiv */ 2110 2122 {mCX|mBX,mCX|mBX,0,0}, /* _ULDIV@ ulmod */ 2111 2123 2112 2124 #if TARGET_WINDOS 2113 2125 {DOUBLEREGS_16,DOUBLEREGS_32,8,INFfloat,1,1}, // _DMUL@ dmul 2114 2126 {DOUBLEREGS_16,DOUBLEREGS_32,8,INFfloat,1,1}, // _DDIV@ ddiv 2115 2127 {0,0,0,2}, // _DTST0@ 2116 2128 {0,0,0,2}, // _DTST0EXC@ 2117 2129 {0,0,8,INFfloat,1,1}, // _DCMP@ dcmp 2118 2130 {0,0,8,INFfloat,1,1}, // _DCMPEXC@ dcmp 2119 2131 {DOUBLEREGS_16,DOUBLEREGS_32,0,2}, // _DNEG@ dneg 2120 2132 {DOUBLEREGS_16,DOUBLEREGS_32,8,INFfloat,1,1}, // _DADD@ dadd … … 2158 2170 {DOUBLEREGS_16,DOUBLEREGS_32,0,INFfloat,1,1}, // _ULLNGDBL@ 2159 2171 2160 2172 {0,0,0,2}, // _DTST@ dtst 2161 2173 {mES|mBX,mES|mBX,0,0}, // _HTOFPTR@ vptrfptr 2162 2174 {mES|mBX,mES|mBX,0,0}, // _HCTOFPTR@ cvptrfptr 2163 2175 {0,0,0,2}, // _87TOPSW@ 87topsw 2164 2176 {mST0,mST0,0,INFfloat,1,0}, // _FLTTO87@ fltto87 2165 2177 {mST0,mST0,0,INFfloat,1,0}, // _DBLTO87@ dblto87 2166 2178 {mAX,mAX,0,2}, // _DBLINT87@ dblint87 2167 2179 {mDX|mAX,mAX,0,2}, // _DBLLNG87@ dbllng87 2168 2180 {0,0,0,2}, // _FTST@ 2169 2181 {mPSW,mPSW,0,INFfloat,0,2}, // _FCOMPP@ 2170 2182 {mPSW,mPSW,0,2}, // _FTEST@ 2171 2183 {mPSW,mPSW,0,2}, // _FTEST0@ 2172 2184 {mST0,mST0,0,INFfloat,1,1}, // _FDIV@ 2173 2185 2174 2186 {mST01,mST01,0,INF32|INFfloat,3,5}, // _Cmul 2175 2187 {mST01,mST01,0,INF32|INFfloat,0,2}, // _Cdiv 2176 2188 {mPSW, mPSW, 0,INF32|INFfloat,0,4}, // _Ccmp 2177 2189 2178 {mST0,mST0,0,INF32|INF float,2,1}, // _U64_LDBL2179 {0,mDX|mAX,0,INF32|INF float,1,2}, // __LDBLULLNG2190 {mST0,mST0,0,INF32|INF64|INFfloat,2,1}, // _U64_LDBL 2191 {0,mDX|mAX,0,INF32|INF64|INFfloat,1,2}, // __LDBLULLNG 2180 2192 }; 2181 2193 2182 2194 if (!clib_inited) /* if not initialized */ 2183 2195 { 2184 2196 assert(sizeof(lib) / sizeof(lib[0]) == CLIBMAX); 2185 2197 assert(sizeof(info) / sizeof(info[0]) == CLIBMAX); 2186 2198 for (int i = 0; i < CLIBMAX; i++) 2187 2199 { lib[i].Stype = tsclib; 2188 2200 #if MARS 2189 2201 lib[i].Sxtrnnum = 0; 2190 2202 lib[i].Stypidx = 0; 2191 2203 #endif 2192 2204 } 2193 2205 2194 2206 if (!I16) 2195 2207 { /* Adjust table for 386 */ 2196 2208 lib[CLIBdbllng].Sregsaved = Z(DOUBLEREGS_32); 2197 2209 lib[CLIBlngdbl].Sregsaved = Z(DOUBLEREGS_32); 2198 2210 lib[CLIBdblint].Sregsaved = Z(DOUBLEREGS_32); 2199 2211 lib[CLIBintdbl].Sregsaved = Z(DOUBLEREGS_32); … … 2202 2214 lib[CLIBdneg].Sregsaved = Z(DOUBLEREGS_32); 2203 2215 lib[CLIBdbluns].Sregsaved = Z(DOUBLEREGS_32); 2204 2216 lib[CLIBunsdbl].Sregsaved = Z(DOUBLEREGS_32); 2205 2217 lib[CLIBdblulng].Sregsaved = Z(DOUBLEREGS_32); 2206 2218 lib[CLIBulngdbl].Sregsaved = Z(DOUBLEREGS_32); 2207 2219 #endif 2208 2220 lib[CLIBdblflt].Sregsaved = Z(DOUBLEREGS_32); 2209 2221 lib[CLIBfltdbl].Sregsaved = Z(DOUBLEREGS_32); 2210 2222 2211 2223 lib[CLIBdblllng].Sregsaved = Z(DOUBLEREGS_32); 2212 2224 lib[CLIBllngdbl].Sregsaved = Z(DOUBLEREGS_32); 2213 2225 lib[CLIBdblullng].Sregsaved = Z(DOUBLEREGS_32); 2214 2226 lib[CLIBullngdbl].Sregsaved = Z(DOUBLEREGS_32); 2215 2227 } 2216 2228 clib_inited++; 2217 2229 } 2218 2230 #undef Z 2219 2231 2220 2232 assert(clib < CLIBMAX); 2221 2233 symbol *s = &lib[clib]; 2222 assert(I32 || !(info[clib].flags & INF32)); 2234 if (I16) 2235 assert(!(info[clib].flags & (INF32 | INF64))); 2223 2236 code *cpop = CNIL; 2224 2237 code *c = getregs((~s->Sregsaved & (mES | mBP | ALLREGS)) & ~keepmask); // mask of regs destroyed 2225 2238 keepmask &= ~s->Sregsaved; 2226 2239 int npushed = numbitsset(keepmask); 2227 2240 gensaverestore2(keepmask, &c, &cpop); 2228 2241 #if 0 2229 2242 while (keepmask) 2230 2243 { unsigned keepreg; 2231 2244 2232 2245 if (keepmask & (mBP|ALLREGS)) 2233 2246 { keepreg = findreg(keepmask & (mBP|ALLREGS)); 2234 2247 c = gen1(c,0x50 + keepreg); /* PUSH keepreg */ 2235 2248 cpop = cat(gen1(CNIL,0x58 + keepreg),cpop); // POP keepreg 2236 2249 keepmask &= ~mask[keepreg]; 2237 2250 npushed++; 2238 2251 } 2239 2252 if (keepmask & mES) 2240 2253 { c = gen1(c,0x06); /* PUSH ES */ 2241 2254 cpop = cat(gen1(CNIL,0x07),cpop); /* POP ES */ 2242 2255 keepmask &= ~mES; … … 3593 3606 code_newreg(c, c->Irm & 7); 3594 3607 if (c->Irex & REX_B) 3595 3608 c->Irex = (c->Irex & ~REX_B) | REX_R; 3596 3609 } 3597 3610 } 3598 3611 } 3599 3612 else if (sz < 8) 3600 3613 { 3601 3614 c = allocreg(®m,®,TYoffset); /* get a register */ 3602 3615 if (I32) // it's a 48 bit pointer 3603 3616 ce = loadea(e,&cs,0x0FB7,reg,REGSIZE,0,0); /* MOVZX reg,data+4 */ 3604 3617 else 3605 3618 { ce = loadea(e,&cs,0x8B,reg,REGSIZE,0,0); /* MOV reg,data+2 */ 3606 3619 if (tym == TYfloat || tym == TYifloat) // dump sign bit 3607 3620 gen2(ce,0xD1,modregrm(3,4,reg)); /* SHL reg,1 */ 3608 3621 } 3609 3622 c = cat(c,ce); 3610 3623 ce = loadea(e,&cs,0x0B,reg,0,regm,0); /* OR reg,data */ 3611 3624 c = cat(c,ce); 3612 3625 } 3613 else if (sz == 8) 3614 { code *c1; 3615 int i; 3616 3626 else if (sz == 8 || (I64 && sz == 2 * REGSIZE && !tyfloating(tym))) 3627 { 3617 3628 c = allocreg(®m,®,TYoffset); /* get a register */ 3618 i = sz - REGSIZE;3629 int i = sz - REGSIZE; 3619 3630 ce = loadea(e,&cs,0x8B,reg,i,0,0); /* MOV reg,data+6 */ 3620 3631 if (tyfloating(tym)) // TYdouble or TYdouble_alias 3621 3632 gen2(ce,0xD1,modregrm(3,4,reg)); // SHL reg,1 3622 3633 c = cat(c,ce); 3623 3634 3624 3635 while ((i -= REGSIZE) >= 0) 3625 3636 { 3626 c 1 = loadea(e,&cs,0x0B,reg,i,regm,0); // OR reg,data+i3637 code *c1 = loadea(e,&cs,0x0B,reg,i,regm,0); // OR reg,data+i 3627 3638 if (i == 0) 3628 3639 c1->Iflags |= CFpsw; // need the flags on last OR 3629 3640 c = cat(c,c1); 3630 3641 } 3631 3642 } 3632 else if (sz == LNGDBLSIZE)// TYldouble3643 else if (sz == tysize[TYldouble]) // TYldouble 3633 3644 return load87(e,0,pretregs,NULL,-1); 3634 3645 else 3646 { 3647 #ifdef DEBUG 3648 elem_print(e); 3649 #endif 3635 3650 assert(0); 3651 } 3636 3652 return c; 3637 3653 } 3638 3654 /* not for flags only */ 3639 3655 flags = *pretregs & mPSW; /* save original */ 3640 3656 forregs = *pretregs & (mBP | ALLREGS | mES | XMMREGS); 3641 3657 if (*pretregs & mSTACK) 3642 3658 forregs |= DOUBLEREGS; 3643 3659 if (e->Eoper == OPconst) 3644 3660 { regm_t save; 3645 3661 3646 3662 if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,®)) 3647 3663 forregs = mask[reg]; 3648 3664 3649 3665 save = regcon.immed.mval; 3650 3666 c = allocreg(&forregs,®,tym); /* allocate registers */ 3651 3667 regcon.immed.mval = save; // KLUDGE! 3652 3668 if (sz <= REGSIZE) 3653 3669 { 3654 3670 if (sz == 1) 3655 3671 flags |= 1; branches/dmd-1.x/src/backend/cod2.c
r601 r627 210 210 if ((tylong(ty1) || ty1 == TYhptr) && 211 211 (tylong(ty2) || ty2 == TYhptr)) 212 212 numwords++; 213 213 } 214 214 215 215 // Special cases where only flags are set 216 216 if (test && tysize[ty1] <= REGSIZE && 217 217 (e1->Eoper == OPvar || (e1->Eoper == OPind && !e1->Ecount))) 218 218 { 219 219 // Handle the case of (var & const) 220 220 if (e2->Eoper == OPconst) 221 221 { 222 222 c = getlvalue(&cs,e1,0); 223 223 targ_size_t value = e2->EV.Vpointer; 224 224 if (sz == 2) 225 225 value &= 0xFFFF; 226 226 else if (sz == 4) 227 227 value &= 0xFFFFFFFF; 228 228 if (reghasvalue(byte ? BYTEREGS : ALLREGS,value,®)) 229 229 goto L11; 230 if (sz == 8 )230 if (sz == 8 && !I64) 231 231 { 232 232 assert(value == (int)value); // sign extend imm32 233 233 } 234 234 op1 = 0xF7; 235 235 cs.IEV2.Vint = value; 236 236 cs.IFL2 = FLconst; 237 237 goto L10; 238 238 } 239 239 240 240 // Handle (exp & reg) 241 241 if (isregvar(e2,&retregs,®)) 242 242 { 243 243 c = getlvalue(&cs,e1,0); 244 244 L11: 245 245 code_newreg(&cs, reg); 246 246 L10: 247 247 cs.Iop = op1 ^ byte; 248 248 cs.Iflags |= word | CFpsw; 249 249 freenode(e1); 250 250 freenode(e2); … … 392 392 393 393 // IMUL reg,imm32 394 394 c = genc2(CNIL,0x69,modregxrm(3,reg,BP),imm32[ss]); 395 395 } 396 396 else 397 397 { // LEA reg,[reg1*ss][reg1] 398 398 c = gen2sib(CNIL,0x8D,modregxrm(0,reg,4),modregrm(ss,reg1 & 7,reg1 & 7)); 399 399 if (reg1 & 8) 400 400 code_orrex(c, REX_X | REX_B); 401 401 } 402 402 reg1 = reg; 403 403 ss = ss2; // use *2 for scale 404 404 } 405 405 else 406 406 c = NULL; 407 407 c = cat4(c1,c2,c3,c); 408 408 409 409 cs.Iop = 0x8D; // LEA reg,c[reg1*ss][reg2] 410 410 cs.Irm = modregrm(2,reg & 7,4); 411 411 cs.Isib = modregrm(ss,reg1 & 7,reg2 & 7); 412 assert(reg2 != BP); 412 413 cs.Iflags = CFoff; 413 414 cs.Irex = 0; 414 415 if (reg & 8) 415 416 cs.Irex |= REX_R; 416 417 if (reg1 & 8) 417 418 cs.Irex |= REX_X; 418 419 if (reg2 & 8) 419 420 cs.Irex |= REX_B; 420 421 cs.IFL1 = FLconst; 421 422 cs.IEV1.Vuns = edisp->EV.Vuns; 422 423 423 424 freenode(edisp); 424 425 freenode(e1); 425 426 c = gen(c,&cs); 426 427 return cat(c,fixresult(e,mask[reg],pretregs)); 427 428 } 428 429 } 429 430 430 431 posregs = (byte) ? BYTEREGS : (mES | ALLREGS | mBP); 431 432 retregs = *pretregs & posregs; … … 759 760 760 761 code *cdmul(elem *e,regm_t *pretregs) 761 762 { unsigned rreg,op,oper,lib,byte; 762 763 regm_t resreg,retregs,rretregs; 763 764 regm_t keepregs; 764 765 tym_t uns; // 1 if unsigned operation, 0 if not 765 766 tym_t tyml; 766 767 code *c,*cg,*cl,*cr,cs; 767 768 elem *e1,*e2; 768 769 int sz; 769 770 targ_size_t e2factor; 770 771 int opunslng; 771 772 int pow2; 772 773 773 774 if (*pretregs == 0) // if don't want result 774 775 { c = codelem(e->E1,pretregs,FALSE); // eval left leaf 775 776 *pretregs = 0; // in case they got set 776 777 return cat(c,codelem(e->E2,pretregs,FALSE)); 777 778 } 778 779 780 //printf("cdmul(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 779 781 keepregs = 0; 780 782 cs.Iflags = 0; 781 783 cs.Irex = 0; 782 784 c = cg = cr = CNIL; // initialize 783 785 e2 = e->E2; 784 786 e1 = e->E1; 785 787 tyml = tybasic(e1->Ety); 786 788 sz = tysize[tyml]; 787 789 byte = tybyte(e->Ety) != 0; 788 790 uns = tyuns(tyml) || tyuns(e2->Ety); 789 791 oper = e->Eoper; 790 792 unsigned rex = (I64 && sz == 8) ? REX_W : 0; 791 793 unsigned grex = rex << 16; 792 794 793 795 if (tyfloating(tyml)) 794 796 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 795 797 return orth87(e,pretregs); 796 798 #else 797 799 return opdouble(e,pretregs,(oper == OPmul) ? CLIBdmul : CLIBddiv); 798 800 #endif … … 1010 1012 case 24: ss = 1; ss2 = 3; goto L4; 1011 1013 1012 1014 case 6: 1013 1015 case 3: ss = 1; goto L4; 1014 1016 1015 1017 case 20: ss = 2; ss2 = 2; goto L4; 1016 1018 case 40: ss = 2; ss2 = 3; goto L4; 1017 1019 1018 1020 case 10: 1019 1021 case 5: ss = 2; goto L4; 1020 1022 1021 1023 case 36: ss = 3; ss2 = 2; goto L4; 1022 1024 case 72: ss = 3; ss2 = 3; goto L4; 1023 1025 1024 1026 case 18: 1025 1027 case 9: ss = 3; goto L4; 1026 1028 1027 1029 L4: 1028 1030 { 1029 1031 #if 1 1030 regm_t regm = byte ? BYTEREGS : ALLREGS; // don't use EBP 1032 regm_t regm = byte ? BYTEREGS : ALLREGS; 1033 regm &= ~(mBP | mR13); // don't use EBP 1031 1034 cl = codelem(e->E1,®m,TRUE); 1032 1035 unsigned r = findreg(regm); 1033 1036 1034 1037 if (ss2) 1035 1038 { // Don't use EBP 1036 resreg &= ~ mBP;1039 resreg &= ~(mBP | mR13); 1037 1040 if (!resreg) 1038 1041 resreg = retregs; 1039 1042 } 1040 1043 cg = allocreg(&resreg,®,tyml); 1041 1044 1042 1045 c = gen2sib(CNIL,0x8D,grex | modregxrm(0,reg,4), 1043 1046 modregxrmx(ss,r,r)); 1047 assert((r & 7) != BP); 1044 1048 if (ss2) 1045 1049 { 1046 1050 gen2sib(c,0x8D,grex | modregxrm(0,reg,4), 1047 1051 modregxrm(ss2,reg,5)); 1048 1052 code_last(c)->IFL1 = FLconst; 1049 1053 code_last(c)->IEV1.Vint = 0; 1050 1054 } 1051 1055 else if (!(e2factor & 1)) // if even factor 1052 1056 { genregs(c,0x03,reg,reg); // ADD reg,reg 1053 1057 code_orrex(c,rex); 1054 1058 } 1055 1059 cg = cat(cg,c); 1056 1060 goto L3; 1057 1061 #else 1058 1062 1059 1063 // Don't use EBP 1060 1064 resreg &= ~mBP; 1061 1065 if (!resreg) 1062 1066 resreg = retregs; 1063 1067 … … 1071 1075 gen2sib(c,0x8D,modregrm(0,reg,4), 1072 1076 modregrm(ss2,reg,5)); 1073 1077 code_last(c)->IFL1 = FLconst; 1074 1078 code_last(c)->IEV1.Vint = 0; 1075 1079 } 1076 1080 else if (!(e2factor & 1)) // if even factor 1077 1081 genregs(c,0x03,reg,reg); // ADD reg,reg 1078 1082 cg = cat(cg,c); 1079 1083 goto L3; 1080 1084 #endif 1081 1085 } 1082 1086 case 37: 1083 1087 case 74: shift = 2; 1084 1088 goto L5; 1085 1089 case 13: 1086 1090 case 26: shift = 0; 1087 1091 goto L5; 1088 1092 L5: 1089 1093 { 1090 1094 // Don't use EBP 1091 resreg &= ~ mBP;1095 resreg &= ~(mBP | mR13); 1092 1096 if (!resreg) 1093 1097 resreg = retregs; 1094 1098 cl = allocreg(&resreg,®,TYint); 1095 1099 1096 regm_t sregm = ALLREGS& ~resreg;1100 regm_t sregm = (ALLREGS & ~mR13) & ~resreg; 1097 1101 cl = cat(cl,codelem(e->E1,&sregm,FALSE)); 1098 1102 unsigned sreg = findreg(sregm); 1099 1103 cg = getregs(resreg | sregm); 1100 1104 // LEA reg,[sreg * 4][sreg] 1101 1105 // SHL sreg,shift 1102 1106 // LEA reg,[sreg * 8][reg] 1107 assert((sreg & 7) != BP); 1108 assert((reg & 7) != BP); 1103 1109 c = gen2sib(CNIL,0x8D,grex | modregxrm(0,reg,4), 1104 1110 modregxrmx(2,sreg,sreg)); 1105 1111 if (shift) 1106 1112 genc2(c,0xC1,grex | modregrmx(3,4,sreg),shift); 1107 1113 gen2sib(c,0x8D,grex | modregxrm(0,reg,4), 1108 1114 modregxrmx(3,sreg,reg)); 1109 1115 if (!(e2factor & 1)) // if even factor 1110 1116 { genregs(c,0x03,reg,reg); // ADD reg,reg 1111 1117 code_orrex(c,rex); 1112 1118 } 1113 1119 cg = cat(cg,c); 1114 1120 goto L3; 1115 1121 } 1116 1122 } 1117 1123 } 1118 1124 1119 1125 cl = scodelem(e->E1,&retregs,0,TRUE); // eval left leaf 1120 1126 reg = findreg(retregs); 1121 1127 cg = allocreg(&resreg,&rreg,e->Ety); 1122 1128 … … 1191 1197 genc2(cg,0xC1,grex | modregrm(3,7,AX),pow2); // SAR AX,pow2 1192 1198 } 1193 1199 else // OPmod 1194 1200 { gen2(cg,0x33,grex | modregrm(3,AX,DX)); // XOR AX,DX 1195 1201 gen2(cg,0x2B,grex | modregrm(3,AX,DX)); // SUB AX,DX 1196 1202 genc2(cg,0x81,grex | modregrm(3,4,AX),m); // AND AX,mask 1197 1203 gen2(cg,0x33,grex | modregrm(3,AX,DX)); // XOR AX,DX 1198 1204 gen2(cg,0x2B,grex | modregrm(3,AX,DX)); // SUB AX,DX 1199 1205 resreg = mAX; 1200 1206 } 1201 1207 } 1202 1208 goto L3; 1203 1209 } 1204 1210 goto L2; 1205 1211 case OPind: 1206 1212 if (!e2->Ecount) /* if not CSE */ 1207 1213 goto L1; /* try OP reg,EA */ 1208 1214 goto L2; 1209 1215 default: /* OPconst and operators */ 1210 1216 L2: 1217 //printf("test2 %p, retregs = %s rretregs = %s resreg = %s\n", e, regm_str(retregs), regm_str(rretregs), regm_str(resreg)); 1211 1218 cl = codelem(e1,&retregs,FALSE); /* eval left leaf */ 1212 1219 cr = scodelem(e2,&rretregs,retregs,TRUE); /* get rvalue */ 1213 1220 if (sz <= REGSIZE) 1214 1221 { cg = getregs(mAX | mDX); /* trash these regs */ 1215 1222 if (op == 7) /* signed divide */ 1216 1223 { cg = gen1(cg,0x99); // CWD 1217 1224 code_orrex(cg,rex); 1218 1225 } 1219 1226 else if (op == 6) /* unsigned divide */ 1220 1227 { 1221 1228 cg = movregconst(cg,DX,0,(sz == 8) ? 64 : 0); // MOV DX,0 1222 1229 cg = cat(cg,getregs(mDX)); 1223 1230 } 1224 1231 rreg = findreg(rretregs); 1225 1232 cg = gen2(cg,0xF7 ^ byte,grex | modregrmx(3,op,rreg)); // OP AX,rreg 1226 1233 L3: 1227 1234 c = fixresult(e,resreg,pretregs); 1228 1235 } 1229 1236 else if (sz == 2 * REGSIZE) 1230 1237 { branches/dmd-1.x/src/backend/cod3.c
r619 r627 3484 3484 unsigned char op; 3485 3485 3486 3486 //printf("jmpaddr()\n"); 3487 3487 cstart = c; /* remember start of code */ 3488 3488 while (c) 3489 3489 { 3490 3490 op = c->Iop; 3491 3491 if (inssize[op & 0xFF] & T && // if second operand 3492 3492 c->IFL2 == FLcode && 3493 3493 ((op & ~0x0F) == 0x70 || op == JMP || op == JMPS || op == JCXZ)) 3494 3494 { ci = code_next(c); 3495 3495 ctarg = c->IEV2.Vcode; /* target code */ 3496 3496 ad = 0; /* IP displacement */ 3497 3497 while (ci && ci != ctarg) 3498 3498 { 3499 3499 ad += calccodsize(ci); 3500 3500 ci = code_next(ci); 3501 3501 } 3502 3502 if (!ci) 3503 3503 goto Lbackjmp; // couldn't find it 3504 if ( I32|| op == JMP || op == JMPS || op == JCXZ)3504 if (!I16 || op == JMP || op == JMPS || op == JCXZ) 3505 3505 c->IEVpointer2 = ad; 3506 3506 else /* else conditional */ 3507 3507 { if (!(c->Iflags & CFjmp16)) /* if branch */ 3508 3508 c->IEVpointer2 = ad; 3509 3509 else /* branch around a long jump */ 3510 3510 { cn = code_next(c); 3511 3511 code_next(c) = code_calloc(); 3512 3512 code_next(code_next(c)) = cn; 3513 3513 c->Iop = op ^ 1; /* converse jmp */ 3514 3514 c->Iflags &= ~CFjmp16; 3515 c->IEVpointer2 = I 32 ? 5 : 3;3515 c->IEVpointer2 = I16 ? 3 : 5; 3516 3516 cn = code_next(c); 3517 3517 cn->Iop = JMP; /* long jump */ 3518 3518 cn->IFL2 = FLconst; 3519 3519 cn->IEVpointer2 = ad; 3520 3520 } 3521 3521 } 3522 3522 c->IFL2 = FLconst; 3523 3523 } 3524 3524 if (op == LOOP && c->IFL2 == FLcode) /* backwards refs */ 3525 3525 { 3526 3526 Lbackjmp: 3527 3527 ctarg = c->IEV2.Vcode; 3528 3528 for (ci = cstart; ci != ctarg; ci = code_next(ci)) 3529 3529 if (!ci || ci == c) 3530 3530 assert(0); 3531 3531 ad = 2; /* - IP displacement */ 3532 3532 while (ci != c) 3533 3533 { assert(ci); 3534 3534 ad += calccodsize(ci); 3535 3535 ci = code_next(ci); 3536 3536 } 3537 3537 c->IEVpointer2 = (-ad) & 0xFF; 3538 3538 c->IFL2 = FLconst; 3539 3539 } 3540 3540 c = code_next(c); 3541 3541 } 3542 3542 } 3543 3543 3544 3544 3545 3545 /******************************* 3546 3546 * Calculate bl->Bsize. 3547 3547 */ 3548 3548 3549 3549 unsigned calcblksize(code *c) 3550 3550 { unsigned size; 3551 3551 3552 3552 for (size = 0; c; c = code_next(c)) 3553 size += calccodsize(c); 3553 { 3554 unsigned sz = calccodsize(c); 3555 //printf("off=%02x, sz = %d, code %p: op=%02x\n", size, sz, c, c->Iop); 3556 size += sz; 3557 } 3554 3558 //printf("calcblksize(c = x%x) = %d\n", c, size); 3555 3559 return size; 3556 3560 } 3557 3561 3558 3562 /***************************** 3559 3563 * Calculate and return code size of a code. 3560 3564 * Note that NOPs are sometimes used as markers, but are 3561 3565 * never output. LINNUMs are never output. 3562 3566 * Note: This routine must be fast. Profiling shows it is significant. 3563 3567 */ 3564 3568 3565 3569 unsigned calccodsize(code *c) 3566 3570 { unsigned size; 3567 3571 unsigned op; 3568 3572 unsigned char rm,mod,ins; 3569 3573 unsigned iflags; 3570 3574 unsigned i32 = I32 || I64; 3571 3575 unsigned a32 = i32; 3572 3576 3573 3577 #ifdef DEBUG … … 5033 5037 else 5034 5038 ins = inssize[op & 0xFF]; 5035 5039 5036 5040 printf("code %p: nxt=%p ",c,code_next(c)); 5037 5041 if (c->Irex) 5038 5042 printf("rex=%x ", c->Irex); 5039 5043 printf("op=%02x",op); 5040 5044 5041 5045 if ((op & 0xFF) == ESCAPE) 5042 5046 { if ((op & 0xFF00) == ESClinnum) 5043 5047 { printf(" linnum = %d\n",c->IEV2.Vsrcpos.Slinnum); 5044 5048 return; 5045 5049 } 5046 5050 printf(" ESCAPE %d",c->Iop >> 8); 5047 5051 } 5048 5052 if (c->Iflags) 5049 5053 printf(" flg=%x",c->Iflags); 5050 5054 if (ins & M) 5051 5055 { unsigned rm = c->Irm; 5052 5056 printf(" rm=%02x=%d,%d,%d",rm,(rm>>6)&3,(rm>>3)&7,rm&7); 5053 if ( I32&& issib(rm))5057 if (!I16 && issib(rm)) 5054 5058 { unsigned char sib = c->Isib; 5055 5059 printf(" sib=%02x=%d,%d,%d",sib,(sib>>6)&3,(sib>>3)&7,sib&7); 5056 5060 } 5057 5061 if ((rm & 0xC7) == BPRM || (rm & 0xC0) == 0x80 || (rm & 0xC0) == 0x40) 5058 5062 { 5059 5063 switch (c->IFL1) 5060 5064 { 5061 5065 case FLconst: 5062 5066 case FLoffset: 5063 5067 printf(" int = %4d",c->IEV1.Vuns); 5064 5068 break; 5065 5069 case FLblock: 5066 5070 printf(" block = %p",c->IEV1.Vblock); 5067 5071 break; 5068 5072 case FLswitch: 5069 5073 case FLblockoff: 5070 5074 case FLlocalsize: 5071 5075 case FLframehandler: 5072 5076 case 0: 5073 5077 break; branches/dmd-1.x/src/backend/cod4.c
r618 r627 2862 2862 code *c; 2863 2863 2864 2864 //printf("cdmsw(e->Ecount = %d)\n", e->Ecount); 2865 2865 assert(e->Eoper == OPmsw); 2866 2866 2867 2867 retregs = *pretregs ? ALLREGS : 0; 2868 2868 c = codelem(e->E1,&retregs,FALSE); 2869 2869 retregs &= mMSW; // want MSW only 2870 2870 2871 2871 // We "destroy" a reg by assigning it the result of a new e, even 2872 2872 // though the values are the same. Weakness of our CSE strategy that 2873 2873 // a register can only hold the contents of one elem at a time. 2874 2874 if (e->Ecount) 2875 2875 c = cat(c,getregs(retregs)); 2876 2876 else 2877 2877 useregs(retregs); 2878 2878 2879 2879 #ifdef DEBUG 2880 2880 if (!(!*pretregs || retregs)) 2881 2881 { WROP(e->Eoper); 2882 printf(" *pretregs = x%x, retregs = x%x\n",*pretregs,retregs); 2882 printf(" *pretregs = %s, retregs = %s\n",regm_str(*pretregs),regm_str(retregs)); 2883 elem_print(e); 2883 2884 } 2884 2885 #endif 2885 2886 assert(!*pretregs || retregs); 2886 2887 return cat(c,fixresult(e,retregs,pretregs)); // msw only 2887 2888 } 2888 2889 2889 2890 2890 2891 2891 2892 /****************************** 2892 2893 * Handle operators OPinp and OPoutp. 2893 2894 */ 2894 2895 2895 2896 code *cdport(elem *e,regm_t *pretregs) 2896 2897 { regm_t retregs; 2897 2898 code *c1,*c2,*c3; 2898 2899 unsigned char op,port; 2899 2900 unsigned sz; 2900 2901 elem *e1; 2901 2902 2902 2903 //printf("cdport\n"); branches/dmd-1.x/src/backend/debug.c
r618 r627 193 193 { nest++; 194 194 ferr("("); 195 195 WReqn(e->E2); 196 196 ferr(")"); 197 197 nest--; 198 198 } 199 199 else 200 200 WReqn(e->E2); 201 201 } 202 202 else 203 203 { 204 204 switch (e->Eoper) 205 205 { case OPconst: 206 206 switch (tybasic(e->Ety)) 207 207 { 208 208 case TYfloat: 209 209 dbg_printf("%g <float> ",e->EV.Vfloat); 210 210 break; 211 211 case TYdouble: 212 212 dbg_printf("%g ",e->EV.Vdouble); 213 break; 214 case TYcent: 215 case TYucent: 216 dbg_printf("%lld+%lld ", e->EV.Vcent.msw, e->EV.Vcent.lsw); 213 217 break; 214 218 default: 215 219 dbg_printf("%lld ",el_tolong(e)); 216 220 break; 217 221 } 218 222 break; 219 223 case OPrelconst: 220 224 ferr("#"); 221 225 /* FALL-THROUGH */ 222 226 case OPvar: 223 227 dbg_printf("%s",e->EV.sp.Vsym->Sident); 224 228 if (e->EV.sp.Vsym->Ssymnum != -1) 225 229 dbg_printf("(%d)",e->EV.sp.Vsym->Ssymnum); 226 230 if (e->Eoffset != 0) 227 231 dbg_printf(".%ld",(long)e->Eoffset); 228 232 break; 229 233 case OPasm: 230 234 #if TARGET_MAC 231 235 if (e->Eflags & EFsmasm) 232 236 { branches/dmd-1.x/src/backend/el.c
r618 r627 2547 2547 if (n1->EV.Vshort != n2->EV.Vshort) 2548 2548 goto nomatch; 2549 2549 break; 2550 2550 case TYlong: 2551 2551 case TYulong: 2552 2552 case TYdchar: 2553 2553 #if TARGET_MAC 2554 2554 case TYfptr: 2555 2555 case TYvptr: 2556 2556 #endif 2557 2557 case_long: 2558 2558 if (n1->EV.Vlong != n2->EV.Vlong) 2559 2559 goto nomatch; 2560 2560 break; 2561 2561 case TYllong: 2562 2562 case TYullong: 2563 2563 case_llong: 2564 2564 if (n1->EV.Vllong != n2->EV.Vllong) 2565 2565 goto nomatch; 2566 2566 break; 2567 case TYcent: 2568 case TYucent: 2569 if (n1->EV.Vcent.lsw != n2->EV.Vcent.lsw || 2570 n1->EV.Vcent.msw != n2->EV.Vcent.msw) 2571 goto nomatch; 2572 break; 2567 2573 case TYenum: 2568 2574 if (PARSER) 2569 2575 { tym = n1->ET->Tnext->Tty; 2570 2576 goto Lagain; 2571 2577 } 2572 2578 case TYint: 2573 2579 case TYuint: 2574 2580 if (intsize == SHORTSIZE) 2575 2581 goto case_short; 2576 2582 else 2577 2583 goto case_long; 2578 2584 2579 2585 #if TX86 2580 2586 #if JHANDLE 2581 2587 case TYjhandle: 2582 2588 #endif 2583 2589 case TYnullptr: 2584 2590 case TYnptr: 2585 2591 case TYsptr: 2586 2592 case TYcptr: branches/dmd-1.x/src/backend/evalu8.c
r618 r627 175 175 b = 1; 176 176 else 177 177 b = e->EV.Vcdouble.re != 0 || e->EV.Vcdouble.im != 0; 178 178 break; 179 179 case TYcldouble: 180 180 if (isnan(e->EV.Vcldouble.re) || isnan(e->EV.Vcldouble.im)) 181 181 b = 1; 182 182 else 183 183 b = e->EV.Vcldouble.re != 0 || e->EV.Vcldouble.im != 0; 184 184 break; 185 185 case TYstruct: // happens on syntax error of (struct x)0 186 186 #if SCPP 187 187 assert(errcnt); 188 188 #else 189 189 assert(0); 190 190 #endif 191 191 case TYvoid: /* happens if we get syntax errors or 192 192 on RHS of && || expressions */ 193 193 b = 0; 194 194 break; 195 196 case TYcent: 197 case TYucent: 198 b = e->EV.Vcent.lsw || e->EV.Vcent.msw; 199 break; 200 195 201 default: 196 202 #ifdef DEBUG 197 203 WRTYxx(typemask(e)); 198 204 #endif 199 205 assert(0); 200 206 } 201 207 break; 202 208 default: 203 209 assert(0); 204 210 } 205 211 return b; 206 212 } 207 213 208 214 /*************************** 209 215 * Return TRUE if expression will always evaluate to TRUE. 210 216 */ 211 217 212 218 HINT iftrue(elem *e) 213 219 { 214 220 while (1) branches/dmd-1.x/src/todt.c
r602 r627 269 269 else if (dim > tadim) 270 270 { 271 271 #ifdef DEBUG 272 272 printf("1: "); 273 273 #endif 274 274 error(loc, "too many initializers, %d, for array[%d]", dim, tadim); 275 275 } 276 276 break; 277 277 } 278 278 279 279 case Tpointer: 280 280 case Tarray: 281 281 // Create symbol, and then refer to it 282 282 Symbol *s; 283 283 s = static_sym(); 284 284 s->Sdt = d; 285 285 outdata(s); 286 286 287 287 d = NULL; 288 288 if (tb->ty == Tarray) 289 dt dword(&d, dim);289 dtsize_t(&d, dim); 290 290 dtxoff(&d, s, 0, TYnptr); 291 291 break; 292 292 293 293 default: 294 294 assert(0); 295 295 } 296 296 return d; 297 297 } 298 298 299 299 300 300 dt_t *ArrayInitializer::toDtBit() 301 301 { 302 302 #if DMDV1 303 303 unsigned size; 304 304 unsigned length; 305 305 unsigned i; 306 306 unsigned tadim; 307 307 dt_t *d; 308 308 dt_t **pdtend; 309 309 Type *tb = type->toBasetype(); … … 384 384 } 385 385 else 386 386 { 387 387 tadim = (tadim + 31) / 32; 388 388 if (databits.allocdim < tadim) 389 389 pdtend = dtnzeros(pdtend, size * (tadim - databits.allocdim)); // pad out end of array 390 390 } 391 391 break; 392 392 } 393 393 394 394 case Tpointer: 395 395 case Tarray: 396 396 // Create symbol, and then refer to it 397 397 Symbol *s; 398 398 s = static_sym(); 399 399 s->Sdt = d; 400 400 outdata(s); 401 401 402 402 d = NULL; 403 403 if (tb->ty == Tarray) 404 dt dword(&d, dim);404 dtsize_t(&d, dim); 405 405 dtxoff(&d, s, 0, TYnptr); 406 406 break; 407 407 408 408 default: 409 409 assert(0); 410 410 } 411 411 return d; 412 412 #else 413 413 return NULL; 414 414 #endif 415 415 } 416 416 417 417 418 418 dt_t *ExpInitializer::toDt() 419 419 { 420 420 dt_t *dt = NULL; 421 421 422 422 exp = exp->optimize(WANTvalue); 423 423 exp->toDt(&dt); 424 424 return dt; … … 526 526 break; 527 527 } 528 528 return pdt; 529 529 } 530 530 531 531 dt_t **NullExp::toDt(dt_t **pdt) 532 532 { 533 533 assert(type); 534 534 return dtnzeros(pdt, type->size()); 535 535 } 536 536 537 537 dt_t **StringExp::toDt(dt_t **pdt) 538 538 { 539 539 //printf("StringExp::toDt() '%s', type = %s\n", toChars(), type->toChars()); 540 540 Type *t = type->toBasetype(); 541 541 542 542 // BUG: should implement some form of static string pooling 543 543 switch (t->ty) 544 544 { 545 545 case Tarray: 546 dt dword(pdt, len);546 dtsize_t(pdt, len); 547 547 pdt = dtabytes(pdt, TYnptr, 0, (len + 1) * sz, (char *)string); 548 548 break; 549 549 550 550 case Tsarray: 551 551 { TypeSArray *tsa = (TypeSArray *)type; 552 552 dinteger_t dim; 553 553 554 554 pdt = dtnbytes(pdt, len * sz, (const char *)string); 555 555 if (tsa->dim) 556 556 { 557 557 dim = tsa->dim->toInteger(); 558 558 if (len < dim) 559 559 { 560 560 // Pad remainder with 0 561 561 pdt = dtnzeros(pdt, (dim - len) * tsa->next->size()); 562 562 } 563 563 } 564 564 break; 565 565 } 566 566 case Tpointer: … … 582 582 dt_t **pdtend; 583 583 584 584 d = NULL; 585 585 pdtend = &d; 586 586 for (int i = 0; i < elements->dim; i++) 587 587 { Expression *e = (Expression *)elements->data[i]; 588 588 589 589 pdtend = e->toDt(pdtend); 590 590 } 591 591 Type *t = type->toBasetype(); 592 592 593 593 switch (t->ty) 594 594 { 595 595 case Tsarray: 596 596 pdt = dtcat(pdt, d); 597 597 break; 598 598 599 599 case Tpointer: 600 600 case Tarray: 601 601 if (t->ty == Tarray) 602 dt dword(pdt, elements->dim);602 dtsize_t(pdt, elements->dim); 603 603 if (d) 604 604 { 605 605 // Create symbol, and then refer to it 606 606 Symbol *s; 607 607 s = static_sym(); 608 608 s->Sdt = d; 609 609 outdata(s); 610 610 611 611 dtxoff(pdt, s, 0, TYnptr); 612 612 } 613 613 else 614 dt dword(pdt, 0);614 dtsize_t(pdt, 0); 615 615 616 616 break; 617 617 618 618 default: 619 619 assert(0); 620 620 } 621 621 return pdt; 622 622 } 623 623 624 624 dt_t **StructLiteralExp::toDt(dt_t **pdt) 625 625 { 626 626 Array dts; 627 627 unsigned i; 628 628 unsigned j; 629 629 dt_t *dt; 630 630 dt_t *d; 631 631 unsigned offset; 632 632 633 633 //printf("StructLiteralExp::toDt() %s)\n", toChars()); 634 634 dts.setDim(sd->fields.dim); … … 772 772 return pdt; 773 773 } 774 774 #ifdef DEBUG 775 775 printf("VarExp::toDt(), kind = %s\n", var->kind()); 776 776 #endif 777 777 error("non-constant expression %s", toChars()); 778 778 pdt = dtnzeros(pdt, 1); 779 779 return pdt; 780 780 } 781 781 782 782 /* ================================================================= */ 783 783 784 784 // Generate the data for the static initializer. 785 785 786 786 void ClassDeclaration::toDt(dt_t **pdt) 787 787 { 788 788 //printf("ClassDeclaration::toDt(this = '%s')\n", toChars()); 789 789 790 790 // Put in first two members, the vtbl[] and the monitor 791 791 dtxoff(pdt, toVtblSymbol(), 0, TYnptr); 792 dt dword(pdt, 0); // monitor792 dtsize_t(pdt, 0); // monitor 793 793 794 794 // Put in the rest 795 795 toDt2(pdt, this); 796 796 797 797 //printf("-ClassDeclaration::toDt(this = '%s')\n", toChars()); 798 798 } 799 799 800 800 void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) 801 801 { 802 802 unsigned offset; 803 803 unsigned i; 804 804 dt_t *dt; 805 805 unsigned csymoffset; 806 806 807 807 #define LOG 0 808 808 809 809 #if LOG 810 810 printf("ClassDeclaration::toDt2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); 811 811 #endif 812 812 if (baseClass) trunk/src/backend/cg87.c
r622 r627 193 193 #endif 194 194 { 195 195 int i; 196 196 197 197 #if NDPP 198 198 dbg_printf("pop87(%s(%d): stackused=%d)\n", file, line, stackused); 199 199 #endif 200 200 --stackused; 201 201 assert(stackused >= 0); 202 202 for (i = 0; i < arraysize(_8087elems) - 1; i++) 203 203 _8087elems[i] = _8087elems[i + 1]; 204 204 /* end of stack is nothing */ 205 205 _8087elems[arraysize(_8087elems) - 1] = ndp_zero; 206 206 } 207 207 208 208 /******************************* 209 209 * Push 8087 stack. Generate and return any code 210 210 * necessary to preserve anything that might run off the end of the stack. 211 211 */ 212 212 213 code *push87() 213 #undef push87 214 215 #ifdef DEBUG 216 code *push87(int line, const char *file); 217 code *push87() { return push87(__LINE__,__FILE__); } 218 #endif 219 220 code *push87( 221 #ifdef DEBUG 222 int line, const char *file 223 #endif 224 ) 225 #ifdef DEBUG 226 #define push87() push87(__LINE__,__FILE__) 227 #endif 214 228 { 215 229 code *c; 216 230 int i; 217 231 218 232 c = CNIL; 219 233 // if we would lose the top register off of the stack 220 234 if (_8087elems[7].e != NULL) 221 235 { 222 236 i = getemptyslot(); 223 237 NDP::save[i] = _8087elems[7]; 224 238 c = genf2(c,0xD9,0xF6); // FDECSTP 225 239 c = genfwait(c); 226 240 c = ndp_fstp(c, i, _8087elems[7].e->Ety); // FSTP i[BP] 227 241 assert(stackused == 8); 228 242 if (NDPP) dbg_printf("push87() : overflow\n"); 229 243 } 230 244 else 231 245 { 232 if (NDPP) dbg_printf("push87(%d)\n",stackused); 246 #ifdef DEBUG 247 if (NDPP) dbg_printf("push87(%s(%d): %d)\n", file, line, stackused); 248 #endif 233 249 stackused++; 234 250 assert(stackused <= 8); 235 251 } 236 252 // Shift the stack up 237 253 for (i = 7; i > 0; i--) 238 254 _8087elems[i] = _8087elems[i - 1]; 239 255 _8087elems[0] = ndp_zero; 240 256 return c; 241 257 } 242 258 243 259 /***************************** 244 260 * Note elem e as being in ST(i) as being a value we want to keep. 245 261 */ 246 262 247 263 #ifdef DEBUG 248 264 void note87(elem *e, unsigned offset, int i, int linnum); 249 265 void note87(elem *e, unsigned offset, int i) 250 266 { 251 267 return note87(e, offset, i, 0); 252 268 } … … 472 488 c = cat(c,fixresult(e,mST0,pretregs)); 473 489 } 474 490 else 475 491 // Reload 476 492 c = loaddata(e,pretregs); 477 493 } 478 494 479 495 freenode(e); 480 496 return c; 481 497 } 482 498 483 499 484 500 /************************** 485 501 * Generate code to deal with floatreg. 486 502 */ 487 503 488 504 code * genfltreg(code *c,unsigned opcode,unsigned reg,targ_size_t offset) 489 505 { 490 506 floatreg = TRUE; 491 507 reflocal = TRUE; 492 if ((opcode & 0xF8) == 0xD8)508 if ((opcode & ~7) == 0xD8) 493 509 c = genfwait(c); 494 unsigned grex = I64 ? (REX_W << 16) : 0; 495 return genc1(c,opcode,grex | modregxrm(2,reg,BPRM),FLfltreg,offset); 510 return genc1(c,opcode,modregxrm(2,reg,BPRM),FLfltreg,offset); 496 511 } 497 512 498 513 /******************************* 499 514 * Decide if we need to gen an FWAIT. 500 515 */ 501 516 502 517 code *genfwait(code *c) 503 518 { 504 519 if (ADDFWAIT()) 505 520 c = gen1(c,FWAIT); 506 521 return c; 507 522 } 508 523 509 524 /*************************************** 510 525 * Generate floating point instruction. 511 526 */ 512 527 513 528 STATIC code * genf2(code *c,unsigned op,unsigned rm) 514 529 { 515 530 return gen2(genfwait(c),op,rm); … … 824 839 else 825 840 { c2 = genfltreg(c2,0x8B,AX,6); 826 841 genfltreg(c2,0x8B,BX,4); 827 842 genfltreg(c2,0x8B,CX,2); 828 843 genfltreg(c2,0x8B,DX,0); 829 844 } 830 845 } 831 846 } 832 847 else if (*pretregs == 0 && retregs == mST0) 833 848 { 834 849 c1 = genf2(c1,0xDD,modregrm(3,3,0)); // FPOP 835 850 pop87(); 836 851 } 837 852 else 838 853 { if (*pretregs & mPSW) 839 854 { if (!(retregs & mPSW)) 840 855 { assert(retregs & mST0); 841 856 c1 = genftst(c1,e,!(*pretregs & mST0)); // FTST 842 857 } 843 858 } 844 assert(!(*pretregs & mST0) || (retregs & mST0)); 859 if (*pretregs & mST0 && retregs & XMMREGS) 860 { 861 assert(sz <= DOUBLESIZE); 862 unsigned mf = (sz == FLOATSIZE) ? MFfloat : MFdouble; 863 // MOVD floatreg,XMM? 864 unsigned reg = findreg(retregs); 865 c1 = genfltreg(c1,0xF20F11,reg - XMM0,0); 866 c2 = push87(); 867 c2 = genfltreg(c2,ESC(mf,1),0,0); // FLD float/double ptr fltreg 868 } 869 else if (retregs & mST0 && *pretregs & XMMREGS) 870 { 871 assert(sz <= DOUBLESIZE); 872 unsigned mf = (sz == FLOATSIZE) ? MFfloat : MFdouble; 873 // FSTP floatreg 874 pop87(); 875 c1 = genfltreg(c1,ESC(mf,1),3,0); 876 genfwait(c1); 877 // MOVD XMM?,floatreg 878 unsigned reg; 879 c2 = allocreg(pretregs,®,(sz == FLOATSIZE) ? TYfloat : TYdouble); 880 c2 = genfltreg(c2,0xF20F10,reg -XMM0,0); 881 } 882 else 883 assert(!(*pretregs & mST0) || (retregs & mST0)); 845 884 } 846 885 if (*pretregs & mST0) 847 886 note87(e,0,0); 848 887 return cat(c1,c2); 849 888 } 850 889 851 890 /******************************** 852 891 * Generate in-line 8087 code for the following operators: 853 892 * add 854 893 * min 855 894 * mul 856 895 * div 857 896 * cmp 858 897 */ 859 898 860 899 // Reverse the order that the op is done in 861 900 static const char oprev[9] = { -1,0,1,2,3,5,4,7,6 }; 862 901 863 902 code *orth87(elem *e,regm_t *pretregs) 864 903 { … … 1699 1738 c = regwithvalue(c,ALLREGS & mMSW,0,®,0); // 0-extend 1700 1739 retregs |= mask[reg]; 1701 1740 mf1 = MFlong; 1702 1741 goto L3; 1703 1742 } 1704 1743 case OPs16_d: mf1 = MFword; goto L6; 1705 1744 case OPs32_d: mf1 = MFlong; goto L6; 1706 1745 L6: 1707 1746 if (op != -1) 1708 1747 note87(eleft,eoffset,0); // don't trash this value 1709 1748 if (e->E1->Eoper == OPvar || 1710 1749 (e->E1->Eoper == OPind && e->E1->Ecount == 0)) 1711 1750 { 1712 1751 goto L4; 1713 1752 } 1714 1753 else 1715 1754 { 1716 1755 retregs = ALLREGS; 1717 1756 c = codelem(e->E1,&retregs,FALSE); 1718 1757 L3: 1719 if ( !I32&& e->Eoper != OPs16_d)1758 if (I16 && e->Eoper != OPs16_d) 1720 1759 { 1721 1760 /* MOV floatreg+2,reg */ 1722 1761 reg = findregmsw(retregs); 1723 1762 c = genfltreg(c,0x89,reg,REGSIZE); 1724 1763 retregs &= mLSW; 1725 1764 } 1726 1765 reg = findreg(retregs); 1727 1766 c = genfltreg(c,0x89,reg,0); /* MOV floatreg,reg */ 1728 1767 if (op != -1) 1729 1768 { c = cat(c,makesure87(eleft,eoffset,0,0)); 1730 1769 genfltreg(c,ESC(mf1,0),op,0); /* Fop floatreg */ 1731 1770 } 1732 1771 else 1733 1772 { 1734 1773 /* FLD long ptr floatreg */ 1735 1774 c = cat(c,push87()); 1736 1775 c = genfltreg(c,ESC(mf1,1),0,0); 1737 1776 } 1738 1777 } 1739 1778 break; … … 3304 3343 c2 = genfltreg(c2, 0x8B, DX, 0); // MOV EDX,floatreg 3305 3344 3306 3345 pop87(); 3307 3346 c2 = genfltreg(c2, ESC(MFfloat,1),3,0); // FSTP floatreg 3308 3347 genfwait(c2); 3309 3348 c2 = genfltreg(c2, 0x8B, AX, 0); // MOV EAX,floatreg 3310 3349 } 3311 3350 else if (tym == TYcfloat && retregs & (mAX|mDX) && *pretregs & mST01) 3312 3351 { 3313 3352 c1 = push87(); 3314 3353 c1 = genfltreg(c1, 0x89, AX, 0); // MOV floatreg, EAX 3315 3354 genfltreg(c1, 0xD9, 0, 0); // FLD float ptr floatreg 3316 3355 3317 3356 c2 = push87(); 3318 3357 c2 = genfltreg(c2, 0x89, DX, 0); // MOV floatreg, EDX 3319 3358 genfltreg(c2, 0xD9, 0, 0); // FLD float ptr floatreg 3320 3359 3321 3360 if (*pretregs & mPSW) 3322 3361 c2 = genctst(c2,e,0); // FTST 3323 3362 } 3363 else if ((tym == TYcfloat || tym == TYcdouble) && 3364 *pretregs & (mXMM0|mXMM1) && retregs & mST01) 3365 { 3366 if (*pretregs & mPSW && !(retregs & mPSW)) 3367 c1 = genctst(c1,e,0); // FTST 3368 pop87(); 3369 c1 = genfltreg(c1, ESC(MFdouble,1),3,0); // FSTP floatreg 3370 genfwait(c1); 3371 c2 = getregs(mXMM0|mXMM1); 3372 c2 = genfltreg(c2, 0xF20F10, XMM1 - XMM0, 0); // MOVD XMM1,floatreg 3373 3374 pop87(); 3375 c2 = genfltreg(c2, ESC(MFdouble,1),3,0); // FSTP floatreg 3376 genfwait(c2); 3377 c2 = genfltreg(c2, 0xF20F10, XMM0 - XMM0, 0); // MOVD XMM0,floatreg 3378 } 3379 else if ((tym == TYcfloat || tym == TYcdouble) && 3380 retregs & (mXMM0|mXMM1) && *pretregs & mST01) 3381 { 3382 c1 = push87(); 3383 c1 = genfltreg(c1, 0xF20F11, XMM0-XMM0, 0); // MOVD floatreg, XMM0 3384 genfltreg(c1, 0xDD, 0, 0); // FLD double ptr floatreg 3385 3386 c2 = push87(); 3387 c2 = genfltreg(c2, 0xF20F11, XMM1-XMM0, 0); // MOV floatreg, XMM1 3388 genfltreg(c2, 0xDD, 0, 0); // FLD double ptr floatreg 3389 3390 if (*pretregs & mPSW) 3391 c2 = genctst(c2,e,0); // FTST 3392 } 3324 3393 else 3325 3394 { if (*pretregs & mPSW) 3326 3395 { if (!(retregs & mPSW)) 3327 3396 { assert(retregs & mST01); 3328 3397 c1 = genctst(c1,e,!(*pretregs & mST01)); // FTST 3329 3398 } 3330 3399 } 3331 3400 assert(!(*pretregs & mST01) || (retregs & mST01)); 3332 3401 } 3333 3402 if (*pretregs & mST01) 3334 3403 { note87(e,0,1); 3335 3404 note87(e,sz/2,0); 3336 3405 } 3337 3406 return cat(c1,c2); 3338 3407 } 3339 3408 3340 3409 /***************************************** 3341 3410 * Operators OPc_r and OPc_i 3342 3411 */ 3343 3412 … … 3381 3450 assert(*pretregs & (mST01 | mPSW)); 3382 3451 assert(!(*pretregs & ~(mST01 | mPSW))); 3383 3452 } 3384 3453 __out (result) 3385 3454 { 3386 3455 } 3387 3456 __body 3388 3457 #endif 3389 3458 { 3390 3459 tym_t ty = tybasic(e->Ety); 3391 3460 code *c = NULL; 3392 3461 code *cpush = NULL; 3393 3462 code cs; 3394 3463 unsigned mf; 3395 3464 unsigned sz; 3396 3465 unsigned char ldop; 3397 3466 regm_t retregs; 3398 3467 symbol *s; 3399 3468 int i; 3400 3469 3470 //printf("cload87(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 3401 3471 sz = tysize[ty] / 2; 3402 3472 memset(&cs, 0, sizeof(cs)); 3403 3473 if (ADDFWAIT()) 3404 3474 cs.Iflags = CFwait; 3405 3475 switch (ty) 3406 3476 { 3407 3477 case TYcfloat: mf = MFfloat; break; 3408 3478 case TYcdouble: mf = MFdouble; break; 3409 3479 case TYcldouble: break; 3410 3480 default: assert(0); 3411 3481 } 3412 3482 switch (e->Eoper) 3413 3483 { 3414 3484 case OPvar: 3415 3485 notreg(e); // never enregister this variable 3416 3486 case OPind: 3417 3487 cpush = cat(push87(), push87()); 3418 3488 switch (ty) 3419 3489 { 3420 3490 case TYcfloat: trunk/src/backend/cgcod.c
r619 r627 377 377 i = branch(b,0); // see if jmp => jmp short 378 378 if (i) /* if any bytes saved */ 379 379 { targ_size_t offset; 380 380 381 381 b->Bsize -= i; 382 382 offset = b->Boffset + b->Bsize; 383 383 for (bn = b->Bnext; bn; bn = bn->Bnext) 384 384 { 385 385 if (bn->Balign) 386 386 { targ_size_t u = bn->Balign - 1; 387 387 388 388 offset = (offset + u) & ~u; 389 389 } 390 390 bn->Boffset = offset; 391 391 offset += bn->Bsize; 392 392 } 393 393 coffset = offset; 394 394 flag = TRUE; 395 395 } 396 396 } 397 if ( I32&& !(config.flags4 & CFG4optimized))397 if (!I16 && !(config.flags4 & CFG4optimized)) 398 398 break; // use the long conditional jmps 399 399 } while (flag); // loop till no more bytes saved 400 400 #ifdef DEBUG 401 401 debugw && printf("code jump optimization complete\n"); 402 402 #endif 403 403 404 404 // Compute starting offset for switch tables 405 405 #if ELFOBJ || MACHOBJ 406 406 swoffset = (config.flags & CFGromable) ? coffset : CDoffset; 407 407 #else 408 408 swoffset = (config.flags & CFGromable) ? coffset : Doffset; 409 409 #endif 410 410 swoffset = align(0,swoffset); 411 411 412 412 // Emit the generated code 413 413 if (eecontext.EEcompile == 1) 414 414 { 415 415 codout(eecontext.EEcode); 416 416 code_free(eecontext.EEcode); 417 417 #if SCPP trunk/src/backend/cgelem.c
r618 r627 2066 2066 return optelem(e,TRUE); 2067 2067 } 2068 2068 #else 2069 2069 { 2070 2070 e->Eoper = OPeq; 2071 2071 el_free(e->E2); 2072 2072 e->E2 = el_copytree(e1); 2073 2073 e->E2 = el_una(OPneg,tym,e->E2); 2074 2074 return optelem(e,TRUE); 2075 2075 } 2076 2076 #endif 2077 2077 #endif 2078 2078 } 2079 2079 2080 2080 if (OPTIMIZER) 2081 2081 { 2082 2082 if (tyintegral(tym) && (e->Eoper == OPdiv || e->Eoper == OPmod)) 2083 2083 { int sz = tysize(tym); 2084 2084 2085 2085 // See if we can replace with OPremquo 2086 if (sz == intsize)2086 if (sz == REGSIZE && !I64) // need cent and ucent working for I64 to work 2087 2087 { 2088 2088 // Don't do it if there are special code sequences in the 2089 2089 // code generator (see cdmul()) 2090 2090 int pow2; 2091 2091 if (e->E2->Eoper == OPconst && 2092 2092 sz == REGSIZE && !uns && 2093 2093 (pow2 = ispow2(el_tolong(e->E2))) != -1 && 2094 2094 !(config.target_cpu < TARGET_80286 && pow2 != 1 && e->Eoper == OPdiv) 2095 2095 ) 2096 2096 ; 2097 2097 else 2098 2098 { 2099 2099 assert(sz == 2 || sz == 4); 2100 2100 int op = OPmsw; 2101 2101 if (e->Eoper == OPdiv) 2102 2102 { 2103 2103 op = (sz == 2) ? OP32_16 : OP64_32; 2104 2104 } 2105 2105 e->Eoper = OPremquo; 2106 2106 e = el_una(op, tym, e); trunk/src/backend/cgen.c
r605 r627 144 144 * Add code to end of linked list. 145 145 * Note that unused operands are garbage. 146 146 * gen1() and gen2() are shortcut routines. 147 147 * Input: 148 148 * c -> linked list that code is to be added to end of 149 149 * cs -> data for the code 150 150 * Returns: 151 151 * pointer to start of code list 152 152 */ 153 153 154 154 code *gen(code *c,code *cs) 155 155 { code *ce,*cstart; 156 156 unsigned reg; 157 157 158 158 #ifdef DEBUG /* this is a high usage routine */ 159 159 assert(cs); 160 160 #endif 161 161 assert(I64 || cs->Irex == 0); 162 162 ce = code_calloc(); 163 163 *ce = *cs; 164 //printf("ce = %p %02x\n", ce, ce->Iop); 165 if (ce->Iop == LEA && ce->Irm == 4 && ce->Isib == 0x6D && ce->IFL1 == FLunde) *(char*)0=0; 164 166 if (config.flags4 & CFG4optimized && 165 167 ce->IFL2 == FLconst && 166 168 (ce->Iop == 0x81 || ce->Iop == 0x80) && 167 169 reghasvalue((ce->Iop == 0x80) ? BYTEREGS : ALLREGS,ce->IEV2.Vlong,®) && 168 170 !(ce->Iflags & CFopsize && I16) 169 171 ) 170 172 { // See if we can replace immediate instruction with register instruction 171 173 static unsigned char regop[8] = 172 174 { 0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38 }; 173 175 174 176 //printf("replacing 0x%02x, val = x%lx\n",ce->Iop,ce->IEV2.Vlong); 175 177 ce->Iop = regop[(ce->Irm & modregrm(0,7,0)) >> 3] | (ce->Iop & 1); 176 178 code_newreg(ce, reg); 177 179 } 178 180 code_next(ce) = CNIL; 179 181 if (c) 180 182 { cstart = c; 181 183 while (code_next(c)) c = code_next(c); /* find end of list */ 182 184 code_next(c) = ce; /* link into list */ 183 185 return cstart; 184 186 } 185 187 return ce; 186 188 } 187 189 188 190 code *gen1(code *c,unsigned op) 189 191 { code *ce,*cstart; 190 192 191 193 ce = code_calloc(); 192 194 ce->Iop = op; 195 assert(op != LEA); 193 196 if (c) 194 197 { cstart = c; 195 198 while (code_next(c)) c = code_next(c); /* find end of list */ 196 199 code_next(c) = ce; /* link into list */ 197 200 return cstart; 198 201 } 199 202 return ce; 200 203 } 201 204 202 205 code *gen2(code *c,unsigned op,unsigned rm) 203 206 { code *ce,*cstart; 204 207 205 208 cstart = ce = code_calloc(); 206 209 /*cxcalloc++;*/ 207 210 ce->Iop = op; 208 211 ce->Iea = rm; 209 212 if (c) 210 213 { cstart = c; 211 214 while (code_next(c)) c = code_next(c); /* find end of list */ 212 215 code_next(c) = ce; /* link into list */ 213 216 } 214 217 return cstart; 215 218 } 216 219 217 220 code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib) 218 221 { code *ce,*cstart; 219 222 220 223 cstart = ce = code_calloc(); 221 224 /*cxcalloc++;*/ 225 if (op == LEA && (rm & 0xFF) == 4 && (sib & 0xFF) == 0x6D) *(char*)0=0; 222 226 ce->Iop = op; 223 227 ce->Irm = rm; 224 228 ce->Isib = sib; 225 229 ce->Irex = (rm | (sib & (REX_B << 16))) >> 16; 226 230 if (sib & (REX_R << 16)) 227 231 ce->Irex |= REX_X; 228 232 if (c) 229 233 { cstart = c; 230 234 while (code_next(c)) c = code_next(c); /* find end of list */ 231 235 code_next(c) = ce; /* link into list */ 232 236 } 233 237 return cstart; 234 238 } 235 239 236 240 code *genregs(code *c,unsigned op,unsigned dstreg,unsigned srcreg) 237 241 { return gen2(c,op,modregxrmx(3,dstreg,srcreg)); } 238 242 239 243 code *gentstreg(code *c,unsigned t) 240 244 { 241 245 c = gen2(c,0x85,modregxrmx(3,t,t)); // TEST t,t … … 370 374 cs.Iea = ea; 371 375 cs.Iflags = CFoff; 372 376 cs.IFL2 = FLconst; 373 377 cs.IEV2.Vsize_t = EV2; 374 378 return gen(c,&cs); 375 379 } 376 380 377 381 /***************** 378 382 * Generate code. 379 383 */ 380 384 381 385 code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 382 386 { code cs; 383 387 384 388 assert(FL1 < FLMAX); 385 389 cs.Iop = op; 386 390 cs.Iflags = CFoff; 387 391 cs.Iea = ea; 388 392 cs.IFL1 = FL1; 389 393 cs.IEV1.Vsize_t = EV1; 394 if (cs.Iop == LEA && cs.IFL1 == FLunde) *(char*)0=0; 390 395 return gen(c,&cs); 391 396 } 392 397 393 398 /***************** 394 399 * Generate code. 395 400 */ 396 401 397 402 code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 398 403 { code cs; 399 404 400 405 assert(FL1 < FLMAX); 401 406 cs.Iop = op; 402 407 cs.Iea = ea; 403 408 cs.Iflags = CFoff; 404 409 cs.IFL1 = FL1; 405 410 cs.IEV1.Vsize_t = EV1; 406 411 assert(FL2 < FLMAX); 407 412 cs.IFL2 = FL2; 408 413 cs.IEV2.Vsize_t = EV2; 409 414 return gen(c,&cs); trunk/src/backend/cod1.c
r621 r627 1855 1855 c = getregs(forregs); 1856 1856 ce = gen1(ce,0x58 + DX); 1857 1857 gen1(ce,0x58 + CX); 1858 1858 gen1(ce,0x58 + BX); 1859 1859 gen1(ce,0x58 + AX); 1860 1860 stackpush -= DOUBLESIZE; 1861 1861 retregs = DOUBLEREGS_16; /* for tstresult() below */ 1862 1862 } 1863 1863 else 1864 1864 #ifdef DEBUG 1865 1865 printf("retregs = x%x, forregs = x%x\n",retregs,forregs), 1866 1866 #endif 1867 1867 assert(0); 1868 1868 if (EOP(e)) 1869 1869 opsflag = TRUE; 1870 1870 } 1871 1871 else 1872 1872 { 1873 1873 c = allocreg(pretregs,&rreg,tym); /* allocate return regs */ 1874 1874 if (sz > REGSIZE) 1875 { unsigned msreg,lsreg; 1876 unsigned msrreg,lsrreg; 1877 1878 msreg = findregmsw(retregs); 1879 lsreg = findreglsw(retregs); 1880 msrreg = findregmsw(*pretregs); 1881 lsrreg = findreglsw(*pretregs); 1875 { 1876 unsigned msreg = findregmsw(retregs); 1877 unsigned lsreg = findreglsw(retregs); 1878 unsigned msrreg = findregmsw(*pretregs); 1879 unsigned lsrreg = findreglsw(*pretregs); 1882 1880 1883 1881 ce = genmovreg(ce,msrreg,msreg); /* MOV msrreg,msreg */ 1884 1882 ce = genmovreg(ce,lsrreg,lsreg); /* MOV lsrreg,lsreg */ 1885 1883 } 1884 else if (retregs & XMMREGS) 1885 { 1886 reg = findreg(retregs & XMMREGS); 1887 // MOVD floatreg, XMM? 1888 ce = genfltreg(ce,0xF20F11,reg - XMM0,0); 1889 // MOV rreg,floatreg 1890 ce = genfltreg(ce,0x8B,rreg,0); 1891 if (sz == 8) 1892 code_orrex(ce,REX_W); 1893 } 1886 1894 else 1887 { reg = findreg(retregs & (mBP | ALLREGS)); 1895 { 1896 reg = findreg(retregs & (mBP | ALLREGS)); 1888 1897 ce = genmovreg(ce,rreg,reg); /* MOV rreg,reg */ 1889 1898 } 1890 1899 } 1891 1900 c = cat(c,ce); 1892 1901 cssave(e,retregs | *pretregs,opsflag); 1893 1902 forregs = 0; /* don't care about result in reg */ 1894 1903 /* cuz we have real result in rreg */ 1895 1904 retregs = *pretregs & ~mPSW; 1896 1905 } 1897 1906 if (forccs) /* if return result in flags */ 1898 1907 c = cat(c,tstresult(retregs,tym,forregs)); 1899 1908 return c; 1900 1909 } 1901 1910 1902 1911 1903 1912 /******************************** 1904 1913 * Generate code sequence to call C runtime library support routine. 1905 1914 * clib = CLIBxxxx 1906 1915 * keepmask = mask of registers not to destroy. Currently can 1907 1916 * handle only 1. Should use a temporary rather than 1908 1917 * push/pop for speed. 1909 1918 */ 1910 1919 1911 1920 int clib_inited = 0; // != 0 if initialized 1912 1921 1913 1922 code *callclib(elem *e,unsigned clib,regm_t *pretregs,regm_t keepmask) 1914 1923 { 1924 //printf("callclib(e = %p, clib = %d, *pretregs = %s, keepmask = %s\n", e, clib, regm_str(*pretregs), regm_str(keepmask)); 1925 //elem_print(e); 1915 1926 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 1916 1927 static symbol lib[] = 1917 1928 { 1918 1929 /* Convert destroyed regs into saved regs */ 1919 1930 #define Z(desregs) (~(desregs) & (mBP| mES | ALLREGS)) 1920 1931 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 1921 1932 #define N(name) "_" name 1922 1933 #else 1923 1934 #define N(name) name 1924 1935 #endif 1925 1936 1926 1937 /* Shorthand to map onto SYMBOLY() */ 1927 1938 #define Y(desregs,name) SYMBOLY(FLfunc,Z(desregs),N(name),0) 1928 1939 1929 1940 Y(0,"_LCMP__"), // CLIBlcmp 1930 1941 Y(mAX|mCX|mDX,"_LMUL__"), // CLIBlmul 1931 1942 #if 1 1932 1943 Y(mAX|mBX|mCX|mDX,"_LDIV__"), // CLIBldiv 1933 1944 Y(mAX|mBX|mCX|mDX,"_LDIV__"), // CLIBlmod 1934 1945 Y(mAX|mBX|mCX|mDX,"_ULDIV__"), // CLIBuldiv … … 2081 2092 2082 2093 // NOTE: desregs is wrong for 16 bit code, mBX should be included 2083 2094 Y(mST0|mST01,"_Cmul"), // CLIBcmul 2084 2095 Y(mAX|mCX|mDX|mST0|mST01,"_Cdiv"), // CLIBcdiv 2085 2096 Y(mAX|mST0|mST01,"_Ccmp"), // CLIBccmp 2086 2097 2087 2098 Y(mST0,"_U64_LDBL"), // CLIBu64_ldbl 2088 2099 Y(mST0|mAX|mDX,"__LDBLULLNG"), // CLIBld_u64 2089 2100 }; 2090 2101 #endif 2091 2102 2092 2103 static struct 2093 2104 { 2094 2105 regm_t retregs16; /* registers that 16 bit result is returned in */ 2095 2106 regm_t retregs32; /* registers that 32 bit result is returned in */ 2096 2107 char pop; /* # of bytes popped off of stack upon return */ 2097 2108 char flags; 2098 2109 #define INF32 1 // if 32 bit only 2099 2110 #define INFfloat 2 // if this is floating point 2100 2111 #define INFwkdone 4 // if weak extern is already done 2112 #define INF64 8 // if 64 bit only 2101 2113 char push87; // # of pushes onto the 8087 stack 2102 2114 char pop87; // # of pops off of the 8087 stack 2103 2115 } info[CLIBMAX] = 2104 2116 { 2105 2117 {0,0,0,0}, /* _LCMP@ lcmp */ 2106 2118 {mDX|mAX,mDX|mAX,0,0}, // _LMUL@ lmul 2107 2119 {mDX|mAX,mDX|mAX,0,0}, // _LDIV@ ldiv 2108 2120 {mCX|mBX,mCX|mBX,0,0}, /* _LDIV@ lmod */ 2109 2121 {mDX|mAX,mDX|mAX,0,0}, /* _ULDIV@ uldiv */ 2110 2122 {mCX|mBX,mCX|mBX,0,0}, /* _ULDIV@ ulmod */ 2111 2123 2112 2124 #if TARGET_WINDOS 2113 2125 {DOUBLEREGS_16,DOUBLEREGS_32,8,INFfloat,1,1}, // _DMUL@ dmul 2114 2126 {DOUBLEREGS_16,DOUBLEREGS_32,8,INFfloat,1,1}, // _DDIV@ ddiv 2115 2127 {0,0,0,2}, // _DTST0@ 2116 2128 {0,0,0,2}, // _DTST0EXC@ 2117 2129 {0,0,8,INFfloat,1,1}, // _DCMP@ dcmp 2118 2130 {0,0,8,INFfloat,1,1}, // _DCMPEXC@ dcmp 2119 2131 {DOUBLEREGS_16,DOUBLEREGS_32,0,2}, // _DNEG@ dneg 2120 2132 {DOUBLEREGS_16,DOUBLEREGS_32,8,INFfloat,1,1}, // _DADD@ dadd … … 2158 2170 {DOUBLEREGS_16,DOUBLEREGS_32,0,INFfloat,1,1}, // _ULLNGDBL@ 2159 2171 2160 2172 {0,0,0,2}, // _DTST@ dtst 2161 2173 {mES|mBX,mES|mBX,0,0}, // _HTOFPTR@ vptrfptr 2162 2174 {mES|mBX,mES|mBX,0,0}, // _HCTOFPTR@ cvptrfptr 2163 2175 {0,0,0,2}, // _87TOPSW@ 87topsw 2164 2176 {mST0,mST0,0,INFfloat,1,0}, // _FLTTO87@ fltto87 2165 2177 {mST0,mST0,0,INFfloat,1,0}, // _DBLTO87@ dblto87 2166 2178 {mAX,mAX,0,2}, // _DBLINT87@ dblint87 2167 2179 {mDX|mAX,mAX,0,2}, // _DBLLNG87@ dbllng87 2168 2180 {0,0,0,2}, // _FTST@ 2169 2181 {mPSW,mPSW,0,INFfloat,0,2}, // _FCOMPP@ 2170 2182 {mPSW,mPSW,0,2}, // _FTEST@ 2171 2183 {mPSW,mPSW,0,2}, // _FTEST0@ 2172 2184 {mST0,mST0,0,INFfloat,1,1}, // _FDIV@ 2173 2185 2174 2186 {mST01,mST01,0,INF32|INFfloat,3,5}, // _Cmul 2175 2187 {mST01,mST01,0,INF32|INFfloat,0,2}, // _Cdiv 2176 2188 {mPSW, mPSW, 0,INF32|INFfloat,0,4}, // _Ccmp 2177 2189 2178 {mST0,mST0,0,INF32|INF float,2,1}, // _U64_LDBL2179 {0,mDX|mAX,0,INF32|INF float,1,2}, // __LDBLULLNG2190 {mST0,mST0,0,INF32|INF64|INFfloat,2,1}, // _U64_LDBL 2191 {0,mDX|mAX,0,INF32|INF64|INFfloat,1,2}, // __LDBLULLNG 2180 2192 }; 2181 2193 2182 2194 if (!clib_inited) /* if not initialized */ 2183 2195 { 2184 2196 assert(sizeof(lib) / sizeof(lib[0]) == CLIBMAX); 2185 2197 assert(sizeof(info) / sizeof(info[0]) == CLIBMAX); 2186 2198 for (int i = 0; i < CLIBMAX; i++) 2187 2199 { lib[i].Stype = tsclib; 2188 2200 #if MARS 2189 2201 lib[i].Sxtrnnum = 0; 2190 2202 lib[i].Stypidx = 0; 2191 2203 #endif 2192 2204 } 2193 2205 2194 2206 if (!I16) 2195 2207 { /* Adjust table for 386 */ 2196 2208 lib[CLIBdbllng].Sregsaved = Z(DOUBLEREGS_32); 2197 2209 lib[CLIBlngdbl].Sregsaved = Z(DOUBLEREGS_32); 2198 2210 lib[CLIBdblint].Sregsaved = Z(DOUBLEREGS_32); 2199 2211 lib[CLIBintdbl].Sregsaved = Z(DOUBLEREGS_32); … … 2202 2214 lib[CLIBdneg].Sregsaved = Z(DOUBLEREGS_32); 2203 2215 lib[CLIBdbluns].Sregsaved = Z(DOUBLEREGS_32); 2204 2216 lib[CLIBunsdbl].Sregsaved = Z(DOUBLEREGS_32); 2205 2217 lib[CLIBdblulng].Sregsaved = Z(DOUBLEREGS_32); 2206 2218 lib[CLIBulngdbl].Sregsaved = Z(DOUBLEREGS_32); 2207 2219 #endif 2208 2220 lib[CLIBdblflt].Sregsaved = Z(DOUBLEREGS_32); 2209 2221 lib[CLIBfltdbl].Sregsaved = Z(DOUBLEREGS_32); 2210 2222 2211 2223 lib[CLIBdblllng].Sregsaved = Z(DOUBLEREGS_32); 2212 2224 lib[CLIBllngdbl].Sregsaved = Z(DOUBLEREGS_32); 2213 2225 lib[CLIBdblullng].Sregsaved = Z(DOUBLEREGS_32); 2214 2226 lib[CLIBullngdbl].Sregsaved = Z(DOUBLEREGS_32); 2215 2227 } 2216 2228 clib_inited++; 2217 2229 } 2218 2230 #undef Z 2219 2231 2220 2232 assert(clib < CLIBMAX); 2221 2233 symbol *s = &lib[clib]; 2222 assert(I32 || !(info[clib].flags & INF32)); 2234 if (I16) 2235 assert(!(info[clib].flags & (INF32 | INF64))); 2223 2236 code *cpop = CNIL; 2224 2237 code *c = getregs((~s->Sregsaved & (mES | mBP | ALLREGS)) & ~keepmask); // mask of regs destroyed 2225 2238 keepmask &= ~s->Sregsaved; 2226 2239 int npushed = numbitsset(keepmask); 2227 2240 gensaverestore2(keepmask, &c, &cpop); 2228 2241 #if 0 2229 2242 while (keepmask) 2230 2243 { unsigned keepreg; 2231 2244 2232 2245 if (keepmask & (mBP|ALLREGS)) 2233 2246 { keepreg = findreg(keepmask & (mBP|ALLREGS)); 2234 2247 c = gen1(c,0x50 + keepreg); /* PUSH keepreg */ 2235 2248 cpop = cat(gen1(CNIL,0x58 + keepreg),cpop); // POP keepreg 2236 2249 keepmask &= ~mask[keepreg]; 2237 2250 npushed++; 2238 2251 } 2239 2252 if (keepmask & mES) 2240 2253 { c = gen1(c,0x06); /* PUSH ES */ 2241 2254 cpop = cat(gen1(CNIL,0x07),cpop); /* POP ES */ 2242 2255 keepmask &= ~mES; … … 3593 3606 code_newreg(c, c->Irm & 7); 3594 3607 if (c->Irex & REX_B) 3595 3608 c->Irex = (c->Irex & ~REX_B) | REX_R; 3596 3609 } 3597 3610 } 3598 3611 } 3599 3612 else if (sz < 8) 3600 3613 { 3601 3614 c = allocreg(®m,®,TYoffset); /* get a register */ 3602 3615 if (I32) // it's a 48 bit pointer 3603 3616 ce = loadea(e,&cs,0x0FB7,reg,REGSIZE,0,0); /* MOVZX reg,data+4 */ 3604 3617 else 3605 3618 { ce = loadea(e,&cs,0x8B,reg,REGSIZE,0,0); /* MOV reg,data+2 */ 3606 3619 if (tym == TYfloat || tym == TYifloat) // dump sign bit 3607 3620 gen2(ce,0xD1,modregrm(3,4,reg)); /* SHL reg,1 */ 3608 3621 } 3609 3622 c = cat(c,ce); 3610 3623 ce = loadea(e,&cs,0x0B,reg,0,regm,0); /* OR reg,data */ 3611 3624 c = cat(c,ce); 3612 3625 } 3613 else if (sz == 8) 3614 { code *c1; 3615 int i; 3616 3626 else if (sz == 8 || (I64 && sz == 2 * REGSIZE && !tyfloating(tym))) 3627 { 3617 3628 c = allocreg(®m,®,TYoffset); /* get a register */ 3618 i = sz - REGSIZE;3629 int i = sz - REGSIZE; 3619 3630 ce = loadea(e,&cs,0x8B,reg,i,0,0); /* MOV reg,data+6 */ 3620 3631 if (tyfloating(tym)) // TYdouble or TYdouble_alias 3621 3632 gen2(ce,0xD1,modregrm(3,4,reg)); // SHL reg,1 3622 3633 c = cat(c,ce); 3623 3634 3624 3635 while ((i -= REGSIZE) >= 0) 3625 3636 { 3626 c 1 = loadea(e,&cs,0x0B,reg,i,regm,0); // OR reg,data+i3637 code *c1 = loadea(e,&cs,0x0B,reg,i,regm,0); // OR reg,data+i 3627 3638 if (i == 0) 3628 3639 c1->Iflags |= CFpsw; // need the flags on last OR 3629 3640 c = cat(c,c1); 3630 3641 } 3631 3642 } 3632 else if (sz == LNGDBLSIZE)// TYldouble3643 else if (sz == tysize[TYldouble]) // TYldouble 3633 3644 return load87(e,0,pretregs,NULL,-1); 3634 3645 else 3646 { 3647 #ifdef DEBUG 3648 elem_print(e); 3649 #endif 3635 3650 assert(0); 3651 } 3636 3652 return c; 3637 3653 } 3638 3654 /* not for flags only */ 3639 3655 flags = *pretregs & mPSW; /* save original */ 3640 3656 forregs = *pretregs & (mBP | ALLREGS | mES | XMMREGS); 3641 3657 if (*pretregs & mSTACK) 3642 3658 forregs |= DOUBLEREGS; 3643 3659 if (e->Eoper == OPconst) 3644 3660 { regm_t save; 3645 3661 3646 3662 if (sz == REGSIZE && reghasvalue(forregs,e->EV.Vint,®)) 3647 3663 forregs = mask[reg]; 3648 3664 3649 3665 save = regcon.immed.mval; 3650 3666 c = allocreg(&forregs,®,tym); /* allocate registers */ 3651 3667 regcon.immed.mval = save; // KLUDGE! 3652 3668 if (sz <= REGSIZE) 3653 3669 { 3654 3670 if (sz == 1) 3655 3671 flags |= 1; trunk/src/backend/cod2.c
r601 r627 210 210 if ((tylong(ty1) || ty1 == TYhptr) && 211 211 (tylong(ty2) || ty2 == TYhptr)) 212 212 numwords++; 213 213 } 214 214 215 215 // Special cases where only flags are set 216 216 if (test && tysize[ty1] <= REGSIZE && 217 217 (e1->Eoper == OPvar || (e1->Eoper == OPind && !e1->Ecount))) 218 218 { 219 219 // Handle the case of (var & const) 220 220 if (e2->Eoper == OPconst) 221 221 { 222 222 c = getlvalue(&cs,e1,0); 223 223 targ_size_t value = e2->EV.Vpointer; 224 224 if (sz == 2) 225 225 value &= 0xFFFF; 226 226 else if (sz == 4) 227 227 value &= 0xFFFFFFFF; 228 228 if (reghasvalue(byte ? BYTEREGS : ALLREGS,value,®)) 229 229 goto L11; 230 if (sz == 8 )230 if (sz == 8 && !I64) 231 231 { 232 232 assert(value == (int)value); // sign extend imm32 233 233 } 234 234 op1 = 0xF7; 235 235 cs.IEV2.Vint = value; 236 236 cs.IFL2 = FLconst; 237 237 goto L10; 238 238 } 239 239 240 240 // Handle (exp & reg) 241 241 if (isregvar(e2,&retregs,®)) 242 242 { 243 243 c = getlvalue(&cs,e1,0); 244 244 L11: 245 245 code_newreg(&cs, reg); 246 246 L10: 247 247 cs.Iop = op1 ^ byte; 248 248 cs.Iflags |= word | CFpsw; 249 249 freenode(e1); 250 250 freenode(e2); … … 392 392 393 393 // IMUL reg,imm32 394 394 c = genc2(CNIL,0x69,modregxrm(3,reg,BP),imm32[ss]); 395 395 } 396 396 else 397 397 { // LEA reg,[reg1*ss][reg1] 398 398 c = gen2sib(CNIL,0x8D,modregxrm(0,reg,4),modregrm(ss,reg1 & 7,reg1 & 7)); 399 399 if (reg1 & 8) 400 400 code_orrex(c, REX_X | REX_B); 401 401 } 402 402 reg1 = reg; 403 403 ss = ss2; // use *2 for scale 404 404 } 405 405 else 406 406 c = NULL; 407 407 c = cat4(c1,c2,c3,c); 408 408 409 409 cs.Iop = 0x8D; // LEA reg,c[reg1*ss][reg2] 410 410 cs.Irm = modregrm(2,reg & 7,4); 411 411 cs.Isib = modregrm(ss,reg1 & 7,reg2 & 7); 412 assert(reg2 != BP); 412 413 cs.Iflags = CFoff; 413 414 cs.Irex = 0; 414 415 if (reg & 8) 415 416 cs.Irex |= REX_R; 416 417 if (reg1 & 8) 417 418 cs.Irex |= REX_X; 418 419 if (reg2 & 8) 419 420 cs.Irex |= REX_B; 420 421 cs.IFL1 = FLconst; 421 422 cs.IEV1.Vuns = edisp->EV.Vuns; 422 423 423 424 freenode(edisp); 424 425 freenode(e1); 425 426 c = gen(c,&cs); 426 427 return cat(c,fixresult(e,mask[reg],pretregs)); 427 428 } 428 429 } 429 430 430 431 posregs = (byte) ? BYTEREGS : (mES | ALLREGS | mBP); 431 432 retregs = *pretregs & posregs; … … 759 760 760 761 code *cdmul(elem *e,regm_t *pretregs) 761 762 { unsigned rreg,op,oper,lib,byte; 762 763 regm_t resreg,retregs,rretregs; 763 764 regm_t keepregs; 764 765 tym_t uns; // 1 if unsigned operation, 0 if not 765 766 tym_t tyml; 766 767 code *c,*cg,*cl,*cr,cs; 767 768 elem *e1,*e2; 768 769 int sz; 769 770 targ_size_t e2factor; 770 771 int opunslng; 771 772 int pow2; 772 773 773 774 if (*pretregs == 0) // if don't want result 774 775 { c = codelem(e->E1,pretregs,FALSE); // eval left leaf 775 776 *pretregs = 0; // in case they got set 776 777 return cat(c,codelem(e->E2,pretregs,FALSE)); 777 778 } 778 779 780 //printf("cdmul(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 779 781 keepregs = 0; 780 782 cs.Iflags = 0; 781 783 cs.Irex = 0; 782 784 c = cg = cr = CNIL; // initialize 783 785 e2 = e->E2; 784 786 e1 = e->E1; 785 787 tyml = tybasic(e1->Ety); 786 788 sz = tysize[tyml]; 787 789 byte = tybyte(e->Ety) != 0; 788 790 uns = tyuns(tyml) || tyuns(e2->Ety); 789 791 oper = e->Eoper; 790 792 unsigned rex = (I64 && sz == 8) ? REX_W : 0; 791 793 unsigned grex = rex << 16; 792 794 793 795 if (tyfloating(tyml)) 794 796 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 795 797 return orth87(e,pretregs); 796 798 #else 797 799 return opdouble(e,pretregs,(oper == OPmul) ? CLIBdmul : CLIBddiv); 798 800 #endif … … 1010 1012 case 24: ss = 1; ss2 = 3; goto L4; 1011 1013 1012 1014 case 6: 1013 1015 case 3: ss = 1; goto L4; 1014 1016 1015 1017 case 20: ss = 2; ss2 = 2; goto L4; 1016 1018 case 40: ss = 2; ss2 = 3; goto L4; 1017 1019 1018 1020 case 10: 1019 1021 case 5: ss = 2; goto L4; 1020 1022 1021 1023 case 36: ss = 3; ss2 = 2; goto L4; 1022 1024 case 72: ss = 3; ss2 = 3; goto L4; 1023 1025 1024 1026 case 18: 1025 1027 case 9: ss = 3; goto L4; 1026 1028 1027 1029 L4: 1028 1030 { 1029 1031 #if 1 1030 regm_t regm = byte ? BYTEREGS : ALLREGS; // don't use EBP 1032 regm_t regm = byte ? BYTEREGS : ALLREGS; 1033 regm &= ~(mBP | mR13); // don't use EBP 1031 1034 cl = codelem(e->E1,®m,TRUE); 1032 1035 unsigned r = findreg(regm); 1033 1036 1034 1037 if (ss2) 1035 1038 { // Don't use EBP 1036 resreg &= ~ mBP;1039 resreg &= ~(mBP | mR13); 1037 1040 if (!resreg) 1038 1041 resreg = retregs; 1039 1042 } 1040 1043 cg = allocreg(&resreg,®,tyml); 1041 1044 1042 1045 c = gen2sib(CNIL,0x8D,grex | modregxrm(0,reg,4), 1043 1046 modregxrmx(ss,r,r)); 1047 assert((r & 7) != BP); 1044 1048 if (ss2) 1045 1049 { 1046 1050 gen2sib(c,0x8D,grex | modregxrm(0,reg,4), 1047 1051 modregxrm(ss2,reg,5)); 1048 1052 code_last(c)->IFL1 = FLconst; 1049 1053 code_last(c)->IEV1.Vint = 0; 1050 1054 } 1051 1055 else if (!(e2factor & 1)) // if even factor 1052 1056 { genregs(c,0x03,reg,reg); // ADD reg,reg 1053 1057 code_orrex(c,rex); 1054 1058 } 1055 1059 cg = cat(cg,c); 1056 1060 goto L3; 1057 1061 #else 1058 1062 1059 1063 // Don't use EBP 1060 1064 resreg &= ~mBP; 1061 1065 if (!resreg) 1062 1066 resreg = retregs; 1063 1067 … … 1071 1075 gen2sib(c,0x8D,modregrm(0,reg,4), 1072 1076 modregrm(ss2,reg,5)); 1073 1077 code_last(c)->IFL1 = FLconst; 1074 1078 code_last(c)->IEV1.Vint = 0; 1075 1079 } 1076 1080 else if (!(e2factor & 1)) // if even factor 1077 1081 genregs(c,0x03,reg,reg); // ADD reg,reg 1078 1082 cg = cat(cg,c); 1079 1083 goto L3; 1080 1084 #endif 1081 1085 } 1082 1086 case 37: 1083 1087 case 74: shift = 2; 1084 1088 goto L5; 1085 1089 case 13: 1086 1090 case 26: shift = 0; 1087 1091 goto L5; 1088 1092 L5: 1089 1093 { 1090 1094 // Don't use EBP 1091 resreg &= ~ mBP;1095 resreg &= ~(mBP | mR13); 1092 1096 if (!resreg) 1093 1097 resreg = retregs; 1094 1098 cl = allocreg(&resreg,®,TYint); 1095 1099 1096 regm_t sregm = ALLREGS& ~resreg;1100 regm_t sregm = (ALLREGS & ~mR13) & ~resreg; 1097 1101 cl = cat(cl,codelem(e->E1,&sregm,FALSE)); 1098 1102 unsigned sreg = findreg(sregm); 1099 1103 cg = getregs(resreg | sregm); 1100 1104 // LEA reg,[sreg * 4][sreg] 1101 1105 // SHL sreg,shift 1102 1106 // LEA reg,[sreg * 8][reg] 1107 assert((sreg & 7) != BP); 1108 assert((reg & 7) != BP); 1103 1109 c = gen2sib(CNIL,0x8D,grex | modregxrm(0,reg,4), 1104 1110 modregxrmx(2,sreg,sreg)); 1105 1111 if (shift) 1106 1112 genc2(c,0xC1,grex | modregrmx(3,4,sreg),shift); 1107 1113 gen2sib(c,0x8D,grex | modregxrm(0,reg,4), 1108 1114 modregxrmx(3,sreg,reg)); 1109 1115 if (!(e2factor & 1)) // if even factor 1110 1116 { genregs(c,0x03,reg,reg); // ADD reg,reg 1111 1117 code_orrex(c,rex); 1112 1118 } 1113 1119 cg = cat(cg,c); 1114 1120 goto L3; 1115 1121 } 1116 1122 } 1117 1123 } 1118 1124 1119 1125 cl = scodelem(e->E1,&retregs,0,TRUE); // eval left leaf 1120 1126 reg = findreg(retregs); 1121 1127 cg = allocreg(&resreg,&rreg,e->Ety); 1122 1128 … … 1191 1197 genc2(cg,0xC1,grex | modregrm(3,7,AX),pow2); // SAR AX,pow2 1192 1198 } 1193 1199 else // OPmod 1194 1200 { gen2(cg,0x33,grex | modregrm(3,AX,DX)); // XOR AX,DX 1195 1201 gen2(cg,0x2B,grex | modregrm(3,AX,DX)); // SUB AX,DX 1196 1202 genc2(cg,0x81,grex | modregrm(3,4,AX),m); // AND AX,mask 1197 1203 gen2(cg,0x33,grex | modregrm(3,AX,DX)); // XOR AX,DX 1198 1204 gen2(cg,0x2B,grex | modregrm(3,AX,DX)); // SUB AX,DX 1199 1205 resreg = mAX; 1200 1206 } 1201 1207 } 1202 1208 goto L3; 1203 1209 } 1204 1210 goto L2; 1205 1211 case OPind: 1206 1212 if (!e2->Ecount) /* if not CSE */ 1207 1213 goto L1; /* try OP reg,EA */ 1208 1214 goto L2; 1209 1215 default: /* OPconst and operators */ 1210 1216 L2: 1217 //printf("test2 %p, retregs = %s rretregs = %s resreg = %s\n", e, regm_str(retregs), regm_str(rretregs), regm_str(resreg)); 1211 1218 cl = codelem(e1,&retregs,FALSE); /* eval left leaf */ 1212 1219 cr = scodelem(e2,&rretregs,retregs,TRUE); /* get rvalue */ 1213 1220 if (sz <= REGSIZE) 1214 1221 { cg = getregs(mAX | mDX); /* trash these regs */ 1215 1222 if (op == 7) /* signed divide */ 1216 1223 { cg = gen1(cg,0x99); // CWD 1217 1224 code_orrex(cg,rex); 1218 1225 } 1219 1226 else if (op == 6) /* unsigned divide */ 1220 1227 { 1221 1228 cg = movregconst(cg,DX,0,(sz == 8) ? 64 : 0); // MOV DX,0 1222 1229 cg = cat(cg,getregs(mDX)); 1223 1230 } 1224 1231 rreg = findreg(rretregs); 1225 1232 cg = gen2(cg,0xF7 ^ byte,grex | modregrmx(3,op,rreg)); // OP AX,rreg 1226 1233 L3: 1227 1234 c = fixresult(e,resreg,pretregs); 1228 1235 } 1229 1236 else if (sz == 2 * REGSIZE) 1230 1237 { trunk/src/backend/cod3.c
r619 r627 3484 3484 unsigned char op; 3485 3485 3486 3486 //printf("jmpaddr()\n"); 3487 3487 cstart = c; /* remember start of code */ 3488 3488 while (c) 3489 3489 { 3490 3490 op = c->Iop; 3491 3491 if (inssize[op & 0xFF] & T && // if second operand 3492 3492 c->IFL2 == FLcode && 3493 3493 ((op & ~0x0F) == 0x70 || op == JMP || op == JMPS || op == JCXZ)) 3494 3494 { ci = code_next(c); 3495 3495 ctarg = c->IEV2.Vcode; /* target code */ 3496 3496 ad = 0; /* IP displacement */ 3497 3497 while (ci && ci != ctarg) 3498 3498 { 3499 3499 ad += calccodsize(ci); 3500 3500 ci = code_next(ci); 3501 3501 } 3502 3502 if (!ci) 3503 3503 goto Lbackjmp; // couldn't find it 3504 if ( I32|| op == JMP || op == JMPS || op == JCXZ)3504 if (!I16 || op == JMP || op == JMPS || op == JCXZ) 3505 3505 c->IEVpointer2 = ad; 3506 3506 else /* else conditional */ 3507 3507 { if (!(c->Iflags & CFjmp16)) /* if branch */ 3508 3508 c->IEVpointer2 = ad; 3509 3509 else /* branch around a long jump */ 3510 3510 { cn = code_next(c); 3511 3511 code_next(c) = code_calloc(); 3512 3512 code_next(code_next(c)) = cn; 3513 3513 c->Iop = op ^ 1; /* converse jmp */ 3514 3514 c->Iflags &= ~CFjmp16; 3515 c->IEVpointer2 = I 32 ? 5 : 3;3515 c->IEVpointer2 = I16 ? 3 : 5; 3516 3516 cn = code_next(c); 3517 3517 cn->Iop = JMP; /* long jump */ 3518 3518 cn->IFL2 = FLconst; 3519 3519 cn->IEVpointer2 = ad; 3520 3520 } 3521 3521 } 3522 3522 c->IFL2 = FLconst; 3523 3523 } 3524 3524 if (op == LOOP && c->IFL2 == FLcode) /* backwards refs */ 3525 3525 { 3526 3526 Lbackjmp: 3527 3527 ctarg = c->IEV2.Vcode; 3528 3528 for (ci = cstart; ci != ctarg; ci = code_next(ci)) 3529 3529 if (!ci || ci == c) 3530 3530 assert(0); 3531 3531 ad = 2; /* - IP displacement */ 3532 3532 while (ci != c) 3533 3533 { assert(ci); 3534 3534 ad += calccodsize(ci); 3535 3535 ci = code_next(ci); 3536 3536 } 3537 3537 c->IEVpointer2 = (-ad) & 0xFF; 3538 3538 c->IFL2 = FLconst; 3539 3539 } 3540 3540 c = code_next(c); 3541 3541 } 3542 3542 } 3543 3543 3544 3544 3545 3545 /******************************* 3546 3546 * Calculate bl->Bsize. 3547 3547 */ 3548 3548 3549 3549 unsigned calcblksize(code *c) 3550 3550 { unsigned size; 3551 3551 3552 3552 for (size = 0; c; c = code_next(c)) 3553 size += calccodsize(c); 3553 { 3554 unsigned sz = calccodsize(c); 3555 //printf("off=%02x, sz = %d, code %p: op=%02x\n", size, sz, c, c->Iop); 3556 size += sz; 3557 } 3554 3558 //printf("calcblksize(c = x%x) = %d\n", c, size); 3555 3559 return size; 3556 3560 } 3557 3561 3558 3562 /***************************** 3559 3563 * Calculate and return code size of a code. 3560 3564 * Note that NOPs are sometimes used as markers, but are 3561 3565 * never output. LINNUMs are never output. 3562 3566 * Note: This routine must be fast. Profiling shows it is significant. 3563 3567 */ 3564 3568 3565 3569 unsigned calccodsize(code *c) 3566 3570 { unsigned size; 3567 3571 unsigned op; 3568 3572 unsigned char rm,mod,ins; 3569 3573 unsigned iflags; 3570 3574 unsigned i32 = I32 || I64; 3571 3575 unsigned a32 = i32; 3572 3576 3573 3577 #ifdef DEBUG … … 5033 5037 else 5034 5038 ins = inssize[op & 0xFF]; 5035 5039 5036 5040 printf("code %p: nxt=%p ",c,code_next(c)); 5037 5041 if (c->Irex) 5038 5042 printf("rex=%x ", c->Irex); 5039 5043 printf("op=%02x",op); 5040 5044 5041 5045 if ((op & 0xFF) == ESCAPE) 5042 5046 { if ((op & 0xFF00) == ESClinnum) 5043 5047 { printf(" linnum = %d\n",c->IEV2.Vsrcpos.Slinnum); 5044 5048 return; 5045 5049 } 5046 5050 printf(" ESCAPE %d",c->Iop >> 8); 5047 5051 } 5048 5052 if (c->Iflags) 5049 5053 printf(" flg=%x",c->Iflags); 5050 5054 if (ins & M) 5051 5055 { unsigned rm = c->Irm; 5052 5056 printf(" rm=%02x=%d,%d,%d",rm,(rm>>6)&3,(rm>>3)&7,rm&7); 5053 if ( I32&& issib(rm))5057 if (!I16 && issib(rm)) 5054 5058 { unsigned char sib = c->Isib; 5055 5059 printf(" sib=%02x=%d,%d,%d",sib,(sib>>6)&3,(sib>>3)&7,sib&7); 5056 5060 } 5057 5061 if ((rm & 0xC7) == BPRM || (rm & 0xC0) == 0x80 || (rm & 0xC0) == 0x40) 5058 5062 { 5059 5063 switch (c->IFL1) 5060 5064 { 5061 5065 case FLconst: 5062 5066 case FLoffset: 5063 5067 printf(" int = %4d",c->IEV1.Vuns); 5064 5068 break; 5065 5069 case FLblock: 5066 5070 printf(" block = %p",c->IEV1.Vblock); 5067 5071 break; 5068 5072 case FLswitch: 5069 5073 case FLblockoff: 5070 5074 case FLlocalsize: 5071 5075 case FLframehandler: 5072 5076 case 0: 5073 5077 break; trunk/src/backend/cod4.c
r618 r627 2862 2862 code *c; 2863 2863 2864 2864 //printf("cdmsw(e->Ecount = %d)\n", e->Ecount); 2865 2865 assert(e->Eoper == OPmsw); 2866 2866 2867 2867 retregs = *pretregs ? ALLREGS : 0; 2868 2868 c = codelem(e->E1,&retregs,FALSE); 2869 2869 retregs &= mMSW; // want MSW only 2870 2870 2871 2871 // We "destroy" a reg by assigning it the result of a new e, even 2872 2872 // though the values are the same. Weakness of our CSE strategy that 2873 2873 // a register can only hold the contents of one elem at a time. 2874 2874 if (e->Ecount) 2875 2875 c = cat(c,getregs(retregs)); 2876 2876 else 2877 2877 useregs(retregs); 2878 2878 2879 2879 #ifdef DEBUG 2880 2880 if (!(!*pretregs || retregs)) 2881 2881 { WROP(e->Eoper); 2882 printf(" *pretregs = x%x, retregs = x%x\n",*pretregs,retregs); 2882 printf(" *pretregs = %s, retregs = %s\n",regm_str(*pretregs),regm_str(retregs)); 2883 elem_print(e); 2883 2884 } 2884 2885 #endif 2885 2886 assert(!*pretregs || retregs); 2886 2887 return cat(c,fixresult(e,retregs,pretregs)); // msw only 2887 2888 } 2888 2889 2889 2890 2890 2891 2891 2892 /****************************** 2892 2893 * Handle operators OPinp and OPoutp. 2893 2894 */ 2894 2895 2895 2896 code *cdport(elem *e,regm_t *pretregs) 2896 2897 { regm_t retregs; 2897 2898 code *c1,*c2,*c3; 2898 2899 unsigned char op,port; 2899 2900 unsigned sz; 2900 2901 elem *e1; 2901 2902 2902 2903 //printf("cdport\n"); trunk/src/backend/debug.c
r618 r627 193 193 { nest++; 194 194 ferr("("); 195 195 WReqn(e->E2); 196 196 ferr(")"); 197 197 nest--; 198 198 } 199 199 else 200 200 WReqn(e->E2); 201 201 } 202 202 else 203 203 { 204 204 switch (e->Eoper) 205 205 { case OPconst: 206 206 switch (tybasic(e->Ety)) 207 207 { 208 208 case TYfloat: 209 209 dbg_printf("%g <float> ",e->EV.Vfloat); 210 210 break; 211 211 case TYdouble: 212 212 dbg_printf("%g ",e->EV.Vdouble); 213 break; 214 case TYcent: 215 case TYucent: 216 dbg_printf("%lld+%lld ", e->EV.Vcent.msw, e->EV.Vcent.lsw); 213 217 break; 214 218 default: 215 219 dbg_printf("%lld ",el_tolong(e)); 216 220 break; 217 221 } 218 222 break; 219 223 case OPrelconst: 220 224 ferr("#"); 221 225 /* FALL-THROUGH */ 222 226 case OPvar: 223 227 dbg_printf("%s",e->EV.sp.Vsym->Sident); 224 228 if (e->EV.sp.Vsym->Ssymnum != -1) 225 229 dbg_printf("(%d)",e->EV.sp.Vsym->Ssymnum); 226 230 if (e->Eoffset != 0) 227 231 dbg_printf(".%ld",(long)e->Eoffset); 228 232 break; 229 233 case OPasm: 230 234 #if TARGET_MAC 231 235 if (e->Eflags & EFsmasm) 232 236 { trunk/src/backend/el.c
r618 r627 2547 2547 if (n1->EV.Vshort != n2->EV.Vshort) 2548 2548 goto nomatch; 2549 2549 break; 2550 2550 case TYlong: 2551 2551 case TYulong: 2552 2552 case TYdchar: 2553 2553 #if TARGET_MAC 2554 2554 case TYfptr: 2555 2555 case TYvptr: 2556 2556 #endif 2557 2557 case_long: 2558 2558 if (n1->EV.Vlong != n2->EV.Vlong) 2559 2559 goto nomatch; 2560 2560 break; 2561 2561 case TYllong: 2562 2562 case TYullong: 2563 2563 case_llong: 2564 2564 if (n1->EV.Vllong != n2->EV.Vllong) 2565 2565 goto nomatch; 2566 2566 break; 2567 case TYcent: 2568 case TYucent: 2569 if (n1->EV.Vcent.lsw != n2->EV.Vcent.lsw || 2570 n1->EV.Vcent.msw != n2->EV.Vcent.msw) 2571 goto nomatch; 2572 break; 2567 2573 case TYenum: 2568 2574 if (PARSER) 2569 2575 { tym = n1->ET->Tnext->Tty; 2570 2576 goto Lagain; 2571 2577 } 2572 2578 case TYint: 2573 2579 case TYuint: 2574 2580 if (intsize == SHORTSIZE) 2575 2581 goto case_short; 2576 2582 else 2577 2583 goto case_long; 2578 2584 2579 2585 #if TX86 2580 2586 #if JHANDLE 2581 2587 case TYjhandle: 2582 2588 #endif 2583 2589 case TYnullptr: 2584 2590 case TYnptr: 2585 2591 case TYsptr: 2586 2592 case TYcptr: trunk/src/backend/evalu8.c
r618 r627 175 175 b = 1; 176 176 else 177 177 b = e->EV.Vcdouble.re != 0 || e->EV.Vcdouble.im != 0; 178 178 break; 179 179 case TYcldouble: 180 180 if (isnan(e->EV.Vcldouble.re) || isnan(e->EV.Vcldouble.im)) 181 181 b = 1; 182 182 else 183 183 b = e->EV.Vcldouble.re != 0 || e->EV.Vcldouble.im != 0; 184 184 break; 185 185 case TYstruct: // happens on syntax error of (struct x)0 186 186 #if SCPP 187 187 assert(errcnt); 188 188 #else 189 189 assert(0); 190 190 #endif 191 191 case TYvoid: /* happens if we get syntax errors or 192 192 on RHS of && || expressions */ 193 193 b = 0; 194 194 break; 195 196 case TYcent: 197 case TYucent: 198 b = e->EV.Vcent.lsw || e->EV.Vcent.msw; 199 break; 200 195 201 default: 196 202 #ifdef DEBUG 197 203 WRTYxx(typemask(e)); 198 204 #endif 199 205 assert(0); 200 206 } 201 207 break; 202 208 default: 203 209 assert(0); 204 210 } 205 211 return b; 206 212 } 207 213 208 214 /*************************** 209 215 * Return TRUE if expression will always evaluate to TRUE. 210 216 */ 211 217 212 218 HINT iftrue(elem *e) 213 219 { 214 220 while (1) trunk/src/todt.c
r602 r627 134 134 break; // overlap 135 135 } 136 136 } 137 137 } 138 138 if (d) 139 139 { 140 140 if (v->offset < offset) 141 141 error(loc, "duplicate union initialization for %s", v->toChars()); 142 142 else 143 143 { unsigned sz = dt_size(d); 144 144 unsigned vsz = v->type->size(); 145 145 unsigned voffset = v->offset; 146 146 147 147 unsigned dim = 1; 148 148 for (Type *vt = v->type->toBasetype(); 149 149 vt->ty == Tsarray; 150 150 vt = vt->nextOf()->toBasetype()) 151 151 { TypeSArray *tsa = (TypeSArray *)vt; 152 152 dim *= tsa->dim->toInteger(); 153 153 } 154 //printf("sz = %d, dim = %d, vsz = %d\n", sz, dim, vsz); 154 155 assert(sz == vsz || sz * dim <= vsz); 155 156 156 157 for (size_t i = 0; i < dim; i++) 157 158 { 158 159 if (offset < voffset) 159 160 pdtend = dtnzeros(pdtend, voffset - offset); 160 161 if (!d) 161 162 { 162 163 if (v->init) 163 164 d = v->init->toDt(); 164 165 else 165 166 v->type->toDt(&d); 166 167 } 167 168 pdtend = dtcat(pdtend, d); 168 169 d = NULL; 169 170 offset = voffset + sz; 170 171 voffset += vsz / dim; 171 172 if (sz == vsz) 172 173 break; 173 174 } … … 265 266 else if (dim > tadim) 266 267 { 267 268 #ifdef DEBUG 268 269 printf("1: "); 269 270 #endif 270 271 error(loc, "too many initializers, %d, for array[%d]", dim, tadim); 271 272 } 272 273 break; 273 274 } 274 275 275 276 case Tpointer: 276 277 case Tarray: 277 278 // Create symbol, and then refer to it 278 279 Symbol *s; 279 280 s = static_sym(); 280 281 s->Sdt = d; 281 282 outdata(s); 282 283 283 284 d = NULL; 284 285 if (tb->ty == Tarray) 285 dt dword(&d, dim);286 dtsize_t(&d, dim); 286 287 dtxoff(&d, s, 0, TYnptr); 287 288 break; 288 289 289 290 default: 290 291 assert(0); 291 292 } 292 293 return d; 293 294 } 294 295 295 296 296 297 dt_t *ArrayInitializer::toDtBit() 297 298 { 298 299 #if DMDV1 299 300 unsigned size; 300 301 unsigned length; 301 302 unsigned i; 302 303 unsigned tadim; 303 304 dt_t *d; 304 305 dt_t **pdtend; 305 306 Type *tb = type->toBasetype(); … … 380 381 } 381 382 else 382 383 { 383 384 tadim = (tadim + 31) / 32; 384 385 if (databits.allocdim < tadim) 385 386 pdtend = dtnzeros(pdtend, size * (tadim - databits.allocdim)); // pad out end of array 386 387 } 387 388 break; 388 389 } 389 390 390 391 case Tpointer: 391 392 case Tarray: 392 393 // Create symbol, and then refer to it 393 394 Symbol *s; 394 395 s = static_sym(); 395 396 s->Sdt = d; 396 397 outdata(s); 397 398 398 399 d = NULL; 399 400 if (tb->ty == Tarray) 400 dt dword(&d, dim);401 dtsize_t(&d, dim); 401 402 dtxoff(&d, s, 0, TYnptr); 402 403 break; 403 404 404 405 default: 405 406 assert(0); 406 407 } 407 408 return d; 408 409 #else 409 410 return NULL; 410 411 #endif 411 412 } 412 413 413 414 414 415 dt_t *ExpInitializer::toDt() 415 416 { 416 417 dt_t *dt = NULL; 417 418 418 419 exp = exp->optimize(WANTvalue); 419 420 exp->toDt(&dt); 420 421 return dt; … … 522 523 break; 523 524 } 524 525 return pdt; 525 526 } 526 527 527 528 dt_t **NullExp::toDt(dt_t **pdt) 528 529 { 529 530 assert(type); 530 531 return dtnzeros(pdt, type->size()); 531 532 } 532 533 533 534 dt_t **StringExp::toDt(dt_t **pdt) 534 535 { 535 536 //printf("StringExp::toDt() '%s', type = %s\n", toChars(), type->toChars()); 536 537 Type *t = type->toBasetype(); 537 538 538 539 // BUG: should implement some form of static string pooling 539 540 switch (t->ty) 540 541 { 541 542 case Tarray: 542 dt dword(pdt, len);543 dtsize_t(pdt, len); 543 544 pdt = dtabytes(pdt, TYnptr, 0, (len + 1) * sz, (char *)string); 544 545 break; 545 546 546 547 case Tsarray: 547 548 { TypeSArray *tsa = (TypeSArray *)type; 548 549 dinteger_t dim; 549 550 550 551 pdt = dtnbytes(pdt, len * sz, (const char *)string); 551 552 if (tsa->dim) 552 553 { 553 554 dim = tsa->dim->toInteger(); 554 555 if (len < dim) 555 556 { 556 557 // Pad remainder with 0 557 558 pdt = dtnzeros(pdt, (dim - len) * tsa->next->size()); 558 559 } 559 560 } 560 561 break; 561 562 } 562 563 case Tpointer: … … 578 579 dt_t **pdtend; 579 580 580 581 d = NULL; 581 582 pdtend = &d; 582 583 for (int i = 0; i < elements->dim; i++) 583 584 { Expression *e = (Expression *)elements->data[i]; 584 585 585 586 pdtend = e->toDt(pdtend); 586 587 } 587 588 Type *t = type->toBasetype(); 588 589 589 590 switch (t->ty) 590 591 { 591 592 case Tsarray: 592 593 pdt = dtcat(pdt, d); 593 594 break; 594 595 595 596 case Tpointer: 596 597 case Tarray: 597 598 if (t->ty == Tarray) 598 dt dword(pdt, elements->dim);599 dtsize_t(pdt, elements->dim); 599 600 if (d) 600 601 { 601 602 // Create symbol, and then refer to it 602 603 Symbol *s; 603 604 s = static_sym(); 604 605 s->Sdt = d; 605 606 outdata(s); 606 607 607 608 dtxoff(pdt, s, 0, TYnptr); 608 609 } 609 610 else 610 dt dword(pdt, 0);611 dtsize_t(pdt, 0); 611 612 612 613 break; 613 614 614 615 default: 615 616 assert(0); 616 617 } 617 618 return pdt; 618 619 } 619 620 620 621 dt_t **StructLiteralExp::toDt(dt_t **pdt) 621 622 { 622 623 Array dts; 623 624 unsigned i; 624 625 unsigned j; 625 626 dt_t *dt; 626 627 dt_t *d; 627 628 unsigned offset; 628 629 629 630 //printf("StructLiteralExp::toDt() %s)\n", toChars()); 630 631 dts.setDim(sd->fields.dim); … … 770 772 return pdt; 771 773 } 772 774 #ifdef DEBUG 773 775 printf("VarExp::toDt(), kind = %s\n", var->kind()); 774 776 #endif 775 777 error("non-constant expression %s", toChars()); 776 778 pdt = dtnzeros(pdt, 1); 777 779 return pdt; 778 780 } 779 781 780 782 /* ================================================================= */ 781 783 782 784 // Generate the data for the static initializer. 783 785 784 786 void ClassDeclaration::toDt(dt_t **pdt) 785 787 { 786 788 //printf("ClassDeclaration::toDt(this = '%s')\n", toChars()); 787 789 788 790 // Put in first two members, the vtbl[] and the monitor 789 791 dtxoff(pdt, toVtblSymbol(), 0, TYnptr); 790 dt dword(pdt, 0); // monitor792 dtsize_t(pdt, 0); // monitor 791 793 792 794 // Put in the rest 793 795 toDt2(pdt, this); 794 796 795 797 //printf("-ClassDeclaration::toDt(this = '%s')\n", toChars()); 796 798 } 797 799 798 800 void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd) 799 801 { 800 802 unsigned offset; 801 803 unsigned i; 802 804 dt_t *dt; 803 805 unsigned csymoffset; 804 806 805 807 #define LOG 0 806 808 807 809 #if LOG 808 810 printf("ClassDeclaration::toDt2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); 809 811 #endif 810 812 if (baseClass)
