126440Ssam #ifndef lint
2*35390Sdonn static char sccsid[] = "@(#)c21.c 1.10 (Berkeley/CCI) 08/25/88";
326440Ssam #endif
426440Ssam
526440Ssam /*
626440Ssam * C object code improver-- second part
726440Ssam */
826440Ssam
926440Ssam #include "c2.h"
1026440Ssam #include <stdio.h>
1126440Ssam #include <ctype.h>
1226440Ssam
1326440Ssam int bitsize[] = {0,8,16,32,64,32,64}; /* index by type codes */
1426440Ssam
redun3(p)1526440Ssam redun3(p) register struct node *p; {
1626440Ssam /* check for 3 addr instr which should be 2 addr */
1729775Ssam if (has3ops(p)) {
1826440Ssam if (equstr(regs[RT1],regs[RT3])
1926440Ssam && (p->op==ADD || p->op==MUL || p->op==AND || p->op==OR || p->op==XOR)) {
2026440Ssam register char *t=regs[RT1]; regs[RT1]=regs[RT2]; regs[RT2]=t;
2126440Ssam }
2226440Ssam if (equstr(regs[RT2],regs[RT3])) {
2326440Ssam p->subop=(p->subop&0xF)|(OP2<<4); p->pop=0;
2426440Ssam lastrand=regs[RT2]; *regs[RT3]=0; return(1);
2526440Ssam }
2626440Ssam } return(0);
2726440Ssam }
2826440Ssam
bmove()2926440Ssam bmove() {
3026440Ssam register struct node *p, *lastp; register char *cp1,*cp2; register int r;
3126440Ssam struct node *flops();
3226440Ssam
3326440Ssam refcount();
3426440Ssam for (p=lastp= &first; 0!=(p=p->forw); lastp=p);
3526440Ssam clearreg(); clearuse();
3626440Ssam for (p=lastp; p!= &first; p=p->back) {
3726440Ssam if (debug) {
3826440Ssam printf("Uses: ");
3926440Ssam if (useacc)
4026440Ssam printf("acc: %s\n",useacc->code? useacc->code:"");
4126440Ssam for (r=NUSE;--r>=0;) if (uses[r])
4226440Ssam printf("%d: %s\n",r,uses[r]->code? uses[r]->code:"");
4326440Ssam printf("-\n");
4426440Ssam }
4526440Ssam r=(p->subop>>4)&0xF;
4626440Ssam splitrand(p);
4726440Ssam if (OP3==r && 0!=redun3(p)) {newcode(p); redunm++;}
4826440Ssam /* ops that do nothing */
4926440Ssam if(p->op==MOV && equstr(regs[RT1], regs[RT2]))
5026440Ssam if(p->forw->op!=CBR) {
5126440Ssam delnode(p); redunm++; continue;
5226440Ssam } else {
5326440Ssam p->op=TST; p->pop=0;
5426440Ssam while(*p->code++ != ',');
5526440Ssam redunm++;
5626440Ssam }
5726440Ssam else if((cp1=p->code, *cp1++)=='$' &&
5826440Ssam (*cp1=='0' || *cp1=='1' || *cp1++=='-' && *cp1=='1') && cp1[1]==',') {
5929775Ssam switch((p->code[1]<<8)|ord(p->op)) {
6029775Ssam case (('0'<<8)|ord(ADD)):
6129775Ssam case (('0'<<8)|ord(SUB)):
6229775Ssam case (('-'<<8)|ord(AND)):
6329775Ssam case (('0'<<8)|ord(OR)):
6429775Ssam case (('0'<<8)|ord(XOR)):
6529775Ssam case (('1'<<8)|ord(MUL)):
6629775Ssam case (('1'<<8)|ord(DIV)):
6729775Ssam case (('0'<<8)|ord(SHAL)):
6829775Ssam case (('0'<<8)|ord(SHAR)):
6929775Ssam case (('0'<<8)|ord(SHL)):
7029775Ssam case (('0'<<8)|ord(SHR)):
7126440Ssam if(r == OP2) {
7226440Ssam if(p->forw->op!=CBR) {
7326440Ssam delnode(p); redunm++; continue;
7426440Ssam } else {
7526440Ssam p->op=TST; p->subop&=0xF; p->pop=0;
7626440Ssam while(*p->code++ != ',');
7726440Ssam redunm++;
7826440Ssam }
7926440Ssam } else { /* OP3 or shift */
8026440Ssam p->op=MOV; p->subop&=0xF; p->pop=0;
8126440Ssam while(*p->code++ != ',');
8226440Ssam p = p->forw; redunm++; continue;
8326440Ssam }
8426440Ssam break;
8529775Ssam case (('0'<<8)|ord(MUL)):
8629775Ssam case (('0'<<8)|ord(AND)):
8726440Ssam p->op=CLR; p->subop&=0xF; p->pop=0;
8826440Ssam while(*p->code++ != ',');
8926440Ssam if(r == OP3)
9026440Ssam while(*p->code++ != ',');
9126440Ssam redunm++;
9226440Ssam }
9326440Ssam }
9426440Ssam switch (p->op) {
9526440Ssam case LABEL: case DLABEL:
9626440Ssam for (r=NUSE; --r>=0;)
9726440Ssam if (uses[r]) p->ref=(struct node *) (((int)p->ref)|(1<<r));
9826440Ssam if (useacc) p->ref=(struct node *) (((int)p->ref)|(1<<NUSE));
9926440Ssam break;
10026440Ssam case CALLS:
10126440Ssam case CALLF:
10226440Ssam clearuse(); goto std;
10329775Ssam case NIL:
10426440Ssam clearuse(); break;
10526440Ssam case CVT:
10626440Ssam { long n;
10726440Ssam if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
10826440Ssam if (*cp1++!='$') goto std; splitrand(p);
10926440Ssam n = getnum(®s[RT1][1]);
11026440Ssam if(r==BYTE && (n<-128 || n>127)) goto std;
11126440Ssam if(r==WORD && (n<-32768 || n>32767)) goto std;
11226440Ssam p->op = MOV; p->subop = r; p->pop = 0;
11326440Ssam } goto std;
11426440Ssam
11526440Ssam case SUB:
11626440Ssam if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
11726440Ssam if (*cp1++!='$') goto std; splitrand(p);
11826440Ssam #ifdef MOVAFASTER
11926440Ssam if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
12026440Ssam char buf[C2_ASIZE]; cp2=buf; *cp2++='-';
12126440Ssam cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
12226440Ssam cp1="(fp),"; while (*cp2++= *cp1++); --cp2;
12326440Ssam cp1=regs[RT3]; while (*cp2++= *cp1++);
12426440Ssam p->code=copy(buf); p->op = MOVA; p->subop = BYTE; p->pop=0;
12526440Ssam } else
12626440Ssam #endif MOVAFASTER
12729670Ssam if (*cp1++=='-' && 0==(r=getnum(cp1)) &&
12829670Ssam !checkexpr(cp1)) {
12926440Ssam p->op=ADD; p->pop=0; *--cp1='$'; p->code=cp1;
13026440Ssam } goto std;
13126440Ssam case ADD:
13226440Ssam if ((p->subop&0xF)!=LONG) goto std; cp1=p->code;
13326440Ssam if (*cp1++!='$') goto std; splitrand(p);
13429775Ssam if (isstatic(cp1) && tempreg(regs[RT2],r) && uses[r]==p->forw)
13526440Ssam {
13626440Ssam /* address comp:
13726440Ssam ** addl2 $_foo,r0 \ movab _foo[r0],bar
13826440Ssam ** movl r0,bar /
13926440Ssam */
14026440Ssam register struct node *pnext = p->forw;
14126440Ssam char buf[C2_ASIZE];
14226440Ssam
14326440Ssam if (pnext->op == MOV && pnext->subop == LONG)
14426440Ssam {
14526440Ssam cp1 = ®s[RT1][1]; cp2 = &buf[0];
14626440Ssam while (*cp2++ = *cp1++) ; cp2--;
14726440Ssam splitrand(pnext);
14826440Ssam if (r == isreg(regs[RT1]))
14926440Ssam {
15026440Ssam delnode(p); p = pnext;
15126440Ssam p->op = MOVA; p->subop = BYTE;
15226440Ssam p->pop = 0;
15326440Ssam cp1 = regs[RT1]; *cp2++ = '[';
15426440Ssam while (*cp2++ = *cp1++) ; cp2--;
15526440Ssam *cp2++ = ']'; *cp2++ = ',';
15626440Ssam cp1 = regs[RT2];
15726440Ssam while (*cp2++ = *cp1++) ;
15826440Ssam p->code = copy(buf);
15926440Ssam }
16026440Ssam }
16126440Ssam }
16226440Ssam else
16326440Ssam #ifdef MOVAFASTER
16426440Ssam if (equstr(regs[RT2],"fp") && !indexa(regs[RT1])) {/* address comp. */
16526440Ssam cp2=cp1-1; cp1=regs[RT1]+1; while (*cp2++= *cp1++); --cp2;
16626440Ssam cp1="(fp)"; while (*cp2++= *cp1++); *--cp2=',';
16726440Ssam p->op = MOVA; p->subop = BYTE; p->pop=0;
16826440Ssam } else
16926440Ssam #endif MOVAFASTER
17029670Ssam if (*cp1++=='-' && 0==(r=getnum(cp1)) &&
17129670Ssam !checkexpr(cp1)) {
17226440Ssam p->op=SUB; p->pop=0; *--cp1='$'; p->code=cp1;
17326440Ssam }
17426440Ssam /* fall thru ... */
17526440Ssam case CASE:
17626440Ssam default: std:
17726440Ssam p=bflow(p); break;
17826440Ssam
17926440Ssam case MUL:
18026440Ssam /*
18126440Ssam ** Change multiplication
18226440Ssam ** by constant powers of 2 to shifts.
18326440Ssam */
18426440Ssam splitrand(p);
18526440Ssam if (regs[RT1][0] != '$' || regs[RT1][1] == '-') goto std;
18626440Ssam if ((r = ispow2(getnum(®s[RT1][1]))) <= 0) goto std;
18726440Ssam /* mull2 $2,x */
18826440Ssam if(r == 1 && p->subop == U(LONG, OP2)) {
18926440Ssam strcpy(regs[RT1], regs[RT2]);
19026440Ssam p->op = ADD; p->pop = 0; newcode(p);
19126440Ssam goto std;
19226440Ssam }
19326440Ssam if (p->subop == U(LONG,OP2))
19426440Ssam strcpy(regs[RT3], regs[RT2]);
19526440Ssam sprintf(regs[RT1], "$%d", r);
19626440Ssam p->op = SHL; p->subop = LONG;
19726440Ssam p->pop = 0; newcode(p);
19826440Ssam goto std;
19926440Ssam
20026440Ssam case SHAL:
20126440Ssam case SHL:
20226440Ssam {
20326440Ssam /* bit tests:
20426440Ssam ** shll A,$1,rC \
20526440Ssam ** bitl B,rC > jbc A,B,D
20626440Ssam ** jeql D /
20726440Ssam **
20826440Ssam ** address comp:
20926440Ssam ** shll $1,bar,r0 \ movl bar,r0
21026440Ssam ** movab _foo[r0] / movaw _foo[r0]
21126440Ssam **
21226440Ssam ** shll $2,r0,r0 \ moval _foo[r0]
21326440Ssam ** movab _foo[r0] /
21426440Ssam */
21526440Ssam register struct node *pf;
21626440Ssam register struct node *pn;
21726440Ssam register int shfrom, shto;
21826440Ssam long shcnt;
21926440Ssam char *regfrom;
22026440Ssam
22126440Ssam splitrand(p);
22226440Ssam if (regs[RT1][0] != '$') {
22326440Ssam if(isreg(regs[RT1]) < 0) goto std; /* alignment */
22426440Ssam if (regs[RT2][0] != '$') goto std;
22526440Ssam if (getnum(®s[RT2][1]) != 1) goto std;
22629775Ssam if (!tempreg(regs[RT3],r)) goto std;
22726440Ssam if ((pf = p->forw)->op != BIT && pf->op!=AND) goto std;
22826440Ssam if (uses[r] && uses[r] != pf) goto std;
22926440Ssam splitrand(pf);
23026440Ssam if (r == isreg(regs[RT1])) cp2 = regs[RT2];
23126440Ssam else if (r == isreg(regs[RT2])) cp2 = regs[RT1];
23226440Ssam else goto std;
23326440Ssam if (*cp2 == '$') goto std;
23426440Ssam if ((pn = pf->forw)->op != CBR) goto std;
23526440Ssam if (pn->subop != JEQ && pn->subop != JNE) goto std;
23626440Ssam delnode(p); delnode(pf);
23726440Ssam pn->subop = (pn->subop == JEQ) ? JBC : JBS;
23826440Ssam for(cp1=p->code; *cp1++!=',';);
23926440Ssam while (*cp1++= *cp2++);
24026440Ssam pn->code = p->code; pn->pop = NULL;
24126440Ssam uses[r] = NULL;
24226440Ssam nbj++;
24326440Ssam p = pn;
24426440Ssam goto std;
24526440Ssam }
24626440Ssam if ((shcnt = getnum(®s[RT1][1])) < 1 || shcnt > 2) goto std;
24726440Ssam if ((shfrom = isreg(regs[RT2])) >= 0)
24826440Ssam regfrom = copy(regs[RT2]);
24929775Ssam if (tempreg(regs[RT3],shto))
25026440Ssam {
25126440Ssam int regnum;
25226440Ssam
25326440Ssam if (uses[shto] != (pf = p->forw)) goto ashadd;
25426440Ssam if (pf->op != MOVA && pf->op != PUSHA) goto ashadd;
25526440Ssam if (pf->subop != BYTE) goto ashadd;
25626440Ssam splitrand(pf);
25726440Ssam if (!indexa(regs[RT1])) goto std;
25826440Ssam cp2 = regs[RT1];
25926440Ssam if(!isstatic(cp2)) goto std;
26026440Ssam while (*cp2++ != '[') ;
26126440Ssam if (*cp2++ != 'r' || !isdigit(*cp2)) goto std;
26226440Ssam regnum = *cp2++ - '0';
26326440Ssam if (isdigit(*cp2))
26426440Ssam {
26526440Ssam if (cp2[1] != ']') goto std;
26626440Ssam regnum *= 10; regnum += *cp2 - '0';
26726440Ssam }
26826440Ssam if (regnum != shto) goto std;
26926440Ssam if (shfrom >= 0) /* shll $N,r*,r0 */
27026440Ssam {
27126440Ssam delnode(p);
27226440Ssam p = pf;
27326440Ssam if (shfrom != shto)
27426440Ssam {
27526440Ssam uses[shto] = NULL; splitrand(pf);
27626440Ssam cp2=regs[RT1]; while (*cp2++!='[');
27726440Ssam cp1=regfrom; while (*cp2++= *cp1++);
27826440Ssam cp2[-1] = ']'; *cp2 = 0;
27926440Ssam newcode(pf);
28026440Ssam }
28126440Ssam }
28226440Ssam else
28326440Ssam {
28426440Ssam p->op = MOV; splitrand(p);
28526440Ssam strcpy(regs[RT1], regs[RT2]);
28626440Ssam strcpy(regs[RT2], regs[RT3]);
28726440Ssam regs[RT3][0] = '\0';
28826440Ssam p->pop = 0; newcode(p);
28926440Ssam }
29026440Ssam switch (shcnt)
29126440Ssam {
29226440Ssam case 1: pf->subop = WORD; break;
29326440Ssam case 2: pf->subop = LONG; break;
29426440Ssam }
29534266Sdonn pf->pop = 0;
29626440Ssam redunm++; nsaddr++;
297*35390Sdonn goto std;
29826440Ssam }
29926440Ssam ashadd:
30026440Ssam /* at this point, RT2 and RT3 are guaranteed to be simple regs*/
30126440Ssam if (shcnt == 1) {
30226440Ssam /*
30326440Ssam ** quickie:
30426440Ssam ** shll $1,A,A > addl2 A,A
30526440Ssam ** shll $1,A,B > addl3 A,A,B
30626440Ssam */
307*35390Sdonn if ((pf = p->forw)->op == CBR ||
308*35390Sdonn (pf->op == MOV && (pf = pf->forw)->op == CBR))
309*35390Sdonn /*
310*35390Sdonn ** shll and addl handle the N bit differently
311*35390Sdonn ** on overflow; avoid N bit CBRs
312*35390Sdonn */
313*35390Sdonn switch (pf->subop) {
314*35390Sdonn case JLE: case JGE: case JLT: case JGT:
315*35390Sdonn goto std;
316*35390Sdonn }
31726440Ssam p->op = ADD;
31826440Ssam strcpy(regs[RT1], regs[RT2]);
31926440Ssam if(equstr(regs[RT2], regs[RT3])) {
32026440Ssam p->subop = U(LONG,OP2);
32126440Ssam regs[RT3][0] = '\0';
32226440Ssam } else
32326440Ssam p->subop = U(LONG,OP3);
32426440Ssam p->pop = 0;
32526440Ssam newcode(p);
32626440Ssam }
32726440Ssam goto std;
32826440Ssam }
32926440Ssam
33026440Ssam case SHAR:
33126440Ssam case SHR:
33226440Ssam {
33326440Ssam /* bit tests:
33426440Ssam ** shrl A,B,rC \
33526440Ssam ** bitl $1,rC > jbc A,B,D
33626440Ssam ** jeql D /
33726440Ssam */
33826440Ssam register struct node *pf; /* forward node */
33926440Ssam register struct node *pn; /* next node (after pf) */
34026440Ssam register int extreg; /* reg extracted to */
34126440Ssam
34226440Ssam splitrand(p);
34326440Ssam if(isreg(regs[RT1]) < 0) goto std; /* alignment */
34429775Ssam if (!tempreg(regs[RT3],extreg)) goto std;
34526440Ssam if ((pf = p->forw)->op != BIT) goto std;
34626440Ssam if (uses[extreg] && uses[extreg] != pf) goto std;
34726440Ssam splitrand(pf);
34826440Ssam if (regs[RT1][0] != '$') goto std;
34926440Ssam if (getnum(®s[RT1][1]) != 1) goto std;
35026440Ssam if (extreg != isreg(regs[RT2])) goto std;
35126440Ssam if ((pn = pf->forw)->op != CBR) goto std;
35226440Ssam if (pn->subop != JEQ && pn->subop != JNE) goto std;
35326440Ssam delnode(p); delnode(pf);
35426440Ssam pn->subop = (pn->subop == JEQ) ? JBC : JBS;
35526440Ssam for(cp1=p->code; *cp1++!=',';);
35626440Ssam while (*cp1!=',') cp1++; *cp1='\0';
35726440Ssam pn->code = p->code; pn->pop = NULL;
35826440Ssam uses[extreg] = NULL; nbj++;
35926440Ssam p = pn;
36026440Ssam goto std;
36126440Ssam }
36226440Ssam
36326440Ssam case AND:
36426440Ssam {
36526440Ssam /* unsigned conversion:
36626440Ssam ** cvtbl A,B; andl2 $255,B > movzbl A,B
36726440Ssam **
36826440Ssam ** also byte- and word-size fields:
36926440Ssam ** shrl $(3-n)*8,A,B; andl2 $255,B > movzbl n+A,B
37026440Ssam ** shrl $(1-n)*16,A,B; andl2 $65535,B > movzwl n+A,B
37126440Ssam */
37226440Ssam char src[C2_ASIZE];
37326440Ssam register int f; /* field length */
37426440Ssam register struct node *pb = p->back; /* backward node */
37526440Ssam
37626440Ssam if (p->subop != U(LONG,OP2))
37726440Ssam goto std;
37826440Ssam splitrand(p); cp1=regs[RT1];
37926440Ssam if (*cp1++!='$' || (f=getnum(cp1))!=0xff && f!=0xffff)
38026440Ssam goto std;
38126440Ssam f = f==0xff ? 8 : 16;
38226440Ssam if (pb->op!=CVT && pb->op!=MOVZ && pb->op!=SHAR && pb->op!=SHR)
38326440Ssam goto std;
38426440Ssam /* save source of ANDL in 'src' */
38526440Ssam strcpy(src, regs[RT2]);
38626440Ssam splitrand(pb);
38726440Ssam if (!equstr(src,lastrand))
38826440Ssam goto std;
38926440Ssam if (pb->op==CVT || pb->op==MOVZ) {
39026440Ssam if (!(bitsize[pb->subop&0xF]==f
39126440Ssam && bitsize[pb->subop>>4]>=f)) /* good CVT */
39226440Ssam goto std;
39326440Ssam strcpy(src, regs[RT1]);
39426440Ssam } else {
39526440Ssam register int boff; /* bit offset */
39626440Ssam
39726440Ssam if (regs[RT1][0] != '$') goto std;
39826440Ssam if ((boff = getnum(®s[RT1][1])) < 0) goto std;
39926440Ssam if (isreg(regs[RT2])>=0 || !natural(regs[RT2])) goto std;
40026440Ssam if ((boff & (f-1)) != 0) goto std;
40126440Ssam boff = (32-boff-f) / 8;
40226440Ssam if (boff == 0)
40326440Ssam strcpy(src, regs[RT2]);
40426440Ssam else
40526440Ssam sprintf(src, "%d%s%s", boff, regs[RT2][0]=='(' ? "":"+",
40626440Ssam regs[RT2]);
40726440Ssam }
40826440Ssam delnode(pb);
40926440Ssam p->op = MOVZ;
41026440Ssam p->subop = U((f==8 ? BYTE : WORD), LONG);
41126440Ssam sprintf(line,"%s,%s",src,lastrand);
41226440Ssam p->pop=0;
41326440Ssam p->code = copy(line);
41426440Ssam goto std;
41526440Ssam }
41626440Ssam
41726440Ssam case CMP:
41826440Ssam {
41926440Ssam /* comparison to -63 to -1:
42026440Ssam ** cmpl r0,$-1 > incl r0
42126440Ssam ** jeql ...
42226440Ssam **
42326440Ssam ** cmpl r0,$-63 > addl2 $63,r0
42426440Ssam ** jeql ...
42526440Ssam */
42626440Ssam register int num;
42726440Ssam register int reg;
42826440Ssam register struct node *regp = p->back;
42926440Ssam
43026440Ssam if (p->forw->op != CBR) goto std;
43126440Ssam if (p->forw->subop != JEQ && p->forw->subop != JNE) goto std;
43226440Ssam splitrand(p);
43326440Ssam if (strncmp(regs[RT2], "$-", 2) != 0) goto std;
43426440Ssam reg = r = isreg(regs[RT1]);
43526440Ssam if (r < 0) goto std;
43626440Ssam if (r < NUSE && uses[r] != 0) goto std;
43726440Ssam if (r >= NUSE && regp->op == MOV && p->subop == regp->subop)
43826440Ssam {
43926440Ssam if (*regp->code != 'r') goto std;
44026440Ssam reg = regp->code[1] - '0';
44126440Ssam if (isdigit(regp->code[2]) || reg >= NUSE || uses[reg])
44226440Ssam goto std;
44326440Ssam }
44426440Ssam if (r >= NUSE) goto std;
44526440Ssam if (reg != r)
44626440Ssam sprintf(regs[RT1], "r%d", reg);
44726440Ssam if ((num = getnum(®s[RT2][2])) <= 0 || num > 63) goto std;
44826440Ssam if (num == 1)
44926440Ssam {
45026440Ssam p->op = INC; regs[RT2][0] = '\0';
45126440Ssam }
45226440Ssam else
45326440Ssam {
45426440Ssam register char *t;
45526440Ssam
45626440Ssam t=regs[RT1];regs[RT1]=regs[RT2];regs[RT2]=t;
45726440Ssam p->op = ADD; p->subop = U(p->subop, OP2);
45826440Ssam for (t = ®s[RT1][2]; t[-1] = *t; t++) ;
45926440Ssam }
46026440Ssam p->pop = 0; newcode(p);
46126440Ssam goto std;
46226440Ssam }
46326440Ssam
46426440Ssam case JBR: case JMP:
46526440Ssam clearuse();
46626440Ssam if ((p->subop&0xF)==RET) {
46726440Ssam switch((p->subop>>4)&0xF) {
46826440Ssam case 2: uses[1]=p; regs[1][0]= -1;
46926440Ssam case 1: uses[0]=p; regs[0][0]= -1;
47026440Ssam }
47126440Ssam break;
47226440Ssam }
47326440Ssam if (p->ref==0) goto std; /* jmp (r0) */
47426440Ssam /* fall through */
47526440Ssam case CBR:
47626440Ssam if (p->ref->ref!=0) {
47726440Ssam for (r=NUSE;--r>=0;)
47826440Ssam if ((1<<r) & (int)p->ref->ref) {uses[r]=p; regs[r][0]= -1;}
47926440Ssam if ((1<<NUSE) & (int)p->ref->ref) useacc=p;
48026440Ssam }
48126440Ssam break;
48226440Ssam case LNF:
48326440Ssam /* lnf a; addf b ==> ldf b; subf a */
48426440Ssam { register struct node *pf = p->forw;
48526440Ssam if(pf->op==ADDF && p->subop==pf->subop) {
48626440Ssam p->op = LDF;
48726440Ssam p->pop = 0;
48826440Ssam pf->op = SUBF;
48926440Ssam pf->pop = 0;
49026440Ssam cp1 = p->code;
49126440Ssam p->code = pf->code;
49226440Ssam pf->code = cp1;
49326440Ssam p = pf->forw;
49426440Ssam break;
49526440Ssam }}
49626440Ssam case LDF: case LDFD: case CVLF: /* destroy acc */
49726440Ssam useacc = 0;
49826440Ssam goto std;
49926440Ssam case STF:
50026440Ssam { register struct node *pf;
50126440Ssam if((pf=flops(p)) != p) {
50226440Ssam p = pf; /* usually p->forw; */
50326440Ssam break;
50426440Ssam }}
50526440Ssam if(ldmov(p)) {
50626440Ssam p = p->forw;
50726440Ssam break;
50826440Ssam }
50926440Ssam if(useacc == 0)
51026440Ssam useacc = p;
51126440Ssam goto std;
51226440Ssam case ADDF: case MULF: /* commutatives - create clients for flops */
51326440Ssam /* stf a; ldf b; addf a => stf a; ldf a; addf b */
51426440Ssam { register struct node *pb = p->back;
51526440Ssam register struct node *pbb = pb->back;
51626440Ssam if(pb->op==LDF && pb->subop==p->subop &&
51726440Ssam pbb && pbb->op==STF && pbb->subop==p->subop &&
51826440Ssam equstr(pbb->code, p->code)) {
51926440Ssam cp1 = p->code;
52026440Ssam p->code = pb->code;
52126440Ssam pb->code = cp1;
52226440Ssam }}
52326440Ssam /* use acc and regs */
52426440Ssam case CMPF: case CVFL: case SUBF: case DIVF:
52526440Ssam if(useacc == 0)
52626440Ssam useacc = p;
52726440Ssam goto std;
52829670Ssam case TSTF:
52929670Ssam break;
53029670Ssam case PUSHD:
53126440Ssam if(ldmov(p)) {
53226440Ssam p = p->forw;
53326440Ssam break;
53426440Ssam }
53526440Ssam case CVDF: case NEGF: /* use only acc */
53626440Ssam case SINF: case COSF: case ATANF: case LOGF: case SQRTF: case EXPF:
53726440Ssam if(useacc == 0)
53826440Ssam useacc = p;
53926440Ssam case EROU: case JSW:
54026440Ssam case TEXT: case DATA: case BSS: case ALIGN: case WGEN: case END: ;
54126440Ssam }
54226440Ssam }
54326440Ssam for (p= &first; p!=0; p=p->forw)
54426440Ssam if (p->op==LABEL || p->op==DLABEL) p->ref=0; /* erase our tracks */
54526440Ssam }
54626440Ssam
54726440Ssam char *
byondrd(p)54826440Ssam byondrd(p) register struct node *p; {
54926440Ssam /* return pointer to register which is "beyond last read/modify operand" */
55029775Ssam if (has2ops(p)) return(regs[RT3]);
55126440Ssam switch (p->op) {
55226440Ssam case MFPR:
55326440Ssam case PUSHA:
55426440Ssam case TST: case INC: case DEC: case PUSH:
55526440Ssam case LDF: case LNF: case CVLF: case LDFD:
55626440Ssam case ADDF: case SUBF: case MULF: case DIVF:
55726440Ssam case CMPF:
55826440Ssam return(regs[RT2]);
55926440Ssam case MTPR:
56026440Ssam #ifndef EMOD
56126440Ssam case EDIV:
56226440Ssam #endif EMOD
56326440Ssam case CBR: /* must be JBC/JBS */
56426440Ssam case BIT: case CMP: case CALLS: case CALLF:
56526440Ssam case CMPF2:
56626440Ssam return(regs[RT3]);
56726440Ssam case EMUL:
56826440Ssam case PROBE:
56926440Ssam case MOVBLK:
57026440Ssam case CASE:
57126440Ssam return(regs[RT4]);
57226440Ssam }
57326440Ssam return(lastrand);
57426440Ssam }
57526440Ssam
57626440Ssam struct node *
bflow(p)57726440Ssam bflow(p)
57829775Ssam register struct node *p;
57926440Ssam {
58026440Ssam register char *cp1,*cp2,**preg;
58126440Ssam register int r, fr, dblflg=0;
58226440Ssam int flow= -1;
58326440Ssam struct node *olduse=0, *olduse1=0;
58426440Ssam
58533361Sdonn if (p->subop==QUAD || p->subop==DOUBLE || (p->subop&0xF0)==DOUBLE<<4 ||
58633361Sdonn p->op==EMUL)
58726440Ssam dblflg |= 1; /* double dest */
58829775Ssam if ((p->subop&0xF)==DOUBLE || p->subop==QUAD)
58926440Ssam dblflg |= 2; /* double src */
59026440Ssam splitrand(p);
59129775Ssam if (p->op!=PUSH &&
59226440Ssam #ifndef EMOD
59329775Ssam p->op!=EDIV &&
59426440Ssam #endif EMOD
59529775Ssam p->op!=EMUL &&
59629775Ssam p->subop && tempreg(lastrand,r) && uses[r]==p->forw) {
59729775Ssam if (equtype(p->subop,regs[r][0]) ||
59829775Ssam ((p->op==CVT || p->op==MOVZ || p->op==CVFL) &&
59929775Ssam (regs[r][0]&0xf) && compat((p->subop>>4)&0xf,regs[r][0])) ||
60029775Ssam p->op==MOVA && compat(LONG, regs[r][0])) {
60126440Ssam register int r2;
60229775Ssam
60329775Ssam if (regs[r][1]!=0) { /* send directly to destination */
60426440Ssam if (p->op==INC || p->op==DEC) {
60529775Ssam p->op = (p->op==DEC) ? SUB : ADD;
60629775Ssam /* use 2 now, convert to 3 later */
60729775Ssam p->subop=(OP2<<4)+(p->subop&0xF);
60826440Ssam p->pop=0;
60929775Ssam cp1=lastrand; cp2=regs[RT2];
61029775Ssam while (*cp2++= *cp1++) /* copy reg */
61129775Ssam ;
61226440Ssam cp1=lastrand; *cp1++='$'; *cp1++='1'; *cp1=0;
61326440Ssam }
61426440Ssam cp1=regs[r]+1; cp2=lastrand;
61529775Ssam if (has2ops(p)) {
61629775Ssam /* use 3 operand form of instruction */
61726440Ssam p->pop=0;
61829775Ssam p->subop += (OP3-OP2)<<4;
61929775Ssam lastrand = cp2 = regs[RT3];
62026440Ssam }
62129775Ssam while (*cp2++= *cp1++)
62229775Ssam ;
62326440Ssam if (p->op==MOVA && p->forw->op==PUSH) {
62426440Ssam p->op=PUSHA;
62526440Ssam *regs[RT2]=0; p->pop=0;
62629775Ssam } else if ((p->op==MOV || p->op==CVT) &&
62729775Ssam p->forw->op==PUSH) {
62826440Ssam p->op=PUSH; p->subop &= 0xF;
62926440Ssam *regs[RT2]=0; p->pop=0;
63026440Ssam }
63126440Ssam delnode(p->forw);
63229775Ssam if (tempreg(lastrand,r2))
63329775Ssam uses[r2]=uses[r], uses[r]=0;
63426440Ssam redun3(p);
63526440Ssam newcode(p); redunm++; flow=r;
63629775Ssam } else if (p->op==MOV) { /* superfluous fetch */
63726440Ssam int nmatch;
63826440Ssam char src[C2_ASIZE];
63926440Ssam movit:
64029775Ssam for (cp2=src, cp1=regs[RT1]; *cp2++= *cp1++;)
64129775Ssam ;
64226440Ssam splitrand(p->forw);
64326440Ssam if (p->forw->op != INC && p->forw->op != DEC)
64426440Ssam lastrand=byondrd(p->forw);
64526440Ssam nmatch=0;
64626440Ssam for (preg=regs+RT1;*preg!=lastrand;preg++)
64726440Ssam if (r==isreg(*preg)) {
64829775Ssam cp2= *preg; cp1=src;
64929775Ssam while (*cp2++= *cp1++)
65029775Ssam ;
65129775Ssam ++nmatch;
65226440Ssam }
65326440Ssam if (nmatch==1) {
65429775Ssam if (has2ops(p->forw) && equstr(src,regs[RT2])) {
65526440Ssam p->forw->pop=0;
65629775Ssam p->forw->subop += (OP3-OP2)<<4;
65729775Ssam cp1=regs[RT3];
65829775Ssam *cp1++ = 'r'; *cp1++ = r+'0'; *cp1=0;
65926440Ssam }
66029775Ssam delnode(p);
66129775Ssam p=p->forw;
66229775Ssam if (tempreg(src,r2))
66329775Ssam uses[r2]=uses[r], uses[r]=0;
66426440Ssam redun3(p);
66533359Sdonn newcode(p); redunm++;
66633359Sdonn return(p); /* avoid stale uses[] data */
66729775Ssam } else
66829775Ssam splitrand(p);
66926440Ssam }
67029775Ssam } else if (p->op==MOV && (p->forw->op==CVT || p->forw->op==MOVZ) &&
67129775Ssam p->forw->subop&0xf && /* if base or index, then forget it */
67229775Ssam compat(p->subop,p->forw->subop) && !indexa(cp1=regs[RT1]))
67329775Ssam goto movit;
67426440Ssam }
67526440Ssam /* adjust 'lastrand' past any 'read' or 'modify' operands. */
67626440Ssam lastrand=byondrd(p);
67726440Ssam /* a 'write' clobbers the register. */
67829775Ssam if (tempreg(lastrand,r) ||
67929775Ssam (has2ops(p) && tempreg(regs[RT2],r) && uses[r]==0)) {
68029775Ssam /*
68129775Ssam * Writing a dead register is useless,
68229775Ssam * but watch side effects
68329775Ssam */
68426440Ssam switch (p->op) {
68526440Ssam #ifndef EMOD
68626440Ssam case EDIV:
68726440Ssam #endif EMOD
68829775Ssam case AOBLEQ: case AOBLSS:
68929775Ssam break;
69026440Ssam default:
69129775Ssam /*
69229775Ssam * If no direct uses, check for
69329775Ssam * use of condition codes
69429775Ssam */
69526440Ssam if (uses[r]==0 && ((dblflg&1)==0 || uses[r+1]==0)) {
69629775Ssam register struct node *q = p;
69729775Ssam
69829775Ssam while ((q = nonlab(q->forw))->op==JBR &&
69929775Ssam q->subop==0)
70029775Ssam q=q->ref; /* cc unused, unchanged */
70129775Ssam if (q->op!=CBR && q->op!=ADDA && q->op!=SUBA) {
70229775Ssam /* ... and destroyed */
70326440Ssam preg=regs+RT1;
70429775Ssam while (cp1 = *preg++) {
70529775Ssam if (cp1==lastrand &&
70629775Ssam p->op != CLR &&
70729775Ssam p->op != CVFL) {
70829775Ssam redunm++;
70929775Ssam delnode(p);
71029775Ssam return(p->forw);
71129775Ssam }
71229775Ssam if (equstr(cp1,lastrand))
71329775Ssam break;
71426440Ssam }
71526440Ssam }
71626440Ssam }
71726440Ssam flow=r;
71826440Ssam }
71926440Ssam }
72029775Ssam if ((r=flow) >= 0) {
72129775Ssam olduse=uses[r], uses[r]=0;
72229775Ssam *(short *)(regs[r])=0;
72326440Ssam /* if r0 destroyed, dont keep r1 */
72429775Ssam if (dblflg&1) {
72529775Ssam olduse1=uses[++r], uses[r]=0;
72629775Ssam *(short *)(regs[r])=0;
72726440Ssam }
72826440Ssam }
72926440Ssam /* now look for 'read' or 'modify' (read & write) uses */
73026440Ssam preg=regs+RT1;
73126440Ssam while (*(cp1= *preg++)) {
73226440Ssam /* check for r */
73333301Sdonn if (lastrand!=cp1 && tempreg(cp1,r)) {
73433301Sdonn int isunused;
73533301Sdonn if (isunused=(uses[r]==0)) {
73633301Sdonn uses[r]=p;
73733301Sdonn cp2=regs[r]; *cp2++=p->subop;
73833301Sdonn if ((p->op==SHAL || p->op==SHAR ||
73933301Sdonn p->op==SHL || p->op==SHR) &&
74033301Sdonn cp1==regs[RT1])
74133301Sdonn cp2[-1] = BYTE;
74233301Sdonn if (p->op==CBR && (p->subop==JBC || p->subop==JBS))
74333301Sdonn cp2[-1] = LONG;
74433301Sdonn if (p->op==MOVA && cp1==regs[RT2])
74533301Sdonn cp2[-1]=LONG;
74633301Sdonn }
74726440Ssam /* ediv/emod's 2nd operand is quad */
74829775Ssam if (((p->op==EDIV
74926440Ssam #ifdef EMOD
75029775Ssam || p->op==EMOD
75126440Ssam #endif EMOD
75229775Ssam ) && cp1==regs[RT2] || (dblflg&2)) &&
75329775Ssam ++r<NUSE && uses[r]==0) {
75433301Sdonn if (isunused)
75533301Sdonn *cp2=0;
75629775Ssam uses[r]=p;
75729775Ssam cp2=regs[r]; *cp2++=p->subop;
75833301Sdonn if (!isunused)
75933301Sdonn *cp2=0;
76026440Ssam }
76133301Sdonn if (!isunused)
76233301Sdonn continue;
76329775Ssam if (p->op==MOV || p->op==PUSH || p->op==CVT ||
76429775Ssam p->op==MOVZ || p->op==COM || p->op==NEG ||
76529775Ssam p->op==STF) {
76629775Ssam if (p->op!=PUSH) {
76726440Ssam cp1=regs[RT2];
76829775Ssam if (tempreg(cp1,r)) {
76929775Ssam /*
77029775Ssam * reincarnation!!
77129775Ssam * (as in addl2 r0,r1;
77229775Ssam * movl r1,r0; ret)
77329775Ssam */
77429775Ssam if (uses[r]==0)
77526440Ssam uses[r]=olduse;
77629775Ssam if ((dblflg&1) && uses[r+1]==0)
77726440Ssam uses[r+1]=olduse1;
77826440Ssam }
77929775Ssam if (p->op!=MOV)
78029775Ssam cp1=0;
78129775Ssam } else
78229775Ssam cp1="-(sp)";
78329775Ssam if (cp1)
78429775Ssam while (*cp2++= *cp1++)
78529775Ssam ;
78629775Ssam else
78729775Ssam *cp2=0;
78829775Ssam } else
78929775Ssam *cp2=0;
79026440Ssam continue;
79126440Ssam }
79226440Ssam /* check for (r),[r] */
79329775Ssam do {
79429775Ssam if (*cp1=='(' || *cp1=='[') { /* get register number */
79529775Ssam char t;
79629775Ssam for (cp2= ++cp1; *++cp1!=')' && *cp1!=']';)
79729775Ssam ;
79829775Ssam t= *cp1; *cp1=0;
79929775Ssam if (tempreg(cp2,r) &&
80029775Ssam (uses[r]==0 || uses[r]==p)) {
80129775Ssam uses[r]=p;
80229775Ssam regs[r][0] =
80329775Ssam (*--cp2=='[' ? OPX<<4 : OPB<<4);
80434266Sdonn regs[r][1] = '\0';
80529775Ssam }
80629775Ssam *cp1=t;
80726440Ssam }
80826440Ssam } while (*++cp1);
80926440Ssam }
81026440Ssam #ifdef MOVAFASTER
81126440Ssam /* pushax or movax possibility? */
81226440Ssam cp1=regs[RT1];
81326440Ssam if (*cp1++=='$' && isstatic(cp1)) {
81426440Ssam if (p->op==MOV && p->subop==LONG) {
81526440Ssam if (regs[RT1][1]=='L' && 0!=(p->labno=getnum(regs[RT1]+2))) {
81626440Ssam cp1=p->code; while (*cp1++!=','); p->code= --cp1;
81726440Ssam }
81826440Ssam p->op = MOVA; p->subop = BYTE; ++p->code; p->pop=0;
81926440Ssam } else if (p->op==PUSH && p->subop==LONG) {
82026440Ssam p->op = PUSHA; p->subop = BYTE; ++p->code; p->pop=0;
82126440Ssam } else if (p->op==ADD && p->subop==U(LONG,OP3)
82226440Ssam && 0<=(r=isreg(regs[RT2]))) {
82326440Ssam cp1=cp2=p->code; ++cp1;
82426440Ssam do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]='[';
82526440Ssam do *cp2++= *cp1; while (*cp1++!=','); cp2[-1]=']';
82626440Ssam if (!equstr(regs[RT3],"-(sp)")){ p->op = MOVA; p->subop = BYTE;}
82726440Ssam else {p->op = PUSHA; p->subop = BYTE; *cp2=0;}
82826440Ssam if (uses[r]==0) {uses[r]=p; regs[r][0]=OPX<<4;}
82926440Ssam p->pop=0;
83026440Ssam }
83126440Ssam }
83226440Ssam #endif MOVAFASTER
83329775Ssam return (p);
83426440Ssam }
83526440Ssam
83626440Ssam /* try to eliminate STF's */
83726440Ssam struct node *
flops(q)83826440Ssam flops(q)
83926440Ssam register struct node *q;
84026440Ssam {
84126440Ssam register struct node *p;
84226440Ssam register int r;
84326440Ssam
84429775Ssam if(q->op!=STF || !tempreg(q->code,r))
84526440Ssam return(q);
84626440Ssam if(uses[r]) {
84726440Ssam /* see if anyone destroys acc between us */
84826440Ssam for(p=q->forw; p!=uses[r]; p=p->forw)
84926440Ssam switch(p->op) {
85026440Ssam case LABEL:
85126440Ssam case LDF: case LNF: case CVLF: case LDFD:
85226440Ssam case CVDF: case NEGF: case ADDF: case SUBF:
85326440Ssam case MULF: case DIVF: case SINF: case COSF:
85426440Ssam case ATANF: case LOGF: case SQRTF: case EXPF:
85526440Ssam return(q);
85626440Ssam }
85734266Sdonn again:
85826440Ssam if(q->subop == p->subop)
85926440Ssam switch(p->op) { /* do it in the accumulator */
86026440Ssam case LDF: /* redundant load */
86126440Ssam delnode(p); nld++;
86226440Ssam p = p->forw;
86326440Ssam break;
86426440Ssam case LNF: /* stf r; lnf r ==> negf */
86526440Ssam p->op = NEGF;
86626440Ssam p->pop = 0;
86726440Ssam p->code = 0;
86826440Ssam break;
86926440Ssam case CMPF2: /* stf r; cmpf2 r,x ==> cmpf x */
87026440Ssam { register char *s;
87126440Ssam register struct node *p1=p->forw;
87226440Ssam for(s=p->code; *s!=','; s++);
87326440Ssam *s = 0;
87426440Ssam if(isreg(p->code) == r)
87526440Ssam p->code = s+1;
87626440Ssam else {
87726440Ssam if(p1->op != CBR || isreg(s+1) != r) {
87826440Ssam *s = ',';
87926440Ssam return(q);
88026440Ssam }
88126440Ssam if(p1->subop > JNE) {
88226440Ssam p1->subop ^= 1;
88326440Ssam p1->pop = 0;
88426440Ssam nrevbr++;
88526440Ssam }
88626440Ssam }
88726440Ssam p->op = CMPF;
88826440Ssam p->pop = 0;
88926440Ssam }
89026440Ssam break;
89126440Ssam default:
89226440Ssam return(q);
89326440Ssam }
89426440Ssam else if(p->subop==LONG) {
89526440Ssam switch(p->op) {
89626440Ssam case TST: /* stf r; tstl r ==> tstf */
89726440Ssam p->op = TSTF;
89826440Ssam p->code = 0;
89926440Ssam break;
90026440Ssam /* send directly to destination */
90126440Ssam case MOV: /* stf r; movl r,x ==> stf x */
90226440Ssam case PUSH: /* stf r; pushl r ==> stf -(sp)/pushd */
90326440Ssam if(q->subop == DOUBLE) {
90426440Ssam register struct node *b = p->back;
90526440Ssam /* assume b's 2nd arg is ok */
90626440Ssam if(!(b==uses[r+1] && b->op==p->op && b->subop==LONG))
90726440Ssam return(q);
90826440Ssam delnode(b); redunm++;
90926440Ssam }
91026440Ssam if(p->op==PUSH) {
91126440Ssam if(q->subop == DOUBLE) {
91226440Ssam p->op = PUSHD;
91326440Ssam p->code = 0;
91426440Ssam } else {
91526440Ssam p->op = q->op;
91626440Ssam p->code = copy("-(sp)");
91726440Ssam }
91826440Ssam } else {
91926440Ssam p->op = q->op;
92026440Ssam while(*p->code++ != ',');
92126440Ssam }
92226440Ssam break;
92326440Ssam default:
92426440Ssam return(q);
92526440Ssam }
92626440Ssam p->pop = 0;
92726440Ssam p->subop = q->subop;
92826440Ssam } else
92926440Ssam return(q);
93026440Ssam uses[r] = 0;
93126440Ssam if(q->subop == DOUBLE)
93226440Ssam uses[r+1] = 0;
93334266Sdonn for(p = p->back; p != q && (!uses[r] || !uses[r+1]); p = p->back) {
93434266Sdonn int xr;
93534266Sdonn
93634266Sdonn splitrand(p);
93734266Sdonn if((xr=isreg(regs[RT1])) < 0)
93834266Sdonn continue;
93934266Sdonn if(!uses[r] && xr == r)
94034266Sdonn uses[r] = p;
94134266Sdonn else if(q->subop == DOUBLE && !uses[r+1] && xr == r+1)
94234266Sdonn uses[r+1] = p;
94334266Sdonn }
94434266Sdonn if(p = uses[r])
94534266Sdonn goto again;
94633615Sdonn return(q->forw); /* DON'T re-scan code with dated uses[] */
94726440Ssam }
94826440Ssam /* it's a store to reg which isnt used elsewhere */
94926440Ssam if((p=q->forw)->op == CBR) {
95026440Ssam q->op = TSTF;
95126440Ssam q->pop = 0;
95226440Ssam q->code = 0;
95326440Ssam } else {
95426440Ssam delnode(q); nst++;
95526440Ssam if(p->op ==STF || p->op==TSTF || p->op==PUSHD) {
95626440Ssam if(useacc == p)
95726440Ssam useacc = 0;
95826440Ssam return(p->forw); /* so ldmov can be used on p */
95926440Ssam }
96026440Ssam }
96126440Ssam return(p);
96226440Ssam }
96326440Ssam
96426440Ssam /* try to change load/store sequences to movl */
ldmov(q)96526440Ssam ldmov(q)
96626440Ssam register struct node *q;
96726440Ssam {
96826440Ssam register struct node *p;
96926440Ssam register char *s, *pcod, *cp;
97026440Ssam char *dlsw();
97126440Ssam
97226440Ssam p = q->back;
97326440Ssam if(!(useacc==0 && (q->op==STF || q->op==TSTF || q->op==PUSHD)
97426440Ssam && ((p->op==LDF && p->subop==q->subop) || (p->op==LDFD && q->subop==DOUBLE))))
97526440Ssam return(0);
97626440Ssam pcod = p->code;
97726440Ssam cp = p->code;
97826440Ssam /* prepare args for movl/pushl */
97926440Ssam if(q->op!=TSTF && q->subop==DOUBLE) {
98026440Ssam if(p->op == LDF) {
98126440Ssam if((s = dlsw(p->code)) == NULL)
98226440Ssam return(0);
98329670Ssam
98426440Ssam strcpy(line, s);
98526440Ssam if(q->op == STF) {
98626440Ssam strcat(line, ",");
98726440Ssam if((s = dlsw(q->code)) == NULL)
98826440Ssam return(0);
98926440Ssam strcat(line, s);
99026440Ssam p->op = MOV;
99126440Ssam } else
99226440Ssam p->op = PUSH;
99326440Ssam } else { /* LDFD */
99426440Ssam if(q->op == STF) {
99526440Ssam if((s = dlsw(q->code)) == NULL)
99626440Ssam return(0);
99726440Ssam } else
99826440Ssam s = "-(sp)";
99926440Ssam strcpy(line, s);
100026440Ssam p->op = CLR;
100126440Ssam }
100226440Ssam p->pop = 0;
100326440Ssam p->subop = LONG;
100426440Ssam p->code = copy(line);
100526440Ssam } else
100626440Ssam {
100726440Ssam if ((p->op == LDF) && (p->subop == DOUBLE) &&
100826440Ssam (indexa(cp))) return(0);
100926440Ssam delnode(p);
101026440Ssam }
101126440Ssam strcpy(line, pcod);
101226440Ssam if(q->op == STF) { /* ldf x; stf y ==> movl x,y */
101326440Ssam strcat(line, ",");
101426440Ssam strcat(line, q->code);
101526440Ssam q->op = MOV;
101626440Ssam nst++;
101726440Ssam } else if(q->op == TSTF) /* ldf x; tstf ==> tstl x */
101826440Ssam q->op = TST;
101926440Ssam else /* ldd x; pushd ==> pushl x+4; pushl x */
102026440Ssam q->op = PUSH;
102126440Ssam q->pop = 0;
102226440Ssam q->subop = LONG;
102326440Ssam q->code = copy(line);
102426440Ssam nld++;
102526440Ssam return(1);
102626440Ssam }
102726440Ssam
102826440Ssam /* reconstruct the address of l.s.w. of a double operand */
102926440Ssam char *
dlsw(d)103026440Ssam dlsw(d)
103126440Ssam register char *d;
103226440Ssam {
103329670Ssam register char *s, *t, *c;
103426440Ssam register int r;
103526440Ssam static char lsw[C2_ASIZE];
103626440Ssam
103726440Ssam if(d[0] == '*' || d[0] == '$')
103826440Ssam return(NULL);
103929670Ssam if (((strncmp(d, "(r", 2)) == 0) && isdigit(d[2]))
104029670Ssam return(NULL);
104126440Ssam t = lsw;
104226440Ssam if((r=isreg(d)) >= 0)
104326440Ssam sprintf(t, "r%d", r+1);
104426440Ssam else {
104526440Ssam for(s=d; *s && *s!='('; *t++ = *s++)
104626440Ssam if(*s == '[')
104726440Ssam return(NULL);
104829670Ssam if(s!=d)
104929670Ssam *t++ = '+';
105029670Ssam *t++ = '4';
105126440Ssam while(*t++ = *s)
105229670Ssam if(*s++ == '[' )
105329670Ssam {
105426440Ssam return(NULL);
105529670Ssam }
105626440Ssam }
105726440Ssam return(lsw);
105826440Ssam }
checkexpr(p)105929670Ssam checkexpr(p)
106029670Ssam register char *p;
106129670Ssam {
106229670Ssam
106329670Ssam while(*p && *p != ','){
106429670Ssam if ((*p == '+' ) || (*p == '-'))
106529670Ssam return(1);
106629670Ssam *p++;
106729670Ssam }
106829670Ssam return(0);
106929670Ssam }
1070