static char sccsid
[] = "@(#)c21.c 1.1 (Berkeley) %G%";
* C object code improver-- second part
int bitsize
[] = {0,8,16,32,64,32,64}; /* index by type codes */
redun3(p
) register struct node
*p
; {
/* check for 3 addr instr which should be 2 addr */
if (OP3
==((p
->subop
>>4)&0xF)) {
if (equstr(regs
[RT1
],regs
[RT3
])
&& (p
->op
==ADD
|| p
->op
==MUL
|| p
->op
==AND
|| p
->op
==OR
|| p
->op
==XOR
)) {
register char *t
=regs
[RT1
]; regs
[RT1
]=regs
[RT2
]; regs
[RT2
]=t
;
if (equstr(regs
[RT2
],regs
[RT3
])) {
p
->subop
=(p
->subop
&0xF)|(OP2
<<4); p
->pop
=0;
lastrand
=regs
[RT2
]; *regs
[RT3
]=0; return(1);
register struct node
*p
, *lastp
; register char *cp1
,*cp2
; register int r
;
for (p
=lastp
= &first
; 0!=(p
=p
->forw
); lastp
=p
);
for (p
=lastp
; p
!= &first
; p
=p
->back
) {
printf("acc: %s\n",useacc
->code
? useacc
->code
:"");
for (r
=NUSE
;--r
>=0;) if (uses
[r
])
printf("%d: %s\n",r
,uses
[r
]->code
? uses
[r
]->code
:"");
if (OP3
==r
&& 0!=redun3(p
)) {newcode(p
); redunm
++;}
/* ops that do nothing */
if(p
->op
==MOV
&& equstr(regs
[RT1
], regs
[RT2
]))
delnode(p
); redunm
++; continue;
while(*p
->code
++ != ',');
else if((cp1
=p
->code
, *cp1
++)=='$' &&
(*cp1
=='0' || *cp1
=='1' || *cp1
++=='-' && *cp1
=='1') && cp1
[1]==',') {
switch((p
->code
[1]<<8)|p
->op
) {
delnode(p
); redunm
++; continue;
p
->op
=TST
; p
->subop
&=0xF; p
->pop
=0;
while(*p
->code
++ != ',');
} else { /* OP3 or shift */
p
->op
=MOV
; p
->subop
&=0xF; p
->pop
=0;
while(*p
->code
++ != ',');
p
= p
->forw
; redunm
++; continue;
p
->op
=CLR
; p
->subop
&=0xF; p
->pop
=0;
while(*p
->code
++ != ',');
while(*p
->code
++ != ',');
if (uses
[r
]) p
->ref
=(struct node
*) (((int)p
->ref
)|(1<<r
));
if (useacc
) p
->ref
=(struct node
*) (((int)p
->ref
)|(1<<NUSE
));
if ((p
->subop
&0xF)!=LONG
) goto std
; cp1
=p
->code
;
if (*cp1
++!='$') goto std
; splitrand(p
);
n
= getnum(®s
[RT1
][1]);
if(r
==BYTE
&& (n
<-128 || n
>127)) goto std
;
if(r
==WORD
&& (n
<-32768 || n
>32767)) goto std
;
p
->op
= MOV
; p
->subop
= r
; p
->pop
= 0;
if ((p
->subop
&0xF)!=LONG
) goto std
; cp1
=p
->code
;
if (*cp1
++!='$') goto std
; splitrand(p
);
if (equstr(regs
[RT2
],"fp") && !indexa(regs
[RT1
])) {/* address comp. */
char buf
[C2_ASIZE
]; cp2
=buf
; *cp2
++='-';
cp1
=regs
[RT1
]+1; while (*cp2
++= *cp1
++); --cp2
;
cp1
="(fp),"; while (*cp2
++= *cp1
++); --cp2
;
cp1
=regs
[RT3
]; while (*cp2
++= *cp1
++);
p
->code
=copy(buf
); p
->op
= MOVA
; p
->subop
= BYTE
; p
->pop
=0;
if (*cp1
++=='-' && 0<=(r
=getnum(cp1
))) {
p
->op
=ADD
; p
->pop
=0; *--cp1
='$'; p
->code
=cp1
;
if ((p
->subop
&0xF)!=LONG
) goto std
; cp1
=p
->code
;
if (*cp1
++!='$') goto std
; splitrand(p
);
if (isstatic(cp1
) && (r
=isreg(regs
[RT2
]))>=0 && r
<NUSE
&& uses
[r
]==p
->forw
)
** addl2 $_foo,r0 \ movab _foo[r0],bar
register struct node
*pnext
= p
->forw
;
if (pnext
->op
== MOV
&& pnext
->subop
== LONG
)
cp1
= ®s
[RT1
][1]; cp2
= &buf
[0];
while (*cp2
++ = *cp1
++) ; cp2
--;
if (r
== isreg(regs
[RT1
]))
p
->op
= MOVA
; p
->subop
= BYTE
;
cp1
= regs
[RT1
]; *cp2
++ = '[';
while (*cp2
++ = *cp1
++) ; cp2
--;
*cp2
++ = ']'; *cp2
++ = ',';
while (*cp2
++ = *cp1
++) ;
if (equstr(regs
[RT2
],"fp") && !indexa(regs
[RT1
])) {/* address comp. */
cp2
=cp1
-1; cp1
=regs
[RT1
]+1; while (*cp2
++= *cp1
++); --cp2
;
cp1
="(fp)"; while (*cp2
++= *cp1
++); *--cp2
=',';
p
->op
= MOVA
; p
->subop
= BYTE
; p
->pop
=0;
if (*cp1
++=='-' && 0<=(r
=getnum(cp1
))) {
p
->op
=SUB
; p
->pop
=0; *--cp1
='$'; p
->code
=cp1
;
** by constant powers of 2 to shifts.
if (regs
[RT1
][0] != '$' || regs
[RT1
][1] == '-') goto std
;
if ((r
= ispow2(getnum(®s
[RT1
][1]))) <= 0) goto std
;
if(r
== 1 && p
->subop
== U(LONG
, OP2
)) {
strcpy(regs
[RT1
], regs
[RT2
]);
p
->op
= ADD
; p
->pop
= 0; newcode(p
);
if (p
->subop
== U(LONG
,OP2
))
strcpy(regs
[RT3
], regs
[RT2
]);
sprintf(regs
[RT1
], "$%d", r
);
p
->op
= SHL
; p
->subop
= LONG
;
** shll $1,bar,r0 \ movl bar,r0
** movab _foo[r0] / movaw _foo[r0]
** shll $2,r0,r0 \ moval _foo[r0]
register struct node
*pf
;
register struct node
*pn
;
register int shfrom
, shto
;
if (regs
[RT1
][0] != '$') {
if(isreg(regs
[RT1
]) < 0) goto std
; /* alignment */
if (regs
[RT2
][0] != '$') goto std
;
if (getnum(®s
[RT2
][1]) != 1) goto std
;
if (r
< 0 || r
>= NUSE
) goto std
;
if ((pf
= p
->forw
)->op
!= BIT
&& pf
->op
!=AND
) goto std
;
if (uses
[r
] && uses
[r
] != pf
) goto std
;
if (r
== isreg(regs
[RT1
])) cp2
= regs
[RT2
];
else if (r
== isreg(regs
[RT2
])) cp2
= regs
[RT1
];
if (*cp2
== '$') goto std
;
if ((pn
= pf
->forw
)->op
!= CBR
) goto std
;
if (pn
->subop
!= JEQ
&& pn
->subop
!= JNE
) goto std
;
pn
->subop
= (pn
->subop
== JEQ
) ? JBC
: JBS
;
for(cp1
=p
->code
; *cp1
++!=',';);
pn
->code
= p
->code
; pn
->pop
= NULL
;
if ((shcnt
= getnum(®s
[RT1
][1])) < 1 || shcnt
> 2) goto std
;
if ((shfrom
= isreg(regs
[RT2
])) >= 0)
regfrom
= copy(regs
[RT2
]);
if ((shto
= isreg(regs
[RT3
])) >= 0 && shto
<NUSE
)
if (uses
[shto
] != (pf
= p
->forw
)) goto ashadd
;
if (pf
->op
!= MOVA
&& pf
->op
!= PUSHA
) goto ashadd
;
if (pf
->subop
!= BYTE
) goto ashadd
;
if (!indexa(regs
[RT1
])) goto std
;
if(!isstatic(cp2
)) goto std
;
if (*cp2
++ != 'r' || !isdigit(*cp2
)) goto std
;
if (cp2
[1] != ']') goto std
;
regnum
*= 10; regnum
+= *cp2
- '0';
if (regnum
!= shto
) goto std
;
if (shfrom
>= 0) /* shll $N,r*,r0 */
uses
[shto
] = NULL
; splitrand(pf
);
cp2
=regs
[RT1
]; while (*cp2
++!='[');
cp1
=regfrom
; while (*cp2
++= *cp1
++);
p
->op
= MOV
; splitrand(p
);
strcpy(regs
[RT1
], regs
[RT2
]);
strcpy(regs
[RT2
], regs
[RT3
]);
case 1: pf
->subop
= WORD
; break;
case 2: pf
->subop
= LONG
; break;
/* at this point, RT2 and RT3 are guaranteed to be simple regs*/
** shll $1,A,A > addl2 A,A
** shll $1,A,B > addl3 A,A,B
strcpy(regs
[RT1
], regs
[RT2
]);
if(equstr(regs
[RT2
], regs
[RT3
])) {
** bitl $1,rC > jbc A,B,D
register struct node
*pf
; /* forward node */
register struct node
*pn
; /* next node (after pf) */
register int extreg
; /* reg extracted to */
if(isreg(regs
[RT1
]) < 0) goto std
; /* alignment */
extreg
= isreg(regs
[RT3
]);
if (extreg
< 0 || extreg
>= NUSE
) goto std
;
if ((pf
= p
->forw
)->op
!= BIT
) goto std
;
if (uses
[extreg
] && uses
[extreg
] != pf
) goto std
;
if (regs
[RT1
][0] != '$') goto std
;
if (getnum(®s
[RT1
][1]) != 1) goto std
;
if (extreg
!= isreg(regs
[RT2
])) goto std
;
if ((pn
= pf
->forw
)->op
!= CBR
) goto std
;
if (pn
->subop
!= JEQ
&& pn
->subop
!= JNE
) goto std
;
pn
->subop
= (pn
->subop
== JEQ
) ? JBC
: JBS
;
for(cp1
=p
->code
; *cp1
++!=',';);
while (*cp1
!=',') cp1
++; *cp1
='\0';
pn
->code
= p
->code
; pn
->pop
= NULL
;
uses
[extreg
] = NULL
; nbj
++;
** cvtbl A,B; andl2 $255,B > movzbl A,B
** also byte- and word-size fields:
** shrl $(3-n)*8,A,B; andl2 $255,B > movzbl n+A,B
** shrl $(1-n)*16,A,B; andl2 $65535,B > movzwl n+A,B
register int f
; /* field length */
register struct node
*pb
= p
->back
; /* backward node */
if (p
->subop
!= U(LONG
,OP2
))
splitrand(p
); cp1
=regs
[RT1
];
if (*cp1
++!='$' || (f
=getnum(cp1
))!=0xff && f
!=0xffff)
if (pb
->op
!=CVT
&& pb
->op
!=MOVZ
&& pb
->op
!=SHAR
&& pb
->op
!=SHR
)
/* save source of ANDL in 'src' */
if (!equstr(src
,lastrand
))
if (pb
->op
==CVT
|| pb
->op
==MOVZ
) {
if (!(bitsize
[pb
->subop
&0xF]==f
&& bitsize
[pb
->subop
>>4]>=f
)) /* good CVT */
register int boff
; /* bit offset */
if (regs
[RT1
][0] != '$') goto std
;
if ((boff
= getnum(®s
[RT1
][1])) < 0) goto std
;
if (isreg(regs
[RT2
])>=0 || !natural(regs
[RT2
])) goto std
;
if ((boff
& (f
-1)) != 0) goto std
;
sprintf(src
, "%d%s%s", boff
, regs
[RT2
][0]=='(' ? "":"+",
p
->subop
= U((f
==8 ? BYTE
: WORD
), LONG
);
sprintf(line
,"%s,%s",src
,lastrand
);
/* comparison to -63 to -1:
** cmpl r0,$-63 > addl2 $63,r0
register struct node
*regp
= p
->back
;
if (p
->forw
->op
!= CBR
) goto std
;
if (p
->forw
->subop
!= JEQ
&& p
->forw
->subop
!= JNE
) goto std
;
if (strncmp(regs
[RT2
], "$-", 2) != 0) goto std
;
reg
= r
= isreg(regs
[RT1
]);
if (r
< NUSE
&& uses
[r
] != 0) goto std
;
if (r
>= NUSE
&& regp
->op
== MOV
&& p
->subop
== regp
->subop
)
if (*regp
->code
!= 'r') goto std
;
reg
= regp
->code
[1] - '0';
if (isdigit(regp
->code
[2]) || reg
>= NUSE
|| uses
[reg
])
sprintf(regs
[RT1
], "r%d", reg
);
if ((num
= getnum(®s
[RT2
][2])) <= 0 || num
> 63) goto std
;
p
->op
= INC
; regs
[RT2
][0] = '\0';
t
=regs
[RT1
];regs
[RT1
]=regs
[RT2
];regs
[RT2
]=t
;
p
->op
= ADD
; p
->subop
= U(p
->subop
, OP2
);
for (t
= ®s
[RT1
][2]; t
[-1] = *t
; t
++) ;
if ((p
->subop
&0xF)==RET
) {
switch((p
->subop
>>4)&0xF) {
case 2: uses
[1]=p
; regs
[1][0]= -1;
case 1: uses
[0]=p
; regs
[0][0]= -1;
if (p
->ref
==0) goto std
; /* jmp (r0) */
if ((1<<r
) & (int)p
->ref
->ref
) {uses
[r
]=p
; regs
[r
][0]= -1;}
if ((1<<NUSE
) & (int)p
->ref
->ref
) useacc
=p
;
/* lnf a; addf b ==> ldf b; subf a */
{ register struct node
*pf
= p
->forw
;
if(pf
->op
==ADDF
&& p
->subop
==pf
->subop
) {
case LDF
: case LDFD
: case CVLF
: /* destroy acc */
{ register struct node
*pf
;
p
= pf
; /* usually p->forw; */
case ADDF
: case MULF
: /* commutatives - create clients for flops */
/* stf a; ldf b; addf a => stf a; ldf a; addf b */
{ register struct node
*pb
= p
->back
;
register struct node
*pbb
= pb
->back
;
if(pb
->op
==LDF
&& pb
->subop
==p
->subop
&&
pbb
&& pbb
->op
==STF
&& pbb
->subop
==p
->subop
&&
equstr(pbb
->code
, p
->code
)) {
case CMPF
: case CVFL
: case SUBF
: case DIVF
:
case CVDF
: case NEGF
: /* use only acc */
case SINF
: case COSF
: case ATANF
: case LOGF
: case SQRTF
: case EXPF
:
case TEXT
: case DATA
: case BSS
: case ALIGN
: case WGEN
: case END
: ;
for (p
= &first
; p
!=0; p
=p
->forw
)
if (p
->op
==LABEL
|| p
->op
==DLABEL
) p
->ref
=0; /* erase our tracks */
byondrd(p
) register struct node
*p
; {
/* return pointer to register which is "beyond last read/modify operand" */
if (OP2
==(p
->subop
>>4)) return(regs
[RT3
]);
case TST
: case INC
: case DEC
: case PUSH
:
case LDF
: case LNF
: case CVLF
: case LDFD
:
case ADDF
: case SUBF
: case MULF
: case DIVF
:
case CBR
: /* must be JBC/JBS */
case BIT
: case CMP
: case CALLS
: case CALLF
:
register char *cp1
,*cp2
,**preg
;
register int r
, fr
, dblflg
=0;
struct node
*olduse
=0, *olduse1
=0;
if(p
->subop
==QUAD
|| p
->subop
==DOUBLE
|| (p
->subop
&0xF0)==DOUBLE
<<4)
dblflg
|= 1; /* double dest */
if((p
->subop
&0xF)==DOUBLE
|| p
->subop
==QUAD
)
dblflg
|= 2; /* double src */
&& p
->subop
&& 0<=(r
=isreg(lastrand
)) && r
<NUSE
&& uses
[r
]==p
->forw
) {
if (equtype(p
->subop
,regs
[r
][0])
|| ((p
->op
==CVT
|| p
->op
==MOVZ
|| p
->op
==CVFL
)
&& 0xf®s
[r
][0] && compat(0xf&(p
->subop
>>4),regs
[r
][0]))
|| p
->op
==MOVA
&& compat(LONG
, regs
[r
][0])) {
if (regs
[r
][1]!=0) {/* send directly to destination */
if (p
->op
==INC
|| p
->op
==DEC
) {
if (p
->op
==DEC
) p
->op
=SUB
; else p
->op
=ADD
;
p
->subop
=(OP2
<<4)+(p
->subop
&0xF); /* use 2 now, convert to 3 later */
cp1
=lastrand
; cp2
=regs
[RT2
]; while (*cp2
++= *cp1
++); /* copy reg */
cp1
=lastrand
; *cp1
++='$'; *cp1
++='1'; *cp1
=0;
cp1
=regs
[r
]+1; cp2
=lastrand
;
if (OP2
==(p
->subop
>>4)) {/* use 3 operand form of instruction */
p
->subop
+= (OP3
-OP2
)<<4; lastrand
=cp2
=regs
[RT3
];
if (p
->op
==MOVA
&& p
->forw
->op
==PUSH
) {
} else if ((p
->op
==MOV
|| p
->op
==CVT
) && p
->forw
->op
==PUSH
) {
p
->op
=PUSH
; p
->subop
&= 0xF;
if (0<=(r2
=isreg(lastrand
)) && r2
<NUSE
) {
uses
[r2
]=uses
[r
]; uses
[r
]=0;
newcode(p
); redunm
++; flow
=r
;
cp2
=src
; cp1
=regs
[RT1
]; while (*cp2
++= *cp1
++);
if (p
->forw
->op
!= INC
&& p
->forw
->op
!= DEC
)
lastrand
=byondrd(p
->forw
);
for (preg
=regs
+RT1
;*preg
!=lastrand
;preg
++)
cp2
= *preg
; cp1
=src
; while (*cp2
++= *cp1
++); ++nmatch
;
if (OP2
==(p
->forw
->subop
>>4) && equstr(src
,regs
[RT2
])) {
p
->forw
->subop
+= (OP3
-OP2
)<<4; cp1
=regs
[RT3
];
*cp1
++='r'; *cp1
++=r
+'0'; *cp1
=0;
if (0<=(r2
=isreg(src
)) && r2
<NUSE
) {
uses
[r2
]=uses
[r
]; uses
[r
]=0;
newcode(p
); redunm
++; flow
=r
;
} else if (p
->op
==MOV
&& (p
->forw
->op
==CVT
|| p
->forw
->op
==MOVZ
)
&& p
->forw
->subop
&0xf /* if base or index, then forget it */
&& compat(p
->subop
,p
->forw
->subop
) && !indexa(cp1
=regs
[RT1
]))
/* adjust 'lastrand' past any 'read' or 'modify' operands. */
/* a 'write' clobbers the register. */
if (0<=(r
=isreg(lastrand
)) && r
<NUSE
|| OP2
==(p
->subop
>>4) && 0<=(r
=isreg(regs
[RT2
])) && r
<NUSE
&& uses
[r
]==0) {
/* writing a dead register is useless, but watch side effects */
case AOBLEQ
: case AOBLSS
: break;
if (uses
[r
]==0 && ((dblflg
&1)==0 || uses
[r
+1]==0)) {
/* no direct uses, check for use of condition codes */
register struct node
*q
=p
;
while ((q
=nonlab(q
->forw
))->op
==JBR
&& q
->subop
==0) q
=q
->ref
; /* cc unused, unchanged */
if (q
->op
!=CBR
&& q
->op
!=ADDA
&& q
->op
!=SUBA
) {/* ... and destroyed */
{redunm
++; delnode(p
); return(p
->forw
);}
if (equstr(cp1
,lastrand
)) break;
olduse
=uses
[r
]; uses
[r
]=0; *(short *)(regs
[r
])=0;
/* if r0 destroyed, dont keep r1 */
olduse1
=uses
[++r
]; uses
[r
]=0; *(short *)(regs
[r
])=0;
/* now look for 'read' or 'modify' (read & write) uses */
while (*(cp1
= *preg
++)) {
if (lastrand
!=cp1
&& 0<=(r
=isreg(cp1
)) && r
<NUSE
&& (uses
[r
]==0)){
uses
[r
]=p
; cp2
=regs
[r
]; *cp2
++=p
->subop
;
if((p
->op
==SHAL
|| p
->op
==SHAR
|| p
->op
==SHL
|| p
->op
==SHR
)
&& cp1
==regs
[RT1
]) cp2
[-1]=BYTE
;
if(p
->op
==CBR
&& (p
->subop
==JBC
|| p
->subop
==JBS
)) cp2
[-1]=LONG
;
if(p
->op
==MOVA
&& cp1
==regs
[RT2
]) cp2
[-1]=LONG
;
/* ediv/emod's 2nd operand is quad */
) && cp1
==regs
[RT2
] || (dblflg
&2))
&& ++r
<NUSE
&& uses
[r
]==0) {
uses
[r
]=p
; cp2
=regs
[r
]; *cp2
++=p
->subop
;
if(p
->op
==MOV
|| p
->op
==PUSH
|| p
->op
==CVT
||
p
->op
==MOVZ
|| p
->op
==COM
|| p
->op
==NEG
|| p
->op
==STF
) {
if (p
->op
==PUSH
) cp1
="-(sp)";
if (0<=(r
=isreg(cp1
)) && r
<NUSE
) {
/* as in addl2 r0,r1; movl r1,r0; ret */
if((dblflg
&1) && uses
[r
+1]==0)
if (cp1
) while (*cp2
++= *cp1
++);
do if (*cp1
=='(' || *cp1
=='[') {/* get register number */
cp2
= ++cp1
; while (*++cp1
!=')' && *cp1
!=']'); t
= *cp1
; *cp1
=0;
if (0<=(r
=isreg(cp2
)) && r
<NUSE
&& (uses
[r
]==0 || uses
[r
]==p
)) {
uses
[r
]=p
; regs
[r
][0]=(*--cp2
=='[' ? OPX
<<4 : OPB
<<4);
/* pushax or movax possibility? */
if (*cp1
++=='$' && isstatic(cp1
)) {
if (p
->op
==MOV
&& p
->subop
==LONG
) {
if (regs
[RT1
][1]=='L' && 0!=(p
->labno
=getnum(regs
[RT1
]+2))) {
cp1
=p
->code
; while (*cp1
++!=','); p
->code
= --cp1
;
p
->op
= MOVA
; p
->subop
= BYTE
; ++p
->code
; p
->pop
=0;
} else if (p
->op
==PUSH
&& p
->subop
==LONG
) {
p
->op
= PUSHA
; p
->subop
= BYTE
; ++p
->code
; p
->pop
=0;
} else if (p
->op
==ADD
&& p
->subop
==U(LONG
,OP3
)
&& 0<=(r
=isreg(regs
[RT2
]))) {
do *cp2
++= *cp1
; while (*cp1
++!=','); cp2
[-1]='[';
do *cp2
++= *cp1
; while (*cp1
++!=','); cp2
[-1]=']';
if (!equstr(regs
[RT3
],"-(sp)")){ p
->op
= MOVA
; p
->subop
= BYTE
;}
else {p
->op
= PUSHA
; p
->subop
= BYTE
; *cp2
=0;}
if (uses
[r
]==0) {uses
[r
]=p
; regs
[r
][0]=OPX
<<4;}
/* try to eliminate STF's */
if(!(q
->op
==STF
&& ((r
=isreg(q
->code
))<NUSE
) && r
>=0))
/* see if anyone destroys acc between us */
for(p
=q
->forw
; p
!=uses
[r
]; p
=p
->forw
)
case LDF
: case LNF
: case CVLF
: case LDFD
:
case CVDF
: case NEGF
: case ADDF
: case SUBF
:
case MULF
: case DIVF
: case SINF
: case COSF
:
case ATANF
: case LOGF
: case SQRTF
: case EXPF
:
switch(p
->op
) { /* do it in the accumulator */
case LDF
: /* redundant load */
case LNF
: /* stf r; lnf r ==> negf */
case CMPF2
: /* stf r; cmpf2 r,x ==> cmpf x */
register struct node
*p1
=p
->forw
;
for(s
=p
->code
; *s
!=','; s
++);
if(p1
->op
!= CBR
|| isreg(s
+1) != r
) {
else if(p
->subop
==LONG
) {
case TST
: /* stf r; tstl r ==> tstf */
/* send directly to destination */
case MOV
: /* stf r; movl r,x ==> stf x */
case PUSH
: /* stf r; pushl r ==> stf -(sp)/pushd */
register struct node
*b
= p
->back
;
/* assume b's 2nd arg is ok */
if(!(b
==uses
[r
+1] && b
->op
==p
->op
&& b
->subop
==LONG
))
while(*p
->code
++ != ',');
{ /* undo any effect on uses in the area between p and q,
* as we are going over it again */
for(b
=p
; b
!=q
; b
=b
->back
) {
return(p
->forw
); /* make p the next for bflow */
/* it's a store to reg which isnt used elsewhere */
if((p
=q
->forw
)->op
== CBR
) {
if(p
->op
==STF
|| p
->op
==TSTF
|| p
->op
==PUSHD
) {
return(p
->forw
); /* so ldmov can be used on p */
/* try to change load/store sequences to movl */
register char *s
, *pcod
, *cp
;
if(!(useacc
==0 && (q
->op
==STF
|| q
->op
==TSTF
|| q
->op
==PUSHD
)
&& ((p
->op
==LDF
&& p
->subop
==q
->subop
) || (p
->op
==LDFD
&& q
->subop
==DOUBLE
))))
/* prepare args for movl/pushl */
if(q
->op
!=TSTF
&& q
->subop
==DOUBLE
) {
if((s
= dlsw(p
->code
)) == NULL
)
if((s
= dlsw(q
->code
)) == NULL
)
if((s
= dlsw(q
->code
)) == NULL
)
if ((p
->op
== LDF
) && (p
->subop
== DOUBLE
) &&
if(q
->op
== STF
) { /* ldf x; stf y ==> movl x,y */
} else if(q
->op
== TSTF
) /* ldf x; tstf ==> tstl x */
else /* ldd x; pushd ==> pushl x+4; pushl x */
/* reconstruct the address of l.s.w. of a double operand */
static char lsw
[C2_ASIZE
];
if(d
[0] == '*' || d
[0] == '$')
for(s
=d
; *s
&& *s
!='('; *t
++ = *s
++)