221 lines
5.7 KiB
Plaintext
221 lines
5.7 KiB
Plaintext
|
|
/* 68020 desciptor table for ACK target optimizer */
|
|
|
|
MAXOP 2;
|
|
PAREN_OPEN "(";
|
|
PAREN_CLOSE ")";
|
|
|
|
%%;
|
|
|
|
/* useful addressing modes-> */
|
|
|
|
CONST {VAL[0] == '#' }; /* constant */
|
|
NUM {is_number(VAL) };
|
|
A,B {no_side_effects(VAL) };
|
|
D {VAL[0] != '#' && !is_areg(VAL) }; /* not an addr. reg */
|
|
X,Y {TRUE };
|
|
DREG,DREG2 {is_dreg(VAL) }; /* data register */
|
|
DSREG {is_dsreg(VAL) }; /* data register */
|
|
AREG {is_areg(VAL) }; /* addressregister */
|
|
LAB,L1,L2 {VAL[0] == 'I' }; /* label */
|
|
BITNO {TRUE };
|
|
|
|
%%;
|
|
|
|
/* optimization patterns-> */
|
|
|
|
/* rewriting rules */
|
|
tst X -> tst.w X ;
|
|
cmp X,Y -> cmp.w X,Y ;
|
|
|
|
/* special instructions */
|
|
move.w #0,D -> clr.w D ;
|
|
move.l #0,D -> clr.l D ;
|
|
move.l #0,AREG -> sub.l AREG,AREG ;
|
|
|
|
/* tst-elimination */
|
|
add.l #2,sp : tst.w X {no_part("sp",X)} -> move.w X,(sp)+ ;
|
|
add.l #4,sp : tst.l D {no_part("sp",D)} -> move.l D,(sp)+ ;
|
|
add.l #2,sp : move.w X,-(sp) -> move.w X,(sp) ;
|
|
add.l #4,sp : move.l X,-(sp) -> move.l X,(sp) ;
|
|
add.l #4,sp : pea (NUM) -> move.l #NUM,(sp) ;
|
|
add.l #NUM,sp : unlk AREG -> unlk AREG ;
|
|
move.w A,X : tst.w A -> move.w A,X ;
|
|
move.w X,A : tst.w A -> move.w X,A ;
|
|
move.l A,D : tst.l A {no_part(D,A)} -> move.l A,D ;
|
|
move.l X,D : tst.l D -> move.l X,D ;
|
|
move.l A,AREG : tst.l A
|
|
{no_part(AREG,A)} -> tst.l A : move.l A,AREG ;
|
|
move.l X,AREG : move.l AREG,DREG :
|
|
tst.l DREG : beq LAB -> move.l X,DREG :
|
|
move.l DREG,AREG: beq LAB ;
|
|
move.l X,AREG : move.l AREG,DREG :
|
|
tst.l DREG : bne LAB -> move.l X,DREG :
|
|
move.l DREG,AREG: bne LAB ;
|
|
|
|
/* redundant move */
|
|
move.l DREG,DREG2 : move.l DREG2,DREG -> move.l DREG,DREG2 ;
|
|
move.l DREG,AREG : move.l AREG,DREG -> move.l DREG,AREG : tst.l DREG ;
|
|
move.l AREG,DREG : move.l DREG,AREG -> move.l AREG,DREG ;
|
|
move.w DREG,DREG2 : move.w DREG2,DREG -> move.w DREG,DREG2 ;
|
|
|
|
/* register subsumption */
|
|
move.w DREG,A : ANY A,X
|
|
{reg_subs_allowed(ANY) &&
|
|
!is_dreg(A) } -> move.w DREG,A : ANY DREG,X ;
|
|
move.l DREG,A : ANY A,X
|
|
{reg_subs_allowed(ANY) &&
|
|
!is_dreg(A) } -> move.l DREG,A : ANY DREG,X ;
|
|
|
|
/* change some compares to tests */
|
|
cmp.w #0,D : beq LAB -> tst.w D : beq LAB ;
|
|
cmp.w #0,D : bne LAB -> tst.w D : bne LAB ;
|
|
cmp.w #0,D : blt LAB -> tst.w D : bgt LAB ;
|
|
cmp.w #0,D : ble LAB -> tst.w D : bge LAB ;
|
|
cmp.w #0,D : bge LAB -> tst.w D : ble LAB ;
|
|
cmp.w #0,D : bgt LAB -> tst.w D : blt LAB ;
|
|
|
|
cmp.l #0,D : beq LAB -> tst.l D : beq LAB ;
|
|
cmp.l #0,D : bne LAB -> tst.l D : bne LAB ;
|
|
cmp.l #0,D : blt LAB -> tst.l D : bgt LAB ;
|
|
cmp.l #0,D : ble LAB -> tst.l D : bge LAB ;
|
|
cmp.l #0,D : bge LAB -> tst.l D : ble LAB ;
|
|
cmp.l #0,D : bgt LAB -> tst.l D : blt LAB ;
|
|
|
|
cmp.w D,#0 : beq LAB -> tst.w D : beq LAB ;
|
|
cmp.w D,#0 : bne LAB -> tst.w D : bne LAB ;
|
|
cmp.w D,#0 : blt LAB -> tst.w D : blt LAB ;
|
|
cmp.w D,#0 : ble LAB -> tst.w D : ble LAB ;
|
|
cmp.w D,#0 : bge LAB -> tst.w D : bge LAB ;
|
|
cmp.w D,#0 : bgt LAB -> tst.w D : bgt LAB ;
|
|
|
|
cmp.l D,#0 : beq LAB -> tst.l D : beq LAB ;
|
|
cmp.l D,#0 : bne LAB -> tst.l D : bne LAB ;
|
|
cmp.l D,#0 : blt LAB -> tst.l D : blt LAB ;
|
|
cmp.l D,#0 : ble LAB -> tst.l D : ble LAB ;
|
|
cmp.l D,#0 : bge LAB -> tst.l D : bge LAB ;
|
|
cmp.l D,#0 : bgt LAB -> tst.l D : bgt LAB ;
|
|
|
|
/* change "cmp" into "add" or "sub" (possibly "addq" or "subq") */
|
|
cmp.w #-NUM,DSREG : beq LAB -> add.w #NUM,DSREG : beq LAB ;
|
|
cmp.l #-NUM,DSREG : beq LAB -> add.l #NUM,DSREG : beq LAB ;
|
|
cmp.w #-NUM,DSREG : bne LAB -> add.w #NUM,DSREG : bne LAB ;
|
|
cmp.l #-NUM,DSREG : bne LAB -> add.l #NUM,DSREG : bne LAB ;
|
|
|
|
cmp.w #NUM,DSREG : beq LAB -> sub.w #NUM,DSREG : beq LAB ;
|
|
cmp.l #NUM,DSREG : beq LAB -> sub.l #NUM,DSREG : beq LAB ;
|
|
cmp.w #NUM,DSREG : bne LAB -> sub.w #NUM,DSREG : bne LAB ;
|
|
cmp.l #NUM,DSREG : bne LAB -> sub.l #NUM,DSREG : bne LAB ;
|
|
|
|
/* addq and subq */
|
|
lea -1(AREG),AREG -> sub.l #1,AREG ;
|
|
add.w #-NUM,X -> sub.w #NUM,X ;
|
|
add.l #-NUM,X -> sub.l #NUM,X ;
|
|
sub.w #-NUM,X -> add.w #NUM,X ;
|
|
sub.l #-NUM,X -> add.l #NUM,X ;
|
|
|
|
/* bit-test instruction */
|
|
move.b X,DSREG : and.w #NUM,DSREG :
|
|
tst.w DSREG : beq LAB
|
|
{ bitno(NUM,BITNO)} -> btst #BITNO,X ;
|
|
move.b X,DSREG : and.l #NUM,DSREG :
|
|
tst.l DSREG : beq LAB
|
|
{ bitno(NUM,BITNO)} -> btst #BITNO,X ;
|
|
|
|
/* skip over jump */
|
|
beq L1 : bra L2: labdef L1 -> bne L2 : labdef L1 ;
|
|
bge L1 : bra L2: labdef L1 -> blt L2 : labdef L1 ;
|
|
bgt L1 : bra L2: labdef L1 -> ble L2 : labdef L1 ;
|
|
blt L1 : bra L2: labdef L1 -> bge L2 : labdef L1 ;
|
|
ble L1 : bra L2: labdef L1 -> bgt L2 : labdef L1 ;
|
|
bne L1 : bra L2: labdef L1 -> beq L2 : labdef L1 ;
|
|
|
|
%%;
|
|
|
|
/* auxiliary routines: */
|
|
|
|
int no_side_effects(s)
|
|
register char *s;
|
|
{
|
|
|
|
for(;;) {
|
|
switch(*s++) {
|
|
case '\0': return TRUE;
|
|
case '-': if (*s == '(') return FALSE; break;
|
|
case ')': if (*s == '+') return FALSE; break;
|
|
}
|
|
}
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
|
|
int is_dreg(s)
|
|
register char *s;
|
|
{
|
|
return *s++ == 'd' && *s >= '0' && *s++ <= '7' && *s == '\0';
|
|
}
|
|
|
|
int is_dsreg(s)
|
|
register char *s;
|
|
{
|
|
return *s++ == 'd' && *s >= '0' && *s++ <= '2' && *s == '\0';
|
|
}
|
|
|
|
int is_areg(s)
|
|
register char *s;
|
|
{
|
|
return *s++ == 'a' && *s >= '0' && *s++ <= '6' && *s == '\0';
|
|
}
|
|
|
|
int no_part(part,s)
|
|
char *part,*s;
|
|
{
|
|
char *tmp1,*tmp2;
|
|
|
|
while (*s != '\0') {
|
|
if (*s == *part) {
|
|
for (tmp1=part,tmp2=s;; tmp1++,tmp2++) {
|
|
if (*tmp1== '\0') return FALSE;
|
|
if (*tmp1 != *tmp2) break;
|
|
}
|
|
}
|
|
s++;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* see if register subsumption is allowed for instruction Opc */
|
|
|
|
int reg_subs_allowed(opc)
|
|
char *opc;
|
|
{
|
|
return strcmp(opc,"cmp") != 0 && strcmp(opc,"lea") != 0;
|
|
}
|
|
|
|
int is_number(s)
|
|
register char *s;
|
|
{
|
|
while (*s != '\0') {
|
|
if (*s < '0' || *s++ > '9') return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
int bitno(s,no)
|
|
char *s,*no;
|
|
{
|
|
int n,i;
|
|
|
|
n = atoi(s);
|
|
if (n < 1 || n > 128) return FALSE;
|
|
for (i = 0; i < 8 ; i++) {
|
|
if (n == 1) {
|
|
sprintf(no,"%d",i);
|
|
return TRUE;
|
|
}
|
|
n >>= 1;
|
|
}
|
|
return FALSE;
|
|
}
|