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