#include #include #include #include #include #include #include #include #include "booth.h" char * myalloc(n) { register char *p; p= malloc((unsigned)n); if (p==0) { yyerror("Out of core"); exit(1); } return(p); } tstint(e) expr_t e; { if(e.expr_typ != TYPINT) yyerror("Must be integer expression"); } tstbool(e) expr_t e; { if(e.expr_typ != TYPBOOL) yyerror("Must be boolean expression"); } structsize(s) register list2 s; { register list1 l; register sum; sum = 0; while ( s != 0 ) { l = s->l2list->l1next; while ( l != 0 ) { sum++; l = l->l1next; } s = s->l2next; } return(sum); } list2 lookstruct(ll) list2 ll; { list3 l3; list2 l21,l22; list1 l11,l12; for (l3=structpool;l3 != 0;l3=l3->l3next) { for (l21=l3->l3list,l22=ll;l21!=0 && l22!=0; l21=l21->l2next,l22=l22->l2next) { for(l11=l21->l2list,l12=l22->l2list; l11!=0 && l12!=0 && strcmp(l11->l1name,l12->l1name)==0; l11=l11->l1next,l12=l12->l1next) ; if (l11!=0 || l12!=0) goto contin; } if(l21==0 && l22==0) return(l3->l3list); contin:; } l3 = (list3) myalloc(sizeof(struct list3str)); l3->l3next=structpool; l3->l3list=ll; structpool=l3; return(ll); } instno(inst) inst_t inst; { register i,j; for(i=1;itokpatlen) yyerror("Number within %[] out of range"); if (*s == ']') { s++; *p++ = PR_TOK; *p++ = num; } else if (*s++ != '.') yyerror("Bad character following %%[digit in codestring"); else { char field[256]; register char *f=field; int type,offset; while( *s != ']' && *s != 0) *f++ = *s++; *f++ = 0; if (*s != ']') yyerror("Unterminated %[] construction in codestring"); else s++; if (isdigit(field[0])) { chkregexp(pattokexp[num]); *p++ = PR_SUBREG; *p++ = num; *p++ = atoi(field); } else { offset = findstructel(pattokexp[num],field,&type); *p++ = PR_TOKFLD; *p++ = num; *p++ = offset; } } } else if (*s >= 'a' && *s < 'a'+nallreg) { int reg,subreg; reg = *s++ -'a'+1; if(*s == ']') subreg = 255; else { if (*s != '.') yyerror("Bad character following %%[x in codestring"); s++; if(!isdigit(*s)) yyerror("Bad character following %%[x. in codestring"); subreg = *s - '0'; s++; if(*s != ']') yyerror("Bad character following %%[x.y in codestring"); } s++; *p++ = PR_ALLREG; *p++ = reg; *p++ = subreg; } else yyerror("Bad character following %%[ in codestring"); } *p++ = 0; return(strlookup(buf)); } tabovf(tablename) string tablename; { char buf[256]; sprintf(buf,"%s overflow",tablename); yyerror(buf); exit(-1); } main(argc,argv) char *argv[]; { while (--argc) { ++argv; if (argv[0][0]=='-') { switch (argv[0][1]) { case 'h': hname= &argv[0][2]; break; case 'c': cname= &argv[0][2]; break; default: fprintf(stderr,"Bad flag %s\n",argv[0]); break; } } else { iname= argv[0]; } } inithash(); initio(); inittables(); yyparse(); if (nerrors==0) { compueq(); hashpatterns(); finishio(); verbose(); } debug(); exit(nerrors); } lookup(comm,operator,lnode,rnode) { register node_p p; for (p=nodes+1;pex_operator != operator) continue; if (!(p->ex_lnode == lnode && p->ex_rnode == rnode || comm && p->ex_lnode == rnode && p->ex_rnode == lnode)) continue; return(p-nodes); } if (lastnode >= &nodes[MAXNODES]) yyerror("node table overflow"); lastnode++; p->ex_operator = operator; p->ex_lnode = lnode; p->ex_rnode = rnode; return(p-nodes); } compueq() { register i,j; for (i=1;i>4]; int member; rp1 = machregs[r1]; rp2 = machregs[r2]; for (i=0;i<((nprops+15)>>4);i++) if (rp1->rprop[i] != rp2->rprop[i]) return(0); for (i=0;i<((MAXREGS+15)>>4);i++) regbits[i] = 0; for (i=0;irmembers[i]) regbits[member>>4] |= (1<<(member&017)); } for (i=0;irmembers[i]; if (regbits[member>>4]&(1<<(member&017))) return(0); } return(1); } unsigned hash(name) register string name; { register unsigned sum; register i; for (sum=i=0;*name;i+=3) sum ^= (*name++)<<(i&07); return(sum); } ident_p ilookup(name,enterf) string name; int enterf; { register ident_p p,*pp; pp = &identtab[hash(name)%ITABSIZE]; while (*pp != 0) { if (strcmp((*pp)->i_name,name)==0) if (enterf != ENTER) return(*pp); else yyerror("Multiply defined symbol"); pp = &(*pp)->i_next; } if (enterf == LOOKUP) yyerror("Undefined symbol"); if (enterf == JUSTLOOKING) return(0); p = *pp = (ident_p) myalloc(sizeof(ident_t)); p->i_name = name; p->i_next = 0; p->i_type = 0; return(p); } initio() { if (iname!=0 && freopen(iname,"r",stdin)==NULL) { fprintf(stderr,"Can't open %s\n",iname); exit(-1); } if ((cfile=fopen(cname,"w"))==NULL) { fprintf(stderr,"Can't create %s\n",cname); exit(-1); } if ((hfile=fopen(hname,"w"))==NULL) { fprintf(stderr,"Can't create %s\n",hname); exit(-1); } fprintf(cfile,"#include \"param.h\"\n"); fprintf(cfile,"#include \"tables.h\"\n"); fprintf(cfile,"#include \"types.h\"\n"); fprintf(cfile,"#include \n"); fprintf(cfile,"#include \"data.h\"\n"); fprintf(cfile,"\nbyte coderules[] = {\n"); patbyte(0); } exprlookup(sett) set_t sett; { register i,j,ok; for(i=0;irname = "cc reg"; r->rrepr = "CC"; r->rsize = -1; r->rregvar= -1; for(i=0;irmembers[i] = 0; for(i=0;irprop[i] = 0; r->rprop[cocopropno>>4] |= (1<<(cocopropno&017)); chktabsiz(nmachregs,MAXREGS,"Register table"); machregs[nmachregs++] = r; inst.in_which = IN_RIDENT; inst.in_info[0] = nmachregs-1; for(i=1;i>4] |= (01<<(nmachregs&017)); cocosetno=exprlookup(sett); } outregs() { register i,j,k; static short rset[(MAXREGS+15)>>4]; int t,ready; fprintf(cfile,"char stregclass[] = {\n"); for (i=0;irrepr), machregs[i]->rsize); if (maxmembers!=0) { fprintf(cfile,",{"); for(j=0;jrmembers[j]); /* now compute and print set of registers * that clashes with this register. * A register clashes with al its children (and theirs) * and with all their parents. */ for (j=0;j<((MAXREGS+15)>>4);j++) rset[j]=0; rset[i>>4] |= (1<<(i&017)); do { ready=1; for (j=1;j>4]&(1<<(j&017))) for (k=0;krmembers[k])!=0) { if ((rset[t>>4]&(1<<(t&017)))==0) ready=0; rset[t>>4] |= (1<<(t&017)); } } while (!ready); do { ready=1; for (j=1;jrmembers[k])!=0) if (rset[t>>4]&(1<<(t&017))) { if (rset[j>>4]&(1<<(j&017))==0) ready=0; rset[j>>4] |= (1<<(j&017)); } } while (!ready); fprintf(cfile,"},{"); for (j=0;j<((nmachregs+15)>>4);j++) fprintf(cfile,"%d,",rset[j]); fprintf(cfile,"}"); } if (machregs[i]->rregvar>=0) fprintf(cfile,",1"); fprintf(cfile,"},\n"); } fprintf(cfile,"};\n\n"); } finishio() { register i; register node_p np; int j; int setsize; register move_p mp; fprintf(cfile,"};\n\n"); if (wsize>0) fprintf(hfile,"#define TEM_WSIZE %d\n",wsize); else yyerror("Wordsize undefined"); if (psize>0) fprintf(hfile,"#define TEM_PSIZE %d\n",psize); else yyerror("Pointersize undefined"); if (bsize>=0) fprintf(hfile,"#define TEM_BSIZE %d\n",bsize); else yyerror("EM_BSIZE undefined"); if (fmt!=0) fprintf(hfile,"#define WRD_FMT \"%s\"\n",fmt); fprintf(hfile,"#define MAXALLREG %d\n",maxallreg); setsize = (nmachregs+1 + nmachtokens + 15)>>4; fprintf(hfile,"#define SETSIZE %d\n",setsize); fprintf(hfile,"#define NPROPS %d\n",nprops); fprintf(hfile,"#define NREGS %d\n",nmachregs); fprintf(hfile,"#define REGSETSIZE %d\n",(nmachregs+15)>>4); fprintf(hfile,"#define TOKENSIZE %d\n",maxtokensize); fprintf(hfile,"#define MAXMEMBERS %d\n",maxmembers); fprintf(hfile,"#define LONGESTPATTERN %d\n",maxempatlen); fprintf(hfile,"#define MAXRULE %d\n",maxrule); fprintf(hfile,"#define NMOVES %d\n",nmoves); fprintf(hfile,"#define NC1 %d\n",nc1); if (nc2) { assert(maxsplit!=0); fprintf(hfile,"#define NC2 %d\n",nc2); fprintf(hfile,"#define MAXSPLIT %d\n",maxsplit); } fprintf(hfile,"#define NC3 %d\n",nc3); outregs(); fprintf(cfile,"tkdef_t tokens[] = {\n"); for(i=0;iex_operator,np->ex_lnode, np->ex_rnode); fprintf(cfile,"};\n\nstring codestrings[] = {\n"); for(i=0;i>6)&03, but this triggered a bug in GCC 2.4.5 on SPARC. */ fprintf(cfile,"\\%c%c%c",((*p>>6) &03)+'0', ((c>>3)&07)+'0',(c&07)+'0'); } else putc(c, cfile); p++; } fprintf(cfile,"\",\n"); } fprintf(cfile,"};\n\nset_t machsets[] = {\n"); for(i=0;im_set1, mp->m_expr1, mp->m_set2, mp->m_expr2, mp->m_cindex, mp->m_cost.c_size,mp->m_cost.c_time); } fprintf(cfile,"};\n\nbyte pattern[] = {\n"); for (i=0;irregvar<0 && (machprops[i].propset.set_val[j>>4]&(1<<(j&017)))) fprintf(cfile,"\t&machregs[%d],\n",j-1); } fprintf(cfile,"\t0\n};\n"); } fprintf(cfile,"struct reginfo **reglist[] = {\n"); for (i=0;i0) fprintf(cfile,"struct regassigned ratar%d[%d];\n", i,nregvar[i]); for (i=0;i<4;i++) if (nregvar[i]>0) { fprintf(cfile,"int rvtar%d[] = {",i); for (j=0;j0) fprintf(cfile,"\trvtar%d,\n",i); else fprintf(cfile,"\t0,\n"); fprintf(cfile,"};\n\nstruct regassigned *regassigned[] = {\n"); for (i=0;i<4;i++) if (nregvar[i]>0) fprintf(cfile,"\tratar%d,\n",i); else fprintf(cfile,"\t0,\n"); fprintf(cfile,"};\n"); } verbose() { fprintf(stderr,"Codebytes %d\n",codebytes); fprintf(stderr,"Registers %d(%d)\n",nmachregs,MAXREGS); fprintf(stderr,"Properties %d(%d)\n",nprops,MAXPROPS); fprintf(stderr,"Tokens %d(%d)\n",nmachtokens,MAXTOKENS); fprintf(stderr,"Sets %d(%d)\n",nmachsets,MAXSETS); fprintf(stderr,"Tokeninstances %d(%d)\n",narinstance,MAXINSTANCE); fprintf(stderr,"Strings %d(%d)\n",ncodestrings,MAXSTRINGS); fprintf(stderr,"Enodes %d(%d)\n",lastnode-nodes,MAXNODES); fprintf(stderr,"Patbytes %d(%d)\n",npatbytes,MAXPATTERN); } inbetween() { register ident_p ip; register i,j; register move_p mp; lookident=1; /* for lexical analysis */ chktabsiz(nmachsets+1,MAXSETS,"Expressiontable"); for (i=0;ii_type=IEXP; ip->i_i.i_expno = nmachsets++; for (i=0;ii_type=IEXP; allexpno = ip->i_i.i_expno = nmachsets++; mp = &machmoves[nmoves++]; mp->m_set1 = cocosetno; mp->m_expr1 = 0; mp->m_set2 = nmachsets-1; mp->m_expr2 = 0; mp->m_cindex = 0; mp->m_cost.c_size = 0; mp->m_cost.c_time = 0; /* * Create sets of registers per property */ for (i=0;irprop[i>>4]&(1<<(i&017))) sp[j>>4] |= (1<<(j&017)); } } formconversion(p,tp) register char *p; register token_p tp; { char buf[256]; register char *q=buf; char field[256]; register char *f; int i; if (p==0) return(0); while (*p) switch(*p) { default: *q++ = *p++; continue; case '%': p++; if(*p == '%') { *q++ = *p++; continue; } if (*p == '[') p++; else yyerror("Bad character after % in format"); f=field; while (*p != 0 && *p != ']') *f++ = *p++; *f++ = 0; if (*p == ']') p++; else yyerror("Unterminated %[] construct in format"); for (i=0;it_fields[i].t_sname)==0) break; if (i==TOKENSIZE-1) yyerror("Unknown field in %[] construct in format"); *q++ = i+1; } *q++ = 0; return(strlookup(buf)); } setfields(tp,format) register token_p tp; string format; { register i; list2 ll; register list1 l; int type; for(i=0;it_fields[i].t_type = 0; i=0; for(ll=tp->t_struct;ll!=0;ll=ll->l2next) { l=ll->l2list; if(strcmp(l->l1name,"REGISTER")==0) type = TYPREG; else if (strcmp(l->l1name,"INT")==0) type = TYPINT; else type = TYPSTR; for(l=l->l1next;l!=0;l=l->l1next) { tp->t_fields[i].t_type = type; tp->t_fields[i].t_sname = l->l1name; i++; } } if (format != 0) tp->t_format = formconversion(format,tp); else tp->t_format = -1; } chkregexp(number) { register i; for(i=nmachregs+1;i>4]&(01<<(i&017))) yyerror("No tokens allowed in this set"); } findstructel(number,name,t) string name; int *t; { register i; register token_p tp; register list2 structdecl; int offset; for(i=1;i<=nmachregs;i++) if (machsets[number].set_val[i>>4]&(01<<(i&017))) yyerror("No registers allowed in this set"); structdecl = 0; for (i=nmachregs+1;i>4]&(01<<(i&017))) { if (structdecl == 0) { structdecl = machtokens[i-(nmachregs+1)].t_struct; tp = &machtokens[i-(nmachregs+1)]; } else if(structdecl != machtokens[i-(nmachregs+1)].t_struct) yyerror("Multiple structs in this set"); } } if (structdecl == 0) { yyerror("No structs in this set"); return(0); } for(offset=0;offsett_fields[offset].t_type != 0 && strcmp(tp->t_fields[offset].t_sname,name)==0) { *t = tp->t_fields[offset].t_type; return(offset+1); } yyerror("No such field in this struct"); return(0); } extern char em_flag[]; argtyp(mn) { switch(em_flag[mn-sp_fmnem]&EM_PAR) { case PAR_W: case PAR_S: case PAR_Z: case PAR_O: case PAR_N: case PAR_L: case PAR_F: case PAR_R: case PAR_C: return(TYPINT); default: return(TYPSTR); } } commontype(e1,e2) expr_t e1,e2; { if(e1.expr_typ != e2.expr_typ) yyerror("Type incompatibility"); return(e1.expr_typ); } extern char em_mnem[][4]; #define HASHSIZE (2*(sp_lmnem-sp_fmnem)) struct hashmnem { char h_name[3]; byte h_value; } hashmnem[HASHSIZE]; inithash() { register i; for(i=0;i<=sp_lmnem-sp_fmnem;i++) enter(em_mnem[i],i+sp_fmnem); } enter(name,value) char *name; { register unsigned h; h=hash(name)%HASHSIZE; while (hashmnem[h].h_name[0] != 0) h = (h+1)%HASHSIZE; strncpy(hashmnem[h].h_name,name,3); hashmnem[h].h_value = value; } int mlookup(name) char *name; { register unsigned h; h = hash(name)%HASHSIZE; while (strncmp(hashmnem[h].h_name,name,3) != 0 && hashmnem[h].h_name[0] != 0) h = (h+1)%HASHSIZE; return(hashmnem[h].h_value&BMASK); /* 0 if not found */ } hashpatterns() { short index; register byte *bp,*tp; register short i; unsigned short hashvalue; int patlen; index = prevind; while (index != 0) { bp = &pattern[index]; tp = &bp[PO_MATCH]; i = *tp++&BMASK; if (i==BMASK) { i = *tp++&BMASK; i |= (*tp++&BMASK)<>BSHIFT; hashvalue &= BMASK; bp[PO_NEXT] = pathash[hashvalue]&BMASK; bp[PO_NEXT+1] = pathash[hashvalue]>>BSHIFT; pathash[hashvalue] = i; } } debug() { register i,j; for(i=0;ii_next) printf("%-14s %1d %3d\n",ip->i_name, ip->i_type,ip->i_i.i_regno); } for(i=2;irname,rp->rrepr,rp->rsize); for(j=0;jrmembers[j] != 0) printf(", %s",machregs[rp->rmembers[j]]->rname); printf(")"); for(j=0;jrprop[j>>4]&(1<<(j&017))) printf(", %s",machprops[j].propname->i_name); printf(".\n"); } } out(n) { assert(n>=0); if (n<128) outbyte(n); else { outbyte(n/256+128); outbyte(n%256); } } outbyte(n) { fprintf(cfile,"%d, ",n&BMASK); codebytes++; } pat(n) { assert(n>=0); if (n<128) patbyte(n); else { patbyte(n/256+128); patbyte(n%256); } } patshort(n) { patbyte(n&BMASK); patbyte(n>>BSHIFT); } patbyte(n) { chktabsiz(npatbytes,MAXPATTERN,"Pattern table"); pattern[npatbytes++] = n; } max(a,b) { if (a>b) return(a); return(b); }