xref: /inferno-os/utils/0l/span.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
174a4d8c2SCharles.Forsyth #include	"l.h"
274a4d8c2SCharles.Forsyth 
374a4d8c2SCharles.Forsyth void
span(void)474a4d8c2SCharles.Forsyth span(void)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth 	Prog *p, *q;
774a4d8c2SCharles.Forsyth 	Sym *setext;
874a4d8c2SCharles.Forsyth 	Optab *o;
974a4d8c2SCharles.Forsyth 	int m, bflag;
1074a4d8c2SCharles.Forsyth 	long c, otxt;
1174a4d8c2SCharles.Forsyth 
1274a4d8c2SCharles.Forsyth 	if(debug['v'])
1374a4d8c2SCharles.Forsyth 		Bprint(&bso, "%5.2f span\n", cputime());
1474a4d8c2SCharles.Forsyth 	Bflush(&bso);
1574a4d8c2SCharles.Forsyth 
1674a4d8c2SCharles.Forsyth 	bflag = 0;
1774a4d8c2SCharles.Forsyth 	c = INITTEXT;
1874a4d8c2SCharles.Forsyth 	otxt = c;
1974a4d8c2SCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
2074a4d8c2SCharles.Forsyth 		p->pc = c;
2174a4d8c2SCharles.Forsyth 		o = oplook(p);
2274a4d8c2SCharles.Forsyth 		m = o->size;
2374a4d8c2SCharles.Forsyth 		if(m == 0) {
2474a4d8c2SCharles.Forsyth 			if(p->as == ATEXT) {
2574a4d8c2SCharles.Forsyth 				curtext = p;
2674a4d8c2SCharles.Forsyth 				autosize = p->to.offset + 8;
2774a4d8c2SCharles.Forsyth 				if(p->from.sym != S)
2874a4d8c2SCharles.Forsyth 					p->from.sym->value = c;
2974a4d8c2SCharles.Forsyth 				/* need passes to resolve branches */
3074a4d8c2SCharles.Forsyth 				if(c-otxt >= 1L<<17)
3174a4d8c2SCharles.Forsyth 					bflag = 1;
3274a4d8c2SCharles.Forsyth 				otxt = c;
3374a4d8c2SCharles.Forsyth 				continue;
3474a4d8c2SCharles.Forsyth 			}
3574a4d8c2SCharles.Forsyth 			diag("zero-width instruction\n%P\n", p);
3674a4d8c2SCharles.Forsyth 			continue;
3774a4d8c2SCharles.Forsyth 		}
3874a4d8c2SCharles.Forsyth 		c += m;
3974a4d8c2SCharles.Forsyth 	}
4074a4d8c2SCharles.Forsyth 
4174a4d8c2SCharles.Forsyth 	/*
4274a4d8c2SCharles.Forsyth 	 * if any procedure is large enough to
4374a4d8c2SCharles.Forsyth 	 * generate a large SBRA branch, then
4474a4d8c2SCharles.Forsyth 	 * generate extra passes putting branches
4574a4d8c2SCharles.Forsyth 	 * around jmps to fix. this is rare.
4674a4d8c2SCharles.Forsyth 	 */
4774a4d8c2SCharles.Forsyth 	while(bflag) {
4874a4d8c2SCharles.Forsyth 		if(debug['v'])
4974a4d8c2SCharles.Forsyth 			Bprint(&bso, "%5.2f span1\n", cputime());
5074a4d8c2SCharles.Forsyth 		bflag = 0;
5174a4d8c2SCharles.Forsyth 		c = INITTEXT;
5274a4d8c2SCharles.Forsyth 		for(p = firstp; p != P; p = p->link) {
5374a4d8c2SCharles.Forsyth 			p->pc = c;
5474a4d8c2SCharles.Forsyth 			o = oplook(p);
5574a4d8c2SCharles.Forsyth 			if(o->type == 6 && p->cond) {
5674a4d8c2SCharles.Forsyth 				otxt = p->cond->pc - c;
5774a4d8c2SCharles.Forsyth 				if(otxt < 0)
5874a4d8c2SCharles.Forsyth 					otxt = -otxt;
5974a4d8c2SCharles.Forsyth 				if(otxt >= (1L<<17) - 10) {
6074a4d8c2SCharles.Forsyth 					q = prg();
6174a4d8c2SCharles.Forsyth 					q->link = p->link;
6274a4d8c2SCharles.Forsyth 					p->link = q;
6374a4d8c2SCharles.Forsyth 					q->as = AJMP;
6474a4d8c2SCharles.Forsyth 					q->to.type = D_BRANCH;
6574a4d8c2SCharles.Forsyth 					q->cond = p->cond;
6674a4d8c2SCharles.Forsyth 					p->cond = q;
6774a4d8c2SCharles.Forsyth 					q = prg();
6874a4d8c2SCharles.Forsyth 					q->link = p->link;
6974a4d8c2SCharles.Forsyth 					p->link = q;
7074a4d8c2SCharles.Forsyth 					q->as = AJMP;
7174a4d8c2SCharles.Forsyth 					q->to.type = D_BRANCH;
7274a4d8c2SCharles.Forsyth 					q->cond = q->link->link;
7374a4d8c2SCharles.Forsyth 					addnop(p->link);
7474a4d8c2SCharles.Forsyth 					addnop(p);
7574a4d8c2SCharles.Forsyth 					bflag = 1;
7674a4d8c2SCharles.Forsyth 				}
7774a4d8c2SCharles.Forsyth 			}
7874a4d8c2SCharles.Forsyth 			m = o->size;
7974a4d8c2SCharles.Forsyth 			if(m == 0) {
8074a4d8c2SCharles.Forsyth 				if(p->as == ATEXT) {
8174a4d8c2SCharles.Forsyth 					curtext = p;
8274a4d8c2SCharles.Forsyth 					autosize = p->to.offset + 8;
8374a4d8c2SCharles.Forsyth 					if(p->from.sym != S)
8474a4d8c2SCharles.Forsyth 						p->from.sym->value = c;
8574a4d8c2SCharles.Forsyth 					continue;
8674a4d8c2SCharles.Forsyth 				}
8774a4d8c2SCharles.Forsyth 				diag("zero-width instruction\n%P\n", p);
8874a4d8c2SCharles.Forsyth 				continue;
8974a4d8c2SCharles.Forsyth 			}
9074a4d8c2SCharles.Forsyth 			c += m;
9174a4d8c2SCharles.Forsyth 		}
9274a4d8c2SCharles.Forsyth 	}
9374a4d8c2SCharles.Forsyth 	c = rnd(c, 8);
9474a4d8c2SCharles.Forsyth 
9574a4d8c2SCharles.Forsyth 	setext = lookup("etext", 0);
9674a4d8c2SCharles.Forsyth 	if(setext != S) {
9774a4d8c2SCharles.Forsyth 		setext->value = c;
9874a4d8c2SCharles.Forsyth 		textsize = c - INITTEXT;
9974a4d8c2SCharles.Forsyth 	}
10074a4d8c2SCharles.Forsyth 	if(INITRND)
10174a4d8c2SCharles.Forsyth 		INITDAT = rnd(c, INITRND);
10274a4d8c2SCharles.Forsyth 	if(debug['v'])
10374a4d8c2SCharles.Forsyth 		Bprint(&bso, "tsize = %lux\n", textsize);
10474a4d8c2SCharles.Forsyth 	Bflush(&bso);
10574a4d8c2SCharles.Forsyth }
10674a4d8c2SCharles.Forsyth 
10774a4d8c2SCharles.Forsyth void
xdefine(char * p,int t,long v)10874a4d8c2SCharles.Forsyth xdefine(char *p, int t, long v)
10974a4d8c2SCharles.Forsyth {
11074a4d8c2SCharles.Forsyth 	Sym *s;
11174a4d8c2SCharles.Forsyth 
11274a4d8c2SCharles.Forsyth 	s = lookup(p, 0);
11374a4d8c2SCharles.Forsyth 	if(s->type == 0 || s->type == SXREF) {
11474a4d8c2SCharles.Forsyth 		s->type = t;
11574a4d8c2SCharles.Forsyth 		s->value = v;
11674a4d8c2SCharles.Forsyth 	}
11774a4d8c2SCharles.Forsyth }
11874a4d8c2SCharles.Forsyth 
11974a4d8c2SCharles.Forsyth long
regoff(Adr * a)12074a4d8c2SCharles.Forsyth regoff(Adr *a)
12174a4d8c2SCharles.Forsyth {
12274a4d8c2SCharles.Forsyth 
12374a4d8c2SCharles.Forsyth 	instoffset = 0;
12474a4d8c2SCharles.Forsyth 	aclass(a);
12574a4d8c2SCharles.Forsyth 	return instoffset;
12674a4d8c2SCharles.Forsyth }
12774a4d8c2SCharles.Forsyth 
12874a4d8c2SCharles.Forsyth int
aclass(Adr * a)12974a4d8c2SCharles.Forsyth aclass(Adr *a)
13074a4d8c2SCharles.Forsyth {
13174a4d8c2SCharles.Forsyth 	Sym *s;
13274a4d8c2SCharles.Forsyth 	int t;
13374a4d8c2SCharles.Forsyth 
13474a4d8c2SCharles.Forsyth 	switch(a->type) {
13574a4d8c2SCharles.Forsyth 	case D_NONE:
13674a4d8c2SCharles.Forsyth 		return C_NONE;
13774a4d8c2SCharles.Forsyth 
13874a4d8c2SCharles.Forsyth 	case D_REG:
13974a4d8c2SCharles.Forsyth 		return C_REG;
14074a4d8c2SCharles.Forsyth 
14174a4d8c2SCharles.Forsyth 	case D_FREG:
14274a4d8c2SCharles.Forsyth 		return C_FREG;
14374a4d8c2SCharles.Forsyth 
14474a4d8c2SCharles.Forsyth 	case D_FCREG:
14574a4d8c2SCharles.Forsyth 		return C_FCREG;
14674a4d8c2SCharles.Forsyth 
14774a4d8c2SCharles.Forsyth 	case D_MREG:
14874a4d8c2SCharles.Forsyth 		return C_MREG;
14974a4d8c2SCharles.Forsyth 
15074a4d8c2SCharles.Forsyth 	case D_OREG:
15174a4d8c2SCharles.Forsyth 		switch(a->name) {
15274a4d8c2SCharles.Forsyth 		case D_EXTERN:
15374a4d8c2SCharles.Forsyth 		case D_STATIC:
15474a4d8c2SCharles.Forsyth 			if(a->sym == 0 || a->sym->name == 0) {
15574a4d8c2SCharles.Forsyth 				print("null sym external\n");
15674a4d8c2SCharles.Forsyth 				print("%D\n", a);
15774a4d8c2SCharles.Forsyth 				return C_GOK;
15874a4d8c2SCharles.Forsyth 			}
15974a4d8c2SCharles.Forsyth 			t = a->sym->type;
16074a4d8c2SCharles.Forsyth 			if(t == 0 || t == SXREF) {
16174a4d8c2SCharles.Forsyth 				diag("undefined external: %s in %s\n",
16274a4d8c2SCharles.Forsyth 					a->sym->name, TNAME);
16374a4d8c2SCharles.Forsyth 				a->sym->type = SDATA;
16474a4d8c2SCharles.Forsyth 			}
16574a4d8c2SCharles.Forsyth 			instoffset = a->sym->value + a->offset - BIG;
16674a4d8c2SCharles.Forsyth 			if(instoffset >= -BIG && instoffset < BIG)
16774a4d8c2SCharles.Forsyth 				return C_SEXT;
16874a4d8c2SCharles.Forsyth 			return C_LEXT;
16974a4d8c2SCharles.Forsyth 		case D_AUTO:
17074a4d8c2SCharles.Forsyth 			instoffset = autosize + a->offset;
17174a4d8c2SCharles.Forsyth 			if(instoffset >= -BIG && instoffset < BIG)
17274a4d8c2SCharles.Forsyth 				return C_SAUTO;
17374a4d8c2SCharles.Forsyth 			return C_LAUTO;
17474a4d8c2SCharles.Forsyth 
17574a4d8c2SCharles.Forsyth 		case D_PARAM:
17674a4d8c2SCharles.Forsyth 			instoffset = autosize + a->offset + 8L;
17774a4d8c2SCharles.Forsyth 			if(instoffset >= -BIG && instoffset < BIG)
17874a4d8c2SCharles.Forsyth 				return C_SAUTO;
17974a4d8c2SCharles.Forsyth 			return C_LAUTO;
18074a4d8c2SCharles.Forsyth 		case D_NONE:
18174a4d8c2SCharles.Forsyth 			instoffset = a->offset;
18274a4d8c2SCharles.Forsyth 			if(instoffset == 0)
18374a4d8c2SCharles.Forsyth 				return C_ZOREG;
18474a4d8c2SCharles.Forsyth 			if(instoffset >= -BIG && instoffset < BIG)
18574a4d8c2SCharles.Forsyth 				return C_SOREG;
18674a4d8c2SCharles.Forsyth 			return C_LOREG;
18774a4d8c2SCharles.Forsyth 		}
18874a4d8c2SCharles.Forsyth 		return C_GOK;
18974a4d8c2SCharles.Forsyth 
19074a4d8c2SCharles.Forsyth 	case D_HI:
19174a4d8c2SCharles.Forsyth 		return C_LO;
19274a4d8c2SCharles.Forsyth 	case D_LO:
19374a4d8c2SCharles.Forsyth 		return C_HI;
19474a4d8c2SCharles.Forsyth 
19574a4d8c2SCharles.Forsyth 	case D_OCONST:
19674a4d8c2SCharles.Forsyth 		switch(a->name) {
19774a4d8c2SCharles.Forsyth 		case D_EXTERN:
19874a4d8c2SCharles.Forsyth 		case D_STATIC:
19974a4d8c2SCharles.Forsyth 			s = a->sym;
20074a4d8c2SCharles.Forsyth 			t = s->type;
20174a4d8c2SCharles.Forsyth 			if(t == 0 || t == SXREF) {
20274a4d8c2SCharles.Forsyth 				diag("undefined external: %s in %s\n",
20374a4d8c2SCharles.Forsyth 					s->name, TNAME);
20474a4d8c2SCharles.Forsyth 				s->type = SDATA;
20574a4d8c2SCharles.Forsyth 			}
20674a4d8c2SCharles.Forsyth 			instoffset = s->value + a->offset + INITDAT;
20774a4d8c2SCharles.Forsyth 			if(s->type == STEXT || s->type == SLEAF)
20874a4d8c2SCharles.Forsyth 				instoffset = s->value + a->offset;
20974a4d8c2SCharles.Forsyth 			return C_LCON;
21074a4d8c2SCharles.Forsyth 		}
21174a4d8c2SCharles.Forsyth 		return C_GOK;
21274a4d8c2SCharles.Forsyth 
21374a4d8c2SCharles.Forsyth 	case D_CONST:
21474a4d8c2SCharles.Forsyth 		switch(a->name) {
21574a4d8c2SCharles.Forsyth 
21674a4d8c2SCharles.Forsyth 		case D_NONE:
21774a4d8c2SCharles.Forsyth 			instoffset = a->offset;
21874a4d8c2SCharles.Forsyth 		consize:
21974a4d8c2SCharles.Forsyth 			if(instoffset > 0) {
22074a4d8c2SCharles.Forsyth 				if(instoffset <= 0x7fff)
22174a4d8c2SCharles.Forsyth 					return C_SCON;
22274a4d8c2SCharles.Forsyth 				if(instoffset <= 0xffff)
22374a4d8c2SCharles.Forsyth 					return C_ANDCON;
22474a4d8c2SCharles.Forsyth 				if((instoffset & 0xffff) == 0)
22574a4d8c2SCharles.Forsyth 					return C_UCON;
22674a4d8c2SCharles.Forsyth 				return C_LCON;
22774a4d8c2SCharles.Forsyth 			}
22874a4d8c2SCharles.Forsyth 			if(instoffset == 0)
22974a4d8c2SCharles.Forsyth 				return C_ZCON;
23074a4d8c2SCharles.Forsyth 			if(instoffset >= -0x8000)
23174a4d8c2SCharles.Forsyth 				return C_ADDCON;
23274a4d8c2SCharles.Forsyth 			if((instoffset & 0xffff) == 0)
23374a4d8c2SCharles.Forsyth 				return C_UCON;
23474a4d8c2SCharles.Forsyth 			return C_LCON;
23574a4d8c2SCharles.Forsyth 
23674a4d8c2SCharles.Forsyth 		case D_EXTERN:
23774a4d8c2SCharles.Forsyth 		case D_STATIC:
23874a4d8c2SCharles.Forsyth 			s = a->sym;
23974a4d8c2SCharles.Forsyth 			if(s == S)
24074a4d8c2SCharles.Forsyth 				break;
24174a4d8c2SCharles.Forsyth 			t = s->type;
24274a4d8c2SCharles.Forsyth 			switch(t) {
24374a4d8c2SCharles.Forsyth 			case 0:
24474a4d8c2SCharles.Forsyth 			case SXREF:
24574a4d8c2SCharles.Forsyth 				diag("undefined external: %s in %s\n",
24674a4d8c2SCharles.Forsyth 					s->name, TNAME);
24774a4d8c2SCharles.Forsyth 				s->type = SDATA;
24874a4d8c2SCharles.Forsyth 				break;
24974a4d8c2SCharles.Forsyth 			case SCONST:
25074a4d8c2SCharles.Forsyth 				instoffset = s->value + a->offset;
25174a4d8c2SCharles.Forsyth 				goto consize;
25274a4d8c2SCharles.Forsyth 			case STEXT:
25374a4d8c2SCharles.Forsyth 			case SLEAF:
25474a4d8c2SCharles.Forsyth 				instoffset = s->value + a->offset;
25574a4d8c2SCharles.Forsyth 				return C_LCON;
25674a4d8c2SCharles.Forsyth 			}
25774a4d8c2SCharles.Forsyth 			instoffset = s->value + a->offset - BIG;
25874a4d8c2SCharles.Forsyth 			if(instoffset >= -BIG && instoffset < BIG && instoffset != 0L)
25974a4d8c2SCharles.Forsyth 				return C_SECON;
26074a4d8c2SCharles.Forsyth 			instoffset = s->value + a->offset + INITDAT;
26174a4d8c2SCharles.Forsyth 			return C_LCON;
26274a4d8c2SCharles.Forsyth 
26374a4d8c2SCharles.Forsyth 		case D_AUTO:
26474a4d8c2SCharles.Forsyth 			instoffset = autosize + a->offset;
26574a4d8c2SCharles.Forsyth 			if(instoffset >= -BIG && instoffset < BIG)
26674a4d8c2SCharles.Forsyth 				return C_SACON;
26774a4d8c2SCharles.Forsyth 			return C_LACON;
26874a4d8c2SCharles.Forsyth 
26974a4d8c2SCharles.Forsyth 		case D_PARAM:
27074a4d8c2SCharles.Forsyth 			instoffset = autosize + a->offset + 8L;
27174a4d8c2SCharles.Forsyth 			if(instoffset >= -BIG && instoffset < BIG)
27274a4d8c2SCharles.Forsyth 				return C_SACON;
27374a4d8c2SCharles.Forsyth 			return C_LACON;
27474a4d8c2SCharles.Forsyth 		}
27574a4d8c2SCharles.Forsyth 		return C_GOK;
27674a4d8c2SCharles.Forsyth 
27774a4d8c2SCharles.Forsyth 	case D_BRANCH:
27874a4d8c2SCharles.Forsyth 		return C_SBRA;
27974a4d8c2SCharles.Forsyth 	}
28074a4d8c2SCharles.Forsyth 	return C_GOK;
28174a4d8c2SCharles.Forsyth }
28274a4d8c2SCharles.Forsyth 
28374a4d8c2SCharles.Forsyth Optab*
oplook(Prog * p)28474a4d8c2SCharles.Forsyth oplook(Prog *p)
28574a4d8c2SCharles.Forsyth {
28674a4d8c2SCharles.Forsyth 	int a1, a2, a3, r, t;
28774a4d8c2SCharles.Forsyth 	char *c1, *c3;
28874a4d8c2SCharles.Forsyth 	Optab *o, *e;
28974a4d8c2SCharles.Forsyth 
29074a4d8c2SCharles.Forsyth 	a1 = p->optab;
29174a4d8c2SCharles.Forsyth 	if(a1)
29274a4d8c2SCharles.Forsyth 		return optab+(a1-1);
29374a4d8c2SCharles.Forsyth 	a1 = p->from.class;
29474a4d8c2SCharles.Forsyth 	if(a1 == 0) {
29574a4d8c2SCharles.Forsyth 		a1 = aclass(&p->from) + 1;
29674a4d8c2SCharles.Forsyth 		p->from.class = a1;
29774a4d8c2SCharles.Forsyth 	}
29874a4d8c2SCharles.Forsyth 	a1--;
29974a4d8c2SCharles.Forsyth 	a3 = p->to.class;
30074a4d8c2SCharles.Forsyth 	if(a3 == 0) {
30174a4d8c2SCharles.Forsyth 		a3 = aclass(&p->to) + 1;
30274a4d8c2SCharles.Forsyth 		p->to.class = a3;
30374a4d8c2SCharles.Forsyth 	}
30474a4d8c2SCharles.Forsyth 	a3--;
30574a4d8c2SCharles.Forsyth 	a2 = C_NONE;
30674a4d8c2SCharles.Forsyth 	if(p->reg != NREG)
30774a4d8c2SCharles.Forsyth 		a2 = C_REG;
30874a4d8c2SCharles.Forsyth 	r = p->as;
30974a4d8c2SCharles.Forsyth 	o = oprange[r].start;
31074a4d8c2SCharles.Forsyth 	if(o == 0) {
31174a4d8c2SCharles.Forsyth 		t = opcross[repop[r]][a1][a2][a3];
31274a4d8c2SCharles.Forsyth 		if(t) {
31374a4d8c2SCharles.Forsyth 			p->optab = t+1;
31474a4d8c2SCharles.Forsyth 			return optab+t;
31574a4d8c2SCharles.Forsyth 		}
31674a4d8c2SCharles.Forsyth 		o = oprange[r].stop; /* just generate an error */
31774a4d8c2SCharles.Forsyth 	}
31874a4d8c2SCharles.Forsyth 	e = oprange[r].stop;
31974a4d8c2SCharles.Forsyth 	c1 = xcmp[a1];
32074a4d8c2SCharles.Forsyth 	c3 = xcmp[a3];
32174a4d8c2SCharles.Forsyth 	for(; o<e; o++)
32274a4d8c2SCharles.Forsyth 		if(o->a2 == a2)
32374a4d8c2SCharles.Forsyth 		if(c1[o->a1])
32474a4d8c2SCharles.Forsyth 		if(c3[o->a3]) {
32574a4d8c2SCharles.Forsyth 			p->optab = (o-optab)+1;
32674a4d8c2SCharles.Forsyth 			return o;
32774a4d8c2SCharles.Forsyth 		}
32874a4d8c2SCharles.Forsyth 	diag("illegal combination %A %d %d %d",
32974a4d8c2SCharles.Forsyth 		p->as, a1, a2, a3);
33074a4d8c2SCharles.Forsyth 	if(!debug['a'])
33174a4d8c2SCharles.Forsyth 		prasm(p);
33274a4d8c2SCharles.Forsyth 	o = optab;
33374a4d8c2SCharles.Forsyth 	p->optab = (o-optab)+1;
33474a4d8c2SCharles.Forsyth 	return o;
33574a4d8c2SCharles.Forsyth }
33674a4d8c2SCharles.Forsyth 
33774a4d8c2SCharles.Forsyth int
cmp(int a,int b)33874a4d8c2SCharles.Forsyth cmp(int a, int b)
33974a4d8c2SCharles.Forsyth {
34074a4d8c2SCharles.Forsyth 
34174a4d8c2SCharles.Forsyth 	if(a == b)
34274a4d8c2SCharles.Forsyth 		return 1;
34374a4d8c2SCharles.Forsyth 	switch(a) {
34474a4d8c2SCharles.Forsyth 	case C_LCON:
34574a4d8c2SCharles.Forsyth 		if(b == C_ZCON || b == C_SCON || b == C_UCON ||
34674a4d8c2SCharles.Forsyth 		   b == C_ADDCON || b == C_ANDCON)
34774a4d8c2SCharles.Forsyth 			return 1;
34874a4d8c2SCharles.Forsyth 		break;
34974a4d8c2SCharles.Forsyth 	case C_ADD0CON:
35074a4d8c2SCharles.Forsyth 		if(b == C_ADDCON)
35174a4d8c2SCharles.Forsyth 			return 1;
35274a4d8c2SCharles.Forsyth 	case C_ADDCON:
35374a4d8c2SCharles.Forsyth 		if(b == C_ZCON || b == C_SCON)
35474a4d8c2SCharles.Forsyth 			return 1;
35574a4d8c2SCharles.Forsyth 		break;
35674a4d8c2SCharles.Forsyth 	case C_AND0CON:
35774a4d8c2SCharles.Forsyth 		if(b == C_ANDCON)
35874a4d8c2SCharles.Forsyth 			return 1;
35974a4d8c2SCharles.Forsyth 	case C_ANDCON:
36074a4d8c2SCharles.Forsyth 		if(b == C_ZCON || b == C_SCON)
36174a4d8c2SCharles.Forsyth 			return 1;
36274a4d8c2SCharles.Forsyth 		break;
36374a4d8c2SCharles.Forsyth 	case C_UCON:
36474a4d8c2SCharles.Forsyth 		if(b == C_ZCON)
36574a4d8c2SCharles.Forsyth 			return 1;
36674a4d8c2SCharles.Forsyth 		break;
36774a4d8c2SCharles.Forsyth 	case C_SCON:
36874a4d8c2SCharles.Forsyth 		if(b == C_ZCON)
36974a4d8c2SCharles.Forsyth 			return 1;
37074a4d8c2SCharles.Forsyth 		break;
37174a4d8c2SCharles.Forsyth 	case C_LACON:
37274a4d8c2SCharles.Forsyth 		if(b == C_SACON)
37374a4d8c2SCharles.Forsyth 			return 1;
37474a4d8c2SCharles.Forsyth 		break;
37574a4d8c2SCharles.Forsyth 	case C_LBRA:
37674a4d8c2SCharles.Forsyth 		if(b == C_SBRA)
37774a4d8c2SCharles.Forsyth 			return 1;
37874a4d8c2SCharles.Forsyth 		break;
37974a4d8c2SCharles.Forsyth 	case C_LEXT:
38074a4d8c2SCharles.Forsyth 		if(b == C_SEXT)
38174a4d8c2SCharles.Forsyth 			return 1;
38274a4d8c2SCharles.Forsyth 		break;
38374a4d8c2SCharles.Forsyth 	case C_LAUTO:
38474a4d8c2SCharles.Forsyth 		if(b == C_SAUTO)
38574a4d8c2SCharles.Forsyth 			return 1;
38674a4d8c2SCharles.Forsyth 		break;
38774a4d8c2SCharles.Forsyth 	case C_REG:
38874a4d8c2SCharles.Forsyth 		if(b == C_ZCON)
38974a4d8c2SCharles.Forsyth 			return 1;
39074a4d8c2SCharles.Forsyth 		break;
39174a4d8c2SCharles.Forsyth 	case C_LOREG:
39274a4d8c2SCharles.Forsyth 		if(b == C_ZOREG || b == C_SOREG)
39374a4d8c2SCharles.Forsyth 			return 1;
39474a4d8c2SCharles.Forsyth 		break;
39574a4d8c2SCharles.Forsyth 	case C_SOREG:
39674a4d8c2SCharles.Forsyth 		if(b == C_ZOREG)
39774a4d8c2SCharles.Forsyth 			return 1;
39874a4d8c2SCharles.Forsyth 		break;
39974a4d8c2SCharles.Forsyth 	}
40074a4d8c2SCharles.Forsyth 	return 0;
40174a4d8c2SCharles.Forsyth }
40274a4d8c2SCharles.Forsyth 
40374a4d8c2SCharles.Forsyth int
ocmp(void * a1,void * a2)404*45a20ab7Sforsyth ocmp(void *a1, void *a2)
40574a4d8c2SCharles.Forsyth {
40674a4d8c2SCharles.Forsyth 	Optab *p1, *p2;
40774a4d8c2SCharles.Forsyth 	int n;
40874a4d8c2SCharles.Forsyth 
40974a4d8c2SCharles.Forsyth 	p1 = (Optab*)a1;
41074a4d8c2SCharles.Forsyth 	p2 = (Optab*)a2;
41174a4d8c2SCharles.Forsyth 	n = p1->as - p2->as;
41274a4d8c2SCharles.Forsyth 	if(n)
41374a4d8c2SCharles.Forsyth 		return n;
41474a4d8c2SCharles.Forsyth 	n = p1->a1 - p2->a1;
41574a4d8c2SCharles.Forsyth 	if(n)
41674a4d8c2SCharles.Forsyth 		return n;
41774a4d8c2SCharles.Forsyth 	n = p1->a2 - p2->a2;
41874a4d8c2SCharles.Forsyth 	if(n)
41974a4d8c2SCharles.Forsyth 		return n;
42074a4d8c2SCharles.Forsyth 	n = p1->a3 - p2->a3;
42174a4d8c2SCharles.Forsyth 	if(n)
42274a4d8c2SCharles.Forsyth 		return n;
42374a4d8c2SCharles.Forsyth 	return 0;
42474a4d8c2SCharles.Forsyth }
42574a4d8c2SCharles.Forsyth 
42674a4d8c2SCharles.Forsyth void
buildop(void)42774a4d8c2SCharles.Forsyth buildop(void)
42874a4d8c2SCharles.Forsyth {
42974a4d8c2SCharles.Forsyth 	int i, n, r;
43074a4d8c2SCharles.Forsyth 
43174a4d8c2SCharles.Forsyth 	for(i=0; i<32; i++)
43274a4d8c2SCharles.Forsyth 		for(n=0; n<32; n++)
43374a4d8c2SCharles.Forsyth 			xcmp[i][n] = cmp(n, i);
43474a4d8c2SCharles.Forsyth 	for(n=0; optab[n].as != AXXX; n++)
43574a4d8c2SCharles.Forsyth 		;
43674a4d8c2SCharles.Forsyth 	qsort(optab, n, sizeof(optab[0]), ocmp);
43774a4d8c2SCharles.Forsyth 	for(i=0; i<n; i++) {
43874a4d8c2SCharles.Forsyth 		r = optab[i].as;
43974a4d8c2SCharles.Forsyth 		oprange[r].start = optab+i;
44074a4d8c2SCharles.Forsyth 		while(optab[i].as == r)
44174a4d8c2SCharles.Forsyth 			i++;
44274a4d8c2SCharles.Forsyth 		oprange[r].stop = optab+i;
44374a4d8c2SCharles.Forsyth 		i--;
44474a4d8c2SCharles.Forsyth 
44574a4d8c2SCharles.Forsyth 		switch(r)
44674a4d8c2SCharles.Forsyth 		{
44774a4d8c2SCharles.Forsyth 		default:
44874a4d8c2SCharles.Forsyth 			diag("unknown op in build: %A\n", r);
44974a4d8c2SCharles.Forsyth 			errorexit();
45074a4d8c2SCharles.Forsyth 		case AABSF:
45174a4d8c2SCharles.Forsyth 			oprange[AMOVFD] = oprange[r];
45274a4d8c2SCharles.Forsyth 			oprange[AMOVDF] = oprange[r];
45374a4d8c2SCharles.Forsyth 			oprange[AMOVWF] = oprange[r];
45474a4d8c2SCharles.Forsyth 			oprange[AMOVFW] = oprange[r];
45574a4d8c2SCharles.Forsyth 			oprange[AMOVWD] = oprange[r];
45674a4d8c2SCharles.Forsyth 			oprange[AMOVDW] = oprange[r];
45774a4d8c2SCharles.Forsyth 			oprange[ANEGF] = oprange[r];
45874a4d8c2SCharles.Forsyth 			oprange[ANEGD] = oprange[r];
45974a4d8c2SCharles.Forsyth 			oprange[AABSD] = oprange[r];
46074a4d8c2SCharles.Forsyth 			oprange[ATRUNCDW] = oprange[r];
46174a4d8c2SCharles.Forsyth 			oprange[ATRUNCFW] = oprange[r];
46274a4d8c2SCharles.Forsyth 			oprange[ATRUNCDV] = oprange[r];
46374a4d8c2SCharles.Forsyth 			oprange[ATRUNCFV] = oprange[r];
46474a4d8c2SCharles.Forsyth 			oprange[AMOVDV] = oprange[r];
46574a4d8c2SCharles.Forsyth 			oprange[AMOVFV] = oprange[r];
46674a4d8c2SCharles.Forsyth 			oprange[AMOVVD] = oprange[r];
46774a4d8c2SCharles.Forsyth 			oprange[AMOVVF] = oprange[r];
46874a4d8c2SCharles.Forsyth 			break;
46974a4d8c2SCharles.Forsyth 		case AADD:
47074a4d8c2SCharles.Forsyth 			buildrep(1, AADD);
47174a4d8c2SCharles.Forsyth 			oprange[ASGT] = oprange[r];
47274a4d8c2SCharles.Forsyth 			repop[ASGT] = 1;
47374a4d8c2SCharles.Forsyth 			oprange[ASGTU] = oprange[r];
47474a4d8c2SCharles.Forsyth 			repop[ASGTU] = 1;
47574a4d8c2SCharles.Forsyth 			oprange[AADDU] = oprange[r];
47674a4d8c2SCharles.Forsyth 			repop[AADDU] = 1;
47774a4d8c2SCharles.Forsyth 			oprange[AADDVU] = oprange[r];
47874a4d8c2SCharles.Forsyth 			repop[AADDVU] = 1;
47974a4d8c2SCharles.Forsyth 			oprange[AADDV] = oprange[r];
48074a4d8c2SCharles.Forsyth 			repop[AADDV] = 1;
48174a4d8c2SCharles.Forsyth 			break;
48274a4d8c2SCharles.Forsyth 		case AADDF:
48374a4d8c2SCharles.Forsyth 			oprange[ADIVF] = oprange[r];
48474a4d8c2SCharles.Forsyth 			oprange[ADIVD] = oprange[r];
48574a4d8c2SCharles.Forsyth 			oprange[AMULF] = oprange[r];
48674a4d8c2SCharles.Forsyth 			oprange[AMULD] = oprange[r];
48774a4d8c2SCharles.Forsyth 			oprange[ASUBF] = oprange[r];
48874a4d8c2SCharles.Forsyth 			oprange[ASUBD] = oprange[r];
48974a4d8c2SCharles.Forsyth 			oprange[AADDD] = oprange[r];
49074a4d8c2SCharles.Forsyth 			break;
49174a4d8c2SCharles.Forsyth 		case AAND:
49274a4d8c2SCharles.Forsyth 			buildrep(2, AAND);
49374a4d8c2SCharles.Forsyth 			oprange[AXOR] = oprange[r];
49474a4d8c2SCharles.Forsyth 			repop[AXOR] = 2;
49574a4d8c2SCharles.Forsyth 			oprange[AOR] = oprange[r];
49674a4d8c2SCharles.Forsyth 			repop[AOR] = 2;
49774a4d8c2SCharles.Forsyth 			break;
49874a4d8c2SCharles.Forsyth 		case ABEQ:
49974a4d8c2SCharles.Forsyth 			oprange[ABNE] = oprange[r];
50074a4d8c2SCharles.Forsyth 			break;
50174a4d8c2SCharles.Forsyth 		case ABLEZ:
50274a4d8c2SCharles.Forsyth 			oprange[ABGEZ] = oprange[r];
50374a4d8c2SCharles.Forsyth 			oprange[ABGEZAL] = oprange[r];
50474a4d8c2SCharles.Forsyth 			oprange[ABLTZ] = oprange[r];
50574a4d8c2SCharles.Forsyth 			oprange[ABLTZAL] = oprange[r];
50674a4d8c2SCharles.Forsyth 			oprange[ABGTZ] = oprange[r];
50774a4d8c2SCharles.Forsyth 			break;
50874a4d8c2SCharles.Forsyth 		case AMOVB:
50974a4d8c2SCharles.Forsyth 			buildrep(3, AMOVB);
51074a4d8c2SCharles.Forsyth 			oprange[AMOVH] = oprange[r];
51174a4d8c2SCharles.Forsyth 			repop[AMOVH] = 3;
51274a4d8c2SCharles.Forsyth 			break;
51374a4d8c2SCharles.Forsyth 		case AMOVBU:
51474a4d8c2SCharles.Forsyth 			buildrep(4, AMOVBU);
51574a4d8c2SCharles.Forsyth 			oprange[AMOVHU] = oprange[r];
51674a4d8c2SCharles.Forsyth 			repop[AMOVHU] = 4;
51774a4d8c2SCharles.Forsyth 			break;
51874a4d8c2SCharles.Forsyth 		case AMUL:
51974a4d8c2SCharles.Forsyth 			oprange[AREM] = oprange[r];
52074a4d8c2SCharles.Forsyth 			oprange[AREMU] = oprange[r];
52174a4d8c2SCharles.Forsyth 			oprange[ADIVU] = oprange[r];
52274a4d8c2SCharles.Forsyth 			oprange[AMULU] = oprange[r];
52374a4d8c2SCharles.Forsyth 			oprange[ADIV] = oprange[r];
52474a4d8c2SCharles.Forsyth 			oprange[ADIVV] = oprange[r];
52574a4d8c2SCharles.Forsyth 			oprange[ADIVVU] = oprange[r];
52674a4d8c2SCharles.Forsyth 			oprange[AMULV] = oprange[r];
52774a4d8c2SCharles.Forsyth 			oprange[AMULVU] = oprange[r];
52874a4d8c2SCharles.Forsyth 			oprange[AREMV] = oprange[r];
52974a4d8c2SCharles.Forsyth 			oprange[AREMVU] = oprange[r];
53074a4d8c2SCharles.Forsyth 			break;
53174a4d8c2SCharles.Forsyth 		case ASLL:
53274a4d8c2SCharles.Forsyth 			oprange[ASRL] = oprange[r];
53374a4d8c2SCharles.Forsyth 			oprange[ASRA] = oprange[r];
53474a4d8c2SCharles.Forsyth 			oprange[ASLLV] = oprange[r];
53574a4d8c2SCharles.Forsyth 			oprange[ASRAV] = oprange[r];
53674a4d8c2SCharles.Forsyth 			oprange[ASRLV] = oprange[r];
53774a4d8c2SCharles.Forsyth 			break;
53874a4d8c2SCharles.Forsyth 		case ASUB:
53974a4d8c2SCharles.Forsyth 			oprange[ASUBU] = oprange[r];
54074a4d8c2SCharles.Forsyth 			oprange[ASUBV] = oprange[r];
54174a4d8c2SCharles.Forsyth 			oprange[ASUBVU] = oprange[r];
54274a4d8c2SCharles.Forsyth 			oprange[ANOR] = oprange[r];
54374a4d8c2SCharles.Forsyth 			break;
54474a4d8c2SCharles.Forsyth 		case ASYSCALL:
54574a4d8c2SCharles.Forsyth 			oprange[ATLBP] = oprange[r];
54674a4d8c2SCharles.Forsyth 			oprange[ATLBR] = oprange[r];
54774a4d8c2SCharles.Forsyth 			oprange[ATLBWI] = oprange[r];
54874a4d8c2SCharles.Forsyth 			oprange[ATLBWR] = oprange[r];
54974a4d8c2SCharles.Forsyth 			break;
55074a4d8c2SCharles.Forsyth 		case ACMPEQF:
55174a4d8c2SCharles.Forsyth 			oprange[ACMPGTF] = oprange[r];
55274a4d8c2SCharles.Forsyth 			oprange[ACMPGTD] = oprange[r];
55374a4d8c2SCharles.Forsyth 			oprange[ACMPGEF] = oprange[r];
55474a4d8c2SCharles.Forsyth 			oprange[ACMPGED] = oprange[r];
55574a4d8c2SCharles.Forsyth 			oprange[ACMPEQD] = oprange[r];
55674a4d8c2SCharles.Forsyth 			break;
55774a4d8c2SCharles.Forsyth 		case ABFPT:
55874a4d8c2SCharles.Forsyth 			oprange[ABFPF] = oprange[r];
55974a4d8c2SCharles.Forsyth 			break;
56074a4d8c2SCharles.Forsyth 		case AMOVWL:
56174a4d8c2SCharles.Forsyth 			oprange[AMOVWR] = oprange[r];
56274a4d8c2SCharles.Forsyth 			oprange[AMOVVR] = oprange[r];
56374a4d8c2SCharles.Forsyth 			oprange[AMOVVL] = oprange[r];
56474a4d8c2SCharles.Forsyth 			break;
56574a4d8c2SCharles.Forsyth 		case AMOVW:
56674a4d8c2SCharles.Forsyth 			buildrep(5, AMOVW);
56774a4d8c2SCharles.Forsyth 			break;
56874a4d8c2SCharles.Forsyth 		case AMOVD:
56974a4d8c2SCharles.Forsyth 			buildrep(6, AMOVD);
57074a4d8c2SCharles.Forsyth 			break;
57174a4d8c2SCharles.Forsyth 		case AMOVF:
57274a4d8c2SCharles.Forsyth 			buildrep(7, AMOVF);
57374a4d8c2SCharles.Forsyth 			break;
57474a4d8c2SCharles.Forsyth 		case AMOVV:
57574a4d8c2SCharles.Forsyth 			buildrep(8, AMOVV);
57674a4d8c2SCharles.Forsyth 			break;
57774a4d8c2SCharles.Forsyth 		case ABREAK:
57874a4d8c2SCharles.Forsyth 		case AWORD:
57974a4d8c2SCharles.Forsyth 		case ARFE:
58074a4d8c2SCharles.Forsyth 		case AJAL:
58174a4d8c2SCharles.Forsyth 		case AJMP:
58274a4d8c2SCharles.Forsyth 		case ATEXT:
58374a4d8c2SCharles.Forsyth 		case ACASE:
58474a4d8c2SCharles.Forsyth 		case ABCASE:
58574a4d8c2SCharles.Forsyth 		case AMOVWU:
58674a4d8c2SCharles.Forsyth 			break;
58774a4d8c2SCharles.Forsyth 		}
58874a4d8c2SCharles.Forsyth 	}
58974a4d8c2SCharles.Forsyth }
59074a4d8c2SCharles.Forsyth 
59174a4d8c2SCharles.Forsyth void
buildrep(int x,int as)59274a4d8c2SCharles.Forsyth buildrep(int x, int as)
59374a4d8c2SCharles.Forsyth {
59474a4d8c2SCharles.Forsyth 	Opcross *p;
59574a4d8c2SCharles.Forsyth 	Optab *e, *s, *o;
59674a4d8c2SCharles.Forsyth 	int a1, a2, a3, n;
59774a4d8c2SCharles.Forsyth 
59874a4d8c2SCharles.Forsyth 	if(C_NONE != 0 ||
59974a4d8c2SCharles.Forsyth 	   C_REG != 1 ||
60074a4d8c2SCharles.Forsyth 	   C_GOK >= 32 ||
60174a4d8c2SCharles.Forsyth 	   x >= nelem(opcross)) {
60274a4d8c2SCharles.Forsyth 		diag("assumptions fail in buildrep");
60374a4d8c2SCharles.Forsyth 		errorexit();
60474a4d8c2SCharles.Forsyth 	}
60574a4d8c2SCharles.Forsyth 	repop[as] = x;
60674a4d8c2SCharles.Forsyth 	p = (opcross + x);
60774a4d8c2SCharles.Forsyth 	s = oprange[as].start;
60874a4d8c2SCharles.Forsyth 	e = oprange[as].stop;
60974a4d8c2SCharles.Forsyth 	for(o=e-1; o>=s; o--) {
61074a4d8c2SCharles.Forsyth 		n = o-optab;
61174a4d8c2SCharles.Forsyth 		for(a2=0; a2<2; a2++) {
61274a4d8c2SCharles.Forsyth 			if(a2) {
61374a4d8c2SCharles.Forsyth 				if(o->a2 == C_NONE)
61474a4d8c2SCharles.Forsyth 					continue;
61574a4d8c2SCharles.Forsyth 			} else
61674a4d8c2SCharles.Forsyth 				if(o->a2 != C_NONE)
61774a4d8c2SCharles.Forsyth 					continue;
61874a4d8c2SCharles.Forsyth 			for(a1=0; a1<32; a1++) {
61974a4d8c2SCharles.Forsyth 				if(!xcmp[a1][o->a1])
62074a4d8c2SCharles.Forsyth 					continue;
62174a4d8c2SCharles.Forsyth 				for(a3=0; a3<32; a3++)
62274a4d8c2SCharles.Forsyth 					if(xcmp[a3][o->a3])
62374a4d8c2SCharles.Forsyth 						(*p)[a1][a2][a3] = n;
62474a4d8c2SCharles.Forsyth 			}
62574a4d8c2SCharles.Forsyth 		}
62674a4d8c2SCharles.Forsyth 	}
62774a4d8c2SCharles.Forsyth 	oprange[as].start = 0;
62874a4d8c2SCharles.Forsyth }
629