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