Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"l.h"
2
 
3
/* can't include a.out.h due to name clashes, but these are taken from it */
4
#define	_MAGIC(f, b)	((f)|((((4*(b))+0)*(b))+7))
5
#define	V_MAGIC		_MAGIC(0, 16)		/* mips 3000 BE */
6
#define	M_MAGIC		_MAGIC(0, 18)		/* mips 4000 BE */
7
#define	N_MAGIC		_MAGIC(0, 22)		/* mips 4000 LE */
8
#define	P_MAGIC		_MAGIC(0, 24)		/* mips 3000 LE */
9
 
10
long	OFFSET;
11
/*
12
long	BADOFFSET	=	-1;
13
 
14
		if(OFFSET <= BADOFFSET && OFFSET+4 > BADOFFSET)\
15
			abort();\
16
		OFFSET += 4;\
17
 
18
		if(OFFSET == BADOFFSET)\
19
			abort();\
20
		OFFSET++;\
21
*/
22
 
23
#define LPUT(l) { \
24
		if (little) { \
25
			LLEPUT(l); \
26
		} else { \
27
			LBEPUT(l); \
28
		} \
29
	}
30
 
31
#define	LLEPUT(c)\
32
	{\
33
		cbp[0] = (c);\
34
		cbp[1] = (c)>>8;\
35
		cbp[2] = (c)>>16;\
36
		cbp[3] = (c)>>24;\
37
		cbp += 4;\
38
		cbc -= 4;\
39
		if(cbc <= 0)\
40
			cflush();\
41
	}
42
 
43
#define	LBEPUT(c)\
44
	{\
45
		cbp[0] = (c)>>24;\
46
		cbp[1] = (c)>>16;\
47
		cbp[2] = (c)>>8;\
48
		cbp[3] = (c);\
49
		cbp += 4;\
50
		cbc -= 4;\
51
		if(cbc <= 0)\
52
			cflush();\
53
	}
54
 
55
#define HPUT(h) { \
56
		if (little) { \
57
			HLEPUT(h); \
58
		} else { \
59
			HBEPUT(h); \
60
		} \
61
	}
62
 
63
#define	HLEPUT(c)\
64
	{\
65
		cbp[0] = (c);\
66
		cbp[1] = (c)>>8;\
67
		cbp += 2;\
68
		cbc -= 2;\
69
		if(cbc <= 0)\
70
			cflush();\
71
	}
72
 
73
#define	HBEPUT(c)\
74
	{\
75
		cbp[0] = (c)>>8;\
76
		cbp[1] = (c);\
77
		cbp += 2;\
78
		cbc -= 2;\
79
		if(cbc <= 0)\
80
			cflush();\
81
	}
82
 
83
 
84
#define	CPUT(c)\
85
	{\
86
		cbp[0] = (c);\
87
		cbp++;\
88
		cbc--;\
89
		if(cbc <= 0)\
90
			cflush();\
91
	}
92
 
93
void
94
cput(long l)
95
{
96
	CPUT(l);
97
}
98
 
99
void
100
objput(long l)	/* emit long in byte order appropriate to object machine */
101
{
102
	LPUT(l);
103
}
104
 
105
void
106
objhput(short s)
107
{
108
	HPUT(s);
109
}
110
 
111
void
112
wput(long l)
113
{
114
 
115
	cbp[0] = l>>8;
116
	cbp[1] = l;
117
	cbp += 2;
118
	cbc -= 2;
119
	if(cbc <= 0)
120
		cflush();
121
}
122
 
123
void
124
wputl(long l)
125
{
126
 
127
	cbp[0] = l;
128
	cbp[1] = l>>8;
129
	cbp += 2;
130
	cbc -= 2;
131
	if(cbc <= 0)
132
		cflush();
133
}
134
 
135
void
136
lput(long l)		/* emit long in big-endian byte order */
137
{
138
	LBEPUT(l);
139
}
140
 
141
void
142
lputl(long l)		/* emit long in big-endian byte order */
143
{
144
	LLEPUT(l);
145
}
146
 
147
void
148
llput(vlong v)
149
{
150
	lput(v>>32);
151
	lput(v);
152
}
153
 
154
void
155
llputl(vlong v)
156
{
157
	lputl(v);
158
	lputl(v>>32);
159
}
160
 
161
long
162
entryvalue(void)
163
{
164
	char *a;
165
	Sym *s;
166
 
167
	a = INITENTRY;
168
	if(*a >= '0' && *a <= '9')
169
		return atolwhex(a);
170
	s = lookup(a, 0);
171
	if(s->type == 0)
172
		return INITTEXT;
173
	if(s->type != STEXT && s->type != SLEAF)
174
		diag("entry not text: %s", s->name);
175
	return s->value;
176
}
177
 
178
static void
179
plan9bootimage(ulong sects, ulong submagicvers, ulong tm,
180
	ulong hdrtxtsz, ulong textsz, ulong textva, ulong lcsize)
181
{
182
	lput(0x160L<<16|sects);		/* magic and sections */
183
	lput(tm);			/* time and date */
184
	lput(hdrtxtsz+datsize);		/* offset to symbol table */
185
	lput(symsize);			/* size of symbol table */
186
	lput((0x38L<<16)|7L);		/* size of optional hdr and flags */
187
	lput(submagicvers);		/* magic and version */
188
 
189
	lput(textsz);			/* segment sizes */
190
	lput(datsize);
191
	lput(bsssize);
192
 
193
	lput(entryvalue());		/* va of entry */
194
	lput(textva);			/* va of base of text */
195
	lput(INITDAT);			/* va of base of data */
196
	lput(INITDAT+datsize);		/* va of base of bss */
197
 
198
	lput(~0);			/* gp reg mask */
199
	lput(lcsize);			/* pcsize / cprmask[0] */
200
	lput(0);			/* coproc reg masks[1⋯3] */
201
	lput(0);
202
	lput(0);
203
	lput(~0);			/* gp value ?? */
204
}
205
 
