1007 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1007 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <stdio.h>
 | |
| #include <assert.h>
 | |
| #include <ctype.h>
 | |
| #include <em_spec.h>
 | |
| #include <em_flag.h>
 | |
| #include <em_reg.h>
 | |
| 
 | |
| #include "booth.h"
 | |
| 
 | |
| char *strncpy(), *strcpy(), *sprintf();
 | |
| 
 | |
| char * myalloc(n) {
 | |
| 	register char *p;
 | |
| 
 | |
| 	p= (char*) 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;i<narinstance;i++) {
 | |
| 		if (arinstance[i].in_which != inst.in_which)
 | |
| 			continue;
 | |
| 		for(j=0;j<TOKENSIZE;j++)
 | |
| 			if(arinstance[i].in_info[j] != inst.in_info[j])
 | |
| 				goto cont;
 | |
| 		return(i);
 | |
| 	cont:;
 | |
| 	}
 | |
| 	chktabsiz(narinstance,MAXINSTANCE,"Instance table");
 | |
| 	arinstance[narinstance] = inst;
 | |
| 	return(narinstance++);
 | |
| }
 | |
| 
 | |
| string scopy(s) string s; {
 | |
| 	register string t;
 | |
| 
 | |
| 	t = (char *) myalloc(strlen(s)+1);
 | |
| 	strcpy(t,s);
 | |
| 	return(t);
 | |
| }
 | |
| 
 | |
| strlookup(s) string s; {
 | |
| 	register i;
 | |
| 
 | |
| 	for(i=0;i<ncodestrings;i++)
 | |
| 		if(strcmp(s,codestrings[i])==0)
 | |
| 			return(i);
 | |
| 	chktabsiz(ncodestrings,MAXSTRINGS,"string table");
 | |
| 	codestrings[ncodestrings] = scopy(s);
 | |
| 	return(ncodestrings++);
 | |
| }
 | |
| 
 | |
