Pristine Ack-5.5
[Ack-5.5.git] / mach / ns / as / mach4.c
1 #define RCSID4 "$Id: mach4.c,v 0.3 1994/06/24 13:09:55 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 /* Author: Ed Keizer */
10
11 operation:
12                 BR      expr
13                 /* format 0 */
14                         { dot_adjust(&$2) ; form0($1) ; disp(&$2, RELPC) ;}
15         |       WAIT
16                 /* format 1 */
17                         { form1($1) ;}
18         |       BSR     expr
19                 /* format 1 */
20                         { dot_adjust(&$2) ; form1($1) ; disp(&$2, RELPC) ;}
21         |       RET     expr
22                 /* format 1 */
23                         { form1($1) ; disp(&$2, 0) ;}
24         |       SAVE    reg_list
25                 /* format 1 */
26                         { form1($1) ; emit1(reg_list($2,id_op($1)!=0x6)) ;}
27         |       ENTER   reg_list ',' expr
28                 /* format 1 */
29                         { form1($1) ; emit1(reg_list($2,0)) ; disp(&$4, 0) ;}
30         |       LPR     AREG ',' gen1
31                 /* format 2 */
32                         { if ( id_op($1)==0x2 ) not_imm(&mode1) ;
33                           form2($1,$2) ; gen1($1) ;
34                         }
35         |       SEQ     gen1
36                 /* format 2 */
37                         { form2($1,id_cc($1)) ; gen1($1) ; not_imm(&mode1) ;}
38         |       MOVQ    absexp ',' gen1
39                 /* format 2 */
40                         {
41                           if ( !fit4($2) ) {
42                                 serror("Constant too large") ;
43                           }
44                           form2($1,low4($2)) ; gen1($1) ;
45                           if ( id_op($1)!=0x1 ) not_imm(&mode1) ; /* !cmp */
46                         }
47         |       ACB     absexp ',' gen1 ',' expr
48                 /* format 2 */
49                         {
50                           dot_adjust(&$6) ;
51                           if (!fit4($2) ) {
52                                 serror("Constant too large") ;
53                           }
54                           form2($1,low4($2)) ; gen1($1) ; not_imm(&mode1) ;
55                           disp(&$6, RELPC) ;
56                         }
57         |       ADJSP   gen1
58                 /* format 3 */
59                         {
60                           if ( id_op($1)==0 ) not_imm(&mode1) ; /* cxpd */
61                           form3($1) ; gen1($1) ;}
62         |       JSR     gen1
63                 /* format 3 */
64                         {
65 #ifndef NO_OPTIM
66                           if ( mode1.m_mode==0x15 ) { /* Absolute */
67                                 dot_adjust(&mode1.m_expr1) ;
68                                 RELOMOVE(relonami, mode1.m_rel1);
69                                 form1(0) ; disp(&mode1.m_expr1, RELPC) ; /* bsr */
70                           } else
71 #endif
72                           { form3($1) ; gen1($1) ; }
73                           not_imm(&mode1) ;
74                         }
75         |       JUMP    gen1
76                 /* format 3 */
77                         {
78 #ifndef NO_OPTIM
79                           if ( mode1.m_mode==0x15 ) { /* Absolute */
80                                 dot_adjust(&mode1.m_expr1) ;
81                                 RELOMOVE(relonami, mode1.m_rel1);
82                                 form0(B_TRUE) ; disp(&mode1.m_expr1, RELPC) ; /* br */
83                           } else
84 #endif
85                           { form3($1) ; gen1($1) ; }
86                           not_imm(&mode1) ;
87                         }
88         |       ADD_I   gen1 ',' gen2
89                 /* format 4 */
90                         {
91                           register opc ;
92                           opc=id_op($1) ;
93                           if ( opc==0x9 ) not_imm(&mode1) ; /* addr */
94                           if ( opc!=0x1 ) not_imm(&mode2) ; /* !cmp */
95 #ifndef NO_OPTIM
96                           if ( mode1.m_mode==0x14 && /* Immediate */
97                                (mode1.m_expr1.typ & ~S_EXT) == S_ABS &&
98                                (
99                                  (fit4(mode1.m_expr1.val) &&
100                                   (opc==0 || opc==1 || opc==5))
101                                  ||
102                                  (fit4(-mode1.m_expr1.val) &&
103                                   (opc==8))
104                                )
105                              )
106                            {
107                                /* Warning, an absolute expression derived
108                                   from a symbol that is defined after
109                                   use might - if the value now suddenly fits -
110                                   cause failed assertions in newlabel
111                                 */
112                                /* add,     cmp,     mov         */
113                                /* added: the subtract of a signed
114                                 *        short is the same as the add
115                                 *        of the negation of that short
116                                 * so: subi short,x == addqi -short,x
117                                 * 19/04/85 h.m.kodden,m.j.a.leliveld 
118                                 */
119                                 if (opc==8)     /* do the negate */
120                                         mode1.m_expr1.val = 
121                                         (~mode1.m_expr1.val+1)&0xF;
122                                 opc=low4(mode1.m_expr1.val) ;
123                                 mode1= mode2 ;
124                                 form2($1,opc) ; gen1($1) ;
125                           } else
126 #endif
127                           { form4($1) ; gengen($1) ; }
128                         }
129         |       SETCFG  cpu_opts
130                 /* format 5 */
131                         { form5($1,$2) ;}
132         |       MOVS    string_opts
133                 /* format 5 */
134                         { form5($1,($2)|id_cc($1)) ;}
135         |       COM     gen1 ',' gen2
136                 /* format 6 */
137                         { form6($1) ; gengen($1) ; not_imm(&mode2) ;}
138         |       MUL_I   gen1 ',' gen2
139                 /* format 7 */
140                         { 
141                           if ( id_op($1)==0x9 || id_op($1)==0xB ) {
142                                 /* mei or dei */
143                                 switch ( mode2.m_mode ) {
144                                 case 1 : case 3 : case 5 : case 7 :
145                                         serror("register must be even") ;
146                                 }
147                           }
148                           form7($1) ; gengen($1) ; not_imm(&mode2) ;
149                         }
150         |       MOVID   gen1 ',' gen2
151                 /* format 7 */
152                         { form7x($1,id_g1($1)) ; gengen($1) ; not_imm(&mode2) ;}
153         |       MOVM    gen1 ',' gen2 ',' expr
154                 /* format 7 */
155                         {
156                           register s_size ;
157                           s_size= id_g1($1)+1 ;
158                           /* $6.val= $6.val*s_size - s_size ; */
159                           $6.val= $6.val -1 ;
160                           form7($1) ; gengen($1) ; disp(&$6, 0) ;
161                           not_imm(&mode1) ; not_imm(&mode2) ;
162                         }
163         |       INSS    gen1 ',' gen2 ',' absexp ',' absexp
164                 /* format 7 */
165                         { 
166                           if ( ( $6<0 || $6>7 || $8<1 || $8>32 )
167                              ) { serror("Constant out of bounds") ; }
168                           form7($1) ; gengen($1) ;
169                           if ( id_op($1)==0x3 ) not_imm(&mode1) ; /* exts */
170                           not_imm(&mode2) ;
171                           emit1((((int)$6)<<5)+(int)$8-1) ;
172                         }
173         |       FFS     gen1 ',' gen2
174                 /* format 8 */
175                         { form8($1,id_cc($1)) ; gengen($1) ; not_imm(&mode2) ;}
176         |       CHECK   REG ',' gen1 ',' gen2
177                 /* format 8 */
178                         {
179                           form8($1,$2) ; gengen($1) ;
180                           if ( id_op($1)!=0x4 ) {
181                                 not_imm(&mode1) ; /* check, cvtp */
182                                 if ( id_op($1)==0x1 ) not_imm(&mode2) ;/*cvtp */
183                           }
184                         }
185         |       INS     REG ',' gen1 ',' gen2 ',' expr
186                 /* format 8 */
187                         {
188                           form8($1,$2) ; gengen($1) ; disp(&$8, 0) ;
189                           if ( id_op($1)==0x0 ) not_imm(&mode1) ;
190                           not_imm(&mode2) ;
191                         }
192         |       MOVIF   gen1 ',' fgen2
193                 /* format 9 */
194                         {
195                           assert( id_t1($1)==T_INT && id_t2($1)==T_FL ) ;
196                           form9($1,id_g1($1),id_g2($1)) ; gengen($1) ;
197                           not_imm(&mode2) ;
198                         }
199         |       MOVFL   fgen1 ',' fgen2
200                 /* format 9 */
201                         {
202                           assert( id_t1($1)==T_FL && id_t2($1)==T_FL ) ;
203                           form9($1,id_g1($1),( id_g2($1)==F_LONG?3:2 )) ;
204                           gengen($1) ; not_imm(&mode2) ;
205                         }
206         |       TRUNC   fgen1 ',' gen2
207                 /* format 9 */
208                         {
209                           assert( id_t1($1)==T_FL && id_t2($1)==T_INT ) ;
210                           form9($1,id_g2($1),id_g1($1)) ; gengen($1) ;
211                           not_imm(&mode2) ;
212                         }
213         |       LFSR    gen1
214                 /* format 9 */
215                         { 
216                           if ( id_op($1)==6 ) { /* SFSR */
217                                 not_imm(&mode1) ;
218                                 mode2.m_mode=mode1.m_mode ;
219                                 mode1.m_mode=0 ;
220                           } else {
221                                 mode2.m_mode=0 ;
222                           }
223                           form9($1,0,0) ;
224                           if ( id_op($1)==6 ) {
225                                 mode1.m_mode=mode2.m_mode ;
226                           }
227                           gen1($1) ;
228                         }
229         |       ADD_F   fgen1 ',' fgen2
230                 /* format 11 */
231                         { if ( id_op($1)!=0x2 ) not_imm(&mode2) ; /* !CMPF */
232                           form11($1) ; gengen($1) ;
233                         }
234         |       RDVAL   gen1
235                 /* format 14 */
236                         { form14($1,0) ; gen1($1) ; not_imm(&mode1) ;}
237         |       LMR     MREG ',' gen1
238                 /* format 14 */
239                         {
240                           form14($1,$2) ; gen1($1) ;
241                           if ( id_op($1)==0x3 ) not_imm(&mode1) ;
242                         }
243                         /* All remaining categories are not checked for
244                            illegal immediates */
245         |       LCR     CREG ',' gen1
246                 /* format 15.0 */
247                         { frm15_0($1,$2) ; gen1($1) ;}
248         |       CATST   gen1
249                 /* format 15.0 */
250                         { frm15_0($1,0) ; gen1($1) ;}
251         |       LCSR    gen1
252                 /* format 15.1 */ /* Sure? */
253                         { mode2.m_mode=0 ; frm15_1($1,0,0) ; gen1($1) ;}
254         |       CCVIS   gen1 ',' gen2
255                 /* format 15.1 */
256                         {
257                           assert( id_t1($1)==T_INT && id_t2($1)==T_SLAVE ) ;
258                           frm15_1($1,id_g1($1),id_g2($1)) ; gengen($1) ;
259                         }
260         |       CCVSI   gen1 ',' gen2
261                 /* format 15.1 */
262                         { 
263                           assert( id_t1($1)==T_SLAVE && id_t2($1)==T_INT ) ;
264                           frm15_1($1,id_g2($1),id_g1($1)) ; gengen($1) ;
265                         }
266         |       CCVSS   gen1 ',' gen2
267                 /* format 15.1 */
268                         {
269                           assert( id_t1($1)==T_SLAVE && id_t2($1)==T_SLAVE ) ;
270                           frm15_1($1,0,0) ; gengen($1) ; /* Sure? */
271                         }
272         |       CMOV    gen1 ',' gen2
273                 /* format 15.5 */
274                         { frm15_5($1) ; gengen($1) ;}
275         ;
276
277 gen1    :       { mode_ptr= &mode1 ; clrmode() ; } gen
278         ;
279 gen2    :       { mode_ptr= &mode2 ; clrmode() ; } gen
280         ;
281 fgen1   :       { mode_ptr= &mode1 ; clrmode() ; } fgen
282         ;
283 fgen2   :       { mode_ptr= &mode2 ; clrmode() ; } fgen
284         ;
285
286 gen     :       gen_not_reg             /* Every mode except register */
287         |       REG
288                         { mode_ptr->m_mode= $1 ; }
289         ;
290 fgen    :       gen_not_reg             /* Every mode except register */
291         |       FREG
292                         { mode_ptr->m_mode= $1 ; }
293         ;
294
295 gen_not_reg:    gen_a                   /* general mode with eff. address */
296         |       REG { mode_ptr->m_mode=$1 ;} index
297                                 /* The register is supposed to contain the
298                                    address
299                                 */
300         |       gen_a index             /* As above, but indexed */
301         |       expr                    /* Immediate */
302                         { mode_ptr->m_mode= 0x14 ;
303                           mode_ptr->m_expr1= $1 ;
304                           RELOMOVE(mode_ptr->m_rel1, relonami);
305                         }
306         ;
307
308 gen_a   :       expr '(' REG ')'                /* Register relative */
309                         { mode_ptr->m_mode= 0x8 + $3 ;
310                           mode_ptr->m_ndisp= 1 ;
311                           mode_ptr->m_expr1= $1 ;
312                           RELOMOVE(mode_ptr->m_rel1, relonami);
313                         }
314         |       expr '(' AREG ')'               /* Memory space */
315                         { if ( $3<0x8 || $3>0xA ) badsyntax() ;
316                           mode_ptr->m_mode= 0x18 + ($3&3) ;
317                           mode_ptr->m_ndisp= 1 ;
318                           mode_ptr->m_expr1= $1 ;
319                           RELOMOVE(mode_ptr->m_rel1, relonami);
320                         }
321         |       expr '(' PC ')'                 /* Memory space */
322                         { mode_ptr->m_mode= 0x1B ;
323                           mode_ptr->m_ndisp= 1 ;
324                           mode_ptr->m_expr1= $1 ;
325                           RELOMOVE(mode_ptr->m_rel1, relonami);
326                           dot_adjust(&mode_ptr->m_expr1) ;
327                         }
328         |       expr '('
329                         { mode_ptr->m_expr2 = $1;
330                           RELOMOVE(mode_ptr->m_rel2, relonami);
331                         }
332                 expr '(' AREG ')' ')'   /* Memory relative */
333                         { if ( $6<0x8 || $6>0xA ) badsyntax() ;
334                           mode_ptr->m_mode= 0x10 + ($6&3) ;
335                           mode_ptr->m_ndisp= 2 ;
336                           mode_ptr->m_expr1= $4 ;
337                           RELOMOVE(mode_ptr->m_rel1, relonami);
338                         }
339         |       '@' expr                        /* Absolute */
340                         { mode_ptr->m_mode= 0x15 ;
341                           mode_ptr->m_ndisp= 1 ;
342                           mode_ptr->m_expr1= $2 ;
343                           RELOMOVE(mode_ptr->m_rel1, relonami);
344                         }
345         |       EXTERNAL '(' expr ')' 
346                         { mode_ptr->m_mode= 0x16 ;
347                           mode_ptr->m_ndisp= 2 ;
348                           mode_ptr->m_expr1= $3 ;
349                           RELOMOVE(mode_ptr->m_rel1, relonami);
350                         }
351                 '+' expr        /* External */
352                         {
353                           mode_ptr->m_expr2= $7 ;
354                           RELOMOVE(mode_ptr->m_rel2, relonami);
355                         }
356         |       TOS                             /* Top Of Stack */
357                         { mode_ptr->m_mode= 0x17 ; }
358         ;
359
360 index   :       '[' REG ':' INDICATOR ']'       /* Indexed postfix */
361                         { mode_ptr->m_index= (mode_ptr->m_mode<<3) | $2 ;
362                           mode_ptr->m_mode= ind_mode( $4 ) ;
363                         }
364         ;
365
366 cpu_opts:
367                 '[' ']'
368                         { $$=0 ;}
369         |       '[' cpu_list ']'
370                         { $$= $2 ;}
371         ;
372
373 cpu_list:
374                 INDICATOR
375                         { $$=cpu_opt($1) ; }
376         |       cpu_list ',' INDICATOR
377                         { $$= ($1) | cpu_opt($3) ;}
378         ;
379
380 string_opts:
381                         { $$=0 ;}
382         |       INDICATOR
383                         { $$= string_opt($1) ; }
384         |       INDICATOR ',' INDICATOR
385                         { if ( $1 != 'b' ||
386                                 ( $3 != 'u' && $3 != 'w' ) ) {
387                                         serror("illegal string options") ;
388                           }
389                           $$ = string_opt($1)|string_opt($3) ;
390                         }
391         ;
392
393 reg_list:
394                 '[' ']'
395                         { $$=0 ;}
396         |       '[' reg_items ']'
397                         { $$= $2 ;}
398         ;
399
400 reg_items:
401                 REG
402                         { $$= 1<<($1) ; }
403         |       reg_items ',' REG
404                         { $$= ($1) | ( 1<<($3) ) ;}
405         ;