1 #ifndef lint 2 static char sccsid[] = "@(#)c21.c 1.10 (Berkeley/CCI) 08/25/88"; 3 #endif 4 5 /* 6 * C object code improver-- second part 7 */ 8 9 #include "c2.h" 10 #include <stdio.h> 11 #include <ctype.h> 12 13 int bitsize[] = {0,8,16,32,64,32,64}; /* index by type codes */ 14 15 redun3(p) register struct node *p; { 16 /* check for 3 addr instr which should be 2 addr */ 17 if (has3ops(p)) { 18 if (equstr(regs[RT1],regs[RT3]) 19 && (p->op==ADD || p->op==MUL || p->op==AND || p->op==OR || p->op==XOR)) { 20 register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t; 21 } 22 if (equstr(regs[RT2],regs[RT3])) { 23 p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0; 24 lastrand=regs[RT2]; *regs[RT3]=0; return(1); 25 } 26 } return(0); 27 } 28 29 bmove() { 30 register struct node *p, *lastp; register char *cp1,*cp2; register int r; 31 struct node *flops(); 32 33 refcount(); 34 for (p=lastp= &first; 0!=(p=p->forw); lastp=p); 35 clearreg(); clearuse(); 36 for (p=lastp; p!= &first; p=p->back) { 37 if (debug) { 38 printf("Uses: "); 39 if (useacc) 40 printf("acc: %s\n",useacc->code? useacc->code:""); 41 for (r=NUSE;--r>=0;) if (uses[r]) 42 printf("%d: %s\n",r,uses[r]->code? uses[r]->code:""); 43 printf("-\n"); 44 } 45 r=(p->subop>>4)&0xF; 46 splitrand(p); 47 if (OP3==r && 0!=redun3(p)) {newcode(p); redunm++;} 48 /* ops that do nothing */ 49 if(p->op==MOV && equstr(regs[RT1], regs[RT2])) 50 if(p->forw->op!=CBR) { 51 delnode(p); redunm++; continue; 52 } else { 53 p->op=TST; p->pop=0; 54 while(*p->code++ != ','); 55 redunm++; 56 } 57 else if((cp1=p->code, *cp1++)=='$' && 58 (*cp1=='0' || *cp1=='1' || *cp1++=='-' && *cp1=='1') && cp1[1]==',') { 59 switch((p->code[1]<<8)|ord(p->op)) { 60 case (('0'<<8)|ord(ADD)): 61 case (('0'<<8)|ord(SUB)): 62 case (('-'<<8)|ord(AND)): 63 case (('0'<<8)|ord(OR)): 64 case (('0'<<8)|ord(XOR)): 65 case (('1'<<8)|ord(MUL)): 66 case (('1'<<8)|ord(DIV)): 67 case (('0'<<8)|ord(SHAL)): 68 case (('0'<<8)|ord(SHAR)): 69 case (('0'<<8)|ord(SHL)): 70 case (('0'<<8)|ord(SHR)): 71 if(r == OP2) { 72 if(p->forw->op!=CBR) { 73 delnode(p); redunm++; continue; 74 } else { 75 p->op=TST; p->subop&=0xF; p->pop=0; 76 while(*p->code++ != ','); 77 redunm++; 78 } 79 } else { /* OP3 or shift */ 80 p->op=MOV; p->subop&=0xF; p->pop=0; 81 while(*p->code++ != ','); 82 p = p->forw; redunm++; continue; 83 } 84 break; 85 case (('0'<<8)|ord(MUL)): 86 case (('0'<<8)|ord(AND)): 87 p->op=CLR; p->subop&=0xF; p->pop=0; 88 while(*p->code++ != ','); 89 if(r == OP3) 90 while(*p->code++ != ','); 91 redunm++; 92 } 93 } 94 switch (p->op) { 95 case LABEL: case DLABEL: 96 for (r=NUSE; --r>=0;) 97 if (uses[r]) p->ref=(struct node *) (((int)p->ref)|(1<<r)); 98 if (useacc) p->ref=(struct node *) (((int)p->ref)|(1<<NUSE)); 99 break; 100 case CALLS: 101 case CALLF: 102 clearuse(); goto std; 103 case NIL: 104 clearuse(); break; 105 case CVT: 106 { long n; 107 if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; 108 if (*cp1++!='$') goto std; splitrand(p); 109 n = getnum(®s[RT1][1]); 110 if(r==BYTE && (n<-128 || n>127)) goto std; 111 if(r==WORD && (n<-32768 || n>32767)) goto std; 112 p->op = MOV; p->subop = r; p->pop = 0; 113 } goto std; 114 115 case SUB: 116 if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; 117 if (*cp1++!='$') goto std; splitrand(p); 118 #ifdef MOVAFASTER 119 if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ 120 char buf[C2_ASIZE]; cp2=buf; *cp2++='-'; 121 cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; 122 cp1="(fp),"; while (*cp2++= *cp1++); --cp2; 123 cp1=regs[RT3]; while (*cp2++= *cp1++); 124 p->code=copy(buf); p->op = MOVA; p->subop = BYTE; p->pop=0; 125 } else 126 #endif MOVAFASTER 127 if (*cp1++=='-' && 0==(r=getnum(cp1)) && 128 !checkexpr(cp1)) { 129 p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1; 130 } goto std; 131 case ADD: 132 if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; 133 if (*cp1++!='$') goto std; splitrand(p); 134 if (isstatic(cp1) && tempreg(regs[RT2],r) && uses[r]==p->forw) 135 { 136 /* address comp: 137 ** addl2 $_foo,r0 \ movab _foo[r0],bar 138 ** movl r0,bar / 139 */ 140 register struct node *pnext = p->forw; 141 char buf[C2_ASIZE]; 142 143 if (pnext->op == MOV && pnext->subop == LONG) 144 { 145 cp1 = ®s[RT1][1]; cp2 = &buf[0]; 146 while (*cp2++ = *cp1++) ; cp2--; 147 splitrand(pnext); 148 if (r == isreg(regs[RT1])) 149 { 150 delnode(p); p = pnext; 151 p->op = MOVA; p->subop = BYTE; 152 p->pop = 0; 153 cp1 = regs[RT1]; *cp2++ = '['; 154 while (*cp2++ = *cp1++) ; cp2--; 155 *cp2++ = ']'; *cp2++ = ','; 156 cp1 = regs[RT2]; 157 while (*cp2++ = *cp1++) ; 158 p->code = copy(buf); 159 } 160 } 161 } 162 else 163 #ifdef MOVAFASTER 164 if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ 165 cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; 166 cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=','; 167 p->op = MOVA; p->subop = BYTE; p->pop=0; 168 } else 169 #endif MOVAFASTER 170 if (*cp1++=='-' && 0==(r=getnum(cp1)) && 171 !checkexpr(cp1)) { 172 p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1; 173 } 174 /* fall thru ... */ 175 case CASE: 176 default: std: 177 p=bflow(p); break; 178 179 case MUL: 180 /* 181 ** Change multiplication 182 ** by constant powers of 2 to shifts. 183 */ 184 splitrand(p); 185 if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std; 186 if ((r = ispow2(getnum(®s[RT1][1]))) <= 0) goto std; 187 /* mull2 $2,x */ 188 if(r == 1 && p->subop == U(LONG, OP2)) { 189 strcpy(regs[RT1], regs[RT2]); 190 p->op = ADD; p->pop = 0; newcode(p); 191 goto std; 192 } 193 if (p->subop == U(LONG,OP2)) 194 strcpy(regs[RT3], regs[RT2]); 195 sprintf(regs[RT1], "$%d", r); 196 p->op = SHL; p->subop = LONG; 197 p->pop = 0; newcode(p); 198 goto std; 199 200 case SHAL: 201 case SHL: 202 { 203 /* bit tests: 204 ** shll A,$1,rC \ 205 ** bitl B,rC > jbc A,B,D 206 ** jeql D / 207 ** 208 ** address comp: 209 ** shll $1,bar,r0 \ movl bar,r0 210 ** movab _foo[r0] / movaw _foo[r0] 211 ** 212 ** shll $2,r0,r0 \ moval _foo[r0] 213 ** movab _foo[r0] / 214 */ 215 register struct node *pf; 216 register struct node *pn; 217 register int shfrom, shto; 218 long shcnt; 219 char *regfrom; 220 221 splitrand(p); 222 if (regs[RT1][0] != '$') { 223 if(isreg(regs[RT1]) < 0) goto std; /* alignment */ 224 if (regs[RT2][0] != '$') goto std; 225 if (getnum(®s[RT2][1]) != 1) goto std; 226 if (!tempreg(regs[RT3],r)) goto std; 227 if ((pf = p->forw)->op != BIT && pf->op!=AND) goto std; 228 if (uses[r] && uses[r] != pf) goto std; 229 splitrand(pf); 230 if (r == isreg(regs[RT1])) cp2 = regs[RT2]; 231 else if (r == isreg(regs[RT2])) cp2 = regs[RT1]; 232 else goto std; 233 if (*cp2 == '$') goto std; 234 if ((pn = pf->forw)->op != CBR) goto std; 235 if (pn->subop != JEQ && pn->subop != JNE) goto std; 236 delnode(p); delnode(pf); 237 pn->subop = (pn->subop == JEQ) ? JBC : JBS; 238 for(cp1=p->code; *cp1++!=',';); 239 while (*cp1++= *cp2++); 240 pn->code = p->code; pn->pop = NULL; 241 uses[r] = NULL; 242 nbj++; 243 p = pn; 244 goto std; 245 } 246 if ((shcnt = getnum(®s[RT1][1])) < 1 || shcnt > 2) goto std; 247 if ((shfrom = isreg(regs[RT2])) >= 0) 248 regfrom = copy(regs[RT2]); 249 if (tempreg(regs[RT3],shto)) 250 { 251 int regnum; 252 253 if (uses[shto] != (pf = p->forw)) goto ashadd; 254 if (pf->op != MOVA && pf->op != PUSHA) goto ashadd; 255 if (pf->subop != BYTE) goto ashadd; 256 splitrand(pf); 257 if (!indexa(regs[RT1])) goto std; 258 cp2 = regs[RT1]; 259 if(!isstatic(cp2)) goto std; 260 while (*cp2++ != '[') ; 261 if (*cp2++ != 'r' || !isdigit(*cp2)) goto std; 262 regnum = *cp2++ - '0'; 263 if (isdigit(*cp2)) 264 { 265 if (cp2[1] != ']') goto std; 266 regnum *= 10; regnum += *cp2 - '0'; 267 } 268 if (regnum != shto) goto std; 269 if (shfrom >= 0) /* shll $N,r*,r0 */ 270 { 271 delnode(p); 272 p = pf; 273 if (shfrom != shto) 274 { 275 uses[shto] = NULL; splitrand(pf); 276 cp2=regs[RT1]; while (*cp2++!='['); 277 cp1=regfrom; while (*cp2++= *cp1++); 278 cp2[-1] = ']'; *cp2 = 0; 279 newcode(pf); 280 } 281 } 282 else 283 { 284 p->op = MOV; splitrand(p); 285 strcpy(regs[RT1], regs[RT2]); 286 strcpy(regs[RT2], regs[RT3]); 287 regs[RT3][0] = '\0'; 288 p->pop = 0; newcode(p); 289 } 290 switch (shcnt) 291 { 292 case 1: pf->subop = WORD; break; 293 case 2: pf->subop = LONG; break; 294 } 295 pf->pop = 0; 296 redunm++; nsaddr++; 297 goto std; 298 } 299 ashadd: 300 /* at this point, RT2 and RT3 are guaranteed to be simple regs*/ 301 if (shcnt == 1) { 302 /* 303 ** quickie: 304 ** shll $1,A,A > addl2 A,A 305 ** shll $1,A,B > addl3 A,A,B 306 */ 307 if ((pf = p->forw)->op == CBR || 308 (pf->op == MOV && (pf = pf->forw)->op == CBR)) 309 /* 310 ** shll and addl handle the N bit differently 311 ** on overflow; avoid N bit CBRs 312 */ 313 switch (pf->subop) { 314 case JLE: case JGE: case JLT: case JGT: 315 goto std; 316 } 317 p->op = ADD; 318 strcpy(regs[RT1], regs[RT2]); 319 if(equstr(regs[RT2], regs[RT3])) { 320 p->subop = U(LONG,OP2); 321 regs[RT3][0] = '\0'; 322 } else 323 p->subop = U(LONG,OP3); 324 p->pop = 0; 325 newcode(p); 326 } 327 goto std; 328 } 329 330 case SHAR: 331 case SHR: 332 { 333 /* bit tests: 334 ** shrl A,B,rC \ 335 ** bitl $1,rC > jbc A,B,D 336 ** jeql D / 337 */ 338 register struct node *pf; /* forward node */ 339 register struct node *pn; /* next node (after pf) */ 340 register int extreg; /* reg extracted to */ 341 342 splitrand(p); 343 if(isreg(regs[RT1]) < 0) goto std; /* alignment */ 344 if (!tempreg(regs[RT3],extreg)) goto std; 345 if ((pf = p->forw)->op != BIT) goto std; 346 if (uses[extreg] && uses[extreg] != pf) goto std; 347 splitrand(pf); 348 if (regs[RT1][0] != '$') goto std; 349 if (getnum(®s[RT1][1]) != 1) goto std; 350 if (extreg != isreg(regs[RT2])) goto std; 351 if ((pn = pf->forw)->op != CBR) goto std; 352 if (pn->subop != JEQ && pn->subop != JNE) goto std; 353 delnode(p); delnode(pf); 354 pn->subop = (pn->subop == JEQ) ? JBC : JBS; 355 for(cp1=p->code; *cp1++!=',';); 356 while (*cp1!=',') cp1++; *cp1='\0'; 357 pn->code = p->code; pn->pop = NULL; 358 uses[extreg] = NULL; nbj++; 359 p = pn; 360 goto std; 361 } 362 363 case AND: 364 { 365 /* unsigned conversion: 366 ** cvtbl A,B; andl2 $255,B > movzbl A,B 367 ** 368 ** also byte- and word-size fields: 369 ** shrl $(3-n)*8,A,B; andl2 $255,B > movzbl n+A,B 370 ** shrl $(1-n)*16,A,B; andl2 $65535,B > movzwl n+A,B 371 */ 372 char src[C2_ASIZE]; 373 register int f; /* field length */ 374 register struct node *pb = p->back; /* backward node */ 375 376 if (p->subop != U(LONG,OP2)) 377 goto std; 378 splitrand(p); cp1=regs[RT1]; 379 if (*cp1++!='$' || (f=getnum(cp1))!=0xff && f!=0xffff) 380 goto std; 381 f = f==0xff ? 8 : 16; 382 if (pb->op!=CVT && pb->op!=MOVZ && pb->op!=SHAR && pb->op!=SHR) 383 goto std; 384 /* save source of ANDL in 'src' */ 385 strcpy(src, regs[RT2]); 386 splitrand(pb); 387 if (!equstr(src,lastrand)) 388 goto std; 389 if (pb->op==CVT || pb->op==MOVZ) { 390 if (!(bitsize[pb->subop&0xF]==f 391 && bitsize[pb->subop>>4]>=f)) /* good CVT */ 392 goto std; 393 strcpy(src, regs[RT1]); 394 } else { 395 register int boff; /* bit offset */ 396 397 if (regs[RT1][0] != '$') goto std; 398 if ((boff = getnum(®s[RT1][1])) < 0) goto std; 399 if (isreg(regs[RT2])>=0 || !natural(regs[RT2])) goto std; 400 if ((boff & (f-1)) != 0) goto std; 401 boff = (32-boff-f) / 8; 402 if (boff == 0) 403 strcpy(src, regs[RT2]); 404 else 405 sprintf(src, "%d%s%s", boff, regs[RT2][0]=='(' ? "":"+", 406 regs[RT2]); 407 } 408 delnode(pb); 409 p->op = MOVZ; 410 p->subop = U((f==8 ? BYTE : WORD), LONG); 411 sprintf(line,"%s,%s",src,lastrand); 412 p->pop=0; 413 p->code = copy(line); 414 goto std; 415 } 416 417 case CMP: 418 { 419 /* comparison to -63 to -1: 420 ** cmpl r0,$-1 > incl r0 421 ** jeql ... 422 ** 423 ** cmpl r0,$-63 > addl2 $63,r0 424 ** jeql ... 425 */ 426 register int num; 427 register int reg; 428 register struct node *regp = p->back; 429 430 if (p->forw->op != CBR) goto std; 431 if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std; 432 splitrand(p); 433 if (strncmp(regs[RT2], "$-", 2) != 0) goto std; 434 reg = r = isreg(regs[RT1]); 435 if (r < 0) goto std; 436 if (r < NUSE && uses[r] != 0) goto std; 437 if (r >= NUSE && regp->op == MOV && p->subop == regp->subop) 438 { 439 if (*regp->code != 'r') goto std; 440 reg = regp->code[1] - '0'; 441 if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg]) 442 goto std; 443 } 444 if (r >= NUSE) goto std; 445 if (reg != r) 446 sprintf(regs[RT1], "r%d", reg); 447 if ((num = getnum(®s[RT2][2])) <= 0 || num > 63) goto std; 448 if (num == 1) 449 { 450 p->op = INC; regs[RT2][0] = '\0'; 451 } 452 else 453 { 454 register char *t; 455 456 t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t; 457 p->op = ADD; p->subop = U(p->subop, OP2); 458 for (t = ®s[RT1][2]; t[-1] = *t; t++) ; 459 } 460 p->pop = 0; newcode(p); 461 goto std; 462 } 463 464 case JBR: case JMP: 465 clearuse(); 466 if ((p->subop&0xF)==RET) { 467 switch((p->subop>>4)&0xF) { 468 case 2: uses[1]=p; regs[1][0]= -1; 469 case 1: uses[0]=p; regs[0][0]= -1; 470 } 471 break; 472 } 473 if (p->ref==0) goto std; /* jmp (r0) */ 474 /* fall through */ 475 case CBR: 476 if (p->ref->ref!=0) { 477 for (r=NUSE;--r>=0;) 478 if ((1<<r) & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;} 479 if ((1<<NUSE) & (int)p->ref->ref) useacc=p; 480 } 481 break; 482 case LNF: 483 /* lnf a; addf b ==> ldf b; subf a */ 484 { register struct node *pf = p->forw; 485 if(pf->op==ADDF && p->subop==pf->subop) { 486 p->op = LDF; 487 p->pop = 0; 488 pf->op = SUBF; 489 pf->pop = 0; 490 cp1 = p->code; 491 p->code = pf->code; 492 pf->code = cp1; 493 p = pf->forw; 494 break; 495 }} 496 case LDF: case LDFD: case CVLF: /* destroy acc */ 497 useacc = 0; 498 goto std; 499 case STF: 500 { register struct node *pf; 501 if((pf=flops(p)) != p) { 502 p = pf; /* usually p->forw; */ 503 break; 504 }} 505 if(ldmov(p)) { 506 p = p->forw; 507 break; 508 } 509 if(useacc == 0) 510 useacc = p; 511 goto std; 512 case ADDF: case MULF: /* commutatives - create clients for flops */ 513 /* stf a; ldf b; addf a => stf a; ldf a; addf b */ 514 { register struct node *pb = p->back; 515 register struct node *pbb = pb->back; 516 if(pb->op==LDF && pb->subop==p->subop && 517 pbb && pbb->op==STF && pbb->subop==p->subop && 518 equstr(pbb->code, p->code)) { 519 cp1 = p->code; 520 p->code = pb->code; 521 pb->code = cp1; 522 }} 523 /* use acc and regs */ 524 case CMPF: case CVFL: case SUBF: case DIVF: 525 if(useacc == 0) 526 useacc = p; 527 goto std; 528 case TSTF: 529 break; 530 case PUSHD: 531 if(ldmov(p)) { 532 p = p->forw; 533 break; 534 } 535 case CVDF: case NEGF: /* use only acc */ 536 case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF: 537 if(useacc == 0) 538 useacc = p; 539 case EROU: case JSW: 540 case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ; 541 } 542 } 543 for (p= &first; p!=0; p=p->forw) 544 if (p->op==LABEL || p->op==DLABEL) p->ref=0; /* erase our tracks */ 545 } 546 547 char * 548 byondrd(p) register struct node *p; { 549 /* return pointer to register which is "beyond last read/modify operand" */ 550 if (has2ops(p)) return(regs[RT3]); 551 switch (p->op) { 552 case MFPR: 553 case PUSHA: 554 case TST: case INC: case DEC: case PUSH: 555 case LDF: case LNF: case CVLF: case LDFD: 556 case ADDF: case SUBF: case MULF: case DIVF: 557 case CMPF: 558 return(regs[RT2]); 559 case MTPR: 560 #ifndef EMOD 561 case EDIV: 562 #endif EMOD 563 case CBR: /* must be JBC/JBS */ 564 case BIT: case CMP: case CALLS: case CALLF: 565 case CMPF2: 566 return(regs[RT3]); 567 case EMUL: 568 case PROBE: 569 case MOVBLK: 570 case CASE: 571 return(regs[RT4]); 572 } 573 return(lastrand); 574 } 575 576 struct node * 577 bflow(p) 578 register struct node *p; 579 { 580 register char *cp1,*cp2,**preg; 581 register int r, fr, dblflg=0; 582 int flow= -1; 583 struct node *olduse=0, *olduse1=0; 584 585 if (p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4 || 586 p->op==EMUL) 587 dblflg |= 1; /* double dest */ 588 if ((p->subop&0xF)==DOUBLE || p->subop==QUAD) 589 dblflg |= 2; /* double src */ 590 splitrand(p); 591 if (p->op!=PUSH && 592 #ifndef EMOD 593 p->op!=EDIV && 594 #endif EMOD 595 p->op!=EMUL && 596 p->subop && tempreg(lastrand,r) && uses[r]==p->forw) { 597 if (equtype(p->subop,regs[r][0]) || 598 ((p->op==CVT || p->op==MOVZ || p->op==CVFL) && 599 (regs[r][0]&0xf) && compat((p->subop>>4)&0xf,regs[r][0])) || 600 p->op==MOVA && compat(LONG, regs[r][0])) { 601 register int r2; 602 603 if (regs[r][1]!=0) { /* send directly to destination */ 604 if (p->op==INC || p->op==DEC) { 605 p->op = (p->op==DEC) ? SUB : ADD; 606 /* use 2 now, convert to 3 later */ 607 p->subop=(OP2<<4)+(p->subop&0xF); 608 p->pop=0; 609 cp1=lastrand; cp2=regs[RT2]; 610 while (*cp2++= *cp1++) /* copy reg */ 611 ; 612 cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; 613 } 614 cp1=regs[r]+1; cp2=lastrand; 615 if (has2ops(p)) { 616 /* use 3 operand form of instruction */ 617 p->pop=0; 618 p->subop += (OP3-OP2)<<4; 619 lastrand = cp2 = regs[RT3]; 620 } 621 while (*cp2++= *cp1++) 622 ; 623 if (p->op==MOVA && p->forw->op==PUSH) { 624 p->op=PUSHA; 625 *regs[RT2]=0; p->pop=0; 626 } else if ((p->op==MOV || p->op==CVT) && 627 p->forw->op==PUSH) { 628 p->op=PUSH; p->subop &= 0xF; 629 *regs[RT2]=0; p->pop=0; 630 } 631 delnode(p->forw); 632 if (tempreg(lastrand,r2)) 633 uses[r2]=uses[r], uses[r]=0; 634 redun3(p); 635 newcode(p); redunm++; flow=r; 636 } else if (p->op==MOV) { /* superfluous fetch */ 637 int nmatch; 638 char src[C2_ASIZE]; 639 movit: 640 for (cp2=src, cp1=regs[RT1]; *cp2++= *cp1++;) 641 ; 642 splitrand(p->forw); 643 if (p->forw->op != INC && p->forw->op != DEC) 644 lastrand=byondrd(p->forw); 645 nmatch=0; 646 for (preg=regs+RT1;*preg!=lastrand;preg++) 647 if (r==isreg(*preg)) { 648 cp2= *preg; cp1=src; 649 while (*cp2++= *cp1++) 650 ; 651 ++nmatch; 652 } 653 if (nmatch==1) { 654 if (has2ops(p->forw) && equstr(src,regs[RT2])) { 655 p->forw->pop=0; 656 p->forw->subop += (OP3-OP2)<<4; 657 cp1=regs[RT3]; 658 *cp1++ = 'r'; *cp1++ = r+'0'; *cp1=0; 659 } 660 delnode(p); 661 p=p->forw; 662 if (tempreg(src,r2)) 663 uses[r2]=uses[r], uses[r]=0; 664 redun3(p); 665 newcode(p); redunm++; 666 return(p); /* avoid stale uses[] data */ 667 } else 668 splitrand(p); 669 } 670 } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) && 671 p->forw->subop&0xf && /* if base or index, then forget it */ 672 compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1])) 673 goto movit; 674 } 675 /* adjust 'lastrand' past any 'read' or 'modify' operands. */ 676 lastrand=byondrd(p); 677 /* a 'write' clobbers the register. */ 678 if (tempreg(lastrand,r) || 679 (has2ops(p) && tempreg(regs[RT2],r) && uses[r]==0)) { 680 /* 681 * Writing a dead register is useless, 682 * but watch side effects 683 */ 684 switch (p->op) { 685 #ifndef EMOD 686 case EDIV: 687 #endif EMOD 688 case AOBLEQ: case AOBLSS: 689 break; 690 default: 691 /* 692 * If no direct uses, check for 693 * use of condition codes 694 */ 695 if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) { 696 register struct node *q = p; 697 698 while ((q = nonlab(q->forw))->op==JBR && 699 q->subop==0) 700 q=q->ref; /* cc unused, unchanged */ 701 if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) { 702 /* ... and destroyed */ 703 preg=regs+RT1; 704 while (cp1 = *preg++) { 705 if (cp1==lastrand && 706 p->op != CLR && 707 p->op != CVFL) { 708 redunm++; 709 delnode(p); 710 return(p->forw); 711 } 712 if (equstr(cp1,lastrand)) 713 break; 714 } 715 } 716 } 717 flow=r; 718 } 719 } 720 if ((r=flow) >= 0) { 721 olduse=uses[r], uses[r]=0; 722 *(short *)(regs[r])=0; 723 /* if r0 destroyed, dont keep r1 */ 724 if (dblflg&1) { 725 olduse1=uses[++r], uses[r]=0; 726 *(short *)(regs[r])=0; 727 } 728 } 729 /* now look for 'read' or 'modify' (read & write) uses */ 730 preg=regs+RT1; 731 while (*(cp1= *preg++)) { 732 /* check for r */ 733 if (lastrand!=cp1 && tempreg(cp1,r)) { 734 int isunused; 735 if (isunused=(uses[r]==0)) { 736 uses[r]=p; 737 cp2=regs[r]; *cp2++=p->subop; 738 if ((p->op==SHAL || p->op==SHAR || 739 p->op==SHL || p->op==SHR) && 740 cp1==regs[RT1]) 741 cp2[-1] = BYTE; 742 if (p->op==CBR && (p->subop==JBC || p->subop==JBS)) 743 cp2[-1] = LONG; 744 if (p->op==MOVA && cp1==regs[RT2]) 745 cp2[-1]=LONG; 746 } 747 /* ediv/emod's 2nd operand is quad */ 748 if (((p->op==EDIV 749 #ifdef EMOD 750 || p->op==EMOD 751 #endif EMOD 752 ) && cp1==regs[RT2] || (dblflg&2)) && 753 ++r<NUSE && uses[r]==0) { 754 if (isunused) 755 *cp2=0; 756 uses[r]=p; 757 cp2=regs[r]; *cp2++=p->subop; 758 if (!isunused) 759 *cp2=0; 760 } 761 if (!isunused) 762 continue; 763 if (p->op==MOV || p->op==PUSH || p->op==CVT || 764 p->op==MOVZ || p->op==COM || p->op==NEG || 765 p->op==STF) { 766 if (p->op!=PUSH) { 767 cp1=regs[RT2]; 768 if (tempreg(cp1,r)) { 769 /* 770 * reincarnation!! 771 * (as in addl2 r0,r1; 772 * movl r1,r0; ret) 773 */ 774 if (uses[r]==0) 775 uses[r]=olduse; 776 if ((dblflg&1) && uses[r+1]==0) 777 uses[r+1]=olduse1; 778 } 779 if (p->op!=MOV) 780 cp1=0; 781 } else 782 cp1="-(sp)"; 783 if (cp1) 784 while (*cp2++= *cp1++) 785 ; 786 else 787 *cp2=0; 788 } else 789 *cp2=0; 790 continue; 791 } 792 /* check for (r),[r] */ 793 do { 794 if (*cp1=='(' || *cp1=='[') { /* get register number */ 795 char t; 796 for (cp2= ++cp1; *++cp1!=')' && *cp1!=']';) 797 ; 798 t= *cp1; *cp1=0; 799 if (tempreg(cp2,r) && 800 (uses[r]==0 || uses[r]==p)) { 801 uses[r]=p; 802 regs[r][0] = 803 (*--cp2=='[' ? OPX<<4 : OPB<<4); 804 regs[r][1] = '\0'; 805 } 806 *cp1=t; 807 } 808 } while (*++cp1); 809 } 810 #ifdef MOVAFASTER 811 /* pushax or movax possibility? */ 812 cp1=regs[RT1]; 813 if (*cp1++=='$' && isstatic(cp1)) { 814 if (p->op==MOV && p->subop==LONG) { 815 if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { 816 cp1=p->code; while (*cp1++!=','); p->code= --cp1; 817 } 818 p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0; 819 } else if (p->op==PUSH && p->subop==LONG) { 820 p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0; 821 } else if (p->op==ADD && p->subop==U(LONG,OP3) 822 && 0<=(r=isreg(regs[RT2]))) { 823 cp1=cp2=p->code; ++cp1; 824 do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='['; 825 do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']'; 826 if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;} 827 else {p->op = PUSHA; p->subop = BYTE; *cp2=0;} 828 if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;} 829 p->pop=0; 830 } 831 } 832 #endif MOVAFASTER 833 return (p); 834 } 835 836 /* try to eliminate STF's */ 837 struct node * 838 flops(q) 839 register struct node *q; 840 { 841 register struct node *p; 842 register int r; 843 844 if(q->op!=STF || !tempreg(q->code,r)) 845 return(q); 846 if(uses[r]) { 847 /* see if anyone destroys acc between us */ 848 for(p=q->forw; p!=uses[r]; p=p->forw) 849 switch(p->op) { 850 case LABEL: 851 case LDF: case LNF: case CVLF: case LDFD: 852 case CVDF: case NEGF: case ADDF: case SUBF: 853 case MULF: case DIVF: case SINF: case COSF: 854 case ATANF: case LOGF: case SQRTF: case EXPF: 855 return(q); 856 } 857 again: 858 if(q->subop == p->subop) 859 switch(p->op) { /* do it in the accumulator */ 860 case LDF: /* redundant load */ 861 delnode(p); nld++; 862 p = p->forw; 863 break; 864 case LNF: /* stf r; lnf r ==> negf */ 865 p->op = NEGF; 866 p->pop = 0; 867 p->code = 0; 868 break; 869 case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */ 870 { register char *s; 871 register struct node *p1=p->forw; 872 for(s=p->code; *s!=','; s++); 873 *s = 0; 874 if(isreg(p->code) == r) 875 p->code = s+1; 876 else { 877 if(p1->op != CBR || isreg(s+1) != r) { 878 *s = ','; 879 return(q); 880 } 881 if(p1->subop > JNE) { 882 p1->subop ^= 1; 883 p1->pop = 0; 884 nrevbr++; 885 } 886 } 887 p->op = CMPF; 888 p->pop = 0; 889 } 890 break; 891 default: 892 return(q); 893 } 894 else if(p->subop==LONG) { 895 switch(p->op) { 896 case TST: /* stf r; tstl r ==> tstf */ 897 p->op = TSTF; 898 p->code = 0; 899 break; 900 /* send directly to destination */ 901 case MOV: /* stf r; movl r,x ==> stf x */ 902 case PUSH: /* stf r; pushl r ==> stf -(sp)/pushd */ 903 if(q->subop == DOUBLE) { 904 register struct node *b = p->back; 905 /* assume b's 2nd arg is ok */ 906 if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG)) 907 return(q); 908 delnode(b); redunm++; 909 } 910 if(p->op==PUSH) { 911 if(q->subop == DOUBLE) { 912 p->op = PUSHD; 913 p->code = 0; 914 } else { 915 p->op = q->op; 916 p->code = copy("-(sp)"); 917 } 918 } else { 919 p->op = q->op; 920 while(*p->code++ != ','); 921 } 922 break; 923 default: 924 return(q); 925 } 926 p->pop = 0; 927 p->subop = q->subop; 928 } else 929 return(q); 930 uses[r] = 0; 931 if(q->subop == DOUBLE) 932 uses[r+1] = 0; 933 for(p = p->back; p != q && (!uses[r] || !uses[r+1]); p = p->back) { 934 int xr; 935 936 splitrand(p); 937 if((xr=isreg(regs[RT1])) < 0) 938 continue; 939 if(!uses[r] && xr == r) 940 uses[r] = p; 941 else if(q->subop == DOUBLE && !uses[r+1] && xr == r+1) 942 uses[r+1] = p; 943 } 944 if(p = uses[r]) 945 goto again; 946 return(q->forw); /* DON'T re-scan code with dated uses[] */ 947 } 948 /* it's a store to reg which isnt used elsewhere */ 949 if((p=q->forw)->op == CBR) { 950 q->op = TSTF; 951 q->pop = 0; 952 q->code = 0; 953 } else { 954 delnode(q); nst++; 955 if(p->op ==STF || p->op==TSTF || p->op==PUSHD) { 956 if(useacc == p) 957 useacc = 0; 958 return(p->forw); /* so ldmov can be used on p */ 959 } 960 } 961 return(p); 962 } 963 964 /* try to change load/store sequences to movl */ 965 ldmov(q) 966 register struct node *q; 967 { 968 register struct node *p; 969 register char *s, *pcod, *cp; 970 char *dlsw(); 971 972 p = q->back; 973 if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD) 974 && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE)))) 975 return(0); 976 pcod = p->code; 977 cp = p->code; 978 /* prepare args for movl/pushl */ 979 if(q->op!=TSTF && q->subop==DOUBLE) { 980 if(p->op == LDF) { 981 if((s = dlsw(p->code)) == NULL) 982 return(0); 983 984 strcpy(line, s); 985 if(q->op == STF) { 986 strcat(line, ","); 987 if((s = dlsw(q->code)) == NULL) 988 return(0); 989 strcat(line, s); 990 p->op = MOV; 991 } else 992 p->op = PUSH; 993 } else { /* LDFD */ 994 if(q->op == STF) { 995 if((s = dlsw(q->code)) == NULL) 996 return(0); 997 } else 998 s = "-(sp)"; 999 strcpy(line, s); 1000 p->op = CLR; 1001 } 1002 p->pop = 0; 1003 p->subop = LONG; 1004 p->code = copy(line); 1005 } else 1006 { 1007 if ((p->op == LDF) && (p->subop == DOUBLE) && 1008 (indexa(cp))) return(0); 1009 delnode(p); 1010 } 1011 strcpy(line, pcod); 1012 if(q->op == STF) { /* ldf x; stf y ==> movl x,y */ 1013 strcat(line, ","); 1014 strcat(line, q->code); 1015 q->op = MOV; 1016 nst++; 1017 } else if(q->op == TSTF) /* ldf x; tstf ==> tstl x */ 1018 q->op = TST; 1019 else /* ldd x; pushd ==> pushl x+4; pushl x */ 1020 q->op = PUSH; 1021 q->pop = 0; 1022 q->subop = LONG; 1023 q->code = copy(line); 1024 nld++; 1025 return(1); 1026 } 1027 1028 /* reconstruct the address of l.s.w. of a double operand */ 1029 char * 1030 dlsw(d) 1031 register char *d; 1032 { 1033 register char *s, *t, *c; 1034 register int r; 1035 static char lsw[C2_ASIZE]; 1036 1037 if(d[0] == '*' || d[0] == '$') 1038 return(NULL); 1039 if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2])) 1040 return(NULL); 1041 t = lsw; 1042 if((r=isreg(d)) >= 0) 1043 sprintf(t, "r%d", r+1); 1044 else { 1045 for(s=d; *s && *s!='('; *t++ = *s++) 1046 if(*s == '[') 1047 return(NULL); 1048 if(s!=d) 1049 *t++ = '+'; 1050 *t++ = '4'; 1051 while(*t++ = *s) 1052 if(*s++ == '[' ) 1053 { 1054 return(NULL); 1055 } 1056 } 1057 return(lsw); 1058 } 1059 checkexpr(p) 1060 register char *p; 1061 { 1062 1063 while(*p && *p != ','){ 1064 if ((*p == '+' ) || (*p == '-')) 1065 return(1); 1066 *p++; 1067 } 1068 return(0); 1069 } 1070