1 /* $Id: mach4.c,v 1.18 1994/06/24 13:05:50 ceriel Exp $ */
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".
7 * Motorola 68020 syntax rules
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.
17 curr_instr = curr_token;
25 { emit2($1 | $2 | $4<<9);}
26 | bcdx '-' '(' AREG ')' ',' '-' '(' AREG ')'
27 { emit2($1 | $4 | $9<<9 | 010);}
34 | SHIFT sizedef ea /* This syntax is also allowed */
36 T_EMIT2(($1 & 0177700) | mrg_2,0,0,0);
37 ea_2(SIZE_W, MEM|ALT);
42 { T_EMIT2($1 | $2,0,0,0);
43 $4.val -= (DOTVAL+dot_offset);
45 T_EMIT2(loww($4.val), $4.typ,
46 RELPC|RELO2, relonami);
50 | BITFIELD ea off_width
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
59 T_EMIT2((0140300^($1<<8))|mrg_2|$5<<9,
63 else { /* 32 bit dividend or product */
64 T_EMIT2((046000 | ($1 & ~1)) | mrg_2,
66 T_EMIT2(($1&1)<<11 | $5<<12 | $5,
71 | DIVMUL sizedef ea ',' DREG ':' DREG
72 { /* 64 bit dividend or product */
74 T_EMIT2((046000 | ($1 & ~1)) | mrg_2, 0, 0, 0);
75 T_EMIT2(($1&1)<<11 | $7<<12 | $5 | 02000 ,0,0,0);
78 | DIVL sizedef ea ',' DREG ':' DREG
79 { /* 32 bit long division with remainder */
81 T_EMIT2(($1 & ~1) | mrg_2, 0, 0, 0);
82 T_EMIT2(($1 & 1)<<11 | $7<<12 | $5 , 0, 0, 0);
86 { T_EMIT2(040700 | mrg_2 | $4<<9,0,0,0);
91 serror("bad adressing category");
92 T_EMIT2(($1&0177700) | mrg_2,0,0,0);
93 ea_2($1&0300, $1&017);
98 { checksize($2, ($1 & 0400) ? 4 : (2|4));
99 emit2($1 | $2+0100 | $3);
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);
107 { checksize($2, 2|4);
108 T_EMIT2($1 | ($2>>6)+1,0,0,0);
111 | TRAPCC { emit2($1 | 4);}
112 | PACK '-' '(' AREG ')' ',' '-' '(' AREG ')' ',' imm
113 { T_EMIT2($1 | 8 | $4 | $9<<9, 0, 0, 0);
116 | PACK DREG ',' DREG ',' imm
117 { T_EMIT2($1 | $2 | $4<<9, 0, 0, 0);
122 | CHK sizedef ea ',' DREG
123 { checksize($2, 2|4);
124 T_EMIT2(040000 | mrg_2 | $5<<9 |
125 ($2==SIZE_W ? 0600 : 0400),
131 | MOVEM sizedef regs ',' notimmreg
133 | MOVEM sizedef notimmreg ',' regs
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);
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);
153 { T_EMIT2(047172,0,0,0);
154 T_EMIT2($2 | $4<<12,0,0,0);
157 { T_EMIT2(047173,0,0,0);
158 T_EMIT2($4 | $2<<12,0,0,0);
161 { if (($2 & 010) == 0)
169 (0140610|$2|($4&07)<<9)
175 { emit2(044100 | $2);}
177 { T_EMIT2($1, 0, 0, 0);
180 | LINK sizenon AREG ',' imm
181 { link_instr($2, $3);}
183 { emit2(047130 | $2);}
186 emit2(047100|low4($3));
189 { fit(($3 & ~07) == 0);
190 emit2(044110 | low3($3));
192 | CALLM '#' absexp ',' ea
194 T_EMIT2(03300 | mrg_2,0,0,0);
195 T_EMIT2((short) $3,0,0,0);
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);
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));
220 | SPEC { if ($1 != 075)
225 off_width /* note: these should be curly brackets, but that would
226 * leave us without brackets for expressions.
228 : '[' abs31 ':' abs31 ']'
232 abs31 : DREG { $$ = 040 | $1;}
233 | absexp { fit(fit5($1));
250 for ($$ = 0; $1 <= $3; $1++)
265 { mrg_2 = 0; ffew_2 = 0400; /* initialization */}
275 | '(' expr ')' sizenon
276 { bd_2 = $2; ea7071($4);
277 RELOMOVE(bd_rel2, relonami);
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)
286 mrg_2 = (loww(bd_2.val)?050:020) | $2;
288 mrg_2 = (mrg_2&PC_MODE)?073:(060 | $2);
289 ffew_2 |= 060; /* long displacement */
292 | '(' '[' bd_areg_index ']' index_od ')'
293 { switch(mrg_2 & INDEX) {
295 ffew_2 |= 0163; /* suppress index */
298 serror("bad indexing");
300 ffew_2 |= 063; break;
302 ffew_2 |= 067; break;
304 mrg_2 = (mrg_2 & PC_MODE) ? 073 : (060 | $3);
308 { mrg_2 = 074; bd_2 = $2;
309 RELOMOVE(bd_rel2, relonami);
314 { $$ = 0; ffew_2 |= 0200;
315 /* base-reg suppressed */
316 bd_2.typ = S_ABS; bd_2.val = (valu_t)0;
317 /* zero displacement */
319 | expr { $$ = 0; ffew_2 |= 0200;
321 RELOMOVE(bd_rel2, relonami);
324 { bd_2.typ = S_ABS; bd_2.val = (valu_t)0;
326 | expr ',' areg_index
327 { $$ = $3; bd_2 = $1;
328 RELOMOVE(bd_rel2, relonami);
334 ffew_2 |= 0200; /* base-reg suppressed */
338 { mrg_2 |= PRE_INDEX;
342 | PC { mrg_2 |= PC_MODE;
343 ffew_2 |= $1; /* base-reg suppressed for zpc */
347 index : reg sizedef scale
348 { checksize($2, 2|4);
349 ffew_2 |= $1<<12 | ($2&0200)<<4 | $3;
355 { $$ = checkscale($2);}
357 index_od: /* empty */
358 { od_2.typ = S_ABS; od_2.val = (valu_t)0;}
360 { od_2.typ = S_ABS; od_2.val = (valu_t)0;
365 RELOMOVE(od_rel2, relonami);
370 RELOMOVE(od_rel2, relonami);
377 sizedef : /* empty */
378 { $$ = SIZE_DEF; curr_size = SIZE_DEF; }
379 | SIZE { curr_size = $1; $$ = $1; }
381 sizenon : /* empty */
390 RELOMOVE(bd_rel1, bd_rel2);
391 RELOMOVE(od_rel1, od_rel2);
398 | { co_id = DEF_FP; }
401 fp_op1 : FMOVE fsize ea ',' FPCR
402 { check_fsize($2, FSIZE_L);
403 if ((mrg_2&070) == 010 && $5 != 001)
405 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
406 T_EMIT2((0100000|($5<<10)),0,0,0);
409 | FMOVE fsize FPCR ',' ea
410 { check_fsize($2, FSIZE_L);
411 if ((mrg_2&070) == 010 && $3 == 001)
413 T_EMIT2((0170000|co_id|mrg_2),0,0,0);
414 T_EMIT2((0120000|($3<<10)),0,0,0);
417 | FMOVE fsize FPREG ',' FPREG
418 { emit2(0170000|co_id);
419 emit2(($3<<10)|($5<<7));
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);
427 | FMOVE fsize FPREG ',' ea
428 { ch_sz_dreg($2, mrg_2&070);
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);
435 | FMOVE fsize FPREG ',' ea '{' '#' absexp '}'
436 { check_fsize($2, FSIZE_P);
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);
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);
448 | FMOVECR fsize '#' absexp ',' FPREG
450 check_fsize($2, FSIZE_X);
451 emit2(0170000|co_id);
452 emit2(056000|($6<<7)|low7($4));
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);
460 (((mrg_2&070)==040 || ($3&04000)) ?
462 (010000|reverse($3,8))),
464 ea_2(SIZE_L, MEM|ALT);
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);
474 | FMOVEM SIZE fcregs ',' ea
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);
485 | FMOVEM SIZE ea ',' fcregs
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);
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);
502 | FDYADIC fsize FPREG ',' FPREG
503 { check_fsize($2, FSIZE_X);
504 emit2(0170000|co_id);
505 emit2(($3<<10)|($5<<7)|$1);
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);
513 | FMONADIC fsize FPREG ',' FPREG
514 { check_fsize($2, FSIZE_X);
515 emit2(0170000|co_id);
516 emit2(($3<<10)|($5<<7)|$1);
518 | FMONADIC fsize FPREG
519 { check_fsize($2, FSIZE_X);
520 emit2(0170000|co_id);
521 emit2(($3<<10)|($3<<7)|$1);
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);
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);
535 | FDBCC DREG ',' expr
536 { T_EMIT2(0170110|co_id|$2,0,0,0);
538 $4.val -= (DOTVAL+dot_offset);
540 T_EMIT2(loww($4.val), $4.typ,
541 RELPC|RELO2,relonami);
544 { emit2(0170200|co_id);
548 { T_EMIT2(0170100|co_id|mrg_2,0,0,0);
550 ea_2(SIZE_B, DTA|ALT);
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);
559 { check_fsize($2, FSIZE_X);
560 emit2(0170000|co_id);
564 { if ((mrg_2&070) == ($1&070))
566 T_EMIT2((0170000|co_id|($1&0700)|mrg_2),0,0,0);
570 { emit2(0170174|co_id);
574 { checksize($2, 2|4);
575 T_EMIT2((0170170|co_id|($2==SIZE_L?03:02)),
582 { $$ = 04000 | $1 << 4; }
594 for ($$ = 0; $1 <= $3; $1++)
601 { $$ = $1 | ($3 << 10); }
608 else if ($1 == SIZE_W)
617 | { co_id = DEF_MM; }
620 mm_op1 : /* Coprocessor instructions; syntax may be changed (please).
621 * No coprocessor defined extension words are emitted.
624 { cpbcc($1 | co_id | $2, $3);
626 | CPDBCC cp_cond DREG ',' expr
627 { T_EMIT2($1 | co_id | $3,0,0,0);
628 $5.val -= (DOTVAL+dot_offset);
630 T_EMIT2(loww($5.val), $5.typ,
631 RELPC|RELO2, relonami);
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 ?)
641 { T_EMIT2($1 | co_id | mrg_2,0,0,0);
644 ea_2(SIZE_W, (mrg_2 & 070)==030 ? 0 : CTR);
646 else ea_2(SIZE_W,(mrg_2 & 070)==020 ? 0 : CTR|ALT);
649 { T_EMIT2($1 | co_id | mrg_2,0,0,0);
651 ea_2(SIZE_B,DTA|ALT);
653 | CPTRAPCC cp_cond SIZE imm
655 T_EMIT2($1 | co_id | ($3>>6)+1,0,0,0);
660 { emit2($1 | co_id | 4);
663 /* M68030 MMU instructions */
670 emit2($1|010000|($4<<5)|$2);
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);
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);
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);
688 { T_EMIT2(0170000|mrg_2, 0, 0, 0);
689 T_EMIT2($1|$2, 0, 0, 0);
690 ea_2(SIZE_L, DTA|CTR);
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);
698 { T_EMIT2(0170000|mrg_2, 0, 0, 0);
699 T_EMIT2($1|$4, 0, 0, 0);
700 ea_2(SIZE_L, DTA|CTR);
717 { if ($1 > 1) serror("illegal control register");