1 #ifndef lint 2 static char sccsid[] = "@(#)c21.c 1.1 (Berkeley) 03/02/86"; 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 (OP3==((p->subop>>4)&0xF)) { 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)|p->op) { 60 case (('0'<<8)|ADD): 61 case (('0'<<8)|SUB): 62 case (('-'<<8)|AND): 63 case (('0'<<8)|OR): 64 case (('0'<<8)|XOR): 65 case (('1'<<8)|MUL): 66 case (('1'<<8)|DIV): 67 case (('0'<<8)|SHAL): 68 case (('0'<<8)|SHAR): 69 case (('0'<<8)|SHL): 70 case (('0'<<8)|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)|MUL): 86 case (('0'<<8)|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 0: 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 p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1; 129 } goto std; 130 case ADD: 131 if ((p->subop&0xF)!=LONG) goto std; cp1=p->code; 132 if (*cp1++!='$') goto std; splitrand(p); 133 if (isstatic(cp1) && (r=isreg(regs[RT2]))>=0 && r<NUSE && uses[r]==p->forw) 134 { 135 /* address comp: 136 ** addl2 $_foo,r0 \ movab _foo[r0],bar 137 ** movl r0,bar / 138 */ 139 register struct node *pnext = p->forw; 140 char buf[C2_ASIZE]; 141 142 if (pnext->op == MOV && pnext->subop == LONG) 143 { 144 cp1 = ®s[RT1][1]; cp2 = &buf[0]; 145 while (*cp2++ = *cp1++) ; cp2--; 146 splitrand(pnext); 147 if (r == isreg(regs[RT1])) 148 { 149 delnode(p); p = pnext; 150 p->op = MOVA; p->subop = BYTE; 151 p->pop = 0; 152 cp1 = regs[RT1]; *cp2++ = '['; 153 while (*cp2++ = *cp1++) ; cp2--; 154 *cp2++ = ']'; *cp2++ = ','; 155 cp1 = regs[RT2]; 156 while (*cp2++ = *cp1++) ; 157 p->code = copy(buf); 158 } 159 } 160 } 161 else 162 #ifdef MOVAFASTER 163 if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */ 164 cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2; 165 cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=','; 166 p->op = MOVA; p->subop = BYTE; p->pop=0; 167 } else 168 #endif MOVAFASTER 169 if (*cp1++=='-' && 0<=(r=getnum(cp1))) { 170 p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1; 171 } 172 /* fall thru ... */ 173 case CASE: 174 default: std: 175 p=bflow(p); break; 176 177 case MUL: 178 /* 179 ** Change multiplication 180 ** by constant powers of 2 to shifts. 181 */ 182 splitrand(p); 183 if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std; 184 if ((r = ispow2(getnum(®s[RT1][1]))) <= 0) goto std; 185 /* mull2 $2,x */ 186 if(r == 1 && p->subop == U(LONG, OP2)) { 187 strcpy(regs[RT1], regs[RT2]); 188 p->op = ADD; p->pop = 0; newcode(p); 189 goto std; 190 } 191 if (p->subop == U(LONG,OP2)) 192 strcpy(regs[RT3], regs[RT2]); 193 sprintf(regs[RT1], "$%d", r); 194 p->op = SHL; p->subop = LONG; 195 p->pop = 0; newcode(p); 196 goto std; 197 198 case SHAL: 199 case SHL: 200 { 201 /* bit tests: 202 ** shll A,$1,rC \ 203 ** bitl B,rC > jbc A,B,D 204 ** jeql D / 205 ** 206 ** address comp: 207 ** shll $1,bar,r0 \ movl bar,r0 208 ** movab _foo[r0] / movaw _foo[r0] 209 ** 210 ** shll $2,r0,r0 \ moval _foo[r0] 211 ** movab _foo[r0] / 212 */ 213 register struct node *pf; 214 register struct node *pn; 215 register int shfrom, shto; 216 long shcnt; 217 char *regfrom; 218 219 splitrand(p); 220 if (regs[RT1][0] != '$') { 221 if(isreg(regs[RT1]) < 0) goto std; /* alignment */ 222 if (regs[RT2][0] != '$') goto std; 223 if (getnum(®s[RT2][1]) != 1) goto std; 224 r = isreg(regs[RT3]); 225 if (r < 0 || r >= NUSE) goto std; 226 if ((pf = p->forw)->op != BIT && pf->op!=AND) goto std; 227 if (uses[r] && uses[r] != pf) goto std; 228 splitrand(pf); 229 if (r == isreg(regs[RT1])) cp2 = regs[RT2]; 230 else if (r == isreg(regs[RT2])) cp2 = regs[RT1]; 231 else goto std; 232 if (*cp2 == '$') goto std; 233 if ((pn = pf->forw)->op != CBR) goto std; 234 if (pn->subop != JEQ && pn->subop != JNE) goto std; 235 delnode(p); delnode(pf); 236 pn->subop = (pn->subop == JEQ) ? JBC : JBS; 237 for(cp1=p->code; *cp1++!=',';); 238 while (*cp1++= *cp2++); 239 pn->code = p->code; pn->pop = NULL; 240 uses[r] = NULL; 241 nbj++; 242 p = pn; 243 goto std; 244 } 245 if ((shcnt = getnum(®s[RT1][1])) < 1 || shcnt > 2) goto std; 246 if ((shfrom = isreg(regs[RT2])) >= 0) 247 regfrom = copy(regs[RT2]); 248 if ((shto = isreg(regs[RT3])) >= 0 && shto<NUSE) 249 { 250 int regnum; 251 252 if (uses[shto] != (pf = p->forw)) goto ashadd; 253 if (pf->op != MOVA && pf->op != PUSHA) goto ashadd; 254 if (pf->subop != BYTE) goto ashadd; 255 splitrand(pf); 256 if (!indexa(regs[RT1])) goto std; 257 cp2 = regs[RT1]; 258 if(!isstatic(cp2)) goto std; 259 while (*cp2++ != '[') ; 260 if (*cp2++ != 'r' || !isdigit(*cp2)) goto std; 261 regnum = *cp2++ - '0'; 262 if (isdigit(*cp2)) 263 { 264 if (cp2[1] != ']') goto std; 265 regnum *= 10; regnum += *cp2 - '0'; 266 } 267 if (regnum != shto) goto std; 268 if (shfrom >= 0) /* shll $N,r*,r0 */ 269 { 270 delnode(p); 271 p = pf; 272 if (shfrom != shto) 273 { 274 uses[shto] = NULL; splitrand(pf); 275 cp2=regs[RT1]; while (*cp2++!='['); 276 cp1=regfrom; while (*cp2++= *cp1++); 277 cp2[-1] = ']'; *cp2 = 0; 278 newcode(pf); 279 } 280 } 281 else 282 { 283 p->op = MOV; splitrand(p); 284 strcpy(regs[RT1], regs[RT2]); 285 strcpy(regs[RT2], regs[RT3]); 286 regs[RT3][0] = '\0'; 287 p->pop = 0; newcode(p); 288 } 289 switch (shcnt) 290 { 291 case 1: pf->subop = WORD; break; 292 case 2: pf->subop = LONG; break; 293 } 294 redunm++; nsaddr++; 295 } 296 goto std; 297 ashadd: 298 /* at this point, RT2 and RT3 are guaranteed to be simple regs*/ 299 if (shcnt == 1) { 300 /* 301 ** quickie: 302 ** shll $1,A,A > addl2 A,A 303 ** shll $1,A,B > addl3 A,A,B 304 */ 305 p->op = ADD; 306 strcpy(regs[RT1], regs[RT2]); 307 if(equstr(regs[RT2], regs[RT3])) { 308 p->subop = U(LONG,OP2); 309 regs[RT3][0] = '\0'; 310 } else 311 p->subop = U(LONG,OP3); 312 p->pop = 0; 313 newcode(p); 314 } 315 goto std; 316 } 317 318 case SHAR: 319 case SHR: 320 { 321 /* bit tests: 322 ** shrl A,B,rC \ 323 ** bitl $1,rC > jbc A,B,D 324 ** jeql D / 325 */ 326 register struct node *pf; /* forward node */ 327 register struct node *pn; /* next node (after pf) */ 328 register int extreg; /* reg extracted to */ 329 330 splitrand(p); 331 if(isreg(regs[RT1]) < 0) goto std; /* alignment */ 332 extreg = isreg(regs[RT3]); 333 if (extreg < 0 || extreg >= NUSE) 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: case PUSHD: 518 if(ldmov(p)) { 519 p = p->forw; 520 break; 521 } 522 case CVDF: case NEGF: /* use only acc */ 523 case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF: 524 if(useacc == 0) 525 useacc = p; 526 case EROU: case JSW: 527 case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ; 528 } 529 } 530 for (p= &first; p!=0; p=p->forw) 531 if (p->op==LABEL || p->op==DLABEL) p->ref=0; /* erase our tracks */ 532 } 533 534 char * 535 byondrd(p) register struct node *p; { 536 /* return pointer to register which is "beyond last read/modify operand" */ 537 if (OP2==(p->subop>>4)) return(regs[RT3]); 538 switch (p->op) { 539 case MFPR: 540 case PUSHA: 541 case TST: case INC: case DEC: case PUSH: 542 case LDF: case LNF: case CVLF: case LDFD: 543 case ADDF: case SUBF: case MULF: case DIVF: 544 case CMPF: 545 return(regs[RT2]); 546 case MTPR: 547 #ifndef EMOD 548 case EDIV: 549 #endif EMOD 550 case CBR: /* must be JBC/JBS */ 551 case BIT: case CMP: case CALLS: case CALLF: 552 case CMPF2: 553 return(regs[RT3]); 554 case EMUL: 555 case PROBE: 556 case MOVBLK: 557 case CASE: 558 return(regs[RT4]); 559 } 560 return(lastrand); 561 } 562 563 struct node * 564 bflow(p) 565 register struct node *p; 566 { 567 register char *cp1,*cp2,**preg; 568 register int r, fr, dblflg=0; 569 int flow= -1; 570 struct node *olduse=0, *olduse1=0; 571 572 if(p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4) 573 dblflg |= 1; /* double dest */ 574 if((p->subop&0xF)==DOUBLE || p->subop==QUAD) 575 dblflg |= 2; /* double src */ 576 splitrand(p); 577 if (p->op!=PUSH 578 #ifndef EMOD 579 && p->op!=EDIV 580 #endif EMOD 581 && p->op!=EMUL 582 && p->subop && 0<=(r=isreg(lastrand)) && r<NUSE && uses[r]==p->forw) { 583 if (equtype(p->subop,regs[r][0]) 584 || ((p->op==CVT || p->op==MOVZ || p->op==CVFL) 585 && 0xf®s[r][0] && compat(0xf&(p->subop>>4),regs[r][0])) 586 || p->op==MOVA && compat(LONG, regs[r][0])) { 587 register int r2; 588 if (regs[r][1]!=0) {/* send directly to destination */ 589 if (p->op==INC || p->op==DEC) { 590 if (p->op==DEC) p->op=SUB; else p->op=ADD; 591 p->subop=(OP2<<4)+(p->subop&0xF); /* use 2 now, convert to 3 later */ 592 p->pop=0; 593 cp1=lastrand; cp2=regs[RT2]; while (*cp2++= *cp1++); /* copy reg */ 594 cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; 595 } 596 cp1=regs[r]+1; cp2=lastrand; 597 if (OP2==(p->subop>>4)) {/* use 3 operand form of instruction */ 598 p->pop=0; 599 p->subop += (OP3-OP2)<<4; lastrand=cp2=regs[RT3]; 600 } 601 while (*cp2++= *cp1++); 602 if (p->op==MOVA && p->forw->op==PUSH) { 603 p->op=PUSHA; 604 *regs[RT2]=0; p->pop=0; 605 } else if ((p->op==MOV || p->op==CVT) && p->forw->op==PUSH) { 606 p->op=PUSH; p->subop &= 0xF; 607 *regs[RT2]=0; p->pop=0; 608 } 609 delnode(p->forw); 610 if (0<=(r2=isreg(lastrand)) && r2<NUSE) { 611 uses[r2]=uses[r]; uses[r]=0; 612 } 613 redun3(p); 614 newcode(p); redunm++; flow=r; 615 } else if (p->op==MOV) { 616 /* superfluous fetch */ 617 int nmatch; 618 char src[C2_ASIZE]; 619 movit: 620 cp2=src; cp1=regs[RT1]; while (*cp2++= *cp1++); 621 splitrand(p->forw); 622 if (p->forw->op != INC && p->forw->op != DEC) 623 lastrand=byondrd(p->forw); 624 nmatch=0; 625 for (preg=regs+RT1;*preg!=lastrand;preg++) 626 if (r==isreg(*preg)) { 627 cp2= *preg; cp1=src; while (*cp2++= *cp1++); ++nmatch; 628 } 629 if (nmatch==1) { 630 if (OP2==(p->forw->subop>>4) && equstr(src,regs[RT2])) { 631 p->forw->pop=0; 632 p->forw->subop += (OP3-OP2)<<4; cp1=regs[RT3]; 633 *cp1++='r'; *cp1++=r+'0'; *cp1=0; 634 } 635 delnode(p); p=p->forw; 636 if (0<=(r2=isreg(src)) && r2<NUSE) { 637 uses[r2]=uses[r]; uses[r]=0; 638 } 639 redun3(p); 640 newcode(p); redunm++; flow=r; 641 } else splitrand(p); 642 } 643 } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) 644 && p->forw->subop&0xf /* if base or index, then forget it */ 645 && compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1])) 646 goto movit; 647 } 648 /* adjust 'lastrand' past any 'read' or 'modify' operands. */ 649 lastrand=byondrd(p); 650 /* a 'write' clobbers the register. */ 651 if (0<=(r=isreg(lastrand)) && r<NUSE 652 || OP2==(p->subop>>4) && 0<=(r=isreg(regs[RT2])) && r<NUSE && uses[r]==0) { 653 /* writing a dead register is useless, but watch side effects */ 654 switch (p->op) { 655 #ifndef EMOD 656 case EDIV: 657 #endif EMOD 658 case EMUL: 659 case AOBLEQ: case AOBLSS: break; 660 default: 661 if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) { 662 /* no direct uses, check for use of condition codes */ 663 register struct node *q=p; 664 while ((q=nonlab(q->forw))->op==JBR && q->subop==0) q=q->ref; /* cc unused, unchanged */ 665 if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) {/* ... and destroyed */ 666 preg=regs+RT1; 667 while (cp1= *preg++) { 668 if ((cp1==lastrand) && 669 (p->op != CLR) && 670 (p->op != CVFL)) 671 {redunm++; delnode(p); return(p->forw);} 672 if (equstr(cp1,lastrand)) break; 673 } 674 } 675 } 676 flow=r; 677 } 678 } 679 if (0<=(r=flow)) { 680 olduse=uses[r]; uses[r]=0; *(short *)(regs[r])=0; 681 /* if r0 destroyed, dont keep r1 */ 682 if(dblflg&1) { 683 olduse1=uses[++r]; uses[r]=0; *(short *)(regs[r])=0; 684 } 685 } 686 /* now look for 'read' or 'modify' (read & write) uses */ 687 preg=regs+RT1; 688 while (*(cp1= *preg++)) { 689 /* check for r */ 690 if (lastrand!=cp1 && 0<=(r=isreg(cp1)) && r<NUSE && (uses[r]==0)){ 691 uses[r]=p; cp2=regs[r]; *cp2++=p->subop; 692 if((p->op==SHAL || p->op==SHAR || p->op==SHL || p->op==SHR) 693 && cp1==regs[RT1]) cp2[-1]=BYTE; 694 if(p->op==CBR && (p->subop==JBC || p->subop==JBS)) cp2[-1]=LONG; 695 if(p->op==MOVA && cp1==regs[RT2]) cp2[-1]=LONG; 696 /* ediv/emod's 2nd operand is quad */ 697 if(((p->op==EDIV 698 #ifdef EMOD 699 || p->op==EMOD 700 #endif EMOD 701 ) && cp1==regs[RT2] || (dblflg&2)) 702 && ++r<NUSE && uses[r]==0) { 703 *cp2=0; 704 uses[r]=p; cp2=regs[r]; *cp2++=p->subop; 705 } 706 if(p->op==MOV || p->op==PUSH || p->op==CVT || 707 p->op==MOVZ || p->op==COM || p->op==NEG || p->op==STF) { 708 if (p->op==PUSH) cp1="-(sp)"; 709 else { 710 cp1=regs[RT2]; 711 if (0<=(r=isreg(cp1)) && r<NUSE) { 712 /* reincarnation!! */ 713 /* as in addl2 r0,r1; movl r1,r0; ret */ 714 if(uses[r]==0) 715 uses[r]=olduse; 716 if((dblflg&1) && uses[r+1]==0) 717 uses[r+1]=olduse1; 718 } 719 if (p->op!=MOV) cp1=0; 720 } 721 if (cp1) while (*cp2++= *cp1++); 722 else *cp2=0; 723 } else *cp2=0; 724 continue; 725 } 726 /* check for (r),[r] */ 727 do if (*cp1=='(' || *cp1=='[') {/* get register number */ 728 char t; 729 cp2= ++cp1; while (*++cp1!=')' && *cp1!=']'); t= *cp1; *cp1=0; 730 if (0<=(r=isreg(cp2)) && r<NUSE && (uses[r]==0 || uses[r]==p)) { 731 uses[r]=p; regs[r][0]=(*--cp2=='[' ? OPX<<4 : OPB<<4); 732 } 733 *cp1=t; 734 } while (*++cp1); 735 } 736 #ifdef MOVAFASTER 737 /* pushax or movax possibility? */ 738 cp1=regs[RT1]; 739 if (*cp1++=='$' && isstatic(cp1)) { 740 if (p->op==MOV && p->subop==LONG) { 741 if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { 742 cp1=p->code; while (*cp1++!=','); p->code= --cp1; 743 } 744 p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0; 745 } else if (p->op==PUSH && p->subop==LONG) { 746 p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0; 747 } else if (p->op==ADD && p->subop==U(LONG,OP3) 748 && 0<=(r=isreg(regs[RT2]))) { 749 cp1=cp2=p->code; ++cp1; 750 do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='['; 751 do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']'; 752 if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;} 753 else {p->op = PUSHA; p->subop = BYTE; *cp2=0;} 754 if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;} 755 p->pop=0; 756 } 757 } 758 #endif MOVAFASTER 759 return(p); 760 } 761 762 /* try to eliminate STF's */ 763 struct node * 764 flops(q) 765 register struct node *q; 766 { 767 register struct node *p; 768 register int r; 769 770 if(!(q->op==STF && ((r=isreg(q->code))<NUSE) && r>=0)) 771 return(q); 772 if(uses[r]) { 773 /* see if anyone destroys acc between us */ 774 for(p=q->forw; p!=uses[r]; p=p->forw) 775 switch(p->op) { 776 case LABEL: 777 case LDF: case LNF: case CVLF: case LDFD: 778 case CVDF: case NEGF: case ADDF: case SUBF: 779 case MULF: case DIVF: case SINF: case COSF: 780 case ATANF: case LOGF: case SQRTF: case EXPF: 781 return(q); 782 } 783 784 if(q->subop == p->subop) 785 switch(p->op) { /* do it in the accumulator */ 786 case LDF: /* redundant load */ 787 delnode(p); nld++; 788 p = p->forw; 789 break; 790 case LNF: /* stf r; lnf r ==> negf */ 791 p->op = NEGF; 792 p->pop = 0; 793 p->code = 0; 794 break; 795 case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */ 796 { register char *s; 797 register struct node *p1=p->forw; 798 for(s=p->code; *s!=','; s++); 799 *s = 0; 800 if(isreg(p->code) == r) 801 p->code = s+1; 802 else { 803 if(p1->op != CBR || isreg(s+1) != r) { 804 *s = ','; 805 return(q); 806 } 807 if(p1->subop > JNE) { 808 p1->subop ^= 1; 809 p1->pop = 0; 810 nrevbr++; 811 } 812 } 813 p->op = CMPF; 814 p->pop = 0; 815 } 816 break; 817 default: 818 return(q); 819 } 820 else if(p->subop==LONG) { 821 switch(p->op) { 822 case TST: /* stf r; tstl r ==> tstf */ 823 p->op = TSTF; 824 p->code = 0; 825 break; 826 /* send directly to destination */ 827 case MOV: /* stf r; movl r,x ==> stf x */ 828 case PUSH: /* stf r; pushl r ==> stf -(sp)/pushd */ 829 if(q->subop == DOUBLE) { 830 register struct node *b = p->back; 831 /* assume b's 2nd arg is ok */ 832 if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG)) 833 return(q); 834 delnode(b); redunm++; 835 } 836 if(p->op==PUSH) { 837 if(q->subop == DOUBLE) { 838 p->op = PUSHD; 839 p->code = 0; 840 } else { 841 p->op = q->op; 842 p->code = copy("-(sp)"); 843 } 844 } else { 845 p->op = q->op; 846 while(*p->code++ != ','); 847 } 848 break; 849 default: 850 return(q); 851 } 852 p->pop = 0; 853 p->subop = q->subop; 854 } else 855 return(q); 856 uses[r] = 0; 857 if(q->subop == DOUBLE) 858 uses[r+1] = 0; 859 { /* undo any effect on uses in the area between p and q, 860 * as we are going over it again */ 861 register struct node *b; 862 for(b=p; b!=q; b=b->back) { 863 for(r=0; r<NUSE; r++) { 864 if(uses[r] == b) 865 uses[r] = 0; 866 if(useacc == b) 867 useacc = 0; 868 } 869 } 870 } 871 return(p->forw); /* make p the next for bflow */ 872 } 873 /* it's a store to reg which isnt used elsewhere */ 874 if((p=q->forw)->op == CBR) { 875 q->op = TSTF; 876 q->pop = 0; 877 q->code = 0; 878 } else { 879 delnode(q); nst++; 880 if(p->op ==STF || p->op==TSTF || p->op==PUSHD) { 881 if(useacc == p) 882 useacc = 0; 883 return(p->forw); /* so ldmov can be used on p */ 884 } 885 } 886 return(p); 887 } 888 889 /* try to change load/store sequences to movl */ 890 ldmov(q) 891 register struct node *q; 892 { 893 register struct node *p; 894 register char *s, *pcod, *cp; 895 char *dlsw(); 896 897 p = q->back; 898 if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD) 899 && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE)))) 900 return(0); 901 pcod = p->code; 902 cp = p->code; 903 /* prepare args for movl/pushl */ 904 if(q->op!=TSTF && q->subop==DOUBLE) { 905 if(p->op == LDF) { 906 if((s = dlsw(p->code)) == NULL) 907 return(0); 908 strcpy(line, s); 909 if(q->op == STF) { 910 strcat(line, ","); 911 if((s = dlsw(q->code)) == NULL) 912 return(0); 913 strcat(line, s); 914 p->op = MOV; 915 } else 916 p->op = PUSH; 917 } else { /* LDFD */ 918 if(q->op == STF) { 919 if((s = dlsw(q->code)) == NULL) 920 return(0); 921 } else 922 s = "-(sp)"; 923 strcpy(line, s); 924 p->op = CLR; 925 } 926 p->pop = 0; 927 p->subop = LONG; 928 p->code = copy(line); 929 } else 930 { 931 if ((p->op == LDF) && (p->subop == DOUBLE) && 932 (indexa(cp))) return(0); 933 delnode(p); 934 } 935 strcpy(line, pcod); 936 if(q->op == STF) { /* ldf x; stf y ==> movl x,y */ 937 strcat(line, ","); 938 strcat(line, q->code); 939 q->op = MOV; 940 nst++; 941 } else if(q->op == TSTF) /* ldf x; tstf ==> tstl x */ 942 q->op = TST; 943 else /* ldd x; pushd ==> pushl x+4; pushl x */ 944 q->op = PUSH; 945 q->pop = 0; 946 q->subop = LONG; 947 q->code = copy(line); 948 nld++; 949 return(1); 950 } 951 952 /* reconstruct the address of l.s.w. of a double operand */ 953 char * 954 dlsw(d) 955 register char *d; 956 { 957 register char *s, *t; 958 register int r; 959 static char lsw[C2_ASIZE]; 960 961 if(d[0] == '*' || d[0] == '$') 962 return(NULL); 963 t = lsw; 964 if((r=isreg(d)) >= 0) 965 sprintf(t, "r%d", r+1); 966 else { 967 for(s=d; *s && *s!='('; *t++ = *s++) 968 if(*s == '[') 969 return(NULL); 970 *t++ = '+'; *t++ = '4'; 971 while(*t++ = *s) 972 if(*s++ == '[') 973 return(NULL); 974 } 975 return(lsw); 976 } 977