206
static void
207
symhdrs(ulong hdrtxtsz)
208
{
209
	strnput(".text", 8);		/* text segment */
210
	lput(INITTEXT);			/* address */
211
	lput(INITTEXT);
212
	lput(textsize);
213
	lput(HEADR);
214
	lput(0);
215
	lput(HEADR+textsize+datsize+symsize);
216
	lput(lcsize);			/* line number size */
217
	lput(0x20);			/* flags */
218
 
219
	strnput(".data", 8);		/* data segment */
220
	lput(INITDAT);			/* address */
221
	lput(INITDAT);
222
	lput(datsize);
223
	lput(hdrtxtsz);
224
	lput(0);
225
	lput(0);
226
	lput(0);
227
	lput(0x40);			/* flags */
228
 
229
	strnput(".bss", 8);		/* bss segment */
230
	lput(INITDAT+datsize);		/* address */
231
	lput(INITDAT+datsize);
232
	lput(bsssize);
233
	lput(0);
234
	lput(0);
235
	lput(0);
236
	lput(0);
237
	lput(0x80);			/* flags */
238
}
239
 
240
void
241
asmb(void)
242
{
243
	Prog *p;
244
	long tm;
245
	ulong rndtxtsz;
246
	vlong t, etext;
247
	Optab *o;
248
 
249
	if(debug['v'])
250
		Bprint(&bso, "%5.2f asm\n", cputime());
251
	Bflush(&bso);
252
	OFFSET = HEADR;
253
	seek(cout, OFFSET, 0);
254
	pc = INITTEXT;
255
	for(p = firstp; p != P; p = p->link) {
256
		if(p->as == ATEXT) {
257
			curtext = p;
258
			autosize = p->to.offset + 4;
259
		}
260
		if(p->pc != pc) {
261
			diag("phase error %llux sb %llux", p->pc, pc);
262
			if(!debug['a'])
263
				prasm(curp);
264
			pc = p->pc;
265
		}
266
		curp = p;
267
		o = oplook(p);	/* could probably avoid this call */
268
		if(asmout(p, o, 0)) {
269
			p = p->link;
270
			pc += 4;
271
		}
272
		pc += o->size;
273
	}
274
	if(debug['a'])
275
		Bprint(&bso, "\n");
276
	Bflush(&bso);
277
	cflush();
278
 
279
	etext = INITTEXT + textsize;
280
	for(t = pc; t < etext; t += sizeof(buf)-100) {
281
		if(etext-t > sizeof(buf)-100)
282
			datblk(t, sizeof(buf)-100, 1);
283
		else
284
			datblk(t, etext-t, 1);
285
	}
286
 
287
	Bflush(&bso);
288
	cflush();
289
 
290
	curtext = P;
291
	switch(HEADTYPE) {
292
	case 0:
293
	case 4:
294
		OFFSET = rnd(HEADR+textsize, 4096);
295
		seek(cout, OFFSET, 0);
296
		break;
297
	case 1:
298
	case 2:
299
	case 3:
300
	case 5:
301
	case 6:
302
	case 7:
303
		OFFSET = HEADR+textsize;
304
		seek(cout, OFFSET, 0);
305
		break;
306
	}
307
	for(t = 0; t < datsize; t += sizeof(buf)-100) {
308
		if(datsize-t > sizeof(buf)-100)
309
			datblk(t, sizeof(buf)-100, 0);
310
		else
311
			datblk(t, datsize-t, 0);
312
	}
313
 
314
	symsize = 0;
315
	lcsize = 0;
316
	if(!debug['s']) {
317
		if(debug['v'])
318
			Bprint(&bso, "%5.2f sym\n", cputime());
319
		Bflush(&bso);
320
		switch(HEADTYPE) {
321
		case 0:
322
		case 4:
323
			OFFSET = rnd(HEADR+textsize, 4096)+datsize;
324
			seek(cout, OFFSET, 0);
325
			break;
326
		case 3:
327
		case 2:
328
		case 1:
329
		case 5:
330
		case 6:
331
		case 7:
332
			OFFSET = HEADR+textsize+datsize;
333
			seek(cout, OFFSET, 0);
334
			break;
335
		}
336
		if(!debug['s'])
337
			asmsym();
338
		if(debug['v'])
339
			Bprint(&bso, "%5.2f pc\n", cputime());
340
		Bflush(&bso);
341
		if(!debug['s'])
342
			asmlc();
343
		cflush();
344
	}
345
 
346
	if(debug['v'])
347
		Bprint(&bso, "%5.2f header\n", cputime());
348
	Bflush(&bso);
349
	OFFSET = 0;
350
	seek(cout, OFFSET, 0);
351
 
352
	rndtxtsz = rnd(HEADR+textsize, (INITRND > 0? INITRND: 4096));
353
	tm = time(0);
354
	switch(HEADTYPE) {
355
	case 0:
356
		/* 0413: plan 9 boot image, text segment rounded (to 4KB) */
357
		plan9bootimage(0, 0413<<16|0437, 0, rndtxtsz, rndtxtsz,
358
			INITTEXT-HEADR, 0);
359
		break;
360
	case 1:
361
		/* 0407: plan 9 boot image, extra word */
362
		plan9bootimage(0, 0407<<16|0437, 0, HEADR+textsize, textsize,
363
			INITTEXT, lcsize);
364
		lput(0);			/* extra; complete mystery */
365
		break;
366
	case 2:					/* plan 9 format */
367
		if (little)
368
			lput(P_MAGIC);		/* mips 3000 LE */
369
		else
370
			lput(V_MAGIC);		/* mips 3000 BE */
371
		lput(textsize);			/* sizes */
372
		lput(datsize);
373
		lput(bsssize);
374
		lput(symsize);			/* nsyms */
375
		lput(entryvalue());		/* va of entry */
376
		lput(0L);
377
		lput(lcsize);
378
		break;
379
	case 3:
380
		/* 0407: plan 9 mips 4k boot image with symbols */
381
		plan9bootimage(3, 0407<<16|0437, tm, HEADR+textsize, textsize,
382
			INITTEXT, lcsize);
383
		symhdrs(HEADR+textsize);
384
		break;
385
	case 4:
386
		/* 0413: plan 9 mips 4k boot image with symbols */
387
		plan9bootimage(3, 0413<<16|01012, tm, rndtxtsz, textsize,
388
			INITTEXT, lcsize);
389
		symhdrs(rndtxtsz);
390
		break;
391
	case 5:
392
		elf32(MIPS, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
393
		break;
394
	case 6:
395
		break;
396
	case 7:
397
		elf64(MIPSR4K, little? ELFDATA2LSB: ELFDATA2MSB, 0, nil);
398
		break;
399
	}
400
	cflush();
401
}
402
 
403
void
404
strnput(char *s, int n)
405
{
406
	for(; *s; s++){
407
		CPUT(*s);
408
		n--;
409
	}
410
	for(; n > 0; n--)
411
		CPUT(0);
412
}
413
 
414
void
415
cflush(void)
416
{
417
	int n;
418
 
419
	n = sizeof(buf.cbuf) - cbc;
420
	if(n)
421
		write(cout, buf.cbuf, n);
422
	cbp = buf.cbuf;
423
	cbc = sizeof(buf.cbuf);
424
}
425
 
426
void
427
nopstat(char *f, Count *c)
428
{
429
	if(c->outof)
430
	Bprint(&bso, "%s delay %ld/%ld (%.2f)\n", f,
431
		c->outof - c->count, c->outof,
432
		(double)(c->outof - c->count)/c->outof);
433
}
434
 
435
void
436
asmsym(void)
437
{
438
	Prog *p;
439
	Auto *a;
440
	Sym *s;
441
	int h;
442
 
443
	s = lookup("etext", 0);
444
	if(s->type == STEXT)
445
		putsymb(s->name, 'T', s->value, s->version);
446
 
447
	for(h=0; h<NHASH; h++)
448
		for(s=hash[h]; s!=S; s=s->link)
449
			switch(s->type) {
450
			case SCONST:
451
				putsymb(s->name, 'D', s->value, s->version);
452
				continue;
453
 
454
			case SSTRING:
455
				putsymb(s->name, 'T', s->value, s->version);
456
				continue;
457
 
458
			case SDATA:
459
				putsymb(s->name, 'D', s->value+INITDAT, s->version);
460
				continue;
461
 
462
			case SBSS:
463
				putsymb(s->name, 'B', s->value+INITDAT, s->version);
464
				continue;
465
 
466
			case SFILE:
467
				putsymb(s->name, 'f', s->value, s->version);
468
				continue;
469
			}
470
 
471
	for(p=textp; p!=P; p=p->cond) {
472
		s = p->from.sym;
473
		if(s->type != STEXT && s->type != SLEAF)
474
			continue;
475
 
476
		/* filenames first */
477
		for(a=p->to.autom; a; a=a->link)
478
			if(a->type == D_FILE)
479
				putsymb(a->asym->name, 'z', a->aoffset, 0);
480
			else
481
			if(a->type == D_FILE1)
482
				putsymb(a->asym->name, 'Z', a->aoffset, 0);
483
 
484
		if(s->type == STEXT)
485
			putsymb(s->name, 'T', s->value, s->version);
486
		else
487
			putsymb(s->name, 'L', s->value, s->version);
488
 
489
		/* frame, auto and param after */
490
		putsymb(".frame", 'm', p->to.offset+4, 0);
491
		for(a=p->to.autom; a; a=a->link)
492
			if(a->type == D_AUTO)
493
				putsymb(a->asym->name, 'a', -a->aoffset, 0);
494
			else
495
			if(a->type == D_PARAM)
496
				putsymb(a->asym->name, 'p', a->aoffset, 0);
497
	}
498
	if(debug['v'] || debug['n'])
499
		Bprint(&bso, "symsize = %lud\n", symsize);
500
	Bflush(&bso);
501
}
502
 
503
void
504
putsymb(char *s, int t, long v, int ver)
505
{
506
	int i, f;
507
 
508
	if(t == 'f')
509
		s++;
510
	LBEPUT(v);
511
	if(ver)
512
		t += 'a' - 'A';
513
	CPUT(t+0x80);			/* 0x80 is variable length */
514
 
515
	if(t == 'Z' || t == 'z') {
516
		CPUT(s[0]);
517
		for(i=1; s[i] != 0 || s[i+1] != 0; i += 2) {
518
			CPUT(s[i]);
519
			CPUT(s[i+1]);
520
		}
521
		CPUT(0);
522
		CPUT(0);
523
		i++;
524
	}
525
	else {
526
		for(i=0; s[i]; i++)
527
			CPUT(s[i]);
528
		CPUT(0);
529
	}
530
	symsize += 4 + 1 + i + 1;
531
 
532
	if(debug['n']) {
533
		if(t == 'z' || t == 'Z') {
534
			Bprint(&bso, "%c %.8lux ", t, v);
535
			for(i=1; s[i] != 0 || s[i+1] != 0; i+=2) {
536
				f = ((s[i]&0xff) << 8) | (s[i+1]&0xff);
537
				Bprint(&bso, "/%x", f);
538
			}
539
			Bprint(&bso, "\n");
540
			return;
541
		}
542
		if(ver)
543
			Bprint(&bso, "%c %.8lux %s<%d>\n", t, v, s, ver);
544
		else
545
			Bprint(&bso, "%c %.8lux %s\n", t, v, s);
546
	}
547
}
548
 
549
#define	MINLC	4
550
void
551
asmlc(void)
552
{
553
	long oldlc, v, s;
554
	vlong oldpc;
555
	Prog *p;
556
 
557
	oldpc = INITTEXT;
558
	oldlc = 0;
559
	for(p = firstp; p != P; p = p->link) {
560
		if(p->line == oldlc || p->as == ATEXT || p->as == ANOP) {
561
			if(p->as == ATEXT)
562
				curtext = p;
563
			if(debug['V'])
564
				Bprint(&bso, "%6llux %P\n", p->pc, p);
565
			continue;
566
		}
567
		if(debug['V'])
568
			Bprint(&bso, "\t\t%6ld", lcsize);
569
		v = (p->pc - oldpc) / MINLC;
570
		while(v) {
571
			s = 127;
572
			if(v < 127)
573
				s = v;
574
			CPUT(s+128);	/* 129-255 +pc */
575
			if(debug['V'])
576
				Bprint(&bso, " pc+%ld*%d(%ld)", s, MINLC, s+128);
577
			v -= s;
578
			lcsize++;
579
		}
580
		s = p->line - oldlc;
581
		oldlc = p->line;
582
		oldpc = p->pc + MINLC;
583
		if(s > 64 || s < -64) {
584
			CPUT(0);	/* 0 vv +lc */
585
			CPUT(s>>24);
586
			CPUT(s>>16);
587
			CPUT(s>>8);
588
			CPUT(s);
589
			if(debug['V']) {
590
				if(s > 0)
591
					Bprint(&bso, " lc+%ld(%d,%ld)\n",
592
						s, 0, s);
593
				else
594
					Bprint(&bso, " lc%ld(%d,%ld)\n",
595
						s, 0, s);
596
				Bprint(&bso, "%6llux %P\n", p->pc, p);
597
			}
598
			lcsize += 5;
599
			continue;
600
		}
601
		if(s > 0) {
602
			CPUT(0+s);	/* 1-64 +lc */
603
			if(debug['V']) {
604
				Bprint(&bso, " lc+%ld(%ld)\n", s, 0+s);
605
				Bprint(&bso, "%6llux %P\n", p->pc, p);
606
			}
607
		} else {
608
			CPUT(64-s);	/* 65-128 -lc */
609
			if(debug['V']) {
610
				Bprint(&bso, " lc%ld(%ld)\n", s, 64-s);
611
				Bprint(&bso, "%6llux %P\n", p->pc, p);
612
			}
613
		}
614
		lcsize++;
615
	}
616
	while(lcsize & 1) {
617
		s = 129;
618
		CPUT(s);
619
		lcsize++;
620
	}
621
	if(debug['v'] || debug['V'])
622
		Bprint(&bso, "lcsize = %ld\n", lcsize);
623
	Bflush(&bso);
624
}
625
 
626
void
627
datblk(long s, long n, int str)
628
{
629
	Prog *p;
630
	char *cast;
631
	long l, fl, j, d;
632
	int i, c;
633
 
634
	memset(buf.dbuf, 0, n+100);
635
	for(p = datap; p != P; p = p->link) {
636
		curp = p;
637
		if(str != (p->from.sym->type == SSTRING))
638
			continue;
639
		l = p->from.sym->value + p->from.offset - s;
640
		c = p->reg;
641
		i = 0;
642
		if(l < 0) {
643
			if(l+c <= 0)
644
				continue;
645
			while(l < 0) {
646
				l++;
647
				i++;
648
			}
649
		}
650
		if(l >= n)
651
			continue;
652
		if(p->as != AINIT && p->as != ADYNT) {
653
			for(j=l+(c-i)-1; j>=l; j--)
654
				if(buf.dbuf[j]) {
655
					print("%P\n", p);
656
					diag("multiple initialization");
657
					break;
658
				}
659
		}
660
		switch(p->to.type) {
661
		default:
662
			diag("unknown mode in initialization\n%P", p);
663
			break;
664
 
665
		case D_FCONST:
666
			switch(c) {
667
			default:
668
			case 4:
669
				fl = ieeedtof(p->to.ieee);
670
				cast = (char*)&fl;
671
				for(; i<c; i++) {
672
					buf.dbuf[l] = cast[fnuxi8[i+4]];
673
					l++;
674
				}
675
				break;
676
			case 8:
677
				cast = (char*)p->to.ieee;
678
				for(; i<c; i++) {
679
					buf.dbuf[l] = cast[fnuxi8[i]];
680
					l++;
681
				}
682
				break;
683
			}
684
			break;
685
 
686
		case D_SCONST:
687
			for(; i<c; i++) {
688
				buf.dbuf[l] = p->to.sval[i];
689
				l++;
690
			}
691
			break;
692
 
693
		case D_CONST:
694
			d = p->to.offset;
695
			if(p->to.sym) {
696
				switch(p->to.sym->type) {
697
				case STEXT:
698
				case SLEAF:
699
				case SSTRING:
700
					d += p->to.sym->value;
701
					break;
702
				case SDATA:
703
				case SBSS:
704
					d += p->to.sym->value + INITDAT;
705
					break;
706
				}
707
			}
708
			cast = (char*)&d;
709
			switch(c) {
710
			default:
711
				diag("bad nuxi %d %d\n%P", c, i, curp);
712
				break;
713
			case 1:
714
				for(; i<c; i++) {
715
					buf.dbuf[l] = cast[inuxi1[i]];
716
					l++;
717
				}
718
				break;
719
			case 2:
720
				for(; i<c; i++) {
721
					buf.dbuf[l] = cast[inuxi2[i]];
722
					l++;
723
				}
724
				break;
725
			case 4:
726
				for(; i<c; i++) {
727
					buf.dbuf[l] = cast[inuxi4[i]];
728
					l++;
729
				}
730
				break;
731
			}
732
			break;
733
		}
734
	}
735
	write(cout, buf.dbuf, n);
736
}
737
 
738
#define	OP_RRR(op,r1,r2,r3)\
739
	(op|(((r1)&31L)<<16)|(((r2)&31L)<<21)|(((r3)&31L)<<11))
740
#define	OP_IRR(op,i,r2,r3)\
741
	(op|((i)&0xffffL)|(((r2)&31L)<<21)|(((r3)&31L)<<16))
742
#define	OP_SRR(op,s,r2,r3)\
743
	(op|(((s)&31L)<<6)|(((r2)&31L)<<16)|(((r3)&31L)<<11))
744
#define	OP_FRRR(op,r1,r2,r3)\
745
	(op|(((r1)&31L)<<16)|(((r2)&31L)<<11)|(((r3)&31L)<<6))
746
#define	OP_JMP(op,i)\
747
		((op)|((i)&0x3ffffffL))
748
 
749
#define	OP(x,y)\
750
	(((x)<<3)|((y)<<0))
751
#define	SP(x,y)\
752
	(((x)<<29)|((y)<<26))
753
#define	BCOND(x,y)\
754
	(((x)<<19)|((y)<<16))
755
#define	MMU(x,y)\
756
	(SP(2,0)|(16<<21)|((x)<<3)|((y)<<0))
757
#define	FPF(x,y)\
758
	(SP(2,1)|(16<<21)|((x)<<3)|((y)<<0))
759
#define	FPD(x,y)\
760
	(SP(2,1)|(17<<21)|((x)<<3)|((y)<<0))
761
#define	FPW(x,y)\
762
	(SP(2,1)|(20<<21)|((x)<<3)|((y)<<0))
763
 
764
int vshift(int);
765
 
766
int
767
asmout(Prog *p, Optab *o, int aflag)
768
{
769
	long o1, o2, o3, o4, o5, o6, o7, v;
770
	Prog *ct;
771
	int r, a;
772
 
773
	o1 = 0;
774
	o2 = 0;
775
	o3 = 0;
776
	o4 = 0;
777
	o5 = 0;
778
	o6 = 0;
779
	o7 = 0;
780
	switch(o->type) {
781
	default:
782
		diag("unknown type %d", o->type);
783
		if(!debug['a'])
784
			prasm(p);
785
		break;
786
 
787
	case 0:		/* pseudo ops */
788
		if(aflag) {
789
			if(p->link) {
790
				if(p->as == ATEXT) {
791
					ct = curtext;
792
					o2 = autosize;
793
					curtext = p;
794
					autosize = p->to.offset + 4;
795
					o1 = asmout(p->link, oplook(p->link), aflag);
796
					curtext = ct;
797
					autosize = o2;
798
				} else
799
					o1 = asmout(p->link, oplook(p->link), aflag);
800
			}
801
			return o1;
802
		}
803
		break;
804
 
805
	case 1:		/* mov[v] r1,r2 ==> OR r1,r0,r2 */
806
		o1 = OP_RRR(oprrr(AOR), p->from.reg, REGZERO, p->to.reg);
807
		break;
808
 
809
	case 2:		/* add/sub r1,[r2],r3 */
810
		r = p->reg;
811
		if(r == NREG)
812
			r = p->to.reg;
813
		o1 = OP_RRR(oprrr(p->as), p->from.reg, r, p->to.reg);
814
		break;
815
 
816
	case 3:		/* mov $soreg, r ==> or/add $i,o,r */
817
		v = regoff(&p->from);
818
		r = p->from.reg;
819
		if(r == NREG)
820
			r = o->param;
821
		a = AADDU;
822
		if(o->a1 == C_ANDCON)
823
			a = AOR;
824
		o1 = OP_IRR(opirr(a), v, r, p->to.reg);
825
		break;
826
 
827
	case 4:		/* add $scon,[r1],r2 */
828
		v = regoff(&p->from);
829
		r = p->reg;
830
		if(r == NREG)
831
			r = p->to.reg;
832
		o1 = OP_IRR(opirr(p->as), v, r, p->to.reg);
833
		break;
834
 
835
	case 5:		/* syscall */
836
		if(aflag)
837
			return 0;
838
		o1 = oprrr(p->as);
839
		break;
840
 
841
	case 6:		/* beq r1,[r2],sbra */
842
		if(aflag)
843
			return 0;
844
		if(p->cond == P)
845
			v = -4 >> 2;
846
		else
847
			v = (p->cond->pc - pc-4) >> 2;
848
		if(((v << 16) >> 16) != v)
849
			diag("short branch too far: %ld\n%P", v, p);
850
		o1 = OP_IRR(opirr(p->as), v, p->from.reg, p->reg);
851
		break;
852
 
853
	case 7:		/* mov r, soreg ==> sw o(r) */
854
		r = p->to.reg;
855
		if(r == NREG)
856
			r = o->param;
857
		v = regoff(&p->to);
858
		o1 = OP_IRR(opirr(p->as), v, r, p->from.reg);
859
		break;
860
 
861
	case 8:		/* mov soreg, r ==> lw o(r) */
862
		r = p->from.reg;
863
		if(r == NREG)
864
			r = o->param;
865
		v = regoff(&p->from);
866
		o1 = OP_IRR(opirr(p->as+ALAST), v, r, p->to.reg);
867
		break;
868
 
869
	case 9:		/* asl r1,[r2],r3 */
870
		r = p->reg;
871
		if(r == NREG)
872
			r = p->to.reg;
873
		o1 = OP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg);
874
		break;
875
 
876
	case 10:	/* add $con,[r1],r2 ==> mov $con,t; add t,[r1],r2 */
877
		v = regoff(&p->from);
878
		r = AOR;
879
		if(v < 0)
880
			r = AADDU;
881
		o1 = OP_IRR(opirr(r), v, 0, REGTMP);
882
		r = p->reg;
883
		if(r == NREG)
884
			r = p->to.reg;
885
		o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
886
		break;
887
 
888
	case 11:	/* jmp lbra */
889
		if(aflag)
890
			return 0;
891
		if(p->cond == P)
892
			v = p->pc >> 2;
893
		else
894
			v = p->cond->pc >> 2;
895
		o1 = OP_JMP(opirr(p->as), v);
896
		if(!debug['Y'] && p->link && p->cond && isnop(p->link)) {
897
			nop.branch.count--;
898
			nop.branch.outof--;
899
			nop.jump.outof++;
900
			o2 = asmout(p->cond, oplook(p->cond), 1);
901
			if(o2) {
902
				o1 += 1;
903
				if(debug['a'])
904
					Bprint(&bso, " %.8llux: %.8lux %.8lux%P\n",
905
						p->pc, o1, o2, p);
906
				LPUT(o1);
907
				LPUT(o2);
908
				return 1;
909
			}
910
		}
911
		break;
912
 
913
	case 12:	/* movbs r,r */
914
		v = 16;
915
		if(p->as == AMOVB)
916
			v = 24;
917
		o1 = OP_SRR(opirr(ASLL), v, p->from.reg, p->to.reg);
918
		o2 = OP_SRR(opirr(ASRA), v, p->to.reg, p->to.reg);
919
		break;
920
 
921
	case 13:	/* movbu r,r */
922
		if(p->as == AMOVBU)
923
			o1 = OP_IRR(opirr(AAND), 0xffL, p->from.reg, p->to.reg);
924
		else
925
			o1 = OP_IRR(opirr(AAND), 0xffffL, p->from.reg, p->to.reg);
926
		break;
927
 
928
	case 16:	/* sll $c,[r1],r2 */
929
		v = regoff(&p->from);
930
		r = p->reg;
931
		if(r == NREG)
932
			r = p->to.reg;
933
 
934
		/* OP_SRR will use only the low 5 bits of the shift value */
935
		if(v >= 32 && vshift(p->as))
936
			o1 = OP_SRR(opirr(p->as+ALAST), v-32, r, p->to.reg);
937
		else 
938
			o1 = OP_SRR(opirr(p->as), v, r, p->to.reg);
939
		break;
940
 
941
	case 18:	/* jmp [r1],0(r2) */
942
		if(aflag)
943
			return 0;
944
		r = p->reg;
945
		if(r == NREG)
946
			r = o->param;
947
		o1 = OP_RRR(oprrr(p->as), 0, p->to.reg, r);
948
		break;
949
 
950
	case 19:	/* mov $lcon,r ==> lu+or */
951
		v = regoff(&p->from);
952
		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
953
		o2 = OP_IRR(opirr(AOR), v, p->to.reg, p->to.reg);
954
		break;
955
 
956
	case 20:	/* mov lohi,r */
957
		r = OP(2,0);		/* mfhi */
958
		if(p->from.type == D_LO)
959
			r = OP(2,2);	/* mflo */
960
		o1 = OP_RRR(r, REGZERO, REGZERO, p->to.reg);
961
		break;
962
 
963
	case 21:	/* mov r,lohi */
964
		r = OP(2,1);		/* mthi */
965
		if(p->to.type == D_LO)
966
			r = OP(2,3);	/* mtlo */
967
		o1 = OP_RRR(r, REGZERO, p->from.reg, REGZERO);
968
		break;
969
 
970
	case 22:	/* mul r1,r2 */
971
		o1 = OP_RRR(oprrr(p->as), p->from.reg, p->reg, REGZERO);
972
		break;
973
 
974
	case 23:	/* add $lcon,r1,r2 ==> lu+or+add */
975
		v = regoff(&p->from);
976
		if(p->to.reg == REGTMP || p->reg == REGTMP)
977
			diag("cant synthesize large constant\n%P", p);
978
		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
979
		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
980
		r = p->reg;
981
		if(r == NREG)
982
			r = p->to.reg;
983
		o3 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
984
		break;
985
 
986
	case 24:	/* mov $ucon,,r ==> lu r */
987
		v = regoff(&p->from);
988
		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, p->to.reg);
989
		break;
990
 
991
	case 25:	/* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
992
		v = regoff(&p->from);
993
		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
994
		r = p->reg;
995
		if(r == NREG)
996
			r = p->to.reg;
997
		o2 = OP_RRR(oprrr(p->as), REGTMP, r, p->to.reg);
998
		break;
999
 
1000
	case 26:	/* mov $lsext/auto/oreg,,r2 ==> lu+or+add */
1001
		v = regoff(&p->from);
1002
		if(p->to.reg == REGTMP)
1003
			diag("cant synthesize large constant\n%P", p);
1004
		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1005
		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1006
		r = p->from.reg;
1007
		if(r == NREG)
1008
			r = o->param;
1009
		o3 = OP_RRR(oprrr(AADDU), REGTMP, r, p->to.reg);
1010
		break;
1011
 
1012
	case 27:		/* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
1013
		r = p->from.reg;
1014
		if(r == NREG)
1015
			r = o->param;
1016
		v = regoff(&p->from);
1017
		switch(o->size) {
1018
		case 20:
1019
			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1020
			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1021
			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1022
			o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg+1);
1023
			o5 = OP_IRR(opirr(AMOVF+ALAST), 4, REGTMP, p->to.reg);
1024
			break;
1025
		case 16:
1026
			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1027
			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1028
			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1029
			o4 = OP_IRR(opirr(AMOVF+ALAST), 0, REGTMP, p->to.reg);
1030
			break;
1031
		case 8:
1032
			o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg+1);
1033
			o2 = OP_IRR(opirr(AMOVF+ALAST), v+4, r, p->to.reg);
1034
			break;
1035
		case 4:
1036
			o1 = OP_IRR(opirr(AMOVF+ALAST), v, r, p->to.reg);
1037
			break;
1038
		}
1039
		break;
1040
 
1041
	case 28:		/* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
1042
		r = p->to.reg;
1043
		if(r == NREG)
1044
			r = o->param;
1045
		v = regoff(&p->to);
1046
		switch(o->size) {
1047
		case 20:
1048
			if(r == REGTMP)
1049
				diag("cant synthesize large constant\n%P", p);
1050
			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1051
			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1052
			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1053
			o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg+1);
1054
			o5 = OP_IRR(opirr(AMOVF), 4, REGTMP, p->from.reg);
1055
			break;
1056
		case 16:
1057
			if(r == REGTMP)
1058
				diag("cant synthesize large constant\n%P", p);
1059
			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1060
			o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1061
			o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1062
			o4 = OP_IRR(opirr(AMOVF), 0, REGTMP, p->from.reg);
1063
			break;
1064
		case 8:
1065
			o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg+1);
1066
			o2 = OP_IRR(opirr(AMOVF), v+4, r, p->from.reg);
1067
			break;
1068
		case 4:
1069
			o1 = OP_IRR(opirr(AMOVF), v, r, p->from.reg);
1070
			break;
1071
		}
1072
		break;
1073
 
1074
	case 30:	/* movw r,fr */
1075
		r = SP(2,1)|(4<<21);		/* mtc1 */
1076
		o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
1077
		break;
1078
 
1079
	case 31:	/* movw fr,r */
1080
		r = SP(2,1)|(0<<21);		/* mfc1 */
1081
		o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
1082
		break;
1083
 
1084
	case 32:	/* fadd fr1,[fr2],fr3 */
1085
		r = p->reg;
1086
		if(r == NREG)
1087
			o1 = OP_FRRR(oprrr(p->as), p->from.reg, p->to.reg, p->to.reg);
1088
		else
1089
			o1 = OP_FRRR(oprrr(p->as), p->from.reg, r, p->to.reg);
1090
		break;
1091
 
1092
	case 33:	/* fabs fr1,fr3 */
1093
		o1 = OP_FRRR(oprrr(p->as), 0, p->from.reg, p->to.reg);
1094
		break;
1095
 
1096
	case 34:	/* mov $con,fr ==> or/add $i,r,r2 */
1097
		v = regoff(&p->from);
1098
		r = AADDU;
1099
		if(o->a1 == C_ANDCON)
1100
			r = AOR;
1101
		o1 = OP_IRR(opirr(r), v, 0, REGTMP);
1102
		o2 = OP_RRR(SP(2,1)|(4<<21), REGTMP, 0, p->to.reg);	/* mtc1 */
1103
		break;
1104
 
1105
	case 35:	/* mov r,lext/luto/oreg ==> sw o(r) */
1106
		/*
1107
		 * the lowbits of the constant cannot
1108
		 * be moved into the offset of the load
1109
		 * because the mips 4000 in 64-bit mode
1110
		 * does a 64-bit add and it will screw up.
1111
		 */
1112
		v = regoff(&p->to);
1113
		r = p->to.reg;
1114
		if(r == NREG)
1115
			r = o->param;
1116
		if(r == REGTMP)
1117
			diag("cant synthesize large constant\n%P", p);
1118
		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1119
		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1120
		o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1121
		o4 = OP_IRR(opirr(p->as), 0, REGTMP, p->from.reg);
1122
		break;
1123
 
1124
	case 36:	/* mov lext/lauto/lreg,r ==> lw o(r30) */
1125
		v = regoff(&p->from);
1126
		r = p->from.reg;
1127
		if(r == NREG)
1128
			r = o->param;
1129
		if(r == REGTMP)
1130
			diag("cant synthesize large constant\n%P", p);
1131
		o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1132
		o2 = OP_IRR(opirr(AOR), v, REGTMP, REGTMP);
1133
		o3 = OP_RRR(oprrr(AADDU), r, REGTMP, REGTMP);
1134
		o4 = OP_IRR(opirr(p->as+ALAST), 0, REGTMP, p->to.reg);
1135
		break;
1136
 
1137
	case 37:	/* movw r,mr */
1138
		r = SP(2,0)|(4<<21);		/* mtc0 */
1139
		if(p->as == AMOVV)
1140
			r = SP(2,0)|(5<<21);	/* dmtc0 */
1141
		o1 = OP_RRR(r, p->from.reg, 0, p->to.reg);
1142
		break;
1143
 
1144
	case 38:	/* movw mr,r */
1145
		r = SP(2,0)|(0<<21);		/* mfc0 */
1146
		if(p->as == AMOVV)
1147
			r = SP(2,0)|(1<<21);	/* dmfc0 */
1148
		o1 = OP_RRR(r, p->to.reg, 0, p->from.reg);
1149
		break;
1150
 
1151
	case 39:	/* rfe ==> jmp+rfe */
1152
		if(aflag)
1153
			return 0;
1154
		o1 = OP_RRR(oprrr(AJMP), 0, p->to.reg, REGZERO);
1155
		o2 = oprrr(p->as);
1156
		break;
1157
 
1158
	case 40:	/* word */
1159
		if(aflag)
1160
			return 0;
1161
		o1 = regoff(&p->to);
1162
		break;
1163
 
1164
	case 41:	/* movw r,fcr */
1165
		o1 = OP_RRR(SP(2,1)|(2<<21), REGZERO, 0, p->to.reg); 	/* mfcc1 */
1166
		o2 = OP_RRR(SP(2,1)|(6<<21), p->from.reg, 0, p->to.reg);/* mtcc1 */
1167
		break;
1168
 
1169
	case 42:	/* movw fcr,r */
1170
		o1 = OP_RRR(SP(2,1)|(2<<21), p->to.reg, 0, p->from.reg);/* mfcc1 */
1171
		break;
1172
 
1173
	case 45:	/* case r */
1174
		if(p->link == P)
1175
			v = p->pc+28;
1176
		else
1177
			v = p->link->pc;
1178
		if(v & (1<<15))
1179
			o1 = OP_IRR(opirr(ALAST), (v>>16)+1, REGZERO, REGTMP);
1180
		else
1181
			o1 = OP_IRR(opirr(ALAST), v>>16, REGZERO, REGTMP);
1182
		o2 = OP_SRR(opirr(ASLL), 2, p->from.reg, p->from.reg);
1183
		o3 = OP_RRR(oprrr(AADD), p->from.reg, REGTMP, REGTMP);
1184
		o4 = OP_IRR(opirr(AMOVW+ALAST), v, REGTMP, REGTMP);
1185
		o5 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
1186
		o6 = OP_RRR(oprrr(AJMP), 0, REGTMP, REGZERO);
1187
		o7 = OP_RRR(oprrr(ANOR), REGZERO, REGZERO, REGZERO);
1188
		break;
1189
 
1190
	case 46:	/* bcase $con,lbra */
1191
		if(p->cond == P)
1192
			v = p->pc;
1193
		else
1194
			v = p->cond->pc;
1195
		o1 = v;
1196
		break;
1197
	}
