xref: /inferno-os/utils/6l/span.c (revision 45a20ab721a513710138340faff3d59a31c3e01e)
1b370703fSCharles.Forsyth #include	"l.h"
2b370703fSCharles.Forsyth 
3b370703fSCharles.Forsyth static int	rexflag;
4b370703fSCharles.Forsyth static int	asmode;
5b370703fSCharles.Forsyth 
6b370703fSCharles.Forsyth void
span(void)7b370703fSCharles.Forsyth span(void)
8b370703fSCharles.Forsyth {
9b370703fSCharles.Forsyth 	Prog *p, *q;
10b370703fSCharles.Forsyth 	long v;
11b370703fSCharles.Forsyth 	vlong c, idat;
12b370703fSCharles.Forsyth 	int m, n, again;
13b370703fSCharles.Forsyth 
14b370703fSCharles.Forsyth 	xdefine("etext", STEXT, 0L);
15b370703fSCharles.Forsyth 	idat = INITDAT;
16b370703fSCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
17b370703fSCharles.Forsyth 		if(p->as == ATEXT)
18b370703fSCharles.Forsyth 			curtext = p;
19b370703fSCharles.Forsyth 		n = 0;
20b370703fSCharles.Forsyth 		if(p->to.type == D_BRANCH)
21b370703fSCharles.Forsyth 			if(p->pcond == P)
22b370703fSCharles.Forsyth 				p->pcond = p;
23b370703fSCharles.Forsyth 		if((q = p->pcond) != P)
24b370703fSCharles.Forsyth 			if(q->back != 2)
25b370703fSCharles.Forsyth 				n = 1;
26b370703fSCharles.Forsyth 		p->back = n;
27b370703fSCharles.Forsyth 		if(p->as == AADJSP) {
28b370703fSCharles.Forsyth 			p->to.type = D_SP;
29b370703fSCharles.Forsyth 			v = -p->from.offset;
30b370703fSCharles.Forsyth 			p->from.offset = v;
31b370703fSCharles.Forsyth 			p->as = p->mode != 64? AADDL: AADDQ;
32b370703fSCharles.Forsyth 			if(v < 0) {
33b370703fSCharles.Forsyth 				p->as = p->mode != 64? ASUBL: ASUBQ;
34b370703fSCharles.Forsyth 				v = -v;
35b370703fSCharles.Forsyth 				p->from.offset = v;
36b370703fSCharles.Forsyth 			}
37b370703fSCharles.Forsyth 			if(v == 0)
38b370703fSCharles.Forsyth 				p->as = ANOP;
39b370703fSCharles.Forsyth 		}
40b370703fSCharles.Forsyth 	}
41b370703fSCharles.Forsyth 	n = 0;
42b370703fSCharles.Forsyth 
43b370703fSCharles.Forsyth start:
44b370703fSCharles.Forsyth 	if(debug['v'])
45b370703fSCharles.Forsyth 		Bprint(&bso, "%5.2f span\n", cputime());
46b370703fSCharles.Forsyth 	Bflush(&bso);
47b370703fSCharles.Forsyth 	c = INITTEXT;
48b370703fSCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
49b370703fSCharles.Forsyth 		if(p->as == ATEXT)
50b370703fSCharles.Forsyth 			curtext = p;
51b370703fSCharles.Forsyth 		if(p->to.type == D_BRANCH)
52b370703fSCharles.Forsyth 			if(p->back)
53b370703fSCharles.Forsyth 				p->pc = c;
54b370703fSCharles.Forsyth 		asmins(p);
55b370703fSCharles.Forsyth 		p->pc = c;
56b370703fSCharles.Forsyth 		m = andptr-and;
57b370703fSCharles.Forsyth 		p->mark = m;
58b370703fSCharles.Forsyth 		c += m;
59b370703fSCharles.Forsyth 	}
60b370703fSCharles.Forsyth 
61b370703fSCharles.Forsyth loop:
62b370703fSCharles.Forsyth 	n++;
63b370703fSCharles.Forsyth 	if(debug['v'])
64b370703fSCharles.Forsyth 		Bprint(&bso, "%5.2f span %d\n", cputime(), n);
65b370703fSCharles.Forsyth 	Bflush(&bso);
66b370703fSCharles.Forsyth 	if(n > 50) {
67b370703fSCharles.Forsyth 		print("span must be looping\n");
68b370703fSCharles.Forsyth 		errorexit();
69b370703fSCharles.Forsyth 	}
70b370703fSCharles.Forsyth 	again = 0;
71b370703fSCharles.Forsyth 	c = INITTEXT;
72b370703fSCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
73b370703fSCharles.Forsyth 		if(p->as == ATEXT)
74b370703fSCharles.Forsyth 			curtext = p;
75b370703fSCharles.Forsyth 		if(p->to.type == D_BRANCH || p->back & 0100) {
76b370703fSCharles.Forsyth 			if(p->back)
77b370703fSCharles.Forsyth 				p->pc = c;
78b370703fSCharles.Forsyth 			asmins(p);
79b370703fSCharles.Forsyth 			m = andptr-and;
80b370703fSCharles.Forsyth 			if(m != p->mark) {
81b370703fSCharles.Forsyth 				p->mark = m;
82b370703fSCharles.Forsyth 				again++;
83b370703fSCharles.Forsyth 			}
84b370703fSCharles.Forsyth 		}
85b370703fSCharles.Forsyth 		p->pc = c;
86b370703fSCharles.Forsyth 		c += p->mark;
87b370703fSCharles.Forsyth 	}
88b370703fSCharles.Forsyth 	if(again) {
89b370703fSCharles.Forsyth 		textsize = c;
90b370703fSCharles.Forsyth 		goto loop;
91b370703fSCharles.Forsyth 	}
92b370703fSCharles.Forsyth 	if(INITRND) {
93b370703fSCharles.Forsyth 		INITDAT = rnd(c, INITRND);
94b370703fSCharles.Forsyth 		if(INITDAT != idat) {
95b370703fSCharles.Forsyth 			idat = INITDAT;
96b370703fSCharles.Forsyth 			goto start;
97b370703fSCharles.Forsyth 		}
98b370703fSCharles.Forsyth 	}
99b370703fSCharles.Forsyth 	xdefine("etext", STEXT, c);
100b370703fSCharles.Forsyth 	if(debug['v'])
101b370703fSCharles.Forsyth 		Bprint(&bso, "etext = %llux\n", c);
102b370703fSCharles.Forsyth 	Bflush(&bso);
103b370703fSCharles.Forsyth 	for(p = textp; p != P; p = p->pcond)
104b370703fSCharles.Forsyth 		p->from.sym->value = p->pc;
105b370703fSCharles.Forsyth 	textsize = c - INITTEXT;
106b370703fSCharles.Forsyth }
107b370703fSCharles.Forsyth 
108b370703fSCharles.Forsyth void
xdefine(char * p,int t,vlong v)109b370703fSCharles.Forsyth xdefine(char *p, int t, vlong v)
110b370703fSCharles.Forsyth {
111b370703fSCharles.Forsyth 	Sym *s;
112b370703fSCharles.Forsyth 
113b370703fSCharles.Forsyth 	s = lookup(p, 0);
114b370703fSCharles.Forsyth 	if(s->type == 0 || s->type == SXREF) {
115b370703fSCharles.Forsyth 		s->type = t;
116b370703fSCharles.Forsyth 		s->value = v;
117b370703fSCharles.Forsyth 	}
118b370703fSCharles.Forsyth 	if(s->type == STEXT && s->value == 0)
119b370703fSCharles.Forsyth 		s->value = v;
120b370703fSCharles.Forsyth }
121b370703fSCharles.Forsyth 
122b370703fSCharles.Forsyth void
putsymb(char * s,int t,vlong v,int ver)1232303ddadSforsyth putsymb(char *s, int t, vlong v, int ver)
124b370703fSCharles.Forsyth {
1252303ddadSforsyth 	int i, f, l;
126b370703fSCharles.Forsyth 
127b370703fSCharles.Forsyth 	if(t == 'f')
128b370703fSCharles.Forsyth 		s++;
1292303ddadSforsyth 	l = 4;
130*45a20ab7Sforsyth 	switch(HEADTYPE){
131*45a20ab7Sforsyth 	default:
132*45a20ab7Sforsyth 		break;
133*45a20ab7Sforsyth 	case 5:
134*45a20ab7Sforsyth 		if(debug['8'])
135*45a20ab7Sforsyth 			break;
136*45a20ab7Sforsyth 	case 2:
137*45a20ab7Sforsyth 	case 6:
1382303ddadSforsyth 		lput(v>>32);
1392303ddadSforsyth 		l = 8;
140*45a20ab7Sforsyth 		break;
1412303ddadSforsyth 	}
142b370703fSCharles.Forsyth 	lput(v);
143b370703fSCharles.Forsyth 	if(ver)
144b370703fSCharles.Forsyth 		t += 'a' - 'A';
145b370703fSCharles.Forsyth 	cput(t+0x80);			/* 0x80 is variable length */
146b370703fSCharles.Forsyth 
147b370703fSCharles.Forsyth 	if(t == 'Z' || t == 'z') {
148b370703fSCharles.Forsyth 		cput(s[0]);
149b370703fSCharles.Forsyth 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
150b370703fSCharles.Forsyth 			cput(s[i]);
151b370703fSCharles.Forsyth 			cput(s[i+1]);
152b370703fSCharles.Forsyth 		}
153b370703fSCharles.Forsyth 		cput(0);
154b370703fSCharles.Forsyth 		cput(0);
155b370703fSCharles.Forsyth 		i++;
156b370703fSCharles.Forsyth 	}
157b370703fSCharles.Forsyth 	else {
158b370703fSCharles.Forsyth 		for(i=0; s[i]; i++)
159b370703fSCharles.Forsyth 			cput(s[i]);
160b370703fSCharles.Forsyth 		cput(0);
161b370703fSCharles.Forsyth 	}
1622303ddadSforsyth 	symsize += l + 1 + i + 1;
163b370703fSCharles.Forsyth 
164b370703fSCharles.Forsyth 	if(debug['n']) {
165b370703fSCharles.Forsyth 		if(t == 'z' || t == 'Z') {
1662303ddadSforsyth 			Bprint(&bso, "%c %.8llux ", t, v);
167b370703fSCharles.Forsyth 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
168b370703fSCharles.Forsyth 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
169b370703fSCharles.Forsyth 				Bprint(&bso, "/%x", f);
170b370703fSCharles.Forsyth 			}
171b370703fSCharles.Forsyth 			Bprint(&bso, "\n");
172b370703fSCharles.Forsyth 			return;
173b370703fSCharles.Forsyth 		}
174b370703fSCharles.Forsyth 		if(ver)
1752303ddadSforsyth 			Bprint(&bso, "%c %.8llux %s<%d>\n", t, v, s, ver);
176b370703fSCharles.Forsyth 		else
1772303ddadSforsyth 			Bprint(&bso, "%c %.8llux %s\n", t, v, s);
178b370703fSCharles.Forsyth 	}
179b370703fSCharles.Forsyth }
180b370703fSCharles.Forsyth 
181b370703fSCharles.Forsyth void
asmsym(void)182b370703fSCharles.Forsyth asmsym(void)
183b370703fSCharles.Forsyth {
184b370703fSCharles.Forsyth 	Prog *p;
185b370703fSCharles.Forsyth 	Auto *a;
186b370703fSCharles.Forsyth 	Sym *s;
187b370703fSCharles.Forsyth 	int h;
188b370703fSCharles.Forsyth 
189b370703fSCharles.Forsyth 	s = lookup("etext", 0);
190b370703fSCharles.Forsyth 	if(s->type == STEXT)
191b370703fSCharles.Forsyth 		putsymb(s->name, 'T', s->value, s->version);
192b370703fSCharles.Forsyth 
193b370703fSCharles.Forsyth 	for(h=0; h<NHASH; h++)
194b370703fSCharles.Forsyth 		for(s=hash[h]; s!=S; s=s->link)
195b370703fSCharles.Forsyth 			switch(s->type) {
196b370703fSCharles.Forsyth 			case SCONST:
197b370703fSCharles.Forsyth 				putsymb(s->name, 'D', s->value, s->version);
198b370703fSCharles.Forsyth 				continue;
199b370703fSCharles.Forsyth 
200b370703fSCharles.Forsyth 			case SDATA:
201b370703fSCharles.Forsyth 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
202b370703fSCharles.Forsyth 				continue;
203b370703fSCharles.Forsyth 
204b370703fSCharles.Forsyth 			case SBSS:
205b370703fSCharles.Forsyth 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
206b370703fSCharles.Forsyth 				continue;
207b370703fSCharles.Forsyth 
208b370703fSCharles.Forsyth 			case SFILE:
209b370703fSCharles.Forsyth 				putsymb(s->name, 'f', s->value, s->version);
210b370703fSCharles.Forsyth 				continue;
211b370703fSCharles.Forsyth 			}
212b370703fSCharles.Forsyth 
213b370703fSCharles.Forsyth 	for(p=textp; p!=P; p=p->pcond) {
214b370703fSCharles.Forsyth 		s = p->from.sym;
215b370703fSCharles.Forsyth 		if(s->type != STEXT)
216b370703fSCharles.Forsyth 			continue;
217b370703fSCharles.Forsyth 
218b370703fSCharles.Forsyth 		/* filenames first */
219b370703fSCharles.Forsyth 		for(a=p->to.autom; a; a=a->link)
220b370703fSCharles.Forsyth 			if(a->type == D_FILE)
221b370703fSCharles.Forsyth 				putsymb(a->asym->name, 'z', a->aoffset, 0);
222b370703fSCharles.Forsyth 			else
223b370703fSCharles.Forsyth 			if(a->type == D_FILE1)
224b370703fSCharles.Forsyth 				putsymb(a->asym->name, 'Z', a->aoffset, 0);
225b370703fSCharles.Forsyth 
226b370703fSCharles.Forsyth 		putsymb(s->name, 'T', s->value, s->version);
227b370703fSCharles.Forsyth 
228b370703fSCharles.Forsyth 		/* frame, auto and param after */
2292303ddadSforsyth 		putsymb(".frame", 'm', p->to.offset+8, 0);
230b370703fSCharles.Forsyth 
231b370703fSCharles.Forsyth 		for(a=p->to.autom; a; a=a->link)
232b370703fSCharles.Forsyth 			if(a->type == D_AUTO)
233b370703fSCharles.Forsyth 				putsymb(a->asym->name, 'a', -a->aoffset, 0);
234b370703fSCharles.Forsyth 			else
235b370703fSCharles.Forsyth 			if(a->type == D_PARAM)
236b370703fSCharles.Forsyth 				putsymb(a->asym->name, 'p', a->aoffset, 0);
237b370703fSCharles.Forsyth 	}
238b370703fSCharles.Forsyth 	if(debug['v'] || debug['n'])
239b370703fSCharles.Forsyth 		Bprint(&bso, "symsize = %lud\n", symsize);
240b370703fSCharles.Forsyth 	Bflush(&bso);
241b370703fSCharles.Forsyth }
242b370703fSCharles.Forsyth 
243b370703fSCharles.Forsyth void
asmlc(void)244b370703fSCharles.Forsyth asmlc(void)
245b370703fSCharles.Forsyth {
2462303ddadSforsyth 	vlong oldpc;
247b370703fSCharles.Forsyth 	Prog *p;
2482303ddadSforsyth 	long oldlc, v, s;
249b370703fSCharles.Forsyth 
250b370703fSCharles.Forsyth 	oldpc = INITTEXT;
251b370703fSCharles.Forsyth 	oldlc = 0;
252b370703fSCharles.Forsyth 	for(p = firstp; p != P; p = p->link) {
253b370703fSCharles.Forsyth 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
254b370703fSCharles.Forsyth 			if(p->as == ATEXT)
255b370703fSCharles.Forsyth 				curtext = p;
256*45a20ab7Sforsyth 			if(debug['V'])
257b370703fSCharles.Forsyth 				Bprint(&bso, "%6llux %P\n",
258b370703fSCharles.Forsyth 					p->pc, p);
259b370703fSCharles.Forsyth 			continue;
260b370703fSCharles.Forsyth 		}
261*45a20ab7Sforsyth 		if(debug['V'])
262b370703fSCharles.Forsyth 			Bprint(&bso, "\t\t%6ld", lcsize);
263b370703fSCharles.Forsyth 		v = (p->pc - oldpc) / MINLC;
264b370703fSCharles.Forsyth 		while(v) {
265b370703fSCharles.Forsyth 			s = 127;
266b370703fSCharles.Forsyth 			if(v < 127)
267b370703fSCharles.Forsyth 				s = v;
268b370703fSCharles.Forsyth 			cput(s+128);	/* 129-255 +pc */
269*45a20ab7Sforsyth 			if(debug['V'])
270b370703fSCharles.Forsyth 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
271b370703fSCharles.Forsyth 			v -= s;
272b370703fSCharles.Forsyth 			lcsize++;
273b370703fSCharles.Forsyth 		}
274b370703fSCharles.Forsyth 		s = p->line - oldlc;
275b370703fSCharles.Forsyth 		oldlc = p->line;
276b370703fSCharles.Forsyth 		oldpc = p->pc + MINLC;
277b370703fSCharles.Forsyth 		if(s > 64 || s < -64) {
278b370703fSCharles.Forsyth 			cput(0);	/* 0 vv +lc */
279b370703fSCharles.Forsyth 			cput(s>>24);
280b370703fSCharles.Forsyth 			cput(s>>16);
281b370703fSCharles.Forsyth 			cput(s>>8);
282b370703fSCharles.Forsyth 			cput(s);
283*45a20ab7Sforsyth 			if(debug['V']) {
284b370703fSCharles.Forsyth 				if(s > 0)
285b370703fSCharles.Forsyth 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
286b370703fSCharles.Forsyth 						s, 0, s);
287b370703fSCharles.Forsyth 				else
288b370703fSCharles.Forsyth 					Bprint(&bso, " lc%ld(%d,%ld)\n",
289b370703fSCharles.Forsyth 						s, 0, s);
290b370703fSCharles.Forsyth 				Bprint(&bso, "%6llux %P\n",
291b370703fSCharles.Forsyth 					p->pc, p);
292b370703fSCharles.Forsyth 			}
293b370703fSCharles.Forsyth 			lcsize += 5;
294b370703fSCharles.Forsyth 			continue;
295b370703fSCharles.Forsyth 		}
296b370703fSCharles.Forsyth 		if(s > 0) {
297b370703fSCharles.Forsyth 			cput(0+s);	/* 1-64 +lc */
298*45a20ab7Sforsyth 			if(debug['V']) {
299b370703fSCharles.Forsyth 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
300b370703fSCharles.Forsyth 				Bprint(&bso, "%6llux %P\n",
301b370703fSCharles.Forsyth 					p->pc, p);
302b370703fSCharles.Forsyth 			}
303b370703fSCharles.Forsyth 		} else {
304b370703fSCharles.Forsyth 			cput(64-s);	/* 65-128 -lc */
305*45a20ab7Sforsyth 			if(debug['V']) {
306b370703fSCharles.Forsyth 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
307b370703fSCharles.Forsyth 				Bprint(&bso, "%6llux %P\n",
308b370703fSCharles.Forsyth 					p->pc, p);
309b370703fSCharles.Forsyth 			}
310b370703fSCharles.Forsyth 		}
311b370703fSCharles.Forsyth 		lcsize++;
312b370703fSCharles.Forsyth 	}
313b370703fSCharles.Forsyth 	while(lcsize & 1) {
314b370703fSCharles.Forsyth 		s = 129;
315b370703fSCharles.Forsyth 		cput(s);
316b370703fSCharles.Forsyth 		lcsize++;
317b370703fSCharles.Forsyth 	}
318*45a20ab7Sforsyth 	if(debug['v'] || debug['V'])
319b370703fSCharles.Forsyth 		Bprint(&bso, "lcsize = %ld\n", lcsize);
320b370703fSCharles.Forsyth 	Bflush(&bso);
321b370703fSCharles.Forsyth }
322b370703fSCharles.Forsyth 
323b370703fSCharles.Forsyth int
oclass(Adr * a)324b370703fSCharles.Forsyth oclass(Adr *a)
325b370703fSCharles.Forsyth {
326b370703fSCharles.Forsyth 	vlong v;
327b370703fSCharles.Forsyth 	long l;
328b370703fSCharles.Forsyth 
329b370703fSCharles.Forsyth 	if(a->type >= D_INDIR || a->index != D_NONE) {
330b370703fSCharles.Forsyth 		if(a->index != D_NONE && a->scale == 0) {
331b370703fSCharles.Forsyth 			if(a->type == D_ADDR) {
332b370703fSCharles.Forsyth 				switch(a->index) {
333b370703fSCharles.Forsyth 				case D_EXTERN:
334b370703fSCharles.Forsyth 				case D_STATIC:
335b370703fSCharles.Forsyth 					return Yi32;	/* TO DO: Yi64 */
336b370703fSCharles.Forsyth 				case D_AUTO:
337b370703fSCharles.Forsyth 				case D_PARAM:
338b370703fSCharles.Forsyth 					return Yiauto;
339b370703fSCharles.Forsyth 				}
340b370703fSCharles.Forsyth 				return Yxxx;
341b370703fSCharles.Forsyth 			}
342b370703fSCharles.Forsyth 			return Ycol;
343b370703fSCharles.Forsyth 		}
344b370703fSCharles.Forsyth 		return Ym;
345b370703fSCharles.Forsyth 	}
346b370703fSCharles.Forsyth 	switch(a->type)
347b370703fSCharles.Forsyth 	{
348b370703fSCharles.Forsyth 	case D_AL:
349b370703fSCharles.Forsyth 		return Yal;
350b370703fSCharles.Forsyth 
351b370703fSCharles.Forsyth 	case D_AX:
352b370703fSCharles.Forsyth 		return Yax;
353b370703fSCharles.Forsyth 
354b370703fSCharles.Forsyth /*
355b370703fSCharles.Forsyth 	case D_SPB:
356b370703fSCharles.Forsyth */
357b370703fSCharles.Forsyth 	case D_BPB:
358b370703fSCharles.Forsyth 	case D_SIB:
359b370703fSCharles.Forsyth 	case D_DIB:
360b370703fSCharles.Forsyth 	case D_R8B:
361b370703fSCharles.Forsyth 	case D_R9B:
362b370703fSCharles.Forsyth 	case D_R10B:
363b370703fSCharles.Forsyth 	case D_R11B:
364b370703fSCharles.Forsyth 	case D_R12B:
365b370703fSCharles.Forsyth 	case D_R13B:
366b370703fSCharles.Forsyth 	case D_R14B:
367b370703fSCharles.Forsyth 	case D_R15B:
368b370703fSCharles.Forsyth 		if(asmode != 64)
369b370703fSCharles.Forsyth 			return Yxxx;
370b370703fSCharles.Forsyth 	case D_DL:
371b370703fSCharles.Forsyth 	case D_BL:
372b370703fSCharles.Forsyth 	case D_AH:
373b370703fSCharles.Forsyth 	case D_CH:
374b370703fSCharles.Forsyth 	case D_DH:
375b370703fSCharles.Forsyth 	case D_BH:
376b370703fSCharles.Forsyth 		return Yrb;
377b370703fSCharles.Forsyth 
378b370703fSCharles.Forsyth 	case D_CL:
379b370703fSCharles.Forsyth 		return Ycl;
380b370703fSCharles.Forsyth 
381b370703fSCharles.Forsyth 	case D_CX:
382b370703fSCharles.Forsyth 		return Ycx;
383b370703fSCharles.Forsyth 
384b370703fSCharles.Forsyth 	case D_DX:
385b370703fSCharles.Forsyth 	case D_BX:
386b370703fSCharles.Forsyth 		return Yrx;
387b370703fSCharles.Forsyth 
388b370703fSCharles.Forsyth 	case D_R8:	/* not really Yrl */
389b370703fSCharles.Forsyth 	case D_R9:
390b370703fSCharles.Forsyth 	case D_R10:
391b370703fSCharles.Forsyth 	case D_R11:
392b370703fSCharles.Forsyth 	case D_R12:
393b370703fSCharles.Forsyth 	case D_R13:
394b370703fSCharles.Forsyth 	case D_R14:
395b370703fSCharles.Forsyth 	case D_R15:
396b370703fSCharles.Forsyth 		if(asmode != 64)
397b370703fSCharles.Forsyth 			return Yxxx;
398b370703fSCharles.Forsyth 	case D_SP:
399b370703fSCharles.Forsyth 	case D_BP:
400b370703fSCharles.Forsyth 	case D_SI:
401b370703fSCharles.Forsyth 	case D_DI:
402b370703fSCharles.Forsyth 		return Yrl;
403b370703fSCharles.Forsyth 
404b370703fSCharles.Forsyth 	case D_F0+0:
405b370703fSCharles.Forsyth 		return	Yf0;
406b370703fSCharles.Forsyth 
407b370703fSCharles.Forsyth 	case D_F0+1:
408b370703fSCharles.Forsyth 	case D_F0+2:
409b370703fSCharles.Forsyth 	case D_F0+3:
410b370703fSCharles.Forsyth 	case D_F0+4:
411b370703fSCharles.Forsyth 	case D_F0+5:
412b370703fSCharles.Forsyth 	case D_F0+6:
413b370703fSCharles.Forsyth 	case D_F0+7:
414b370703fSCharles.Forsyth 		return	Yrf;
415b370703fSCharles.Forsyth 
416b370703fSCharles.Forsyth 	case D_M0+0:
417b370703fSCharles.Forsyth 	case D_M0+1:
418b370703fSCharles.Forsyth 	case D_M0+2:
419b370703fSCharles.Forsyth 	case D_M0+3:
420b370703fSCharles.Forsyth 	case D_M0+4:
421b370703fSCharles.Forsyth 	case D_M0+5:
422b370703fSCharles.Forsyth 	case D_M0+6:
423b370703fSCharles.Forsyth 	case D_M0+7:
424b370703fSCharles.Forsyth 		return	Ymr;
425b370703fSCharles.Forsyth 
426b370703fSCharles.Forsyth 	case D_X0+0:
427b370703fSCharles.Forsyth 	case D_X0+1:
428b370703fSCharles.Forsyth 	case D_X0+2:
429b370703fSCharles.Forsyth 	case D_X0+3:
430b370703fSCharles.Forsyth 	case D_X0+4:
431b370703fSCharles.Forsyth 	case D_X0+5:
432b370703fSCharles.Forsyth 	case D_X0+6:
433b370703fSCharles.Forsyth 	case D_X0+7:
434b370703fSCharles.Forsyth 	case D_X0+8:
435b370703fSCharles.Forsyth 	case D_X0+9:
436b370703fSCharles.Forsyth 	case D_X0+10:
437b370703fSCharles.Forsyth 	case D_X0+11:
438b370703fSCharles.Forsyth 	case D_X0+12:
439b370703fSCharles.Forsyth 	case D_X0+13:
440b370703fSCharles.Forsyth 	case D_X0+14:
441b370703fSCharles.Forsyth 	case D_X0+15:
442b370703fSCharles.Forsyth 		return	Yxr;
443b370703fSCharles.Forsyth 
444b370703fSCharles.Forsyth 	case D_NONE:
445b370703fSCharles.Forsyth 		return Ynone;
446b370703fSCharles.Forsyth 
447b370703fSCharles.Forsyth 	case D_CS:	return	Ycs;
448b370703fSCharles.Forsyth 	case D_SS:	return	Yss;
449b370703fSCharles.Forsyth 	case D_DS:	return	Yds;
450b370703fSCharles.Forsyth 	case D_ES:	return	Yes;
451b370703fSCharles.Forsyth 	case D_FS:	return	Yfs;
452b370703fSCharles.Forsyth 	case D_GS:	return	Ygs;
453b370703fSCharles.Forsyth 
454b370703fSCharles.Forsyth 	case D_GDTR:	return	Ygdtr;
455b370703fSCharles.Forsyth 	case D_IDTR:	return	Yidtr;
456b370703fSCharles.Forsyth 	case D_LDTR:	return	Yldtr;
457b370703fSCharles.Forsyth 	case D_MSW:	return	Ymsw;
458b370703fSCharles.Forsyth 	case D_TASK:	return	Ytask;
459b370703fSCharles.Forsyth 
460b370703fSCharles.Forsyth 	case D_CR+0:	return	Ycr0;
461b370703fSCharles.Forsyth 	case D_CR+1:	return	Ycr1;
462b370703fSCharles.Forsyth 	case D_CR+2:	return	Ycr2;
463b370703fSCharles.Forsyth 	case D_CR+3:	return	Ycr3;
464b370703fSCharles.Forsyth 	case D_CR+4:	return	Ycr4;
465b370703fSCharles.Forsyth 	case D_CR+5:	return	Ycr5;
466b370703fSCharles.Forsyth 	case D_CR+6:	return	Ycr6;
467b370703fSCharles.Forsyth 	case D_CR+7:	return	Ycr7;
468b370703fSCharles.Forsyth 	case D_CR+8:	return	Ycr8;
469b370703fSCharles.Forsyth 
470b370703fSCharles.Forsyth 	case D_DR+0:	return	Ydr0;
471b370703fSCharles.Forsyth 	case D_DR+1:	return	Ydr1;
472b370703fSCharles.Forsyth 	case D_DR+2:	return	Ydr2;
473b370703fSCharles.Forsyth 	case D_DR+3:	return	Ydr3;
474b370703fSCharles.Forsyth 	case D_DR+4:	return	Ydr4;
475b370703fSCharles.Forsyth 	case D_DR+5:	return	Ydr5;
476b370703fSCharles.Forsyth 	case D_DR+6:	return	Ydr6;
477b370703fSCharles.Forsyth 	case D_DR+7:	return	Ydr7;
478b370703fSCharles.Forsyth 
479b370703fSCharles.Forsyth 	case D_TR+0:	return	Ytr0;
480b370703fSCharles.Forsyth 	case D_TR+1:	return	Ytr1;
481b370703fSCharles.Forsyth 	case D_TR+2:	return	Ytr2;
482b370703fSCharles.Forsyth 	case D_TR+3:	return	Ytr3;
483b370703fSCharles.Forsyth 	case D_TR+4:	return	Ytr4;
484b370703fSCharles.Forsyth 	case D_TR+5:	return	Ytr5;
485b370703fSCharles.Forsyth 	case D_TR+6:	return	Ytr6;
486b370703fSCharles.Forsyth 	case D_TR+7:	return	Ytr7;
487b370703fSCharles.Forsyth 
488b370703fSCharles.Forsyth 	case D_EXTERN:
489b370703fSCharles.Forsyth 	case D_STATIC:
490b370703fSCharles.Forsyth 	case D_AUTO:
491b370703fSCharles.Forsyth 	case D_PARAM:
492b370703fSCharles.Forsyth 		return Ym;
493b370703fSCharles.Forsyth 
494b370703fSCharles.Forsyth 	case D_CONST:
495b370703fSCharles.Forsyth 	case D_ADDR:
496b370703fSCharles.Forsyth 		if(a->sym == S) {
497b370703fSCharles.Forsyth 			v = a->offset;
498b370703fSCharles.Forsyth 			if(v == 0)
499b370703fSCharles.Forsyth 				return Yi0;
500b370703fSCharles.Forsyth 			if(v == 1)
501b370703fSCharles.Forsyth 				return Yi1;
502b370703fSCharles.Forsyth 			if(v >= -128 && v <= 127)
503b370703fSCharles.Forsyth 				return Yi8;
504b370703fSCharles.Forsyth 			l = v;
505b370703fSCharles.Forsyth 			if((vlong)l == v)
506b370703fSCharles.Forsyth 				return Ys32;	/* can sign extend */
507b370703fSCharles.Forsyth 			if((v>>32) == 0)
508b370703fSCharles.Forsyth 				return Yi32;	/* unsigned */
509b370703fSCharles.Forsyth 			return Yi64;
510b370703fSCharles.Forsyth 		}
511b370703fSCharles.Forsyth 		return Yi32;	/* TO DO: D_ADDR as Yi64 */
512b370703fSCharles.Forsyth 
513b370703fSCharles.Forsyth 	case D_BRANCH:
514b370703fSCharles.Forsyth 		return Ybr;
515b370703fSCharles.Forsyth 	}
516b370703fSCharles.Forsyth 	return Yxxx;
517b370703fSCharles.Forsyth }
518b370703fSCharles.Forsyth 
519b370703fSCharles.Forsyth void
asmidx(Adr * a,int base)520b370703fSCharles.Forsyth asmidx(Adr *a, int base)
521b370703fSCharles.Forsyth {
522b370703fSCharles.Forsyth 	int i;
523b370703fSCharles.Forsyth 
524b370703fSCharles.Forsyth 	switch(a->index) {
525b370703fSCharles.Forsyth 	default:
526b370703fSCharles.Forsyth 		goto bad;
527b370703fSCharles.Forsyth 
528b370703fSCharles.Forsyth 	case D_NONE:
529b370703fSCharles.Forsyth 		i = 4 << 3;
530b370703fSCharles.Forsyth 		goto bas;
531b370703fSCharles.Forsyth 
532b370703fSCharles.Forsyth 	case D_R8:
533b370703fSCharles.Forsyth 	case D_R9:
534b370703fSCharles.Forsyth 	case D_R10:
535b370703fSCharles.Forsyth 	case D_R11:
536b370703fSCharles.Forsyth 	case D_R12:
537b370703fSCharles.Forsyth 	case D_R13:
538b370703fSCharles.Forsyth 	case D_R14:
539b370703fSCharles.Forsyth 	case D_R15:
540b370703fSCharles.Forsyth 		if(asmode != 64)
541b370703fSCharles.Forsyth 			goto bad;
542b370703fSCharles.Forsyth 	case D_AX:
543b370703fSCharles.Forsyth 	case D_CX:
544b370703fSCharles.Forsyth 	case D_DX:
545b370703fSCharles.Forsyth 	case D_BX:
546b370703fSCharles.Forsyth 	case D_BP:
547b370703fSCharles.Forsyth 	case D_SI:
548b370703fSCharles.Forsyth 	case D_DI:
549b370703fSCharles.Forsyth 		i = reg[a->index] << 3;
550b370703fSCharles.Forsyth 		break;
551b370703fSCharles.Forsyth 	}
552b370703fSCharles.Forsyth 	switch(a->scale) {
553b370703fSCharles.Forsyth 	default:
554b370703fSCharles.Forsyth 		goto bad;
555b370703fSCharles.Forsyth 	case 1:
556b370703fSCharles.Forsyth 		break;
557b370703fSCharles.Forsyth 	case 2:
558b370703fSCharles.Forsyth 		i |= (1<<6);
559b370703fSCharles.Forsyth 		break;
560b370703fSCharles.Forsyth 	case 4:
561b370703fSCharles.Forsyth 		i |= (2<<6);
562b370703fSCharles.Forsyth 		break;
563b370703fSCharles.Forsyth 	case 8:
564b370703fSCharles.Forsyth 		i |= (3<<6);
565b370703fSCharles.Forsyth 		break;
566b370703fSCharles.Forsyth 	}
567b370703fSCharles.Forsyth bas:
568b370703fSCharles.Forsyth 	switch(base) {
569b370703fSCharles.Forsyth 	default:
570b370703fSCharles.Forsyth 		goto bad;
571b370703fSCharles.Forsyth 	case D_NONE:	/* must be mod=00 */
572b370703fSCharles.Forsyth 		i |= 5;
573b370703fSCharles.Forsyth 		break;
574b370703fSCharles.Forsyth 	case D_R8:
575b370703fSCharles.Forsyth 	case D_R9:
576b370703fSCharles.Forsyth 	case D_R10:
577b370703fSCharles.Forsyth 	case D_R11:
578b370703fSCharles.Forsyth 	case D_R12:
579b370703fSCharles.Forsyth 	case D_R13:
580b370703fSCharles.Forsyth 	case D_R14:
581b370703fSCharles.Forsyth 	case D_R15:
582b370703fSCharles.Forsyth 		if(asmode != 64)
583b370703fSCharles.Forsyth 			goto bad;
584b370703fSCharles.Forsyth 	case D_AX:
585b370703fSCharles.Forsyth 	case D_CX:
586b370703fSCharles.Forsyth 	case D_DX:
587b370703fSCharles.Forsyth 	case D_BX:
588b370703fSCharles.Forsyth 	case D_SP:
589b370703fSCharles.Forsyth 	case D_BP:
590b370703fSCharles.Forsyth 	case D_SI:
591b370703fSCharles.Forsyth 	case D_DI:
592b370703fSCharles.Forsyth 		i |= reg[base];
593b370703fSCharles.Forsyth 		break;
594b370703fSCharles.Forsyth 	}
595b370703fSCharles.Forsyth 	*andptr++ = i;
596b370703fSCharles.Forsyth 	return;
597b370703fSCharles.Forsyth bad:
598b370703fSCharles.Forsyth 	diag("asmidx: bad address %D", a);
599b370703fSCharles.Forsyth 	*andptr++ = 0;
600b370703fSCharles.Forsyth 	return;
601b370703fSCharles.Forsyth }
602b370703fSCharles.Forsyth 
603b370703fSCharles.Forsyth static void
put4(long v)604b370703fSCharles.Forsyth put4(long v)
605b370703fSCharles.Forsyth {
606b370703fSCharles.Forsyth 	if(dlm && curp != P && reloca != nil){
607b370703fSCharles.Forsyth 		dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
608b370703fSCharles.Forsyth 		reloca = nil;
609b370703fSCharles.Forsyth 	}
610b370703fSCharles.Forsyth 	andptr[0] = v;
611b370703fSCharles.Forsyth 	andptr[1] = v>>8;
612b370703fSCharles.Forsyth 	andptr[2] = v>>16;
613b370703fSCharles.Forsyth 	andptr[3] = v>>24;
614b370703fSCharles.Forsyth 	andptr += 4;
615b370703fSCharles.Forsyth }
616b370703fSCharles.Forsyth 
617b370703fSCharles.Forsyth static void
put8(vlong v)618b370703fSCharles.Forsyth put8(vlong v)
619b370703fSCharles.Forsyth {
620b370703fSCharles.Forsyth 	if(dlm && curp != P && reloca != nil){
621b370703fSCharles.Forsyth 		dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);	/* TO DO */
622b370703fSCharles.Forsyth 		reloca = nil;
623b370703fSCharles.Forsyth 	}
624b370703fSCharles.Forsyth 	andptr[0] = v;
625b370703fSCharles.Forsyth 	andptr[1] = v>>8;
626b370703fSCharles.Forsyth 	andptr[2] = v>>16;
627b370703fSCharles.Forsyth 	andptr[3] = v>>24;
628b370703fSCharles.Forsyth 	andptr[4] = v>>32;
629b370703fSCharles.Forsyth 	andptr[5] = v>>40;
630b370703fSCharles.Forsyth 	andptr[6] = v>>48;
631b370703fSCharles.Forsyth 	andptr[7] = v>>56;
632b370703fSCharles.Forsyth 	andptr += 8;
633b370703fSCharles.Forsyth }
634b370703fSCharles.Forsyth 
635b370703fSCharles.Forsyth vlong
vaddr(Adr * a)636b370703fSCharles.Forsyth vaddr(Adr *a)
637b370703fSCharles.Forsyth {
638b370703fSCharles.Forsyth 	int t;
639b370703fSCharles.Forsyth 	vlong v;
640b370703fSCharles.Forsyth 	Sym *s;
641b370703fSCharles.Forsyth 
642b370703fSCharles.Forsyth 	t = a->type;
643b370703fSCharles.Forsyth 	v = a->offset;
644b370703fSCharles.Forsyth 	if(t == D_ADDR)
645b370703fSCharles.Forsyth 		t = a->index;
646b370703fSCharles.Forsyth 	switch(t) {
647b370703fSCharles.Forsyth 	case D_STATIC:
648b370703fSCharles.Forsyth 	case D_EXTERN:
649b370703fSCharles.Forsyth 		s = a->sym;
650b370703fSCharles.Forsyth 		if(s != nil) {
651b370703fSCharles.Forsyth 			if(dlm && curp != P)
652b370703fSCharles.Forsyth 				reloca = a;
653b370703fSCharles.Forsyth 			switch(s->type) {
654b370703fSCharles.Forsyth 			case SUNDEF:
655b370703fSCharles.Forsyth 				ckoff(s, v);
656b370703fSCharles.Forsyth 			case STEXT:
657b370703fSCharles.Forsyth 			case SCONST:
658b370703fSCharles.Forsyth 				if((uvlong)s->value < (uvlong)INITTEXT)
659b370703fSCharles.Forsyth 					v += INITTEXT;	/* TO DO */
660b370703fSCharles.Forsyth 				v += s->value;
661b370703fSCharles.Forsyth 				break;
662b370703fSCharles.Forsyth 			default:
663b370703fSCharles.Forsyth 				v += INITDAT + s->value;
664b370703fSCharles.Forsyth 			}
665b370703fSCharles.Forsyth 		}
666b370703fSCharles.Forsyth 	}
667b370703fSCharles.Forsyth 	return v;
668b370703fSCharles.Forsyth }
669b370703fSCharles.Forsyth 
670b370703fSCharles.Forsyth static void
asmandsz(Adr * a,int r,int rex,int m64)671b370703fSCharles.Forsyth asmandsz(Adr *a, int r, int rex, int m64)
672b370703fSCharles.Forsyth {
673b370703fSCharles.Forsyth 	long v;
674b370703fSCharles.Forsyth 	int t;
675b370703fSCharles.Forsyth 	Adr aa;
676b370703fSCharles.Forsyth 
677b370703fSCharles.Forsyth 	rex &= (0x40 | Rxr);
678b370703fSCharles.Forsyth 	v = a->offset;
679b370703fSCharles.Forsyth 	t = a->type;
680b370703fSCharles.Forsyth 	if(a->index != D_NONE) {
681b370703fSCharles.Forsyth 		if(t >= D_INDIR) {
682b370703fSCharles.Forsyth 			t -= D_INDIR;
683b370703fSCharles.Forsyth 			rexflag |= (regrex[a->index] & Rxx) | (regrex[t] & Rxb) | rex;
684b370703fSCharles.Forsyth 			if(t == D_NONE) {
685b370703fSCharles.Forsyth 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
686b370703fSCharles.Forsyth 				asmidx(a, t);
687b370703fSCharles.Forsyth 				put4(v);
688b370703fSCharles.Forsyth 				return;
689b370703fSCharles.Forsyth 			}
690b370703fSCharles.Forsyth 			if(v == 0 && t != D_BP && t != D_R13) {
691b370703fSCharles.Forsyth 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
692b370703fSCharles.Forsyth 				asmidx(a, t);
693b370703fSCharles.Forsyth 				return;
694b370703fSCharles.Forsyth 			}
695b370703fSCharles.Forsyth 			if(v >= -128 && v < 128) {
696b370703fSCharles.Forsyth 				*andptr++ = (1 << 6) | (4 << 0) | (r << 3);
697b370703fSCharles.Forsyth 				asmidx(a, t);
698b370703fSCharles.Forsyth 				*andptr++ = v;
699b370703fSCharles.Forsyth 				return;
700b370703fSCharles.Forsyth 			}
701b370703fSCharles.Forsyth 			*andptr++ = (2 << 6) | (4 << 0) | (r << 3);
702b370703fSCharles.Forsyth 			asmidx(a, t);
703b370703fSCharles.Forsyth 			put4(v);
704b370703fSCharles.Forsyth 			return;
705b370703fSCharles.Forsyth 		}
706b370703fSCharles.Forsyth 		switch(t) {
707b370703fSCharles.Forsyth 		default:
708b370703fSCharles.Forsyth 			goto bad;
709b370703fSCharles.Forsyth 		case D_STATIC:
710b370703fSCharles.Forsyth 		case D_EXTERN:
711b370703fSCharles.Forsyth 			aa.type = D_NONE+D_INDIR;
712b370703fSCharles.Forsyth 			break;
713b370703fSCharles.Forsyth 		case D_AUTO:
714b370703fSCharles.Forsyth 		case D_PARAM:
715b370703fSCharles.Forsyth 			aa.type = D_SP+D_INDIR;
716b370703fSCharles.Forsyth 			break;
717b370703fSCharles.Forsyth 		}
718b370703fSCharles.Forsyth 		aa.offset = vaddr(a);
719b370703fSCharles.Forsyth 		aa.index = a->index;
720b370703fSCharles.Forsyth 		aa.scale = a->scale;
721b370703fSCharles.Forsyth 		asmandsz(&aa, r, rex, m64);
722b370703fSCharles.Forsyth 		return;
723b370703fSCharles.Forsyth 	}
724b370703fSCharles.Forsyth 	if(t >= D_AL && t <= D_X0+15) {
725b370703fSCharles.Forsyth 		if(v)
726b370703fSCharles.Forsyth 			goto bad;
727b370703fSCharles.Forsyth 		*andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
728b370703fSCharles.Forsyth 		rexflag |= (regrex[t] & (0x40 | Rxb)) | rex;
729b370703fSCharles.Forsyth 		return;
730b370703fSCharles.Forsyth 	}
731b370703fSCharles.Forsyth 	if(t >= D_INDIR) {
732b370703fSCharles.Forsyth 		t -= D_INDIR;
733b370703fSCharles.Forsyth 		rexflag |= (regrex[t] & Rxb) | rex;
734b370703fSCharles.Forsyth 		if(t == D_NONE) {
735b370703fSCharles.Forsyth 			if(asmode != 64){
736b370703fSCharles.Forsyth 				*andptr++ = (0 << 6) | (5 << 0) | (r << 3);
737b370703fSCharles.Forsyth 				put4(v);
738b370703fSCharles.Forsyth 				return;
739b370703fSCharles.Forsyth 			}
740b370703fSCharles.Forsyth 			/* temporary */
741b370703fSCharles.Forsyth 			*andptr++ = (0 <<  6) | (4 << 0) | (r << 3);	/* sib present */
742b370703fSCharles.Forsyth 			*andptr++ = (0 << 6) | (4 << 3) | (5 << 0);	/* DS:d32 */
743b370703fSCharles.Forsyth 			put4(v);
744b370703fSCharles.Forsyth 			return;
745b370703fSCharles.Forsyth 		}
746b370703fSCharles.Forsyth 		if(t == D_SP || t == D_R12) {
747b370703fSCharles.Forsyth 			if(v == 0) {
748b370703fSCharles.Forsyth 				*andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
749b370703fSCharles.Forsyth 				asmidx(a, t);
750b370703fSCharles.Forsyth 				return;
751b370703fSCharles.Forsyth 			}
752b370703fSCharles.Forsyth 			if(v >= -128 && v < 128) {
753b370703fSCharles.Forsyth 				*andptr++ = (1 << 6) | (reg[t] << 0) | (r << 3);
754b370703fSCharles.Forsyth 				asmidx(a, t);
755b370703fSCharles.Forsyth 				*andptr++ = v;
756b370703fSCharles.Forsyth 				return;
757b370703fSCharles.Forsyth 			}
758b370703fSCharles.Forsyth 			*andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
759b370703fSCharles.Forsyth 			asmidx(a, t);
760b370703fSCharles.Forsyth 			put4(v);
761b370703fSCharles.Forsyth 			return;
762b370703fSCharles.Forsyth 		}
763b370703fSCharles.Forsyth 		if(t >= D_AX && t <= D_R15) {
764b370703fSCharles.Forsyth 			if(v == 0 && t != D_BP && t != D_R13) {
765b370703fSCharles.Forsyth 				*andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
766b370703fSCharles.Forsyth 				return;
767b370703fSCharles.Forsyth 			}
768b370703fSCharles.Forsyth 			if(v >= -128 && v < 128) {
769b370703fSCharles.Forsyth 				andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
770b370703fSCharles.Forsyth 				andptr[1] = v;
771b370703fSCharles.Forsyth 				andptr += 2;
772b370703fSCharles.Forsyth 				return;
773b370703fSCharles.Forsyth 			}
774b370703fSCharles.Forsyth 			*andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
775b370703fSCharles.Forsyth 			put4(v);
776b370703fSCharles.Forsyth 			return;
777b370703fSCharles.Forsyth 		}
778b370703fSCharles.Forsyth 		goto bad;
779b370703fSCharles.Forsyth 	}
780b370703fSCharles.Forsyth 	switch(a->type) {
781b370703fSCharles.Forsyth 	default:
782b370703fSCharles.Forsyth 		goto bad;
783b370703fSCharles.Forsyth 	case D_STATIC:
784b370703fSCharles.Forsyth 	case D_EXTERN:
785b370703fSCharles.Forsyth 		aa.type = D_NONE+D_INDIR;
786b370703fSCharles.Forsyth 		break;
787b370703fSCharles.Forsyth 	case D_AUTO:
788b370703fSCharles.Forsyth 	case D_PARAM:
789b370703fSCharles.Forsyth 		aa.type = D_SP+D_INDIR;
790b370703fSCharles.Forsyth 		break;
791b370703fSCharles.Forsyth 	}
792b370703fSCharles.Forsyth 	aa.index = D_NONE;
793b370703fSCharles.Forsyth 	aa.scale = 1;
794b370703fSCharles.Forsyth 	aa.offset = vaddr(a);
795b370703fSCharles.Forsyth 	asmandsz(&aa, r, rex, m64);
796b370703fSCharles.Forsyth 	return;
797b370703fSCharles.Forsyth bad:
798b370703fSCharles.Forsyth 	diag("asmand: bad address %D", a);
799b370703fSCharles.Forsyth 	return;
800b370703fSCharles.Forsyth }
801b370703fSCharles.Forsyth 
802b370703fSCharles.Forsyth void
asmand(Adr * a,Adr * ra)803b370703fSCharles.Forsyth asmand(Adr *a, Adr *ra)
804b370703fSCharles.Forsyth {
805b370703fSCharles.Forsyth 	asmandsz(a, reg[ra->type], regrex[ra->type], 0);
806b370703fSCharles.Forsyth }
807b370703fSCharles.Forsyth 
808b370703fSCharles.Forsyth void
asmando(Adr * a,int o)809b370703fSCharles.Forsyth asmando(Adr *a, int o)
810b370703fSCharles.Forsyth {
811b370703fSCharles.Forsyth 	asmandsz(a, o, 0, 0);
812b370703fSCharles.Forsyth }
813b370703fSCharles.Forsyth 
814b370703fSCharles.Forsyth static void
bytereg(Adr * a)815b370703fSCharles.Forsyth bytereg(Adr *a)
816b370703fSCharles.Forsyth {
817b370703fSCharles.Forsyth 	if(a->index == D_NONE && (a->type >= D_AX && a->type <= D_R15))
818b370703fSCharles.Forsyth 		a->type = D_AL + (a->type-D_AX);
819b370703fSCharles.Forsyth }
820b370703fSCharles.Forsyth 
821b370703fSCharles.Forsyth #define	E	0xff
822b370703fSCharles.Forsyth Movtab	ymovtab[] =
823b370703fSCharles.Forsyth {
824b370703fSCharles.Forsyth /* push */
825b370703fSCharles.Forsyth 	{APUSHL,	Ycs,	Ynone,	0,	0x0e,E,0,0},
826b370703fSCharles.Forsyth 	{APUSHL,	Yss,	Ynone,	0,	0x16,E,0,0},
827b370703fSCharles.Forsyth 	{APUSHL,	Yds,	Ynone,	0,	0x1e,E,0,0},
828b370703fSCharles.Forsyth 	{APUSHL,	Yes,	Ynone,	0,	0x06,E,0,0},
829b370703fSCharles.Forsyth 	{APUSHL,	Yfs,	Ynone,	0,	0x0f,0xa0,E,0},
830b370703fSCharles.Forsyth 	{APUSHL,	Ygs,	Ynone,	0,	0x0f,0xa8,E,0},
831b370703fSCharles.Forsyth 	{APUSHQ,	Yfs,	Ynone,	0,	0x0f,0xa0,E,0},
832b370703fSCharles.Forsyth 	{APUSHQ,	Ygs,	Ynone,	0,	0x0f,0xa8,E,0},
833b370703fSCharles.Forsyth 
834b370703fSCharles.Forsyth 	{APUSHW,	Ycs,	Ynone,	0,	Pe,0x0e,E,0},
835b370703fSCharles.Forsyth 	{APUSHW,	Yss,	Ynone,	0,	Pe,0x16,E,0},
836b370703fSCharles.Forsyth 	{APUSHW,	Yds,	Ynone,	0,	Pe,0x1e,E,0},
837b370703fSCharles.Forsyth 	{APUSHW,	Yes,	Ynone,	0,	Pe,0x06,E,0},
838b370703fSCharles.Forsyth 	{APUSHW,	Yfs,	Ynone,	0,	Pe,0x0f,0xa0,E},
839b370703fSCharles.Forsyth 	{APUSHW,	Ygs,	Ynone,	0,	Pe,0x0f,0xa8,E},
840b370703fSCharles.Forsyth 
841b370703fSCharles.Forsyth /* pop */
842b370703fSCharles.Forsyth 	{APOPL,	Ynone,	Yds,	0,	0x1f,E,0,0},
843b370703fSCharles.Forsyth 	{APOPL,	Ynone,	Yes,	0,	0x07,E,0,0},
844b370703fSCharles.Forsyth 	{APOPL,	Ynone,	Yss,	0,	0x17,E,0,0},
845b370703fSCharles.Forsyth 	{APOPL,	Ynone,	Yfs,	0,	0x0f,0xa1,E,0},
846b370703fSCharles.Forsyth 	{APOPL,	Ynone,	Ygs,	0,	0x0f,0xa9,E,0},
847b370703fSCharles.Forsyth 	{APOPQ,	Ynone,	Yfs,	0,	0x0f,0xa1,E,0},
848b370703fSCharles.Forsyth 	{APOPQ,	Ynone,	Ygs,	0,	0x0f,0xa9,E,0},
849b370703fSCharles.Forsyth 
850b370703fSCharles.Forsyth 	{APOPW,	Ynone,	Yds,	0,	Pe,0x1f,E,0},
851b370703fSCharles.Forsyth 	{APOPW,	Ynone,	Yes,	0,	Pe,0x07,E,0},
852b370703fSCharles.Forsyth 	{APOPW,	Ynone,	Yss,	0,	Pe,0x17,E,0},
853b370703fSCharles.Forsyth 	{APOPW,	Ynone,	Yfs,	0,	Pe,0x0f,0xa1,E},
854b370703fSCharles.Forsyth 	{APOPW,	Ynone,	Ygs,	0,	Pe,0x0f,0xa9,E},
855b370703fSCharles.Forsyth 
856b370703fSCharles.Forsyth /* mov seg */
857b370703fSCharles.Forsyth 	{AMOVW,	Yes,	Yml,	1,	0x8c,0,0,0},
858b370703fSCharles.Forsyth 	{AMOVW,	Ycs,	Yml,	1,	0x8c,1,0,0},
859b370703fSCharles.Forsyth 	{AMOVW,	Yss,	Yml,	1,	0x8c,2,0,0},
860b370703fSCharles.Forsyth 	{AMOVW,	Yds,	Yml,	1,	0x8c,3,0,0},
861b370703fSCharles.Forsyth 	{AMOVW,	Yfs,	Yml,	1,	0x8c,4,0,0},
862b370703fSCharles.Forsyth 	{AMOVW,	Ygs,	Yml,	1,	0x8c,5,0,0},
863b370703fSCharles.Forsyth 
864b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Yes,	2,	0x8e,0,0,0},
865b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Ycs,	2,	0x8e,1,0,0},
866b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Yss,	2,	0x8e,2,0,0},
867b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Yds,	2,	0x8e,3,0,0},
868b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Yfs,	2,	0x8e,4,0,0},
869b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Ygs,	2,	0x8e,5,0,0},
870b370703fSCharles.Forsyth 
871b370703fSCharles.Forsyth /* mov cr */
872b370703fSCharles.Forsyth 	{AMOVL,	Ycr0,	Yml,	3,	0x0f,0x20,0,0},
873b370703fSCharles.Forsyth 	{AMOVL,	Ycr2,	Yml,	3,	0x0f,0x20,2,0},
874b370703fSCharles.Forsyth 	{AMOVL,	Ycr3,	Yml,	3,	0x0f,0x20,3,0},
875b370703fSCharles.Forsyth 	{AMOVL,	Ycr4,	Yml,	3,	0x0f,0x20,4,0},
876b370703fSCharles.Forsyth 	{AMOVL,	Ycr8,	Yml,	3,	0x0f,0x20,8,0},
877b370703fSCharles.Forsyth 	{AMOVQ,	Ycr0,	Yml,	3,	0x0f,0x20,0,0},
878b370703fSCharles.Forsyth 	{AMOVQ,	Ycr2,	Yml,	3,	0x0f,0x20,2,0},
879b370703fSCharles.Forsyth 	{AMOVQ,	Ycr3,	Yml,	3,	0x0f,0x20,3,0},
880b370703fSCharles.Forsyth 	{AMOVQ,	Ycr4,	Yml,	3,	0x0f,0x20,4,0},
881b370703fSCharles.Forsyth 	{AMOVQ,	Ycr8,	Yml,	3,	0x0f,0x20,8,0},
882b370703fSCharles.Forsyth 
883b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ycr0,	4,	0x0f,0x22,0,0},
884b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ycr2,	4,	0x0f,0x22,2,0},
885b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ycr3,	4,	0x0f,0x22,3,0},
886b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ycr4,	4,	0x0f,0x22,4,0},
887b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ycr8,	4,	0x0f,0x22,8,0},
888b370703fSCharles.Forsyth 	{AMOVQ,	Yml,	Ycr0,	4,	0x0f,0x22,0,0},
889b370703fSCharles.Forsyth 	{AMOVQ,	Yml,	Ycr2,	4,	0x0f,0x22,2,0},
890b370703fSCharles.Forsyth 	{AMOVQ,	Yml,	Ycr3,	4,	0x0f,0x22,3,0},
891b370703fSCharles.Forsyth 	{AMOVQ,	Yml,	Ycr4,	4,	0x0f,0x22,4,0},
892b370703fSCharles.Forsyth 	{AMOVQ,	Yml,	Ycr8,	4,	0x0f,0x22,8,0},
893b370703fSCharles.Forsyth 
894b370703fSCharles.Forsyth /* mov dr */
895b370703fSCharles.Forsyth 	{AMOVL,	Ydr0,	Yml,	3,	0x0f,0x21,0,0},
896b370703fSCharles.Forsyth 	{AMOVL,	Ydr6,	Yml,	3,	0x0f,0x21,6,0},
897b370703fSCharles.Forsyth 	{AMOVL,	Ydr7,	Yml,	3,	0x0f,0x21,7,0},
898b370703fSCharles.Forsyth 	{AMOVQ,	Ydr0,	Yml,	3,	0x0f,0x21,0,0},
899b370703fSCharles.Forsyth 	{AMOVQ,	Ydr6,	Yml,	3,	0x0f,0x21,6,0},
900b370703fSCharles.Forsyth 	{AMOVQ,	Ydr7,	Yml,	3,	0x0f,0x21,7,0},
901b370703fSCharles.Forsyth 
902b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ydr0,	4,	0x0f,0x23,0,0},
903b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ydr6,	4,	0x0f,0x23,6,0},
904b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ydr7,	4,	0x0f,0x23,7,0},
905b370703fSCharles.Forsyth 	{AMOVQ,	Yml,	Ydr0,	4,	0x0f,0x23,0,0},
906b370703fSCharles.Forsyth 	{AMOVQ,	Yml,	Ydr6,	4,	0x0f,0x23,6,0},
907b370703fSCharles.Forsyth 	{AMOVQ,	Yml,	Ydr7,	4,	0x0f,0x23,7,0},
908b370703fSCharles.Forsyth 
909b370703fSCharles.Forsyth /* mov tr */
910b370703fSCharles.Forsyth 	{AMOVL,	Ytr6,	Yml,	3,	0x0f,0x24,6,0},
911b370703fSCharles.Forsyth 	{AMOVL,	Ytr7,	Yml,	3,	0x0f,0x24,7,0},
912b370703fSCharles.Forsyth 
913b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ytr6,	4,	0x0f,0x26,6,E},
914b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ytr7,	4,	0x0f,0x26,7,E},
915b370703fSCharles.Forsyth 
916b370703fSCharles.Forsyth /* lgdt, sgdt, lidt, sidt */
917b370703fSCharles.Forsyth 	{AMOVL,	Ym,	Ygdtr,	4,	0x0f,0x01,2,0},
918b370703fSCharles.Forsyth 	{AMOVL,	Ygdtr,	Ym,	3,	0x0f,0x01,0,0},
919b370703fSCharles.Forsyth 	{AMOVL,	Ym,	Yidtr,	4,	0x0f,0x01,3,0},
920b370703fSCharles.Forsyth 	{AMOVL,	Yidtr,	Ym,	3,	0x0f,0x01,1,0},
921b370703fSCharles.Forsyth 	{AMOVQ,	Ym,	Ygdtr,	4,	0x0f,0x01,2,0},
922b370703fSCharles.Forsyth 	{AMOVQ,	Ygdtr,	Ym,	3,	0x0f,0x01,0,0},
923b370703fSCharles.Forsyth 	{AMOVQ,	Ym,	Yidtr,	4,	0x0f,0x01,3,0},
924b370703fSCharles.Forsyth 	{AMOVQ,	Yidtr,	Ym,	3,	0x0f,0x01,1,0},
925b370703fSCharles.Forsyth 
926b370703fSCharles.Forsyth /* lldt, sldt */
927b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Yldtr,	4,	0x0f,0x00,2,0},
928b370703fSCharles.Forsyth 	{AMOVW,	Yldtr,	Yml,	3,	0x0f,0x00,0,0},
929b370703fSCharles.Forsyth 
930b370703fSCharles.Forsyth /* lmsw, smsw */
931b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Ymsw,	4,	0x0f,0x01,6,0},
932b370703fSCharles.Forsyth 	{AMOVW,	Ymsw,	Yml,	3,	0x0f,0x01,4,0},
933b370703fSCharles.Forsyth 
934b370703fSCharles.Forsyth /* ltr, str */
935b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Ytask,	4,	0x0f,0x00,3,0},
936b370703fSCharles.Forsyth 	{AMOVW,	Ytask,	Yml,	3,	0x0f,0x00,1,0},
937b370703fSCharles.Forsyth 
938b370703fSCharles.Forsyth /* load full pointer */
939b370703fSCharles.Forsyth 	{AMOVL,	Yml,	Ycol,	5,	0,0,0,0},
940b370703fSCharles.Forsyth 	{AMOVW,	Yml,	Ycol,	5,	Pe,0,0,0},
941b370703fSCharles.Forsyth 
942b370703fSCharles.Forsyth /* double shift */
943b370703fSCharles.Forsyth 	{ASHLL,	Ycol,	Yml,	6,	0xa4,0xa5,0,0},
944b370703fSCharles.Forsyth 	{ASHRL,	Ycol,	Yml,	6,	0xac,0xad,0,0},
945b370703fSCharles.Forsyth 	{ASHLQ,	Ycol,	Yml,	6,	Pw,0xa4,0xa5,0},
946b370703fSCharles.Forsyth 	{ASHRQ,	Ycol,	Yml,	6,	Pw,0xac,0xad,0},
947b370703fSCharles.Forsyth 	{ASHLW,	Ycol,	Yml,	6,	Pe,0xa4,0xa5,0},
948b370703fSCharles.Forsyth 	{ASHRW,	Ycol,	Yml,	6,	Pe,0xac,0xad,0},
949b370703fSCharles.Forsyth 	0
950b370703fSCharles.Forsyth };
951b370703fSCharles.Forsyth 
952b370703fSCharles.Forsyth int
isax(Adr * a)953b370703fSCharles.Forsyth isax(Adr *a)
954b370703fSCharles.Forsyth {
955b370703fSCharles.Forsyth 
956b370703fSCharles.Forsyth 	switch(a->type) {
957b370703fSCharles.Forsyth 	case D_AX:
958b370703fSCharles.Forsyth 	case D_AL:
959b370703fSCharles.Forsyth 	case D_AH:
960b370703fSCharles.Forsyth 	case D_INDIR+D_AX:
961b370703fSCharles.Forsyth 		return 1;
962b370703fSCharles.Forsyth 	}
963b370703fSCharles.Forsyth 	if(a->index == D_AX)
964b370703fSCharles.Forsyth 		return 1;
965b370703fSCharles.Forsyth 	return 0;
966b370703fSCharles.Forsyth }
967b370703fSCharles.Forsyth 
968b370703fSCharles.Forsyth void
subreg(Prog * p,int from,int to)969b370703fSCharles.Forsyth subreg(Prog *p, int from, int to)
970b370703fSCharles.Forsyth {
971b370703fSCharles.Forsyth 
972b370703fSCharles.Forsyth 	if(debug['Q'])
973b370703fSCharles.Forsyth 		print("\n%P	s/%R/%R/\n", p, from, to);
974b370703fSCharles.Forsyth 
975b370703fSCharles.Forsyth 	if(p->from.type == from)
976b370703fSCharles.Forsyth 		p->from.type = to;
977b370703fSCharles.Forsyth 	if(p->to.type == from)
978b370703fSCharles.Forsyth 		p->to.type = to;
979b370703fSCharles.Forsyth 
980b370703fSCharles.Forsyth 	if(p->from.index == from)
981b370703fSCharles.Forsyth 		p->from.index = to;
982b370703fSCharles.Forsyth 	if(p->to.index == from)
983b370703fSCharles.Forsyth 		p->to.index = to;
984b370703fSCharles.Forsyth 
985b370703fSCharles.Forsyth 	from += D_INDIR;
986b370703fSCharles.Forsyth 	if(p->from.type == from)
987b370703fSCharles.Forsyth 		p->from.type = to+D_INDIR;
988b370703fSCharles.Forsyth 	if(p->to.type == from)
989b370703fSCharles.Forsyth 		p->to.type = to+D_INDIR;
990b370703fSCharles.Forsyth 
991b370703fSCharles.Forsyth 	if(debug['Q'])
992b370703fSCharles.Forsyth 		print("%P\n", p);
993b370703fSCharles.Forsyth }
994b370703fSCharles.Forsyth 
995b370703fSCharles.Forsyth static int
mediaop(Optab * o,int op,int osize,int z)996b370703fSCharles.Forsyth mediaop(Optab *o, int op, int osize, int z)
997b370703fSCharles.Forsyth {
998b370703fSCharles.Forsyth 	switch(op){
999b370703fSCharles.Forsyth 	case Pm:
1000b370703fSCharles.Forsyth 	case Pe:
1001b370703fSCharles.Forsyth 	case Pf2:
1002b370703fSCharles.Forsyth 	case Pf3:
1003b370703fSCharles.Forsyth 		if(osize != 1){
1004b370703fSCharles.Forsyth 			if(op != Pm)
1005b370703fSCharles.Forsyth 				*andptr++ = op;
1006b370703fSCharles.Forsyth 			*andptr++ = Pm;
1007b370703fSCharles.Forsyth 			op = o->op[++z];
1008b370703fSCharles.Forsyth 			break;
1009b370703fSCharles.Forsyth 		}
1010b370703fSCharles.Forsyth 	default:
1011b370703fSCharles.Forsyth 		if(andptr == and || andptr[-1] != Pm)
1012b370703fSCharles.Forsyth 			*andptr++ = Pm;
1013b370703fSCharles.Forsyth 		break;
1014b370703fSCharles.Forsyth 	}
1015b370703fSCharles.Forsyth 	*andptr++ = op;
1016b370703fSCharles.Forsyth 	return z;
1017b370703fSCharles.Forsyth }
1018b370703fSCharles.Forsyth 
1019b370703fSCharles.Forsyth void
doasm(Prog * p)1020b370703fSCharles.Forsyth doasm(Prog *p)
1021b370703fSCharles.Forsyth {
1022b370703fSCharles.Forsyth 	Optab *o;
1023b370703fSCharles.Forsyth 	Prog *q, pp;
1024b370703fSCharles.Forsyth 	uchar *t;
1025b370703fSCharles.Forsyth 	Movtab *mo;
1026b370703fSCharles.Forsyth 	int z, op, ft, tt, xo, l;
1027b370703fSCharles.Forsyth 	vlong v;
1028b370703fSCharles.Forsyth 
1029b370703fSCharles.Forsyth 	o = opindex[p->as];
1030b370703fSCharles.Forsyth 	if(o == nil) {
1031b370703fSCharles.Forsyth 		diag("asmins: missing op %P", p);
1032b370703fSCharles.Forsyth 		return;
1033b370703fSCharles.Forsyth 	}
1034b370703fSCharles.Forsyth 	ft = oclass(&p->from) * Ymax;
1035b370703fSCharles.Forsyth 	tt = oclass(&p->to) * Ymax;
1036b370703fSCharles.Forsyth 	t = o->ytab;
1037b370703fSCharles.Forsyth 	if(t == 0) {
1038b370703fSCharles.Forsyth 		diag("asmins: noproto %P", p);
1039b370703fSCharles.Forsyth 		return;
1040b370703fSCharles.Forsyth 	}
1041b370703fSCharles.Forsyth 	xo = o->op[0] == 0x0f;
1042b370703fSCharles.Forsyth 	for(z=0; *t; z+=t[3]+xo,t+=4)
1043b370703fSCharles.Forsyth 		if(ycover[ft+t[0]])
1044b370703fSCharles.Forsyth 		if(ycover[tt+t[1]])
1045b370703fSCharles.Forsyth 			goto found;
1046b370703fSCharles.Forsyth 	goto domov;
1047b370703fSCharles.Forsyth 
1048b370703fSCharles.Forsyth found:
1049b370703fSCharles.Forsyth 	switch(o->prefix) {
1050b370703fSCharles.Forsyth 	case Pq:	/* 16 bit escape and opcode escape */
1051b370703fSCharles.Forsyth 		*andptr++ = Pe;
1052b370703fSCharles.Forsyth 		*andptr++ = Pm;
1053b370703fSCharles.Forsyth 		break;
1054b370703fSCharles.Forsyth 
1055b370703fSCharles.Forsyth 	case Pf2:	/* xmm opcode escape */
1056b370703fSCharles.Forsyth 	case Pf3:
1057b370703fSCharles.Forsyth 		*andptr++ = o->prefix;
1058b370703fSCharles.Forsyth 		*andptr++ = Pm;
1059b370703fSCharles.Forsyth 		break;
1060b370703fSCharles.Forsyth 
1061b370703fSCharles.Forsyth 	case Pm:	/* opcode escape */
1062b370703fSCharles.Forsyth 		*andptr++ = Pm;
1063b370703fSCharles.Forsyth 		break;
1064b370703fSCharles.Forsyth 
1065b370703fSCharles.Forsyth 	case Pe:	/* 16 bit escape */
1066b370703fSCharles.Forsyth 		*andptr++ = Pe;
1067b370703fSCharles.Forsyth 		break;
1068b370703fSCharles.Forsyth 
1069b370703fSCharles.Forsyth 	case Pw:	/* 64-bit escape */
1070b370703fSCharles.Forsyth 		if(p->mode != 64)
1071b370703fSCharles.Forsyth 			diag("asmins: illegal 64: %P", p);
1072b370703fSCharles.Forsyth 		rexflag |= Pw;
1073b370703fSCharles.Forsyth 		break;
1074b370703fSCharles.Forsyth 
1075b370703fSCharles.Forsyth 	case Pb:	/* botch */
1076b370703fSCharles.Forsyth 		bytereg(&p->from);
1077b370703fSCharles.Forsyth 		bytereg(&p->to);
1078b370703fSCharles.Forsyth 		break;
1079b370703fSCharles.Forsyth 
1080b370703fSCharles.Forsyth 	case P32:	/* 32 bit but illegal if 64-bit mode */
1081b370703fSCharles.Forsyth 		if(p->mode == 64)
1082b370703fSCharles.Forsyth 			diag("asmins: illegal in 64-bit mode: %P", p);
1083b370703fSCharles.Forsyth 		break;
1084b370703fSCharles.Forsyth 
1085b370703fSCharles.Forsyth 	case Py:	/* 64-bit only, no prefix */
1086b370703fSCharles.Forsyth 		if(p->mode != 64)
1087b370703fSCharles.Forsyth 			diag("asmins: illegal in %d-bit mode: %P", p->mode, p);
1088b370703fSCharles.Forsyth 		break;
1089b370703fSCharles.Forsyth 	}
1090b370703fSCharles.Forsyth 	v = vaddr(&p->from);
1091b370703fSCharles.Forsyth 	op = o->op[z];
1092b370703fSCharles.Forsyth 	if(op == 0x0f) {
1093b370703fSCharles.Forsyth 		*andptr++ = op;
1094b370703fSCharles.Forsyth 		op = o->op[++z];
1095b370703fSCharles.Forsyth 	}
1096b370703fSCharles.Forsyth 	switch(t[2]) {
1097b370703fSCharles.Forsyth 	default:
1098b370703fSCharles.Forsyth 		diag("asmins: unknown z %d %P", t[2], p);
1099b370703fSCharles.Forsyth 		return;
1100b370703fSCharles.Forsyth 
1101b370703fSCharles.Forsyth 	case Zpseudo:
1102b370703fSCharles.Forsyth 		break;
1103b370703fSCharles.Forsyth 
1104b370703fSCharles.Forsyth 	case Zlit:
1105b370703fSCharles.Forsyth 		for(; op = o->op[z]; z++)
1106b370703fSCharles.Forsyth 			*andptr++ = op;
1107b370703fSCharles.Forsyth 		break;
1108b370703fSCharles.Forsyth 
1109b370703fSCharles.Forsyth 	case Zmb_r:
1110b370703fSCharles.Forsyth 		bytereg(&p->from);
1111b370703fSCharles.Forsyth 		/* fall through */
1112b370703fSCharles.Forsyth 	case Zm_r:
1113b370703fSCharles.Forsyth 		*andptr++ = op;
1114b370703fSCharles.Forsyth 		asmand(&p->from, &p->to);
1115b370703fSCharles.Forsyth 		break;
1116b370703fSCharles.Forsyth 
1117b370703fSCharles.Forsyth 	case Zm_r_xm:
1118b370703fSCharles.Forsyth 		mediaop(o, op, t[3], z);
1119b370703fSCharles.Forsyth 		asmand(&p->from, &p->to);
1120b370703fSCharles.Forsyth 		break;
1121b370703fSCharles.Forsyth 
1122b370703fSCharles.Forsyth 	case Zm_r_xm_nr:
1123b370703fSCharles.Forsyth 		rexflag = 0;
1124b370703fSCharles.Forsyth 		mediaop(o, op, t[3], z);
1125b370703fSCharles.Forsyth 		asmand(&p->from, &p->to);
1126b370703fSCharles.Forsyth 		break;
1127b370703fSCharles.Forsyth 
1128b370703fSCharles.Forsyth 	case Zm_r_i_xm:
1129b370703fSCharles.Forsyth 		mediaop(o, op, t[3], z);
1130b370703fSCharles.Forsyth 		asmand(&p->from, &p->to);
1131b370703fSCharles.Forsyth 		*andptr++ = p->to.offset;
1132b370703fSCharles.Forsyth 		break;
1133b370703fSCharles.Forsyth 
1134b370703fSCharles.Forsyth 	case Zm_r_3d:
1135b370703fSCharles.Forsyth 		*andptr++ = 0x0f;
1136b370703fSCharles.Forsyth 		*andptr++ = 0x0f;
1137b370703fSCharles.Forsyth 		asmand(&p->from, &p->to);
1138b370703fSCharles.Forsyth 		*andptr++ = op;
1139b370703fSCharles.Forsyth 		break;
1140b370703fSCharles.Forsyth 
1141b370703fSCharles.Forsyth 	case Zibm_r:
1142b370703fSCharles.Forsyth 		*andptr++ = op;
1143b370703fSCharles.Forsyth 		asmand(&p->from, &p->to);
1144b370703fSCharles.Forsyth 		*andptr++ = p->to.offset;
1145b370703fSCharles.Forsyth 		break;
1146b370703fSCharles.Forsyth 
1147b370703fSCharles.Forsyth 	case Zaut_r:
1148b370703fSCharles.Forsyth 		*andptr++ = 0x8d;	/* leal */
1149b370703fSCharles.Forsyth 		if(p->from.type != D_ADDR)
1150b370703fSCharles.Forsyth 			diag("asmins: Zaut sb type ADDR");
1151b370703fSCharles.Forsyth 		p->from.type = p->from.index;
1152b370703fSCharles.Forsyth 		p->from.index = D_NONE;
1153b370703fSCharles.Forsyth 		asmand(&p->from, &p->to);
1154b370703fSCharles.Forsyth 		p->from.index = p->from.type;
1155b370703fSCharles.Forsyth 		p->from.type = D_ADDR;
1156b370703fSCharles.Forsyth 		break;
1157b370703fSCharles.Forsyth 
1158b370703fSCharles.Forsyth 	case Zm_o:
1159b370703fSCharles.Forsyth 		*andptr++ = op;
1160b370703fSCharles.Forsyth 		asmando(&p->from, o->op[z+1]);
1161b370703fSCharles.Forsyth 		break;
1162b370703fSCharles.Forsyth 
1163b370703fSCharles.Forsyth 	case Zr_m:
1164b370703fSCharles.Forsyth 		*andptr++ = op;
1165b370703fSCharles.Forsyth 		asmand(&p->to, &p->from);
1166b370703fSCharles.Forsyth 		break;
1167b370703fSCharles.Forsyth 
1168b370703fSCharles.Forsyth 	case Zr_m_xm:
1169b370703fSCharles.Forsyth 		mediaop(o, op, t[3], z);
1170b370703fSCharles.Forsyth 		asmand(&p->to, &p->from);
1171b370703fSCharles.Forsyth 		break;
1172b370703fSCharles.Forsyth 
1173b370703fSCharles.Forsyth 	case Zr_m_xm_nr:
1174b370703fSCharles.Forsyth 		rexflag = 0;
1175b370703fSCharles.Forsyth 		mediaop(o, op, t[3], z);
1176b370703fSCharles.Forsyth 		asmand(&p->to, &p->from);
1177b370703fSCharles.Forsyth 		break;
1178b370703fSCharles.Forsyth 
1179b370703fSCharles.Forsyth 	case Zr_m_i_xm:
1180b370703fSCharles.Forsyth 		mediaop(o, op, t[3], z);
1181b370703fSCharles.Forsyth 		asmand(&p->to, &p->from);
1182b370703fSCharles.Forsyth 		*andptr++ = p->from.offset;
1183b370703fSCharles.Forsyth 		break;
1184b370703fSCharles.Forsyth 
1185b370703fSCharles.Forsyth 	case Zo_m:
1186b370703fSCharles.Forsyth 		*andptr++ = op;
1187b370703fSCharles.Forsyth 		asmando(&p->to, o->op[z+1]);
1188b370703fSCharles.Forsyth 		break;
1189b370703fSCharles.Forsyth 
1190b370703fSCharles.Forsyth 	case Zo_m64:
1191b370703fSCharles.Forsyth 		*andptr++ = op;
1192b370703fSCharles.Forsyth 		asmandsz(&p->to, o->op[z+1], 0, 1);
1193b370703fSCharles.Forsyth 		break;
1194b370703fSCharles.Forsyth 
1195b370703fSCharles.Forsyth 	case Zm_ibo:
1196b370703fSCharles.Forsyth 		v = vaddr(&p->to);
1197b370703fSCharles.Forsyth 		*andptr++ = op;
1198b370703fSCharles.Forsyth 		asmando(&p->from, o->op[z+1]);
1199b370703fSCharles.Forsyth 		*andptr++ = v;
1200b370703fSCharles.Forsyth 		break;
1201b370703fSCharles.Forsyth 
1202b370703fSCharles.Forsyth 	case Zibo_m:
1203b370703fSCharles.Forsyth 		*andptr++ = op;
1204b370703fSCharles.Forsyth 		asmando(&p->to, o->op[z+1]);
1205b370703fSCharles.Forsyth 		*andptr++ = v;
1206b370703fSCharles.Forsyth 		break;
1207b370703fSCharles.Forsyth 
1208b370703fSCharles.Forsyth 	case Zibo_m_xm:
1209b370703fSCharles.Forsyth 		z = mediaop(o, op, t[3], z);
1210b370703fSCharles.Forsyth 		asmando(&p->to, o->op[z+1]);
1211b370703fSCharles.Forsyth 		*andptr++ = v;
1212b370703fSCharles.Forsyth 		break;
1213b370703fSCharles.Forsyth 
1214b370703fSCharles.Forsyth 	case Z_ib:
1215b370703fSCharles.Forsyth 		v = vaddr(&p->to);
1216b370703fSCharles.Forsyth 	case Zib_:
1217b370703fSCharles.Forsyth 		*andptr++ = op;
1218b370703fSCharles.Forsyth 		*andptr++ = v;
1219b370703fSCharles.Forsyth 		break;
1220b370703fSCharles.Forsyth 
1221b370703fSCharles.Forsyth 	case Zib_rp:
1222b370703fSCharles.Forsyth 		rexflag |= regrex[p->to.type] & (Rxb|0x40);
1223b370703fSCharles.Forsyth 		*andptr++ = op + reg[p->to.type];
1224b370703fSCharles.Forsyth 		*andptr++ = v;
1225b370703fSCharles.Forsyth 		break;
1226b370703fSCharles.Forsyth 
1227b370703fSCharles.Forsyth 	case Zil_rp:
1228b370703fSCharles.Forsyth 		rexflag |= regrex[p->to.type] & Rxb;
1229b370703fSCharles.Forsyth 		*andptr++ = op + reg[p->to.type];
1230b370703fSCharles.Forsyth 		if(o->prefix == Pe) {
1231b370703fSCharles.Forsyth 			*andptr++ = v;
1232b370703fSCharles.Forsyth 			*andptr++ = v>>8;
1233b370703fSCharles.Forsyth 		}
1234b370703fSCharles.Forsyth 		else
1235b370703fSCharles.Forsyth 			put4(v);
1236b370703fSCharles.Forsyth 		break;
1237b370703fSCharles.Forsyth 
1238b370703fSCharles.Forsyth 	case Zo_iw:
1239b370703fSCharles.Forsyth 		*andptr++ = op;
1240b370703fSCharles.Forsyth 		if(p->from.type != D_NONE){
1241b370703fSCharles.Forsyth 			*andptr++ = v;
1242b370703fSCharles.Forsyth 			*andptr++ = v>>8;
1243b370703fSCharles.Forsyth 		}
1244b370703fSCharles.Forsyth 		break;
1245b370703fSCharles.Forsyth 
1246b370703fSCharles.Forsyth 	case Ziq_rp:
1247b370703fSCharles.Forsyth 		l = v>>32;
1248b370703fSCharles.Forsyth 		if(l == 0){
1249b370703fSCharles.Forsyth 			//p->mark |= 0100;
1250b370703fSCharles.Forsyth 			//print("zero: %llux %P\n", v, p);
1251b370703fSCharles.Forsyth 			rexflag &= ~(0x40|Rxw);
1252b370703fSCharles.Forsyth 			rexflag |= regrex[p->to.type] & Rxb;
1253b370703fSCharles.Forsyth 			*andptr++ = 0xb8 + reg[p->to.type];
1254b370703fSCharles.Forsyth 			put4(v);
1255b370703fSCharles.Forsyth 		}else if(l == -1 && (v&((uvlong)1<<31))!=0){	/* sign extend */
1256b370703fSCharles.Forsyth 			//p->mark |= 0100;
1257b370703fSCharles.Forsyth 			//print("sign: %llux %P\n", v, p);
1258b370703fSCharles.Forsyth 			*andptr ++ = 0xc7;
1259b370703fSCharles.Forsyth 			asmando(&p->to, 0);
1260b370703fSCharles.Forsyth 			put4(v);
1261b370703fSCharles.Forsyth 		}else{	/* need all 8 */
1262b370703fSCharles.Forsyth 			//print("all: %llux %P\n", v, p);
1263b370703fSCharles.Forsyth 			rexflag |= regrex[p->to.type] & Rxb;
1264b370703fSCharles.Forsyth 			*andptr++ = op + reg[p->to.type];
1265b370703fSCharles.Forsyth 			put8(v);
1266b370703fSCharles.Forsyth 		}
1267b370703fSCharles.Forsyth 		break;
1268b370703fSCharles.Forsyth 
1269b370703fSCharles.Forsyth 	case Zib_rr:
1270b370703fSCharles.Forsyth 		*andptr++ = op;
1271b370703fSCharles.Forsyth 		asmand(&p->to, &p->to);
1272b370703fSCharles.Forsyth 		*andptr++ = v;
1273b370703fSCharles.Forsyth 		break;
1274b370703fSCharles.Forsyth 
1275b370703fSCharles.Forsyth 	case Z_il:
1276b370703fSCharles.Forsyth 		v = vaddr(&p->to);
1277b370703fSCharles.Forsyth 	case Zil_:
1278b370703fSCharles.Forsyth 		*andptr++ = op;
1279b370703fSCharles.Forsyth 		if(o->prefix == Pe) {
1280b370703fSCharles.Forsyth 			*andptr++ = v;
1281b370703fSCharles.Forsyth 			*andptr++ = v>>8;
1282b370703fSCharles.Forsyth 		}
1283b370703fSCharles.Forsyth 		else
1284b370703fSCharles.Forsyth 			put4(v);
1285b370703fSCharles.Forsyth 		break;
1286b370703fSCharles.Forsyth 
1287b370703fSCharles.Forsyth 	case Zm_ilo:
1288b370703fSCharles.Forsyth 		v = vaddr(&p->to);
1289b370703fSCharles.Forsyth 		*andptr++ = op;
1290b370703fSCharles.Forsyth 		asmando(&p->from, o->op[z+1]);
1291b370703fSCharles.Forsyth 		if(o->prefix == Pe) {
1292b370703fSCharles.Forsyth 			*andptr++ = v;
1293b370703fSCharles.Forsyth 			*andptr++ = v>>8;
1294b370703fSCharles.Forsyth 		}
1295b370703fSCharles.Forsyth 		else
1296b370703fSCharles.Forsyth 			put4(v);
1297b370703fSCharles.Forsyth 		break;
1298b370703fSCharles.Forsyth 
1299b370703fSCharles.Forsyth 	case Zilo_m:
1300b370703fSCharles.Forsyth 		*andptr++ = op;
1301b370703fSCharles.Forsyth 		asmando(&p->to, o->op[z+1]);
1302b370703fSCharles.Forsyth 		if(o->prefix == Pe) {
1303b370703fSCharles.Forsyth 			*andptr++ = v;
1304b370703fSCharles.Forsyth 			*andptr++ = v>>8;
1305b370703fSCharles.Forsyth 		}
1306b370703fSCharles.Forsyth 		else
1307b370703fSCharles.Forsyth 			put4(v);
1308b370703fSCharles.Forsyth 		break;
1309b370703fSCharles.Forsyth 
1310b370703fSCharles.Forsyth 	case Zil_rr:
1311b370703fSCharles.Forsyth 		*andptr++ = op;
1312b370703fSCharles.Forsyth 		asmand(&p->to, &p->to);
1313b370703fSCharles.Forsyth 		if(o->prefix == Pe) {
1314b370703fSCharles.Forsyth 			*andptr++ = v;
1315b370703fSCharles.Forsyth 			*andptr++ = v>>8;
1316b370703fSCharles.Forsyth 		}
1317b370703fSCharles.Forsyth 		else
1318b370703fSCharles.Forsyth 			put4(v);
1319b370703fSCharles.Forsyth 		break;
1320b370703fSCharles.Forsyth 
1321b370703fSCharles.Forsyth 	case Z_rp:
1322b370703fSCharles.Forsyth 		rexflag |= regrex[p->to.type] & (Rxb|0x40);
1323b370703fSCharles.Forsyth 		*andptr++ = op + reg[p->to.type];
1324b370703fSCharles.Forsyth 		break;
1325b370703fSCharles.Forsyth 
1326b370703fSCharles.Forsyth 	case Zrp_:
1327b370703fSCharles.Forsyth 		rexflag |= regrex[p->from.type] & (Rxb|0x40);
1328b370703fSCharles.Forsyth 		*andptr++ = op + reg[p->from.type];
1329b370703fSCharles.Forsyth 		break;
1330b370703fSCharles.Forsyth 
1331b370703fSCharles.Forsyth 	case Zclr:
1332b370703fSCharles.Forsyth 		*andptr++ = op;
1333b370703fSCharles.Forsyth 		asmand(&p->to, &p->to);
1334b370703fSCharles.Forsyth 		break;
1335b370703fSCharles.Forsyth 
1336b370703fSCharles.Forsyth 	case Zbr:
1337b370703fSCharles.Forsyth 		q = p->pcond;
1338b370703fSCharles.Forsyth 		if(q) {
1339b370703fSCharles.Forsyth 			v = q->pc - p->pc - 2;
1340b370703fSCharles.Forsyth 			if(v >= -128 && v <= 127) {
1341b370703fSCharles.Forsyth 				*andptr++ = op;
1342b370703fSCharles.Forsyth 				*andptr++ = v;
1343b370703fSCharles.Forsyth 			} else {
1344b370703fSCharles.Forsyth 				v -= 6-2;
1345b370703fSCharles.Forsyth 				*andptr++ = 0x0f;
1346b370703fSCharles.Forsyth 				*andptr++ = o->op[z+1];
1347b370703fSCharles.Forsyth 				*andptr++ = v;
1348b370703fSCharles.Forsyth 				*andptr++ = v>>8;
1349b370703fSCharles.Forsyth 				*andptr++ = v>>16;
1350b370703fSCharles.Forsyth 				*andptr++ = v>>24;
1351b370703fSCharles.Forsyth 			}
1352b370703fSCharles.Forsyth 		}
1353b370703fSCharles.Forsyth 		break;
1354b370703fSCharles.Forsyth 
1355b370703fSCharles.Forsyth 	case Zcall:
1356b370703fSCharles.Forsyth 		q = p->pcond;
1357b370703fSCharles.Forsyth 		if(q) {
1358b370703fSCharles.Forsyth 			v = q->pc - p->pc - 5;
1359b370703fSCharles.Forsyth 			if(dlm && curp != P && p->to.sym->type == SUNDEF){
1360b370703fSCharles.Forsyth 				/* v = 0 - p->pc - 5; */
1361b370703fSCharles.Forsyth 				v = 0;
1362b370703fSCharles.Forsyth 				ckoff(p->to.sym, v);
1363b370703fSCharles.Forsyth 				v += p->to.sym->value;
1364b370703fSCharles.Forsyth 				dynreloc(p->to.sym, p->pc+1, 0);
1365b370703fSCharles.Forsyth 			}
1366b370703fSCharles.Forsyth 			*andptr++ = op;
1367b370703fSCharles.Forsyth 			*andptr++ = v;
1368b370703fSCharles.Forsyth 			*andptr++ = v>>8;
1369b370703fSCharles.Forsyth 			*andptr++ = v>>16;
1370b370703fSCharles.Forsyth 			*andptr++ = v>>24;
1371b370703fSCharles.Forsyth 		}
1372b370703fSCharles.Forsyth 		break;
1373b370703fSCharles.Forsyth 
1374b370703fSCharles.Forsyth 	case Zjmp:
1375b370703fSCharles.Forsyth 		q = p->pcond;
1376b370703fSCharles.Forsyth 		if(q) {
1377b370703fSCharles.Forsyth 			v = q->pc - p->pc - 2;
1378b370703fSCharles.Forsyth 			if(v >= -128 && v <= 127) {
1379b370703fSCharles.Forsyth 				*andptr++ = op;
1380b370703fSCharles.Forsyth 				*andptr++ = v;
1381b370703fSCharles.Forsyth 			} else {
1382b370703fSCharles.Forsyth 				v -= 5-2;
1383b370703fSCharles.Forsyth 				*andptr++ = o->op[z+1];
1384b370703fSCharles.Forsyth 				*andptr++ = v;
1385b370703fSCharles.Forsyth 				*andptr++ = v>>8;
1386b370703fSCharles.Forsyth 				*andptr++ = v>>16;
1387b370703fSCharles.Forsyth 				*andptr++ = v>>24;
1388b370703fSCharles.Forsyth 			}
1389b370703fSCharles.Forsyth 		}
1390b370703fSCharles.Forsyth 		break;
1391b370703fSCharles.Forsyth 
1392b370703fSCharles.Forsyth 	case Zloop:
1393b370703fSCharles.Forsyth 		q = p->pcond;
1394b370703fSCharles.Forsyth 		if(q) {
1395b370703fSCharles.Forsyth 			v = q->pc - p->pc - 2;
1396*45a20ab7Sforsyth 			if(v < -128 || v > 127)
1397b370703fSCharles.Forsyth 				diag("loop too far: %P", p);
1398b370703fSCharles.Forsyth 			*andptr++ = op;
1399b370703fSCharles.Forsyth 			*andptr++ = v;
1400b370703fSCharles.Forsyth 		}
1401b370703fSCharles.Forsyth 		break;
1402b370703fSCharles.Forsyth 
1403b370703fSCharles.Forsyth 	case Zbyte:
1404b370703fSCharles.Forsyth 		*andptr++ = v;
1405b370703fSCharles.Forsyth 		if(op > 1) {
1406b370703fSCharles.Forsyth 			*andptr++ = v>>8;
1407b370703fSCharles.Forsyth 			if(op > 2) {
1408b370703fSCharles.Forsyth 				*andptr++ = v>>16;
1409b370703fSCharles.Forsyth 				*andptr++ = v>>24;
1410b370703fSCharles.Forsyth 				if(op > 4) {
1411b370703fSCharles.Forsyth 					*andptr++ = v>>32;
1412b370703fSCharles.Forsyth 					*andptr++ = v>>40;
1413b370703fSCharles.Forsyth 					*andptr++ = v>>48;
1414b370703fSCharles.Forsyth 					*andptr++ = v>>56;
1415b370703fSCharles.Forsyth 				}
1416b370703fSCharles.Forsyth 			}
1417b370703fSCharles.Forsyth 		}
1418b370703fSCharles.Forsyth 		break;
1419b370703fSCharles.Forsyth 	}
1420b370703fSCharles.Forsyth 	return;
1421b370703fSCharles.Forsyth 
1422b370703fSCharles.Forsyth domov:
1423b370703fSCharles.Forsyth 	for(mo=ymovtab; mo->as; mo++)
1424b370703fSCharles.Forsyth 		if(p->as == mo->as)
1425b370703fSCharles.Forsyth 		if(ycover[ft+mo->ft])
1426b370703fSCharles.Forsyth 		if(ycover[tt+mo->tt]){
1427b370703fSCharles.Forsyth 			t = mo->op;
1428b370703fSCharles.Forsyth 			goto mfound;
1429b370703fSCharles.Forsyth 		}
1430b370703fSCharles.Forsyth bad:
1431b370703fSCharles.Forsyth 	if(p->mode != 64){
1432b370703fSCharles.Forsyth 		/*
1433b370703fSCharles.Forsyth 		 * here, the assembly has failed.
1434b370703fSCharles.Forsyth 		 * if its a byte instruction that has
1435b370703fSCharles.Forsyth 		 * unaddressable registers, try to
1436b370703fSCharles.Forsyth 		 * exchange registers and reissue the
1437b370703fSCharles.Forsyth 		 * instruction with the operands renamed.
1438b370703fSCharles.Forsyth 		 */
1439b370703fSCharles.Forsyth 		pp = *p;
1440b370703fSCharles.Forsyth 		z = p->from.type;
1441b370703fSCharles.Forsyth 		if(z >= D_BP && z <= D_DI) {
1442b370703fSCharles.Forsyth 			if(isax(&p->to)) {
1443b370703fSCharles.Forsyth 				*andptr++ = 0x87;			/* xchg lhs,bx */
1444b370703fSCharles.Forsyth 				asmando(&p->from, reg[D_BX]);
1445b370703fSCharles.Forsyth 				subreg(&pp, z, D_BX);
1446b370703fSCharles.Forsyth 				doasm(&pp);
1447b370703fSCharles.Forsyth 				*andptr++ = 0x87;			/* xchg lhs,bx */
1448b370703fSCharles.Forsyth 				asmando(&p->from, reg[D_BX]);
1449b370703fSCharles.Forsyth 			} else {
1450b370703fSCharles.Forsyth 				*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
1451b370703fSCharles.Forsyth 				subreg(&pp, z, D_AX);
1452b370703fSCharles.Forsyth 				doasm(&pp);
1453b370703fSCharles.Forsyth 				*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
1454b370703fSCharles.Forsyth 			}
1455b370703fSCharles.Forsyth 			return;
1456b370703fSCharles.Forsyth 		}
1457b370703fSCharles.Forsyth 		z = p->to.type;
1458b370703fSCharles.Forsyth 		if(z >= D_BP && z <= D_DI) {
1459b370703fSCharles.Forsyth 			if(isax(&p->from)) {
1460b370703fSCharles.Forsyth 				*andptr++ = 0x87;			/* xchg rhs,bx */
1461b370703fSCharles.Forsyth 				asmando(&p->to, reg[D_BX]);
1462b370703fSCharles.Forsyth 				subreg(&pp, z, D_BX);
1463b370703fSCharles.Forsyth 				doasm(&pp);
1464b370703fSCharles.Forsyth 				*andptr++ = 0x87;			/* xchg rhs,bx */
1465b370703fSCharles.Forsyth 				asmando(&p->to, reg[D_BX]);
1466b370703fSCharles.Forsyth 			} else {
1467b370703fSCharles.Forsyth 				*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
1468b370703fSCharles.Forsyth 				subreg(&pp, z, D_AX);
1469b370703fSCharles.Forsyth 				doasm(&pp);
1470b370703fSCharles.Forsyth 				*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
1471b370703fSCharles.Forsyth 			}
1472b370703fSCharles.Forsyth 			return;
1473b370703fSCharles.Forsyth 		}
1474b370703fSCharles.Forsyth 	}
1475b370703fSCharles.Forsyth 	diag("doasm: notfound from=%ux to=%ux %P", p->from.type, p->to.type, p);
1476b370703fSCharles.Forsyth 	return;
1477b370703fSCharles.Forsyth 
1478b370703fSCharles.Forsyth mfound:
1479b370703fSCharles.Forsyth 	switch(mo->code) {
1480b370703fSCharles.Forsyth 	default:
1481b370703fSCharles.Forsyth 		diag("asmins: unknown mov %d %P", mo->code, p);
1482b370703fSCharles.Forsyth 		break;
1483b370703fSCharles.Forsyth 
1484b370703fSCharles.Forsyth 	case 0:	/* lit */
1485b370703fSCharles.Forsyth 		for(z=0; t[z]!=E; z++)
1486b370703fSCharles.Forsyth 			*andptr++ = t[z];
1487b370703fSCharles.Forsyth 		break;
1488b370703fSCharles.Forsyth 
1489b370703fSCharles.Forsyth 	case 1:	/* r,m */
1490b370703fSCharles.Forsyth 		*andptr++ = t[0];
1491b370703fSCharles.Forsyth 		asmando(&p->to, t[1]);
1492b370703fSCharles.Forsyth 		break;
1493b370703fSCharles.Forsyth 
1494b370703fSCharles.Forsyth 	case 2:	/* m,r */
1495b370703fSCharles.Forsyth 		*andptr++ = t[0];
1496b370703fSCharles.Forsyth 		asmando(&p->from, t[1]);
1497b370703fSCharles.Forsyth 		break;
1498b370703fSCharles.Forsyth 
1499b370703fSCharles.Forsyth 	case 3:	/* r,m - 2op */
1500b370703fSCharles.Forsyth 		*andptr++ = t[0];
1501b370703fSCharles.Forsyth 		*andptr++ = t[1];
1502b370703fSCharles.Forsyth 		asmando(&p->to, t[2]);
1503b370703fSCharles.Forsyth 		rexflag |= regrex[p->from.type] & (Rxr|0x40);
1504b370703fSCharles.Forsyth 		break;
1505b370703fSCharles.Forsyth 
1506b370703fSCharles.Forsyth 	case 4:	/* m,r - 2op */
1507b370703fSCharles.Forsyth 		*andptr++ = t[0];
1508b370703fSCharles.Forsyth 		*andptr++ = t[1];
1509b370703fSCharles.Forsyth 		asmando(&p->from, t[2]);
1510b370703fSCharles.Forsyth 		rexflag |= regrex[p->to.type] & (Rxr|0x40);
1511b370703fSCharles.Forsyth 		break;
1512b370703fSCharles.Forsyth 
1513b370703fSCharles.Forsyth 	case 5:	/* load full pointer, trash heap */
1514b370703fSCharles.Forsyth 		if(t[0])
1515b370703fSCharles.Forsyth 			*andptr++ = t[0];
1516b370703fSCharles.Forsyth 		switch(p->to.index) {
1517b370703fSCharles.Forsyth 		default:
1518b370703fSCharles.Forsyth 			goto bad;
1519b370703fSCharles.Forsyth 		case D_DS:
1520b370703fSCharles.Forsyth 			*andptr++ = 0xc5;
1521b370703fSCharles.Forsyth 			break;
1522b370703fSCharles.Forsyth 		case D_SS:
1523b370703fSCharles.Forsyth 			*andptr++ = 0x0f;
1524b370703fSCharles.Forsyth 			*andptr++ = 0xb2;
1525b370703fSCharles.Forsyth 			break;
1526b370703fSCharles.Forsyth 		case D_ES:
1527b370703fSCharles.Forsyth 			*andptr++ = 0xc4;
1528b370703fSCharles.Forsyth 			break;
1529b370703fSCharles.Forsyth 		case D_FS:
1530b370703fSCharles.Forsyth 			*andptr++ = 0x0f;
1531b370703fSCharles.Forsyth 			*andptr++ = 0xb4;
1532b370703fSCharles.Forsyth 			break;
1533b370703fSCharles.Forsyth 		case D_GS:
1534b370703fSCharles.Forsyth 			*andptr++ = 0x0f;
1535b370703fSCharles.Forsyth 			*andptr++ = 0xb5;
1536b370703fSCharles.Forsyth 			break;
1537b370703fSCharles.Forsyth 		}
1538b370703fSCharles.Forsyth 		asmand(&p->from, &p->to);
1539b370703fSCharles.Forsyth 		break;
1540b370703fSCharles.Forsyth 
1541b370703fSCharles.Forsyth 	case 6:	/* double shift */
1542b370703fSCharles.Forsyth 		if(t[0] == Pw){
1543b370703fSCharles.Forsyth 			if(p->mode != 64)
1544b370703fSCharles.Forsyth 				diag("asmins: illegal 64: %P", p);
1545b370703fSCharles.Forsyth 			rexflag |= Pw;
1546b370703fSCharles.Forsyth 			t++;
1547b370703fSCharles.Forsyth 		}else if(t[0] == Pe){
1548b370703fSCharles.Forsyth 			*andptr++ = Pe;
1549b370703fSCharles.Forsyth 			t++;
1550b370703fSCharles.Forsyth 		}
1551b370703fSCharles.Forsyth 		z = p->from.type;
1552b370703fSCharles.Forsyth 		switch(z) {
1553b370703fSCharles.Forsyth 		default:
1554b370703fSCharles.Forsyth 			goto bad;
1555b370703fSCharles.Forsyth 		case D_CONST:
1556b370703fSCharles.Forsyth 			*andptr++ = 0x0f;
1557b370703fSCharles.Forsyth 			*andptr++ = t[0];
1558b370703fSCharles.Forsyth 			asmandsz(&p->to, reg[p->from.index], regrex[p->from.index], 0);
1559b370703fSCharles.Forsyth 			*andptr++ = p->from.offset;
1560b370703fSCharles.Forsyth 			break;
1561b370703fSCharles.Forsyth 		case D_CL:
1562b370703fSCharles.Forsyth 		case D_CX:
1563b370703fSCharles.Forsyth 			*andptr++ = 0x0f;
1564b370703fSCharles.Forsyth 			*andptr++ = t[1];
1565b370703fSCharles.Forsyth 			asmandsz(&p->to, reg[p->from.index], regrex[p->from.index], 0);
1566b370703fSCharles.Forsyth 			break;
1567b370703fSCharles.Forsyth 		}
1568b370703fSCharles.Forsyth 		break;
1569b370703fSCharles.Forsyth 	}
1570b370703fSCharles.Forsyth }
1571b370703fSCharles.Forsyth 
1572b370703fSCharles.Forsyth void
asmins(Prog * p)1573b370703fSCharles.Forsyth asmins(Prog *p)
1574b370703fSCharles.Forsyth {
1575b370703fSCharles.Forsyth 	int n, np, c;
1576b370703fSCharles.Forsyth 
1577b370703fSCharles.Forsyth 	rexflag = 0;
1578b370703fSCharles.Forsyth 	andptr = and;
1579b370703fSCharles.Forsyth 	asmode = p->mode;
1580b370703fSCharles.Forsyth 	doasm(p);
1581b370703fSCharles.Forsyth 	if(rexflag){
1582b370703fSCharles.Forsyth 		/*
1583b370703fSCharles.Forsyth 		 * as befits the whole approach of the architecture,
1584b370703fSCharles.Forsyth 		 * the rex prefix must appear before the first opcode byte
1585*45a20ab7Sforsyth 		 * (and thus after any 66/67/f2/f3/26/2e/3e prefix bytes, but
1586b370703fSCharles.Forsyth 		 * before the 0f opcode escape!), or it might be ignored.
1587b370703fSCharles.Forsyth 		 * note that the handbook often misleadingly shows 66/f2/f3 in `opcode'.
1588b370703fSCharles.Forsyth 		 */
1589b370703fSCharles.Forsyth 		if(p->mode != 64)
1590b370703fSCharles.Forsyth 			diag("asmins: illegal in mode %d: %P", p->mode, p);
1591b370703fSCharles.Forsyth 		n = andptr - and;
1592b370703fSCharles.Forsyth 		for(np = 0; np < n; np++) {
1593b370703fSCharles.Forsyth 			c = and[np];
1594*45a20ab7Sforsyth 			if(c != 0xf2 && c != 0xf3 && (c < 0x64 || c > 0x67) && c != 0x2e && c != 0x3e && c != 0x26)
1595b370703fSCharles.Forsyth 				break;
1596b370703fSCharles.Forsyth 		}
1597b370703fSCharles.Forsyth 		memmove(and+np+1, and+np, n-np);
1598b370703fSCharles.Forsyth 		and[np] = 0x40 | rexflag;
1599b370703fSCharles.Forsyth 		andptr++;
1600b370703fSCharles.Forsyth 	}
1601b370703fSCharles.Forsyth }
1602b370703fSCharles.Forsyth 
1603b370703fSCharles.Forsyth enum{
1604b370703fSCharles.Forsyth 	ABSD = 0,
1605b370703fSCharles.Forsyth 	ABSU = 1,
1606b370703fSCharles.Forsyth 	RELD = 2,
1607b370703fSCharles.Forsyth 	RELU = 3,
1608b370703fSCharles.Forsyth };
1609b370703fSCharles.Forsyth 
1610b370703fSCharles.Forsyth int modemap[4] = { 0, 1, -1, 2, };
1611b370703fSCharles.Forsyth 
1612b370703fSCharles.Forsyth typedef struct Reloc Reloc;
1613b370703fSCharles.Forsyth 
1614b370703fSCharles.Forsyth struct Reloc
1615b370703fSCharles.Forsyth {
1616b370703fSCharles.Forsyth 	int n;
1617b370703fSCharles.Forsyth 	int t;
1618b370703fSCharles.Forsyth 	uchar *m;
1619b370703fSCharles.Forsyth 	ulong *a;
1620b370703fSCharles.Forsyth };
1621b370703fSCharles.Forsyth 
1622b370703fSCharles.Forsyth Reloc rels;
1623b370703fSCharles.Forsyth 
1624b370703fSCharles.Forsyth static void
grow(Reloc * r)1625b370703fSCharles.Forsyth grow(Reloc *r)
1626b370703fSCharles.Forsyth {
1627b370703fSCharles.Forsyth 	int t;
1628b370703fSCharles.Forsyth 	uchar *m, *nm;
1629b370703fSCharles.Forsyth 	ulong *a, *na;
1630b370703fSCharles.Forsyth 
1631b370703fSCharles.Forsyth 	t = r->t;
1632b370703fSCharles.Forsyth 	r->t += 64;
1633b370703fSCharles.Forsyth 	m = r->m;
1634b370703fSCharles.Forsyth 	a = r->a;
1635b370703fSCharles.Forsyth 	r->m = nm = malloc(r->t*sizeof(uchar));
1636b370703fSCharles.Forsyth 	r->a = na = malloc(r->t*sizeof(ulong));
1637b370703fSCharles.Forsyth 	memmove(nm, m, t*sizeof(uchar));
1638b370703fSCharles.Forsyth 	memmove(na, a, t*sizeof(ulong));
1639b370703fSCharles.Forsyth 	free(m);
1640b370703fSCharles.Forsyth 	free(a);
1641b370703fSCharles.Forsyth }
1642b370703fSCharles.Forsyth 
1643b370703fSCharles.Forsyth void
dynreloc(Sym * s,ulong v,int abs)1644b370703fSCharles.Forsyth dynreloc(Sym *s, ulong v, int abs)
1645b370703fSCharles.Forsyth {
1646b370703fSCharles.Forsyth 	int i, k, n;
1647b370703fSCharles.Forsyth 	uchar *m;
1648b370703fSCharles.Forsyth 	ulong *a;
1649b370703fSCharles.Forsyth 	Reloc *r;
1650b370703fSCharles.Forsyth 
1651b370703fSCharles.Forsyth 	if(s->type == SUNDEF)
1652b370703fSCharles.Forsyth 		k = abs ? ABSU : RELU;
1653b370703fSCharles.Forsyth 	else
1654b370703fSCharles.Forsyth 		k = abs ? ABSD : RELD;
1655b370703fSCharles.Forsyth 	/* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */
1656b370703fSCharles.Forsyth 	k = modemap[k];
1657b370703fSCharles.Forsyth 	r = &rels;
1658b370703fSCharles.Forsyth 	n = r->n;
1659b370703fSCharles.Forsyth 	if(n >= r->t)
1660b370703fSCharles.Forsyth 		grow(r);
1661b370703fSCharles.Forsyth 	m = r->m;
1662b370703fSCharles.Forsyth 	a = r->a;
1663b370703fSCharles.Forsyth 	for(i = n; i > 0; i--){
1664b370703fSCharles.Forsyth 		if(v < a[i-1]){	/* happens occasionally for data */
1665b370703fSCharles.Forsyth 			m[i] = m[i-1];
1666b370703fSCharles.Forsyth 			a[i] = a[i-1];
1667b370703fSCharles.Forsyth 		}
1668b370703fSCharles.Forsyth 		else
1669b370703fSCharles.Forsyth 			break;
1670b370703fSCharles.Forsyth 	}
1671b370703fSCharles.Forsyth 	m[i] = k;
1672b370703fSCharles.Forsyth 	a[i] = v;
1673b370703fSCharles.Forsyth 	r->n++;
1674b370703fSCharles.Forsyth }
1675b370703fSCharles.Forsyth 
1676b370703fSCharles.Forsyth static int
sput(char * s)1677b370703fSCharles.Forsyth sput(char *s)
1678b370703fSCharles.Forsyth {
1679b370703fSCharles.Forsyth 	char *p;
1680b370703fSCharles.Forsyth 
1681b370703fSCharles.Forsyth 	p = s;
1682b370703fSCharles.Forsyth 	while(*s)
1683b370703fSCharles.Forsyth 		cput(*s++);
1684b370703fSCharles.Forsyth 	cput(0);
1685b370703fSCharles.Forsyth 	return s-p+1;
1686b370703fSCharles.Forsyth }
1687b370703fSCharles.Forsyth 
1688b370703fSCharles.Forsyth void
asmdyn()1689b370703fSCharles.Forsyth asmdyn()
1690b370703fSCharles.Forsyth {
1691b370703fSCharles.Forsyth 	int i, n, t, c;
1692b370703fSCharles.Forsyth 	Sym *s;
1693b370703fSCharles.Forsyth 	ulong la, ra, *a;
1694b370703fSCharles.Forsyth 	vlong off;
1695b370703fSCharles.Forsyth 	uchar *m;
1696b370703fSCharles.Forsyth 	Reloc *r;
1697b370703fSCharles.Forsyth 
1698b370703fSCharles.Forsyth 	cflush();
1699b370703fSCharles.Forsyth 	off = seek(cout, 0, 1);
1700b370703fSCharles.Forsyth 	lput(0);
1701b370703fSCharles.Forsyth 	t = 0;
1702b370703fSCharles.Forsyth 	lput(imports);
1703b370703fSCharles.Forsyth 	t += 4;
1704b370703fSCharles.Forsyth 	for(i = 0; i < NHASH; i++)
1705b370703fSCharles.Forsyth 		for(s = hash[i]; s != S; s = s->link)
1706b370703fSCharles.Forsyth 			if(s->type == SUNDEF){
1707b370703fSCharles.Forsyth 				lput(s->sig);
1708b370703fSCharles.Forsyth 				t += 4;
1709b370703fSCharles.Forsyth 				t += sput(s->name);
1710b370703fSCharles.Forsyth 			}
1711b370703fSCharles.Forsyth 
1712b370703fSCharles.Forsyth 	la = 0;
1713b370703fSCharles.Forsyth 	r = &rels;
1714b370703fSCharles.Forsyth 	n = r->n;
1715b370703fSCharles.Forsyth 	m = r->m;
1716b370703fSCharles.Forsyth 	a = r->a;
1717b370703fSCharles.Forsyth 	lput(n);
1718b370703fSCharles.Forsyth 	t += 4;
1719b370703fSCharles.Forsyth 	for(i = 0; i < n; i++){
1720b370703fSCharles.Forsyth 		ra = *a-la;
1721b370703fSCharles.Forsyth 		if(*a < la)
1722b370703fSCharles.Forsyth 			diag("bad relocation order");
1723b370703fSCharles.Forsyth 		if(ra < 256)
1724b370703fSCharles.Forsyth 			c = 0;
1725b370703fSCharles.Forsyth 		else if(ra < 65536)
1726b370703fSCharles.Forsyth 			c = 1;
1727b370703fSCharles.Forsyth 		else
1728b370703fSCharles.Forsyth 			c = 2;
1729b370703fSCharles.Forsyth 		cput((c<<6)|*m++);
1730b370703fSCharles.Forsyth 		t++;
1731b370703fSCharles.Forsyth 		if(c == 0){
1732b370703fSCharles.Forsyth 			cput(ra);
1733b370703fSCharles.Forsyth 			t++;
1734b370703fSCharles.Forsyth 		}
1735b370703fSCharles.Forsyth 		else if(c == 1){
1736b370703fSCharles.Forsyth 			wput(ra);
1737b370703fSCharles.Forsyth 			t += 2;
1738b370703fSCharles.Forsyth 		}
1739b370703fSCharles.Forsyth 		else{
1740b370703fSCharles.Forsyth 			lput(ra);
1741b370703fSCharles.Forsyth 			t += 4;
1742b370703fSCharles.Forsyth 		}
1743b370703fSCharles.Forsyth 		la = *a++;
1744b370703fSCharles.Forsyth 	}
1745b370703fSCharles.Forsyth 
1746b370703fSCharles.Forsyth 	cflush();
1747b370703fSCharles.Forsyth 	seek(cout, off, 0);
1748b370703fSCharles.Forsyth 	lput(t);
1749b370703fSCharles.Forsyth 
1750b370703fSCharles.Forsyth 	if(debug['v']){
1751b370703fSCharles.Forsyth 		Bprint(&bso, "import table entries = %d\n", imports);
1752b370703fSCharles.Forsyth 		Bprint(&bso, "export table entries = %d\n", exports);
1753b370703fSCharles.Forsyth 	}
1754b370703fSCharles.Forsyth }
1755