static char sccsid
[] = "@(#)c21.c 1.9 (Berkeley/CCI) 5/12/88";
* 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 (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)|ord(p
->op
)) {
case (('0'<<8)|ord(ADD
)):
case (('0'<<8)|ord(SUB
)):
case (('-'<<8)|ord(AND
)):
case (('0'<<8)|ord(XOR
)):
case (('1'<<8)|ord(MUL
)):
case (('1'<<8)|ord(DIV
)):
case (('0'<<8)|ord(SHAL
)):
case (('0'<<8)|ord(SHAR
)):
case (('0'<<8)|ord(SHL
)):
case (('0'<<8)|ord(SHR
)):
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;
case (('0'<<8)|ord(MUL
)):
case (('0'<<8)|ord(AND
)):
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
) && tempreg(regs
[RT2
],r
) && 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 (!tempreg(regs
[RT3
],r
)) 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 (tempreg(regs
[RT3
],shto
))
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 */
if (!tempreg(regs
[RT3
],extreg
)) 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 (has2ops(p
)) 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
&& tempreg(lastrand
,r
) && uses
[r
]==p
->forw
) {
if (equtype(p
->subop
,regs
[r
][0]) ||
((p
->op
==CVT
|| p
->op
==MOVZ
|| p
->op
==CVFL
) &&
(regs
[r
][0]&0xf) && compat((p
->subop
>>4)&0xf,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
) {
p
->op
= (p
->op
==DEC
) ? SUB
: ADD
;
/* use 2 now, convert to 3 later */
p
->subop
=(OP2
<<4)+(p
->subop
&0xF);
cp1
=lastrand
; cp2
=regs
[RT2
];
while (*cp2
++= *cp1
++) /* copy reg */
cp1
=lastrand
; *cp1
++='$'; *cp1
++='1'; *cp1
=0;
cp1
=regs
[r
]+1; cp2
=lastrand
;
/* 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
->op
=PUSH
; p
->subop
&= 0xF;
if (tempreg(lastrand
,r2
))
uses
[r2
]=uses
[r
], uses
[r
]=0;
newcode(p
); redunm
++; flow
=r
;
} else if (p
->op
==MOV
) { /* superfluous fetch */
for (cp2
=src
, cp1
=regs
[RT1
]; *cp2
++= *cp1
++;)
if (p
->forw
->op
!= INC
&& p
->forw
->op
!= DEC
)
lastrand
=byondrd(p
->forw
);
for (preg
=regs
+RT1
;*preg
!=lastrand
;preg
++)
if (has2ops(p
->forw
) && equstr(src
,regs
[RT2
])) {
p
->forw
->subop
+= (OP3
-OP2
)<<4;
*cp1
++ = 'r'; *cp1
++ = r
+'0'; *cp1
=0;
uses
[r2
]=uses
[r
], uses
[r
]=0;
return(p
); /* avoid stale uses[] data */
} 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 (tempreg(lastrand
,r
) ||
(has2ops(p
) && tempreg(regs
[RT2
],r
) && uses
[r
]==0)) {
* Writing a dead register is useless,
case AOBLEQ
: case AOBLSS
:
* If no direct uses, check for
if (uses
[r
]==0 && ((dblflg
&1)==0 || uses
[r
+1]==0)) {
register struct node
*q
= p
;
while ((q
= nonlab(q
->forw
))->op
==JBR
&&
q
=q
->ref
; /* cc unused, unchanged */
if (q
->op
!=CBR
&& q
->op
!=ADDA
&& q
->op
!=SUBA
) {
if (equstr(cp1
,lastrand
))
olduse
=uses
[r
], uses
[r
]=0;
/* if r0 destroyed, dont keep r1 */
olduse1
=uses
[++r
], uses
[r
]=0;
/* now look for 'read' or 'modify' (read & write) uses */
while (*(cp1
= *preg
++)) {
if (lastrand
!=cp1
&& tempreg(cp1
,r
)) {
if (isunused
=(uses
[r
]==0)) {
cp2
=regs
[r
]; *cp2
++=p
->subop
;
if ((p
->op
==SHAL
|| p
->op
==SHAR
||
p
->op
==SHL
|| p
->op
==SHR
) &&
if (p
->op
==CBR
&& (p
->subop
==JBC
|| p
->subop
==JBS
))
if (p
->op
==MOVA
&& cp1
==regs
[RT2
])
/* ediv/emod's 2nd operand is quad */
) && cp1
==regs
[RT2
] || (dblflg
&2)) &&
++r
<NUSE
&& uses
[r
]==0) {
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
||
if ((dblflg
&1) && uses
[r
+1]==0)
if (*cp1
=='(' || *cp1
=='[') { /* get register number */
for (cp2
= ++cp1
; *++cp1
!=')' && *cp1
!=']';)
(uses
[r
]==0 || uses
[r
]==p
)) {
(*--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
|| !tempreg(q
->code
,r
))
/* 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
++ != ',');
for(p
= p
->back
; p
!= q
&& (!uses
[r
] || !uses
[r
+1]); p
= p
->back
) {
if((xr
=isreg(regs
[RT1
])) < 0)
else if(q
->subop
== DOUBLE
&& !uses
[r
+1] && xr
== r
+1)
return(q
->forw
); /* DON'T re-scan code with dated uses[] */
/* 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 */
register char *s
, *t
, *c
;
static char lsw
[C2_ASIZE
];
if(d
[0] == '*' || d
[0] == '$')
if (((strncmp(d
, "(r", 2)) == 0) && isdigit(d
[2]))
for(s
=d
; *s
&& *s
!='('; *t
++ = *s
++)
if ((*p
== '+' ) || (*p
== '-'))