Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

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