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