Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"l.h"
2
 
3
#define	LPUT(c)\
4
	{\
5
		cbp[0] = (c)>>24;\
6
		cbp[1] = (c)>>16;\
7
		cbp[2] = (c)>>8;\
8
		cbp[3] = (c);\
9
		cbp += 4;\
10
		cbc -= 4;\
11
		if(cbc <= 0)\
12
			cflush();\
13
	}
14
 
15
#define	CPUT(c)\
16
	{\
17
		cbp[0] = (c);\
18
		cbp++;\
19
		cbc--;\
20
		if(cbc <= 0)\
21
			cflush();\
22
	}
23
 
24
long
25
entryvalue(void)
26
{
27
	char *a;
28
	Sym *s;
29
 
30
	a = INITENTRY;
31
	if(*a >= '0' && *a <= '9')
32
		return atolwhex(a);
33
	s = lookup(a, 0);
34
	if(s->type == 0)
35
		return INITTEXT;
36
	if(s->type != STEXT && s->type != SLEAF)
37
		diag("entry not text: %s", s->name);
38
	return s->value;
39
}
40
 
41
void
42
asmb(void)
43
{
44
	Prog *p;
45
	long t;
46
	Optab *o;
47
 
48
	if(debug['v'])
49
		Bprint(&bso, "%5.2f asm\n", cputime());
50
	Bflush(&bso);
51
	seek(cout, HEADR, 0);
52
	pc = INITTEXT;
53
	for(p = firstp; p != P; p = p->link) {
54
		if(p->as == ATEXT) {
55
			curtext = p;
56
			autosize = p->to.offset + 4;
57
		}
58
		if(p->pc != pc) {
59
			diag("phase error %lux sb %lux",
60
				p->pc, pc);
61
			if(!debug['a'])
62
				prasm(curp);
63
			pc = p->pc;
64
		}
65
		curp = p;
66
		o = oplook(p);	/* could probably avoid this call */
67
		if(asmout(p, o, 0)) {
68
			p = p->link;
69
			pc += 4;
70
		}
71
		pc += o->size;
72
	}
73
	if(debug['a'])
74
		Bprint(&bso, "\n");
75
	Bflush(&bso);
76
	cflush();
77
 
78
	curtext = P;
79
	switch(HEADTYPE) {
80
	case 0:
81
	case 3:
82
		seek(cout, HEADR+textsize, 0);
83
		break;
84
	case 1:
85
	case 2:
86
		seek(cout, HEADR+textsize, 0);
87
		break;
88
	}
89
	for(t = 0; t < datsize; t += sizeof(buf)-100) {
90
		if(datsize-t > sizeof(buf)-100)
91
			datblk(t, sizeof(buf)-100);
92
		else
93
			datblk(t, datsize-t);
94
	}
95
 
96
	symsize = 0;
97
	lcsize = 0;
98
	if(!debug['s']) {
99
		if(debug['v'])
100
			Bprint(&bso, "%5.2f sym\n", cputime());
101
		Bflush(&bso);
102
		switch(HEADTYPE) {
103
		case 0:
104
		case 3:
105
			seek(cout, HEADR+textsize+datsize, 0);
106
			break;
107
		case 2:
108
		case 1:
109
			seek(cout, HEADR+textsize+datsize, 0);
110
			break;
111
		}
112
		if(!debug['s'])
113
			asmsym();
114
		if(debug['v'])
115
			Bprint(&bso, "%5.2f sp\n", cputime());
116
		Bflush(&bso);
117
		if(!debug['s'])
118
			asmlc();
119
		 /* round up file length for boot image */
120
		if(HEADTYPE == 0 || HEADTYPE == 3)
121
			if((symsize+lcsize) & 1)
122
				CPUT(0);
123
		cflush();
124
	}
125
 
126
	seek(cout, 0L, 0);
127
	switch(HEADTYPE) {
128
	case 0:
129
		lput(0x1030107);		/* magic and sections */
130
		lput(textsize);			/* sizes */
131
		lput(datsize);
132
		lput(bsssize);
133
		lput(symsize);			/* nsyms */
134
		lput(entryvalue());		/* va of entry */
135
		lput(0L);
136
		lput(lcsize);
137
		break;
138
	case 1:
139
		break;
140
	case 2:
141
		lput(4*13*13+7);		/* magic */
142
		lput(textsize);			/* sizes */
143
		lput(datsize);
144
		lput(bsssize);
145
		lput(symsize);			/* nsyms */
146
		lput(entryvalue());		/* va of entry */
147
		lput(0L);
148
		lput(lcsize);
149
		break;
150
	case 3:
151
		lput(0x1030107);		/* magic and sections */
152
		lput(0x90100000);
153
#define SPARC_NOOP 0x01000000
154
		lput(SPARC_NOOP);
155
		lput(SPARC_NOOP);
156
		lput(SPARC_NOOP);
157
		lput(SPARC_NOOP);
158
		lput(SPARC_NOOP);
159
		lput(SPARC_NOOP);
160
		break;
161
	}
162
	cflush();
163
}
164
 
165
void
166
lput(long l)
167
{
168
 
169
	LPUT(l);
170
}
171
 
172
void
173
cflush(void)
174
{
175
	int n;
176
 
177
	n = sizeof(buf.cbuf) - cbc;
178
	if(n)
179
		write(cout, buf.cbuf, n);
180
	cbp = buf.cbuf;
181
	cbc = sizeof(buf.cbuf);
182
}
183
 
