2 /* 68020 desciptor table for ACK target optimizer */
10 /* useful addressing modes-> */
12 CONST {VAL[0] == '#' }; /* constant */
13 NUM {is_number(VAL) };
14 A,B {no_side_effects(VAL) };
15 D {VAL[0] != '#' && !is_areg(VAL) }; /* not an addr. reg */
17 DREG,DREG2 {is_dreg(VAL) }; /* data register */
18 DSREG {is_dsreg(VAL) }; /* data register */
19 AREG {is_areg(VAL) }; /* addressregister */
20 FPREG,FPREG2 {is_fpreg(VAL) }; /* fp register */
21 LAB,L1,L2 {VAL[0] == 'I' }; /* label */
22 NO32 {no_part("div",VAL) && no_part("mul",VAL) && no_part(".l",VAL)};
28 /* optimization patterns-> */
32 cmp X,Y -> cmp.w X,Y ;
34 /* special instructions */
35 move.w #0,D -> clr.w D ;
36 move.l #0,D -> clr.l D ;
37 move.l #0,AREG -> sub.l AREG,AREG ;
40 add.l #2,sp : tst.w X {no_part("sp",X)} -> move.w X,(sp)+ ;
41 add.l #4,sp : tst.l D {no_part("sp",D)} -> move.l D,(sp)+ ;
42 add.l #2,sp : move.w X,-(sp) -> move.w X,(sp) ;
43 add.l #4,sp : move.l X,-(sp) -> move.l X,(sp) ;
44 add.l #4,sp : pea (NUM) -> move.l #NUM,(sp) ;
45 add.l #4,sp : pea (AREG) -> move.l AREG,(sp) ;
46 add.l #NUM,sp : unlk AREG -> unlk AREG ;
47 add.l #NUM,sp : movem.l X,Y : unlk AREG
48 {no_part("sp",X) && no_part("sp",Y)} -> movem.l X,Y : unlk AREG ;
49 move.w A,X : tst.w A -> move.w A,X ;
50 move.w X,A : tst.w A -> move.w X,A ;
51 move.l A,D : tst.l A {no_part(D,A)} -> move.l A,D ;
52 move.l X,D : tst.l D -> move.l X,D ;
53 move.l A,AREG : tst.l A
54 {no_part(AREG,A)} -> tst.l A : move.l A,AREG ;
55 move.l X,AREG : move.l AREG,DREG :
56 tst.l DREG : beq LAB -> move.l X,DREG :
57 move.l DREG,AREG: beq LAB ;
58 move.l X,AREG : move.l AREG,DREG :
59 tst.l DREG : bne LAB -> move.l X,DREG :
60 move.l DREG,AREG: bne LAB ;
63 move.l DREG,DREG2 : move.l DREG2,DREG -> move.l DREG,DREG2 ;
64 move.l DREG,AREG : move.l AREG,DREG -> move.l DREG,AREG : tst.l DREG ;
65 move.l AREG,DREG : move.l DREG,AREG -> move.l AREG,DREG ;
66 move.w DREG,DREG2 : move.w DREG2,DREG -> move.w DREG,DREG2 ;
69 /* register subsumption */
70 move.w DREG,A : ANY A,X
71 {reg_subs_allowed(ANY) &&
72 !is_dreg(A) } -> move.w DREG,A : ANY DREG,X ;
73 move.l DREG,A : ANY A,X
74 {reg_subs_allowed(ANY) &&
75 !is_dreg(A) } -> move.l DREG,A : ANY DREG,X ;
77 move.w DREG,DREG2 : NO32 A,DREG2 : move.w DREG2,DREG
78 {no_part(DREG2,A)} -> NO32 A,DREG : move.w DREG,DREG2 ;
79 move.l DREG,DREG2 : ANY A,DREG2 : move.l DREG2,DREG
80 {no_part(DREG2,A)} -> ANY A,DREG : move.l DREG,DREG2 ;
82 cmp.b A,A : beq LAB -> bra LAB ;
83 cmp.w A,A : beq LAB -> bra LAB ;
84 cmp.l A,A : beq LAB -> bra LAB ;
86 /* cannot delete cmp's because they affect condition codes (obvious, but ... )*/
87 cmp.b A,A : bne LAB -> cmp.b A,A ;
88 cmp.w A,A : bne LAB -> cmp.w A,A ;
89 cmp.l A,A : bne LAB -> cmp.l A,A ;
91 /* change some compares to tests */
92 cmp.w #0,D : beq LAB -> tst.w D : beq LAB ;
93 cmp.w #0,D : bne LAB -> tst.w D : bne LAB ;
94 cmp.w #0,D : blt LAB -> tst.w D : blt LAB ;
95 cmp.w #0,D : ble LAB -> tst.w D : ble LAB ;
96 cmp.w #0,D : bge LAB -> tst.w D : bge LAB ;
97 cmp.w #0,D : bgt LAB -> tst.w D : bgt LAB ;
99 cmp.l #0,D : beq LAB -> tst.l D : beq LAB ;
100 cmp.l #0,D : bne LAB -> tst.l D : bne LAB ;
101 cmp.l #0,D : blt LAB -> tst.l D : blt LAB ;
102 cmp.l #0,D : ble LAB -> tst.l D : ble LAB ;
103 cmp.l #0,D : bge LAB -> tst.l D : bge LAB ;
104 cmp.l #0,D : bgt LAB -> tst.l D : bgt LAB ;
106 cmp.w D,#0 : beq LAB -> tst.w D : beq LAB ;
107 cmp.w D,#0 : bne LAB -> tst.w D : bne LAB ;
108 cmp.w D,#0 : blt LAB -> tst.w D : bgt LAB ;
109 cmp.w D,#0 : ble LAB -> tst.w D : bge LAB ;
110 cmp.w D,#0 : bge LAB -> tst.w D : ble LAB ;
111 cmp.w D,#0 : bgt LAB -> tst.w D : blt LAB ;
113 cmp.l D,#0 : beq LAB -> tst.l D : beq LAB ;
114 cmp.l D,#0 : bne LAB -> tst.l D : bne LAB ;
115 cmp.l D,#0 : blt LAB -> tst.l D : bgt LAB ;
116 cmp.l D,#0 : ble LAB -> tst.l D : bge LAB ;
117 cmp.l D,#0 : bge LAB -> tst.l D : ble LAB ;
118 cmp.l D,#0 : bgt LAB -> tst.l D : blt LAB ;
120 /* change "cmp" into "add" or "sub" (possibly "addq" or "subq") */
121 cmp.w #-NUM,DSREG : beq LAB -> add.w #NUM,DSREG : beq LAB ;
122 cmp.l #-NUM,DSREG : beq LAB -> add.l #NUM,DSREG : beq LAB ;
123 cmp.w #-NUM,DSREG : bne LAB -> add.w #NUM,DSREG : bne LAB ;
124 cmp.l #-NUM,DSREG : bne LAB -> add.l #NUM,DSREG : bne LAB ;
126 cmp.w #NUM,DSREG : beq LAB -> sub.w #NUM,DSREG : beq LAB ;
127 cmp.l #NUM,DSREG : beq LAB -> sub.l #NUM,DSREG : beq LAB ;
128 cmp.w #NUM,DSREG : bne LAB -> sub.w #NUM,DSREG : bne LAB ;
129 cmp.l #NUM,DSREG : bne LAB -> sub.l #NUM,DSREG : bne LAB ;
132 lea -1(AREG),AREG -> sub.l #1,AREG ;
133 add.w #-NUM,X -> sub.w #NUM,X ;
134 add.l #-NUM,X -> sub.l #NUM,X ;
135 sub.w #-NUM,X -> add.w #NUM,X ;
136 sub.l #-NUM,X -> add.l #NUM,X ;
138 /* bit-test instruction */
139 move.b X,DSREG : and.w #NUM,DSREG :
140 tst.w DSREG : beq LAB
141 { bitno(NUM,BITNO)} -> btst #BITNO,X ;
142 move.b X,DSREG : and.l #NUM,DSREG :
143 tst.l DSREG : beq LAB
144 { bitno(NUM,BITNO)} -> btst #BITNO,X ;
147 beq L1 : bra L2: labdef L1 -> bne L2 : labdef L1 ;
148 bge L1 : bra L2: labdef L1 -> blt L2 : labdef L1 ;
149 bgt L1 : bra L2: labdef L1 -> ble L2 : labdef L1 ;
150 blt L1 : bra L2: labdef L1 -> bge L2 : labdef L1 ;
151 ble L1 : bra L2: labdef L1 -> bgt L2 : labdef L1 ;
152 bne L1 : bra L2: labdef L1 -> beq L2 : labdef L1 ;
154 move.l A, B : bra LAB : labdef L1 : move.l A, B : labdef LAB
155 -> labdef L1 : move.l A, B :
157 /* some strength reduction */
158 mulu.l #NUM,DREG -> muls.l #NUM,DREG ;
160 {isshift_once(NUM,X,Y)} -> asl.l #X,DREG :
163 {is_shift_twice(NUM,X,Y)} -> asl.l #X,DREG :
168 asl.l #1,DREG -> add.l DREG,DREG ;
171 move.l A,-(sp) : move.l B,-(sp) : fmove.d (sp)+,FPREG
172 {combines_to_double(A,B)} -> fmove.d B,FPREG ;
173 move.l A,-(sp) : move.l B,-(sp) : fmove.d X,FPREG : fmove.d (sp)+,FPREG2
174 {combines_to_double(A,B) &&
175 strcmp(FPREG,FPREG2) &&
176 no_part("sp",X) } -> fmove.d X,FPREG :
180 /* auxiliary routines: */
182 int no_side_effects(s)
188 case '\0': return TRUE;
189 case '-': if (*s == '(') return FALSE; break;
190 case ')': if (*s == '+') return FALSE; break;
196 int isshift_once(s, c1, c2)
201 long val = atol(s), pow = 1;
207 sprintf(c1, "%d", i <= 8 ? i : 8);
208 sprintf(c2, "%d", i <= 8 ? 0 : i - 8);
219 int is_shift_twice(s, c1, c2)
224 long val = atol(s), pow = 1;
229 sprintf(c1, "%d", i);
236 if (pow > 0 && val) {
241 sprintf(c2, "%d", i);
242 if (val == 0) return 1;
256 return *s++ == 'd' && *s >= '0' && *s++ <= '7' && *s == '\0';
262 return *s++ == 'f' && *s++ == 'p' &&
263 *s >= '0' && *s++ <= '7' && *s == '\0';
269 return *s++ == 'd' && *s >= '0' && *s++ <= '2' && *s == '\0';
275 return *s++ == 'a' && *s >= '0' && *s++ <= '6' && *s == '\0';
285 for (tmp1=part,tmp2=s;; tmp1++,tmp2++) {
286 if (*tmp1== '\0') return FALSE;
287 if (*tmp1 != *tmp2) break;
296 /* see if register subsumption is allowed for instruction Opc */
298 int reg_subs_allowed(opc)
301 return strcmp(opc,"cmp") != 0 && strcmp(opc,"lea") != 0;
308 if (*s < '0' || *s++ > '9') return FALSE;
319 if (n < 1 || n > 128) return FALSE;
320 for (i = 0; i < 8 ; i++) {
330 int combines_to_double(a,b)
333 /* recognize (_name+4) combined with (_name),
334 and (offset+4,...) combined with (offset,...)
336 if (*a++ == '(' && *b++ == '(') {
337 if (*a == '-' || *a >= '0' && *a <= '9') {
344 while (*a >= '0' && *a <= '9') a++;
345 while (*b >= '0' && *b <= '9') b++;
346 return !strcmp(a,b) && *a++ == ',' &&
347 *a++ == 'a' && *a++ && *a++ == ')' &&
352 while (*a && *a == *b) {
356 if (*b++ == ')' && ! *b && *a++ == '+' && *a++ == '4' &&