]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/new9a/a.y
[dev.cc] cmd/new5a etc, cmd/internal/asm: edit to produce working Go code
[gostls13.git] / src / cmd / new9a / a.y
1 // cmd/9a/a.y from Vita Nuova.
2 //
3 //      Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
4 //      Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
5 //      Portions Copyright © 1997-1999 Vita Nuova Limited
6 //      Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
7 //      Portions Copyright © 2004,2006 Bruce Ellis
8 //      Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
9 //      Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
10 //      Portions Copyright © 2009 The Go Authors.  All rights reserved.
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to deal
14 // in the Software without restriction, including without limitation the rights
15 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 // copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be included in
20 // all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 // THE SOFTWARE.
29
30 %{
31 package main
32
33 import (
34         "cmd/internal/asm"
35         "cmd/internal/obj"
36         . "cmd/internal/obj/ppc64"
37 )
38 %}
39
40 %union
41 {
42         sym *asm.Sym
43         lval int64
44         dval float64
45         sval string
46         addr obj.Addr
47 }
48
49 %left   '|'
50 %left   '^'
51 %left   '&'
52 %left   '<' '>'
53 %left   '+' '-'
54 %left   '*' '/' '%'
55 %token  <lval>  LMOVW LMOVB LABS LLOGW LSHW LADDW LCMP LCROP
56 %token  <lval>  LBRA LFMOV LFCONV LFCMP LFADD LFMA LTRAP LXORW
57 %token  <lval>  LNOP LEND LRETT LWORD LTEXT LDATA LRETRN
58 %token  <lval>  LCONST LSP LSB LFP LPC LCREG LFLUSH
59 %token  <lval>  LREG LFREG LR LCR LF LFPSCR
60 %token  <lval>  LLR LCTR LSPR LSPREG LSEG LMSR
61 %token  <lval>  LPCDAT LFUNCDAT LSCHED LXLD LXST LXOP LXMV
62 %token  <lval>  LRLWM LMOVMW LMOVEM LMOVFL LMTFSB LMA
63 %token  <dval>  LFCONST
64 %token  <sval>  LSCONST
65 %token  <sym>   LNAME LLAB LVAR
66 %type   <lval>  con expr pointer offset sreg
67 %type   <addr>  addr rreg regaddr name creg freg xlreg lr ctr
68 %type   <addr>  imm ximm fimm rel psr lcr cbit fpscr fpscrf msr mask
69 %%
70 prog:
71 |       prog line
72
73 line:
74         LNAME ':'
75         {
76                 $1 = asm.LabelLookup($1);
77                 if $1.Type == LLAB && $1.Value != int64(asm.PC) {
78                         yyerror("redeclaration of %s", $1.Labelname)
79                 }
80                 $1.Type = LLAB;
81                 $1.Value = int64(asm.PC);
82         }
83         line
84 |       LNAME '=' expr ';'
85         {
86                 $1.Type = LVAR;
87                 $1.Value = $3;
88         }
89 |       LVAR '=' expr ';'
90         {
91                 if $1.Value != $3 {
92                         yyerror("redeclaration of %s", $1.Name)
93                 }
94                 $1.Value = $3;
95         }
96 |       LSCHED ';'
97         {
98                 nosched = int($1);
99         }
100 |       ';'
101 |       inst ';'
102 |       error ';'
103
104 inst:
105 /*
106  * load ints and bytes
107  */
108         LMOVW rreg ',' rreg
109         {
110                 outcode(int($1), &$2, NREG, &$4);
111         }
112 |       LMOVW addr ',' rreg
113         {
114                 outcode(int($1), &$2, NREG, &$4);
115         }
116 |       LMOVW regaddr ',' rreg
117         {
118                 outcode(int($1), &$2, NREG, &$4);
119         }
120 |       LMOVB rreg ',' rreg
121         {
122                 outcode(int($1), &$2, NREG, &$4);
123         }
124 |       LMOVB addr ',' rreg
125         {
126                 outcode(int($1), &$2, NREG, &$4);
127         }
128 |       LMOVB regaddr ',' rreg
129         {
130                 outcode(int($1), &$2, NREG, &$4);
131         }
132 /*
133  * load floats
134  */
135 |       LFMOV addr ',' freg
136         {
137                 outcode(int($1), &$2, NREG, &$4);
138         }
139 |       LFMOV regaddr ',' freg
140         {
141                 outcode(int($1), &$2, NREG, &$4);
142         }
143 |       LFMOV fimm ',' freg
144         {
145                 outcode(int($1), &$2, NREG, &$4);
146         }
147 |       LFMOV freg ',' freg
148         {
149                 outcode(int($1), &$2, NREG, &$4);
150         }
151 |       LFMOV freg ',' addr
152         {
153                 outcode(int($1), &$2, NREG, &$4);
154         }
155 |       LFMOV freg ',' regaddr
156         {
157                 outcode(int($1), &$2, NREG, &$4);
158         }
159 /*
160  * store ints and bytes
161  */
162 |       LMOVW rreg ',' addr
163         {
164                 outcode(int($1), &$2, NREG, &$4);
165         }
166 |       LMOVW rreg ',' regaddr
167         {
168                 outcode(int($1), &$2, NREG, &$4);
169         }
170 |       LMOVB rreg ',' addr
171         {
172                 outcode(int($1), &$2, NREG, &$4);
173         }
174 |       LMOVB rreg ',' regaddr
175         {
176                 outcode(int($1), &$2, NREG, &$4);
177         }
178 /*
179  * store floats
180  */
181 |       LMOVW freg ',' addr
182         {
183                 outcode(int($1), &$2, NREG, &$4);
184         }
185 |       LMOVW freg ',' regaddr
186         {
187                 outcode(int($1), &$2, NREG, &$4);
188         }
189 /*
190  * floating point status
191  */
192 |       LMOVW fpscr ',' freg
193         {
194                 outcode(int($1), &$2, NREG, &$4);
195         }
196 |       LMOVW freg ','  fpscr
197         {
198                 outcode(int($1), &$2, NREG, &$4);
199         }
200 |       LMOVW freg ',' imm ',' fpscr
201         {
202                 outgcode(int($1), &$2, NREG, &$4, &$6);
203         }
204 |       LMOVW fpscr ',' creg
205         {
206                 outcode(int($1), &$2, NREG, &$4);
207         }
208 |       LMOVW imm ',' fpscrf
209         {
210                 outcode(int($1), &$2, NREG, &$4);
211         }
212 |       LMTFSB imm ',' con
213         {
214                 outcode(int($1), &$2, int($4), &nullgen);
215         }
216 /*
217  * field moves (mtcrf)
218  */
219 |       LMOVW rreg ',' imm ',' lcr
220         {
221                 outgcode(int($1), &$2, NREG, &$4, &$6);
222         }
223 |       LMOVW rreg ',' creg
224         {
225                 outcode(int($1), &$2, NREG, &$4);
226         }
227 |       LMOVW rreg ',' lcr
228         {
229                 outcode(int($1), &$2, NREG, &$4);
230         }
231 /*
232  * integer operations
233  * logical instructions
234  * shift instructions
235  * unary instructions
236  */
237 |       LADDW rreg ',' sreg ',' rreg
238         {
239                 outcode(int($1), &$2, int($4), &$6);
240         }
241 |       LADDW imm ',' sreg ',' rreg
242         {
243                 outcode(int($1), &$2, int($4), &$6);
244         }
245 |       LADDW rreg ',' imm ',' rreg
246         {
247                 outgcode(int($1), &$2, NREG, &$4, &$6);
248         }
249 |       LADDW rreg ',' rreg
250         {
251                 outcode(int($1), &$2, NREG, &$4);
252         }
253 |       LADDW imm ',' rreg
254         {
255                 outcode(int($1), &$2, NREG, &$4);
256         }
257 |       LLOGW rreg ',' sreg ',' rreg
258         {
259                 outcode(int($1), &$2, int($4), &$6);
260         }
261 |       LLOGW rreg ',' rreg
262         {
263                 outcode(int($1), &$2, NREG, &$4);
264         }
265 |       LSHW rreg ',' sreg ',' rreg
266         {
267                 outcode(int($1), &$2, int($4), &$6);
268         }
269 |       LSHW rreg ',' rreg
270         {
271                 outcode(int($1), &$2, NREG, &$4);
272         }
273 |       LSHW imm ',' sreg ',' rreg
274         {
275                 outcode(int($1), &$2, int($4), &$6);
276         }
277 |       LSHW imm ',' rreg
278         {
279                 outcode(int($1), &$2, NREG, &$4);
280         }
281 |       LABS rreg ',' rreg
282         {
283                 outcode(int($1), &$2, NREG, &$4);
284         }
285 |       LABS rreg
286         {
287                 outcode(int($1), &$2, NREG, &$2);
288         }
289 /*
290  * multiply-accumulate
291  */
292 |       LMA rreg ',' sreg ',' rreg
293         {
294                 outcode(int($1), &$2, int($4), &$6);
295         }
296 /*
297  * move immediate: macro for cau+or, addi, addis, and other combinations
298  */
299 |       LMOVW imm ',' rreg
300         {
301                 outcode(int($1), &$2, NREG, &$4);
302         }
303 |       LMOVW ximm ',' rreg
304         {
305                 outcode(int($1), &$2, NREG, &$4);
306         }
307 /*
308  * condition register operations
309  */
310 |       LCROP cbit ',' cbit
311         {
312                 outcode(int($1), &$2, int($4.Reg), &$4);
313         }
314 |       LCROP cbit ',' con ',' cbit
315         {
316                 outcode(int($1), &$2, int($4), &$6);
317         }
318 /*
319  * condition register moves
320  * move from machine state register
321  */
322 |       LMOVW creg ',' creg
323         {
324                 outcode(int($1), &$2, NREG, &$4);
325         }
326 |       LMOVW psr ',' creg
327         {
328                 outcode(int($1), &$2, NREG, &$4);
329         }
330 |       LMOVW lcr ',' rreg
331         {
332                 outcode(int($1), &$2, NREG, &$4);
333         }
334 |       LMOVW psr ',' rreg
335         {
336                 outcode(int($1), &$2, NREG, &$4);
337         }
338 |       LMOVW xlreg ',' rreg
339         {
340                 outcode(int($1), &$2, NREG, &$4);
341         }
342 |       LMOVW rreg ',' xlreg
343         {
344                 outcode(int($1), &$2, NREG, &$4);
345         }
346 |       LMOVW creg ',' psr
347         {
348                 outcode(int($1), &$2, NREG, &$4);
349         }
350 |       LMOVW rreg ',' psr
351         {
352                 outcode(int($1), &$2, NREG, &$4);
353         }
354 /*
355  * branch, branch conditional
356  * branch conditional register
357  * branch conditional to count register
358  */
359 |       LBRA rel
360         {
361                 outcode(int($1), &nullgen, NREG, &$2);
362         }
363 |       LBRA addr
364         {
365                 outcode(int($1), &nullgen, NREG, &$2);
366         }
367 |       LBRA '(' xlreg ')'
368         {
369                 outcode(int($1), &nullgen, NREG, &$3);
370         }
371 |       LBRA ',' rel
372         {
373                 outcode(int($1), &nullgen, NREG, &$3);
374         }
375 |       LBRA ',' addr
376         {
377                 outcode(int($1), &nullgen, NREG, &$3);
378         }
379 |       LBRA ',' '(' xlreg ')'
380         {
381                 outcode(int($1), &nullgen, NREG, &$4);
382         }
383 |       LBRA creg ',' rel
384         {
385                 outcode(int($1), &$2, NREG, &$4);
386         }
387 |       LBRA creg ',' addr
388         {
389                 outcode(int($1), &$2, NREG, &$4);
390         }
391 |       LBRA creg ',' '(' xlreg ')'
392         {
393                 outcode(int($1), &$2, NREG, &$5);
394         }
395 |       LBRA con ',' rel
396         {
397                 outcode(int($1), &nullgen, int($2), &$4);
398         }
399 |       LBRA con ',' addr
400         {
401                 outcode(int($1), &nullgen, int($2), &$4);
402         }
403 |       LBRA con ',' '(' xlreg ')'
404         {
405                 outcode(int($1), &nullgen, int($2), &$5);
406         }
407 |       LBRA con ',' con ',' rel
408         {
409                 var g obj.Addr
410                 g = nullgen;
411                 g.Type_ = D_CONST;
412                 g.Offset = $2;
413                 outcode(int($1), &g, int($4), &$6);
414         }
415 |       LBRA con ',' con ',' addr
416         {
417                 var g obj.Addr
418                 g = nullgen;
419                 g.Type_ = D_CONST;
420                 g.Offset = $2;
421                 outcode(int($1), &g, int($4), &$6);
422         }
423 |       LBRA con ',' con ',' '(' xlreg ')'
424         {
425                 var g obj.Addr
426                 g = nullgen;
427                 g.Type_ = D_CONST;
428                 g.Offset = $2;
429                 outcode(int($1), &g, int($4), &$7);
430         }
431 /*
432  * conditional trap
433  */
434 |       LTRAP rreg ',' sreg
435         {
436                 outcode(int($1), &$2, int($4), &nullgen);
437         }
438 |       LTRAP imm ',' sreg
439         {
440                 outcode(int($1), &$2, int($4), &nullgen);
441         }
442 |       LTRAP rreg comma
443         {
444                 outcode(int($1), &$2, NREG, &nullgen);
445         }
446 |       LTRAP comma
447         {
448                 outcode(int($1), &nullgen, NREG, &nullgen);
449         }
450 /*
451  * floating point operate
452  */
453 |       LFCONV freg ',' freg
454         {
455                 outcode(int($1), &$2, NREG, &$4);
456         }
457 |       LFADD freg ',' freg
458         {
459                 outcode(int($1), &$2, NREG, &$4);
460         }
461 |       LFADD freg ',' freg ',' freg
462         {
463                 outcode(int($1), &$2, int($4.Reg), &$6);
464         }
465 |       LFMA freg ',' freg ',' freg ',' freg
466         {
467                 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
468         }
469 |       LFCMP freg ',' freg
470         {
471                 outcode(int($1), &$2, NREG, &$4);
472         }
473 |       LFCMP freg ',' freg ',' creg
474         {
475                 outcode(int($1), &$2, int($6.Reg), &$4);
476         }
477 /*
478  * CMP
479  */
480 |       LCMP rreg ',' rreg
481         {
482                 outcode(int($1), &$2, NREG, &$4);
483         }
484 |       LCMP rreg ',' imm
485         {
486                 outcode(int($1), &$2, NREG, &$4);
487         }
488 |       LCMP rreg ',' rreg ',' creg
489         {
490                 outcode(int($1), &$2, int($6.Reg), &$4);
491         }
492 |       LCMP rreg ',' imm ',' creg
493         {
494                 outcode(int($1), &$2, int($6.Reg), &$4);
495         }
496 /*
497  * rotate and mask
498  */
499 |       LRLWM  imm ',' rreg ',' imm ',' rreg
500         {
501                 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
502         }
503 |       LRLWM  imm ',' rreg ',' mask ',' rreg
504         {
505                 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
506         }
507 |       LRLWM  rreg ',' rreg ',' imm ',' rreg
508         {
509                 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
510         }
511 |       LRLWM  rreg ',' rreg ',' mask ',' rreg
512         {
513                 outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
514         }
515 /*
516  * load/store multiple
517  */
518 |       LMOVMW addr ',' rreg
519         {
520                 outcode(int($1), &$2, NREG, &$4);
521         }
522 |       LMOVMW rreg ',' addr
523         {
524                 outcode(int($1), &$2, NREG, &$4);
525         }
526 /*
527  * various indexed load/store
528  * indexed unary (eg, cache clear)
529  */
530 |       LXLD regaddr ',' rreg
531         {
532                 outcode(int($1), &$2, NREG, &$4);
533         }
534 |       LXLD regaddr ',' imm ',' rreg
535         {
536                 outgcode(int($1), &$2, NREG, &$4, &$6);
537         }
538 |       LXST rreg ',' regaddr
539         {
540                 outcode(int($1), &$2, NREG, &$4);
541         }
542 |       LXST rreg ',' imm ',' regaddr
543         {
544                 outgcode(int($1), &$2, NREG, &$4, &$6);
545         }
546 |       LXMV regaddr ',' rreg
547         {
548                 outcode(int($1), &$2, NREG, &$4);
549         }
550 |       LXMV rreg ',' regaddr
551         {
552                 outcode(int($1), &$2, NREG, &$4);
553         }
554 |       LXOP regaddr
555         {
556                 outcode(int($1), &$2, NREG, &nullgen);
557         }
558 /*
559  * NOP
560  */
561 |       LNOP comma
562         {
563                 outcode(int($1), &nullgen, NREG, &nullgen);
564         }
565 |       LNOP rreg comma
566         {
567                 outcode(int($1), &$2, NREG, &nullgen);
568         }
569 |       LNOP freg comma
570         {
571                 outcode(int($1), &$2, NREG, &nullgen);
572         }
573 |       LNOP ',' rreg
574         {
575                 outcode(int($1), &nullgen, NREG, &$3);
576         }
577 |       LNOP ',' freg
578         {
579                 outcode(int($1), &nullgen, NREG, &$3);
580         }
581 |       LNOP imm /* SYSCALL $num: load $num to R0 before syscall and restore R0 to 0 afterwards. */
582         {
583                 outcode(int($1), &$2, NREG, &nullgen);
584         }
585 /*
586  * word
587  */
588 |       LWORD imm comma
589         {
590                 outcode(int($1), &$2, NREG, &nullgen);
591         }
592 |       LWORD ximm comma
593         {
594                 outcode(int($1), &$2, NREG, &nullgen);
595         }
596 /*
597  * PCDATA
598  */
599 |       LPCDAT imm ',' imm
600         {
601                 if $2.Type_ != D_CONST || $4.Type_ != D_CONST {
602                         yyerror("arguments to PCDATA must be integer constants")
603                 }
604                 outcode(int($1), &$2, NREG, &$4);
605         }
606 /*
607  * FUNCDATA
608  */
609 |       LFUNCDAT imm ',' addr
610         {
611                 if $2.Type_ != D_CONST {
612                         yyerror("index for FUNCDATA must be integer constant")
613                 }
614                 if $4.Type_ != D_EXTERN && $4.Type_ != D_STATIC && $4.Type_ != D_OREG {
615                         yyerror("value for FUNCDATA must be symbol reference")
616                 }
617                 outcode(int($1), &$2, NREG, &$4);
618         }
619 /*
620  * END
621  */
622 |       LEND comma
623         {
624                 outcode(int($1), &nullgen, NREG, &nullgen);
625         }
626 /*
627  * TEXT/GLOBL
628  */
629 |       LTEXT name ',' imm
630         {
631                 asm.Settext($2.Sym);
632                 outcode(int($1), &$2, NREG, &$4);
633         }
634 |       LTEXT name ',' con ',' imm
635         {
636                 asm.Settext($2.Sym);
637                 $6.Offset &= 0xffffffff;
638                 $6.Offset |= -obj.ArgsSizeUnknown << 32;
639                 outcode(int($1), &$2, int($4), &$6);
640         }
641 |       LTEXT name ',' con ',' imm '-' con
642         {
643                 asm.Settext($2.Sym);
644                 $6.Offset &= 0xffffffff;
645                 $6.Offset |= ($8 & 0xffffffff) << 32;
646                 outcode(int($1), &$2, int($4), &$6);
647         }
648 /*
649  * DATA
650  */
651 |       LDATA name '/' con ',' imm
652         {
653                 outcode(int($1), &$2, int($4), &$6);
654         }
655 |       LDATA name '/' con ',' ximm
656         {
657                 outcode(int($1), &$2, int($4), &$6);
658         }
659 |       LDATA name '/' con ',' fimm
660         {
661                 outcode(int($1), &$2, int($4), &$6);
662         }
663 /*
664  * RETURN
665  */
666 |       LRETRN  comma
667         {
668                 outcode(int($1), &nullgen, NREG, &nullgen);
669         }
670
671 rel:
672         con '(' LPC ')'
673         {
674                 $$ = nullgen;
675                 $$.Type_ = D_BRANCH;
676                 $$.Offset = $1 + int64(asm.PC);
677         }
678 |       LNAME offset
679         {
680                 $1 = asm.LabelLookup($1);
681                 $$ = nullgen;
682                 if asm.Pass == 2 && $1.Type != LLAB {
683                         yyerror("undefined label: %s", $1.Labelname)
684                 }
685                 $$.Type_ = D_BRANCH;
686                 $$.Offset = $1.Value + $2;
687         }
688
689 rreg:
690         sreg
691         {
692                 $$ = nullgen;
693                 $$.Type_ = D_REG;
694                 $$.Reg = int8($1);
695         }
696
697 xlreg:
698         lr
699 |       ctr
700
701 lr:
702         LLR
703         {
704                 $$ = nullgen;
705                 $$.Type_ = D_SPR;
706                 $$.Offset = $1;
707         }
708
709 lcr:
710         LCR
711         {
712                 $$ = nullgen;
713                 $$.Type_ = D_CREG;
714                 $$.Reg = NREG;  /* whole register */
715         }
716
717 ctr:
718         LCTR
719         {
720                 $$ = nullgen;
721                 $$.Type_ = D_SPR;
722                 $$.Offset = $1;
723         }
724
725 msr:
726         LMSR
727         {
728                 $$ = nullgen;
729                 $$.Type_ = D_MSR;
730         }
731
732 psr:
733         LSPREG
734         {
735                 $$ = nullgen;
736                 $$.Type_ = D_SPR;
737                 $$.Offset = $1;
738         }
739 |       LSPR '(' con ')'
740         {
741                 $$ = nullgen;
742                 $$.Type_ = int16($1);
743                 $$.Offset = $3;
744         }
745 |       msr
746
747 fpscr:
748         LFPSCR
749         {
750                 $$ = nullgen;
751                 $$.Type_ = D_FPSCR;
752                 $$.Reg = NREG;
753         }
754
755 fpscrf:
756         LFPSCR '(' con ')'
757         {
758                 $$ = nullgen;
759                 $$.Type_ = D_FPSCR;
760                 $$.Reg = int8($3);
761         }
762
763 freg:
764         LFREG
765         {
766                 $$ = nullgen;
767                 $$.Type_ = D_FREG;
768                 $$.Reg = int8($1);
769         }
770 |       LF '(' con ')'
771         {
772                 $$ = nullgen;
773                 $$.Type_ = D_FREG;
774                 $$.Reg = int8($3);
775         }
776
777 creg:
778         LCREG
779         {
780                 $$ = nullgen;
781                 $$.Type_ = D_CREG;
782                 $$.Reg = int8($1);
783         }
784 |       LCR '(' con ')'
785         {
786                 $$ = nullgen;
787                 $$.Type_ = D_CREG;
788                 $$.Reg = int8($3);
789         }
790
791
792 cbit:   con
793         {
794                 $$ = nullgen;
795                 $$.Type_ = D_REG;
796                 $$.Reg = int8($1);
797         }
798
799 mask:
800         con ',' con
801         {
802                 var mb, me int
803                 var v uint32
804
805                 $$ = nullgen;
806                 $$.Type_ = D_CONST;
807                 mb = int($1);
808                 me = int($3);
809                 if(mb < 0 || mb > 31 || me < 0 || me > 31){
810                         yyerror("illegal mask start/end value(s)");
811                         mb = 0
812                         me = 0;
813                 }
814                 if mb <= me {
815                         v = (^uint32(0)>>uint(mb)) & (^uint32(0)<<uint(31-me))
816                 } else {
817                         v = (^uint32(0)>>uint(me+1)) & (^uint32(0)<<uint(31-(mb-1)))
818                 }
819                 $$.Offset = int64(v);
820         }
821
822 ximm:
823         '$' addr
824         {
825                 $$ = $2;
826                 $$.Type_ = D_CONST;
827         }
828 |       '$' LSCONST
829         {
830                 $$ = nullgen;
831                 $$.Type_ = D_SCONST;
832                 $$.U.Sval = $2
833         }
834
835 fimm:
836         '$' LFCONST
837         {
838                 $$ = nullgen;
839                 $$.Type_ = D_FCONST;
840                 $$.U.Dval = $2;
841         }
842 |       '$' '-' LFCONST
843         {
844                 $$ = nullgen;
845                 $$.Type_ = D_FCONST;
846                 $$.U.Dval = -$3;
847         }
848
849 imm:    '$' con
850         {
851                 $$ = nullgen;
852                 $$.Type_ = D_CONST;
853                 $$.Offset = $2;
854         }
855
856 sreg:
857         LREG
858 |       LR '(' con ')'
859         {
860                 if $$ < 0 || $$ >= NREG {
861                         print("register value out of range\n")
862                 }
863                 $$ = $3;
864         }
865
866 regaddr:
867         '(' sreg ')'
868         {
869                 $$ = nullgen;
870                 $$.Type_ = D_OREG;
871                 $$.Reg = int8($2);
872                 $$.Offset = 0;
873         }
874 |       '(' sreg '+' sreg ')'
875         {
876                 $$ = nullgen;
877                 $$.Type_ = D_OREG;
878                 $$.Reg = int8($2);
879                 $$.Scale = int8($4);
880                 $$.Offset = 0;
881         }
882
883 addr:
884         name
885 |       con '(' sreg ')'
886         {
887                 $$ = nullgen;
888                 $$.Type_ = D_OREG;
889                 $$.Reg = int8($3);
890                 $$.Offset = $1;
891         }
892
893 name:
894         con '(' pointer ')'
895         {
896                 $$ = nullgen;
897                 $$.Type_ = D_OREG;
898                 $$.Name = int8($3);
899                 $$.Sym = nil;
900                 $$.Offset = $1;
901         }
902 |       LNAME offset '(' pointer ')'
903         {
904                 $$ = nullgen;
905                 $$.Type_ = D_OREG;
906                 $$.Name = int8($4);
907                 $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
908                 $$.Offset = $2;
909         }
910 |       LNAME '<' '>' offset '(' LSB ')'
911         {
912                 $$ = nullgen;
913                 $$.Type_ = D_OREG;
914                 $$.Name = D_STATIC;
915                 $$.Sym = obj.Linklookup(asm.Ctxt, $1.Name, 0);
916                 $$.Offset = $4;
917         }
918
919 comma:
920 |       ','
921
922 offset:
923         {
924                 $$ = 0;
925         }
926 |       '+' con
927         {
928                 $$ = $2;
929         }
930 |       '-' con
931         {
932                 $$ = -$2;
933         }
934
935 pointer:
936         LSB
937 |       LSP
938 |       LFP
939
940 con:
941         LCONST
942 |       LVAR
943         {
944                 $$ = $1.Value;
945         }
946 |       '-' con
947         {
948                 $$ = -$2;
949         }
950 |       '+' con
951         {
952                 $$ = $2;
953         }
954 |       '~' con
955         {
956                 $$ = ^$2;
957         }
958 |       '(' expr ')'
959         {
960                 $$ = $2;
961         }
962
963 expr:
964         con
965 |       expr '+' expr
966         {
967                 $$ = $1 + $3;
968         }
969 |       expr '-' expr
970         {
971                 $$ = $1 - $3;
972         }
973 |       expr '*' expr
974         {
975                 $$ = $1 * $3;
976         }
977 |       expr '/' expr
978         {
979                 $$ = $1 / $3;
980         }
981 |       expr '%' expr
982         {
983                 $$ = $1 % $3;
984         }
985 |       expr '<' '<' expr
986         {
987                 $$ = $1 << uint($4);
988         }
989 |       expr '>' '>' expr
990         {
991                 $$ = $1 >> uint($4);
992         }
993 |       expr '&' expr
994         {
995                 $$ = $1 & $3;
996         }
997 |       expr '^' expr
998         {
999                 $$ = $1 ^ $3;
1000         }
1001 |       expr '|' expr
1002         {
1003                 $$ = $1 | $3;
1004         }