184
void
185
asmsym(void)
186
{
187
	Prog *p;
188
	Auto *a;
189
	Sym *s;
190
	int h;
191
 
192
	s = lookup("etext", 0);
193
	if(s->type == STEXT)
194
		putsymb(s->name, 'T', s->value, s->version);
195
 
196
	for(h=0; h<NHASH; h++)
197
		for(s=hash[h]; s!=S; s=s->link)
198
			switch(s->type) {
199
			case SCONST:
200
				putsymb(s->name, 'D', s->value, s->version);
201
				continue;
202
 
203
			case SDATA:
204
				putsymb(s->name, 'D', s->value+INITDAT, s->version);
205
				continue;
206
 
207
			case SBSS:
208
				putsymb(s->name, 'B', s->value+INITDAT, s->version);
209
				continue;
210
 
211
			case SFILE:
212
				putsymb(s->name, 'f', s->value, s->version);
213
				continue;
214
			}
215
 
216
	for(p=textp; p!=P; p=p->cond) {
217
		s = p->from.sym;
218
		if(s->type != STEXT && s->type != SLEAF)
219
			continue;
220
 
221
		/* filenames first */
222
		for(a=p->to.autom; a; a=a->link)
223
			if(a->type == D_FILE)
224
				putsymb(a->asym->name, 'z', a->aoffset, 0);
225
			else
226
			if(a->type == D_FILE1)
227
				putsymb(a->asym->name, 'Z', a->aoffset, 0);
228
 
229
		if(s->type == STEXT)
230
			putsymb(s->name, 'T', s->value, s->version);
231
		else
232
			putsymb(s->name, 'L', s->value, s->version);
233
 
234
		/* frame, auto and param after */
235
		putsymb(".frame", 'm', p->to.offset+4, 0);
236
		for(a=p->to.autom; a; a=a->link)
237
			if(a->type == D_AUTO)
238
				putsymb(a->asym->name, 'a', -a->aoffset, 0);
239
			else
240
			if(a->type == D_PARAM)
241
				putsymb(a->asym->name, 'p', a->aoffset, 0);
242
	}
243
	if(debug['v'] || debug['n'])
244
		Bprint(&bso, "symsize = %lud\n", symsize);
245
	Bflush(&bso);
246
}
247
 
248
void
249
putsymb(char *s, int t, long v, int ver)
250
{
251
	int i, f;
252
 
253
	if(t == 'f')
254
		s++;
255
	LPUT(v);
256
	if(ver)
257
		t += 'a' - 'A';
258
	CPUT(t+0x80);			/* 0x80 is variable length */
259
 
260
	if(t == 'Z' || t == 'z') {
261
		CPUT(s[0]);
262
		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
263
			CPUT(s[i]);
264
			CPUT(s[i+1]);
265
		}
266
		CPUT(0);
267
		CPUT(0);
268
		i++;
269
	}
270
	else {
271
		for(i=0; s[i]; i++)
272
			CPUT(s[i]);
273
		CPUT(0);
274
	}
275
	symsize += 4 + 1 + i + 1;
276
 
277
	if(debug['n']) {
278
		if(t == 'z' || t == 'Z') {
279
			Bprint(&bso, "%c %.8lux ", t, v);
280
			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
281
				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
282
				Bprint(&bso, "/%x", f);
283
			}
284
			Bprint(&bso, "\n");
285
			return;
286
		}
287
		if(ver)
288
			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
289
		else
290
			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
291
	}
292
}
293
 
294
#define	MINLC	4
295
void
296
asmlc(void)
297
{
298
	long oldpc, oldlc;
299
	Prog *p;
300
	long v, s;
301
 
302
	oldpc = INITTEXT;
303
	oldlc = 0;
304
	for(p = firstp; p != P; p = p->link) {
305
		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
306
			if(p->as == ATEXT)
307
				curtext = p;
308
			if(debug['V'])
309
				Bprint(&bso, "%6lux %P\n",
310
					p->pc, p);
311
			continue;
312
		}
313
		if(debug['V'])
314
			Bprint(&bso, "\t\t%6ld", lcsize);
315
		v = (p->pc - oldpc) / MINLC;
316
		while(v) {
317
			s = 127;
318
			if(v < 127)
319
				s = v;
320
			CPUT(s+128);	/* 129-255 +pc */
321
			if(debug['V'])
322
				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
323
			v -= s;
324
			lcsize++;
325
		}
326
		s = p->line - oldlc;
327
		oldlc = p->line;
328
		oldpc = p->pc + MINLC;
329
		if(s > 64 || s < -64) {
330
			CPUT(0);	/* 0 vv +lc */
331
			CPUT(s>>24);
332
			CPUT(s>>16);
333
			CPUT(s>>8);
334
			CPUT(s);
335
			if(debug['V']) {
336
				if(s > 0)
337
					Bprint(&bso, " lc+%ld(%d,%ld)\n",
338
						s, 0, s);
339
				else
340
					Bprint(&bso, " lc%ld(%d,%ld)\n",
341
						s, 0, s);
342
				Bprint(&bso, "%6lux %P\n",
343
					p->pc, p);
344
			}
345
			lcsize += 5;
346
			continue;
347
		}
348
		if(s > 0) {
349
			CPUT(0+s);	/* 1-64 +lc */
350
			if(debug['V']) {
351
				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
352
				Bprint(&bso, "%6lux %P\n",
353
					p->pc, p);
354
			}
355
		} else {
356
			CPUT(64-s);	/* 65-128 -lc */
357
			if(debug['V']) {
358
				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
359
				Bprint(&bso, "%6lux %P\n",
360
					p->pc, p);
361
			}
362
		}
363
		lcsize++;
364
	}
