Pristine Ack-5.5
[Ack-5.5.git] / mach / i386 / as / mach4.c
1 #define RCSID4 "$Id: mach4.c,v 1.16 1996/04/25 08:38:05 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 operation
10         :
11                 USE16
12                         {       use32 = 0; address_long = 0; operand_long = 0; }
13         |
14                 USE32
15                         {       use32 = 1; address_long = 1; operand_long = 1; }
16         |       prefix oper
17                         {       address_long = use32; operand_long = use32; }
18         |       prefix1         /* to allow for only prefixes on a line */
19         ;
20 prefix  :       /* empty */
21         |       prefix1
22         ;
23 prefix1:        prefix PREFIX   { emit1($2); }
24         |
25                 prefix ATOGGLE
26                                 { if ((($2&0200) >> 7) == address_long) {
27                                         if (pass == PASS_3) warning("address size toggle ignored");
28                                   } else {
29                                         emit1($2 & 0177);
30                                         address_long = ! address_long;
31                                   }
32                                 }
33         |
34                 prefix OTOGGLE
35                                 { if ((($2&0200) >> 7) == operand_long) {
36                                         if (pass == PASS_3) warning("operand size toggle ignored");
37                                   } else {
38                                         emit1($2 & 0177);
39                                         operand_long = ! operand_long;
40                                   }
41                                 }
42         ;
43 oper    :       NOOP_1
44                         {       emit1($1);}
45         |       NOOP_2
46                         {       emit2($1);}
47         |       JOP expr
48                         {       branch($1,$2);}
49         |       JOP2 expr
50                         {       ebranch($1,$2);}
51         |       PUSHOP ea_1
52                         {       pushop($1);}
53         |       IOOP absexp
54                         {       emit1($1);
55                                 fit(ufitb($2));
56                                 emit1((int)$2);
57                         }
58         |       IOOP R32
59                         {       if ($2!=2) serror("register error");
60                                 emit1($1+010);
61                         }
62         |       BITTEST ea_ea
63                         {       bittestop($1);}
64         |       ADDOP ea_ea
65                         {       addop($1);}
66         |       ROLOP ea_ea
67                         {       rolop($1);}
68         |       INCOP ea_1
69                         {       incop($1);}
70         |       NOTOP ea_1
71                         {       regsize($1); emit1(0366|($1&1)); ea_1($1&070);}
72         |       CALLOP ea_1
73                         {       callop($1&0xFFFF);}
74         |       CALFOP expr ':' expr
75                         {       emit1($1>>8);
76                                 adsize_exp($4, 0);
77 #ifdef RELOCATION
78                                 newrelo($2.typ, RELO2);
79 #endif
80                                 emit2((int)($2.val));
81                         }
82         |       CALFOP mem
83                         {       emit1(0377); ea_2($1&0xFF);}
84         |       ENTER absexp ',' absexp
85                         {       fit(fitw($2)); fit(fitb($4));
86                                 emit1($1); emit2((int)$2); emit1((int)$4);
87                         }
88         |       LEAOP R32 ',' mem
89                         {       emit1($1); ea_2($2<<3);}
90         |       LEAOP2 R32 ',' mem
91                         {       emit1(0xF); emit1($1); ea_2($2<<3);}
92         |       ARPLOP ea_2 ',' R32
93                         {       emit1($1); ea_2($4<<3);}
94         |       LSHFT   ea_1 ',' R32 ',' ea_2
95                         {       extshft($1, $4);}
96         |       EXTEND R32 ',' ea_2
97                         {       emit1(0xF); emit1($1); ea_2($2<<3);}
98         |       EXTOP R32 ',' ea_2
99                         {       emit1(0xF); emit1($1); ea_2($2<<3);}
100         |       EXTOP1 ea_1
101                         {       emit1(0xF); emit1($1&07); ea_1($1&070);}
102         |       IMULB   ea_1
103                         {       regsize(0); emit1(0366); ea_1($1&070);}
104         |       IMUL    ea_2
105                         {       reg_1 = IS_R32 | (address_long ? 0 : 0310);
106                                 imul(0);
107                         }
108         |       IMUL    R32 ',' ea_2
109                         {       reg_1 = $2 | IS_R32 | (address_long ? 0 : 0310);
110                                 imul($2|0x10);
111                         }
112         |       IMUL    R32 ',' ea_ea
113                         {       imul($2|0x10);}
114         |       INT absexp
115                         {       if ($2==3)
116                                         emit1(0314);
117                                 else {
118                                         fit(ufitb($2));
119                                         emit1(0315); emit1((int)$2);
120                                 }
121                         }
122         |       RET
123                         {       emit1($1);}
124         |       RET expr
125                         {       emit1($1-1);
126 #ifdef RELOCATION
127                                 newrelo($2.typ, RELO2);
128 #endif
129                                 emit2((int)($2.val));
130                         }
131         |       SETCC ea_2
132                         {       if (reg_2 & (IS_R32|IS_RSEG)) {
133                                         serror("register error");
134                                 }
135                                 emit1(0xF); emit1($1|0x90); ea_2(0);
136                         }
137         |       XCHG ea_ea
138                         {       xchg($1);}
139         |       TEST ea_ea
140                         {       test($1);}
141         |       MOV ea_ea
142                         {       mov($1);}
143         |       /*      What is really needed is just
144                         MOV R32 ',' RSYSCR
145                         but this gives a bad yacc conflict
146                 */
147                 MOV ea_1 ',' RSYSCR
148                         {
149                                 if ($1 != 1 || !(reg_1 & IS_R32))
150                                         serror("syntax error");
151                                 emit1(0xF); emit1(0x20); emit1(0300|($4<<3)|(reg_1&07));}
152         |       MOV ea_1 ',' RSYSDR
153                         {
154                                 if ($1 != 1 || !(reg_1 & IS_R32))
155                                         serror("syntax error");
156                                 emit1(0xF); emit1(0x21); emit1(0300|($4<<3)|(reg_1&07));}
157         |       MOV ea_1 ',' RSYSTR
158                         {
159                                 if ($1 != 1 || !(reg_1 & IS_R32))
160                                         serror("syntax error");
161                                 emit1(0xF); emit1(0x24); emit1(0300|($4<<3)|(reg_1&07));}
162         |       MOV RSYSCR ',' R32
163                         {
164                                 if ($1 != 1) serror("syntax error");
165                                 emit1(0xF); emit1(0x22); emit1(0300|($2<<3)|$4);}
166         |       MOV RSYSDR ',' R32
167                         {
168                                 if ($1 != 1) serror("syntax error");
169                                 emit1(0xF); emit1(0x23); emit1(0300|($2<<3)|$4);}
170         |       MOV RSYSTR ',' R32
171                         {
172                                 if ($1 != 1) serror("syntax error");
173                                 emit1(0xF); emit1(0x26); emit1(0300|($2<<3)|$4);}
174 /* Intel 80[23]87 coprocessor instructions */
175         |       FNOOP
176                         {       emit1($1); emit1($1>>8);}
177         |       FMEM mem
178                         {       emit1($1); ea_2(($1>>8)&070);}
179         |       FMEM_AX mem
180                         {       emit1($1); ea_2(($1>>8)&070);}
181         |       FMEM_AX R32
182                         {       if ($2 != 0) {
183                                         serror("illegal register");
184                                 }
185                                 emit1(FESC|7); emit1(7<<5);
186                         }
187         |       FST_I st_i
188                         {       emit1($1); emit1(($1>>8)|$2); }
189         |       FST_I ST
190                         {       emit1($1); emit1($1>>8); }
191         |       FST_ST ST ',' st_i
192                         {       emit1($1); emit1(($1>>8)|$4); }
193         |       FST_ST2 ST ',' st_i
194                         {       emit1($1); emit1(($1>>8)|$4); }
195         |       FST_ST st_i ',' ST
196                         {       emit1($1|4); emit1((($1>>8)|$2)); }
197         |       FST_ST2 st_i ',' ST
198                         {       emit1($1|4); emit1((($1>>8)|$2)^010); }
199         /* 486 instructions */
200         |       BSWAP R32
201                         {       emit1(0xF); emit1($1|$2); }
202         |       EXTOPBW ea_2 ',' reg
203                         {       regsize($1);
204                                 emit1(0xF); emit1($1); ea_2($4<<3);
205                         }
206         ;
207
208 st_i    :       ST '(' absexp ')'
209                         {       if (!fit3($3)) {
210                                         serror("illegal index in FP stack");
211                                 }
212                                 $$ = $3;
213                         }
214         ;
215
216         ;
217 mem     :       '(' expr ')'
218                         {       if (address_long) reg_2 = 05;
219                                 else reg_2 = 06;
220                                 mod_2 = 0;
221                                 rm_2 = 05;
222                                 exp_2 = $2;
223                                 RELOMOVE(rel_2, relonami);
224                                         
225                         }
226         |       bases
227                         {       exp_2.val = 0; exp_2.typ = S_ABS; indexed();}
228         |       expr bases
229                         {       exp_2 = $1; indexed();
230                                 RELOMOVE(rel_2, relonami);
231                         }
232         ;
233 bases   :       '(' R32 ')'
234                         {       if (address_long) reg_2 = $2;
235                                 else    reg_2 = sr_m[$2];
236                                 sib_2 = 0; rm_2 = 0;
237                         }
238         |       '(' R32 ')' '(' R32 scale ')'
239                         {       if (address_long) reg_2 = $2;
240                                 else reg_2 = dr_m[$2][$5];
241                                 rm_2 = 04;
242                                 sib_2 |= regindex_ind[$2][$5];
243                         }
244         |       '(' R32 '*' absexp ')'
245                         {       if ($4 == 1) {
246                                         reg_2 = $2; sib_2 = 0; rm_2 = 0;
247                                 }
248                                 else {
249                                         rm_2 = 04;
250                                         sib_2 = checkscale($4) | regindex_ind[05][$2];
251                                         reg_2 = 015;
252                                 }
253                         }
254         ;
255 scale   :       /* empty */
256                         {       sib_2 = 0;}
257         |       '*' absexp
258                         {       sib_2 = checkscale($2);}
259         ;
260 ea_2    :       mem
261         |       R8
262                         {       reg_2 = ($1 | IS_R8) | (address_long ? 0 : 0300);
263                                 rm_2 = 0;
264                         }
265         |       R32
266                         {       reg_2 = ($1 | IS_R32) | (address_long ? 0 : 0310);
267                                 rm_2 = 0;
268                         }
269         |       RSEG
270                         {       reg_2 = ($1 | IS_RSEG) | (address_long ? 0 : 020);
271                                 rm_2 = 0;
272                         }
273         |       expr
274                         {       reg_2 = IS_EXPR | (address_long ? 0 : 040);
275                                 exp_2 = $1; rm_2 = 0;
276                                 RELOMOVE(rel_2, relonami);
277                         }
278         ;
279 reg     :       R8      {       reg_1 = ($1 | IS_R8) | (address_long ? 0 : 0300);
280                                 rm_1 = 0;
281                                 $$ = $1;
282                         }
283         |       R32
284                         {       reg_1 = ($1 | IS_R32) | (address_long ? 0 : 0310);
285                                 rm_1 = 0;
286                                 $$ = $1;
287                         }
288         ;
289 ea_1    :       ea_2
290                         {       op_1 = op_2;
291                                 RELOMOVE(rel_1, rel_2);
292                         }
293         ;
294 ea_ea   :       ea_1 ',' ea_2
295         ;