|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)c21.c 1.10 (Berkeley/CCI) 8/25/88";
3: #endif
4:
5: /*
6: * C object code improver-- second part
7: */
8:
9: #include "c2.h"
10: #include <stdio.h>
11: #include <ctype.h>
12:
13: int bitsize[] = {0,8,16,32,64,32,64}; /* index by type codes */
14:
15: redun3(p) register struct node *p; {
16: /* check for 3 addr instr which should be 2 addr */
17: if (has3ops(p)) {
18: if (equstr(regs[RT1],regs[RT3])
19: && (p->op==ADD || p->op==MUL || p->op==AND || p->op==OR || p->op==XOR)) {
20: register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t;
21: }
22: if (equstr(regs[RT2],regs[RT3])) {
23: p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0;
24: lastrand=regs[RT2]; *regs[RT3]=0; return(1);
25: }
26: } return(0);
27: }
28:
29: bmove() {
30: register struct node *p, *lastp; register char *cp1,*cp2; register int r;
31: struct node *flops();
32:
33: refcount();
34: for (p=lastp= &first; 0!=(p=p->forw); lastp=p);
35: clearreg(); clearuse();
36: for (p=lastp; p!= &first; p=p->back) {
37: if (debug) {
38: printf("Uses: ");
39: if (useacc)
40: printf("acc: %s\n",useacc->code? useacc->code:"");
41: for (r=NUSE;--r>=0;) if (uses[r])
42: printf("%d: %s\n",r,uses[r]->code? uses[r]->code:"");
43: printf("-\n");
44: }
45: r=(p->subop>>4)&0xF;
46: splitrand(p);
47: if (OP3==r && 0!=redun3(p)) {newcode(p); redunm++;}
48: /* ops that do nothing */
49: if(p->op==MOV && equstr(regs[RT1], regs[RT2]))
50: if(p->forw->op!=CBR) {
51: delnode(p); redunm++; continue;
52: } else {
53: p->op=TST; p->pop=0;
54: while(*p->code++ != ',');
55: redunm++;
56: }
57: else if((cp1=p->code, *cp1++)=='$' &&
58: (*cp1=='0' || *cp1=='1' || *cp1++=='-' && *cp1=='1') && cp1[1]==',') {
59: switch((p->code[1]<<8)|ord(p->op)) {
60: case (('0'<<8)|ord(ADD)):
61: case (('0'<<8)|ord(SUB)):
62: case (('-'<<8)|ord(AND)):
63: case (('0'<<8)|ord(OR)):
64: case (('0'<<8)|ord(XOR)):
65: case (('1'<<8)|ord(MUL)):
66: case (('1'<<8)|ord(DIV)):
67: case (('0'<<8)|ord(SHAL)):
68: case (('0'<<8)|ord(SHAR)):
69: case (('0'<<8)|ord(SHL)):
70: case (('0'<<8)|ord(SHR)):
71: if(r == OP2) {
72: if(p->forw->op!=CBR) {
73: delnode(p); redunm++; continue;
74: } else {
75: p->op=TST; p->subop&=0xF; p->pop=0;
76: while(*p->code++ != ',');
77: redunm++;
78: }
79: } else { /* OP3 or shift */
80: p->op=MOV; p->subop&=0xF; p->pop=0;
81: while(*p->code++ != ',');
82: p = p->forw; redunm++; continue;
83: }
84: break;
85: case (('0'<<8)|ord(MUL)):
86: case (('0'<<8)|ord(AND)):
87: p->op=CLR; p->subop&=0xF; p->pop=0;
88: while(*p->code++ != ',');
89: if(r == OP3)
90: while(*p->code++ != ',');
91: redunm++;
92: }
93: }
94: switch (p->op) {
95: case LABEL: case DLABEL:
96: for (r=NUSE; --r>=0;)
97: if (uses[r]) p->ref=(struct node *) (((int)p->ref)|(1<<r));
98: if (useacc) p->ref=(struct node *) (((int)p->ref)|(1<<NUSE));
99: break;
100: case CALLS:
101: case CALLF:
102: clearuse(); goto std;
103: case NIL:
104: clearuse(); break;
105: case CVT:
106: { long n;
107: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
108: if (*cp1++!='$') goto std; splitrand(p);
109: n = getnum(®s[RT1][1]);
110: if(r==BYTE && (n<-128 || n>127)) goto std;
111: if(r==WORD && (n<-32768 || n>32767)) goto std;
112: p->op = MOV; p->subop = r; p->pop = 0;
113: } goto std;
114:
115: case SUB:
116: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
117: if (*cp1++!='$') goto std; splitrand(p);
118: #ifdef MOVAFASTER
119: if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
120: char buf[C2_ASIZE]; cp2=buf; *cp2++='-';
121: cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
122: cp1="(fp),"; while (*cp2++= *cp1++); --cp2;
123: cp1=regs[RT3]; while (*cp2++= *cp1++);
124: p->code=copy(buf); p->op = MOVA; p->subop = BYTE; p->pop=0;
125: } else
126: #endif MOVAFASTER
127: if (*cp1++=='-' && 0==(r=getnum(cp1)) &&
128: !checkexpr(cp1)) {
129: p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1;
130: } goto std;
131: case ADD:
132: if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
133: if (*cp1++!='$') goto std; splitrand(p);
134: if (isstatic(cp1) && tempreg(regs[RT2],r) && uses[r]==p->forw)
135: {
136: /* address comp:
137: ** addl2 $_foo,r0 \ movab _foo[r0],bar
138: ** movl r0,bar /
139: */
140: register struct node *pnext = p->forw;
141: char buf[C2_ASIZE];
142:
143: if (pnext->op == MOV && pnext->subop == LONG)
144: {
145: cp1 = ®s[RT1][1]; cp2 = &buf[0];
146: while (*cp2++ = *cp1++) ; cp2--;
147: splitrand(pnext);
148: if (r == isreg(regs[RT1]))
149: {
150: delnode(p); p = pnext;
151: p->op = MOVA; p->subop = BYTE;
152: p->pop = 0;
153: cp1 = regs[RT1]; *cp2++ = '[';
154: while (*cp2++ = *cp1++) ; cp2--;
155: *cp2++ = ']'; *cp2++ = ',';
156: cp1 = regs[RT2];
157: while (*cp2++ = *cp1++) ;
158: p->code = copy(buf);
159: }
160: }
161: }
162: else
163: #ifdef MOVAFASTER
164: if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
165: cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
166: cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=',';
167: p->op = MOVA; p->subop = BYTE; p->pop=0;
168: } else
169: #endif MOVAFASTER
170: if (*cp1++=='-' && 0==(r=getnum(cp1)) &&
171: !checkexpr(cp1)) {
172: p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1;
173: }
174: /* fall thru ... */
175: case CASE:
176: default: std:
177: p=bflow(p); break;
178:
179: case MUL:
180: /*
181: ** Change multiplication
182: ** by constant powers of 2 to shifts.
183: */
184: splitrand(p);
185: if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std;
186: if ((r = ispow2(getnum(®s[RT1][1]))) <= 0) goto std;
187: /* mull2 $2,x */
188: if(r == 1 && p->subop == U(LONG, OP2)) {
189: strcpy(regs[RT1], regs[RT2]);
190: p->op = ADD; p->pop = 0; newcode(p);
191: goto std;
192: }
193: if (p->subop == U(LONG,OP2))
194: strcpy(regs[RT3], regs[RT2]);
195: sprintf(regs[RT1], "$%d", r);
196: p->op = SHL; p->subop = LONG;
197: p->pop = 0; newcode(p);
198: goto std;
199:
200: case SHAL:
201: case SHL:
202: {
203: /* bit tests:
204: ** shll A,$1,rC \
205: ** bitl B,rC > jbc A,B,D
206: ** jeql D /
207: **
208: ** address comp:
209: ** shll $1,bar,r0 \ movl bar,r0
210: ** movab _foo[r0] / movaw _foo[r0]
211: **
212: ** shll $2,r0,r0 \ moval _foo[r0]
213: ** movab _foo[r0] /
214: */
215: register struct node *pf;
216: register struct node *pn;
217: register int shfrom, shto;
218: long shcnt;
219: char *regfrom;
220:
221: splitrand(p);
222: if (regs[RT1][0] != '$') {
223: if(isreg(regs[RT1]) < 0) goto std; /* alignment */
224: if (regs[RT2][0] != '$') goto std;
225: if (getnum(®s[RT2][1]) != 1) goto std;
226: if (!tempreg(regs[RT3],r)) goto std;
227: if ((pf = p->forw)->op != BIT && pf->op!=AND) goto std;
228: if (uses[r] && uses[r] != pf) goto std;
229: splitrand(pf);
230: if (r == isreg(regs[RT1])) cp2 = regs[RT2];
231: else if (r == isreg(regs[RT2])) cp2 = regs[RT1];
232: else goto std;
233: if (*cp2 == '$') goto std;
234: if ((pn = pf->forw)->op != CBR) goto std;
235: if (pn->subop != JEQ && pn->subop != JNE) goto std;
236: delnode(p); delnode(pf);
237: pn->subop = (pn->subop == JEQ) ? JBC : JBS;
238: for(cp1=p->code; *cp1++!=',';);
239: while (*cp1++= *cp2++);
240: pn->code = p->code; pn->pop = NULL;
241: uses[r] = NULL;
242: nbj++;
243: p = pn;
244: goto std;
245: }
246: if ((shcnt = getnum(®s[RT1][1])) < 1 || shcnt > 2) goto std;
247: if ((shfrom = isreg(regs[RT2])) >= 0)
248: regfrom = copy(regs[RT2]);
249: if (tempreg(regs[RT3],shto))
250: {
251: int regnum;
252:
253: if (uses[shto] != (pf = p->forw)) goto ashadd;
254: if (pf->op != MOVA && pf->op != PUSHA) goto ashadd;
255: if (pf->subop != BYTE) goto ashadd;
256: splitrand(pf);
257: if (!indexa(regs[RT1])) goto std;
258: cp2 = regs[RT1];
259: if(!isstatic(cp2)) goto std;
260: while (*cp2++ != '[') ;
261: if (*cp2++ != 'r' || !isdigit(*cp2)) goto std;
262: regnum = *cp2++ - '0';
263: if (isdigit(*cp2))
264: {
265: if (cp2[1] != ']') goto std;
266: regnum *= 10; regnum += *cp2 - '0';
267: }
268: if (regnum != shto) goto std;
269: if (shfrom >= 0) /* shll $N,r*,r0 */
270: {
271: delnode(p);
272: p = pf;
273: if (shfrom != shto)
274: {
275: uses[shto] = NULL; splitrand(pf);
276: cp2=regs[RT1]; while (*cp2++!='[');
277: cp1=regfrom; while (*cp2++= *cp1++);
278: cp2[-1] = ']'; *cp2 = 0;
279: newcode(pf);
280: }
281: }
282: else
283: {
284: p->op = MOV; splitrand(p);
285: strcpy(regs[RT1], regs[RT2]);
286: strcpy(regs[RT2], regs[RT3]);
287: regs[RT3][0] = '\0';
288: p->pop = 0; newcode(p);
289: }
290: switch (shcnt)
291: {
292: case 1: pf->subop = WORD; break;
293: case 2: pf->subop = LONG; break;
294: }
295: pf->pop = 0;
296: redunm++; nsaddr++;
297: goto std;
298: }
299: ashadd:
300: /* at this point, RT2 and RT3 are guaranteed to be simple regs*/
301: if (shcnt == 1) {
302: /*
303: ** quickie:
304: ** shll $1,A,A > addl2 A,A
305: ** shll $1,A,B > addl3 A,A,B
306: */
307: if ((pf = p->forw)->op == CBR ||
308: (pf->op == MOV && (pf = pf->forw)->op == CBR))
309: /*
310: ** shll and addl handle the N bit differently
311: ** on overflow; avoid N bit CBRs
312: */
313: switch (pf->subop) {
314: case JLE: case JGE: case JLT: case JGT:
315: goto std;
316: }
317: p->op = ADD;
318: strcpy(regs[RT1], regs[RT2]);
319: if(equstr(regs[RT2], regs[RT3])) {
320: p->subop = U(LONG,OP2);
321: regs[RT3][0] = '\0';
322: } else
323: p->subop = U(LONG,OP3);
324: p->pop = 0;
325: newcode(p);
326: }
327: goto std;
328: }
329:
330: case SHAR:
331: case SHR:
332: {
333: /* bit tests:
334: ** shrl A,B,rC \
335: ** bitl $1,rC > jbc A,B,D
336: ** jeql D /
337: */
338: register struct node *pf; /* forward node */
339: register struct node *pn; /* next node (after pf) */
340: register int extreg; /* reg extracted to */
341:
342: splitrand(p);
343: if(isreg(regs[RT1]) < 0) goto std; /* alignment */
344: if (!tempreg(regs[RT3],extreg)) goto std;
345: if ((pf = p->forw)->op != BIT) goto std;
346: if (uses[extreg] && uses[extreg] != pf) goto std;
347: splitrand(pf);
348: if (regs[RT1][0] != '$') goto std;
349: if (getnum(®s[RT1][1]) != 1) goto std;
350: if (extreg != isreg(regs[RT2])) goto std;
351: if ((pn = pf->forw)->op != CBR) goto std;
352: if (pn->subop != JEQ && pn->subop != JNE) goto std;
353: delnode(p); delnode(pf);
354: pn->subop = (pn->subop == JEQ) ? JBC : JBS;
355: for(cp1=p->code; *cp1++!=',';);
356: while (*cp1!=',') cp1++; *cp1='\0';
357: pn->code = p->code; pn->pop = NULL;
358: uses[extreg] = NULL; nbj++;
359: p = pn;
360: goto std;
361: }
362:
363: case AND:
364: {
365: /* unsigned conversion:
366: ** cvtbl A,B; andl2 $255,B > movzbl A,B
367: **
368: ** also byte- and word-size fields:
369: ** shrl $(3-n)*8,A,B; andl2 $255,B > movzbl n+A,B
370: ** shrl $(1-n)*16,A,B; andl2 $65535,B > movzwl n+A,B
371: */
372: char src[C2_ASIZE];
373: register int f; /* field length */
374: register struct node *pb = p->back; /* backward node */
375:
376: if (p->subop != U(LONG,OP2))
377: goto std;
378: splitrand(p); cp1=regs[RT1];
379: if (*cp1++!='$' || (f=getnum(cp1))!=0xff && f!=0xffff)
380: goto std;
381: f = f==0xff ? 8 : 16;
382: if (pb->op!=CVT && pb->op!=MOVZ && pb->op!=SHAR && pb->op!=SHR)
383: goto std;
384: /* save source of ANDL in 'src' */
385: strcpy(src, regs[RT2]);
386: splitrand(pb);
387: if (!equstr(src,lastrand))
388: goto std;
389: if (pb->op==CVT || pb->op==MOVZ) {
390: if (!(bitsize[pb->subop&0xF]==f
391: && bitsize[pb->subop>>4]>=f)) /* good CVT */
392: goto std;
393: strcpy(src, regs[RT1]);
394: } else {
395: register int boff; /* bit offset */
396:
397: if (regs[RT1][0] != '$') goto std;
398: if ((boff = getnum(®s[RT1][1])) < 0) goto std;
399: if (isreg(regs[RT2])>=0 || !natural(regs[RT2])) goto std;
400: if ((boff & (f-1)) != 0) goto std;
401: boff = (32-boff-f) / 8;
402: if (boff == 0)
403: strcpy(src, regs[RT2]);
404: else
405: sprintf(src, "%d%s%s", boff, regs[RT2][0]=='(' ? "":"+",
406: regs[RT2]);
407: }
408: delnode(pb);
409: p->op = MOVZ;
410: p->subop = U((f==8 ? BYTE : WORD), LONG);
411: sprintf(line,"%s,%s",src,lastrand);
412: p->pop=0;
413: p->code = copy(line);
414: goto std;
415: }
416:
417: case CMP:
418: {
419: /* comparison to -63 to -1:
420: ** cmpl r0,$-1 > incl r0
421: ** jeql ...
422: **
423: ** cmpl r0,$-63 > addl2 $63,r0
424: ** jeql ...
425: */
426: register int num;
427: register int reg;
428: register struct node *regp = p->back;
429:
430: if (p->forw->op != CBR) goto std;
431: if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std;
432: splitrand(p);
433: if (strncmp(regs[RT2], "$-", 2) != 0) goto std;
434: reg = r = isreg(regs[RT1]);
435: if (r < 0) goto std;
436: if (r < NUSE && uses[r] != 0) goto std;
437: if (r >= NUSE && regp->op == MOV && p->subop == regp->subop)
438: {
439: if (*regp->code != 'r') goto std;
440: reg = regp->code[1] - '0';
441: if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg])
442: goto std;
443: }
444: if (r >= NUSE) goto std;
445: if (reg != r)
446: sprintf(regs[RT1], "r%d", reg);
447: if ((num = getnum(®s[RT2][2])) <= 0 || num > 63) goto std;
448: if (num == 1)
449: {
450: p->op = INC; regs[RT2][0] = '\0';
451: }
452: else
453: {
454: register char *t;
455:
456: t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t;
457: p->op = ADD; p->subop = U(p->subop, OP2);
458: for (t = ®s[RT1][2]; t[-1] = *t; t++) ;
459: }
460: p->pop = 0; newcode(p);
461: goto std;
462: }
463:
464: case JBR: case JMP:
465: clearuse();
466: if ((p->subop&0xF)==RET) {
467: switch((p->subop>>4)&0xF) {
468: case 2: uses[1]=p; regs[1][0]= -1;
469: case 1: uses[0]=p; regs[0][0]= -1;
470: }
471: break;
472: }
473: if (p->ref==0) goto std; /* jmp (r0) */
474: /* fall through */
475: case CBR:
476: if (p->ref->ref!=0) {
477: for (r=NUSE;--r>=0;)
478: if ((1<<r) & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;}
479: if ((1<<NUSE) & (int)p->ref->ref) useacc=p;
480: }
481: break;
482: case LNF:
483: /* lnf a; addf b ==> ldf b; subf a */
484: { register struct node *pf = p->forw;
485: if(pf->op==ADDF && p->subop==pf->subop) {
486: p->op = LDF;
487: p->pop = 0;
488: pf->op = SUBF;
489: pf->pop = 0;
490: cp1 = p->code;
491: p->code = pf->code;
492: pf->code = cp1;
493: p = pf->forw;
494: break;
495: }}
496: case LDF: case LDFD: case CVLF: /* destroy acc */
497: useacc = 0;
498: goto std;
499: case STF:
500: { register struct node *pf;
501: if((pf=flops(p)) != p) {
502: p = pf; /* usually p->forw; */
503: break;
504: }}
505: if(ldmov(p)) {
506: p = p->forw;
507: break;
508: }
509: if(useacc == 0)
510: useacc = p;
511: goto std;
512: case ADDF: case MULF: /* commutatives - create clients for flops */
513: /* stf a; ldf b; addf a => stf a; ldf a; addf b */
514: { register struct node *pb = p->back;
515: register struct node *pbb = pb->back;
516: if(pb->op==LDF && pb->subop==p->subop &&
517: pbb && pbb->op==STF && pbb->subop==p->subop &&
518: equstr(pbb->code, p->code)) {
519: cp1 = p->code;
520: p->code = pb->code;
521: pb->code = cp1;
522: }}
523: /* use acc and regs */
524: case CMPF: case CVFL: case SUBF: case DIVF:
525: if(useacc == 0)
526: useacc = p;
527: goto std;
528: case TSTF:
529: break;
530: case PUSHD:
531: if(ldmov(p)) {
532: p = p->forw;
533: break;
534: }
535: case CVDF: case NEGF: /* use only acc */
536: case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF:
537: if(useacc == 0)
538: useacc = p;
539: case EROU: case JSW:
540: case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ;
541: }
542: }
543: for (p= &first; p!=0; p=p->forw)
544: if (p->op==LABEL || p->op==DLABEL) p->ref=0; /* erase our tracks */
545: }
546:
547: char *
548: byondrd(p) register struct node *p; {
549: /* return pointer to register which is "beyond last read/modify operand" */
550: if (has2ops(p)) return(regs[RT3]);
551: switch (p->op) {
552: case MFPR:
553: case PUSHA:
554: case TST: case INC: case DEC: case PUSH:
555: case LDF: case LNF: case CVLF: case LDFD:
556: case ADDF: case SUBF: case MULF: case DIVF:
557: case CMPF:
558: return(regs[RT2]);
559: case MTPR:
560: #ifndef EMOD
561: case EDIV:
562: #endif EMOD
563: case CBR: /* must be JBC/JBS */
564: case BIT: case CMP: case CALLS: case CALLF:
565: case CMPF2:
566: return(regs[RT3]);
567: case EMUL:
568: case PROBE:
569: case MOVBLK:
570: case CASE:
571: return(regs[RT4]);
572: }
573: return(lastrand);
574: }
575:
576: struct node *
577: bflow(p)
578: register struct node *p;
579: {
580: register char *cp1,*cp2,**preg;
581: register int r, fr, dblflg=0;
582: int flow= -1;
583: struct node *olduse=0, *olduse1=0;
584:
585: if (p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4 ||
586: p->op==EMUL)
587: dblflg |= 1; /* double dest */
588: if ((p->subop&0xF)==DOUBLE || p->subop==QUAD)
589: dblflg |= 2; /* double src */
590: splitrand(p);
591: if (p->op!=PUSH &&
592: #ifndef EMOD
593: p->op!=EDIV &&
594: #endif EMOD
595: p->op!=EMUL &&
596: p->subop && tempreg(lastrand,r) && uses[r]==p->forw) {
597: if (equtype(p->subop,regs[r][0]) ||
598: ((p->op==CVT || p->op==MOVZ || p->op==CVFL) &&
599: (regs[r][0]&0xf) && compat((p->subop>>4)&0xf,regs[r][0])) ||
600: p->op==MOVA && compat(LONG, regs[r][0])) {
601: register int r2;
602:
603: if (regs[r][1]!=0) { /* send directly to destination */
604: if (p->op==INC || p->op==DEC) {
605: p->op = (p->op==DEC) ? SUB : ADD;
606: /* use 2 now, convert to 3 later */
607: p->subop=(OP2<<4)+(p->subop&0xF);
608: p->pop=0;
609: cp1=lastrand; cp2=regs[RT2];
610: while (*cp2++= *cp1++) /* copy reg */
611: ;
612: cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0;
613: }
614: cp1=regs[r]+1; cp2=lastrand;
615: if (has2ops(p)) {
616: /* use 3 operand form of instruction */
617: p->pop=0;
618: p->subop += (OP3-OP2)<<4;
619: lastrand = cp2 = regs[RT3];
620: }
621: while (*cp2++= *cp1++)
622: ;
623: if (p->op==MOVA && p->forw->op==PUSH) {
624: p->op=PUSHA;
625: *regs[RT2]=0; p->pop=0;
626: } else if ((p->op==MOV || p->op==CVT) &&
627: p->forw->op==PUSH) {
628: p->op=PUSH; p->subop &= 0xF;
629: *regs[RT2]=0; p->pop=0;
630: }
631: delnode(p->forw);
632: if (tempreg(lastrand,r2))
633: uses[r2]=uses[r], uses[r]=0;
634: redun3(p);
635: newcode(p); redunm++; flow=r;
636: } else if (p->op==MOV) { /* superfluous fetch */
637: int nmatch;
638: char src[C2_ASIZE];
639: movit:
640: for (cp2=src, cp1=regs[RT1]; *cp2++= *cp1++;)
641: ;
642: splitrand(p->forw);
643: if (p->forw->op != INC && p->forw->op != DEC)
644: lastrand=byondrd(p->forw);
645: nmatch=0;
646: for (preg=regs+RT1;*preg!=lastrand;preg++)
647: if (r==isreg(*preg)) {
648: cp2= *preg; cp1=src;
649: while (*cp2++= *cp1++)
650: ;
651: ++nmatch;
652: }
653: if (nmatch==1) {
654: if (has2ops(p->forw) && equstr(src,regs[RT2])) {
655: p->forw->pop=0;
656: p->forw->subop += (OP3-OP2)<<4;
657: cp1=regs[RT3];
658: *cp1++ = 'r'; *cp1++ = r+'0'; *cp1=0;
659: }
660: delnode(p);
661: p=p->forw;
662: if (tempreg(src,r2))
663: uses[r2]=uses[r], uses[r]=0;
664: redun3(p);
665: newcode(p); redunm++;
666: return(p); /* avoid stale uses[] data */
667: } else
668: splitrand(p);
669: }
670: } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) &&
671: p->forw->subop&0xf && /* if base or index, then forget it */
672: compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1]))
673: goto movit;
674: }
675: /* adjust 'lastrand' past any 'read' or 'modify' operands. */
676: lastrand=byondrd(p);
677: /* a 'write' clobbers the register. */
678: if (tempreg(lastrand,r) ||
679: (has2ops(p) && tempreg(regs[RT2],r) && uses[r]==0)) {
680: /*
681: * Writing a dead register is useless,
682: * but watch side effects
683: */
684: switch (p->op) {
685: #ifndef EMOD
686: case EDIV:
687: #endif EMOD
688: case AOBLEQ: case AOBLSS:
689: break;
690: default:
691: /*
692: * If no direct uses, check for
693: * use of condition codes
694: */
695: if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) {
696: register struct node *q = p;
697:
698: while ((q = nonlab(q->forw))->op==JBR &&
699: q->subop==0)
700: q=q->ref; /* cc unused, unchanged */
701: if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) {
702: /* ... and destroyed */
703: preg=regs+RT1;
704: while (cp1 = *preg++) {
705: if (cp1==lastrand &&
706: p->op != CLR &&
707: p->op != CVFL) {
708: redunm++;
709: delnode(p);
710: return(p->forw);
711: }
712: if (equstr(cp1,lastrand))
713: break;
714: }
715: }
716: }
717: flow=r;
718: }
719: }
720: if ((r=flow) >= 0) {
721: olduse=uses[r], uses[r]=0;
722: *(short *)(regs[r])=0;
723: /* if r0 destroyed, dont keep r1 */
724: if (dblflg&1) {
725: olduse1=uses[++r], uses[r]=0;
726: *(short *)(regs[r])=0;
727: }
728: }
729: /* now look for 'read' or 'modify' (read & write) uses */
730: preg=regs+RT1;
731: while (*(cp1= *preg++)) {
732: /* check for r */
733: if (lastrand!=cp1 && tempreg(cp1,r)) {
734: int isunused;
735: if (isunused=(uses[r]==0)) {
736: uses[r]=p;
737: cp2=regs[r]; *cp2++=p->subop;
738: if ((p->op==SHAL || p->op==SHAR ||
739: p->op==SHL || p->op==SHR) &&
740: cp1==regs[RT1])
741: cp2[-1] = BYTE;
742: if (p->op==CBR && (p->subop==JBC || p->subop==JBS))
743: cp2[-1] = LONG;
744: if (p->op==MOVA && cp1==regs[RT2])
745: cp2[-1]=LONG;
746: }
747: /* ediv/emod's 2nd operand is quad */
748: if (((p->op==EDIV
749: #ifdef EMOD
750: || p->op==EMOD
751: #endif EMOD
752: ) && cp1==regs[RT2] || (dblflg&2)) &&
753: ++r<NUSE && uses[r]==0) {
754: if (isunused)
755: *cp2=0;
756: uses[r]=p;
757: cp2=regs[r]; *cp2++=p->subop;
758: if (!isunused)
759: *cp2=0;
760: }
761: if (!isunused)
762: continue;
763: if (p->op==MOV || p->op==PUSH || p->op==CVT ||
764: p->op==MOVZ || p->op==COM || p->op==NEG ||
765: p->op==STF) {
766: if (p->op!=PUSH) {
767: cp1=regs[RT2];
768: if (tempreg(cp1,r)) {
769: /*
770: * reincarnation!!
771: * (as in addl2 r0,r1;
772: * movl r1,r0; ret)
773: */
774: if (uses[r]==0)
775: uses[r]=olduse;
776: if ((dblflg&1) && uses[r+1]==0)
777: uses[r+1]=olduse1;
778: }
779: if (p->op!=MOV)
780: cp1=0;
781: } else
782: cp1="-(sp)";
783: if (cp1)
784: while (*cp2++= *cp1++)
785: ;
786: else
787: *cp2=0;
788: } else
789: *cp2=0;
790: continue;
791: }
792: /* check for (r),[r] */
793: do {
794: if (*cp1=='(' || *cp1=='[') { /* get register number */
795: char t;
796: for (cp2= ++cp1; *++cp1!=')' && *cp1!=']';)
797: ;
798: t= *cp1; *cp1=0;
799: if (tempreg(cp2,r) &&
800: (uses[r]==0 || uses[r]==p)) {
801: uses[r]=p;
802: regs[r][0] =
803: (*--cp2=='[' ? OPX<<4 : OPB<<4);
804: regs[r][1] = '\0';
805: }
806: *cp1=t;
807: }
808: } while (*++cp1);
809: }
810: #ifdef MOVAFASTER
811: /* pushax or movax possibility? */
812: cp1=regs[RT1];
813: if (*cp1++=='$' && isstatic(cp1)) {
814: if (p->op==MOV && p->subop==LONG) {
815: if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) {
816: cp1=p->code; while (*cp1++!=','); p->code= --cp1;
817: }
818: p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0;
819: } else if (p->op==PUSH && p->subop==LONG) {
820: p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0;
821: } else if (p->op==ADD && p->subop==U(LONG,OP3)
822: && 0<=(r=isreg(regs[RT2]))) {
823: cp1=cp2=p->code; ++cp1;
824: do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='[';
825: do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']';
826: if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;}
827: else {p->op = PUSHA; p->subop = BYTE; *cp2=0;}
828: if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;}
829: p->pop=0;
830: }
831: }
832: #endif MOVAFASTER
833: return (p);
834: }
835:
836: /* try to eliminate STF's */
837: struct node *
838: flops(q)
839: register struct node *q;
840: {
841: register struct node *p;
842: register int r;
843:
844: if(q->op!=STF || !tempreg(q->code,r))
845: return(q);
846: if(uses[r]) {
847: /* see if anyone destroys acc between us */
848: for(p=q->forw; p!=uses[r]; p=p->forw)
849: switch(p->op) {
850: case LABEL:
851: case LDF: case LNF: case CVLF: case LDFD:
852: case CVDF: case NEGF: case ADDF: case SUBF:
853: case MULF: case DIVF: case SINF: case COSF:
854: case ATANF: case LOGF: case SQRTF: case EXPF:
855: return(q);
856: }
857: again:
858: if(q->subop == p->subop)
859: switch(p->op) { /* do it in the accumulator */
860: case LDF: /* redundant load */
861: delnode(p); nld++;
862: p = p->forw;
863: break;
864: case LNF: /* stf r; lnf r ==> negf */
865: p->op = NEGF;
866: p->pop = 0;
867: p->code = 0;
868: break;
869: case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */
870: { register char *s;
871: register struct node *p1=p->forw;
872: for(s=p->code; *s!=','; s++);
873: *s = 0;
874: if(isreg(p->code) == r)
875: p->code = s+1;
876: else {
877: if(p1->op != CBR || isreg(s+1) != r) {
878: *s = ',';
879: return(q);
880: }
881: if(p1->subop > JNE) {
882: p1->subop ^= 1;
883: p1->pop = 0;
884: nrevbr++;
885: }
886: }
887: p->op = CMPF;
888: p->pop = 0;
889: }
890: break;
891: default:
892: return(q);
893: }
894: else if(p->subop==LONG) {
895: switch(p->op) {
896: case TST: /* stf r; tstl r ==> tstf */
897: p->op = TSTF;
898: p->code = 0;
899: break;
900: /* send directly to destination */
901: case MOV: /* stf r; movl r,x ==> stf x */
902: case PUSH: /* stf r; pushl r ==> stf -(sp)/pushd */
903: if(q->subop == DOUBLE) {
904: register struct node *b = p->back;
905: /* assume b's 2nd arg is ok */
906: if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG))
907: return(q);
908: delnode(b); redunm++;
909: }
910: if(p->op==PUSH) {
911: if(q->subop == DOUBLE) {
912: p->op = PUSHD;
913: p->code = 0;
914: } else {
915: p->op = q->op;
916: p->code = copy("-(sp)");
917: }
918: } else {
919: p->op = q->op;
920: while(*p->code++ != ',');
921: }
922: break;
923: default:
924: return(q);
925: }
926: p->pop = 0;
927: p->subop = q->subop;
928: } else
929: return(q);
930: uses[r] = 0;
931: if(q->subop == DOUBLE)
932: uses[r+1] = 0;
933: for(p = p->back; p != q && (!uses[r] || !uses[r+1]); p = p->back) {
934: int xr;
935:
936: splitrand(p);
937: if((xr=isreg(regs[RT1])) < 0)
938: continue;
939: if(!uses[r] && xr == r)
940: uses[r] = p;
941: else if(q->subop == DOUBLE && !uses[r+1] && xr == r+1)
942: uses[r+1] = p;
943: }
944: if(p = uses[r])
945: goto again;
946: return(q->forw); /* DON'T re-scan code with dated uses[] */
947: }
948: /* it's a store to reg which isnt used elsewhere */
949: if((p=q->forw)->op == CBR) {
950: q->op = TSTF;
951: q->pop = 0;
952: q->code = 0;
953: } else {
954: delnode(q); nst++;
955: if(p->op ==STF || p->op==TSTF || p->op==PUSHD) {
956: if(useacc == p)
957: useacc = 0;
958: return(p->forw); /* so ldmov can be used on p */
959: }
960: }
961: return(p);
962: }
963:
964: /* try to change load/store sequences to movl */
965: ldmov(q)
966: register struct node *q;
967: {
968: register struct node *p;
969: register char *s, *pcod, *cp;
970: char *dlsw();
971:
972: p = q->back;
973: if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD)
974: && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE))))
975: return(0);
976: pcod = p->code;
977: cp = p->code;
978: /* prepare args for movl/pushl */
979: if(q->op!=TSTF && q->subop==DOUBLE) {
980: if(p->op == LDF) {
981: if((s = dlsw(p->code)) == NULL)
982: return(0);
983:
984: strcpy(line, s);
985: if(q->op == STF) {
986: strcat(line, ",");
987: if((s = dlsw(q->code)) == NULL)
988: return(0);
989: strcat(line, s);
990: p->op = MOV;
991: } else
992: p->op = PUSH;
993: } else { /* LDFD */
994: if(q->op == STF) {
995: if((s = dlsw(q->code)) == NULL)
996: return(0);
997: } else
998: s = "-(sp)";
999: strcpy(line, s);
1000: p->op = CLR;
1001: }
1002: p->pop = 0;
1003: p->subop = LONG;
1004: p->code = copy(line);
1005: } else
1006: {
1007: if ((p->op == LDF) && (p->subop == DOUBLE) &&
1008: (indexa(cp))) return(0);
1009: delnode(p);
1010: }
1011: strcpy(line, pcod);
1012: if(q->op == STF) { /* ldf x; stf y ==> movl x,y */
1013: strcat(line, ",");
1014: strcat(line, q->code);
1015: q->op = MOV;
1016: nst++;
1017: } else if(q->op == TSTF) /* ldf x; tstf ==> tstl x */
1018: q->op = TST;
1019: else /* ldd x; pushd ==> pushl x+4; pushl x */
1020: q->op = PUSH;
1021: q->pop = 0;
1022: q->subop = LONG;
1023: q->code = copy(line);
1024: nld++;
1025: return(1);
1026: }
1027:
1028: /* reconstruct the address of l.s.w. of a double operand */
1029: char *
1030: dlsw(d)
1031: register char *d;
1032: {
1033: register char *s, *t, *c;
1034: register int r;
1035: static char lsw[C2_ASIZE];
1036:
1037: if(d[0] == '*' || d[0] == '$')
1038: return(NULL);
1039: if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2]))
1040: return(NULL);
1041: t = lsw;
1042: if((r=isreg(d)) >= 0)
1043: sprintf(t, "r%d", r+1);
1044: else {
1045: for(s=d; *s && *s!='('; *t++ = *s++)
1046: if(*s == '[')
1047: return(NULL);
1048: if(s!=d)
1049: *t++ = '+';
1050: *t++ = '4';
1051: while(*t++ = *s)
1052: if(*s++ == '[' )
1053: {
1054: return(NULL);
1055: }
1056: }
1057: return(lsw);
1058: }
1059: checkexpr(p)
1060: register char *p;
1061: {
1062:
1063: while(*p && *p != ','){
1064: if ((*p == '+' ) || (*p == '-'))
1065: return(1);
1066: *p++;
1067: }
1068: return(0);
1069: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.