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