1198
	if(aflag)
1199
		return o1;
1200
	v = p->pc;
1201
	switch(o->size) {
1202
	default:
1203
		if(debug['a'])
1204
			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
1205
		break;
1206
	case 4:
1207
		if(debug['a'])
1208
			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
1209
		LPUT(o1);
1210
		break;
1211
	case 8:
1212
		if(debug['a'])
1213
			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
1214
		LPUT(o1);
1215
		LPUT(o2);
1216
		break;
1217
	case 12:
1218
		if(debug['a'])
1219
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
1220
		LPUT(o1);
1221
		LPUT(o2);
1222
		LPUT(o3);
1223
		break;
1224
	case 16:
1225
		if(debug['a'])
1226
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
1227
				v, o1, o2, o3, o4, p);
1228
		LPUT(o1);
1229
		LPUT(o2);
1230
		LPUT(o3);
1231
		LPUT(o4);
1232
		break;
1233
	case 20:
1234
		if(debug['a'])
1235
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1236
				v, o1, o2, o3, o4, o5, p);
1237
		LPUT(o1);
1238
		LPUT(o2);
1239
		LPUT(o3);
1240
		LPUT(o4);
1241
		LPUT(o5);
1242
		break;
1243
 
1244
	case 28:
1245
		if(debug['a'])