365
	while(lcsize & 1) {
366
		s = 129;
367
		CPUT(s);
368
		lcsize++;
369
	}
370
	if(debug['v'] || debug['V'])
371
		Bprint(&bso, "lcsize = %ld\n", lcsize);
372
	Bflush(&bso);
373
}
374
 
375
void
376
datblk(long s, long n)
377
{
378
	Prog *p;
379
	char *cast;
380
	long l, fl, j, d;
381
	int i, c;
382
 
383
	memset(buf.dbuf, 0, n+100);
384
	for(p = datap; p != P; p = p->link) {
385
		curp = p;
386
		l = p->from.sym->value + p->from.offset - s;
387
		c = p->reg;
388
		i = 0;
389
		if(l < 0) {
390
			if(l+c <= 0)
391
				continue;
392
			while(l < 0) {
393
				l++;
394
				i++;
395
			}
396
		}
397
		if(l >= n)
398
			continue;
399
		if(p->as != AINIT && p->as != ADYNT) {
400
			for(j=l+(c-i)-1; j>=l; j--)
401
				if(buf.dbuf[j]) {
402
					print("%P\n", p);
403
					diag("multiple initialization");
404
					break;
405
				}
406
		}
407
		switch(p->to.type) {
408
		default:
409
			diag("unknown mode in initialization\n%P", p);
410
			break;
411
 
412
		case D_FCONST:
413
			switch(c) {
414
			default:
415
			case 4:
416
				fl = ieeedtof(&p->to.ieee);
417
				cast = (char*)&fl;
418
				for(; i<c; i++) {
419
					buf.dbuf[l] = cast[fnuxi8[i+4]];
420
					l++;
421
				}
422
				break;
423
			case 8:
424
				cast = (char*)&p->to.ieee;
425
				for(; i<c; i++) {
426
					buf.dbuf[l] = cast[fnuxi8[i]];
427
					l++;
428
				}
429
				break;
430
			}
431
			break;
432
 
433
		case D_SCONST:
434
			for(; i<c; i++) {
435
				buf.dbuf[l] = p->to.sval[i];
436
				l++;
437
			}
438
			break;
439
 
440
		case D_CONST:
441
			d = p->to.offset;
442
			if(p->to.sym) {
443
				if(p->to.sym->type == STEXT ||
444
				   p->to.sym->type == SLEAF)
445
					d += p->to.sym->value;
446
				if(p->to.sym->type == SDATA)
447
					d += p->to.sym->value + INITDAT;
448
				if(p->to.sym->type == SBSS)
449
					d += p->to.sym->value + INITDAT;
450
			}
451
			cast = (char*)&d;
452
			switch(c) {
453
			default:
454
				diag("bad nuxi %d %d\n%P", c, i, curp);
455
				break;
456
			case 1:
457
				for(; i<c; i++) {
458
					buf.dbuf[l] = cast[inuxi1[i]];
459
					l++;
460
				}
461
				break;
462
			case 2:
463
				for(; i<c; i++) {
464
					buf.dbuf[l] = cast[inuxi2[i]];
465
					l++;
466
				}
467
				break;
468
			case 4:
469
				for(; i<c; i++) {
470
					buf.dbuf[l] = cast[inuxi4[i]];
471
					l++;
472
				}
473
				break;
474
			}
475
			break;
476
		}
477
	}
478
	write(cout, buf.dbuf, n);
479
}
480
 
481
#define	OP2(x)	(0x80000000|((x)<<19))
482
#define	OP3(x)	(0xc0000000|((x)<<19))
483
#define	OPB(x)	(0x00800000|((x)<<25))
484
#define	OPT(x)	(0x81d02000|((x)<<25))
485
#define	OPF1(x)	(0x81a00000|((x)<<5))
486
#define	OPF2(x)	(0x81a80000|((x)<<5))
487
#define	OPFB(x)	(0x01800000|((x)<<25))
488
 
489
#define	OP_RRR(op,r1,r2,r3)\
490
	(0x00000000 | op |\
491
	(((r1)&31L)<<0) |\
492
	(((r2)&31L)<<14) |\
493
	(((r3)&31L)<<25))
494
#define	OP_IRR(op,i,r2,r3)\
495
	(0x00002000L | (op) |\
496
	(((i)&0x1fffL)<<0) |\
497
	(((r2)&31L)<<14) |\
498
	(((r3)&31L)<<25))
499
#define	OP_BRA(op,pc)\
500
	((op) |\
501
	(((pc)&0x3fffff)<<0))
502
 
