123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- /* 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 */
- FPREG,FPREG2 {is_fpreg(VAL) }; /* fp register */
- LAB,L1,L2 {VAL[0] == 'I' }; /* label */
- NO32 {no_part("div",VAL) && no_part("mul",VAL) && no_part(".l",VAL)};
- /* for move.w ... */
- 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 #4,sp : pea (AREG) -> move.l AREG,(sp) ;
- add.l #NUM,sp : unlk AREG -> unlk AREG ;
- add.l #NUM,sp : movem.l X,Y : unlk AREG
- {no_part("sp",X) && no_part("sp",Y)} -> movem.l X,Y : 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 ;
- move.l AREG,AREG -> ;
- move.l A,B : move.l A,B -> move.l A,B ;
- move.w A,B : move.w A,B -> move.w A,B ;
- move.b A,B : move.b A,B -> move.b A,B ;
- /* 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 ;
- move.w DREG,DREG2 : NO32 A,DREG2 : move.w DREG2,DREG
- {no_part(DREG2,A)} -> NO32 A,DREG : move.w DREG,DREG2 ;
- move.l DREG,DREG2 : ANY A,DREG2 : move.l DREG2,DREG
- {no_part(DREG2,A)} -> ANY A,DREG : move.l DREG,DREG2 ;
- cmp.b A,A : beq LAB -> bra LAB ;
- cmp.w A,A : beq LAB -> bra LAB ;
- cmp.l A,A : beq LAB -> bra LAB ;
- /* cannot delete cmp's because they affect condition codes (obvious, but ... )*/
- cmp.b A,A : bne LAB -> cmp.b A,A ;
- cmp.w A,A : bne LAB -> cmp.w A,A ;
- cmp.l A,A : bne LAB -> cmp.l A,A ;
- /* 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 : blt LAB ;
- cmp.w #0,D : ble LAB -> tst.w D : ble LAB ;
- cmp.w #0,D : bge LAB -> tst.w D : bge LAB ;
- cmp.w #0,D : bgt LAB -> tst.w D : bgt 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 : blt LAB ;
- cmp.l #0,D : ble LAB -> tst.l D : ble LAB ;
- cmp.l #0,D : bge LAB -> tst.l D : bge LAB ;
- cmp.l #0,D : bgt LAB -> tst.l D : bgt 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 : bgt LAB ;
- cmp.w D,#0 : ble LAB -> tst.w D : bge LAB ;
- cmp.w D,#0 : bge LAB -> tst.w D : ble LAB ;
- cmp.w D,#0 : bgt LAB -> tst.w D : blt 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 : bgt LAB ;
- cmp.l D,#0 : ble LAB -> tst.l D : bge LAB ;
- cmp.l D,#0 : bge LAB -> tst.l D : ble LAB ;
- cmp.l D,#0 : bgt LAB -> tst.l D : blt 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 ;
- move.l A, B : bra LAB : labdef L1 : move.l A, B : labdef LAB
- -> labdef L1 : move.l A, B :
- labdef LAB ;
- /* some strength reduction */
- mulu.l #NUM,DREG -> muls.l #NUM,DREG ;
- muls.l #NUM,DREG
- {isshift_once(NUM,X,Y)} -> asl.l #X,DREG :
- asl.l #Y,DREG ;
- muls.l #NUM,DREG
- {is_shift_twice(NUM,X,Y)} -> asl.l #X,DREG :
- move.l DREG,-(sp) :
- asl.l #Y,DREG :
- add.l (sp)+,DREG ;
- asl.l #0,DREG -> ;
- asl.l #1,DREG -> add.l DREG,DREG ;
- move.l A,-(sp) : move.l B,-(sp) : fmove.d (sp)+,FPREG
- {combines_to_double(A,B)} -> fmove.d B,FPREG ;
- move.l A,-(sp) : move.l B,-(sp) : fmove.d X,FPREG : fmove.d (sp)+,FPREG2
- {combines_to_double(A,B) &&
- strcmp(FPREG,FPREG2) &&
- no_part("sp",X) } -> fmove.d X,FPREG :
- fmove.d B,FPREG2 ;
- %%;
- /* 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 isshift_once(s, c1, c2)
- char *s, *c1, *c2;
- {
- long atol();
- register int i = 0;
- long val = atol(s), pow = 1;
- while (i <= 16) {
- if (pow & val) {
- val -= pow;
- if (val == 0) {
- sprintf(c1, "%d", i <= 8 ? i : 8);
- sprintf(c2, "%d", i <= 8 ? 0 : i - 8);
- return 1;
- }
- return 0;
- }
- pow <<= 1;
- i++;
- }
- return 0;
- }
- int is_shift_twice(s, c1, c2)
- char *s, *c1, *c2;
- {
- long atol();
- register int i = 0;
- long val = atol(s), pow = 1;
- while (i <= 8) {
- if (pow & val) {
- val -= pow;
- sprintf(c1, "%d", i);
- break;
- }
- pow <<= 1;
- i++;
- }
- if (i > 8) return 0;
- if (pow > 0 && val) {
- i = 0;
- while (i <= 8) {
- if (pow & val) {
- val -= pow;
- sprintf(c2, "%d", i);
- if (val == 0) return 1;
- break;
- }
- pow <<= 1;
- i++;
- }
- }
- return 0;
- }
- int is_dreg(s)
- register char *s;
- {
- return *s++ == 'd' && *s >= '0' && *s++ <= '7' && *s == '\0';
- }
- int is_fpreg(s)
- register char *s;
- {
- return *s++ == 'f' && *s++ == 'p' &&
- *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;
- }
- int combines_to_double(a,b)
- register char *a,*b;
- {
- /* recognize (_name+4) combined with (_name),
- and (offset+4,...) combined with (offset,...)
- */
- if (*a++ == '(' && *b++ == '(') {
- if (*a == '-' || *a >= '0' && *a <= '9') {
- int na = atoi(a);
- int nb = atoi(b);
- if (*a == '-') a++;
- if (*b == '-') b++;
- if (na == nb + 4) {
- while (*a >= '0' && *a <= '9') a++;
- while (*b >= '0' && *b <= '9') b++;
- return !strcmp(a,b) && *a++ == ',' &&
- *a++ == 'a' && *a++ && *a++ == ')' &&
- !*a;
- }
- return FALSE;
- }
- while (*a && *a == *b) {
- a++;
- b++;
- }
- if (*b++ == ')' && ! *b && *a++ == '+' && *a++ == '4' &&
- *a++ == ')' && !*a)
- return TRUE;
- }
- return FALSE;
- }
|