Changeset 768
- Timestamp:
- 11/28/10 23:17:41 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cg87.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cgcod.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cod1.c (modified) (5 diffs)
- branches/dmd-1.x/src/backend/cod2.c (modified) (7 diffs)
- branches/dmd-1.x/src/backend/cod3.c (modified) (3 diffs)
- branches/dmd-1.x/src/backend/cod4.c (modified) (4 diffs)
- branches/dmd-1.x/src/backend/code.h (modified) (1 diff)
- branches/dmd-1.x/src/backend/el.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/gloop.c (modified) (1 diff)
- branches/dmd-1.x/src/e2ir.c (modified) (1 diff)
- branches/dmd-1.x/src/msc.c (modified) (1 diff)
- branches/dmd-1.x/src/mtype.h (modified) (1 diff)
- branches/dmd-1.x/src/template.c (modified) (1 diff)
- trunk/src/backend/cg87.c (modified) (1 diff)
- trunk/src/backend/cgcod.c (modified) (1 diff)
- trunk/src/backend/cod1.c (modified) (5 diffs)
- trunk/src/backend/cod2.c (modified) (7 diffs)
- trunk/src/backend/cod3.c (modified) (3 diffs)
- trunk/src/backend/cod4.c (modified) (4 diffs)
- trunk/src/backend/code.h (modified) (1 diff)
- trunk/src/backend/el.c (modified) (1 diff)
- trunk/src/backend/gloop.c (modified) (1 diff)
- trunk/src/e2ir.c (modified) (1 diff)
- trunk/src/msc.c (modified) (1 diff)
- trunk/src/mtype.h (modified) (1 diff)
- trunk/src/template.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cg87.c
r767 r768 2045 2045 cs.Iop = op1; 2046 2046 c2 = getlvalue(&cs, e->E1, 0); 2047 2047 cs.IEVoffset1 += sz; 2048 2048 cs.Irm |= modregrm(0, op2, 0); 2049 2049 c2 = cat(c2, makesure87(e->E2, sz, 0, 0)); 2050 2050 c2 = gen(c2, &cs); 2051 2051 c2 = genfwait(c2); 2052 2052 c2 = cat(c2, makesure87(e->E2, 0, 1, 0)); 2053 2053 } 2054 2054 else 2055 2055 { 2056 2056 c2 = loadea(e->E1,&cs,op1,op2,sz,0,0); 2057 2057 c2 = genfwait(c2); 2058 2058 } 2059 2059 if (fxch) 2060 2060 c2 = genf2(c2,0xD9,0xC8 + 1); // FXCH ST(1) 2061 2061 cs.IEVoffset1 -= sz; 2062 2062 gen(c2, &cs); 2063 2063 if (fxch) 2064 2064 genf2(c2,0xD9,0xC8 + 1); // FXCH ST(1) 2065 #if LNGDBLSIZE == 12 2066 if (op1 == 0xDB) 2067 { 2068 cs.Iop = 0xC7; // MOV EA+10,0 2069 NEWREG(cs.Irm, 0); 2070 cs.IEV1.sp.Voffset += 10; 2071 cs.IFL2 = FLconst; 2072 cs.IEV2.Vint = 0; 2073 cs.Iflags |= CFopsize; 2074 c2 = gen(c2, &cs); 2075 cs.IEVoffset1 += 12; 2076 c2 = gen(c2, &cs); // MOV EA+22,0 2077 } 2078 #endif 2065 if (tysize[TYldouble] == 12) 2066 { 2067 if (op1 == 0xDB) 2068 { 2069 cs.Iop = 0xC7; // MOV EA+10,0 2070 NEWREG(cs.Irm, 0); 2071 cs.IEV1.sp.Voffset += 10; 2072 cs.IFL2 = FLconst; 2073 cs.IEV2.Vint = 0; 2074 cs.Iflags |= CFopsize; 2075 c2 = gen(c2, &cs); 2076 cs.IEVoffset1 += 12; 2077 c2 = gen(c2, &cs); // MOV EA+22,0 2078 } 2079 } 2079 2080 if (tysize[TYldouble] == 16) 2080 2081 { 2081 if (op1 == 0xDB)2082 {2083 cs.Iop = 0xC7; // MOV EA+10,02084 NEWREG(cs.Irm, 0);2085 cs.IEV1.sp.Voffset += 10;2086 cs.IFL2 = FLconst;2087 cs.IEV2.Vint = 0;2088 cs.Iflags |= CFopsize;2089 c2 = gen(c2, &cs);2090 2091 cs.IEV1.sp.Voffset += 2;2092 cs.Iflags &= ~CFopsize;2093 c2 = gen(c2, &cs);2094 2095 cs.IEVoffset1+= 14;2096 cs.Iflags |= CFopsize;2097 c2 = gen(c2, &cs);2098 2099 cs.IEV1.sp.Voffset += 2;2100 cs.Iflags &= ~CFopsize;2101 c2 = gen(c2, &cs);2102 }2082 if (op1 == 0xDB) 2083 { 2084 cs.Iop = 0xC7; // MOV EA+10,0 2085 NEWREG(cs.Irm, 0); 2086 cs.IEV1.sp.Voffset += 10; 2087 cs.IFL2 = FLconst; 2088 cs.IEV2.Vint = 0; 2089 cs.Iflags |= CFopsize; 2090 c2 = gen(c2, &cs); 2091 2092 cs.IEV1.sp.Voffset += 2; 2093 cs.Iflags &= ~CFopsize; 2094 c2 = gen(c2, &cs); 2095 2096 cs.IEV1.sp.Voffset += 14; 2097 cs.Iflags |= CFopsize; 2098 c2 = gen(c2, &cs); 2099 2100 cs.IEV1.sp.Voffset += 2; 2101 cs.Iflags &= ~CFopsize; 2102 c2 = gen(c2, &cs); 2103 } 2103 2104 } 2104 2105 c2 = genfwait(c2); 2105 2106 freenode(e->E1); 2106 2107 return cat3(c1,c2,fixresult_complex87(e,mST01 | mPSW,pretregs)); 2107 2108 } 2108 2109 2109 2110 /******************************* 2110 2111 * Perform an assignment while converting to integral type, 2111 2112 * i.e. handle (e1 = (int) e2) 2112 2113 */ 2113 2114 2114 2115 code *cnvteq87(elem *e,regm_t *pretregs) 2115 2116 { 2116 2117 regm_t retregs; 2117 2118 code *c1,*c2; 2118 2119 code cs; 2119 2120 unsigned op1; 2120 2121 unsigned op2; 2121 2122 tym_t ty1; 2122 2123 branches/dmd-1.x/src/backend/cgcod.c
r767 r768 1534 1534 case TYint: 1535 1535 case TYuint: 1536 1536 #if JHANDLE 1537 1537 case TYjhandle: 1538 1538 #endif 1539 1539 case TYnullptr: 1540 1540 case TYnptr: 1541 1541 case TYsptr: 1542 1542 case TYcptr: 1543 1543 return mAX; 1544 1544 1545 1545 case TYfloat: 1546 1546 case TYifloat: 1547 1547 if (I64) 1548 1548 return mXMM0; 1549 1549 if (config.exe & EX_flat) 1550 1550 return mST0; 1551 1551 case TYlong: 1552 1552 case TYulong: 1553 1553 case TYdchar: 1554 if ( I32)1554 if (!I16) 1555 1555 return mAX; 1556 1556 case TYfptr: 1557 1557 case TYhptr: 1558 1558 return mDX | mAX; 1559 1559 1560 1560 case TYcent: 1561 1561 case TYucent: 1562 1562 assert(I64); 1563 1563 return mDX | mAX; 1564 1564 1565 1565 case TYvptr: 1566 1566 return mDX | mBX; 1567 1567 1568 1568 case TYdouble: 1569 1569 case TYdouble_alias: 1570 1570 case TYidouble: 1571 1571 if (I64) 1572 1572 return mXMM0; 1573 1573 if (config.exe & EX_flat) 1574 1574 return mST0; branches/dmd-1.x/src/backend/cod1.c
r767 r768 171 171 if (index == -1) 172 172 rm = modregrm(0,0,5); 173 173 else 174 174 { 175 175 rm = modregrm(0,0,4); 176 176 sib = modregrm(ss,index & 7,5); 177 177 if (index & 8) 178 178 rex |= REX_X; 179 179 } 180 180 } 181 181 else if (index == -1) 182 182 { 183 183 if (base == SP) 184 184 { 185 185 rm = modregrm(2,0,4); 186 186 sib = modregrm(0,4,SP); 187 187 } 188 188 else 189 189 { rm = modregrm(2,0,base & 7); 190 190 if (base & 8) 191 rex |= REX_B; 191 { rex |= REX_B; 192 if (base == R12) 193 { 194 rm = modregrm(2,0,4); 195 sib = modregrm(0,4,4); 196 } 197 } 192 198 } 193 199 } 194 200 else 195 201 { 196 202 rm = modregrm(2,0,4); 197 203 sib = modregrm(ss,index & 7,base & 7); 198 204 if (index & 8) 199 205 rex |= REX_X; 200 206 if (base & 8) 201 207 rex |= REX_B; 202 208 } 203 209 } 204 210 else 205 211 { 206 212 // -1 AX CX DX BX SP BP SI DI 207 213 static unsigned char EA16rm[9][9] = 208 214 { 209 215 { 0x06,0x09,0x09,0x09,0x87,0x09,0x86,0x84,0x85, }, // -1 210 216 { 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, }, // AX 211 217 { 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, }, // CX 212 218 { 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, }, // DX 213 219 { 0x87,0x09,0x09,0x09,0x09,0x09,0x09,0x80,0x81, }, // BX 214 220 { 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, }, // SP 215 221 { 0x86,0x09,0x09,0x09,0x09,0x09,0x09,0x82,0x83, }, // BP 216 222 { 0x84,0x09,0x09,0x09,0x80,0x09,0x82,0x09,0x09, }, // SI 217 223 { 0x85,0x09,0x09,0x09,0x81,0x09,0x83,0x09,0x09, } // DI 218 224 }; 219 225 220 226 assert(scale == 1); 221 227 rm = EA16rm[base + 1][index + 1]; 222 228 assert(rm != 9); 223 229 } 224 230 c->Irm = rm; 225 231 c->Isib = sib; 226 232 c->Irex = rex; 227 233 c->IFL1 = FLconst; 228 234 c->IEV1.Vuns = disp; 235 } 236 237 /********************************************* 238 * Build REX, modregrm and sib bytes 239 */ 240 241 unsigned buildModregrm(int mod, int reg, int rm) 242 { unsigned m; 243 if (I16) 244 m = modregrm(mod, reg, rm); 245 else 246 { 247 unsigned rex = 0; 248 if ((rm & 7) == SP && mod != 3) 249 m = (modregrm(0,4,SP) << 8) | modregrm(mod,reg & 7,4); 250 else 251 m = modregrm(mod,reg & 7,rm & 7); 252 if (reg & 8) 253 m |= REX_R << 16; 254 if (rm & 8) 255 m |= REX_B << 16; 256 } 257 return m; 229 258 } 230 259 231 260 /************************** 232 261 * For elems in regcon that don't match regconsave, 233 262 * clear the corresponding bit in regcon.cse.mval. 234 263 * Do same for regcon.immed. 235 264 */ 236 265 237 266 void andregcon(con_t *pregconsave) 238 267 { 239 268 regm_t m = ~1; 240 269 for (int i = 0; i < REGMAX; i++) 241 270 { if (pregconsave->cse.value[i] != regcon.cse.value[i]) 242 271 regcon.cse.mval &= m; 243 272 if (pregconsave->immed.value[i] != regcon.immed.value[i]) 244 273 regcon.immed.mval &= m; 245 274 m <<= 1; 246 275 m |= 1; 247 276 } 248 277 //printf("regcon.cse.mval = x%x, regconsave->mval = x%x ",regcon.cse.mval,pregconsave->cse.mval); … … 860 889 break; 861 890 default: 862 891 #ifdef DEBUG 863 892 elem_print(e); 864 893 #endif 865 894 assert(0); 866 895 } 867 896 e1ty = tybasic(e1->Ety); 868 897 if (e1isadd) 869 898 { e12 = e1->E2; 870 899 e11 = e1->E1; 871 900 } 872 901 873 902 /* First see if we can replace *(e+&v) with 874 903 * MOV idxreg,e 875 904 * EA = [ES:] &v+idxreg 876 905 */ 877 906 878 907 if (e1isadd && 879 908 e12->Eoper == OPrelconst && 909 !(I64 && config.flags3 & CFG3pic) && 880 910 (f = el_fl(e12)) != FLfardata && 881 911 e1->Ecount == e1->Ecomsub && 882 912 (!e1->Ecount || (~keepmsk & ALLREGS & mMSW) || (e1ty != TYfptr && e1ty != TYhptr)) && 883 913 tysize(e11->Ety) == REGSIZE 884 914 ) 885 915 { unsigned char t; /* component of r/m field */ 886 916 int ss; 887 917 int ssi; 888 918 889 919 /*assert(datafl[f]);*/ /* what if addr of func? */ 890 920 if (!I16) 891 921 { /* Any register can be an index register */ 892 922 regm_t idxregs = allregs & ~keepmsk; 893 923 assert(idxregs); 894 924 895 925 /* See if e1->E1 can be a scaled index */ 896 926 ss = isscaledindex(e11); 897 927 if (ss) 898 928 { 899 929 /* Load index register with result of e11->E1 */ … … 942 972 assert(!stackfl[f]); 943 973 pcs->Irm = modregrm(2,0,4); 944 974 pcs->Isib = modregrm(ss1,reg & 7,reg & 7); 945 975 if (reg & 8) 946 976 pcs->Irex |= REX_X | REX_B; 947 977 } 948 978 else 949 979 { int rbase; 950 980 unsigned r; 951 981 952 982 scratchm = ALLREGS & ~keepmsk; 953 983 c = cat(c,allocreg(&scratchm,&r,TYint)); 954 984 955 985 if (ssflags & SSFLnobase1) 956 986 { t = 0; 957 987 rbase = 5; 958 988 } 959 989 else 960 990 { t = 0; 961 991 rbase = reg; 962 if (rbase == BP )992 if (rbase == BP || rbase == R13) 963 993 { static unsigned imm32[4] = {1+1,2+1,4+1,8+1}; 964 994 965 995 // IMUL r,BP,imm32 966 c = genc2(c,0x69,modregxrm (3,r,BP),imm32[ss1]);996 c = genc2(c,0x69,modregxrmx(3,r,rbase),imm32[ss1]); 967 997 goto L7; 968 998 } 969 999 } 970 1000 971 1001 c = gen2sib(c,0x8D,modregxrm(t,r,4),modregrm(ss1,reg & 7,rbase & 7)); 972 1002 if (reg & 8) 973 1003 code_orrex(c, REX_X); 974 1004 if (rbase & 8) 975 1005 code_orrex(c, REX_B); 976 1006 if (I64) 977 1007 code_orrex(c, REX_W); 978 1008 979 1009 if (ssflags & SSFLnobase1) 980 1010 { code_last(c)->IFL1 = FLconst; 981 1011 code_last(c)->IEV1.Vuns = 0; 982 1012 } 983 1013 L7: 984 1014 if (ssflags & SSFLnobase) 985 1015 { t = stackfl[f] ? 2 : 0; 986 1016 rbase = 5; … … 3219 3249 if (!(config.exe & EX_flat)) 3220 3250 { seg = CFes; 3221 3251 retregs |= mES; 3222 3252 } 3223 3253 c1 = codelem(e1,&retregs,FALSE); 3224 3254 break; 3225 3255 default: 3226 3256 #ifdef DEBUG 3227 3257 elem_print(e1); 3228 3258 #endif 3229 3259 assert(0); 3230 3260 } 3231 3261 reg = findreglsw(retregs); 3232 3262 rm = I16 ? regtorm[reg] : regtorm32[reg]; 3233 3263 if (op16) 3234 3264 seg |= CFopsize; // operand size 3235 3265 if (npushes <= 4) 3236 3266 { 3237 3267 assert(!doneoff); 3238 3268 for (c2 = CNIL; npushes > 1; npushes--) 3239 { c2 = genc1(c2,0xFF, modregrmx(2,6,rm),FLconst,pushsize * (npushes - 1)); // PUSH [reg]3269 { c2 = genc1(c2,0xFF,buildModregrm(2,6,rm),FLconst,pushsize * (npushes - 1)); // PUSH [reg] 3240 3270 code_orflag(c2,seg); 3241 3271 genadjesp(c2,pushsize); 3242 3272 } 3243 c3 = gen2(CNIL,0xFF, modregrmx(0,6,rm)); // PUSH [reg]3273 c3 = gen2(CNIL,0xFF,buildModregrm(0,6,rm)); // PUSH [reg] 3244 3274 c3->Iflags |= seg; 3245 3275 genadjesp(c3,pushsize); 3246 3276 ce = cat4(cc,c1,c2,c3); 3247 3277 } 3248 3278 else if (sz) 3249 3279 { int size; 3250 3280 3251 3281 c2 = getregs_imm(mCX | retregs); 3252 3282 /* MOV CX,sz/2 */ 3253 3283 c2 = movregconst(c2,CX,npushes,0); 3254 3284 if (!doneoff) 3255 3285 { /* This disgusting thing should be done when */ 3256 3286 /* reg is loaded. Too lazy to fix it now. */ 3257 3287 /* ADD reg,sz-2 */ 3258 3288 c2 = genc2(c2,0x81,grex | modregrmx(3,0,reg),sz-pushsize); 3259 3289 } 3260 c3 = gen2(CNIL,0xFF, modregrmx(0,6,rm)); // PUSH [reg]3290 c3 = gen2(CNIL,0xFF,buildModregrm(0,6,rm)); // PUSH [reg] 3261 3291 c3->Iflags |= seg | CFtarg2; 3262 genc2(c3,0x81,grex | modregrmx(3,5,reg),pushsize); // SUB reg,23292 genc2(c3,0x81,grex | buildModregrm(3,5,reg),pushsize); // SUB reg,2 3263 3293 size = ((seg & CFSEG) ? -8 : -7) - op16; 3264 3294 if (code_next(c3)->Iop != 0x81) 3265 3295 size++; 3266 3296 //genc2(c3,0xE2,0,size); // LOOP .-7 or .-8 3267 3297 genjmp(c3,0xE2,FLcode,(block *)c3); // LOOP c3 3268 3298 regimmed_set(CX,0); 3269 3299 genadjesp(c3,sz); 3270 3300 ce = cat4(cc,c1,c2,c3); 3271 3301 } 3272 3302 else 3273 3303 ce = cat(cc,c1); 3274 3304 stackpush += sz; 3275 3305 goto L2; 3276 3306 } 3277 3307 case OPind: 3278 3308 if (!e->Ecount) /* if *e1 */ 3279 3309 { if (sz <= REGSIZE) 3280 3310 { // Watch out for single byte quantities being up 3281 3311 // against the end of a segment or in memory-mapped I/O 3282 3312 if (!(config.exe & EX_flat) && szb == 1) … … 3676 3706 { 3677 3707 regm = allregs; 3678 3708 if (e->Eoper == OPconst) 3679 3709 { /* TRUE: OR SP,SP (SP is never 0) */ 3680 3710 /* FALSE: CMP SP,SP (always equal) */ 3681 3711 c = genregs(CNIL,(boolres(e)) ? 0x09 : 0x39,SP,SP); 3682 3712 if (I64) 3683 3713 code_orrex(c, REX_W); 3684 3714 } 3685 3715 else if (sz <= REGSIZE) 3686 3716 { 3687 3717 if (!I16 && (tym == TYfloat || tym == TYifloat)) 3688 3718 { c = allocreg(®m,®,TYoffset); /* get a register */ 3689 3719 ce = loadea(e,&cs,0x8B,reg,0,0,0); // MOV reg,data 3690 3720 c = cat(c,ce); 3691 3721 ce = gen2(CNIL,0xD1,modregrmx(3,4,reg)); /* SHL reg,1 */ 3692 3722 c = cat(c,ce); 3693 3723 } 3694 3724 else 3695 3725 { cs.IFL2 = FLconst; 3696 cs.IEV2.V int = 0;3726 cs.IEV2.Vsize_t = 0; 3697 3727 op = (sz == 1) ? 0x80 : 0x81; 3698 3728 c = loadea(e,&cs,op,7,0,0,0); /* CMP EA,0 */ 3699 3729 3700 3730 // Convert to TEST instruction if EA is a register 3701 3731 // (to avoid register contention on Pentium) 3702 3732 if ((c->Iop & ~1) == 0x38 && 3703 3733 (c->Irm & modregrm(3,0,0)) == modregrm(3,0,0) 3704 3734 ) 3705 3735 { c->Iop = (c->Iop & 1) | 0x84; 3706 3736 code_newreg(c, c->Irm & 7); 3707 3737 if (c->Irex & REX_B) 3708 c->Irex = (c->Irex & ~REX_B) | REX_R; 3738 //c->Irex = (c->Irex & ~REX_B) | REX_R; 3739 c->Irex |= REX_R; 3709 3740 } 3710 3741 } 3711 3742 } 3712 3743 else if (sz < 8) 3713 3744 { 3714 3745 c = allocreg(®m,®,TYoffset); /* get a register */ 3715 3746 if (I32) // it's a 48 bit pointer 3716 3747 ce = loadea(e,&cs,0x0FB7,reg,REGSIZE,0,0); /* MOVZX reg,data+4 */ 3717 3748 else 3718 3749 { ce = loadea(e,&cs,0x8B,reg,REGSIZE,0,0); /* MOV reg,data+2 */ 3719 3750 if (tym == TYfloat || tym == TYifloat) // dump sign bit 3720 3751 gen2(ce,0xD1,modregrm(3,4,reg)); /* SHL reg,1 */ 3721 3752 } 3722 3753 c = cat(c,ce); 3723 3754 ce = loadea(e,&cs,0x0B,reg,0,regm,0); /* OR reg,data */ 3724 3755 c = cat(c,ce); 3725 3756 } 3726 3757 else if (sz == 8 || (I64 && sz == 2 * REGSIZE && !tyfloating(tym))) 3727 3758 { 3728 3759 c = allocreg(®m,®,TYoffset); /* get a register */ branches/dmd-1.x/src/backend/cod2.c
r767 r768 226 226 else if (sz == 4) 227 227 value &= 0xFFFFFFFF; 228 228 if (reghasvalue(byte ? BYTEREGS : ALLREGS,value,®)) 229 229 goto L11; 230 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 if (I64 && byte && reg >= 4) 247 cs.Irex |= REX; 246 248 L10: 247 249 cs.Iop = op1 ^ byte; 248 250 cs.Iflags |= word | CFpsw; 249 251 freenode(e1); 250 252 freenode(e2); 251 253 return gen(c,&cs); 252 254 } 253 255 } 254 256 255 257 // Look for possible uses of LEA 256 258 if (e->Eoper == OPadd && 257 259 !(*pretregs & mPSW) && /* flags aren't set by LEA */ 258 260 !nest && // could cause infinite recursion if e->Ecount 259 261 (sz == REGSIZE || (I64 && sz == 4))) // far pointers aren't handled 260 262 { 261 263 unsigned rex = (sz == 8) ? REX_W : 0; 262 264 263 265 // Handle the case of (e + &var) 264 266 int e1oper = e1->Eoper; 265 267 if ((e2oper == OPrelconst && (config.target_cpu >= TARGET_Pentium || (!e2->Ecount && stackfl[el_fl(e2)]))) … … 571 573 rretregs &= BYTEREGS; 572 574 573 575 cr = scodelem(e2,&rretregs,retregs,TRUE); /* get rvalue */ 574 576 rreg = (tysize[ty2] > REGSIZE) ? findreglsw(rretregs) : findreg(rretregs); 575 577 c = CNIL; 576 578 if (numwords == 1) /* ADD reg,rreg */ 577 579 { 578 580 /* reverse operands to avoid moving around the segment value */ 579 581 if (tysize[ty2] > REGSIZE) 580 582 { c = cat(c,getregs(rretregs)); 581 583 c = genregs(c,op1,rreg,reg); 582 584 retregs = rretregs; /* reverse operands */ 583 585 } 584 586 else 585 587 { c = genregs(c,op1,reg,rreg); 586 588 if (!I16 && *pretregs & mPSW) 587 589 c->Iflags |= word; 588 590 } 589 591 if (I64 && sz == 8) 590 592 code_orrex(c, REX_W); 593 if (I64 && byte && reg >= 4) 594 code_orrex(c, REX); 591 595 } 592 596 else /* numwords == 2 */ /* ADD lsreg,lsrreg */ 593 597 { 594 598 reg = findreglsw(retregs); 595 599 rreg = findreglsw(rretregs); 596 600 c = genregs(c,op1,reg,rreg); 597 601 if (e->Eoper == OPadd || e->Eoper == OPmin) 598 602 code_orflag(c,CFpsw); 599 603 reg = findregmsw(retregs); 600 604 rreg = findregmsw(rretregs); 601 605 if (!(e2oper == OPu16_32 && // if second operand is 0 602 606 (op2 == 0x0B || op2 == 0x33)) // and OR or XOR 603 607 ) 604 608 genregs(c,op2,reg,rreg); // ADC msreg,msrreg 605 609 } 606 610 break; 607 611 608 612 case OPrelconst: 609 613 if (sz != REGSIZE) 610 614 goto L2; … … 3203 3207 3204 3208 /********************************* 3205 3209 * Generate code for memset(s,val,n) intrinsic. 3206 3210 * (s OPmemset (n OPparam val)) 3207 3211 */ 3208 3212 3209 3213 #if 1 3210 3214 code *cdmemset(elem *e,regm_t *pretregs) 3211 3215 { code *c1,*c2,*c3 = NULL,*c4; 3212 3216 regm_t retregs1; 3213 3217 regm_t retregs2; 3214 3218 regm_t retregs3; 3215 3219 unsigned reg,vreg; 3216 3220 tym_t ty1; 3217 3221 elem *e2,*e1; 3218 3222 int segreg; 3219 3223 unsigned remainder; 3220 3224 targ_uns numbytes,numwords; 3221 3225 int op; 3222 3226 targ_size_t value; 3227 unsigned m; 3223 3228 3224 3229 //printf("cdmemset(*pretregs = x%x)\n", *pretregs); 3225 3230 e1 = e->E1; 3226 3231 e2 = e->E2; 3227 3232 assert(e2->Eoper == OPparam); 3228 3233 3229 3234 unsigned char rex = I64 ? REX_W : 0; 3230 3235 3231 3236 if (e2->E2->Eoper == OPconst) 3232 3237 { 3233 3238 value = el_tolong(e2->E2); 3234 3239 value &= 0xFF; 3235 3240 value |= value << 8; 3236 3241 value |= value << 16; 3237 3242 value |= value << 32; 3238 3243 } 3239 3244 3240 3245 if (e2->E1->Eoper == OPconst) 3241 3246 { 3242 3247 numbytes = el_tolong(e2->E1); 3243 3248 if (numbytes <= REP_THRESHOLD && 3244 3249 !I16 && // doesn't work for 16 bits 3245 3250 e2->E2->Eoper == OPconst) 3246 3251 { 3247 3252 targ_uns offset = 0; 3248 3253 retregs1 = *pretregs; 3249 3254 if (!retregs1) 3250 3255 retregs1 = ALLREGS; 3251 3256 c1 = codelem(e->E1,&retregs1,FALSE); 3252 3257 reg = findreg(retregs1); 3253 3258 if (e2->E2->Eoper == OPconst) 3254 3259 { 3260 unsigned m = buildModregrm(0,0,reg); 3255 3261 switch (numbytes) 3256 3262 { 3257 3263 case 4: // MOV [reg],imm32 3258 c3 = genc2(CNIL,0xC7,m odregrmx(0,0,reg),value);3264 c3 = genc2(CNIL,0xC7,m,value); 3259 3265 goto fixres; 3260 3266 case 2: // MOV [reg],imm16 3261 c3 = genc2(CNIL,0xC7,m odregrmx(0,0,reg),value);3267 c3 = genc2(CNIL,0xC7,m,value); 3262 3268 c3->Iflags = CFopsize; 3263 3269 goto fixres; 3264 3270 case 1: // MOV [reg],imm8 3265 c3 = genc2(CNIL,0xC6,m odregrmx(0,0,reg),value);3271 c3 = genc2(CNIL,0xC6,m,value); 3266 3272 goto fixres; 3267 3273 } 3268 3274 } 3269 3275 3270 3276 c1 = regwithvalue(c1, BYTEREGS & ~retregs1, value, &vreg, I64 ? 64 : 0); 3271 3277 freenode(e2->E2); 3272 3278 freenode(e2); 3273 3279 3280 m = (rex << 16) | buildModregrm(2,vreg,reg); 3274 3281 while (numbytes >= REGSIZE) 3275 3282 { // MOV dword ptr offset[reg],vreg 3276 c2 = gen2(CNIL,0x89, (rex << 16) | modregxrmx(2,vreg,reg));3283 c2 = gen2(CNIL,0x89,m); 3277 3284 c2->IEVoffset1 = offset; 3278 3285 c2->IFL1 = FLconst; 3279 3286 numbytes -= REGSIZE; 3280 3287 offset += REGSIZE; 3281 3288 c3 = cat(c3,c2); 3282 3289 } 3283 3290 if (numbytes & 4) 3284 3291 { // MOV dword ptr offset[reg],vreg 3285 c2 = gen2(CNIL,0x89,m odregxrmx(2,vreg,reg));3292 c2 = gen2(CNIL,0x89,m); 3286 3293 c2->IEVoffset1 = offset; 3287 3294 c2->IFL1 = FLconst; 3288 3295 offset += 4; 3289 3296 c3 = cat(c3,c2); 3290 3297 } 3291 3298 if (numbytes & 2) 3292 3299 { // MOV word ptr offset[reg],vreg 3293 c2 = gen2(CNIL,0x89,m odregxrmx(2,vreg,reg));3300 c2 = gen2(CNIL,0x89,m); 3294 3301 c2->IEVoffset1 = offset; 3295 3302 c2->IFL1 = FLconst; 3296 3303 c2->Iflags = CFopsize; 3297 3304 offset += 2; 3298 3305 c3 = cat(c3,c2); 3299 3306 } 3300 3307 if (numbytes & 1) 3301 3308 { // MOV byte ptr offset[reg],vreg 3302 c2 = gen2(CNIL,0x88,m odregxrmx(2,vreg,reg));3309 c2 = gen2(CNIL,0x88,m); 3303 3310 c2->IEVoffset1 = offset; 3304 3311 c2->IFL1 = FLconst; 3312 if (I64 && vreg >= 4) 3313 c2->Irex |= REX; 3305 3314 c3 = cat(c3,c2); 3306 3315 } 3307 3316 fixres: 3308 3317 return cat3(c1,c3,fixresult(e,retregs1,pretregs)); 3309 3318 } 3310 3319 } 3311 3320 3312 3321 // Get nbytes into CX 3313 3322 retregs2 = mCX; 3314 3323 if (!I16 && e2->E1->Eoper == OPconst && e2->E2->Eoper == OPconst) 3315 3324 { 3316 3325 remainder = numbytes & (4 - 1); 3317 3326 numwords = numbytes / 4; // number of words 3318 3327 op = 0xAB; // moving by words 3319 3328 c1 = getregs(mCX); 3320 3329 c1 = movregconst(c1,CX,numwords,I64?64:0); // # of bytes/words 3321 3330 } 3322 3331 else 3323 3332 { 3324 3333 remainder = 0; … … 3365 3374 if (*pretregs) // if need return value 3366 3375 { c3 = getregs(mBX); 3367 3376 c3 = genmovreg(c3,BX,DI); 3368 3377 code_orrex(c3,rex); 3369 3378 } 3370 3379 3371 3380 c3 = cat(c3,getregs(mDI | mCX)); 3372 3381 if (I16 && config.flags4 & CFG4speed) // if speed optimization 3373 3382 { 3374 3383 c3 = cat(c3,getregs(mAX)); 3375 3384 c3 = gen2(c3,0x8A,modregrm(3,AH,AL)); // MOV AH,AL 3376 3385 gen2(c3,0xD1,modregrm(3,5,CX)); // SHR CX,1 3377 3386 gen1(c3,0xF3); // REP 3378 3387 gen1(c3,0xAB); // STOSW 3379 3388 gen2(c3,0x11,modregrm(3,CX,CX)); // ADC CX,CX 3380 3389 op = 0xAA; 3381 3390 } 3382 3391 3383 3392 c3 = gen1(c3,0xF3); // REP 3384 3393 gen1(c3,op); // STOSD 3394 m = buildModregrm(2,AX,reg); 3385 3395 if (remainder & 4) 3386 3396 { 3387 3397 code *ctmp; 3388 ctmp = gen2(CNIL,0x89,m odregrmx(2,AX,reg));3398 ctmp = gen2(CNIL,0x89,m); 3389 3399 ctmp->IFL1 = FLconst; 3390 3400 c3 = cat(c3,ctmp); 3391 3401 } 3392 3402 if (remainder & 2) 3393 3403 { 3394 3404 code *ctmp; 3395 ctmp = gen2(CNIL,0x89,m odregrmx(2,AX,reg));3405 ctmp = gen2(CNIL,0x89,m); 3396 3406 ctmp->Iflags = CFopsize; 3397 3407 ctmp->IEVoffset1 = remainder & 4; 3398 3408 ctmp->IFL1 = FLconst; 3399 3409 c3 = cat(c3,ctmp); 3400 3410 } 3401 3411 if (remainder & 1) 3402 3412 { 3403 3413 code *ctmp; 3404 ctmp = gen2(CNIL,0x88,m odregrmx(2,AX,reg));3414 ctmp = gen2(CNIL,0x88,m); 3405 3415 ctmp->IEVoffset1 = remainder & ~1; 3406 3416 ctmp->IFL1 = FLconst; 3407 3417 c3 = cat(c3,ctmp); 3408 3418 } 3409 3419 regimmed_set(CX,0); 3410 3420 return cat4(c1,c2,c3,fixresult(e,mES|mBX,pretregs)); 3411 3421 } 3412 3422 #else 3413 3423 // BUG: Pat made many improvements in the linux version, I need 3414 3424 // to verify they work for 16 bits and fold them in. -Walter 3415 3425 3416 3426 code *cdmemset(elem *e,regm_t *pretregs) 3417 3427 { code *c1,*c2,*c3 = NULL,*c4; 3418 3428 regm_t retregs1; 3419 3429 regm_t retregs2; 3420 3430 regm_t retregs3; 3421 3431 tym_t ty1; 3422 3432 elem *e2; 3423 3433 targ_size_t value; 3424 3434 … … 4143 4153 } 4144 4154 else 4145 4155 assert(0); 4146 4156 return cat4(c1,cg,c,fixresult(e,retregs,pretregs)); 4147 4157 } 4148 4158 4149 4159 /************************** 4150 4160 * Post increment and post decrement. 4151 4161 */ 4152 4162 4153 4163 code *cdpost(elem *e,regm_t *pretregs) 4154 4164 { code cs,*c1,*c2,*c3,*c4,*c5,*c6; 4155 4165 unsigned reg,op,byte; 4156 4166 tym_t tyml; 4157 4167 regm_t retregs,possregs,idxregs; 4158 4168 targ_int n; 4159 4169 elem *e2; 4160 4170 int sz; 4161 4171 int stackpushsave; 4162 4172 4173 //printf("cdpost(pretregs = %s)\n", regm_str(*pretregs)); 4163 4174 retregs = *pretregs; 4164 4175 op = e->Eoper; /* OPxxxx */ 4165 4176 if (retregs == 0) /* if nothing to return */ 4166 4177 return cdaddass(e,pretregs); 4167 4178 c4 = c5 = CNIL; 4168 4179 tyml = tybasic(e->E1->Ety); 4169 4180 sz = tysize[tyml]; 4170 4181 e2 = e->E2; 4171 4182 unsigned rex = (I64 && sz == 8) ? REX_W : 0; 4172 4183 4173 4184 if (tyfloating(tyml)) 4174 4185 { 4175 4186 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 4176 4187 return post87(e,pretregs); 4177 4188 #else 4178 4189 if (config.inline8087) 4179 4190 return post87(e,pretregs); 4180 4191 assert(sz <= 8); 4181 4192 c1 = getlvalue(&cs,e->E1,DOUBLEREGS); 4182 4193 freenode(e->E1); … … 4283 4294 // LEA reg,n[reg] // don't affect flags 4284 4295 int rm; 4285 4296 4286 4297 reg = cs.Irm & 7; 4287 4298 if (cs.Irex & REX_B) 4288 4299 reg |= 8; 4289 4300 cs.Iop = 0x85 ^ byte; 4290 4301 code_newreg(&cs, reg); 4291 4302 cs.Iflags |= CFpsw; 4292 4303 c2 = gen(NULL,&cs); // TEST reg,reg 4293 4304 4294 4305 // If lvalue is a register variable, we must mark it as modified 4295 4306 c3 = modEA(&cs); 4296 4307 4297 4308 n = e2->EV.Vint; 4298 4309 if (op == OPpostdec) 4299 4310 n = -n; 4300 4311 rm = reg; 4301 4312 if (I16) 4302 4313 rm = regtorm[reg]; 4303 c4 = genc1(NULL,0x8D,(rex << 16) | modregxrmx(2,reg,rm),FLconst,n); // LEA reg,n[reg]4314 c4 = genc1(NULL,0x8D,(rex << 16) | buildModregrm(2,reg,rm),FLconst,n); // LEA reg,n[reg] 4304 4315 return cat4(c1,c2,c3,c4); 4305 4316 } 4306 4317 else if (sz <= REGSIZE || tyfv(tyml)) 4307 4318 { code cs2; 4308 4319 4309 4320 cs.Iop = 0x8B ^ byte; 4310 4321 retregs = possregs & ~idxregs & *pretregs; 4311 4322 if (!tyfv(tyml)) 4312 4323 { if (retregs == 0) 4313 4324 retregs = possregs & ~idxregs; 4314 4325 } 4315 4326 else /* tyfv(tyml) */ 4316 4327 { if ((retregs &= mLSW) == 0) 4317 4328 retregs = mLSW & ~idxregs; 4318 4329 /* Can't use LES if the EA uses ES as a seg override */ 4319 4330 if (*pretregs & mES && (cs.Iflags & CFSEG) != CFes) 4320 4331 { cs.Iop = 0xC4; /* LES */ 4321 4332 c1 = cat(c1,getregs(mES)); /* allocate ES */ 4322 4333 } 4323 4334 } … … 4685 4696 4686 4697 /**************************************** 4687 4698 * Check to see if pointer is NULL. 4688 4699 */ 4689 4700 4690 4701 code *cdnullcheck(elem *e,regm_t *pretregs) 4691 4702 { regm_t retregs; 4692 4703 regm_t scratch; 4693 4704 unsigned reg; 4694 4705 code *c; 4695 4706 code *cs; 4696 4707 4697 4708 assert(!I16); 4698 4709 retregs = *pretregs; 4699 4710 if ((retregs & allregs) == 0) 4700 4711 retregs |= allregs; 4701 4712 c = codelem(e->E1,&retregs,FALSE); 4702 4713 scratch = allregs & ~retregs; 4703 4714 cs = allocreg(&scratch,®,TYint); 4704 4715 unsigned rex = I64 ? REX_W : 0; 4705 cs = genc1(cs,0x8B,(rex << 16) | modregxrmx(2,reg,findreg(retregs)),FLconst,0); // MOV reg,0[e]4716 cs = genc1(cs,0x8B,(rex << 16) | buildModregrm(2,reg,findreg(retregs)),FLconst,0); // MOV reg,0[e] 4706 4717 return cat3(c,cs,fixresult(e,retregs,pretregs)); 4707 4718 } 4708 4719 4709 4720 #endif // !SPP branches/dmd-1.x/src/backend/cod3.c
r767 r768 2299 2299 ADD p[ESP],d 2300 2300 For direct call: 2301 2301 JMP sfunc 2302 2302 For virtual call: 2303 2303 MOV EAX, p[ESP] EAX = this 2304 2304 MOV EAX, d2[EAX] EAX = this->vptr 2305 2305 JMP i[EAX] jump to virtual function 2306 2306 */ 2307 2307 unsigned reg = 0; 2308 2308 if ((targ_ptrdiff_t)d < 0) 2309 2309 { 2310 2310 d = -d; 2311 2311 reg = 5; // switch from ADD to SUB 2312 2312 } 2313 2313 if (thunkty == TYmfunc) 2314 2314 { // ADD ECX,d 2315 2315 c = CNIL; 2316 2316 if (d) 2317 2317 c = genc2(c,0x81,modregrm(3,reg,CX),d); 2318 2318 } 2319 else if (thunkty == TYjfunc )2319 else if (thunkty == TYjfunc || (I64 && thunkty == TYnfunc)) 2320 2320 { // ADD EAX,d 2321 2321 c = CNIL; 2322 2322 if (d) 2323 2323 c = genc2(c,0x81,modregrm(3,reg,I64 ? DI : AX),d); 2324 2324 } 2325 2325 else 2326 2326 { 2327 2327 c = genc(CNIL,0x81,modregrm(2,reg,4), 2328 2328 FLconst,p, // to this 2329 2329 FLconst,d); // ADD p[ESP],d 2330 2330 c->Isib = modregrm(0,4,SP); 2331 2331 } 2332 2332 if (I64) 2333 2333 c->Irex |= REX_W; 2334 2334 } 2335 2335 else 2336 2336 { 2337 2337 /* 2338 2338 Generate: 2339 2339 MOV BX,SP … … 3428 3428 config.target_cpu >= TARGET_80486) 3429 3429 { 3430 3430 c->Iop &= 1; 3431 3431 c->Irm = (rm & modregrm(3,0,7)) | (ereg << 3); 3432 3432 if (c->Irex & REX_B) 3433 3433 c->Irex |= REX_R; 3434 3434 if (!(c->Iflags & CFpsw) && !I16) 3435 3435 c->Iflags &= ~CFopsize; 3436 3436 goto L1; 3437 3437 } 3438 3438 3439 3439 /* Look for sign extended modregrm displacement, or 0 3440 3440 * displacement. 3441 3441 */ 3442 3442 3443 3443 if (((rm & 0xC0) == 0x80) && // it's a 16/32 bit disp 3444 3444 c->IFL1 == FLconst) // and it's a constant 3445 3445 { 3446 3446 a = c->IEVpointer1; 3447 3447 if (a == 0 && (rm & 7) != local_BPRM && // if 0[disp] 3448 !(local_BPRM == 5 && (rm & 7) == 4 && (c->Isib & 7) == BP && !(c->Irex & REX_B))3448 !(local_BPRM == 5 && (rm & 7) == 4 && (c->Isib & 7) == BP) 3449 3449 ) 3450 3450 c->Irm &= 0x3F; 3451 3451 else if (!I16) 3452 3452 { 3453 3453 if ((targ_size_t)(targ_schar)a == a) 3454 3454 c->Irm ^= 0xC0; /* do 8 sx */ 3455 3455 } 3456 3456 else if (((targ_size_t)(targ_schar)a & 0xFFFF) == (a & 0xFFFF)) 3457 3457 c->Irm ^= 0xC0; /* do 8 sx */ 3458 3458 } 3459 3459 3460 3460 /* Look for LEA reg,[ireg], replace with MOV reg,ireg */ 3461 3461 else if (op == 0x8D) 3462 3462 { rm = c->Irm & 7; 3463 3463 mod = c->Irm & modregrm(3,0,0); 3464 3464 if (mod == 0) 3465 3465 { 3466 3466 if (!I16) 3467 3467 { 3468 3468 switch (rm) … … 5257 5257 break; 5258 5258 case FLswitch: 5259 5259 case FLblockoff: 5260 5260 case FLlocalsize: 5261 5261 case FLframehandler: 5262 5262 case 0: 5263 5263 break; 5264 5264 case FLdatseg: 5265 5265 printf(" %d.%llx",c->IEVseg1,(unsigned long long)c->IEVpointer1); 5266 5266 break; 5267 5267 case FLauto: 5268 5268 case FLreg: 5269 5269 case FLdata: 5270 5270 case FLudata: 5271 5271 case FLpara: 5272 5272 case FLtmp: 5273 5273 case FLbprel: 5274 5274 case FLtlsdata: 5275 5275 printf(" sym='%s'",c->IEVsym1->Sident); 5276 5276 break; 5277 case FLextern: 5278 printf(" FLextern offset = %4d",(int)c->IEVoffset1); 5279 break; 5277 5280 default: 5278 5281 WRFL((enum FL)c->IFL1); 5279 5282 break; 5280 5283 } 5281 5284 } 5282 5285 } 5283 5286 if (ins & T) 5284 5287 { printf(" "); WRFL((enum FL)c->IFL2); 5285 5288 switch (c->IFL2) 5286 5289 { 5287 5290 case FLconst: 5288 5291 printf(" int = %4d",c->IEV2.Vuns); 5289 5292 break; 5290 5293 case FLblock: 5291 5294 printf(" block = %p",c->IEV2.Vblock); 5292 5295 break; 5293 5296 case FLswitch: 5294 5297 case FLblockoff: 5295 5298 case 0: 5296 5299 case FLlocalsize: branches/dmd-1.x/src/backend/cod4.c
r767 r768 346 346 if (!(retregs == 0 && 347 347 (e2oper == OPconst || e2oper == OPvar || e2oper == OPind)) 348 348 ) 349 349 return eq87(e,pretregs); 350 350 if (config.target_cpu >= TARGET_PentiumPro && 351 351 (e2oper == OPvar || e2oper == OPind) 352 352 ) 353 353 return eq87(e,pretregs); 354 354 if (tyml == TYldouble || tyml == TYildouble) 355 355 return eq87(e,pretregs); 356 356 } 357 357 358 358 unsigned sz = tysize[tyml]; // # of bytes to transfer 359 359 assert((int)sz > 0); 360 360 361 361 if (retregs == 0) /* if no return value */ 362 362 { int fl; 363 363 364 364 if ((e2oper == OPconst || /* if rvalue is a constant */ 365 365 e2oper == OPrelconst && 366 !(I64 && config.flags3 & CFG3pic) && 366 367 ((fl = el_fl(e2)) == FLdata || 367 368 fl==FLudata || fl == FLextern) && 368 369 !(e2->EV.sp.Vsym->ty() & mTYcs) 369 370 ) && 370 371 !evalinregister(e2) && 371 372 !e1->Ecount) /* and no CSE headaches */ 372 373 { 373 374 // Look for special case of (*p++ = ...), where p is a register variable 374 375 if (e1->Eoper == OPind && 375 376 ((e11 = e1->E1)->Eoper == OPpostinc || e11->Eoper == OPpostdec) && 376 377 e11->E1->Eoper == OPvar && 377 378 e11->E1->EV.sp.Vsym->Sfl == FLreg && 378 379 (!I16 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 379 380 ) 380 381 { 381 382 postinc = e11->E2->EV.Vint; 382 383 if (e11->Eoper == OPpostdec) 383 384 postinc = -postinc; 384 385 cl = getlvalue(&cs,e11,RMstore); 385 386 freenode(e11->E2); 386 387 } 387 388 else 388 389 { postinc = 0; 389 390 cl = getlvalue(&cs,e1,RMstore); 390 391 391 392 if (e2oper == OPconst && 392 393 config.flags4 & CFG4speed && 393 394 (config.target_cpu == TARGET_Pentium || 394 395 config.target_cpu == TARGET_PentiumMMX) && 395 396 (cs.Irm & 0xC0) == 0x80 396 397 ) 397 398 { 398 399 if (I64 && sz == 8 && e2->EV.Vpointer) 399 400 { 400 401 // MOV reg,imm64 401 402 // MOV EA,reg 402 403 regm_t rregm = allregs & ~idxregm(&cs); 403 404 unsigned reg; 404 cl = regwithvalue(cl,rregm,e2->EV.Vpointer,®, CFoffset64);405 cl = regwithvalue(cl,rregm,e2->EV.Vpointer,®,64); 405 406 cs.Iop = 0x89; 406 407 cs.Irm |= modregrm(0,reg & 7,0); 407 408 if (reg & 8) 408 409 cs.Irex |= REX_R; 409 410 c = gen(cl,&cs); 410 411 freenode(e2); 411 412 goto Lp; 412 413 } 413 414 if ((sz == REGSIZE || (I64 && sz == 4)) && e2->EV.Vint) 414 415 { 415 416 // MOV reg,imm 416 417 // MOV EA,reg 417 418 regm_t rregm = allregs & ~idxregm(&cs); 418 419 unsigned reg; 419 420 cl = regwithvalue(cl,rregm,e2->EV.Vint,®,0); 420 421 cs.Iop = 0x89; 421 422 cs.Irm |= modregrm(0,reg & 7,0); 422 423 if (reg & 8) 423 424 cs.Irex |= REX_R; 424 425 c = gen(cl,&cs); … … 475 476 else 476 477 { 477 478 assert(e2oper == OPconst); 478 479 cs.IFL2 = FLconst; 479 480 targ_size_t *p = (targ_size_t *) &(e2->EV); 480 481 cs.IEV2.Vsize_t = *p; 481 482 // Look for loading a register variable 482 483 if ((cs.Irm & 0xC0) == 0xC0) 483 484 { unsigned reg = cs.Irm & 7; 484 485 485 486 if (cs.Irex & REX_B) 486 487 reg |= 8; 487 488 if (I64 && sz == 8) 488 489 cl = movregconst(cl,reg,*p,CFoffset64); 489 490 else 490 491 cl = movregconst(cl,reg,*p,1 ^ (cs.Iop & 1)); 491 492 if (sz == 2 * REGSIZE) 492 493 { getlvalue_msw(&cs); 493 494 cl = movregconst(cl,cs.Irm & 7,p[1],0); 494 495 } 496 } 497 else if (I64 && sz == 8 && *p != *(unsigned *)p) 498 { 499 // MOV reg,imm64 500 // MOV EA,reg 501 regm_t rregm = allregs & ~idxregm(&cs); 502 unsigned reg; 503 cl = regwithvalue(cl,rregm,e2->EV.Vpointer,®,64); 504 cs.Iop = 0x89; 505 cs.Irm |= modregrm(0,reg & 7,0); 506 if (reg & 8) 507 cs.Irex |= REX_R; 508 c = gen(cl,&cs); 509 freenode(e2); 510 goto Lp; 495 511 } 496 512 else 497 513 { int regsize; 498 514 499 515 i = sz; 500 516 do 501 517 { regsize = REGSIZE; 502 518 retregs = (sz == 1) ? BYTEREGS : allregs; 503 519 if (i >= 4 && I16 && I386) 504 520 { 505 521 regsize = 4; 506 522 cs.Iflags |= CFopsize; // use opsize to do 32 bit operation 507 523 } 508 524 else 509 525 { 510 526 if (reghasvalue(retregs,*p,®)) 511 527 { 512 528 cs.Iop = (cs.Iop & 1) | 0x88; 513 529 cs.Irm |= modregrm(0,reg & 7,0); // MOV EA,reg 514 530 if (reg & 8) … … 673 689 } 674 690 if (e1->Ecount || /* if lvalue is a CSE or */ 675 691 regvar) /* rvalue can't be a CSE */ 676 692 { 677 693 c = cat(c,getregs_imm(retregs)); // necessary if both lvalue and 678 694 // rvalue are CSEs (since a reg 679 695 // can hold only one e at a time) 680 696 cssave(e1,retregs,EOP(e1)); /* if lvalue is a CSE */ 681 697 } 682 698 683 699 c = cat4(cr,cl,c,fixresult(e,retregs,pretregs)); 684 700 Lp: 685 701 if (postinc) 686 702 { 687 703 int reg = findreg(idxregm(&cs)); 688 704 if (*pretregs & mPSW) 689 705 { // Use LEA to avoid touching the flags 690 706 unsigned rm = cs.Irm & 7; 691 707 if (cs.Irex & REX_B) 692 708 rm |= 8; 693 c = genc1(c,0x8D, modregxrmx(2,reg,rm),FLconst,postinc);709 c = genc1(c,0x8D,buildModregrm(2,reg,rm),FLconst,postinc); 694 710 if (sz == 8) 695 711 code_orrex(c, REX_W); 696 712 } 697 713 else if (I64) 698 714 { 699 715 c = genc2(c,0x81,modregrmx(3,0,reg),postinc); 700 716 if (sz == 8) 701 717 code_orrex(c, REX_W); 702 718 } 703 719 else 704 720 { 705 721 if (postinc == 1) 706 722 c = gen1(c,0x40 + reg); // INC reg 707 723 else if (postinc == -(targ_int)1) 708 724 c = gen1(c,0x48 + reg); // DEC reg 709 725 else 710 726 { 711 727 c = genc2(c,0x81,modregrm(3,0,reg),postinc); 712 728 } 713 729 } … … 1817 1833 if (I64 && byte && (reg >= 4 || rreg >= 4)) 1818 1834 c->Irex |= REX; // address byte registers 1819 1835 } 1820 1836 else 1821 1837 { assert(sz <= 2 * REGSIZE); 1822 1838 1823 1839 /* Compare MSW, if they're equal then compare the LSW */ 1824 1840 reg = findregmsw(retregs); 1825 1841 rreg = findregmsw(rretregs); 1826 1842 c = genregs(CNIL,0x3B ^ reverse,reg,rreg); /* CMP reg,rreg */ 1827 1843 if (!I16 && sz == 6) 1828 1844 c->Iflags |= CFopsize; /* seg is only 16 bits */ 1829 1845 genjmp(c,JNE,FLcode,(block *) ce); /* JNE nop */ 1830 1846 1831 1847 reg = findreglsw(retregs); 1832 1848 rreg = findreglsw(rretregs); 1833 1849 genregs(c,0x3B ^ reverse,reg,rreg); /* CMP reg,rreg */ 1834 1850 } 1835 1851 break; 1836 1852 case OPrelconst: 1853 if (I64 && config.flags3 & CFG3pic) 1854 goto L2; 1837 1855 fl = el_fl(e2); 1838 1856 switch (fl) 1839 1857 { case FLfunc: 1840 1858 fl = FLextern; // so it won't be self-relative 1841 1859 break; 1842 1860 case FLdata: 1843 1861 case FLudata: 1844 1862 case FLextern: 1845 1863 if (sz > REGSIZE) // compare against DS, not DGROUP 1846 1864 goto L2; 1847 1865 break; 1848 1866 case FLfardata: 1849 1867 break; 1850 1868 default: 1851 1869 goto L2; 1852 1870 } 1853 1871 cs.IFL2 = fl; 1854 1872 cs.IEVsym2 = e2->EV.sp.Vsym; 1855 1873 offset2 = e2->EV.sp.Voffset; 1856 1874 if (sz > REGSIZE) branches/dmd-1.x/src/backend/code.h
r738 r768 635 635 #else 636 636 code *allocreg (regm_t *pretregs , unsigned *preg , tym_t tym ); 637 637 #endif 638 638 void useregs (regm_t regm ); 639 639 code *getregs (regm_t r ); 640 640 code *getregs_imm (regm_t r ); 641 641 code *cse_flush(int); 642 642 void cssave (elem *e , regm_t regm , unsigned opsflag ); 643 643 bool evalinregister (elem *e ); 644 644 regm_t getscratch(); 645 645 code *codelem (elem *e , regm_t *pretregs , bool constflag ); 646 646 const char *regm_str(regm_t rm); 647 647 int numbitsset(regm_t); 648 648 649 649 /* cod1.c */ 650 650 extern int clib_inited; 651 651 652 652 int isscaledindex(elem *); 653 653 int ssindex(int op,targ_uns product); 654 654 void buildEA(code *c,int base,int index,int scale,targ_size_t disp); 655 unsigned buildModregrm(int mod, int reg, int rm); 655 656 void andregcon (con_t *pregconsave); 656 657 code *docommas (elem **pe ); 657 658 code *gencodelem(code *c,elem *e,regm_t *pretregs,bool constflag); 658 659 void gensaverestore(regm_t, code **, code **); 659 660 code *genstackclean(code *c,unsigned numpara,regm_t keepmsk); 660 661 code *logexp (elem *e , int jcond , unsigned fltarg , code *targ ); 661 662 code *loadea (elem *e , code *cs , unsigned op , unsigned reg , targ_size_t offset , regm_t keepmsk , regm_t desmsk ); 662 663 unsigned getaddrmode (regm_t idxregs ); 663 664 void setaddrmode(code *c, regm_t idxregs); 664 665 void getlvalue_msw(code *); 665 666 void getlvalue_lsw(code *); 666 667 code *getlvalue (code *pcs , elem *e , regm_t keepmsk ); 667 668 code *scodelem (elem *e , regm_t *pretregs , regm_t keepmsk , bool constflag ); 668 669 code *fltregs (code *pcs , tym_t tym ); 669 670 code *tstresult (regm_t regm , tym_t tym , unsigned saveflag ); 670 671 code *fixresult (elem *e , regm_t retregs , regm_t *pretregs ); 671 672 code *callclib (elem *e , unsigned clib , regm_t *pretregs , regm_t keepmask ); 672 673 cd_t cdfunc; 673 674 cd_t cdstrthis; 674 675 code *params(elem *, unsigned); branches/dmd-1.x/src/backend/el.c
r738 r768 3205 3205 } 3206 3206 WROP(e->Eoper); 3207 3207 dbg_printf(" "); 3208 3208 if (SCPP && PARSER) 3209 3209 { 3210 3210 if (e->ET) 3211 3211 { type_debug(e->ET); 3212 3212 if (tybasic(e->ET->Tty) == TYstruct 3213 3213 #if !TX86 3214 3214 && (e->PEFflags & PEFstrsize) 3215 3215 #endif 3216 3216 ) 3217 3217 dbg_printf("%d ", (int)type_size(e->ET)); 3218 3218 WRTYxx(e->ET->Tty); 3219 3219 } 3220 3220 } 3221 3221 else 3222 3222 { 3223 3223 if ((e->Eoper == OPstrpar || e->Eoper == OPstrctor || e->Eoper == OPstreq) || 3224 3224 e->Ety == TYstruct) 3225 dbg_printf("%d ", (int)type_size(e->ET)); 3225 if (e->ET) 3226 dbg_printf("%d ", (int)type_size(e->ET)); 3226 3227 WRTYxx(e->Ety); 3227 3228 } 3228 3229 if (OTunary(e->Eoper)) 3229 3230 { 3230 3231 if (e->E2) 3231 3232 dbg_printf("%p %p\n",e->E1,e->E2); 3232 3233 else 3233 3234 dbg_printf("%p\n",e->E1); 3234 3235 elem_print(e->E1); 3235 3236 } 3236 3237 else if (OTbinary(e->Eoper)) 3237 3238 { 3238 3239 if (!PARSER && e->Eoper == OPstreq) 3239 3240 dbg_printf("bytes=%d ", (int)type_size(e->ET)); 3240 3241 dbg_printf("%p %p\n",e->E1,e->E2); 3241 3242 elem_print(e->E1); 3242 3243 elem_print(e->E2); 3243 3244 } 3244 3245 else 3245 3246 { branches/dmd-1.x/src/backend/gloop.c
r738 r768 2134 2134 c.Vchar = 1; 2135 2135 break; 2136 2136 case TYshort: 2137 2137 case TYushort: 2138 2138 case TYchar16: 2139 2139 case TYwchar_t: // BUG: what about 4 byte wchar_t's? 2140 2140 c.Vshort = 1; 2141 2141 break; 2142 2142 #if TX86 2143 2143 case TYsptr: 2144 2144 case TYcptr: 2145 2145 #if JHANDLE 2146 2146 case TYjhandle: 2147 2147 #endif 2148 2148 case TYnptr: 2149 2149 #endif 2150 2150 case TYnullptr: 2151 2151 case TYfptr: 2152 2152 case TYvptr: 2153 2153 ty = TYint; 2154 if (I64) 2155 ty = TYllong; 2154 2156 /* FALL-THROUGH */ 2155 2157 case TYint: 2156 2158 case TYuint: 2157 2159 c.Vint = 1; 2158 2160 break; 2159 2161 #if TX86 2160 2162 case TYhptr: 2161 2163 ty = TYlong; 2162 2164 #endif 2163 2165 case TYlong: 2164 2166 case TYulong: 2165 2167 case TYdchar: 2166 2168 default: 2167 2169 c.Vlong = 1; 2168 2170 break; 2169 2171 #if 0 2170 2172 default: 2171 2173 printf("ty = x%x\n", tybasic(ty)); 2172 2174 assert(0); 2173 2175 #endif branches/dmd-1.x/src/e2ir.c
r767 r768 3125 3125 if (!func->isThis()) 3126 3126 error("delegates are only for non-static functions"); 3127 3127 3128 3128 if (!func->isVirtual() || 3129 3129 directcall || 3130 3130 func->isFinal()) 3131 3131 { 3132 3132 ep = el_ptr(sfunc); 3133 3133 } 3134 3134 else 3135 3135 { 3136 3136 // Get pointer to function out of virtual table 3137 3137 unsigned vindex; 3138 3138 3139 3139 assert(ethis); 3140 3140 ep = el_same(ðis); 3141 3141 ep = el_una(OPind, TYnptr, ep); 3142 3142 vindex = func->vtblIndex; 3143 3143 3144 3144 // Build *(ep + vindex * 4) 3145 ep = el_bin(OPadd,TYnptr,ep,el_long(TYsize_t, vindex * 4));3145 ep = el_bin(OPadd,TYnptr,ep,el_long(TYsize_t, vindex * PTRSIZE)); 3146 3146 ep = el_una(OPind,TYnptr,ep); 3147 3147 } 3148 3148 3149 3149 // if (func->tintro) 3150 3150 // func->error(loc, "cannot form delegate due to covariant return type"); 3151 3151 } 3152 3152 if (ethis->Eoper == OPcomma) 3153 3153 { 3154 3154 ethis->E2 = el_pair(TYdarray, ethis->E2, ep); 3155 3155 ethis->Ety = TYdarray; 3156 3156 e = ethis; 3157 3157 } 3158 3158 else 3159 3159 e = el_pair(TYdarray, ethis, ep); 3160 3160 el_setLoc(e,loc); 3161 3161 return e; 3162 3162 } 3163 3163 3164 3164 elem *DotTypeExp::toElem(IRState *irs) 3165 3165 { branches/dmd-1.x/src/msc.c
r729 r768 309 309 { 310 310 int sz = (tybasic(ty) == TYvoid) ? 1 : tysize(ty); 311 311 #ifdef DEBUG 312 312 if (sz == -1) 313 313 WRTYxx(ty); 314 314 #endif 315 315 assert(sz!= -1); 316 316 return sz; 317 317 } 318 318 319 319 /******************************* 320 320 * Replace (e) with ((stmp = e),stmp) 321 321 */ 322 322 323 323 elem *exp2_copytotemp(elem *e) 324 324 { 325 325 //printf("exp2_copytotemp()\n"); 326 326 elem_debug(e); 327 327 Symbol *stmp = symbol_genauto(e); 328 328 elem *eeq = el_bin(OPeq,e->Ety,el_var(stmp),e); 329 if (e->Ety == TYstruct) 329 elem *er = el_bin(OPcomma,e->Ety,eeq,el_var(stmp)); 330 if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray) 330 331 { 331 332 eeq->Eoper = OPstreq; 332 333 eeq->ET = e->ET; 333 } 334 return el_bin(OPcomma,e->Ety,eeq,el_var(stmp)); 334 eeq->E1->ET = e->ET; 335 er->ET = e->ET; 336 er->E2->ET = e->ET; 337 } 338 return er; 335 339 } 336 340 337 341 /**************************** 338 342 * Generate symbol of type ty at DATA:offset 339 343 */ 340 344 341 345 symbol *symboldata(targ_size_t offset,tym_t ty) 342 346 { 343 347 symbol *s = symbol_generate(SClocstat, type_fake(ty)); 344 348 s->Sfl = FLdata; 345 349 s->Soffset = offset; 346 350 s->Sseg = DATA; 347 351 symbol_keep(s); // keep around 348 352 return s; 349 353 } 350 354 351 355 /************************************ 352 356 * Add symbol to slist. 353 357 */ 354 358 branches/dmd-1.x/src/mtype.h
r729 r768 140 140 #define tfloat80 basic[Tfloat80] 141 141 142 142 #define timaginary32 basic[Timaginary32] 143 143 #define timaginary64 basic[Timaginary64] 144 144 #define timaginary80 basic[Timaginary80] 145 145 146 146 #define tcomplex32 basic[Tcomplex32] 147 147 #define tcomplex64 basic[Tcomplex64] 148 148 #define tcomplex80 basic[Tcomplex80] 149 149 150 150 #define tbit basic[Tbit] 151 151 #define tbool basic[Tbool] 152 152 #define tchar basic[Tchar] 153 153 #define twchar basic[Twchar] 154 154 #define tdchar basic[Tdchar] 155 155 156 156 // Some special types 157 157 #define tshiftcnt tint32 // right side of shift expression 158 158 // #define tboolean tint32 // result of boolean expression 159 159 #define tboolean tbool // result of boolean expression 160 #define tindex t int32// array/ptr index160 #define tindex tsize_t // array/ptr index 161 161 static Type *tvoidptr; // void* 162 162 #define terror basic[Terror] // for error recovery 163 163 164 164 #define tsize_t basic[Tsize_t] // matches size_t alias 165 165 #define tptrdiff_t basic[Tptrdiff_t] // matches ptrdiff_t alias 166 166 #define thash_t tsize_t // matches hash_t alias 167 167 168 168 static ClassDeclaration *typeinfo; 169 169 static ClassDeclaration *typeinfoclass; 170 170 static ClassDeclaration *typeinfointerface; 171 171 static ClassDeclaration *typeinfostruct; 172 172 static ClassDeclaration *typeinfotypedef; 173 173 static ClassDeclaration *typeinfopointer; 174 174 static ClassDeclaration *typeinfoarray; 175 175 static ClassDeclaration *typeinfostaticarray; 176 176 static ClassDeclaration *typeinfoassociativearray; 177 177 static ClassDeclaration *typeinfoenum; 178 178 static ClassDeclaration *typeinfofunction; 179 179 static ClassDeclaration *typeinfodelegate; 180 180 static ClassDeclaration *typeinfotypelist; branches/dmd-1.x/src/template.c
r754 r768 3622 3622 --nest; 3623 3623 #if WINDOWS_SEH 3624 3624 } 3625 3625 __except (__ehfilter(GetExceptionInformation())) 3626 3626 { 3627 3627 global.gag = 0; // ensure error message gets printed 3628 3628 error("recursive expansion"); 3629 3629 fatal(); 3630 3630 } 3631 3631 #endif 3632 3632 } 3633 3633 3634 3634 Laftersemantic: 3635 3635 sc2->pop(); 3636 3636 3637 3637 scope->pop(); 3638 3638 3639 3639 // Give additional context info if error occurred during instantiation 3640 3640 if (global.errors != errorsave) 3641 3641 { 3642 error( "error instantiating");3642 error(loc, "error instantiating"); 3643 3643 if (tinst) 3644 3644 { tinst->printInstantiationTrace(); 3645 3645 if (!global.gag) 3646 3646 fatal(); 3647 3647 } 3648 3648 errors = 1; 3649 3649 if (global.gag) 3650 3650 { // Try to reset things so we can try again later to instantiate it 3651 3651 tempdecl->instances.remove(tempdecl_instance_idx); 3652 3652 if (!(sc->flags & SCOPEstaticif)) 3653 3653 { // Bugzilla 4302 for discussion 3654 3654 semanticRun = 0; 3655 3655 inst = NULL; 3656 3656 } 3657 3657 } 3658 3658 } 3659 3659 3660 3660 #if LOG 3661 3661 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 3662 3662 #endif trunk/src/backend/cg87.c
r767 r768 2045 2045 cs.Iop = op1; 2046 2046 c2 = getlvalue(&cs, e->E1, 0); 2047 2047 cs.IEVoffset1 += sz; 2048 2048 cs.Irm |= modregrm(0, op2, 0); 2049 2049 c2 = cat(c2, makesure87(e->E2, sz, 0, 0)); 2050 2050 c2 = gen(c2, &cs); 2051 2051 c2 = genfwait(c2); 2052 2052 c2 = cat(c2, makesure87(e->E2, 0, 1, 0)); 2053 2053 } 2054 2054 else 2055 2055 { 2056 2056 c2 = loadea(e->E1,&cs,op1,op2,sz,0,0); 2057 2057 c2 = genfwait(c2); 2058 2058 } 2059 2059 if (fxch) 2060 2060 c2 = genf2(c2,0xD9,0xC8 + 1); // FXCH ST(1) 2061 2061 cs.IEVoffset1 -= sz; 2062 2062 gen(c2, &cs); 2063 2063 if (fxch) 2064 2064 genf2(c2,0xD9,0xC8 + 1); // FXCH ST(1) 2065 #if LNGDBLSIZE == 12 2066 if (op1 == 0xDB) 2067 { 2068 cs.Iop = 0xC7; // MOV EA+10,0 2069 NEWREG(cs.Irm, 0); 2070 cs.IEV1.sp.Voffset += 10; 2071 cs.IFL2 = FLconst; 2072 cs.IEV2.Vint = 0; 2073 cs.Iflags |= CFopsize; 2074 c2 = gen(c2, &cs); 2075 cs.IEVoffset1 += 12; 2076 c2 = gen(c2, &cs); // MOV EA+22,0 2077 } 2078 #endif 2065 if (tysize[TYldouble] == 12) 2066 { 2067 if (op1 == 0xDB) 2068 { 2069 cs.Iop = 0xC7; // MOV EA+10,0 2070 NEWREG(cs.Irm, 0); 2071 cs.IEV1.sp.Voffset += 10; 2072 cs.IFL2 = FLconst; 2073 cs.IEV2.Vint = 0; 2074 cs.Iflags |= CFopsize; 2075 c2 = gen(c2, &cs); 2076 cs.IEVoffset1 += 12; 2077 c2 = gen(c2, &cs); // MOV EA+22,0 2078 } 2079 } 2079 2080 if (tysize[TYldouble] == 16) 2080 2081 { 2081 if (op1 == 0xDB)2082 {2083 cs.Iop = 0xC7; // MOV EA+10,02084 NEWREG(cs.Irm, 0);2085 cs.IEV1.sp.Voffset += 10;2086 cs.IFL2 = FLconst;2087 cs.IEV2.Vint = 0;2088 cs.Iflags |= CFopsize;2089 c2 = gen(c2, &cs);2090 2091 cs.IEV1.sp.Voffset += 2;2092 cs.Iflags &= ~CFopsize;2093 c2 = gen(c2, &cs);2094 2095 cs.IEVoffset1+= 14;2096 cs.Iflags |= CFopsize;2097 c2 = gen(c2, &cs);2098 2099 cs.IEV1.sp.Voffset += 2;2100 cs.Iflags &= ~CFopsize;2101 c2 = gen(c2, &cs);2102 }2082 if (op1 == 0xDB) 2083 { 2084 cs.Iop = 0xC7; // MOV EA+10,0 2085 NEWREG(cs.Irm, 0); 2086 cs.IEV1.sp.Voffset += 10; 2087 cs.IFL2 = FLconst; 2088 cs.IEV2.Vint = 0; 2089 cs.Iflags |= CFopsize; 2090 c2 = gen(c2, &cs); 2091 2092 cs.IEV1.sp.Voffset += 2; 2093 cs.Iflags &= ~CFopsize; 2094 c2 = gen(c2, &cs); 2095 2096 cs.IEV1.sp.Voffset += 14; 2097 cs.Iflags |= CFopsize; 2098 c2 = gen(c2, &cs); 2099 2100 cs.IEV1.sp.Voffset += 2; 2101 cs.Iflags &= ~CFopsize; 2102 c2 = gen(c2, &cs); 2103 } 2103 2104 } 2104 2105 c2 = genfwait(c2); 2105 2106 freenode(e->E1); 2106 2107 return cat3(c1,c2,fixresult_complex87(e,mST01 | mPSW,pretregs)); 2107 2108 } 2108 2109 2109 2110 /******************************* 2110 2111 * Perform an assignment while converting to integral type, 2111 2112 * i.e. handle (e1 = (int) e2) 2112 2113 */ 2113 2114 2114 2115 code *cnvteq87(elem *e,regm_t *pretregs) 2115 2116 { 2116 2117 regm_t retregs; 2117 2118 code *c1,*c2; 2118 2119 code cs; 2119 2120 unsigned op1; 2120 2121 unsigned op2; 2121 2122 tym_t ty1; 2122 2123 trunk/src/backend/cgcod.c
r767 r768 1534 1534 case TYint: 1535 1535 case TYuint: 1536 1536 #if JHANDLE 1537 1537 case TYjhandle: 1538 1538 #endif 1539 1539 case TYnullptr: 1540 1540 case TYnptr: 1541 1541 case TYsptr: 1542 1542 case TYcptr: 1543 1543 return mAX; 1544 1544 1545 1545 case TYfloat: 1546 1546 case TYifloat: 1547 1547 if (I64) 1548 1548 return mXMM0; 1549 1549 if (config.exe & EX_flat) 1550 1550 return mST0; 1551 1551 case TYlong: 1552 1552 case TYulong: 1553 1553 case TYdchar: 1554 if ( I32)1554 if (!I16) 1555 1555 return mAX; 1556 1556 case TYfptr: 1557 1557 case TYhptr: 1558 1558 return mDX | mAX; 1559 1559 1560 1560 case TYcent: 1561 1561 case TYucent: 1562 1562 assert(I64); 1563 1563 return mDX | mAX; 1564 1564 1565 1565 case TYvptr: 1566 1566 return mDX | mBX; 1567 1567 1568 1568 case TYdouble: 1569 1569 case TYdouble_alias: 1570 1570 case TYidouble: 1571 1571 if (I64) 1572 1572 return mXMM0; 1573 1573 if (config.exe & EX_flat) 1574 1574 return mST0; trunk/src/backend/cod1.c
r767 r768 171 171 if (index == -1) 172 172 rm = modregrm(0,0,5); 173 173 else 174 174 { 175 175 rm = modregrm(0,0,4); 176 176 sib = modregrm(ss,index & 7,5); 177 177 if (index & 8) 178 178 rex |= REX_X; 179 179 } 180 180 } 181 181 else if (index == -1) 182 182 { 183 183 if (base == SP) 184 184 { 185 185 rm = modregrm(2,0,4); 186 186 sib = modregrm(0,4,SP); 187 187 } 188 188 else 189 189 { rm = modregrm(2,0,base & 7); 190 190 if (base & 8) 191 rex |= REX_B; 191 { rex |= REX_B; 192 if (base == R12) 193 { 194 rm = modregrm(2,0,4); 195 sib = modregrm(0,4,4); 196 } 197 } 192 198 } 193 199 } 194 200 else 195 201 { 196 202 rm = modregrm(2,0,4); 197 203 sib = modregrm(ss,index & 7,base & 7); 198 204 if (index & 8) 199 205 rex |= REX_X; 200 206 if (base & 8) 201 207 rex |= REX_B; 202 208 } 203 209 } 204 210 else 205 211 { 206 212 // -1 AX CX DX BX SP BP SI DI 207 213 static unsigned char EA16rm[9][9] = 208 214 { 209 215 { 0x06,0x09,0x09,0x09,0x87,0x09,0x86,0x84,0x85, }, // -1 210 216 { 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, }, // AX 211 217 { 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, }, // CX 212 218 { 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, }, // DX 213 219 { 0x87,0x09,0x09,0x09,0x09,0x09,0x09,0x80,0x81, }, // BX 214 220 { 0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09, }, // SP 215 221 { 0x86,0x09,0x09,0x09,0x09,0x09,0x09,0x82,0x83, }, // BP 216 222 { 0x84,0x09,0x09,0x09,0x80,0x09,0x82,0x09,0x09, }, // SI 217 223 { 0x85,0x09,0x09,0x09,0x81,0x09,0x83,0x09,0x09, } // DI 218 224 }; 219 225 220 226 assert(scale == 1); 221 227 rm = EA16rm[base + 1][index + 1]; 222 228 assert(rm != 9); 223 229 } 224 230 c->Irm = rm; 225 231 c->Isib = sib; 226 232 c->Irex = rex; 227 233 c->IFL1 = FLconst; 228 234 c->IEV1.Vuns = disp; 235 } 236 237 /********************************************* 238 * Build REX, modregrm and sib bytes 239 */ 240 241 unsigned buildModregrm(int mod, int reg, int rm) 242 { unsigned m; 243 if (I16) 244 m = modregrm(mod, reg, rm); 245 else 246 { 247 unsigned rex = 0; 248 if ((rm & 7) == SP && mod != 3) 249 m = (modregrm(0,4,SP) << 8) | modregrm(mod,reg & 7,4); 250 else 251 m = modregrm(mod,reg & 7,rm & 7); 252 if (reg & 8) 253 m |= REX_R << 16; 254 if (rm & 8) 255 m |= REX_B << 16; 256 } 257 return m; 229 258 } 230 259 231 260 /************************** 232 261 * For elems in regcon that don't match regconsave, 233 262 * clear the corresponding bit in regcon.cse.mval. 234 263 * Do same for regcon.immed. 235 264 */ 236 265 237 266 void andregcon(con_t *pregconsave) 238 267 { 239 268 regm_t m = ~1; 240 269 for (int i = 0; i < REGMAX; i++) 241 270 { if (pregconsave->cse.value[i] != regcon.cse.value[i]) 242 271 regcon.cse.mval &= m; 243 272 if (pregconsave->immed.value[i] != regcon.immed.value[i]) 244 273 regcon.immed.mval &= m; 245 274 m <<= 1; 246 275 m |= 1; 247 276 } 248 277 //printf("regcon.cse.mval = x%x, regconsave->mval = x%x ",regcon.cse.mval,pregconsave->cse.mval); … … 860 889 break; 861 890 default: 862 891 #ifdef DEBUG 863 892 elem_print(e); 864 893 #endif 865 894 assert(0); 866 895 } 867 896 e1ty = tybasic(e1->Ety); 868 897 if (e1isadd) 869 898 { e12 = e1->E2; 870 899 e11 = e1->E1; 871 900 } 872 901 873 902 /* First see if we can replace *(e+&v) with 874 903 * MOV idxreg,e 875 904 * EA = [ES:] &v+idxreg 876 905 */ 877 906 878 907 if (e1isadd && 879 908 e12->Eoper == OPrelconst && 909 !(I64 && config.flags3 & CFG3pic) && 880 910 (f = el_fl(e12)) != FLfardata && 881 911 e1->Ecount == e1->Ecomsub && 882 912 (!e1->Ecount || (~keepmsk & ALLREGS & mMSW) || (e1ty != TYfptr && e1ty != TYhptr)) && 883 913 tysize(e11->Ety) == REGSIZE 884 914 ) 885 915 { unsigned char t; /* component of r/m field */ 886 916 int ss; 887 917 int ssi; 888 918 889 919 /*assert(datafl[f]);*/ /* what if addr of func? */ 890 920 if (!I16) 891 921 { /* Any register can be an index register */ 892 922 regm_t idxregs = allregs & ~keepmsk; 893 923 assert(idxregs); 894 924 895 925 /* See if e1->E1 can be a scaled index */ 896 926 ss = isscaledindex(e11); 897 927 if (ss) 898 928 { 899 929 /* Load index register with result of e11->E1 */ … … 942 972 assert(!stackfl[f]); 943 973 pcs->Irm = modregrm(2,0,4); 944 974 pcs->Isib = modregrm(ss1,reg & 7,reg & 7); 945 975 if (reg & 8) 946 976 pcs->Irex |= REX_X | REX_B; 947 977 } 948 978 else 949 979 { int rbase; 950 980 unsigned r; 951 981 952 982 scratchm = ALLREGS & ~keepmsk; 953 983 c = cat(c,allocreg(&scratchm,&r,TYint)); 954 984 955 985 if (ssflags & SSFLnobase1) 956 986 { t = 0; 957 987 rbase = 5; 958 988 } 959 989 else 960 990 { t = 0; 961 991 rbase = reg; 962 if (rbase == BP )992 if (rbase == BP || rbase == R13) 963 993 { static unsigned imm32[4] = {1+1,2+1,4+1,8+1}; 964 994 965 995 // IMUL r,BP,imm32 966 c = genc2(c,0x69,modregxrm (3,r,BP),imm32[ss1]);996 c = genc2(c,0x69,modregxrmx(3,r,rbase),imm32[ss1]); 967 997 goto L7; 968 998 } 969 999 } 970 1000 971 1001 c = gen2sib(c,0x8D,modregxrm(t,r,4),modregrm(ss1,reg & 7,rbase & 7)); 972 1002 if (reg & 8) 973 1003 code_orrex(c, REX_X); 974 1004 if (rbase & 8) 975 1005 code_orrex(c, REX_B); 976 1006 if (I64) 977 1007 code_orrex(c, REX_W); 978 1008 979 1009 if (ssflags & SSFLnobase1) 980 1010 { code_last(c)->IFL1 = FLconst; 981 1011 code_last(c)->IEV1.Vuns = 0; 982 1012 } 983 1013 L7: 984 1014 if (ssflags & SSFLnobase) 985 1015 { t = stackfl[f] ? 2 : 0; 986 1016 rbase = 5; … … 3219 3249 if (!(config.exe & EX_flat)) 3220 3250 { seg = CFes; 3221 3251 retregs |= mES; 3222 3252 } 3223 3253 c1 = codelem(e1,&retregs,FALSE); 3224 3254 break; 3225 3255 default: 3226 3256 #ifdef DEBUG 3227 3257 elem_print(e1); 3228 3258 #endif 3229 3259 assert(0); 3230 3260 } 3231 3261 reg = findreglsw(retregs); 3232 3262 rm = I16 ? regtorm[reg] : regtorm32[reg]; 3233 3263 if (op16) 3234 3264 seg |= CFopsize; // operand size 3235 3265 if (npushes <= 4) 3236 3266 { 3237 3267 assert(!doneoff); 3238 3268 for (c2 = CNIL; npushes > 1; npushes--) 3239 { c2 = genc1(c2,0xFF, modregrmx(2,6,rm),FLconst,pushsize * (npushes - 1)); // PUSH [reg]3269 { c2 = genc1(c2,0xFF,buildModregrm(2,6,rm),FLconst,pushsize * (npushes - 1)); // PUSH [reg] 3240 3270 code_orflag(c2,seg); 3241 3271 genadjesp(c2,pushsize); 3242 3272 } 3243 c3 = gen2(CNIL,0xFF, modregrmx(0,6,rm)); // PUSH [reg]3273 c3 = gen2(CNIL,0xFF,buildModregrm(0,6,rm)); // PUSH [reg] 3244 3274 c3->Iflags |= seg; 3245 3275 genadjesp(c3,pushsize); 3246 3276 ce = cat4(cc,c1,c2,c3); 3247 3277 } 3248 3278 else if (sz) 3249 3279 { int size; 3250 3280 3251 3281 c2 = getregs_imm(mCX | retregs); 3252 3282 /* MOV CX,sz/2 */ 3253 3283 c2 = movregconst(c2,CX,npushes,0); 3254 3284 if (!doneoff) 3255 3285 { /* This disgusting thing should be done when */ 3256 3286 /* reg is loaded. Too lazy to fix it now. */ 3257 3287 /* ADD reg,sz-2 */ 3258 3288 c2 = genc2(c2,0x81,grex | modregrmx(3,0,reg),sz-pushsize); 3259 3289 } 3260 c3 = gen2(CNIL,0xFF, modregrmx(0,6,rm)); // PUSH [reg]3290 c3 = gen2(CNIL,0xFF,buildModregrm(0,6,rm)); // PUSH [reg] 3261 3291 c3->Iflags |= seg | CFtarg2; 3262 genc2(c3,0x81,grex | modregrmx(3,5,reg),pushsize); // SUB reg,23292 genc2(c3,0x81,grex | buildModregrm(3,5,reg),pushsize); // SUB reg,2 3263 3293 size = ((seg & CFSEG) ? -8 : -7) - op16; 3264 3294 if (code_next(c3)->Iop != 0x81) 3265 3295 size++; 3266 3296 //genc2(c3,0xE2,0,size); // LOOP .-7 or .-8 3267 3297 genjmp(c3,0xE2,FLcode,(block *)c3); // LOOP c3 3268 3298 regimmed_set(CX,0); 3269 3299 genadjesp(c3,sz); 3270 3300 ce = cat4(cc,c1,c2,c3); 3271 3301 } 3272 3302 else 3273 3303 ce = cat(cc,c1); 3274 3304 stackpush += sz; 3275 3305 goto L2; 3276 3306 } 3277 3307 case OPind: 3278 3308 if (!e->Ecount) /* if *e1 */ 3279 3309 { if (sz <= REGSIZE) 3280 3310 { // Watch out for single byte quantities being up 3281 3311 // against the end of a segment or in memory-mapped I/O 3282 3312 if (!(config.exe & EX_flat) && szb == 1) … … 3676 3706 { 3677 3707 regm = allregs; 3678 3708 if (e->Eoper == OPconst) 3679 3709 { /* TRUE: OR SP,SP (SP is never 0) */ 3680 3710 /* FALSE: CMP SP,SP (always equal) */ 3681 3711 c = genregs(CNIL,(boolres(e)) ? 0x09 : 0x39,SP,SP); 3682 3712 if (I64) 3683 3713 code_orrex(c, REX_W); 3684 3714 } 3685 3715 else if (sz <= REGSIZE) 3686 3716 { 3687 3717 if (!I16 && (tym == TYfloat || tym == TYifloat)) 3688 3718 { c = allocreg(®m,®,TYoffset); /* get a register */ 3689 3719 ce = loadea(e,&cs,0x8B,reg,0,0,0); // MOV reg,data 3690 3720 c = cat(c,ce); 3691 3721 ce = gen2(CNIL,0xD1,modregrmx(3,4,reg)); /* SHL reg,1 */ 3692 3722 c = cat(c,ce); 3693 3723 } 3694 3724 else 3695 3725 { cs.IFL2 = FLconst; 3696 cs.IEV2.V int = 0;3726 cs.IEV2.Vsize_t = 0; 3697 3727 op = (sz == 1) ? 0x80 : 0x81; 3698 3728 c = loadea(e,&cs,op,7,0,0,0); /* CMP EA,0 */ 3699 3729 3700 3730 // Convert to TEST instruction if EA is a register 3701 3731 // (to avoid register contention on Pentium) 3702 3732 if ((c->Iop & ~1) == 0x38 && 3703 3733 (c->Irm & modregrm(3,0,0)) == modregrm(3,0,0) 3704 3734 ) 3705 3735 { c->Iop = (c->Iop & 1) | 0x84; 3706 3736 code_newreg(c, c->Irm & 7); 3707 3737 if (c->Irex & REX_B) 3708 c->Irex = (c->Irex & ~REX_B) | REX_R; 3738 //c->Irex = (c->Irex & ~REX_B) | REX_R; 3739 c->Irex |= REX_R; 3709 3740 } 3710 3741 } 3711 3742 } 3712 3743 else if (sz < 8) 3713 3744 { 3714 3745 c = allocreg(®m,®,TYoffset); /* get a register */ 3715 3746 if (I32) // it's a 48 bit pointer 3716 3747 ce = loadea(e,&cs,0x0FB7,reg,REGSIZE,0,0); /* MOVZX reg,data+4 */ 3717 3748 else 3718 3749 { ce = loadea(e,&cs,0x8B,reg,REGSIZE,0,0); /* MOV reg,data+2 */ 3719 3750 if (tym == TYfloat || tym == TYifloat) // dump sign bit 3720 3751 gen2(ce,0xD1,modregrm(3,4,reg)); /* SHL reg,1 */ 3721 3752 } 3722 3753 c = cat(c,ce); 3723 3754 ce = loadea(e,&cs,0x0B,reg,0,regm,0); /* OR reg,data */ 3724 3755 c = cat(c,ce); 3725 3756 } 3726 3757 else if (sz == 8 || (I64 && sz == 2 * REGSIZE && !tyfloating(tym))) 3727 3758 { 3728 3759 c = allocreg(®m,®,TYoffset); /* get a register */ trunk/src/backend/cod2.c
r767 r768 226 226 else if (sz == 4) 227 227 value &= 0xFFFFFFFF; 228 228 if (reghasvalue(byte ? BYTEREGS : ALLREGS,value,®)) 229 229 goto L11; 230 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 if (I64 && byte && reg >= 4) 247 cs.Irex |= REX; 246 248 L10: 247 249 cs.Iop = op1 ^ byte; 248 250 cs.Iflags |= word | CFpsw; 249 251 freenode(e1); 250 252 freenode(e2); 251 253 return gen(c,&cs); 252 254 } 253 255 } 254 256 255 257 // Look for possible uses of LEA 256 258 if (e->Eoper == OPadd && 257 259 !(*pretregs & mPSW) && /* flags aren't set by LEA */ 258 260 !nest && // could cause infinite recursion if e->Ecount 259 261 (sz == REGSIZE || (I64 && sz == 4))) // far pointers aren't handled 260 262 { 261 263 unsigned rex = (sz == 8) ? REX_W : 0; 262 264 263 265 // Handle the case of (e + &var) 264 266 int e1oper = e1->Eoper; 265 267 if ((e2oper == OPrelconst && (config.target_cpu >= TARGET_Pentium || (!e2->Ecount && stackfl[el_fl(e2)]))) … … 571 573 rretregs &= BYTEREGS; 572 574 573 575 cr = scodelem(e2,&rretregs,retregs,TRUE); /* get rvalue */ 574 576 rreg = (tysize[ty2] > REGSIZE) ? findreglsw(rretregs) : findreg(rretregs); 575 577 c = CNIL; 576 578 if (numwords == 1) /* ADD reg,rreg */ 577 579 { 578 580 /* reverse operands to avoid moving around the segment value */ 579 581 if (tysize[ty2] > REGSIZE) 580 582 { c = cat(c,getregs(rretregs)); 581 583 c = genregs(c,op1,rreg,reg); 582 584 retregs = rretregs; /* reverse operands */ 583 585 } 584 586 else 585 587 { c = genregs(c,op1,reg,rreg); 586 588 if (!I16 && *pretregs & mPSW) 587 589 c->Iflags |= word; 588 590 } 589 591 if (I64 && sz == 8) 590 592 code_orrex(c, REX_W); 593 if (I64 && byte && reg >= 4) 594 code_orrex(c, REX); 591 595 } 592 596 else /* numwords == 2 */ /* ADD lsreg,lsrreg */ 593 597 { 594 598 reg = findreglsw(retregs); 595 599 rreg = findreglsw(rretregs); 596 600 c = genregs(c,op1,reg,rreg); 597 601 if (e->Eoper == OPadd || e->Eoper == OPmin) 598 602 code_orflag(c,CFpsw); 599 603 reg = findregmsw(retregs); 600 604 rreg = findregmsw(rretregs); 601 605 if (!(e2oper == OPu16_32 && // if second operand is 0 602 606 (op2 == 0x0B || op2 == 0x33)) // and OR or XOR 603 607 ) 604 608 genregs(c,op2,reg,rreg); // ADC msreg,msrreg 605 609 } 606 610 break; 607 611 608 612 case OPrelconst: 609 613 if (sz != REGSIZE) 610 614 goto L2; … … 3203 3207 3204 3208 /********************************* 3205 3209 * Generate code for memset(s,val,n) intrinsic. 3206 3210 * (s OPmemset (n OPparam val)) 3207 3211 */ 3208 3212 3209 3213 #if 1 3210 3214 code *cdmemset(elem *e,regm_t *pretregs) 3211 3215 { code *c1,*c2,*c3 = NULL,*c4; 3212 3216 regm_t retregs1; 3213 3217 regm_t retregs2; 3214 3218 regm_t retregs3; 3215 3219 unsigned reg,vreg; 3216 3220 tym_t ty1; 3217 3221 elem *e2,*e1; 3218 3222 int segreg; 3219 3223 unsigned remainder; 3220 3224 targ_uns numbytes,numwords; 3221 3225 int op; 3222 3226 targ_size_t value; 3227 unsigned m; 3223 3228 3224 3229 //printf("cdmemset(*pretregs = x%x)\n", *pretregs); 3225 3230 e1 = e->E1; 3226 3231 e2 = e->E2; 3227 3232 assert(e2->Eoper == OPparam); 3228 3233 3229 3234 unsigned char rex = I64 ? REX_W : 0; 3230 3235 3231 3236 if (e2->E2->Eoper == OPconst) 3232 3237 { 3233 3238 value = el_tolong(e2->E2); 3234 3239 value &= 0xFF; 3235 3240 value |= value << 8; 3236 3241 value |= value << 16; 3237 3242 value |= value << 32; 3238 3243 } 3239 3244 3240 3245 if (e2->E1->Eoper == OPconst) 3241 3246 { 3242 3247 numbytes = el_tolong(e2->E1); 3243 3248 if (numbytes <= REP_THRESHOLD && 3244 3249 !I16 && // doesn't work for 16 bits 3245 3250 e2->E2->Eoper == OPconst) 3246 3251 { 3247 3252 targ_uns offset = 0; 3248 3253 retregs1 = *pretregs; 3249 3254 if (!retregs1) 3250 3255 retregs1 = ALLREGS; 3251 3256 c1 = codelem(e->E1,&retregs1,FALSE); 3252 3257 reg = findreg(retregs1); 3253 3258 if (e2->E2->Eoper == OPconst) 3254 3259 { 3260 unsigned m = buildModregrm(0,0,reg); 3255 3261 switch (numbytes) 3256 3262 { 3257 3263 case 4: // MOV [reg],imm32 3258 c3 = genc2(CNIL,0xC7,m odregrmx(0,0,reg),value);3264 c3 = genc2(CNIL,0xC7,m,value); 3259 3265 goto fixres; 3260 3266 case 2: // MOV [reg],imm16 3261 c3 = genc2(CNIL,0xC7,m odregrmx(0,0,reg),value);3267 c3 = genc2(CNIL,0xC7,m,value); 3262 3268 c3->Iflags = CFopsize; 3263 3269 goto fixres; 3264 3270 case 1: // MOV [reg],imm8 3265 c3 = genc2(CNIL,0xC6,m odregrmx(0,0,reg),value);3271 c3 = genc2(CNIL,0xC6,m,value); 3266 3272 goto fixres; 3267 3273 } 3268 3274 } 3269 3275 3270 3276 c1 = regwithvalue(c1, BYTEREGS & ~retregs1, value, &vreg, I64 ? 64 : 0); 3271 3277 freenode(e2->E2); 3272 3278 freenode(e2); 3273 3279 3280 m = (rex << 16) | buildModregrm(2,vreg,reg); 3274 3281 while (numbytes >= REGSIZE) 3275 3282 { // MOV dword ptr offset[reg],vreg 3276 c2 = gen2(CNIL,0x89, (rex << 16) | modregxrmx(2,vreg,reg));3283 c2 = gen2(CNIL,0x89,m); 3277 3284 c2->IEVoffset1 = offset; 3278 3285 c2->IFL1 = FLconst; 3279 3286 numbytes -= REGSIZE; 3280 3287 offset += REGSIZE; 3281 3288 c3 = cat(c3,c2); 3282 3289 } 3283 3290 if (numbytes & 4) 3284 3291 { // MOV dword ptr offset[reg],vreg 3285 c2 = gen2(CNIL,0x89,m odregxrmx(2,vreg,reg));3292 c2 = gen2(CNIL,0x89,m); 3286 3293 c2->IEVoffset1 = offset; 3287 3294 c2->IFL1 = FLconst; 3288 3295 offset += 4; 3289 3296 c3 = cat(c3,c2); 3290 3297 } 3291 3298 if (numbytes & 2) 3292 3299 { // MOV word ptr offset[reg],vreg 3293 c2 = gen2(CNIL,0x89,m odregxrmx(2,vreg,reg));3300 c2 = gen2(CNIL,0x89,m); 3294 3301 c2->IEVoffset1 = offset; 3295 3302 c2->IFL1 = FLconst; 3296 3303 c2->Iflags = CFopsize; 3297 3304 offset += 2; 3298 3305 c3 = cat(c3,c2); 3299 3306 } 3300 3307 if (numbytes & 1) 3301 3308 { // MOV byte ptr offset[reg],vreg 3302 c2 = gen2(CNIL,0x88,m odregxrmx(2,vreg,reg));3309 c2 = gen2(CNIL,0x88,m); 3303 3310 c2->IEVoffset1 = offset; 3304 3311 c2->IFL1 = FLconst; 3312 if (I64 && vreg >= 4) 3313 c2->Irex |= REX; 3305 3314 c3 = cat(c3,c2); 3306 3315 } 3307 3316 fixres: 3308 3317 return cat3(c1,c3,fixresult(e,retregs1,pretregs)); 3309 3318 } 3310 3319 } 3311 3320 3312 3321 // Get nbytes into CX 3313 3322 retregs2 = mCX; 3314 3323 if (!I16 && e2->E1->Eoper == OPconst && e2->E2->Eoper == OPconst) 3315 3324 { 3316 3325 remainder = numbytes & (4 - 1); 3317 3326 numwords = numbytes / 4; // number of words 3318 3327 op = 0xAB; // moving by words 3319 3328 c1 = getregs(mCX); 3320 3329 c1 = movregconst(c1,CX,numwords,I64?64:0); // # of bytes/words 3321 3330 } 3322 3331 else 3323 3332 { 3324 3333 remainder = 0; … … 3365 3374 if (*pretregs) // if need return value 3366 3375 { c3 = getregs(mBX); 3367 3376 c3 = genmovreg(c3,BX,DI); 3368 3377 code_orrex(c3,rex); 3369 3378 } 3370 3379 3371 3380 c3 = cat(c3,getregs(mDI | mCX)); 3372 3381 if (I16 && config.flags4 & CFG4speed) // if speed optimization 3373 3382 { 3374 3383 c3 = cat(c3,getregs(mAX)); 3375 3384 c3 = gen2(c3,0x8A,modregrm(3,AH,AL)); // MOV AH,AL 3376 3385 gen2(c3,0xD1,modregrm(3,5,CX)); // SHR CX,1 3377 3386 gen1(c3,0xF3); // REP 3378 3387 gen1(c3,0xAB); // STOSW 3379 3388 gen2(c3,0x11,modregrm(3,CX,CX)); // ADC CX,CX 3380 3389 op = 0xAA; 3381 3390 } 3382 3391 3383 3392 c3 = gen1(c3,0xF3); // REP 3384 3393 gen1(c3,op); // STOSD 3394 m = buildModregrm(2,AX,reg); 3385 3395 if (remainder & 4) 3386 3396 { 3387 3397 code *ctmp; 3388 ctmp = gen2(CNIL,0x89,m odregrmx(2,AX,reg));3398 ctmp = gen2(CNIL,0x89,m); 3389 3399 ctmp->IFL1 = FLconst; 3390 3400 c3 = cat(c3,ctmp); 3391 3401 } 3392 3402 if (remainder & 2) 3393 3403 { 3394 3404 code *ctmp; 3395 ctmp = gen2(CNIL,0x89,m odregrmx(2,AX,reg));3405 ctmp = gen2(CNIL,0x89,m); 3396 3406 ctmp->Iflags = CFopsize; 3397 3407 ctmp->IEVoffset1 = remainder & 4; 3398 3408 ctmp->IFL1 = FLconst; 3399 3409 c3 = cat(c3,ctmp); 3400 3410 } 3401 3411 if (remainder & 1) 3402 3412 { 3403 3413 code *ctmp; 3404 ctmp = gen2(CNIL,0x88,m odregrmx(2,AX,reg));3414 ctmp = gen2(CNIL,0x88,m); 3405 3415 ctmp->IEVoffset1 = remainder & ~1; 3406 3416 ctmp->IFL1 = FLconst; 3407 3417 c3 = cat(c3,ctmp); 3408 3418 } 3409 3419 regimmed_set(CX,0); 3410 3420 return cat4(c1,c2,c3,fixresult(e,mES|mBX,pretregs)); 3411 3421 } 3412 3422 #else 3413 3423 // BUG: Pat made many improvements in the linux version, I need 3414 3424 // to verify they work for 16 bits and fold them in. -Walter 3415 3425 3416 3426 code *cdmemset(elem *e,regm_t *pretregs) 3417 3427 { code *c1,*c2,*c3 = NULL,*c4; 3418 3428 regm_t retregs1; 3419 3429 regm_t retregs2; 3420 3430 regm_t retregs3; 3421 3431 tym_t ty1; 3422 3432 elem *e2; 3423 3433 targ_size_t value; 3424 3434 … … 4143 4153 } 4144 4154 else 4145 4155 assert(0); 4146 4156 return cat4(c1,cg,c,fixresult(e,retregs,pretregs)); 4147 4157 } 4148 4158 4149 4159 /************************** 4150 4160 * Post increment and post decrement. 4151 4161 */ 4152 4162 4153 4163 code *cdpost(elem *e,regm_t *pretregs) 4154 4164 { code cs,*c1,*c2,*c3,*c4,*c5,*c6; 4155 4165 unsigned reg,op,byte; 4156 4166 tym_t tyml; 4157 4167 regm_t retregs,possregs,idxregs; 4158 4168 targ_int n; 4159 4169 elem *e2; 4160 4170 int sz; 4161 4171 int stackpushsave; 4162 4172 4173 //printf("cdpost(pretregs = %s)\n", regm_str(*pretregs)); 4163 4174 retregs = *pretregs; 4164 4175 op = e->Eoper; /* OPxxxx */ 4165 4176 if (retregs == 0) /* if nothing to return */ 4166 4177 return cdaddass(e,pretregs); 4167 4178 c4 = c5 = CNIL; 4168 4179 tyml = tybasic(e->E1->Ety); 4169 4180 sz = tysize[tyml]; 4170 4181 e2 = e->E2; 4171 4182 unsigned rex = (I64 && sz == 8) ? REX_W : 0; 4172 4183 4173 4184 if (tyfloating(tyml)) 4174 4185 { 4175 4186 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 4176 4187 return post87(e,pretregs); 4177 4188 #else 4178 4189 if (config.inline8087) 4179 4190 return post87(e,pretregs); 4180 4191 assert(sz <= 8); 4181 4192 c1 = getlvalue(&cs,e->E1,DOUBLEREGS); 4182 4193 freenode(e->E1); … … 4283 4294 // LEA reg,n[reg] // don't affect flags 4284 4295 int rm; 4285 4296 4286 4297 reg = cs.Irm & 7; 4287 4298 if (cs.Irex & REX_B) 4288 4299 reg |= 8; 4289 4300 cs.Iop = 0x85 ^ byte; 4290 4301 code_newreg(&cs, reg); 4291 4302 cs.Iflags |= CFpsw; 4292 4303 c2 = gen(NULL,&cs); // TEST reg,reg 4293 4304 4294 4305 // If lvalue is a register variable, we must mark it as modified 4295 4306 c3 = modEA(&cs); 4296 4307 4297 4308 n = e2->EV.Vint; 4298 4309 if (op == OPpostdec) 4299 4310 n = -n; 4300 4311 rm = reg; 4301 4312 if (I16) 4302 4313 rm = regtorm[reg]; 4303 c4 = genc1(NULL,0x8D,(rex << 16) | modregxrmx(2,reg,rm),FLconst,n); // LEA reg,n[reg]4314 c4 = genc1(NULL,0x8D,(rex << 16) | buildModregrm(2,reg,rm),FLconst,n); // LEA reg,n[reg] 4304 4315 return cat4(c1,c2,c3,c4); 4305 4316 } 4306 4317 else if (sz <= REGSIZE || tyfv(tyml)) 4307 4318 { code cs2; 4308 4319 4309 4320 cs.Iop = 0x8B ^ byte; 4310 4321 retregs = possregs & ~idxregs & *pretregs; 4311 4322 if (!tyfv(tyml)) 4312 4323 { if (retregs == 0) 4313 4324 retregs = possregs & ~idxregs; 4314 4325 } 4315 4326 else /* tyfv(tyml) */ 4316 4327 { if ((retregs &= mLSW) == 0) 4317 4328 retregs = mLSW & ~idxregs; 4318 4329 /* Can't use LES if the EA uses ES as a seg override */ 4319 4330 if (*pretregs & mES && (cs.Iflags & CFSEG) != CFes) 4320 4331 { cs.Iop = 0xC4; /* LES */ 4321 4332 c1 = cat(c1,getregs(mES)); /* allocate ES */ 4322 4333 } 4323 4334 } … … 4685 4696 4686 4697 /**************************************** 4687 4698 * Check to see if pointer is NULL. 4688 4699 */ 4689 4700 4690 4701 code *cdnullcheck(elem *e,regm_t *pretregs) 4691 4702 { regm_t retregs; 4692 4703 regm_t scratch; 4693 4704 unsigned reg; 4694 4705 code *c; 4695 4706 code *cs; 4696 4707 4697 4708 assert(!I16); 4698 4709 retregs = *pretregs; 4699 4710 if ((retregs & allregs) == 0) 4700 4711 retregs |= allregs; 4701 4712 c = codelem(e->E1,&retregs,FALSE); 4702 4713 scratch = allregs & ~retregs; 4703 4714 cs = allocreg(&scratch,®,TYint); 4704 4715 unsigned rex = I64 ? REX_W : 0; 4705 cs = genc1(cs,0x8B,(rex << 16) | modregxrmx(2,reg,findreg(retregs)),FLconst,0); // MOV reg,0[e]4716 cs = genc1(cs,0x8B,(rex << 16) | buildModregrm(2,reg,findreg(retregs)),FLconst,0); // MOV reg,0[e] 4706 4717 return cat3(c,cs,fixresult(e,retregs,pretregs)); 4707 4718 } 4708 4719 4709 4720 #endif // !SPP trunk/src/backend/cod3.c
r767 r768 2299 2299 ADD p[ESP],d 2300 2300 For direct call: 2301 2301 JMP sfunc 2302 2302 For virtual call: 2303 2303 MOV EAX, p[ESP] EAX = this 2304 2304 MOV EAX, d2[EAX] EAX = this->vptr 2305 2305 JMP i[EAX] jump to virtual function 2306 2306 */ 2307 2307 unsigned reg = 0; 2308 2308 if ((targ_ptrdiff_t)d < 0) 2309 2309 { 2310 2310 d = -d; 2311 2311 reg = 5; // switch from ADD to SUB 2312 2312 } 2313 2313 if (thunkty == TYmfunc) 2314 2314 { // ADD ECX,d 2315 2315 c = CNIL; 2316 2316 if (d) 2317 2317 c = genc2(c,0x81,modregrm(3,reg,CX),d); 2318 2318 } 2319 else if (thunkty == TYjfunc )2319 else if (thunkty == TYjfunc || (I64 && thunkty == TYnfunc)) 2320 2320 { // ADD EAX,d 2321 2321 c = CNIL; 2322 2322 if (d) 2323 2323 c = genc2(c,0x81,modregrm(3,reg,I64 ? DI : AX),d); 2324 2324 } 2325 2325 else 2326 2326 { 2327 2327 c = genc(CNIL,0x81,modregrm(2,reg,4), 2328 2328 FLconst,p, // to this 2329 2329 FLconst,d); // ADD p[ESP],d 2330 2330 c->Isib = modregrm(0,4,SP); 2331 2331 } 2332 2332 if (I64) 2333 2333 c->Irex |= REX_W; 2334 2334 } 2335 2335 else 2336 2336 { 2337 2337 /* 2338 2338 Generate: 2339 2339 MOV BX,SP … … 3428 3428 config.target_cpu >= TARGET_80486) 3429 3429 { 3430 3430 c->Iop &= 1; 3431 3431 c->Irm = (rm & modregrm(3,0,7)) | (ereg << 3); 3432 3432 if (c->Irex & REX_B) 3433 3433 c->Irex |= REX_R; 3434 3434 if (!(c->Iflags & CFpsw) && !I16) 3435 3435 c->Iflags &= ~CFopsize; 3436 3436 goto L1; 3437 3437 } 3438 3438 3439 3439 /* Look for sign extended modregrm displacement, or 0 3440 3440 * displacement. 3441 3441 */ 3442 3442 3443 3443 if (((rm & 0xC0) == 0x80) && // it's a 16/32 bit disp 3444 3444 c->IFL1 == FLconst) // and it's a constant 3445 3445 { 3446 3446 a = c->IEVpointer1; 3447 3447 if (a == 0 && (rm & 7) != local_BPRM && // if 0[disp] 3448 !(local_BPRM == 5 && (rm & 7) == 4 && (c->Isib & 7) == BP && !(c->Irex & REX_B))3448 !(local_BPRM == 5 && (rm & 7) == 4 && (c->Isib & 7) == BP) 3449 3449 ) 3450 3450 c->Irm &= 0x3F; 3451 3451 else if (!I16) 3452 3452 { 3453 3453 if ((targ_size_t)(targ_schar)a == a) 3454 3454 c->Irm ^= 0xC0; /* do 8 sx */ 3455 3455 } 3456 3456 else if (((targ_size_t)(targ_schar)a & 0xFFFF) == (a & 0xFFFF)) 3457 3457 c->Irm ^= 0xC0; /* do 8 sx */ 3458 3458 } 3459 3459 3460 3460 /* Look for LEA reg,[ireg], replace with MOV reg,ireg */ 3461 3461 else if (op == 0x8D) 3462 3462 { rm = c->Irm & 7; 3463 3463 mod = c->Irm & modregrm(3,0,0); 3464 3464 if (mod == 0) 3465 3465 { 3466 3466 if (!I16) 3467 3467 { 3468 3468 switch (rm) … … 5257 5257 break; 5258 5258 case FLswitch: 5259 5259 case FLblockoff: 5260 5260 case FLlocalsize: 5261 5261 case FLframehandler: 5262 5262 case 0: 5263 5263 break; 5264 5264 case FLdatseg: 5265 5265 printf(" %d.%llx",c->IEVseg1,(unsigned long long)c->IEVpointer1); 5266 5266 break; 5267 5267 case FLauto: 5268 5268 case FLreg: 5269 5269 case FLdata: 5270 5270 case FLudata: 5271 5271 case FLpara: 5272 5272 case FLtmp: 5273 5273 case FLbprel: 5274 5274 case FLtlsdata: 5275 5275 printf(" sym='%s'",c->IEVsym1->Sident); 5276 5276 break; 5277 case FLextern: 5278 printf(" FLextern offset = %4d",(int)c->IEVoffset1); 5279 break; 5277 5280 default: 5278 5281 WRFL((enum FL)c->IFL1); 5279 5282 break; 5280 5283 } 5281 5284 } 5282 5285 } 5283 5286 if (ins & T) 5284 5287 { printf(" "); WRFL((enum FL)c->IFL2); 5285 5288 switch (c->IFL2) 5286 5289 { 5287 5290 case FLconst: 5288 5291 printf(" int = %4d",c->IEV2.Vuns); 5289 5292 break; 5290 5293 case FLblock: 5291 5294 printf(" block = %p",c->IEV2.Vblock); 5292 5295 break; 5293 5296 case FLswitch: 5294 5297 case FLblockoff: 5295 5298 case 0: 5296 5299 case FLlocalsize: trunk/src/backend/cod4.c
r767 r768 346 346 if (!(retregs == 0 && 347 347 (e2oper == OPconst || e2oper == OPvar || e2oper == OPind)) 348 348 ) 349 349 return eq87(e,pretregs); 350 350 if (config.target_cpu >= TARGET_PentiumPro && 351 351 (e2oper == OPvar || e2oper == OPind) 352 352 ) 353 353 return eq87(e,pretregs); 354 354 if (tyml == TYldouble || tyml == TYildouble) 355 355 return eq87(e,pretregs); 356 356 } 357 357 358 358 unsigned sz = tysize[tyml]; // # of bytes to transfer 359 359 assert((int)sz > 0); 360 360 361 361 if (retregs == 0) /* if no return value */ 362 362 { int fl; 363 363 364 364 if ((e2oper == OPconst || /* if rvalue is a constant */ 365 365 e2oper == OPrelconst && 366 !(I64 && config.flags3 & CFG3pic) && 366 367 ((fl = el_fl(e2)) == FLdata || 367 368 fl==FLudata || fl == FLextern) && 368 369 !(e2->EV.sp.Vsym->ty() & mTYcs) 369 370 ) && 370 371 !evalinregister(e2) && 371 372 !e1->Ecount) /* and no CSE headaches */ 372 373 { 373 374 // Look for special case of (*p++ = ...), where p is a register variable 374 375 if (e1->Eoper == OPind && 375 376 ((e11 = e1->E1)->Eoper == OPpostinc || e11->Eoper == OPpostdec) && 376 377 e11->E1->Eoper == OPvar && 377 378 e11->E1->EV.sp.Vsym->Sfl == FLreg && 378 379 (!I16 || e11->E1->EV.sp.Vsym->Sregm & IDXREGS) 379 380 ) 380 381 { 381 382 postinc = e11->E2->EV.Vint; 382 383 if (e11->Eoper == OPpostdec) 383 384 postinc = -postinc; 384 385 cl = getlvalue(&cs,e11,RMstore); 385 386 freenode(e11->E2); 386 387 } 387 388 else 388 389 { postinc = 0; 389 390 cl = getlvalue(&cs,e1,RMstore); 390 391 391 392 if (e2oper == OPconst && 392 393 config.flags4 & CFG4speed && 393 394 (config.target_cpu == TARGET_Pentium || 394 395 config.target_cpu == TARGET_PentiumMMX) && 395 396 (cs.Irm & 0xC0) == 0x80 396 397 ) 397 398 { 398 399 if (I64 && sz == 8 && e2->EV.Vpointer) 399 400 { 400 401 // MOV reg,imm64 401 402 // MOV EA,reg 402 403 regm_t rregm = allregs & ~idxregm(&cs); 403 404 unsigned reg; 404 cl = regwithvalue(cl,rregm,e2->EV.Vpointer,®, CFoffset64);405 cl = regwithvalue(cl,rregm,e2->EV.Vpointer,®,64); 405 406 cs.Iop = 0x89; 406 407 cs.Irm |= modregrm(0,reg & 7,0); 407 408 if (reg & 8) 408 409 cs.Irex |= REX_R; 409 410 c = gen(cl,&cs); 410 411 freenode(e2); 411 412 goto Lp; 412 413 } 413 414 if ((sz == REGSIZE || (I64 && sz == 4)) && e2->EV.Vint) 414 415 { 415 416 // MOV reg,imm 416 417 // MOV EA,reg 417 418 regm_t rregm = allregs & ~idxregm(&cs); 418 419 unsigned reg; 419 420 cl = regwithvalue(cl,rregm,e2->EV.Vint,®,0); 420 421 cs.Iop = 0x89; 421 422 cs.Irm |= modregrm(0,reg & 7,0); 422 423 if (reg & 8) 423 424 cs.Irex |= REX_R; 424 425 c = gen(cl,&cs); … … 475 476 else 476 477 { 477 478 assert(e2oper == OPconst); 478 479 cs.IFL2 = FLconst; 479 480 targ_size_t *p = (targ_size_t *) &(e2->EV); 480 481 cs.IEV2.Vsize_t = *p; 481 482 // Look for loading a register variable 482 483 if ((cs.Irm & 0xC0) == 0xC0) 483 484 { unsigned reg = cs.Irm & 7; 484 485 485 486 if (cs.Irex & REX_B) 486 487 reg |= 8; 487 488 if (I64 && sz == 8) 488 489 cl = movregconst(cl,reg,*p,CFoffset64); 489 490 else 490 491 cl = movregconst(cl,reg,*p,1 ^ (cs.Iop & 1)); 491 492 if (sz == 2 * REGSIZE) 492 493 { getlvalue_msw(&cs); 493 494 cl = movregconst(cl,cs.Irm & 7,p[1],0); 494 495 } 496 } 497 else if (I64 && sz == 8 && *p != *(unsigned *)p) 498 { 499 // MOV reg,imm64 500 // MOV EA,reg 501 regm_t rregm = allregs & ~idxregm(&cs); 502 unsigned reg; 503 cl = regwithvalue(cl,rregm,e2->EV.Vpointer,®,64); 504 cs.Iop = 0x89; 505 cs.Irm |= modregrm(0,reg & 7,0); 506 if (reg & 8) 507 cs.Irex |= REX_R; 508 c = gen(cl,&cs); 509 freenode(e2); 510 goto Lp; 495 511 } 496 512 else 497 513 { int regsize; 498 514 499 515 i = sz; 500 516 do 501 517 { regsize = REGSIZE; 502 518 retregs = (sz == 1) ? BYTEREGS : allregs; 503 519 if (i >= 4 && I16 && I386) 504 520 { 505 521 regsize = 4; 506 522 cs.Iflags |= CFopsize; // use opsize to do 32 bit operation 507 523 } 508 524 else 509 525 { 510 526 if (reghasvalue(retregs,*p,®)) 511 527 { 512 528 cs.Iop = (cs.Iop & 1) | 0x88; 513 529 cs.Irm |= modregrm(0,reg & 7,0); // MOV EA,reg 514 530 if (reg & 8) … … 673 689 } 674 690 if (e1->Ecount || /* if lvalue is a CSE or */ 675 691 regvar) /* rvalue can't be a CSE */ 676 692 { 677 693 c = cat(c,getregs_imm(retregs)); // necessary if both lvalue and 678 694 // rvalue are CSEs (since a reg 679 695 // can hold only one e at a time) 680 696 cssave(e1,retregs,EOP(e1)); /* if lvalue is a CSE */ 681 697 } 682 698 683 699 c = cat4(cr,cl,c,fixresult(e,retregs,pretregs)); 684 700 Lp: 685 701 if (postinc) 686 702 { 687 703 int reg = findreg(idxregm(&cs)); 688 704 if (*pretregs & mPSW) 689 705 { // Use LEA to avoid touching the flags 690 706 unsigned rm = cs.Irm & 7; 691 707 if (cs.Irex & REX_B) 692 708 rm |= 8; 693 c = genc1(c,0x8D, modregxrmx(2,reg,rm),FLconst,postinc);709 c = genc1(c,0x8D,buildModregrm(2,reg,rm),FLconst,postinc); 694 710 if (sz == 8) 695 711 code_orrex(c, REX_W); 696 712 } 697 713 else if (I64) 698 714 { 699 715 c = genc2(c,0x81,modregrmx(3,0,reg),postinc); 700 716 if (sz == 8) 701 717 code_orrex(c, REX_W); 702 718 } 703 719 else 704 720 { 705 721 if (postinc == 1) 706 722 c = gen1(c,0x40 + reg); // INC reg 707 723 else if (postinc == -(targ_int)1) 708 724 c = gen1(c,0x48 + reg); // DEC reg 709 725 else 710 726 { 711 727 c = genc2(c,0x81,modregrm(3,0,reg),postinc); 712 728 } 713 729 } … … 1817 1833 if (I64 && byte && (reg >= 4 || rreg >= 4)) 1818 1834 c->Irex |= REX; // address byte registers 1819 1835 } 1820 1836 else 1821 1837 { assert(sz <= 2 * REGSIZE); 1822 1838 1823 1839 /* Compare MSW, if they're equal then compare the LSW */ 1824 1840 reg = findregmsw(retregs); 1825 1841 rreg = findregmsw(rretregs); 1826 1842 c = genregs(CNIL,0x3B ^ reverse,reg,rreg); /* CMP reg,rreg */ 1827 1843 if (!I16 && sz == 6) 1828 1844 c->Iflags |= CFopsize; /* seg is only 16 bits */ 1829 1845 genjmp(c,JNE,FLcode,(block *) ce); /* JNE nop */ 1830 1846 1831 1847 reg = findreglsw(retregs); 1832 1848 rreg = findreglsw(rretregs); 1833 1849 genregs(c,0x3B ^ reverse,reg,rreg); /* CMP reg,rreg */ 1834 1850 } 1835 1851 break; 1836 1852 case OPrelconst: 1853 if (I64 && config.flags3 & CFG3pic) 1854 goto L2; 1837 1855 fl = el_fl(e2); 1838 1856 switch (fl) 1839 1857 { case FLfunc: 1840 1858 fl = FLextern; // so it won't be self-relative 1841 1859 break; 1842 1860 case FLdata: 1843 1861 case FLudata: 1844 1862 case FLextern: 1845 1863 if (sz > REGSIZE) // compare against DS, not DGROUP 1846 1864 goto L2; 1847 1865 break; 1848 1866 case FLfardata: 1849 1867 break; 1850 1868 default: 1851 1869 goto L2; 1852 1870 } 1853 1871 cs.IFL2 = fl; 1854 1872 cs.IEVsym2 = e2->EV.sp.Vsym; 1855 1873 offset2 = e2->EV.sp.Voffset; 1856 1874 if (sz > REGSIZE) trunk/src/backend/code.h
r738 r768 635 635 #else 636 636 code *allocreg (regm_t *pretregs , unsigned *preg , tym_t tym ); 637 637 #endif 638 638 void useregs (regm_t regm ); 639 639 code *getregs (regm_t r ); 640 640 code *getregs_imm (regm_t r ); 641 641 code *cse_flush(int); 642 642 void cssave (elem *e , regm_t regm , unsigned opsflag ); 643 643 bool evalinregister (elem *e ); 644 644 regm_t getscratch(); 645 645 code *codelem (elem *e , regm_t *pretregs , bool constflag ); 646 646 const char *regm_str(regm_t rm); 647 647 int numbitsset(regm_t); 648 648 649 649 /* cod1.c */ 650 650 extern int clib_inited; 651 651 652 652 int isscaledindex(elem *); 653 653 int ssindex(int op,targ_uns product); 654 654 void buildEA(code *c,int base,int index,int scale,targ_size_t disp); 655 unsigned buildModregrm(int mod, int reg, int rm); 655 656 void andregcon (con_t *pregconsave); 656 657 code *docommas (elem **pe ); 657 658 code *gencodelem(code *c,elem *e,regm_t *pretregs,bool constflag); 658 659 void gensaverestore(regm_t, code **, code **); 659 660 code *genstackclean(code *c,unsigned numpara,regm_t keepmsk); 660 661 code *logexp (elem *e , int jcond , unsigned fltarg , code *targ ); 661 662 code *loadea (elem *e , code *cs , unsigned op , unsigned reg , targ_size_t offset , regm_t keepmsk , regm_t desmsk ); 662 663 unsigned getaddrmode (regm_t idxregs ); 663 664 void setaddrmode(code *c, regm_t idxregs); 664 665 void getlvalue_msw(code *); 665 666 void getlvalue_lsw(code *); 666 667 code *getlvalue (code *pcs , elem *e , regm_t keepmsk ); 667 668 code *scodelem (elem *e , regm_t *pretregs , regm_t keepmsk , bool constflag ); 668 669 code *fltregs (code *pcs , tym_t tym ); 669 670 code *tstresult (regm_t regm , tym_t tym , unsigned saveflag ); 670 671 code *fixresult (elem *e , regm_t retregs , regm_t *pretregs ); 671 672 code *callclib (elem *e , unsigned clib , regm_t *pretregs , regm_t keepmask ); 672 673 cd_t cdfunc; 673 674 cd_t cdstrthis; 674 675 code *params(elem *, unsigned); trunk/src/backend/el.c
r738 r768 3205 3205 } 3206 3206 WROP(e->Eoper); 3207 3207 dbg_printf(" "); 3208 3208 if (SCPP && PARSER) 3209 3209 { 3210 3210 if (e->ET) 3211 3211 { type_debug(e->ET); 3212 3212 if (tybasic(e->ET->Tty) == TYstruct 3213 3213 #if !TX86 3214 3214 && (e->PEFflags & PEFstrsize) 3215 3215 #endif 3216 3216 ) 3217 3217 dbg_printf("%d ", (int)type_size(e->ET)); 3218 3218 WRTYxx(e->ET->Tty); 3219 3219 } 3220 3220 } 3221 3221 else 3222 3222 { 3223 3223 if ((e->Eoper == OPstrpar || e->Eoper == OPstrctor || e->Eoper == OPstreq) || 3224 3224 e->Ety == TYstruct) 3225 dbg_printf("%d ", (int)type_size(e->ET)); 3225 if (e->ET) 3226 dbg_printf("%d ", (int)type_size(e->ET)); 3226 3227 WRTYxx(e->Ety); 3227 3228 } 3228 3229 if (OTunary(e->Eoper)) 3229 3230 { 3230 3231 if (e->E2) 3231 3232 dbg_printf("%p %p\n",e->E1,e->E2); 3232 3233 else 3233 3234 dbg_printf("%p\n",e->E1); 3234 3235 elem_print(e->E1); 3235 3236 } 3236 3237 else if (OTbinary(e->Eoper)) 3237 3238 { 3238 3239 if (!PARSER && e->Eoper == OPstreq) 3239 3240 dbg_printf("bytes=%d ", (int)type_size(e->ET)); 3240 3241 dbg_printf("%p %p\n",e->E1,e->E2); 3241 3242 elem_print(e->E1); 3242 3243 elem_print(e->E2); 3243 3244 } 3244 3245 else 3245 3246 { trunk/src/backend/gloop.c
r738 r768 2134 2134 c.Vchar = 1; 2135 2135 break; 2136 2136 case TYshort: 2137 2137 case TYushort: 2138 2138 case TYchar16: 2139 2139 case TYwchar_t: // BUG: what about 4 byte wchar_t's? 2140 2140 c.Vshort = 1; 2141 2141 break; 2142 2142 #if TX86 2143 2143 case TYsptr: 2144 2144 case TYcptr: 2145 2145 #if JHANDLE 2146 2146 case TYjhandle: 2147 2147 #endif 2148 2148 case TYnptr: 2149 2149 #endif 2150 2150 case TYnullptr: 2151 2151 case TYfptr: 2152 2152 case TYvptr: 2153 2153 ty = TYint; 2154 if (I64) 2155 ty = TYllong; 2154 2156 /* FALL-THROUGH */ 2155 2157 case TYint: 2156 2158 case TYuint: 2157 2159 c.Vint = 1; 2158 2160 break; 2159 2161 #if TX86 2160 2162 case TYhptr: 2161 2163 ty = TYlong; 2162 2164 #endif 2163 2165 case TYlong: 2164 2166 case TYulong: 2165 2167 case TYdchar: 2166 2168 default: 2167 2169 c.Vlong = 1; 2168 2170 break; 2169 2171 #if 0 2170 2172 default: 2171 2173 printf("ty = x%x\n", tybasic(ty)); 2172 2174 assert(0); 2173 2175 #endif trunk/src/e2ir.c
r767 r768 3309 3309 if (!func->isThis()) 3310 3310 error("delegates are only for non-static functions"); 3311 3311 3312 3312 if (!func->isVirtual() || 3313 3313 directcall || 3314 3314 func->isFinal()) 3315 3315 { 3316 3316 ep = el_ptr(sfunc); 3317 3317 } 3318 3318 else 3319 3319 { 3320 3320 // Get pointer to function out of virtual table 3321 3321 unsigned vindex; 3322 3322 3323 3323 assert(ethis); 3324 3324 ep = el_same(ðis); 3325 3325 ep = el_una(OPind, TYnptr, ep); 3326 3326 vindex = func->vtblIndex; 3327 3327 3328 3328 // Build *(ep + vindex * 4) 3329 ep = el_bin(OPadd,TYnptr,ep,el_long(TYsize_t, vindex * 4));3329 ep = el_bin(OPadd,TYnptr,ep,el_long(TYsize_t, vindex * PTRSIZE)); 3330 3330 ep = el_una(OPind,TYnptr,ep); 3331 3331 } 3332 3332 3333 3333 // if (func->tintro) 3334 3334 // func->error(loc, "cannot form delegate due to covariant return type"); 3335 3335 } 3336 3336 if (ethis->Eoper == OPcomma) 3337 3337 { 3338 3338 ethis->E2 = el_pair(TYdelegate, ethis->E2, ep); 3339 3339 ethis->Ety = TYdelegate; 3340 3340 e = ethis; 3341 3341 } 3342 3342 else 3343 3343 e = el_pair(TYdelegate, ethis, ep); 3344 3344 el_setLoc(e,loc); 3345 3345 return e; 3346 3346 } 3347 3347 3348 3348 elem *DotTypeExp::toElem(IRState *irs) 3349 3349 { trunk/src/msc.c
r729 r768 309 309 { 310 310 int sz = (tybasic(ty) == TYvoid) ? 1 : tysize(ty); 311 311 #ifdef DEBUG 312 312 if (sz == -1) 313 313 WRTYxx(ty); 314 314 #endif 315 315 assert(sz!= -1); 316 316 return sz; 317 317 } 318 318 319 319 /******************************* 320 320 * Replace (e) with ((stmp = e),stmp) 321 321 */ 322 322 323 323 elem *exp2_copytotemp(elem *e) 324 324 { 325 325 //printf("exp2_copytotemp()\n"); 326 326 elem_debug(e); 327 327 Symbol *stmp = symbol_genauto(e); 328 328 elem *eeq = el_bin(OPeq,e->Ety,el_var(stmp),e); 329 if (e->Ety == TYstruct) 329 elem *er = el_bin(OPcomma,e->Ety,eeq,el_var(stmp)); 330 if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray) 330 331 { 331 332 eeq->Eoper = OPstreq; 332 333 eeq->ET = e->ET; 333 } 334 return el_bin(OPcomma,e->Ety,eeq,el_var(stmp)); 334 eeq->E1->ET = e->ET; 335 er->ET = e->ET; 336 er->E2->ET = e->ET; 337 } 338 return er; 335 339 } 336 340 337 341 /**************************** 338 342 * Generate symbol of type ty at DATA:offset 339 343 */ 340 344 341 345 symbol *symboldata(targ_size_t offset,tym_t ty) 342 346 { 343 347 symbol *s = symbol_generate(SClocstat, type_fake(ty)); 344 348 s->Sfl = FLdata; 345 349 s->Soffset = offset; 346 350 s->Sseg = DATA; 347 351 symbol_keep(s); // keep around 348 352 return s; 349 353 } 350 354 351 355 /************************************ 352 356 * Add symbol to slist. 353 357 */ 354 358 trunk/src/mtype.h
r767 r768 156 156 #define tfloat80 basic[Tfloat80] 157 157 158 158 #define timaginary32 basic[Timaginary32] 159 159 #define timaginary64 basic[Timaginary64] 160 160 #define timaginary80 basic[Timaginary80] 161 161 162 162 #define tcomplex32 basic[Tcomplex32] 163 163 #define tcomplex64 basic[Tcomplex64] 164 164 #define tcomplex80 basic[Tcomplex80] 165 165 166 166 #define tbit basic[Tbit] 167 167 #define tbool basic[Tbool] 168 168 #define tchar basic[Tchar] 169 169 #define twchar basic[Twchar] 170 170 #define tdchar basic[Tdchar] 171 171 172 172 // Some special types 173 173 #define tshiftcnt tint32 // right side of shift expression 174 174 // #define tboolean tint32 // result of boolean expression 175 175 #define tboolean tbool // result of boolean expression 176 #define tindex t int32// array/ptr index176 #define tindex tsize_t // array/ptr index 177 177 static Type *tvoidptr; // void* 178 178 static Type *tstring; // immutable(char)[] 179 179 #define terror basic[Terror] // for error recovery 180 180 181 181 #define tsize_t basic[Tsize_t] // matches size_t alias 182 182 #define tptrdiff_t basic[Tptrdiff_t] // matches ptrdiff_t alias 183 183 #define thash_t tsize_t // matches hash_t alias 184 184 185 185 static ClassDeclaration *typeinfo; 186 186 static ClassDeclaration *typeinfoclass; 187 187 static ClassDeclaration *typeinfointerface; 188 188 static ClassDeclaration *typeinfostruct; 189 189 static ClassDeclaration *typeinfotypedef; 190 190 static ClassDeclaration *typeinfopointer; 191 191 static ClassDeclaration *typeinfoarray; 192 192 static ClassDeclaration *typeinfostaticarray; 193 193 static ClassDeclaration *typeinfoassociativearray; 194 194 static ClassDeclaration *typeinfoenum; 195 195 static ClassDeclaration *typeinfofunction; 196 196 static ClassDeclaration *typeinfodelegate; trunk/src/template.c
r754 r768 4068 4068 --nest; 4069 4069 #if WINDOWS_SEH 4070 4070 } 4071 4071 __except (__ehfilter(GetExceptionInformation())) 4072 4072 { 4073 4073 global.gag = 0; // ensure error message gets printed 4074 4074 error("recursive expansion"); 4075 4075 fatal(); 4076 4076 } 4077 4077 #endif 4078 4078 } 4079 4079 4080 4080 Laftersemantic: 4081 4081 sc2->pop(); 4082 4082 4083 4083 scope->pop(); 4084 4084 4085 4085 // Give additional context info if error occurred during instantiation 4086 4086 if (global.errors != errorsave) 4087 4087 { 4088 error( "error instantiating");4088 error(loc, "error instantiating"); 4089 4089 if (tinst) 4090 4090 { tinst->printInstantiationTrace(); 4091 4091 } 4092 4092 errors = 1; 4093 4093 if (global.gag) 4094 4094 { // Try to reset things so we can try again later to instantiate it 4095 4095 tempdecl->instances.remove(tempdecl_instance_idx); 4096 4096 if (!(sc->flags & SCOPEstaticif)) 4097 4097 { // Bugzilla 4302 for discussion 4098 4098 semanticRun = 0; 4099 4099 inst = NULL; 4100 4100 } 4101 4101 } 4102 4102 } 4103 4103 4104 4104 #if LOG 4105 4105 printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 4106 4106 #endif 4107 4107 } 4108 4108
