1 #ifndef lint 2 static char sccsid[] = "@(#)c21.c 1.7 (Berkeley/CCI) 01/15/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 p->op==EMUL) 576 dblflg |= 1; /* double dest */ 577 if ((p->subop&0xF)==DOUBLE || p->subop==QUAD) 578 dblflg |= 2; /* double src */ 579 splitrand(p); 580 if (p->op!=PUSH && 581 #ifndef EMOD 582 p->op!=EDIV && 583 #endif EMOD 584 p->op!=EMUL && 585 p->subop && tempreg(lastrand,r) && uses[r]==p->forw) { 586 if (equtype(p->subop,regs[r][0]) || 587 ((p->op==CVT || p->op==MOVZ || p->op==CVFL) && 588 (regs[r][0]&0xf) && compat((p->subop>>4)&0xf,regs[r][0])) || 589 p->op==MOVA && compat(LONG, regs[r][0])) { 590 register int r2; 591 592 if (regs[r][1]!=0) { /* send directly to destination */ 593 if (p->op==INC || p->op==DEC) { 594 p->op = (p->op==DEC) ? SUB : ADD; 595 /* use 2 now, convert to 3 later */ 596 p->subop=(OP2<<4)+(p->subop&0xF); 597 p->pop=0; 598 cp1=lastrand; cp2=regs[RT2]; 599 while (*cp2++= *cp1++) /* copy reg */ 600 ; 601 cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0; 602 } 603 cp1=regs[r]+1; cp2=lastrand; 604 if (has2ops(p)) { 605 /* use 3 operand form of instruction */ 606 p->pop=0; 607 p->subop += (OP3-OP2)<<4; 608 lastrand = cp2 = regs[RT3]; 609 } 610 while (*cp2++= *cp1++) 611 ; 612 if (p->op==MOVA && p->forw->op==PUSH) { 613 p->op=PUSHA; 614 *regs[RT2]=0; p->pop=0; 615 } else if ((p->op==MOV || p->op==CVT) && 616 p->forw->op==PUSH) { 617 p->op=PUSH; p->subop &= 0xF; 618 *regs[RT2]=0; p->pop=0; 619 } 620 delnode(p->forw); 621 if (tempreg(lastrand,r2)) 622 uses[r2]=uses[r], uses[r]=0; 623 redun3(p); 624 newcode(p); redunm++; flow=r; 625 } else if (p->op==MOV) { /* superfluous fetch */ 626 int nmatch; 627 char src[C2_ASIZE]; 628 movit: 629 for (cp2=src, cp1=regs[RT1]; *cp2++= *cp1++;) 630 ; 631 splitrand(p->forw); 632 if (p->forw->op != INC && p->forw->op != DEC) 633 lastrand=byondrd(p->forw); 634 nmatch=0; 635 for (preg=regs+RT1;*preg!=lastrand;preg++) 636 if (r==isreg(*preg)) { 637 cp2= *preg; cp1=src; 638 while (*cp2++= *cp1++) 639 ; 640 ++nmatch; 641 } 642 if (nmatch==1) { 643 if (has2ops(p->forw) && equstr(src,regs[RT2])) { 644 p->forw->pop=0; 645 p->forw->subop += (OP3-OP2)<<4; 646 cp1=regs[RT3]; 647 *cp1++ = 'r'; *cp1++ = r+'0'; *cp1=0; 648 } 649 delnode(p); 650 p=p->forw; 651 if (tempreg(src,r2)) 652 uses[r2]=uses[r], uses[r]=0; 653 redun3(p); 654 newcode(p); redunm++; 655 return(p); /* avoid stale uses[] data */ 656 } else 657 splitrand(p); 658 } 659 } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) && 660 p->forw->subop&0xf && /* if base or index, then forget it */ 661 compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1])) 662 goto movit; 663 } 664 /* adjust 'lastrand' past any 'read' or 'modify' operands. */ 665 lastrand=byondrd(p); 666 /* a 'write' clobbers the register. */ 667 if (tempreg(lastrand,r) || 668 (has2ops(p) && tempreg(regs[RT2],r) && uses[r]==0)) { 669 /* 670 * Writing a dead register is useless, 671 * but watch side effects 672 */ 673 switch (p->op) { 674 #ifndef EMOD 675 case EDIV: 676 #endif EMOD 677 case AOBLEQ: case AOBLSS: 678 break; 679 default: 680 /* 681 * If no direct uses, check for 682 * use of condition codes 683 */ 684 if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) { 685 register struct node *q = p; 686 687 while ((q = nonlab(q->forw))->op==JBR && 688 q->subop==0) 689 q=q->ref; /* cc unused, unchanged */ 690 if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) { 691 /* ... and destroyed */ 692 preg=regs+RT1; 693 while (cp1 = *preg++) { 694 if (cp1==lastrand && 695 p->op != CLR && 696 p->op != CVFL) { 697 redunm++; 698 delnode(p); 699 return(p->forw); 700 } 701 if (equstr(cp1,lastrand)) 702 break; 703 } 704 } 705 } 706 flow=r; 707 } 708 } 709 if ((r=flow) >= 0) { 710 olduse=uses[r], uses[r]=0; 711 *(short *)(regs[r])=0; 712 /* if r0 destroyed, dont keep r1 */ 713 if (dblflg&1) { 714 olduse1=uses[++r], uses[r]=0; 715 *(short *)(regs[r])=0; 716 } 717 } 718 /* now look for 'read' or 'modify' (read & write) uses */ 719 preg=regs+RT1; 720 while (*(cp1= *preg++)) { 721 /* check for r */ 722 if (lastrand!=cp1 && tempreg(cp1,r)) { 723 int isunused; 724 if (isunused=(uses[r]==0)) { 725 uses[r]=p; 726 cp2=regs[r]; *cp2++=p->subop; 727 if ((p->op==SHAL || p->op==SHAR || 728 p->op==SHL || p->op==SHR) && 729 cp1==regs[RT1]) 730 cp2[-1] = BYTE; 731 if (p->op==CBR && (p->subop==JBC || p->subop==JBS)) 732 cp2[-1] = LONG; 733 if (p->op==MOVA && cp1==regs[RT2]) 734 cp2[-1]=LONG; 735 } 736 /* ediv/emod's 2nd operand is quad */ 737 if (((p->op==EDIV 738 #ifdef EMOD 739 || p->op==EMOD 740 #endif EMOD 741 ) && cp1==regs[RT2] || (dblflg&2)) && 742 ++r<NUSE && uses[r]==0) { 743 if (isunused) 744 *cp2=0; 745 uses[r]=p; 746 cp2=regs[r]; *cp2++=p->subop; 747 if (!isunused) 748 *cp2=0; 749 } 750 if (!isunused) 751 continue; 752 if (p->op==MOV || p->op==PUSH || p->op==CVT || 753 p->op==MOVZ || p->op==COM || p->op==NEG || 754 p->op==STF) { 755 if (p->op!=PUSH) { 756 cp1=regs[RT2]; 757 if (tempreg(cp1,r)) { 758 /* 759 * reincarnation!! 760 * (as in addl2 r0,r1; 761 * movl r1,r0; ret) 762 */ 763 if (uses[r]==0) 764 uses[r]=olduse; 765 if ((dblflg&1) && uses[r+1]==0) 766 uses[r+1]=olduse1; 767 } 768 if (p->op!=MOV) 769 cp1=0; 770 } else 771 cp1="-(sp)"; 772 if (cp1) 773 while (*cp2++= *cp1++) 774 ; 775 else 776 *cp2=0; 777 } else 778 *cp2=0; 779 continue; 780 } 781 /* check for (r),[r] */ 782 do { 783 if (*cp1=='(' || *cp1=='[') { /* get register number */ 784 char t; 785 for (cp2= ++cp1; *++cp1!=')' && *cp1!=']';) 786 ; 787 t= *cp1; *cp1=0; 788 if (tempreg(cp2,r) && 789 (uses[r]==0 || uses[r]==p)) { 790 uses[r]=p; 791 regs[r][0] = 792 (*--cp2=='[' ? OPX<<4 : OPB<<4); 793 } 794 *cp1=t; 795 } 796 } while (*++cp1); 797 } 798 #ifdef MOVAFASTER 799 /* pushax or movax possibility? */ 800 cp1=regs[RT1]; 801 if (*cp1++=='$' && isstatic(cp1)) { 802 if (p->op==MOV && p->subop==LONG) { 803 if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) { 804 cp1=p->code; while (*cp1++!=','); p->code= --cp1; 805 } 806 p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0; 807 } else if (p->op==PUSH && p->subop==LONG) { 808 p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0; 809 } else if (p->op==ADD && p->subop==U(LONG,OP3) 810 && 0<=(r=isreg(regs[RT2]))) { 811 cp1=cp2=p->code; ++cp1; 812 do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='['; 813 do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']'; 814 if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;} 815 else {p->op = PUSHA; p->subop = BYTE; *cp2=0;} 816 if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;} 817 p->pop=0; 818 } 819 } 820 #endif MOVAFASTER 821 return (p); 822 } 823 824 /* try to eliminate STF's */ 825 struct node * 826 flops(q) 827 register struct node *q; 828 { 829 register struct node *p; 830 register int r; 831 832 if(q->op!=STF || !tempreg(q->code,r)) 833 return(q); 834 if(uses[r]) { 835 /* see if anyone destroys acc between us */ 836 for(p=q->forw; p!=uses[r]; p=p->forw) 837 switch(p->op) { 838 case LABEL: 839 case LDF: case LNF: case CVLF: case LDFD: 840 case CVDF: case NEGF: case ADDF: case SUBF: 841 case MULF: case DIVF: case SINF: case COSF: 842 case ATANF: case LOGF: case SQRTF: case EXPF: 843 return(q); 844 } 845 846 if(q->subop == p->subop) 847 switch(p->op) { /* do it in the accumulator */ 848 case LDF: /* redundant load */ 849 delnode(p); nld++; 850 p = p->forw; 851 break; 852 case LNF: /* stf r; lnf r ==> negf */ 853 p->op = NEGF; 854 p->pop = 0; 855 p->code = 0; 856 break; 857 case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */ 858 { register char *s; 859 register struct node *p1=p->forw; 860 for(s=p->code; *s!=','; s++); 861 *s = 0; 862 if(isreg(p->code) == r) 863 p->code = s+1; 864 else { 865 if(p1->op != CBR || isreg(s+1) != r) { 866 *s = ','; 867 return(q); 868 } 869 if(p1->subop > JNE) { 870 p1->subop ^= 1; 871 p1->pop = 0; 872 nrevbr++; 873 } 874 } 875 p->op = CMPF; 876 p->pop = 0; 877 } 878 break; 879 default: 880 return(q); 881 } 882 else if(p->subop==LONG) { 883 switch(p->op) { 884 case TST: /* stf r; tstl r ==> tstf */ 885 p->op = TSTF; 886 p->code = 0; 887 break; 888 /* send directly to destination */ 889 case MOV: /* stf r; movl r,x ==> stf x */ 890 case PUSH: /* stf r; pushl r ==> stf -(sp)/pushd */ 891 if(q->subop == DOUBLE) { 892 register struct node *b = p->back; 893 /* assume b's 2nd arg is ok */ 894 if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG)) 895 return(q); 896 delnode(b); redunm++; 897 } 898 if(p->op==PUSH) { 899 if(q->subop == DOUBLE) { 900 p->op = PUSHD; 901 p->code = 0; 902 } else { 903 p->op = q->op; 904 p->code = copy("-(sp)"); 905 } 906 } else { 907 p->op = q->op; 908 while(*p->code++ != ','); 909 } 910 break; 911 default: 912 return(q); 913 } 914 p->pop = 0; 915 p->subop = q->subop; 916 } else 917 return(q); 918 uses[r] = 0; 919 if(q->subop == DOUBLE) 920 uses[r+1] = 0; 921 { /* undo any effect on uses in the area between p and q, 922 * as we are going over it again */ 923 register struct node *b; 924 for(b=p; b!=q; b=b->back) { 925 for(r=0; r<NUSE; r++) { 926 if(uses[r] == b) 927 uses[r] = 0; 928 if(useacc == b) 929 useacc = 0; 930 } 931 } 932 } 933 return(p->forw); /* make p the next for bflow */ 934 } 935 /* it's a store to reg which isnt used elsewhere */ 936 if((p=q->forw)->op == CBR) { 937 q->op = TSTF; 938 q->pop = 0; 939 q->code = 0; 940 } else { 941 delnode(q); nst++; 942 if(p->op ==STF || p->op==TSTF || p->op==PUSHD) { 943 if(useacc == p) 944 useacc = 0; 945 return(p->forw); /* so ldmov can be used on p */ 946 } 947 } 948 return(p); 949 } 950 951 /* try to change load/store sequences to movl */ 952 ldmov(q) 953 register struct node *q; 954 { 955 register struct node *p; 956 register char *s, *pcod, *cp; 957 char *dlsw(); 958 959 p = q->back; 960 if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD) 961 && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE)))) 962 return(0); 963 pcod = p->code; 964 cp = p->code; 965 /* prepare args for movl/pushl */ 966 if(q->op!=TSTF && q->subop==DOUBLE) { 967 if(p->op == LDF) { 968 if((s = dlsw(p->code)) == NULL) 969 return(0); 970 971 strcpy(line, s); 972 if(q->op == STF) { 973 strcat(line, ","); 974 if((s = dlsw(q->code)) == NULL) 975 return(0); 976 strcat(line, s); 977 p->op = MOV; 978 } else 979 p->op = PUSH; 980 } else { /* LDFD */ 981 if(q->op == STF) { 982 if((s = dlsw(q->code)) == NULL) 983 return(0); 984 } else 985 s = "-(sp)"; 986 strcpy(line, s); 987 p->op = CLR; 988 } 989 p->pop = 0; 990 p->subop = LONG; 991 p->code = copy(line); 992 } else 993 { 994 if ((p->op == LDF) && (p->subop == DOUBLE) && 995 (indexa(cp))) return(0); 996 delnode(p); 997 } 998 strcpy(line, pcod); 999 if(q->op == STF) { /* ldf x; stf y ==> movl x,y */ 1000 strcat(line, ","); 1001 strcat(line, q->code); 1002 q->op = MOV; 1003 nst++; 1004 } else if(q->op == TSTF) /* ldf x; tstf ==> tstl x */ 1005 q->op = TST; 1006 else /* ldd x; pushd ==> pushl x+4; pushl x */ 1007 q->op = PUSH; 1008 q->pop = 0; 1009 q->subop = LONG; 1010 q->code = copy(line); 1011 nld++; 1012 return(1); 1013 } 1014 1015 /* reconstruct the address of l.s.w. of a double operand */ 1016 char * 1017 dlsw(d) 1018 register char *d; 1019 { 1020 register char *s, *t, *c; 1021 register int r; 1022 static char lsw[C2_ASIZE]; 1023 1024 if(d[0] == '*' || d[0] == '$') 1025 return(NULL); 1026 if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2])) 1027 return(NULL); 1028 t = lsw; 1029 if((r=isreg(d)) >= 0) 1030 sprintf(t, "r%d", r+1); 1031 else { 1032 for(s=d; *s && *s!='('; *t++ = *s++) 1033 if(*s == '[') 1034 return(NULL); 1035 if(s!=d) 1036 *t++ = '+'; 1037 *t++ = '4'; 1038 while(*t++ = *s) 1039 if(*s++ == '[' ) 1040 { 1041 return(NULL); 1042 } 1043 } 1044 return(lsw); 1045 } 1046 checkexpr(p) 1047 register char *p; 1048 { 1049 1050 while(*p && *p != ','){ 1051 if ((*p == '+' ) || (*p == '-')) 1052 return(1); 1053 *p++; 1054 } 1055 return(0); 1056 } 1057