Pristine Ack-5.5
[Ack-5.5.git] / mach / z80 / as / mach4.c
1 #define RCSID4 "$Id: mach4.c,v 3.5 1994/06/24 13:54:54 ceriel Exp $"
2
3 /*
4  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
5  * See the copyright notice in the ACK home directory, in the file "Copyright".
6  *
7  */
8
9 /*
10  * Zilog Z80 parsing rules
11  */
12 operation
13         :       NOOPOP
14                         {       emit1($1);}
15         |       LDOP ldargs
16         |       PSHPOP R16
17                         {       switch ($2) {
18                                 case BC: emit1($1); break;
19                                 case DE: emit1($1 | 020); break;
20                                 case AF: emit1($1 | 060); break;
21                                 case HL:
22                                 case IX:
23                                 case IY: xyreg($2,$1 | 040); break;
24                                 default: serror("register error");
25                                 }
26                         }
27         |       EXOP R16 ',' R16
28                         {       if ($2==DE && $4==HL)
29                                         emit1(0353);
30                                 else if ($2==AF && $4==AF2)
31                                         emit1(010);
32                                 else serror("register error");
33                         }
34         |       EXOP '(' R16 ')' ',' R16
35                         {       if ($3!=SP) serror("register error");
36                                 xyreg($6,$1);
37                         }
38         |       E_ED
39                         {       emit1(0355); emit1($1);}
40         |       ADDOP R16 ',' R16
41                         {       if ($4 == $2)
42                                         xyreg($2,051);
43                                 else {
44                                         if ($4==HL || $4>SP)
45                                                 serror("register error");
46                                         xyreg($2,011 | $4<<4);
47                                 }
48                         }
49         |       ADCSBC R16 ',' R16
50                         {       if ($2!=HL || $4>SP) serror("register error");
51                                 emit1(0355);
52                                 emit1(($1==0210 ? 0112 : 0102) | ($4<<4));
53                         }
54         |       INCDEC R16
55                         {       switch ($2) {
56                                 case BC: case DE: case SP:
57                                         emit1(($1==04 ? 03 : 013) | $2<<4);
58                                         break;
59                                 case HL: case IX: case IY:
60                                         xyreg($2,$1==04 ? 043 : 053);
61                                         break;
62                                 default: serror("register error");
63                                 }
64                         }
65         |       INCDEC r8
66                         {       emit1($1 | $2<<3);}
67         |       INCDEC ind
68                         {       xymem($2,$1 | 060);}
69         |       ari8 r8
70                         {       emit1($1 | $2);}
71         |       ari8 expr
72                         {       emit1($1 | 0106); emit1($2.val);}
73         |       ari8 ind
74                         {       xymem($2,$1 | 06);}
75         |       IMOP absexp
76                         {       emit1(0355);
77                                 switch ($2) {
78                                 case 0: emit1(0106); break;
79                                 case 1: emit1(0126); break;
80                                 case 2: emit1(0136); break;
81                                 default: serror("range 0..2");
82                                 }
83                         }
84         |       ROTATE r8
85                         {       emit1(0313); emit1($1 | $2);}
86         |       ROTATE ind
87                         {       xymem($2,0313); emit1($1 | 06);}
88         |       BITS absexp ',' r8
89                         {       fit(fit3($2));
90                                 emit1(0313); emit1($1 | low3($2)<<3 | $4);
91                         }
92         |       BITS absexp ',' ind
93                         {       fit(fit3($2));
94                                 xymem($4,0313);
95                                 emit1($1 | low3($2)<<3 | 06);
96                         }
97         |       JP expr
98                         {       emit1($1);
99 #ifdef RELOCATION
100                                 newrelo($2.typ, RELO2);
101 #endif
102                                 emit2($2.val);
103                         }
104         |       JP coco ',' expr
105                         {       emit1(0302 | $2<<3);
106 #ifdef RELOCATION
107                                 newrelo($4.typ, RELO2);
108 #endif
109                                 emit2($4.val);
110                         }
111         |       JP indir
112                         {       xyreg($2,0351);}
113         |       JR expr
114                         {       branch($1,$2);}
115         |       JR coco ',' expr
116                         {       if ($2 > 3) serror("bad condition code");
117                                 branch(040 | ($2<<3), $4);
118                         }
119         |       DJNZ expr
120                         {       branch($1,$2);}
121         |       CALL expr
122                         {       emit1($1);
123 #ifdef RELOCATION
124                                 newrelo($2.typ, RELO2);
125 #endif
126                                 emit2($2.val);
127                         }
128         |       CALL coco ',' expr
129                         {       emit1(0304 | $2<<3);
130 #ifdef RELOCATION
131                                 newrelo($4.typ, RELO2);
132 #endif
133                                 emit2($4.val);
134                         }
135         |       RET
136                         {       emit1($1);}
137         |       RET coco
138                         {       emit1(0300 | $2<<3);}
139         |       RST absexp
140                         {       if (($2&070)!=$2)
141                                         serror("rst expression out of range");
142                                 emit1($1 | $2);
143                         }
144         |       IN R8 ',' expr
145                         {       if ($2 != A) serror("register error");
146                                 emit1($1);
147 #ifdef RELOCATION
148                                 newrelo($4.typ, RELO1);
149 #endif
150                                 emit1($4.val);
151                         }
152         |       IN R8 ',' R8
153                         {       if ($4 != C) serror("register error");
154                                 emit1(0355); emit1(0100 | $2<<3);
155                         }
156         |       OUT expr ',' R8
157                         {       if ($4 != A) serror("register error");
158                                 emit1($1);
159 #ifdef RELOCATION
160                                 newrelo($2.typ, RELO1);
161 #endif
162                                 emit1($2.val);
163                         }
164         |       OUT R8 ',' R8
165                         {       if ($2 != C) serror("register error");
166                                 emit1(0355); emit1(0101 | $4<<3);
167                         }
168         ;
169 ari8    :       ARI8
170         |       ADDOP R8 ','
171                         {       if ($2 != A) serror("register error");}
172         |       ADCSBC R8 ','
173                         {       if ($2 != A) serror("register error");}
174         ;
175 ldargs  :       R8 ',' R8
176                         {       if ($1==F || $3==F) serror("register error");
177                                 if ($1<=A && $3<=A)
178                                         emit1(0100 | $1<<3 | $3);
179                                 else {
180                                         emit1(0355);
181                                         if ((($1==A) ^ ($3==A)) == 0)
182                                                 serror("register error");
183                                         emit1(  0107 |
184                                                 ($1==R||$3==R)<<3 |
185                                                 ($1==A)<<4
186                                         );
187                                 }
188                         }
189         |       R8 ',' expr
190                         {       if ($1==F || $1==I || $1==R)
191                                         serror("register error");
192                                 emit1(06 | $1<<3);
193 #ifdef RELOCATION
194                                 newrelo($3.typ, RELO1);
195 #endif
196                                 emit1($3.val);
197                         }
198         |       R8 ',' indir
199                         {       if ($1==F || $1==I || $1==R)
200                                         serror("register error");
201                                 if ($1==A && ($3==BC || $3==DE))
202                                         emit1($3==BC ? 012 : 032);
203                                 else
204                                         xymem($3,0106 | $1<<3);
205                         }
206         |       R8 ',' index
207                         {       if ($1==F || $1==I || $1==R)
208                                         serror("register error");
209                                 xymem($3,0106 | $1<<3);
210                         }
211         |       R8 ',' '(' expr ')'
212                         {       if ($1!=A) serror("register error");
213                                 emit1(072);
214 #ifdef RELOCATION
215                                 newrelo($4.typ, RELO2);
216 #endif
217                                 emit2($4.val);
218                         }
219         |       indir ',' r8
220                         {       if ($3==A && ($1==BC || $1==DE))
221                                         emit1($1==BC ? 02 : 022);
222                                 else
223                                         xymem($1,0160 | $3);
224                         }
225         |       index ',' r8
226                         {       xymem($1,0160 | $3);}
227         |       indir ',' expr
228                         {       xymem($1,066);
229 #ifdef RELOCATION
230                                 newrelo($3.typ, RELO1);
231 #endif
232                                 emit1($3.val);
233                         }
234         |       index ',' expr
235                         {       xymem($1,066);
236 #ifdef RELOCATION
237                                 newrelo($3.typ, RELO1);
238 #endif
239                                 emit1($3.val);
240                         }
241         |       R16 ',' expr
242                         {       switch ($1) {
243                                 case BC: case DE: case HL: case SP:
244                                         emit1(01 | $1<<4); break;
245                                 case IX: case IY:
246                                         xyreg($1,041); break;
247                                 default: serror("register error");
248                                 }
249 #ifdef RELOCATION
250                                 newrelo($3.typ, RELO2);
251 #endif
252                                 emit2($3.val);
253                         }
254         |       R16 ',' R16
255                         {       if ($1!=SP) serror("register error");
256                                 xyreg($3,0371);
257                         }
258         |       R16 ',' '(' expr ')'
259                         {       switch ($1) {
260                                 case BC: case DE: case SP:
261                                         emit1(0355); emit1(0113 | $1<<4); break;
262                                 case HL: case IX: case IY:
263                                         xyreg($1,052); break;
264                                 default: serror("register error");
265                                 }
266 #ifdef RELOCATION
267                                 newrelo($4.typ, RELO2);
268 #endif
269                                 emit2($4.val);
270                         }
271         |       '(' expr ')' ',' R8
272                         {       if ($5!=A) serror("register error");
273                                 emit1(062);
274 #ifdef RELOCATION
275                                 newrelo($2.typ, RELO2);
276 #endif
277                                 emit2($2.val);
278                         }
279         |       '(' expr ')' ',' R16
280                         {       switch ($5) {
281                                 case BC: case DE: case SP:
282                                         emit1(0355); emit1(0103 | $5<<4); break;
283                                 case HL: case IX: case IY:
284                                         xyreg($5,042); break;
285                                 default: serror("register error");
286                                 }
287 #ifdef RELOCATION
288                                 newrelo($2.typ, RELO2);
289 #endif
290                                 emit2($2.val);
291                         }
292         ;
293 r8      :       R8
294                         {       if ($1==F || $1==I || $1==R)
295                                         serror("register error");
296                         }
297         ;
298 indir   :       '(' R16 ')'
299                         {       if ($2>=SP && $2!=IX && $2!=IY)
300                                         serror("register error");
301                                 exp_ind.typ = S_ABS; exp_ind.val = 0;
302                                 $$ = $2;
303                         }
304         ;
305 index   :       '(' R16 '+' expr ')'
306                         {       if ($2!=IX && $2!=IY) serror("register error");
307                                 exp_ind = $4;
308                                 RELOMOVE(rel_ind, relonami);
309                                 $$ = $2;
310                         }
311         |       '(' R16 '-' expr ')'
312                         {
313                                 if ($2!=IX && $2!=IY) serror("register error");
314                                 fit(fitb($4.val));
315                                 exp_ind = $4;
316                                 RELOMOVE(rel_ind, relonami);
317                                 $$ = $2;
318                         }
319         ;
320 ind     :       indir
321         |       index
322         ;
323 coco    :       CC
324         |       R8
325                         {       if ($1 != C) serror("bad condition code");
326                                 $$ = 3;
327                         }
328         ;