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