xref: /plan9-contrib/sys/src/cmd/ia/a.y (revision ce95e1b3727b9cb1c223ffbed69aff21a8ced255)
1 %{
2 #include "a.h"
3 %}
4 %union
5 {
6 	Sym	*sym;
7 	vlong	lval;
8 	double	dval;
9 	char	sval[8];
10 	Gen	gen;
11 }
12 %left	'|'
13 %left	'^'
14 %left	'&'
15 %left	'<' '>'
16 %left	'+' '-'
17 %left	'*' '/' '%'
18 %token	<lval>	LADD LMUL LBEQ LBR LBRET LCALL LFLT2 LFLT3
19 %token	<lval>	LMOVB LMOVBU LMOVW LMOVF LLUI LSYS LSYS0 LCSR LSWAP LAMO
20 %token	<lval>	LCONST LSP LSB LFP LPC LREG LFREG LR FR LCTL
21 %token	<lval>	LDATA LTEXT LWORD
22 %token	<sval>	LSCONST
23 %token	<dval>	LFCONST
24 %token	<sym>	LNAME LLAB LVAR
25 %type	<lval>	con expr pointer offset sreg freg oprrr
26 %type	<gen>	rreg dreg ctlreg drreg
27 %type	<gen>	addr name oreg rel imm ximm fimm
28 %%
29 prog:
30 |	prog line
31 
32 line:
33 	LLAB ':'
34 	{
35 		if($1->value != pc)
36 			yyerror("redeclaration of %s", $1->name);
37 		$1->value = pc;
38 	}
39 	line
40 |	LNAME ':'
41 	{
42 		$1->type = LLAB;
43 		$1->value = pc;
44 	}
45 	line
46 |	LNAME '=' expr ';'
47 	{
48 		$1->type = LVAR;
49 		$1->value = $3;
50 	}
51 |	LVAR '=' expr ';'
52 	{
53 		if($1->value != $3)
54 			yyerror("redeclaration of %s", $1->name);
55 		$1->value = $3;
56 	}
57 |	';'
58 |	inst ';'
59 |	error ';'
60 
61 inst:
62 	LADD imm ',' rreg
63 	{
64 		outcode($1, &$2, NREG, &$4);
65 	}
66 |	oprrr rreg ',' rreg
67 	{
68 		outcode($1, &$2, NREG, &$4);
69 	}
70 |	LADD imm ',' sreg ',' rreg
71 	{
72 		outcode($1, &$2, $4, &$6);
73 	}
74 |	oprrr rreg ',' sreg ',' rreg
75 	{
76 		outcode($1, &$2, $4, &$6);
77 	}
78 
79 |	LFLT2 drreg ',' drreg
80 	{
81 		outcode($1, &$2, NREG, &$4);
82 	}
83 |	LFLT3 drreg ',' freg ',' drreg
84 	{
85 		outcode($1, &$2, $4, &$6);
86 	}
87 
88 |	LBEQ rreg ',' sreg ',' rel
89 	{
90 		outcode($1, &$2, $4, &$6);
91 	}
92 
93 |	LBEQ rreg ',' rel
94 	{
95 		Gen regzero;
96 		regzero = nullgen;
97 		regzero.type = D_REG;
98 		regzero.reg = 0;
99 		outcode($1, &regzero, $2.reg, &$4);
100 	}
101 
102 |	LBR	rel
103 	{
104 		outcode($1, &nullgen, NREG, &$2);
105 	}
106 
107 |	LBR oreg
108 	{
109 		outcode($1, &nullgen, NREG, &$2);
110 	}
111 
112 
113 |	LBRET
114 	{
115 		outcode($1, &nullgen, NREG, &nullgen);
116 	}
117 
118 |	LCALL sreg ',' addr
119 	{
120 		outcode($1, &nullgen, $2, &$4);
121 	}
122 |	LCALL sreg ',' rel
123 	{
124 		outcode($1, &nullgen, $2, &$4);
125 	}
126 
127 |	LMOVB addr ',' rreg
128 	{
129 		outcode($1, &$2, NREG, &$4);
130 	}
131 |	LMOVBU addr ',' rreg
132 	{
133 		outcode($1, &$2, NREG, &$4);
134 	}
135 |	LMOVB rreg ',' addr
136 	{
137 		outcode($1, &$2, NREG, &$4);
138 	}
139 
140 |	LMOVF addr ',' dreg
141 	{
142 		outcode($1, &$2, NREG, &$4);
143 	}
144 |	LMOVF dreg ',' addr
145 	{
146 		outcode($1, &$2, NREG, &$4);
147 	}
148 |	LMOVF dreg ',' dreg
149 	{
150 		outcode($1, &$2, NREG, &$4);
151 	}
152 
153 
154 |	LMOVW imm ',' rreg
155 	{
156 		outcode($1, &$2, NREG, &$4);
157 	}
158 |	LMOVW ximm ',' rreg
159 	{
160 		outcode($1, &$2, NREG, &$4);
161 	}
162 |	LMOVW rreg ',' rreg
163 	{
164 		outcode($1, &$2, NREG, &$4);
165 	}
166 |	LMOVW addr ',' rreg
167 	{
168 		outcode($1, &$2, NREG, &$4);
169 	}
170 |	LMOVW rreg ',' addr
171 	{
172 		outcode($1, &$2, NREG, &$4);
173 	}
174 |	LMOVW rreg ',' ctlreg
175 	{
176 		Gen regzero;
177 		regzero = nullgen;
178 		regzero.type = D_REG;
179 		regzero.reg = 0;
180 		outcode(ACSRRW, &$4, $2.reg, &regzero);
181 	}
182 |	LMOVW imm ',' ctlreg
183 	{
184 		Gen regzero;
185 		int r = $2.offset;
186 		if(r < 0 || r >= NREG)
187 			yyerror("immediate value out of range");
188 		regzero = nullgen;
189 		regzero.type = D_REG;
190 		regzero.reg = 0;
191 		outcode(ACSRRWI, &$4, r, &regzero);
192 	}
193 |	LMOVW ctlreg ',' rreg
194 	{
195 		outcode(ACSRRS, &$2, REGZERO, &$4);
196 	}
197 
198 |	LLUI name ',' rreg
199 	{
200 		outcode($1, &$2, NREG, &$4);
201 	}
202 |	LLUI imm ',' rreg
203 	{
204 		outcode($1, &$2, NREG, &$4);
205 	}
206 
207 
208 |	LSYS imm
209 	{
210 		outcode($1, &nullgen, NREG, &$2);
211 	}
212 
213 |	LSYS0
214 	{
215 		Gen syscon;
216 		syscon = nullgen;
217 		syscon.type = D_CONST;
218 		syscon.offset = $1;
219 		outcode(ASYS, &nullgen, NREG, &syscon);
220 	}
221 
222 |	LCSR ctlreg ',' sreg ',' rreg
223 	{
224 		outcode($1, &$2, $4, &$6);
225 	}
226 
227 |	LCSR ctlreg ',' '$' con ',' rreg
228 	{
229 		if($5 < 0 || $5 >= NREG)
230 			yyerror("immediate value out of range");
231 		outcode($1 + (ACSRRWI-ACSRRW), &$2, $5, &$7);
232 	}
233 
234 |	LSWAP rreg ',' sreg ',' rreg
235 	{
236 		outcode($1, &$2, $4, &$6);
237 	}
238 
239 |	LAMO con ',' rreg ',' sreg ',' rreg
240 	{
241 		outcode($1, &$4, ($2<<16)|$6, &$8);
242 	}
243 
244 |	LTEXT name ',' imm
245 	{
246 		outcode($1, &$2, NREG, &$4);
247 	}
248 |	LTEXT name ',' con ',' imm
249 	{
250 		outcode($1, &$2, $4, &$6);
251 	}
252 
253 |	LDATA name '/' con ',' imm
254 	{
255 		outcode($1, &$2, $4, &$6);
256 	}
257 |	LDATA name '/' con ',' ximm
258 	{
259 		outcode($1, &$2, $4, &$6);
260 	}
261 |	LDATA name '/' con ',' fimm
262 	{
263 		outcode($1, &$2, $4, &$6);
264 	}
265 
266 |	LWORD imm
267 	{
268 		outcode($1, &nullgen, NREG, &$2);
269 	}
270 
271 rel:
272 	con '(' LPC ')'
273 	{
274 		$$ = nullgen;
275 		$$.type = D_BRANCH;
276 		$$.offset = $1 + pc;
277 	}
278 |	LNAME offset
279 	{
280 		$$ = nullgen;
281 		if(pass == 2)
282 			yyerror("undefined label: %s", $1->name);
283 		$$.type = D_BRANCH;
284 		$$.sym = $1;
285 		$$.offset = $2;
286 	}
287 |	LLAB offset
288 	{
289 		$$ = nullgen;
290 		$$.type = D_BRANCH;
291 		$$.sym = $1;
292 		$$.offset = $1->value + $2;
293 	}
294 
295 oprrr:
296 	LADD
297 |	LMUL
298 
299 addr:
300 	oreg
301 |	name
302 
303 oreg:
304 	'(' sreg ')'
305 	{
306 		$$ = nullgen;
307 		$$.type = D_OREG;
308 		$$.reg = $2;
309 		$$.offset = 0;
310 	}
311 |	con '(' sreg ')'
312 	{
313 		$$ = nullgen;
314 		$$.type = D_OREG;
315 		$$.reg = $3;
316 		$$.offset = $1;
317 	}
318 
319 name:
320 	con '(' pointer ')'
321 	{
322 		$$ = nullgen;
323 		$$.type = D_OREG;
324 		$$.name = $3;
325 		$$.sym = S;
326 		$$.offset = $1;
327 	}
328 |	LNAME offset '(' pointer ')'
329 	{
330 		$$ = nullgen;
331 		$$.type = D_OREG;
332 		$$.name = $4;
333 		$$.sym = $1;
334 		$$.offset = $2;
335 	}
336 |	LNAME '<' '>' offset '(' LSB ')'
337 	{
338 		$$ = nullgen;
339 		$$.type = D_OREG;
340 		$$.name = D_STATIC;
341 		$$.sym = $1;
342 		$$.offset = $4;
343 	}
344 
345 offset:
346 	{
347 		$$ = 0;
348 	}
349 |	'+' con
350 	{
351 		$$ = $2;
352 	}
353 |	'-' con
354 	{
355 		$$ = -$2;
356 	}
357 
358 pointer:
359 	LSB
360 |	LSP
361 |	LFP
362 
363 rreg:
364 	sreg
365 	{
366 		$$ = nullgen;
367 		$$.type = D_REG;
368 		$$.reg = $1;
369 	}
370 
371 dreg:
372 	freg
373 	{
374 		$$ = nullgen;
375 		$$.type = D_FREG;
376 		$$.reg = $1;
377 	}
378 
379 drreg:
380 	dreg
381 |	rreg
382 
383 sreg:
384 	LREG
385 |	LR '(' expr ')'
386 	{
387 		if($3 < 0 || $3 >= NREG)
388 			yyerror("register value out of range");
389 		$$ = $3;
390 	}
391 
392 freg:
393 	LFREG
394 |	FR '(' expr ')'
395 	{
396 		if($3 < 0 || $3 >= NREG)
397 			yyerror("register value out of range");
398 		$$ = $3;
399 	}
400 
401 ctlreg:
402 	LCTL '(' expr ')'
403 	{
404 		if($3 < 0 || $3 >= 0xFFF)
405 			yyerror("CSR value out of range");
406 		$$ = nullgen;
407 		$$.type = D_CTLREG;
408 		$$.offset = $3;
409 	}
410 
411 ximm:
412 	'$' addr
413 	{
414 		$$ = $2;
415 		$$.type = D_CONST;
416 	}
417 |	'$' LSCONST
418 	{
419 		$$ = nullgen;
420 		$$.type = D_SCONST;
421 		memcpy($$.sval, $2, sizeof($$.sval));
422 	}
423 
424 fimm:
425 	'$' LFCONST
426 	{
427 		$$ = nullgen;
428 		$$.type = D_FCONST;
429 		$$.dval = $2;
430 	}
431 |	'$' '-' LFCONST
432 	{
433 		$$ = nullgen;
434 		$$.type = D_FCONST;
435 		$$.dval = -$3;
436 	}
437 
438 imm:
439 	'$' con
440 	{
441 		$$ = nullgen;
442 		$$.type = D_CONST;
443 		$$.offset = $2;
444 		if(thechar == 'j' && (vlong)$$.offset != $2){
445 			$$.type = D_VCONST;
446 			$$.vval = $2;
447 		}
448 	}
449 
450 con:
451 	LCONST
452 |	LVAR
453 	{
454 		$$ = $1->value;
455 	}
456 |	'-' con
457 	{
458 		$$ = -$2;
459 	}
460 |	'+' con
461 	{
462 		$$ = $2;
463 	}
464 |	'~' con
465 	{
466 		$$ = ~$2;
467 	}
468 |	'(' expr ')'
469 	{
470 		$$ = $2;
471 	}
472 
473 expr:
474 	con
475 |	expr '+' expr
476 	{
477 		$$ = $1 + $3;
478 	}
479 |	expr '-' expr
480 	{
481 		$$ = $1 - $3;
482 	}
483 |	expr '*' expr
484 	{
485 		$$ = $1 * $3;
486 	}
487 |	expr '/' expr
488 	{
489 		$$ = $1 / $3;
490 	}
491 |	expr '%' expr
492 	{
493 		$$ = $1 % $3;
494 	}
495 |	expr '<' '<' expr
496 	{
497 		$$ = $1 << $4;
498 	}
499 |	expr '>' '>' expr
500 	{
501 		$$ = $1 >> $4;
502 	}
503 |	expr '&' expr
504 	{
505 		$$ = $1 & $3;
506 	}
507 |	expr '^' expr
508 	{
509 		$$ = $1 ^ $3;
510 	}
511 |	expr '|' expr
512 	{
513 		$$ = $1 | $3;
514 	}
515