| stringno(s) register string s; {
 | |
| 	char buf[256];
 | |
| 	register char *p=buf;
 | |
| 
 | |
| 	while(*s != 0) switch(*s) {
 | |
| 	default:
 | |
| 		*p++ = *s++;
 | |
| 		continue;
 | |
| 	case '$':
 | |
| 		s++;
 | |
| 		switch(*s) {
 | |
| 		default:
 | |
| 			yyerror("Bad character after $ in codestring");
 | |
| 		case '$':
 | |
| 			*p++ = *s++;
 | |
| 			continue;
 | |
| 		case '1':
 | |
| 		case '2':
 | |
| 		case '3':
 | |
| 		case '4':
 | |
| 		case '5':
 | |
| 		case '6':
 | |
| 		case '7':
 | |
| 		case '8':
 | |
| 		case '9':
 | |
| 			*p++ = argtyp(patmnem[*s-'0']) == TYPINT ?
 | |
| 				PR_EMINT : PR_EMSTR;
 | |
| 			*p++ = *s++ -'0';
 | |
| 			continue;
 | |
| 		}
 | |
| 	case '%':
 | |
| 		s++;
 | |
| 		if (*s != '[') {
 | |
| 			if(*s == '%') {
 | |
| 				*p++ = *s++;
 | |
| 				continue;
 | |
| 			} else
 | |
| 				yyerror("Bad character following %% in codestring");
 | |
| 		} else
 | |
| 			s++;
 | |
| 		if(isdigit(*s)) {
 | |
| 			int num;
 | |
| 			num = *s++ - '0';
 | |
| 			if (num<1 || num>tokpatlen)
 | |
| 				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;p<lastnode;p++) {
 | |
| 		if (p->ex_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<nmachregs;i++) {
 | |
| 		for (j=1;j<i;j++)
 | |
| 			if (eqregclass(i,j)) {
 | |
| 				stregclass[i] = stregclass[j];
 | |
| 				break;
 | |
| 			}
 | |
| 		if (j==i)
 | |
| 			stregclass[i] = nregclasses++;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| eqregclass(r1,r2) {
 | |
| 	register reginfo rp1,rp2;
 | |
| 	register i;
 | |
| 	short regbits[(MAXREGS+15)>>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;i<maxmembers;i++) {
 | |
| 		if (member = rp1->rmembers[i])
 | |
| 			regbits[member>>4] |= (1<<(member&017));
 | |
| 	}
 | |
| 	for (i=0;i<maxmembers;i++) {
 | |
| 		member = rp2->rmembers[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 <cg_pattern.h>\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;i<nmachsets;i++) {
 | |
| 		ok= (sett.set_size == machsets[i].set_size);
 | |
| 		for(j=0;j<SETSIZE;j++) {
 | |
| 			if (sett.set_val[j] == machsets[i].set_val[j])
 | |
| 				continue;
 | |
| 			ok=0;
 | |
| 			break;
 | |
| 		}
 | |
| 		if (ok)
 | |
| 			return(i);
 | |
| 	}
 | |
| 	chktabsiz(nmachsets,MAXSETS,"Expression table");
 | |
| 	machsets[nmachsets] = sett;
 | |
| 	return(nmachsets++);
 | |
| }
 | |
| 
 | |
| inittables() {
 | |
| 	register reginfo r;
 | |
| 	register i;
 | |
| 	inst_t inst;
 | |
| 	set_t sett;
 | |
| 
 | |
| 	nodes[0].ex_operator=EX_CON;
 | |
| 	nodes[0].ex_lnode=0;
 | |
| 	nodes[0].ex_rnode=0;
 | |
| 	cocopropno=nprops++;
 | |
| 	r=(reginfo)myalloc(sizeof(struct reginfo));
 | |
| 	r->rname = "cc reg";
 | |
| 	r->rrepr = "CC";
 | |
| 	r->rsize = -1;
 | |
| 	r->rregvar= -1;
 | |
| 	for(i=0;i<MAXMEMBERS;i++)
 | |
| 		r->rmembers[i] = 0;
 | |
| 	for(i=0;i<PROPSETSIZE;i++)
 | |
| 		r->rprop[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<TOKENSIZE;i++)
 | |
| 		inst.in_info[i]=0;
 | |
| 	ccinstanceno=instno(inst);
 | |
| 	ccregexpr=lookup(0,EX_REG,nmachregs-1,0);
 | |
| 	sett.set_size=0;
 | |
| 	for (i=0;i<SETSIZE;i++)
 | |
| 		sett.set_val[i]=0;
 | |
| 	sett.set_val[nmachregs>>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;i<nmachregs;i++)
 | |
| 		fprintf(cfile,"\t%d,\n",stregclass[i]);
 | |
| 	fprintf(cfile,"};\n\nstruct reginfo machregs[] = {\n{0},\n");
 | |
| 	for (i=1;i<nmachregs;i++) {
 | |
| 		fprintf(cfile,"{%d,%d",strlookup(machregs[i]->rrepr),
 | |
| 			machregs[i]->rsize);
 | |
| 		if (maxmembers!=0) {
 | |
| 			fprintf(cfile,",{");
 | |
| 			for(j=0;j<maxmembers;j++)
 | |
| 				fprintf(cfile,"%d,",machregs[i]->rmembers[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<nmachregs;j++)
 | |
| 				if (rset[j>>4]&(1<<(j&017)))
 | |
| 				    for (k=0;k<maxmembers;k++)
 | |
| 					if ((t=machregs[j]->rmembers[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;j<nmachregs;j++)
 | |
| 				for (k=0;k<maxmembers;k++)
 | |
| 				    if ((t=machregs[j]->rmembers[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;i<nmachtokens;i++) {
 | |
| 		fprintf(cfile,"{%d,{%d,%d},{",machtokens[i].t_size,
 | |
| 				machtokens[i].t_cost.c_size,
 | |
| 				machtokens[i].t_cost.c_time);
 | |
| 		for(j=0;j<maxtokensize;j++)
 | |
| 			fprintf(cfile,"%d,",machtokens[i].t_fields[j].t_type);
 | |
| 		fprintf(cfile,"},%d},\n",machtokens[i].t_format);
 | |
| 	}
 | |
| 	fprintf(cfile,"};\n\nnode_t enodes[] = {\n");
 | |
| 	for(np=nodes;np<lastnode;np++)
 | |
| 		fprintf(cfile,"{%d,%d,%d},\n",np->ex_operator,np->ex_lnode,
 | |
| 				np->ex_rnode);
 | |
| 	fprintf(cfile,"};\n\nstring codestrings[] = {\n");
 | |
| 	for(i=0;i<ncodestrings;i++) {
 | |
| 		register char *p;
 | |
| 		p=codestrings[i];
 | |
| 		fprintf(cfile,"\t\"");
 | |
| 		while (*p) {
 | |
| 			register int c = (*p) & BMASK;
 | |
| 			if (! isascii(c) || iscntrl(c)) {
 | |
| 				fprintf(cfile,"\\%c%c%c",((c>>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;i<nmachsets;i++) {
 | |
| 		fprintf(cfile,"{%d,{",machsets[i].set_size);
 | |
| 		for(j=0;j<setsize;j++)
 | |
| 			fprintf(cfile,"0%o,",machsets[i].set_val[j]);
 | |
| 		fprintf(cfile,"}},\n");
 | |
| 	}
 | |
| 	fprintf(cfile,"};\n\ninst_t tokeninstances[] = {\n");
 | |
| 	for(i=0;i<narinstance;i++) {
 | |
| 		fprintf(cfile,"{ %d, {",arinstance[i].in_which);
 | |
| 		for(j=0;j<=maxtokensize;j++)
 | |
| 			fprintf(cfile,"%d,",arinstance[i].in_info[j]);
 | |
| 		fprintf(cfile,"}},\n");
 | |
| 	}
 | |
| 	fprintf(cfile,"};\n\nmove_t moves[] = {\n");
 | |
| 	for (i=0;i<nmoves;i++) {
 | |
| 		mp = &machmoves[i];
 | |
| 		fprintf(cfile,"{%d,%d,%d,%d,%d,{%d,%d}},\n",
 | |
| 			mp->m_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;i<npatbytes;i++) {
 | |
| 		fprintf(cfile,"%3d,",pattern[i]&BMASK);
 | |
| 		if ((i%10)==9)
 | |
| 			fprintf(cfile,"\n");
 | |
| 	}
 | |
| 	fprintf(cfile,"\n};\n\nint pathash[256] = {\n");
 | |
| 	for(i=0;i<256;i++) {
 | |
| 		fprintf(cfile,"%6d,",pathash[i]);
 | |
| 		if((i&07)==07)
 | |
| 			fprintf(cfile,"\n");
 | |
| 	}
 | |
| 	fprintf(cfile,"};\n\nc1_t c1coercs[] = {\n");
 | |
| 	for (i=0;i<nc1;i++)
 | |
| 		fprintf(cfile,"{%d,%d,%d,%d,{%d,%d}},\n",
 | |
| 			c1coercs[i].c1_texpno,
 | |
| 			c1coercs[i].c1_expr,
 | |
| 			c1coercs[i].c1_prop,
 | |
| 			c1coercs[i].c1_codep,
 | |
| 			c1coercs[i].c1_cost.c_size,
 | |
| 			c1coercs[i].c1_cost.c_time);
 | |
| 	if (nc2)
 | |
| 		fprintf(cfile,"};\n\nc2_t c2coercs[] = {\n");
 | |
| 	for (i=0;i<nc2;i++) {
 | |
| 		fprintf(cfile,"{%d,%d,{",
 | |
| 			c2coercs[i].c2_texpno,
 | |
| 			c2coercs[i].c2_nsplit);
 | |
| 		for (j=0;j<maxsplit;j++)
 | |
| 			fprintf(cfile,"%d,",c2coercs[i].c2_repl[j]);
 | |
| 		fprintf(cfile,"},%d},\n",c2coercs[i].c2_codep);
 | |
| 	}
 | |
| 	fprintf(cfile,"};\n\nc3_t c3coercs[] = {\n");
 | |
| 	for (i=0;i<nc3;i++)
 | |
| 		fprintf(cfile,"{%d,%d,%d,%d},\n",
 | |
| 			c3coercs[i].c3_texpno,
 | |
| 			c3coercs[i].c3_prop,
 | |
| 			c3coercs[i].c3_repl,
 | |
| 			c3coercs[i].c3_codep);
 | |
| 	fprintf(cfile,"};\n\n");
 | |
| 	for (i=0;i<nprops;i++) {
 | |
| 		fprintf(cfile,"struct reginfo *rlist%d[] = {\n",i);
 | |
| 		for (j=2;j<=nmachregs;j++) {
 | |
| 			if (machregs[j-1]->rregvar<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;i<nprops;i++) {
 | |
| 		fprintf(cfile,"\trlist%d,\n",i);
 | |
| 	}
 | |
| 	fprintf(cfile,"};\n");
 | |
| 	fprintf(cfile,"unsigned cc1 = %u;\n",cc1);
 | |
| 	fprintf(cfile,"unsigned cc2 = %u;\n",cc2);
 | |
| 	fprintf(cfile,"unsigned cc3 = %u;\n",cc3);
 | |
| 	fprintf(cfile,"unsigned cc4 = %u;\n",cc4);
 | |
| 	if (rvused)
 | |
| 		outregvar();
 | |
| }
 | |
| 
 | |
| outregvar() {
 | |
| 	register i,j;
 | |
| 
 | |
| 	fprintf(hfile,"#define REGVARS\n");
 | |
| 	fprintf(cfile,"#include \"regvar.h\"\n");
 | |
| 	fprintf(cfile,"int nregvar[4] = { ");
 | |
| 	for (i=0;i<4;i++) fprintf(cfile,"%d, ",nregvar[i]);
 | |
| 	fprintf(cfile,"};\n");
 | |
| 	for (i=0;i<4;i++)
 | |
| 		if (nregvar[i]>0)
 | |
| 			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;j<nregvar[i];j++)
 | |
| 			fprintf(cfile,"%d,",rvnumbers[i][j]);
 | |
| 		fprintf(cfile,"};\n");
 | |
| 	}
 | |
| 	fprintf(cfile,"\nint *rvnumbers[] = {\n");
 | |
| 	for (i=0;i<4;i++)
 | |
| 		if (nregvar[i]>0)
 | |
| 			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;i<SETSIZE;i++)
 | |
| 		machsets[nmachsets].set_val[i] = 0xFFFF;
 | |
| 	machsets[nmachsets].set_val[0] &= ~1;
 | |
| 	machsets[nmachsets].set_size = 0;
 | |
| 	ip=ilookup("SCRATCH",ENTER);
 | |
| 	ip->i_type=IEXP;
 | |
| 	ip->i_i.i_expno = nmachsets++;
 | |
| 
 | |
| 	for (i=0;i<SETSIZE;i++)
 | |
| 		machsets[nmachsets].set_val[i] = 0xFFFF;
 | |
| 	machsets[nmachsets].set_size = 0;
 | |
| 	ip=ilookup("ALL",ENTER);
 | |
| 	ip->i_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;i<nprops;i++) {
 | |
| 		short *sp = machprops[i].propset.set_val;
 | |
| 
 | |
| 		sp[0] |= 1;
 | |
| 		for (j=2;j<=nmachregs;j++)
 | |
| 			if (machregs[j-1]->rprop[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;i<TOKENSIZE-1;i++)
 | |
| 			if (strcmp(field,tp->t_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;i<TOKENSIZE-1;i++)
 | |
| 		tp->t_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<nmachregs+1+nmachtokens;i++)
 | |
| 		if(machsets[number].set_val[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<nmachregs+1+nmachtokens;i++) {
 | |
| 		if (machsets[number].set_val[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;offset<TOKENSIZE-1;offset++)
 | |
| 		if(tp->t_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;
 | |
| 		}
 | |
| 		patlen = i;
 | |
| 		hashvalue = 0;
 | |
| 		switch(patlen) {
 | |
| 		default:        /* 3 or more */
 | |
| 			hashvalue = (hashvalue<<4)^(*tp++&BMASK);
 | |
| 		case 2:
 | |
| 			hashvalue = (hashvalue<<4)^(*tp++&BMASK);
 | |
| 		case 1:
 | |
| 			hashvalue = (hashvalue<<4)^(*tp++&BMASK);
 | |
| 		}
 | |
| 		assert(hashvalue!= ILLHASH);
 | |
| 		i=index;
 | |
| 		index = (bp[PO_NEXT]&BMASK)|(bp[PO_NEXT+1]<<BSHIFT);
 | |
| 		bp[PO_HASH] = hashvalue>>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;i<ITABSIZE;i++) {
 | |
| 		register ident_p ip;
 | |
| 		for(ip=identtab[i];ip!=0;ip=ip->i_next)
 | |
| 			printf("%-14s %1d %3d\n",ip->i_name,
 | |
| 				ip->i_type,ip->i_i.i_regno);
 | |
| 	}
 | |
| 
 | |
| 	for(i=2;i<nmachregs;i++) {
 | |
| 		register reginfo rp;
 | |
| 
 | |
| 		rp=machregs[i];
 | |
| 		printf("%s = (\"%s\", %d",rp->rname,rp->rrepr,rp->rsize);
 | |
| 		for(j=0;j<MAXMEMBERS;j++)
 | |
| 			if(rp->rmembers[j] != 0)
 | |
| 				printf(", %s",machregs[rp->rmembers[j]]->rname);
 | |
| 		printf(")");
 | |
| 		for(j=0;j<nprops;j++)
 | |
| 			if(rp->rprop[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);
 | |
| }
 |