503
int
504
asmout(Prog *p, Optab *o, int aflag)
505
{
506
	long o1, o2, o3, o4, o5, v;
507
	Prog *ct;
508
	int r;
509
 
510
	o1 = 0;
511
	o2 = 0;
512
	o3 = 0;
513
	o4 = 0;
514
	o5 = 0;
515
 
516
	switch(o->type) {
517
	default:
518
		if(aflag)
519
			return 0;
520
		diag("unknown type %d", o->type);
521
		if(!debug['a'])
522
			prasm(p);
523
		break;
524
 
525
	case 0:		/* pseudo ops */
526
		if(aflag) {
527
			if(p->link) {
528
				if(p->as == ATEXT) {
529
					ct = curtext;
530
					o2 = autosize;
531
					curtext = p;
532
					autosize = p->to.offset + 4;
533
					o1 = asmout(p->link, oplook(p->link), aflag);
534
					curtext = ct;
535
					autosize = o2;
536
				} else
537
					o1 = asmout(p->link, oplook(p->link), aflag);
538
			}
539
			return o1;
540
		}
541
		break;
542
 
543
	case 1:		/* mov r1,r2 ==> OR r1,r0,r2 */
544
		o1 = OP_RRR(opcode(AOR), p->from.reg, REGZERO, p->to.reg);
545
		break;
546
 
547
	case 2:		/* mov $c,r ==> add r1,r0,r2 */
548
		r = p->from.reg;
549
		if(r == NREG)
550
			r = o->param;
551
		v = regoff(&p->from);
552
		o1 = OP_IRR(opcode(AADD), v, r, p->to.reg);
553
		break;
554
 
555
	case 3:		/* mov soreg, r */
556
		r = p->from.reg;
557
		if(r == NREG)
558
			r = o->param;
559
		v = regoff(&p->from);
560
		if(v == 0 && p->reg != NREG)
561
			o1 = OP_RRR(opcode(p->as), p->reg, r, p->to.reg);
562
		else
563
			o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
564
		break;
565
 
566
	case 4:		/* mov r, soreg */
567
		r = p->to.reg;
568
		if(r == NREG)
569
			r = o->param;
570
		v = regoff(&p->to);
571
		if(v == 0 && p->reg != NREG)
572
			o1 = OP_RRR(opcode(p->as+AEND), p->reg, r, p->from.reg);
573
		else
574
			o1 = OP_IRR(opcode(p->as+AEND), v, r, p->from.reg);
575
		break;
576
 
577
	case 5:		/* mov $lcon, reg => sethi, add */
578
		v = regoff(&p->from);
579
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
580
		o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
581
		break;
582
 
583
	case 6:		/* mov asi, r[+r] */
584
		o1 = OP_RRR(opcode(p->as), p->reg, p->from.reg, p->to.reg);
585
		o1 |= (1<<23) | ((p->from.offset&0xff)<<5);
586
		break;
587
 
588
	case 7:		/* mov [+r]r, asi */
589
		o1 = OP_RRR(opcode(p->as+AEND), p->reg, p->to.reg, p->from.reg);
590
		o1 |= (1<<23) | ((p->to.offset&0xff)<<5);
591
		break;
592
 
593
	case 8:		/* mov r, preg and mov preg, r */
594
		if(p->to.type == D_PREG) {
595
			r = p->from.reg;
596
			switch(p->to.reg)
597
			{
598
			default:
599
				diag("unknown register P%d", p->to.reg);
600
			case D_Y:
601
				o1 = OP2(48);	/* wry */
602
				break;
603
			case D_PSR:
604
				o1 = OP2(49);	/* wrpsr */
605
				break;
606
			case D_WIM:
607
				o1 = OP2(50);	/* wrwim */
608
				break;
609
			case D_TBR:
610
				o1 = OP2(51);	/* wrtbr */
611
				break;
612
			}
613
			o1 = OP_IRR(o1, 0, r, 0);
614
			break;
615
		}
616
		if(p->from.type == D_PREG) {
617
			r = p->to.reg;
618
			switch(p->from.reg)
619
			{
620
			default:
621
				diag("unknown register P%d", p->to.reg);
622
			case D_Y:
623
				o1 = OP2(40);	/* rdy */
624
				break;
625
			case D_PSR:
626
				o1 = OP2(41);	/* rdpsr */
627
				break;
628
			case D_WIM:
629
				o1 = OP2(42);	/* rdwim */
630
				break;
631
			case D_TBR:
632
				o1 = OP2(43);	/* rdtbr */
633
				break;
634
			}
635
			o1 = OP_RRR(o1, 0, 0, r);
636
			break;
637
		}
638
		break;
639
 
640
	case 9:		/* movb r,r */
641
		v = 24;
642
		if(p->as == AMOVH || p->as == AMOVHU)
643
			v = 16;
644
		r = ASRA;
645
		if(p->as == AMOVBU || p->as == AMOVHU)
646
			r = ASRL;
647
		o1 = OP_IRR(opcode(ASLL), v, p->from.reg, p->to.reg);
648
		o2 = OP_IRR(opcode(r), v, p->to.reg, p->to.reg);
649
		break;
650
 
651
	case 10:	/* mov $loreg, reg */
652
		r = p->from.reg;
653
		if(r == NREG)
654
			r = o->param;
655
		v = regoff(&p->from);
656
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
657
		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
658
		o3 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, p->to.reg);
659
		break;
660
 
661
	case 11:	/* mov loreg, r */
662
		r = p->from.reg;
663
		if(r == NREG)
664
			r = o->param;
665
		v = regoff(&p->from);
666
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
667
		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
668
		o3 = OP_IRR(opcode(p->as), (v&0x3ff), REGTMP, p->to.reg);
669
		break;
670
 
671
	case 12:	/* mov r, loreg */
672
		r = p->to.reg;
673
		if(r == NREG)
674
			r = o->param;
675
		v = regoff(&p->to);
676
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
677
		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
678
		o3 = OP_IRR(opcode(p->as+AEND), (v&0x3ff), REGTMP, p->from.reg);
679
		break;
680
 
681
	case 13:	/* mov $ucon, r */
682
		v = regoff(&p->from);
683
		o1 = 0x1000000 | (p->to.reg<<25) | ((v>>10) & 0x3fffff);	/* sethi */
684
		break;
685
 
686
	case 20:	/* op $scon,r */
687
		v = regoff(&p->from);
688
		r = p->reg;
689
		if(r == NREG)
690
			r = p->to.reg;
691
		o1 = OP_IRR(opcode(p->as), v, r, p->to.reg);
692
		break;
693
 
694
	case 21:	/* op r1,r2 */
695
		r = p->reg;
696
		if(r == NREG)
697
			r = p->to.reg;
698
		o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
699
		break;
700
 
701
	case 22:	/* op $lcon,r */
702
		v = regoff(&p->from);
703
		r = p->reg;
704
		if(r == NREG)
705
			r = p->to.reg;
706
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
707
		o2 = OP_IRR(opcode(AADD), (v&0x3ff), REGTMP, REGTMP);
708
		o3 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
709
		break;
710
 
711
	case 23:	/* cmp r,r */
712
		o1 = OP_RRR(opcode(ASUBCC), p->to.reg, p->from.reg, REGZERO);
713
		break;
714
 
715
	case 24:	/* cmp r,$c */
716
		v = regoff(&p->to);
717
		o1 = OP_IRR(opcode(ASUBCC), v, p->from.reg, REGZERO);
718
		break;
719
 
720
	case 25:	/* cmp $c,r BOTCH, fix compiler */
721
		v = regoff(&p->from);
722
		o1 = OP_IRR(opcode(AADD), v, NREG, REGTMP);
723
		o2 = OP_RRR(opcode(ASUBCC), p->to.reg, REGTMP, REGZERO);
724
		break;
725
 
726
	case 26:	/* op $ucon,r */
727
		v = regoff(&p->from);
728
		r = p->reg;
729
		if(r == NREG)
730
			r = p->to.reg;
731
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
732
		o2 = OP_RRR(opcode(p->as), REGTMP, r, p->to.reg);
733
		break;
734
 
735
	case 30:	/* jmp/jmpl soreg */
736
		if(aflag)
737
			return 0;
738
		v = regoff(&p->to);
739
		r = p->reg;
740
		if(r == NREG && p->as == AJMPL)
741
			r = 15;
742
		o1 = OP_IRR(opcode(AJMPL), v, p->to.reg, r);
743
		break;
744
 
745
	case 31:	/* ba jmp */
746
		if(aflag)
747
			return 0;
748
		r = p->as;
749
		if(r == AJMP)
750
			r = ABA;
751
		v = 0;
752
		if(p->cond)
753
			v = p->cond->pc - p->pc;
754
		o1 = OP_BRA(opcode(r), v/4);
755
		if(r == ABA && p->link && p->cond && isnop(p->link)) {
756
			o2 = asmout(p->cond, oplook(p->cond), 1);
757
			if(o2) {
758
				o1 += 1;
759
				if(debug['a'])
760
					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
761
				LPUT(o1);
762
				LPUT(o2);
763
				return 1;
764
			}
765
			/* cant set annul here because pc has already been counted */
766
		}
767
		break;
768
 
769
	case 32:	/* jmpl lbra */
770
		if(aflag)
771
			return 0;
772
		v = 0;
773
		if(p->cond)
774
			v = p->cond->pc - p->pc;
775
		r = p->reg;
776
		if(r != NREG && r != 15)
777
			diag("cant jmpl other than R15");
778
		o1 = 0x40000000 | ((v/4) & 0x3fffffffL);	/* call */
779
		if(p->link && p->cond && isnop(p->link)) {
780
			o2 = asmout(p->cond, oplook(p->cond), 1);
781
			if(o2) {
782
				o1 += 1;
783
				if(debug['a'])
784
					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
785
				LPUT(o1);
786
				LPUT(o2);
787
				return 1;
788
			}
789
		}
790
		break;
791
 
792
	case 33:	/* trap r */
793
		if(aflag)
794
			return 0;
795
		o1 = opcode(p->as) | (p->from.reg<<14);
796
		break;
797
 
798
	case 34:	/* rett r1,r2 -> jmpl (r1); rett (r2) */
799
		if(aflag)
800
			return 0;
801
		o1 = OP_IRR(opcode(AJMPL), 0, p->from.reg, REGZERO);
802
		o2 = OP_IRR(opcode(ARETT), 0, p->to.reg, REGZERO);
803
		break;
804
 
805
	case 40:	/* ldfsr, stfsr, stdq */
806
		if(p->to.type == D_PREG) {
807
			r = p->from.reg;
808
			if(r == NREG)
809
				r = o->param;
810
			v = regoff(&p->from);
811
			if(p->to.reg == D_FSR) {
812
				o1 = OP_IRR(OP3(33), v, r, 0);
813
				break;
814
			}
815
			diag("unknown reg load %d", p->to.reg);
816
		} else {
817
			r = p->to.reg;
818
			if(r == NREG)
819
				r = o->param;
820
			v = regoff(&p->to);
821
			if(p->from.reg == D_FSR) {
822
				o1 = OP_IRR(OP3(37), v, r, 0);
823
				break;
824
			}
825
			if(p->as == AMOVD && p->from.reg == D_FPQ) {
826
				o1 = OP_IRR(OP3(38), v, r, 0);
827
				break;
828
			}
829
			diag("unknown reg store %d", p->from.reg);
830
		}
831
		break;
832
 
833
	case 41:	/* ldf,ldd */
834
		r = p->from.reg;
835
		if(r == NREG)
836
			r = o->param;
837
		v = regoff(&p->from);
838
		if(p->as == AFMOVF || p->as == AMOVW) {
839
			o1 = OP_IRR(OP3(32), v, r, p->to.reg);
840
			break;
841
		}
842
		if(p->as == AMOVD || p->as == AFMOVD) {
843
			o1 = OP_IRR(OP3(35), v, r, p->to.reg);
844
			break;
845
		}
846
		diag("only MOVD and MOVW to FREG");
847
		break;
848
 
849
	case 42:	/* ldd -> ldf,ldf */
850
		/* note should be ldd with proper allignment */
851
		r = p->from.reg;
852
		if(r == NREG)
853
			r = o->param;
854
		v = regoff(&p->from);
855
		o1 = OP_IRR(OP3(32), v, r, p->to.reg);
856
		o2 = OP_IRR(OP3(32), v+4, r, p->to.reg+1);
857
		break;
858
 
859
	case 43:	/* stf */
860
		r = p->to.reg;
861
		if(r == NREG)
862
			r = o->param;
863
		v = regoff(&p->to);
864
		if(p->as == AFMOVF || p->as == AMOVW) {
865
			o1 = OP_IRR(OP3(36), v, r, p->from.reg);
866
			break;
867
		}
868
		if(p->as == AMOVD || p->as == AFMOVD) {
869
			o1 = OP_IRR(OP3(39), v, r, p->from.reg);
870
			break;
871
		}
872
		diag("only MOVD and MOVW from FREG");
873
		break;
874
 
875
	case 44:	/* std -> stf,stf */
876
		/* note should be std with proper allignment */
877
		r = p->to.reg;
878
		if(r == NREG)
879
			r = o->param;
880
		v = regoff(&p->to);
881
		o1 = OP_IRR(OP3(36), v, r, p->from.reg);
882
		o2 = OP_IRR(OP3(36), v+4, r, p->from.reg+1);
883
		break;
884
 
885
	case 45:	/* ldf lorg */
886
		r = p->from.reg;
887
		if(r == NREG)
888
			r = o->param;
889
		v = regoff(&p->from);
890
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
891
		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
892
		o3 = OP_IRR(OP3(32), v&0x3ff, REGTMP, p->to.reg);
893
		break;
894
 
895
	case 46:	/* ldd lorg -> ldf,ldf */
896
		/* note should be ldd with proper allignment */
897
		r = p->from.reg;
898
		if(r == NREG)
899
			r = o->param;
900
		v = regoff(&p->from);
901
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
902
		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
903
		o3 = OP_IRR(OP3(32), (v&0x3ff), REGTMP, p->to.reg);
904
		o4 = OP_IRR(OP3(32), (v&0x3ff)+4, REGTMP, p->to.reg+1);
905
		break;
906
 
907
	case 47:	/* stf lorg */
908
		r = p->to.reg;
909
		if(r == NREG)
910
			r = o->param;
911
		v = regoff(&p->to);
912
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
913
		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
914
		o3 = OP_IRR(OP3(36), v&0x3ff, REGTMP, p->from.reg);
915
		break;
916
 
917
	case 48:	/* std lorg -> stf,stf */
918
		/* note should be std with proper allignment */
919
		r = p->to.reg;
920
		if(r == NREG)
921
			r = o->param;
922
		v = regoff(&p->to);
923
		o1 = 0x1000000 | (REGTMP<<25) | ((v>>10) & 0x3fffff);	/* sethi */
924
		o2 = OP_RRR(opcode(AADD), r, REGTMP, REGTMP);
925
		o3 = OP_IRR(OP3(36), (v&0x3ff), REGTMP, p->from.reg);
926
		o4 = OP_IRR(OP3(36), (v&0x3ff)+4, REGTMP, p->from.reg+1);
927
		break;
928
 
929
	case 49:	/* fmovd -> fmovf,fmovf */
930
		o1 = OP_RRR(opcode(AFMOVF), p->from.reg, 0, p->to.reg);
931
		o2 = OP_RRR(opcode(AFMOVF), p->from.reg+1, 0, p->to.reg+1);
932
		break;
933
 
934
	case 50:	/* fcmp */
935
		o1 = OP_RRR(opcode(p->as), p->to.reg, p->from.reg, 0);
936
		break;
937
 
938
	case 51:	/* word */
939
		if(aflag)
940
			return 0;
941
		o1 = regoff(&p->from);
942
		break;
943
 
944
	case 52:	/* div */
945
		r = p->reg;
946
		if(r == NREG)
947
			r = p->to.reg;
948
		o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
949
		o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
950
		o3 = OP_RRR(opcode(ADIV), p->from.reg, r, p->to.reg);
951
		break;
952
 
953
	case 53:	/* divl */
954
		r = p->reg;
955
		if(r == NREG)
956
			r = p->to.reg;
957
		o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
958
		o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, p->to.reg);