1246
			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
1247
				v, o1, o2, o3, o4, o5, o6, o7, p);
1248
		LPUT(o1);
1249
		LPUT(o2);
1250
		LPUT(o3);
1251
		LPUT(o4);
1252
		LPUT(o5);
1253
		LPUT(o6);
1254
		LPUT(o7);
1255
		break;
1256
	}
1257
	return 0;
1258
}
1259
 
1260
int
1261
isnop(Prog *p)
1262
{
1263
	if(p->as != ANOR)
1264
		return 0;
1265
	if(p->reg != REGZERO && p->reg != NREG)
1266
		return 0;
1267
	if(p->from.type != D_REG || p->from.reg != REGZERO)
1268
		return 0;
1269
	if(p->to.type != D_REG || p->to.reg != REGZERO)
1270
		return 0;
1271
	return 1;
1272
}
1273
 
1274
long
1275
oprrr(int a)
1276
{
1277
	switch(a) {
1278
	case AADD:	return OP(4,0);
1279
	case AADDU:	return OP(4,1);
1280
	case ASGT:	return OP(5,2);
1281
	case ASGTU:	return OP(5,3);
1282
	case AAND:	return OP(4,4);
1283
	case AOR:	return OP(4,5);
1284
	case AXOR:	return OP(4,6);
1285
	case ASUB:	return OP(4,2);
1286
	case ASUBU:	return OP(4,3);
1287
	case ANOR:	return OP(4,7);
1288
	case ASLL:	return OP(0,4);
1289
	case ASRL:	return OP(0,6);
1290
	case ASRA:	return OP(0,7);
1291
 
1292
	case AREM:
1293
	case ADIV:	return OP(3,2);
1294
	case AREMU:
1295
	case ADIVU:	return OP(3,3);
1296
	case AMUL:	return OP(3,0);
1297
	case AMULU:	return OP(3,1);
1298
 
1299
	case AJMP:	return OP(1,0);
1300
	case AJAL:	return OP(1,1);
1301
 
1302
	case ABREAK:	return OP(1,5);
1303
	case ASYSCALL:	return OP(1,4);
1304
	case ATLBP:	return MMU(1,0);
1305
	case ATLBR:	return MMU(0,1);
1306
	case ATLBWI:	return MMU(0,2);
1307
	case ATLBWR:	return MMU(0,6);
1308
	case ARFE:	return MMU(2,0);
1309
 
1310
	case ADIVF:	return FPF(0,3);
1311
	case ADIVD:	return FPD(0,3);
1312
	case AMULF:	return FPF(0,2);
1313
	case AMULD:	return FPD(0,2);
1314
	case ASUBF:	return FPF(0,1);
1315
	case ASUBD:	return FPD(0,1);
1316
	case AADDF:	return FPF(0,0);
1317
	case AADDD:	return FPD(0,0);
1318
 
1319
	case AMOVFW:	return FPF(4,4);
1320
	case AMOVDW:	return FPD(4,4);
1321
	case AMOVWF:	return FPW(4,0);
1322
	case AMOVDF:	return FPD(4,0);
1323
	case AMOVWD:	return FPW(4,1);
1324
	case AMOVFD:	return FPF(4,1);
1325
	case AABSF:	return FPF(0,5);
1326
	case AABSD:	return FPD(0,5);
1327
	case AMOVF:	return FPF(0,6);
1328
	case AMOVD:	return FPD(0,6);
1329
	case ANEGF:	return FPF(0,7);
1330
	case ANEGD:	return FPD(0,7);
1331
 
1332
	case ACMPEQF:	return FPF(6,2);
1333
	case ACMPEQD:	return FPD(6,2);
1334
	case ACMPGTF:	return FPF(7,4);
1335
	case ACMPGTD:	return FPD(7,4);
1336
	case ACMPGEF:	return FPF(7,6);
1337
	case ACMPGED:	return FPD(7,6);
1338
 
1339
	case ADIVV:	return OP(3,6);
1340
	case ADIVVU:	return OP(3,7);
1341
	case AADDV:	return OP(5,4);
1342
	case AADDVU:	return OP(5,5);
1343
	}
1344
	diag("bad rrr %d", a);
1345
	return 0;
1346
}
1347
 
