Pristine Ack-5.5
[Ack-5.5.git] / mach / m68020 / top / table
1
2 /* 68020 desciptor table for ACK target optimizer */
3
4 MAXOP 2;
5 PAREN_OPEN "(";
6 PAREN_CLOSE ")";
7
8 %%;
9
10 /* useful addressing modes-> */
11
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 */
16 X,Y             {TRUE                           };
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)};
23                                                         /* for move.w ... */
24 BITNO           {TRUE                           };
25
26 %%;
27
28 /* optimization patterns-> */
29
30 /* rewriting rules */
31 tst X                                   ->      tst.w X ;
32 cmp X,Y                                 ->      cmp.w X,Y ;
33
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 ;
38
39 /* tst-elimination */
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 ;
61
62 /* redundant move */
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 ;
67 move.l AREG,AREG                        ->      ;
68
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 ;
76
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 ;
81
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 ;
85
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 ;
90
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 ;
98
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 ;
105
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 ;
112
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 ;
119
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 ;
125
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 ;
130
131 /* addq and subq */
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 ;
137
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 ;
145
146 /* skip over jump */
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 ;
153
154 move.l A, B : bra LAB : labdef L1 : move.l A, B : labdef LAB
155                                         ->      labdef L1 : move.l A, B :
156                                                 labdef LAB ;
157 /* some strength reduction */
158 mulu.l #NUM,DREG                        ->      muls.l #NUM,DREG ;
159 muls.l #NUM,DREG
160         {isshift_once(NUM,X,Y)}         ->      asl.l #X,DREG :
161                                                 asl.l #Y,DREG ;
162 muls.l #NUM,DREG
163         {is_shift_twice(NUM,X,Y)}       ->      asl.l #X,DREG :
164                                                 move.l DREG,-(sp) :
165                                                 asl.l #Y,DREG :
166                                                 add.l (sp)+,DREG ;
167 asl.l #0,DREG                           ->      ;
168 asl.l #1,DREG                           ->      add.l DREG,DREG ;
169
170
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 :
177                                                 fmove.d B,FPREG2 ;
178 %%;
179
180 /* auxiliary routines: */
181
182 int no_side_effects(s)
183         register char *s;
184 {
185
186         for(;;) {
187                 switch(*s++) {
188                         case '\0': return TRUE;
189                         case '-':  if (*s == '(') return FALSE; break;
190                         case ')':  if (*s == '+') return FALSE; break;
191                 }
192         }
193         /* NOTREACHED */
194 }
195
196 int isshift_once(s, c1, c2)
197         char *s, *c1, *c2;
198 {
199         long atol();
200         register int i = 0;
201         long val = atol(s), pow = 1;
202
203         while (i <= 16) {
204                 if (pow & val) {
205                         val -= pow;
206                         if (val == 0) {
207                                 sprintf(c1, "%d", i <= 8 ? i : 8);
208                                 sprintf(c2, "%d", i <= 8 ? 0 : i - 8);
209                                 return 1;
210                         }
211                         return 0;
212                 }
213                 pow <<= 1;
214                 i++;
215         }
216         return 0;
217 }
218
219 int is_shift_twice(s, c1, c2)
220         char *s, *c1, *c2;
221 {
222         long atol();
223         register int i = 0;
224         long val = atol(s), pow = 1;
225
226         while (i <= 8) {
227                 if (pow & val) {
228                         val -= pow;
229                         sprintf(c1, "%d", i);
230                         break;
231                 }
232                 pow <<= 1;
233                 i++;
234         }
235         if (i > 8) return 0;
236         if (pow > 0 && val) {
237                 i = 0;
238                 while (i <= 8) {
239                         if (pow & val) {
240                                 val -= pow;
241                                 sprintf(c2, "%d", i);
242                                 if (val == 0) return 1;
243                                 break;
244                         }
245                         pow <<= 1;
246                         i++;
247                 }
248         }
249         return 0;
250 }
251
252
253 int is_dreg(s)
254         register char *s;
255 {
256         return *s++ == 'd' && *s >= '0' && *s++ <= '7' && *s == '\0';
257 }
258
259 int is_fpreg(s)
260         register char *s;
261 {
262         return *s++ == 'f' &&  *s++ == 'p' && 
263                *s >= '0' && *s++ <= '7' && *s == '\0';
264 }
265
266 int is_dsreg(s)
267         register char *s;
268 {
269         return *s++ == 'd' && *s >= '0' && *s++ <= '2' && *s == '\0';
270 }
271
272 int is_areg(s)
273         register char *s;
274 {
275         return *s++ == 'a' && *s >= '0' && *s++ <= '6' && *s == '\0';
276 }
277
278 int no_part(part,s)
279         char *part,*s;
280 {
281         char *tmp1,*tmp2;
282
283         while (*s != '\0') {
284                 if (*s == *part) {
285                         for (tmp1=part,tmp2=s;;  tmp1++,tmp2++) {
286                                 if (*tmp1== '\0') return FALSE;
287                                 if (*tmp1 != *tmp2) break;
288                         }
289                 }
290                 s++;
291         }
292         return TRUE;
293 }
294
295
296 /* see if register subsumption is allowed for instruction Opc */
297
298 int reg_subs_allowed(opc)
299         char *opc;
300 {
301         return strcmp(opc,"cmp") != 0 && strcmp(opc,"lea") != 0;
302 }
303
304 int is_number(s)
305         register char *s;
306 {
307         while (*s != '\0') {
308                 if (*s < '0' || *s++ > '9') return FALSE;
309         }
310         return TRUE;
311 }
312
313 int bitno(s,no)
314         char *s,*no;
315 {
316         int n,i;
317
318         n = atoi(s);
319         if (n < 1 || n > 128) return FALSE;
320         for (i = 0; i < 8 ; i++) {
321                 if (n == 1) {
322                         sprintf(no,"%d",i);
323                         return TRUE;
324                 }
325                 n >>= 1;
326         }
327         return FALSE;
328 }
329
330 int combines_to_double(a,b)
331         register char *a,*b;
332 {
333         /*      recognize (_name+4) combined with (_name),
334                 and (offset+4,...) combined with (offset,...)
335         */
336         if (*a++ == '(' && *b++ == '(') {
337                 if (*a == '-' || *a >= '0' && *a <= '9') {
338                         int na = atoi(a);
339                         int nb = atoi(b);
340
341                         if (*a == '-') a++;
342                         if (*b == '-') b++;
343                         if (na == nb + 4) {
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++ == ')' &&
348                                         !*a;
349                         }
350                         return FALSE;
351                 }
352                 while (*a && *a == *b) {
353                         a++;
354                         b++;
355                 }
356                 if (*b++ == ')' && ! *b && *a++ == '+' && *a++ == '4' &&
357                     *a++ == ')' && !*a)
358                         return TRUE;
359         }
360         return FALSE;
361 }