xref: /plan9-contrib/sys/src/cmd/8l/span.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include	"l.h"
2 
3 void
4 span(void)
5 {
6 	Prog *p, *q;
7 	long v, c, idat;
8 	int m, n, again;
9 
10 	xdefine("etext", STEXT, 0L);
11 	idat = INITDAT;
12 	for(p = firstp; p != P; p = p->link) {
13 		if(p->as == ATEXT)
14 			curtext = p;
15 		n = 0;
16 		if(p->to.type == D_BRANCH)
17 			if(p->cond == P)
18 				p->cond = p;
19 		if((q = p->cond) != P)
20 			if(q->back != 2)
21 				n = 1;
22 		p->back = n;
23 		if(p->as == AADJSP) {
24 			p->to.type = D_SP;
25 			v = -p->from.offset;
26 			p->from.offset = v;
27 			p->as = AADDL;
28 			if(v < 0) {
29 				p->as = ASUBL;
30 				v = -v;
31 				p->from.offset = v;
32 			}
33 			if(v == 0)
34 				p->as = ANOP;
35 		}
36 	}
37 	n = 0;
38 
39 start:
40 	if(debug['v'])
41 		Bprint(&bso, "%5.2f span\n", cputime());
42 	Bflush(&bso);
43 	c = INITTEXT;
44 	for(p = firstp; p != P; p = p->link) {
45 		if(p->as == ATEXT)
46 			curtext = p;
47 		if(p->to.type == D_BRANCH)
48 			if(p->back)
49 				p->pc = c;
50 		asmins(p);
51 		p->pc = c;
52 		m = andptr-and;
53 		p->mark = m;
54 		c += m;
55 	}
56 
57 loop:
58 	n++;
59 	if(debug['v'])
60 		Bprint(&bso, "%5.2f span %d\n", cputime(), n);
61 	Bflush(&bso);
62 	if(n > 50) {
63 		print("span must be looping\n");
64 		errorexit();
65 	}
66 	again = 0;
67 	c = INITTEXT;
68 	for(p = firstp; p != P; p = p->link) {
69 		if(p->as == ATEXT)
70 			curtext = p;
71 		if(p->to.type == D_BRANCH) {
72 			if(p->back)
73 				p->pc = c;
74 			asmins(p);
75 			m = andptr-and;
76 			if(m != p->mark) {
77 				p->mark = m;
78 				again++;
79 			}
80 		}
81 		p->pc = c;
82 		c += p->mark;
83 	}
84 	if(again) {
85 		textsize = c;
86 		goto loop;
87 	}
88 	if(INITRND) {
89 		INITDAT = rnd(c, INITRND);
90 		if(INITDAT != idat) {
91 			idat = INITDAT;
92 			goto start;
93 		}
94 	}
95 	xdefine("etext", STEXT, c);
96 	if(debug['v'])
97 		Bprint(&bso, "etext = %lux\n", c);
98 	Bflush(&bso);
99 	for(p = textp; p != P; p = p->cond)
100 		p->from.sym->value = p->pc;
101 	textsize = c - INITTEXT;
102 }
103 
104 void
105 xdefine(char *p, int t, long v)
106 {
107 	Sym *s;
108 
109 	s = lookup(p, 0);
110 	if(s->type == 0 || s->type == SXREF) {
111 		s->type = t;
112 		s->value = v;
113 	}
114 	if(s->type == STEXT && s->value == 0)
115 		s->value = v;
116 }
117 
118 void
119 putsymb(char *s, int t, long v, int ver)
120 {
121 	int i, f;
122 
123 	if(t == 'f')
124 		s++;
125 	lput(v);
126 	if(ver)
127 		t += 'a' - 'A';
128 	CPUT(t+0x80);			/* 0x80 is variable length */
129 
130 	if(t == 'Z' || t == 'z') {
131 		CPUT(s[0]);
132 		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
133 			CPUT(s[i]);
134 			CPUT(s[i+1]);
135 		}
136 		CPUT(0);
137 		CPUT(0);
138 		i++;
139 	}
140 	else {
141 		for(i=0; s[i]; i++)
142 			CPUT(s[i]);
143 		CPUT(0);
144 	}
145 	symsize += 4 + 1 + i + 1;
146 
147 	if(debug['n']) {
148 		if(t == 'z' || t == 'Z') {
149 			Bprint(&bso, "%c %.8lux ", t, v);
150 			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
151 				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
152 				Bprint(&bso, "/%x", f);
153 			}
154 			Bprint(&bso, "\n");
155 			return;
156 		}
157 		if(ver)
158 			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
159 		else
160 			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
161 	}
162 }
163 
164 void
165 asmsym(void)
166 {
167 	Prog *p;
168 	Auto *a;
169 	Sym *s;
170 	int h;
171 
172 	s = lookup("etext", 0);
173 	if(s->type == STEXT)
174 		putsymb(s->name, 'T', s->value, s->version);
175 
176 	for(h=0; h<NHASH; h++)
177 		for(s=hash[h]; s!=S; s=s->link)
178 			switch(s->type) {
179 			case SCONST:
180 				putsymb(s->name, 'D', s->value, s->version);
181 				continue;
182 
183 			case SDATA:
184 				putsymb(s->name, 'D', s->value+INITDAT, s->version);
185 				continue;
186 
187 			case SBSS:
188 				putsymb(s->name, 'B', s->value+INITDAT, s->version);
189 				continue;
190 
191 			case SFILE:
192 				putsymb(s->name, 'f', s->value, s->version);
193 				continue;
194 			}
195 
196 	for(p=textp; p!=P; p=p->cond) {
197 		s = p->from.sym;
198 		if(s->type != STEXT)
199 			continue;
200 
201 		/* filenames first */
202 		for(a=p->to.autom; a; a=a->link)
203 			if(a->type == D_FILE)
204 				putsymb(a->sym->name, 'z', a->offset, 0);
205 			else
206 			if(a->type == D_FILE1)
207 				putsymb(a->sym->name, 'Z', a->offset, 0);
208 
209 		putsymb(s->name, 'T', s->value, s->version);
210 
211 		/* frame, auto and param after */
212 		putsymb(".frame", 'm', p->to.offset+4, 0);
213 
214 		for(a=p->to.autom; a; a=a->link)
215 			if(a->type == D_AUTO)
216 				putsymb(a->sym->name, 'a', -a->offset, 0);
217 			else
218 			if(a->type == D_PARAM)
219 				putsymb(a->sym->name, 'p', a->offset, 0);
220 	}
221 	if(debug['v'] || debug['n'])
222 		Bprint(&bso, "symsize = %lud\n", symsize);
223 	Bflush(&bso);
224 }
225 
226 void
227 asmlc(void)
228 {
229 	long oldpc, oldlc;
230 	Prog *p;
231 	long v, s;
232 
233 	oldpc = INITTEXT;
234 	oldlc = 0;
235 	for(p = firstp; p != P; p = p->link) {
236 		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
237 			if(p->as == ATEXT)
238 				curtext = p;
239 			if(debug['L'])
240 				Bprint(&bso, "%6lux %P\n",
241 					p->pc, p);
242 			continue;
243 		}
244 		if(debug['L'])
245 			Bprint(&bso, "\t\t%6ld", lcsize);
246 		v = (p->pc - oldpc) / MINLC;
247 		while(v) {
248 			s = 127;
249 			if(v < 127)
250 				s = v;
251 			CPUT(s+128);	/* 129-255 +pc */
252 			if(debug['L'])
253 				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
254 			v -= s;
255 			lcsize++;
256 		}
257 		s = p->line - oldlc;
258 		oldlc = p->line;
259 		oldpc = p->pc + MINLC;
260 		if(s > 64 || s < -64) {
261 			CPUT(0);	/* 0 vv +lc */
262 			CPUT(s>>24);
263 			CPUT(s>>16);
264 			CPUT(s>>8);
265 			CPUT(s);
266 			if(debug['L']) {
267 				if(s > 0)
268 					Bprint(&bso, " lc+%ld(%d,%ld)\n",
269 						s, 0, s);
270 				else
271 					Bprint(&bso, " lc%ld(%d,%ld)\n",
272 						s, 0, s);
273 				Bprint(&bso, "%6lux %P\n",
274 					p->pc, p);
275 			}
276 			lcsize += 5;
277 			continue;
278 		}
279 		if(s > 0) {
280 			CPUT(0+s);	/* 1-64 +lc */
281 			if(debug['L']) {
282 				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
283 				Bprint(&bso, "%6lux %P\n",
284 					p->pc, p);
285 			}
286 		} else {
287 			CPUT(64-s);	/* 65-128 -lc */
288 			if(debug['L']) {
289 				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
290 				Bprint(&bso, "%6lux %P\n",
291 					p->pc, p);
292 			}
293 		}
294 		lcsize++;
295 	}
296 	while(lcsize & 1) {
297 		s = 129;
298 		CPUT(s);
299 		lcsize++;
300 	}
301 	if(debug['v'] || debug['L'])
302 		Bprint(&bso, "lcsize = %ld\n", lcsize);
303 	Bflush(&bso);
304 }
305 
306 int
307 oclass(Adr *a)
308 {
309 	long v;
310 
311 	if(a->type >= D_INDIR || a->index != D_NONE) {
312 		if(a->index != D_NONE && a->scale == 0) {
313 			if(a->type == D_ADDR) {
314 				switch(a->index) {
315 				case D_EXTERN:
316 				case D_STATIC:
317 					return Yi32;
318 				case D_AUTO:
319 				case D_PARAM:
320 					return Yiauto;
321 				}
322 				return Yxxx;
323 			}
324 			return Ycol;
325 		}
326 		return Ym;
327 	}
328 	switch(a->type)
329 	{
330 	case D_AL:
331 		return Yal;
332 
333 	case D_AX:
334 		return Yax;
335 
336 	case D_CL:
337 	case D_DL:
338 	case D_BL:
339 	case D_AH:
340 	case D_CH:
341 	case D_DH:
342 	case D_BH:
343 		return Yrb;
344 
345 	case D_CX:
346 		return Ycx;
347 
348 	case D_DX:
349 	case D_BX:
350 		return Yrx;
351 
352 	case D_SP:
353 	case D_BP:
354 	case D_SI:
355 	case D_DI:
356 		return Yrl;
357 
358 	case D_F0+0:
359 		return	Yf0;
360 
361 	case D_F0+1:
362 	case D_F0+2:
363 	case D_F0+3:
364 	case D_F0+4:
365 	case D_F0+5:
366 	case D_F0+6:
367 	case D_F0+7:
368 		return	Yrf;
369 
370 	case D_NONE:
371 		return Ynone;
372 
373 	case D_CS:	return	Ycs;
374 	case D_SS:	return	Yss;
375 	case D_DS:	return	Yds;
376 	case D_ES:	return	Yes;
377 	case D_FS:	return	Yfs;
378 	case D_GS:	return	Ygs;
379 
380 	case D_GDTR:	return	Ygdtr;
381 	case D_IDTR:	return	Yidtr;
382 	case D_LDTR:	return	Yldtr;
383 	case D_MSW:	return	Ymsw;
384 	case D_TASK:	return	Ytask;
385 
386 	case D_CR+0:	return	Ycr0;
387 	case D_CR+1:	return	Ycr1;
388 	case D_CR+2:	return	Ycr2;
389 	case D_CR+3:	return	Ycr3;
390 	case D_CR+4:	return	Ycr4;
391 	case D_CR+5:	return	Ycr5;
392 	case D_CR+6:	return	Ycr6;
393 	case D_CR+7:	return	Ycr7;
394 
395 	case D_DR+0:	return	Ydr0;
396 	case D_DR+1:	return	Ydr1;
397 	case D_DR+2:	return	Ydr2;
398 	case D_DR+3:	return	Ydr3;
399 	case D_DR+4:	return	Ydr4;
400 	case D_DR+5:	return	Ydr5;
401 	case D_DR+6:	return	Ydr6;
402 	case D_DR+7:	return	Ydr7;
403 
404 	case D_TR+0:	return	Ytr0;
405 	case D_TR+1:	return	Ytr1;
406 	case D_TR+2:	return	Ytr2;
407 	case D_TR+3:	return	Ytr3;
408 	case D_TR+4:	return	Ytr4;
409 	case D_TR+5:	return	Ytr5;
410 	case D_TR+6:	return	Ytr6;
411 	case D_TR+7:	return	Ytr7;
412 
413 	case D_EXTERN:
414 	case D_STATIC:
415 	case D_AUTO:
416 	case D_PARAM:
417 		return Ym;
418 
419 	case D_CONST:
420 	case D_ADDR:
421 		if(a->sym == S) {
422 			v = a->offset;
423 			if(v == 0)
424 				return Yi0;
425 			if(v == 1)
426 				return Yi1;
427 			if(v >= -128 && v <= 127)
428 				return Yi8;
429 		}
430 		return Yi32;
431 
432 	case D_BRANCH:
433 		return Ybr;
434 	}
435 	return Yxxx;
436 }
437 
438 void
439 asmidx(Adr *a, int base)
440 {
441 	int i;
442 
443 	switch(a->index) {
444 	default:
445 		goto bad;
446 
447 	case D_NONE:
448 		i = 4 << 3;
449 		goto bas;
450 
451 	case D_AX:
452 	case D_CX:
453 	case D_DX:
454 	case D_BX:
455 	case D_BP:
456 	case D_SI:
457 	case D_DI:
458 		i = reg[a->index] << 3;
459 		break;
460 	}
461 	switch(a->scale) {
462 	default:
463 		goto bad;
464 	case 1:
465 		break;
466 	case 2:
467 		i |= (1<<6);
468 		break;
469 	case 4:
470 		i |= (2<<6);
471 		break;
472 	case 8:
473 		i |= (3<<6);
474 		break;
475 	}
476 bas:
477 	switch(base) {
478 	default:
479 		goto bad;
480 	case D_NONE:	/* must be mod=00 */
481 		i |= 5;
482 		break;
483 	case D_AX:
484 	case D_CX:
485 	case D_DX:
486 	case D_BX:
487 	case D_SP:
488 	case D_SI:
489 	case D_DI:
490 		i |= reg[base];
491 		break;
492 	}
493 	*andptr++ = i;
494 	return;
495 bad:
496 	diag("asmidx: bad address %D\n", a);
497 	*andptr++ = 0;
498 	return;
499 }
500 
501 long
502 vaddr(Adr *a)
503 {
504 	int t;
505 	long v;
506 
507 	t = a->type;
508 	v = a->offset;
509 	if(t == D_ADDR)
510 		t = a->index;
511 	switch(t) {
512 	case D_STATIC:
513 	case D_EXTERN:
514 		if(a->sym) {
515 			v += a->sym->value;
516 			switch(a->sym->type) {
517 			case STEXT:
518 			case SCONST:
519 				break;
520 			default:
521 				v += INITDAT;
522 			}
523 		}
524 	}
525 	return v;
526 }
527 
528 void
529 asmand(Adr *a, int r)
530 {
531 	long v;
532 	int t;
533 	Adr aa;
534 
535 	v = a->offset;
536 	t = a->type;
537 	if(a->index != D_NONE) {
538 		if(t >= D_INDIR) {
539 			t -= D_INDIR;
540 			if(t == D_NONE) {
541 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
542 				asmidx(a, t);
543 				andptr[0] = v;
544 				andptr[1] = v>>8;
545 				andptr[2] = v>>16;
546 				andptr[3] = v>>24;
547 				andptr += 4;
548 				return;
549 			}
550 			if(v == 0) {
551 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
552 				asmidx(a, t);
553 				return;
554 			}
555 			if(v >= -128 && v < 128) {
556 				*andptr++ = (1 << 6) | (4 << 0) | (r << 3);
557 				asmidx(a, t);
558 				*andptr++ = v;
559 				return;
560 			}
561 			*andptr++ = (2 << 6) | (4 << 0) | (r << 3);
562 			asmidx(a, t);
563 			andptr[0] = v;
564 			andptr[1] = v>>8;
565 			andptr[2] = v>>16;
566 			andptr[3] = v>>24;
567 			andptr += 4;
568 			return;
569 		}
570 		switch(t) {
571 		default:
572 			goto bad;
573 		case D_STATIC:
574 		case D_EXTERN:
575 			aa.type = D_NONE+D_INDIR;
576 			break;
577 		case D_AUTO:
578 		case D_PARAM:
579 			aa.type = D_SP+D_INDIR;
580 			break;
581 		}
582 		aa.offset = vaddr(a);
583 		aa.index = a->index;
584 		aa.scale = a->scale;
585 		asmand(&aa, r);
586 		return;
587 	}
588 	if(t >= D_AL && t <= D_F0+7) {
589 		if(v)
590 			goto bad;
591 		*andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
592 		return;
593 	}
594 	if(t >= D_INDIR) {
595 		t -= D_INDIR;
596 		if(t == D_NONE) {
597 			andptr[0] = (0 << 6) | (5 << 0) | (r << 3);
598 			andptr[1] = v;
599 			andptr[2] = v>>8;
600 			andptr[3] = v>>16;
601 			andptr[4] = v>>24;
602 			andptr += 5;
603 			return;
604 		}
605 		if(t == D_SP) {
606 			if(v == 0) {
607 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
608 				asmidx(a, D_SP);
609 				return;
610 			}
611 			if(v >= -128 && v < 128) {
612 				*andptr++ = (1 << 6) | (4 << 0) | (r << 3);
613 				asmidx(a, D_SP);
614 				*andptr++ = v;
615 				return;
616 			}
617 			*andptr++ = (2 << 6) | (4 << 0) | (r << 3);
618 			asmidx(a, D_SP);
619 			andptr[0] = v;
620 			andptr[1] = v>>8;
621 			andptr[2] = v>>16;
622 			andptr[3] = v>>24;
623 			andptr += 4;
624 			return;
625 		}
626 		if(t >= D_AX && t <= D_DI) {
627 			if(v == 0 && t != D_BP) {
628 				*andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
629 				return;
630 			}
631 			if(v >= -128 && v < 128) {
632 				andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
633 				andptr[1] = v;
634 				andptr += 2;
635 				return;
636 			}
637 			andptr[0] = (2 << 6) | (reg[t] << 0) | (r << 3);
638 			andptr[1] = v;
639 			andptr[2] = v>>8;
640 			andptr[3] = v>>16;
641 			andptr[4] = v>>24;
642 			andptr += 5;
643 			return;
644 		}
645 		goto bad;
646 	}
647 	switch(a->type) {
648 	default:
649 		goto bad;
650 	case D_STATIC:
651 	case D_EXTERN:
652 		aa.type = D_NONE+D_INDIR;
653 		break;
654 	case D_AUTO:
655 	case D_PARAM:
656 		aa.type = D_SP+D_INDIR;
657 		break;
658 	}
659 	aa.index = D_NONE;
660 	aa.scale = 1;
661 	aa.offset = vaddr(a);
662 	asmand(&aa, r);
663 	return;
664 bad:
665 	diag("asmand: bad address %D\n", a);
666 	return;
667 }
668 
669 #define	E	0xff
670 uchar	ymovtab[] =
671 {
672 /* push */
673 	APUSHL,	Ycs,	Ynone,	0,	0x0e,E,0,0,
674 	APUSHL,	Yss,	Ynone,	0,	0x16,E,0,0,
675 	APUSHL,	Yds,	Ynone,	0,	0x1e,E,0,0,
676 	APUSHL,	Yes,	Ynone,	0,	0x06,E,0,0,
677 	APUSHL,	Yfs,	Ynone,	0,	0x0f,0xa0,E,0,
678 	APUSHL,	Ygs,	Ynone,	0,	0x0f,0xa8,E,0,
679 
680 	APUSHW,	Ycs,	Ynone,	0,	Pe,0x0e,E,0,
681 	APUSHW,	Yss,	Ynone,	0,	Pe,0x16,E,0,
682 	APUSHW,	Yds,	Ynone,	0,	Pe,0x1e,E,0,
683 	APUSHW,	Yes,	Ynone,	0,	Pe,0x06,E,0,
684 	APUSHW,	Yfs,	Ynone,	0,	Pe,0x0f,0xa0,E,
685 	APUSHW,	Ygs,	Ynone,	0,	Pe,0x0f,0xa8,E,
686 
687 /* pop */
688 	APOPL,	Ynone,	Yds,	0,	0x1f,E,0,0,
689 	APOPL,	Ynone,	Yes,	0,	0x07,E,0,0,
690 	APOPL,	Ynone,	Yss,	0,	0x17,E,0,0,
691 	APOPL,	Ynone,	Yfs,	0,	0x0f,0xa1,E,0,
692 	APOPL,	Ynone,	Ygs,	0,	0x0f,0xa9,E,0,
693 
694 	APOPW,	Ynone,	Yds,	0,	Pe,0x1f,E,0,
695 	APOPW,	Ynone,	Yes,	0,	Pe,0x07,E,0,
696 	APOPW,	Ynone,	Yss,	0,	Pe,0x17,E,0,
697 	APOPW,	Ynone,	Yfs,	0,	Pe,0x0f,0xa1,E,
698 	APOPW,	Ynone,	Ygs,	0,	Pe,0x0f,0xa9,E,
699 
700 /* mov seg */
701 	AMOVW,	Yes,	Yml,	1,	0x8c,0,0,0,
702 	AMOVW,	Ycs,	Yml,	1,	0x8c,1,0,0,
703 	AMOVW,	Yss,	Yml,	1,	0x8c,2,0,0,
704 	AMOVW,	Yds,	Yml,	1,	0x8c,3,0,0,
705 	AMOVW,	Yfs,	Yml,	1,	0x8c,4,0,0,
706 	AMOVW,	Ygs,	Yml,	1,	0x8c,5,0,0,
707 
708 	AMOVW,	Yml,	Yes,	2,	0x8e,0,0,0,
709 	AMOVW,	Yml,	Ycs,	2,	0x8e,1,0,0,
710 	AMOVW,	Yml,	Yss,	2,	0x8e,2,0,0,
711 	AMOVW,	Yml,	Yds,	2,	0x8e,3,0,0,
712 	AMOVW,	Yml,	Yfs,	2,	0x8e,4,0,0,
713 	AMOVW,	Yml,	Ygs,	2,	0x8e,5,0,0,
714 
715 /* mov cr */
716 	AMOVL,	Ycr0,	Yml,	3,	0x0f,0x20,0,0,
717 	AMOVL,	Ycr2,	Yml,	3,	0x0f,0x20,2,0,
718 	AMOVL,	Ycr3,	Yml,	3,	0x0f,0x20,3,0,
719 
720 	AMOVL,	Yml,	Ycr0,	4,	0x0f,0x22,0,0,
721 	AMOVL,	Yml,	Ycr2,	4,	0x0f,0x22,2,0,
722 	AMOVL,	Yml,	Ycr3,	4,	0x0f,0x22,3,0,
723 
724 /* mov dr */
725 	AMOVL,	Ydr0,	Yml,	3,	0x0f,0x21,0,0,
726 	AMOVL,	Ydr6,	Yml,	3,	0x0f,0x21,6,0,
727 	AMOVL,	Ydr7,	Yml,	3,	0x0f,0x21,7,0,
728 
729 	AMOVL,	Yml,	Ydr0,	4,	0x0f,0x23,0,0,
730 	AMOVL,	Yml,	Ydr6,	4,	0x0f,0x23,6,0,
731 	AMOVL,	Yml,	Ydr7,	4,	0x0f,0x23,7,0,
732 
733 /* mov tr */
734 	AMOVL,	Ytr6,	Yml,	3,	0x0f,0x24,6,0,
735 	AMOVL,	Ytr7,	Yml,	3,	0x0f,0x24,7,0,
736 
737 	AMOVL,	Yml,	Ytr6,	4,	0x0f,0x26,6,E,
738 	AMOVL,	Yml,	Ytr7,	4,	0x0f,0x26,7,E,
739 
740 /* lgdt, sgdt, lidt, sidt */
741 	AMOVL,	Ym,	Ygdtr,	4,	0x0f,0x01,2,0,
742 	AMOVL,	Ygdtr,	Ym,	3,	0x0f,0x01,0,0,
743 	AMOVL,	Ym,	Yidtr,	4,	0x0f,0x01,3,0,
744 	AMOVL,	Yidtr,	Ym,	3,	0x0f,0x01,1,0,
745 
746 /* lldt, sldt */
747 	AMOVW,	Yml,	Yldtr,	4,	0x0f,0x00,2,0,
748 	AMOVW,	Yldtr,	Yml,	3,	0x0f,0x00,0,0,
749 
750 /* lmsw, smsw */
751 	AMOVW,	Yml,	Ymsw,	4,	0x0f,0x01,6,0,
752 	AMOVW,	Ymsw,	Yml,	3,	0x0f,0x01,4,0,
753 
754 /* ltr, str */
755 	AMOVW,	Yml,	Ytask,	4,	0x0f,0x00,3,0,
756 	AMOVW,	Ytask,	Yml,	3,	0x0f,0x00,1,0,
757 
758 /* load full pointer */
759 	AMOVL,	Yml,	Ycol,	5,	0,0,0,0,
760 	AMOVW,	Yml,	Ycol,	5,	Pe,0,0,0,
761 
762 /* double shift */
763 	ASHLL,	Ycol,	Yml,	6,	0xa4,0xa5,0,0,
764 	ASHRL,	Ycol,	Yml,	6,	0xac,0xad,0,0,
765 
766 	0
767 };
768 
769 int
770 isax(Adr *a)
771 {
772 
773 	switch(a->type) {
774 	case D_AX:
775 	case D_AL:
776 	case D_AH:
777 	case D_INDIR+D_AX:
778 		return 1;
779 	}
780 	if(a->index == D_AX)
781 		return 1;
782 	return 0;
783 }
784 
785 void
786 subreg(Prog *p, int from, int to)
787 {
788 
789 	if(debug['Q'])
790 		print("\n%P	s/%R/%R/\n", p, from, to);
791 
792 	if(p->from.type == from)
793 		p->from.type = to;
794 	if(p->to.type == from)
795 		p->to.type = to;
796 
797 	if(p->from.index == from)
798 		p->from.index = to;
799 	if(p->to.index == from)
800 		p->to.index = to;
801 
802 	from += D_INDIR;
803 	if(p->from.type == from)
804 		p->from.type = to+D_INDIR;
805 	if(p->to.type == from)
806 		p->to.type = to+D_INDIR;
807 
808 	if(debug['Q'])
809 		print("%P\n", p);
810 }
811 
812 void
813 doasm(Prog *p)
814 {
815 	Optab *o;
816 	Prog *q, pp;
817 	uchar *t;
818 	int z, op, ft, tt;
819 	long v;
820 
821 	o = &optab[p->as];
822 	ft = oclass(&p->from) * Ymax;
823 	tt = oclass(&p->to) * Ymax;
824 	t = o->ytab;
825 	if(t == 0) {
826 		diag("asmins: noproto %P\n", p);
827 		return;
828 	}
829 	for(z=0; *t; z+=t[3],t+=4)
830 		if(ycover[ft+t[0]])
831 		if(ycover[tt+t[1]])
832 			goto found;
833 	goto domov;
834 
835 found:
836 	switch(o->prefix) {
837 	case Pq:	/* 16 bit escape and opcode escape */
838 		*andptr++ = Pe;
839 		*andptr++ = Pm;
840 		break;
841 
842 	case Pm:	/* opcode escape */
843 		*andptr++ = Pm;
844 		break;
845 
846 	case Pe:	/* 16 bit escape */
847 		*andptr++ = Pe;
848 		break;
849 
850 	case Pb:	/* botch */
851 		break;
852 	}
853 	v = vaddr(&p->from);
854 	op = o->op[z];
855 	switch(t[2]) {
856 	default:
857 		diag("asmins: unknown z %d %P\n", t[2], p);
858 		return;
859 
860 	case Zpseudo:
861 		break;
862 
863 	case Zlit:
864 		for(; op = o->op[z]; z++)
865 			*andptr++ = op;
866 		break;
867 
868 	case Zm_r:
869 		*andptr++ = op;
870 		asmand(&p->from, reg[p->to.type]);
871 		break;
872 
873 	case Zaut_r:
874 		*andptr++ = 0x8d;	/* leal */
875 		if(p->from.type != D_ADDR)
876 			diag("asmins: Zaut sb type ADDR");
877 		p->from.type = p->from.index;
878 		p->from.index = D_NONE;
879 		asmand(&p->from, reg[p->to.type]);
880 		p->from.index = p->from.type;
881 		p->from.type = D_ADDR;
882 		break;
883 
884 	case Zm_o:
885 		*andptr++ = op;
886 		asmand(&p->from, o->op[z+1]);
887 		break;
888 
889 	case Zr_m:
890 		*andptr++ = op;
891 		asmand(&p->to, reg[p->from.type]);
892 		break;
893 
894 	case Zo_m:
895 		*andptr++ = op;
896 		asmand(&p->to, o->op[z+1]);
897 		break;
898 
899 	case Zm_ibo:
900 		v = vaddr(&p->to);
901 		*andptr++ = op;
902 		asmand(&p->from, o->op[z+1]);
903 		*andptr++ = v;
904 		break;
905 
906 	case Zibo_m:
907 		*andptr++ = op;
908 		asmand(&p->to, o->op[z+1]);
909 		*andptr++ = v;
910 		break;
911 
912 	case Z_ib:
913 		v = vaddr(&p->to);
914 	case Zib_:
915 		*andptr++ = op;
916 		*andptr++ = v;
917 		break;
918 
919 	case Zib_rp:
920 		*andptr++ = op + reg[p->to.type];
921 		*andptr++ = v;
922 		break;
923 
924 	case Zil_rp:
925 		*andptr++ = op + reg[p->to.type];
926 		*andptr++ = v;
927 		*andptr++ = v>>8;
928 		if(o->prefix != Pe) {
929 			*andptr++ = v>>16;
930 			*andptr++ = v>>24;
931 		}
932 		break;
933 
934 	case Z_il:
935 		v = vaddr(&p->to);
936 	case Zil_:
937 		*andptr++ = op;
938 		*andptr++ = v;
939 		*andptr++ = v>>8;
940 		if(o->prefix != Pe) {
941 			*andptr++ = v>>16;
942 			*andptr++ = v>>24;
943 		}
944 		break;
945 
946 	case Zm_ilo:
947 		v = vaddr(&p->to);
948 		*andptr++ = op;
949 		asmand(&p->from, o->op[z+1]);
950 		*andptr++ = v;
951 		*andptr++ = v>>8;
952 		if(o->prefix != Pe) {
953 			*andptr++ = v>>16;
954 			*andptr++ = v>>24;
955 		}
956 		break;
957 
958 	case Zilo_m:
959 		*andptr++ = op;
960 		asmand(&p->to, o->op[z+1]);
961 		*andptr++ = v;
962 		*andptr++ = v>>8;
963 		if(o->prefix != Pe) {
964 			*andptr++ = v>>16;
965 			*andptr++ = v>>24;
966 		}
967 		break;
968 
969 	case Z_rp:
970 		*andptr++ = op + reg[p->to.type];
971 		break;
972 
973 	case Zrp_:
974 		*andptr++ = op + reg[p->from.type];
975 		break;
976 
977 	case Zclr:
978 		*andptr++ = op;
979 		asmand(&p->to, reg[p->to.type]);
980 		break;
981 
982 	case Zbr:
983 		q = p->cond;
984 		if(q) {
985 			v = q->pc - p->pc - 2;
986 			if(v >= -128 && v <= 127) {
987 				*andptr++ = op;
988 				*andptr++ = v;
989 			} else {
990 				v -= 6-2;
991 				*andptr++ = 0x0f;
992 				*andptr++ = o->op[z+1];
993 				*andptr++ = v;
994 				*andptr++ = v>>8;
995 				*andptr++ = v>>16;
996 				*andptr++ = v>>24;
997 			}
998 		}
999 		break;
1000 
1001 	case Zcall:
1002 		q = p->cond;
1003 		if(q) {
1004 			v = q->pc - p->pc - 5;
1005 			*andptr++ = op;
1006 			*andptr++ = v;
1007 			*andptr++ = v>>8;
1008 			*andptr++ = v>>16;
1009 			*andptr++ = v>>24;
1010 		}
1011 		break;
1012 
1013 	case Zjmp:
1014 		q = p->cond;
1015 		if(q) {
1016 			v = q->pc - p->pc - 2;
1017 			if(v >= -128 && v <= 127) {
1018 				*andptr++ = op;
1019 				*andptr++ = v;
1020 			} else {
1021 				v -= 5-2;
1022 				*andptr++ = o->op[z+1];
1023 				*andptr++ = v;
1024 				*andptr++ = v>>8;
1025 				*andptr++ = v>>16;
1026 				*andptr++ = v>>24;
1027 			}
1028 		}
1029 		break;
1030 
1031 	case Zloop:
1032 		q = p->cond;
1033 		if(q) {
1034 			v = q->pc - p->pc - 2;
1035 			if(v < -128 && v > 127)
1036 				diag("loop too far: %P\n", p);
1037 			*andptr++ = op;
1038 			*andptr++ = v;
1039 		}
1040 		break;
1041 
1042 	case Zbyte:
1043 		*andptr++ = v;
1044 		if(op > 1) {
1045 			*andptr++ = v>>8;
1046 			if(op > 2) {
1047 				*andptr++ = v>>16;
1048 				*andptr++ = v>>24;
1049 			}
1050 		}
1051 		break;
1052 
1053 	case Zmov:
1054 		goto domov;
1055 	}
1056 	return;
1057 
1058 domov:
1059 	for(t=ymovtab; *t; t+=8)
1060 		if(p->as == t[0])
1061 		if(ycover[ft+t[1]])
1062 		if(ycover[tt+t[2]])
1063 			goto mfound;
1064 bad:
1065 	/*
1066 	 * here, the assembly has failed.
1067 	 * if its a byte instruction that has
1068 	 * unaddressable registers, try to
1069 	 * exchange registers and reissue the
1070 	 * instruction with the operands renamed.
1071 	 */
1072 	pp = *p;
1073 	z = p->from.type;
1074 	if(z >= D_BP && z <= D_DI) {
1075 		if(isax(&p->to)) {
1076 			*andptr++ = 0x87;			/* xchg lhs,bx */
1077 			asmand(&p->from, reg[D_BX]);
1078 			subreg(&pp, z, D_BX);
1079 			doasm(&pp);
1080 			*andptr++ = 0x87;			/* xchg lhs,bx */
1081 			asmand(&p->from, reg[D_BX]);
1082 		} else {
1083 			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
1084 			subreg(&pp, z, D_AX);
1085 			doasm(&pp);
1086 			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
1087 		}
1088 		return;
1089 	}
1090 	z = p->to.type;
1091 	if(z >= D_BP && z <= D_DI) {
1092 		if(isax(&p->from)) {
1093 			*andptr++ = 0x87;			/* xchg rhs,bx */
1094 			asmand(&p->to, reg[D_BX]);
1095 			subreg(&pp, z, D_BX);
1096 			doasm(&pp);
1097 			*andptr++ = 0x87;			/* xchg rhs,bx */
1098 			asmand(&p->to, reg[D_BX]);
1099 		} else {
1100 			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
1101 			subreg(&pp, z, D_AX);
1102 			doasm(&pp);
1103 			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
1104 		}
1105 		return;
1106 	}
1107 	diag("doasm: notfound %P\n", p);
1108 	return;
1109 
1110 mfound:
1111 	switch(t[3]) {
1112 	default:
1113 		diag("asmins: unknown mov %d %P\n", t[3], p);
1114 		break;
1115 
1116 	case 0:	/* lit */
1117 		for(z=4; t[z]!=E; z++)
1118 			*andptr++ = t[z];
1119 		break;
1120 
1121 	case 1:	/* r,m */
1122 		*andptr++ = t[4];
1123 		asmand(&p->to, t[5]);
1124 		break;
1125 
1126 	case 2:	/* m,r */
1127 		*andptr++ = t[4];
1128 		asmand(&p->from, t[5]);
1129 		break;
1130 
1131 	case 3:	/* r,m - 2op */
1132 		*andptr++ = t[4];
1133 		*andptr++ = t[5];
1134 		asmand(&p->to, t[6]);
1135 		break;
1136 
1137 	case 4:	/* m,r - 2op */
1138 		*andptr++ = t[4];
1139 		*andptr++ = t[5];
1140 		asmand(&p->from, t[6]);
1141 		break;
1142 
1143 	case 5:	/* load full pointer, trash heap */
1144 		if(t[4])
1145 			*andptr++ = t[4];
1146 		switch(p->to.index) {
1147 		default:
1148 			goto bad;
1149 		case D_DS:
1150 			*andptr++ = 0xc5;
1151 			break;
1152 		case D_SS:
1153 			*andptr++ = 0x0f;
1154 			*andptr++ = 0xb2;
1155 			break;
1156 		case D_ES:
1157 			*andptr++ = 0xc4;
1158 			break;
1159 		case D_FS:
1160 			*andptr++ = 0x0f;
1161 			*andptr++ = 0xb4;
1162 			break;
1163 		case D_GS:
1164 			*andptr++ = 0x0f;
1165 			*andptr++ = 0xb5;
1166 			break;
1167 		}
1168 		asmand(&p->from, reg[p->to.type]);
1169 		break;
1170 
1171 	case 6:	/* double shift */
1172 		z = p->from.type;
1173 		switch(z) {
1174 		default:
1175 			goto bad;
1176 		case D_CONST:
1177 			*andptr++ = 0x0f;
1178 			*andptr++ = t[4];
1179 			asmand(&p->to, reg[p->from.index]);
1180 			*andptr++ = p->from.offset;
1181 			break;
1182 		case D_CL:
1183 		case D_CX:
1184 			*andptr++ = 0x0f;
1185 			*andptr++ = t[5];
1186 			asmand(&p->to, reg[p->from.index]);
1187 			break;
1188 		}
1189 		break;
1190 	}
1191 }
1192 
1193 void
1194 asmins(Prog *p)
1195 {
1196 
1197 	andptr = and;
1198 	doasm(p);
1199 }
1200