xref: /inferno-os/utils/8l/span.c (revision 2b69dba5038ffd0b59cf30a4c44bce549e5097f8)
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->pcond == P)
18 				p->pcond = p;
19 		if((q = p->pcond) != 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->pcond)
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->pcond) {
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->asym->name, 'z', a->aoffset, 0);
205 			else
206 			if(a->type == D_FILE1)
207 				putsymb(a->asym->name, 'Z', a->aoffset, 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->asym->name, 'a', -a->aoffset, 0);
217 			else
218 			if(a->type == D_PARAM)
219 				putsymb(a->asym->name, 'p', a->aoffset, 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 		return Ycl;
338 
339 	case D_DL:
340 	case D_BL:
341 	case D_AH:
342 	case D_CH:
343 	case D_DH:
344 	case D_BH:
345 		return Yrb;
346 
347 	case D_CX:
348 		return Ycx;
349 
350 	case D_DX:
351 	case D_BX:
352 		return Yrx;
353 
354 	case D_SP:
355 	case D_BP:
356 	case D_SI:
357 	case D_DI:
358 		return Yrl;
359 
360 	case D_F0+0:
361 		return	Yf0;
362 
363 	case D_F0+1:
364 	case D_F0+2:
365 	case D_F0+3:
366 	case D_F0+4:
367 	case D_F0+5:
368 	case D_F0+6:
369 	case D_F0+7:
370 		return	Yrf;
371 
372 	case D_NONE:
373 		return Ynone;
374 
375 	case D_CS:	return	Ycs;
376 	case D_SS:	return	Yss;
377 	case D_DS:	return	Yds;
378 	case D_ES:	return	Yes;
379 	case D_FS:	return	Yfs;
380 	case D_GS:	return	Ygs;
381 
382 	case D_GDTR:	return	Ygdtr;
383 	case D_IDTR:	return	Yidtr;
384 	case D_LDTR:	return	Yldtr;
385 	case D_MSW:	return	Ymsw;
386 	case D_TASK:	return	Ytask;
387 
388 	case D_CR+0:	return	Ycr0;
389 	case D_CR+1:	return	Ycr1;
390 	case D_CR+2:	return	Ycr2;
391 	case D_CR+3:	return	Ycr3;
392 	case D_CR+4:	return	Ycr4;
393 	case D_CR+5:	return	Ycr5;
394 	case D_CR+6:	return	Ycr6;
395 	case D_CR+7:	return	Ycr7;
396 
397 	case D_DR+0:	return	Ydr0;
398 	case D_DR+1:	return	Ydr1;
399 	case D_DR+2:	return	Ydr2;
400 	case D_DR+3:	return	Ydr3;
401 	case D_DR+4:	return	Ydr4;
402 	case D_DR+5:	return	Ydr5;
403 	case D_DR+6:	return	Ydr6;
404 	case D_DR+7:	return	Ydr7;
405 
406 	case D_TR+0:	return	Ytr0;
407 	case D_TR+1:	return	Ytr1;
408 	case D_TR+2:	return	Ytr2;
409 	case D_TR+3:	return	Ytr3;
410 	case D_TR+4:	return	Ytr4;
411 	case D_TR+5:	return	Ytr5;
412 	case D_TR+6:	return	Ytr6;
413 	case D_TR+7:	return	Ytr7;
414 
415 	case D_EXTERN:
416 	case D_STATIC:
417 	case D_AUTO:
418 	case D_PARAM:
419 		return Ym;
420 
421 	case D_CONST:
422 	case D_ADDR:
423 		if(a->sym == S) {
424 			v = a->offset;
425 			if(v == 0)
426 				return Yi0;
427 			if(v == 1)
428 				return Yi1;
429 			if(v >= -128 && v <= 127)
430 				return Yi8;
431 		}
432 		return Yi32;
433 
434 	case D_BRANCH:
435 		return Ybr;
436 	}
437 	return Yxxx;
438 }
439 
440 void
441 asmidx(Adr *a, int base)
442 {
443 	int i;
444 
445 	switch(a->index) {
446 	default:
447 		goto bad;
448 
449 	case D_NONE:
450 		i = 4 << 3;
451 		goto bas;
452 
453 	case D_AX:
454 	case D_CX:
455 	case D_DX:
456 	case D_BX:
457 	case D_BP:
458 	case D_SI:
459 	case D_DI:
460 		i = reg[a->index] << 3;
461 		break;
462 	}
463 	switch(a->scale) {
464 	default:
465 		goto bad;
466 	case 1:
467 		break;
468 	case 2:
469 		i |= (1<<6);
470 		break;
471 	case 4:
472 		i |= (2<<6);
473 		break;
474 	case 8:
475 		i |= (3<<6);
476 		break;
477 	}
478 bas:
479 	switch(base) {
480 	default:
481 		goto bad;
482 	case D_NONE:	/* must be mod=00 */
483 		i |= 5;
484 		break;
485 	case D_AX:
486 	case D_CX:
487 	case D_DX:
488 	case D_BX:
489 	case D_SP:
490 	case D_BP:
491 	case D_SI:
492 	case D_DI:
493 		i |= reg[base];
494 		break;
495 	}
496 	*andptr++ = i;
497 	return;
498 bad:
499 	diag("asmidx: bad address %D", a);
500 	*andptr++ = 0;
501 	return;
502 }
503 
504 static void
505 put4(long v)
506 {
507 	if(dlm && curp != P && reloca != nil){
508 		dynreloc(reloca->sym, curp->pc + andptr - &and[0], 1);
509 		reloca = nil;
510 	}
511 	andptr[0] = v;
512 	andptr[1] = v>>8;
513 	andptr[2] = v>>16;
514 	andptr[3] = v>>24;
515 	andptr += 4;
516 }
517 
518 long
519 vaddr(Adr *a)
520 {
521 	int t;
522 	long v;
523 	Sym *s;
524 
525 	t = a->type;
526 	v = a->offset;
527 	if(t == D_ADDR)
528 		t = a->index;
529 	switch(t) {
530 	case D_STATIC:
531 	case D_EXTERN:
532 		s = a->sym;
533 		if(s != nil) {
534 			if(dlm && curp != P)
535 				reloca = a;
536 			switch(s->type) {
537 			case SUNDEF:
538 				ckoff(s, v);
539 			case STEXT:
540 			case SCONST:
541 				v += s->value;
542 				break;
543 			default:
544 				v += INITDAT + s->value;
545 			}
546 		}
547 	}
548 	return v;
549 }
550 
551 void
552 asmand(Adr *a, int r)
553 {
554 	long v;
555 	int t;
556 	Adr aa;
557 
558 	v = a->offset;
559 	t = a->type;
560 	if(a->index != D_NONE) {
561 		if(t >= D_INDIR) {
562 			t -= D_INDIR;
563 			if(t == D_NONE) {
564 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
565 				asmidx(a, t);
566 				put4(v);
567 				return;
568 			}
569 			if(v == 0 && t != D_BP) {
570 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
571 				asmidx(a, t);
572 				return;
573 			}
574 			if(v >= -128 && v < 128) {
575 				*andptr++ = (1 << 6) | (4 << 0) | (r << 3);
576 				asmidx(a, t);
577 				*andptr++ = v;
578 				return;
579 			}
580 			*andptr++ = (2 << 6) | (4 << 0) | (r << 3);
581 			asmidx(a, t);
582 			put4(v);
583 			return;
584 		}
585 		switch(t) {
586 		default:
587 			goto bad;
588 		case D_STATIC:
589 		case D_EXTERN:
590 			aa.type = D_NONE+D_INDIR;
591 			break;
592 		case D_AUTO:
593 		case D_PARAM:
594 			aa.type = D_SP+D_INDIR;
595 			break;
596 		}
597 		aa.offset = vaddr(a);
598 		aa.index = a->index;
599 		aa.scale = a->scale;
600 		asmand(&aa, r);
601 		return;
602 	}
603 	if(t >= D_AL && t <= D_F0+7) {
604 		if(v)
605 			goto bad;
606 		*andptr++ = (3 << 6) | (reg[t] << 0) | (r << 3);
607 		return;
608 	}
609 	if(t >= D_INDIR) {
610 		t -= D_INDIR;
611 		if(t == D_NONE) {
612 			*andptr++ = (0 << 6) | (5 << 0) | (r << 3);
613 			put4(v);
614 			return;
615 		}
616 		if(t == D_SP) {
617 			if(v == 0) {
618 				*andptr++ = (0 << 6) | (4 << 0) | (r << 3);
619 				asmidx(a, D_SP);
620 				return;
621 			}
622 			if(v >= -128 && v < 128) {
623 				*andptr++ = (1 << 6) | (4 << 0) | (r << 3);
624 				asmidx(a, D_SP);
625 				*andptr++ = v;
626 				return;
627 			}
628 			*andptr++ = (2 << 6) | (4 << 0) | (r << 3);
629 			asmidx(a, D_SP);
630 			put4(v);
631 			return;
632 		}
633 		if(t >= D_AX && t <= D_DI) {
634 			if(v == 0 && t != D_BP) {
635 				*andptr++ = (0 << 6) | (reg[t] << 0) | (r << 3);
636 				return;
637 			}
638 			if(v >= -128 && v < 128) {
639 				andptr[0] = (1 << 6) | (reg[t] << 0) | (r << 3);
640 				andptr[1] = v;
641 				andptr += 2;
642 				return;
643 			}
644 			*andptr++ = (2 << 6) | (reg[t] << 0) | (r << 3);
645 			put4(v);
646 			return;
647 		}
648 		goto bad;
649 	}
650 	switch(a->type) {
651 	default:
652 		goto bad;
653 	case D_STATIC:
654 	case D_EXTERN:
655 		aa.type = D_NONE+D_INDIR;
656 		break;
657 	case D_AUTO:
658 	case D_PARAM:
659 		aa.type = D_SP+D_INDIR;
660 		break;
661 	}
662 	aa.index = D_NONE;
663 	aa.scale = 1;
664 	aa.offset = vaddr(a);
665 	asmand(&aa, r);
666 	return;
667 bad:
668 	diag("asmand: bad address %D", a);
669 	return;
670 }
671 
672 #define	E	0xff
673 uchar	ymovtab[] =
674 {
675 /* push */
676 	APUSHL,	Ycs,	Ynone,	0,	0x0e,E,0,0,
677 	APUSHL,	Yss,	Ynone,	0,	0x16,E,0,0,
678 	APUSHL,	Yds,	Ynone,	0,	0x1e,E,0,0,
679 	APUSHL,	Yes,	Ynone,	0,	0x06,E,0,0,
680 	APUSHL,	Yfs,	Ynone,	0,	0x0f,0xa0,E,0,
681 	APUSHL,	Ygs,	Ynone,	0,	0x0f,0xa8,E,0,
682 
683 	APUSHW,	Ycs,	Ynone,	0,	Pe,0x0e,E,0,
684 	APUSHW,	Yss,	Ynone,	0,	Pe,0x16,E,0,
685 	APUSHW,	Yds,	Ynone,	0,	Pe,0x1e,E,0,
686 	APUSHW,	Yes,	Ynone,	0,	Pe,0x06,E,0,
687 	APUSHW,	Yfs,	Ynone,	0,	Pe,0x0f,0xa0,E,
688 	APUSHW,	Ygs,	Ynone,	0,	Pe,0x0f,0xa8,E,
689 
690 /* pop */
691 	APOPL,	Ynone,	Yds,	0,	0x1f,E,0,0,
692 	APOPL,	Ynone,	Yes,	0,	0x07,E,0,0,
693 	APOPL,	Ynone,	Yss,	0,	0x17,E,0,0,
694 	APOPL,	Ynone,	Yfs,	0,	0x0f,0xa1,E,0,
695 	APOPL,	Ynone,	Ygs,	0,	0x0f,0xa9,E,0,
696 
697 	APOPW,	Ynone,	Yds,	0,	Pe,0x1f,E,0,
698 	APOPW,	Ynone,	Yes,	0,	Pe,0x07,E,0,
699 	APOPW,	Ynone,	Yss,	0,	Pe,0x17,E,0,
700 	APOPW,	Ynone,	Yfs,	0,	Pe,0x0f,0xa1,E,
701 	APOPW,	Ynone,	Ygs,	0,	Pe,0x0f,0xa9,E,
702 
703 /* mov seg */
704 	AMOVW,	Yes,	Yml,	1,	0x8c,0,0,0,
705 	AMOVW,	Ycs,	Yml,	1,	0x8c,1,0,0,
706 	AMOVW,	Yss,	Yml,	1,	0x8c,2,0,0,
707 	AMOVW,	Yds,	Yml,	1,	0x8c,3,0,0,
708 	AMOVW,	Yfs,	Yml,	1,	0x8c,4,0,0,
709 	AMOVW,	Ygs,	Yml,	1,	0x8c,5,0,0,
710 
711 	AMOVW,	Yml,	Yes,	2,	0x8e,0,0,0,
712 	AMOVW,	Yml,	Ycs,	2,	0x8e,1,0,0,
713 	AMOVW,	Yml,	Yss,	2,	0x8e,2,0,0,
714 	AMOVW,	Yml,	Yds,	2,	0x8e,3,0,0,
715 	AMOVW,	Yml,	Yfs,	2,	0x8e,4,0,0,
716 	AMOVW,	Yml,	Ygs,	2,	0x8e,5,0,0,
717 
718 /* mov cr */
719 	AMOVL,	Ycr0,	Yml,	3,	0x0f,0x20,0,0,
720 	AMOVL,	Ycr2,	Yml,	3,	0x0f,0x20,2,0,
721 	AMOVL,	Ycr3,	Yml,	3,	0x0f,0x20,3,0,
722 	AMOVL,	Ycr4,	Yml,	3,	0x0f,0x20,4,0,
723 
724 	AMOVL,	Yml,	Ycr0,	4,	0x0f,0x22,0,0,
725 	AMOVL,	Yml,	Ycr2,	4,	0x0f,0x22,2,0,
726 	AMOVL,	Yml,	Ycr3,	4,	0x0f,0x22,3,0,
727 	AMOVL,	Yml,	Ycr4,	4,	0x0f,0x22,4,0,
728 
729 /* mov dr */
730 	AMOVL,	Ydr0,	Yml,	3,	0x0f,0x21,0,0,
731 	AMOVL,	Ydr6,	Yml,	3,	0x0f,0x21,6,0,
732 	AMOVL,	Ydr7,	Yml,	3,	0x0f,0x21,7,0,
733 
734 	AMOVL,	Yml,	Ydr0,	4,	0x0f,0x23,0,0,
735 	AMOVL,	Yml,	Ydr6,	4,	0x0f,0x23,6,0,
736 	AMOVL,	Yml,	Ydr7,	4,	0x0f,0x23,7,0,
737 
738 /* mov tr */
739 	AMOVL,	Ytr6,	Yml,	3,	0x0f,0x24,6,0,
740 	AMOVL,	Ytr7,	Yml,	3,	0x0f,0x24,7,0,
741 
742 	AMOVL,	Yml,	Ytr6,	4,	0x0f,0x26,6,E,
743 	AMOVL,	Yml,	Ytr7,	4,	0x0f,0x26,7,E,
744 
745 /* lgdt, sgdt, lidt, sidt */
746 	AMOVL,	Ym,	Ygdtr,	4,	0x0f,0x01,2,0,
747 	AMOVL,	Ygdtr,	Ym,	3,	0x0f,0x01,0,0,
748 	AMOVL,	Ym,	Yidtr,	4,	0x0f,0x01,3,0,
749 	AMOVL,	Yidtr,	Ym,	3,	0x0f,0x01,1,0,
750 
751 /* lldt, sldt */
752 	AMOVW,	Yml,	Yldtr,	4,	0x0f,0x00,2,0,
753 	AMOVW,	Yldtr,	Yml,	3,	0x0f,0x00,0,0,
754 
755 /* lmsw, smsw */
756 	AMOVW,	Yml,	Ymsw,	4,	0x0f,0x01,6,0,
757 	AMOVW,	Ymsw,	Yml,	3,	0x0f,0x01,4,0,
758 
759 /* ltr, str */
760 	AMOVW,	Yml,	Ytask,	4,	0x0f,0x00,3,0,
761 	AMOVW,	Ytask,	Yml,	3,	0x0f,0x00,1,0,
762 
763 /* load full pointer */
764 	AMOVL,	Yml,	Ycol,	5,	0,0,0,0,
765 	AMOVW,	Yml,	Ycol,	5,	Pe,0,0,0,
766 
767 /* double shift */
768 	ASHLL,	Ycol,	Yml,	6,	0xa4,0xa5,0,0,
769 	ASHRL,	Ycol,	Yml,	6,	0xac,0xad,0,0,
770 
771 /* extra imul */
772 	AIMULL,	Yml,	Yrl,	7,	Pm,0xaf,0,0,
773 	0
774 };
775 
776 int
777 isax(Adr *a)
778 {
779 
780 	switch(a->type) {
781 	case D_AX:
782 	case D_AL:
783 	case D_AH:
784 	case D_INDIR+D_AX:
785 		return 1;
786 	}
787 	if(a->index == D_AX)
788 		return 1;
789 	return 0;
790 }
791 
792 void
793 subreg(Prog *p, int from, int to)
794 {
795 
796 	if(debug['Q'])
797 		print("\n%P	s/%R/%R/\n", p, from, to);
798 
799 	if(p->from.type == from)
800 		p->from.type = to;
801 	if(p->to.type == from)
802 		p->to.type = to;
803 
804 	if(p->from.index == from)
805 		p->from.index = to;
806 	if(p->to.index == from)
807 		p->to.index = to;
808 
809 	from += D_INDIR;
810 	if(p->from.type == from)
811 		p->from.type = to+D_INDIR;
812 	if(p->to.type == from)
813 		p->to.type = to+D_INDIR;
814 
815 	if(debug['Q'])
816 		print("%P\n", p);
817 }
818 
819 void
820 doasm(Prog *p)
821 {
822 	Optab *o;
823 	Prog *q, pp;
824 	uchar *t;
825 	int z, op, ft, tt;
826 	long v;
827 
828 	o = &optab[p->as];
829 	ft = oclass(&p->from) * Ymax;
830 	tt = oclass(&p->to) * Ymax;
831 	t = o->ytab;
832 	if(t == 0) {
833 		diag("asmins: noproto %P", p);
834 		return;
835 	}
836 	for(z=0; *t; z+=t[3],t+=4)
837 		if(ycover[ft+t[0]])
838 		if(ycover[tt+t[1]])
839 			goto found;
840 	goto domov;
841 
842 found:
843 	switch(o->prefix) {
844 	case Pq:	/* 16 bit escape and opcode escape */
845 		*andptr++ = Pe;
846 		*andptr++ = Pm;
847 		break;
848 
849 	case Pm:	/* opcode escape */
850 		*andptr++ = Pm;
851 		break;
852 
853 	case Pe:	/* 16 bit escape */
854 		*andptr++ = Pe;
855 		break;
856 
857 	case Pb:	/* botch */
858 		break;
859 	}
860 	v = vaddr(&p->from);
861 	op = o->op[z];
862 	switch(t[2]) {
863 	default:
864 		diag("asmins: unknown z %d %P", t[2], p);
865 		return;
866 
867 	case Zpseudo:
868 		break;
869 
870 	case Zlit:
871 		for(; op = o->op[z]; z++)
872 			*andptr++ = op;
873 		break;
874 
875 	case Zm_r:
876 		*andptr++ = op;
877 		asmand(&p->from, reg[p->to.type]);
878 		break;
879 
880 	case Zaut_r:
881 		*andptr++ = 0x8d;	/* leal */
882 		if(p->from.type != D_ADDR)
883 			diag("asmins: Zaut sb type ADDR");
884 		p->from.type = p->from.index;
885 		p->from.index = D_NONE;
886 		asmand(&p->from, reg[p->to.type]);
887 		p->from.index = p->from.type;
888 		p->from.type = D_ADDR;
889 		break;
890 
891 	case Zm_o:
892 		*andptr++ = op;
893 		asmand(&p->from, o->op[z+1]);
894 		break;
895 
896 	case Zr_m:
897 		*andptr++ = op;
898 		asmand(&p->to, reg[p->from.type]);
899 		break;
900 
901 	case Zo_m:
902 		*andptr++ = op;
903 		asmand(&p->to, o->op[z+1]);
904 		break;
905 
906 	case Zm_ibo:
907 		v = vaddr(&p->to);
908 		*andptr++ = op;
909 		asmand(&p->from, o->op[z+1]);
910 		*andptr++ = v;
911 		break;
912 
913 	case Zibo_m:
914 		*andptr++ = op;
915 		asmand(&p->to, o->op[z+1]);
916 		*andptr++ = v;
917 		break;
918 
919 	case Z_ib:
920 		v = vaddr(&p->to);
921 	case Zib_:
922 		*andptr++ = op;
923 		*andptr++ = v;
924 		break;
925 
926 	case Zib_rp:
927 		*andptr++ = op + reg[p->to.type];
928 		*andptr++ = v;
929 		break;
930 
931 	case Zil_rp:
932 		*andptr++ = op + reg[p->to.type];
933 		if(o->prefix == Pe) {
934 			*andptr++ = v;
935 			*andptr++ = v>>8;
936 		}
937 		else
938 			put4(v);
939 		break;
940 
941 	case Zib_rr:
942 		*andptr++ = op;
943 		asmand(&p->to, reg[p->to.type]);
944 		*andptr++ = v;
945 		break;
946 
947 	case Z_il:
948 		v = vaddr(&p->to);
949 	case Zil_:
950 		*andptr++ = op;
951 		if(o->prefix == Pe) {
952 			*andptr++ = v;
953 			*andptr++ = v>>8;
954 		}
955 		else
956 			put4(v);
957 		break;
958 
959 	case Zm_ilo:
960 		v = vaddr(&p->to);
961 		*andptr++ = op;
962 		asmand(&p->from, o->op[z+1]);
963 		if(o->prefix == Pe) {
964 			*andptr++ = v;
965 			*andptr++ = v>>8;
966 		}
967 		else
968 			put4(v);
969 		break;
970 
971 	case Zilo_m:
972 		*andptr++ = op;
973 		asmand(&p->to, o->op[z+1]);
974 		if(o->prefix == Pe) {
975 			*andptr++ = v;
976 			*andptr++ = v>>8;
977 		}
978 		else
979 			put4(v);
980 		break;
981 
982 	case Zil_rr:
983 		*andptr++ = op;
984 		asmand(&p->to, reg[p->to.type]);
985 		if(o->prefix == Pe) {
986 			*andptr++ = v;
987 			*andptr++ = v>>8;
988 		}
989 		else
990 			put4(v);
991 		break;
992 
993 	case Z_rp:
994 		*andptr++ = op + reg[p->to.type];
995 		break;
996 
997 	case Zrp_:
998 		*andptr++ = op + reg[p->from.type];
999 		break;
1000 
1001 	case Zclr:
1002 		*andptr++ = op;
1003 		asmand(&p->to, reg[p->to.type]);
1004 		break;
1005 
1006 	case Zbr:
1007 		q = p->pcond;
1008 		if(q) {
1009 			v = q->pc - p->pc - 2;
1010 			if(v >= -128 && v <= 127) {
1011 				*andptr++ = op;
1012 				*andptr++ = v;
1013 			} else {
1014 				v -= 6-2;
1015 				*andptr++ = 0x0f;
1016 				*andptr++ = o->op[z+1];
1017 				*andptr++ = v;
1018 				*andptr++ = v>>8;
1019 				*andptr++ = v>>16;
1020 				*andptr++ = v>>24;
1021 			}
1022 		}
1023 		break;
1024 
1025 	case Zcall:
1026 		q = p->pcond;
1027 		if(q) {
1028 			v = q->pc - p->pc - 5;
1029 			if(dlm && curp != P && p->to.sym->type == SUNDEF){
1030 				/* v = 0 - p->pc - 5; */
1031 				v = 0;
1032 				ckoff(p->to.sym, v);
1033 				v += p->to.sym->value;
1034 				dynreloc(p->to.sym, p->pc+1, 0);
1035 			}
1036 			*andptr++ = op;
1037 			*andptr++ = v;
1038 			*andptr++ = v>>8;
1039 			*andptr++ = v>>16;
1040 			*andptr++ = v>>24;
1041 		}
1042 		break;
1043 
1044 	case Zjmp:
1045 		q = p->pcond;
1046 		if(q) {
1047 			v = q->pc - p->pc - 2;
1048 			if(v >= -128 && v <= 127) {
1049 				*andptr++ = op;
1050 				*andptr++ = v;
1051 			} else {
1052 				v -= 5-2;
1053 				*andptr++ = o->op[z+1];
1054 				*andptr++ = v;
1055 				*andptr++ = v>>8;
1056 				*andptr++ = v>>16;
1057 				*andptr++ = v>>24;
1058 			}
1059 		}
1060 		break;
1061 
1062 	case Zloop:
1063 		q = p->pcond;
1064 		if(q) {
1065 			v = q->pc - p->pc - 2;
1066 			if(v < -128 && v > 127)
1067 				diag("loop too far: %P", p);
1068 			*andptr++ = op;
1069 			*andptr++ = v;
1070 		}
1071 		break;
1072 
1073 	case Zbyte:
1074 		*andptr++ = v;
1075 		if(op > 1) {
1076 			*andptr++ = v>>8;
1077 			if(op > 2) {
1078 				*andptr++ = v>>16;
1079 				*andptr++ = v>>24;
1080 			}
1081 		}
1082 		break;
1083 
1084 	case Zmov:
1085 		goto domov;
1086 	}
1087 	return;
1088 
1089 domov:
1090 	for(t=ymovtab; *t; t+=8)
1091 		if(p->as == t[0])
1092 		if(ycover[ft+t[1]])
1093 		if(ycover[tt+t[2]])
1094 			goto mfound;
1095 bad:
1096 	/*
1097 	 * here, the assembly has failed.
1098 	 * if its a byte instruction that has
1099 	 * unaddressable registers, try to
1100 	 * exchange registers and reissue the
1101 	 * instruction with the operands renamed.
1102 	 */
1103 	pp = *p;
1104 	z = p->from.type;
1105 	if(z >= D_BP && z <= D_DI) {
1106 		if(isax(&p->to)) {
1107 			*andptr++ = 0x87;			/* xchg lhs,bx */
1108 			asmand(&p->from, reg[D_BX]);
1109 			subreg(&pp, z, D_BX);
1110 			doasm(&pp);
1111 			*andptr++ = 0x87;			/* xchg lhs,bx */
1112 			asmand(&p->from, reg[D_BX]);
1113 		} else {
1114 			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
1115 			subreg(&pp, z, D_AX);
1116 			doasm(&pp);
1117 			*andptr++ = 0x90 + reg[z];		/* xchg lsh,ax */
1118 		}
1119 		return;
1120 	}
1121 	z = p->to.type;
1122 	if(z >= D_BP && z <= D_DI) {
1123 		if(isax(&p->from)) {
1124 			*andptr++ = 0x87;			/* xchg rhs,bx */
1125 			asmand(&p->to, reg[D_BX]);
1126 			subreg(&pp, z, D_BX);
1127 			doasm(&pp);
1128 			*andptr++ = 0x87;			/* xchg rhs,bx */
1129 			asmand(&p->to, reg[D_BX]);
1130 		} else {
1131 			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
1132 			subreg(&pp, z, D_AX);
1133 			doasm(&pp);
1134 			*andptr++ = 0x90 + reg[z];		/* xchg rsh,ax */
1135 		}
1136 		return;
1137 	}
1138 	diag("doasm: notfound t2=%ux from=%ux to=%ux %P", t[2], p->from.type, p->to.type, p);
1139 	return;
1140 
1141 mfound:
1142 	switch(t[3]) {
1143 	default:
1144 		diag("asmins: unknown mov %d %P", t[3], p);
1145 		break;
1146 
1147 	case 0:	/* lit */
1148 		for(z=4; t[z]!=E; z++)
1149 			*andptr++ = t[z];
1150 		break;
1151 
1152 	case 1:	/* r,m */
1153 		*andptr++ = t[4];
1154 		asmand(&p->to, t[5]);
1155 		break;
1156 
1157 	case 2:	/* m,r */
1158 		*andptr++ = t[4];
1159 		asmand(&p->from, t[5]);
1160 		break;
1161 
1162 	case 3:	/* r,m - 2op */
1163 		*andptr++ = t[4];
1164 		*andptr++ = t[5];
1165 		asmand(&p->to, t[6]);
1166 		break;
1167 
1168 	case 4:	/* m,r - 2op */
1169 		*andptr++ = t[4];
1170 		*andptr++ = t[5];
1171 		asmand(&p->from, t[6]);
1172 		break;
1173 
1174 	case 5:	/* load full pointer, trash heap */
1175 		if(t[4])
1176 			*andptr++ = t[4];
1177 		switch(p->to.index) {
1178 		default:
1179 			goto bad;
1180 		case D_DS:
1181 			*andptr++ = 0xc5;
1182 			break;
1183 		case D_SS:
1184 			*andptr++ = 0x0f;
1185 			*andptr++ = 0xb2;
1186 			break;
1187 		case D_ES:
1188 			*andptr++ = 0xc4;
1189 			break;
1190 		case D_FS:
1191 			*andptr++ = 0x0f;
1192 			*andptr++ = 0xb4;
1193 			break;
1194 		case D_GS:
1195 			*andptr++ = 0x0f;
1196 			*andptr++ = 0xb5;
1197 			break;
1198 		}
1199 		asmand(&p->from, reg[p->to.type]);
1200 		break;
1201 
1202 	case 6:	/* double shift */
1203 		z = p->from.type;
1204 		switch(z) {
1205 		default:
1206 			goto bad;
1207 		case D_CONST:
1208 			*andptr++ = 0x0f;
1209 			*andptr++ = t[4];
1210 			asmand(&p->to, reg[p->from.index]);
1211 			*andptr++ = p->from.offset;
1212 			break;
1213 		case D_CL:
1214 		case D_CX:
1215 			*andptr++ = 0x0f;
1216 			*andptr++ = t[5];
1217 			asmand(&p->to, reg[p->from.index]);
1218 			break;
1219 		}
1220 		break;
1221 
1222 	case 7: /* imul rm,r */
1223 		*andptr++ = t[4];
1224 		*andptr++ = t[5];
1225 		asmand(&p->from, reg[p->to.type]);
1226 		break;
1227 	}
1228 }
1229 
1230 void
1231 asmins(Prog *p)
1232 {
1233 
1234 	andptr = and;
1235 	doasm(p);
1236 }
1237 
1238 enum{
1239 	ABSD = 0,
1240 	ABSU = 1,
1241 	RELD = 2,
1242 	RELU = 3,
1243 };
1244 
1245 int modemap[4] = { 0, 1, -1, 2, };
1246 
1247 typedef struct Reloc Reloc;
1248 
1249 struct Reloc
1250 {
1251 	int n;
1252 	int t;
1253 	uchar *m;
1254 	ulong *a;
1255 };
1256 
1257 Reloc rels;
1258 
1259 static void
1260 grow(Reloc *r)
1261 {
1262 	int t;
1263 	uchar *m, *nm;
1264 	ulong *a, *na;
1265 
1266 	t = r->t;
1267 	r->t += 64;
1268 	m = r->m;
1269 	a = r->a;
1270 	r->m = nm = malloc(r->t*sizeof(uchar));
1271 	r->a = na = malloc(r->t*sizeof(ulong));
1272 	memmove(nm, m, t*sizeof(uchar));
1273 	memmove(na, a, t*sizeof(ulong));
1274 	free(m);
1275 	free(a);
1276 }
1277 
1278 void
1279 dynreloc(Sym *s, ulong v, int abs)
1280 {
1281 	int i, k, n;
1282 	uchar *m;
1283 	ulong *a;
1284 	Reloc *r;
1285 
1286 	if(s->type == SUNDEF)
1287 		k = abs ? ABSU : RELU;
1288 	else
1289 		k = abs ? ABSD : RELD;
1290 	/* Bprint(&bso, "R %s a=%ld(%lx) %d\n", s->name, v, v, k); */
1291 	k = modemap[k];
1292 	r = &rels;
1293 	n = r->n;
1294 	if(n >= r->t)
1295 		grow(r);
1296 	m = r->m;
1297 	a = r->a;
1298 	for(i = n; i > 0; i--){
1299 		if(v < a[i-1]){	/* happens occasionally for data */
1300 			m[i] = m[i-1];
1301 			a[i] = a[i-1];
1302 		}
1303 		else
1304 			break;
1305 	}
1306 	m[i] = k;
1307 	a[i] = v;
1308 	r->n++;
1309 }
1310 
1311 static int
1312 sput(char *s)
1313 {
1314 	char *p;
1315 
1316 	p = s;
1317 	while(*s)
1318 		cput(*s++);
1319 	cput(0);
1320 	return s-p+1;
1321 }
1322 
1323 void
1324 asmdyn()
1325 {
1326 	int i, n, t, c;
1327 	Sym *s;
1328 	ulong la, ra, *a;
1329 	vlong off;
1330 	uchar *m;
1331 	Reloc *r;
1332 
1333 	cflush();
1334 	off = seek(cout, 0, 1);
1335 	lput(0);
1336 	t = 0;
1337 	lput(imports);
1338 	t += 4;
1339 	for(i = 0; i < NHASH; i++)
1340 		for(s = hash[i]; s != S; s = s->link)
1341 			if(s->type == SUNDEF){
1342 				lput(s->sig);
1343 				t += 4;
1344 				t += sput(s->name);
1345 			}
1346 
1347 	la = 0;
1348 	r = &rels;
1349 	n = r->n;
1350 	m = r->m;
1351 	a = r->a;
1352 	lput(n);
1353 	t += 4;
1354 	for(i = 0; i < n; i++){
1355 		ra = *a-la;
1356 		if(*a < la)
1357 			diag("bad relocation order");
1358 		if(ra < 256)
1359 			c = 0;
1360 		else if(ra < 65536)
1361 			c = 1;
1362 		else
1363 			c = 2;
1364 		cput((c<<6)|*m++);
1365 		t++;
1366 		if(c == 0){
1367 			cput(ra);
1368 			t++;
1369 		}
1370 		else if(c == 1){
1371 			wput(ra);
1372 			t += 2;
1373 		}
1374 		else{
1375 			lput(ra);
1376 			t += 4;
1377 		}
1378 		la = *a++;
1379 	}
1380 
1381 	cflush();
1382 	seek(cout, off, 0);
1383 	lput(t);
1384 
1385 	if(debug['v']){
1386 		Bprint(&bso, "import table entries = %d\n", imports);
1387 		Bprint(&bso, "export table entries = %d\n", exports);
1388 	}
1389 }
1390