1 #ifndef lint 2 static char sccsid[] = "@(#)c21.c 1.5 (Berkeley/CCI) 01/10/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 redunm++; nsaddr++; 296 } 297 goto std; 298 ashadd: 299 /* at this point, RT2 and RT3 are guaranteed to be simple regs*/ 300 if (shcnt == 1) { 301 /* 302 ** quickie: 303 ** shll $1,A,A > addl2 A,A 304 ** shll $1,A,B > addl3 A,A,B 305 */ 306 p->op = ADD; 307 strcpy(regs[RT1], regs[RT2]); 308 if(equstr(regs[RT2], regs[RT3])) { 309 p->subop = U(LONG,OP2); 310 regs[RT3][0] = '\0'; 311 } else 312 p->subop = U(LONG,OP3); 313 p->pop = 0; 314 newcode(p); 315 } 316 goto std; 317 } 318 319 case SHAR: 320 case SHR: 321 { 322 /* bit tests: 323 ** shrl A,B,rC \ 324 ** bitl $1,rC > jbc A,B,D 325 ** jeql D / 326 */ 327 register struct node *pf; /* forward node */ 328 register struct node *pn; /* next node (after pf) */ 329 register int extreg; /* reg extracted to */ 330 331 splitrand(p); 332 if(isreg(regs[RT1]) < 0) goto std; /* alignment */ 333 if (!tempreg(regs[RT3],extreg)) goto std; 334 if ((pf = p->forw)->op != BIT) goto std; 335 if (uses[extreg] && uses[extreg] != pf) goto std; 336 splitrand(pf); 337 if (regs[RT1][0] != '$') goto std; 338 if (getnum(®s[RT1][1]) != 1) goto std; 339 if (extreg != isreg(regs[RT2])) goto std; 340 if ((pn = pf->forw)->op != CBR) goto std; 341 if (pn->subop != JEQ && pn->subop != JNE) goto std; 342 delnode(p); delnode(pf); 343 pn->subop = (pn->subop == JEQ) ? JBC : JBS; 344 for(cp1=p->code; *cp1++!=',';); 345 while (*cp1!=',') cp1++; *cp1='\0'; 346 pn->code = p->code; pn->pop = NULL; 347 uses[extreg] = NULL; nbj++; 348 p = pn; 349 goto std; 350 } 351 352 case AND: 353 { 354 /* unsigned conversion: 355 ** cvtbl A,B; andl2 $255,B > movzbl A,B 356 ** 357 ** also byte- and word-size fields: 358 ** shrl $(3-n)*8,A,B; andl2 $255,B > movzbl n+A,B 359 ** shrl $(1-n)*16,A,B; andl2 $65535,B > movzwl n+A,B 360 */ 361 char src[C2_ASIZE]; 362 register int f; /* field length */ 363 register struct node *pb = p->back; /* backward node */ 364 365 if (p->subop != U(LONG,OP2)) 366 goto std; 367 splitrand(p); cp1=regs[RT1]; 368 if (*cp1++!='$' || (f=getnum(cp1))!=0xff && f!=0xffff) 369 goto std; 370 f = f==0xff ? 8 : 16; 371 if (pb->op!=CVT && pb->op!=MOVZ && pb->op!=SHAR && pb->op!=SHR) 372 goto std; 373 /* save source of ANDL in 'src' */ 374 strcpy(src, regs[RT2]); 375 splitrand(pb); 376 if (!equstr(src,lastrand)) 377 goto std; 378 if (pb->op==CVT || pb->op==MOVZ) { 379 if (!(bitsize[pb->subop&0xF]==f 380 && bitsize[pb->subop>>4]>=f)) /* good CVT */ 381 goto std; 382 strcpy(src, regs[RT1]); 383 } else { 384 register int boff; /* bit offset */ 385 386 if (regs[RT1][0] != '$') goto std; 387 if ((boff = getnum(®s[RT1][1])) < 0) goto std; 388 if (isreg(regs[RT2])>=0 || !natural(regs[RT2])) goto std; 389 if ((boff & (f-1)) != 0) goto std; 390 boff = (32-boff-f) / 8; 391 if (boff == 0) 392 strcpy(src, regs[RT2]); 393 else 394 sprintf(src, "%d%s%s", boff, regs[RT2][0]=='(' ? "":"+", 395 regs[RT2]); 396 } 397 delnode(pb); 398 p->op = MOVZ; 399 p->subop = U((f==8 ? BYTE : WORD), LONG); 400 sprintf(line,"%s,%s",src,lastrand); 401 p->pop=0; 402 p->code = copy(line); 403 goto std; 404 } 405 406 case CMP: 407 { 408 /* comparison to -63 to -1: 409 ** cmpl r0,$-1 > incl r0 410 ** jeql ... 411 ** 412 ** cmpl r0,$-63 > addl2 $63,r0 413 ** jeql ... 414 */ 415 register int num; 416 register int reg; 417 register struct node *regp = p->back; 418 419 if (p->forw->op != CBR) goto std; 420 if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std; 421 splitrand(p); 422 if (strncmp(regs[RT2], "$-", 2) != 0) goto std; 423 reg = r = isreg(regs[RT1]); 424 if (r < 0) goto std; 425 if (r < NUSE && uses[r] != 0) goto std; 426 if (r >= NUSE && regp->op == MOV && p->subop == regp->subop) 427 { 428 if (*regp->code != 'r') goto std; 429 reg = regp->code[1] - '0'; 430 if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg]) 431 goto std; 432 } 433 if (r >= NUSE) goto std; 434 if (reg != r) 435 sprintf(regs[RT1], "r%d", reg); 436 if ((num = getnum(®s[RT2][2])) <= 0 || num > 63) goto std; 437 if (num == 1) 438 { 439 p->op = INC; regs[RT2][0] = '\0'; 440 } 441 else 442 { 443 register char *t; 444 445 t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t; 446 p->op = ADD; p->subop = U(p->subop, OP2); 447 for (t = ®s[RT1][2]; t[-1] = *t; t++) ; 448 } 449 p->pop = 0; newcode(p); 450 goto std; 451 } 452 453 case JBR: case JMP: 454 clearuse(); 455 if ((p->subop&0xF)==RET) { 456 switch((p->subop>>4)&0xF) { 457 case 2: uses[1]=p; regs[1][0]= -1; 458 case 1: uses[0]=p; regs[0][0]= -1; 459 } 460 break; 461 } 462 if (p->ref==0) goto std; /* jmp (r0) */ 463 /* fall through */ 464 case CBR: 465 if (p->ref->ref!=0) { 466 for (r=NUSE;--r>=0;) 467 if ((1<<r) & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;} 468 if ((1<<NUSE) & (int)p->ref->ref) useacc=p; 469 } 470 break; 471 case LNF: 472 /* lnf a; addf b ==> ldf b; subf a */ 473 { register struct node *pf = p->forw; 474 if(pf->op==ADDF && p->subop==pf->subop) { 475 p->op = LDF; 476 p->pop = 0; 477 pf->op = SUBF; 478 pf->pop = 0; 479 cp1 = p->code; 480 p->code = pf->code; 481 pf->code = cp1; 482 p = pf->forw; 483 break; 484 }} 485 case LDF: case LDFD: case CVLF: /* destroy acc */ 486 useacc = 0; 487 goto std; 488 case STF: 489 { register struct node *pf; 490 if((pf=flops(p)) != p) { 491 p = pf; /* usually p->forw; */ 492 break; 493 }} 494 if(ldmov(p)) { 495 p = p->forw; 496 break; 497 } 498 if(useacc == 0) 499 useacc = p; 500 goto std; 501 case ADDF: case MULF: /* commutatives - create clients for flops */ 502 /* stf a; ldf b; addf a => stf a; ldf a; addf b */ 503 { register struct node *pb = p->back; 504 register struct node *pbb = pb->back; 505 if(pb->op==LDF && pb->subop==p->subop && 506 pbb && pbb->op==STF && pbb->subop==p->subop && 507 equstr(pbb->code, p->code)) { 508 cp1 = p->code; 509 p->code = pb->code; 510 pb->code = cp1; 511 }} 512 /* use acc and regs */ 513 case CMPF: case CVFL: case SUBF: case DIVF: 514 if(useacc == 0) 515 useacc = p; 516 goto std; 517 case TSTF: 518 break; 519 case PUSHD: 520 if(ldmov(p)) { 521 p = p->forw; 522 break; 523 } 524 case CVDF: case NEGF: /* use only acc */ 525 case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF: 526 if(useacc == 0) 527 useacc = p; 528 case EROU: case JSW: 529 case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ; 530 } 531 } 532 for (p= &first; p!=0; p=p->forw) 533 if (p->op==LABEL || p->op==DLABEL) p->ref=0; /* erase our tracks */ 534 } 535 536 char * 537 byondrd(p) register struct node *p; { 538 /* return pointer to register which is "beyond last read/modify operand" */ 539 if (has2ops(p)) return(regs[RT3]); 540 switch (p->op) { 541 case MFPR: 542 case PUSHA: 543 case TST: case INC: case DEC: case PUSH: 544 case LDF: case LNF: case CVLF: case LDFD: 545 case ADDF: case SUBF: case MULF: case DIVF: 546 case CMPF: 547 return(regs[RT2]); 548 case MTPR: 549 #ifndef EMOD 550 case EDIV: 551 #endif EMOD 552 case CBR: /* must be JBC/JBS */ 553 case BIT: case CMP: case CALLS: case CALLF: 554 case CMPF2: 555 return(regs[RT3]); 556 case EMUL: 557 case PROBE: 558 case MOVBLK: 559 case CASE: 560 return(regs[RT4]); 561 } 562 return(lastrand); 563 } 564 565 struct node * 566 bflow(p) 567 register struct node *p; 568 { 569 register char *cp1,*cp2,**preg; 570 register int r, fr, dblflg=0; 571 int flow= -1; 572 struct node *olduse=0, *olduse1=0; 573 574 if (p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4) 575 dblflg |= 1; /* double dest */ 576 if ((p->subop&0xF)==DOUBLE || p->subop==QUAD) 577 dblflg |= 2; /* double src */ 578 splitrand(p); 579 if (p->op!=PUSH && 580 #ifndef EMOD 581 p->op!=EDIV && 582 #endif EMOD 583 p->op!=EMUL && 584 p->subop && tempreg(lastrand,r) && uses[r]==p->forw) { 585 if (equtype(p->subop,regs[r][0]) || 586 ((p->op==CVT || p->op==MOVZ || p->op==CVFL) && 587 (regs[r][0]&0xf) && compat((p->subop>>4)&0xf,regs[r][0])) || 588 p->op==MOVA && compat(LONG, regs[r][0])) { 589 register int r2; 590 591 if (regs[r][1]!=0) { /* send directly to destination */ 592 if (p->op==INC || p->op==DEC) { 593 p->op = (p->op==DEC) ? SUB : ADD; 594 /* use 2 now, convert to 3 later */ 595 p->subop=(OP2<<4)+(p->subop&0xF); 596 p->pop=0; 597 cp1=lastrand; cp2=regs[RT2]; 598 while (*cp2++= *cp1++) /* copy reg */ 599 ; 600 cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; 601 } 602 cp1=regs[r]+1; cp2=lastrand; 603 if (has2ops(p)) { 604 /* use 3 operand form of instruction */ 605 p->pop=0; 606 p->subop += (OP3-OP2)<<4; 607 lastrand = cp2 = regs[RT3]; 608 } 609 while (*cp2++= *cp1++) 610 ; 611 if (p->op==MOVA && p->forw->op==PUSH) { 612 p->op=PUSHA; 613 *regs[RT2]=0; p->pop=0; 614 } else if ((p->op==MOV || p->op==CVT) && 615 p->forw->op==PUSH) { 616 p->op=PUSH; p->subop &= 0xF; 617 *regs[RT2]=0; p->pop=0; 618 } 619 delnode(p->forw); 620 if (tempreg(lastrand,r2)) 621 uses[r2]=uses[r], uses[r]=0; 622 redun3(p); 623 newcode(p); redunm++; flow=r; 624 } else if (p->op==MOV) { /* superfluous fetch */ 625 int nmatch; 626 char src[C2_ASIZE]; 627 movit: 628 for (cp2=src, cp1=regs[RT1]; *cp2++= *cp1++;) 629 ; 630 splitrand(p->forw); 631 if (p->forw->op != INC && p->forw->op != DEC) 632 lastrand=byondrd(p->forw); 633 nmatch=0; 634 for (preg=regs+RT1;*preg!=lastrand;preg++) 635 if (r==isreg(*preg)) { 636 cp2= *preg; cp1=src; 637 while (*cp2++= *cp1++) 638 ; 639 ++nmatch; 640 } 641 if (nmatch==1) { 642 if (has2ops(p->forw) && equstr(src,regs[RT2])) { 643 p->forw->pop=0; 644 p->forw->subop += (OP3-OP2)<<4; 645 cp1=regs[RT3]; 646 *cp1++ = 'r'; *cp1++ = r+'0'; *cp1=0; 647 } 648 delnode(p); 649 p=p->forw; 650 if (tempreg(src,r2)) 651 uses[r2]=uses[r], uses[r]=0; 652 redun3(p); 653 newcode(p); redunm++; flow=r; 654 } else 655 splitrand(p); 656 } 657 } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) && 658 p->forw->subop&0xf && /* if base or index, then forget it */ 659 compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1])) 660 goto movit; 661 } 662 /* adjust 'lastrand' past any 'read' or 'modify' operands. */ 663 lastrand=byondrd(p); 664 /* a 'write' clobbers the register. */ 665 if (tempreg(lastrand,r) || 666 (has2ops(p) && tempreg(regs[RT2],r) && uses[r]==0)) { 667 /* 668 * Writing a dead register is useless, 669 * but watch side effects 670 */ 671 switch (p->op) { 672 #ifndef EMOD 673 case EDIV: 674 #endif EMOD 675 case EMUL: 676 case AOBLEQ: case AOBLSS: 677 break; 678 default: 679 /* 680 * If no direct uses, check for 681 * use of condition codes 682 */ 683 if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) { 684 register struct node *q = p; 685 686 while ((q = nonlab(q->forw))->op==JBR && 687 q->subop==0) 688 q=q->ref; /* cc unused, unchanged */ 689 if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) { 690 /* ... and destroyed */ 691 preg=regs+RT1; 692 while (cp1 = *preg++) { 693 if (cp1==lastrand && 694 p->op != CLR && 695 p->op != CVFL) { 696 redunm++; 697 delnode(p); 698 return(p->forw); 699 } 700 if (equstr(cp1,lastrand)) 701 break; 702 } 703 } 704 } 705 flow=r; 706 } 707 } 708 if ((r=flow) >= 0) { 709 olduse=uses[r], uses[r]=0; 710 *(short *)(regs[r])=0; 711 /* if r0 destroyed, dont keep r1 */ 712 if (dblflg&1) { 713 olduse1=uses[++r], uses[r]=0; 714 *(short *)(regs[r])=0; 715 } 716 } 717 /* now look for 'read' or 'modify' (read & write) uses */ 718 preg=regs+RT1; 719 while (*(cp1= *preg++)) { 720 /* check for r */ 721 if (lastrand!=cp1 && tempreg(cp1,r)) { 722 int isunused; 723 if (isunused=(uses[r]==0)) { 724 uses[r]=p; 725 cp2=regs[r]; *cp2++=p->subop; 726 if ((p->op==SHAL || p->op==SHAR || 727 p->op==SHL || p->op==SHR) && 728 cp1==regs[RT1]) 729 cp2[-1] = BYTE; 730 if (p->op==CBR && (p->subop==JBC || p->subop==JBS)) 731 cp2[-1] = LONG; 732 if (p->op==MOVA && cp1==regs[RT2]) 733 cp2[-1]=LONG; 734 } 735 /* ediv/emod's 2nd operand is quad */ 736 if (((p->op==EDIV 737 #ifdef EMOD 738 || p->op==EMOD 739 #endif EMOD 740 ) && cp1==regs[RT2] || (dblflg&2)) && 741 ++r<NUSE && uses[r]==0) { 742 if (isunused) 743 *cp2=0; 744 uses[r]=p; 745 cp2=regs[r]; *cp2++=p->subop; 746 if (!isunused) 747 *cp2=0; 748 } 749 if (!isunused) 750 continue; 751 if (p->op==MOV || p->op==PUSH || p->op==CVT || 752 p->op==MOVZ || p->op==COM || p->op==NEG || 753 p->op==STF) { 754 if (p->op!=PUSH) { 755 cp1=regs[RT2]; 756 if (tempreg(cp1,r)) { 757 /* 758 * reincarnation!! 759 * (as in addl2 r0,r1; 760 * movl r1,r0; ret) 761 */ 762 if (uses[r]==0) 763 uses[r]=olduse; 764 if ((dblflg&1) && uses[r+1]==0) 765 uses[r+1]=olduse1; 766 } 767 if (p->op!=MOV) 768 cp1=0; 769 } else 770 cp1="-(sp)"; 771 if (cp1) 772 while (*cp2++= *cp1++) 773 ; 774 else 775 *cp2=0; 776 } else 777 *cp2=0; 778 continue; 779 } 780 /* check for (r),[r] */ 781 do { 782 if (*cp1=='(' || *cp1=='[') { /* get register number */ 783 char t; 784 for (cp2= ++cp1; *++cp1!=')' && *cp1!=']';) 785 ; 786 t= *cp1; *cp1=0; 787 if (tempreg(cp2,r) && 788 (uses[r]==0 || uses[r]==p)) { 789 uses[r]=p; 790 regs[r][0] = 791 (*--cp2=='[' ? OPX<<4 : OPB<<4); 792 } 793 *cp1=t; 794 } 795 } while (*++cp1); 796 } 797 #ifdef MOVAFASTER 798 /* pushax or movax possibility? */ 799 cp1=regs[RT1]; 800 if (*cp1++=='$' && isstatic(cp1)) { 801 if (p->op==MOV && p->subop==LONG) { 802 if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { 803 cp1=p->code; while (*cp1++!=','); p->code= --cp1; 804 } 805 p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0; 806 } else if (p->op==PUSH && p->subop==LONG) { 807 p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0; 808 } else if (p->op==ADD && p->subop==U(LONG,OP3) 809 && 0<=(r=isreg(regs[RT2]))) { 810 cp1=cp2=p->code; ++cp1; 811 do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='['; 812 do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']'; 813 if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;} 814 else {p->op = PUSHA; p->subop = BYTE; *cp2=0;} 815 if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;} 816 p->pop=0; 817 } 818 } 819 #endif MOVAFASTER 820 return (p); 821 } 822 823 /* try to eliminate STF's */ 824 struct node * 825 flops(q) 826 register struct node *q; 827 { 828 register struct node *p; 829 register int r; 830 831 if(q->op!=STF || !tempreg(q->code,r)) 832 return(q); 833 if(uses[r]) { 834 /* see if anyone destroys acc between us */ 835 for(p=q->forw; p!=uses[r]; p=p->forw) 836 switch(p->op) { 837 case LABEL: 838 case LDF: case LNF: case CVLF: case LDFD: 839 case CVDF: case NEGF: case ADDF: case SUBF: 840 case MULF: case DIVF: case SINF: case COSF: 841 case ATANF: case LOGF: case SQRTF: case EXPF: 842 return(q); 843 } 844 845 if(q->subop == p->subop) 846 switch(p->op) { /* do it in the accumulator */ 847 case LDF: /* redundant load */ 848 delnode(p); nld++; 849 p = p->forw; 850 break; 851 case LNF: /* stf r; lnf r ==> negf */ 852 p->op = NEGF; 853 p->pop = 0; 854 p->code = 0; 855 break; 856 case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */ 857 { register char *s; 858 register struct node *p1=p->forw; 859 for(s=p->code; *s!=','; s++); 860 *s = 0; 861 if(isreg(p->code) == r) 862 p->code = s+1; 863 else { 864 if(p1->op != CBR || isreg(s+1) != r) { 865 *s = ','; 866 return(q); 867 } 868 if(p1->subop > JNE) { 869 p1->subop ^= 1; 870 p1->pop = 0; 871 nrevbr++; 872 } 873 } 874 p->op = CMPF; 875 p->pop = 0; 876 } 877 break; 878 default: 879 return(q); 880 } 881 else if(p->subop==LONG) { 882 switch(p->op) { 883 case TST: /* stf r; tstl r ==> tstf */ 884 p->op = TSTF; 885 p->code = 0; 886 break; 887 /* send directly to destination */ 888 case MOV: /* stf r; movl r,x ==> stf x */ 889 case PUSH: /* stf r; pushl r ==> stf -(sp)/pushd */ 890 if(q->subop == DOUBLE) { 891 register struct node *b = p->back; 892 /* assume b's 2nd arg is ok */ 893 if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG)) 894 return(q); 895 delnode(b); redunm++; 896 } 897 if(p->op==PUSH) { 898 if(q->subop == DOUBLE) { 899 p->op = PUSHD; 900 p->code = 0; 901 } else { 902 p->op = q->op; 903 p->code = copy("-(sp)"); 904 } 905 } else { 906 p->op = q->op; 907 while(*p->code++ != ','); 908 } 909 break; 910 default: 911 return(q); 912 } 913 p->pop = 0; 914 p->subop = q->subop; 915 } else 916 return(q); 917 uses[r] = 0; 918 if(q->subop == DOUBLE) 919 uses[r+1] = 0; 920 { /* undo any effect on uses in the area between p and q, 921 * as we are going over it again */ 922 register struct node *b; 923 for(b=p; b!=q; b=b->back) { 924 for(r=0; r<NUSE; r++) { 925 if(uses[r] == b) 926 uses[r] = 0; 927 if(useacc == b) 928 useacc = 0; 929 } 930 } 931 } 932 return(p->forw); /* make p the next for bflow */ 933 } 934 /* it's a store to reg which isnt used elsewhere */ 935 if((p=q->forw)->op == CBR) { 936 q->op = TSTF; 937 q->pop = 0; 938 q->code = 0; 939 } else { 940 delnode(q); nst++; 941 if(p->op ==STF || p->op==TSTF || p->op==PUSHD) { 942 if(useacc == p) 943 useacc = 0; 944 return(p->forw); /* so ldmov can be used on p */ 945 } 946 } 947 return(p); 948 } 949 950 /* try to change load/store sequences to movl */ 951 ldmov(q) 952 register struct node *q; 953 { 954 register struct node *p; 955 register char *s, *pcod, *cp; 956 char *dlsw(); 957 958 p = q->back; 959 if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD) 960 && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE)))) 961 return(0); 962 pcod = p->code; 963 cp = p->code; 964 /* prepare args for movl/pushl */ 965 if(q->op!=TSTF && q->subop==DOUBLE) { 966 if(p->op == LDF) { 967 if((s = dlsw(p->code)) == NULL) 968 return(0); 969 970 strcpy(line, s); 971 if(q->op == STF) { 972 strcat(line, ","); 973 if((s = dlsw(q->code)) == NULL) 974 return(0); 975 strcat(line, s); 976 p->op = MOV; 977 } else 978 p->op = PUSH; 979 } else { /* LDFD */ 980 if(q->op == STF) { 981 if((s = dlsw(q->code)) == NULL) 982 return(0); 983 } else 984 s = "-(sp)"; 985 strcpy(line, s); 986 p->op = CLR; 987 } 988 p->pop = 0; 989 p->subop = LONG; 990 p->code = copy(line); 991 } else 992 { 993 if ((p->op == LDF) && (p->subop == DOUBLE) && 994 (indexa(cp))) return(0); 995 delnode(p); 996 } 997 strcpy(line, pcod); 998 if(q->op == STF) { /* ldf x; stf y ==> movl x,y */ 999 strcat(line, ","); 1000 strcat(line, q->code); 1001 q->op = MOV; 1002 nst++; 1003 } else if(q->op == TSTF) /* ldf x; tstf ==> tstl x */ 1004 q->op = TST; 1005 else /* ldd x; pushd ==> pushl x+4; pushl x */ 1006 q->op = PUSH; 1007 q->pop = 0; 1008 q->subop = LONG; 1009 q->code = copy(line); 1010 nld++; 1011 return(1); 1012 } 1013 1014 /* reconstruct the address of l.s.w. of a double operand */ 1015 char * 1016 dlsw(d) 1017 register char *d; 1018 { 1019 register char *s, *t, *c; 1020 register int r; 1021 static char lsw[C2_ASIZE]; 1022 1023 if(d[0] == '*' || d[0] == '$') 1024 return(NULL); 1025 if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2])) 1026 return(NULL); 1027 t = lsw; 1028 if((r=isreg(d)) >= 0) 1029 sprintf(t, "r%d", r+1); 1030 else { 1031 for(s=d; *s && *s!='('; *t++ = *s++) 1032 if(*s == '[') 1033 return(NULL); 1034 if(s!=d) 1035 *t++ = '+'; 1036 *t++ = '4'; 1037 while(*t++ = *s) 1038 if(*s++ == '[' ) 1039 { 1040 return(NULL); 1041 } 1042 } 1043 return(lsw); 1044 } 1045 checkexpr(p) 1046 register char *p; 1047 { 1048 1049 while(*p && *p != ','){ 1050 if ((*p == '+' ) || (*p == '-')) 1051 return(1); 1052 *p++; 1053 } 1054 return(0); 1055 } 1056