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