]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ka/a.y
cc, ?[acl]: fix gethunk() and move common memory allocator code to cc/compat
[plan9front.git] / sys / src / cmd / ka / 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 LMOVD LMOVB LSWAP LADDW LCMP
19 %token  <lval>  LBRA LFMOV LFCONV LFADD LCPOP LTRAP LJMPL LXORW
20 %token  <lval>  LNOP LEND LRETT LUNIMP LTEXT LDATA LRETRN
21 %token  <lval>  LCONST LSP LSB LFP LPC LCREG LFLUSH
22 %token  <lval>  LREG LFREG LR LC LF
23 %token  <lval>  LFSR LFPQ LPSR LSCHED
24 %token  <dval>  LFCONST
25 %token  <sval>  LSCONST
26 %token  <sym>   LNAME LLAB LVAR
27 %type   <lval>  con expr pointer offset sreg
28 %type   <gen>   addr rreg name psr creg freg
29 %type   <gen>   imm ximm fimm rel fsr fpq
30 %%
31 prog:
32 |       prog line
33
34 line:
35         LLAB ':'
36         {
37                 if($1->value != pc)
38                         yyerror("redeclaration of %s", $1->name);
39                 $1->value = pc;
40         }
41         line
42 |       LNAME ':'
43         {
44                 $1->type = LLAB;
45                 $1->value = pc;
46         }
47         line
48 |       LNAME '=' expr ';'
49         {
50                 $1->type = LVAR;
51                 $1->value = $3;
52         }
53 |       LVAR '=' expr ';'
54         {
55                 if($1->value != $3)
56                         yyerror("redeclaration of %s", $1->name);
57                 $1->value = $3;
58         }
59 |       LSCHED ';'
60         {
61                 nosched = $1;
62         }
63 |       ';'
64 |       inst ';'
65 |       error ';'
66
67 inst:
68 /*
69  * B.1 load integer instructions
70  */
71         LMOVW rreg ',' rreg
72         {
73                 outcode($1, &$2, NREG, &$4);
74         }
75 |       LMOVW addr ',' rreg
76         {
77                 outcode($1, &$2, NREG, &$4);
78         }
79 |       LMOVD addr ',' rreg
80         {
81                 outcode($1, &$2, NREG, &$4);
82         }
83 |       LMOVB rreg ',' rreg
84         {
85                 outcode($1, &$2, NREG, &$4);
86         }
87 |       LMOVB addr ',' rreg
88         {
89                 outcode($1, &$2, NREG, &$4);
90         }
91 /*
92  * B.2 load floating instructions
93  *      includes CSR
94  */
95 |       LMOVD addr ',' freg
96         {
97                 outcode($1, &$2, NREG, &$4);
98         }
99 |       LFMOV addr ',' freg
100         {
101                 outcode($1, &$2, NREG, &$4);
102         }
103 |       LFMOV fimm ',' freg
104         {
105                 outcode($1, &$2, NREG, &$4);
106         }
107 |       LFMOV freg ',' freg
108         {
109                 outcode($1, &$2, NREG, &$4);
110         }
111 |       LFMOV freg ',' addr
112         {
113                 outcode($1, &$2, NREG, &$4);
114         }
115 |       LMOVW addr ',' fsr
116         {
117                 outcode($1, &$2, NREG, &$4);
118         }
119 /*
120  * B.3 load coprocessor instructions
121  *      excludes CSR
122  */
123 |       LMOVW addr ',' creg
124         {
125                 outcode($1, &$2, NREG, &$4);
126         }
127 |       LMOVD addr ',' creg
128         {
129                 outcode($1, &$2, NREG, &$4);
130         }
131 /*
132  * B.4 store integer instructions
133  */
134 |       LMOVW rreg ',' addr
135         {
136                 outcode($1, &$2, NREG, &$4);
137         }
138 |       LMOVW imm ',' addr
139         {
140                 if($2.offset != 0)
141                         yyerror("constant must be zero");
142                 outcode($1, &$2, NREG, &$4);
143         }
144 |       LMOVD rreg ',' addr
145         {
146                 outcode($1, &$2, NREG, &$4);
147         }
148 |       LMOVB rreg ',' addr
149         {
150                 outcode($1, &$2, NREG, &$4);
151         }
152 |       LMOVB imm ',' addr
153         {
154                 if($2.offset != 0)
155                         yyerror("constant must be zero");
156                 outcode($1, &$2, NREG, &$4);
157         }
158 /*
159  * B.5 store floating instructions
160  *      includes CSR and CQ
161  */
162 |       LMOVW freg ',' addr
163         {
164                 outcode($1, &$2, NREG, &$4);
165         }
166 |       LMOVD freg ',' addr
167         {
168                 outcode($1, &$2, NREG, &$4);
169         }
170 |       LMOVW fsr ',' addr
171         {
172                 outcode($1, &$2, NREG, &$4);
173         }
174 |       LMOVD fpq ',' addr
175         {
176                 outcode($1, &$2, NREG, &$4);
177         }
178 /*
179  * B.6 store coprocessor instructions
180  *      excludes CSR and CQ
181  */
182 |       LMOVW creg ',' addr
183         {
184                 outcode($1, &$2, NREG, &$4);
185         }
186 |       LMOVD creg ',' addr
187         {
188                 outcode($1, &$2, NREG, &$4);
189         }
190 /*
191  * B.7 atomic load unsigned byte (TAS)
192  * B.8 swap
193  */
194 |       LSWAP addr ',' rreg
195         {
196                 outcode($1, &$2, NREG, &$4);
197         }
198 /*
199  * B.9  add instructions
200  * B.10 tagged add instructions
201  * B.11 subtract instructions
202  * B.12 tagged subtract instructions
203  * B.13 multiply step instruction
204  * B.14 logical instructions
205  * B.15 shift instructions
206  * B.17 save/restore
207  */
208 |       LADDW rreg ',' sreg ',' rreg
209         {
210                 outcode($1, &$2, $4, &$6);
211         }
212 |       LADDW imm ',' sreg ',' rreg
213         {
214                 outcode($1, &$2, $4, &$6);
215         }
216 |       LADDW rreg ',' rreg
217         {
218                 outcode($1, &$2, NREG, &$4);
219         }
220 |       LADDW imm ',' rreg
221         {
222                 outcode($1, &$2, NREG, &$4);
223         }
224 |       LXORW rreg ',' sreg ',' rreg
225         {
226                 outcode($1, &$2, $4, &$6);
227         }
228 |       LXORW imm ',' sreg ',' rreg
229         {
230                 outcode($1, &$2, $4, &$6);
231         }
232 |       LXORW rreg ',' rreg
233         {
234                 outcode($1, &$2, NREG, &$4);
235         }
236 |       LXORW imm ',' rreg
237         {
238                 outcode($1, &$2, NREG, &$4);
239         }
240 /*
241  * B.16 set hi
242  *      other pseudo moves
243  */
244 |       LMOVW imm ',' rreg
245         {
246                 outcode($1, &$2, NREG, &$4);
247         }
248 |       LMOVD imm ',' rreg
249         {
250                 outcode($1, &$2, NREG, &$4);
251         }
252 |       LMOVW ximm ',' rreg
253         {
254                 outcode($1, &$2, NREG, &$4);
255         }
256 |       LMOVD ximm ',' rreg
257         {
258                 outcode($1, &$2, NREG, &$4);
259         }
260 /*
261  * B.18 branch on integer condition
262  * B.19 floating point branch on condition
263  * B.20 coprocessor branch on condition
264  */
265 |       LBRA comma rel
266         {
267                 outcode($1, &nullgen, NREG, &$3);
268         }
269 /*
270  * B.21 call instruction
271  * B.22 jump and link instruction
272  */
273 |       LJMPL comma rel
274         {
275                 outcode($1, &nullgen, NREG, &$3);
276         }
277 |       LJMPL comma addr
278         {
279                 outcode($1, &nullgen, NREG, &$3);
280         }
281 |       LJMPL comma sreg ',' rel
282         {
283                 outcode($1, &nullgen, $3, &$5);
284         }
285 |       LJMPL comma sreg ',' addr
286         {
287                 outcode($1, &nullgen, $3, &$5);
288         }
289 /*
290  * B.23 return from trap
291  */
292 |       LRETT rreg ',' rreg
293         {
294                 outcode($1, &$2, NREG, &$4);
295         }
296 /*
297  * B.28 instruction cache flush
298  */
299 |       LFLUSH rel comma
300         {
301                 outcode($1, &$2, NREG, &nullgen);
302         }
303 |       LFLUSH addr comma
304         {
305                 outcode($1, &$2, NREG, &nullgen);
306         }
307 /*
308  * B.24 trap on condition
309  */
310 |       LTRAP rreg ',' sreg
311         {
312                 outcode($1, &$2, $4, &nullgen);
313         }
314 |       LTRAP imm ',' sreg
315         {
316                 outcode($1, &$2, $4, &nullgen);
317         }
318 |       LTRAP rreg comma
319         {
320                 outcode($1, &$2, NREG, &nullgen);
321         }
322 |       LTRAP comma
323         {
324                 outcode($1, &nullgen, NREG, &nullgen);
325         }
326 /*
327  * B.25 read state register instructions
328  */
329 |       LMOVW psr ',' rreg
330         {
331                 outcode($1, &$2, NREG, &$4);
332         }
333 /*
334  * B.26 write state register instructions BOTCH XOR
335  */
336 |       LMOVW rreg ',' psr
337         {
338                 outcode($1, &$2, NREG, &$4);
339         }
340 |       LMOVW imm ',' psr
341         {
342                 outcode($1, &$2, NREG, &$4);
343         }
344 |       LXORW rreg ',' sreg ',' psr
345         {
346                 outcode($1, &$2, $4, &$6);
347         }
348 |       LXORW imm ',' sreg ',' psr
349         {
350                 outcode($1, &$2, $4, &$6);
351         }
352 /*
353  * B.27 unimplemented trap
354  */
355 |       LUNIMP  comma
356         {
357                 outcode($1, &nullgen, NREG, &nullgen);
358         }
359 |       LUNIMP imm comma
360         {
361                 outcode($1, &$2, NREG, &nullgen);
362         }
363 /*
364  * B.29 floating point operate
365  */
366 |       LFCONV freg ',' freg
367         {
368                 outcode($1, &$2, NREG, &$4);
369         }
370 |       LFADD freg ',' freg
371         {
372                 outcode($1, &$2, NREG, &$4);
373         }
374 |       LFADD freg ',' freg ',' freg
375         {
376                 outcode($1, &$2, $4.reg, &$6);
377         }
378 /*
379  * B.30 coprocessor operate
380  */
381 |       LCPOP creg ',' creg
382         {
383                 outcode($1, &$2, NREG, &$4);
384         }
385 |       LCPOP creg ',' creg ',' creg
386         {
387                 outcode($1, &$2, $4.reg, &$6);
388         }
389 /*
390  * CMP
391  */
392 |       LCMP rreg ',' rreg
393         {
394                 outcode($1, &$2, NREG, &$4);
395         }
396 |       LCMP rreg ',' imm
397         {
398                 outcode($1, &$2, NREG, &$4);
399         }
400 /*
401  * NOP
402  */
403 |       LNOP comma
404         {
405                 outcode($1, &nullgen, NREG, &nullgen);
406         }
407 |       LNOP rreg comma
408         {
409                 outcode($1, &$2, NREG, &nullgen);
410         }
411 |       LNOP freg comma
412         {
413                 outcode($1, &$2, NREG, &nullgen);
414         }
415 |       LNOP ',' rreg
416         {
417                 outcode($1, &nullgen, NREG, &$3);
418         }
419 |       LNOP ',' freg
420         {
421                 outcode($1, &nullgen, NREG, &$3);
422         }
423 /*
424  * END
425  */
426 |       LEND comma
427         {
428                 outcode($1, &nullgen, NREG, &nullgen);
429         }
430 /*
431  * TEXT/GLOBL
432  */
433 |       LTEXT name ',' imm
434         {
435                 outcode($1, &$2, NREG, &$4);
436         }
437 |       LTEXT name ',' con ',' imm
438         {
439                 outcode($1, &$2, $4, &$6);
440         }
441 /*
442  * DATA
443  */
444 |       LDATA name '/' con ',' imm
445         {
446                 outcode($1, &$2, $4, &$6);
447         }
448 |       LDATA name '/' con ',' ximm
449         {
450                 outcode($1, &$2, $4, &$6);
451         }
452 |       LDATA name '/' con ',' fimm
453         {
454                 outcode($1, &$2, $4, &$6);
455         }
456 /*
457  * RETURN
458  */
459 |       LRETRN  comma
460         {
461                 outcode($1, &nullgen, NREG, &nullgen);
462         }
463
464 rel:
465         con '(' LPC ')'
466         {
467                 $$ = nullgen;
468                 $$.type = D_BRANCH;
469                 $$.offset = $1 + pc;
470         }
471 |       LNAME offset
472         {
473                 $$ = nullgen;
474                 if(pass == 2)
475                         yyerror("undefined label: %s", $1->name);
476                 $$.type = D_BRANCH;
477                 $$.sym = $1;
478                 $$.offset = $2;
479         }
480 |       LLAB offset
481         {
482                 $$ = nullgen;
483                 $$.type = D_BRANCH;
484                 $$.sym = $1;
485                 $$.offset = $1->value + $2;
486         }
487
488 rreg:
489         sreg
490         {
491                 $$ = nullgen;
492                 $$.type = D_REG;
493                 $$.reg = $1;
494         }
495
496 fsr:
497         LFSR
498         {
499                 $$ = nullgen;
500                 $$.type = D_PREG;
501                 $$.reg = $1;
502         }
503
504 fpq:
505         LFPQ
506         {
507                 $$ = nullgen;
508                 $$.type = D_PREG;
509                 $$.reg = $1;
510         }
511
512 psr:
513         LPSR
514         {
515                 $$ = nullgen;
516                 $$.type = D_PREG;
517                 $$.reg = $1;
518         }
519
520 creg:
521         LCREG
522         {
523                 $$ = nullgen;
524                 $$.type = D_CREG;
525                 $$.reg = $1;
526         }
527 |       LC '(' con ')'
528         {
529                 $$ = nullgen;
530                 $$.type = D_CREG;
531                 $$.reg = $3;
532         }
533
534 freg:
535         LFREG
536         {
537                 $$ = nullgen;
538                 $$.type = D_FREG;
539                 $$.reg = $1;
540         }
541 |       LF '(' con ')'
542         {
543                 $$ = nullgen;
544                 $$.type = D_FREG;
545                 $$.reg = $3;
546         }
547
548 ximm:
549         '$' addr
550         {
551                 $$ = $2;
552                 $$.type = D_CONST;
553         }
554 |       '$' LSCONST
555         {
556                 $$ = nullgen;
557                 $$.type = D_SCONST;
558                 memcpy($$.sval, $2, sizeof($$.sval));
559         }
560
561 fimm:
562         '$' LFCONST
563         {
564                 $$ = nullgen;
565                 $$.type = D_FCONST;
566                 $$.dval = $2;
567         }
568 |       '$' '-' LFCONST
569         {
570                 $$ = nullgen;
571                 $$.type = D_FCONST;
572                 $$.dval = -$3;
573         }
574
575 imm:    '$' con
576         {
577                 $$ = nullgen;
578                 $$.type = D_CONST;
579                 $$.offset = $2;
580         }
581
582 sreg:
583         LREG
584 |       LR '(' con ')'
585         {
586                 if($$ < 0 || $$ >= NREG)
587                         print("register value out of range\n");
588                 $$ = $3;
589         }
590
591 addr:
592         '(' sreg ')'
593         {
594                 $$ = nullgen;
595                 $$.type = D_OREG;
596                 $$.reg = $2;
597                 $$.offset = 0;
598         }
599 |       '(' sreg ',' con ')'
600         {
601                 $$ = nullgen;
602                 $$.type = D_ASI;
603                 $$.reg = $2;
604                 $$.offset = $4;
605         }
606 |       '(' sreg '+' sreg ')'
607         {
608                 $$ = nullgen;
609                 $$.type = D_OREG;
610                 $$.reg = $2;
611                 $$.xreg = $4;
612                 $$.offset = 0;
613         }
614 |       name
615 |       con '(' sreg ')'
616         {
617                 $$ = nullgen;
618                 $$.type = D_OREG;
619                 $$.reg = $3;
620                 $$.offset = $1;
621         }
622
623 name:
624         con '(' pointer ')'
625         {
626                 $$ = nullgen;
627                 $$.type = D_OREG;
628                 $$.name = $3;
629                 $$.sym = S;
630                 $$.offset = $1;
631         }
632 |       LNAME offset '(' pointer ')'
633         {
634                 $$ = nullgen;
635                 $$.type = D_OREG;
636                 $$.name = $4;
637                 $$.sym = $1;
638                 $$.offset = $2;
639         }
640 |       LNAME '<' '>' offset '(' LSB ')'
641         {
642                 $$ = nullgen;
643                 $$.type = D_OREG;
644                 $$.name = D_STATIC;
645                 $$.sym = $1;
646                 $$.offset = $4;
647         }
648
649 comma:
650 |       ','
651
652 offset:
653         {
654                 $$ = 0;
655         }
656 |       '+' con
657         {
658                 $$ = $2;
659         }
660 |       '-' con
661         {
662                 $$ = -$2;
663         }
664
665 pointer:
666         LSB
667 |       LSP
668 |       LFP
669
670 con:
671         LCONST
672 |       LVAR
673         {
674                 $$ = $1->value;
675         }
676 |       '-' con
677         {
678                 $$ = -$2;
679         }
680 |       '+' con
681         {
682                 $$ = $2;
683         }
684 |       '~' con
685         {
686                 $$ = ~$2;
687         }
688 |       '(' expr ')'
689         {
690                 $$ = $2;
691         }
692
693 expr:
694         con
695 |       expr '+' expr
696         {
697                 $$ = $1 + $3;
698         }
699 |       expr '-' expr
700         {
701                 $$ = $1 - $3;
702         }
703 |       expr '*' expr
704         {
705                 $$ = $1 * $3;
706         }
707 |       expr '/' expr
708         {
709                 $$ = $1 / $3;
710         }
711 |       expr '%' expr
712         {
713                 $$ = $1 % $3;
714         }
715 |       expr '<' '<' expr
716         {
717                 $$ = $1 << $4;
718         }
719 |       expr '>' '>' expr
720         {
721                 $$ = $1 >> $4;
722         }
723 |       expr '&' expr
724         {
725                 $$ = $1 & $3;
726         }
727 |       expr '^' expr
728         {
729                 $$ = $1 ^ $3;
730         }
731 |       expr '|' expr
732         {
733                 $$ = $1 | $3;
734         }