1: #ifndef lint
   2: static  char sccsid[] = "@(#)c21.c 4.19 4/27/86";
   3: #endif
   4: /* char C21[] = {"@(#)c21.c 1.83 80/10/16 21:18:22 JFR"}; /* sccs ident */
   5: 
   6: /*
   7:  * C object code improver-- second part
   8:  */
   9: 
  10: #include "c2.h"
  11: #include <stdio.h>
  12: #include <ctype.h>
  13: 
  14: #define NUSE 6
  15: int ioflag;
  16: int biti[NUSE] = {1,2,4,8,16,32};
  17: int bitsize[] = {   /* index by type codes */
  18:     0,      /* 0	not allocated */
  19:     8,      /* 1	BYTE */
  20:     16,     /* 2	WORD */
  21:     32,     /* 3	LONG */
  22:     32,     /* 4	FFLOAT /
  23: 	64,		/* 5	DFLOAT */
  24:     64,     /* 6	QUAD */
  25:     0,      /* 7	OP2 */
  26:     0,      /* 8	OP3 */
  27:     0,      /* 9	OPB */
  28:     0,      /* 10	OPX */
  29:     64,     /* 11	GFLOAT */
  30:     128,        /* 12	HFLOAT */
  31:     128     /* 13	OCTA */
  32: };
  33: int pos,siz; long f; /* for bit field communication */
  34: struct node *uses[NUSE]; /* for backwards flow analysis */
  35: char *lastrand; /* last operand of instruction */
  36: struct node *bflow();
  37: struct node *bicopt();
  38: char *findcon();
  39: char *strcpy();
  40: 
  41: redun3(p,split) register struct node *p; int split; {
  42: /* check for 3 addr instr which should be 2 addr */
  43:     if (OP3==((p->subop>>4)&0xF)) {
  44:         if (split) splitrand(p);
  45:         if (equstr(regs[RT1],regs[RT3])
  46:           && (p->op==ADD || p->op==MUL || p->op==BIS || p->op==XOR)) {
  47:             register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t;
  48:         }
  49:         if (equstr(regs[RT2],regs[RT3])) {
  50:             p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0;
  51:             lastrand=regs[RT2]; *regs[RT3]=0; return(1);
  52:         }
  53:     } return(0);
  54: }
  55: 
  56: bmove() {
  57:     register struct node *p, *lastp; register char *cp1,*cp2; register int r;
  58:     refcount();
  59:     for (p=lastp= &first; 0!=(p=p->forw); lastp=p);
  60:     clearreg(); clearuse();
  61:     for (p=lastp; p!= &first; p=p->back) {
  62:     if (debug) {
  63:         printf("Uses:\n");
  64:         for (r=NUSE;--r>=0;) if (uses[r])
  65:             printf("%d: %s\n",r,uses[r]->code? uses[r]->code:"");
  66:         printf("-\n");
  67:     }
  68:     r=(p->subop>>4)&0xF;
  69:     if (OP2==r && (cp1=p->code, *cp1++)=='$' && *cp1++=='0' && *cp1++==',' &&
  70:             !source(cp1)) {/* a no-op unless MUL or DIV */
  71:         if (p->op==MUL) {p->op=MOV; p->subop&=0xF; p->pop=0;}
  72:         else if (p->op==DIV) fprintf(stderr,"c2: zero divide\n");
  73:         else {delnode(p); redunm++; continue;}
  74:     }
  75:     if (OP3==r && 0!=redun3(p,1)) {newcode(p); redunm++;}
  76:     switch (p->op) {
  77:     case LABEL: case DLABEL:
  78:         for (r=NUSE; --r>=0;)
  79:             if (uses[r]) p->ref=(struct node *) (((int)p->ref)|biti[r]);
  80:         break;
  81:     case CALLS:
  82:         clearuse(); goto std;
  83:     case 0:
  84:         /*
  85: 		 * Be conservative -- if we don't know what it is, then we
  86: 		 *	assume that it can set anything.
  87: 		 */
  88:         for ( r = 0; r < NUSE; ++r )
  89:             uses[r] = p;
  90:         break;
  91:     case SUB:
  92:         if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
  93:         if (*cp1++!='$') goto std; splitrand(p);
  94:         if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
  95:             char buf[C2_ASIZE]; cp2=buf; *cp2++='-';
  96:             cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
  97:             cp1="(fp),"; while (*cp2++= *cp1++); --cp2;
  98:             cp1=regs[RT3]; while (*cp2++= *cp1++);
  99:             p->code=copy(buf); p->combop=T(MOVA,LONG); p->pop=0;
 100:         } else if (*cp1++=='-' && 0<=(r=getnum(cp1))) {
 101:             p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1;
 102:         } goto std;
 103:     case ADD:
 104:         if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
 105:         if (*cp1++!='$') goto std; splitrand(p);
 106:         if (isstatic(cp1) && (r=isreg(regs[RT2]))>=0 && r<NUSE && uses[r]==p->forw)
 107:         {
 108:             /* address comp:
 109: 			**	addl2	$_foo,r0  \	movab	_foo[r0],bar
 110: 			**	movl	r0,bar	  /
 111: 			*/
 112:             register struct node    *pnext = p->forw;
 113:             char    buf[C2_ASIZE];
 114: 
 115:             if (pnext->op == MOV && pnext->subop == LONG)
 116:             {
 117:                 cp1 = &regs[RT1][1]; cp2 = &buf[0];
 118:                 while (*cp2++ = *cp1++) ; cp2--;
 119:                 splitrand(pnext);
 120:                 if (r == isreg(regs[RT1]))
 121:                 {
 122:                     delnode(p); p = pnext;
 123:                     p->op = MOVA; p->subop = BYTE;
 124:                     p->pop = 0;
 125:                     cp1 = regs[RT1]; *cp2++ = '[';
 126:                     while (*cp2++ = *cp1++) ; cp2--;
 127:                     *cp2++ = ']'; *cp2++ = ',';
 128:                     cp1 = regs[RT2];
 129:                     while (*cp2++ = *cp1++) ;
 130:                     p->code = copy(buf);
 131:                 }
 132:             }
 133:         }
 134:         else
 135:         if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
 136:             cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
 137:             cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=',';
 138:             p->combop=T(MOVA,LONG); p->pop=0;
 139:         } else if (*cp1++=='-' && 0<=(r=getnum(cp1))) {
 140:             p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1;
 141:         }
 142:         /* fall thru ... */
 143:     case CASE:
 144:     default: std:
 145:         p=bflow(p); break;
 146:     case MUL:
 147:     {
 148:         /*
 149: 		** Change multiplication by constant powers of 2 to
 150: 		**	shifts.
 151: 		*/
 152:         splitrand(p);
 153:         if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std;
 154:         if ((r = ispow2(getnum(&regs[RT1][1]))) < 0) goto std;
 155:         switch (r)
 156:         {
 157:         case 0:     /* mull3 $1,x,y */
 158:             if (p->subop == U(LONG,OP3))
 159:             {
 160:                 if (equstr(regs[RT2], regs[RT3]))
 161:                 {
 162:                     delnode(p); p = p->forw;
 163:                 }
 164:                 else
 165:                 {
 166:                     p->op = MOV; p->subop = LONG;
 167:                     p->pop = 0; newcode(p); nchange++;
 168:                 }
 169:             }
 170:             else
 171:             if (p->subop == U(LONG,OP2))
 172:             {
 173:                 delnode(p); p = p->forw;
 174:             }
 175:             goto std;
 176: 
 177:         case 1:     /* mull2 $2,x */
 178:             if (p->subop == U(LONG, OP2) && !source(regs[RT2]))
 179:             {
 180:                 strcpy(regs[RT1], regs[RT2]);
 181:                 p->op = ADD; p->pop = 0; newcode(p); nchange++;
 182:             }
 183:             goto std;
 184:         }
 185:         if(p->subop==U(LONG,OP3)||(p->subop==U(LONG,OP2)&&!source(regs[RT2])))
 186:         {
 187:             if (p->subop == U(LONG,OP2))
 188:                 strcpy(regs[RT3], regs[RT2]);
 189:             sprintf(regs[RT1], "$%d", r);
 190:             p->op = ASH; p->subop = LONG;
 191:             p->pop = 0; newcode(p); nchange++;
 192:         }
 193:         goto std;
 194:     }
 195:     case ASH:
 196:     {
 197:         /* address comp:
 198: 		**	ashl	$1,bar,r0  \	movl	bar,r0
 199: 		**	movab	_foo[r0]   /	movaw	_foo[r0]
 200: 		**
 201: 		**	ashl	$2,r0,r0   \	moval	_foo[r0]
 202: 		**	movab	_foo[r0]   /
 203: 		*/
 204:         register struct node    *pf;
 205:         register int    shfrom, shto;
 206:         long    shcnt;
 207:         char    *regfrom;
 208: 
 209:         splitrand(p);
 210:         if (regs[RT1][0] != '$') goto std;
 211:         if ((shcnt = getnum(&regs[RT1][1])) < 1 || shcnt > 3) goto std;
 212:         if ((shfrom = isreg(regs[RT2])) >= 0)
 213:             regfrom = copy(regs[RT2]);
 214:         if ((shto = isreg(regs[RT3])) >= 0 && shto<NUSE)
 215:         {
 216:             int regnum;
 217: 
 218:             if (uses[shto] != (pf = p->forw)) goto ashadd;
 219:             if (pf->op != MOVA && pf->op != PUSHA) goto ashadd;
 220:             if (pf->subop != BYTE) goto ashadd;
 221:             splitrand(pf);
 222:             if (!indexa(regs[RT1])) goto std;
 223:             cp2 = regs[RT1];
 224:             if(!isstatic(cp2)) goto std;
 225:             while (*cp2++ != '[') ;
 226:             if (*cp2++ != 'r' || !isdigit(*cp2)) goto std;
 227:             regnum = *cp2++ - '0';
 228:             if (isdigit(*cp2))
 229:             {
 230:                 if (cp2[1] != ']') goto std;
 231:                 regnum *= 10; regnum += *cp2 - '0';
 232:             }
 233:             if (regnum != shto) goto std;
 234:             if (shfrom >= 0)    /* ashl $N,r*,r0 */
 235:             {
 236:                 delnode(p);
 237:                 if (shfrom != shto)
 238:                 {
 239:                     uses[shto] = NULL; splitrand(pf);
 240:                     cp2=regs[RT1]; while (*cp2++!='[');
 241:                     cp1=regfrom; while (*cp2++= *cp1++);
 242:                     *--cp2 = ']';
 243:                     *++cp2 = '\0';
 244:                     newcode(pf);
 245:                 }
 246:             }
 247:             else
 248:             {
 249:                 p->op = MOV; splitrand(p);
 250:                 strcpy(regs[RT1], regs[RT2]);
 251:                 strcpy(regs[RT2], regs[RT3]);
 252:                 regs[RT3][0] = '\0';
 253:                 p->pop = 0; newcode(p);
 254:             }
 255:             switch (shcnt)
 256:             {
 257:             case 1: pf->subop = WORD; break;
 258:             case 2: pf->subop = LONG; break;
 259:             case 3: pf->subop = QUAD; break;
 260:             }
 261:             redunm++; nsaddr++; nchange++;
 262:             goto std;
 263:         }
 264: ashadd:
 265:         /* at this point, RT2 and RT3 are guaranteed to be simple regs*/
 266:         if (shcnt == 1 && equstr(regs[RT2], regs[RT3]))
 267:         {
 268:             /*
 269: 			** quickie:
 270: 			**	ashl	$1,A,A	>	addl2	A,A
 271: 			*/
 272:             p->op = ADD; p->subop = U(LONG,OP2); p->pop = 0;
 273:             strcpy(regs[RT1], regs[RT2]); regs[RT3][0] = '\0';
 274:             newcode(p); nchange++;
 275:         }
 276:         goto std;
 277:     }
 278: 
 279:     case EXTV:
 280:     case EXTZV:
 281:     {
 282:         /* bit tests:
 283: 		**	extv	A,$1,B,rC  \
 284: 		**	tstl	rC	    >	jbc	A,B,D
 285: 		**	jeql	D	   /
 286: 		**
 287: 		** also byte- and word-size fields:
 288: 		**	extv	$n*8,$8,A,B	>	cvtbl	n+A,B
 289: 		**	extv	$n*16,$16,A,B	>	cvtwl	2n+A,B
 290: 		**	extzv	$n*8,$8,A,B	>	movzbl	n+A,B
 291: 		**	extzv	$n*16,$16,A,B	>	movzwl	2n+A,B
 292: 		*/
 293:         register struct node    *pf;    /* forward node */
 294:         register struct node    *pn;    /* next node (after pf) */
 295:         int flen;           /* field length */
 296: 
 297:         splitrand(p);
 298:         if (regs[RT2][0] != '$') goto std;
 299:         if ((flen = getnum(&regs[RT2][1])) < 0) goto std;
 300:         if (flen == 1)
 301:         {
 302:             register int    extreg;     /* reg extracted to */
 303: 
 304:             extreg = isreg(regs[RT4]);
 305:             if (extreg < 0 || extreg >= NUSE) goto std;
 306:             if ((pf = p->forw)->op != TST) goto std;
 307:             if (uses[extreg] && uses[extreg] != pf) goto std;
 308:             splitrand(pf);
 309:             if (extreg != isreg(regs[RT1])) goto std;
 310:             if ((pn = pf->forw)->op != CBR) goto std;
 311:             if (pn->subop != JEQ && pn->subop != JNE) goto std;
 312:             delnode(p); delnode(pf);
 313:             pn->subop = (pn->subop == JEQ) ? JBC : JBS;
 314:             for(cp2=p->code; *cp2++!=',';);
 315:             for(cp1=cp2;     *cp1++!=',';);
 316:             while (*cp1!=',') *cp2++= *cp1++; *cp2='\0';
 317:             pn->code = p->code; pn->pop = NULL;
 318:             uses[extreg] = NULL;
 319:         }
 320:         else
 321:         if (flen == 8 || flen == 16)
 322:         {
 323:             register int    boff;   /* bit offset */
 324:             register int    coff;   /* chunk (byte or word) offset*/
 325: 
 326:             if (regs[RT1][0] != '$') goto std;
 327:             if ((boff = getnum(&regs[RT1][1])) < 0) goto std;
 328:             coff = boff / flen;
 329:             if (coff && (isreg(regs[RT3]) >= 0)) goto std;
 330:             if (boff < 0 || (boff % flen) != 0) goto std;
 331:             p->op = (p->op == EXTV) ? CVT : MOVZ;
 332:             p->subop = U((flen == 8 ? BYTE : WORD), LONG);
 333:             if (coff == 0)
 334:                 strcpy(regs[RT1], regs[RT3]);
 335:             else
 336:                 sprintf(regs[RT1], "%d%s%s",
 337:                     (flen == 8 ? coff : 2*coff),
 338:                     (regs[RT3][0] == '(' ? "" : "+"),
 339:                     regs[RT3]);
 340:             strcpy(regs[RT2], regs[RT4]);
 341:             regs[RT3][0] = '\0'; regs[RT4][0] = '\0';
 342:             p->pop = 0; newcode(p);
 343:         }
 344:         nchange++;
 345:         goto std;
 346:     }
 347: 
 348:     case CMP:
 349:     {
 350:         /* comparison to -63 to -1:
 351: 		**	cmpl	r0,$-1	>	incl	r0
 352: 		**	jeql	...
 353: 		**
 354: 		**	cmpl	r0,$-63	>	addl2	$63,r0
 355: 		**	jeql	...
 356: 		*/
 357:         register int    num;
 358:         register int    reg;
 359:         register struct node    *regp = p->back;
 360: 
 361:         if (p->forw->op != CBR) goto std;
 362:         if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std;
 363:         splitrand(p);
 364:         if (strncmp(regs[RT2], "$-", 2) != 0) goto std;
 365:         reg = r = isreg(regs[RT1]);
 366:         if (r < 0) goto std;
 367:         if (r < NUSE && uses[r] != 0) goto std;
 368:         if (r >= NUSE && regp->op == MOV && p->subop == regp->subop)
 369:         {
 370:             if (*regp->code != 'r') goto std;
 371:             reg = regp->code[1] - '0';
 372:             if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg])
 373:                 goto std;
 374:         }
 375:         if (r >= NUSE) goto std;
 376:         if (reg != r)
 377:             sprintf(regs[RT1], "r%d", reg);
 378:         if ((num = getnum(&regs[RT2][2])) <= 0 || num > 63) goto std;
 379:         if (num == 1)
 380:         {
 381:             p->op = INC; regs[RT2][0] = '\0';
 382:         }
 383:         else
 384:         {
 385:             register char   *t;
 386: 
 387:             t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t;
 388:             p->op = ADD; p->subop = U(p->subop, OP2);
 389:             for (t = &regs[RT1][2]; t[-1] = *t; t++) ;
 390:         }
 391:         p->pop = 0; newcode(p);
 392:         nchange++;
 393:         goto std;
 394:     }
 395: 
 396:     case JSB:
 397:         if (equstr(p->code,"mcount")) {uses[0]=p; regs[0][0]= -1;}
 398:         goto std;
 399:     case JBR: case JMP:
 400:         clearuse();
 401:         if (p->subop==RET || p->subop==RSB) {uses[0]=p; regs[0][0]= -1; break;}
 402:         if (p->ref==0) goto std;    /* jmp (r0) */
 403:         /* fall through */
 404:     case CBR:
 405:         if (p->ref->ref!=0) for (r=NUSE;--r>=0;)
 406:             if (biti[r] & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;}
 407:     case EROU: case JSW:
 408:     case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ;
 409:     }
 410:     }
 411:     for (p= &first; p!=0; p=p->forw)
 412:         if (p->op==LABEL || p->op==DLABEL) p->ref=0;    /* erase our tracks */
 413: }
 414: 
 415: rmove()
 416: {
 417:     register struct node *p;
 418:     register int r;
 419:     int r1;
 420: 
 421:     clearreg();
 422:     for (p=first.forw; p!=0; p = p->forw) {
 423:     if (debug) {
 424:         if (*conloc) {
 425:             r1=conval[0];
 426:             printf("Con %s = %d%d %s\n", conloc, r1&0xF, r1>>4, conval+1);
 427:         }
 428:         printf("Regs:\n");
 429:         for (r=0; r<NREG; r++)
 430:             if (regs[r][0]) {
 431:                 r1=regs[r][0];
 432:                 printf("%d: %d%d %s\n", r, r1&0xF, r1>>4, regs[r]+1);
 433:             }
 434:         printf("-\n");
 435:     }
 436:     switch (p->op) {
 437: 
 438:     case CVT:
 439:         splitrand(p); goto mov;
 440: 
 441:     case MOV:
 442:         splitrand(p);
 443:         if ((r = findrand(regs[RT1],p->subop)) >= 0) {
 444:             if (r == isreg(regs[RT2]) && p->forw->op!=CBR) {
 445:                 delnode(p); redunm++; break;
 446:             }
 447:         }
 448: mov:
 449:         repladdr(p);
 450:         r = isreg(regs[RT1]);
 451:         r1 = isreg(regs[RT2]);
 452:         dest(regs[RT2],p->subop);
 453:         if (r>=0) {
 454:             if (r1>=0) savereg(r1, regs[r]+1, p->subop);
 455:             else if (p->op!=CVT) savereg(r, regs[RT2], p->subop);
 456:         } else if (r1>=0) savereg(r1, regs[RT1], p->subop);
 457:         else if (p->op!=CVT) setcon(regs[RT1], regs[RT2], p->subop);
 458:         break;
 459: 
 460: /* .rx,.wx */
 461:     case MFPR:
 462:     case COM:
 463:     case NEG:
 464: /* .rx,.wx or .rx,.rx,.wx */
 465:     case ADD:
 466:     case SUB:
 467:     case BIC:
 468:     case BIS:
 469:     case XOR:
 470:     case MUL:
 471:     case DIV:
 472:     case ASH:
 473:     case MOVZ:
 474: /* .rx,.rx,.rx,.wx */
 475:     case EXTV:
 476:     case EXTZV:
 477:     case INSV:
 478:         splitrand(p);
 479:         repladdr(p);
 480:         dest(lastrand,p->subop);
 481:         if (p->op==INSV) ccloc[0]=0;
 482:         break;
 483: 
 484: /* .mx or .wx */
 485:     case CLR:
 486:     case INC:
 487:     case DEC:
 488:         splitrand(p);
 489:         dest(lastrand,p->subop);
 490:         if (p->op==CLR)
 491:             if ((r = isreg(regs[RT1])) >= 0)
 492:                 savereg(r, "$0", p->subop);
 493:             else
 494:                 setcon("$0", regs[RT1], p->subop);
 495:         break;
 496: 
 497: /* .rx */
 498:     case TST:
 499:     case PUSH:
 500:         splitrand(p);
 501:         lastrand=regs[RT1+1]; /* fool repladdr into doing 1 operand */
 502:         repladdr(p);
 503:         if (p->op==TST && equstr(lastrand=regs[RT1], ccloc+1)
 504:           && ((0xf&(ccloc[0]>>4))==p->subop || equtype(ccloc[0],p->subop))
 505:           &&!source(lastrand)) {
 506:             delnode(p); p = p->back; nrtst++; nchange++;
 507:         }
 508:         setcc(lastrand,p->subop);
 509:         break;
 510: 
 511: /* .rx,.rx,.rx */
 512:     case PROBER:
 513:     case PROBEW:
 514:     case CASE:
 515:     case MOVC3:
 516: /* .rx,.rx */
 517:     case MTPR:
 518:     case CALLS:
 519:     case CMP:
 520:     case BIT:
 521:         splitrand(p);
 522:         /* fool repladdr into doing right number of operands */
 523:         if (p->op==CASE || p->op==PROBER || p->op==PROBEW) lastrand=regs[RT4];
 524: /*		else if (p->op==CMPV || p->op==CMPZV) lastrand=regs[RT4+1]; */
 525:         else if (p->op==MOVC3) lastrand=regs[RT1];
 526:         else lastrand=regs[RT3];
 527:         repladdr(p);
 528:         if (p->op==CALLS || p->op==MOVC3) clearreg();
 529:         if (p->op==BIT) bitopt(p);
 530:         ccloc[0]=0; break;
 531: 
 532:     case CBR:
 533:         if (p->subop>=JBC) {
 534:             splitrand(p);
 535:             if (p->subop<JBCC) lastrand=regs[RT3]; /* 2 operands can be optimized */
 536:             else lastrand=regs[RT2]; /* .mb destinations lose */
 537:             repladdr(p);
 538:         }
 539:         ccloc[0] = 0;
 540:         break;
 541: 
 542:     case JBR:
 543:         redunbr(p);
 544: 
 545: /* .wx,.bb */
 546:     case SOB:
 547: 
 548:     default:
 549:         clearreg();
 550:     }
 551:     }
 552: }
 553: 
 554: char *
 555: byondrd(p) register struct node *p; {
 556: /* return pointer to register which is "beyond last read/modify operand" */
 557:     if (OP2==(p->subop>>4)) return(regs[RT3]);
 558:     switch (p->op) {
 559:         case MFPR:
 560:         case JSB:
 561:         case PUSHA:
 562:         case TST: case INC: case DEC: case PUSH:    return(regs[RT2]);
 563:         case MTPR:
 564:         case BIT: case CMP: case CALLS:             return(regs[RT3]);
 565:         case PROBER: case PROBEW:
 566:         case CASE: case MOVC3:                      return(regs[RT4]);
 567:     }
 568:     return(lastrand);
 569: }
 570: 
 571: struct node *
 572: bflow(p)
 573: register struct node *p;
 574: {
 575:     register char *cp1,*cp2,**preg; register int r;
 576:     int flow= -1;
 577:     struct node *olduse=0;
 578:     splitrand(p);
 579:     if (p->op!=PUSH && p->subop && 0<=(r=isreg(lastrand)) && r<NUSE && uses[r]==p->forw) {
 580:     if (equtype(p->subop,regs[r][0])
 581:     || ((p->op==CVT || p->op==MOVZ)
 582:              && 0xf&regs[r][0] && compat(0xf&(p->subop>>4),regs[r][0]))) {
 583:         register int r2;
 584:         if (regs[r][1]!=0) {/* send directly to destination */
 585:             if (p->op==INC || p->op==DEC) {
 586:                 if (p->op==DEC) p->op=SUB; else p->op=ADD;
 587:                 p->subop=(OP2<<4)+(p->subop&0xF); /* use 2 now, convert to 3 later */
 588:                 p->pop=0;
 589:                 cp1=lastrand; cp2=regs[RT2]; while (*cp2++= *cp1++); /* copy reg */
 590:                 cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0;
 591:             }
 592:             cp1=regs[r]+1; cp2=lastrand;
 593:             if (OP2==(p->subop>>4)) {/* use 3 operand form of instruction */
 594:                 p->pop=0;
 595:                 p->subop += (OP3-OP2)<<4; lastrand=cp2=regs[RT3];
 596:             }
 597:             while (*cp2++= *cp1++);
 598:             if (p->op==MOVA && p->forw->op==PUSH) {
 599:                 p->op=PUSHA; *regs[RT2]=0; p->pop=0;
 600:             } else if (p->op==MOV && p->forw->op==PUSH) {
 601:                 p->op=PUSH ; *regs[RT2]=0; p->pop=0;
 602:             }
 603:             delnode(p->forw);
 604:             if (0<=(r2=isreg(lastrand)) && r2<NUSE) {
 605:                 uses[r2]=uses[r]; uses[r]=0;
 606:             }
 607:             (void) redun3(p,0);
 608:             newcode(p); redunm++; flow=r;
 609:         } else if (p->op==MOV && p->forw->op!=EXTV && p->forw->op!=EXTZV) {
 610:             /* superfluous fetch */
 611:             int nmatch;
 612:             char src[C2_ASIZE];
 613:     movit:
 614:             cp2=src; cp1=regs[RT1]; while (*cp2++= *cp1++);
 615:             splitrand(p->forw);
 616:             if (p->forw->op != INC && p->forw->op != DEC)
 617:                 lastrand=byondrd(p->forw);
 618:             nmatch=0;
 619:             for (preg=regs+RT1;*preg!=lastrand;preg++)
 620:                 if (r==isreg(*preg)) {
 621:                 cp2= *preg; cp1=src; while (*cp2++= *cp1++); ++nmatch;
 622:             }
 623:             if (nmatch==1) {
 624:                 if (OP2==(p->forw->subop>>4) && equstr(src,regs[RT2])) {
 625:                     p->forw->pop=0;
 626:                     p->forw->subop += (OP3-OP2)<<4; cp1=regs[RT3];
 627:                     *cp1++='r'; *cp1++=r+'0'; *cp1=0;
 628:                 }
 629:                 delnode(p); p=p->forw;
 630:                 if (0<=(r2=isreg(src)) && r2<NUSE) {
 631:                     uses[r2]=uses[r]; uses[r]=0;
 632:                 }
 633:                 (void) redun3(p,0);
 634:                 newcode(p); redunm++; flow=r;
 635:             } else splitrand(p);
 636:         }
 637:     } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ)
 638:         && p->forw->subop&0xf   /* if base or index, then forget it */
 639:         && compat(p->subop,p->forw->subop) && !source(cp1=regs[RT1])
 640:         && !indexa(cp1)) goto movit;
 641:     }
 642:     /* adjust 'lastrand' past any 'read' or 'modify' operands. */
 643:     lastrand=byondrd(p);
 644:     /* a 'write' clobbers the register. */
 645:     if (0<=(r=isreg(lastrand)) && r<NUSE
 646:     || OP2==(p->subop>>4) && 0<=(r=isreg(regs[RT2])) && r<NUSE && uses[r]==0) {
 647:         /* writing a dead register is useless, but watch side effects */
 648:         switch (p->op) {
 649:         case ACB:
 650:         case AOBLEQ: case AOBLSS: case SOBGTR: case SOBGEQ: break;
 651:         default:
 652:             if (uses[r]==0) {/* no direct uses, check for use of condition codes */
 653:                 register struct node *q=p;
 654:                 while ((q=nonlab(q->forw))->combop==JBR) q=q->ref;  /* cc unused, unchanged */
 655:                 if (q->op!=CBR) {/* ... and destroyed */
 656:                     preg=regs+RT1;
 657:                     while (cp1= *preg++) {
 658:                         if (cp1==lastrand) {redunm++; delnode(p); return(p->forw);}
 659:                         if (source(cp1) || equstr(cp1,lastrand)) break;
 660:                     }
 661:                 }
 662:             }
 663:             flow=r;
 664:         }
 665:     }
 666:     if (0<=(r=flow)) {
 667:         olduse=uses[r];
 668:         uses[r]=0;
 669:         regs[r][0]=regs[r][1]=0;
 670:     }
 671:         /* these two are here, rather than in bmove(),
 672: 		/* because I decided that it was better to go for 3-address code
 673: 		/* (save time) rather than fancy jbxx (save 1 byte)
 674: 		/* on sequences like  bisl2 $64,r0; movl r0,foo
 675: 		*/
 676:     if (p->op==BIC) {p=bicopt(p); splitrand(p); lastrand=byondrd(p);}
 677:     if (p->op==BIS) {(void) bixprep(p,JBSS);    lastrand=byondrd(p);}
 678:     /* now look for 'read' or 'modify' (read & write) uses */
 679:     preg=regs+RT1;
 680:     while (*(cp1= *preg++)) {
 681:         /* check for  r  */
 682:         if (lastrand!=cp1 && 0<=(r=isreg(cp1)) && r<NUSE && uses[r]==0) {
 683:             uses[r]=p; cp2=regs[r]; *cp2++=p->subop;
 684:             if (p->op==ASH && preg==(regs+RT1+1)) cp2[-1]=BYTE; /* stupid DEC */
 685:             if (p->op==MOV || p->op==PUSH || p->op==CVT || p->op==MOVZ || p->op==COM || p->op==NEG) {
 686:                 if (p->op==PUSH) cp1="-(sp)";
 687:                 else {
 688:                     cp1=regs[RT2];
 689:                     if (0<=(r=isreg(cp1)) && r<NUSE && uses[r]==0)
 690:                         uses[r]=olduse; /* reincarnation!! */
 691:                     /* as in  addl2 r0,r1;  movl r1,r0;  ret  */
 692:                     if (p->op!=MOV) cp1=0;
 693:                 }
 694:                 if (cp1) while (*cp2++= *cp1++);
 695:                 else *cp2=0;
 696:             } else *cp2=0;
 697:             continue;
 698:         }
 699:         /* check for (r),(r)+,-(r),[r] */
 700:         do if (*cp1=='(' || *cp1=='[') {/* get register number */
 701:             char t;
 702:             cp2= ++cp1; while (*++cp1!=')' && *cp1!=']'); t= *cp1; *cp1=0;
 703:             if (0<=(r=isreg(cp2)) && r<NUSE && (uses[r]==0 || uses[r]==p)) {
 704:                 uses[r]=p; regs[r][0]=(*--cp2=='[' ? OPX<<4 : OPB<<4);
 705:             }
 706:             *cp1=t;
 707:         } while (*++cp1);
 708:     }
 709:     /* pushax or movax possibility? */
 710:     cp1=regs[RT1];
 711:     if (*cp1++=='$' && isstatic(cp1) && natural(regs[RT1])) {
 712:         if (p->combop==T(MOV,LONG)) {
 713:             if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) {
 714:                 cp1=p->code; while (*cp1++!=','); p->code= --cp1;
 715:             }
 716:             p->combop=T(MOVA,LONG); ++p->code; p->pop=0;
 717:         } else if (p->combop==T(PUSH,LONG)) {
 718:             p->combop=T(PUSHA,LONG); ++p->code; p->pop=0;
 719:         } else if ((p->combop&0xFFFF)==T(ADD,U(LONG,OP3))
 720:                  && 0<=(r=isreg(regs[RT2]))) {
 721:             cp1=cp2=p->code; ++cp1;
 722:             do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='[';
 723:             do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']';
 724:             if (!equstr(regs[RT3],"-(sp)")) p->combop=T(MOVA,BYTE);
 725:             else {p->combop=T(PUSHA,BYTE); *cp2=0;}
 726:             if (r < NUSE && uses[r] == 0) {
 727:                 uses[r]=p;
 728:                 regs[r][0]=OPX<<4;
 729:             }
 730:             p->pop=0;
 731:         }
 732:     }
 733:     return(p);
 734: }
 735: 
 736: ispow2(n) register long n; {/* -1 -> no; else -> log to base 2 */
 737:     register int log;
 738:     if (n==0 || n&(n-1)) return(-1); log=0;
 739:     for (;;) {n >>= 1; if (n==0) return(log); ++log; if (n== -1) return(log);}
 740: }
 741: 
 742: bitopt(p) register struct node *p; {
 743:     /* change "bitx $<power_of_2>,a" followed by JEQ or JNE
 744: 	/* into JBC or JBS.  watch out for I/O registers. (?)
 745: 	/* assumes that 'splitrand' has already been called.
 746: 	*/
 747:     register char *cp1,*cp2; int b;
 748:     cp1=regs[RT1]; cp2=regs[RT2];
 749:     if (*cp1++!='$' || !okio(cp2) || p->forw->op!=CBR || p->forw->subop&-2 ||
 750:         0>(b=ispow2(getnum(cp1)))) return;
 751:     if (p->subop!=BYTE && !(b==0 && p->subop==LONG) &&
 752:         (source(cp2) || indexa(cp2))) return;
 753:     if (b>=bitsize[p->subop]) {/* you dummy! */
 754:         if (source(cp2)) {/* side effect: auto increment or decrement */
 755:             p->pop=0;
 756:             p->op=TST; --cp1; while (*cp1++= *cp2++);
 757:             regs[RT2][0]=0; newcode(p);
 758:         } else delnode(p);
 759:         p = p->forw;
 760:         if (p->subop==JEQ) {p->combop=JBR; p->pop=0;}
 761:         else delnode(p);
 762:         nchange++; nbj++; return;
 763:     }
 764:     if (cp1=p->forw->code) {/* destination is not an internal label */
 765:         cp2=regs[RT3]; while (*cp2++= *cp1++);
 766:     }
 767:     if (b==0 && (p->subop==LONG || !(source(regs[RT2]) || indexa(regs[RT2])))) {
 768:         /* JLB optimization, ala BLISS */
 769:         cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++);
 770:         cp2=regs[RT2]; cp1=regs[RT3]; while (*cp2++= *cp1++);
 771:         *(regs[RT3])=0; p->forw->subop += JLBC-JBC;
 772:         p->forw->pop=0;
 773:     } else {
 774:         cp1=regs[RT1]+1;
 775:         if (b>9) *cp1++= b/10 +'0'; *cp1++= b%10 +'0'; *cp1=0; /* $<bit_number> */
 776:     }
 777:     nbj++; newcode(p); p->combop = p->forw->combop+((JBC-JEQ)<<8);
 778:     p->labno = p->forw->labno; delnode(p->forw);
 779:     p->pop=0;
 780: }
 781: 
 782: isfield(n) register long n; {/* -1 -> no; else -> position of low bit */
 783:     register int p; register long t;
 784:     t= ((n-1)|n) +1;
 785:     if (n!=0 && (0==t || 0<=ispow2(t))) {
 786:         p=0; while(!(n&1)) {n >>= 1; ++p;} return(p);
 787:     } else return(-1);
 788: }
 789: 
 790: bixprep(p,bix) register struct node *p; {
 791: /* initial setup, single-bit checking for bisopt, bicopt.
 792: /* return: 0->don't bother any more; 1->worthwhile trying
 793: */
 794:     register char *cp1,*cp2;
 795:     splitrand(p); cp1=regs[RT1]; cp2=regs[RT2];
 796:     if (*cp1++!='$' || 0>(pos=isfield(f=getnum(cp1)))
 797:       || !okio(cp2) || indexa(cp2) || source(cp2) || !okio(lastrand)) return(0);
 798:     f |= f-1; if (++f==0) siz=32-pos; else siz=ispow2(f)-pos;
 799:     if (siz==1 && pos>5 && (p->subop>>4)==OP2 && (p->subop&0xF)!=BYTE
 800:       && pos<bitsize[p->subop&0xF]) {
 801:         p->ref = insertl(p->forw); p->combop = CBR | (bix<<8);
 802:         p->pop=0;
 803:         p->labno = p->ref->labno;
 804:         if (pos>9) {*cp1++= pos/10 +'0'; pos %= 10;}
 805:         *cp1++=pos+'0'; *cp1=0; newcode(p); nbj++; return(0);
 806:     }
 807:     return(1);
 808: }
 809: 
 810: 
 811: struct node *
 812: bicopt(p) register struct node *p; {
 813: /* use field operations or MOVZ if possible.  done as part of 'bflow'.
 814: */
 815:     register char *cp1,*cp2; int r;
 816:     char src[C2_ASIZE];
 817:     char lhssiz, sop;
 818:     if (!bixprep(p,JBCC)) return(p);
 819:     if (f==0) {/* the BIC isolates low order bits */
 820:         siz=pos; pos=0;
 821:         if ((p->subop&0xF)==LONG && *(regs[RT2])!='$') {/* result of EXTZV is long */
 822:             /* save source of BICL in 'src' */
 823:             cp1=regs[RT2]; cp2=src; while (*cp2++= *cp1++);
 824:             if (p->back->op==ASH) {/* try for more */
 825:                 splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT3];
 826:                 if (*cp1++=='$' && *(regs[RT2])!='$' && !indexa(regs[RT2])
 827:                   && 0>(f=getnum(cp1)) && equstr(src,cp2)
 828:                   && 0<=(r=isreg(cp2)) && r<NUSE
 829:                   && siz-f <= 32) { /* a good ASH */
 830:                     pos -= f; cp1=regs[RT2]; cp2=src; while (*cp2++= *cp1++);
 831:                     delnode(p->back);
 832:                 }
 833:             }
 834:             /*
 835: 			 * 'pos', 'siz' known; find out the size of the
 836: 			 * left-hand operand of what the bicl will turn into.
 837: 			 */
 838:             if (pos==0 && siz==16)
 839:                 lhssiz = WORD;  /* movzwl */
 840:             else
 841:                 lhssiz = BYTE;  /* movzbl or extzvl */
 842:             if (p->back->op==CVT || p->back->op==MOVZ) {/* greedy, aren't we? */
 843:                 splitrand(p->back); cp1=regs[RT1]; cp2=regs[RT2];
 844:                 /*
 845: 				 * If indexa(cp1) || autoid(cp1), the fold may
 846: 				 * still be OK if the CVT/MOVZ has the same
 847: 				 * size operand on its left size as what we
 848: 				 * will turn the bicl into.
 849: 				 * However, if the CVT is from a float or
 850: 				 * double, forget it!
 851: 				 */
 852:                 sop = p->back->subop&0xF;   /* type of LHS of CVT/MOVZ */
 853:                 if (equstr(src,cp2) && okio(cp1)
 854:                   && sop != FFLOAT && sop != DFLOAT
 855:                   && sop != GFLOAT && sop != HFLOAT
 856:                   && ((!indexa(cp1) && !autoid(cp1)) || lhssiz == sop)
 857:                   && 0<=(r=isreg(cp2)) && r<NUSE
 858:                   && bitsize[sop]>=(pos+siz)
 859:                   && bitsize[p->back->subop>>4]>=(pos+siz)) {/* good CVT */
 860:                     cp1=regs[RT1]; cp2=src; while (*cp2++= *cp1++);
 861:                     delnode(p->back);
 862:                 }
 863:             }
 864:             /* 'pos', 'siz' known; source of field is in 'src' */
 865:             splitrand(p); /* retrieve destination of BICL */
 866:             if ((siz==8 || siz==16) && pos==0) {
 867:                 p->combop = T(MOVZ,U(lhssiz,LONG));
 868:                 sprintf(line,"%s,%s",src,lastrand);
 869:             } else {
 870:                 p->combop = T(EXTZV,LONG);
 871:                 sprintf(line,"$%d,$%d,%s,%s",pos,siz,src,lastrand);
 872:             }
 873:             p->pop=0;
 874:             p->code = copy(line); nfield++; return(p);
 875:         }/* end EXTZV possibility */
 876:     }/* end low order bits */
 877: /* unfortunately, INSV clears the condition codes, thus cannot be used */
 878: /*	else {/* see if BICL2 of positive field should be INSV $0 */
 879: /*		if (p->subop==(LONG | (OP2<<4)) && 6<=(pos+siz)) {
 880: /*			p->combop = INSV;
 881: /*			sprintf(line,"$0,$%d,$%d,%s",pos,siz,lastrand);
 882: /*			p->code = copy(line); nfield++; return(p);
 883: /*		}
 884: /*	}
 885: */
 886:     return(p);
 887: }
 888: 
 889: jumpsw()
 890: {
 891:     register struct node *p, *p1;
 892:     register struct node *tp;
 893:     long tl;
 894:     char *tcp;
 895:     int ti;
 896:     int nj;
 897: 
 898:     ti = 0;
 899:     nj = 0;
 900:     for (p=first.forw; p!=0; p = p->forw)
 901:         p->seq = ++ti;
 902:     for (p=first.forw; p!=0; p = p1) {
 903:         p1 = p->forw;
 904:         if (p->op == CBR && p1->op==JBR && p->ref && p1->ref
 905:          && abs(p->seq - p->ref->seq) > abs(p1->seq - p1->ref->seq)) {
 906:             if (p->ref==p1->ref)
 907:                 continue;
 908:             p->subop = revbr[p->subop];
 909:             p->pop=0;
 910:             tp = p1->ref;
 911:             p1->ref = p->ref;
 912:             p->ref = tp;
 913:             tl = p1->labno;
 914:             p1->labno = p->labno;
 915:             p->labno = tl;
 916: #ifdef COPYCODE
 917:             if (p->labno == 0) {
 918:                 tcp = p1->code;
 919:                 p1->code = p->code;
 920:                 p->code = tcp;
 921:             }
 922: #endif
 923:             nrevbr++;
 924:             nj++;
 925:         }
 926:     }
 927:     return(nj);
 928: }
 929: 
 930: addsob()
 931: {
 932:     register struct node *p, *p1, *p2, *p3;
 933: 
 934:     for (p = &first; (p1 = p->forw)!=0; p = p1) {
 935:     if (p->combop==T(DEC,LONG) && p1->op==CBR) {
 936:         if (abs(p->seq - p1->ref->seq) > 8) continue;
 937:         if (p1->subop==JGE || p1->subop==JGT) {
 938:             if (p1->subop==JGE) p->combop=SOBGEQ; else p->combop=SOBGTR;
 939:             p->pop=0;
 940:             p->labno = p1->labno; delnode(p1); nsob++;
 941:         }
 942:     } else if (p->combop==T(INC,LONG)) {
 943:         if (p1->op==LABEL && p1->refc==1 && p1->forw->combop==T(CMP,LONG)
 944:           && (p2=p1->forw->forw)->combop==T(CBR,JLE)
 945:           && (p3=p2->ref->back)->combop==JBR && p3->ref==p1
 946:           && p3->forw->op==LABEL && p3->forw==p2->ref) {
 947:             /* change	INC LAB: CMP	to	LAB: INC CMP */
 948:             p->back->forw=p1; p1->back=p->back;
 949:             p->forw=p1->forw; p1->forw->back=p;
 950:             p->back=p1; p1->forw=p;
 951:             p1=p->forw;
 952:             /* adjust beginning value by 1 */
 953:                 p2=alloc(sizeof first); p2->combop=T(DEC,LONG);
 954:                 p2->pop=0;
 955:                 p2->forw=p3; p2->back=p3->back; p3->back->forw=p2;
 956:                 p3->back=p2; p2->code=p->code; p2->labno=0;
 957:         }
 958:         if (p1->combop==T(CMP,LONG) && (p2=p1->forw)->op==CBR) {
 959:             register char *cp1,*cp2;
 960:             splitrand(p1); if (!equstr(p->code,regs[RT1])) continue;
 961:             if (abs(p->seq - p2->ref->seq)>8) {/* outside byte displ range */
 962:                 if (p2->subop!=JLE) continue;
 963:                 p->combop=T(ACB,LONG);
 964:                 cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */
 965:                 cp2=regs[RT2]; cp1="$1"; while (*cp2++= *cp1++); /* increment */
 966:                 cp2=regs[RT3]; cp1=p->code; while (*cp2++= *cp1++); /* index */
 967:                 p->pop=0; newcode(p);
 968:                 p->labno = p2->labno; delnode(p2); delnode(p1); nsob++;
 969:             } else if (p2->subop==JLE || p2->subop==JLT) {
 970:                 if (p2->subop==JLE) p->combop=AOBLEQ; else p->combop=AOBLSS;
 971:                 cp2=regs[RT1]; cp1=regs[RT2]; while (*cp2++= *cp1++); /* limit */
 972:                 cp2=regs[RT2]; cp1=p->code; while (*cp2++= *cp1++); /* index */
 973:                 p->pop=0; newcode(p);
 974:                 p->labno = p2->labno; delnode(p2); delnode(p1); nsob++;
 975:             }
 976:         }
 977:     }
 978:     }
 979: }
 980: 
 981: equop(p1, p2)
 982: register struct node *p1;
 983: struct node *p2;
 984: {
 985:     register char *cp1, *cp2;
 986: 
 987:     if (p1->combop != p2->combop)
 988:         return(0);
 989:     if (p1->op>0 && p1->op<MOV)
 990:         return(0);
 991:     switch (p1->combop) {
 992:     case EROU:  case JSW:   case TEXT:  case DATA:
 993:     case BSS:   case ALIGN: case WGEN:  case END:
 994:         /*
 995: 		 * Consider all pseudo-ops to be unique.
 996: 		 */
 997:         return(0);
 998:     }
 999:     if (p1->op==MOVA && p1->labno!=p2->labno) return(0);
1000:     cp1 = p1->code;
1001:     cp2 = p2->code;
1002:     if (cp1==0 && cp2==0)
1003:         return(1);
1004:     if (cp1==0 || cp2==0)
1005:         return(0);
1006:     while (*cp1 == *cp2++)
1007:         if (*cp1++ == 0)
1008:             return(1);
1009:     return(0);
1010: }
1011: 
1012: #ifndef delnode
1013: delnode(p) register struct node *p; {
1014:     p->back->forw = p->forw;
1015:     p->forw->back = p->back;
1016: }
1017: #endif
1018: 
1019: #ifndef decref
1020: decref(p)
1021: register struct node *p;
1022: {
1023:     if (p && --p->refc <= 0) {
1024:         nrlab++;
1025:         delnode(p);
1026:     }
1027: }
1028: #endif
1029: 
1030: struct node *
1031: nonlab(ap)
1032: struct node *ap;
1033: {
1034:     register struct node *p;
1035: 
1036:     p = ap;
1037:     while (p && p->op==LABEL)
1038:         p = p->forw;
1039:     return(p);
1040: }
1041: 
1042: clearuse() {
1043:     register struct node **i;
1044:     for (i=uses+NUSE; i>uses;) *--i=0;
1045: }
1046: 
1047: clearreg() {
1048:     register char **i;
1049:     for (i=regs; i<regs+NREG; ++i) {
1050:         **i = 0;
1051:         *(*i+1) = 0;
1052:     }
1053:     conloc[0] = 0;
1054:     ccloc[0] = 0;
1055: }
1056: 
1057: savereg(ai, s, type)
1058: register char *s;
1059: {
1060:     register char *p, *sp;
1061: 
1062:     sp = p = regs[ai];
1063:     if (source(s)) /* side effects in addressing */
1064:         return;
1065:     /* if any indexing, must be parameter or local */
1066:     /* indirection (as in "*-4(fp)") is ok, however */
1067:     *p++ = type;
1068:     while (*p++ = *s)
1069:         if (*s=='[' || *s++=='(' && *s!='a' && *s!='f') {*sp = 0; return;}
1070: }
1071: 
1072: dest(s,type)
1073: register char *s;
1074: {
1075:     register int i;
1076: 
1077:     (void) source(s); /* handle addressing side effects */
1078:     if (!natural(s)) {
1079:         /* wild store, everything except constants vanishes */
1080:         for (i=NREG; --i>=0;)
1081:             if (regs[i][1] != '$')
1082:                 regs[i][0] = regs[i][1] = 0;
1083:         conloc[0] = 0; ccloc[0] = 0;
1084:         return;
1085:     }
1086:     if ((i = isreg(s)) >= 0) {
1087:         /* if register destination, that reg is a goner */
1088:         regs[i][0] = regs[i][1] = 0;
1089:         switch(type & 0xF){
1090:         case DFLOAT:    /* clobber two at once */
1091:             /*FALLTHROUGH*/
1092:         case GFLOAT:
1093:             regs[i+1][0] = regs[i+1][1] = 0;
1094:             break;
1095:         case HFLOAT:    /* clobber four at once */
1096:             regs[i+1][0] = regs[i+1][1] = 0;
1097:             regs[i+2][0] = regs[i+2][1] = 0;
1098:             regs[i+3][0] = regs[i+3][1] = 0;
1099:             break;
1100:         }
1101:         switch((type>>4)&0xF){
1102:         case DFLOAT:    /* clobber two at once */
1103:             /*FALLTHROUGH*/
1104:         case GFLOAT:
1105:             regs[i+1][0] = regs[i+1][1] = 0;
1106:             break;
1107:         case HFLOAT:    /* clobber four at once */
1108:             regs[i+1][0] = regs[i+1][1] = 0;
1109:             regs[i+2][0] = regs[i+2][1] = 0;
1110:             regs[i+3][0] = regs[i+3][1] = 0;
1111:             break;
1112:         }
1113:     }
1114:     for (i=NREG; --i>=0;)
1115:         if (regs[i][1]=='*' && equstr(s, regs[i]+2))
1116:             regs[i][0] = regs[i][1] = 0; /* previous indirection through destination is invalid */
1117:     while ((i = findrand(s,0)) >= 0) /* previous values of destination are invalid */
1118:         regs[i][0] = regs[i][1] = 0;
1119:     if (*conloc && equstr(conloc, s))
1120:         conloc[0] = 0;
1121:     setcc(s, type); /* natural destinations set condition codes */
1122: }
1123: 
1124: /* separate operands at commas, set up 'regs' and 'lastrand' */
1125: splitrand(p) struct node *p; {
1126:     register char *p1, *p2;
1127:     register char **preg;
1128: 
1129:     preg = regs+RT1;
1130:     if (p1 = p->code)
1131:         while (*p1) {
1132:             lastrand = p2 = *preg++;
1133:             while (*p1)
1134:                 if (',' == (*p2++ = *p1++)) {
1135:                     --p2;
1136:                     break;
1137:                 }
1138:             *p2 = 0;
1139:         }
1140:     while (preg < (regs+RT1+5))
1141:         *(*preg++) = 0;
1142: }
1143: 
1144: compat(have, want) {
1145: register int hsrc, hdst;
1146: if (0==(want &= 0xF)) return(1); /* anything satisfies a wildcard want */
1147: hsrc=have&0xF;
1148: if (0==(hdst=((have>>4)&0xF)) || (hdst>=OP2 && hdst<=OPX)) hdst=hsrc;
1149: if (want>=FFLOAT) return(hdst==want && hsrc==want);
1150:     /* FLOAT, DFLOAT not compat: rounding */
1151: return(hsrc>=want && hdst>=want && hdst<FFLOAT);
1152: }
1153: 
1154: equtype(t1,t2) {return(compat(t1,t2) && compat(t2,t1));}
1155: 
1156: findrand(as, type)
1157: char *as;
1158: {
1159:     register char **i;
1160:     for (i = regs+NREG; --i>=regs;) {
1161:         if (**i && equstr(*i+1, as) && compat(**i,type))
1162:             return(i-regs);
1163:     }
1164:     return(-1);
1165: }
1166: 
1167: isreg(s)
1168: register char *s;
1169: {
1170:     if (*s++!='r' || !isdigit(*s++)) return(-1);
1171:     if (*s==0) return(*--s-'0');
1172:     if (*(s-1)=='1' && isdigit(*s++) && *s==0) return(10+*--s-'0');
1173:     return(-1);
1174: }
1175: 
1176: check()
1177: {
1178:     register struct node *p, *lp;
1179: 
1180:     lp = &first;
1181:     for (p=first.forw; p!=0; p = p->forw) {
1182:         if (p->back != lp) {
1183:             fprintf(stderr, "c2: failed internal consistency check -- help!\n");
1184:             exit(-1);
1185:         }
1186:         lp = p;
1187:     }
1188: }
1189: 
1190: source(ap)
1191: char *ap;
1192: {
1193:     register char *p1, *p2;
1194: 
1195:     p1 = ap;
1196:     p2 = p1;
1197:     if (*p1==0)
1198:         return(0);
1199:     while (*p2++ && *(p2-1)!='[');
1200:     if (*p1=='-' && *(p1+1)=='('
1201:      || *p1=='*' && *(p1+1)=='-' && *(p1+2)=='('
1202:      || *(p2-2)=='+') {
1203:         while (*p1 && *p1++!='r');
1204:         if (isdigit(*p1++))
1205:             if (isdigit(*p1))
1206:                 regs[10+*p1-'0'][0] = regs[10+*p1-'0'][1] = 0;
1207:             else {
1208:                 --p1;
1209:                 regs[*p1-'0'][0] = regs[*p1-'0'][1] = 0;
1210:             }
1211:         return(1);
1212:     }
1213:     return(0);
1214: }
1215: 
1216: newcode(p) struct node *p; {
1217:     register char *p1,*p2,**preg;
1218:     preg=regs+RT1; p2=line;
1219:     while (*(p1= *preg++)) {while (*p2++= *p1++); *(p2-1)=',';}
1220:     *--p2=0;
1221:     p->code=copy(line);
1222: }
1223: 
1224: repladdr(p)
1225: struct node *p;
1226: {
1227:     register r;
1228:     register char *p1;
1229:     char **preg; int nrepl;
1230: 
1231:     preg=regs+RT1; nrepl=0;
1232:     while (lastrand!=(p1= *preg++))
1233:         if (!source(p1) && 0<=(r=findrand(p1,p->subop))) {
1234:             *p1++='r'; if (r>9) {*p1++='1'; r -= 10;} *p1++=r+'0'; *p1=0;
1235:             nrepl++; nsaddr++;
1236:         }
1237:     if (nrepl) newcode(p);
1238: }
1239: 
1240: /* movedat()
1241: /* {
1242: /* 	register struct node *p1, *p2;
1243: /* 	struct node *p3;
1244: /* 	register seg;
1245: /* 	struct node data;
1246: /* 	struct node *datp;
1247: /*
1248: /* 	if (first.forw == 0)
1249: /* 		return;
1250: /* 	datp = &data;
1251: /* 	for (p1 = first.forw; p1!=0; p1 = p1->forw) {
1252: /* 		if (p1->op == DATA) {
1253: /* 			p2 = p1->forw;
1254: /* 			while (p2 && p2->op!=TEXT)
1255: /* 				p2 = p2->forw;
1256: /* 			if (p2==0)
1257: /* 				break;
1258: /* 			p3 = p1->back;
1259: /* 			p1->back->forw = p2->forw;
1260: /* 			p2->forw->back = p3;
1261: /* 			p2->forw = 0;
1262: /* 			datp->forw = p1;
1263: /* 			p1->back = datp;
1264: /* 			p1 = p3;
1265: /* 			datp = p2;
1266: /* 		}
1267: /* 	}
1268: /* 	if (data.forw) {
1269: /* 		datp->forw = first.forw;
1270: /* 		first.forw->back = datp;
1271: /* 		data.forw->back = &first;
1272: /* 		first.forw = data.forw;
1273: /* 	}
1274: /* 	seg = -1;
1275: /* 	for (p1 = first.forw; p1!=0; p1 = p1->forw) {
1276: /* 		if (p1->op==TEXT||p1->op==DATA||p1->op==BSS) {
1277: /* 			if (p1->op == seg || p1->forw&&p1->forw->op==seg) {
1278: /* 				p1->back->forw = p1->forw;
1279: /* 				p1->forw->back = p1->back;
1280: /* 				p1 = p1->back;
1281: /* 				continue;
1282: /* 			}
1283: /* 			seg = p1->op;
1284: /* 		}
1285: /* 	}
1286: /* }
1287: */
1288: 
1289: redunbr(p)
1290: register struct node *p;
1291: {
1292:     register struct node *p1;
1293:     register char *ap1;
1294:     char *ap2;
1295: 
1296:     if ((p1 = p->ref) == 0)
1297:         return;
1298:     p1 = nonlab(p1);
1299:     if (p1->op==TST) {
1300:         splitrand(p1);
1301:         savereg(RT2, "$0", p1->subop);
1302:     } else if (p1->op==CMP)
1303:         splitrand(p1);
1304:     else
1305:         return;
1306:     if (p1->forw->op==CBR) {
1307:         ap1 = findcon(RT1, p1->subop);
1308:         ap2 = findcon(RT2, p1->subop);
1309:         p1 = p1->forw;
1310:         if (compare(p1->subop, ap1, ap2)) {
1311:             nredunj++;
1312:             nchange++;
1313:             decref(p->ref);
1314:             p->ref = p1->ref;
1315:             p->labno = p1->labno;
1316: #ifdef COPYCODE
1317:             if (p->labno == 0)
1318:                 p->code = p1->code;
1319: #endif
1320:             if (p->ref)
1321:                 p->ref->refc++;
1322:         }
1323:     } else if (p1->op==TST && equstr(regs[RT1],ccloc+1) &&
1324:             equtype(ccloc[0],p1->subop)) {
1325:         p1=insertl(p1->forw); decref(p->ref); p->ref=p1;
1326:         nrtst++; nchange++;
1327:     }
1328: }
1329: 
1330: char *
1331: findcon(i, type)
1332: {
1333:     register char *p;
1334:     register r;
1335: 
1336:     p = regs[i];
1337:     if (*p=='$')
1338:         return(p);
1339:     if ((r = isreg(p)) >= 0 && compat(regs[r][0],type))
1340:         return(regs[r]+1);
1341:     if (equstr(p, conloc))
1342:         return(conval+1);
1343:     return(p);
1344: }
1345: 
1346: compare(opc, acp1, acp2)
1347: char *acp1, *acp2;
1348: {
1349:     register char *cp1, *cp2;
1350:     register n1;
1351:     int n2; int sign;
1352: 
1353:     cp1 = acp1;
1354:     cp2 = acp2;
1355:     if (*cp1++ != '$' || *cp2++ != '$')
1356:         return(0);
1357:     n1 = 0; sign=1; if (*cp2=='-') {++cp2; sign= -1;}
1358:     while (isdigit(*cp2)) {n1 *= 10; n1 += (*cp2++ - '0')*sign;}
1359:     n2 = n1;
1360:     n1 = 0; sign=1; if (*cp1=='-') {++cp1; sign= -1;}
1361:     while (isdigit(*cp1)) {n1 *= 10; n1 += (*cp1++ - '0')*sign;}
1362:     if (*cp1=='+')
1363:         cp1++;
1364:     if (*cp2=='+')
1365:         cp2++;
1366:     do {
1367:         if (*cp1++ != *cp2)
1368:             return(0);
1369:     } while (*cp2++);
1370:     switch(opc) {
1371: 
1372:     case JEQ:
1373:         return(n1 == n2);
1374:     case JNE:
1375:         return(n1 != n2);
1376:     case JLE:
1377:         return(n1 <= n2);
1378:     case JGE:
1379:         return(n1 >= n2);
1380:     case JLT:
1381:         return(n1 < n2);
1382:     case JGT:
1383:         return(n1 > n2);
1384:     case JLO:
1385:         return((unsigned) n1 < (unsigned) n2);
1386:     case JHI:
1387:         return((unsigned) n1 > (unsigned) n2);
1388:     case JLOS:
1389:         return((unsigned) n1 <= (unsigned) n2);
1390:     case JHIS:
1391:         return((unsigned) n1 >= (unsigned) n2);
1392:     }
1393:     return(0);
1394: }
1395: 
1396: setcon(cv, cl, type)
1397: register char *cv, *cl;
1398: {
1399:     register char *p;
1400: 
1401:     if (*cv != '$')
1402:         return;
1403:     if (!natural(cl))
1404:         return;
1405:     p = conloc;
1406:     while (*p++ = *cl++);
1407:     p = conval;
1408:     *p++ = type;
1409:     while (*p++ = *cv++);
1410: }
1411: 
1412: equstr(p1, p2)
1413: register char *p1, *p2;
1414: {
1415:     do {
1416:         if (*p1++ != *p2)
1417:             return(0);
1418:     } while (*p2++);
1419:     return(1);
1420: }
1421: 
1422: setcc(ap,type)
1423: char *ap;
1424: {
1425:     register char *p, *p1;
1426: 
1427:     p = ap;
1428:     if (!natural(p)) {
1429:         ccloc[0] = 0;
1430:         return;
1431:     }
1432:     p1 = ccloc;
1433:     *p1++ = type;
1434:     while (*p1++ = *p++);
1435: }
1436: 
1437: okio(p) register char *p; {/* 0->probable I/O space address; 1->not */
1438:     if (ioflag && (!natural(p) || 0>getnum(p))) return(0);
1439:     return(1);
1440: }
1441: 
1442: indexa(p) register char *p; {/* 1-> uses [r] addressing mode; 0->doesn't */
1443:     while (*p) if (*p++=='[') return(1);
1444:     return(0);
1445: }
1446: 
1447: natural(p)
1448: register char *p;
1449: {/* 1->simple local, parameter, global, or register; 0->otherwise */
1450:     if (*p=='*' || *p=='(' || *p=='-'&&p[1]=='(' || *p=='$'&&getnum(p+1))
1451:         return(0);
1452:     while (*p++);
1453:     p--;
1454:     if (*--p=='+' || *p==']' || *p==')' && p[-2]!='a' && p[-2]!='f')
1455:         return(0);
1456:     return(1);
1457: }
1458: 
1459: /*
1460: ** Tell if an argument is most likely static.
1461: */
1462: 
1463: isstatic(cp)
1464: register char   *cp;
1465: {
1466:     if (*cp == '_' || *cp == 'L' || (*cp++ == 'v' && *cp == '.'))
1467:         return (1);
1468:     return (0);
1469: }
1470: 
1471: autoid(p) register char *p; {/* 1-> uses autoincrement/autodecrement; 0->doesn't */
1472:     if (*p == '-' && *(p+1) == '(') return(1);
1473:     while (*p) p++;
1474:     if (*--p == '+' && *--p == ')') return(1);
1475:     return(0);
1476:   }