959
		break;
960
 
961
	case 54:	/* mod */
962
		r = p->reg;
963
		if(r == NREG)
964
			r = p->to.reg;
965
		o1 = OP_IRR(opcode(ASRA), 31, r, REGTMP);
966
		o2 = OP_IRR(OP2(48), 0, REGTMP, 0);
967
		o3 = OP_RRR(opcode(ADIV), p->from.reg, r, REGTMP);
968
		o4 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
969
		o5 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
970
		break;
971
 
972
	case 55:	/* modl */
973
		r = p->reg;
974
		if(r == NREG)
975
			r = p->to.reg;
976
		o1 = OP_IRR(OP2(48), 0, REGZERO, 0);
977
		o2 = OP_RRR(opcode(ADIVL), p->from.reg, r, REGTMP);
978
		o3 = OP_RRR(opcode(AMUL), p->from.reg, REGTMP, REGTMP);
979
		o4 = OP_RRR(opcode(ASUB), REGTMP, r, p->to.reg);
980
		break;
981
 
982
	case 56:	/* b(cc) -- annullable */
983
		if(aflag)
984
			return 0;
985
		r = p->as;
986
		v = 0;
987
		if(p->cond)
988
			v = p->cond->pc - p->pc;
989
		o1 = OP_BRA(opcode(r), v/4);
