4 static char rcsid[]="$Id: bootgram.y,v 2.16 1994/06/24 10:16:05 ceriel Exp $";
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".
11 * Author: Hans van Staveren
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
67 %left CMPLT,CMPLE,CMPGT,CMPGE
71 %nonassoc NOT,COMP,UMINUS
75 : rcsid constants registersection tokensection
77 expressionsection codesection movesection testsection stacksection
88 | constants CIDENT '=' NUMBER
90 | constants SIZEFAC '=' NUMBER optslashnumber
91 { cc1 = $4; cc2 = $5; }
92 | constants TIMEFAC '=' NUMBER optslashnumber
93 { cc3 = $4; cc4 = $5; }
94 | constants FORMAT '=' STRING
105 : REGISTERHEAD registerdefs
109 | registerdefs registerdef
113 : IDENT '=' '(' STRING ',' NUMBER list1 ')' optregvar list1 '.'
114 { register ident_p ip;
119 r=(reginfo) myalloc(sizeof(struct reginfo));
124 yyerror("No subregisters allowed in regvar");
125 for (i=0;i<MAXMEMBERS;i++)
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;
135 maxmembers=max(maxmembers,i);
139 chktabsiz(nregvar[$9],MAXREGVARS,"Regvar");
140 rvnumbers[$9][nregvar[$9]++] = nmachregs;
142 for(i=0;i<PROPSETSIZE;i++)
144 ip=ilookup($1,ENTER);
146 ip->i_i.i_regno=nmachregs;
147 for (l = $10; l!= 0; l=l->l1next) {
148 ip = ilookup(l->l1name,HALFWAY);
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");
155 chktabsiz(nprops,MAXPROPS,"Property");
157 ip->i_i.i_prpno = nprops;
158 machprops[nprops].propname = ip;
159 machprops[nprops++].propset.set_size = r->rsize;
161 r->rprop[ip->i_i.i_prpno>>4] |= (1<<(ip->i_i.i_prpno&017));
163 chktabsiz(nmachregs,MAXREGS,"Register table");
164 machregs[nmachregs++] = r;
174 | REGVAR '(' LOOP ')'
176 | REGVAR '(' POINTER ')'
177 { $$ = reg_pointer; }
178 | REGVAR '(' FLOAT ')'
190 : IDENT '=' structdecl NUMBER optcost optformat
191 { register token_p tp;
194 chktabsiz(nmachtokens,MAXTOKENS,"Token table");
195 tp = &machtokens[nmachtokens];
200 ip = ilookup($1,ENTER);
202 ip->i_i.i_tokno = nmachtokens++;
203 maxtokensize=max(maxtokensize,structsize($3));
210 { $$ = lookstruct($2); }
215 | structlistel structlist
216 { $$=(list2) myalloc(sizeof(struct list2str));
223 { $$=(list1) myalloc(sizeof(struct list1str));
229 optcost : /* empty */
230 { $$.c_size = $$.c_time = 0; }
231 | COST '=' '(' expr ',' expr ')'
245 | EXPRESSIONHEAD tokenexpressions
248 : tokenexpressionline
249 | tokenexpressionline tokenexpressions
252 : IDENT '=' tokenexpression
254 { register ident_p ip;
256 chktabsiz(nmachsets,MAXSETS,"Expression table");
257 machsets[nmachsets] = $3;
258 ip=ilookup($1,ENTER);
260 ip->i_i.i_expno = nmachsets++;
267 { $$ = machprops[$1->i_i.i_prpno].propset; }
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;
277 { $$=machsets[$1->i_i.i_expno]; }
278 | tokenexpression '*' tokenexpression
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];
286 | tokenexpression '+' tokenexpression
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;
297 for (i=0;i<SETSIZE;i++)
298 $$.set_val[i] = $1.set_val[i] | $3.set_val[i];
300 | tokenexpression '-' tokenexpression
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;
311 for (i=0;i<SETSIZE;i++)
312 $$.set_val[i] = $1.set_val[i] & ~ $3.set_val[i];
314 | '(' tokenexpression ')'
326 : { nallreg=emrepllen=tokrepllen=0; }
327 empattern SEP stackpattern SEP code SEP stackreplacement SEP
328 emreplacement SEP cost
332 outbyte(DO_EMREPLACE+(emrepllen<<5));
333 for (i=0;i<emrepllen;i++) {
339 outbyte(DO_TOKREPLACE+(tokrepllen<<5));
340 for(i=0;i<tokrepllen;i++)
343 static int warncount=0;
346 "WARNING: convert to stacksection, will disappear soon");
347 outbyte(DO_TOKREPLACE);
349 if ($12.c_size!=0 || $12.c_time!=0) {
354 outbyte(empatlen==0? DO_RETURN : DO_NEXTEM);
357 maxallreg=max(maxallreg,nallreg);
358 if (empatlen==0) { /* coercion */
359 if (tokrepllen<1 && $8==0)
360 yyerror("No replacement in coercion");
362 yyerror("Token pattern too long");
363 if ($8!=0) { /* stacking */
365 chktabsiz(nc1,MAXC1,"Coerc table 1");
366 cp = &c1coercs[nc1++];
367 cp->c1_texpno = pattokexp[1];
370 } else if (tokrepllen>1) { /* splitting */
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];
381 yyerror("No allocates allowed here");
382 } else { /* one to one coercion */
384 chktabsiz(nc3,MAXC3,"Coerc table 3");
385 cp= &c3coercs[nc3++];
387 cp->c3_texpno = pattokexp[1];
391 yyerror("Too many allocates in coercion");
392 cp->c3_prop = nallreg==0 ? 0 : allreg[0];
393 cp->c3_repl = replinst[0];
403 | mnemlist optboolexpr
409 prevind = npatbytes - 3;
410 maxempatlen = max(empatlen,maxempatlen);
412 for(i=1;i<=empatlen;i++)
415 rulecount = npatbytes;
416 patbyte(1); /* number of different rules with this pattern */
417 pat(codebytes); /* first rule */
420 { pattern[rulecount]++;
421 maxrule= max(maxrule,pattern[rulecount]);
428 { empatlen = 1; patmnem[empatlen] = $1; }
430 { chktabsiz(empatlen+1,MAXEMPATLEN,"EM pattern");
431 patmnem[++empatlen] = $2;
435 { if(strlen($1)!=3 || ($$=mlookup($1))==0)
436 yyerror("not an EM-mnemonic");
441 : optnocoerc tokenexpressionlist optstack
444 if (tokpatlen != 0) {
445 outbyte(($1 ? ( $3 ? DO_XXMATCH: DO_XMATCH ) : DO_MATCH)+(tokpatlen<<5));
446 for(i=1;i<=tokpatlen;i++) {
450 if ($3 && tokpatlen==0 && empatlen==0) {
453 if ($3 && !$1 && empatlen!=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");
480 { $$ = exprlookup($1); }
491 { $$ = codebytes; cchandled=ccspoiled=0; }
493 { if (cchandled==0 && ccspoiled!=0) {
506 : REMOVE '(' tokenexpressionno
509 { outbyte(DO_REMOVE+ ($5!=0 ? 32 : 0));
513 | REMOVE '(' expr ')'
514 { if ($3.expr_typ != TYPREG)
515 yyerror("Expression must be register");
529 restcode: /* empty */
530 | restcode LSTRING expr
531 { outbyte(DO_LOUTPUT);
537 | restcode stringlist
539 for(i=0;nstr>0;i++,nstr--) {
540 if (i%8==0) outbyte(DO_ROUTPUT+(nstr>7 ? 7 : nstr-1)*32);
546 { outbyte(DO_PRETURN); }
556 | restcode SETCC '(' tokeninstanceno ')'
562 | restcode TEST '(' tokeninstanceno ')'
573 strar[0]=stringno($1);
577 { chktabsiz(nstr,MAXNSTR,"Consecutiv strings");
578 strar[nstr++] = stringno($2);
584 : MOVE '(' tokeninstanceno ',' tokeninstanceno ')'
595 if($3.expr_typ != TYPREG)
596 yyerror("Bad argument of erase");
601 : ALLOCATE { dealflag=0; } '(' alloclist ')'
603 outbyte(DO_REALLOCATE);
610 | alloclist optcomma allocel
614 : tokeninstanceno /* deallocate */
615 { outbyte(DO_DEALLOCATE);
620 { allreg[nallreg++] = $1->i_i.i_prpno;
621 outbyte(DO_ALLOCATE);
622 out($1->i_i.i_prpno);
624 | PIDENT '=' tokeninstanceno
625 { allreg[nallreg++] = $1->i_i.i_prpno;
626 outbyte(DO_ALLOCATE+32);
627 out($1->i_i.i_prpno);
644 { tokrepllen=1; replinst[0] = $1; }
645 | stackrepllist tokeninstanceno
646 { chktabsiz(tokrepllen+1,MAXPATLEN,"Stack replacement");
647 replinst[tokrepllen++] = $2;
652 : /* empty, normal case */
659 replexpr[0]=$2.expr_index;
661 | emrepllist mnem optexpr
662 { chktabsiz(emrepllen+1,MAXEMPATLEN,"EM replacement");
663 replmnem[emrepllen]=$2;
664 replexpr[emrepllen]=$3.expr_index;
670 { $$.c_size = $$.c_time = 0;
672 | '(' expr ',' expr ')'
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));
695 : '(' tokenexpressionno
697 optboolexpr ',' tokenexpressionno
703 optboolexpr ',' code optcommacost ')'
704 { register move_p mp;
708 chktabsiz(nmoves,NMOVES,"Move definition table");
709 mp = &machmoves[nmoves++];
729 testdef : '(' tokenexpressionno
732 pattokexp[2] = cocosetno;
735 optboolexpr ',' code optcommacost ')'
736 { register move_p mp;
740 chktabsiz(nmoves,NMOVES,"Move definition table(tests)");
741 mp = &machmoves[nmoves++];
744 mp->m_set2 = cocosetno;
752 : STACKHEAD stackdefs
760 : '(' tokenexpressionno
765 optboolexpr ',' optprop ',' code optcommacost ')'
768 outbyte(DO_TOKREPLACE);
771 chktabsiz(nc1,MAXC1,"Stacking table");
772 cp = &c1coercs[nc1++];
785 { $$ = $1->i_i.i_prpno; }
790 { $$.c_size = 0; $$.c_time = 0;}
797 | optcomma IDENT list1
798 { $$=(list1) myalloc(sizeof(struct list1str));
803 optcomma: /* nothing */
807 { if ($1<1 || $1>empatlen)
808 yyerror("Number after $ out of range");
814 { if ($1<1 || $1>tokpatlen)
815 yyerror("Number within %[] out of range");
820 { $$.expr_index = lookup(0,EX_ARG,$2,0); $$.expr_typ = argtyp(patmnem[$2]);
823 { $$.expr_index = lookup(0,EX_CON,(int)($1&0177777),(int)($1>>16));
824 $$.expr_typ = TYPINT;
827 { $$.expr_index = lookup(0,EX_STRING,strlookup($1),0);
828 $$.expr_typ = TYPSTR;
831 { $$.expr_index = lookup(0,EX_REG,$1->i_i.i_regno,0);
832 $$.expr_typ = TYPREG;
834 | '%' '[' tokargno '.' IDENT ']'
835 { $$.expr_index = lookup(0,EX_TOKFIELD,$3,
836 findstructel(pattokexp[$3],$5,&$$.expr_typ));
838 | '%' '[' tokargno subreg ']'
839 { chkregexp(pattokexp[$3]);
840 $$.expr_index = lookup(0,EX_SUBREG,$3,$4);
841 $$.expr_typ = TYPREG;
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;
850 { $$.expr_index = lookup(0,EX_TOKFIELD,0,
851 findstructel(curtokexp,$3,&$$.expr_typ));
853 | TOSTRING '(' expr ')'
855 $$.expr_index = lookup(0,EX_TOSTRING,exp1,0);
856 $$.expr_typ = TYPSTR;
858 | DEFINED '(' expr ')'
859 { $$.expr_index = lookup(0,EX_DEFINED,$3.expr_index,0);
860 $$.expr_typ = TYPBOOL;
862 | SAMESIGN '(' expr ',' expr ')'
864 $$.expr_index = lookup(1,EX_SAMESIGN,exp1,exp2);
865 $$.expr_typ = TYPBOOL;
867 | SFIT '(' expr ',' expr ')'
869 $$.expr_index = lookup(0,EX_SFIT,exp1,exp2);
870 $$.expr_typ = TYPBOOL;
872 | UFIT '(' expr ',' expr ')'
874 $$.expr_index = lookup(0,EX_UFIT,exp1,exp2);
875 $$.expr_typ = TYPBOOL;
877 | ROM '(' emargno ',' NUMBER ')'
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;
883 | LOWW '(' emargno ')'
885 $$.expr_index = lookup(0,EX_LOWW,$3-1,0);
886 $$.expr_typ = TYPINT;
888 | HIGHW '(' emargno ')'
890 $$.expr_index = lookup(0,EX_HIGHW,$3-1,0);
891 $$.expr_typ = TYPINT;
896 { switch(commontype($1,$3)) {
898 $$.expr_index = lookup(1,EX_NCPEQ,$1.expr_index,$3.expr_index);
901 $$.expr_index = lookup(1,EX_SCPEQ,$1.expr_index,$3.expr_index);
904 $$.expr_index = lookup(1,EX_RCPEQ,$1.expr_index,$3.expr_index);
907 $$.expr_typ = TYPBOOL;
910 { switch(commontype($1,$3)) {
912 $$.expr_index = lookup(1,EX_NCPNE,$1.expr_index,$3.expr_index);
915 $$.expr_index = lookup(1,EX_SCPNE,$1.expr_index,$3.expr_index);
918 $$.expr_index = lookup(1,EX_RCPNE,$1.expr_index,$3.expr_index);
921 $$.expr_typ = TYPBOOL;
925 $$.expr_index = lookup(0,EX_NCPGT,exp1,exp2);
926 $$.expr_typ = TYPBOOL;
930 $$.expr_index = lookup(0,EX_NCPGE,exp1,exp2);
931 $$.expr_typ = TYPBOOL;
935 $$.expr_index = lookup(0,EX_NCPLT,exp1,exp2);
936 $$.expr_typ = TYPBOOL;
940 $$.expr_index = lookup(0,EX_NCPLE,exp1,exp2);
941 $$.expr_typ = TYPBOOL;
944 { MUST2BEBOOL($1,$3);
945 $$.expr_index = lookup(0,EX_OR2,exp1,exp2);
946 $$.expr_typ = TYPBOOL;
949 { MUST2BEBOOL($1,$3);
950 $$.expr_index = lookup(0,EX_AND2,exp1,exp2);
951 $$.expr_typ = TYPBOOL;
954 { switch(commontype($1,$3)) {
956 $$.expr_index = lookup(1,EX_PLUS,$1.expr_index,$3.expr_index);
959 $$.expr_index = lookup(0,EX_CAT,$1.expr_index,$3.expr_index);
962 yyerror("Bad types");
964 $$.expr_typ = $1.expr_typ;
968 $$.expr_index = lookup(0,EX_MINUS,exp1,exp2);
969 $$.expr_typ = TYPINT;
973 $$.expr_index = lookup(1,EX_TIMES,exp1,exp2);
974 $$.expr_typ = TYPINT;
978 $$.expr_index = lookup(0,EX_DIVIDE,exp1,exp2);
979 $$.expr_typ = TYPINT;
983 $$.expr_index = lookup(0,EX_MOD,exp1,exp2);
984 $$.expr_typ = TYPINT;
988 $$.expr_index = lookup(0,EX_LSHIFT,exp1,exp2);
989 $$.expr_typ = TYPINT;
993 $$.expr_index = lookup(0,EX_RSHIFT,exp1,exp2);
994 $$.expr_typ = TYPINT;
998 $$.expr_index = lookup(0,EX_NOT,exp1,0);
999 $$.expr_typ = TYPBOOL;
1003 $$.expr_index = lookup(0,EX_COMP,exp1,0);
1004 $$.expr_typ = TYPINT;
1006 | INREG '(' expr ')'
1008 $$.expr_index = lookup(0,EX_INREG,exp1,0);
1009 $$.expr_typ = TYPINT;
1011 | REGVAR '(' expr ')'
1013 $$.expr_index = lookup(0,EX_REGVAR,exp1,0);
1014 $$.expr_typ = TYPREG;
1017 | '-' expr %prec UMINUS
1019 $$.expr_index = lookup(0,EX_UMINUS,exp1,0);
1020 $$.expr_typ = TYPINT;
1025 subreg : /* empty */
1049 { $$ = instno($1); }
1053 : '%' '[' tokargno subreg ']'
1057 chkregexp(pattokexp[$3]);
1058 $$.in_which = IN_COPY;
1061 for (i=2;i<TOKENSIZE;i++)
1064 | '%' '[' tokargno '.' IDENT ']'
1067 $$.in_which = IN_COPY;
1069 $$.in_info[1] = findstructel(pattokexp[$3],$5,&typ);
1071 yyerror("Must be register");
1072 for (i=2;i<TOKENSIZE;i++)
1077 $$.in_which = IN_RIDENT;
1078 $$.in_info[0] = $1->i_i.i_regno;
1079 for (i=1;i<TOKENSIZE;i++)
1082 | REGVAR '(' expr ')'
1085 $$.in_which = IN_REGVAR;
1086 $$.in_info[0] = exp1;
1087 for (i=1;i<TOKENSIZE;i++)
1090 | '%' '[' LCASELETTER subreg ']'
1092 if ($3 >= 'a'+nallreg)
1093 yyerror("Bad letter in %[x] construct");
1094 $$.in_which = IN_ALLOC;
1095 $$.in_info[0] = $3-'a';
1097 for (i=2;i<TOKENSIZE;i++)
1100 | '{' TIDENT attlist '}'
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;
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");
1122 { arexp[narexp++] = $3; }