Pristine Ack-5.5
[Ack-5.5.git] / util / cgg / bootgram.y
1 %{
2
3 #ifndef NORCSID
4 static char rcsid[]="$Id: bootgram.y,v 2.16 1994/06/24 10:16:05 ceriel Exp $";
5 #endif
6
7 /*
8  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
9  * See the copyright notice in the ACK home directory, in the file "Copyright".
10  *
11  * Author: Hans van Staveren
12  */
13
14 #include <stdio.h>
15 #include <assert.h>
16 #include <em_spec.h>
17 #include <em_flag.h>
18 #include <em_reg.h>
19
20 #define extern
21 #include "booth.h"
22 #undef extern
23
24 %}
25
26 %union {
27         int yy_int;
28         int *yy_intp;
29         string yy_string;
30         list1 yy_list1;
31         list2 yy_list2;
32         expr_t yy_expr;
33         cost_t yy_cost;
34         set_t yy_set;
35         ident_p yy_ident;
36         char yy_char;
37         inst_t yy_instance;
38 }
39
40 %type <yy_list1> list1,structlistel
41 %type <yy_list2> structlist,structdecl
42 %type <yy_expr> expr optexpr
43 %type <yy_cost> optcost cost optcommacost
44 %type <yy_int> optboolexpr optnocoerc mnem emargno tokargno optprop
45 %type <yy_int> optcommabool optstack subreg tokenexpressionno optregvar
46 %type <yy_int> tokeninstanceno code stackreplacement optslashnumber
47 %type <yy_set> tokenexpression
48 %type <yy_instance> tokeninstance
49 %type <yy_string> optformat
50 %token <yy_string> IDENT TYPENAME
51 %token <yy_ident> RIDENT,PIDENT,TIDENT,EIDENT
52 %token <yy_string> LSTRING,STRING
53 %token <yy_int> NUMBER
54 %token <yy_intp> CIDENT
55 %token REGISTERHEAD TOKENHEAD EXPRESSIONHEAD CODEHEAD MOVEHEAD TESTHEAD STACKHEAD
56 %token REGVAR INREG LOOP POINTER FLOAT
57 %token TIMEFAC SIZEFAC FORMAT RETURN
58 %token MOVE ERASE ALLOCATE ELLIPS COST REMOVE STACK
59 %token SEP SAMESIGN SFIT UFIT ROM DEFINED TOSTRING LOWW HIGHW
60 %token NOCC SETCC SAMECC TEST NOCOERC
61 %token <yy_char> LCASELETTER
62 %start machinespec
63
64 %left OR2
65 %left AND2
66 %left CMPEQ,CMPNE
67 %left CMPLT,CMPLE,CMPGT,CMPGE
68 %left RSHIFT,LSHIFT
69 %left '+','-'
70 %left '*','/','%'
71 %nonassoc NOT,COMP,UMINUS
72 %nonassoc '$'
73 %%
74 machinespec
75         : rcsid constants registersection tokensection
76                 { inbetween(); }
77           expressionsection codesection movesection testsection stacksection
78         ;
79
80 rcsid
81         : /* empty */
82         | STRING
83                 { strlookup($1); }
84         ;
85
86 constants
87         : /* empty */
88         | constants CIDENT '=' NUMBER
89                 { *$2 = $4; }
90         | constants SIZEFAC '=' NUMBER optslashnumber
91                 { cc1 = $4; cc2 = $5; }
92         | constants TIMEFAC '=' NUMBER optslashnumber
93                 { cc3 = $4; cc4 = $5; }
94         | constants FORMAT '=' STRING
95                 { fmt = $4; }
96         ;
97 optslashnumber
98         : /* empty */
99                 { $$ = 1; }
100         | '/' NUMBER
101                 { $$ = $2; }
102         ;
103
104 registersection
105         : REGISTERHEAD registerdefs
106         ;
107 registerdefs
108         : /* empty */
109         | registerdefs registerdef
110         ;
111
112 registerdef
113         : IDENT '=' '(' STRING ',' NUMBER list1 ')' optregvar list1 '.'
114                 {       register ident_p ip;
115                         register list1 l;
116                         register reginfo r;
117                         int i;
118
119                         r=(reginfo) myalloc(sizeof(struct reginfo));
120                         r->rname = $1;
121                         r->rrepr = $4;
122                         r->rsize = $6;
123                         if($9>=0 && $7!=0)
124                                 yyerror("No subregisters allowed in regvar");
125                         for (i=0;i<MAXMEMBERS;i++)
126                                 r->rmembers[i] = 0;
127                         i=0;
128                         for (l=$7;l!=0;l=l->l1next) {
129                                 ip=ilookup(l->l1name,LOOKUP);
130                                 if (ip->i_type != IREG)
131                                         yyerror("Bad member of set");
132                                 chktabsiz(i,MAXMEMBERS,"Member of register");
133                                 r->rmembers[i++] = ip->i_i.i_regno;
134                         }
135                         maxmembers=max(maxmembers,i);
136                         r->rregvar=$9;
137                         if ($9>=0) {
138                                 rvused=1;
139                                 chktabsiz(nregvar[$9],MAXREGVARS,"Regvar");
140                                 rvnumbers[$9][nregvar[$9]++] = nmachregs;
141                         }
142                         for(i=0;i<PROPSETSIZE;i++)
143                                 r->rprop[i] = 0;
144                         ip=ilookup($1,ENTER);
145                         ip->i_type=IREG;
146                         ip->i_i.i_regno=nmachregs;
147                         for (l = $10; l!= 0; l=l->l1next) {
148                                 ip = ilookup(l->l1name,HALFWAY);
149                                 if (ip->i_type) {
150                                         if (ip->i_type != IPRP)
151                                                 yyerror("Multiple defined symbol");
152                                         else if(machprops[ip->i_i.i_prpno].propset.set_size != r->rsize)
153                                                 yyerror("property has more than 1 size");
154                                 } else {
155                                         chktabsiz(nprops,MAXPROPS,"Property");
156                                         ip->i_type = IPRP;
157                                         ip->i_i.i_prpno = nprops;
158                                         machprops[nprops].propname = ip;
159                                         machprops[nprops++].propset.set_size = r->rsize;
160                                 }
161                                 r->rprop[ip->i_i.i_prpno>>4] |= (1<<(ip->i_i.i_prpno&017));
162                         }
163                         chktabsiz(nmachregs,MAXREGS,"Register table");
164                         machregs[nmachregs++] = r;
165                 }
166         | error '.'
167         ;
168
169 optregvar
170         : /* nothing */
171                 { $$ = -1; }
172         | REGVAR
173                 { $$ = reg_any; }
174         | REGVAR '(' LOOP ')'
175                 { $$ = reg_loop; }
176         | REGVAR '(' POINTER ')'
177                 { $$ = reg_pointer; }
178         | REGVAR '(' FLOAT ')'
179                 { $$ = reg_float; }
180         ;
181
182 tokensection
183         : TOKENHEAD tkdefs
184         ;
185 tkdefs
186         : /* empty */
187         | tkdefs tkdef
188         ;
189 tkdef
190         : IDENT '=' structdecl NUMBER optcost optformat
191                 { register token_p tp;
192                   register ident_p ip;
193
194                   chktabsiz(nmachtokens,MAXTOKENS,"Token table");
195                   tp = &machtokens[nmachtokens];
196                   tp->t_name = $1;
197                   tp->t_struct = $3;
198                   tp->t_size = $4;
199                   tp->t_cost = $5;
200                   ip = ilookup($1,ENTER);
201                   ip->i_type = ITOK;
202                   ip->i_i.i_tokno = nmachtokens++;
203                   maxtokensize=max(maxtokensize,structsize($3));
204                   setfields(tp,$6);
205                 }
206         | error
207         ;
208 structdecl
209         : '{' structlist '}'
210                 { $$ = lookstruct($2); }
211         ;
212 structlist
213         : /* empty */
214                 { $$=0; }
215         | structlistel structlist
216                 { $$=(list2) myalloc(sizeof(struct list2str));
217                   $$->l2next = $2;
218                   $$->l2list = $1;
219                 }
220         ;
221 structlistel
222         : TYPENAME list1 ';'
223                 { $$=(list1) myalloc(sizeof(struct list1str));
224                   $$->l1next = $2;
225                   $$->l1name = $1;
226                 }
227         ;
228
229 optcost : /* empty */
230                 { $$.c_size = $$.c_time = 0; }
231         | COST '=' '(' expr ',' expr ')'
232                 { MUST2BEINT($4,$6);
233                   $$.c_size = exp1;
234                   $$.c_time = exp2;
235                 }
236         ;
237 optformat
238         : /* empty */
239                 { $$ = 0; }
240         | STRING
241         ;
242
243 expressionsection
244         : /* empty */
245         | EXPRESSIONHEAD tokenexpressions
246         ;
247 tokenexpressions
248         : tokenexpressionline
249         | tokenexpressionline tokenexpressions
250         ;
251 tokenexpressionline
252         : IDENT '=' tokenexpression
253                 {
254                   {     register ident_p ip;
255
256                         chktabsiz(nmachsets,MAXSETS,"Expression table");
257                         machsets[nmachsets] = $3;
258                         ip=ilookup($1,ENTER);
259                         ip->i_type = IEXP;
260                         ip->i_i.i_expno = nmachsets++;
261                   }
262                 }
263         | error
264         ;
265 tokenexpression
266         : PIDENT
267                 { $$ = machprops[$1->i_i.i_prpno].propset; }
268         | TIDENT
269                 { register i;
270
271                   for(i=0;i<SETSIZE;i++) $$.set_val[i]=0;
272                   $$.set_val[($1->i_i.i_tokno+nmachregs+1)>>4] |=
273                         01<<(($1->i_i.i_tokno+nmachregs+1)&017);
274                   $$.set_size = machtokens[$1->i_i.i_tokno].t_size;
275                 }
276         | EIDENT
277                 { $$=machsets[$1->i_i.i_expno]; }
278         | tokenexpression '*' tokenexpression
279                 { register i;
280
281                   if (($$.set_size=$1.set_size)==0)
282                         $$.set_size = $3.set_size;
283                   for (i=0;i<SETSIZE;i++)
284                         $$.set_val[i] = $1.set_val[i] & $3.set_val[i];
285                 }
286         | tokenexpression '+' tokenexpression
287                 { register i;
288
289                   if ($1.set_size == -1)
290                         $$.set_size = $3.set_size;
291                   else if ($3.set_size == -1)
292                         $$.set_size = $1.set_size;
293                   else if ($1.set_size == $3.set_size)
294                         $$.set_size = $1.set_size;
295                   else
296                         $$.set_size = 0;
297                   for (i=0;i<SETSIZE;i++)
298                         $$.set_val[i] = $1.set_val[i] | $3.set_val[i];
299                 }
300         | tokenexpression '-' tokenexpression
301                 { register i;
302
303                   if ($1.set_size == -1)
304                         $$.set_size = $3.set_size;
305                   else if ($3.set_size == -1)
306                         $$.set_size = $1.set_size;
307                   else if ($1.set_size == $3.set_size)
308                         $$.set_size = $1.set_size;
309                   else
310                         $$.set_size = 0;
311                   for (i=0;i<SETSIZE;i++)
312                         $$.set_val[i] = $1.set_val[i] & ~ $3.set_val[i];
313                 }
314         | '(' tokenexpression ')'
315                 { $$ = $2; }
316         ;
317
318 codesection
319         : CODEHEAD coderules
320         ;
321 coderules
322         : coderule
323         | coderules coderule
324         ;
325 coderule
326         : { nallreg=emrepllen=tokrepllen=0; }
327                 empattern SEP stackpattern SEP code SEP stackreplacement SEP
328                 emreplacement SEP cost
329                         { int i;
330
331                           if (emrepllen) {
332                                 outbyte(DO_EMREPLACE+(emrepllen<<5));
333                                 for (i=0;i<emrepllen;i++) {
334                                         out(replmnem[i]);
335                                         out(replexpr[i]);
336                                 }
337                           }
338                           if ($8==0) {
339                                   outbyte(DO_TOKREPLACE+(tokrepllen<<5));
340                                   for(i=0;i<tokrepllen;i++)
341                                         out(replinst[i]);
342                           } else {
343                                 static int warncount=0;
344                                 if (!warncount++)
345                                         fprintf(stderr,
346                 "WARNING: convert to stacksection, will disappear soon");
347                                 outbyte(DO_TOKREPLACE);
348                           }
349                           if ($12.c_size!=0 || $12.c_time!=0) {
350                                   outbyte(DO_COST);
351                                   out($12.c_size);
352                                   out($12.c_time);
353                           }
354                           outbyte(empatlen==0? DO_RETURN : DO_NEXTEM);
355                           fprintf(cfile,"\n");
356                           ncoderules++;
357                           maxallreg=max(maxallreg,nallreg);
358                           if (empatlen==0) { /* coercion */
359                                 if (tokrepllen<1 && $8==0)
360                                         yyerror("No replacement in coercion");
361                                 if (tokpatlen>1)
362                                         yyerror("Token pattern too long");
363                                 if ($8!=0) { /* stacking */
364                                         c1_p cp;
365                                         chktabsiz(nc1,MAXC1,"Coerc table 1");
366                                         cp = &c1coercs[nc1++];
367                                         cp->c1_texpno = pattokexp[1];
368                                         cp->c1_prop = -1;
369                                         cp->c1_codep = $6;
370                                 } else if (tokrepllen>1) { /* splitting */
371                                         c2_p cp;
372                                         chktabsiz(nc2,MAXC2,"Coerc table 2");
373                                         cp= &c2coercs[nc2++];
374                                         cp->c2_texpno = pattokexp[1];
375                                         cp->c2_nsplit = tokrepllen;
376                                         maxsplit=max(maxsplit,tokrepllen);
377                                         for (i=0;i<tokrepllen;i++)
378                                                 cp->c2_repl[i] = replinst[i];
379                                         cp->c2_codep = $6;
380                                         if (nallreg>0)
381                                                 yyerror("No allocates allowed here");
382                                 } else { /* one to one coercion */
383                                         c3_p cp;
384                                         chktabsiz(nc3,MAXC3,"Coerc table 3");
385                                         cp= &c3coercs[nc3++];
386                                         if (tokpatlen)
387                                                 cp->c3_texpno = pattokexp[1];
388                                         else
389                                                 cp->c3_texpno = 0;
390                                         if (nallreg>1)
391                                                 yyerror("Too many allocates in coercion");
392                                         cp->c3_prop = nallreg==0 ? 0 : allreg[0];
393                                         cp->c3_repl = replinst[0];
394                                         cp->c3_codep = $6;
395                                 }
396                           }
397                         }
398         | error
399         ;
400 empattern
401         : /* empty */
402                 { empatlen=0; }
403         | mnemlist optboolexpr
404                 { register i;
405
406                   empatexpr = $2;
407                   patbyte(0);
408                   patshort(prevind);
409                   prevind = npatbytes - 3;
410                   maxempatlen = max(empatlen,maxempatlen);
411                   pat(empatlen);
412                   for(i=1;i<=empatlen;i++)
413                         patbyte(patmnem[i]);
414                   pat(empatexpr);
415                   rulecount = npatbytes;
416                   patbyte(1);   /* number of different rules with this pattern */
417                   pat(codebytes);       /* first rule */
418                 }
419         | ELLIPS
420                 { pattern[rulecount]++;
421                   maxrule= max(maxrule,pattern[rulecount]);
422                   pat(codebytes);
423                 }
424         ;
425
426 mnemlist
427         :       mnem
428                 { empatlen = 1; patmnem[empatlen] = $1; }
429         |       mnemlist mnem
430                 { chktabsiz(empatlen+1,MAXEMPATLEN,"EM pattern");
431                   patmnem[++empatlen] = $2;
432                 }
433         ;
434 mnem    :       IDENT
435                 { if(strlen($1)!=3 || ($$=mlookup($1))==0)
436                         yyerror("not an EM-mnemonic");
437                 }
438         ;
439
440 stackpattern
441         : optnocoerc tokenexpressionlist optstack
442                 { register i;
443
444                   if (tokpatlen != 0) {
445                           outbyte(($1 ? ( $3 ? DO_XXMATCH: DO_XMATCH ) : DO_MATCH)+(tokpatlen<<5));
446                           for(i=1;i<=tokpatlen;i++) {
447                                 out(pattokexp[i]);
448                           }
449                   }
450                   if ($3 && tokpatlen==0 && empatlen==0) {
451                           outbyte(DO_COERC);
452                   }
453                   if ($3 && !$1 && empatlen!=0) {
454                         outbyte(DO_REMOVE);
455                         out(allexpno);
456                   }
457                 }
458         ;
459
460 optnocoerc
461         : /* empty */
462                 { $$ = 0; }
463         | NOCOERC ':'
464                 { $$ = 1; }
465         ;
466
467 tokenexpressionlist
468         : /* empty */
469                 { tokpatlen = 0; }
470         | tokenexpressionlist tokenexpressionno
471                 { chktabsiz(tokpatlen+1,MAXPATLEN,"Token pattern");
472                   pattokexp[++tokpatlen] = $2;
473                   if (machsets[$2].set_size==0)
474                         yyerror("Various sized set in tokenpattern");
475                 }
476         ;
477
478 tokenexpressionno
479         : tokenexpression
480                 { $$ = exprlookup($1); }
481         ;
482
483 optstack
484         :       /* empty */
485                 { $$ = 0; }
486         |       STACK
487                 { $$ = 1; }
488         ;
489
490 code    :
491                 { $$ = codebytes; cchandled=ccspoiled=0; }
492           initcode restcode
493                 { if (cchandled==0 && ccspoiled!=0) {
494                         outbyte(DO_ERASE);
495                         out(ccregexpr);
496                   }
497                 }
498         ;
499
500 initcode
501         : /* empty */
502         | initcode remove
503         | initcode allocate
504         ;
505 remove
506         : REMOVE '(' tokenexpressionno
507                 { curtokexp = $3; }
508           optcommabool ')'
509                 { outbyte(DO_REMOVE+ ($5!=0 ? 32 : 0));
510                   out($3);
511                   if ($5!=0) out($5);
512                 }
513         | REMOVE '(' expr ')'
514                 { if ($3.expr_typ != TYPREG)
515                         yyerror("Expression must be register");
516                   outbyte(DO_RREMOVE);
517                   out($3.expr_index);
518                 }
519         ;
520 optcommabool
521         : /* empty */
522                 { $$ = 0; }
523         | ',' expr
524                 { MUST1BEBOOL($2);
525                   $$ = exp1;
526                 }
527         ;
528
529 restcode: /* empty */
530         | restcode LSTRING expr
531                 { outbyte(DO_LOUTPUT);
532                   out(stringno($2));
533                   free($2);
534                   out($3.expr_index);
535                   ccspoiled++;
536                 }
537         | restcode stringlist
538                 { int i;
539                   for(i=0;nstr>0;i++,nstr--) {
540                         if (i%8==0) outbyte(DO_ROUTPUT+(nstr>7 ? 7 : nstr-1)*32);
541                         out(strar[i]);
542                   }
543                   ccspoiled++;
544                 }
545         | restcode RETURN
546                 { outbyte(DO_PRETURN); }
547         | restcode move
548         | restcode erase
549         | restcode NOCC
550                 { outbyte(DO_ERASE);
551                   out(ccregexpr);
552                   cchandled++;
553                 }
554         | restcode SAMECC
555                 { cchandled++; }
556         | restcode SETCC '(' tokeninstanceno ')'
557                 { outbyte(DO_MOVE);
558                   out(ccinstanceno);
559                   out($4);
560                   cchandled++;
561                 }
562         | restcode TEST '(' tokeninstanceno ')'
563                 { outbyte(DO_MOVE);
564                   out($4);
565                   out(ccinstanceno);
566                   ccspoiled=0;
567                 }
568         ;
569
570 stringlist
571         : STRING
572                 { nstr=1;
573                   strar[0]=stringno($1);
574                   free($1);
575                 }
576         | stringlist STRING
577                 { chktabsiz(nstr,MAXNSTR,"Consecutiv strings");
578                   strar[nstr++] = stringno($2);
579                   free($2);
580                 }
581         ;
582
583 move
584         : MOVE '(' tokeninstanceno ',' tokeninstanceno ')'
585                 { outbyte(DO_MOVE);
586                   out($3);
587                   out($5);
588                 }
589         ;
590
591 erase
592         : ERASE '(' expr ')'
593                 { outbyte(DO_ERASE);
594                   out($3.expr_index);
595                   if($3.expr_typ != TYPREG)
596                         yyerror("Bad argument of erase");
597                 }
598         ;
599
600 allocate
601         : ALLOCATE { dealflag=0; } '(' alloclist ')'
602                 { if (dealflag)
603                         outbyte(DO_REALLOCATE);
604                 }
605         ;
606
607
608 alloclist
609         : allocel
610         | alloclist optcomma allocel
611         ;
612
613 allocel
614         : tokeninstanceno       /* deallocate */
615                 { outbyte(DO_DEALLOCATE);
616                   out($1);
617                   dealflag++;
618                 }
619         | PIDENT
620                 { allreg[nallreg++] = $1->i_i.i_prpno;
621                   outbyte(DO_ALLOCATE);
622                   out($1->i_i.i_prpno);
623                 }
624         | PIDENT '=' tokeninstanceno
625                 { allreg[nallreg++] = $1->i_i.i_prpno;
626                   outbyte(DO_ALLOCATE+32);
627                   out($1->i_i.i_prpno);
628                   out($3);
629                 }
630         ;
631
632 stackreplacement
633         : /* empty */
634                 { $$=0; }
635         | STACK
636                 { $$=1; }
637         | '{' STACK '}'
638                 { $$=1; }
639         | stackrepllist
640                 { $$=0; }
641         ;
642 stackrepllist
643         : tokeninstanceno
644                 { tokrepllen=1; replinst[0] = $1; }
645         | stackrepllist tokeninstanceno
646                 { chktabsiz(tokrepllen+1,MAXPATLEN,"Stack replacement");
647                   replinst[tokrepllen++] = $2;
648                 }
649         ;
650
651 emreplacement
652         : /* empty, normal case */
653         | emrepllist
654         ;
655 emrepllist
656         : mnem optexpr
657                 { emrepllen=1;
658                   replmnem[0]=$1;
659                   replexpr[0]=$2.expr_index;
660                 }
661         | emrepllist mnem optexpr
662                 { chktabsiz(emrepllen+1,MAXEMPATLEN,"EM replacement");
663                   replmnem[emrepllen]=$2;
664                   replexpr[emrepllen]=$3.expr_index;
665                   emrepllen++;
666                 }
667         ;
668
669 cost    : /* empty */
670                 { $$.c_size = $$.c_time = 0;
671                 }
672         | '(' expr ',' expr ')'
673                 { MUST2BEINT($2,$4);
674                   $$.c_size = exp1;
675                   $$.c_time = exp2;
676                 }
677         | cost '+' '%' '[' tokargno ']'
678                 { $$.c_size = lookup(1,EX_PLUS,$1.c_size,
679                                         lookup(0,EX_COST,$5,0));
680                   $$.c_time = lookup(1,EX_PLUS,$1.c_time,
681                                         lookup(0,EX_COST,$5,1));
682                 }
683         ;
684
685 movesection
686         : MOVEHEAD movedefs
687         ;
688
689 movedefs
690         : movedef
691         | movedefs movedef
692         ;
693
694 movedef
695         : '(' tokenexpressionno
696                 { curtokexp = $2; }
697           optboolexpr ',' tokenexpressionno
698                 { curtokexp = $6;
699                   pattokexp[1] = $2;
700                   pattokexp[2] = $6;
701                   tokpatlen=2;
702                 }
703           optboolexpr ',' code optcommacost ')'
704                 { register move_p mp;
705
706                   outbyte(DO_RETURN);
707                   fprintf(cfile,"\n");
708                   chktabsiz(nmoves,NMOVES,"Move definition table");
709                   mp = &machmoves[nmoves++];
710                   mp->m_set1 = $2;
711                   mp->m_expr1= $4;
712                   mp->m_set2 = $6;
713                   mp->m_expr2= $8;
714                   mp->m_cindex=$10;
715                   mp->m_cost = $11;
716                 }
717         | error
718         ;
719
720 testsection
721         : /* empty */
722         | TESTHEAD testdefs
723         ;
724
725 testdefs: testdef
726         | testdefs testdef
727         ;
728
729 testdef : '(' tokenexpressionno
730                 { curtokexp = $2;
731                   pattokexp[1] = $2;
732                   pattokexp[2] = cocosetno;
733                   tokpatlen=2;
734                 }
735           optboolexpr ',' code optcommacost ')'
736                 { register move_p mp;
737
738                   outbyte(DO_RETURN);
739                   fprintf(cfile,"\n");
740                   chktabsiz(nmoves,NMOVES,"Move definition table(tests)");
741                   mp = &machmoves[nmoves++];
742                   mp->m_set1 = $2;
743                   mp->m_expr1 = $4;
744                   mp->m_set2 = cocosetno;
745                   mp->m_expr2 = 0;
746                   mp->m_cindex = $6;
747                   mp->m_cost = $7;
748                 }
749         ;
750
751 stacksection
752         : STACKHEAD stackdefs
753         | /* empty */
754         ;
755 stackdefs
756         : stackdef
757         | stackdefs stackdef
758         ;
759 stackdef
760         : '(' tokenexpressionno
761                 { curtokexp = $2;
762                   pattokexp[1] = $2;
763                   tokpatlen=1;
764                 }
765           optboolexpr ',' optprop ',' code optcommacost ')'
766                 { register c1_p cp;
767
768                   outbyte(DO_TOKREPLACE);
769                   outbyte(DO_RETURN);
770                   fprintf(cfile,"\n");
771                   chktabsiz(nc1,MAXC1,"Stacking table");
772                   cp = &c1coercs[nc1++];
773                   cp->c1_texpno = $2;
774                   cp->c1_expr = $4;
775                   cp->c1_prop = $6;
776                   cp->c1_codep = $8;
777                   cp->c1_cost = $9;
778                 }
779         ;
780
781 optprop
782         : /* empty */
783                 { $$ = -1; }
784         | PIDENT 
785                 { $$ = $1->i_i.i_prpno; }
786         ;
787
788 optcommacost
789         : /* empty */
790                 { $$.c_size = 0; $$.c_time = 0;}
791         | ',' cost
792                 { $$ = $2; }
793         ;
794
795 list1   : /* empty */
796                 { $$ = 0; }
797         | optcomma IDENT list1
798                 { $$=(list1) myalloc(sizeof(struct list1str));
799                   $$->l1next = $3;
800                   $$->l1name = $2;
801                 }
802         ;
803 optcomma: /* nothing */
804         | ','
805         ;
806 emargno : NUMBER
807                 { if ($1<1 || $1>empatlen)
808                         yyerror("Number after $ out of range");
809                   $$ = $1;
810                 }
811         ;
812 tokargno
813         : NUMBER
814                 { if ($1<1 || $1>tokpatlen)
815                         yyerror("Number within %[] out of range");
816                   $$ = $1;
817                 }
818         ;
819 expr    : '$' emargno
820                 { $$.expr_index = lookup(0,EX_ARG,$2,0); $$.expr_typ = argtyp(patmnem[$2]);
821                 }
822         | NUMBER
823                 { $$.expr_index = lookup(0,EX_CON,(int)($1&0177777),(int)($1>>16));
824                   $$.expr_typ = TYPINT;
825                 }
826         | STRING
827                 { $$.expr_index = lookup(0,EX_STRING,strlookup($1),0);
828                   $$.expr_typ = TYPSTR;
829                 }
830         | RIDENT
831                 { $$.expr_index = lookup(0,EX_REG,$1->i_i.i_regno,0);
832                   $$.expr_typ = TYPREG;
833                 }
834         | '%' '[' tokargno '.' IDENT ']'
835                 { $$.expr_index = lookup(0,EX_TOKFIELD,$3,
836                      findstructel(pattokexp[$3],$5,&$$.expr_typ));
837                 }
838         | '%' '[' tokargno subreg ']'
839                 { chkregexp(pattokexp[$3]);
840                   $$.expr_index = lookup(0,EX_SUBREG,$3,$4);
841                   $$.expr_typ = TYPREG;
842                 }
843         | '%' '[' LCASELETTER subreg ']'
844                 { if ($3 >= 'a'+nallreg)
845                         yyerror("Bad letter in %[x] construct");
846                   $$.expr_index = lookup(0,EX_ALLREG,$3-'a'+1,$4);
847                   $$.expr_typ = TYPREG;
848                 }
849         | '%' '[' IDENT ']'
850                 { $$.expr_index = lookup(0,EX_TOKFIELD,0,
851                      findstructel(curtokexp,$3,&$$.expr_typ));
852                 }
853         | TOSTRING '(' expr ')'
854                 { MUST1BEINT($3);
855                   $$.expr_index = lookup(0,EX_TOSTRING,exp1,0);
856                   $$.expr_typ = TYPSTR;
857                 }
858         | DEFINED '(' expr ')'
859                 { $$.expr_index = lookup(0,EX_DEFINED,$3.expr_index,0);
860                   $$.expr_typ = TYPBOOL;
861                 }
862         | SAMESIGN '(' expr ',' expr ')'
863                 { MUST2BEINT($3,$5);
864                   $$.expr_index = lookup(1,EX_SAMESIGN,exp1,exp2);
865                   $$.expr_typ = TYPBOOL;
866                 }
867         | SFIT '(' expr ',' expr ')'
868                 { MUST2BEINT($3,$5);
869                   $$.expr_index = lookup(0,EX_SFIT,exp1,exp2);
870                   $$.expr_typ = TYPBOOL;
871                 }
872         | UFIT '(' expr ',' expr ')'
873                 { MUST2BEINT($3,$5);
874                   $$.expr_index = lookup(0,EX_UFIT,exp1,exp2);
875                   $$.expr_typ = TYPBOOL;
876                 }
877         | ROM '(' emargno ',' NUMBER ')'
878                 { if ($5<1 || $5>3)
879                         yyerror("Second argument of rom must be >=1 and <=3");
880                   $$.expr_index = lookup(0,EX_ROM,$3-1,$5-1);
881                   $$.expr_typ = TYPINT;
882                 }
883         | LOWW '(' emargno ')'
884                 {
885                   $$.expr_index = lookup(0,EX_LOWW,$3-1,0);
886                   $$.expr_typ = TYPINT;
887                 }
888         | HIGHW '(' emargno ')'
889                 {
890                   $$.expr_index = lookup(0,EX_HIGHW,$3-1,0);
891                   $$.expr_typ = TYPINT;
892                 }
893         | '(' expr ')'
894                 { $$ = $2; }
895         | expr CMPEQ expr
896                 { switch(commontype($1,$3)) {
897                   case TYPINT:
898                         $$.expr_index = lookup(1,EX_NCPEQ,$1.expr_index,$3.expr_index);
899                         break;
900                   case TYPSTR:
901                         $$.expr_index = lookup(1,EX_SCPEQ,$1.expr_index,$3.expr_index);
902                         break;
903                   case TYPREG:
904                         $$.expr_index = lookup(1,EX_RCPEQ,$1.expr_index,$3.expr_index);
905                         break;
906                   }
907                   $$.expr_typ = TYPBOOL;
908                 }
909         | expr CMPNE expr
910                 { switch(commontype($1,$3)) {
911                   case TYPINT:
912                         $$.expr_index = lookup(1,EX_NCPNE,$1.expr_index,$3.expr_index);
913                         break;
914                   case TYPSTR:
915                         $$.expr_index = lookup(1,EX_SCPNE,$1.expr_index,$3.expr_index);
916                         break;
917                   case TYPREG:
918                         $$.expr_index = lookup(1,EX_RCPNE,$1.expr_index,$3.expr_index);
919                         break;
920                   }
921                   $$.expr_typ = TYPBOOL;
922                 }
923         | expr CMPGT expr
924                 { MUST2BEINT($1,$3);
925                   $$.expr_index = lookup(0,EX_NCPGT,exp1,exp2);
926                   $$.expr_typ = TYPBOOL;
927                 }
928         | expr CMPGE expr
929                 { MUST2BEINT($1,$3);
930                   $$.expr_index = lookup(0,EX_NCPGE,exp1,exp2);
931                   $$.expr_typ = TYPBOOL;
932                 }
933         | expr CMPLT expr
934                 { MUST2BEINT($1,$3);
935                   $$.expr_index = lookup(0,EX_NCPLT,exp1,exp2);
936                   $$.expr_typ = TYPBOOL;
937                 }
938         | expr CMPLE expr
939                 { MUST2BEINT($1,$3);
940                   $$.expr_index = lookup(0,EX_NCPLE,exp1,exp2);
941                   $$.expr_typ = TYPBOOL;
942                 }
943         | expr OR2 expr
944                 { MUST2BEBOOL($1,$3);
945                   $$.expr_index = lookup(0,EX_OR2,exp1,exp2);
946                   $$.expr_typ = TYPBOOL;
947                 }
948         | expr AND2 expr
949                 { MUST2BEBOOL($1,$3);
950                   $$.expr_index = lookup(0,EX_AND2,exp1,exp2);
951                   $$.expr_typ = TYPBOOL;
952                 }
953         | expr '+' expr
954                 { switch(commontype($1,$3)) {
955                   case TYPINT:
956                         $$.expr_index = lookup(1,EX_PLUS,$1.expr_index,$3.expr_index);
957                         break;
958                   case TYPSTR:
959                         $$.expr_index = lookup(0,EX_CAT,$1.expr_index,$3.expr_index);
960                         break;
961                   default:
962                         yyerror("Bad types");
963                   }
964                   $$.expr_typ = $1.expr_typ;
965                 }
966         | expr '-' expr
967                 { MUST2BEINT($1,$3);
968                   $$.expr_index = lookup(0,EX_MINUS,exp1,exp2);
969                   $$.expr_typ = TYPINT;
970                 }
971         | expr '*' expr
972                 { MUST2BEINT($1,$3);
973                   $$.expr_index = lookup(1,EX_TIMES,exp1,exp2);
974                   $$.expr_typ = TYPINT;
975                 }
976         | expr '/' expr
977                 { MUST2BEINT($1,$3);
978                   $$.expr_index = lookup(0,EX_DIVIDE,exp1,exp2);
979                   $$.expr_typ = TYPINT;
980                 }
981         | expr '%' expr
982                 { MUST2BEINT($1,$3);
983                   $$.expr_index = lookup(0,EX_MOD,exp1,exp2);
984                   $$.expr_typ = TYPINT;
985                 }
986         | expr LSHIFT expr
987                 { MUST2BEINT($1,$3);
988                   $$.expr_index = lookup(0,EX_LSHIFT,exp1,exp2);
989                   $$.expr_typ = TYPINT;
990                 }
991         | expr RSHIFT expr
992                 { MUST2BEINT($1,$3);
993                   $$.expr_index = lookup(0,EX_RSHIFT,exp1,exp2);
994                   $$.expr_typ = TYPINT;
995                 }
996         | NOT expr
997                 { MUST1BEBOOL($2);
998                   $$.expr_index = lookup(0,EX_NOT,exp1,0);
999                   $$.expr_typ = TYPBOOL;
1000                 }
1001         | COMP expr
1002                 { MUST1BEINT($2);
1003                   $$.expr_index = lookup(0,EX_COMP,exp1,0);
1004                   $$.expr_typ = TYPINT;
1005                 }
1006         | INREG '(' expr ')'
1007                 { MUST1BEINT($3);
1008                   $$.expr_index = lookup(0,EX_INREG,exp1,0);
1009                   $$.expr_typ = TYPINT;
1010                 }
1011         | REGVAR '(' expr ')'
1012                 { MUST1BEINT($3);
1013                   $$.expr_index = lookup(0,EX_REGVAR,exp1,0);
1014                   $$.expr_typ = TYPREG;
1015                 }
1016 /*
1017         | '-' expr %prec UMINUS
1018                 { MUST1BEINT($2);
1019                   $$.expr_index = lookup(0,EX_UMINUS,exp1,0);
1020                   $$.expr_typ = TYPINT;
1021                 }
1022 */
1023         ;
1024
1025 subreg  : /* empty */
1026                 { $$=0; }
1027         | '.' NUMBER
1028                 { $$=$2; }
1029         ;
1030
1031 optboolexpr
1032         : /* empty */
1033                 { $$ = 0; }
1034         | expr
1035                 { MUST1BEBOOL($1);
1036                   $$=exp1;
1037                 }
1038         ;
1039 optexpr
1040         : /* empty */
1041                 { $$.expr_typ=0;
1042                   $$.expr_index=0;
1043                 }
1044         | expr
1045         ;
1046
1047 tokeninstanceno
1048         : tokeninstance
1049                 { $$ = instno($1); }
1050         ;
1051
1052 tokeninstance
1053         : '%' '[' tokargno subreg ']'
1054                 { register i;
1055
1056                   if ($4!=0)
1057                           chkregexp(pattokexp[$3]);
1058                   $$.in_which = IN_COPY;
1059                   $$.in_info[0] = $3;
1060                   $$.in_info[1] = $4;
1061                   for (i=2;i<TOKENSIZE;i++)
1062                         $$.in_info[i] = 0;
1063                 }
1064         | '%' '[' tokargno '.' IDENT ']'
1065                 { int typ;
1066                   register i;
1067                   $$.in_which = IN_COPY;
1068                   $$.in_info[0] = $3;
1069                   $$.in_info[1] = findstructel(pattokexp[$3],$5,&typ);
1070                   if (typ != TYPREG)
1071                         yyerror("Must be register");
1072                   for (i=2;i<TOKENSIZE;i++)
1073                         $$.in_info[i] = 0;
1074                 }
1075         | RIDENT
1076                 { register i;
1077                   $$.in_which = IN_RIDENT;
1078                   $$.in_info[0] = $1->i_i.i_regno;
1079                   for (i=1;i<TOKENSIZE;i++)
1080                         $$.in_info[i] = 0;
1081                 }
1082         | REGVAR '(' expr ')'
1083                 { register i;
1084                   MUST1BEINT($3);
1085                   $$.in_which = IN_REGVAR;
1086                   $$.in_info[0] = exp1;
1087                   for (i=1;i<TOKENSIZE;i++)
1088                         $$.in_info[i] = 0;
1089                 }
1090         | '%' '[' LCASELETTER subreg ']'
1091                 { register i;
1092                   if ($3 >= 'a'+nallreg)
1093                         yyerror("Bad letter in %[x] construct");
1094                   $$.in_which = IN_ALLOC;
1095                   $$.in_info[0] = $3-'a';
1096                   $$.in_info[1] = $4;
1097                   for (i=2;i<TOKENSIZE;i++)
1098                         $$.in_info[i] = 0;
1099                 }
1100         | '{' TIDENT attlist '}'
1101                 { register i;
1102                   $$.in_which = IN_DESCR;
1103                   $$.in_info[0] = $2->i_i.i_tokno;
1104                   for(i=0;i<narexp;i++) {
1105                         if (arexp[i].expr_typ !=
1106                               machtokens[$2->i_i.i_tokno].t_fields[i].t_type)
1107                                 yyerror("Attribute %d has wrong type",i+1);
1108                         $$.in_info[i+1] = arexp[i].expr_index;
1109                   }
1110                   for (i=narexp+1;i<TOKENSIZE;i++) {
1111                         if (machtokens[$2->i_i.i_tokno].t_fields[i-1].t_type!=0)
1112                                 yyerror("Too few attributes");
1113                         $$.in_info[i] = 0;
1114                   }
1115                 }
1116         ;
1117
1118 attlist
1119         : /* empty */
1120                 { narexp = 0; }
1121         | attlist ',' expr
1122                 { arexp[narexp++] = $3; }
1123         ;
1124
1125 %%