xref: /plan9/sys/src/cmd/8l/span.c (revision b87cd620ecfdc8c76fc402275c5ab6ae2edfd4ee)
13e12c5d1SDavid du Colombier #include	"l.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier void
span(void)43e12c5d1SDavid du Colombier span(void)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier 	Prog *p, *q;
73e12c5d1SDavid du Colombier 	long v, c, idat;
83e12c5d1SDavid du Colombier 	int m, n, again;
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier 	xdefine("etext", STEXT, 0L);
113e12c5d1SDavid du Colombier 	idat = INITDAT;
123e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
133e12c5d1SDavid du Colombier 		if(p->as == ATEXT)
143e12c5d1SDavid du Colombier 			curtext = p;
153e12c5d1SDavid du Colombier 		n = 0;
163e12c5d1SDavid du Colombier 		if(p->to.type == D_BRANCH)
177dd7cddfSDavid du Colombier 			if(p->pcond == P)
187dd7cddfSDavid du Colombier 				p->pcond = p;
197dd7cddfSDavid du Colombier 		if((q = p->pcond) != P)
203e12c5d1SDavid du Colombier 			if(q->back != 2)
213e12c5d1SDavid du Colombier 				n = 1;
223e12c5d1SDavid du Colombier 		p->back = n;
233e12c5d1SDavid du Colombier 		if(p->as == AADJSP) {
243e12c5d1SDavid du Colombier 			p->to.type = D_SP;
253e12c5d1SDavid du Colombier 			v = -p->from.offset;
263e12c5d1SDavid du Colombier 			p->from.offset = v;
273e12c5d1SDavid du Colombier 			p->as = AADDL;
283e12c5d1SDavid du Colombier 			if(v < 0) {
293e12c5d1SDavid du Colombier 				p->as = ASUBL;
303e12c5d1SDavid du Colombier 				v = -v;
313e12c5d1SDavid du Colombier 				p->from.offset = v;
323e12c5d1SDavid du Colombier 			}
333e12c5d1SDavid du Colombier 			if(v == 0)
343e12c5d1SDavid du Colombier 				p->as = ANOP;
353e12c5d1SDavid du Colombier 		}
363e12c5d1SDavid du Colombier 	}
373e12c5d1SDavid du Colombier 	n = 0;
383e12c5d1SDavid du Colombier 
393e12c5d1SDavid du Colombier start:
403e12c5d1SDavid du Colombier 	if(debug['v'])
413e12c5d1SDavid du Colombier 		Bprint(&bso, "%5.2f span\n", cputime());
423e12c5d1SDavid du Colombier 	Bflush(&bso);
433e12c5d1SDavid du Colombier 	c = INITTEXT;
443e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
453e12c5d1SDavid du Colombier 		if(p->as == ATEXT)
463e12c5d1SDavid du Colombier 			curtext = p;
473e12c5d1SDavid du Colombier 		if(p->to.type == D_BRANCH)
483e12c5d1SDavid du Colombier 			if(p->back)
493e12c5d1SDavid du Colombier 				p->pc = c;
503e12c5d1SDavid du Colombier 		asmins(p);
513e12c5d1SDavid du Colombier 		p->pc = c;
523e12c5d1SDavid du Colombier 		m = andptr-and;
533e12c5d1SDavid du Colombier 		p->mark = m;
543e12c5d1SDavid du Colombier 		c += m;
553e12c5d1SDavid du Colombier 	}
563e12c5d1SDavid du Colombier 
573e12c5d1SDavid du Colombier loop:
583e12c5d1SDavid du Colombier 	n++;
593e12c5d1SDavid du Colombier 	if(debug['v'])
603e12c5d1SDavid du Colombier 		Bprint(&bso, "%5.2f span %d\n", cputime(), n);
613e12c5d1SDavid du Colombier 	Bflush(&bso);
623e12c5d1SDavid du Colombier 	if(n > 50) {
633e12c5d1SDavid du Colombier 		print("span must be looping\n");
643e12c5d1SDavid du Colombier 		errorexit();
653e12c5d1SDavid du Colombier 	}
663e12c5d1SDavid du Colombier 	again = 0;
673e12c5d1SDavid du Colombier 	c = INITTEXT;
683e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
693e12c5d1SDavid du Colombier 		if(p->as == ATEXT)
703e12c5d1SDavid du Colombier 			curtext = p;
713e12c5d1SDavid du Colombier 		if(p->to.type == D_BRANCH) {
723e12c5d1SDavid du Colombier 			if(p->back)
733e12c5d1SDavid du Colombier 				p->pc = c;
743e12c5d1SDavid du Colombier 			asmins(p);
753e12c5d1SDavid du Colombier 			m = andptr-and;
763e12c5d1SDavid du Colombier 			if(m != p->mark) {
773e12c5d1SDavid du Colombier 				p->mark = m;
783e12c5d1SDavid du Colombier 				again++;
793e12c5d1SDavid du Colombier 			}
803e12c5d1SDavid du Colombier 		}
813e12c5d1SDavid du Colombier 		p->pc = c;
823e12c5d1SDavid du Colombier 		c += p->mark;
833e12c5d1SDavid du Colombier 	}
843e12c5d1SDavid du Colombier 	if(again) {
853e12c5d1SDavid du Colombier 		textsize = c;
863e12c5d1SDavid du Colombier 		goto loop;
873e12c5d1SDavid du Colombier 	}
883e12c5d1SDavid du Colombier 	if(INITRND) {
893e12c5d1SDavid du Colombier 		INITDAT = rnd(c, INITRND);
903e12c5d1SDavid du Colombier 		if(INITDAT != idat) {
913e12c5d1SDavid du Colombier 			idat = INITDAT;
923e12c5d1SDavid du Colombier 			goto start;
933e12c5d1SDavid du Colombier 		}
943e12c5d1SDavid du Colombier 	}
953e12c5d1SDavid du Colombier 	xdefine("etext", STEXT, c);
963e12c5d1SDavid du Colombier 	if(debug['v'])
973e12c5d1SDavid du Colombier 		Bprint(&bso, "etext = %lux\n", c);
983e12c5d1SDavid du Colombier 	Bflush(&bso);
997dd7cddfSDavid du Colombier 	for(p = textp; p != P; p = p->pcond)
1003e12c5d1SDavid du Colombier 		p->from.sym->value = p->pc;
1013e12c5d1SDavid du Colombier 	textsize = c - INITTEXT;
1023e12c5d1SDavid du Colombier }
1033e12c5d1SDavid du Colombier 
1043e12c5d1SDavid du Colombier void
xdefine(char * p,int t,long v)1053e12c5d1SDavid du Colombier xdefine(char *p, int t, long v)
1063e12c5d1SDavid du Colombier {
1073e12c5d1SDavid du Colombier 	Sym *s;
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier 	s = lookup(p, 0);
1103e12c5d1SDavid du Colombier 	if(s->type == 0 || s->type == SXREF) {
1113e12c5d1SDavid du Colombier 		s->type = t;
1123e12c5d1SDavid du Colombier 		s->value = v;
1133e12c5d1SDavid du Colombier 	}
1143e12c5d1SDavid du Colombier 	if(s->type == STEXT && s->value == 0)
1153e12c5d1SDavid du Colombier 		s->value = v;
1163e12c5d1SDavid du Colombier }
1173e12c5d1SDavid du Colombier 
1183e12c5d1SDavid du Colombier void
putsymb(char * s,int t,long v,int ver)119219b2ee8SDavid du Colombier putsymb(char *s, int t, long v, int ver)
1203e12c5d1SDavid du Colombier {
1213e12c5d1SDavid du Colombier 	int i, f;
1223e12c5d1SDavid du Colombier 
1233e12c5d1SDavid du Colombier 	if(t == 'f')
124219b2ee8SDavid du Colombier 		s++;
1253e12c5d1SDavid du Colombier 	lput(v);
126219b2ee8SDavid du Colombier 	if(ver)
1273e12c5d1SDavid du Colombier 		t += 'a' - 'A';
12859cc4ca5SDavid du Colombier 	cput(t+0x80);			/* 0x80 is variable length */
129219b2ee8SDavid du Colombier 
130219b2ee8SDavid du Colombier 	if(t == 'Z' || t == 'z') {
13159cc4ca5SDavid du Colombier 		cput(s[0]);
132219b2ee8SDavid du Colombier 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
13359cc4ca5SDavid du Colombier 			cput(s[i]);
13459cc4ca5SDavid du Colombier 			cput(s[i+1]);
135219b2ee8SDavid du Colombier 		}
13659cc4ca5SDavid du Colombier 		cput(0);
13759cc4ca5SDavid du Colombier 		cput(0);
138219b2ee8SDavid du Colombier 		i++;
139219b2ee8SDavid du Colombier 	}
140219b2ee8SDavid du Colombier 	else {
141219b2ee8SDavid du Colombier 		for(i=0; s[i]; i++)
14259cc4ca5SDavid du Colombier 			cput(s[i]);
14359cc4ca5SDavid du Colombier 		cput(0);
144219b2ee8SDavid du Colombier 	}
145219b2ee8SDavid du Colombier 	symsize += 4 + 1 + i + 1;
146219b2ee8SDavid du Colombier 
1473e12c5d1SDavid du Colombier 	if(debug['n']) {
1483e12c5d1SDavid du Colombier 		if(t == 'z' || t == 'Z') {
149219b2ee8SDavid du Colombier 			Bprint(&bso, "%c %.8lux ", t, v);
150219b2ee8SDavid du Colombier 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
151219b2ee8SDavid du Colombier 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
152219b2ee8SDavid du Colombier 				Bprint(&bso, "/%x", f);
1533e12c5d1SDavid du Colombier 			}
154219b2ee8SDavid du Colombier 			Bprint(&bso, "\n");
1553e12c5d1SDavid du Colombier 			return;
1563e12c5d1SDavid du Colombier 		}
157219b2ee8SDavid du Colombier 		if(ver)
158219b2ee8SDavid du Colombier 			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
1593e12c5d1SDavid du Colombier 		else
160219b2ee8SDavid du Colombier 			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
1613e12c5d1SDavid du Colombier 	}
1623e12c5d1SDavid du Colombier }
1633e12c5d1SDavid du Colombier 
1643e12c5d1SDavid du Colombier void
asmsym(void)1653e12c5d1SDavid du Colombier asmsym(void)
1663e12c5d1SDavid du Colombier {
1673e12c5d1SDavid du Colombier 	Prog *p;
1683e12c5d1SDavid du Colombier 	Auto *a;
1693e12c5d1SDavid du Colombier 	Sym *s;
1703e12c5d1SDavid du Colombier 	int h;
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier 	s = lookup("etext", 0);
1733e12c5d1SDavid du Colombier 	if(s->type == STEXT)
174219b2ee8SDavid du Colombier 		putsymb(s->name, 'T', s->value, s->version);
1753e12c5d1SDavid du Colombier 
1763e12c5d1SDavid du Colombier 	for(h=0; h<NHASH; h++)
1773e12c5d1SDavid du Colombier 		for(s=hash[h]; s!=S; s=s->link)
1783e12c5d1SDavid du Colombier 			switch(s->type) {
179219b2ee8SDavid du Colombier 			case SCONST:
180219b2ee8SDavid du Colombier 				putsymb(s->name, 'D', s->value, s->version);
181219b2ee8SDavid du Colombier 				continue;
182219b2ee8SDavid du Colombier 
1833e12c5d1SDavid du Colombier 			case SDATA:
184219b2ee8SDavid du Colombier 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
1853e12c5d1SDavid du Colombier 				continue;
1863e12c5d1SDavid du Colombier 
1873e12c5d1SDavid du Colombier 			case SBSS:
188219b2ee8SDavid du Colombier 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
1893e12c5d1SDavid du Colombier 				continue;
1903e12c5d1SDavid du Colombier 
1913e12c5d1SDavid du Colombier 			case SFILE:
192219b2ee8SDavid du Colombier 				putsymb(s->name, 'f', s->value, s->version);
1933e12c5d1SDavid du Colombier 				continue;
1943e12c5d1SDavid du Colombier 			}
1953e12c5d1SDavid du Colombier 
1967dd7cddfSDavid du Colombier 	for(p=textp; p!=P; p=p->pcond) {
1973e12c5d1SDavid du Colombier 		s = p->from.sym;
1983e12c5d1SDavid du Colombier 		if(s->type != STEXT)
1993e12c5d1SDavid du Colombier 			continue;
2003e12c5d1SDavid du Colombier 
2013e12c5d1SDavid du Colombier 		/* filenames first */
2023e12c5d1SDavid du Colombier 		for(a=p->to.autom; a; a=a->link)
2033e12c5d1SDavid du Colombier 			if(a->type == D_FILE)
2047dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'z', a->aoffset, 0);
2053e12c5d1SDavid du Colombier 			else
2063e12c5d1SDavid du Colombier 			if(a->type == D_FILE1)
2077dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'Z', a->aoffset, 0);
2083e12c5d1SDavid du Colombier 
209219b2ee8SDavid du Colombier 		putsymb(s->name, 'T', s->value, s->version);
2103e12c5d1SDavid du Colombier 
211219b2ee8SDavid du Colombier 		/* frame, auto and param after */
212219b2ee8SDavid du Colombier 		putsymb(".frame", 'm', p->to.offset+4, 0);
213219b2ee8SDavid du Colombier 
2143e12c5d1SDavid du Colombier 		for(a=p->to.autom; a; a=a->link)
2153e12c5d1SDavid du Colombier 			if(a->type == D_AUTO)
2167dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'a', -a->aoffset, 0);
2173e12c5d1SDavid du Colombier 			else
2183e12c5d1SDavid du Colombier 			if(a->type == D_PARAM)
2197dd7cddfSDavid du Colombier 				putsymb(a->asym->name, 'p', a->aoffset, 0);
2203e12c5d1SDavid du Colombier 	}
2213e12c5d1SDavid du Colombier 	if(debug['v'] || debug['n'])
2223e12c5d1SDavid du Colombier 		Bprint(&bso, "symsize = %lud\n", symsize);
2233e12c5d1SDavid du Colombier 	Bflush(&bso);
2243e12c5d1SDavid du Colombier }
2253e12c5d1SDavid du Colombier 
2263e12c5d1SDavid du Colombier void
asmlc(void)2273e12c5d1SDavid du Colombier asmlc(void)
2283e12c5d1SDavid du Colombier {
2293e12c5d1SDavid du Colombier 	long oldpc, oldlc;
2303e12c5d1SDavid du Colombier 	Prog *p;
2313e12c5d1SDavid du Colombier 	long v, s;
2323e12c5d1SDavid du Colombier 
2333e12c5d1SDavid du Colombier 	oldpc = INITTEXT;
2343e12c5d1SDavid du Colombier 	oldlc = 0;
2353e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
2363e12c5d1SDavid du Colombier 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
2373e12c5d1SDavid du Colombier 			if(p->as == ATEXT)
2383e12c5d1SDavid du Colombier 				curtext = p;
239*b87cd620SDavid du Colombier 			if(debug['V'])
2403e12c5d1SDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
2413e12c5d1SDavid du Colombier 					p->pc, p);
2423e12c5d1SDavid du Colombier 			continue;
2433e12c5d1SDavid du Colombier 		}
244*b87cd620SDavid du Colombier 		if(debug['V'])
2453e12c5d1SDavid du Colombier 			Bprint(&bso, "\t\t%6ld", lcsize);
2463e12c5d1SDavid du Colombier 		v = (p->pc - oldpc) / MINLC;
2473e12c5d1SDavid du Colombier 		while(v) {
2483e12c5d1SDavid du Colombier 			s = 127;
2493e12c5d1SDavid du Colombier 			if(v < 127)
2503e12c5d1SDavid du Colombier 				s = v;
25159cc4ca5SDavid du Colombier 			cput(s+128);	/* 129-255 +pc */
252*b87cd620SDavid du Colombier 			if(debug['V'])
2533e12c5d1SDavid du Colombier 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
2543e12c5d1SDavid du Colombier 			v -= s;
2553e12c5d1SDavid du Colombier 			lcsize++;
2563e12c5d1SDavid du Colombier 		}
2573e12c5d1SDavid du Colombier 		s = p->line - oldlc;
2583e12c5d1SDavid du Colombier 		oldlc = p->line;
2593e12c5d1SDavid du Colombier 		oldpc = p->pc + MINLC;
2603e12c5d1SDavid du Colombier 		if(s > 64 || s < -64) {
26159cc4ca5SDavid du Colombier 			cput(0);	/* 0 vv +lc */
26259cc4ca5SDavid du Colombier 			cput(s>>24);
26359cc4ca5SDavid du Colombier 			cput(s>>16);
26459cc4ca5SDavid du Colombier 			cput(s>>8);
26559cc4ca5SDavid du Colombier 			cput(s);
266*b87cd620SDavid du Colombier 			if(debug['V']) {
2673e12c5d1SDavid du Colombier 				if(s > 0)
2683e12c5d1SDavid du Colombier 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
2693e12c5d1SDavid du Colombier 						s, 0, s);
2703e12c5d1SDavid du Colombier 				else
2713e12c5d1SDavid du Colombier 					Bprint(&bso, " lc%ld(%d,%ld)\n",
2723e12c5d1SDavid du Colombier 						s, 0, s);
2733e12c5d1SDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
2743e12c5d1SDavid du Colombier 					p->pc, p);
2753e12c5d1SDavid du Colombier 			}
2763e12c5d1SDavid du Colombier 			lcsize += 5;
2773e12c5d1SDavid du Colombier 			continue;
2783e12c5d1SDavid du Colombier 		}
2793e12c5d1SDavid du Colombier 		if(s > 0) {
28059cc4ca5SDavid du Colombier 			cput(0+s);	/* 1-64 +lc */
281*b87cd620SDavid du Colombier 			if(debug['V']) {
2823e12c5d1SDavid du Colombier 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
2833e12c5d1SDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
2843e12c5d1SDavid du Colombier 					p->pc, p);
2853e12c5d1SDavid du Colombier 			}
2863e12c5d1SDavid du Colombier 		} else {
28759cc4ca5SDavid du Colombier 			cput(64-s);	/* 65-128 -lc */
288*b87cd620SDavid du Colombier 			if(debug['V']) {
2893e12c5d1SDavid du Colombier 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
2903e12c5d1SDavid du Colombier 				Bprint(&bso, "%6lux %P\n",
2913e12c5d1SDavid du Colombier 					p->pc, p);
2923e12c5d1SDavid du Colombier 			}
2933e12c5d1SDavid du Colombier 		}
2943e12c5d1SDavid du Colombier 		lcsize++;
2953e12c5d1SDavid du Colombier 	}
2963e12c5d1SDavid du Colombier 	while(lcsize & 1) {
2973e12c5d1SDavid du Colombier 		s = 129;
29859cc4ca5SDavid du Colombier 		cput(s);
2993e12c5d1SDavid du Colombier 		lcsize++;
3003e12c5d1SDavid du Colombier 	}
301*b87cd620SDavid du Colombier 	if(debug['v'] || debug['V'])
3023e12c5d1SDavid du Colombier 		Bprint(&bso, "lcsize = %ld\n", lcsize);
3033e12c5d1SDavid du Colombier 	Bflush(&bso);
3043e12c5d1SDavid du Colombier }
3053e12c5d1SDavid du Colombier 
3063e12c5d1SDavid du Colombier int
prefixof(Adr * a)3076520663fSDavid du Colombier prefixof(Adr *a)
3086520663fSDavid du Colombier {
3096520663fSDavid du Colombier 	switch(a->type) {
3106520663fSDavid du Colombier 	case D_INDIR+D_CS:
3116520663fSDavid du Colombier 		return 0x2e;
3126520663fSDavid du Colombier 	case D_INDIR+D_DS:
3136520663fSDavid du Colombier 		return 0x3e;
3146520663fSDavid du Colombier 	case D_INDIR+D_ES:
3156520663fSDavid du Colombier 		return 0x26;
3166520663fSDavid du Colombier 	case D_INDIR+D_FS:
3176520663fSDavid du Colombier 		return 0x64;
3186520663fSDavid du Colombier 	case D_INDIR+D_GS:
3196520663fSDavid du Colombier 		return 0x65;
3206520663fSDavid du Colombier 	}
3216520663fSDavid du Colombier 	return 0;
3226520663fSDavid du Colombier }
3236520663fSDavid du Colombier 
3246520663fSDavid du Colombier int
oclass(Adr * a)3253e12c5d1SDavid du Colombier oclass(Adr *a)
3263e12c5d1SDavid du Colombier {
3273e12c5d1SDavid du Colombier 	long v;
3283e12c5d1SDavid du Colombier 
3293e12c5d1SDavid du Colombier 	if(a->type >= D_INDIR || a->index != D_NONE) {
3303e12c5d1SDavid du Colombier 		if(a->index != D_NONE && a->scale == 0) {
331219b2ee8SDavid du Colombier 			if(a->type == D_ADDR) {
332219b2ee8SDavid du Colombier 				switch(a->index) {
333219b2ee8SDavid du Colombier 				case D_EXTERN:
334219b2ee8SDavid du Colombier 				case D_STATIC:
3353e12c5d1SDavid du Colombier 					return Yi32;
336219b2ee8SDavid du Colombier 				case D_AUTO:
337219b2ee8SDavid du Colombier 				case D_PARAM:
338219b2ee8SDavid du Colombier 					return Yiauto;
339219b2ee8SDavid du Colombier 				}
340219b2ee8SDavid du Colombier 				return Yxxx;
341219b2ee8SDavid du Colombier 			}
3423e12c5d1SDavid du Colombier 			return Ycol;
3433e12c5d1SDavid du Colombier 		}
3443e12c5d1SDavid du Colombier 		return Ym;
3453e12c5d1SDavid du Colombier 	}
3463e12c5d1SDavid du Colombier 	switch(a->type)
3473e12c5d1SDavid du Colombier 	{
3483e12c5d1SDavid du Colombier 	case D_AL:
3493e12c5d1SDavid du Colombier 		return Yal;
3503e12c5d1SDavid du Colombier 
3513e12c5d1SDavid du Colombier 	case D_AX:
3523e12c5d1SDavid du Colombier 		return Yax;
3533e12c5d1SDavid du Colombier 
3543e12c5d1SDavid du Colombier 	case D_CL:
3556520663fSDavid du Colombier 		return Ycl;
3566520663fSDavid du Colombier 
3573e12c5d1SDavid du Colombier 	case D_DL:
3583e12c5d1SDavid du Colombier 	case D_BL:
3593e12c5d1SDavid du Colombier 	case D_AH:
3603e12c5d1SDavid du Colombier 	case D_CH:
3613e12c5d1SDavid du Colombier 	case D_DH:
3623e12c5d1SDavid du Colombier 	case D_BH:
3633e12c5d1SDavid du Colombier 		return Yrb;
3643e12c5d1SDavid du Colombier 
3653e12c5d1SDavid du Colombier 	case D_CX:
3663e12c5d1SDavid du Colombier 		return Ycx;
3673e12c5d1SDavid du Colombier 
3683e12c5d1SDavid du Colombier 	case D_DX:
3693e12c5d1SDavid du Colombier 	case D_BX:
3703e12c5d1SDavid du Colombier 		return Yrx;
3713e12c5d1SDavid du Colombier 
3723e12c5d1SDavid du Colombier 	case D_SP:
3733e12c5d1SDavid du Colombier 	case D_BP:
3743e12c5d1SDavid du Colombier 	case D_SI:
3753e12c5d1SDavid du Colombier 	case D_DI:
3763e12c5d1SDavid du Colombier 		return Yrl;
3773e12c5d1SDavid du Colombier 
3783e12c5d1SDavid du Colombier 	case D_F0+0:
3793e12c5d1SDavid du Colombier 		return	Yf0;
3803e12c5d1SDavid du Colombier 
3813e12c5d1SDavid du Colombier 	case D_F0+1:
3823e12c5d1SDavid du Colombier 	case D_F0+2:
3833e12c5d1SDavid du Colombier 	case D_F0+3:
3843e12c5d1SDavid du Colombier 	case D_F0+4:
3853e12c5d1SDavid du Colombier 	case D_F0+5:
3863e12c5d1SDavid du Colombier 	case D_F0+6:
3873e12c5d1SDavid du Colombier 	case D_F0+7:
3883e12c5d1SDavid du Colombier 		return	Yrf;
3893e12c5d1SDavid du Colombier 
3903e12c5d1SDavid du Colombier 	case D_NONE:
3913e12c5d1SDavid du Colombier 		return Ynone;
3923e12c5d1SDavid du Colombier 
3933e12c5d1SDavid du Colombier 	case D_CS:	return	Ycs;
3943e12c5d1SDavid du Colombier 	case D_SS:	return	Yss;
3953e12c5d1SDavid du Colombier 	case D_DS:	return	Yds;
3963e12c5d1SDavid du Colombier 	case D_ES:	return	Yes;
3973e12c5d1SDavid du Colombier 	case D_FS:	return	Yfs;
3983e12c5d1SDavid du Colombier 	case D_GS:	return	Ygs;
3993e12c5d1SDavid du Colombier 
4003e12c5d1SDavid du Colombier 	case D_GDTR:	return	Ygdtr;
4013e12c5d1SDavid du Colombier 	case D_IDTR:	return	Yidtr;
4023e12c5d1SDavid du Colombier 	case D_LDTR:	return	Yldtr;
4033e12c5d1SDavid du Colombier 	case D_MSW:	return	Ymsw;
4043e12c5d1SDavid du Colombier 	case D_TASK:	return	Ytask;
4053e12c5d1SDavid du Colombier 
4063e12c5d1SDavid du Colombier 	case D_CR+0:	return	Ycr0;
4073e12c5d1SDavid du Colombier 	case D_CR+1:	return	Ycr1;
4083e12c5d1SDavid du Colombier 	case D_CR+2:	return	Ycr2;
4093e12c5d1SDavid du Colombier 	case D_CR+3:	return	Ycr3;
4103e12c5d1SDavid du Colombier 	case D_CR+4:	return	Ycr4;
4113e12c5d1SDavid du Colombier 	case D_CR+5:	return	Ycr5;
4123e12c5d1SDavid du Colombier 	case D_CR+6:	return	Ycr6;
4133e12c5d1SDavid du Colombier 	case D_CR+7:	return	Ycr7;
4143e12c5d1SDavid du Colombier 
4153e12c5d1SDavid du Colombier 	case D_DR+0:	return	Ydr0;
4163e12c5d1SDavid du Colombier 	case D_DR+1:	return	Ydr1;
4173e12c5d1SDavid du Colombier 	case D_DR+2:	return	Ydr2;
4183e12c5d1SDavid du Colombier 	case D_DR+3:	return	Ydr3;
4193e12c5d1SDavid du Colombier 	case D_DR+4:	return	Ydr4;
4203e12c5d1SDavid du Colombier 	case D_DR+5:	return	Ydr5;
4213e12c5d1SDavid du Colombier 	case D_DR+6:	return	Ydr6;
4223e12c5d1SDavid du Colombier 	case D_DR+7:	return	Ydr7;
4233e12c5d1SDavid du Colombier 
4243e12c5d1SDavid du Colombier 	case D_TR+0:	return	Ytr0;
4253e12c5d1SDavid du Colombier 	case D_TR+1:	return	Ytr1;
4263e12c5d1SDavid du Colombier 	case D_TR+2:	return	Ytr2;
4273e12c5d1SDavid du Colombier 	case D_TR+3:	return	Ytr3;
4283e12c5d1SDavid du Colombier 	case D_TR+4:	return	Ytr4;
4293e12c5d1SDavid du Colombier 	case D_TR+5:	return	Ytr5;
4303e12c5d1SDavid du Colombier 	case D_TR+6:	return	Ytr6;
4313e12c5d1SDavid du Colombier 	case D_TR+7:	return	Ytr7;
4323e12c5d1SDavid du Colombier 
4333e12c5d1SDavid du Colombier 	case D_EXTERN:
4343e12c5d1SDavid du Colombier 	case D_STATIC:
4353e12c5d1SDavid du Colombier 	case D_AUTO:
4363e12c5d1SDavid du Colombier 	case D_PARAM:
4373e12c5d1SDavid du Colombier 		return Ym;
4383e12c5d1SDavid du Colombier 
4393e12c5d1SDavid du Colombier 	case D_CONST:
4403e12c5d1SDavid du Colombier 	case D_ADDR:
4413e12c5d1SDavid du Colombier 		if(a->sym == S) {
4423e12c5d1SDavid du Colombier 			v = a->offset;
4433e12c5d1SDavid du Colombier 			if(v == 0)
4443e12c5d1SDavid du Colombier 				return Yi0;
4453e12c5d1SDavid du Colombier 			if(v == 1)
4463e12c5d1SDavid du Colombier 				return Yi1;
4473e12c5d1SDavid du Colombier 			if(v >= -128 && v <= 127)
4483e12c5d1SDavid du Colombier 				return Yi8;
4493e12c5d1SDavid du Colombier 		}
4503e12c5d1SDavid du Colombier 		return Yi32;
4513e12c5d1SDavid du Colombier 
4523e12c5d1SDavid du Colombier 	case D_BRANCH:
4533e12c5d1SDavid du Colombier 		return Ybr;
4543e12c5d1SDavid du Colombier 	}
4553e12c5d1SDavid du Colombier 	return Yxxx;
4563e12c5d1SDavid du Colombier }
4573e12c5d1SDavid du Colombier 
4583e12c5d1SDavid du Colombier void
asmidx(Adr * a,int base)4593e12c5d1SDavid du Colombier asmidx(Adr *a, int base)
4603e12c5d1SDavid du Colombier {
4613e12c5d1SDavid du Colombier 	int i;
4623e12c5d1SDavid du Colombier 
4633e12c5d1SDavid du Colombier 	switch(a->index) {
4643e12c5d1SDavid du Colombier 	default:
4653e12c5d1SDavid du Colombier 		goto bad;
4663e12c5d1SDavid du Colombier 
4673e12c5d1SDavid du Colombier 	case D_NONE:
4683e12c5d1SDavid du Colombier 		i = 4 << 3;
4693e12c5d1SDavid du Colombier 		goto bas;
4703e12c5d1SDavid du Colombier 
4713e12c5d1SDavid du Colombier 	case D_AX:
4723e12c5d1SDavid du Colombier 	case D_CX:
4733e12c5d1SDavid du Colombier 	case D_DX:
4743e12c5d1SDavid du Colombier 	case D_BX:
4753e12c5d1SDavid du Colombier 	case D_BP:
4763e12c5d1SDavid du Colombier 	case D_SI:
4773e12c5d1SDavid du Colombier 	case D_DI:
4783e12c5d1SDavid du Colombier 		i = reg[a->index] << 3;
4793e12c5d1SDavid du Colombier 		break;
4803e12c5d1SDavid du Colombier 	}
4813e12c5d1SDavid du Colombier 	switch(a->scale) {
4823e12c5d1SDavid du Colombier 	default:
4833e12c5d1SDavid du Colombier 		goto bad;
4843e12c5d1SDavid du Colombier 	case 1:
4853e12c5d1SDavid du Colombier 		break;
4863e12c5d1SDavid du Colombier 	case 2:
4873e12c5d1SDavid du Colombier 		i |= (1<<6);
4883e12c5d1SDavid du Colombier 		break;
4893e12c5d1SDavid du Colombier 	case 4:
4903e12c5d1SDavid du Colombier 		i |= (2<<6);
4913e12c5d1SDavid du Colombier 		break;
4923e12c5d1SDavid du Colombier 	case 8:
4933e12c5d1SDavid du Colombier 		i |= (3<<6);
4943e12c5d1SDavid du Colombier 		break;
4953e12c5d1SDavid du Colombier 	}
4963e12c5d1SDavid du Colombier bas:
4973e12c5d1SDavid du Colombier 	switch(base) {
4983e12c5d1SDavid du Colombier 	default:
4993e12c5d1SDavid du Colombier 		goto bad;
5003e12c5d1SDavid du Colombier 	case D_NONE:	/* must be mod=00 */
5013e12c5d1SDavid du Colombier 		i |= 5;
5023e12c5d1SDavid du Colombier 		break;
5033e12c5d1SDavid du Colombier 	case D_AX:
5043e12c5d1SDavid du Colombier 	case D_CX:
5053e12c5d1SDavid du Colombier 	case D_DX:
5063e12c5d1SDavid du Colombier 	case D_BX:
5073e12c5d1SDavid du Colombier 	case D_SP:
508375daca8SDavid du Colombier 	case D_BP:
5093e12c5d1SDavid du Colombier 	case D_SI:
5103e12c5d1SDavid du Colombier 	case D_DI:
5113e12c5d1SDavid du Colombier 		i |= reg[base];
5123e12c5d1SDavid du Colombier 		break;
5133e12c5d1SDavid du Colombier 	}
5143e12c5d1SDavid du Colombier 	*andptr++ = i;
5153e12c5d1SDavid du Colombier 	return;
5163e12c5d1SDavid du Colombier bad:
5176b6b9ac8SDavid du Colombier 	diag("asmidx: bad address %D", a);
5183e12c5d1SDavid du Colombier 	*andptr++ = 0;
5193e12c5d1SDavid du Colombier 	return;
5203e12c5d1SDavid du Colombier }
5213e12c5d1SDavid du Colombier 
5229a747e4fSDavid du Colombier static void
put4(long v)5239a747e4fSDavid du Colombier put4(long v)
5249a747e4fSDavid du Colombier {
525375daca8SDavid du Colombier 	if(dlm && curp != P && reloca != nil){
526375daca8SDavid du Colombier 		dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
5279a747e4fSDavid du Colombier 		reloca = nil;
5289a747e4fSDavid du Colombier 	}
5299a747e4fSDavid du Colombier 	andptr[0] = v;
5309a747e4fSDavid du Colombier 	andptr[1] = v>>8;
5319a747e4fSDavid du Colombier 	andptr[2] = v>>16;
5329a747e4fSDavid du Colombier 	andptr[3] = v>>24;
5339a747e4fSDavid du Colombier 	andptr += 4;
5349a747e4fSDavid du Colombier }
5359a747e4fSDavid du Colombier 
5363e12c5d1SDavid du Colombier long
vaddr(Adr * a)5373e12c5d1SDavid du Colombier vaddr(Adr *a)
5383e12c5d1SDavid du Colombier {
5393e12c5d1SDavid du Colombier 	int t;
5403e12c5d1SDavid du Colombier 	long v;
5419a747e4fSDavid du Colombier 	Sym *s;
5423e12c5d1SDavid du Colombier 
5433e12c5d1SDavid du Colombier 	t = a->type;
5443e12c5d1SDavid du Colombier 	v = a->offset;
5453e12c5d1SDavid du Colombier 	if(t == D_ADDR)
5463e12c5d1SDavid du Colombier 		t = a->index;
5473e12c5d1SDavid du Colombier 	switch(t) {
5483e12c5d1SDavid du Colombier 	case D_STATIC:
5493e12c5d1SDavid du Colombier 	case D_EXTERN:
5509a747e4fSDavid du Colombier 		s = a->sym;
5519a747e4fSDavid du Colombier 		if(s != nil) {
552375daca8SDavid du Colombier 			if(dlm && curp != P)
5539a747e4fSDavid du Colombier 				reloca = a;
5549a747e4fSDavid du Colombier 			switch(s->type) {
5559a747e4fSDavid du Colombier 			case SUNDEF:
556375daca8SDavid du Colombier 				ckoff(s, v);
557219b2ee8SDavid du Colombier 			case STEXT:
558219b2ee8SDavid du Colombier 			case SCONST:
5599a747e4fSDavid du Colombier 				v += s->value;
560219b2ee8SDavid du Colombier 				break;
561219b2ee8SDavid du Colombier 			default:
5629a747e4fSDavid du Colombier 				v += INITDAT + s->value;
5633e12c5d1SDavid du Colombier 			}
5643e12c5d1SDavid du Colombier 		}
565219b2ee8SDavid du Colombier 	}
5663e12c5d1SDavid du Colombier 	return v;
5673e12c5d1SDavid du Colombier }
5683e12c5d1SDavid du Colombier 
5693e12c5d1SDavid du Colombier void
asmand(Adr * a,int r)5703e12c5d1SDavid du Colombier asmand(Adr *a, int r)
5713e12c5d1SDavid du Colombier {
5723e12c5d1SDavid du Colombier 	long v;
5733e12c5d1SDavid du Colombier 	int t;
5743e12c5d1SDavid du Colombier 	Adr aa;
5753e12c5d1SDavid du Colombier 
5763e12c5d1SDavid du Colombier 	v = a->offset;
5773e12c5d1SDavid du Colombier 	t = a->type;
5783e12c5d1SDavid du Colombier 	if(a->index != D_NONE) {
5793e12c5d1SDavid du Colombier 		if(t >= D_INDIR) {
5803e12c5d1SDavid du Colombier 			t -= D_INDIR;
5813e12c5d1SDavid du Colombier 			if(t == D_NONE) {
5823e12c5d1SDavid du Colombier 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
5833e12c5d1SDavid du Colombier 				asmidx(a, t);
5849a747e4fSDavid du Colombier 				put4(v);
5853e12c5d1SDavid du Colombier 				return;
5863e12c5d1SDavid du Colombier 			}
587375daca8SDavid du Colombier 			if(v == 0 && t != D_BP) {
5883e12c5d1SDavid du Colombier 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
5893e12c5d1SDavid du Colombier 				asmidx(a, t);
5903e12c5d1SDavid du Colombier 				return;
5913e12c5d1SDavid du Colombier 			}
5923e12c5d1SDavid du Colombier 			if(v >= -128 && v < 128) {
5933e12c5d1SDavid du Colombier 				*andptr++ = (1 << 6) | (4 << 0) | (r << 3);
5943e12c5d1SDavid du Colombier 				asmidx(a, t);
5953e12c5d1SDavid du Colombier 				*andptr++ = v;
5963e12c5d1SDavid du Colombier 				return;
5973e12c5d1SDavid du Colombier 			}
5983e12c5d1SDavid du Colombier 			*andptr++ = (2 << 6) | (4 << 0) | (r << 3);
5993e12c5d1SDavid du Colombier 			asmidx(a, t);
6009a747e4fSDavid du Colombier 			put4(v);
6013e12c5d1SDavid du Colombier 			return;
6023e12c5d1SDavid du Colombier 		}
6033e12c5d1SDavid du Colombier 		switch(t) {
6043e12c5d1SDavid du Colombier 		default:
6053e12c5d1SDavid du Colombier 			goto bad;
6063e12c5d1SDavid du Colombier 		case D_STATIC:
6073e12c5d1SDavid du Colombier 		case D_EXTERN:
6083e12c5d1SDavid du Colombier 			aa.type = D_NONE+D_INDIR;
6093e12c5d1SDavid du Colombier 			break;
6103e12c5d1SDavid du Colombier 		case D_AUTO:
6113e12c5d1SDavid du Colombier 		case D_PARAM:
6123e12c5d1SDavid du Colombier 			aa.type = D_SP+D_INDIR;
6133e12c5d1SDavid du Colombier 			break;
6143e12c5d1SDavid du Colombier 		}
6153e12c5d1SDavid du Colombier 		aa.offset = vaddr(a);
6163e12c5d1SDavid du Colombier 		aa.index = a->index;
6173e12c5d1SDavid du Colombier 		aa.scale = a->scale;
6183e12c5d1SDavid du Colombier 		asmand(&aa, r);
6193e12c5d1SDavid du Colombier 		return;
6203e12c5d1SDavid du Colombier 	}
6213e12c5d1SDavid du Colombier 	if(t >= D_AL && t <= D_F0+7) {
6223e12c5d1SDavid du Colombier 		if(v)
6233e12c5d1SDavid du Colombier 			goto bad;
6243e12c5d1SDavid du Colombier 		*andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
6253e12c5d1SDavid du Colombier 		return;
6263e12c5d1SDavid du Colombier 	}
6273e12c5d1SDavid du Colombier 	if(t >= D_INDIR) {
6283e12c5d1SDavid du Colombier 		t -= D_INDIR;
6296520663fSDavid du Colombier 		if(t == D_NONE || D_CS <= t && t <= D_GS) {
6309a747e4fSDavid du Colombier 			*andptr++ = (0 << 6) | (5 << 0) | (r << 3);
6319a747e4fSDavid du Colombier 			put4(v);
6323e12c5d1SDavid du Colombier 			return;
6333e12c5d1SDavid du Colombier 		}
6343e12c5d1SDavid du Colombier 		if(t == D_SP) {
6353e12c5d1SDavid du Colombier 			if(v == 0) {
6363e12c5d1SDavid du Colombier 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
6373e12c5d1SDavid du Colombier 				asmidx(a, D_SP);
6383e12c5d1SDavid du Colombier 				return;
6393e12c5d1SDavid du Colombier 			}
6403e12c5d1SDavid du Colombier 			if(v >= -128 && v < 128) {
6413e12c5d1SDavid du Colombier 				*andptr++ = (1 << 6) | (4 << 0) | (r << 3);
6423e12c5d1SDavid du Colombier 				asmidx(a, D_SP);
6433e12c5d1SDavid du Colombier 				*andptr++ = v;
6443e12c5d1SDavid du Colombier 				return;
6453e12c5d1SDavid du Colombier 			}
6463e12c5d1SDavid du Colombier 			*andptr++ = (2 << 6) | (4 << 0) | (r << 3);
6473e12c5d1SDavid du Colombier 			asmidx(a, D_SP);
6489a747e4fSDavid du Colombier 			put4(v);
6493e12c5d1SDavid du Colombier 			return;
6503e12c5d1SDavid du Colombier 		}
6513e12c5d1SDavid du Colombier 		if(t >= D_AX && t <= D_DI) {
6523e12c5d1SDavid du Colombier 			if(v == 0 && t != D_BP) {
6533e12c5d1SDavid du Colombier 				*andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
6543e12c5d1SDavid du Colombier 				return;
6553e12c5d1SDavid du Colombier 			}
6563e12c5d1SDavid du Colombier 			if(v >= -128 && v < 128) {
6573e12c5d1SDavid du Colombier 				andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
6583e12c5d1SDavid du Colombier 				andptr[1] = v;
6593e12c5d1SDavid du Colombier 				andptr += 2;
6603e12c5d1SDavid du Colombier 				return;
6613e12c5d1SDavid du Colombier 			}
6629a747e4fSDavid du Colombier 			*andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
6639a747e4fSDavid du Colombier 			put4(v);
6643e12c5d1SDavid du Colombier 			return;
6653e12c5d1SDavid du Colombier 		}
6663e12c5d1SDavid du Colombier 		goto bad;
6673e12c5d1SDavid du Colombier 	}
6683e12c5d1SDavid du Colombier 	switch(a->type) {
6693e12c5d1SDavid du Colombier 	default:
6703e12c5d1SDavid du Colombier 		goto bad;
6713e12c5d1SDavid du Colombier 	case D_STATIC:
6723e12c5d1SDavid du Colombier 	case D_EXTERN:
6733e12c5d1SDavid du Colombier 		aa.type = D_NONE+D_INDIR;
6743e12c5d1SDavid du Colombier 		break;
6753e12c5d1SDavid du Colombier 	case D_AUTO:
6763e12c5d1SDavid du Colombier 	case D_PARAM:
6773e12c5d1SDavid du Colombier 		aa.type = D_SP+D_INDIR;
6783e12c5d1SDavid du Colombier 		break;
6793e12c5d1SDavid du Colombier 	}
6803e12c5d1SDavid du Colombier 	aa.index = D_NONE;
6813e12c5d1SDavid du Colombier 	aa.scale = 1;
6823e12c5d1SDavid du Colombier 	aa.offset = vaddr(a);
6833e12c5d1SDavid du Colombier 	asmand(&aa, r);
6843e12c5d1SDavid du Colombier 	return;
6853e12c5d1SDavid du Colombier bad:
6866b6b9ac8SDavid du Colombier 	diag("asmand: bad address %D", a);
6873e12c5d1SDavid du Colombier 	return;
6883e12c5d1SDavid du Colombier }
6893e12c5d1SDavid du Colombier 
6903e12c5d1SDavid du Colombier #define	E	0xff
6913e12c5d1SDavid du Colombier uchar	ymovtab[] =
6923e12c5d1SDavid du Colombier {
6933e12c5d1SDavid du Colombier /* push */
6943e12c5d1SDavid du Colombier 	APUSHL,	Ycs,	Ynone,	0,	0x0e,E,0,0,
6953e12c5d1SDavid du Colombier 	APUSHL,	Yss,	Ynone,	0,	0x16,E,0,0,
6963e12c5d1SDavid du Colombier 	APUSHL,	Yds,	Ynone,	0,	0x1e,E,0,0,
6973e12c5d1SDavid du Colombier 	APUSHL,	Yes,	Ynone,	0,	0x06,E,0,0,
6983e12c5d1SDavid du Colombier 	APUSHL,	Yfs,	Ynone,	0,	0x0f,0xa0,E,0,
6993e12c5d1SDavid du Colombier 	APUSHL,	Ygs,	Ynone,	0,	0x0f,0xa8,E,0,
7003e12c5d1SDavid du Colombier 
7013e12c5d1SDavid du Colombier 	APUSHW,	Ycs,	Ynone,	0,	Pe,0x0e,E,0,
7023e12c5d1SDavid du Colombier 	APUSHW,	Yss,	Ynone,	0,	Pe,0x16,E,0,
7033e12c5d1SDavid du Colombier 	APUSHW,	Yds,	Ynone,	0,	Pe,0x1e,E,0,
7043e12c5d1SDavid du Colombier 	APUSHW,	Yes,	Ynone,	0,	Pe,0x06,E,0,
7053e12c5d1SDavid du Colombier 	APUSHW,	Yfs,	Ynone,	0,	Pe,0x0f,0xa0,E,
7063e12c5d1SDavid du Colombier 	APUSHW,	Ygs,	Ynone,	0,	Pe,0x0f,0xa8,E,
7073e12c5d1SDavid du Colombier 
7083e12c5d1SDavid du Colombier /* pop */
7093e12c5d1SDavid du Colombier 	APOPL,	Ynone,	Yds,	0,	0x1f,E,0,0,
7103e12c5d1SDavid du Colombier 	APOPL,	Ynone,	Yes,	0,	0x07,E,0,0,
7113e12c5d1SDavid du Colombier 	APOPL,	Ynone,	Yss,	0,	0x17,E,0,0,
7123e12c5d1SDavid du Colombier 	APOPL,	Ynone,	Yfs,	0,	0x0f,0xa1,E,0,
7133e12c5d1SDavid du Colombier 	APOPL,	Ynone,	Ygs,	0,	0x0f,0xa9,E,0,
7143e12c5d1SDavid du Colombier 
7153e12c5d1SDavid du Colombier 	APOPW,	Ynone,	Yds,	0,	Pe,0x1f,E,0,
7163e12c5d1SDavid du Colombier 	APOPW,	Ynone,	Yes,	0,	Pe,0x07,E,0,
7173e12c5d1SDavid du Colombier 	APOPW,	Ynone,	Yss,	0,	Pe,0x17,E,0,
7183e12c5d1SDavid du Colombier 	APOPW,	Ynone,	Yfs,	0,	Pe,0x0f,0xa1,E,
7193e12c5d1SDavid du Colombier 	APOPW,	Ynone,	Ygs,	0,	Pe,0x0f,0xa9,E,
7203e12c5d1SDavid du Colombier 
7213e12c5d1SDavid du Colombier /* mov seg */
7223e12c5d1SDavid du Colombier 	AMOVW,	Yes,	Yml,	1,	0x8c,0,0,0,
7233e12c5d1SDavid du Colombier 	AMOVW,	Ycs,	Yml,	1,	0x8c,1,0,0,
7243e12c5d1SDavid du Colombier 	AMOVW,	Yss,	Yml,	1,	0x8c,2,0,0,
7253e12c5d1SDavid du Colombier 	AMOVW,	Yds,	Yml,	1,	0x8c,3,0,0,
7263e12c5d1SDavid du Colombier 	AMOVW,	Yfs,	Yml,	1,	0x8c,4,0,0,
7273e12c5d1SDavid du Colombier 	AMOVW,	Ygs,	Yml,	1,	0x8c,5,0,0,
7283e12c5d1SDavid du Colombier 
7293e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Yes,	2,	0x8e,0,0,0,
7303e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Ycs,	2,	0x8e,1,0,0,
7313e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Yss,	2,	0x8e,2,0,0,
7323e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Yds,	2,	0x8e,3,0,0,
7333e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Yfs,	2,	0x8e,4,0,0,
7343e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Ygs,	2,	0x8e,5,0,0,
7353e12c5d1SDavid du Colombier 
7363e12c5d1SDavid du Colombier /* mov cr */
7373e12c5d1SDavid du Colombier 	AMOVL,	Ycr0,	Yml,	3,	0x0f,0x20,0,0,
7383e12c5d1SDavid du Colombier 	AMOVL,	Ycr2,	Yml,	3,	0x0f,0x20,2,0,
7393e12c5d1SDavid du Colombier 	AMOVL,	Ycr3,	Yml,	3,	0x0f,0x20,3,0,
7407dd7cddfSDavid du Colombier 	AMOVL,	Ycr4,	Yml,	3,	0x0f,0x20,4,0,
7413e12c5d1SDavid du Colombier 
7423e12c5d1SDavid du Colombier 	AMOVL,	Yml,	Ycr0,	4,	0x0f,0x22,0,0,
7433e12c5d1SDavid du Colombier 	AMOVL,	Yml,	Ycr2,	4,	0x0f,0x22,2,0,
7443e12c5d1SDavid du Colombier 	AMOVL,	Yml,	Ycr3,	4,	0x0f,0x22,3,0,
7457dd7cddfSDavid du Colombier 	AMOVL,	Yml,	Ycr4,	4,	0x0f,0x22,4,0,
7463e12c5d1SDavid du Colombier 
7473e12c5d1SDavid du Colombier /* mov dr */
7483e12c5d1SDavid du Colombier 	AMOVL,	Ydr0,	Yml,	3,	0x0f,0x21,0,0,
7493e12c5d1SDavid du Colombier 	AMOVL,	Ydr6,	Yml,	3,	0x0f,0x21,6,0,
7503e12c5d1SDavid du Colombier 	AMOVL,	Ydr7,	Yml,	3,	0x0f,0x21,7,0,
7513e12c5d1SDavid du Colombier 
7523e12c5d1SDavid du Colombier 	AMOVL,	Yml,	Ydr0,	4,	0x0f,0x23,0,0,
7533e12c5d1SDavid du Colombier 	AMOVL,	Yml,	Ydr6,	4,	0x0f,0x23,6,0,
7543e12c5d1SDavid du Colombier 	AMOVL,	Yml,	Ydr7,	4,	0x0f,0x23,7,0,
7553e12c5d1SDavid du Colombier 
7563e12c5d1SDavid du Colombier /* mov tr */
7573e12c5d1SDavid du Colombier 	AMOVL,	Ytr6,	Yml,	3,	0x0f,0x24,6,0,
7583e12c5d1SDavid du Colombier 	AMOVL,	Ytr7,	Yml,	3,	0x0f,0x24,7,0,
7593e12c5d1SDavid du Colombier 
7603e12c5d1SDavid du Colombier 	AMOVL,	Yml,	Ytr6,	4,	0x0f,0x26,6,E,
7613e12c5d1SDavid du Colombier 	AMOVL,	Yml,	Ytr7,	4,	0x0f,0x26,7,E,
7623e12c5d1SDavid du Colombier 
7633e12c5d1SDavid du Colombier /* lgdt, sgdt, lidt, sidt */
7643e12c5d1SDavid du Colombier 	AMOVL,	Ym,	Ygdtr,	4,	0x0f,0x01,2,0,
7653e12c5d1SDavid du Colombier 	AMOVL,	Ygdtr,	Ym,	3,	0x0f,0x01,0,0,
7663e12c5d1SDavid du Colombier 	AMOVL,	Ym,	Yidtr,	4,	0x0f,0x01,3,0,
7673e12c5d1SDavid du Colombier 	AMOVL,	Yidtr,	Ym,	3,	0x0f,0x01,1,0,
7683e12c5d1SDavid du Colombier 
7693e12c5d1SDavid du Colombier /* lldt, sldt */
7703e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Yldtr,	4,	0x0f,0x00,2,0,
7713e12c5d1SDavid du Colombier 	AMOVW,	Yldtr,	Yml,	3,	0x0f,0x00,0,0,
7723e12c5d1SDavid du Colombier 
7733e12c5d1SDavid du Colombier /* lmsw, smsw */
7743e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Ymsw,	4,	0x0f,0x01,6,0,
7753e12c5d1SDavid du Colombier 	AMOVW,	Ymsw,	Yml,	3,	0x0f,0x01,4,0,
7763e12c5d1SDavid du Colombier 
7773e12c5d1SDavid du Colombier /* ltr, str */
7783e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Ytask,	4,	0x0f,0x00,3,0,
7793e12c5d1SDavid du Colombier 	AMOVW,	Ytask,	Yml,	3,	0x0f,0x00,1,0,
7803e12c5d1SDavid du Colombier 
7813e12c5d1SDavid du Colombier /* load full pointer */
7823e12c5d1SDavid du Colombier 	AMOVL,	Yml,	Ycol,	5,	0,0,0,0,
7833e12c5d1SDavid du Colombier 	AMOVW,	Yml,	Ycol,	5,	Pe,0,0,0,
7843e12c5d1SDavid du Colombier 
7853e12c5d1SDavid du Colombier /* double shift */
7863e12c5d1SDavid du Colombier 	ASHLL,	Ycol,	Yml,	6,	0xa4,0xa5,0,0,
7873e12c5d1SDavid du Colombier 	ASHRL,	Ycol,	Yml,	6,	0xac,0xad,0,0,
7883e12c5d1SDavid du Colombier 
789282e677fSDavid du Colombier /* extra imul */
7906520663fSDavid du Colombier 	AIMULW,	Yml,	Yrl,	7,	Pq,0xaf,0,0,
791282e677fSDavid du Colombier 	AIMULL,	Yml,	Yrl,	7,	Pm,0xaf,0,0,
7923e12c5d1SDavid du Colombier 	0
7933e12c5d1SDavid du Colombier };
7943e12c5d1SDavid du Colombier 
7953e12c5d1SDavid du Colombier int
isax(Adr * a)7963e12c5d1SDavid du Colombier isax(Adr *a)
7973e12c5d1SDavid du Colombier {
7983e12c5d1SDavid du Colombier 
7993e12c5d1SDavid du Colombier 	switch(a->type) {
8003e12c5d1SDavid du Colombier 	case D_AX:
8013e12c5d1SDavid du Colombier 	case D_AL:
8023e12c5d1SDavid du Colombier 	case D_AH:
8033e12c5d1SDavid du Colombier 	case D_INDIR+D_AX:
8043e12c5d1SDavid du Colombier 		return 1;
8053e12c5d1SDavid du Colombier 	}
8063e12c5d1SDavid du Colombier 	if(a->index == D_AX)
8073e12c5d1SDavid du Colombier 		return 1;
8083e12c5d1SDavid du Colombier 	return 0;
8093e12c5d1SDavid du Colombier }
8103e12c5d1SDavid du Colombier 
8113e12c5d1SDavid du Colombier void
subreg(Prog * p,int from,int to)8123e12c5d1SDavid du Colombier subreg(Prog *p, int from, int to)
8133e12c5d1SDavid du Colombier {
8143e12c5d1SDavid du Colombier 
8153e12c5d1SDavid du Colombier 	if(debug['Q'])
8163e12c5d1SDavid du Colombier 		print("\n%P	s/%R/%R/\n", p, from, to);
8173e12c5d1SDavid du Colombier 
8183e12c5d1SDavid du Colombier 	if(p->from.type == from)
8193e12c5d1SDavid du Colombier 		p->from.type = to;
8203e12c5d1SDavid du Colombier 	if(p->to.type == from)
8213e12c5d1SDavid du Colombier 		p->to.type = to;
8223e12c5d1SDavid du Colombier 
8233e12c5d1SDavid du Colombier 	if(p->from.index == from)
8243e12c5d1SDavid du Colombier 		p->from.index = to;
8253e12c5d1SDavid du Colombier 	if(p->to.index == from)
8263e12c5d1SDavid du Colombier 		p->to.index = to;
8273e12c5d1SDavid du Colombier 
8283e12c5d1SDavid du Colombier 	from += D_INDIR;
8293e12c5d1SDavid du Colombier 	if(p->from.type == from)
8303e12c5d1SDavid du Colombier 		p->from.type = to+D_INDIR;
8313e12c5d1SDavid du Colombier 	if(p->to.type == from)
8323e12c5d1SDavid du Colombier 		p->to.type = to+D_INDIR;
8333e12c5d1SDavid du Colombier 
8343e12c5d1SDavid du Colombier 	if(debug['Q'])
8353e12c5d1SDavid du Colombier 		print("%P\n", p);
8363e12c5d1SDavid du Colombier }
8373e12c5d1SDavid du Colombier 
8383e12c5d1SDavid du Colombier void
doasm(Prog * p)8393e12c5d1SDavid du Colombier doasm(Prog *p)
8403e12c5d1SDavid du Colombier {
8413e12c5d1SDavid du Colombier 	Optab *o;
8423e12c5d1SDavid du Colombier 	Prog *q, pp;
8433e12c5d1SDavid du Colombier 	uchar *t;
8443e12c5d1SDavid du Colombier 	int z, op, ft, tt;
8456520663fSDavid du Colombier 	long v, pre;
8466520663fSDavid du Colombier 
8476520663fSDavid du Colombier 	pre = prefixof(&p->from);
8486520663fSDavid du Colombier 	if(pre)
8496520663fSDavid du Colombier 		*andptr++ = pre;
8506520663fSDavid du Colombier 	pre = prefixof(&p->to);
8516520663fSDavid du Colombier 	if(pre)
8526520663fSDavid du Colombier 		*andptr++ = pre;
8533e12c5d1SDavid du Colombier 
8543e12c5d1SDavid du Colombier 	o = &optab[p->as];
8553e12c5d1SDavid du Colombier 	ft = oclass(&p->from) * Ymax;
8563e12c5d1SDavid du Colombier 	tt = oclass(&p->to) * Ymax;
8573e12c5d1SDavid du Colombier 	t = o->ytab;
8583e12c5d1SDavid du Colombier 	if(t == 0) {
8596b6b9ac8SDavid du Colombier 		diag("asmins: noproto %P", p);
8603e12c5d1SDavid du Colombier 		return;
8613e12c5d1SDavid du Colombier 	}
8623e12c5d1SDavid du Colombier 	for(z=0; *t; z+=t[3],t+=4)
8633e12c5d1SDavid du Colombier 		if(ycover[ft+t[0]])
8643e12c5d1SDavid du Colombier 		if(ycover[tt+t[1]])
8653e12c5d1SDavid du Colombier 			goto found;
8663e12c5d1SDavid du Colombier 	goto domov;
8673e12c5d1SDavid du Colombier 
8683e12c5d1SDavid du Colombier found:
8693e12c5d1SDavid du Colombier 	switch(o->prefix) {
8703e12c5d1SDavid du Colombier 	case Pq:	/* 16 bit escape and opcode escape */
8713e12c5d1SDavid du Colombier 		*andptr++ = Pe;
8723e12c5d1SDavid du Colombier 		*andptr++ = Pm;
8733e12c5d1SDavid du Colombier 		break;
8743e12c5d1SDavid du Colombier 
8753e12c5d1SDavid du Colombier 	case Pm:	/* opcode escape */
8763e12c5d1SDavid du Colombier 		*andptr++ = Pm;
8773e12c5d1SDavid du Colombier 		break;
8783e12c5d1SDavid du Colombier 
8793e12c5d1SDavid du Colombier 	case Pe:	/* 16 bit escape */
8803e12c5d1SDavid du Colombier 		*andptr++ = Pe;
8813e12c5d1SDavid du Colombier 		break;
8823e12c5d1SDavid du Colombier 
8833e12c5d1SDavid du Colombier 	case Pb:	/* botch */
8843e12c5d1SDavid du Colombier 		break;
8853e12c5d1SDavid du Colombier 	}
8863e12c5d1SDavid du Colombier 	v = vaddr(&p->from);
8873e12c5d1SDavid du Colombier 	op = o->op[z];
8883e12c5d1SDavid du Colombier 	switch(t[2]) {
8893e12c5d1SDavid du Colombier 	default:
8906b6b9ac8SDavid du Colombier 		diag("asmins: unknown z %d %P", t[2], p);
8913e12c5d1SDavid du Colombier 		return;
8923e12c5d1SDavid du Colombier 
8933e12c5d1SDavid du Colombier 	case Zpseudo:
8943e12c5d1SDavid du Colombier 		break;
8953e12c5d1SDavid du Colombier 
8963e12c5d1SDavid du Colombier 	case Zlit:
8973e12c5d1SDavid du Colombier 		for(; op = o->op[z]; z++)
8983e12c5d1SDavid du Colombier 			*andptr++ = op;
8993e12c5d1SDavid du Colombier 		break;
9003e12c5d1SDavid du Colombier 
9013e12c5d1SDavid du Colombier 	case Zm_r:
9023e12c5d1SDavid du Colombier 		*andptr++ = op;
9033e12c5d1SDavid du Colombier 		asmand(&p->from, reg[p->to.type]);
9043e12c5d1SDavid du Colombier 		break;
9053e12c5d1SDavid du Colombier 
906219b2ee8SDavid du Colombier 	case Zaut_r:
907219b2ee8SDavid du Colombier 		*andptr++ = 0x8d;	/* leal */
908219b2ee8SDavid du Colombier 		if(p->from.type != D_ADDR)
909219b2ee8SDavid du Colombier 			diag("asmins: Zaut sb type ADDR");
910219b2ee8SDavid du Colombier 		p->from.type = p->from.index;
911219b2ee8SDavid du Colombier 		p->from.index = D_NONE;
912219b2ee8SDavid du Colombier 		asmand(&p->from, reg[p->to.type]);
913219b2ee8SDavid du Colombier 		p->from.index = p->from.type;
914219b2ee8SDavid du Colombier 		p->from.type = D_ADDR;
915219b2ee8SDavid du Colombier 		break;
916219b2ee8SDavid du Colombier 
9173e12c5d1SDavid du Colombier 	case Zm_o:
9183e12c5d1SDavid du Colombier 		*andptr++ = op;
9193e12c5d1SDavid du Colombier 		asmand(&p->from, o->op[z+1]);
9203e12c5d1SDavid du Colombier 		break;
9213e12c5d1SDavid du Colombier 
9223e12c5d1SDavid du Colombier 	case Zr_m:
9233e12c5d1SDavid du Colombier 		*andptr++ = op;
9243e12c5d1SDavid du Colombier 		asmand(&p->to, reg[p->from.type]);
9253e12c5d1SDavid du Colombier 		break;
9263e12c5d1SDavid du Colombier 
9273e12c5d1SDavid du Colombier 	case Zo_m:
9283e12c5d1SDavid du Colombier 		*andptr++ = op;
9293e12c5d1SDavid du Colombier 		asmand(&p->to, o->op[z+1]);
9303e12c5d1SDavid du Colombier 		break;
9313e12c5d1SDavid du Colombier 
9323e12c5d1SDavid du Colombier 	case Zm_ibo:
9333e12c5d1SDavid du Colombier 		v = vaddr(&p->to);
9343e12c5d1SDavid du Colombier 		*andptr++ = op;
9353e12c5d1SDavid du Colombier 		asmand(&p->from, o->op[z+1]);
9363e12c5d1SDavid du Colombier 		*andptr++ = v;
9373e12c5d1SDavid du Colombier 		break;
9383e12c5d1SDavid du Colombier 
9393e12c5d1SDavid du Colombier 	case Zibo_m:
9403e12c5d1SDavid du Colombier 		*andptr++ = op;
9413e12c5d1SDavid du Colombier 		asmand(&p->to, o->op[z+1]);
9423e12c5d1SDavid du Colombier 		*andptr++ = v;
9433e12c5d1SDavid du Colombier 		break;
9443e12c5d1SDavid du Colombier 
9453e12c5d1SDavid du Colombier 	case Z_ib:
9463e12c5d1SDavid du Colombier 		v = vaddr(&p->to);
9473e12c5d1SDavid du Colombier 	case Zib_:
9483e12c5d1SDavid du Colombier 		*andptr++ = op;
9493e12c5d1SDavid du Colombier 		*andptr++ = v;
9503e12c5d1SDavid du Colombier 		break;
9513e12c5d1SDavid du Colombier 
9523e12c5d1SDavid du Colombier 	case Zib_rp:
9533e12c5d1SDavid du Colombier 		*andptr++ = op + reg[p->to.type];
9543e12c5d1SDavid du Colombier 		*andptr++ = v;
9553e12c5d1SDavid du Colombier 		break;
9563e12c5d1SDavid du Colombier 
9573e12c5d1SDavid du Colombier 	case Zil_rp:
9583e12c5d1SDavid du Colombier 		*andptr++ = op + reg[p->to.type];
9599a747e4fSDavid du Colombier 		if(o->prefix == Pe) {
9603e12c5d1SDavid du Colombier 			*andptr++ = v;
9613e12c5d1SDavid du Colombier 			*andptr++ = v>>8;
9623e12c5d1SDavid du Colombier 		}
9639a747e4fSDavid du Colombier 		else
9649a747e4fSDavid du Colombier 			put4(v);
9659a747e4fSDavid du Colombier 		break;
9669a747e4fSDavid du Colombier 
9679a747e4fSDavid du Colombier 	case Zib_rr:
9689a747e4fSDavid du Colombier 		*andptr++ = op;
9699a747e4fSDavid du Colombier 		asmand(&p->to, reg[p->to.type]);
9709a747e4fSDavid du Colombier 		*andptr++ = v;
9713e12c5d1SDavid du Colombier 		break;
9723e12c5d1SDavid du Colombier 
9733e12c5d1SDavid du Colombier 	case Z_il:
9743e12c5d1SDavid du Colombier 		v = vaddr(&p->to);
9753e12c5d1SDavid du Colombier 	case Zil_:
9763e12c5d1SDavid du Colombier 		*andptr++ = op;
9779a747e4fSDavid du Colombier 		if(o->prefix == Pe) {
9783e12c5d1SDavid du Colombier 			*andptr++ = v;
9793e12c5d1SDavid du Colombier 			*andptr++ = v>>8;
9803e12c5d1SDavid du Colombier 		}
9819a747e4fSDavid du Colombier 		else
9829a747e4fSDavid du Colombier 			put4(v);
9833e12c5d1SDavid du Colombier 		break;
9843e12c5d1SDavid du Colombier 
9853e12c5d1SDavid du Colombier 	case Zm_ilo:
9863e12c5d1SDavid du Colombier 		v = vaddr(&p->to);
9873e12c5d1SDavid du Colombier 		*andptr++ = op;
9883e12c5d1SDavid du Colombier 		asmand(&p->from, o->op[z+1]);
9899a747e4fSDavid du Colombier 		if(o->prefix == Pe) {
9903e12c5d1SDavid du Colombier 			*andptr++ = v;
9913e12c5d1SDavid du Colombier 			*andptr++ = v>>8;
9923e12c5d1SDavid du Colombier 		}
9939a747e4fSDavid du Colombier 		else
9949a747e4fSDavid du Colombier 			put4(v);
9953e12c5d1SDavid du Colombier 		break;
9963e12c5d1SDavid du Colombier 
9973e12c5d1SDavid du Colombier 	case Zilo_m:
9983e12c5d1SDavid du Colombier 		*andptr++ = op;
9993e12c5d1SDavid du Colombier 		asmand(&p->to, o->op[z+1]);
10009a747e4fSDavid du Colombier 		if(o->prefix == Pe) {
10013e12c5d1SDavid du Colombier 			*andptr++ = v;
10023e12c5d1SDavid du Colombier 			*andptr++ = v>>8;
10033e12c5d1SDavid du Colombier 		}
10049a747e4fSDavid du Colombier 		else
10059a747e4fSDavid du Colombier 			put4(v);
10069a747e4fSDavid du Colombier 		break;
10079a747e4fSDavid du Colombier 
10089a747e4fSDavid du Colombier 	case Zil_rr:
10099a747e4fSDavid du Colombier 		*andptr++ = op;
10109a747e4fSDavid du Colombier 		asmand(&p->to, reg[p->to.type]);
10119a747e4fSDavid du Colombier 		if(o->prefix == Pe) {
10129a747e4fSDavid du Colombier 			*andptr++ = v;
10139a747e4fSDavid du Colombier 			*andptr++ = v>>8;
10149a747e4fSDavid du Colombier 		}
10159a747e4fSDavid du Colombier 		else
10169a747e4fSDavid du Colombier 			put4(v);
10173e12c5d1SDavid du Colombier 		break;
10183e12c5d1SDavid du Colombier 
10193e12c5d1SDavid du Colombier 	case Z_rp:
10203e12c5d1SDavid du Colombier 		*andptr++ = op + reg[p->to.type];
10213e12c5d1SDavid du Colombier 		break;
10223e12c5d1SDavid du Colombier 
10233e12c5d1SDavid du Colombier 	case Zrp_:
10243e12c5d1SDavid du Colombier 		*andptr++ = op + reg[p->from.type];
10253e12c5d1SDavid du Colombier 		break;
10263e12c5d1SDavid du Colombier 
10273e12c5d1SDavid du Colombier 	case Zclr:
10283e12c5d1SDavid du Colombier 		*andptr++ = op;
10293e12c5d1SDavid du Colombier 		asmand(&p->to, reg[p->to.type]);
10303e12c5d1SDavid du Colombier 		break;
10313e12c5d1SDavid du Colombier 
10323e12c5d1SDavid du Colombier 	case Zbr:
10337dd7cddfSDavid du Colombier 		q = p->pcond;
10343e12c5d1SDavid du Colombier 		if(q) {
10353e12c5d1SDavid du Colombier 			v = q->pc - p->pc - 2;
10363e12c5d1SDavid du Colombier 			if(v >= -128 && v <= 127) {
10373e12c5d1SDavid du Colombier 				*andptr++ = op;
10383e12c5d1SDavid du Colombier 				*andptr++ = v;
10393e12c5d1SDavid du Colombier 			} else {
10403e12c5d1SDavid du Colombier 				v -= 6-2;
10413e12c5d1SDavid du Colombier 				*andptr++ = 0x0f;
10423e12c5d1SDavid du Colombier 				*andptr++ = o->op[z+1];
10433e12c5d1SDavid du Colombier 				*andptr++ = v;
10443e12c5d1SDavid du Colombier 				*andptr++ = v>>8;
10453e12c5d1SDavid du Colombier 				*andptr++ = v>>16;
10463e12c5d1SDavid du Colombier 				*andptr++ = v>>24;
10473e12c5d1SDavid du Colombier 			}
10483e12c5d1SDavid du Colombier 		}
10493e12c5d1SDavid du Colombier 		break;
10503e12c5d1SDavid du Colombier 
10513e12c5d1SDavid du Colombier 	case Zcall:
10527dd7cddfSDavid du Colombier 		q = p->pcond;
10533e12c5d1SDavid du Colombier 		if(q) {
10543e12c5d1SDavid du Colombier 			v = q->pc - p->pc - 5;
1055375daca8SDavid du Colombier 			if(dlm && curp != P && p->to.sym->type == SUNDEF){
1056375daca8SDavid du Colombier 				/* v = 0 - p->pc - 5; */
10579a747e4fSDavid du Colombier 				v = 0;
1058375daca8SDavid du Colombier 				ckoff(p->to.sym, v);
1059375daca8SDavid du Colombier 				v += p->to.sym->value;
1060375daca8SDavid du Colombier 				dynreloc(p->to.sym, p->pc+1, 0);
10619a747e4fSDavid du Colombier 			}
10623e12c5d1SDavid du Colombier 			*andptr++ = op;
10633e12c5d1SDavid du Colombier 			*andptr++ = v;
10643e12c5d1SDavid du Colombier 			*andptr++ = v>>8;
10653e12c5d1SDavid du Colombier 			*andptr++ = v>>16;
10663e12c5d1SDavid du Colombier 			*andptr++ = v>>24;
10673e12c5d1SDavid du Colombier 		}
10683e12c5d1SDavid du Colombier 		break;
10693e12c5d1SDavid du Colombier 
10703e12c5d1SDavid du Colombier 	case Zjmp:
10717dd7cddfSDavid du Colombier 		q = p->pcond;
10723e12c5d1SDavid du Colombier 		if(q) {
10733e12c5d1SDavid du Colombier 			v = q->pc - p->pc - 2;
10743e12c5d1SDavid du Colombier 			if(v >= -128 && v <= 127) {
10753e12c5d1SDavid du Colombier 				*andptr++ = op;
10763e12c5d1SDavid du Colombier 				*andptr++ = v;
10773e12c5d1SDavid du Colombier 			} else {
10783e12c5d1SDavid du Colombier 				v -= 5-2;
10793e12c5d1SDavid du Colombier 				*andptr++ = o->op[z+1];
10803e12c5d1SDavid du Colombier 				*andptr++ = v;
10813e12c5d1SDavid du Colombier 				*andptr++ = v>>8;
10823e12c5d1SDavid du Colombier 				*andptr++ = v>>16;
10833e12c5d1SDavid du Colombier 				*andptr++ = v>>24;
10843e12c5d1SDavid du Colombier 			}
10853e12c5d1SDavid du Colombier 		}
10863e12c5d1SDavid du Colombier 		break;
10873e12c5d1SDavid du Colombier 
10883e12c5d1SDavid du Colombier 	case Zloop:
10897dd7cddfSDavid du Colombier 		q = p->pcond;
10903e12c5d1SDavid du Colombier 		if(q) {
10913e12c5d1SDavid du Colombier 			v = q->pc - p->pc - 2;
1092b9d84512SDavid du Colombier 			if(v < -128 || v > 127)
10936b6b9ac8SDavid du Colombier 				diag("loop too far: %P", p);
10943e12c5d1SDavid du Colombier 			*andptr++ = op;
10953e12c5d1SDavid du Colombier 			*andptr++ = v;
10963e12c5d1SDavid du Colombier 		}
10973e12c5d1SDavid du Colombier 		break;
10983e12c5d1SDavid du Colombier 
10993e12c5d1SDavid du Colombier 	case Zbyte:
11003e12c5d1SDavid du Colombier 		*andptr++ = v;
11013e12c5d1SDavid du Colombier 		if(op > 1) {
11023e12c5d1SDavid du Colombier 			*andptr++ = v>>8;
11033e12c5d1SDavid du Colombier 			if(op > 2) {
11043e12c5d1SDavid du Colombier 				*andptr++ = v>>16;
11053e12c5d1SDavid du Colombier 				*andptr++ = v>>24;
11063e12c5d1SDavid du Colombier 			}
11073e12c5d1SDavid du Colombier 		}
11083e12c5d1SDavid du Colombier 		break;
11093e12c5d1SDavid du Colombier 
11103e12c5d1SDavid du Colombier 	case Zmov:
11113e12c5d1SDavid du Colombier 		goto domov;
11123e12c5d1SDavid du Colombier 	}
11133e12c5d1SDavid du Colombier 	return;
11143e12c5d1SDavid du Colombier 
11153e12c5d1SDavid du Colombier domov:
11163e12c5d1SDavid du Colombier 	for(t=ymovtab; *t; t+=8)
11173e12c5d1SDavid du Colombier 		if(p->as == t[0])
11183e12c5d1SDavid du Colombier 		if(ycover[ft+t[1]])
11193e12c5d1SDavid du Colombier 		if(ycover[tt+t[2]])
11203e12c5d1SDavid du Colombier 			goto mfound;
11213e12c5d1SDavid du Colombier bad:
11223e12c5d1SDavid du Colombier 	/*
11233e12c5d1SDavid du Colombier 	 * here, the assembly has failed.
11243e12c5d1SDavid du Colombier 	 * if its a byte instruction that has
11253e12c5d1SDavid du Colombier 	 * unaddressable registers, try to
11263e12c5d1SDavid du Colombier 	 * exchange registers and reissue the
11273e12c5d1SDavid du Colombier 	 * instruction with the operands renamed.
11283e12c5d1SDavid du Colombier 	 */
11293e12c5d1SDavid du Colombier 	pp = *p;
11303e12c5d1SDavid du Colombier 	z = p->from.type;
11313e12c5d1SDavid du Colombier 	if(z >= D_BP && z <= D_DI) {
11323e12c5d1SDavid du Colombier 		if(isax(&p->to)) {
11333e12c5d1SDavid du Colombier 			*andptr++ = 0x87;			/* xchg lhs,bx */
11343e12c5d1SDavid du Colombier 			asmand(&p->from, reg[D_BX]);
11353e12c5d1SDavid du Colombier 			subreg(&pp, z, D_BX);
11363e12c5d1SDavid du Colombier 			doasm(&pp);
11373e12c5d1SDavid du Colombier 			*andptr++ = 0x87;			/* xchg lhs,bx */
11383e12c5d1SDavid du Colombier 			asmand(&p->from, reg[D_BX]);
11393e12c5d1SDavid du Colombier 		} else {
11403e12c5d1SDavid du Colombier 			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
11413e12c5d1SDavid du Colombier 			subreg(&pp, z, D_AX);
11423e12c5d1SDavid du Colombier 			doasm(&pp);
11433e12c5d1SDavid du Colombier 			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
11443e12c5d1SDavid du Colombier 		}
11453e12c5d1SDavid du Colombier 		return;
11463e12c5d1SDavid du Colombier 	}
11473e12c5d1SDavid du Colombier 	z = p->to.type;
11483e12c5d1SDavid du Colombier 	if(z >= D_BP && z <= D_DI) {
11493e12c5d1SDavid du Colombier 		if(isax(&p->from)) {
11503e12c5d1SDavid du Colombier 			*andptr++ = 0x87;			/* xchg rhs,bx */
11513e12c5d1SDavid du Colombier 			asmand(&p->to, reg[D_BX]);
11523e12c5d1SDavid du Colombier 			subreg(&pp, z, D_BX);
11533e12c5d1SDavid du Colombier 			doasm(&pp);
11543e12c5d1SDavid du Colombier 			*andptr++ = 0x87;			/* xchg rhs,bx */
11553e12c5d1SDavid du Colombier 			asmand(&p->to, reg[D_BX]);
11563e12c5d1SDavid du Colombier 		} else {
11573e12c5d1SDavid du Colombier 			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
11583e12c5d1SDavid du Colombier 			subreg(&pp, z, D_AX);
11593e12c5d1SDavid du Colombier 			doasm(&pp);
11603e12c5d1SDavid du Colombier 			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
11613e12c5d1SDavid du Colombier 		}
11623e12c5d1SDavid du Colombier 		return;
11633e12c5d1SDavid du Colombier 	}
1164406758d9SDavid du Colombier 	diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
11653e12c5d1SDavid du Colombier 	return;
11663e12c5d1SDavid du Colombier 
11673e12c5d1SDavid du Colombier mfound:
11683e12c5d1SDavid du Colombier 	switch(t[3]) {
11693e12c5d1SDavid du Colombier 	default:
11706b6b9ac8SDavid du Colombier 		diag("asmins: unknown mov %d %P", t[3], p);
11713e12c5d1SDavid du Colombier 		break;
11723e12c5d1SDavid du Colombier 
11733e12c5d1SDavid du Colombier 	case 0:	/* lit */
11743e12c5d1SDavid du Colombier 		for(z=4; t[z]!=E; z++)
11753e12c5d1SDavid du Colombier 			*andptr++ = t[z];
11763e12c5d1SDavid du Colombier 		break;
11773e12c5d1SDavid du Colombier 
11783e12c5d1SDavid du Colombier 	case 1:	/* r,m */
11793e12c5d1SDavid du Colombier 		*andptr++ = t[4];
11803e12c5d1SDavid du Colombier 		asmand(&p->to, t[5]);
11813e12c5d1SDavid du Colombier 		break;
11823e12c5d1SDavid du Colombier 
11833e12c5d1SDavid du Colombier 	case 2:	/* m,r */
11843e12c5d1SDavid du Colombier 		*andptr++ = t[4];
11853e12c5d1SDavid du Colombier 		asmand(&p->from, t[5]);
11863e12c5d1SDavid du Colombier 		break;
11873e12c5d1SDavid du Colombier 
11883e12c5d1SDavid du Colombier 	case 3:	/* r,m - 2op */
11893e12c5d1SDavid du Colombier 		*andptr++ = t[4];
11903e12c5d1SDavid du Colombier 		*andptr++ = t[5];
11913e12c5d1SDavid du Colombier 		asmand(&p->to, t[6]);
11923e12c5d1SDavid du Colombier 		break;
11933e12c5d1SDavid du Colombier 
11943e12c5d1SDavid du Colombier 	case 4:	/* m,r - 2op */
11953e12c5d1SDavid du Colombier 		*andptr++ = t[4];
11963e12c5d1SDavid du Colombier 		*andptr++ = t[5];
11973e12c5d1SDavid du Colombier 		asmand(&p->from, t[6]);
11983e12c5d1SDavid du Colombier 		break;
11993e12c5d1SDavid du Colombier 
12003e12c5d1SDavid du Colombier 	case 5:	/* load full pointer, trash heap */
12013e12c5d1SDavid du Colombier 		if(t[4])
12023e12c5d1SDavid du Colombier 			*andptr++ = t[4];
12033e12c5d1SDavid du Colombier 		switch(p->to.index) {
12043e12c5d1SDavid du Colombier 		default:
12053e12c5d1SDavid du Colombier 			goto bad;
12063e12c5d1SDavid du Colombier 		case D_DS:
12073e12c5d1SDavid du Colombier 			*andptr++ = 0xc5;
12083e12c5d1SDavid du Colombier 			break;
12093e12c5d1SDavid du Colombier 		case D_SS:
12103e12c5d1SDavid du Colombier 			*andptr++ = 0x0f;
12113e12c5d1SDavid du Colombier 			*andptr++ = 0xb2;
12123e12c5d1SDavid du Colombier 			break;
12133e12c5d1SDavid du Colombier 		case D_ES:
12143e12c5d1SDavid du Colombier 			*andptr++ = 0xc4;
12153e12c5d1SDavid du Colombier 			break;
12163e12c5d1SDavid du Colombier 		case D_FS:
12173e12c5d1SDavid du Colombier 			*andptr++ = 0x0f;
12183e12c5d1SDavid du Colombier 			*andptr++ = 0xb4;
12193e12c5d1SDavid du Colombier 			break;
12203e12c5d1SDavid du Colombier 		case D_GS:
12213e12c5d1SDavid du Colombier 			*andptr++ = 0x0f;
12223e12c5d1SDavid du Colombier 			*andptr++ = 0xb5;
12233e12c5d1SDavid du Colombier 			break;
12243e12c5d1SDavid du Colombier 		}
12253e12c5d1SDavid du Colombier 		asmand(&p->from, reg[p->to.type]);
12263e12c5d1SDavid du Colombier 		break;
12273e12c5d1SDavid du Colombier 
1228219b2ee8SDavid du Colombier 	case 6:	/* double shift */
12293e12c5d1SDavid du Colombier 		z = p->from.type;
12303e12c5d1SDavid du Colombier 		switch(z) {
12313e12c5d1SDavid du Colombier 		default:
12323e12c5d1SDavid du Colombier 			goto bad;
12333e12c5d1SDavid du Colombier 		case D_CONST:
12343e12c5d1SDavid du Colombier 			*andptr++ = 0x0f;
12353e12c5d1SDavid du Colombier 			*andptr++ = t[4];
1236219b2ee8SDavid du Colombier 			asmand(&p->to, reg[p->from.index]);
12373e12c5d1SDavid du Colombier 			*andptr++ = p->from.offset;
12383e12c5d1SDavid du Colombier 			break;
12393e12c5d1SDavid du Colombier 		case D_CL:
12403e12c5d1SDavid du Colombier 		case D_CX:
12413e12c5d1SDavid du Colombier 			*andptr++ = 0x0f;
12423e12c5d1SDavid du Colombier 			*andptr++ = t[5];
1243219b2ee8SDavid du Colombier 			asmand(&p->to, reg[p->from.index]);
12443e12c5d1SDavid du Colombier 			break;
12453e12c5d1SDavid du Colombier 		}
12463e12c5d1SDavid du Colombier 		break;
1247282e677fSDavid du Colombier 
1248282e677fSDavid du Colombier 	case 7: /* imul rm,r */
1249282e677fSDavid du Colombier 		*andptr++ = t[4];
1250282e677fSDavid du Colombier 		*andptr++ = t[5];
1251282e677fSDavid du Colombier 		asmand(&p->from, reg[p->to.type]);
1252282e677fSDavid du Colombier 		break;
12533e12c5d1SDavid du Colombier 	}
12543e12c5d1SDavid du Colombier }
12553e12c5d1SDavid du Colombier 
12563e12c5d1SDavid du Colombier void
asmins(Prog * p)12573e12c5d1SDavid du Colombier asmins(Prog *p)
12583e12c5d1SDavid du Colombier {
12593e12c5d1SDavid du Colombier 
12603e12c5d1SDavid du Colombier 	andptr = and;
12613e12c5d1SDavid du Colombier 	doasm(p);
12623e12c5d1SDavid du Colombier }
1263375daca8SDavid du Colombier 
1264375daca8SDavid du Colombier enum{
1265375daca8SDavid du Colombier 	ABSD = 0,
1266375daca8SDavid du Colombier 	ABSU = 1,
1267375daca8SDavid du Colombier 	RELD = 2,
1268375daca8SDavid du Colombier 	RELU = 3,
1269375daca8SDavid du Colombier };
1270375daca8SDavid du Colombier 
1271375daca8SDavid du Colombier int modemap[4] = { 0, 1, -1, 2, };
1272375daca8SDavid du Colombier 
1273375daca8SDavid du Colombier typedef struct Reloc Reloc;
1274375daca8SDavid du Colombier 
1275375daca8SDavid du Colombier struct Reloc
1276375daca8SDavid du Colombier {
1277375daca8SDavid du Colombier 	int n;
1278375daca8SDavid du Colombier 	int t;
1279375daca8SDavid du Colombier 	uchar *m;
1280375daca8SDavid du Colombier 	ulong *a;
1281375daca8SDavid du Colombier };
1282375daca8SDavid du Colombier 
1283375daca8SDavid du Colombier Reloc rels;
1284375daca8SDavid du Colombier 
1285375daca8SDavid du Colombier static void
grow(Reloc * r)1286375daca8SDavid du Colombier grow(Reloc *r)
1287375daca8SDavid du Colombier {
1288375daca8SDavid du Colombier 	int t;
1289375daca8SDavid du Colombier 	uchar *m, *nm;
1290375daca8SDavid du Colombier 	ulong *a, *na;
1291375daca8SDavid du Colombier 
1292375daca8SDavid du Colombier 	t = r->t;
1293375daca8SDavid du Colombier 	r->t += 64;
1294375daca8SDavid du Colombier 	m = r->m;
1295375daca8SDavid du Colombier 	a = r->a;
1296375daca8SDavid du Colombier 	r->m = nm = malloc(r->t*sizeof(uchar));
1297375daca8SDavid du Colombier 	r->a = na = malloc(r->t*sizeof(ulong));
1298375daca8SDavid du Colombier 	memmove(nm, m, t*sizeof(uchar));
1299375daca8SDavid du Colombier 	memmove(na, a, t*sizeof(ulong));
1300375daca8SDavid du Colombier 	free(m);
1301375daca8SDavid du Colombier 	free(a);
1302375daca8SDavid du Colombier }
1303375daca8SDavid du Colombier 
1304375daca8SDavid du Colombier void
dynreloc(Sym * s,ulong v,int abs)1305375daca8SDavid du Colombier dynreloc(Sym *s, ulong v, int abs)
1306375daca8SDavid du Colombier {
1307375daca8SDavid du Colombier 	int i, k, n;
1308375daca8SDavid du Colombier 	uchar *m;
1309375daca8SDavid du Colombier 	ulong *a;
1310375daca8SDavid du Colombier 	Reloc *r;
1311375daca8SDavid du Colombier 
1312375daca8SDavid du Colombier 	if(s->type == SUNDEF)
1313375daca8SDavid du Colombier 		k = abs ? ABSU : RELU;
1314375daca8SDavid du Colombier 	else
1315375daca8SDavid du Colombier 		k = abs ? ABSD : RELD;
1316375daca8SDavid du Colombier 	/* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */
1317375daca8SDavid du Colombier 	k = modemap[k];
1318375daca8SDavid du Colombier 	r = &rels;
1319375daca8SDavid du Colombier 	n = r->n;
1320375daca8SDavid du Colombier 	if(n >= r->t)
1321375daca8SDavid du Colombier 		grow(r);
1322375daca8SDavid du Colombier 	m = r->m;
1323375daca8SDavid du Colombier 	a = r->a;
1324375daca8SDavid du Colombier 	for(i = n; i > 0; i--){
1325375daca8SDavid du Colombier 		if(v < a[i-1]){	/* happens occasionally for data */
1326375daca8SDavid du Colombier 			m[i] = m[i-1];
1327375daca8SDavid du Colombier 			a[i] = a[i-1];
1328375daca8SDavid du Colombier 		}
1329375daca8SDavid du Colombier 		else
1330375daca8SDavid du Colombier 			break;
1331375daca8SDavid du Colombier 	}
1332375daca8SDavid du Colombier 	m[i] = k;
1333375daca8SDavid du Colombier 	a[i] = v;
1334375daca8SDavid du Colombier 	r->n++;
1335375daca8SDavid du Colombier }
1336375daca8SDavid du Colombier 
1337375daca8SDavid du Colombier static int
sput(char * s)1338375daca8SDavid du Colombier sput(char *s)
1339375daca8SDavid du Colombier {
1340375daca8SDavid du Colombier 	char *p;
1341375daca8SDavid du Colombier 
1342375daca8SDavid du Colombier 	p = s;
1343375daca8SDavid du Colombier 	while(*s)
1344375daca8SDavid du Colombier 		cput(*s++);
1345375daca8SDavid du Colombier 	cput(0);
1346375daca8SDavid du Colombier 	return s-p+1;
1347375daca8SDavid du Colombier }
1348375daca8SDavid du Colombier 
1349375daca8SDavid du Colombier void
asmdyn()1350375daca8SDavid du Colombier asmdyn()
1351375daca8SDavid du Colombier {
1352375daca8SDavid du Colombier 	int i, n, t, c;
1353375daca8SDavid du Colombier 	Sym *s;
1354375daca8SDavid du Colombier 	ulong la, ra, *a;
1355375daca8SDavid du Colombier 	vlong off;
1356375daca8SDavid du Colombier 	uchar *m;
1357375daca8SDavid du Colombier 	Reloc *r;
1358375daca8SDavid du Colombier 
1359375daca8SDavid du Colombier 	cflush();
1360375daca8SDavid du Colombier 	off = seek(cout, 0, 1);
1361375daca8SDavid du Colombier 	lput(0);
1362375daca8SDavid du Colombier 	t = 0;
1363375daca8SDavid du Colombier 	lput(imports);
1364375daca8SDavid du Colombier 	t += 4;
1365375daca8SDavid du Colombier 	for(i = 0; i < NHASH; i++)
1366375daca8SDavid du Colombier 		for(s = hash[i]; s != S; s = s->link)
1367375daca8SDavid du Colombier 			if(s->type == SUNDEF){
1368375daca8SDavid du Colombier 				lput(s->sig);
1369375daca8SDavid du Colombier 				t += 4;
1370375daca8SDavid du Colombier 				t += sput(s->name);
1371375daca8SDavid du Colombier 			}
1372375daca8SDavid du Colombier 
1373375daca8SDavid du Colombier 	la = 0;
1374375daca8SDavid du Colombier 	r = &rels;
1375375daca8SDavid du Colombier 	n = r->n;
1376375daca8SDavid du Colombier 	m = r->m;
1377375daca8SDavid du Colombier 	a = r->a;
1378375daca8SDavid du Colombier 	lput(n);
1379375daca8SDavid du Colombier 	t += 4;
1380375daca8SDavid du Colombier 	for(i = 0; i < n; i++){
1381375daca8SDavid du Colombier 		ra = *a-la;
1382375daca8SDavid du Colombier 		if(*a < la)
1383375daca8SDavid du Colombier 			diag("bad relocation order");
1384375daca8SDavid du Colombier 		if(ra < 256)
1385375daca8SDavid du Colombier 			c = 0;
1386375daca8SDavid du Colombier 		else if(ra < 65536)
1387375daca8SDavid du Colombier 			c = 1;
1388375daca8SDavid du Colombier 		else
1389375daca8SDavid du Colombier 			c = 2;
1390375daca8SDavid du Colombier 		cput((c<<6)|*m++);
1391375daca8SDavid du Colombier 		t++;
1392375daca8SDavid du Colombier 		if(c == 0){
1393375daca8SDavid du Colombier 			cput(ra);
1394375daca8SDavid du Colombier 			t++;
1395375daca8SDavid du Colombier 		}
1396375daca8SDavid du Colombier 		else if(c == 1){
1397260f7b65SDavid du Colombier 			wput(ra);
1398375daca8SDavid du Colombier 			t += 2;
1399375daca8SDavid du Colombier 		}
1400375daca8SDavid du Colombier 		else{
1401375daca8SDavid du Colombier 			lput(ra);
1402375daca8SDavid du Colombier 			t += 4;
1403375daca8SDavid du Colombier 		}
1404375daca8SDavid du Colombier 		la = *a++;
1405375daca8SDavid du Colombier 	}
1406375daca8SDavid du Colombier 
1407375daca8SDavid du Colombier 	cflush();
1408375daca8SDavid du Colombier 	seek(cout, off, 0);
1409375daca8SDavid du Colombier 	lput(t);
1410375daca8SDavid du Colombier 
1411375daca8SDavid du Colombier 	if(debug['v']){
1412375daca8SDavid du Colombier 		Bprint(&bso, "import table entries = %d\n", imports);
1413375daca8SDavid du Colombier 		Bprint(&bso, "export table entries = %d\n", exports);
1414375daca8SDavid du Colombier 	}
1415375daca8SDavid du Colombier }
1416