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