xref: /inferno-os/utils/0a/a.y (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 %{
2 #include "a.h"
3 %}
4 %union
5 {
6 	Sym	*sym;
7 	long	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>	LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
19 %token	<lval>	LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
20 %token	<lval>	LTYPEB LTYPEC LTYPED LTYPEE LTYPEF
21 %token	<lval>	LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
22 %token	<lval>	LCONST LSP LSB LFP LPC LHI LLO LMREG
23 %token	<lval>	LTYPEX LREG LFREG LFCREG LR LM LF
24 %token	<lval>	LFCR LSCHED
25 %token	<dval>	LFCONST
26 %token	<sval>	LSCONST
27 %token	<sym>	LNAME LLAB LVAR
28 %type	<lval>	con expr pointer offset sreg
29 %type	<gen>	gen vgen lgen vlgen rel reg freg mreg fcreg
30 %type	<gen>	imm ximm ireg name oreg imr nireg fgen
31 %%
32 prog:
33 |	prog line
34 
35 line:
36 	LLAB ':'
37 	{
38 		if($1->value != pc)
39 			yyerror("redeclaration of %s", $1->name);
40 		$1->value = pc;
41 	}
42 	line
43 |	LNAME ':'
44 	{
45 		$1->type = LLAB;
46 		$1->value = pc;
47 	}
48 	line
49 |	LNAME '=' expr ';'
50 	{
51 		$1->type = LVAR;
52 		$1->value = $3;
53 	}
54 |	LVAR '=' expr ';'
55 	{
56 		if($1->value != $3)
57 			yyerror("redeclaration of %s", $1->name);
58 		$1->value = $3;
59 	}
60 |	LSCHED ';'
61 	{
62 		nosched = $1;
63 	}
64 |	';'
65 |	inst ';'
66 |	error ';'
67 
68 inst:
69 /*
70  * Immed-type
71  */
72 	LTYPE1 imr ',' sreg ',' reg
73 	{
74 		outcode($1, &$2, $4, &$6);
75 	}
76 |	LTYPE1 imr ',' reg
77 	{
78 		outcode($1, &$2, NREG, &$4);
79 	}
80 /*
81  * NOR
82  */
83 |	LTYPE2 imr ',' sreg ',' imr
84 	{
85 		outcode($1, &$2, $4, &$6);
86 	}
87 |	LTYPE2 imr ',' imr
88 	{
89 		outcode($1, &$2, NREG, &$4);
90 	}
91 /*
92  * LOAD/STORE, but not MOVW
93  */
94 |	LTYPE3 lgen ',' gen
95 	{
96 		if(!isreg(&$2) && !isreg(&$4))
97 			print("one side must be register\n");
98 		outcode($1, &$2, NREG, &$4);
99 	}
100 /*
101  * SPECIAL
102  */
103 |	LTYPE4 comma
104 	{
105 		outcode($1, &nullgen, NREG, &nullgen);
106 	}
107 /*
108  * MOVW
109  */
110 |	LTYPE5 vlgen ',' vgen
111 	{
112 		if(!isreg(&$2) && !isreg(&$4))
113 			print("one side must be register\n");
114 		outcode($1, &$2, NREG, &$4);
115 	}
116 /*
117  * MUL/DIV
118  */
119 |	LTYPE6 reg ',' sreg comma
120 	{
121 		outcode($1, &$2, $4, &nullgen);
122 	}
123 |	LTYPE6 reg ',' sreg ',' reg
124 	{
125 		outcode($1, &$2, $4, &$6);
126 	}
127 /*
128  * JMP/JAL
129  */
130 |	LTYPE7 comma rel
131 	{
132 		outcode($1, &nullgen, NREG, &$3);
133 	}
134 |	LTYPE7 comma nireg
135 	{
136 		outcode($1, &nullgen, NREG, &$3);
137 	}
138 |	LTYPE8 comma rel
139 	{
140 		outcode($1, &nullgen, NREG, &$3);
141 	}
142 |	LTYPE8 comma nireg
143 	{
144 		outcode($1, &nullgen, NREG, &$3);
145 	}
146 |	LTYPE8 sreg ',' nireg
147 	{
148 		outcode($1, &nullgen, $2, &$4);
149 	}
150 /*
151  * BEQ/BNE
152  */
153 |	LTYPE9 gen ',' rel
154 	{
155 		if(!isreg(&$2))
156 			print("left side must be register\n");
157 		outcode($1, &$2, NREG, &$4);
158 	}
159 |	LTYPE9 gen ',' sreg ',' rel
160 	{
161 		if(!isreg(&$2))
162 			print("left side must be register\n");
163 		outcode($1, &$2, $4, &$6);
164 	}
165 /*
166  * B-other
167  */
168 |	LTYPEA gen ',' rel
169 	{
170 		if(!isreg(&$2))
171 			print("left side must be register\n");
172 		outcode($1, &$2, NREG, &$4);
173 	}
174 /*
175  * TEXT/GLOBL
176  */
177 |	LTYPEB name ',' imm
178 	{
179 		outcode($1, &$2, NREG, &$4);
180 	}
181 |	LTYPEB name ',' con ',' imm
182 	{
183 		outcode($1, &$2, $4, &$6);
184 	}
185 /*
186  * DATA
187  */
188 |	LTYPEC name '/' con ',' ximm
189 	{
190 		outcode($1, &$2, $4, &$6);
191 	}
192 /*
193  * floating-type
194  */
195 |	LTYPED freg ',' freg
196 	{
197 		outcode($1, &$2, NREG, &$4);
198 	}
199 |	LTYPEE freg ',' freg
200 	{
201 		outcode($1, &$2, NREG, &$4);
202 	}
203 |	LTYPEE freg ',' LFREG ',' freg
204 	{
205 		outcode($1, &$2, $4, &$6);
206 	}
207 |	LTYPEF freg ',' LFREG comma
208 	{
209 		outcode($1, &$2, $4, &nullgen);
210 	}
211 /*
212  * coprocessor branch
213  */
214 |	LTYPEG comma rel
215 	{
216 		outcode($1, &nullgen, NREG, &$3);
217 	}
218 /*
219  * word
220  */
221 |	LTYPEH comma ximm
222 	{
223 		outcode($1, &nullgen, NREG, &$3);
224 	}
225 /*
226  * NOP
227  */
228 |	LTYPEI comma
229 	{
230 		outcode($1, &nullgen, NREG, &nullgen);
231 	}
232 |	LTYPEI ',' vgen
233 	{
234 		outcode($1, &nullgen, NREG, &$3);
235 	}
236 |	LTYPEI vgen comma
237 	{
238 		outcode($1, &$2, NREG, &nullgen);
239 	}
240 /*
241  * BREAK -- overloaded with CACHE opcode
242  */
243 |	LTYPEJ comma
244 	{
245 		outcode($1, &nullgen, NREG, &nullgen);
246 	}
247 |	LTYPEJ vgen ',' vgen
248 	{
249 		outcode($1, &$2, NREG, &$4);
250 	}
251 
252 comma:
253 |	','
254 
255 rel:
256 	con '(' LPC ')'
257 	{
258 		$$ = nullgen;
259 		$$.type = D_BRANCH;
260 		$$.offset = $1 + pc;
261 	}
262 |	LNAME offset
263 	{
264 		$$ = nullgen;
265 		if(pass == 2)
266 			yyerror("undefined label: %s", $1->name);
267 		$$.type = D_BRANCH;
268 		$$.sym = $1;
269 		$$.offset = $2;
270 	}
271 |	LLAB offset
272 	{
273 		$$ = nullgen;
274 		$$.type = D_BRANCH;
275 		$$.sym = $1;
276 		$$.offset = $1->value + $2;
277 	}
278 
279 vlgen:
280 	lgen
281 |	fgen
282 |	mreg
283 |	fcreg
284 |	LHI
285 	{
286 		$$ = nullgen;
287 		$$.type = D_HI;
288 	}
289 |	LLO
290 	{
291 		$$ = nullgen;
292 		$$.type = D_LO;
293 	}
294 
295 vgen:
296 	gen
297 |	fgen
298 |	mreg
299 |	fcreg
300 |	LHI
301 	{
302 		$$ = nullgen;
303 		$$.type = D_HI;
304 	}
305 |	LLO
306 	{
307 		$$ = nullgen;
308 		$$.type = D_LO;
309 	}
310 
311 lgen:
312 	gen
313 |	ximm
314 
315 fgen:
316 	freg
317 
318 mreg:
319 	LMREG
320 	{
321 		$$ = nullgen;
322 		$$.type = D_MREG;
323 		$$.reg = $1;
324 	}
325 |	LM '(' con ')'
326 	{
327 		$$ = nullgen;
328 		$$.type = D_MREG;
329 		$$.reg = $3;
330 	}
331 
332 fcreg:
333 	LFCREG
334 	{
335 		$$ = nullgen;
336 		$$.type = D_FCREG;
337 		$$.reg = $1;
338 	}
339 |	LFCR '(' con ')'
340 	{
341 		$$ = nullgen;
342 		$$.type = D_FCREG;
343 		$$.reg = $3;
344 	}
345 
346 freg:
347 	LFREG
348 	{
349 		$$ = nullgen;
350 		$$.type = D_FREG;
351 		$$.reg = $1;
352 	}
353 |	LF '(' con ')'
354 	{
355 		$$ = nullgen;
356 		$$.type = D_FREG;
357 		$$.reg = $3;
358 	}
359 
360 ximm:	'$' con
361 	{
362 		$$ = nullgen;
363 		$$.type = D_CONST;
364 		$$.offset = $2;
365 	}
366 |	'$' oreg
367 	{
368 		$$ = $2;
369 		$$.type = D_CONST;
370 	}
371 |	'$' '*' '$' oreg
372 	{
373 		$$ = $4;
374 		$$.type = D_OCONST;
375 	}
376 |	'$' LSCONST
377 	{
378 		$$ = nullgen;
379 		$$.type = D_SCONST;
380 		memcpy($$.sval, $2, sizeof($$.sval));
381 	}
382 |	'$' LFCONST
383 	{
384 		$$ = nullgen;
385 		$$.type = D_FCONST;
386 		$$.dval = $2;
387 	}
388 |	'$' '-' LFCONST
389 	{
390 		$$ = nullgen;
391 		$$.type = D_FCONST;
392 		$$.dval = -$3;
393 	}
394 
395 nireg:
396 	ireg
397 |	con ireg
398 	{
399 		if($1 != 0)
400 			yyerror("offset must be zero");
401 		$$ = $2;
402 	}
403 |	name
404 	{
405 		$$ = $1;
406 		if($1.name != D_EXTERN && $1.name != D_STATIC) {
407 		}
408 	}
409 
410 ireg:
411 	'(' sreg ')'
412 	{
413 		$$ = nullgen;
414 		$$.type = D_OREG;
415 		$$.reg = $2;
416 		$$.offset = 0;
417 	}
418 
419 gen:
420 	reg
421 |	con
422 	{
423 		$$ = nullgen;
424 		$$.type = D_OREG;
425 		$$.offset = $1;
426 	}
427 |	oreg
428 
429 oreg:
430 	name
431 |	name '(' sreg ')'
432 	{
433 		$$ = $1;
434 		$$.type = D_OREG;
435 		$$.reg = $3;
436 	}
437 |	'(' sreg ')'
438 	{
439 		$$ = nullgen;
440 		$$.type = D_OREG;
441 		$$.reg = $2;
442 		$$.offset = 0;
443 	}
444 |	con '(' sreg ')'
445 	{
446 		$$ = nullgen;
447 		$$.type = D_OREG;
448 		$$.reg = $3;
449 		$$.offset = $1;
450 	}
451 
452 imr:
453 	reg
454 |	imm
455 
456 imm:	'$' con
457 	{
458 		$$ = nullgen;
459 		$$.type = D_CONST;
460 		$$.offset = $2;
461 	}
462 
463 reg:
464 	sreg
465 	{
466 		$$ = nullgen;
467 		$$.type = D_REG;
468 		$$.reg = $1;
469 	}
470 
471 sreg:
472 	LREG
473 |	LR '(' expr ')'
474 	{
475 		if($$ < 0 || $$ >= NREG)
476 			print("register value out of range\n");
477 		$$ = $3;
478 	}
479 
480 name:
481 	con '(' pointer ')'
482 	{
483 		$$ = nullgen;
484 		$$.type = D_OREG;
485 		$$.name = $3;
486 		$$.sym = S;
487 		$$.offset = $1;
488 	}
489 |	LNAME offset '(' pointer ')'
490 	{
491 		$$ = nullgen;
492 		$$.type = D_OREG;
493 		$$.name = $4;
494 		$$.sym = $1;
495 		$$.offset = $2;
496 	}
497 |	LNAME '<' '>' offset '(' LSB ')'
498 	{
499 		$$ = nullgen;
500 		$$.type = D_OREG;
501 		$$.name = D_STATIC;
502 		$$.sym = $1;
503 		$$.offset = $4;
504 	}
505 
506 offset:
507 	{
508 		$$ = 0;
509 	}
510 |	'+' con
511 	{
512 		$$ = $2;
513 	}
514 |	'-' con
515 	{
516 		$$ = -$2;
517 	}
518 
519 pointer:
520 	LSB
521 |	LSP
522 |	LFP
523 
524 con:
525 	LCONST
526 |	LVAR
527 	{
528 		$$ = $1->value;
529 	}
530 |	'-' con
531 	{
532 		$$ = -$2;
533 	}
534 |	'+' con
535 	{
536 		$$ = $2;
537 	}
538 |	'~' con
539 	{
540 		$$ = ~$2;
541 	}
542 |	'(' expr ')'
543 	{
544 		$$ = $2;
545 	}
546 
547 expr:
548 	con
549 |	expr '+' expr
550 	{
551 		$$ = $1 + $3;
552 	}
553 |	expr '-' expr
554 	{
555 		$$ = $1 - $3;
556 	}
557 |	expr '*' expr
558 	{
559 		$$ = $1 * $3;
560 	}
561 |	expr '/' expr
562 	{
563 		$$ = $1 / $3;
564 	}
565 |	expr '%' expr
566 	{
567 		$$ = $1 % $3;
568 	}
569 |	expr '<' '<' expr
570 	{
571 		$$ = $1 << $4;
572 	}
573 |	expr '>' '>' expr
574 	{
575 		$$ = $1 >> $4;
576 	}
577 |	expr '&' expr
578 	{
579 		$$ = $1 & $3;
580 	}
581 |	expr '^' expr
582 	{
583 		$$ = $1 ^ $3;
584 	}
585 |	expr '|' expr
586 	{
587 		$$ = $1 | $3;
588 	}
589