xref: /plan9-contrib/sys/src/cmd/8a/a.y (revision 6520663fb7ebac8d17e4a1dbc55d10bf525f7b14)
1 %{
2 #include "a.h"
3 %}
4 %union	{
5 	Sym	*sym;
6 	long	lval;
7 	struct {
8 		long v1;
9 		long v2;
10 	} con2;
11 	double	dval;
12 	char	sval[8];
13 	Gen	gen;
14 	Gen2	gen2;
15 }
16 %left	'|'
17 %left	'^'
18 %left	'&'
19 %left	'<' '>'
20 %left	'+' '-'
21 %left	'*' '/' '%'
22 %token	<lval>	LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
23 %token	<lval>	LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG
24 %token	<lval>	LCONST LFP LPC LSB
25 %token	<lval>	LBREG LLREG LSREG LFREG
26 %token	<dval>	LFCONST
27 %token	<sval>	LSCONST LSP
28 %token	<sym>	LNAME LLAB LVAR
29 %type	<lval>	con expr pointer offset
30 %type	<con2>	con2
31 %type	<gen>	mem imm imm2 reg nam rel rem rim rom omem nmem
32 %type	<gen2>	nonnon nonrel nonrem rimnon rimrem remrim
33 %type	<gen2>	spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8
34 %%
35 prog:
36 |	prog line
37 
38 line:
39 	LLAB ':'
40 	{
41 		if($1->value != pc)
42 			yyerror("redeclaration of %s", $1->name);
43 		$1->value = pc;
44 	}
45 	line
46 |	LNAME ':'
47 	{
48 		$1->type = LLAB;
49 		$1->value = pc;
50 	}
51 	line
52 |	';'
53 |	inst ';'
54 |	error ';'
55 
56 inst:
57 	LNAME '=' expr
58 	{
59 		$1->type = LVAR;
60 		$1->value = $3;
61 	}
62 |	LVAR '=' expr
63 	{
64 		if($1->value != $3)
65 			yyerror("redeclaration of %s", $1->name);
66 		$1->value = $3;
67 	}
68 |	LTYPE0 nonnon	{ outcode($1, &$2); }
69 |	LTYPE1 nonrem	{ outcode($1, &$2); }
70 |	LTYPE2 rimnon	{ outcode($1, &$2); }
71 |	LTYPE3 rimrem	{ outcode($1, &$2); }
72 |	LTYPE4 remrim	{ outcode($1, &$2); }
73 |	LTYPER nonrel	{ outcode($1, &$2); }
74 |	LTYPED spec1	{ outcode($1, &$2); }
75 |	LTYPET spec2	{ outcode($1, &$2); }
76 |	LTYPEC spec3	{ outcode($1, &$2); }
77 |	LTYPEN spec4	{ outcode($1, &$2); }
78 |	LTYPES spec5	{ outcode($1, &$2); }
79 |	LTYPEM spec6	{ outcode($1, &$2); }
80 |	LTYPEI spec7	{ outcode($1, &$2); }
81 |	LTYPEG spec8	{ outcode($1, &$2); }
82 
83 nonnon:
84 	{
85 		$$.from = nullgen;
86 		$$.to = nullgen;
87 	}
88 |	','
89 	{
90 		$$.from = nullgen;
91 		$$.to = nullgen;
92 	}
93 
94 rimrem:
95 	rim ',' rem
96 	{
97 		$$.from = $1;
98 		$$.to = $3;
99 	}
100 
101 remrim:
102 	rem ',' rim
103 	{
104 		$$.from = $1;
105 		$$.to = $3;
106 	}
107 
108 rimnon:
109 	rim ','
110 	{
111 		$$.from = $1;
112 		$$.to = nullgen;
113 	}
114 |	rim
115 	{
116 		$$.from = $1;
117 		$$.to = nullgen;
118 	}
119 
120 nonrem:
121 	',' rem
122 	{
123 		$$.from = nullgen;
124 		$$.to = $2;
125 	}
126 |	rem
127 	{
128 		$$.from = nullgen;
129 		$$.to = $1;
130 	}
131 
132 nonrel:
133 	',' rel
134 	{
135 		$$.from = nullgen;
136 		$$.to = $2;
137 	}
138 |	rel
139 	{
140 		$$.from = nullgen;
141 		$$.to = $1;
142 	}
143 
144 spec1:	/* DATA */
145 	nam '/' con ',' imm
146 	{
147 		$$.from = $1;
148 		$$.from.scale = $3;
149 		$$.to = $5;
150 	}
151 
152 spec2:	/* TEXT */
153 	mem ',' imm
154 	{
155 		$$.from = $1;
156 		$$.to = $3;
157 	}
158 |	mem ',' con ',' imm
159 	{
160 		$$.from = $1;
161 		$$.from.scale = $3;
162 		$$.to = $5;
163 	}
164 
165 spec3:	/* JMP/CALL */
166 	',' rom
167 	{
168 		$$.from = nullgen;
169 		$$.to = $2;
170 	}
171 |	rom
172 	{
173 		$$.from = nullgen;
174 		$$.to = $1;
175 	}
176 
177 spec4:	/* NOP */
178 	nonnon
179 |	nonrem
180 
181 spec5:	/* SHL/SHR */
182 	rim ',' rem
183 	{
184 		$$.from = $1;
185 		$$.to = $3;
186 	}
187 |	rim ',' rem ':' LLREG
188 	{
189 		$$.from = $1;
190 		$$.to = $3;
191 		if($$.from.index != D_NONE)
192 			yyerror("dp shift with lhs index");
193 		$$.from.index = $5;
194 	}
195 
196 spec6:	/* MOVW/MOVL */
197 	rim ',' rem
198 	{
199 		$$.from = $1;
200 		$$.to = $3;
201 	}
202 |	rim ',' rem ':' LSREG
203 	{
204 		$$.from = $1;
205 		$$.to = $3;
206 		if($$.to.index != D_NONE)
207 			yyerror("dp move with lhs index");
208 		$$.to.index = $5;
209 	}
210 
211 spec7:
212 	rim ','
213 	{
214 		$$.from = $1;
215 		$$.to = nullgen;
216 	}
217 |	rim
218 	{
219 		$$.from = $1;
220 		$$.to = nullgen;
221 	}
222 |	rim ',' rem
223 	{
224 		$$.from = $1;
225 		$$.to = $3;
226 	}
227 
228 spec8:	/* GLOBL */
229 	mem ',' imm
230 	{
231 		$$.from = $1;
232 		$$.to = $3;
233 	}
234 |	mem ',' con ',' imm
235 	{
236 		$$.from = $1;
237 		$$.from.scale = $3;
238 		$$.to = $5;
239 	}
240 
241 rem:
242 	reg
243 |	mem
244 
245 rom:
246 	rel
247 |	nmem
248 |	'*' reg
249 	{
250 		$$ = $2;
251 	}
252 |	'*' omem
253 	{
254 		$$ = $2;
255 	}
256 |	reg
257 |	omem
258 |	imm
259 
260 rim:
261 	rem
262 |	imm
263 
264 rel:
265 	con '(' LPC ')'
266 	{
267 		$$ = nullgen;
268 		$$.type = D_BRANCH;
269 		$$.offset = $1 + pc;
270 	}
271 |	LNAME offset
272 	{
273 		$$ = nullgen;
274 		if(pass == 2)
275 			yyerror("undefined label: %s", $1->name);
276 		$$.type = D_BRANCH;
277 		$$.sym = $1;
278 		$$.offset = $2;
279 	}
280 |	LLAB offset
281 	{
282 		$$ = nullgen;
283 		$$.type = D_BRANCH;
284 		$$.sym = $1;
285 		$$.offset = $1->value + $2;
286 	}
287 
288 reg:
289 	LBREG
290 	{
291 		$$ = nullgen;
292 		$$.type = $1;
293 	}
294 |	LFREG
295 	{
296 		$$ = nullgen;
297 		$$.type = $1;
298 	}
299 |	LLREG
300 	{
301 		$$ = nullgen;
302 		$$.type = $1;
303 	}
304 |	LSP
305 	{
306 		$$ = nullgen;
307 		$$.type = D_SP;
308 	}
309 |	LSREG
310 	{
311 		$$ = nullgen;
312 		$$.type = $1;
313 	}
314 
315 imm:
316 	'$' con
317 	{
318 		$$ = nullgen;
319 		$$.type = D_CONST;
320 		$$.offset = $2;
321 	}
322 |	'$' nam
323 	{
324 		$$ = $2;
325 		$$.index = $2.type;
326 		$$.type = D_ADDR;
327 		/*
328 		if($2.type == D_AUTO || $2.type == D_PARAM)
329 			yyerror("constant cannot be automatic: %s",
330 				$2.sym->name);
331 		 */
332 	}
333 |	'$' LSCONST
334 	{
335 		$$ = nullgen;
336 		$$.type = D_SCONST;
337 		memcpy($$.sval, $2, sizeof($$.sval));
338 	}
339 |	'$' LFCONST
340 	{
341 		$$ = nullgen;
342 		$$.type = D_FCONST;
343 		$$.dval = $2;
344 	}
345 |	'$' '(' LFCONST ')'
346 	{
347 		$$ = nullgen;
348 		$$.type = D_FCONST;
349 		$$.dval = $3;
350 	}
351 |	'$' '-' LFCONST
352 	{
353 		$$ = nullgen;
354 		$$.type = D_FCONST;
355 		$$.dval = -$3;
356 	}
357 
358 imm2:
359 	'$' con2
360 	{
361 		$$ = nullgen;
362 		$$.type = D_CONST2;
363 		$$.offset = $2.v1;
364 		$$.offset2 = $2.v2;
365 	}
366 
367 con2:
368 	LCONST
369 	{
370 		$$.v1 = $1;
371 		$$.v2 = 0;
372 	}
373 |	'-' LCONST
374 	{
375 		$$.v1 = -$2;
376 		$$.v2 = 0;
377 	}
378 |	LCONST '-' LCONST
379 	{
380 		$$.v1 = $1;
381 		$$.v2 = $3;
382 	}
383 |	'-' LCONST '-' LCONST
384 	{
385 		$$.v1 = -$2;
386 		$$.v2 = $4;
387 	}
388 
389 mem:
390 	omem
391 |	nmem
392 
393 omem:
394 	con
395 	{
396 		$$ = nullgen;
397 		$$.type = D_INDIR+D_NONE;
398 		$$.offset = $1;
399 	}
400 |	con '(' LLREG ')'
401 	{
402 		$$ = nullgen;
403 		$$.type = D_INDIR+$3;
404 		$$.offset = $1;
405 	}
406 |	con '(' LSP ')'
407 	{
408 		$$ = nullgen;
409 		$$.type = D_INDIR+D_SP;
410 		$$.offset = $1;
411 	}
412 |	con '(' LLREG '*' con ')'
413 	{
414 		$$ = nullgen;
415 		$$.type = D_INDIR+D_NONE;
416 		$$.offset = $1;
417 		$$.index = $3;
418 		$$.scale = $5;
419 		checkscale($$.scale);
420 	}
421 |	con '(' LLREG ')' '(' LLREG '*' con ')'
422 	{
423 		$$ = nullgen;
424 		$$.type = D_INDIR+$3;
425 		$$.offset = $1;
426 		$$.index = $6;
427 		$$.scale = $8;
428 		checkscale($$.scale);
429 	}
430 |	'(' LLREG ')'
431 	{
432 		$$ = nullgen;
433 		$$.type = D_INDIR+$2;
434 	}
435 |	'(' LSP ')'
436 	{
437 		$$ = nullgen;
438 		$$.type = D_INDIR+D_SP;
439 	}
440 |	con '(' LSREG ')'
441 	{
442 		$$ = nullgen;
443 		$$.type = D_INDIR+$3;
444 		$$.offset = $1;
445 	}
446 |	'(' LLREG '*' con ')'
447 	{
448 		$$ = nullgen;
449 		$$.type = D_INDIR+D_NONE;
450 		$$.index = $2;
451 		$$.scale = $4;
452 		checkscale($$.scale);
453 	}
454 |	'(' LLREG ')' '(' LLREG '*' con ')'
455 	{
456 		$$ = nullgen;
457 		$$.type = D_INDIR+$2;
458 		$$.index = $5;
459 		$$.scale = $7;
460 		checkscale($$.scale);
461 	}
462 
463 nmem:
464 	nam
465 	{
466 		$$ = $1;
467 	}
468 |	nam '(' LLREG '*' con ')'
469 	{
470 		$$ = $1;
471 		$$.index = $3;
472 		$$.scale = $5;
473 		checkscale($$.scale);
474 	}
475 
476 nam:
477 	LNAME offset '(' pointer ')'
478 	{
479 		$$ = nullgen;
480 		$$.type = $4;
481 		$$.sym = $1;
482 		$$.offset = $2;
483 	}
484 |	LNAME '<' '>' offset '(' LSB ')'
485 	{
486 		$$ = nullgen;
487 		$$.type = D_STATIC;
488 		$$.sym = $1;
489 		$$.offset = $4;
490 	}
491 
492 offset:
493 	{
494 		$$ = 0;
495 	}
496 |	'+' con
497 	{
498 		$$ = $2;
499 	}
500 |	'-' con
501 	{
502 		$$ = -$2;
503 	}
504 
505 pointer:
506 	LSB
507 |	LSP
508 	{
509 		$$ = D_AUTO;
510 	}
511 |	LFP
512 
513 con:
514 	LCONST
515 |	LVAR
516 	{
517 		$$ = $1->value;
518 	}
519 |	'-' con
520 	{
521 		$$ = -$2;
522 	}
523 |	'+' con
524 	{
525 		$$ = $2;
526 	}
527 |	'~' con
528 	{
529 		$$ = ~$2;
530 	}
531 |	'(' expr ')'
532 	{
533 		$$ = $2;
534 	}
535 
536 expr:
537 	con
538 |	expr '+' expr
539 	{
540 		$$ = $1 + $3;
541 	}
542 |	expr '-' expr
543 	{
544 		$$ = $1 - $3;
545 	}
546 |	expr '*' expr
547 	{
548 		$$ = $1 * $3;
549 	}
550 |	expr '/' expr
551 	{
552 		$$ = $1 / $3;
553 	}
554 |	expr '%' expr
555 	{
556 		$$ = $1 % $3;
557 	}
558 |	expr '<' '<' expr
559 	{
560 		$$ = $1 << $4;
561 	}
562 |	expr '>' '>' expr
563 	{
564 		$$ = $1 >> $4;
565 	}
566 |	expr '&' expr
567 	{
568 		$$ = $1 & $3;
569 	}
570 |	expr '^' expr
571 	{
572 		$$ = $1 ^ $3;
573 	}
574 |	expr '|' expr
575 	{
576 		$$ = $1 | $3;
577 	}
578