]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/new5a/a.y
d365c753433f1052d0b5d322e95f36d1750c0cef
[gostls13.git] / src / cmd / new5a / a.y
1 // Inferno utils/5a/a.y
2 // http://code.google.com/p/inferno-os/source/browse/utils/5a/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 {
40         Sym     *sym;
41         int32   lval;
42         double  dval;
43         char    sval[8];
44         Addr    addr;
45 }
46 %left   '|'
47 %left   '^'
48 %left   '&'
49 %left   '<' '>'
50 %left   '+' '-'
51 %left   '*' '/' '%'
52 %token  <lval>  LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
53 %token  <lval>  LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
54 %token  <lval>  LTYPEB LTYPEC LTYPED LTYPEE
55 %token  <lval>  LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
56 %token  <lval>  LTYPEL LTYPEM LTYPEN LTYPEBX LTYPEPLD
57 %token  <lval>  LCONST LSP LSB LFP LPC
58 %token  <lval>  LTYPEX LTYPEPC LTYPEF LR LREG LF LFREG LC LCREG LPSR LFCR
59 %token  <lval>  LCOND LS LAT
60 %token  <dval>  LFCONST
61 %token  <sval>  LSCONST
62 %token  <sym>   LNAME LLAB LVAR
63 %type   <lval>  con expr oexpr pointer offset sreg spreg creg
64 %type   <lval>  rcon cond reglist
65 %type   <addr>  gen rel reg regreg freg shift fcon frcon
66 %type   <addr>  imm ximm name oreg ireg nireg ioreg imsr
67 %%
68 prog:
69 |       prog
70         {
71                 stmtline = lineno;
72         }
73         line
74
75 line:
76         LNAME ':'
77         {
78                 $1 = labellookup($1);
79                 if($1->type == LLAB && $1->value != pc)
80                         yyerror("redeclaration of %s", $1->labelname);
81                 $1->type = LLAB;
82                 $1->value = pc;
83         }
84         line
85 |       LNAME '=' expr ';'
86         {
87                 $1->type = LVAR;
88                 $1->value = $3;
89         }
90 |       LVAR '=' expr ';'
91         {
92                 if($1->value != $3)
93                         yyerror("redeclaration of %s", $1->name);
94                 $1->value = $3;
95         }
96 |       ';'
97 |       inst ';'
98 |       error ';'
99
100 inst:
101 /*
102  * ADD
103  */
104         LTYPE1 cond imsr ',' spreg ',' reg
105         {
106                 outcode($1, $2, &$3, $5, &$7);
107         }
108 |       LTYPE1 cond imsr ',' spreg ','
109         {
110                 outcode($1, $2, &$3, $5, &nullgen);
111         }
112 |       LTYPE1 cond imsr ',' reg
113         {
114                 outcode($1, $2, &$3, NREG, &$5);
115         }
116 /*
117  * MVN
118  */
119 |       LTYPE2 cond imsr ',' reg
120         {
121                 outcode($1, $2, &$3, NREG, &$5);
122         }
123 /*
124  * MOVW
125  */
126 |       LTYPE3 cond gen ',' gen
127         {
128                 outcode($1, $2, &$3, NREG, &$5);
129         }
130 /*
131  * B/BL
132  */
133 |       LTYPE4 cond comma rel
134         {
135                 outcode($1, $2, &nullgen, NREG, &$4);
136         }
137 |       LTYPE4 cond comma nireg
138         {
139                 outcode($1, $2, &nullgen, NREG, &$4);
140         }
141 /*
142  * BX
143  */
144 |       LTYPEBX comma ireg
145         {
146                 outcode($1, Always, &nullgen, NREG, &$3);
147         }
148 /*
149  * BEQ
150  */
151 |       LTYPE5 comma rel
152         {
153                 outcode($1, Always, &nullgen, NREG, &$3);
154         }
155 /*
156  * SWI
157  */
158 |       LTYPE6 cond comma gen
159         {
160                 outcode($1, $2, &nullgen, NREG, &$4);
161         }
162 /*
163  * CMP
164  */
165 |       LTYPE7 cond imsr ',' spreg comma
166         {
167                 outcode($1, $2, &$3, $5, &nullgen);
168         }
169 /*
170  * MOVM
171  */
172 |       LTYPE8 cond ioreg ',' '[' reglist ']'
173         {
174                 Addr g;
175
176                 g = nullgen;
177                 g.type = D_CONST;
178                 g.offset = $6;
179                 outcode($1, $2, &$3, NREG, &g);
180         }
181 |       LTYPE8 cond '[' reglist ']' ',' ioreg
182         {
183                 Addr g;
184
185                 g = nullgen;
186                 g.type = D_CONST;
187                 g.offset = $4;
188                 outcode($1, $2, &g, NREG, &$7);
189         }
190 /*
191  * SWAP
192  */
193 |       LTYPE9 cond reg ',' ireg ',' reg
194         {
195                 outcode($1, $2, &$5, $3.reg, &$7);
196         }
197 |       LTYPE9 cond reg ',' ireg comma
198         {
199                 outcode($1, $2, &$5, $3.reg, &$3);
200         }
201 |       LTYPE9 cond comma ireg ',' reg
202         {
203                 outcode($1, $2, &$4, $6.reg, &$6);
204         }
205 /*
206  * RET
207  */
208 |       LTYPEA cond comma
209         {
210                 outcode($1, $2, &nullgen, NREG, &nullgen);
211         }
212 /*
213  * TEXT/GLOBL
214  */
215 |       LTYPEB name ',' imm
216         {
217                 settext($2.sym);
218                 $4.type = D_CONST2;
219                 $4.offset2 = ArgsSizeUnknown;
220                 outcode($1, Always, &$2, 0, &$4);
221         }
222 |       LTYPEB name ',' con ',' imm
223         {
224                 settext($2.sym);
225                 $6.type = D_CONST2;
226                 $6.offset2 = ArgsSizeUnknown;
227                 outcode($1, Always, &$2, $4, &$6);
228         }
229 |       LTYPEB name ',' con ',' imm '-' con
230         {
231                 settext($2.sym);
232                 $6.type = D_CONST2;
233                 $6.offset2 = $8;
234                 outcode($1, Always, &$2, $4, &$6);
235         }
236 /*
237  * DATA
238  */
239 |       LTYPEC name '/' con ',' ximm
240         {
241                 outcode($1, Always, &$2, $4, &$6);
242         }
243 /*
244  * CASE
245  */
246 |       LTYPED cond reg comma
247         {
248                 outcode($1, $2, &$3, NREG, &nullgen);
249         }
250 /*
251  * word
252  */
253 |       LTYPEH comma ximm
254         {
255                 outcode($1, Always, &nullgen, NREG, &$3);
256         }
257 /*
258  * floating-point coprocessor
259  */
260 |       LTYPEI cond freg ',' freg
261         {
262                 outcode($1, $2, &$3, NREG, &$5);
263         }
264 |       LTYPEK cond frcon ',' freg
265         {
266                 outcode($1, $2, &$3, NREG, &$5);
267         }
268 |       LTYPEK cond frcon ',' LFREG ',' freg
269         {
270                 outcode($1, $2, &$3, $5, &$7);
271         }
272 |       LTYPEL cond freg ',' freg comma
273         {
274                 outcode($1, $2, &$3, $5.reg, &nullgen);
275         }
276 /*
277  * MCR MRC
278  */
279 |       LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
280         {
281                 Addr g;
282
283                 g = nullgen;
284                 g.type = D_CONST;
285                 g.offset =
286                         (0xe << 24) |           /* opcode */
287                         ($1 << 20) |            /* MCR/MRC */
288                         ($2 << 28) |            /* scond */
289                         (($3 & 15) << 8) |      /* coprocessor number */
290                         (($5 & 7) << 21) |      /* coprocessor operation */
291                         (($7 & 15) << 12) |     /* arm register */
292                         (($9 & 15) << 16) |     /* Crn */
293                         (($11 & 15) << 0) |     /* Crm */
294                         (($12 & 7) << 5) |      /* coprocessor information */
295                         (1<<4);                 /* must be set */
296                 outcode(AMRC, Always, &nullgen, NREG, &g);
297         }
298 /*
299  * MULL r1,r2,(hi,lo)
300  */
301 |       LTYPEM cond reg ',' reg ',' regreg
302         {
303                 outcode($1, $2, &$3, $5.reg, &$7);
304         }
305 /*
306  * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4
307  * MULAW{T,B} r1,r2,r3,r4
308  */
309 |       LTYPEN cond reg ',' reg ',' reg ',' spreg
310         {
311                 $7.type = D_REGREG2;
312                 $7.offset = $9;
313                 outcode($1, $2, &$3, $5.reg, &$7);
314         }
315 /*
316  * PLD
317  */
318 |       LTYPEPLD oreg
319         {
320                 outcode($1, Always, &$2, NREG, &nullgen);
321         }
322 /*
323  * PCDATA
324  */
325 |       LTYPEPC gen ',' gen
326         {
327                 if($2.type != D_CONST || $4.type != D_CONST)
328                         yyerror("arguments to PCDATA must be integer constants");
329                 outcode($1, Always, &$2, NREG, &$4);
330         }
331 /*
332  * FUNCDATA
333  */
334 |       LTYPEF gen ',' gen
335         {
336                 if($2.type != D_CONST)
337                         yyerror("index for FUNCDATA must be integer constant");
338                 if($4.type != D_EXTERN && $4.type != D_STATIC && $4.type != D_OREG)
339                         yyerror("value for FUNCDATA must be symbol reference");
340                 outcode($1, Always, &$2, NREG, &$4);
341         }
342 /*
343  * END
344  */
345 |       LTYPEE comma
346         {
347                 outcode($1, Always, &nullgen, NREG, &nullgen);
348         }
349
350 cond:
351         {
352                 $$ = Always;
353         }
354 |       cond LCOND
355         {
356                 $$ = ($1 & ~C_SCOND) | $2;
357         }
358 |       cond LS
359         {
360                 $$ = $1 | $2;
361         }
362
363 comma:
364 |       ',' comma
365
366 rel:
367         con '(' LPC ')'
368         {
369                 $$ = nullgen;
370                 $$.type = D_BRANCH;
371                 $$.offset = $1 + pc;
372         }
373 |       LNAME offset
374         {
375                 $1 = labellookup($1);
376                 $$ = nullgen;
377                 if(pass == 2 && $1->type != LLAB)
378                         yyerror("undefined label: %s", $1->labelname);
379                 $$.type = D_BRANCH;
380                 $$.offset = $1->value + $2;
381         }
382
383 ximm:   '$' con
384         {
385                 $$ = nullgen;
386                 $$.type = D_CONST;
387                 $$.offset = $2;
388         }
389 |       '$' oreg
390         {
391                 $$ = $2;
392                 $$.type = D_CONST;
393         }
394 |       '$' '*' '$' oreg
395         {
396                 $$ = $4;
397                 $$.type = D_OCONST;
398         }
399 |       '$' LSCONST
400         {
401                 $$ = nullgen;
402                 $$.type = D_SCONST;
403                 memcpy($$.u.sval, $2, sizeof($$.u.sval));
404         }
405 |       fcon
406
407 fcon:
408         '$' LFCONST
409         {
410                 $$ = nullgen;
411                 $$.type = D_FCONST;
412                 $$.u.dval = $2;
413         }
414 |       '$' '-' LFCONST
415         {
416                 $$ = nullgen;
417                 $$.type = D_FCONST;
418                 $$.u.dval = -$3;
419         }
420
421 reglist:
422         spreg
423         {
424                 $$ = 1 << $1;
425         }
426 |       spreg '-' spreg
427         {
428                 int i;
429                 $$=0;
430                 for(i=$1; i<=$3; i++)
431                         $$ |= 1<<i;
432                 for(i=$3; i<=$1; i++)
433                         $$ |= 1<<i;
434         }
435 |       spreg comma reglist
436         {
437                 $$ = (1<<$1) | $3;
438         }
439
440 gen:
441         reg
442 |       ximm
443 |       shift
444 |       shift '(' spreg ')'
445         {
446                 $$ = $1;
447                 $$.reg = $3;
448         }
449 |       LPSR
450         {
451                 $$ = nullgen;
452                 $$.type = D_PSR;
453                 $$.reg = $1;
454         }
455 |       LFCR
456         {
457                 $$ = nullgen;
458                 $$.type = D_FPCR;
459                 $$.reg = $1;
460         }
461 |       con
462         {
463                 $$ = nullgen;
464                 $$.type = D_OREG;
465                 $$.offset = $1;
466         }
467 |       oreg
468 |       freg
469
470 nireg:
471         ireg
472 |       name
473         {
474                 $$ = $1;
475                 if($1.name != D_EXTERN && $1.name != D_STATIC) {
476                 }
477         }
478
479 ireg:
480         '(' spreg ')'
481         {
482                 $$ = nullgen;
483                 $$.type = D_OREG;
484                 $$.reg = $2;
485                 $$.offset = 0;
486         }
487
488 ioreg:
489         ireg
490 |       con '(' sreg ')'
491         {
492                 $$ = nullgen;
493                 $$.type = D_OREG;
494                 $$.reg = $3;
495                 $$.offset = $1;
496         }
497
498 oreg:
499         name
500 |       name '(' sreg ')'
501         {
502                 $$ = $1;
503                 $$.type = D_OREG;
504                 $$.reg = $3;
505         }
506 |       ioreg
507
508 imsr:
509         reg
510 |       imm
511 |       shift
512
513 imm:    '$' con
514         {
515                 $$ = nullgen;
516                 $$.type = D_CONST;
517                 $$.offset = $2;
518         }
519
520 reg:
521         spreg
522         {
523                 $$ = nullgen;
524                 $$.type = D_REG;
525                 $$.reg = $1;
526         }
527
528 regreg:
529         '(' spreg ',' spreg ')'
530         {
531                 $$ = nullgen;
532                 $$.type = D_REGREG;
533                 $$.reg = $2;
534                 $$.offset = $4;
535         }
536
537 shift:
538         spreg '<' '<' rcon
539         {
540                 $$ = nullgen;
541                 $$.type = D_SHIFT;
542                 $$.offset = $1 | $4 | (0 << 5);
543         }
544 |       spreg '>' '>' rcon
545         {
546                 $$ = nullgen;
547                 $$.type = D_SHIFT;
548                 $$.offset = $1 | $4 | (1 << 5);
549         }
550 |       spreg '-' '>' rcon
551         {
552                 $$ = nullgen;
553                 $$.type = D_SHIFT;
554                 $$.offset = $1 | $4 | (2 << 5);
555         }
556 |       spreg LAT '>' rcon
557         {
558                 $$ = nullgen;
559                 $$.type = D_SHIFT;
560                 $$.offset = $1 | $4 | (3 << 5);
561         }
562
563 rcon:
564         spreg
565         {
566                 if($$ < 0 || $$ >= 16)
567                         print("register value out of range\n");
568                 $$ = (($1&15) << 8) | (1 << 4);
569         }
570 |       con
571         {
572                 if($$ < 0 || $$ >= 32)
573                         print("shift value out of range\n");
574                 $$ = ($1&31) << 7;
575         }
576
577 sreg:
578         LREG
579 |       LPC
580         {
581                 $$ = REGPC;
582         }
583 |       LR '(' expr ')'
584         {
585                 if($3 < 0 || $3 >= NREG)
586                         print("register value out of range\n");
587                 $$ = $3;
588         }
589
590 spreg:
591         sreg
592 |       LSP
593         {
594                 $$ = REGSP;
595         }
596
597 creg:
598         LCREG
599 |       LC '(' expr ')'
600         {
601                 if($3 < 0 || $3 >= NREG)
602                         print("register value out of range\n");
603                 $$ = $3;
604         }
605
606 frcon:
607         freg
608 |       fcon
609
610 freg:
611         LFREG
612         {
613                 $$ = nullgen;
614                 $$.type = D_FREG;
615                 $$.reg = $1;
616         }
617 |       LF '(' con ')'
618         {
619                 $$ = nullgen;
620                 $$.type = D_FREG;
621                 $$.reg = $3;
622         }
623
624 name:
625         con '(' pointer ')'
626         {
627                 $$ = nullgen;
628                 $$.type = D_OREG;
629                 $$.name = $3;
630                 $$.sym = nil;
631                 $$.offset = $1;
632         }
633 |       LNAME offset '(' pointer ')'
634         {
635                 $$ = nullgen;
636                 $$.type = D_OREG;
637                 $$.name = $4;
638                 $$.sym = linklookup(ctxt, $1->name, 0);
639                 $$.offset = $2;
640         }
641 |       LNAME '<' '>' offset '(' LSB ')'
642         {
643                 $$ = nullgen;
644                 $$.type = D_OREG;
645                 $$.name = D_STATIC;
646                 $$.sym = linklookup(ctxt, $1->name, 1);
647                 $$.offset = $4;
648         }
649
650 offset:
651         {
652                 $$ = 0;
653         }
654 |       '+' con
655         {
656                 $$ = $2;
657         }
658 |       '-' con
659         {
660                 $$ = -$2;
661         }
662
663 pointer:
664         LSB
665 |       LSP
666 |       LFP
667
668 con:
669         LCONST
670 |       LVAR
671         {
672                 $$ = $1->value;
673         }
674 |       '-' con
675         {
676                 $$ = -$2;
677         }
678 |       '+' con
679         {
680                 $$ = $2;
681         }
682 |       '~' con
683         {
684                 $$ = ~$2;
685         }
686 |       '(' expr ')'
687         {
688                 $$ = $2;
689         }
690
691 oexpr:
692         {
693                 $$ = 0;
694         }
695 |       ',' expr
696         {
697                 $$ = $2;
698         }
699
700 expr:
701         con
702 |       expr '+' expr
703         {
704                 $$ = $1 + $3;
705         }
706 |       expr '-' expr
707         {
708                 $$ = $1 - $3;
709         }
710 |       expr '*' expr
711         {
712                 $$ = $1 * $3;
713         }
714 |       expr '/' expr
715         {
716                 $$ = $1 / $3;
717         }
718 |       expr '%' expr
719         {
720                 $$ = $1 % $3;
721         }
722 |       expr '<' '<' expr
723         {
724                 $$ = $1 << $4;
725         }
726 |       expr '>' '>' expr
727         {
728                 $$ = $1 >> $4;
729         }
730 |       expr '&' expr
731         {
732                 $$ = $1 & $3;
733         }
734 |       expr '^' expr
735         {
736                 $$ = $1 ^ $3;
737         }
738 |       expr '|' expr
739         {
740                 $$ = $1 | $3;
741         }