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