990
		if(p->link && p->cond && isnop(p->link))
991
		if(!debug['A']) {
992
			o2 = asmout(p->cond, oplook(p->cond), 2);
993
			if(o2) {
994
				o1 |= 1<<29;	/* annul */
995
				o1 += 1;
996
				if(debug['a'])
997
					Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", p->pc, o1, o2, p);
998
				LPUT(o1);
999
				LPUT(o2);
1000
				return 1;
1001
			}
1002
		}
1003
		break;
1004
 
1005
	case 57:	/* op r1,r2 with reserved rs1 */
1006
		r = 0;
1007
		o1 = OP_RRR(opcode(p->as), p->from.reg, r, p->to.reg);
1008
		break;
1009
	}
1010
	if(aflag)
1011
		return o1;
1012
	v = p->pc;
1013
	switch(o->size) {
1014
	default:
1015
		if(debug['a'])
1016
			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
1017
		break;
1018
	case 4:
1019
		if(debug['a'])
1020
			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
1021
		LPUT(o1);
1022
		break;
1023
	case 8:
1024
		if(debug['a'])
1025
			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
1026
		LPUT(o1);
1027
		LPUT(o2);
1028
		break;
1029
	case 12:
1030
		if(debug['a'])
1031
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
1032
		LPUT(o1);
1033
		LPUT(o2);
1034
		LPUT(o3);
1035
		break;
1036
	case 16:
1037
		if(debug['a'])
1038
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
1039
				v, o1, o2, o3, o4, p);
