Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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