Changeset 770
- Timestamp:
- 11/29/10 03:41:47 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cgen.c (modified) (5 diffs)
- branches/dmd-1.x/src/backend/cod1.c (modified) (1 diff)
- trunk/src/backend/cod1.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cgen.c
r738 r770 8 8 * only. The license is in /dmd/src/dmd/backendlicense.txt 9 9 * or /dm/src/dmd/backendlicense.txt 10 10 * For any other uses, please contact Digital Mars. 11 11 */ 12 12 13 13 #if !SPP 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 17 #include <time.h> 18 18 #include "cc.h" 19 19 #include "el.h" 20 20 #include "oper.h" 21 21 #include "code.h" 22 22 #include "type.h" 23 23 #include "global.h" 24 24 25 25 static char __file__[] = __FILE__; /* for tassert.h */ 26 26 #include "tassert.h" 27 27 28 /************************************* 29 * Handy function to answer the question: who the heck is generating this piece of code? 30 */ 31 inline void ccheck(code *cs) 32 { 33 // if (cs->Iop == LEA && (cs->Irm & 0x3F) == 0x34 && cs->Isib == 7) *(char*)0=0; 34 } 35 28 36 /***************************** 29 37 * Find last code in list. 30 38 */ 31 39 32 40 code *code_last(code *c) 33 41 { 34 42 if (c) 35 43 { while (c->next) 36 44 c = c->next; 37 45 } 38 46 return c; 39 47 } 40 48 41 49 /***************************** 42 50 * Set flag bits on last code in list. 43 51 */ 44 52 45 53 void code_orflag(code *c,unsigned flag) 46 54 { 47 55 if (flag && c) … … 145 153 * Note that unused operands are garbage. 146 154 * gen1() and gen2() are shortcut routines. 147 155 * Input: 148 156 * c -> linked list that code is to be added to end of 149 157 * cs -> data for the code 150 158 * Returns: 151 159 * pointer to start of code list 152 160 */ 153 161 154 162 code *gen(code *c,code *cs) 155 163 { code *ce,*cstart; 156 164 unsigned reg; 157 165 158 166 #ifdef DEBUG /* this is a high usage routine */ 159 167 assert(cs); 160 168 #endif 161 169 assert(I64 || cs->Irex == 0); 162 170 ce = code_calloc(); 163 171 *ce = *cs; 164 172 //printf("ce = %p %02x\n", ce, ce->Iop); 165 if (ce->Iop == LEA && ce->Irm == 4 && ce->Isib == 0x6D && ce->IFL1 == FLunde) *(char*)0=0;173 ccheck(ce); 166 174 if (config.flags4 & CFG4optimized && 167 175 ce->IFL2 == FLconst && 168 176 (ce->Iop == 0x81 || ce->Iop == 0x80) && 169 177 reghasvalue((ce->Iop == 0x80) ? BYTEREGS : ALLREGS,ce->IEV2.Vlong,®) && 170 178 !(ce->Iflags & CFopsize && I16) 171 179 ) 172 180 { // See if we can replace immediate instruction with register instruction 173 181 static unsigned char regop[8] = 174 182 { 0x00,0x08,0x10,0x18,0x20,0x28,0x30,0x38 }; 175 183 176 184 //printf("replacing 0x%02x, val = x%lx\n",ce->Iop,ce->IEV2.Vlong); 177 185 ce->Iop = regop[(ce->Irm & modregrm(0,7,0)) >> 3] | (ce->Iop & 1); 178 186 code_newreg(ce, reg); 179 187 } 180 188 code_next(ce) = CNIL; 181 189 if (c) 182 190 { cstart = c; 183 191 while (code_next(c)) c = code_next(c); /* find end of list */ 184 192 code_next(c) = ce; /* link into list */ 185 193 return cstart; … … 192 200 193 201 ce = code_calloc(); 194 202 ce->Iop = op; 195 203 assert(op != LEA); 196 204 if (c) 197 205 { cstart = c; 198 206 while (code_next(c)) c = code_next(c); /* find end of list */ 199 207 code_next(c) = ce; /* link into list */ 200 208 return cstart; 201 209 } 202 210 return ce; 203 211 } 204 212 205 213 code *gen2(code *c,unsigned op,unsigned rm) 206 214 { code *ce,*cstart; 207 215 208 216 cstart = ce = code_calloc(); 209 217 /*cxcalloc++;*/ 210 218 ce->Iop = op; 211 219 ce->Iea = rm; 220 ccheck(ce); 212 221 if (c) 213 222 { cstart = c; 214 223 while (code_next(c)) c = code_next(c); /* find end of list */ 215 224 code_next(c) = ce; /* link into list */ 216 225 } 217 226 return cstart; 218 227 } 219 228 220 229 code *gen2sib(code *c,unsigned op,unsigned rm,unsigned sib) 221 230 { code *ce,*cstart; 222 231 223 232 cstart = ce = code_calloc(); 224 233 /*cxcalloc++;*/ 225 if (op == LEA && (rm & 0xFF) == 4 && (sib & 0xFF) == 0x6D) *(char*)0=0;226 234 ce->Iop = op; 227 235 ce->Irm = rm; 228 236 ce->Isib = sib; 229 237 ce->Irex = (rm | (sib & (REX_B << 16))) >> 16; 230 238 if (sib & (REX_R << 16)) 231 239 ce->Irex |= REX_X; 240 ccheck(ce); 232 241 if (c) 233 242 { cstart = c; 234 243 while (code_next(c)) c = code_next(c); /* find end of list */ 235 244 code_next(c) = ce; /* link into list */ 236 245 } 237 246 return cstart; 238 247 } 239 248 240 249 code *genregs(code *c,unsigned op,unsigned dstreg,unsigned srcreg) 241 250 { return gen2(c,op,modregxrmx(3,dstreg,srcreg)); } 242 251 243 252 code *gentstreg(code *c,unsigned t) 244 253 { 245 254 c = gen2(c,0x85,modregxrmx(3,t,t)); // TEST t,t 246 255 code_orflag(c,CFpsw); 247 256 return c; 248 257 } 249 258 250 259 code *genpush(code *c, unsigned reg) 251 260 { … … 342 351 c = genjmp(c,JP,FLcode,(block *) cnop); 343 352 cat(cj,cnop); 344 353 break; 345 354 case 1 << 8: /* toggled no jump */ 346 355 case 0 << 8: 347 356 break; 348 357 default: 349 358 #ifdef DEBUG 350 359 printf("jop = x%x\n",op); 351 360 #endif 352 361 assert(0); 353 362 } 354 363 return cat(c,cj); 355 364 } 356 365 357 366 code *gencs(code *c,unsigned op,unsigned ea,unsigned FL2,symbol *s) 358 367 { code cs; 359 368 360 369 cs.Iop = op; 361 370 cs.Iea = ea; 371 ccheck(&cs); 362 372 cs.Iflags = 0; 363 373 cs.IFL2 = FL2; 364 374 cs.IEVsym2 = s; 365 375 cs.IEVoffset2 = 0; 366 376 367 377 return gen(c,&cs); 368 378 } 369 379 370 380 code *genc2(code *c,unsigned op,unsigned ea,targ_size_t EV2) 371 381 { code cs; 372 382 373 383 cs.Iop = op; 374 384 cs.Iea = ea; 385 ccheck(&cs); 375 386 cs.Iflags = CFoff; 376 387 cs.IFL2 = FLconst; 377 388 cs.IEV2.Vsize_t = EV2; 378 389 return gen(c,&cs); 379 390 } 380 391 381 392 /***************** 382 393 * Generate code. 383 394 */ 384 395 385 396 code *genc1(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1) 386 397 { code cs; 387 398 388 399 assert(FL1 < FLMAX); 389 400 cs.Iop = op; 390 401 cs.Iflags = CFoff; 391 402 cs.Iea = ea; 403 ccheck(&cs); 392 404 cs.IFL1 = FL1; 393 405 cs.IEV1.Vsize_t = EV1; 394 if (cs.Iop == LEA && cs.IFL1 == FLunde) *(char*)0=0;395 406 return gen(c,&cs); 396 407 } 397 408 398 409 /***************** 399 410 * Generate code. 400 411 */ 401 412 402 413 code *genc(code *c,unsigned op,unsigned ea,unsigned FL1,targ_size_t EV1,unsigned FL2,targ_size_t EV2) 403 414 { code cs; 404 415 405 416 assert(FL1 < FLMAX); 406 417 cs.Iop = op; 407 418 cs.Iea = ea; 419 ccheck(&cs); 408 420 cs.Iflags = CFoff; 409 421 cs.IFL1 = FL1; 410 422 cs.IEV1.Vsize_t = EV1; 411 423 assert(FL2 < FLMAX); 412 424 cs.IFL2 = FL2; 413 425 cs.IEV2.Vsize_t = EV2; 414 426 return gen(c,&cs); 415 427 } 416 428 417 429 /*************************************** 418 430 * Generate immediate multiply instruction for r1=r2*imm. 419 431 * Optimize it into LEA's if we can. 420 432 */ 421 433 422 434 code *genmulimm(code *c,unsigned r1,unsigned r2,targ_int imm) 423 435 { code cs; 424 436 425 437 // These optimizations should probably be put into pinholeopt() 426 438 switch (imm) 427 439 { case 1: … … 539 551 * set flags based on result 540 552 * Else if flags & 8 541 553 * do not disturb flags 542 554 * Else 543 555 * don't care about flags 544 556 * If flags & 1 then byte move 545 557 * If flags & 2 then short move (for I32 and I64) 546 558 * If flags & 4 then don't disturb unused portion of register 547 559 * If flags & 16 then reg is a byte register AL..BH 548 560 * If flags & 64 then 64 bit move (I64 only) 549 561 * Returns: 550 562 * code (if any) generated 551 563 */ 552 564 553 565 code *movregconst(code *c,unsigned reg,targ_size_t value,regm_t flags) 554 566 { unsigned r; 555 567 regm_t regm; 556 568 regm_t mreg; 557 569 targ_size_t regv; 558 570 571 //printf("movregconst(%llx)\n", value); 559 572 #define genclrreg(a,r) genregs(a,0x31,r,r) 560 573 561 574 regm = regcon.immed.mval & mask[reg]; 562 575 regv = regcon.immed.value[reg]; 563 576 564 577 if (flags & 1) // 8 bits 565 578 { unsigned msk; 566 579 567 580 value &= 0xFF; 568 581 regm &= BYTEREGS; 569 582 570 583 // If we already have the right value in the right register 571 584 if (regm && (regv & 0xFF) == value) 572 585 goto L2; 573 586 574 587 if (flags & 16 && reg & 4 && // if an H byte register 575 588 regcon.immed.mval & mask[reg & 3] && 576 589 (((regv = regcon.immed.value[reg & 3]) >> 8) & 0xFF) == value) 577 590 goto L2; 578 591 branches/dmd-1.x/src/backend/cod1.c
r768 r770 2948 2948 { if (mfuncreg == 0) /* if no registers left */ 2949 2949 { needframe = TRUE; 2950 2950 break; 2951 2951 } 2952 2952 } 2953 2953 } 2954 2954 } 2955 2955 } 2956 2956 } 2957 2957 #endif 2958 2958 2959 2959 retregs = regmask(e->Ety, tym1); 2960 2960 2961 2961 // If stack needs cleanup 2962 2962 if (OTbinary(e->Eoper) && 2963 2963 !typfunc(tym1) && 2964 2964 !(s && s->Sflags & SFLexit)) 2965 2965 { 2966 2966 if (tym1 == TYhfunc) 2967 2967 { // Hidden parameter is popped off by the callee 2968 c = genadjesp(c, - 4);2969 stackpush -= 4;2970 if (numpara + numalign > 4)2971 c = genstackclean(c, numpara + numalign - 4, retregs);2968 c = genadjesp(c, -REGSIZE); 2969 stackpush -= REGSIZE; 2970 if (numpara + numalign > REGSIZE) 2971 c = genstackclean(c, numpara + numalign - REGSIZE, retregs); 2972 2972 } 2973 2973 else 2974 2974 c = genstackclean(c,numpara + numalign,retregs); 2975 2975 } 2976 2976 else 2977 2977 { 2978 2978 c = genadjesp(c,-numpara); 2979 2979 stackpush -= numpara; 2980 2980 if (numalign) 2981 2981 c = genstackclean(c,numalign,retregs); 2982 2982 } 2983 2983 2984 2984 /* Special handling for functions which return a floating point 2985 2985 value in the top of the 8087 stack. 2986 2986 */ 2987 2987 2988 2988 if (retregs & mST0) 2989 2989 { 2990 2990 if (*pretregs) // if we want the result 2991 2991 { //assert(stackused == 0); trunk/src/backend/cod1.c
r768 r770 2948 2948 { if (mfuncreg == 0) /* if no registers left */ 2949 2949 { needframe = TRUE; 2950 2950 break; 2951 2951 } 2952 2952 } 2953 2953 } 2954 2954 } 2955 2955 } 2956 2956 } 2957 2957 #endif 2958 2958 2959 2959 retregs = regmask(e->Ety, tym1); 2960 2960 2961 2961 // If stack needs cleanup 2962 2962 if (OTbinary(e->Eoper) && 2963 2963 !typfunc(tym1) && 2964 2964 !(s && s->Sflags & SFLexit)) 2965 2965 { 2966 2966 if (tym1 == TYhfunc) 2967 2967 { // Hidden parameter is popped off by the callee 2968 c = genadjesp(c, - 4);2969 stackpush -= 4;2970 if (numpara + numalign > 4)2971 c = genstackclean(c, numpara + numalign - 4, retregs);2968 c = genadjesp(c, -REGSIZE); 2969 stackpush -= REGSIZE; 2970 if (numpara + numalign > REGSIZE) 2971 c = genstackclean(c, numpara + numalign - REGSIZE, retregs); 2972 2972 } 2973 2973 else 2974 2974 c = genstackclean(c,numpara + numalign,retregs); 2975 2975 } 2976 2976 else 2977 2977 { 2978 2978 c = genadjesp(c,-numpara); 2979 2979 stackpush -= numpara; 2980 2980 if (numalign) 2981 2981 c = genstackclean(c,numalign,retregs); 2982 2982 } 2983 2983 2984 2984 /* Special handling for functions which return a floating point 2985 2985 value in the top of the 8087 stack. 2986 2986 */ 2987 2987 2988 2988 if (retregs & mST0) 2989 2989 { 2990 2990 if (*pretregs) // if we want the result 2991 2991 { //assert(stackused == 0);