1040
		LPUT(o1);
1041
		LPUT(o2);
1042
		LPUT(o3);
1043
		LPUT(o4);
1044
		break;
1045
	case 20:
1046
		if(debug['a'])
1047
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1048
				v, o1, o2, o3, o4, o5, p);
1049
		LPUT(o1);
1050
		LPUT(o2);
1051
		LPUT(o3);
1052
		LPUT(o4);
1053
		LPUT(o5);
1054
		break;
1055
	}
1056
	return 0;
1057
}
1058
 
1059
int
1060
isnop(Prog *p)
1061
{
1062
	if(p->as != AORN)
1063
		return 0;
1064
	if(p->reg != REGZERO && p->reg != NREG)
1065
		return 0;
1066
	if(p->from.type != D_REG || p->from.reg != REGZERO)
1067
		return 0;
1068
	if(p->to.type != D_REG || p->to.reg != REGZERO)
1069
		return 0;
1070
	return 1;
1071
}
1072
 
1073
long
1074
opcode(int a)
1075
{
1076
	switch(a) {
1077
	case AADD:	return OP2(0);
1078
	case AADDCC:	return OP2(16);
1079
	case AADDX:	return OP2(8);
1080
	case AADDXCC:	return OP2(24);
1081
 
1082
	case AMUL:	return OP2(10);
1083
	case ADIV:	return OP2(15);
1084
	case ADIVL:	return OP2(14);
1085
 
1086
	case ATADDCC:	return OP2(32);
1087
	case ATADDCCTV:	return OP2(34);
1088
 
1089
	case ASUB:	return OP2(4);
1090
	case ASUBCC:	return OP2(20);
1091
	case ASUBX:	return OP2(12);
1092
	case ASUBXCC:	return OP2(28);
1093
 
1094
	case ATSUBCC:	return OP2(33);
1095
	case ATSUBCCTV:	return OP2(35);
1096
 
1097
	case AMULSCC:	return OP2(36);
1098
	case ASAVE:	return OP2(60);
1099
	case ARESTORE:	return OP2(61);
1100
 
1101
	case AAND:	return OP2(1);
1102
	case AANDCC:	return OP2(17);
1103
	case AANDN:	return OP2(5);
1104
	case AANDNCC:	return OP2(21);
1105
 
1106
	case AOR:	return OP2(2);
1107
	case AORCC:	return OP2(18);
1108
	case AORN:	return OP2(6);
1109
	case AORNCC:	return OP2(22);
1110
 
1111
	case AXOR:	return OP2(3);
1112
	case AXORCC:	return OP2(19);
1113
	case AXNOR:	return OP2(7);
1114
	case AXNORCC:	return OP2(23);
1115
 
1116
	case ASLL:	return OP2(37);
1117
	case ASRL:	return OP2(38);
1118
	case ASRA:	return OP2(39);
1119
 
1120
	case AJMPL:
1121
	case AJMP:	return OP2(56);
1122
	case ARETT:	return OP2(57);
1123
 
1124
	case AMOVBU:	return OP3(1);	/* ldub */
1125
	case AMOVB:	return OP3(9);	/* ldsb */
1126
	case AMOVHU:	return OP3(2);	/* lduh */
1127
	case AMOVH:	return OP3(10);	/* ldsh */
1128
	case AMOVW:	return OP3(0);	/* ld */
1129
	case AMOVD:	return OP3(3);	/* ldd */
1130
 
1131
	case AMOVBU+AEND:
1132
	case AMOVB+AEND:return OP3(5);	/* stb */
1133
 
1134
	case AMOVHU+AEND:
1135
	case AMOVH+AEND:return OP3(6);	/* sth */
1136
 
1137
	case AMOVW+AEND:return OP3(4);	/* st */
1138
 
1139
	case AMOVD+AEND:return OP3(7);	/* std */
1140
 
1141
	case ASWAP:			/* swap is symmetric */
1142
	case ASWAP+AEND:return OP3(15);
1143
 
1144
	case ATAS:	return OP3(13);	/* tas is really ldstub */
1145
 
1146
	case ABN:	return OPB(0);
1147
	case ABE:	return OPB(1);
1148
	case ABLE:	return OPB(2);
1149
	case ABL:	return OPB(3);
1150
	case ABLEU:	return OPB(4);
1151
	case ABCS:	return OPB(5);
1152
	case ABNEG:	return OPB(6);
1153
	case ABVS:	return OPB(7);
1154
	case ABA:	return OPB(8);
1155
	case ABNE:	return OPB(9);
1156
	case ABG:	return OPB(10);
1157
	case ABGE:	return OPB(11);
1158
	case ABGU:	return OPB(12);
1159
	case ABCC:	return OPB(13);
1160
	case ABPOS:	return OPB(14);
1161
	case ABVC:	return OPB(15);
1162
 
1163
	case AFBA:	return OPFB(8);
1164
	case AFBE:	return OPFB(9);
1165
	case AFBG:	return OPFB(6);
1166
	case AFBGE:	return OPFB(11);
1167
	case AFBL:	return OPFB(4);
1168
	case AFBLE:	return OPFB(13);
1169
	case AFBLG:	return OPFB(2);
1170
	case AFBN:	return OPFB(0);
1171
	case AFBNE:	return OPFB(1);
1172
	case AFBO:	return OPFB(15);
1173
	case AFBU:	return OPFB(7);
1174
	case AFBUE:	return OPFB(10);
1175
	case AFBUG:	return OPFB(5);
1176
	case AFBUGE:	return OPFB(12);
1177
	case AFBUL:	return OPFB(3);
1178
	case AFBULE:	return OPFB(14);
1179
 
1180
	case ATN:	return OPT(0);
1181
	case ATE:	return OPT(1);
1182
	case ATLE:	return OPT(2);
1183
	case ATL:	return OPT(3);
1184
	case ATLEU:	return OPT(4);
1185
	case ATCS:	return OPT(5);
1186
	case ATNEG:	return OPT(6);
1187
	case ATVS:	return OPT(7);
1188
	case ATA:	return OPT(8);
1189
	case ATNE:	return OPT(9);
1190
	case ATG:	return OPT(10);
1191
	case ATGE:	return OPT(11);
1192
	case ATGU:	return OPT(12);
1193
	case ATCC:	return OPT(13);
1194
	case ATPOS:	return OPT(14);
1195
	case ATVC:	return OPT(15);
1196
 
1197
	case AFADDF:	return OPF1(65);
1198
	case AFADDD:	return OPF1(66);
1199
	case AFADDX:	return OPF1(67);
1200
	case AFSUBF:	return OPF1(69);
1201
	case AFSUBD:	return OPF1(70);
1202
	case AFSUBX:	return OPF1(71);
1203
	case AFMULF:	return OPF1(73);
1204
	case AFMULD:	return OPF1(74);
1205
	case AFMULX:	return OPF1(75);
1206
	case AFDIVF:	return OPF1(77);
1207
	case AFDIVD:	return OPF1(78);
1208
	case AFDIVX:	return OPF1(79);
1209
 
1210
	case AFMOVF:	return OPF1(1);
1211
	case AFNEGF:	return OPF1(5);
1212
	case AFABSF:	return OPF1(9);
1213
 
1214
	case AFSQRTF:	return OPF1(41);
1215
	case AFSQRTD:	return OPF1(42);
1216
	case AFSQRTX:	return OPF1(43);
1217
 
1218
	case AFMOVWF:	return OPF1(196);
1219
	case AFMOVWD:	return OPF1(200);
1220
	case AFMOVWX:	return OPF1(204);
1221
	case AFMOVFW:	return OPF1(209);
1222
	case AFMOVDW:	return OPF1(210);
1223
	case AFMOVXW:	return OPF1(211);
1224
	case AFMOVFD:	return OPF1(201);
1225
	case AFMOVFX:	return OPF1(205);
1226
	case AFMOVDF:	return OPF1(198);
1227
	case AFMOVDX:	return OPF1(206);
1228
	case AFMOVXF:	return OPF1(199);
1229
	case AFMOVXD:	return OPF1(203);
1230
 
1231
	case AFCMPF:	return OPF2(81);
1232
	case AFCMPD:	return OPF2(82);
1233
	case AFCMPX:	return OPF2(83);
1234
	case AFCMPEF:	return OPF2(85);
1235
	case AFCMPED:	return OPF2(86);
1236
	case AFCMPEX:	return OPF2(87);
1237
 
1238
	case AUNIMP:	return 0;
1239
	}
1240
	diag("bad opcode %A", a);
1241
	return 0;
1242
}