Defined functions

addsob defined in line 930; used 1 times
autoid defined in line 1471; used 1 times
bflow defined in line 571; used 2 times
bicopt defined in line 811; used 2 times
bitopt defined in line 742; used 1 times
bixprep defined in line 790; used 2 times
bmove defined in line 56; used 1 times
byondrd defined in line 554; used 4 times
check defined in line 1176; never used
clearreg defined in line 1047; used 5 times
clearuse defined in line 1042; used 3 times
compare defined in line 1346; used 1 times
compat defined in line 1144; used 6 times
decref defined in line 1020; never used
delnode defined in line 1013; never used
dest defined in line 1072; used 3 times
equop defined in line 981; used 2 times
equstr defined in line 1412; used 20 times
equtype defined in line 1154; used 3 times
findcon defined in line 1330; used 3 times
findrand defined in line 1156; used 3 times
indexa defined in line 1442; used 9 times
isfield defined in line 782; used 1 times
ispow2 defined in line 736; used 4 times
isreg defined in line 1167; used 26 times
isstatic defined in line 1463; used 3 times
jumpsw defined in line 889; used 1 times
natural defined in line 1447; used 5 times
newcode defined in line 1216; used 17 times
nonlab defined in line 1030; used 6 times
okio defined in line 1437; used 4 times
redun3 defined in line 41; used 3 times
redunbr defined in line 1289; used 1 times
repladdr defined in line 1224; used 5 times
rmove defined in line 415; used 1 times
savereg defined in line 1057; used 5 times
setcc defined in line 1422; used 2 times
setcon defined in line 1396; used 2 times
source defined in line 1190; used 13 times
splitrand defined in line 1125; used 30 times

Defined variables

biti defined in line 16; used 2 times
bitsize defined in line 17; used 4 times
f defined in line 33; used 9 times
ioflag defined in line 15; used 1 times
lastrand defined in line 35; used 33 times
pos defined in line 33; used 17 times
sccsid defined in line 2; never used
siz defined in line 33; used 11 times
uses defined in line 34; used 38 times

Defined macros

NUSE defined in line 14; used 25 times
Last modified: 1986-04-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3720
Valid CSS Valid XHTML 1.0 Strict