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