xref: /plan9-contrib/sys/src/cmd/4l/span.c (revision f8bc6aaf8056e137bcdfb6117a990ac3eff62cc9)
17edc7532SDavid du Colombier #include	"l.h"
27edc7532SDavid du Colombier 
37edc7532SDavid du Colombier void
pagebug(Prog * p)4*f8bc6aafSDavid du Colombier pagebug(Prog *p)
5*f8bc6aafSDavid du Colombier {
6*f8bc6aafSDavid du Colombier 	Prog *q;
7*f8bc6aafSDavid du Colombier 
8*f8bc6aafSDavid du Colombier 	switch(p->as) {
9*f8bc6aafSDavid du Colombier 	case ABGEZAL:
10*f8bc6aafSDavid du Colombier 	case ABLTZAL:
11*f8bc6aafSDavid du Colombier 	case AJAL:
12*f8bc6aafSDavid du Colombier 	case ABEQ:
13*f8bc6aafSDavid du Colombier 	case ABGEZ:
14*f8bc6aafSDavid du Colombier 	case ABGTZ:
15*f8bc6aafSDavid du Colombier 	case ABLEZ:
16*f8bc6aafSDavid du Colombier 	case ABLTZ:
17*f8bc6aafSDavid du Colombier 	case ABNE:
18*f8bc6aafSDavid du Colombier 	case ABFPT:
19*f8bc6aafSDavid du Colombier 	case ABFPF:
20*f8bc6aafSDavid du Colombier 	case AJMP:
21*f8bc6aafSDavid du Colombier 		q = prg();
22*f8bc6aafSDavid du Colombier 		*q = *p;
23*f8bc6aafSDavid du Colombier 		p->link = q;
24*f8bc6aafSDavid du Colombier 		p->as = ANOR;
25*f8bc6aafSDavid du Colombier 		p->optab = 0;
26*f8bc6aafSDavid du Colombier 		p->from = zprg.from;
27*f8bc6aafSDavid du Colombier 		p->from.type = D_REG;
28*f8bc6aafSDavid du Colombier 		p->from.reg = REGZERO;
29*f8bc6aafSDavid du Colombier 		p->to = p->from;
30*f8bc6aafSDavid du Colombier 	}
31*f8bc6aafSDavid du Colombier }
32*f8bc6aafSDavid du Colombier 
33*f8bc6aafSDavid du Colombier void
span(void)347edc7532SDavid du Colombier span(void)
357edc7532SDavid du Colombier {
367edc7532SDavid du Colombier 	Prog *p, *q;
37*f8bc6aafSDavid du Colombier 	Sym *setext, *s;
387edc7532SDavid du Colombier 	Optab *o;
39*f8bc6aafSDavid du Colombier 	int m, bflag, i;
40*f8bc6aafSDavid du Colombier 	vlong c, otxt, v;
417edc7532SDavid du Colombier 
427edc7532SDavid du Colombier 	if(debug['v'])
437edc7532SDavid du Colombier 		Bprint(&bso, "%5.2f span\n", cputime());
447edc7532SDavid du Colombier 	Bflush(&bso);
457edc7532SDavid du Colombier 
467edc7532SDavid du Colombier 	bflag = 0;
477edc7532SDavid du Colombier 	c = INITTEXT;
487edc7532SDavid du Colombier 	otxt = c;
497edc7532SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
50*f8bc6aafSDavid du Colombier 		/* bug in early 4000 chips delayslot on page boundary */
51*f8bc6aafSDavid du Colombier 		if((c&(0x1000-1)) == 0xffc)
52*f8bc6aafSDavid du Colombier 			pagebug(p);
537edc7532SDavid du Colombier 		p->pc = c;
547edc7532SDavid du Colombier 		o = oplook(p);
557edc7532SDavid du Colombier 		m = o->size;
567edc7532SDavid du Colombier 		if(m == 0) {
577edc7532SDavid du Colombier 			if(p->as == ATEXT) {
587edc7532SDavid du Colombier 				curtext = p;
597edc7532SDavid du Colombier 				autosize = p->to.offset + 8;
607edc7532SDavid du Colombier 				if(p->from.sym != S)
617edc7532SDavid du Colombier 					p->from.sym->value = c;
627edc7532SDavid du Colombier 				/* need passes to resolve branches */
637edc7532SDavid du Colombier 				if(c-otxt >= 1L<<17)
647edc7532SDavid du Colombier 					bflag = 1;
657edc7532SDavid du Colombier 				otxt = c;
667edc7532SDavid du Colombier 				continue;
677edc7532SDavid du Colombier 			}
687edc7532SDavid du Colombier 			diag("zero-width instruction\n%P", p);
697edc7532SDavid du Colombier 			continue;
707edc7532SDavid du Colombier 		}
717edc7532SDavid du Colombier 		c += m;
727edc7532SDavid du Colombier 	}
737edc7532SDavid du Colombier 
747edc7532SDavid du Colombier 	/*
757edc7532SDavid du Colombier 	 * if any procedure is large enough to
767edc7532SDavid du Colombier 	 * generate a large SBRA branch, then
777edc7532SDavid du Colombier 	 * generate extra passes putting branches
787edc7532SDavid du Colombier 	 * around jmps to fix. this is rare.
797edc7532SDavid du Colombier 	 */
807edc7532SDavid du Colombier 	while(bflag) {
817edc7532SDavid du Colombier 		if(debug['v'])
827edc7532SDavid du Colombier 			Bprint(&bso, "%5.2f span1\n", cputime());
837edc7532SDavid du Colombier 		bflag = 0;
847edc7532SDavid du Colombier 		c = INITTEXT;
857edc7532SDavid du Colombier 		for(p = firstp; p != P; p = p->link) {
86*f8bc6aafSDavid du Colombier 			/* bug in early 4000 chips delayslot on page boundary */
87*f8bc6aafSDavid du Colombier 			if((c&(0x1000-1)) == 0xffc)
88*f8bc6aafSDavid du Colombier 				pagebug(p);
897edc7532SDavid du Colombier 			p->pc = c;
907edc7532SDavid du Colombier 			o = oplook(p);
917edc7532SDavid du Colombier 			if(o->type == 6 && p->cond) {
927edc7532SDavid du Colombier 				otxt = p->cond->pc - c;
937edc7532SDavid du Colombier 				if(otxt < 0)
947edc7532SDavid du Colombier 					otxt = -otxt;
957edc7532SDavid du Colombier 				if(otxt >= (1L<<17) - 10) {
967edc7532SDavid du Colombier 					q = prg();
977edc7532SDavid du Colombier 					q->link = p->link;
987edc7532SDavid du Colombier 					p->link = q;
997edc7532SDavid du Colombier 					q->as = AJMP;
1007edc7532SDavid du Colombier 					q->to.type = D_BRANCH;
1017edc7532SDavid du Colombier 					q->cond = p->cond;
1027edc7532SDavid du Colombier 					p->cond = q;
1037edc7532SDavid du Colombier 					q = prg();
1047edc7532SDavid du Colombier 					q->link = p->link;
1057edc7532SDavid du Colombier 					p->link = q;
1067edc7532SDavid du Colombier 					q->as = AJMP;
1077edc7532SDavid du Colombier 					q->to.type = D_BRANCH;
1087edc7532SDavid du Colombier 					q->cond = q->link->link;
1097edc7532SDavid du Colombier 					addnop(p->link);
1107edc7532SDavid du Colombier 					addnop(p);
1117edc7532SDavid du Colombier 					bflag = 1;
1127edc7532SDavid du Colombier 				}
1137edc7532SDavid du Colombier 			}
1147edc7532SDavid du Colombier 			m = o->size;
1157edc7532SDavid du Colombier 			if(m == 0) {
1167edc7532SDavid du Colombier 				if(p->as == ATEXT) {
1177edc7532SDavid du Colombier 					curtext = p;
1187edc7532SDavid du Colombier 					autosize = p->to.offset + 8;
1197edc7532SDavid du Colombier 					if(p->from.sym != S)
1207edc7532SDavid du Colombier 						p->from.sym->value = c;
1217edc7532SDavid du Colombier 					continue;
1227edc7532SDavid du Colombier 				}
1237edc7532SDavid du Colombier 				diag("zero-width instruction\n%P", p);
1247edc7532SDavid du Colombier 				continue;
1257edc7532SDavid du Colombier 			}
1267edc7532SDavid du Colombier 			c += m;
1277edc7532SDavid du Colombier 		}
1287edc7532SDavid du Colombier 	}
129*f8bc6aafSDavid du Colombier 
130*f8bc6aafSDavid du Colombier 	if(debug['t']) {
131*f8bc6aafSDavid du Colombier 		/*
132*f8bc6aafSDavid du Colombier 		 * add strings to text segment
133*f8bc6aafSDavid du Colombier 		 */
134*f8bc6aafSDavid du Colombier 		c = rnd(c, 8);
135*f8bc6aafSDavid du Colombier 		for(i=0; i<NHASH; i++)
136*f8bc6aafSDavid du Colombier 		for(s = hash[i]; s != S; s = s->link) {
137*f8bc6aafSDavid du Colombier 			if(s->type != SSTRING)
138*f8bc6aafSDavid du Colombier 				continue;
139*f8bc6aafSDavid du Colombier 			v = s->value;
140*f8bc6aafSDavid du Colombier 			while(v & 3)
141*f8bc6aafSDavid du Colombier 				v++;
142*f8bc6aafSDavid du Colombier 			s->value = c;
143*f8bc6aafSDavid du Colombier 			c += v;
144*f8bc6aafSDavid du Colombier 		}
145*f8bc6aafSDavid du Colombier 	}
146*f8bc6aafSDavid du Colombier 
1477edc7532SDavid du Colombier 	c = rnd(c, 8);
1487edc7532SDavid du Colombier 
1497edc7532SDavid du Colombier 	setext = lookup("etext", 0);
1507edc7532SDavid du Colombier 	if(setext != S) {
1517edc7532SDavid du Colombier 		setext->value = c;
1527edc7532SDavid du Colombier 		textsize = c - INITTEXT;
1537edc7532SDavid du Colombier 	}
1547edc7532SDavid du Colombier 	if(INITRND)
1557edc7532SDavid du Colombier 		INITDAT = rnd(c, INITRND);
1567edc7532SDavid du Colombier 	if(debug['v'])
157*f8bc6aafSDavid du Colombier 		Bprint(&bso, "tsize = %llux\n", textsize);
1587edc7532SDavid du Colombier 	Bflush(&bso);
1597edc7532SDavid du Colombier }
1607edc7532SDavid du Colombier 
1617edc7532SDavid du Colombier void
xdefine(char * p,int t,vlong v)162*f8bc6aafSDavid du Colombier xdefine(char *p, int t, vlong v)
1637edc7532SDavid du Colombier {
1647edc7532SDavid du Colombier 	Sym *s;
1657edc7532SDavid du Colombier 
1667edc7532SDavid du Colombier 	s = lookup(p, 0);
1677edc7532SDavid du Colombier 	if(s->type == 0 || s->type == SXREF) {
1687edc7532SDavid du Colombier 		s->type = t;
1697edc7532SDavid du Colombier 		s->value = v;
1707edc7532SDavid du Colombier 	}
1717edc7532SDavid du Colombier }
1727edc7532SDavid du Colombier 
1737edc7532SDavid du Colombier long
regoff(Adr * a)1747edc7532SDavid du Colombier regoff(Adr *a)
1757edc7532SDavid du Colombier {
1767edc7532SDavid du Colombier 
1777edc7532SDavid du Colombier 	instoffset = 0;
1787edc7532SDavid du Colombier 	aclass(a);
1797edc7532SDavid du Colombier 	return instoffset;
1807edc7532SDavid du Colombier }
1817edc7532SDavid du Colombier 
1827edc7532SDavid du Colombier int
isint32(vlong v)183*f8bc6aafSDavid du Colombier isint32(vlong v)
184*f8bc6aafSDavid du Colombier {
185*f8bc6aafSDavid du Colombier 	long l;
186*f8bc6aafSDavid du Colombier 
187*f8bc6aafSDavid du Colombier 	l = v;
188*f8bc6aafSDavid du Colombier 	return (vlong)l == v;
189*f8bc6aafSDavid du Colombier }
190*f8bc6aafSDavid du Colombier 
191*f8bc6aafSDavid du Colombier int
isuint32(uvlong v)192*f8bc6aafSDavid du Colombier isuint32(uvlong v)
193*f8bc6aafSDavid du Colombier {
194*f8bc6aafSDavid du Colombier 	ulong l;
195*f8bc6aafSDavid du Colombier 
196*f8bc6aafSDavid du Colombier 	l = v;
197*f8bc6aafSDavid du Colombier 	return (uvlong)l == v;
198*f8bc6aafSDavid du Colombier }
199*f8bc6aafSDavid du Colombier 
200*f8bc6aafSDavid du Colombier int
aclass(Adr * a)2017edc7532SDavid du Colombier aclass(Adr *a)
2027edc7532SDavid du Colombier {
2037edc7532SDavid du Colombier 	Sym *s;
2047edc7532SDavid du Colombier 	int t;
2057edc7532SDavid du Colombier 
2067edc7532SDavid du Colombier 	switch(a->type) {
2077edc7532SDavid du Colombier 	case D_NONE:
2087edc7532SDavid du Colombier 		return C_NONE;
2097edc7532SDavid du Colombier 
2107edc7532SDavid du Colombier 	case D_REG:
2117edc7532SDavid du Colombier 		return C_REG;
2127edc7532SDavid du Colombier 
2137edc7532SDavid du Colombier 	case D_FREG:
2147edc7532SDavid du Colombier 		return C_FREG;
2157edc7532SDavid du Colombier 
2167edc7532SDavid du Colombier 	case D_FCREG:
2177edc7532SDavid du Colombier 		return C_FCREG;
2187edc7532SDavid du Colombier 
2197edc7532SDavid du Colombier 	case D_MREG:
2207edc7532SDavid du Colombier 		return C_MREG;
2217edc7532SDavid du Colombier 
2227edc7532SDavid du Colombier 	case D_OREG:
2237edc7532SDavid du Colombier 		switch(a->name) {
2247edc7532SDavid du Colombier 		case D_EXTERN:
2257edc7532SDavid du Colombier 		case D_STATIC:
2267edc7532SDavid du Colombier 			if(a->sym == 0 || a->sym->name == 0) {
2277edc7532SDavid du Colombier 				print("null sym external\n");
2287edc7532SDavid du Colombier 				print("%D\n", a);
2297edc7532SDavid du Colombier 				return C_GOK;
2307edc7532SDavid du Colombier 			}
2317edc7532SDavid du Colombier 			t = a->sym->type;
2327edc7532SDavid du Colombier 			if(t == 0 || t == SXREF) {
2337edc7532SDavid du Colombier 				diag("undefined external: %s in %s",
2347edc7532SDavid du Colombier 					a->sym->name, TNAME);
2357edc7532SDavid du Colombier 				a->sym->type = SDATA;
2367edc7532SDavid du Colombier 			}
2377edc7532SDavid du Colombier 			instoffset = a->sym->value + a->offset - BIG;
2387edc7532SDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
2397edc7532SDavid du Colombier 				return C_SEXT;
2407edc7532SDavid du Colombier 			return C_LEXT;
2417edc7532SDavid du Colombier 		case D_AUTO:
2427edc7532SDavid du Colombier 			instoffset = autosize + a->offset;
2437edc7532SDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
2447edc7532SDavid du Colombier 				return C_SAUTO;
2457edc7532SDavid du Colombier 			return C_LAUTO;
2467edc7532SDavid du Colombier 
2477edc7532SDavid du Colombier 		case D_PARAM:
2487edc7532SDavid du Colombier 			instoffset = autosize + a->offset + 8L;
2497edc7532SDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
2507edc7532SDavid du Colombier 				return C_SAUTO;
2517edc7532SDavid du Colombier 			return C_LAUTO;
2527edc7532SDavid du Colombier 		case D_NONE:
2537edc7532SDavid du Colombier 			instoffset = a->offset;
2547edc7532SDavid du Colombier 			if(instoffset == 0)
2557edc7532SDavid du Colombier 				return C_ZOREG;
2567edc7532SDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
2577edc7532SDavid du Colombier 				return C_SOREG;
2587edc7532SDavid du Colombier 			return C_LOREG;
2597edc7532SDavid du Colombier 		}
2607edc7532SDavid du Colombier 		return C_GOK;
2617edc7532SDavid du Colombier 
2627edc7532SDavid du Colombier 	case D_HI:
2637edc7532SDavid du Colombier 		return C_LO;
2647edc7532SDavid du Colombier 	case D_LO:
2657edc7532SDavid du Colombier 		return C_HI;
2667edc7532SDavid du Colombier 
2677edc7532SDavid du Colombier 	case D_OCONST:
2687edc7532SDavid du Colombier 		switch(a->name) {
2697edc7532SDavid du Colombier 		case D_EXTERN:
2707edc7532SDavid du Colombier 		case D_STATIC:
2717edc7532SDavid du Colombier 			s = a->sym;
2727edc7532SDavid du Colombier 			t = s->type;
2737edc7532SDavid du Colombier 			if(t == 0 || t == SXREF) {
2747edc7532SDavid du Colombier 				diag("undefined external: %s in %s",
2757edc7532SDavid du Colombier 					s->name, TNAME);
2767edc7532SDavid du Colombier 				s->type = SDATA;
2777edc7532SDavid du Colombier 			}
2787edc7532SDavid du Colombier 			instoffset = s->value + a->offset + INITDAT;
2797edc7532SDavid du Colombier 			if(s->type == STEXT || s->type == SLEAF)
2807edc7532SDavid du Colombier 				instoffset = s->value + a->offset;
2817edc7532SDavid du Colombier 			return C_LCON;
2827edc7532SDavid du Colombier 		}
2837edc7532SDavid du Colombier 		return C_GOK;
2847edc7532SDavid du Colombier 
2857edc7532SDavid du Colombier 	case D_CONST:
2867edc7532SDavid du Colombier 		switch(a->name) {
2877edc7532SDavid du Colombier 		case D_NONE:
2887edc7532SDavid du Colombier 			instoffset = a->offset;
2897edc7532SDavid du Colombier 		consize:
2907edc7532SDavid du Colombier 			if(instoffset > 0) {
2917edc7532SDavid du Colombier 				if(instoffset <= 0x7fff)
2927edc7532SDavid du Colombier 					return C_SCON;
2937edc7532SDavid du Colombier 				if(instoffset <= 0xffff)
2947edc7532SDavid du Colombier 					return C_ANDCON;
295*f8bc6aafSDavid du Colombier 				if((instoffset & 0xffff) == 0 && isuint32(instoffset))
2967edc7532SDavid du Colombier 					return C_UCON;
2977edc7532SDavid du Colombier 				return C_LCON;
2987edc7532SDavid du Colombier 			}
2997edc7532SDavid du Colombier 			if(instoffset == 0)
3007edc7532SDavid du Colombier 				return C_ZCON;
3017edc7532SDavid du Colombier 			if(instoffset >= -0x8000)
3027edc7532SDavid du Colombier 				return C_ADDCON;
303*f8bc6aafSDavid du Colombier 			if((instoffset & 0xffff) == 0 && isint32(instoffset))
3047edc7532SDavid du Colombier 				return C_UCON;
3057edc7532SDavid du Colombier 			return C_LCON;
3067edc7532SDavid du Colombier 
3077edc7532SDavid du Colombier 		case D_EXTERN:
3087edc7532SDavid du Colombier 		case D_STATIC:
3097edc7532SDavid du Colombier 			s = a->sym;
3107edc7532SDavid du Colombier 			if(s == S)
3117edc7532SDavid du Colombier 				break;
3127edc7532SDavid du Colombier 			t = s->type;
3137edc7532SDavid du Colombier 			switch(t) {
3147edc7532SDavid du Colombier 			case 0:
3157edc7532SDavid du Colombier 			case SXREF:
3167edc7532SDavid du Colombier 				diag("undefined external: %s in %s",
3177edc7532SDavid du Colombier 					s->name, TNAME);
3187edc7532SDavid du Colombier 				s->type = SDATA;
3197edc7532SDavid du Colombier 				break;
3207edc7532SDavid du Colombier 			case SCONST:
3217edc7532SDavid du Colombier 				instoffset = s->value + a->offset;
3227edc7532SDavid du Colombier 				goto consize;
3237edc7532SDavid du Colombier 			case STEXT:
3247edc7532SDavid du Colombier 			case SLEAF:
3257edc7532SDavid du Colombier 				instoffset = s->value + a->offset;
3267edc7532SDavid du Colombier 				return C_LCON;
3277edc7532SDavid du Colombier 			}
3287edc7532SDavid du Colombier 			instoffset = s->value + a->offset - BIG;
3297edc7532SDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L)
3307edc7532SDavid du Colombier 				return C_SECON;
3317edc7532SDavid du Colombier 			instoffset = s->value + a->offset + INITDAT;
3327edc7532SDavid du Colombier 			return C_LCON;
3337edc7532SDavid du Colombier 
3347edc7532SDavid du Colombier 		case D_AUTO:
3357edc7532SDavid du Colombier 			instoffset = autosize + a->offset;
3367edc7532SDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
3377edc7532SDavid du Colombier 				return C_SACON;
3387edc7532SDavid du Colombier 			return C_LACON;
3397edc7532SDavid du Colombier 
3407edc7532SDavid du Colombier 		case D_PARAM:
3417edc7532SDavid du Colombier 			instoffset = autosize + a->offset + 8L;
3427edc7532SDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
3437edc7532SDavid du Colombier 				return C_SACON;
3447edc7532SDavid du Colombier 			return C_LACON;
3457edc7532SDavid du Colombier 		}
3467edc7532SDavid du Colombier 		return C_GOK;
3477edc7532SDavid du Colombier 
3487edc7532SDavid du Colombier 	case D_BRANCH:
3497edc7532SDavid du Colombier 		return C_SBRA;
3507edc7532SDavid du Colombier 	}
3517edc7532SDavid du Colombier 	return C_GOK;
3527edc7532SDavid du Colombier }
3537edc7532SDavid du Colombier 
3547edc7532SDavid du Colombier Optab*
oplook(Prog * p)3557edc7532SDavid du Colombier oplook(Prog *p)
3567edc7532SDavid du Colombier {
357*f8bc6aafSDavid du Colombier 	int a1, a2, a3, r;
3587edc7532SDavid du Colombier 	char *c1, *c3;
3597edc7532SDavid du Colombier 	Optab *o, *e;
3607edc7532SDavid du Colombier 
3617edc7532SDavid du Colombier 	a1 = p->optab;
3627edc7532SDavid du Colombier 	if(a1)
3637edc7532SDavid du Colombier 		return optab+(a1-1);
3647edc7532SDavid du Colombier 	a1 = p->from.class;
3657edc7532SDavid du Colombier 	if(a1 == 0) {
3667edc7532SDavid du Colombier 		a1 = aclass(&p->from) + 1;
3677edc7532SDavid du Colombier 		p->from.class = a1;
3687edc7532SDavid du Colombier 	}
3697edc7532SDavid du Colombier 	a1--;
3707edc7532SDavid du Colombier 	a3 = p->to.class;
3717edc7532SDavid du Colombier 	if(a3 == 0) {
3727edc7532SDavid du Colombier 		a3 = aclass(&p->to) + 1;
3737edc7532SDavid du Colombier 		p->to.class = a3;
3747edc7532SDavid du Colombier 	}
3757edc7532SDavid du Colombier 	a3--;
3767edc7532SDavid du Colombier 	a2 = C_NONE;
3777edc7532SDavid du Colombier 	if(p->reg != NREG)
3787edc7532SDavid du Colombier 		a2 = C_REG;
3797edc7532SDavid du Colombier 	r = p->as;
3807edc7532SDavid du Colombier 	o = oprange[r].start;
3817edc7532SDavid du Colombier 	if(o == 0) {
382*f8bc6aafSDavid du Colombier 		a1 = opcross[repop[r]][a1][a2][a3];
383*f8bc6aafSDavid du Colombier 		if(a1) {
384*f8bc6aafSDavid du Colombier 			p->optab = a1+1;
385*f8bc6aafSDavid du Colombier 			return optab+a1;
3867edc7532SDavid du Colombier 		}
3877edc7532SDavid du Colombier 		o = oprange[r].stop; /* just generate an error */
3887edc7532SDavid du Colombier 	}
3897edc7532SDavid du Colombier 	e = oprange[r].stop;
3907edc7532SDavid du Colombier 	c1 = xcmp[a1];
3917edc7532SDavid du Colombier 	c3 = xcmp[a3];
3927edc7532SDavid du Colombier 	for(; o<e; o++)
3937edc7532SDavid du Colombier 		if(o->a2 == a2)
3947edc7532SDavid du Colombier 		if(c1[o->a1])
3957edc7532SDavid du Colombier 		if(c3[o->a3]) {
3967edc7532SDavid du Colombier 			p->optab = (o-optab)+1;
3977edc7532SDavid du Colombier 			return o;
3987edc7532SDavid du Colombier 		}
3997edc7532SDavid du Colombier 	diag("illegal combination %A %d %d %d",
400*f8bc6aafSDavid du Colombier 		p->as, p->from.class-1, a2, a3);
4017edc7532SDavid du Colombier 	if(!debug['a'])
4027edc7532SDavid du Colombier 		prasm(p);
4037edc7532SDavid du Colombier 	o = optab;
4047edc7532SDavid du Colombier 	p->optab = (o-optab)+1;
4057edc7532SDavid du Colombier 	return o;
4067edc7532SDavid du Colombier }
4077edc7532SDavid du Colombier 
4087edc7532SDavid du Colombier int
cmp(int a,int b)4097edc7532SDavid du Colombier cmp(int a, int b)
4107edc7532SDavid du Colombier {
4117edc7532SDavid du Colombier 
4127edc7532SDavid du Colombier 	if(a == b)
4137edc7532SDavid du Colombier 		return 1;
4147edc7532SDavid du Colombier 	switch(a) {
4157edc7532SDavid du Colombier 	case C_LCON:
4167edc7532SDavid du Colombier 		if(b == C_ZCON || b == C_SCON || b == C_UCON ||
4177edc7532SDavid du Colombier 		   b == C_ADDCON || b == C_ANDCON)
4187edc7532SDavid du Colombier 			return 1;
4197edc7532SDavid du Colombier 		break;
4207edc7532SDavid du Colombier 	case C_ADD0CON:
4217edc7532SDavid du Colombier 		if(b == C_ADDCON)
4227edc7532SDavid du Colombier 			return 1;
4237edc7532SDavid du Colombier 	case C_ADDCON:
4247edc7532SDavid du Colombier 		if(b == C_ZCON || b == C_SCON)
4257edc7532SDavid du Colombier 			return 1;
4267edc7532SDavid du Colombier 		break;
4277edc7532SDavid du Colombier 	case C_AND0CON:
4287edc7532SDavid du Colombier 		if(b == C_ANDCON)
4297edc7532SDavid du Colombier 			return 1;
4307edc7532SDavid du Colombier 	case C_ANDCON:
4317edc7532SDavid du Colombier 		if(b == C_ZCON || b == C_SCON)
4327edc7532SDavid du Colombier 			return 1;
4337edc7532SDavid du Colombier 		break;
4347edc7532SDavid du Colombier 	case C_UCON:
4357edc7532SDavid du Colombier 		if(b == C_ZCON)
4367edc7532SDavid du Colombier 			return 1;
4377edc7532SDavid du Colombier 		break;
4387edc7532SDavid du Colombier 	case C_SCON:
4397edc7532SDavid du Colombier 		if(b == C_ZCON)
4407edc7532SDavid du Colombier 			return 1;
4417edc7532SDavid du Colombier 		break;
4427edc7532SDavid du Colombier 	case C_LACON:
4437edc7532SDavid du Colombier 		if(b == C_SACON)
4447edc7532SDavid du Colombier 			return 1;
4457edc7532SDavid du Colombier 		break;
4467edc7532SDavid du Colombier 	case C_LBRA:
4477edc7532SDavid du Colombier 		if(b == C_SBRA)
4487edc7532SDavid du Colombier 			return 1;
4497edc7532SDavid du Colombier 		break;
4507edc7532SDavid du Colombier 	case C_LEXT:
4517edc7532SDavid du Colombier 		if(b == C_SEXT)
4527edc7532SDavid du Colombier 			return 1;
4537edc7532SDavid du Colombier 		break;
4547edc7532SDavid du Colombier 	case C_LAUTO:
4557edc7532SDavid du Colombier 		if(b == C_SAUTO)
4567edc7532SDavid du Colombier 			return 1;
4577edc7532SDavid du Colombier 		break;
4587edc7532SDavid du Colombier 	case C_REG:
4597edc7532SDavid du Colombier 		if(b == C_ZCON)
4607edc7532SDavid du Colombier 			return 1;
4617edc7532SDavid du Colombier 		break;
4627edc7532SDavid du Colombier 	case C_LOREG:
4637edc7532SDavid du Colombier 		if(b == C_ZOREG || b == C_SOREG)
4647edc7532SDavid du Colombier 			return 1;
4657edc7532SDavid du Colombier 		break;
4667edc7532SDavid du Colombier 	case C_SOREG:
4677edc7532SDavid du Colombier 		if(b == C_ZOREG)
4687edc7532SDavid du Colombier 			return 1;
4697edc7532SDavid du Colombier 		break;
4707edc7532SDavid du Colombier 	}
4717edc7532SDavid du Colombier 	return 0;
4727edc7532SDavid du Colombier }
4737edc7532SDavid du Colombier 
4747edc7532SDavid du Colombier int
ocmp(const void * a1,const void * a2)4757edc7532SDavid du Colombier ocmp(const void *a1, const void *a2)
4767edc7532SDavid du Colombier {
4777edc7532SDavid du Colombier 	Optab *p1, *p2;
4787edc7532SDavid du Colombier 	int n;
4797edc7532SDavid du Colombier 
4807edc7532SDavid du Colombier 	p1 = (Optab*)a1;
4817edc7532SDavid du Colombier 	p2 = (Optab*)a2;
4827edc7532SDavid du Colombier 	n = p1->as - p2->as;
4837edc7532SDavid du Colombier 	if(n)
4847edc7532SDavid du Colombier 		return n;
4857edc7532SDavid du Colombier 	n = p1->a1 - p2->a1;
4867edc7532SDavid du Colombier 	if(n)
4877edc7532SDavid du Colombier 		return n;
4887edc7532SDavid du Colombier 	n = p1->a2 - p2->a2;
4897edc7532SDavid du Colombier 	if(n)
4907edc7532SDavid du Colombier 		return n;
4917edc7532SDavid du Colombier 	n = p1->a3 - p2->a3;
4927edc7532SDavid du Colombier 	if(n)
4937edc7532SDavid du Colombier 		return n;
4947edc7532SDavid du Colombier 	return 0;
4957edc7532SDavid du Colombier }
4967edc7532SDavid du Colombier 
4977edc7532SDavid du Colombier void
buildop(void)4987edc7532SDavid du Colombier buildop(void)
4997edc7532SDavid du Colombier {
5007edc7532SDavid du Colombier 	int i, n, r;
5017edc7532SDavid du Colombier 
5027edc7532SDavid du Colombier 	for(i=0; i<32; i++)
5037edc7532SDavid du Colombier 		for(n=0; n<32; n++)
5047edc7532SDavid du Colombier 			xcmp[i][n] = cmp(n, i);
5057edc7532SDavid du Colombier 	for(n=0; optab[n].as != AXXX; n++)
5067edc7532SDavid du Colombier 		;
5077edc7532SDavid du Colombier 	qsort(optab, n, sizeof(optab[0]), ocmp);
5087edc7532SDavid du Colombier 	for(i=0; i<n; i++) {
5097edc7532SDavid du Colombier 		r = optab[i].as;
5107edc7532SDavid du Colombier 		oprange[r].start = optab+i;
5117edc7532SDavid du Colombier 		while(optab[i].as == r)
5127edc7532SDavid du Colombier 			i++;
5137edc7532SDavid du Colombier 		oprange[r].stop = optab+i;
5147edc7532SDavid du Colombier 		i--;
5157edc7532SDavid du Colombier 
5167edc7532SDavid du Colombier 		switch(r)
5177edc7532SDavid du Colombier 		{
5187edc7532SDavid du Colombier 		default:
5197edc7532SDavid du Colombier 			diag("unknown op in build: %A", r);
5207edc7532SDavid du Colombier 			errorexit();
5217edc7532SDavid du Colombier 		case AABSF:
5227edc7532SDavid du Colombier 			oprange[AMOVFD] = oprange[r];
5237edc7532SDavid du Colombier 			oprange[AMOVDF] = oprange[r];
5247edc7532SDavid du Colombier 			oprange[AMOVWF] = oprange[r];
5257edc7532SDavid du Colombier 			oprange[AMOVFW] = oprange[r];
5267edc7532SDavid du Colombier 			oprange[AMOVWD] = oprange[r];
5277edc7532SDavid du Colombier 			oprange[AMOVDW] = oprange[r];
5287edc7532SDavid du Colombier 			oprange[ANEGF] = oprange[r];
5297edc7532SDavid du Colombier 			oprange[ANEGD] = oprange[r];
5307edc7532SDavid du Colombier 			oprange[AABSD] = oprange[r];
5317edc7532SDavid du Colombier 			oprange[ATRUNCDW] = oprange[r];
5327edc7532SDavid du Colombier 			oprange[ATRUNCFW] = oprange[r];
5337edc7532SDavid du Colombier 			oprange[ATRUNCDV] = oprange[r];
5347edc7532SDavid du Colombier 			oprange[ATRUNCFV] = oprange[r];
5357edc7532SDavid du Colombier 			oprange[AMOVDV] = oprange[r];
5367edc7532SDavid du Colombier 			oprange[AMOVFV] = oprange[r];
5377edc7532SDavid du Colombier 			oprange[AMOVVD] = oprange[r];
5387edc7532SDavid du Colombier 			oprange[AMOVVF] = oprange[r];
5397edc7532SDavid du Colombier 			break;
5407edc7532SDavid du Colombier 		case AADD:
5417edc7532SDavid du Colombier 			buildrep(1, AADD);
5427edc7532SDavid du Colombier 			oprange[ASGT] = oprange[r];
5437edc7532SDavid du Colombier 			repop[ASGT] = 1;
5447edc7532SDavid du Colombier 			oprange[ASGTU] = oprange[r];
5457edc7532SDavid du Colombier 			repop[ASGTU] = 1;
5467edc7532SDavid du Colombier 			oprange[AADDU] = oprange[r];
5477edc7532SDavid du Colombier 			repop[AADDU] = 1;
5487edc7532SDavid du Colombier 			oprange[AADDVU] = oprange[r];
5497edc7532SDavid du Colombier 			repop[AADDVU] = 1;
5507edc7532SDavid du Colombier 			oprange[AADDV] = oprange[r];
5517edc7532SDavid du Colombier 			repop[AADDV] = 1;
5527edc7532SDavid du Colombier 			break;
5537edc7532SDavid du Colombier 		case AADDF:
5547edc7532SDavid du Colombier 			oprange[ADIVF] = oprange[r];
5557edc7532SDavid du Colombier 			oprange[ADIVD] = oprange[r];
5567edc7532SDavid du Colombier 			oprange[AMULF] = oprange[r];
5577edc7532SDavid du Colombier 			oprange[AMULD] = oprange[r];
5587edc7532SDavid du Colombier 			oprange[ASUBF] = oprange[r];
5597edc7532SDavid du Colombier 			oprange[ASUBD] = oprange[r];
5607edc7532SDavid du Colombier 			oprange[AADDD] = oprange[r];
5617edc7532SDavid du Colombier 			break;
5627edc7532SDavid du Colombier 		case AAND:
5637edc7532SDavid du Colombier 			buildrep(2, AAND);
5647edc7532SDavid du Colombier 			oprange[AXOR] = oprange[r];
5657edc7532SDavid du Colombier 			repop[AXOR] = 2;
5667edc7532SDavid du Colombier 			oprange[AOR] = oprange[r];
5677edc7532SDavid du Colombier 			repop[AOR] = 2;
5687edc7532SDavid du Colombier 			break;
5697edc7532SDavid du Colombier 		case ABEQ:
5707edc7532SDavid du Colombier 			oprange[ABNE] = oprange[r];
5717edc7532SDavid du Colombier 			break;
5727edc7532SDavid du Colombier 		case ABLEZ:
5737edc7532SDavid du Colombier 			oprange[ABGEZ] = oprange[r];
5747edc7532SDavid du Colombier 			oprange[ABGEZAL] = oprange[r];
5757edc7532SDavid du Colombier 			oprange[ABLTZ] = oprange[r];
5767edc7532SDavid du Colombier 			oprange[ABLTZAL] = oprange[r];
5777edc7532SDavid du Colombier 			oprange[ABGTZ] = oprange[r];
5787edc7532SDavid du Colombier 			break;
5797edc7532SDavid du Colombier 		case AMOVB:
5807edc7532SDavid du Colombier 			buildrep(3, AMOVB);
5817edc7532SDavid du Colombier 			oprange[AMOVH] = oprange[r];
5827edc7532SDavid du Colombier 			repop[AMOVH] = 3;
5837edc7532SDavid du Colombier 			break;
5847edc7532SDavid du Colombier 		case AMOVBU:
5857edc7532SDavid du Colombier 			buildrep(4, AMOVBU);
5867edc7532SDavid du Colombier 			oprange[AMOVHU] = oprange[r];
5877edc7532SDavid du Colombier 			repop[AMOVHU] = 4;
5887edc7532SDavid du Colombier 			break;
5897edc7532SDavid du Colombier 		case AMUL:
5907edc7532SDavid du Colombier 			oprange[AREM] = oprange[r];
5917edc7532SDavid du Colombier 			oprange[AREMU] = oprange[r];
5927edc7532SDavid du Colombier 			oprange[ADIVU] = oprange[r];
5937edc7532SDavid du Colombier 			oprange[AMULU] = oprange[r];
5947edc7532SDavid du Colombier 			oprange[ADIV] = oprange[r];
5957edc7532SDavid du Colombier 			oprange[ADIVV] = oprange[r];
5967edc7532SDavid du Colombier 			oprange[ADIVVU] = oprange[r];
5977edc7532SDavid du Colombier 			oprange[AMULV] = oprange[r];
5987edc7532SDavid du Colombier 			oprange[AMULVU] = oprange[r];
5997edc7532SDavid du Colombier 			oprange[AREMV] = oprange[r];
6007edc7532SDavid du Colombier 			oprange[AREMVU] = oprange[r];
6017edc7532SDavid du Colombier 			break;
6027edc7532SDavid du Colombier 		case ASLL:
6037edc7532SDavid du Colombier 			oprange[ASRL] = oprange[r];
6047edc7532SDavid du Colombier 			oprange[ASRA] = oprange[r];
6057edc7532SDavid du Colombier 			oprange[ASLLV] = oprange[r];
6067edc7532SDavid du Colombier 			oprange[ASRAV] = oprange[r];
6077edc7532SDavid du Colombier 			oprange[ASRLV] = oprange[r];
6087edc7532SDavid du Colombier 			break;
6097edc7532SDavid du Colombier 		case ASUB:
6107edc7532SDavid du Colombier 			oprange[ASUBU] = oprange[r];
6117edc7532SDavid du Colombier 			oprange[ASUBV] = oprange[r];
6127edc7532SDavid du Colombier 			oprange[ASUBVU] = oprange[r];
6137edc7532SDavid du Colombier 			oprange[ANOR] = oprange[r];
6147edc7532SDavid du Colombier 			break;
6157edc7532SDavid du Colombier 		case ASYSCALL:
6167edc7532SDavid du Colombier 			oprange[ATLBP] = oprange[r];
6177edc7532SDavid du Colombier 			oprange[ATLBR] = oprange[r];
6187edc7532SDavid du Colombier 			oprange[ATLBWI] = oprange[r];
6197edc7532SDavid du Colombier 			oprange[ATLBWR] = oprange[r];
6207edc7532SDavid du Colombier 			break;
6217edc7532SDavid du Colombier 		case ACMPEQF:
6227edc7532SDavid du Colombier 			oprange[ACMPGTF] = oprange[r];
6237edc7532SDavid du Colombier 			oprange[ACMPGTD] = oprange[r];
6247edc7532SDavid du Colombier 			oprange[ACMPGEF] = oprange[r];
6257edc7532SDavid du Colombier 			oprange[ACMPGED] = oprange[r];
6267edc7532SDavid du Colombier 			oprange[ACMPEQD] = oprange[r];
6277edc7532SDavid du Colombier 			break;
6287edc7532SDavid du Colombier 		case ABFPT:
6297edc7532SDavid du Colombier 			oprange[ABFPF] = oprange[r];
6307edc7532SDavid du Colombier 			break;
6317edc7532SDavid du Colombier 		case AMOVWL:
6327edc7532SDavid du Colombier 			oprange[AMOVWR] = oprange[r];
6337edc7532SDavid du Colombier 			oprange[AMOVVR] = oprange[r];
6347edc7532SDavid du Colombier 			oprange[AMOVVL] = oprange[r];
6357edc7532SDavid du Colombier 			break;
6367edc7532SDavid du Colombier 		case AMOVW:
6377edc7532SDavid du Colombier 			buildrep(5, AMOVW);
6387edc7532SDavid du Colombier 			break;
6397edc7532SDavid du Colombier 		case AMOVD:
6407edc7532SDavid du Colombier 			buildrep(6, AMOVD);
6417edc7532SDavid du Colombier 			break;
6427edc7532SDavid du Colombier 		case AMOVF:
6437edc7532SDavid du Colombier 			buildrep(7, AMOVF);
6447edc7532SDavid du Colombier 			break;
6457edc7532SDavid du Colombier 		case AMOVV:
6467edc7532SDavid du Colombier 			buildrep(8, AMOVV);
6477edc7532SDavid du Colombier 			break;
6487edc7532SDavid du Colombier 		case ABREAK:
6497edc7532SDavid du Colombier 		case AWORD:
6507edc7532SDavid du Colombier 		case ARFE:
6517edc7532SDavid du Colombier 		case AJAL:
6527edc7532SDavid du Colombier 		case AJMP:
6537edc7532SDavid du Colombier 		case ATEXT:
6547edc7532SDavid du Colombier 		case ACASE:
6557edc7532SDavid du Colombier 		case ABCASE:
6567edc7532SDavid du Colombier 		case AMOVWU:
6577edc7532SDavid du Colombier 			break;
6587edc7532SDavid du Colombier 		}
6597edc7532SDavid du Colombier 	}
6607edc7532SDavid du Colombier }
6617edc7532SDavid du Colombier 
6627edc7532SDavid du Colombier void
buildrep(int x,int as)6637edc7532SDavid du Colombier buildrep(int x, int as)
6647edc7532SDavid du Colombier {
6657edc7532SDavid du Colombier 	Opcross *p;
6667edc7532SDavid du Colombier 	Optab *e, *s, *o;
6677edc7532SDavid du Colombier 	int a1, a2, a3, n;
6687edc7532SDavid du Colombier 
669*f8bc6aafSDavid du Colombier 	if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
6707edc7532SDavid du Colombier 		diag("assumptions fail in buildrep");
6717edc7532SDavid du Colombier 		errorexit();
6727edc7532SDavid du Colombier 	}
6737edc7532SDavid du Colombier 	repop[as] = x;
6747edc7532SDavid du Colombier 	p = (opcross + x);
6757edc7532SDavid du Colombier 	s = oprange[as].start;
6767edc7532SDavid du Colombier 	e = oprange[as].stop;
6777edc7532SDavid du Colombier 	for(o=e-1; o>=s; o--) {
6787edc7532SDavid du Colombier 		n = o-optab;
6797edc7532SDavid du Colombier 		for(a2=0; a2<2; a2++) {
6807edc7532SDavid du Colombier 			if(a2) {
6817edc7532SDavid du Colombier 				if(o->a2 == C_NONE)
6827edc7532SDavid du Colombier 					continue;
6837edc7532SDavid du Colombier 			} else
6847edc7532SDavid du Colombier 				if(o->a2 != C_NONE)
6857edc7532SDavid du Colombier 					continue;
6867edc7532SDavid du Colombier 			for(a1=0; a1<32; a1++) {
6877edc7532SDavid du Colombier 				if(!xcmp[a1][o->a1])
6887edc7532SDavid du Colombier 					continue;
6897edc7532SDavid du Colombier 				for(a3=0; a3<32; a3++)
6907edc7532SDavid du Colombier 					if(xcmp[a3][o->a3])
6917edc7532SDavid du Colombier 						(*p)[a1][a2][a3] = n;
6927edc7532SDavid du Colombier 			}
6937edc7532SDavid du Colombier 		}
6947edc7532SDavid du Colombier 	}
6957edc7532SDavid du Colombier 	oprange[as].start = 0;
6967edc7532SDavid du Colombier }
697