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