blob: 6bcf1313bf653548e2fd69699dac0f3fa1f0cf02 [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001// Inferno utils/8a/a.y
2// http://code.google.com/p/inferno-os/source/browse/utils/8a/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 int32 lval;
41 struct {
42 int32 v1;
43 int32 v2;
44 } con2;
45 double dval;
46 char sval[8];
47 Addr addr;
48 Addr2 addr2;
49}
50%left '|'
51%left '^'
52%left '&'
53%left '<' '>'
54%left '+' '-'
55%left '*' '/' '%'
56%token <lval> LTYPE0 LTYPE1 LTYPE2 LTYPE3 LTYPE4
57%token <lval> LTYPEC LTYPED LTYPEN LTYPER LTYPET LTYPES LTYPEM LTYPEI LTYPEG LTYPEXC
58%token <lval> LTYPEX LTYPEPC LTYPEF LCONST LFP LPC LSB
59%token <lval> LBREG LLREG LSREG LFREG LXREG
60%token <dval> LFCONST
61%token <sval> LSCONST LSP
62%token <sym> LNAME LLAB LVAR
63%type <lval> con expr pointer offset
64%type <con2> con2
65%type <addr> mem imm imm2 reg nam rel rem rim rom omem nmem
66%type <addr2> nonnon nonrel nonrem rimnon rimrem remrim
67%type <addr2> spec1 spec2 spec3 spec4 spec5 spec6 spec7 spec8 spec9 spec10 spec11 spec12
68%%
69prog:
70| prog
71 {
72 stmtline = lineno;
73 }
74 line
75
76line:
77 LLAB ':'
78 {
79 if($1->value != pc)
80 yyerror("redeclaration of %s", $1->name);
81 $1->value = pc;
82 }
83 line
84| LNAME ':'
85 {
86 $1->type = LLAB;
87 $1->value = pc;
88 }
89 line
90| ';'
91| inst ';'
92| error ';'
93
94inst:
95 LNAME '=' expr
96 {
97 $1->type = LVAR;
98 $1->value = $3;
99 }
100| LVAR '=' expr
101 {
102 if($1->value != $3)
103 yyerror("redeclaration of %s", $1->name);
104 $1->value = $3;
105 }
106| LTYPE0 nonnon { outcode($1, &$2); }
107| LTYPE1 nonrem { outcode($1, &$2); }
108| LTYPE2 rimnon { outcode($1, &$2); }
109| LTYPE3 rimrem { outcode($1, &$2); }
110| LTYPE4 remrim { outcode($1, &$2); }
111| LTYPER nonrel { outcode($1, &$2); }
112| LTYPED spec1 { outcode($1, &$2); }
113| LTYPET spec2 { outcode($1, &$2); }
114| LTYPEC spec3 { outcode($1, &$2); }
115| LTYPEN spec4 { outcode($1, &$2); }
116| LTYPES spec5 { outcode($1, &$2); }
117| LTYPEM spec6 { outcode($1, &$2); }
118| LTYPEI spec7 { outcode($1, &$2); }
119| LTYPEG spec8 { outcode($1, &$2); }
120| LTYPEXC spec9 { outcode($1, &$2); }
121| LTYPEX spec10 { outcode($1, &$2); }
122| LTYPEPC spec11 { outcode($1, &$2); }
123| LTYPEF spec12 { outcode($1, &$2); }
124
125nonnon:
126 {
127 $$.from = nullgen;
128 $$.to = nullgen;
129 }
130| ','
131 {
132 $$.from = nullgen;
133 $$.to = nullgen;
134 }
135
136rimrem:
137 rim ',' rem
138 {
139 $$.from = $1;
140 $$.to = $3;
141 }
142
143remrim:
144 rem ',' rim
145 {
146 $$.from = $1;
147 $$.to = $3;
148 }
149
150rimnon:
151 rim ','
152 {
153 $$.from = $1;
154 $$.to = nullgen;
155 }
156| rim
157 {
158 $$.from = $1;
159 $$.to = nullgen;
160 }
161
162nonrem:
163 ',' rem
164 {
165 $$.from = nullgen;
166 $$.to = $2;
167 }
168| rem
169 {
170 $$.from = nullgen;
171 $$.to = $1;
172 }
173
174nonrel:
175 ',' rel
176 {
177 $$.from = nullgen;
178 $$.to = $2;
179 }
180| rel
181 {
182 $$.from = nullgen;
183 $$.to = $1;
184 }
185| imm ',' rel
186 {
187 $$.from = $1;
188 $$.to = $3;
189 }
190
191spec1: /* DATA */
192 nam '/' con ',' imm
193 {
194 $$.from = $1;
195 $$.from.scale = $3;
196 $$.to = $5;
197 }
198
199spec2: /* TEXT */
200 mem ',' imm2
201 {
202 $$.from = $1;
203 $$.to = $3;
204 }
205| mem ',' con ',' imm2
206 {
207 $$.from = $1;
208 $$.from.scale = $3;
209 $$.to = $5;
210 }
211
212spec3: /* JMP/CALL */
213 ',' rom
214 {
215 $$.from = nullgen;
216 $$.to = $2;
217 }
218| rom
219 {
220 $$.from = nullgen;
221 $$.to = $1;
222 }
223| '*' nam
224 {
225 $$.from = nullgen;
226 $$.to = $2;
227 $$.to.index = $2.type;
228 $$.to.type = D_INDIR+D_ADDR;
229 }
230
231spec4: /* NOP */
232 nonnon
233| nonrem
234
235spec5: /* SHL/SHR */
236 rim ',' rem
237 {
238 $$.from = $1;
239 $$.to = $3;
240 }
241| rim ',' rem ':' LLREG
242 {
243 $$.from = $1;
244 $$.to = $3;
245 if($$.from.index != D_NONE)
246 yyerror("dp shift with lhs index");
247 $$.from.index = $5;
248 }
249
250spec6: /* MOVW/MOVL */
251 rim ',' rem
252 {
253 $$.from = $1;
254 $$.to = $3;
255 }
256| rim ',' rem ':' LSREG
257 {
258 $$.from = $1;
259 $$.to = $3;
260 if($$.to.index != D_NONE)
261 yyerror("dp move with lhs index");
262 $$.to.index = $5;
263 }
264
265spec7:
266 rim ','
267 {
268 $$.from = $1;
269 $$.to = nullgen;
270 }
271| rim
272 {
273 $$.from = $1;
274 $$.to = nullgen;
275 }
276| rim ',' rem
277 {
278 $$.from = $1;
279 $$.to = $3;
280 }
281
282spec8: /* GLOBL */
283 mem ',' imm
284 {
285 $$.from = $1;
286 $$.to = $3;
287 }
288| mem ',' con ',' imm
289 {
290 $$.from = $1;
291 $$.from.scale = $3;
292 $$.to = $5;
293 }
294
295spec9: /* CMPPS/CMPPD */
296 reg ',' rem ',' con
297 {
298 $$.from = $1;
299 $$.to = $3;
300 $$.to.offset = $5;
301 }
302
303spec10: /* PINSRD */
304 imm ',' rem ',' reg
305 {
306 $$.from = $3;
307 $$.to = $5;
308 if($1.type != D_CONST)
309 yyerror("illegal constant");
310 $$.to.offset = $1.offset;
311 }
312
313spec11: /* PCDATA */
314 rim ',' rim
315 {
316 if($1.type != D_CONST || $3.type != D_CONST)
317 yyerror("arguments to PCDATA must be integer constants");
318 $$.from = $1;
319 $$.to = $3;
320 }
321
322spec12: /* FUNCDATA */
323 rim ',' rim
324 {
325 if($1.type != D_CONST)
326 yyerror("index for FUNCDATA must be integer constant");
327 if($3.type != D_EXTERN && $3.type != D_STATIC)
328 yyerror("value for FUNCDATA must be symbol reference");
329 $$.from = $1;
330 $$.to = $3;
331 }
332
333rem:
334 reg
335| mem
336
337rom:
338 rel
339| nmem
340| '*' reg
341 {
342 $$ = $2;
343 }
344| '*' omem
345 {
346 $$ = $2;
347 }
348| reg
349| omem
350| imm
351
352rim:
353 rem
354| imm
355
356rel:
357 con '(' LPC ')'
358 {
359 $$ = nullgen;
360 $$.type = D_BRANCH;
361 $$.offset = $1 + pc;
362 }
363| LNAME offset
364 {
365 $$ = nullgen;
366 if(pass == 2)
367 yyerror("undefined label: %s", $1->name);
368 $$.type = D_BRANCH;
369 $$.offset = $2;
370 }
371| LLAB offset
372 {
373 $$ = nullgen;
374 $$.type = D_BRANCH;
375 $$.offset = $1->value + $2;
376 }
377
378reg:
379 LBREG
380 {
381 $$ = nullgen;
382 $$.type = $1;
383 }
384| LFREG
385 {
386 $$ = nullgen;
387 $$.type = $1;
388 }
389| LLREG
390 {
391 $$ = nullgen;
392 $$.type = $1;
393 }
394| LXREG
395 {
396 $$ = nullgen;
397 $$.type = $1;
398 }
399| LSP
400 {
401 $$ = nullgen;
402 $$.type = D_SP;
403 }
404| LSREG
405 {
406 $$ = nullgen;
407 $$.type = $1;
408 }
409
410imm:
411 '$' con
412 {
413 $$ = nullgen;
414 $$.type = D_CONST;
415 $$.offset = $2;
416 }
417| '$' nam
418 {
419 $$ = $2;
420 $$.index = $2.type;
421 $$.type = D_ADDR;
422 /*
423 if($2.type == D_AUTO || $2.type == D_PARAM)
424 yyerror("constant cannot be automatic: %s",
425 $2.sym->name);
426 */
427 }
428| '$' LSCONST
429 {
430 $$ = nullgen;
431 $$.type = D_SCONST;
432 memcpy($$.u.sval, $2, sizeof($$.u.sval));
433 }
434| '$' LFCONST
435 {
436 $$ = nullgen;
437 $$.type = D_FCONST;
438 $$.u.dval = $2;
439 }
440| '$' '(' LFCONST ')'
441 {
442 $$ = nullgen;
443 $$.type = D_FCONST;
444 $$.u.dval = $3;
445 }
446| '$' '(' '-' LFCONST ')'
447 {
448 $$ = nullgen;
449 $$.type = D_FCONST;
450 $$.u.dval = -$4;
451 }
452| '$' '-' LFCONST
453 {
454 $$ = nullgen;
455 $$.type = D_FCONST;
456 $$.u.dval = -$3;
457 }
458
459imm2:
460 '$' con2
461 {
462 $$ = nullgen;
463 $$.type = D_CONST2;
464 $$.offset = $2.v1;
465 $$.offset2 = $2.v2;
466 }
467
468con2:
469 LCONST
470 {
471 $$.v1 = $1;
472 $$.v2 = ArgsSizeUnknown;
473 }
474| '-' LCONST
475 {
476 $$.v1 = -$2;
477 $$.v2 = ArgsSizeUnknown;
478 }
479| LCONST '-' LCONST
480 {
481 $$.v1 = $1;
482 $$.v2 = $3;
483 }
484| '-' LCONST '-' LCONST
485 {
486 $$.v1 = -$2;
487 $$.v2 = $4;
488 }
489
490mem:
491 omem
492| nmem
493
494omem:
495 con
496 {
497 $$ = nullgen;
498 $$.type = D_INDIR+D_NONE;
499 $$.offset = $1;
500 }
501| con '(' LLREG ')'
502 {
503 $$ = nullgen;
504 $$.type = D_INDIR+$3;
505 $$.offset = $1;
506 }
507| con '(' LSP ')'
508 {
509 $$ = nullgen;
510 $$.type = D_INDIR+D_SP;
511 $$.offset = $1;
512 }
513| con '(' LLREG '*' con ')'
514 {
515 $$ = nullgen;
516 $$.type = D_INDIR+D_NONE;
517 $$.offset = $1;
518 $$.index = $3;
519 $$.scale = $5;
520 checkscale($$.scale);
521 }
522| con '(' LLREG ')' '(' LLREG '*' con ')'
523 {
524 $$ = nullgen;
525 $$.type = D_INDIR+$3;
526 $$.offset = $1;
527 $$.index = $6;
528 $$.scale = $8;
529 checkscale($$.scale);
530 }
531| con '(' LLREG ')' '(' LSREG '*' con ')'
532 {
533 $$ = nullgen;
534 $$.type = D_INDIR+$3;
535 $$.offset = $1;
536 $$.index = $6;
537 $$.scale = $8;
538 checkscale($$.scale);
539 }
540| '(' LLREG ')'
541 {
542 $$ = nullgen;
543 $$.type = D_INDIR+$2;
544 }
545| '(' LSP ')'
546 {
547 $$ = nullgen;
548 $$.type = D_INDIR+D_SP;
549 }
550| con '(' LSREG ')'
551 {
552 $$ = nullgen;
553 $$.type = D_INDIR+$3;
554 $$.offset = $1;
555 }
556| '(' LLREG '*' con ')'
557 {
558 $$ = nullgen;
559 $$.type = D_INDIR+D_NONE;
560 $$.index = $2;
561 $$.scale = $4;
562 checkscale($$.scale);
563 }
564| '(' LLREG ')' '(' LLREG '*' con ')'
565 {
566 $$ = nullgen;
567 $$.type = D_INDIR+$2;
568 $$.index = $5;
569 $$.scale = $7;
570 checkscale($$.scale);
571 }
572
573nmem:
574 nam
575 {
576 $$ = $1;
577 }
578| nam '(' LLREG '*' con ')'
579 {
580 $$ = $1;
581 $$.index = $3;
582 $$.scale = $5;
583 checkscale($$.scale);
584 }
585
586nam:
587 LNAME offset '(' pointer ')'
588 {
589 $$ = nullgen;
590 $$.type = $4;
591 $$.sym = linklookup(ctxt, $1->name, 0);
592 $$.offset = $2;
593 }
594| LNAME '<' '>' offset '(' LSB ')'
595 {
596 $$ = nullgen;
597 $$.type = D_STATIC;
598 $$.sym = linklookup(ctxt, $1->name, 1);
599 $$.offset = $4;
600 }
601
602offset:
603 {
604 $$ = 0;
605 }
606| '+' con
607 {
608 $$ = $2;
609 }
610| '-' con
611 {
612 $$ = -$2;
613 }
614
615pointer:
616 LSB
617| LSP
618 {
619 $$ = D_AUTO;
620 }
621| LFP
622
623con:
624 LCONST
625| LVAR
626 {
627 $$ = $1->value;
628 }
629| '-' con
630 {
631 $$ = -$2;
632 }
633| '+' con
634 {
635 $$ = $2;
636 }
637| '~' con
638 {
639 $$ = ~$2;
640 }
641| '(' expr ')'
642 {
643 $$ = $2;
644 }
645
646expr:
647 con
648| expr '+' expr
649 {
650 $$ = $1 + $3;
651 }
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 << $4;
671 }
672| expr '>' '>' expr
673 {
674 $$ = $1 >> $4;
675 }
676| expr '&' expr
677 {
678 $$ = $1 & $3;
679 }
680| expr '^' expr
681 {
682 $$ = $1 ^ $3;
683 }
684| expr '|' expr
685 {
686 $$ = $1 | $3;
687 }