xref: /plan9/sys/src/cmd/5l/span.c (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
17dd7cddfSDavid du Colombier #include	"l.h"
27dd7cddfSDavid du Colombier 
37dd7cddfSDavid du Colombier static struct {
47dd7cddfSDavid du Colombier 	ulong	start;
57dd7cddfSDavid du Colombier 	ulong	size;
67dd7cddfSDavid du Colombier } pool;
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier void	checkpool(Prog*);
97dd7cddfSDavid du Colombier void 	flushpool(Prog*, int);
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier void
span(void)127dd7cddfSDavid du Colombier span(void)
137dd7cddfSDavid du Colombier {
147dd7cddfSDavid du Colombier 	Prog *p;
159a747e4fSDavid du Colombier 	Sym *setext, *s;
167dd7cddfSDavid du Colombier 	Optab *o;
179a747e4fSDavid du Colombier 	int m, bflag, i;
189a747e4fSDavid du Colombier 	long c, otxt, v;
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier 	if(debug['v'])
217dd7cddfSDavid du Colombier 		Bprint(&bso, "%5.2f span\n", cputime());
227dd7cddfSDavid du Colombier 	Bflush(&bso);
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier 	bflag = 0;
257dd7cddfSDavid du Colombier 	c = INITTEXT;
267dd7cddfSDavid du Colombier 	otxt = c;
277dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
287dd7cddfSDavid du Colombier 		p->pc = c;
297dd7cddfSDavid du Colombier 		o = oplook(p);
307dd7cddfSDavid du Colombier 		m = o->size;
317dd7cddfSDavid du Colombier 		if(m == 0) {
327dd7cddfSDavid du Colombier 			if(p->as == ATEXT) {
337dd7cddfSDavid du Colombier 				curtext = p;
347dd7cddfSDavid du Colombier 				autosize = p->to.offset + 4;
357dd7cddfSDavid du Colombier 				if(p->from.sym != S)
367dd7cddfSDavid du Colombier 					p->from.sym->value = c;
377dd7cddfSDavid du Colombier 				/* need passes to resolve branches */
387dd7cddfSDavid du Colombier 				if(c-otxt >= 1L<<17)
397dd7cddfSDavid du Colombier 					bflag = 1;
407dd7cddfSDavid du Colombier 				otxt = c;
417dd7cddfSDavid du Colombier 				continue;
427dd7cddfSDavid du Colombier 			}
436b6b9ac8SDavid du Colombier 			diag("zero-width instruction\n%P", p);
447dd7cddfSDavid du Colombier 			continue;
457dd7cddfSDavid du Colombier 		}
4659cc4ca5SDavid du Colombier 		switch(o->flag & (LFROM|LTO|LPOOL)) {
477dd7cddfSDavid du Colombier 		case LFROM:
487dd7cddfSDavid du Colombier 			addpool(p, &p->from);
497dd7cddfSDavid du Colombier 			break;
507dd7cddfSDavid du Colombier 		case LTO:
517dd7cddfSDavid du Colombier 			addpool(p, &p->to);
527dd7cddfSDavid du Colombier 			break;
537dd7cddfSDavid du Colombier 		case LPOOL:
5459cc4ca5SDavid du Colombier 			if ((p->scond&C_SCOND) == 14)
557dd7cddfSDavid du Colombier 				flushpool(p, 0);
567dd7cddfSDavid du Colombier 			break;
577dd7cddfSDavid du Colombier 		}
5859cc4ca5SDavid du Colombier 		if(p->as==AMOVW && p->to.type==D_REG && p->to.reg==REGPC && (p->scond&C_SCOND) == 14)
5959cc4ca5SDavid du Colombier 			flushpool(p, 0);
607dd7cddfSDavid du Colombier 		c += m;
617dd7cddfSDavid du Colombier 		if(blitrl)
627dd7cddfSDavid du Colombier 			checkpool(p);
637dd7cddfSDavid du Colombier 	}
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier 	/*
667dd7cddfSDavid du Colombier 	 * if any procedure is large enough to
677dd7cddfSDavid du Colombier 	 * generate a large SBRA branch, then
687dd7cddfSDavid du Colombier 	 * generate extra passes putting branches
697dd7cddfSDavid du Colombier 	 * around jmps to fix. this is rare.
707dd7cddfSDavid du Colombier 	 */
717dd7cddfSDavid du Colombier 	while(bflag) {
727dd7cddfSDavid du Colombier 		if(debug['v'])
737dd7cddfSDavid du Colombier 			Bprint(&bso, "%5.2f span1\n", cputime());
747dd7cddfSDavid du Colombier 		bflag = 0;
757dd7cddfSDavid du Colombier 		c = INITTEXT;
767dd7cddfSDavid du Colombier 		for(p = firstp; p != P; p = p->link) {
777dd7cddfSDavid du Colombier 			p->pc = c;
787dd7cddfSDavid du Colombier 			o = oplook(p);
797dd7cddfSDavid du Colombier /* very larg branches
807dd7cddfSDavid du Colombier 			if(o->type == 6 && p->cond) {
817dd7cddfSDavid du Colombier 				otxt = p->cond->pc - c;
827dd7cddfSDavid du Colombier 				if(otxt < 0)
837dd7cddfSDavid du Colombier 					otxt = -otxt;
847dd7cddfSDavid du Colombier 				if(otxt >= (1L<<17) - 10) {
857dd7cddfSDavid du Colombier 					q = prg();
867dd7cddfSDavid du Colombier 					q->link = p->link;
877dd7cddfSDavid du Colombier 					p->link = q;
887dd7cddfSDavid du Colombier 					q->as = AB;
897dd7cddfSDavid du Colombier 					q->to.type = D_BRANCH;
907dd7cddfSDavid du Colombier 					q->cond = p->cond;
917dd7cddfSDavid du Colombier 					p->cond = q;
927dd7cddfSDavid du Colombier 					q = prg();
937dd7cddfSDavid du Colombier 					q->link = p->link;
947dd7cddfSDavid du Colombier 					p->link = q;
957dd7cddfSDavid du Colombier 					q->as = AB;
967dd7cddfSDavid du Colombier 					q->to.type = D_BRANCH;
977dd7cddfSDavid du Colombier 					q->cond = q->link->link;
987dd7cddfSDavid du Colombier 					bflag = 1;
997dd7cddfSDavid du Colombier 				}
1007dd7cddfSDavid du Colombier 			}
1017dd7cddfSDavid du Colombier  */
1027dd7cddfSDavid du Colombier 			m = o->size;
1037dd7cddfSDavid du Colombier 			if(m == 0) {
1047dd7cddfSDavid du Colombier 				if(p->as == ATEXT) {
1057dd7cddfSDavid du Colombier 					curtext = p;
1067dd7cddfSDavid du Colombier 					autosize = p->to.offset + 4;
1077dd7cddfSDavid du Colombier 					if(p->from.sym != S)
1087dd7cddfSDavid du Colombier 						p->from.sym->value = c;
1097dd7cddfSDavid du Colombier 					continue;
1107dd7cddfSDavid du Colombier 				}
1116b6b9ac8SDavid du Colombier 				diag("zero-width instruction\n%P", p);
1127dd7cddfSDavid du Colombier 				continue;
1137dd7cddfSDavid du Colombier 			}
1147dd7cddfSDavid du Colombier 			c += m;
1157dd7cddfSDavid du Colombier 		}
1167dd7cddfSDavid du Colombier 	}
1179a747e4fSDavid du Colombier 
1189a747e4fSDavid du Colombier 	if(debug['t']) {
1199a747e4fSDavid du Colombier 		/*
1209a747e4fSDavid du Colombier 		 * add strings to text segment
1219a747e4fSDavid du Colombier 		 */
1229a747e4fSDavid du Colombier 		c = rnd(c, 8);
1239a747e4fSDavid du Colombier 		for(i=0; i<NHASH; i++)
1249a747e4fSDavid du Colombier 		for(s = hash[i]; s != S; s = s->link) {
1259a747e4fSDavid du Colombier 			if(s->type != SSTRING)
1269a747e4fSDavid du Colombier 				continue;
1279a747e4fSDavid du Colombier 			v = s->value;
1289a747e4fSDavid du Colombier 			while(v & 3)
1299a747e4fSDavid du Colombier 				v++;
1309a747e4fSDavid du Colombier 			s->value = c;
1319a747e4fSDavid du Colombier 			c += v;
1329a747e4fSDavid du Colombier 		}
1339a747e4fSDavid du Colombier 	}
1349a747e4fSDavid du Colombier 
1357dd7cddfSDavid du Colombier 	c = rnd(c, 8);
1367dd7cddfSDavid du Colombier 
1377dd7cddfSDavid du Colombier 	setext = lookup("etext", 0);
1387dd7cddfSDavid du Colombier 	if(setext != S) {
1397dd7cddfSDavid du Colombier 		setext->value = c;
1407dd7cddfSDavid du Colombier 		textsize = c - INITTEXT;
1417dd7cddfSDavid du Colombier 	}
1427dd7cddfSDavid du Colombier 	if(INITRND)
1437dd7cddfSDavid du Colombier 		INITDAT = rnd(c, INITRND);
1447dd7cddfSDavid du Colombier 	if(debug['v'])
1457dd7cddfSDavid du Colombier 		Bprint(&bso, "tsize = %lux\n", textsize);
1467dd7cddfSDavid du Colombier 	Bflush(&bso);
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier /*
1507dd7cddfSDavid du Colombier  * when the first reference to the literal pool threatens
1517dd7cddfSDavid du Colombier  * to go out of range of a 12-bit PC-relative offset,
1527dd7cddfSDavid du Colombier  * drop the pool now, and branch round it.
1537dd7cddfSDavid du Colombier  * this happens only in extended basic blocks that exceed 4k.
1547dd7cddfSDavid du Colombier  */
1557dd7cddfSDavid du Colombier void
checkpool(Prog * p)1567dd7cddfSDavid du Colombier checkpool(Prog *p)
1577dd7cddfSDavid du Colombier {
1587dd7cddfSDavid du Colombier 	if(pool.size >= 0xffc || immaddr((p->pc+4)+4+pool.size - pool.start+8) == 0)
1597dd7cddfSDavid du Colombier 		flushpool(p, 1);
16059cc4ca5SDavid du Colombier 	else if(p->link == P)
16159cc4ca5SDavid du Colombier 		flushpool(p, 2);
1627dd7cddfSDavid du Colombier }
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier void
flushpool(Prog * p,int skip)1657dd7cddfSDavid du Colombier flushpool(Prog *p, int skip)
1667dd7cddfSDavid du Colombier {
1677dd7cddfSDavid du Colombier 	Prog *q;
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier 	if(blitrl) {
1707dd7cddfSDavid du Colombier 		if(skip){
1719a747e4fSDavid du Colombier 			if(debug['v'] && skip == 1)
1729a747e4fSDavid du Colombier 				print("note: flush literal pool at %lux: len=%lud ref=%lux\n", p->pc+4, pool.size, pool.start);
1737dd7cddfSDavid du Colombier 			q = prg();
1747dd7cddfSDavid du Colombier 			q->as = AB;
1757dd7cddfSDavid du Colombier 			q->to.type = D_BRANCH;
1767dd7cddfSDavid du Colombier 			q->cond = p->link;
1777dd7cddfSDavid du Colombier 			q->link = blitrl;
1787dd7cddfSDavid du Colombier 			blitrl = q;
1797dd7cddfSDavid du Colombier 		}
18059cc4ca5SDavid du Colombier 		else if(p->pc+pool.size-pool.start < 2048)
18159cc4ca5SDavid du Colombier 			return;
1827dd7cddfSDavid du Colombier 		elitrl->link = p->link;
1837dd7cddfSDavid du Colombier 		p->link = blitrl;
1847dd7cddfSDavid du Colombier 		blitrl = 0;	/* BUG: should refer back to values until out-of-range */
1857dd7cddfSDavid du Colombier 		elitrl = 0;
1867dd7cddfSDavid du Colombier 		pool.size = 0;
1877dd7cddfSDavid du Colombier 		pool.start = 0;
1887dd7cddfSDavid du Colombier 	}
1897dd7cddfSDavid du Colombier }
1907dd7cddfSDavid du Colombier 
1917dd7cddfSDavid du Colombier void
addpool(Prog * p,Adr * a)1927dd7cddfSDavid du Colombier addpool(Prog *p, Adr *a)
1937dd7cddfSDavid du Colombier {
1947dd7cddfSDavid du Colombier 	Prog *q, t;
1957dd7cddfSDavid du Colombier 	int c;
1967dd7cddfSDavid du Colombier 
1977dd7cddfSDavid du Colombier 	c = aclass(a);
1987dd7cddfSDavid du Colombier 
1997dd7cddfSDavid du Colombier 	t = zprg;
2007dd7cddfSDavid du Colombier 	t.as = AWORD;
2017dd7cddfSDavid du Colombier 
2027dd7cddfSDavid du Colombier 	switch(c) {
2037dd7cddfSDavid du Colombier 	default:
2047dd7cddfSDavid du Colombier 		t.to = *a;
2057dd7cddfSDavid du Colombier 		break;
20659cc4ca5SDavid du Colombier 
20759cc4ca5SDavid du Colombier 	case C_SROREG:
2087dd7cddfSDavid du Colombier 	case C_LOREG:
2097dd7cddfSDavid du Colombier 	case C_ROREG:
21059cc4ca5SDavid du Colombier 	case C_FOREG:
21159cc4ca5SDavid du Colombier 	case C_SOREG:
21259cc4ca5SDavid du Colombier 	case C_FAUTO:
21359cc4ca5SDavid du Colombier 	case C_SAUTO:
2147dd7cddfSDavid du Colombier 	case C_LAUTO:
2157dd7cddfSDavid du Colombier 	case C_LACON:
2167dd7cddfSDavid du Colombier 		t.to.type = D_CONST;
2177dd7cddfSDavid du Colombier 		t.to.offset = instoffset;
2187dd7cddfSDavid du Colombier 		break;
2197dd7cddfSDavid du Colombier 	}
2207dd7cddfSDavid du Colombier 
2217dd7cddfSDavid du Colombier 	for(q = blitrl; q != P; q = q->link)	/* could hash on t.t0.offset */
2227dd7cddfSDavid du Colombier 		if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) {
2237dd7cddfSDavid du Colombier 			p->cond = q;
2247dd7cddfSDavid du Colombier 			return;
2257dd7cddfSDavid du Colombier 		}
2267dd7cddfSDavid du Colombier 
2277dd7cddfSDavid du Colombier 	q = prg();
2287dd7cddfSDavid du Colombier 	*q = t;
2297dd7cddfSDavid du Colombier 	q->pc = pool.size;
2307dd7cddfSDavid du Colombier 
2317dd7cddfSDavid du Colombier 	if(blitrl == P) {
2327dd7cddfSDavid du Colombier 		blitrl = q;
2337dd7cddfSDavid du Colombier 		pool.start = p->pc;
2347dd7cddfSDavid du Colombier 	} else
2357dd7cddfSDavid du Colombier 		elitrl->link = q;
2367dd7cddfSDavid du Colombier 	elitrl = q;
2377dd7cddfSDavid du Colombier 	pool.size += 4;
2387dd7cddfSDavid du Colombier 
2397dd7cddfSDavid du Colombier 	p->cond = q;
2407dd7cddfSDavid du Colombier }
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier void
xdefine(char * p,int t,long v)2437dd7cddfSDavid du Colombier xdefine(char *p, int t, long v)
2447dd7cddfSDavid du Colombier {
2457dd7cddfSDavid du Colombier 	Sym *s;
2467dd7cddfSDavid du Colombier 
2477dd7cddfSDavid du Colombier 	s = lookup(p, 0);
2487dd7cddfSDavid du Colombier 	if(s->type == 0 || s->type == SXREF) {
2497dd7cddfSDavid du Colombier 		s->type = t;
2507dd7cddfSDavid du Colombier 		s->value = v;
2517dd7cddfSDavid du Colombier 	}
2527dd7cddfSDavid du Colombier }
2537dd7cddfSDavid du Colombier 
2547dd7cddfSDavid du Colombier long
regoff(Adr * a)2557dd7cddfSDavid du Colombier regoff(Adr *a)
2567dd7cddfSDavid du Colombier {
2577dd7cddfSDavid du Colombier 
2587dd7cddfSDavid du Colombier 	instoffset = 0;
2597dd7cddfSDavid du Colombier 	aclass(a);
2607dd7cddfSDavid du Colombier 	return instoffset;
2617dd7cddfSDavid du Colombier }
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier long
immrot(ulong v)2647dd7cddfSDavid du Colombier immrot(ulong v)
2657dd7cddfSDavid du Colombier {
2667dd7cddfSDavid du Colombier 	int i;
2677dd7cddfSDavid du Colombier 
2687dd7cddfSDavid du Colombier 	for(i=0; i<16; i++) {
2697dd7cddfSDavid du Colombier 		if((v & ~0xff) == 0)
2707dd7cddfSDavid du Colombier 			return (i<<8) | v | (1<<25);
2717dd7cddfSDavid du Colombier 		v = (v<<2) | (v>>30);
2727dd7cddfSDavid du Colombier 	}
2737dd7cddfSDavid du Colombier 	return 0;
2747dd7cddfSDavid du Colombier }
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier long
immaddr(long v)2777dd7cddfSDavid du Colombier immaddr(long v)
2787dd7cddfSDavid du Colombier {
2797dd7cddfSDavid du Colombier 	if(v >= 0 && v <= 0xfff)
2807dd7cddfSDavid du Colombier 		return (v & 0xfff) |
2817dd7cddfSDavid du Colombier 			(1<<24) |	/* pre indexing */
2827dd7cddfSDavid du Colombier 			(1<<23);	/* pre indexing, up */
2837dd7cddfSDavid du Colombier 	if(v >= -0xfff && v < 0)
2847dd7cddfSDavid du Colombier 		return (-v & 0xfff) |
2857dd7cddfSDavid du Colombier 			(1<<24);	/* pre indexing */
2867dd7cddfSDavid du Colombier 	return 0;
2877dd7cddfSDavid du Colombier }
2887dd7cddfSDavid du Colombier 
2897dd7cddfSDavid du Colombier int
immfloat(long v)2907dd7cddfSDavid du Colombier immfloat(long v)
2917dd7cddfSDavid du Colombier {
2927dd7cddfSDavid du Colombier 	return (v & 0xC03) == 0;	/* offset will fit in floating-point load/store */
2937dd7cddfSDavid du Colombier }
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier int
immhalf(long v)29659cc4ca5SDavid du Colombier immhalf(long v)
29759cc4ca5SDavid du Colombier {
29859cc4ca5SDavid du Colombier 	if(v >= 0 && v <= 0xff)
29959cc4ca5SDavid du Colombier 		return v|
30059cc4ca5SDavid du Colombier 			(1<<24)|	/* pre indexing */
30159cc4ca5SDavid du Colombier 			(1<<23);	/* pre indexing, up */
30259cc4ca5SDavid du Colombier 	if(v >= -0xff && v < 0)
30359cc4ca5SDavid du Colombier 		return (-v & 0xff)|
30459cc4ca5SDavid du Colombier 			(1<<24);	/* pre indexing */
30559cc4ca5SDavid du Colombier 	return 0;
30659cc4ca5SDavid du Colombier }
30759cc4ca5SDavid du Colombier 
30859cc4ca5SDavid du Colombier int
aclass(Adr * a)3097dd7cddfSDavid du Colombier aclass(Adr *a)
3107dd7cddfSDavid du Colombier {
3117dd7cddfSDavid du Colombier 	Sym *s;
3127dd7cddfSDavid du Colombier 	int t;
3137dd7cddfSDavid du Colombier 
3147dd7cddfSDavid du Colombier 	switch(a->type) {
3157dd7cddfSDavid du Colombier 	case D_NONE:
3167dd7cddfSDavid du Colombier 		return C_NONE;
3177dd7cddfSDavid du Colombier 
3187dd7cddfSDavid du Colombier 	case D_REG:
3197dd7cddfSDavid du Colombier 		return C_REG;
3207dd7cddfSDavid du Colombier 
32159cc4ca5SDavid du Colombier 	case D_REGREG:
32259cc4ca5SDavid du Colombier 		return C_REGREG;
32359cc4ca5SDavid du Colombier 
3247dd7cddfSDavid du Colombier 	case D_SHIFT:
3257dd7cddfSDavid du Colombier 		return C_SHIFT;
3267dd7cddfSDavid du Colombier 
3277dd7cddfSDavid du Colombier 	case D_FREG:
3287dd7cddfSDavid du Colombier 		return C_FREG;
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier 	case D_FPCR:
3317dd7cddfSDavid du Colombier 		return C_FCR;
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier 	case D_OREG:
3347dd7cddfSDavid du Colombier 		switch(a->name) {
3357dd7cddfSDavid du Colombier 		case D_EXTERN:
3367dd7cddfSDavid du Colombier 		case D_STATIC:
3377dd7cddfSDavid du Colombier 			if(a->sym == 0 || a->sym->name == 0) {
3387dd7cddfSDavid du Colombier 				print("null sym external\n");
3397dd7cddfSDavid du Colombier 				print("%D\n", a);
3407dd7cddfSDavid du Colombier 				return C_GOK;
3417dd7cddfSDavid du Colombier 			}
3429a747e4fSDavid du Colombier 			s = a->sym;
3439a747e4fSDavid du Colombier 			t = s->type;
3447dd7cddfSDavid du Colombier 			if(t == 0 || t == SXREF) {
3456b6b9ac8SDavid du Colombier 				diag("undefined external: %s in %s",
3469a747e4fSDavid du Colombier 					s->name, TNAME);
3479a747e4fSDavid du Colombier 				s->type = SDATA;
3487dd7cddfSDavid du Colombier 			}
349375daca8SDavid du Colombier 			if(dlm) {
3509a747e4fSDavid du Colombier 				switch(t) {
3519a747e4fSDavid du Colombier 				default:
3529a747e4fSDavid du Colombier 					instoffset = s->value + a->offset + INITDAT;
3539a747e4fSDavid du Colombier 					break;
354375daca8SDavid du Colombier 				case SUNDEF:
3559a747e4fSDavid du Colombier 				case STEXT:
3569a747e4fSDavid du Colombier 				case SCONST:
3579a747e4fSDavid du Colombier 				case SLEAF:
3589a747e4fSDavid du Colombier 				case SSTRING:
3599a747e4fSDavid du Colombier 					instoffset = s->value + a->offset;
3609a747e4fSDavid du Colombier 					break;
3619a747e4fSDavid du Colombier 				}
3629a747e4fSDavid du Colombier 				return C_ADDR;
3639a747e4fSDavid du Colombier 			}
3649a747e4fSDavid du Colombier 			instoffset = s->value + a->offset - BIG;
3657dd7cddfSDavid du Colombier 			t = immaddr(instoffset);
3667dd7cddfSDavid du Colombier 			if(t) {
36759cc4ca5SDavid du Colombier 				if(immhalf(instoffset))
36859cc4ca5SDavid du Colombier 					return immfloat(t) ? C_HFEXT : C_HEXT;
3697dd7cddfSDavid du Colombier 				if(immfloat(t))
3707dd7cddfSDavid du Colombier 					return C_FEXT;
3717dd7cddfSDavid du Colombier 				return C_SEXT;
3727dd7cddfSDavid du Colombier 			}
3737dd7cddfSDavid du Colombier 			return C_LEXT;
3747dd7cddfSDavid du Colombier 		case D_AUTO:
3757dd7cddfSDavid du Colombier 			instoffset = autosize + a->offset;
3767dd7cddfSDavid du Colombier 			t = immaddr(instoffset);
3777dd7cddfSDavid du Colombier 			if(t){
37859cc4ca5SDavid du Colombier 				if(immhalf(instoffset))
37959cc4ca5SDavid du Colombier 					return immfloat(t) ? C_HFAUTO : C_HAUTO;
3807dd7cddfSDavid du Colombier 				if(immfloat(t))
3817dd7cddfSDavid du Colombier 					return C_FAUTO;
3827dd7cddfSDavid du Colombier 				return C_SAUTO;
3837dd7cddfSDavid du Colombier 			}
3847dd7cddfSDavid du Colombier 			return C_LAUTO;
3857dd7cddfSDavid du Colombier 
3867dd7cddfSDavid du Colombier 		case D_PARAM:
3877dd7cddfSDavid du Colombier 			instoffset = autosize + a->offset + 4L;
3887dd7cddfSDavid du Colombier 			t = immaddr(instoffset);
3897dd7cddfSDavid du Colombier 			if(t){
39059cc4ca5SDavid du Colombier 				if(immhalf(instoffset))
39159cc4ca5SDavid du Colombier 					return immfloat(t) ? C_HFAUTO : C_HAUTO;
3927dd7cddfSDavid du Colombier 				if(immfloat(t))
3937dd7cddfSDavid du Colombier 					return C_FAUTO;
3947dd7cddfSDavid du Colombier 				return C_SAUTO;
3957dd7cddfSDavid du Colombier 			}
3967dd7cddfSDavid du Colombier 			return C_LAUTO;
3977dd7cddfSDavid du Colombier 		case D_NONE:
3987dd7cddfSDavid du Colombier 			instoffset = a->offset;
3997dd7cddfSDavid du Colombier 			t = immaddr(instoffset);
4007dd7cddfSDavid du Colombier 			if(t) {
40159cc4ca5SDavid du Colombier 				if(immhalf(instoffset))		 /* n.b. that it will also satisfy immrot */
40259cc4ca5SDavid du Colombier 					return immfloat(t) ? C_HFOREG : C_HOREG;
4037dd7cddfSDavid du Colombier 				if(immfloat(t))
4047dd7cddfSDavid du Colombier 					return C_FOREG; /* n.b. that it will also satisfy immrot */
4057dd7cddfSDavid du Colombier 				t = immrot(instoffset);
4067dd7cddfSDavid du Colombier 				if(t)
40759cc4ca5SDavid du Colombier 					return C_SROREG;
40859cc4ca5SDavid du Colombier 				if(immhalf(instoffset))
40959cc4ca5SDavid du Colombier 					return C_HOREG;
4107dd7cddfSDavid du Colombier 				return C_SOREG;
4117dd7cddfSDavid du Colombier 			}
4127dd7cddfSDavid du Colombier 			t = immrot(instoffset);
4137dd7cddfSDavid du Colombier 			if(t)
4147dd7cddfSDavid du Colombier 				return C_ROREG;
4157dd7cddfSDavid du Colombier 			return C_LOREG;
4167dd7cddfSDavid du Colombier 		}
4177dd7cddfSDavid du Colombier 		return C_GOK;
4187dd7cddfSDavid du Colombier 
4197dd7cddfSDavid du Colombier 	case D_PSR:
4207dd7cddfSDavid du Colombier 		return C_PSR;
4217dd7cddfSDavid du Colombier 
4227dd7cddfSDavid du Colombier 	case D_OCONST:
4237dd7cddfSDavid du Colombier 		switch(a->name) {
4247dd7cddfSDavid du Colombier 		case D_EXTERN:
4257dd7cddfSDavid du Colombier 		case D_STATIC:
4267dd7cddfSDavid du Colombier 			s = a->sym;
4277dd7cddfSDavid du Colombier 			t = s->type;
4287dd7cddfSDavid du Colombier 			if(t == 0 || t == SXREF) {
4296b6b9ac8SDavid du Colombier 				diag("undefined external: %s in %s",
4307dd7cddfSDavid du Colombier 					s->name, TNAME);
4317dd7cddfSDavid du Colombier 				s->type = SDATA;
4327dd7cddfSDavid du Colombier 			}
4337dd7cddfSDavid du Colombier 			instoffset = s->value + a->offset + INITDAT;
434375daca8SDavid du Colombier 			if(s->type == STEXT || s->type == SLEAF || s->type == SUNDEF)
4357dd7cddfSDavid du Colombier 				instoffset = s->value + a->offset;
4367dd7cddfSDavid du Colombier 			return C_LCON;
4377dd7cddfSDavid du Colombier 		}
4387dd7cddfSDavid du Colombier 		return C_GOK;
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier 	case D_FCONST:
4417dd7cddfSDavid du Colombier 		return C_FCON;
4427dd7cddfSDavid du Colombier 
4437dd7cddfSDavid du Colombier 	case D_CONST:
4447dd7cddfSDavid du Colombier 		switch(a->name) {
4457dd7cddfSDavid du Colombier 
4467dd7cddfSDavid du Colombier 		case D_NONE:
4477dd7cddfSDavid du Colombier 			instoffset = a->offset;
4487dd7cddfSDavid du Colombier 			if(a->reg != NREG)
4497dd7cddfSDavid du Colombier 				goto aconsize;
4507dd7cddfSDavid du Colombier 
4517dd7cddfSDavid du Colombier 			t = immrot(instoffset);
4527dd7cddfSDavid du Colombier 			if(t)
4537dd7cddfSDavid du Colombier 				return C_RCON;
4547dd7cddfSDavid du Colombier 			t = immrot(~instoffset);
4557dd7cddfSDavid du Colombier 			if(t)
4567dd7cddfSDavid du Colombier 				return C_NCON;
4577dd7cddfSDavid du Colombier 			return C_LCON;
4587dd7cddfSDavid du Colombier 
4597dd7cddfSDavid du Colombier 		case D_EXTERN:
4607dd7cddfSDavid du Colombier 		case D_STATIC:
4617dd7cddfSDavid du Colombier 			s = a->sym;
4627dd7cddfSDavid du Colombier 			if(s == S)
4637dd7cddfSDavid du Colombier 				break;
4647dd7cddfSDavid du Colombier 			t = s->type;
4657dd7cddfSDavid du Colombier 			switch(t) {
4667dd7cddfSDavid du Colombier 			case 0:
4677dd7cddfSDavid du Colombier 			case SXREF:
4686b6b9ac8SDavid du Colombier 				diag("undefined external: %s in %s",
4697dd7cddfSDavid du Colombier 					s->name, TNAME);
4707dd7cddfSDavid du Colombier 				s->type = SDATA;
4717dd7cddfSDavid du Colombier 				break;
472375daca8SDavid du Colombier 			case SUNDEF:
4737dd7cddfSDavid du Colombier 			case STEXT:
4749a747e4fSDavid du Colombier 			case SSTRING:
4759a747e4fSDavid du Colombier 			case SCONST:
4767dd7cddfSDavid du Colombier 			case SLEAF:
4777dd7cddfSDavid du Colombier 				instoffset = s->value + a->offset;
4787dd7cddfSDavid du Colombier 				return C_LCON;
4797dd7cddfSDavid du Colombier 			}
480375daca8SDavid du Colombier 			if(!dlm) {
4817dd7cddfSDavid du Colombier 				instoffset = s->value + a->offset - BIG;
4827dd7cddfSDavid du Colombier 				t = immrot(instoffset);
4837dd7cddfSDavid du Colombier 				if(t && instoffset != 0)
4847dd7cddfSDavid du Colombier 					return C_RECON;
4859a747e4fSDavid du Colombier 			}
4867dd7cddfSDavid du Colombier 			instoffset = s->value + a->offset + INITDAT;
4877dd7cddfSDavid du Colombier 			return C_LCON;
4887dd7cddfSDavid du Colombier 
4897dd7cddfSDavid du Colombier 		case D_AUTO:
4907dd7cddfSDavid du Colombier 			instoffset = autosize + a->offset;
4917dd7cddfSDavid du Colombier 			goto aconsize;
4927dd7cddfSDavid du Colombier 
4937dd7cddfSDavid du Colombier 		case D_PARAM:
4947dd7cddfSDavid du Colombier 			instoffset = autosize + a->offset + 4L;
4957dd7cddfSDavid du Colombier 		aconsize:
4967dd7cddfSDavid du Colombier 			t = immrot(instoffset);
4977dd7cddfSDavid du Colombier 			if(t)
4987dd7cddfSDavid du Colombier 				return C_RACON;
4997dd7cddfSDavid du Colombier 			return C_LACON;
5007dd7cddfSDavid du Colombier 		}
5017dd7cddfSDavid du Colombier 		return C_GOK;
5027dd7cddfSDavid du Colombier 
5037dd7cddfSDavid du Colombier 	case D_BRANCH:
5047dd7cddfSDavid du Colombier 		return C_SBRA;
5057dd7cddfSDavid du Colombier 	}
5067dd7cddfSDavid du Colombier 	return C_GOK;
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier 
5097dd7cddfSDavid du Colombier Optab*
oplook(Prog * p)5107dd7cddfSDavid du Colombier oplook(Prog *p)
5117dd7cddfSDavid du Colombier {
5127dd7cddfSDavid du Colombier 	int a1, a2, a3, r;
5137dd7cddfSDavid du Colombier 	char *c1, *c3;
5147dd7cddfSDavid du Colombier 	Optab *o, *e;
5157dd7cddfSDavid du Colombier 
5167dd7cddfSDavid du Colombier 	a1 = p->optab;
5177dd7cddfSDavid du Colombier 	if(a1)
5187dd7cddfSDavid du Colombier 		return optab+(a1-1);
5197dd7cddfSDavid du Colombier 	a1 = p->from.class;
5207dd7cddfSDavid du Colombier 	if(a1 == 0) {
5217dd7cddfSDavid du Colombier 		a1 = aclass(&p->from) + 1;
5227dd7cddfSDavid du Colombier 		p->from.class = a1;
5237dd7cddfSDavid du Colombier 	}
5247dd7cddfSDavid du Colombier 	a1--;
5257dd7cddfSDavid du Colombier 	a3 = p->to.class;
5267dd7cddfSDavid du Colombier 	if(a3 == 0) {
5277dd7cddfSDavid du Colombier 		a3 = aclass(&p->to) + 1;
5287dd7cddfSDavid du Colombier 		p->to.class = a3;
5297dd7cddfSDavid du Colombier 	}
5307dd7cddfSDavid du Colombier 	a3--;
5317dd7cddfSDavid du Colombier 	a2 = C_NONE;
5327dd7cddfSDavid du Colombier 	if(p->reg != NREG)
5337dd7cddfSDavid du Colombier 		a2 = C_REG;
5347dd7cddfSDavid du Colombier 	r = p->as;
5357dd7cddfSDavid du Colombier 	o = oprange[r].start;
5367dd7cddfSDavid du Colombier 	if(o == 0) {
5377dd7cddfSDavid du Colombier 		a1 = opcross[repop[r]][a1][a2][a3];
5387dd7cddfSDavid du Colombier 		if(a1) {
5397dd7cddfSDavid du Colombier 			p->optab = a1+1;
5407dd7cddfSDavid du Colombier 			return optab+a1;
5417dd7cddfSDavid du Colombier 		}
5427dd7cddfSDavid du Colombier 		o = oprange[r].stop; /* just generate an error */
5437dd7cddfSDavid du Colombier 	}
5447dd7cddfSDavid du Colombier 	if(0) {
5457dd7cddfSDavid du Colombier 		print("oplook %A %d %d %d\n",
5467dd7cddfSDavid du Colombier 			(int)p->as, a1, a2, a3);
5477dd7cddfSDavid du Colombier 		print("		%d %d\n", p->from.type, p->to.type);
5487dd7cddfSDavid du Colombier 	}
5497dd7cddfSDavid du Colombier 	e = oprange[r].stop;
5507dd7cddfSDavid du Colombier 	c1 = xcmp[a1];
5517dd7cddfSDavid du Colombier 	c3 = xcmp[a3];
5527dd7cddfSDavid du Colombier 	for(; o<e; o++)
5537dd7cddfSDavid du Colombier 		if(o->a2 == a2)
5547dd7cddfSDavid du Colombier 		if(c1[o->a1])
5557dd7cddfSDavid du Colombier 		if(c3[o->a3]) {
5567dd7cddfSDavid du Colombier 			p->optab = (o-optab)+1;
5577dd7cddfSDavid du Colombier 			return o;
5587dd7cddfSDavid du Colombier 		}
5596b6b9ac8SDavid du Colombier 	diag("illegal combination %A %d %d %d",
5607dd7cddfSDavid du Colombier 		p->as, a1, a2, a3);
5617dd7cddfSDavid du Colombier 	prasm(p);
5627dd7cddfSDavid du Colombier 	if(o == 0)
5637dd7cddfSDavid du Colombier 		o = optab;
5647dd7cddfSDavid du Colombier 	return o;
5657dd7cddfSDavid du Colombier }
5667dd7cddfSDavid du Colombier 
5677dd7cddfSDavid du Colombier int
cmp(int a,int b)5687dd7cddfSDavid du Colombier cmp(int a, int b)
5697dd7cddfSDavid du Colombier {
5707dd7cddfSDavid du Colombier 
5717dd7cddfSDavid du Colombier 	if(a == b)
5727dd7cddfSDavid du Colombier 		return 1;
5737dd7cddfSDavid du Colombier 	switch(a) {
5747dd7cddfSDavid du Colombier 	case C_LCON:
5757dd7cddfSDavid du Colombier 		if(b == C_RCON || b == C_NCON)
5767dd7cddfSDavid du Colombier 			return 1;
5777dd7cddfSDavid du Colombier 		break;
5787dd7cddfSDavid du Colombier 	case C_LACON:
5797dd7cddfSDavid du Colombier 		if(b == C_RACON)
5807dd7cddfSDavid du Colombier 			return 1;
5817dd7cddfSDavid du Colombier 		break;
5827dd7cddfSDavid du Colombier 	case C_LECON:
5837dd7cddfSDavid du Colombier 		if(b == C_RECON)
5847dd7cddfSDavid du Colombier 			return 1;
5857dd7cddfSDavid du Colombier 		break;
58659cc4ca5SDavid du Colombier 
58759cc4ca5SDavid du Colombier 	case C_HFEXT:
58859cc4ca5SDavid du Colombier 		return b == C_HEXT || b == C_FEXT;
58959cc4ca5SDavid du Colombier 	case C_FEXT:
59059cc4ca5SDavid du Colombier 	case C_HEXT:
59159cc4ca5SDavid du Colombier 		return b == C_HFEXT;
5927dd7cddfSDavid du Colombier 	case C_SEXT:
59359cc4ca5SDavid du Colombier 		return cmp(C_HFEXT, b);
5947dd7cddfSDavid du Colombier 	case C_LEXT:
59559cc4ca5SDavid du Colombier 		return cmp(C_SEXT, b);
59659cc4ca5SDavid du Colombier 
59759cc4ca5SDavid du Colombier 	case C_HFAUTO:
59859cc4ca5SDavid du Colombier 		return b == C_HAUTO || b == C_FAUTO;
59959cc4ca5SDavid du Colombier 	case C_FAUTO:
60059cc4ca5SDavid du Colombier 	case C_HAUTO:
60159cc4ca5SDavid du Colombier 		return b == C_HFAUTO;
6027dd7cddfSDavid du Colombier 	case C_SAUTO:
60359cc4ca5SDavid du Colombier 		return cmp(C_HFAUTO, b);
6047dd7cddfSDavid du Colombier 	case C_LAUTO:
60559cc4ca5SDavid du Colombier 		return cmp(C_SAUTO, b);
60659cc4ca5SDavid du Colombier 
60759cc4ca5SDavid du Colombier 	case C_HFOREG:
60859cc4ca5SDavid du Colombier 		return b == C_HOREG || b == C_FOREG;
60959cc4ca5SDavid du Colombier 	case C_FOREG:
61059cc4ca5SDavid du Colombier 	case C_HOREG:
61159cc4ca5SDavid du Colombier 		return b == C_HFOREG;
61259cc4ca5SDavid du Colombier 	case C_SROREG:
61359cc4ca5SDavid du Colombier 		return cmp(C_SOREG, b) || cmp(C_ROREG, b);
6147dd7cddfSDavid du Colombier 	case C_SOREG:
6157dd7cddfSDavid du Colombier 	case C_ROREG:
61659cc4ca5SDavid du Colombier 		return b == C_SROREG || cmp(C_HFOREG, b);
61759cc4ca5SDavid du Colombier 	case C_LOREG:
61859cc4ca5SDavid du Colombier 		return cmp(C_SROREG, b);
61959cc4ca5SDavid du Colombier 
6207dd7cddfSDavid du Colombier 	case C_LBRA:
6217dd7cddfSDavid du Colombier 		if(b == C_SBRA)
6227dd7cddfSDavid du Colombier 			return 1;
6237dd7cddfSDavid du Colombier 		break;
6247dd7cddfSDavid du Colombier 	}
6257dd7cddfSDavid du Colombier 	return 0;
6267dd7cddfSDavid du Colombier }
6277dd7cddfSDavid du Colombier 
6287dd7cddfSDavid du Colombier int
ocmp(const void * a1,const void * a2)6297dd7cddfSDavid du Colombier ocmp(const void *a1, const void *a2)
6307dd7cddfSDavid du Colombier {
6317dd7cddfSDavid du Colombier 	Optab *p1, *p2;
6327dd7cddfSDavid du Colombier 	int n;
6337dd7cddfSDavid du Colombier 
6347dd7cddfSDavid du Colombier 	p1 = (Optab*)a1;
6357dd7cddfSDavid du Colombier 	p2 = (Optab*)a2;
6367dd7cddfSDavid du Colombier 	n = p1->as - p2->as;
6377dd7cddfSDavid du Colombier 	if(n)
6387dd7cddfSDavid du Colombier 		return n;
63959cc4ca5SDavid du Colombier 	n = (p2->flag&V4) - (p1->flag&V4);	/* architecture version */
64059cc4ca5SDavid du Colombier 	if(n)
64159cc4ca5SDavid du Colombier 		return n;
642*9b7bf7dfSDavid du Colombier 	n = (p2->flag&VFP) - (p1->flag&VFP);	/* floating point arch */
643*9b7bf7dfSDavid du Colombier 	if(n)
644*9b7bf7dfSDavid du Colombier 		return n;
6457dd7cddfSDavid du Colombier 	n = p1->a1 - p2->a1;
6467dd7cddfSDavid du Colombier 	if(n)
6477dd7cddfSDavid du Colombier 		return n;
6487dd7cddfSDavid du Colombier 	n = p1->a2 - p2->a2;
6497dd7cddfSDavid du Colombier 	if(n)
6507dd7cddfSDavid du Colombier 		return n;
6517dd7cddfSDavid du Colombier 	n = p1->a3 - p2->a3;
6527dd7cddfSDavid du Colombier 	if(n)
6537dd7cddfSDavid du Colombier 		return n;
6547dd7cddfSDavid du Colombier 	return 0;
6557dd7cddfSDavid du Colombier }
6567dd7cddfSDavid du Colombier 
6577dd7cddfSDavid du Colombier void
buildop(void)6587dd7cddfSDavid du Colombier buildop(void)
6597dd7cddfSDavid du Colombier {
6607dd7cddfSDavid du Colombier 	int i, n, r;
6617dd7cddfSDavid du Colombier 
66259cc4ca5SDavid du Colombier 	armv4 = !debug['h'];
663*9b7bf7dfSDavid du Colombier 	vfp = debug['f'];
66459cc4ca5SDavid du Colombier 	for(i=0; i<C_GOK; i++)
66559cc4ca5SDavid du Colombier 		for(n=0; n<C_GOK; n++)
6667dd7cddfSDavid du Colombier 			xcmp[i][n] = cmp(n, i);
667*9b7bf7dfSDavid du Colombier 	for(n=0; optab[n].as != AXXX; n++) {
668*9b7bf7dfSDavid du Colombier 		if((optab[n].flag & VFP) && !vfp)
669*9b7bf7dfSDavid du Colombier 			optab[n].as = AXXX;
67059cc4ca5SDavid du Colombier 		if((optab[n].flag & V4) && !armv4) {
67159cc4ca5SDavid du Colombier 			optab[n].as = AXXX;
67259cc4ca5SDavid du Colombier 			break;
67359cc4ca5SDavid du Colombier 		}
674*9b7bf7dfSDavid du Colombier 	}
6757dd7cddfSDavid du Colombier 	qsort(optab, n, sizeof(optab[0]), ocmp);
6767dd7cddfSDavid du Colombier 	for(i=0; i<n; i++) {
6777dd7cddfSDavid du Colombier 		r = optab[i].as;
6787dd7cddfSDavid du Colombier 		oprange[r].start = optab+i;
6797dd7cddfSDavid du Colombier 		while(optab[i].as == r)
6807dd7cddfSDavid du Colombier 			i++;
6817dd7cddfSDavid du Colombier 		oprange[r].stop = optab+i;
6827dd7cddfSDavid du Colombier 		i--;
6837dd7cddfSDavid du Colombier 
6847dd7cddfSDavid du Colombier 		switch(r)
6857dd7cddfSDavid du Colombier 		{
6867dd7cddfSDavid du Colombier 		default:
6876b6b9ac8SDavid du Colombier 			diag("unknown op in build: %A", r);
6887dd7cddfSDavid du Colombier 			errorexit();
689*9b7bf7dfSDavid du Colombier 		case AXXX:
690*9b7bf7dfSDavid du Colombier 			break;
6917dd7cddfSDavid du Colombier 		case AADD:
6927dd7cddfSDavid du Colombier 			oprange[AAND] = oprange[r];
6937dd7cddfSDavid du Colombier 			oprange[AEOR] = oprange[r];
6947dd7cddfSDavid du Colombier 			oprange[ASUB] = oprange[r];
6957dd7cddfSDavid du Colombier 			oprange[ARSB] = oprange[r];
6967dd7cddfSDavid du Colombier 			oprange[AADC] = oprange[r];
6977dd7cddfSDavid du Colombier 			oprange[ASBC] = oprange[r];
6987dd7cddfSDavid du Colombier 			oprange[ARSC] = oprange[r];
6997dd7cddfSDavid du Colombier 			oprange[AORR] = oprange[r];
7007dd7cddfSDavid du Colombier 			oprange[ABIC] = oprange[r];
7017dd7cddfSDavid du Colombier 			break;
7027dd7cddfSDavid du Colombier 		case ACMP:
7037dd7cddfSDavid du Colombier 			oprange[ATST] = oprange[r];
7047dd7cddfSDavid du Colombier 			oprange[ATEQ] = oprange[r];
7057dd7cddfSDavid du Colombier 			oprange[ACMN] = oprange[r];
7067dd7cddfSDavid du Colombier 			break;
7077dd7cddfSDavid du Colombier 		case AMVN:
7087dd7cddfSDavid du Colombier 			break;
7097dd7cddfSDavid du Colombier 		case ABEQ:
7107dd7cddfSDavid du Colombier 			oprange[ABNE] = oprange[r];
7117dd7cddfSDavid du Colombier 			oprange[ABCS] = oprange[r];
7127dd7cddfSDavid du Colombier 			oprange[ABHS] = oprange[r];
7137dd7cddfSDavid du Colombier 			oprange[ABCC] = oprange[r];
7147dd7cddfSDavid du Colombier 			oprange[ABLO] = oprange[r];
7157dd7cddfSDavid du Colombier 			oprange[ABMI] = oprange[r];
7167dd7cddfSDavid du Colombier 			oprange[ABPL] = oprange[r];
7177dd7cddfSDavid du Colombier 			oprange[ABVS] = oprange[r];
7187dd7cddfSDavid du Colombier 			oprange[ABVC] = oprange[r];
7197dd7cddfSDavid du Colombier 			oprange[ABHI] = oprange[r];
7207dd7cddfSDavid du Colombier 			oprange[ABLS] = oprange[r];
7217dd7cddfSDavid du Colombier 			oprange[ABGE] = oprange[r];
7227dd7cddfSDavid du Colombier 			oprange[ABLT] = oprange[r];
7237dd7cddfSDavid du Colombier 			oprange[ABGT] = oprange[r];
7247dd7cddfSDavid du Colombier 			oprange[ABLE] = oprange[r];
7257dd7cddfSDavid du Colombier 			break;
7267dd7cddfSDavid du Colombier 		case ASLL:
7277dd7cddfSDavid du Colombier 			oprange[ASRL] = oprange[r];
7287dd7cddfSDavid du Colombier 			oprange[ASRA] = oprange[r];
7297dd7cddfSDavid du Colombier 			break;
7307dd7cddfSDavid du Colombier 		case AMUL:
7317dd7cddfSDavid du Colombier 			oprange[AMULU] = oprange[r];
7327dd7cddfSDavid du Colombier 			break;
7337dd7cddfSDavid du Colombier 		case ADIV:
7347dd7cddfSDavid du Colombier 			oprange[AMOD] = oprange[r];
7357dd7cddfSDavid du Colombier 			oprange[AMODU] = oprange[r];
7367dd7cddfSDavid du Colombier 			oprange[ADIVU] = oprange[r];
7377dd7cddfSDavid du Colombier 			break;
7387dd7cddfSDavid du Colombier 		case AMOVW:
7397dd7cddfSDavid du Colombier 		case AMOVB:
7407dd7cddfSDavid du Colombier 		case AMOVBU:
7417dd7cddfSDavid du Colombier 		case AMOVH:
7427dd7cddfSDavid du Colombier 		case AMOVHU:
7437dd7cddfSDavid du Colombier 			break;
7447dd7cddfSDavid du Colombier 		case ASWPW:
7457dd7cddfSDavid du Colombier 			oprange[ASWPBU] = oprange[r];
7467dd7cddfSDavid du Colombier 			break;
7477dd7cddfSDavid du Colombier 		case AB:
7487dd7cddfSDavid du Colombier 		case ABL:
749375daca8SDavid du Colombier 		case ABX:
750375daca8SDavid du Colombier 		case ABXRET:
7517dd7cddfSDavid du Colombier 		case ASWI:
7527dd7cddfSDavid du Colombier 		case AWORD:
7537dd7cddfSDavid du Colombier 		case AMOVM:
7547dd7cddfSDavid du Colombier 		case ARFE:
7557dd7cddfSDavid du Colombier 		case ATEXT:
7567dd7cddfSDavid du Colombier 		case ACASE:
7577dd7cddfSDavid du Colombier 		case ABCASE:
7587dd7cddfSDavid du Colombier 			break;
7597dd7cddfSDavid du Colombier 		case AADDF:
7607dd7cddfSDavid du Colombier 			oprange[AADDD] = oprange[r];
7617dd7cddfSDavid du Colombier 			oprange[ASUBF] = oprange[r];
7627dd7cddfSDavid du Colombier 			oprange[ASUBD] = oprange[r];
7637dd7cddfSDavid du Colombier 			oprange[AMULF] = oprange[r];
7647dd7cddfSDavid du Colombier 			oprange[AMULD] = oprange[r];
7657dd7cddfSDavid du Colombier 			oprange[ADIVF] = oprange[r];
7667dd7cddfSDavid du Colombier 			oprange[ADIVD] = oprange[r];
7677dd7cddfSDavid du Colombier 			oprange[AMOVFD] = oprange[r];
7687dd7cddfSDavid du Colombier 			oprange[AMOVDF] = oprange[r];
7697dd7cddfSDavid du Colombier 			break;
7707dd7cddfSDavid du Colombier 
7717dd7cddfSDavid du Colombier 		case ACMPF:
7727dd7cddfSDavid du Colombier 			oprange[ACMPD] = oprange[r];
7737dd7cddfSDavid du Colombier 			break;
7747dd7cddfSDavid du Colombier 
7757dd7cddfSDavid du Colombier 		case AMOVF:
7767dd7cddfSDavid du Colombier 			oprange[AMOVD] = oprange[r];
7777dd7cddfSDavid du Colombier 			break;
7787dd7cddfSDavid du Colombier 
7797dd7cddfSDavid du Colombier 		case AMOVFW:
7807dd7cddfSDavid du Colombier 			oprange[AMOVWF] = oprange[r];
7817dd7cddfSDavid du Colombier 			oprange[AMOVWD] = oprange[r];
7827dd7cddfSDavid du Colombier 			oprange[AMOVDW] = oprange[r];
7837dd7cddfSDavid du Colombier 			break;
78459cc4ca5SDavid du Colombier 
78559cc4ca5SDavid du Colombier 		case AMULL:
78680ee5cbfSDavid du Colombier 			oprange[AMULA] = oprange[r];
78759cc4ca5SDavid du Colombier 			oprange[AMULAL] = oprange[r];
78859cc4ca5SDavid du Colombier 			oprange[AMULLU] = oprange[r];
78959cc4ca5SDavid du Colombier 			oprange[AMULALU] = oprange[r];
79059cc4ca5SDavid du Colombier 			break;
7917dd7cddfSDavid du Colombier 		}
7927dd7cddfSDavid du Colombier 	}
7937dd7cddfSDavid du Colombier }
7947dd7cddfSDavid du Colombier 
79559cc4ca5SDavid du Colombier /*
7967dd7cddfSDavid du Colombier void
7977dd7cddfSDavid du Colombier buildrep(int x, int as)
7987dd7cddfSDavid du Colombier {
7997dd7cddfSDavid du Colombier 	Opcross *p;
8007dd7cddfSDavid du Colombier 	Optab *e, *s, *o;
8017dd7cddfSDavid du Colombier 	int a1, a2, a3, n;
8027dd7cddfSDavid du Colombier 
8037dd7cddfSDavid du Colombier 	if(C_NONE != 0 || C_REG != 1 || C_GOK >= 32 || x >= nelem(opcross)) {
8047dd7cddfSDavid du Colombier 		diag("assumptions fail in buildrep");
8057dd7cddfSDavid du Colombier 		errorexit();
8067dd7cddfSDavid du Colombier 	}
8077dd7cddfSDavid du Colombier 	repop[as] = x;
8087dd7cddfSDavid du Colombier 	p = (opcross + x);
8097dd7cddfSDavid du Colombier 	s = oprange[as].start;
8107dd7cddfSDavid du Colombier 	e = oprange[as].stop;
8117dd7cddfSDavid du Colombier 	for(o=e-1; o>=s; o--) {
8127dd7cddfSDavid du Colombier 		n = o-optab;
8137dd7cddfSDavid du Colombier 		for(a2=0; a2<2; a2++) {
8147dd7cddfSDavid du Colombier 			if(a2) {
8157dd7cddfSDavid du Colombier 				if(o->a2 == C_NONE)
8167dd7cddfSDavid du Colombier 					continue;
8177dd7cddfSDavid du Colombier 			} else
8187dd7cddfSDavid du Colombier 				if(o->a2 != C_NONE)
8197dd7cddfSDavid du Colombier 					continue;
8207dd7cddfSDavid du Colombier 			for(a1=0; a1<32; a1++) {
8217dd7cddfSDavid du Colombier 				if(!xcmp[a1][o->a1])
8227dd7cddfSDavid du Colombier 					continue;
8237dd7cddfSDavid du Colombier 				for(a3=0; a3<32; a3++)
8247dd7cddfSDavid du Colombier 					if(xcmp[a3][o->a3])
8257dd7cddfSDavid du Colombier 						(*p)[a1][a2][a3] = n;
8267dd7cddfSDavid du Colombier 			}
8277dd7cddfSDavid du Colombier 		}
8287dd7cddfSDavid du Colombier 	}
8297dd7cddfSDavid du Colombier 	oprange[as].start = 0;
8307dd7cddfSDavid du Colombier }
83159cc4ca5SDavid du Colombier */
832375daca8SDavid du Colombier 
833375daca8SDavid du Colombier enum{
834375daca8SDavid du Colombier 	ABSD = 0,
835375daca8SDavid du Colombier 	ABSU = 1,
836375daca8SDavid du Colombier 	RELD = 2,
837375daca8SDavid du Colombier 	RELU = 3,
838375daca8SDavid du Colombier };
839375daca8SDavid du Colombier 
840375daca8SDavid du Colombier int modemap[4] = { 0, 1, -1, 2, };
841375daca8SDavid du Colombier 
842375daca8SDavid du Colombier typedef struct Reloc Reloc;
843375daca8SDavid du Colombier 
844375daca8SDavid du Colombier struct Reloc
845375daca8SDavid du Colombier {
846375daca8SDavid du Colombier 	int n;
847375daca8SDavid du Colombier 	int t;
848375daca8SDavid du Colombier 	uchar *m;
849375daca8SDavid du Colombier 	ulong *a;
850375daca8SDavid du Colombier };
851375daca8SDavid du Colombier 
852375daca8SDavid du Colombier Reloc rels;
853375daca8SDavid du Colombier 
854375daca8SDavid du Colombier static void
grow(Reloc * r)855375daca8SDavid du Colombier grow(Reloc *r)
856375daca8SDavid du Colombier {
857375daca8SDavid du Colombier 	int t;
858375daca8SDavid du Colombier 	uchar *m, *nm;
859375daca8SDavid du Colombier 	ulong *a, *na;
860375daca8SDavid du Colombier 
861375daca8SDavid du Colombier 	t = r->t;
862375daca8SDavid du Colombier 	r->t += 64;
863375daca8SDavid du Colombier 	m = r->m;
864375daca8SDavid du Colombier 	a = r->a;
865375daca8SDavid du Colombier 	r->m = nm = malloc(r->t*sizeof(uchar));
866375daca8SDavid du Colombier 	r->a = na = malloc(r->t*sizeof(ulong));
867375daca8SDavid du Colombier 	memmove(nm, m, t*sizeof(uchar));
868375daca8SDavid du Colombier 	memmove(na, a, t*sizeof(ulong));
869375daca8SDavid du Colombier 	free(m);
870375daca8SDavid du Colombier 	free(a);
871375daca8SDavid du Colombier }
872375daca8SDavid du Colombier 
873375daca8SDavid du Colombier void
dynreloc(Sym * s,long v,int abs)874375daca8SDavid du Colombier dynreloc(Sym *s, long v, int abs)
875375daca8SDavid du Colombier {
876375daca8SDavid du Colombier 	int i, k, n;
877375daca8SDavid du Colombier 	uchar *m;
878375daca8SDavid du Colombier 	ulong *a;
879375daca8SDavid du Colombier 	Reloc *r;
880375daca8SDavid du Colombier 
881375daca8SDavid du Colombier 	if(v&3)
882375daca8SDavid du Colombier 		diag("bad relocation address");
883375daca8SDavid du Colombier 	v >>= 2;
884375daca8SDavid du Colombier 	if(s != S && s->type == SUNDEF)
885375daca8SDavid du Colombier 		k = abs ? ABSU : RELU;
886375daca8SDavid du Colombier 	else
887375daca8SDavid du Colombier 		k = abs ? ABSD : RELD;
888375daca8SDavid du Colombier 	/* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, a, a, k); */
889375daca8SDavid du Colombier 	k = modemap[k];
890375daca8SDavid du Colombier 	r = &rels;
891375daca8SDavid du Colombier 	n = r->n;
892375daca8SDavid du Colombier 	if(n >= r->t)
893375daca8SDavid du Colombier 		grow(r);
894375daca8SDavid du Colombier 	m = r->m;
895375daca8SDavid du Colombier 	a = r->a;
896375daca8SDavid du Colombier 	for(i = n; i > 0; i--){
897375daca8SDavid du Colombier 		if(v < a[i-1]){	/* happens occasionally for data */
898375daca8SDavid du Colombier 			m[i] = m[i-1];
899375daca8SDavid du Colombier 			a[i] = a[i-1];
900375daca8SDavid du Colombier 		}
901375daca8SDavid du Colombier 		else
902375daca8SDavid du Colombier 			break;
903375daca8SDavid du Colombier 	}
904375daca8SDavid du Colombier 	m[i] = k;
905375daca8SDavid du Colombier 	a[i] = v;
906375daca8SDavid du Colombier 	r->n++;
907375daca8SDavid du Colombier }
908375daca8SDavid du Colombier 
909375daca8SDavid du Colombier static int
sput(char * s)910375daca8SDavid du Colombier sput(char *s)
911375daca8SDavid du Colombier {
912375daca8SDavid du Colombier 	char *p;
913375daca8SDavid du Colombier 
914375daca8SDavid du Colombier 	p = s;
915375daca8SDavid du Colombier 	while(*s)
916375daca8SDavid du Colombier 		cput(*s++);
917375daca8SDavid du Colombier 	cput(0);
918375daca8SDavid du Colombier 	return  s-p+1;
919375daca8SDavid du Colombier }
920375daca8SDavid du Colombier 
921375daca8SDavid du Colombier void
asmdyn()922375daca8SDavid du Colombier asmdyn()
923375daca8SDavid du Colombier {
924375daca8SDavid du Colombier 	int i, n, t, c;
925375daca8SDavid du Colombier 	Sym *s;
926375daca8SDavid du Colombier 	ulong la, ra, *a;
927375daca8SDavid du Colombier 	vlong off;
928375daca8SDavid du Colombier 	uchar *m;
929375daca8SDavid du Colombier 	Reloc *r;
930375daca8SDavid du Colombier 
931375daca8SDavid du Colombier 	cflush();
932375daca8SDavid du Colombier 	off = seek(cout, 0, 1);
933375daca8SDavid du Colombier 	lput(0);
934375daca8SDavid du Colombier 	t = 0;
935375daca8SDavid du Colombier 	lput(imports);
936375daca8SDavid du Colombier 	t += 4;
937375daca8SDavid du Colombier 	for(i = 0; i < NHASH; i++)
938375daca8SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
939375daca8SDavid du Colombier 			if(s->type == SUNDEF){
940375daca8SDavid du Colombier 				lput(s->sig);
941375daca8SDavid du Colombier 				t += 4;
942375daca8SDavid du Colombier 				t += sput(s->name);
943375daca8SDavid du Colombier 			}
944375daca8SDavid du Colombier 
945375daca8SDavid du Colombier 	la = 0;
946375daca8SDavid du Colombier 	r = &rels;
947375daca8SDavid du Colombier 	n = r->n;
948375daca8SDavid du Colombier 	m = r->m;
949375daca8SDavid du Colombier 	a = r->a;
950375daca8SDavid du Colombier 	lput(n);
951375daca8SDavid du Colombier 	t += 4;
952375daca8SDavid du Colombier 	for(i = 0; i < n; i++){
953375daca8SDavid du Colombier 		ra = *a-la;
954375daca8SDavid du Colombier 		if(*a < la)
955375daca8SDavid du Colombier 			diag("bad relocation order");
956375daca8SDavid du Colombier 		if(ra < 256)
957375daca8SDavid du Colombier 			c = 0;
958375daca8SDavid du Colombier 		else if(ra < 65536)
959375daca8SDavid du Colombier 			c = 1;
960375daca8SDavid du Colombier 		else
961375daca8SDavid du Colombier 			c = 2;
962375daca8SDavid du Colombier 		cput((c<<6)|*m++);
963375daca8SDavid du Colombier 		t++;
964375daca8SDavid du Colombier 		if(c == 0){
965375daca8SDavid du Colombier 			cput(ra);
966375daca8SDavid du Colombier 			t++;
967375daca8SDavid du Colombier 		}
968375daca8SDavid du Colombier 		else if(c == 1){
969375daca8SDavid du Colombier 			wput(ra);
970375daca8SDavid du Colombier 			t += 2;
971375daca8SDavid du Colombier 		}
972375daca8SDavid du Colombier 		else{
973375daca8SDavid du Colombier 			lput(ra);
974375daca8SDavid du Colombier 			t += 4;
975375daca8SDavid du Colombier 		}
976375daca8SDavid du Colombier 		la = *a++;
977375daca8SDavid du Colombier 	}
978375daca8SDavid du Colombier 
979375daca8SDavid du Colombier 	cflush();
980375daca8SDavid du Colombier 	seek(cout, off, 0);
981375daca8SDavid du Colombier 	lput(t);
982375daca8SDavid du Colombier 
983375daca8SDavid du Colombier 	if(debug['v']){
984375daca8SDavid du Colombier 		Bprint(&bso, "import table entries = %d\n", imports);
985375daca8SDavid du Colombier 		Bprint(&bso, "export table entries = %d\n", exports);
986375daca8SDavid du Colombier 	}
987375daca8SDavid du Colombier }
988