1348
long
1349
opirr(int a)
1350
{
1351
	switch(a) {
1352
	case AADD:	return SP(1,0);
1353
	case AADDU:	return SP(1,1);
1354
	case ASGT:	return SP(1,2);
1355
	case ASGTU:	return SP(1,3);
1356
	case AAND:	return SP(1,4);
1357
	case AOR:	return SP(1,5);
1358
	case AXOR:	return SP(1,6);
1359
	case ALAST:	return SP(1,7);
1360
	case ASLL:	return OP(0,0);
1361
	case ASRL:	return OP(0,2);
1362
	case ASRA:	return OP(0,3);
1363
 
1364
	case AJMP:	return SP(0,2);
1365
	case AJAL:	return SP(0,3);
1366
	case ABEQ:	return SP(0,4);
1367
	case ABNE:	return SP(0,5);
1368
 
1369
	case ABGEZ:	return SP(0,1)|BCOND(0,1);
1370
	case ABGEZAL:	return SP(0,1)|BCOND(2,1);
1371
	case ABGTZ:	return SP(0,7);
1372
	case ABLEZ:	return SP(0,6);
1373
	case ABLTZ:	return SP(0,1)|BCOND(0,0);
1374
	case ABLTZAL:	return SP(0,1)|BCOND(2,0);
1375
 
1376
	case ABFPT:	return SP(2,1)|(257<<16);
1377
	case ABFPF:	return SP(2,1)|(256<<16);
1378
 
1379
	case AMOVB:
1380
	case AMOVBU:	return SP(5,0);
1381
	case AMOVH:
1382
	case AMOVHU:	return SP(5,1);
1383
	case AMOVW:	return SP(5,3);
1384
	case AMOVV:	return SP(7,7);
1385
	case AMOVF:	return SP(7,1);
1386
	case AMOVWL:	return SP(5,2);
1387
	case AMOVWR:	return SP(5,6);
1388
	case AMOVVL:	return SP(5,4);
1389
	case AMOVVR:	return SP(5,5);
1390
 
1391
	case ABREAK:	return SP(5,7);
1392
 
1393
	case AMOVWL+ALAST:	return SP(4,2);
1394
	case AMOVWR+ALAST:	return SP(4,6);
1395
	case AMOVVL+ALAST:	return SP(3,2);
1396
	case AMOVVR+ALAST:	return SP(3,3);
1397
	case AMOVB+ALAST:	return SP(4,0);
1398
	case AMOVBU+ALAST:	return SP(4,4);
1399
	case AMOVH+ALAST:	return SP(4,1);
1400
	case AMOVHU+ALAST:	return SP(4,5);
1401
	case AMOVW+ALAST:	return SP(4,3);
1402
	case AMOVV+ALAST:	return SP(6,7);
1403
	case AMOVF+ALAST:	return SP(6,1);
1404
 
1405
	case ASLLV:		return OP(7,0);
1406
	case ASRLV:		return OP(7,2);
1407
	case ASRAV:		return OP(7,3);
1408
	case ASLLV+ALAST:	return OP(7,4);
1409
	case ASRLV+ALAST:	return OP(7,6);
1410
	case ASRAV+ALAST:	return OP(7,7);
1411
 
1412
	case AADDV:		return SP(3,0);
1413
	case AADDVU:		return SP(3,1);
1414
	}
1415
	diag("bad irr %d", a);
1416
abort();
1417
	return 0;
1418
}
1419
 
1420
int
1421
vshift(int a)
1422
{
1423
	switch(a){
1424
	case ASLLV:		return 1;
1425
	case ASRLV:		return 1;
1426
	case ASRAV:		return 1;
1427
	}
1428
	return 0;
1429
}