Pristine Ack-5.5
[Ack-5.5.git] / mach / m68k2 / top / table
1
2 /* 68000 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 LAB,L1,L2       {VAL[0] == 'I'                  };      /* label */
21 BITNO           {TRUE                           };
22
23 %%;
24
25 /* optimization patterns-> */
26
27 /* rewriting rules */
28 tst X                                   ->      tst.w X ;
29 cmp X,Y                                 ->      cmp.w X,Y ;
30
31 /* special instructions */
32 move.w #0,D                             ->      clr.w D ;
33 move.l #0,D                             ->      clr.l D ;
34 move.l #0,AREG                          ->      sub.l AREG,AREG ;
35
36 /* tst-elimination */
37 add.l #2,sp : tst.w X {no_part("sp",X)} ->      move.w X,(sp)+ ;
38 add.l #4,sp : tst.l D {no_part("sp",D)} ->      move.l D,(sp)+ ;
39 add.l #2,sp : move.w X,-(sp)            ->      move.w X,(sp) ;
40 add.l #4,sp : move.l X,-(sp)            ->      move.l X,(sp) ;
41 add.l #4,sp : pea (NUM)                 ->      move.l #NUM,(sp) ;
42 add.l #NUM,sp : unlk AREG               ->      unlk AREG ;
43 move.w A,X : tst.w A                    ->      move.w A,X ;
44 move.w X,A : tst.w A                    ->      move.w X,A ;
45 move.l A,D : tst.l A {no_part(D,A)}     ->      move.l A,D ;
46 move.l X,D : tst.l D                    ->      move.l X,D ;
47 move.l A,AREG : tst.l A
48                 {no_part(AREG,A)}       ->      tst.l A: move.l A,AREG ;
49 move.l X,AREG : move.l AREG,DREG :
50         tst.l DREG : beq LAB            ->      move.l X,DREG :
51                                                 move.l DREG,AREG: beq LAB ;
52 move.l X,AREG : move.l AREG,DREG :
53         tst.l DREG : bne LAB            ->      move.l X,DREG :
54                                                 move.l DREG,AREG: bne LAB ;
55
56 /* redundant move */
57 move.l DREG,DREG2 : move.l DREG2,DREG   ->      move.l DREG,DREG2 ;
58 move.w DREG,DREG2 : move.w DREG2,DREG   ->      move.w DREG,DREG2 ;
59
60 /* register subsumption */
61 move.w DREG,A : ANY A,X
62         {reg_subs_allowed(ANY) &&
63          !is_dreg(A)    }               ->      move.w DREG,A : ANY DREG,X ;
64 move.l DREG,A : ANY A,X
65         {reg_subs_allowed(ANY) &&
66          !is_dreg(A)    }               ->      move.l DREG,A : ANY DREG,X ;
67
68 cmp.b A,A : beq LAB                     ->      bra LAB ;
69 cmp.w A,A : beq LAB                     ->      bra LAB ;
70 cmp.l A,A : beq LAB                     ->      bra LAB ;
71
72 /* cannot delete cmp's because they affect condition codes (obvious, but ... )*/
73 cmp.b A,A : bne LAB                     ->      cmp.b A,A ;
74 cmp.w A,A : bne LAB                     ->      cmp.w A,A ;
75 cmp.l A,A : bne LAB                     ->      cmp.l A,A ;
76
77 /* change some compares to tests */
78 cmp.w #0,X : beq LAB                    ->      tst.w X : beq LAB ;
79 cmp.w #0,X : bne LAB                    ->      tst.w X : bne LAB ;
80 cmp.w #0,X : blt LAB                    ->      tst.w X : blt LAB ;
81 cmp.w #0,X : ble LAB                    ->      tst.w X : ble LAB ;
82 cmp.w #0,X : bge LAB                    ->      tst.w X : bge LAB ;
83 cmp.w #0,X : bgt LAB                    ->      tst.w X : bgt LAB ;
84
85 cmp.l #0,X : beq LAB                    ->      tst.l X : beq LAB ;
86 cmp.l #0,X : bne LAB                    ->      tst.l X : bne LAB ;
87 cmp.l #0,X : blt LAB                    ->      tst.l X : blt LAB ;
88 cmp.l #0,X : ble LAB                    ->      tst.l X : ble LAB ;
89 cmp.l #0,X : bge LAB                    ->      tst.l X : bge LAB ;
90 cmp.l #0,X : bgt LAB                    ->      tst.l X : bgt LAB ;
91
92 cmp.w X,#0 : beq LAB                    ->      tst.w X : beq LAB ;
93 cmp.w X,#0 : bne LAB                    ->      tst.w X : bne LAB ;
94 cmp.w X,#0 : blt LAB                    ->      tst.w X : bgt LAB ;
95 cmp.w X,#0 : ble LAB                    ->      tst.w X : bge LAB ;
96 cmp.w X,#0 : bge LAB                    ->      tst.w X : ble LAB ;
97 cmp.w X,#0 : bgt LAB                    ->      tst.w X : blt LAB ;
98
99 cmp.l X,#0 : beq LAB                    ->      tst.l X : beq LAB ;
100 cmp.l X,#0 : bne LAB                    ->      tst.l X : bne LAB ;
101 cmp.l X,#0 : blt LAB                    ->      tst.l X : bgt LAB ;
102 cmp.l X,#0 : ble LAB                    ->      tst.l X : bge LAB ;
103 cmp.l X,#0 : bge LAB                    ->      tst.l X : ble LAB ;
104 cmp.l X,#0 : bgt LAB                    ->      tst.l X : blt LAB ;
105
106 /* change "cmp" into "add" or "sub" (possibly "addq" or "subq") */
107 cmp.w #-NUM,DSREG : beq LAB             ->      add.w #NUM,DSREG : beq LAB ;
108 cmp.l #-NUM,DSREG : beq LAB             ->      add.l #NUM,DSREG : beq LAB ;
109 cmp.w #-NUM,DSREG : bne LAB             ->      add.w #NUM,DSREG : bne LAB ;
110 cmp.l #-NUM,DSREG : bne LAB             ->      add.l #NUM,DSREG : bne LAB ;
111
112 cmp.w #NUM,DSREG : beq LAB              ->      sub.w #NUM,DSREG : beq LAB ;
113 cmp.l #NUM,DSREG : beq LAB              ->      sub.l #NUM,DSREG : beq LAB ;
114 cmp.w #NUM,DSREG : bne LAB              ->      sub.w #NUM,DSREG : bne LAB ;
115 cmp.l #NUM,DSREG : bne LAB              ->      sub.l #NUM,DSREG : bne LAB ;
116
117 /* addq and subq */
118 lea -1(AREG),AREG                       ->      sub.l #1,AREG ;
119 add.w #-NUM,X                           ->      sub.w #NUM,X ;
120 add.l #-NUM,X                           ->      sub.l #NUM,X ;
121 sub.w #-NUM,X                           ->      add.w #NUM,X ;
122 sub.l #-NUM,X                           ->      add.l #NUM,X ;
123
124 /* bit-test instruction */
125 move.b X,DSREG : and.w #NUM,DSREG : 
126  tst.w DSREG : beq LAB 
127  { bitno(NUM,BITNO)}                    ->      btst #BITNO,X ;
128 move.b X,DSREG : and.l #NUM,DSREG : 
129  tst.l DSREG : beq LAB 
130  { bitno(NUM,BITNO)}                    ->      btst #BITNO,X ;
131
132 /* skip over jump */
133 beq L1 : bra L2: labdef L1              ->      bne L2 : labdef L1 ;
134 bge L1 : bra L2: labdef L1              ->      blt L2 : labdef L1 ;
135 bgt L1 : bra L2: labdef L1              ->      ble L2 : labdef L1 ;
136 blt L1 : bra L2: labdef L1              ->      bge L2 : labdef L1 ;
137 ble L1 : bra L2: labdef L1              ->      bgt L2 : labdef L1 ;
138 bne L1 : bra L2: labdef L1              ->      beq L2 : labdef L1 ;
139
140 %%;
141
142 /* auxiliary routines: */
143
144 int no_side_effects(s)
145         register char *s;
146 {
147
148         for(;;) {
149                 switch(*s++) {
150                         case '\0': return TRUE;
151                         case '-':  if (*s == '(') return FALSE; break;
152                         case ')':  if (*s == '+') return FALSE; break;
153                 }
154         }
155         /* NOTREACHED */
156 }
157
158
159 int is_dreg(s)
160         register char *s;
161 {
162         return *s++ == 'd' && *s >= '0' && *s++ <= '7' && *s == '\0';
163 }
164
165 int is_dsreg(s)
166         register char *s;
167 {
168         return *s++ == 'd' && *s >= '0' && *s++ <= '2' && *s == '\0';
169 }
170
171 int is_areg(s)
172         register char *s;
173 {
174         return *s++ == 'a' && *s >= '0' && *s++ <= '6' && *s == '\0';
175 }
176
177 int no_part(part,s)
178         char *part,*s;
179 {
180         char *tmp1,*tmp2;
181
182         while (*s != '\0') {
183                 if (*s == *part) {
184                         for (tmp1=part,tmp2=s;;  tmp1++,tmp2++) {
185                                 if (*tmp1== '\0') return FALSE;
186                                 if (*tmp1 != *tmp2) break;
187                         }
188                 }
189                 s++;
190         }
191         return TRUE;
192 }
193
194
195 /* see if register subsumption is allowed for instruction Opc */
196
197 int reg_subs_allowed(opc)
198         char *opc;
199 {
200         return strcmp(opc,"cmp") != 0 && strcmp(opc,"lea") != 0;
201 }
202
203 int is_number(s)
204         register char *s;
205 {
206         while (*s != '\0') {
207                 if (*s < '0' || *s++ > '9') return FALSE;
208         }
209         return TRUE;
210 }
211
212 int bitno(s,no)
213         char *s,*no;
214 {
215         int n,i;
216
217         n = atoi(s);
218         if (n < 1 || n > 128) return FALSE;
219         for (i = 0; i < 8 ; i++) {
220                 if (n == 1) {
221                         sprintf(no,"%d",i);
222                         return TRUE;
223                 }
224                 n >>= 1;
225         }
226         return FALSE;
227 }