blob: 1089d4061c5e5a0e248369154029439f502dcb70 [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001// Inferno utils/6a/a.y
2// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.y
3//
4// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6// Portions Copyright © 1997-1999 Vita Nuova Limited
7// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8// Portions Copyright © 2004,2006 Bruce Ellis
9// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11// Portions Copyright © 2009 The Go Authors. All rights reserved.
12//
13// Permission is hereby granted, free of charge, to any person obtaining a copy
14// of this software and associated documentation files (the "Software"), to deal
15// in the Software without restriction, including without limitation the rights
16// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17// copies of the Software, and to permit persons to whom the Software is
18// furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included in
21// all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29// THE SOFTWARE.
30
31%{
32#include <u.h>
33#include <stdio.h> /* if we don't, bison will, and a.h re-#defines getc */
34#include <libc.h>
35#include "a.h"
36#include "../../runtime/funcdata.h"
37%}
38%union {
39 Sym *sym;
40 vlong lval;
41 double dval;
42 char sval[8];
43 Addr addr;
44 Addr2 addr2;
45}
46%left '|'
47%left '^'
48%left '&'
49%left '<' '>'
50%left '+' '-'
51%left '*' '/' '%'
52%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
53%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPEG LTYPEPC
54%token <lval> LTYPES LTYPEM LTYPEI LTYPEXC LTYPEX LTYPERT LTYPEF
55%token <lval> LCONST LFP LPC LSB
56%token <lval> LBREG LLREG LSREG LFREG LMREG LXREG
57%token <dval> LFCONST
58%token <sval> LSCONST LSP
59%token <sym> LNAME LLAB LVAR
60%type <lval> con con2 expr pointer offset
61%type <addr> mem imm imm2 reg nam rel rem rim rom omem nmem
62%type <addr2> nonnon nonrel nonrem rimnon rimrem remrim
63%type <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9
64%type <addr2> spec10 spec11 spec12 spec13
65%%
66prog:
67| prog
68 {
69 stmtline = lineno;
70 }
71 line
72
73line:
74 LLAB ':'
75 {
76 if($1->value != pc)
77 yyerror("redeclaration of %s", $1->name);
78 $1->value = pc;
79 }
80 line
81| LNAME ':'
82 {
83 $1->type = LLAB;
84 $1->value = pc;
85 }
86 line
87| ';'
88| inst ';'
89| error ';'
90
91inst:
92 LNAME '=' expr
93 {
94 $1->type = LVAR;
95 $1->value = $3;
96 }
97| LVAR '=' expr
98 {
99 if($1->value != $3)
100 yyerror("redeclaration of %s", $1->name);
101 $1->value = $3;
102 }
103| LTYPE0 nonnon { outcode($1, &$2); }
104| LTYPE1 nonrem { outcode($1, &$2); }
105| LTYPE2 rimnon { outcode($1, &$2); }
106| LTYPE3 rimrem { outcode($1, &$2); }
107| LTYPE4 remrim { outcode($1, &$2); }
108| LTYPER nonrel { outcode($1, &$2); }
109| LTYPED spec1 { outcode($1, &$2); }
110| LTYPET spec2 { outcode($1, &$2); }
111| LTYPEC spec3 { outcode($1, &$2); }
112| LTYPEN spec4 { outcode($1, &$2); }
113| LTYPES spec5 { outcode($1, &$2); }
114| LTYPEM spec6 { outcode($1, &$2); }
115| LTYPEI spec7 { outcode($1, &$2); }
116| LTYPEXC spec8 { outcode($1, &$2); }
117| LTYPEX spec9 { outcode($1, &$2); }
118| LTYPERT spec10 { outcode($1, &$2); }
119| LTYPEG spec11 { outcode($1, &$2); }
120| LTYPEPC spec12 { outcode($1, &$2); }
121| LTYPEF spec13 { outcode($1, &$2); }
122
123nonnon:
124 {
125 $$.from = nullgen;
126 $$.to = nullgen;
127 }
128| ','
129 {
130 $$.from = nullgen;
131 $$.to = nullgen;
132 }
133
134rimrem:
135 rim ',' rem
136 {
137 $$.from = $1;
138 $$.to = $3;
139 }
140
141remrim:
142 rem ',' rim
143 {
144 $$.from = $1;
145 $$.to = $3;
146 }
147
148rimnon:
149 rim ','
150 {
151 $$.from = $1;
152 $$.to = nullgen;
153 }
154| rim
155 {
156 $$.from = $1;
157 $$.to = nullgen;
158 }
159
160nonrem:
161 ',' rem
162 {
163 $$.from = nullgen;
164 $$.to = $2;
165 }
166| rem
167 {
168 $$.from = nullgen;
169 $$.to = $1;
170 }
171
172nonrel:
173 ',' rel
174 {
175 $$.from = nullgen;
176 $$.to = $2;
177 }
178| rel
179 {
180 $$.from = nullgen;
181 $$.to = $1;
182 }
183| imm ',' rel
184 {
185 $$.from = $1;
186 $$.to = $3;
187 }
188
189spec1: /* DATA */
190 nam '/' con ',' imm
191 {
192 $$.from = $1;
193 $$.from.scale = $3;
194 $$.to = $5;
195 }
196
197spec2: /* TEXT */
198 mem ',' imm2
199 {
200 $$.from = $1;
201 $$.to = $3;
202 }
203| mem ',' con ',' imm2
204 {
205 $$.from = $1;
206 $$.from.scale = $3;
207 $$.to = $5;
208 }
209
210spec3: /* JMP/CALL */
211 ',' rom
212 {
213 $$.from = nullgen;
214 $$.to = $2;
215 }
216| rom
217 {
218 $$.from = nullgen;
219 $$.to = $1;
220 }
221
222spec4: /* NOP */
223 nonnon
224| nonrem
225
226spec5: /* SHL/SHR */
227 rim ',' rem
228 {
229 $$.from = $1;
230 $$.to = $3;
231 }
232| rim ',' rem ':' LLREG
233 {
234 $$.from = $1;
235 $$.to = $3;
236 if($$.from.index != D_NONE)
237 yyerror("dp shift with lhs index");
238 $$.from.index = $5;
239 }
240
241spec6: /* MOVW/MOVL */
242 rim ',' rem
243 {
244 $$.from = $1;
245 $$.to = $3;
246 }
247| rim ',' rem ':' LSREG
248 {
249 $$.from = $1;
250 $$.to = $3;
251 if($$.to.index != D_NONE)
252 yyerror("dp move with lhs index");
253 $$.to.index = $5;
254 }
255
256spec7:
257 rim ','
258 {
259 $$.from = $1;
260 $$.to = nullgen;
261 }
262| rim
263 {
264 $$.from = $1;
265 $$.to = nullgen;
266 }
267| rim ',' rem
268 {
269 $$.from = $1;
270 $$.to = $3;
271 }
272
273spec8: /* CMPPS/CMPPD */
274 reg ',' rem ',' con
275 {
276 $$.from = $1;
277 $$.to = $3;
278 $$.to.offset = $5;
279 }
280
281spec9: /* shufl */
282 imm ',' rem ',' reg
283 {
284 $$.from = $3;
285 $$.to = $5;
286 if($1.type != D_CONST)
287 yyerror("illegal constant");
288 $$.to.offset = $1.offset;
289 }
290
291spec10: /* RET/RETF */
292 {
293 $$.from = nullgen;
294 $$.to = nullgen;
295 }
296| imm
297 {
298 $$.from = $1;
299 $$.to = nullgen;
300 }
301
302spec11: /* GLOBL */
303 mem ',' imm
304 {
305 $$.from = $1;
306 $$.to = $3;
307 }
308| mem ',' con ',' imm
309 {
310 $$.from = $1;
311 $$.from.scale = $3;
312 $$.to = $5;
313 }
314
315spec12: /* PCDATA */
316 rim ',' rim
317 {
318 if($1.type != D_CONST || $3.type != D_CONST)
319 yyerror("arguments to PCDATA must be integer constants");
320 $$.from = $1;
321 $$.to = $3;
322 }
323
324spec13: /* FUNCDATA */
325 rim ',' rim
326 {
327 if($1.type != D_CONST)
328 yyerror("index for FUNCDATA must be integer constant");
329 if($3.type != D_EXTERN && $3.type != D_STATIC)
330 yyerror("value for FUNCDATA must be symbol reference");
331 $$.from = $1;
332 $$.to = $3;
333 }
334
335rem:
336 reg
337| mem
338
339rom:
340 rel
341| nmem
342| '*' reg
343 {
344 $$ = $2;
345 }
346| '*' omem
347 {
348 $$ = $2;
349 }
350| reg
351| omem
352
353rim:
354 rem
355| imm
356
357rel:
358 con '(' LPC ')'
359 {
360 $$ = nullgen;
361 $$.type = D_BRANCH;
362 $$.offset = $1 + pc;
363 }
364| LNAME offset
365 {
366 $$ = nullgen;
367 if(pass == 2)
368 yyerror("undefined label: %s", $1->name);
369 $$.type = D_BRANCH;
370 $$.offset = $2;
371 }
372| LLAB offset
373 {
374 $$ = nullgen;
375 $$.type = D_BRANCH;
376 $$.offset = $1->value + $2;
377 }
378
379reg:
380 LBREG
381 {
382 $$ = nullgen;
383 $$.type = $1;
384 }
385| LFREG
386 {
387 $$ = nullgen;
388 $$.type = $1;
389 }
390| LLREG
391 {
392 $$ = nullgen;
393 $$.type = $1;
394 }
395| LMREG
396 {
397 $$ = nullgen;
398 $$.type = $1;
399 }
400| LSP
401 {
402 $$ = nullgen;
403 $$.type = D_SP;
404 }
405| LSREG
406 {
407 $$ = nullgen;
408 $$.type = $1;
409 }
410| LXREG
411 {
412 $$ = nullgen;
413 $$.type = $1;
414 }
415imm2:
416 '$' con2
417 {
418 $$ = nullgen;
419 $$.type = D_CONST;
420 $$.offset = $2;
421 }
422
423imm:
424 '$' con
425 {
426 $$ = nullgen;
427 $$.type = D_CONST;
428 $$.offset = $2;
429 }
430| '$' nam
431 {
432 $$ = $2;
433 $$.index = $2.type;
434 $$.type = D_ADDR;
435 /*
436 if($2.type == D_AUTO || $2.type == D_PARAM)
437 yyerror("constant cannot be automatic: %s",
438 $2.sym->name);
439 */
440 }
441| '$' LSCONST
442 {
443 $$ = nullgen;
444 $$.type = D_SCONST;
445 memcpy($$.u.sval, $2, sizeof($$.u.sval));
446 }
447| '$' LFCONST
448 {
449 $$ = nullgen;
450 $$.type = D_FCONST;
451 $$.u.dval = $2;
452 }
453| '$' '(' LFCONST ')'
454 {
455 $$ = nullgen;
456 $$.type = D_FCONST;
457 $$.u.dval = $3;
458 }
459| '$' '(' '-' LFCONST ')'
460 {
461 $$ = nullgen;
462 $$.type = D_FCONST;
463 $$.u.dval = -$4;
464 }
465| '$' '-' LFCONST
466 {
467 $$ = nullgen;
468 $$.type = D_FCONST;
469 $$.u.dval = -$3;
470 }
471
472mem:
473 omem
474| nmem
475
476omem:
477 con
478 {
479 $$ = nullgen;
480 $$.type = D_INDIR+D_NONE;
481 $$.offset = $1;
482 }
483| con '(' LLREG ')'
484 {
485 $$ = nullgen;
486 $$.type = D_INDIR+$3;
487 $$.offset = $1;
488 }
489| con '(' LSP ')'
490 {
491 $$ = nullgen;
492 $$.type = D_INDIR+D_SP;
493 $$.offset = $1;
494 }
495| con '(' LSREG ')'
496 {
497 $$ = nullgen;
498 $$.type = D_INDIR+$3;
499 $$.offset = $1;
500 }
501| con '(' LLREG '*' con ')'
502 {
503 $$ = nullgen;
504 $$.type = D_INDIR+D_NONE;
505 $$.offset = $1;
506 $$.index = $3;
507 $$.scale = $5;
508 checkscale($$.scale);
509 }
510| con '(' LLREG ')' '(' LLREG '*' con ')'
511 {
512 $$ = nullgen;
513 $$.type = D_INDIR+$3;
514 $$.offset = $1;
515 $$.index = $6;
516 $$.scale = $8;
517 checkscale($$.scale);
518 }
519| con '(' LLREG ')' '(' LSREG '*' con ')'
520 {
521 $$ = nullgen;
522 $$.type = D_INDIR+$3;
523 $$.offset = $1;
524 $$.index = $6;
525 $$.scale = $8;
526 checkscale($$.scale);
527 }
528| '(' LLREG ')'
529 {
530 $$ = nullgen;
531 $$.type = D_INDIR+$2;
532 }
533| '(' LSP ')'
534 {
535 $$ = nullgen;
536 $$.type = D_INDIR+D_SP;
537 }
538| '(' LLREG '*' con ')'
539 {
540 $$ = nullgen;
541 $$.type = D_INDIR+D_NONE;
542 $$.index = $2;
543 $$.scale = $4;
544 checkscale($$.scale);
545 }
546| '(' LLREG ')' '(' LLREG '*' con ')'
547 {
548 $$ = nullgen;
549 $$.type = D_INDIR+$2;
550 $$.index = $5;
551 $$.scale = $7;
552 checkscale($$.scale);
553 }
554
555nmem:
556 nam
557 {
558 $$ = $1;
559 }
560| nam '(' LLREG '*' con ')'
561 {
562 $$ = $1;
563 $$.index = $3;
564 $$.scale = $5;
565 checkscale($$.scale);
566 }
567
568nam:
569 LNAME offset '(' pointer ')'
570 {
571 $$ = nullgen;
572 $$.type = $4;
573 $$.sym = linklookup(ctxt, $1->name, 0);
574 $$.offset = $2;
575 }
576| LNAME '<' '>' offset '(' LSB ')'
577 {
578 $$ = nullgen;
579 $$.type = D_STATIC;
580 $$.sym = linklookup(ctxt, $1->name, 1);
581 $$.offset = $4;
582 }
583
584offset:
585 {
586 $$ = 0;
587 }
588| '+' con
589 {
590 $$ = $2;
591 }
592| '-' con
593 {
594 $$ = -$2;
595 }
596
597pointer:
598 LSB
599| LSP
600 {
601 $$ = D_AUTO;
602 }
603| LFP
604
605con:
606 LCONST
607| LVAR
608 {
609 $$ = $1->value;
610 }
611| '-' con
612 {
613 $$ = -$2;
614 }
615| '+' con
616 {
617 $$ = $2;
618 }
619| '~' con
620 {
621 $$ = ~$2;
622 }
623| '(' expr ')'
624 {
625 $$ = $2;
626 }
627
628con2:
629 LCONST
630 {
631 $$ = ($1 & 0xffffffffLL) +
632 ((vlong)ArgsSizeUnknown << 32);
633 }
634| '-' LCONST
635 {
636 $$ = (-$2 & 0xffffffffLL) +
637 ((vlong)ArgsSizeUnknown << 32);
638 }
639| LCONST '-' LCONST
640 {
641 $$ = ($1 & 0xffffffffLL) +
642 (($3 & 0xffffLL) << 32);
643 }
644| '-' LCONST '-' LCONST
645 {
646 $$ = (-$2 & 0xffffffffLL) +
647 (($4 & 0xffffLL) << 32);
648 }
649
650expr:
651 con
652| expr '+' expr
653 {
654 $$ = $1 + $3;
655 }
656| expr '-' expr
657 {
658 $$ = $1 - $3;
659 }
660| expr '*' expr
661 {
662 $$ = $1 * $3;
663 }
664| expr '/' expr
665 {
666 $$ = $1 / $3;
667 }
668| expr '%' expr
669 {
670 $$ = $1 % $3;
671 }
672| expr '<' '<' expr
673 {
674 $$ = $1 << $4;
675 }
676| expr '>' '>' expr
677 {
678 $$ = $1 >> $4;
679 }
680| expr '&' expr
681 {
682 $$ = $1 & $3;
683 }
684| expr '^' expr
685 {
686 $$ = $1 ^ $3;
687 }
688| expr '|' expr
689 {
690 $$ = $1 | $3;
691 }