xref: /plan9/sys/src/cmd/vl/span.c (revision a587111c8770e522e3667ff2b63cba8a77811dd9)
13e12c5d1SDavid du Colombier #include	"l.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier void
pagebug(Prog * p)47dd7cddfSDavid du Colombier pagebug(Prog *p)
53e12c5d1SDavid du Colombier {
67dd7cddfSDavid du Colombier 	Prog *q;
73e12c5d1SDavid du Colombier 
8219b2ee8SDavid du Colombier 	switch(p->as) {
9219b2ee8SDavid du Colombier 	case ABGEZAL:
10219b2ee8SDavid du Colombier 	case ABLTZAL:
11219b2ee8SDavid du Colombier 	case AJAL:
12219b2ee8SDavid du Colombier 	case ABEQ:
13219b2ee8SDavid du Colombier 	case ABGEZ:
14219b2ee8SDavid du Colombier 	case ABGTZ:
15219b2ee8SDavid du Colombier 	case ABLEZ:
16219b2ee8SDavid du Colombier 	case ABLTZ:
17219b2ee8SDavid du Colombier 	case ABNE:
18219b2ee8SDavid du Colombier 	case ABFPT:
19219b2ee8SDavid du Colombier 	case ABFPF:
20219b2ee8SDavid du Colombier 	case AJMP:
21219b2ee8SDavid du Colombier 		q = prg();
22219b2ee8SDavid du Colombier 		*q = *p;
23219b2ee8SDavid du Colombier 		p->link = q;
24219b2ee8SDavid du Colombier 		p->as = ANOR;
25219b2ee8SDavid du Colombier 		p->optab = 0;
26219b2ee8SDavid du Colombier 		p->from = zprg.from;
27219b2ee8SDavid du Colombier 		p->from.type = D_REG;
28219b2ee8SDavid du Colombier 		p->from.reg = REGZERO;
29219b2ee8SDavid du Colombier 		p->to = p->from;
30219b2ee8SDavid du Colombier 	}
31219b2ee8SDavid du Colombier }
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier void
span(void)347dd7cddfSDavid du Colombier span(void)
357dd7cddfSDavid du Colombier {
367dd7cddfSDavid du Colombier 	Prog *p, *q;
379a747e4fSDavid du Colombier 	Sym *setext, *s;
387dd7cddfSDavid du Colombier 	Optab *o;
399a747e4fSDavid du Colombier 	int m, bflag, i;
40*a587111cSDavid du Colombier 	vlong c, otxt, v;
417dd7cddfSDavid du Colombier 
427dd7cddfSDavid du Colombier 	if(debug['v'])
437dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f span\n", cputime());
447dd7cddfSDavid du Colombier 	Bflush(&bso);
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier 	bflag = 0;
477dd7cddfSDavid du Colombier 	c = INITTEXT;
487dd7cddfSDavid du Colombier 	otxt = c;
497dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
507dd7cddfSDavid du Colombier 		/* bug in early 4000 chips delayslot on page boundary */
517dd7cddfSDavid du Colombier 		if((c&(0x1000-1)) == 0xffc)
527dd7cddfSDavid du Colombier 			pagebug(p);
533e12c5d1SDavid du Colombier 		p->pc = c;
543e12c5d1SDavid du Colombier 		o = oplook(p);
553e12c5d1SDavid du Colombier 		m = o->size;
563e12c5d1SDavid du Colombier 		if(m == 0) {
573e12c5d1SDavid du Colombier 			if(p->as == ATEXT) {
583e12c5d1SDavid du Colombier 				curtext = p;
593e12c5d1SDavid du Colombier 				autosize = p->to.offset + 4;
603e12c5d1SDavid du Colombier 				if(p->from.sym != S)
613e12c5d1SDavid du Colombier 					p->from.sym->value = c;
627dd7cddfSDavid du Colombier 				/* need passes to resolve branches */
637dd7cddfSDavid du Colombier 				if(c-otxt >= 1L<<17)
647dd7cddfSDavid du Colombier 					bflag = 1;
657dd7cddfSDavid du Colombier 				otxt = c;
667dd7cddfSDavid du Colombier 				continue;
677dd7cddfSDavid du Colombier 			}
686b6b9ac8SDavid du Colombier 			diag("zero-width instruction\n%P", p);
697dd7cddfSDavid du Colombier 			continue;
707dd7cddfSDavid du Colombier 		}
717dd7cddfSDavid du Colombier 		c += m;
727dd7cddfSDavid du Colombier 	}
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier 	/*
757dd7cddfSDavid du Colombier 	 * if any procedure is large enough to
767dd7cddfSDavid du Colombier 	 * generate a large SBRA branch, then
777dd7cddfSDavid du Colombier 	 * generate extra passes putting branches
787dd7cddfSDavid du Colombier 	 * around jmps to fix. this is rare.
797dd7cddfSDavid du Colombier 	 */
807dd7cddfSDavid du Colombier 	while(bflag) {
817dd7cddfSDavid du Colombier 		if(debug['v'])
827dd7cddfSDavid du Colombier 			Bprint(&bso, "%5.2f span1\n", cputime());
837dd7cddfSDavid du Colombier 		bflag = 0;
847dd7cddfSDavid du Colombier 		c = INITTEXT;
857dd7cddfSDavid du Colombier 		for(p = firstp; p != P; p = p->link) {
867dd7cddfSDavid du Colombier 			/* bug in early 4000 chips delayslot on page boundary */
877dd7cddfSDavid du Colombier 			if((c&(0x1000-1)) == 0xffc)
887dd7cddfSDavid du Colombier 				pagebug(p);
897dd7cddfSDavid du Colombier 			p->pc = c;
907dd7cddfSDavid du Colombier 			o = oplook(p);
917dd7cddfSDavid du Colombier 			if(o->type == 6 && p->cond) {
927dd7cddfSDavid du Colombier 				otxt = p->cond->pc - c;
937dd7cddfSDavid du Colombier 				if(otxt < 0)
947dd7cddfSDavid du Colombier 					otxt = -otxt;
957dd7cddfSDavid du Colombier 				if(otxt >= (1L<<17) - 10) {
967dd7cddfSDavid du Colombier 					q = prg();
977dd7cddfSDavid du Colombier 					q->link = p->link;
987dd7cddfSDavid du Colombier 					p->link = q;
997dd7cddfSDavid du Colombier 					q->as = AJMP;
1007dd7cddfSDavid du Colombier 					q->to.type = D_BRANCH;
1017dd7cddfSDavid du Colombier 					q->cond = p->cond;
1027dd7cddfSDavid du Colombier 					p->cond = q;
1037dd7cddfSDavid du Colombier 					q = prg();
1047dd7cddfSDavid du Colombier 					q->link = p->link;
1057dd7cddfSDavid du Colombier 					p->link = q;
1067dd7cddfSDavid du Colombier 					q->as = AJMP;
1077dd7cddfSDavid du Colombier 					q->to.type = D_BRANCH;
1087dd7cddfSDavid du Colombier 					q->cond = q->link->link;
1097dd7cddfSDavid du Colombier 					addnop(p->link);
1107dd7cddfSDavid du Colombier 					addnop(p);
1117dd7cddfSDavid du Colombier 					bflag = 1;
1127dd7cddfSDavid du Colombier 				}
1137dd7cddfSDavid du Colombier 			}
1147dd7cddfSDavid du Colombier 			m = o->size;
1157dd7cddfSDavid du Colombier 			if(m == 0) {
1167dd7cddfSDavid du Colombier 				if(p->as == ATEXT) {
1177dd7cddfSDavid du Colombier 					curtext = p;
1187dd7cddfSDavid du Colombier 					autosize = p->to.offset + 4;
1197dd7cddfSDavid du Colombier 					if(p->from.sym != S)
1207dd7cddfSDavid du Colombier 						p->from.sym->value = c;
1213e12c5d1SDavid du Colombier 					continue;
1223e12c5d1SDavid du Colombier 				}
1236b6b9ac8SDavid du Colombier 				diag("zero-width instruction\n%P", p);
1243e12c5d1SDavid du Colombier 				continue;
1253e12c5d1SDavid du Colombier 			}
1263e12c5d1SDavid du Colombier 			c += m;
1273e12c5d1SDavid du Colombier 		}
1287dd7cddfSDavid du Colombier 	}
1299a747e4fSDavid du Colombier 
1309a747e4fSDavid du Colombier 	if(debug['t']) {
1319a747e4fSDavid du Colombier 		/*
1329a747e4fSDavid du Colombier 		 * add strings to text segment
1339a747e4fSDavid du Colombier 		 */
1349a747e4fSDavid du Colombier 		c = rnd(c, 8);
1359a747e4fSDavid du Colombier 		for(i=0; i<NHASH; i++)
1369a747e4fSDavid du Colombier 		for(s = hash[i]; s != S; s = s->link) {
1379a747e4fSDavid du Colombier 			if(s->type != SSTRING)
1389a747e4fSDavid du Colombier 				continue;
1399a747e4fSDavid du Colombier 			v = s->value;
1409a747e4fSDavid du Colombier 			while(v & 3)
1419a747e4fSDavid du Colombier 				v++;
1429a747e4fSDavid du Colombier 			s->value = c;
1439a747e4fSDavid du Colombier 			c += v;
1449a747e4fSDavid du Colombier 		}
1459a747e4fSDavid du Colombier 	}
1469a747e4fSDavid du Colombier 
1473e12c5d1SDavid du Colombier 	c = rnd(c, 8);
1483e12c5d1SDavid du Colombier 
1493e12c5d1SDavid du Colombier 	setext = lookup("etext", 0);
1503e12c5d1SDavid du Colombier 	if(setext != S) {
1513e12c5d1SDavid du Colombier 		setext->value = c;
1523e12c5d1SDavid du Colombier 		textsize = c - INITTEXT;
1533e12c5d1SDavid du Colombier 	}
1543e12c5d1SDavid du Colombier 	if(INITRND)
1553e12c5d1SDavid du Colombier 		INITDAT = rnd(c, INITRND);
1563e12c5d1SDavid du Colombier 	if(debug['v'])
157*a587111cSDavid du Colombier 		Bprint(&bso, "tsize = %llux\n", textsize);
1583e12c5d1SDavid du Colombier 	Bflush(&bso);
1593e12c5d1SDavid du Colombier }
1603e12c5d1SDavid du Colombier 
1613e12c5d1SDavid du Colombier void
xdefine(char * p,int t,long v)1623e12c5d1SDavid du Colombier xdefine(char *p, int t, long v)
1633e12c5d1SDavid du Colombier {
1643e12c5d1SDavid du Colombier 	Sym *s;
1653e12c5d1SDavid du Colombier 
1663e12c5d1SDavid du Colombier 	s = lookup(p, 0);
1673e12c5d1SDavid du Colombier 	if(s->type == 0 || s->type == SXREF) {
1683e12c5d1SDavid du Colombier 		s->type = t;
1693e12c5d1SDavid du Colombier 		s->value = v;
1703e12c5d1SDavid du Colombier 	}
1713e12c5d1SDavid du Colombier }
1723e12c5d1SDavid du Colombier 
1733e12c5d1SDavid du Colombier long
regoff(Adr * a)1743e12c5d1SDavid du Colombier regoff(Adr *a)
1753e12c5d1SDavid du Colombier {
1763e12c5d1SDavid du Colombier 
1777dd7cddfSDavid du Colombier 	instoffset = 0;
1783e12c5d1SDavid du Colombier 	aclass(a);
1797dd7cddfSDavid du Colombier 	return instoffset;
1803e12c5d1SDavid du Colombier }
1813e12c5d1SDavid du Colombier 
aclass(Adr * a)1823e12c5d1SDavid du Colombier aclass(Adr *a)
1833e12c5d1SDavid du Colombier {
1843e12c5d1SDavid du Colombier 	Sym *s;
1853e12c5d1SDavid du Colombier 	int t;
1863e12c5d1SDavid du Colombier 
1873e12c5d1SDavid du Colombier 	switch(a->type) {
1883e12c5d1SDavid du Colombier 	case D_NONE:
1893e12c5d1SDavid du Colombier 		return C_NONE;
1903e12c5d1SDavid du Colombier 
1913e12c5d1SDavid du Colombier 	case D_REG:
1923e12c5d1SDavid du Colombier 		return C_REG;
1933e12c5d1SDavid du Colombier 
1943e12c5d1SDavid du Colombier 	case D_FREG:
1953e12c5d1SDavid du Colombier 		return C_FREG;
1963e12c5d1SDavid du Colombier 
1973e12c5d1SDavid du Colombier 	case D_FCREG:
1983e12c5d1SDavid du Colombier 		return C_FCREG;
1993e12c5d1SDavid du Colombier 
2003e12c5d1SDavid du Colombier 	case D_MREG:
2013e12c5d1SDavid du Colombier 		return C_MREG;
2023e12c5d1SDavid du Colombier 
2033e12c5d1SDavid du Colombier 	case D_OREG:
2043e12c5d1SDavid du Colombier 		switch(a->name) {
2053e12c5d1SDavid du Colombier 		case D_EXTERN:
2063e12c5d1SDavid du Colombier 		case D_STATIC:
207219b2ee8SDavid du Colombier 			if(a->sym == 0 || a->sym->name == 0) {
2083e12c5d1SDavid du Colombier 				print("null sym external\n");
2093e12c5d1SDavid du Colombier 				print("%D\n", a);
2103e12c5d1SDavid du Colombier 				return C_GOK;
2113e12c5d1SDavid du Colombier 			}
2123e12c5d1SDavid du Colombier 			t = a->sym->type;
2133e12c5d1SDavid du Colombier 			if(t == 0 || t == SXREF) {
2146b6b9ac8SDavid du Colombier 				diag("undefined external: %s in %s",
2153e12c5d1SDavid du Colombier 					a->sym->name, TNAME);
2163e12c5d1SDavid du Colombier 				a->sym->type = SDATA;
2173e12c5d1SDavid du Colombier 			}
2187dd7cddfSDavid du Colombier 			instoffset = a->sym->value + a->offset - BIG;
2197dd7cddfSDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
2203e12c5d1SDavid du Colombier 				return C_SEXT;
2213e12c5d1SDavid du Colombier 			return C_LEXT;
2223e12c5d1SDavid du Colombier 		case D_AUTO:
2237dd7cddfSDavid du Colombier 			instoffset = autosize + a->offset;
2247dd7cddfSDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
2253e12c5d1SDavid du Colombier 				return C_SAUTO;
2263e12c5d1SDavid du Colombier 			return C_LAUTO;
2273e12c5d1SDavid du Colombier 
2283e12c5d1SDavid du Colombier 		case D_PARAM:
2297dd7cddfSDavid du Colombier 			instoffset = autosize + a->offset + 4L;
2307dd7cddfSDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
2313e12c5d1SDavid du Colombier 				return C_SAUTO;
2323e12c5d1SDavid du Colombier 			return C_LAUTO;
2333e12c5d1SDavid du Colombier 		case D_NONE:
2347dd7cddfSDavid du Colombier 			instoffset = a->offset;
2357dd7cddfSDavid du Colombier 			if(instoffset == 0)
2363e12c5d1SDavid du Colombier 				return C_ZOREG;
2377dd7cddfSDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
2383e12c5d1SDavid du Colombier 				return C_SOREG;
2393e12c5d1SDavid du Colombier 			return C_LOREG;
2403e12c5d1SDavid du Colombier 		}
2413e12c5d1SDavid du Colombier 		return C_GOK;
2423e12c5d1SDavid du Colombier 
2433e12c5d1SDavid du Colombier 	case D_HI:
2443e12c5d1SDavid du Colombier 		return C_LO;
2453e12c5d1SDavid du Colombier 	case D_LO:
2463e12c5d1SDavid du Colombier 		return C_HI;
2473e12c5d1SDavid du Colombier 
248219b2ee8SDavid du Colombier 	case D_OCONST:
249219b2ee8SDavid du Colombier 		switch(a->name) {
250219b2ee8SDavid du Colombier 		case D_EXTERN:
251219b2ee8SDavid du Colombier 		case D_STATIC:
252219b2ee8SDavid du Colombier 			s = a->sym;
253219b2ee8SDavid du Colombier 			t = s->type;
254219b2ee8SDavid du Colombier 			if(t == 0 || t == SXREF) {
2556b6b9ac8SDavid du Colombier 				diag("undefined external: %s in %s",
256219b2ee8SDavid du Colombier 					s->name, TNAME);
257219b2ee8SDavid du Colombier 				s->type = SDATA;
258219b2ee8SDavid du Colombier 			}
2597dd7cddfSDavid du Colombier 			instoffset = s->value + a->offset + INITDAT;
260219b2ee8SDavid du Colombier 			if(s->type == STEXT || s->type == SLEAF)
2617dd7cddfSDavid du Colombier 				instoffset = s->value + a->offset;
262219b2ee8SDavid du Colombier 			return C_LCON;
263219b2ee8SDavid du Colombier 		}
264219b2ee8SDavid du Colombier 		return C_GOK;
265219b2ee8SDavid du Colombier 
2663e12c5d1SDavid du Colombier 	case D_CONST:
2673e12c5d1SDavid du Colombier 		switch(a->name) {
2683e12c5d1SDavid du Colombier 
2693e12c5d1SDavid du Colombier 		case D_NONE:
2707dd7cddfSDavid du Colombier 			instoffset = a->offset;
271219b2ee8SDavid du Colombier 		consize:
2727dd7cddfSDavid du Colombier 			if(instoffset > 0) {
2737dd7cddfSDavid du Colombier 				if(instoffset <= 0x7fff)
2743e12c5d1SDavid du Colombier 					return C_SCON;
2757dd7cddfSDavid du Colombier 				if(instoffset <= 0xffff)
2763e12c5d1SDavid du Colombier 					return C_ANDCON;
2777dd7cddfSDavid du Colombier 				if((instoffset & 0xffff) == 0)
2783e12c5d1SDavid du Colombier 					return C_UCON;
2793e12c5d1SDavid du Colombier 				return C_LCON;
2803e12c5d1SDavid du Colombier 			}
2817dd7cddfSDavid du Colombier 			if(instoffset == 0)
2823e12c5d1SDavid du Colombier 				return C_ZCON;
2837dd7cddfSDavid du Colombier 			if(instoffset >= -0x8000)
2843e12c5d1SDavid du Colombier 				return C_ADDCON;
2857dd7cddfSDavid du Colombier 			if((instoffset & 0xffff) == 0)
2863e12c5d1SDavid du Colombier 				return C_UCON;
2873e12c5d1SDavid du Colombier 			return C_LCON;
2883e12c5d1SDavid du Colombier 
2893e12c5d1SDavid du Colombier 		case D_EXTERN:
2903e12c5d1SDavid du Colombier 		case D_STATIC:
2913e12c5d1SDavid du Colombier 			s = a->sym;
292219b2ee8SDavid du Colombier 			if(s == S)
293219b2ee8SDavid du Colombier 				break;
2943e12c5d1SDavid du Colombier 			t = s->type;
295219b2ee8SDavid du Colombier 			switch(t) {
296219b2ee8SDavid du Colombier 			case 0:
297219b2ee8SDavid du Colombier 			case SXREF:
2986b6b9ac8SDavid du Colombier 				diag("undefined external: %s in %s",
2993e12c5d1SDavid du Colombier 					s->name, TNAME);
3003e12c5d1SDavid du Colombier 				s->type = SDATA;
301219b2ee8SDavid du Colombier 				break;
302219b2ee8SDavid du Colombier 			case SCONST:
3037dd7cddfSDavid du Colombier 				instoffset = s->value + a->offset;
304219b2ee8SDavid du Colombier 				goto consize;
305219b2ee8SDavid du Colombier 			case STEXT:
306219b2ee8SDavid du Colombier 			case SLEAF:
3079a747e4fSDavid du Colombier 			case SSTRING:
3087dd7cddfSDavid du Colombier 				instoffset = s->value + a->offset;
3093e12c5d1SDavid du Colombier 				return C_LCON;
3103e12c5d1SDavid du Colombier 			}
3117dd7cddfSDavid du Colombier 			instoffset = s->value + a->offset - BIG;
3127dd7cddfSDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L)
3133e12c5d1SDavid du Colombier 				return C_SECON;
3147dd7cddfSDavid du Colombier 			instoffset = s->value + a->offset + INITDAT;
3153e12c5d1SDavid du Colombier 			return C_LCON;
3163e12c5d1SDavid du Colombier 
3173e12c5d1SDavid du Colombier 		case D_AUTO:
3187dd7cddfSDavid du Colombier 			instoffset = autosize + a->offset;
3197dd7cddfSDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
3203e12c5d1SDavid du Colombier 				return C_SACON;
3213e12c5d1SDavid du Colombier 			return C_LACON;
3223e12c5d1SDavid du Colombier 
3233e12c5d1SDavid du Colombier 		case D_PARAM:
3247dd7cddfSDavid du Colombier 			instoffset = autosize + a->offset + 4L;
3257dd7cddfSDavid du Colombier 			if(instoffset >= -BIG && instoffset < BIG)
3263e12c5d1SDavid du Colombier 				return C_SACON;
3273e12c5d1SDavid du Colombier 			return C_LACON;
3283e12c5d1SDavid du Colombier 		}
3293e12c5d1SDavid du Colombier 		return C_GOK;
3303e12c5d1SDavid du Colombier 
3313e12c5d1SDavid du Colombier 	case D_BRANCH:
3323e12c5d1SDavid du Colombier 		return C_SBRA;
3333e12c5d1SDavid du Colombier 	}
3343e12c5d1SDavid du Colombier 	return C_GOK;
3353e12c5d1SDavid du Colombier }
3363e12c5d1SDavid du Colombier 
3373e12c5d1SDavid du Colombier Optab*
oplook(Prog * p)3383e12c5d1SDavid du Colombier oplook(Prog *p)
3393e12c5d1SDavid du Colombier {
3403e12c5d1SDavid du Colombier 	int a1, a2, a3, r;
3413e12c5d1SDavid du Colombier 	char *c1, *c3;
3423e12c5d1SDavid du Colombier 	Optab *o, *e;
3433e12c5d1SDavid du Colombier 
3443e12c5d1SDavid du Colombier 	a1 = p->optab;
3453e12c5d1SDavid du Colombier 	if(a1)
3463e12c5d1SDavid du Colombier 		return optab+(a1-1);
3473e12c5d1SDavid du Colombier 	a1 = p->from.class;
3483e12c5d1SDavid du Colombier 	if(a1 == 0) {
3493e12c5d1SDavid du Colombier 		a1 = aclass(&p->from) + 1;
3503e12c5d1SDavid du Colombier 		p->from.class = a1;
3513e12c5d1SDavid du Colombier 	}
3523e12c5d1SDavid du Colombier 	a1--;
3533e12c5d1SDavid du Colombier 	a3 = p->to.class;
3543e12c5d1SDavid du Colombier 	if(a3 == 0) {
3553e12c5d1SDavid du Colombier 		a3 = aclass(&p->to) + 1;
3563e12c5d1SDavid du Colombier 		p->to.class = a3;
3573e12c5d1SDavid du Colombier 	}
3583e12c5d1SDavid du Colombier 	a3--;
3593e12c5d1SDavid du Colombier 	a2 = C_NONE;
3603e12c5d1SDavid du Colombier 	if(p->reg != NREG)
3613e12c5d1SDavid du Colombier 		a2 = C_REG;
3623e12c5d1SDavid du Colombier 	r = p->as;
3633e12c5d1SDavid du Colombier 	o = oprange[r].start;
3643e12c5d1SDavid du Colombier 	if(o == 0) {
3653e12c5d1SDavid du Colombier 		a1 = opcross[repop[r]][a1][a2][a3];
3663e12c5d1SDavid du Colombier 		if(a1) {
3673e12c5d1SDavid du Colombier 			p->optab = a1+1;
3683e12c5d1SDavid du Colombier 			return optab+a1;
3693e12c5d1SDavid du Colombier 		}
3703e12c5d1SDavid du Colombier 		o = oprange[r].stop; /* just generate an error */
3713e12c5d1SDavid du Colombier 	}
3723e12c5d1SDavid du Colombier 	e = oprange[r].stop;
3733e12c5d1SDavid du Colombier 	c1 = xcmp[a1];
3743e12c5d1SDavid du Colombier 	c3 = xcmp[a3];
3753e12c5d1SDavid du Colombier 	for(; o<e; o++)
3763e12c5d1SDavid du Colombier 		if(o->a2 == a2)
3773e12c5d1SDavid du Colombier 		if(c1[o->a1])
3783e12c5d1SDavid du Colombier 		if(c3[o->a3]) {
3793e12c5d1SDavid du Colombier 			p->optab = (o-optab)+1;
3803e12c5d1SDavid du Colombier 			return o;
3813e12c5d1SDavid du Colombier 		}
3826b6b9ac8SDavid du Colombier 	diag("illegal combination %A %d %d %d",
3833e12c5d1SDavid du Colombier 		p->as, a1, a2, a3);
3843e12c5d1SDavid du Colombier 	if(!debug['a'])
3853e12c5d1SDavid du Colombier 		prasm(p);
3867dd7cddfSDavid du Colombier 	o = optab;
3877dd7cddfSDavid du Colombier 	p->optab = (o-optab)+1;
3883e12c5d1SDavid du Colombier 	return o;
3893e12c5d1SDavid du Colombier }
3903e12c5d1SDavid du Colombier 
3913e12c5d1SDavid du Colombier int
cmp(int a,int b)3923e12c5d1SDavid du Colombier cmp(int a, int b)
3933e12c5d1SDavid du Colombier {
3943e12c5d1SDavid du Colombier 
3953e12c5d1SDavid du Colombier 	if(a == b)
3963e12c5d1SDavid du Colombier 		return 1;
3973e12c5d1SDavid du Colombier 	switch(a) {
3983e12c5d1SDavid du Colombier 	case C_LCON:
3993e12c5d1SDavid du Colombier 		if(b == C_ZCON || b == C_SCON || b == C_UCON ||
4003e12c5d1SDavid du Colombier 		   b == C_ADDCON || b == C_ANDCON)
4013e12c5d1SDavid du Colombier 			return 1;
4023e12c5d1SDavid du Colombier 		break;
4033e12c5d1SDavid du Colombier 	case C_ADD0CON:
4043e12c5d1SDavid du Colombier 		if(b == C_ADDCON)
4053e12c5d1SDavid du Colombier 			return 1;
4063e12c5d1SDavid du Colombier 	case C_ADDCON:
4073e12c5d1SDavid du Colombier 		if(b == C_ZCON || b == C_SCON)
4083e12c5d1SDavid du Colombier 			return 1;
4093e12c5d1SDavid du Colombier 		break;
4103e12c5d1SDavid du Colombier 	case C_AND0CON:
4113e12c5d1SDavid du Colombier 		if(b == C_ANDCON)
4123e12c5d1SDavid du Colombier 			return 1;
4133e12c5d1SDavid du Colombier 	case C_ANDCON:
4143e12c5d1SDavid du Colombier 		if(b == C_ZCON || b == C_SCON)
4153e12c5d1SDavid du Colombier 			return 1;
4163e12c5d1SDavid du Colombier 		break;
4173e12c5d1SDavid du Colombier 	case C_UCON:
4183e12c5d1SDavid du Colombier 		if(b == C_ZCON)
4193e12c5d1SDavid du Colombier 			return 1;
4203e12c5d1SDavid du Colombier 		break;
4213e12c5d1SDavid du Colombier 	case C_SCON:
4223e12c5d1SDavid du Colombier 		if(b == C_ZCON)
4233e12c5d1SDavid du Colombier 			return 1;
4243e12c5d1SDavid du Colombier 		break;
4253e12c5d1SDavid du Colombier 	case C_LACON:
4263e12c5d1SDavid du Colombier 		if(b == C_SACON)
4273e12c5d1SDavid du Colombier 			return 1;
4283e12c5d1SDavid du Colombier 		break;
4293e12c5d1SDavid du Colombier 	case C_LBRA:
4303e12c5d1SDavid du Colombier 		if(b == C_SBRA)
4313e12c5d1SDavid du Colombier 			return 1;
4323e12c5d1SDavid du Colombier 		break;
4333e12c5d1SDavid du Colombier 	case C_LEXT:
4343e12c5d1SDavid du Colombier 		if(b == C_SEXT)
4353e12c5d1SDavid du Colombier 			return 1;
4363e12c5d1SDavid du Colombier 		break;
4373e12c5d1SDavid du Colombier 	case C_LAUTO:
4383e12c5d1SDavid du Colombier 		if(b == C_SAUTO)
4393e12c5d1SDavid du Colombier 			return 1;
4403e12c5d1SDavid du Colombier 		break;
4413e12c5d1SDavid du Colombier 	case C_REG:
4423e12c5d1SDavid du Colombier 		if(b == C_ZCON)
4433e12c5d1SDavid du Colombier 			return 1;
4443e12c5d1SDavid du Colombier 		break;
4453e12c5d1SDavid du Colombier 	case C_LOREG:
4463e12c5d1SDavid du Colombier 		if(b == C_ZOREG || b == C_SOREG)
4473e12c5d1SDavid du Colombier 			return 1;
4483e12c5d1SDavid du Colombier 		break;
4493e12c5d1SDavid du Colombier 	case C_SOREG:
4503e12c5d1SDavid du Colombier 		if(b == C_ZOREG)
4513e12c5d1SDavid du Colombier 			return 1;
4523e12c5d1SDavid du Colombier 		break;
4533e12c5d1SDavid du Colombier 	}
4543e12c5d1SDavid du Colombier 	return 0;
4553e12c5d1SDavid du Colombier }
4563e12c5d1SDavid du Colombier 
4573e12c5d1SDavid du Colombier int
ocmp(const void * a1,const void * a2)4587dd7cddfSDavid du Colombier ocmp(const void *a1, const void *a2)
4593e12c5d1SDavid du Colombier {
4603e12c5d1SDavid du Colombier 	Optab *p1, *p2;
4613e12c5d1SDavid du Colombier 	int n;
4623e12c5d1SDavid du Colombier 
4637dd7cddfSDavid du Colombier 	p1 = (Optab*)a1;
4647dd7cddfSDavid du Colombier 	p2 = (Optab*)a2;
4653e12c5d1SDavid du Colombier 	n = p1->as - p2->as;
4663e12c5d1SDavid du Colombier 	if(n)
4673e12c5d1SDavid du Colombier 		return n;
4683e12c5d1SDavid du Colombier 	n = p1->a1 - p2->a1;
4693e12c5d1SDavid du Colombier 	if(n)
4703e12c5d1SDavid du Colombier 		return n;
4713e12c5d1SDavid du Colombier 	n = p1->a2 - p2->a2;
4723e12c5d1SDavid du Colombier 	if(n)
4733e12c5d1SDavid du Colombier 		return n;
4743e12c5d1SDavid du Colombier 	n = p1->a3 - p2->a3;
4753e12c5d1SDavid du Colombier 	if(n)
4763e12c5d1SDavid du Colombier 		return n;
4773e12c5d1SDavid du Colombier 	return 0;
4783e12c5d1SDavid du Colombier }
4793e12c5d1SDavid du Colombier 
4803e12c5d1SDavid du Colombier void
buildop(void)4813e12c5d1SDavid du Colombier buildop(void)
4823e12c5d1SDavid du Colombier {
4833e12c5d1SDavid du Colombier 	int i, n, r;
4843e12c5d1SDavid du Colombier 
4853e12c5d1SDavid du Colombier 	for(i=0; i<32; i++)
4863e12c5d1SDavid du Colombier 		for(n=0; n<32; n++)
4873e12c5d1SDavid du Colombier 			xcmp[i][n] = cmp(n, i);
4883e12c5d1SDavid du Colombier 	for(n=0; optab[n].as != AXXX; n++)
4893e12c5d1SDavid du Colombier 		;
4903e12c5d1SDavid du Colombier 	qsort(optab, n, sizeof(optab[0]), ocmp);
4913e12c5d1SDavid du Colombier 	for(i=0; i<n; i++) {
4923e12c5d1SDavid du Colombier 		r = optab[i].as;
4933e12c5d1SDavid du Colombier 		oprange[r].start = optab+i;
4943e12c5d1SDavid du Colombier 		while(optab[i].as == r)
4953e12c5d1SDavid du Colombier 			i++;
4963e12c5d1SDavid du Colombier 		oprange[r].stop = optab+i;
4973e12c5d1SDavid du Colombier 		i--;
4983e12c5d1SDavid du Colombier 
4993e12c5d1SDavid du Colombier 		switch(r)
5003e12c5d1SDavid du Colombier 		{
5013e12c5d1SDavid du Colombier 		default:
5026b6b9ac8SDavid du Colombier 			diag("unknown op in build: %A", r);
5033e12c5d1SDavid du Colombier 			errorexit();
5043e12c5d1SDavid du Colombier 		case AABSF:
5053e12c5d1SDavid du Colombier 			oprange[AMOVFD] = oprange[r];
5063e12c5d1SDavid du Colombier 			oprange[AMOVDF] = oprange[r];
5073e12c5d1SDavid du Colombier 			oprange[AMOVWF] = oprange[r];
5083e12c5d1SDavid du Colombier 			oprange[AMOVFW] = oprange[r];
5093e12c5d1SDavid du Colombier 			oprange[AMOVWD] = oprange[r];
5103e12c5d1SDavid du Colombier 			oprange[AMOVDW] = oprange[r];
5113e12c5d1SDavid du Colombier 			oprange[ANEGF] = oprange[r];
5123e12c5d1SDavid du Colombier 			oprange[ANEGD] = oprange[r];
5133e12c5d1SDavid du Colombier 			oprange[AABSD] = oprange[r];
5143e12c5d1SDavid du Colombier 			break;
5153e12c5d1SDavid du Colombier 		case AADD:
5163e12c5d1SDavid du Colombier 			buildrep(1, AADD);
5173e12c5d1SDavid du Colombier 			oprange[ASGT] = oprange[r];
5183e12c5d1SDavid du Colombier 			repop[ASGT] = 1;
5193e12c5d1SDavid du Colombier 			oprange[ASGTU] = oprange[r];
5203e12c5d1SDavid du Colombier 			repop[ASGTU] = 1;
5213e12c5d1SDavid du Colombier 			oprange[AADDU] = oprange[r];
5223e12c5d1SDavid du Colombier 			repop[AADDU] = 1;
5237dd7cddfSDavid du Colombier 			oprange[AADDVU] = oprange[r];
5247dd7cddfSDavid du Colombier 			repop[AADDVU] = 1;
5253e12c5d1SDavid du Colombier 			break;
5263e12c5d1SDavid du Colombier 		case AADDF:
5273e12c5d1SDavid du Colombier 			oprange[ADIVF] = oprange[r];
5283e12c5d1SDavid du Colombier 			oprange[ADIVD] = oprange[r];
5293e12c5d1SDavid du Colombier 			oprange[AMULF] = oprange[r];
5303e12c5d1SDavid du Colombier 			oprange[AMULD] = oprange[r];
5313e12c5d1SDavid du Colombier 			oprange[ASUBF] = oprange[r];
5323e12c5d1SDavid du Colombier 			oprange[ASUBD] = oprange[r];
5333e12c5d1SDavid du Colombier 			oprange[AADDD] = oprange[r];
5343e12c5d1SDavid du Colombier 			break;
5353e12c5d1SDavid du Colombier 		case AAND:
5363e12c5d1SDavid du Colombier 			buildrep(2, AAND);
5373e12c5d1SDavid du Colombier 			oprange[AXOR] = oprange[r];
5383e12c5d1SDavid du Colombier 			repop[AXOR] = 2;
5393e12c5d1SDavid du Colombier 			oprange[AOR] = oprange[r];
5403e12c5d1SDavid du Colombier 			repop[AOR] = 2;
5413e12c5d1SDavid du Colombier 			break;
5423e12c5d1SDavid du Colombier 		case ABEQ:
5433e12c5d1SDavid du Colombier 			oprange[ABNE] = oprange[r];
5443e12c5d1SDavid du Colombier 			break;
5453e12c5d1SDavid du Colombier 		case ABLEZ:
5463e12c5d1SDavid du Colombier 			oprange[ABGEZ] = oprange[r];
5473e12c5d1SDavid du Colombier 			oprange[ABGEZAL] = oprange[r];
5483e12c5d1SDavid du Colombier 			oprange[ABLTZ] = oprange[r];
5493e12c5d1SDavid du Colombier 			oprange[ABLTZAL] = oprange[r];
5503e12c5d1SDavid du Colombier 			oprange[ABGTZ] = oprange[r];
5513e12c5d1SDavid du Colombier 			break;
5523e12c5d1SDavid du Colombier 		case AMOVB:
5533e12c5d1SDavid du Colombier 			buildrep(3, AMOVB);
5543e12c5d1SDavid du Colombier 			oprange[AMOVH] = oprange[r];
5553e12c5d1SDavid du Colombier 			repop[AMOVH] = 3;
5563e12c5d1SDavid du Colombier 			break;
5573e12c5d1SDavid du Colombier 		case AMOVBU:
5583e12c5d1SDavid du Colombier 			buildrep(4, AMOVBU);
5593e12c5d1SDavid du Colombier 			oprange[AMOVHU] = oprange[r];
5603e12c5d1SDavid du Colombier 			repop[AMOVHU] = 4;
5613e12c5d1SDavid du Colombier 			break;
5623e12c5d1SDavid du Colombier 		case AMUL:
5633e12c5d1SDavid du Colombier 			oprange[AREM] = oprange[r];
5643e12c5d1SDavid du Colombier 			oprange[AREMU] = oprange[r];
5653e12c5d1SDavid du Colombier 			oprange[ADIVU] = oprange[r];
5663e12c5d1SDavid du Colombier 			oprange[AMULU] = oprange[r];
5673e12c5d1SDavid du Colombier 			oprange[ADIV] = oprange[r];
5687dd7cddfSDavid du Colombier 			oprange[ADIVVU] = oprange[r];
5697dd7cddfSDavid du Colombier 			oprange[ADIVV] = oprange[r];
5703e12c5d1SDavid du Colombier 			break;
5713e12c5d1SDavid du Colombier 		case ASLL:
5723e12c5d1SDavid du Colombier 			oprange[ASRL] = oprange[r];
5733e12c5d1SDavid du Colombier 			oprange[ASRA] = oprange[r];
574219b2ee8SDavid du Colombier 			oprange[ASLLV] = oprange[r];
575219b2ee8SDavid du Colombier 			oprange[ASRAV] = oprange[r];
576219b2ee8SDavid du Colombier 			oprange[ASRLV] = oprange[r];
5773e12c5d1SDavid du Colombier 			break;
5783e12c5d1SDavid du Colombier 		case ASUB:
5793e12c5d1SDavid du Colombier 			oprange[ASUBU] = oprange[r];
5803e12c5d1SDavid du Colombier 			oprange[ANOR] = oprange[r];
5813e12c5d1SDavid du Colombier 			break;
5823e12c5d1SDavid du Colombier 		case ASYSCALL:
5833e12c5d1SDavid du Colombier 			oprange[ATLBP] = oprange[r];
5843e12c5d1SDavid du Colombier 			oprange[ATLBR] = oprange[r];
5853e12c5d1SDavid du Colombier 			oprange[ATLBWI] = oprange[r];
5863e12c5d1SDavid du Colombier 			oprange[ATLBWR] = oprange[r];
5873e12c5d1SDavid du Colombier 			break;
5883e12c5d1SDavid du Colombier 		case ACMPEQF:
5893e12c5d1SDavid du Colombier 			oprange[ACMPGTF] = oprange[r];
5903e12c5d1SDavid du Colombier 			oprange[ACMPGTD] = oprange[r];
5913e12c5d1SDavid du Colombier 			oprange[ACMPGEF] = oprange[r];
5923e12c5d1SDavid du Colombier 			oprange[ACMPGED] = oprange[r];
5933e12c5d1SDavid du Colombier 			oprange[ACMPEQD] = oprange[r];
5943e12c5d1SDavid du Colombier 			break;
5953e12c5d1SDavid du Colombier 		case ABFPT:
5963e12c5d1SDavid du Colombier 			oprange[ABFPF] = oprange[r];
5973e12c5d1SDavid du Colombier 			break;
5983e12c5d1SDavid du Colombier 		case AMOVWL:
5993e12c5d1SDavid du Colombier 			oprange[AMOVWR] = oprange[r];
600219b2ee8SDavid du Colombier 			oprange[AMOVVR] = oprange[r];
601219b2ee8SDavid du Colombier 			oprange[AMOVVL] = oprange[r];
6023e12c5d1SDavid du Colombier 			break;
6033e12c5d1SDavid du Colombier 		case AMOVW:
6047dd7cddfSDavid du Colombier 			buildrep(5, AMOVW);
6053e12c5d1SDavid du Colombier 			break;
6063e12c5d1SDavid du Colombier 		case AMOVD:
6077dd7cddfSDavid du Colombier 			buildrep(6, AMOVD);
6083e12c5d1SDavid du Colombier 			break;
6093e12c5d1SDavid du Colombier 		case AMOVF:
6107dd7cddfSDavid du Colombier 			buildrep(7, AMOVF);
6113e12c5d1SDavid du Colombier 			break;
612219b2ee8SDavid du Colombier 		case AMOVV:
6137dd7cddfSDavid du Colombier 			buildrep(8, AMOVV);
614219b2ee8SDavid du Colombier 			break;
615bd389b36SDavid du Colombier 		case ABREAK:
6163e12c5d1SDavid du Colombier 		case AWORD:
6173e12c5d1SDavid du Colombier 		case ARFE:
6183e12c5d1SDavid du Colombier 		case AJAL:
6193e12c5d1SDavid du Colombier 		case AJMP:
6203e12c5d1SDavid du Colombier 		case ATEXT:
6217dd7cddfSDavid du Colombier 		case ACASE:
6227dd7cddfSDavid du Colombier 		case ABCASE:
6233e12c5d1SDavid du Colombier 			break;
6243e12c5d1SDavid du Colombier 		}
6253e12c5d1SDavid du Colombier 	}
6263e12c5d1SDavid du Colombier }
6273e12c5d1SDavid du Colombier 
6283e12c5d1SDavid du Colombier void
buildrep(int x,int as)6293e12c5d1SDavid du Colombier buildrep(int x, int as)
6303e12c5d1SDavid du Colombier {
6313e12c5d1SDavid du Colombier 	Opcross *p;
6323e12c5d1SDavid du Colombier 	Optab *e, *s, *o;
6333e12c5d1SDavid du Colombier 	int a1, a2, a3, n;
6343e12c5d1SDavid du Colombier 
635219b2ee8SDavid du Colombier 	if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
6363e12c5d1SDavid du Colombier 		diag("assumptions fail in buildrep");
6373e12c5d1SDavid du Colombier 		errorexit();
6383e12c5d1SDavid du Colombier 	}
6393e12c5d1SDavid du Colombier 	repop[as] = x;
6403e12c5d1SDavid du Colombier 	p = (opcross + x);
6413e12c5d1SDavid du Colombier 	s = oprange[as].start;
6423e12c5d1SDavid du Colombier 	e = oprange[as].stop;
6433e12c5d1SDavid du Colombier 	for(o=e-1; o>=s; o--) {
6443e12c5d1SDavid du Colombier 		n = o-optab;
6453e12c5d1SDavid du Colombier 		for(a2=0; a2<2; a2++) {
6463e12c5d1SDavid du Colombier 			if(a2) {
6473e12c5d1SDavid du Colombier 				if(o->a2 == C_NONE)
6483e12c5d1SDavid du Colombier 					continue;
6493e12c5d1SDavid du Colombier 			} else
6503e12c5d1SDavid du Colombier 				if(o->a2 != C_NONE)
6513e12c5d1SDavid du Colombier 					continue;
6523e12c5d1SDavid du Colombier 			for(a1=0; a1<32; a1++) {
6533e12c5d1SDavid du Colombier 				if(!xcmp[a1][o->a1])
6543e12c5d1SDavid du Colombier 					continue;
6553e12c5d1SDavid du Colombier 				for(a3=0; a3<32; a3++)
6563e12c5d1SDavid du Colombier 					if(xcmp[a3][o->a3])
6573e12c5d1SDavid du Colombier 						(*p)[a1][a2][a3] = n;
6583e12c5d1SDavid du Colombier 			}
6593e12c5d1SDavid du Colombier 		}
6603e12c5d1SDavid du Colombier 	}
6613e12c5d1SDavid du Colombier 	oprange[as].start = 0;
6623e12c5d1SDavid du Colombier }
663