Pristine Ack-5.5
[Ack-5.5.git] / mach / m68020 / as / mach4.c
1 /* $Id: mach4.c,v 1.18 1994/06/24 13:05:50 ceriel Exp $ */
2 /*
3  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4  * See the copyright notice in the ACK home directory, in the file "Copyright".
5  */
6 /*
7  *  Motorola 68020 syntax rules
8  */
9 /* Please do not add more terminal symbols. As it is, 127 terminal symbols
10    are used, and this is the limit for some "yacc" implementations,
11    notably the Ultrix one.
12 */
13
14 operation
15         :               {       instrp = instr;
16                                 dot_offset = 0;
17                                 curr_instr = curr_token;
18                         }
19                 instruction
20                         {       emit_instr();
21                         }
22         ;
23 instruction
24         :       bcdx DREG ',' DREG
25                         {       emit2($1 | $2 | $4<<9);}
26         |       bcdx '-' '(' AREG ')' ',' '-' '(' AREG ')'
27                         {       emit2($1 | $4 | $9<<9 | 010);}
28         |       ADD sizedef ea_ea
29                         {       add($1, $2);}
30         |       AND sizenon ea_ea
31                         {       and($1, $2);}
32         |       SHIFT sizedef ea_ea
33                         {       shift_op($1, $2);}
34         |       SHIFT sizedef ea        /* This syntax is also allowed */
35                         {       checksize($2, 2);
36                                 T_EMIT2(($1 & 0177700) | mrg_2,0,0,0);
37                                 ea_2(SIZE_W, MEM|ALT);
38                         }
39         |       BR expr
40                         {       branch($1, $2);}
41         |       DBR DREG ',' expr
42                         {       T_EMIT2($1 | $2,0,0,0);
43                                 $4.val -= (DOTVAL+dot_offset);
44                                 fit(fitw($4.val));
45                                 T_EMIT2(loww($4.val), $4.typ,
46                                                 RELPC|RELO2, relonami);
47                         }
48         |       BITOP ea_ea
49                         {       bitop($1);}
50         |       BITFIELD ea off_width
51                         {       bitfield($1, $3);}
52         |       BF_TO_D ea off_width ',' DREG
53                         {       bitfield($1, $3 | $5<<12);}
54         |       BFINS DREG ',' ea off_width
55                         {       bitfield($1, $5 | $2<<12);}
56         |       DIVMUL sizedef ea ',' DREG
57                         {       checksize($2, 2|4);
58                                 if ($2 == SIZE_W) {
59                                         T_EMIT2((0140300^($1<<8))|mrg_2|$5<<9,
60                                                                 0, 0, 0);
61                                         ea_2(SIZE_W, DTA);
62                                 }
63                                 else {  /* 32 bit dividend or product */
64                                         T_EMIT2((046000 | ($1 & ~1)) | mrg_2,
65                                                                 0, 0, 0);
66                                         T_EMIT2(($1&1)<<11 | $5<<12 | $5,
67                                                                 0, 0, 0);
68                                         ea_2(SIZE_L, DTA);
69                                 }
70                         }
71         |       DIVMUL sizedef ea ',' DREG ':' DREG
72                         {               /* 64 bit dividend or product */
73                                 checksize($2, 4);
74                                 T_EMIT2((046000 | ($1 & ~1)) | mrg_2, 0, 0, 0);
75                                 T_EMIT2(($1&1)<<11 | $7<<12 | $5 | 02000 ,0,0,0);
76                                 ea_2(SIZE_L, DTA);
77                         }
78         |       DIVL sizedef ea ',' DREG ':' DREG
79                         {           /* 32 bit long division with remainder */
80                                 checksize($2, 4);
81                                 T_EMIT2(($1 & ~1) | mrg_2, 0, 0, 0);
82                                 T_EMIT2(($1 & 1)<<11 | $7<<12 | $5 , 0, 0, 0);
83                                 ea_2(SIZE_L, DTA);
84                         }
85         |       LEA ea ',' AREG
86                         {       T_EMIT2(040700 | mrg_2 | $4<<9,0,0,0);
87                                 ea_2(SIZE_L, CTR);
88                         }
89         |       op_ea ea
90                         {       if (mrg_2==074)
91                                         serror("bad adressing category");
92                                 T_EMIT2(($1&0177700) | mrg_2,0,0,0);
93                                 ea_2($1&0300, $1&017);
94                         }
95         |       OP_NOOP
96                         {       emit2($1);}
97         |       OP_EXT SIZE DREG
98                         {       checksize($2, ($1 & 0400) ? 4 : (2|4));
99                                 emit2($1 | $2+0100 | $3);
100                         }
101         |       OP_RANGE sizedef ea ',' reg
102                         {       T_EMIT2(0300 | ($2<<3) | mrg_2,0,0,0);
103                                 T_EMIT2($1 | ($5<<12),0,0,0);
104                                 ea_2($2, CTR);
105                         }
106         |       TRAPCC SIZE imm
107                         {       checksize($2, 2|4);
108                                 T_EMIT2($1 | ($2>>6)+1,0,0,0);
109                                 ea_2($2, 0);
110                         }
111         |       TRAPCC  {       emit2($1 | 4);}
112         |       PACK '-' '(' AREG ')' ',' '-' '(' AREG ')' ',' imm
113                         {       T_EMIT2($1 | 8 | $4 | $9<<9, 0, 0, 0);
114                                 ea_2(SIZE_W, 0);
115                         }
116         |       PACK DREG ',' DREG ',' imm
117                         {       T_EMIT2($1 | $2 | $4<<9, 0, 0, 0);
118                                 ea_2(SIZE_W, 0);
119                         }
120         |       CMP sizedef ea_ea
121                         {       cmp($2);}
122         |       CHK sizedef ea ',' DREG
123                         {       checksize($2, 2|4);
124                                 T_EMIT2(040000 | mrg_2 | $5<<9 |
125                                                 ($2==SIZE_W ? 0600 : 0400),
126                                                                 0, 0, 0);
127                                 ea_2($2, DTA);
128                         }
129         |       MOVE sizenon ea_ea
130                         {       move($2);}
131         |       MOVEM sizedef regs ',' notimmreg
132                         {       movem(0, $2, $3);}
133         |       MOVEM sizedef notimmreg ',' regs
134                         {       movem(1, $2, $5);}
135         |       MOVESP sizedef
136                         {       curr_size = $1; }
137                 ea_ea
138                         {       if ($1 == 0) {
139                                         /* movep */
140                                         movep($2);
141                                 } else if (mrg_1 <= 017) {
142                                         T_EMIT2(007000 | $2 | mrg_2,0,0,0);
143                                         T_EMIT2(mrg_1 << 12 | 04000,0,0,0);
144                                         ea_2($2,ALT|MEM);
145                                 } else if (mrg_2 <= 017) {
146                                         T_EMIT2(007000 | $2 | mrg_1,0,0,0);
147                                         T_EMIT2(mrg_2 << 12,0,0,0);
148                                         ea_1($2,ALT|MEM);
149                                 } else
150                                         badoperand();
151                         }
152         |       MOVEC creg ',' reg
153                         {       T_EMIT2(047172,0,0,0);
154                                 T_EMIT2($2 | $4<<12,0,0,0);
155                         }
156         |       MOVEC reg ',' creg
157                         {       T_EMIT2(047173,0,0,0);
158                                 T_EMIT2($4 | $2<<12,0,0,0);
159                         }
160         |       EXG reg ',' reg
161                         {       if (($2 & 010) == 0)
162                                         emit2(
163                                                 (0140500|$4|$2<<9)
164                                                 +
165                                                 (($4&010)<<3)
166                                         );
167                                 else
168                                         emit2(
169                                                 (0140610|$2|($4&07)<<9)
170                                                 -
171                                                 (($4&010)<<3)
172                                         );
173                         }
174         |       SWAP DREG
175                         {       emit2(044100 | $2);}
176         |       OP_IMM imm
177                         {       T_EMIT2($1, 0, 0, 0);
178                                 ea_2(SIZE_W, 0);
179                         }
180         |       LINK sizenon AREG ',' imm
181                         {       link_instr($2, $3);}
182         |       UNLK AREG
183                         {       emit2(047130 | $2);}
184         |       TRAP '#' absexp
185                         {       fit(fit4($3));
186                                 emit2(047100|low4($3));
187                         }
188         |       BKPT '#' absexp
189                         {       fit(($3 & ~07) == 0);
190                                 emit2(044110 | low3($3));
191                         }
192         |       CALLM '#' absexp ',' ea
193                         {       fit(fitb($3));
194                                 T_EMIT2(03300 | mrg_2,0,0,0);
195                                 T_EMIT2((short) $3,0,0,0);
196                                 ea_2(SIZE_L, CTR);
197                         }
198         |       RTM reg
199                         {       emit2(03300 | $2);}
200         |       CAS sizedef DREG ',' DREG ',' ea
201                         {       T_EMIT2(04300 | (($2+0100)<<3) | mrg_2,0,0,0);
202                                 T_EMIT2($3 | ($5<<6),0,0,0);
203                                 ea_2($2, MEM|ALT);
204                         }
205         |       CAS2 sizedef DREG ':' DREG ',' DREG ':' DREG ','
206                                         '(' reg ')' ':' '(' reg ')'
207                         {       checksize($2 , 2|4);
208                                 emit2(04374 | (($2+0100)<<3));
209                                 emit2($3 | ($7<<6) | ($12<<12));
210                                 emit2($5 | ($9<<6) | ($16<<12));
211                         }
212         |       fp_op
213         |       mm_op
214         ;
215 bcdx    :       ABCD
216         |       ADDX sizedef
217                         {       $$ = $1 | $2;}
218         ;
219 creg    :       CREG
220         |       SPEC    {       if ($1 != 075)
221                                         badoperand();
222                                 $$ = 04000;
223                         }
224         ;
225 off_width               /* note: these should be curly brackets, but that would
226                          * leave us without brackets for expressions.
227                          */
228         :       '[' abs31 ':' abs31 ']'
229                         {       $$ = ($2<<6) | $4;
230                         }
231         ;
232 abs31   :       DREG    {       $$ = 040 | $1;}
233         |       absexp  {       fit(fit5($1));
234                                 $$ = low5($1);
235                         }
236         ;
237 op_ea   :       OP_EA
238         |       SZ_EA sizedef
239                         {       $$ = $1 | $2;}
240         ;
241 regs    :       rrange
242         |       regs '/' rrange
243                         {       $$ = $1 | $3;}
244         ;
245 rrange  :       reg
246                         {       $$ = 1<<$1;}
247         |       reg '-' reg
248                         {       if ($1 > $3)
249                                         badoperand();
250                                 for ($$ = 0; $1 <= $3; $1++)
251                                         $$ |= (1<<$1);
252                         }
253         ;
254 ea      :       DREG
255                         {       mrg_2 = $1;}
256         |       AREG
257                         {       mrg_2 = 010 | $1;}
258         |       SPEC
259                         {       mrg_2 = $1;}
260         |       notimmreg
261         |       imm
262         ;
263 notimmreg
264         :
265                         {       mrg_2 = 0; ffew_2 = 0400; /* initialization */}
266         notimmreg1
267         ;
268 notimmreg1
269         :       '(' AREG ')'
270                         {       mrg_2 = 020 | $2;}
271         |       '(' AREG ')' '+'
272                         {       mrg_2 = 030 | $2;}
273         |       '-' '(' AREG ')'
274                         {       mrg_2 = 040 | $3;}
275         |       '(' expr ')' sizenon
276                         {       bd_2 = $2; ea7071($4);
277                                 RELOMOVE(bd_rel2, relonami);
278                         }
279         |       '(' bd_areg_index ')'
280                         {       if ((mrg_2 & INDEX) == 0)
281                                         ffew_2 |= 0100; /* suppress index */
282                                 if (    !(mrg_2 & PC_MODE) &&
283                                         (ffew_2 & 0300) == 0100 &&
284                                         bd_2.typ==S_ABS && fitw(bd_2.val)
285                                    )
286                                         mrg_2 = (loww(bd_2.val)?050:020) | $2;
287                                 else {
288                                         mrg_2 = (mrg_2&PC_MODE)?073:(060 | $2);
289                                         ffew_2 |= 060; /* long displacement */
290                                 }
291                         }
292         |       '(' '[' bd_areg_index ']' index_od ')'
293                         {       switch(mrg_2 & INDEX) {
294                                 case 0:
295                                         ffew_2 |= 0163; /* suppress index */
296                                         break;
297                                 case DBL_INDEX:
298                                         serror("bad indexing");
299                                 case PRE_INDEX:
300                                         ffew_2 |= 063; break;
301                                 case POST_INDEX:
302                                         ffew_2 |= 067; break;
303                                 }
304                                 mrg_2 = (mrg_2 & PC_MODE) ? 073 : (060 | $3);
305                         }
306         ;
307 imm     :       '#' expr
308                         {       mrg_2 = 074; bd_2 = $2;
309                                 RELOMOVE(bd_rel2, relonami);
310                         }
311         ;
312 bd_areg_index
313         :       /* empty */
314                         {       $$ = 0; ffew_2 |= 0200;
315                                             /* base-reg suppressed */
316                                 bd_2.typ = S_ABS; bd_2.val = (valu_t)0;
317                                             /* zero displacement */
318                         }
319         |       expr    {       $$ = 0; ffew_2 |= 0200;
320                                 bd_2 = $1;
321                                 RELOMOVE(bd_rel2, relonami);
322                         }
323         |       areg_index
324                         {       bd_2.typ = S_ABS; bd_2.val = (valu_t)0;
325                         }
326         |       expr ',' areg_index
327                         {       $$ = $3; bd_2 = $1;
328                                 RELOMOVE(bd_rel2, relonami);
329                         }
330         ;
331 areg_index
332         :       areg
333         |       index   {       $$ = 0;
334                                 ffew_2 |= 0200; /* base-reg suppressed */
335                                 mrg_2 |= PRE_INDEX;
336                         }
337         |       areg ',' index
338                         {       mrg_2 |= PRE_INDEX;
339                         }
340         ;
341 areg    :       AREG
342         |       PC      {       mrg_2 |= PC_MODE;
343                                 ffew_2 |= $1; /* base-reg suppressed for zpc */
344                                 $$ = 0;
345                         }
346         ;
347 index   :       reg sizedef scale
348                         {       checksize($2, 2|4);
349                                 ffew_2 |= $1<<12 | ($2&0200)<<4 | $3;
350                         }
351         ;
352 scale   :       /* empty */
353                         {       $$ = 0;}
354         |       '*' absexp
355                         {       $$ = checkscale($2);}
356         ;
357 index_od:       /* empty */
358                         {       od_2.typ = S_ABS; od_2.val = (valu_t)0;}
359         |       ',' index
360                         {       od_2.typ = S_ABS; od_2.val = (valu_t)0;
361                                 mrg_2 |= POST_INDEX;
362                         }
363         |       ',' expr
364                         {       od_2 = $2;
365                                 RELOMOVE(od_rel2, relonami);
366                         }
367         |       ',' index ',' expr
368                         {       od_2 = $4;
369                                 mrg_2 |= POST_INDEX;
370                                 RELOMOVE(od_rel2, relonami);
371                         }
372         ;
373 reg     :       DREG
374         |       AREG
375                         {       $$ = $1 | 010;}
376         ;
377 sizedef :       /* empty */
378                         {       $$ = SIZE_DEF; curr_size = SIZE_DEF; }
379         |       SIZE    {       curr_size = $1; $$ = $1; }
380         ;
381 sizenon :       /* empty */
382                         {       $$ = SIZE_NON;}
383         |       SIZE
384         ;
385 ea_ea   :       ea ','
386                         {       mrg_1  = mrg_2;
387                                 bd_1   = bd_2;
388                                 od_1   = od_2;
389                                 ffew_1 = ffew_2;
390                                 RELOMOVE(bd_rel1, bd_rel2);
391                                 RELOMOVE(od_rel1, od_rel2);
392                         }
393                 ea
394         ;
395 fp_op   :       CP
396                         {       co_id = $1; }
397                 fp_op1
398         |               {       co_id = DEF_FP; }
399                 fp_op1
400         ;
401 fp_op1  :       FMOVE fsize ea ',' FPCR
402                         {       check_fsize($2, FSIZE_L);
403                                 if ((mrg_2&070) == 010 && $5 != 001)
404                                         badoperand();
405                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
406                                 T_EMIT2((0100000|($5<<10)),0,0,0);
407                                 ea_2(SIZE_L, 0);
408                         }
409         |       FMOVE fsize FPCR ',' ea
410                         {       check_fsize($2, FSIZE_L);
411                                 if ((mrg_2&070) == 010 && $3 == 001)
412                                         badoperand();
413                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
414                                 T_EMIT2((0120000|($3<<10)),0,0,0);
415                                 ea_2(SIZE_L, ALT);
416                         }
417         |       FMOVE fsize FPREG ',' FPREG
418                         {       emit2(0170000|co_id);
419                                 emit2(($3<<10)|($5<<7));
420                         }
421         |       FMOVE fsize ea ',' FPREG
422                         {       ch_sz_dreg($2, mrg_2&070);
423                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
424                                 T_EMIT2((0040000|($2<<10)|($5<<7)),0,0,0);
425                                 ea_2(SIZE_L, DTA);
426                         }
427         |       FMOVE fsize FPREG ',' ea
428                         {       ch_sz_dreg($2, mrg_2&070);
429                                 if ($2 == FSIZE_P)
430                                         serror("packed decimal needs k-factor");
431                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
432                                 T_EMIT2((0060000|($2<<10)|($3<<7)),0,0,0);
433                                 ea_2(SIZE_L, DTA|ALT);
434                         }
435         |       FMOVE fsize FPREG ',' ea '{' '#' absexp '}'
436                         {       check_fsize($2, FSIZE_P);
437                                 fit(sfit7($8));
438                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
439                                 T_EMIT2((0066000|($3<<7)|low7($8)),0,0,0);
440                                 ea_2(SIZE_L, MEM|DTA|ALT);
441                         }
442         |       FMOVE fsize FPREG ',' ea '{' DREG '}'
443                         {       check_fsize($2, FSIZE_P);
444                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
445                                 T_EMIT2((0076000|($3<<7)|($7<<4)),0,0,0);
446                                 ea_2(SIZE_L, MEM|DTA|ALT);
447                         }
448         |       FMOVECR fsize '#' absexp ',' FPREG
449                         {       fit(fit7($4));
450                                 check_fsize($2, FSIZE_X);
451                                 emit2(0170000|co_id);
452                                 emit2(056000|($6<<7)|low7($4));
453                         } 
454         |       FMOVEM FSIZE fregs ',' notimmreg
455                         {       check_fsize($2, FSIZE_X);
456                                 if ((mrg_2&070) == 030)
457                                         serror("bad addressing category");
458                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
459                                 T_EMIT2(0160000 |
460                                         (((mrg_2&070)==040 || ($3&04000)) ?
461                                                 $3 :
462                                                 (010000|reverse($3,8))),
463                                         0,0,0);
464                                 ea_2(SIZE_L, MEM|ALT);
465                         }
466         |       FMOVEM FSIZE notimmreg ',' fregs
467                         {       check_fsize($2, FSIZE_X);
468                                 if ((mrg_2&070) == 040)
469                                         serror("bad addressing category");
470                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
471                                 T_EMIT2((0150000|(($5&04000)?$5:reverse($5,8))),0,0,0);
472                                 ea_2(SIZE_L, MEM);
473                         }
474         |       FMOVEM SIZE fcregs ',' ea
475                         {       checksize($2, 4);
476                                 if ((mrg_2&070) == 1 && $3!= 02000)
477                                         serror("bad addressing category");
478                                 if ((mrg_2 & 070) == 0 &&
479                                     $3 != 02000 && $3 != 04000 && $3 != 010000)
480                                         serror("bad addressing category");
481                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
482                                 T_EMIT2((0120000|$3),0,0,0);
483                                 ea_2(SIZE_L, ALT);
484                         }
485         |       FMOVEM SIZE ea ',' fcregs
486                         {       checksize($2, 4);
487                                 if ((mrg_2&070) == 1 && $5!= 02000)
488                                         serror("bad addressing category");
489                                 if ((mrg_2 & 070) == 0 &&
490                                     $5 != 02000 && $5 != 04000 && $5 != 010000)
491                                         serror("bad addressing category");
492                                 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
493                                 T_EMIT2((0100000|$5),0,0,0);
494                                 ea_2(SIZE_L, 0);
495                         }
496         |       FDYADIC fsize ea ',' FPREG
497                         {       T_EMIT2((0170000|co_id|mrg_2),0,0,0);
498                                 T_EMIT2((0040000|($2<<10)|($5<<7)|$1),0,0,0);
499                                 ch_sz_dreg($2, mrg_2&070);
500                                 ea_2(SIZE_L, DTA);
501                         }
502         |       FDYADIC fsize FPREG ',' FPREG
503                         {       check_fsize($2, FSIZE_X);
504                                 emit2(0170000|co_id);
505                                 emit2(($3<<10)|($5<<7)|$1);
506                         }
507         |       FMONADIC fsize ea ',' FPREG
508                         {       T_EMIT2((0170000|co_id|mrg_2),0,0,0);
509                                 T_EMIT2((0040000|($2<<10)|($5<<7)|$1),0,0,0);
510                                 ch_sz_dreg($2, mrg_2&070);
511                                 ea_2(SIZE_L, DTA);
512                         }
513         |       FMONADIC fsize FPREG ',' FPREG
514                         {       check_fsize($2, FSIZE_X);
515                                 emit2(0170000|co_id);
516                                 emit2(($3<<10)|($5<<7)|$1);
517                         }
518         |       FMONADIC fsize FPREG
519                         {       check_fsize($2, FSIZE_X);
520                                 emit2(0170000|co_id);
521                                 emit2(($3<<10)|($3<<7)|$1);
522                         }
523         |       FSINCOS fsize ea ',' FPREG ':' FPREG
524                         {       T_EMIT2(0170000|co_id|mrg_2,0,0,0);
525                                 T_EMIT2(0040000|($2<<10)|($7<<7)|$1|$5,0,0,0);
526                                 ea_2(SIZE_L, DTA);
527                         }
528         |       FSINCOS fsize FPREG ',' FPREG ':' FPREG
529                         {       check_fsize($2, FSIZE_X);
530                                 emit2(0170000|co_id);
531                                 emit2(($3<<10)|($7<<7)|$1|$5);
532                         }
533         |       FBCC expr
534                         {       fbranch($1, $2);}
535         |       FDBCC DREG ',' expr
536                         {       T_EMIT2(0170110|co_id|$2,0,0,0);
537                                 T_EMIT2($1,0,0,0);
538                                 $4.val -= (DOTVAL+dot_offset);
539                                 fit(fitw($4.val));
540                                 T_EMIT2(loww($4.val), $4.typ,
541                                         RELPC|RELO2,relonami);
542                         }
543         |       FNOP
544                         {       emit2(0170200|co_id);
545                                 emit2(0);
546                         }
547         |       FSCC ea
548                         {       T_EMIT2(0170100|co_id|mrg_2,0,0,0);
549                                 T_EMIT2($1,0,0,0);
550                                 ea_2(SIZE_B, DTA|ALT);
551                         }
552         |       FTST fsize ea
553                         {       T_EMIT2((0170000|co_id|mrg_2),0,0,0);
554                                 T_EMIT2((0040072|($2<<10)),0,0,0);
555                                 ch_sz_dreg($2, mrg_2&070);
556                                 ea_2(SIZE_L, DTA);
557                         }
558         |       FTST fsize FPREG
559                         {       check_fsize($2, FSIZE_X);
560                                 emit2(0170000|co_id);
561                                 emit2(($3<<10)|072);
562                         }
563         |       FSAVRES ea
564                         {       if ((mrg_2&070) == ($1&070))
565                                         badoperand();
566                                 T_EMIT2((0170000|co_id|($1&0700)|mrg_2),0,0,0);
567                                 ea_2(0, $1&07);
568                         }
569         |       FTRAPCC
570                         {       emit2(0170174|co_id);
571                                 emit2($1);
572                         }
573         |       FTRAPCC SIZE imm
574                         {       checksize($2, 2|4);
575                                 T_EMIT2((0170170|co_id|($2==SIZE_L?03:02)),
576                                         0,0,0);
577                                 T_EMIT2($1,0,0,0);
578                                 ea_2($2,0);
579                         }
580         ;
581 fregs   :       DREG
582                         {       $$ = 04000 | $1 << 4; }
583         |       frlist
584         ;
585 frlist  :       frrange
586         |       frlist '/' frrange
587                         {       $$ = $1 | $3;}
588         ;
589 frrange :       FPREG
590                         {       $$ = 1 << $1; }
591         |       FPREG '-' FPREG
592                         {       if ($1 > $3)
593                                         badoperand();
594                                 for ($$ = 0; $1 <= $3; $1++)
595                                         $$ |= (1 << $1);
596                         }
597         ;
598 fcregs  :       FPCR
599                         {       $$ = $1 << 10; }
600         |       fcregs '/' FPCR
601                         {       $$ = $1 | ($3 << 10); }
602         ;
603 fsize   :       /*      empty */
604                         {       $$ = FSIZE_X; }
605         |       SIZE
606                         {       if ($1 == SIZE_L)
607                                         $$ = FSIZE_L;
608                                 else if ($1 == SIZE_W)
609                                         $$ = FSIZE_W;
610                                 else    $$ = FSIZE_B;
611                         }
612         |       FSIZE
613         ;
614 mm_op   :       CP
615                         {       co_id = $1; }
616                 mm_op1
617         |               {       co_id = DEF_MM; }
618                 mm_op1
619         ;
620 mm_op1  :   /* Coprocessor instructions; syntax may be changed (please).
621              * No coprocessor defined extension words are emitted.
622              */
623                 CPBCC cp_cond expr
624                         {       cpbcc($1 | co_id | $2, $3);
625                         }
626         |       CPDBCC cp_cond DREG ',' expr
627                         {       T_EMIT2($1 | co_id | $3,0,0,0);
628                                 $5.val -= (DOTVAL+dot_offset);
629                                 fit(fitw($5.val));
630                                 T_EMIT2(loww($5.val), $5.typ,
631                                                 RELPC|RELO2, relonami);
632                         }
633         |       CPGEN
634                         {       T_EMIT2($1 | co_id,0,0,0);
635                                 /* NO COMMAND WORD IS EMITTED;
636                                  * THIS INSTRUCTIONS IS (STILL) ONE BIG RIDDLE.
637                                  * NO EFFECTIVE ADDRESS IS CALCULATED (SYNTAX ?)
638                                  */
639                         }
640         |       CPSAVREST ea
641                         {       T_EMIT2($1 | co_id | mrg_2,0,0,0);
642                                 if ($1 & 0100) {
643                                         /* restore */
644                                         ea_2(SIZE_W, (mrg_2 & 070)==030 ? 0 : CTR);
645                                 }
646                                 else ea_2(SIZE_W,(mrg_2 & 070)==020 ? 0 : CTR|ALT);
647                         }
648         |       CPSCC cp_cond ea
649                         {       T_EMIT2($1 | co_id | mrg_2,0,0,0);
650                                 T_EMIT2($2,0,0,0);
651                                 ea_2(SIZE_B,DTA|ALT);
652                         }
653         |       CPTRAPCC cp_cond SIZE imm
654                         {       checksize($3,2|4);
655                                 T_EMIT2($1 | co_id | ($3>>6)+1,0,0,0);
656                                 T_EMIT2($2,0,0,0);
657                                 ea_2($3, 0);
658                         }
659         |       CPTRAPCC cp_cond
660                         {       emit2($1 | co_id | 4);
661                                 emit2($2);
662                         }
663         /* M68030 MMU instructions */
664         |       PFLUSHA
665                         {       emit2(0170000);
666                                 emit2($1);
667                         }
668         |       PFLUSH fc ',' mask
669                         {       emit2(0170000);
670                                 emit2($1|010000|($4<<5)|$2);
671                         }
672         |       PFLUSH fc ',' mask ',' ea
673                         {       T_EMIT2(0170000|mrg_2, 0, 0, 0);
674                                 T_EMIT2($1|014000|($4<<5)|$2, 0, 0, 0);
675                                 ea_2(SIZE_L, DTA|CTR);
676                         }
677         |       PTEST fc ',' ea ',' mask
678                         {       T_EMIT2(0170000|mrg_2, 0, 0, 0);
679                                 T_EMIT2($1|($6<<10)|$2, 0, 0, 0);
680                                 ea_2(SIZE_L, DTA|CTR);
681                         }
682         |       PTEST fc ',' ea ',' mask ',' AREG
683                         {       T_EMIT2(0170000|mrg_2, 0, 0, 0);
684                                 T_EMIT2($1|($6<<10)|$2|0400|($8<<5), 0, 0, 0);
685                                 ea_2(SIZE_L, DTA|CTR);
686                         }
687         |       PLOAD fc ',' ea
688                         {       T_EMIT2(0170000|mrg_2, 0, 0, 0);
689                                 T_EMIT2($1|$2, 0, 0, 0);
690                                 ea_2(SIZE_L, DTA|CTR);
691                         }
692         |       PMOVE MREG ',' ea
693                         {       T_EMIT2(0170000|mrg_2, 0, 0, 0);
694                                 T_EMIT2($1|$2|01000, 0, 0, 0);
695                                 ea_2(SIZE_L, DTA|CTR);
696                         }
697         |       PMOVE ea ',' MREG
698                         {       T_EMIT2(0170000|mrg_2, 0, 0, 0);
699                                 T_EMIT2($1|$4, 0, 0, 0);
700                                 ea_2(SIZE_L, DTA|CTR);
701                         }
702         ;
703
704 mask    :       '#' absexp
705                         {       fit(fit3($2));
706                                 $$ = low3($2);
707                         }
708         ;
709
710 fc      :       '#' absexp
711                         {       fit(fit3($2));
712                                 $$ = (020|low3($2));
713                         }
714         |       DREG
715                         {       $$ = (010|$1); }
716         |       CREG
717                         {       if ($1 > 1) serror("illegal control register");
718                                 $$ = ($1&01);
719                         }
720         ;
721
722 cp_cond :       DOT absexp
723                         {       fit(fit6($2));
724                                 $$ = low6($2);
725                         }
726         ;